From 8f8ccee0d9e1c3adfb1de484f26f6d9f6ff08708 Mon Sep 17 00:00:00 2001 From: Sebastian Huber Date: Mon, 23 Apr 2018 09:50:39 +0200 Subject: bsps: Move interrupt controller support to bsps This patch is a part of the BSP source reorganization. Update #3285. --- bsps/arm/beagle/irq/irq.c | 144 +++ bsps/arm/csb336/irq/irq.c | 51 ++ bsps/arm/csb337/irq/irq.c | 56 ++ bsps/arm/edb7312/irq/bsp_irq_asm.S | 323 +++++++ bsps/arm/edb7312/irq/irq.c | 180 ++++ bsps/arm/gdbarmsim/irq/irq-dispatch.c | 50 ++ bsps/arm/gdbarmsim/irq/irq.c | 71 ++ bsps/arm/gumstix/irq/irq.c | 51 ++ bsps/arm/lpc176x/irq/irq.c | 75 ++ bsps/arm/lpc24xx/irq/irq-dispatch.c | 50 ++ bsps/arm/lpc24xx/irq/irq.c | 120 +++ bsps/arm/lpc32xx/irq/irq.c | 344 +++++++ bsps/arm/raspberrypi/irq/irq.c | 168 ++++ bsps/arm/rtl22xx/irq/irq.c | 70 ++ bsps/arm/shared/irq/irq-armv7m.c | 67 ++ bsps/arm/shared/irq/irq-dispatch-armv7m.c | 32 + bsps/arm/shared/irq/irq-gic.c | 180 ++++ bsps/arm/smdk2410/irq/irq.c | 45 + bsps/arm/tms570/irq/irq.c | 202 +++++ bsps/epiphany/epiphany_sim/irq/irq.c | 64 ++ bsps/i386/shared/irq/elcr.c | 170 ++++ bsps/i386/shared/irq/elcr.h | 37 + bsps/i386/shared/irq/idt.c | 381 ++++++++ bsps/i386/shared/irq/irq.c | 405 +++++++++ bsps/i386/shared/irq/irq_asm.S | 268 ++++++ bsps/i386/shared/irq/irq_init.c | 191 ++++ bsps/lm32/shared/irq/irq.c | 30 + bsps/m68k/genmcf548x/irq/intc-icr-init-values.c | 29 + bsps/m68k/genmcf548x/irq/irq.c | 229 +++++ bsps/mips/csb350/irq/vectorisrs.c | 168 ++++ bsps/mips/hurricane/irq/vectorisrs.c | 58 ++ bsps/mips/jmr3904/irq/vectorisrs.c | 47 + bsps/mips/malta/irq/interruptmask.c | 36 + bsps/mips/malta/irq/vectorisrs.c | 90 ++ bsps/mips/rbtx4925/irq/vectorisrs.c | 64 ++ bsps/mips/rbtx4938/irq/vectorisrs.c | 64 ++ bsps/mips/shared/irq/exception.S | 661 ++++++++++++++ bsps/mips/shared/irq/i8259.c | 332 +++++++ bsps/mips/shared/irq/interruptmask.c | 29 + bsps/mips/shared/irq/interruptmask_TX49.c | 29 + bsps/mips/shared/irq/irq.c | 101 +++ bsps/mips/shared/irq/vectorexceptions.c | 81 ++ bsps/or1k/generic_or1k/irq/irq.c | 43 + bsps/powerpc/beatnik/irq/discovery_pic.c | 993 +++++++++++++++++++++ bsps/powerpc/beatnik/irq/irq_init.c | 110 +++ bsps/powerpc/beatnik/irq/irq_test_app.c | 164 ++++ bsps/powerpc/gen5200/irq/irq.c | 722 +++++++++++++++ bsps/powerpc/gen83xx/irq/irq.c | 596 +++++++++++++ bsps/powerpc/haleakala/irq/irq.c | 237 +++++ bsps/powerpc/haleakala/irq/irq_init.c | 96 ++ bsps/powerpc/mpc8260ads/irq/irq.c | 372 ++++++++ bsps/powerpc/mvme3100/irq/irq_init.c | 138 +++ bsps/powerpc/mvme5500/README.irq | 20 + bsps/powerpc/mvme5500/irq/BSP_irq.c | 483 ++++++++++ bsps/powerpc/mvme5500/irq/irq_init.c | 148 +++ bsps/powerpc/psim/irq/irq_init.c | 125 +++ bsps/powerpc/qemuppc/irq/irq_init.c | 61 ++ bsps/powerpc/qoriq/irq/irq.c | 387 ++++++++ bsps/powerpc/shared/irq/i8259.c | 149 ++++ bsps/powerpc/shared/irq/irq_init.c | 364 ++++++++ bsps/powerpc/shared/irq/openpic.c | 622 +++++++++++++ bsps/powerpc/shared/irq/openpic_i8259_irq.c | 331 +++++++ bsps/powerpc/t32mppc/irq/irq.c | 41 + bsps/powerpc/tqm8xx/irq/irq.c | 231 +++++ bsps/powerpc/virtex/irq/irq_init.c | 167 ++++ bsps/powerpc/virtex4/irq/irq_init.c | 326 +++++++ bsps/powerpc/virtex5/irq/irq_init.c | 343 +++++++ bsps/riscv/riscv_generic/irq/irq.c | 60 ++ c/src/lib/libbsp/arm/altera-cyclone-v/Makefile.am | 2 +- c/src/lib/libbsp/arm/atsam/Makefile.am | 4 +- c/src/lib/libbsp/arm/beagle/Makefile.am | 2 +- c/src/lib/libbsp/arm/beagle/irq.c | 144 --- c/src/lib/libbsp/arm/csb336/Makefile.am | 2 +- c/src/lib/libbsp/arm/csb336/irq/irq.c | 51 -- c/src/lib/libbsp/arm/csb337/Makefile.am | 2 +- c/src/lib/libbsp/arm/csb337/irq/irq.c | 56 -- c/src/lib/libbsp/arm/edb7312/Makefile.am | 4 +- c/src/lib/libbsp/arm/edb7312/irq/bsp_irq_asm.S | 323 ------- c/src/lib/libbsp/arm/edb7312/irq/irq.c | 180 ---- c/src/lib/libbsp/arm/gdbarmsim/Makefile.am | 4 +- c/src/lib/libbsp/arm/gdbarmsim/irq/irq-dispatch.c | 50 -- c/src/lib/libbsp/arm/gdbarmsim/irq/irq.c | 71 -- c/src/lib/libbsp/arm/gumstix/Makefile.am | 2 +- c/src/lib/libbsp/arm/gumstix/irq/irq.c | 51 -- c/src/lib/libbsp/arm/imx/Makefile.am | 2 +- c/src/lib/libbsp/arm/lm3s69xx/Makefile.am | 4 +- c/src/lib/libbsp/arm/lpc176x/Makefile.am | 6 +- c/src/lib/libbsp/arm/lpc176x/irq/irq.c | 75 -- c/src/lib/libbsp/arm/lpc24xx/Makefile.am | 8 +- c/src/lib/libbsp/arm/lpc24xx/irq/irq-dispatch.c | 50 -- c/src/lib/libbsp/arm/lpc24xx/irq/irq.c | 120 --- c/src/lib/libbsp/arm/lpc32xx/Makefile.am | 2 +- c/src/lib/libbsp/arm/lpc32xx/irq/irq.c | 344 ------- c/src/lib/libbsp/arm/raspberrypi/Makefile.am | 2 +- c/src/lib/libbsp/arm/raspberrypi/irq/irq.c | 168 ---- c/src/lib/libbsp/arm/realview-pbx-a9/Makefile.am | 2 +- c/src/lib/libbsp/arm/rtl22xx/Makefile.am | 2 +- c/src/lib/libbsp/arm/rtl22xx/irq/irq.c | 70 -- c/src/lib/libbsp/arm/shared/arm-gic-irq.c | 180 ---- .../arm/shared/armv7m/irq/armv7m-irq-dispatch.c | 32 - .../lib/libbsp/arm/shared/armv7m/irq/armv7m-irq.c | 67 -- c/src/lib/libbsp/arm/smdk2410/Makefile.am | 2 +- c/src/lib/libbsp/arm/smdk2410/irq/irq.c | 45 - c/src/lib/libbsp/arm/stm32f4/Makefile.am | 4 +- c/src/lib/libbsp/arm/tms570/Makefile.am | 2 +- c/src/lib/libbsp/arm/tms570/irq/irq.c | 202 ----- c/src/lib/libbsp/arm/xilinx-zynq/Makefile.am | 2 +- c/src/lib/libbsp/epiphany/epiphany_sim/Makefile.am | 2 +- c/src/lib/libbsp/epiphany/epiphany_sim/irq/irq.c | 64 -- c/src/lib/libbsp/i386/pc386/Makefile.am | 10 +- c/src/lib/libbsp/i386/shared/irq/elcr.c | 170 ---- c/src/lib/libbsp/i386/shared/irq/elcr.h | 37 - c/src/lib/libbsp/i386/shared/irq/idt.c | 381 -------- c/src/lib/libbsp/i386/shared/irq/irq.c | 405 --------- c/src/lib/libbsp/i386/shared/irq/irq_asm.S | 268 ------ c/src/lib/libbsp/i386/shared/irq/irq_init.c | 191 ---- c/src/lib/libbsp/lm32/milkymist/Makefile.am | 2 +- c/src/lib/libbsp/lm32/shared/irq/irq.c | 30 - c/src/lib/libbsp/m68k/genmcf548x/Makefile.am | 4 +- .../m68k/genmcf548x/irq/intc-icr-init-values.c | 29 - c/src/lib/libbsp/m68k/genmcf548x/irq/irq.c | 229 ----- c/src/lib/libbsp/mips/csb350/Makefile.am | 8 +- c/src/lib/libbsp/mips/csb350/irq/vectorisrs.c | 168 ---- c/src/lib/libbsp/mips/hurricane/Makefile.am | 10 +- c/src/lib/libbsp/mips/hurricane/irq/vectorisrs.c | 58 -- c/src/lib/libbsp/mips/jmr3904/Makefile.am | 8 +- c/src/lib/libbsp/mips/jmr3904/irq/vectorisrs.c | 47 - c/src/lib/libbsp/mips/malta/Makefile.am | 10 +- c/src/lib/libbsp/mips/malta/irq/interruptmask.c | 36 - c/src/lib/libbsp/mips/malta/irq/vectorisrs.c | 90 -- c/src/lib/libbsp/mips/rbtx4925/Makefile.am | 10 +- c/src/lib/libbsp/mips/rbtx4925/irq/vectorisrs.c | 64 -- c/src/lib/libbsp/mips/rbtx4938/Makefile.am | 10 +- c/src/lib/libbsp/mips/rbtx4938/irq/vectorisrs.c | 64 -- c/src/lib/libbsp/mips/shared/irq/exception.S | 661 -------------- c/src/lib/libbsp/mips/shared/irq/i8259.c | 332 ------- c/src/lib/libbsp/mips/shared/irq/interruptmask.c | 29 - .../libbsp/mips/shared/irq/interruptmask_TX49.c | 29 - c/src/lib/libbsp/mips/shared/irq/irq.c | 101 --- .../lib/libbsp/mips/shared/irq/vectorexceptions.c | 81 -- c/src/lib/libbsp/or1k/generic_or1k/Makefile.am | 2 +- c/src/lib/libbsp/or1k/generic_or1k/irq/irq.c | 43 - c/src/lib/libbsp/powerpc/beatnik/Makefile.am | 4 +- .../lib/libbsp/powerpc/beatnik/irq/discovery_pic.c | 993 --------------------- c/src/lib/libbsp/powerpc/beatnik/irq/irq_init.c | 110 --- .../lib/libbsp/powerpc/beatnik/irq/irq_test_app.c | 164 ---- c/src/lib/libbsp/powerpc/gen5200/Makefile.am | 2 +- c/src/lib/libbsp/powerpc/gen5200/irq/irq.c | 722 --------------- c/src/lib/libbsp/powerpc/gen83xx/Makefile.am | 2 +- c/src/lib/libbsp/powerpc/gen83xx/irq/irq.c | 596 ------------- c/src/lib/libbsp/powerpc/haleakala/Makefile.am | 4 +- c/src/lib/libbsp/powerpc/haleakala/irq/irq.c | 237 ----- c/src/lib/libbsp/powerpc/haleakala/irq/irq_init.c | 96 -- .../libbsp/powerpc/motorola_powerpc/Makefile.am | 8 +- c/src/lib/libbsp/powerpc/mpc8260ads/Makefile.am | 2 +- c/src/lib/libbsp/powerpc/mpc8260ads/irq/irq.c | 372 -------- c/src/lib/libbsp/powerpc/mvme3100/Makefile.am | 6 +- c/src/lib/libbsp/powerpc/mvme3100/irq/irq_init.c | 138 --- c/src/lib/libbsp/powerpc/mvme5500/Makefile.am | 4 +- c/src/lib/libbsp/powerpc/mvme5500/README.irq | 20 - c/src/lib/libbsp/powerpc/mvme5500/irq/BSP_irq.c | 483 ---------- c/src/lib/libbsp/powerpc/mvme5500/irq/irq_init.c | 148 --- c/src/lib/libbsp/powerpc/psim/Makefile.am | 6 +- c/src/lib/libbsp/powerpc/psim/irq/irq_init.c | 125 --- c/src/lib/libbsp/powerpc/qemuppc/Makefile.am | 2 +- c/src/lib/libbsp/powerpc/qemuppc/irq/irq_init.c | 61 -- c/src/lib/libbsp/powerpc/qoriq/Makefile.am | 2 +- c/src/lib/libbsp/powerpc/qoriq/irq/irq.c | 387 -------- c/src/lib/libbsp/powerpc/shared/irq/i8259.c | 149 ---- c/src/lib/libbsp/powerpc/shared/irq/irq_init.c | 364 -------- .../libbsp/powerpc/shared/irq/openpic_i8259_irq.c | 331 ------- c/src/lib/libbsp/powerpc/shared/openpic/openpic.c | 622 ------------- c/src/lib/libbsp/powerpc/t32mppc/Makefile.am | 2 +- c/src/lib/libbsp/powerpc/t32mppc/irq/irq.c | 41 - c/src/lib/libbsp/powerpc/tqm8xx/Makefile.am | 2 +- c/src/lib/libbsp/powerpc/tqm8xx/irq/irq.c | 231 ----- c/src/lib/libbsp/powerpc/virtex/Makefile.am | 2 +- c/src/lib/libbsp/powerpc/virtex/irq/irq_init.c | 167 ---- c/src/lib/libbsp/powerpc/virtex4/Makefile.am | 2 +- c/src/lib/libbsp/powerpc/virtex4/irq/irq_init.c | 326 ------- c/src/lib/libbsp/powerpc/virtex5/Makefile.am | 2 +- c/src/lib/libbsp/powerpc/virtex5/irq/irq_init.c | 343 ------- c/src/lib/libbsp/riscv/riscv_generic/Makefile.am | 2 +- c/src/lib/libbsp/riscv/riscv_generic/irq/irq.c | 60 -- 184 files changed, 13267 insertions(+), 13267 deletions(-) create mode 100644 bsps/arm/beagle/irq/irq.c create mode 100644 bsps/arm/csb336/irq/irq.c create mode 100644 bsps/arm/csb337/irq/irq.c create mode 100644 bsps/arm/edb7312/irq/bsp_irq_asm.S create mode 100644 bsps/arm/edb7312/irq/irq.c create mode 100644 bsps/arm/gdbarmsim/irq/irq-dispatch.c create mode 100644 bsps/arm/gdbarmsim/irq/irq.c create mode 100644 bsps/arm/gumstix/irq/irq.c create mode 100644 bsps/arm/lpc176x/irq/irq.c create mode 100644 bsps/arm/lpc24xx/irq/irq-dispatch.c create mode 100644 bsps/arm/lpc24xx/irq/irq.c create mode 100755 bsps/arm/lpc32xx/irq/irq.c create mode 100644 bsps/arm/raspberrypi/irq/irq.c create mode 100644 bsps/arm/rtl22xx/irq/irq.c create mode 100644 bsps/arm/shared/irq/irq-armv7m.c create mode 100644 bsps/arm/shared/irq/irq-dispatch-armv7m.c create mode 100644 bsps/arm/shared/irq/irq-gic.c create mode 100644 bsps/arm/smdk2410/irq/irq.c create mode 100644 bsps/arm/tms570/irq/irq.c create mode 100644 bsps/epiphany/epiphany_sim/irq/irq.c create mode 100644 bsps/i386/shared/irq/elcr.c create mode 100644 bsps/i386/shared/irq/elcr.h create mode 100644 bsps/i386/shared/irq/idt.c create mode 100644 bsps/i386/shared/irq/irq.c create mode 100644 bsps/i386/shared/irq/irq_asm.S create mode 100644 bsps/i386/shared/irq/irq_init.c create mode 100644 bsps/lm32/shared/irq/irq.c create mode 100644 bsps/m68k/genmcf548x/irq/intc-icr-init-values.c create mode 100644 bsps/m68k/genmcf548x/irq/irq.c create mode 100644 bsps/mips/csb350/irq/vectorisrs.c create mode 100644 bsps/mips/hurricane/irq/vectorisrs.c create mode 100644 bsps/mips/jmr3904/irq/vectorisrs.c create mode 100644 bsps/mips/malta/irq/interruptmask.c create mode 100644 bsps/mips/malta/irq/vectorisrs.c create mode 100644 bsps/mips/rbtx4925/irq/vectorisrs.c create mode 100644 bsps/mips/rbtx4938/irq/vectorisrs.c create mode 100644 bsps/mips/shared/irq/exception.S create mode 100644 bsps/mips/shared/irq/i8259.c create mode 100644 bsps/mips/shared/irq/interruptmask.c create mode 100644 bsps/mips/shared/irq/interruptmask_TX49.c create mode 100644 bsps/mips/shared/irq/irq.c create mode 100644 bsps/mips/shared/irq/vectorexceptions.c create mode 100644 bsps/or1k/generic_or1k/irq/irq.c create mode 100644 bsps/powerpc/beatnik/irq/discovery_pic.c create mode 100644 bsps/powerpc/beatnik/irq/irq_init.c create mode 100644 bsps/powerpc/beatnik/irq/irq_test_app.c create mode 100644 bsps/powerpc/gen5200/irq/irq.c create mode 100644 bsps/powerpc/gen83xx/irq/irq.c create mode 100644 bsps/powerpc/haleakala/irq/irq.c create mode 100644 bsps/powerpc/haleakala/irq/irq_init.c create mode 100644 bsps/powerpc/mpc8260ads/irq/irq.c create mode 100644 bsps/powerpc/mvme3100/irq/irq_init.c create mode 100644 bsps/powerpc/mvme5500/README.irq create mode 100644 bsps/powerpc/mvme5500/irq/BSP_irq.c create mode 100644 bsps/powerpc/mvme5500/irq/irq_init.c create mode 100644 bsps/powerpc/psim/irq/irq_init.c create mode 100644 bsps/powerpc/qemuppc/irq/irq_init.c create mode 100644 bsps/powerpc/qoriq/irq/irq.c create mode 100644 bsps/powerpc/shared/irq/i8259.c create mode 100644 bsps/powerpc/shared/irq/irq_init.c create mode 100644 bsps/powerpc/shared/irq/openpic.c create mode 100644 bsps/powerpc/shared/irq/openpic_i8259_irq.c create mode 100644 bsps/powerpc/t32mppc/irq/irq.c create mode 100644 bsps/powerpc/tqm8xx/irq/irq.c create mode 100644 bsps/powerpc/virtex/irq/irq_init.c create mode 100644 bsps/powerpc/virtex4/irq/irq_init.c create mode 100644 bsps/powerpc/virtex5/irq/irq_init.c create mode 100644 bsps/riscv/riscv_generic/irq/irq.c delete mode 100644 c/src/lib/libbsp/arm/beagle/irq.c delete mode 100644 c/src/lib/libbsp/arm/csb336/irq/irq.c delete mode 100644 c/src/lib/libbsp/arm/csb337/irq/irq.c delete mode 100644 c/src/lib/libbsp/arm/edb7312/irq/bsp_irq_asm.S delete mode 100644 c/src/lib/libbsp/arm/edb7312/irq/irq.c delete mode 100644 c/src/lib/libbsp/arm/gdbarmsim/irq/irq-dispatch.c delete mode 100644 c/src/lib/libbsp/arm/gdbarmsim/irq/irq.c delete mode 100644 c/src/lib/libbsp/arm/gumstix/irq/irq.c delete mode 100644 c/src/lib/libbsp/arm/lpc176x/irq/irq.c delete mode 100644 c/src/lib/libbsp/arm/lpc24xx/irq/irq-dispatch.c delete mode 100644 c/src/lib/libbsp/arm/lpc24xx/irq/irq.c delete mode 100755 c/src/lib/libbsp/arm/lpc32xx/irq/irq.c delete mode 100644 c/src/lib/libbsp/arm/raspberrypi/irq/irq.c delete mode 100644 c/src/lib/libbsp/arm/rtl22xx/irq/irq.c delete mode 100644 c/src/lib/libbsp/arm/shared/arm-gic-irq.c delete mode 100644 c/src/lib/libbsp/arm/shared/armv7m/irq/armv7m-irq-dispatch.c delete mode 100644 c/src/lib/libbsp/arm/shared/armv7m/irq/armv7m-irq.c delete mode 100644 c/src/lib/libbsp/arm/smdk2410/irq/irq.c delete mode 100644 c/src/lib/libbsp/arm/tms570/irq/irq.c delete mode 100644 c/src/lib/libbsp/epiphany/epiphany_sim/irq/irq.c delete mode 100644 c/src/lib/libbsp/i386/shared/irq/elcr.c delete mode 100644 c/src/lib/libbsp/i386/shared/irq/elcr.h delete mode 100644 c/src/lib/libbsp/i386/shared/irq/idt.c delete mode 100644 c/src/lib/libbsp/i386/shared/irq/irq.c delete mode 100644 c/src/lib/libbsp/i386/shared/irq/irq_asm.S delete mode 100644 c/src/lib/libbsp/i386/shared/irq/irq_init.c delete mode 100644 c/src/lib/libbsp/lm32/shared/irq/irq.c delete mode 100644 c/src/lib/libbsp/m68k/genmcf548x/irq/intc-icr-init-values.c delete mode 100644 c/src/lib/libbsp/m68k/genmcf548x/irq/irq.c delete mode 100644 c/src/lib/libbsp/mips/csb350/irq/vectorisrs.c delete mode 100644 c/src/lib/libbsp/mips/hurricane/irq/vectorisrs.c delete mode 100644 c/src/lib/libbsp/mips/jmr3904/irq/vectorisrs.c delete mode 100644 c/src/lib/libbsp/mips/malta/irq/interruptmask.c delete mode 100644 c/src/lib/libbsp/mips/malta/irq/vectorisrs.c delete mode 100644 c/src/lib/libbsp/mips/rbtx4925/irq/vectorisrs.c delete mode 100644 c/src/lib/libbsp/mips/rbtx4938/irq/vectorisrs.c delete mode 100644 c/src/lib/libbsp/mips/shared/irq/exception.S delete mode 100644 c/src/lib/libbsp/mips/shared/irq/i8259.c delete mode 100644 c/src/lib/libbsp/mips/shared/irq/interruptmask.c delete mode 100644 c/src/lib/libbsp/mips/shared/irq/interruptmask_TX49.c delete mode 100644 c/src/lib/libbsp/mips/shared/irq/irq.c delete mode 100644 c/src/lib/libbsp/mips/shared/irq/vectorexceptions.c delete mode 100644 c/src/lib/libbsp/or1k/generic_or1k/irq/irq.c delete mode 100644 c/src/lib/libbsp/powerpc/beatnik/irq/discovery_pic.c delete mode 100644 c/src/lib/libbsp/powerpc/beatnik/irq/irq_init.c delete mode 100644 c/src/lib/libbsp/powerpc/beatnik/irq/irq_test_app.c delete mode 100644 c/src/lib/libbsp/powerpc/gen5200/irq/irq.c delete mode 100644 c/src/lib/libbsp/powerpc/gen83xx/irq/irq.c delete mode 100644 c/src/lib/libbsp/powerpc/haleakala/irq/irq.c delete mode 100644 c/src/lib/libbsp/powerpc/haleakala/irq/irq_init.c delete mode 100644 c/src/lib/libbsp/powerpc/mpc8260ads/irq/irq.c delete mode 100644 c/src/lib/libbsp/powerpc/mvme3100/irq/irq_init.c delete mode 100644 c/src/lib/libbsp/powerpc/mvme5500/README.irq delete mode 100644 c/src/lib/libbsp/powerpc/mvme5500/irq/BSP_irq.c delete mode 100644 c/src/lib/libbsp/powerpc/mvme5500/irq/irq_init.c delete mode 100644 c/src/lib/libbsp/powerpc/psim/irq/irq_init.c delete mode 100644 c/src/lib/libbsp/powerpc/qemuppc/irq/irq_init.c delete mode 100644 c/src/lib/libbsp/powerpc/qoriq/irq/irq.c delete mode 100644 c/src/lib/libbsp/powerpc/shared/irq/i8259.c delete mode 100644 c/src/lib/libbsp/powerpc/shared/irq/irq_init.c delete mode 100644 c/src/lib/libbsp/powerpc/shared/irq/openpic_i8259_irq.c delete mode 100644 c/src/lib/libbsp/powerpc/shared/openpic/openpic.c delete mode 100644 c/src/lib/libbsp/powerpc/t32mppc/irq/irq.c delete mode 100644 c/src/lib/libbsp/powerpc/tqm8xx/irq/irq.c delete mode 100644 c/src/lib/libbsp/powerpc/virtex/irq/irq_init.c delete mode 100644 c/src/lib/libbsp/powerpc/virtex4/irq/irq_init.c delete mode 100644 c/src/lib/libbsp/powerpc/virtex5/irq/irq_init.c delete mode 100644 c/src/lib/libbsp/riscv/riscv_generic/irq/irq.c diff --git a/bsps/arm/beagle/irq/irq.c b/bsps/arm/beagle/irq/irq.c new file mode 100644 index 0000000000..2fa1a5b0f0 --- /dev/null +++ b/bsps/arm/beagle/irq/irq.c @@ -0,0 +1,144 @@ +/** + * @file + * + * @ingroup bsp_interrupt + * @ingroup arm_beagle + * + * @brief Interrupt support. + */ + +/* + * Copyright (c) 2014 Ben Gras . All rights reserved. + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.org/license/LICENSE. + */ + +#include +#include +#include +#include + +#include + +#include + +struct omap_intr +{ + uint32_t base; + int size; +}; + +#if IS_DM3730 +static struct omap_intr omap_intr = { + .base = OMAP3_DM37XX_INTR_BASE, + .size = 0x1000, +}; +#endif + +#if IS_AM335X +static struct omap_intr omap_intr = { + .base = OMAP3_AM335X_INTR_BASE, + .size = 0x1000, +}; +#endif + +/* Enables interrupts at the Interrupt Controller side. */ +static inline void omap_irq_ack(void) +{ + mmio_write(omap_intr.base + OMAP3_INTCPS_CONTROL, OMAP3_INTR_NEWIRQAGR); + + /* Flush data cache to make sure all the previous writes are done + before re-enabling interrupts. */ + flush_data_cache(); +} + +void bsp_interrupt_dispatch(void) +{ + const uint32_t reg = mmio_read(omap_intr.base + OMAP3_INTCPS_SIR_IRQ); + + if ((reg & OMAP3_INTR_SPURIOUSIRQ_MASK) != OMAP3_INTR_SPURIOUSIRQ_MASK) { + const rtems_vector_number irq = reg & OMAP3_INTR_ACTIVEIRQ_MASK; + + bsp_interrupt_handler_dispatch(irq); + } else { + /* Ignore spurious interrupts. We'll still ACK it so new interrupts + can be generated. */ + } + + omap_irq_ack(); +} + +/* There are 4 32-bit interrupt mask registers for a total of 128 interrupts. + The IRQ number tells us which register to use. */ +static uint32_t omap_get_mir_reg(rtems_vector_number vector, uint32_t *const mask) +{ + uint32_t mir_reg; + + /* Select which bit to set/clear in the MIR register. */ + *mask = 1ul << (vector % 32u); + + if (vector < 32u) { + mir_reg = OMAP3_INTCPS_MIR0; + } else if (vector < 64u) { + mir_reg = OMAP3_INTCPS_MIR1; + } else if (vector < 96u) { + mir_reg = OMAP3_INTCPS_MIR2; + } else if (vector < 128u) { + mir_reg = OMAP3_INTCPS_MIR3; + } else { + /* Invalid IRQ number. This should never happen. */ + bsp_fatal(0); + } + + return mir_reg; +} + +void bsp_interrupt_vector_enable(rtems_vector_number vector) +{ + uint32_t mask, cur; + uint32_t mir_reg = omap_get_mir_reg(vector, &mask); + + bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector)); + + cur = mmio_read(omap_intr.base + mir_reg); + mmio_write(omap_intr.base + mir_reg, cur & ~mask); + flush_data_cache(); +} + +void bsp_interrupt_vector_disable(rtems_vector_number vector) +{ + uint32_t mask, cur; + uint32_t mir_reg = omap_get_mir_reg(vector, &mask); + + bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector)); + + cur = mmio_read(omap_intr.base + mir_reg); + mmio_write(omap_intr.base + mir_reg, cur | mask); + flush_data_cache(); +} + +rtems_status_code bsp_interrupt_facility_initialize(void) +{ + int i; + uint32_t intc_ilrx; + + /* AM335X TRM 6.2.1 Initialization Sequence */ + mmio_write(omap_intr.base + OMAP3_INTCPS_SYSCONFIG, OMAP3_SYSCONFIG_AUTOIDLE); + mmio_write(omap_intr.base + OMAP3_INTCPS_IDLE, 0); + /* priority 0 to all IRQs */ + for(intc_ilrx = 0x100; intc_ilrx <= 0x2fc; intc_ilrx += 4) { + mmio_write(omap_intr.base + intc_ilrx, 0); + } + + /* Mask all interrupts */ + for(i = BSP_INTERRUPT_VECTOR_MIN; i <= BSP_INTERRUPT_VECTOR_MAX; i++) + bsp_interrupt_vector_disable(i); + + /* Install generic interrupt handler */ + arm_cp15_set_exception_handler(ARM_EXCEPTION_IRQ, _ARMV4_Exception_interrupt); + arm_cp15_set_vector_base_address(bsp_vector_table_begin); + + return RTEMS_SUCCESSFUL; +} diff --git a/bsps/arm/csb336/irq/irq.c b/bsps/arm/csb336/irq/irq.c new file mode 100644 index 0000000000..e5887b9717 --- /dev/null +++ b/bsps/arm/csb336/irq/irq.c @@ -0,0 +1,51 @@ +/* + * Motorola MC9328MXL Interrupt handler + * + * Copyright (c) 2010 embedded brains GmbH. + * + * Copyright (c) 2004 by Jay Monkman + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.org/license/LICENSE. + */ + +#include + +#include +#include +#include + +#include + +void bsp_interrupt_dispatch(void) +{ + + rtems_vector_number vector = MC9328MXL_AITC_NIVECSR >> 16; + + bsp_interrupt_handler_dispatch(vector); +} + +void bsp_interrupt_vector_enable(rtems_vector_number vector) +{ + bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector)); + + if (vector < MC9328MXL_NUM_INTS) + MC9328MXL_AITC_INTENNUM = vector; +} + +void bsp_interrupt_vector_disable(rtems_vector_number vector) +{ + bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector)); + + if (vector < MC9328MXL_NUM_INTS) + MC9328MXL_AITC_INTDISNUM = vector; +} + +rtems_status_code bsp_interrupt_facility_initialize(void) +{ + + _CPU_ISR_install_vector(ARM_EXCEPTION_IRQ, _ARMV4_Exception_interrupt, NULL); + + return RTEMS_SUCCESSFUL; +} diff --git a/bsps/arm/csb337/irq/irq.c b/bsps/arm/csb337/irq/irq.c new file mode 100644 index 0000000000..95e93845b9 --- /dev/null +++ b/bsps/arm/csb337/irq/irq.c @@ -0,0 +1,56 @@ +/* + * Atmel AT91RM9200 Interrupt handler + * + * Copyright (c) 2010 embedded brains GmbH. + * + * Copyright (c) 2004 by Jay Monkman + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.org/license/LICENSE. + */ + +#include + +#include +#include +#include + +#include + +void bsp_interrupt_dispatch(void) +{ + rtems_vector_number vector = AIC_CTL_REG(AIC_IVR); + + bsp_interrupt_handler_dispatch(vector); + + AIC_CTL_REG(AIC_EOICR) = 0; +} + +void bsp_interrupt_vector_enable(rtems_vector_number vector) +{ + bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector)); + AIC_CTL_REG(AIC_IECR) = 1 << vector; +} + +void bsp_interrupt_vector_disable(rtems_vector_number vector) +{ + bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector)); + AIC_CTL_REG(AIC_IDCR) = 1 << vector; +} + +rtems_status_code bsp_interrupt_facility_initialize(void) +{ + unsigned long i = 0; + + for (i = 0; i < 32; ++i) { + AIC_SVR_REG(i<<2) = i; + } + + /* disable all interrupts */ + AIC_CTL_REG(AIC_IDCR) = 0xffffffff; + + _CPU_ISR_install_vector(ARM_EXCEPTION_IRQ, _ARMV4_Exception_interrupt, NULL); + + return RTEMS_SUCCESSFUL; +} diff --git a/bsps/arm/edb7312/irq/bsp_irq_asm.S b/bsps/arm/edb7312/irq/bsp_irq_asm.S new file mode 100644 index 0000000000..c48466967b --- /dev/null +++ b/bsps/arm/edb7312/irq/bsp_irq_asm.S @@ -0,0 +1,323 @@ +/* + * Cirrus EP7312 Intererrupt handler + */ + +/* + * Copyright (c) 2002 by Jay Monkman + * + * Copyright (c) 2002 by Charlie Steader + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.org/license/LICENSE. +*/ + +#define __asm__ +#include +#include + + .extern edb7312_interrupt_dispatch + +/* + * Function to obtain, execute an IT handler and acknowledge the IT + */ + + .globl bsp_interrupt_dispatch +bsp_interrupt_dispatch : +/* + * Look at interrupt status register to determine source. + * From source, determine offset into expanded vector table + * and load handler address into r0. + */ + + ldr r1, =0x80000000 /* close to interrupt status/mask registers 1 */ + ldr r2, =0x80001000 /* close to interrupt status/mask registers 2 */ + ldr r3, =0x80002000 /* close to interrupt status/mask registers 3 */ + + stmdb sp!,{r4, r5, r6} + +/* + * INTSR3 + */ +check_dai: + ldr r4, [r3, #0x240] + ldr r5, [r3, #0x280] + and r6, r4, r5 /* only look at interrupts which are enabled */ + tst r6, #0x0001 + beq check_extfiq + mov r0, #BSP_DAIINT + b get_handler + +/* + * INTSR1 + */ +check_extfiq: + ldr r4, [r1, #0x240] + ldr r5, [r1, #0x280] + and r6, r4, r5 /* only look at interrupts which are enabled */ + tst r6, #0x0001 + beq check_bl + mov r0, #BSP_EXTFIQ + b get_handler + +check_bl: +#if 0 +MUST REMEMBER TO UNCOMMENT IF THIS HANDLER MOVES + ldr r4, [r1, #0x240] + ldr r5, [r1, #0x280] + and r6, r4, r5 /* only look at interrupts which are enabled */ +#endif + tst r6, #0x0002 + beq check_we + mov r0, #BSP_BLINT + b get_handler + +check_we: +#if 0 +MUST REMEMBER TO UNCOMMENT IF THIS HANDLER MOVES + ldr r4, [r1, #0x240] + ldr r5, [r1, #0x280] + and r6, r4, r5 /* only look at interrupts which are enabled */ +#endif + tst r6, #0x0004 + beq check_mc + mov r0, #BSP_WEINT + b get_handler + +check_mc: +#if 0 +MUST REMEMBER TO UNCOMMENT IF THIS HANDLER MOVES + ldr r4, [r1, #0x240] + ldr r5, [r1, #0x280] + and r6, r4, r5 /* only look at interrupts which are enabled */ +#endif + tst r6, #0x0008 + beq check_cs + mov r0, #BSP_MCINT + b get_handler + +check_cs: +#if 0 +MUST REMEMBER TO UNCOMMENT IF THIS HANDLER MOVES + ldr r4, [r1, #0x240] + ldr r5, [r1, #0x280] + and r6, r4, r5 /* only look at interrupts which are enabled */ +#endif + tst r6, #0x0010 + beq check_e1 + mov r0, #BSP_CSINT + b get_handler + +check_e1: +#if 0 +MUST REMEMBER TO UNCOMMENT IF THIS HANDLER MOVES + ldr r4, [r1, #0x240] + ldr r5, [r1, #0x280] + and r6, r4, r5 /* only look at interrupts which are enabled */ +#endif + tst r6, #0x0020 + beq check_e2 + mov r0, #BSP_EINT1 + b get_handler + +check_e2: +#if 0 +MUST REMEMBER TO UNCOMMENT IF THIS HANDLER MOVES + ldr r4, [r1, #0x240] + ldr r5, [r1, #0x280] + and r6, r4, r5 /* only look at interrupts which are enabled */ +#endif + tst r6, #0x0040 + beq check_e3 + mov r0, #BSP_EINT2 + b get_handler + +check_e3: +#if 0 +MUST REMEMBER TO UNCOMMENT IF THIS HANDLER MOVES + ldr r4, [r1, #0x240] + ldr r5, [r1, #0x280] + and r6, r4, r5 /* only look at interrupts which are enabled */ +#endif + tst r6, #0x0080 + beq check_tc1 + mov r0, #BSP_EINT3 + b get_handler + +check_tc1: +#if 0 +MUST REMEMBER TO UNCOMMENT IF THIS HANDLER MOVES + ldr r4, [r1, #0x240] + ldr r5, [r1, #0x280] + and r6, r4, r5 /* only look at interrupts which are enabled */ +#endif + tst r6, #0x0100 + beq check_tc2 + mov r0, #BSP_TC1OI + b get_handler + +check_tc2: +#if 0 +MUST REMEMBER TO UNCOMMENT IF THIS HANDLER MOVES + ldr r4, [r1, #0x240] + ldr r5, [r1, #0x280] + and r6, r4, r5 /* only look at interrupts which are enabled */ +#endif + tst r6, #0x0200 + beq check_rtc + mov r0, #BSP_TC2OI + b get_handler + +check_rtc: +#if 0 +MUST REMEMBER TO UNCOMMENT IF THIS HANDLER MOVES + ldr r4, [r1, #0x240] + ldr r5, [r1, #0x280] + and r6, r4, r5 /* only look at interrupts which are enabled */ +#endif + tst r6, #0x0400 + beq check_tick + mov r0, #BSP_RTCMI + b get_handler + +check_tick: +#if 0 +MUST REMEMBER TO UNCOMMENT IF THIS HANDLER MOVES + ldr r4, [r1, #0x240] + ldr r5, [r1, #0x280] + and r6, r4, r5 /* only look at interrupts which are enabled */ +#endif + tst r6, #0x0800 + beq check_utx1 + mov r0, #BSP_TINT + b get_handler + +check_utx1: +#if 0 +MUST REMEMBER TO UNCOMMENT IF THIS HANDLER MOVES + ldr r4, [r1, #0x240] + ldr r5, [r1, #0x280] + and r6, r4, r5 /* only look at interrupts which are enabled */ +#endif + tst r6, #0x1000 + beq check_urx1 + mov r0, #BSP_UTXINT1 + b get_handler + +check_urx1: +#if 0 +MUST REMEMBER TO UNCOMMENT IF THIS HANDLER MOVES + ldr r4, [r1, #0x240] + ldr r5, [r1, #0x280] + and r6, r4, r5 /* only look at interrupts which are enabled */ +#endif + tst r6, #0x2000 + beq check_ums + mov r0, #BSP_URXINT1 + b get_handler + +check_ums: +#if 0 +MUST REMEMBER TO UNCOMMENT IF THIS HANDLER MOVES + ldr r4, [r1, #0x240] + ldr r5, [r1, #0x280] + and r6, r4, r5 /* only look at interrupts which are enabled */ +#endif + tst r6, #0x4000 + beq check_sse + mov r0, #BSP_UMSINT + b get_handler + +check_sse: +#if 0 +MUST REMEMBER TO UNCOMMENT IF THIS HANDLER MOVES + ldr r4, [r1, #0x240] + ldr r5, [r1, #0x280] + and r6, r4, r5 /* only look at interrupts which are enabled */ +#endif + tst r6, #0x8000 + beq check_kbd + mov r0, #BSP_SSEOTI + b get_handler + +/* + * INTSR2 + */ +check_kbd: + ldr r4, [r2, #0x240] + ldr r5, [r2, #0x280] + and r6, r4, r5 /* only look at interrupts which are enabled */ + tst r6, #0x0001 + beq check_ss2rx + mov r0, #BSP_KBDINT + b get_handler + +check_ss2rx: +#if 0 +MUST REMEMBER TO UNCOMMENT IF THIS HANDLER MOVES + ldr r4, [r2, #0x240] + ldr r5, [r2, #0x280] + and r6, r4, r5 /* only look at interrupts which are enabled */ +#endif + tst r6, #0x0002 + beq check_ss2tx + mov r0, #BSP_SS2RX + b get_handler + +check_ss2tx: +#if 0 +MUST REMEMBER TO UNCOMMENT IF THIS HANDLER MOVES + ldr r4, [r2, #0x240] + ldr r5, [r2, #0x280] + and r6, r4, r5 /* only look at interrupts which are enabled */ +#endif + tst r6, #0x0004 + beq check_utx2 + mov r0, #BSP_SS2TX + b get_handler + +check_utx2: +#if 0 +MUST REMEMBER TO UNCOMMENT IF THIS HANDLER MOVES + ldr r4, [r2, #0x240] + ldr r5, [r2, #0x280] + and r6, r4, r5 /* only look at interrupts which are enabled */ +#endif + tst r6, #0x1000 + beq check_urx2 + mov r0, #BSP_UTXINT2 + b get_handler + +check_urx2: +#if 0 +MUST REMEMBER TO UNCOMMENT IF THIS HANDLER MOVES + ldr r4, [r2, #0x240] + ldr r5, [r2, #0x280] + and r6, r4, r5 /* only look at interrupts which are enabled */ +#endif + tst r6, #0x2000 + beq IRQ_NoInterrupt + mov r0, #BSP_URXINT2 + b get_handler + +get_handler: + + ldmia sp!,{r4, r5, r6} + + /* + * re-enable interrupts at processor level as the current + * interrupt source is now masked via VEGA logic + */ +/* + mrs r1, cpsr + and r1, r1, #0xFFFFFF3F + msr cpsr, r1 +*/ + + stmdb sp!,{lr} + bl edb7312_interrupt_dispatch + ldmia sp!,{lr} + +IRQ_NoInterrupt: + /* return to the "main" interrupt handler */ + mov pc, lr diff --git a/bsps/arm/edb7312/irq/irq.c b/bsps/arm/edb7312/irq/irq.c new file mode 100644 index 0000000000..1d9151a1bd --- /dev/null +++ b/bsps/arm/edb7312/irq/irq.c @@ -0,0 +1,180 @@ +/* + * Cirrus EP7312 Intererrupt handler + */ + +/* + * Copyright (c) 2010 embedded brains GmbH. + * + * Copyright (c) 2002 by Jay Monkman + * + * Copyright (c) 2002 by Charlie Steader + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.org/license/LICENSE. +*/ + +#include + +#include +#include +#include + +#include + +void edb7312_interrupt_dispatch(rtems_vector_number vector) +{ + bsp_interrupt_handler_dispatch(vector); +} + +void bsp_interrupt_vector_enable(rtems_vector_number vector) +{ + bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector)); + + if(vector >= BSP_EXTFIQ && vector <= BSP_SSEOTI) + { + /* interrupt managed by INTMR1 and INTSR1 */ + *EP7312_INTMR1 |= (1 << vector); + } + else if(vector >= BSP_KBDINT && vector <= BSP_SS2TX) + { + /* interrupt managed by INTMR2 and INTSR2 */ + *EP7312_INTMR2 |= (1 << (vector - 16)); + } + else if(vector >= BSP_UTXINT2 && vector <= BSP_URXINT2) + { + /* interrupt managed by INTMR2 and INTSR2 */ + *EP7312_INTMR2 |= (1 << (vector - 7)); + } + else if(vector == BSP_DAIINT) + { + /* interrupt managed by INTMR3 and INTSR3 */ + *EP7312_INTMR3 |= (1 << (vector - 21)); + } +} + +void bsp_interrupt_vector_disable(rtems_vector_number vector) +{ + bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector)); + + if(vector >= BSP_EXTFIQ && vector <= BSP_SSEOTI) + { + /* interrupt managed by INTMR1 and INTSR1 */ + *EP7312_INTMR1 &= ~(1 << vector); + } + else if(vector >= BSP_KBDINT && vector <= BSP_SS2TX) + { + /* interrupt managed by INTMR2 and INTSR2 */ + *EP7312_INTMR2 &= ~(1 << (vector - 16)); + } + else if(vector >= BSP_UTXINT2 && vector <= BSP_URXINT2) + { + /* interrupt managed by INTMR2 and INTSR2 */ + *EP7312_INTMR2 &= ~(1 << (vector - 7)); + } + else if(vector == BSP_DAIINT) + { + /* interrupt managed by INTMR3 and INTSR3 */ + *EP7312_INTMR3 &= ~(1 << (vector - 21)); + } +} + +rtems_status_code bsp_interrupt_facility_initialize(void) +{ + uint32_t int_stat = 0; + + /* mask all interrupts */ + *EP7312_INTMR1 = 0x0; + *EP7312_INTMR2 = 0x0; + *EP7312_INTMR3 = 0x0; + + /* clear all pending interrupt status' */ + int_stat = *EP7312_INTSR1; + if(int_stat & EP7312_INTR1_EXTFIQ) + { + } + if(int_stat & EP7312_INTR1_BLINT) + { + *EP7312_BLEOI = 0xFFFFFFFF; + } + if(int_stat & EP7312_INTR1_WEINT) + { + *EP7312_TEOI = 0xFFFFFFFF; + } + if(int_stat & EP7312_INTR1_MCINT) + { + } + if(int_stat & EP7312_INTR1_CSINT) + { + *EP7312_COEOI = 0xFFFFFFFF; + } + if(int_stat & EP7312_INTR1_EINT1) + { + } + if(int_stat & EP7312_INTR1_EINT2) + { + } + if(int_stat & EP7312_INTR1_EINT3) + { + } + if(int_stat & EP7312_INTR1_TC1OI) + { + *EP7312_TC1EOI = 0xFFFFFFFF; + } + if(int_stat & EP7312_INTR1_TC2OI) + { + *EP7312_TC2EOI = 0xFFFFFFFF; + } + if(int_stat & EP7312_INTR1_RTCMI) + { + *EP7312_RTCEOI = 0xFFFFFFFF; + } + if(int_stat & EP7312_INTR1_TINT) + { + *EP7312_TEOI = 0xFFFFFFFF; + } + if(int_stat & EP7312_INTR1_URXINT1) + { + } + if(int_stat & EP7312_INTR1_UTXINT1) + { + } + if(int_stat & EP7312_INTR1_UMSINT) + { + *EP7312_UMSEOI = 0xFFFFFFFF; + } + if(int_stat & EP7312_INTR1_SSEOTI) + { + *EP7312_SYNCIO; + } + int_stat = *EP7312_INTSR1; + + int_stat = *EP7312_INTSR2; + if(int_stat & EP7312_INTR2_KBDINT) + { + *EP7312_KBDEOI = 0xFFFFFFFF; + } + if(int_stat & EP7312_INTR2_SS2RX) + { + } + if(int_stat & EP7312_INTR2_SS2TX) + { + } + if(int_stat & EP7312_INTR2_URXINT2) + { + } + if(int_stat & EP7312_INTR2_UTXINT2) + { + } + int_stat = *EP7312_INTSR2; + + int_stat = *EP7312_INTSR3; + if(int_stat & EP7312_INTR2_DAIINT) + { + } + int_stat = *EP7312_INTSR3; + + _CPU_ISR_install_vector(ARM_EXCEPTION_IRQ, _ARMV4_Exception_interrupt, NULL); + + return RTEMS_SUCCESSFUL; +} diff --git a/bsps/arm/gdbarmsim/irq/irq-dispatch.c b/bsps/arm/gdbarmsim/irq/irq-dispatch.c new file mode 100644 index 0000000000..f045fb8149 --- /dev/null +++ b/bsps/arm/gdbarmsim/irq/irq-dispatch.c @@ -0,0 +1,50 @@ +/** + * @file + * + * @ingroup bsp_interrupt + * + * @brief GDB ARM Simulator interrupt support. + */ + +/* + * Copyright (c) 2008-2012 embedded brains GmbH. All rights reserved. + * + * embedded brains GmbH + * Obere Lagerstr. 30 + * 82178 Puchheim + * Germany + * + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.org/license/LICENSE. + */ + +#include + +#include +#include +#include + +#ifdef ARM_MULTILIB_ARCH_V4 + +void bsp_interrupt_dispatch(void) +{ + /* Read current vector number */ + /* rtems_vector_number vector = VICVectAddr; */ + rtems_vector_number vector = 0; + + /* Enable interrupts in program status register */ + uint32_t psr = _ARMV4_Status_irq_enable(); + + /* Dispatch interrupt handlers */ + bsp_interrupt_handler_dispatch(vector); + + /* Restore program status register */ + _ARMV4_Status_restore(psr); + + /* Acknowledge interrupt */ + //VICVectAddr = 0; +} + +#endif /* ARM_MULTILIB_ARCH_V4 */ diff --git a/bsps/arm/gdbarmsim/irq/irq.c b/bsps/arm/gdbarmsim/irq/irq.c new file mode 100644 index 0000000000..886f928d2d --- /dev/null +++ b/bsps/arm/gdbarmsim/irq/irq.c @@ -0,0 +1,71 @@ +/** + * @file + * + * @ingroup bsp_interrupt + * + * @brief GDB ARM Simulator interrupt support. + */ + +/* + * Copyright (c) 2008-2012 embedded brains GmbH. All rights reserved. + * + * embedded brains GmbH + * Obere Lagerstr. 30 + * 82178 Puchheim + * Germany + * + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.org/license/LICENSE. + */ + +#include +#include + +#include +#include +#include +#include + +/* + * Prototypes + */ +void lpc24xx_irq_set_priority(rtems_vector_number, unsigned); +unsigned lpc24xx_irq_get_priority(rtems_vector_number); + +static inline bool lpc24xx_irq_is_valid(rtems_vector_number vector) +{ + return vector <= BSP_INTERRUPT_VECTOR_MAX; +} + +void lpc24xx_irq_set_priority(rtems_vector_number vector, unsigned priority) +{ +} + +unsigned lpc24xx_irq_get_priority(rtems_vector_number vector) +{ + return 0; /* bogus value to avoid warning */ +} + +#ifdef ARM_MULTILIB_ARCH_V4 + +void bsp_interrupt_vector_enable(rtems_vector_number vector) +{ + bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector)); +} + +void bsp_interrupt_vector_disable(rtems_vector_number vector) +{ + bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector)); +} + +rtems_status_code bsp_interrupt_facility_initialize(void) +{ + /* Install the IRQ exception handler */ + _CPU_ISR_install_vector(ARM_EXCEPTION_IRQ, _ARMV4_Exception_interrupt, NULL); + + return RTEMS_SUCCESSFUL; +} + +#endif /* ARM_MULTILIB_ARCH_V4 */ diff --git a/bsps/arm/gumstix/irq/irq.c b/bsps/arm/gumstix/irq/irq.c new file mode 100644 index 0000000000..425795b165 --- /dev/null +++ b/bsps/arm/gumstix/irq/irq.c @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2010 embedded brains GmbH. + * + * PXA255 Interrupt handler by Yang Xi + * Copyright (c) 2004 by Jay Monkman + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.org/license/LICENSE. + */ + +#include + +#include +#include +#include + +#include + +void bsp_interrupt_dispatch(void) +{ + rtems_vector_number vector = 31 - __builtin_clz(XSCALE_INT_ICIP); + + bsp_interrupt_handler_dispatch(vector); +} + +void bsp_interrupt_vector_enable(rtems_vector_number vector) +{ + bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector)); + XSCALE_INT_ICMR |= 1 << vector; +} + +void bsp_interrupt_vector_disable(rtems_vector_number vector) +{ + bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector)); + XSCALE_INT_ICMR &= ~(1 << vector); +} + +rtems_status_code bsp_interrupt_facility_initialize(void) +{ + /* disable all interrupts */ + XSCALE_INT_ICMR = 0x0; + + /* Direct the interrupt to IRQ*/ + XSCALE_INT_ICLR = 0x0; + + /* Install the IRQ exception handler */ + _CPU_ISR_install_vector(ARM_EXCEPTION_IRQ, _ARMV4_Exception_interrupt, NULL); + + return RTEMS_SUCCESSFUL; +} diff --git a/bsps/arm/lpc176x/irq/irq.c b/bsps/arm/lpc176x/irq/irq.c new file mode 100644 index 0000000000..e05fd59e6c --- /dev/null +++ b/bsps/arm/lpc176x/irq/irq.c @@ -0,0 +1,75 @@ +/** + * @file + * + * @ingroup bsp_interrupt + * + * @brief LPC176X interrupt support. + */ + +/* + * Copyright (c) 2008-2012 embedded brains GmbH. All rights reserved. + * + * embedded brains GmbH + * Obere Lagerstr. 30 + * 82178 Puchheim + * Germany + * + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.org/license/LICENSE. + */ + +#include +#include + +#include +#include +#include +#include +#include + +/** + * @brief Checks if the current interrupt vector length is valid or not. + * + * @param vector The current interrupt vector length. + * @return TRUE if valid. + * FALSE otherwise. + */ +static inline bool lpc176x_irq_is_valid( const rtems_vector_number vector ) +{ + return vector <= BSP_INTERRUPT_VECTOR_MAX; +} + +void lpc176x_irq_set_priority( + const rtems_vector_number vector, + unsigned priority +) +{ + if ( lpc176x_irq_is_valid( vector ) ) { + if ( priority > LPC176X_IRQ_PRIORITY_VALUE_MAX ) { + priority = LPC176X_IRQ_PRIORITY_VALUE_MAX; + } + + /* else implies that the priority is unlocked. Also, + there is nothing to do. */ + + _ARMV7M_NVIC_Set_priority( (int) vector, (int) ( priority << 3u ) ); + } + + /* else implies that the rtems vector number is invalid. Also, + there is nothing to do. */ +} + +unsigned lpc176x_irq_get_priority( const rtems_vector_number vector ) +{ + unsigned priority; + + if ( lpc176x_irq_is_valid( vector ) ) { + priority = (unsigned) ( _ARMV7M_NVIC_Get_priority( (int) vector ) >> 3u ); + } else { + priority = LPC176X_IRQ_PRIORITY_VALUE_MIN - 1u; + } + + return priority; +} diff --git a/bsps/arm/lpc24xx/irq/irq-dispatch.c b/bsps/arm/lpc24xx/irq/irq-dispatch.c new file mode 100644 index 0000000000..66d05fdf9d --- /dev/null +++ b/bsps/arm/lpc24xx/irq/irq-dispatch.c @@ -0,0 +1,50 @@ +/** + * @file + * + * @ingroup bsp_interrupt + * + * @brief LPC24XX interrupt support. + */ + +/* + * Copyright (c) 2008-2012 embedded brains GmbH. All rights reserved. + * + * embedded brains GmbH + * Obere Lagerstr. 30 + * 82178 Puchheim + * Germany + * + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.org/license/LICENSE. + */ + +#include + +#include +#include +#include +#include + +#ifdef ARM_MULTILIB_ARCH_V4 + +void bsp_interrupt_dispatch(void) +{ + /* Read current vector number */ + rtems_vector_number vector = VICVectAddr; + + /* Enable interrupts in program status register */ + uint32_t psr = _ARMV4_Status_irq_enable(); + + /* Dispatch interrupt handlers */ + bsp_interrupt_handler_dispatch(vector); + + /* Restore program status register */ + _ARMV4_Status_restore(psr); + + /* Acknowledge interrupt */ + VICVectAddr = 0; +} + +#endif /* ARM_MULTILIB_ARCH_V4 */ diff --git a/bsps/arm/lpc24xx/irq/irq.c b/bsps/arm/lpc24xx/irq/irq.c new file mode 100644 index 0000000000..7801c37843 --- /dev/null +++ b/bsps/arm/lpc24xx/irq/irq.c @@ -0,0 +1,120 @@ +/** + * @file + * + * @ingroup bsp_interrupt + * + * @brief LPC24XX interrupt support. + */ + +/* + * Copyright (c) 2008-2012 embedded brains GmbH. All rights reserved. + * + * embedded brains GmbH + * Obere Lagerstr. 30 + * 82178 Puchheim + * Germany + * + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.org/license/LICENSE. + */ + +#include +#include + +#include +#include +#include +#include +#include + +static inline bool lpc24xx_irq_is_valid(rtems_vector_number vector) +{ + return vector <= BSP_INTERRUPT_VECTOR_MAX; +} + +void lpc24xx_irq_set_priority(rtems_vector_number vector, unsigned priority) +{ + if (lpc24xx_irq_is_valid(vector)) { + if (priority > LPC24XX_IRQ_PRIORITY_VALUE_MAX) { + priority = LPC24XX_IRQ_PRIORITY_VALUE_MAX; + } + + #ifdef ARM_MULTILIB_ARCH_V4 + VICVectPriorityBase [vector] = priority; + #else + _ARMV7M_NVIC_Set_priority((int) vector, (int) (priority << 3)); + #endif + } +} + +unsigned lpc24xx_irq_get_priority(rtems_vector_number vector) +{ + if (lpc24xx_irq_is_valid(vector)) { + #ifdef ARM_MULTILIB_ARCH_V4 + return VICVectPriorityBase [vector]; + #else + return (unsigned) (_ARMV7M_NVIC_Get_priority((int) vector) >> 3); + #endif + } else { + return LPC24XX_IRQ_PRIORITY_VALUE_MIN - 1U; + } +} + +#ifdef ARM_MULTILIB_ARCH_V4 + +void bsp_interrupt_vector_enable(rtems_vector_number vector) +{ + bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector)); + VICIntEnable = 1U << vector; +} + +void bsp_interrupt_vector_disable(rtems_vector_number vector) +{ + bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector)); + VICIntEnClear = 1U << vector; +} + +rtems_status_code bsp_interrupt_facility_initialize(void) +{ + volatile uint32_t *addr = VICVectAddrBase; + volatile uint32_t *prio = VICVectPriorityBase; + rtems_vector_number i = 0; + + /* Disable all interrupts */ + VICIntEnClear = 0xffffffff; + + /* Clear all software interrupts */ + VICSoftIntClear = 0xffffffff; + + /* Use IRQ category */ + VICIntSelect = 0; + + for (i = BSP_INTERRUPT_VECTOR_MIN; i <= BSP_INTERRUPT_VECTOR_MAX; ++i) { + /* Use the vector address register to store the vector number */ + addr [i] = i; + + /* Give vector lowest priority */ + prio [i] = 15; + } + + /* Reset priority mask register */ + VICSWPrioMask = 0xffff; + + /* Acknowledge interrupts for all priorities */ + for ( + i = LPC24XX_IRQ_PRIORITY_VALUE_MIN; + i <= LPC24XX_IRQ_PRIORITY_VALUE_MAX; + ++i + ) { + VICVectAddr = 0; + } + + /* Install the IRQ exception handler */ + _CPU_ISR_install_vector(ARM_EXCEPTION_IRQ, _ARMV4_Exception_interrupt, NULL); + + return RTEMS_SUCCESSFUL; +} + +#endif /* ARM_MULTILIB_ARCH_V4 */ diff --git a/bsps/arm/lpc32xx/irq/irq.c b/bsps/arm/lpc32xx/irq/irq.c new file mode 100755 index 0000000000..eac320000b --- /dev/null +++ b/bsps/arm/lpc32xx/irq/irq.c @@ -0,0 +1,344 @@ +/** + * @file + * + * @ingroup lpc32xx_interrupt + * + * @brief Interrupt support. + */ + +/* + * Copyright (c) 2009 + * embedded brains GmbH + * Obere Lagerstr. 30 + * D-82178 Puchheim + * Germany + * + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.org/license/LICENSE. + */ + +#include + +#include +#include +#include +#include +#include +#include + +/* + * Mask out SIC 1 and 2 IRQ request. There is no need to mask out the FIQ, + * since a pending FIQ would be a fatal error. The default handler will be + * invoked in this case. + */ +#define LPC32XX_MIC_STATUS_MASK (~0x3U) + +typedef union { + struct { + uint32_t mic; + uint32_t sic_1; + uint32_t sic_2; + } field; + uint32_t fields_table [LPC32XX_IRQ_MODULE_COUNT]; +} lpc32xx_irq_fields; + +static uint8_t lpc32xx_irq_priority_table [LPC32XX_IRQ_COUNT]; + +static lpc32xx_irq_fields lpc32xx_irq_priority_masks [LPC32XX_IRQ_PRIORITY_COUNT]; + +static lpc32xx_irq_fields lpc32xx_irq_enable; + +static inline bool lpc32xx_irq_priority_is_valid(unsigned priority) +{ + return priority <= LPC32XX_IRQ_PRIORITY_LOWEST; +} + +#define LPC32XX_IRQ_BIT_OPS_DEFINE \ + unsigned bit = index & 0x1fU; \ + unsigned module = index >> 5 + +#define LPC32XX_IRQ_BIT_OPS_FOR_REG_DEFINE \ + LPC32XX_IRQ_BIT_OPS_DEFINE; \ + unsigned module_offset = module << 14; \ + volatile uint32_t *reg = (volatile uint32_t *) \ + ((volatile char *) &lpc32xx.mic + module_offset + register_offset) + +#define LPC32XX_IRQ_OFFSET_ER 0U +#define LPC32XX_IRQ_OFFSET_RSR 4U +#define LPC32XX_IRQ_OFFSET_SR 8U +#define LPC32XX_IRQ_OFFSET_APR 12U +#define LPC32XX_IRQ_OFFSET_ATR 16U +#define LPC32XX_IRQ_OFFSET_ITR 20U + +static inline bool lpc32xx_irq_is_bit_set_in_register(unsigned index, unsigned register_offset) +{ + LPC32XX_IRQ_BIT_OPS_FOR_REG_DEFINE; + + return *reg & (1U << bit); +} + +static inline void lpc32xx_irq_set_bit_in_register(unsigned index, unsigned register_offset) +{ + LPC32XX_IRQ_BIT_OPS_FOR_REG_DEFINE; + + *reg |= 1U << bit; +} + +static inline void lpc32xx_irq_clear_bit_in_register(unsigned index, unsigned register_offset) +{ + LPC32XX_IRQ_BIT_OPS_FOR_REG_DEFINE; + + *reg &= ~(1U << bit); +} + +static inline void lpc32xx_irq_set_bit_in_field(unsigned index, lpc32xx_irq_fields *fields) +{ + LPC32XX_IRQ_BIT_OPS_DEFINE; + + fields->fields_table [module] |= 1U << bit; +} + +static inline void lpc32xx_irq_clear_bit_in_field(unsigned index, lpc32xx_irq_fields *fields) +{ + LPC32XX_IRQ_BIT_OPS_DEFINE; + + fields->fields_table [module] &= ~(1U << bit); +} + +static inline unsigned lpc32xx_irq_get_index(uint32_t val) +{ + ARM_SWITCH_REGISTERS; + + __asm__ volatile ( + ARM_SWITCH_TO_ARM + "clz %[val], %[val]\n" + "rsb %[val], %[val], #31\n" + ARM_SWITCH_BACK + : [val] "=r" (val) ARM_SWITCH_ADDITIONAL_OUTPUT + : "[val]" (val) + ); + + return val; +} + +void lpc32xx_irq_set_priority(rtems_vector_number vector, unsigned priority) +{ + if (bsp_interrupt_is_valid_vector(vector)) { + rtems_interrupt_level level; + unsigned i = 0; + + if (priority > LPC32XX_IRQ_PRIORITY_LOWEST) { + priority = LPC32XX_IRQ_PRIORITY_LOWEST; + } + + lpc32xx_irq_priority_table [vector] = (uint8_t) priority; + + for (i = LPC32XX_IRQ_PRIORITY_HIGHEST; i <= priority; ++i) { + rtems_interrupt_disable(level); + lpc32xx_irq_clear_bit_in_field(vector, &lpc32xx_irq_priority_masks [i]); + rtems_interrupt_enable(level); + } + + for (i = priority + 1; i <= LPC32XX_IRQ_PRIORITY_LOWEST; ++i) { + rtems_interrupt_disable(level); + lpc32xx_irq_set_bit_in_field(vector, &lpc32xx_irq_priority_masks [i]); + rtems_interrupt_enable(level); + } + } +} + +unsigned lpc32xx_irq_get_priority(rtems_vector_number vector) +{ + if (bsp_interrupt_is_valid_vector(vector)) { + return lpc32xx_irq_priority_table [vector]; + } else { + return LPC32XX_IRQ_PRIORITY_LOWEST; + } +} + +void lpc32xx_irq_set_activation_polarity(rtems_vector_number vector, lpc32xx_irq_activation_polarity activation_polarity) +{ + if (bsp_interrupt_is_valid_vector(vector)) { + rtems_interrupt_level level; + + rtems_interrupt_disable(level); + if (activation_polarity == LPC32XX_IRQ_ACTIVE_HIGH_OR_RISING_EDGE) { + lpc32xx_irq_set_bit_in_register(vector, LPC32XX_IRQ_OFFSET_APR); + } else { + lpc32xx_irq_clear_bit_in_register(vector, LPC32XX_IRQ_OFFSET_APR); + } + rtems_interrupt_enable(level); + } +} + +lpc32xx_irq_activation_polarity lpc32xx_irq_get_activation_polarity(rtems_vector_number vector) +{ + if (bsp_interrupt_is_valid_vector(vector)) { + if (lpc32xx_irq_is_bit_set_in_register(vector, LPC32XX_IRQ_OFFSET_APR)) { + return LPC32XX_IRQ_ACTIVE_HIGH_OR_RISING_EDGE; + } else { + return LPC32XX_IRQ_ACTIVE_LOW_OR_FALLING_EDGE; + } + } else { + return LPC32XX_IRQ_ACTIVE_LOW_OR_FALLING_EDGE; + } +} + +void lpc32xx_irq_set_activation_type(rtems_vector_number vector, lpc32xx_irq_activation_type activation_type) +{ + if (bsp_interrupt_is_valid_vector(vector)) { + rtems_interrupt_level level; + + rtems_interrupt_disable(level); + if (activation_type == LPC32XX_IRQ_EDGE_SENSITIVE) { + lpc32xx_irq_set_bit_in_register(vector, LPC32XX_IRQ_OFFSET_ATR); + } else { + lpc32xx_irq_clear_bit_in_register(vector, LPC32XX_IRQ_OFFSET_ATR); + } + rtems_interrupt_enable(level); + } +} + +lpc32xx_irq_activation_type lpc32xx_irq_get_activation_type(rtems_vector_number vector) +{ + if (bsp_interrupt_is_valid_vector(vector)) { + if (lpc32xx_irq_is_bit_set_in_register(vector, LPC32XX_IRQ_OFFSET_ATR)) { + return LPC32XX_IRQ_EDGE_SENSITIVE; + } else { + return LPC32XX_IRQ_LEVEL_SENSITIVE; + } + } else { + return LPC32XX_IRQ_LEVEL_SENSITIVE; + } +} + +void bsp_interrupt_dispatch(void) +{ + uint32_t status = lpc32xx.mic.sr & LPC32XX_MIC_STATUS_MASK; + uint32_t er_mic = lpc32xx.mic.er; + uint32_t er_sic_1 = lpc32xx.sic_1.er; + uint32_t er_sic_2 = lpc32xx.sic_2.er; + uint32_t psr = 0; + lpc32xx_irq_fields *masks = NULL; + rtems_vector_number vector = 0; + unsigned priority = 0; + + if (status != 0) { + vector = lpc32xx_irq_get_index(status); + } else { + status = lpc32xx.sic_1.sr; + if (status != 0) { + vector = lpc32xx_irq_get_index(status) + LPC32XX_IRQ_MODULE_SIC_1; + } else { + status = lpc32xx.sic_2.sr; + if (status != 0) { + vector = lpc32xx_irq_get_index(status) + LPC32XX_IRQ_MODULE_SIC_2; + } else { + return; + } + } + } + + priority = lpc32xx_irq_priority_table [vector]; + + masks = &lpc32xx_irq_priority_masks [priority]; + + lpc32xx.mic.er = er_mic & masks->field.mic; + lpc32xx.sic_1.er = er_sic_1 & masks->field.sic_1; + lpc32xx.sic_2.er = er_sic_2 & masks->field.sic_2; + + psr = _ARMV4_Status_irq_enable(); + + bsp_interrupt_handler_dispatch(vector); + + _ARMV4_Status_restore(psr); + + lpc32xx.mic.er = er_mic & lpc32xx_irq_enable.field.mic; + lpc32xx.sic_1.er = er_sic_1 & lpc32xx_irq_enable.field.sic_1; + lpc32xx.sic_2.er = er_sic_2 & lpc32xx_irq_enable.field.sic_2; +} + +void bsp_interrupt_vector_enable(rtems_vector_number vector) +{ + rtems_interrupt_level level; + + bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector)); + + rtems_interrupt_disable(level); + lpc32xx_irq_set_bit_in_register(vector, LPC32XX_IRQ_OFFSET_ER); + lpc32xx_irq_set_bit_in_field(vector, &lpc32xx_irq_enable); + rtems_interrupt_enable(level); +} + +void bsp_interrupt_vector_disable(rtems_vector_number vector) +{ + rtems_interrupt_level level; + + bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector)); + + rtems_interrupt_disable(level); + lpc32xx_irq_clear_bit_in_field(vector, &lpc32xx_irq_enable); + lpc32xx_irq_clear_bit_in_register(vector, LPC32XX_IRQ_OFFSET_ER); + rtems_interrupt_enable(level); +} + +void lpc32xx_set_exception_handler( + Arm_symbolic_exception_name exception, + void (*handler)(void) +) +{ + if ((unsigned) exception < MAX_EXCEPTIONS) { + uint32_t *table = (uint32_t *) bsp_vector_table_begin + MAX_EXCEPTIONS; + + table [exception] = (uint32_t) handler; + + #ifndef LPC32XX_DISABLE_MMU + rtems_cache_flush_multiple_data_lines(table, 64); + rtems_cache_invalidate_multiple_instruction_lines(NULL, 64); + #endif + } +} + +rtems_status_code bsp_interrupt_facility_initialize(void) +{ + size_t i = 0; + + /* Set default priority */ + for (i = 0; i < LPC32XX_IRQ_COUNT; ++i) { + lpc32xx_irq_priority_table [i] = LPC32XX_IRQ_PRIORITY_LOWEST; + } + + /* Enable SIC 1 and 2 at all priorities */ + for (i = 0; i < LPC32XX_IRQ_PRIORITY_COUNT; ++i) { + lpc32xx_irq_priority_masks [i].field.mic = 0xc0000003; + } + + /* Disable all interrupts except SIC 1 and 2 */ + lpc32xx_irq_enable.field.sic_2 = 0x0; + lpc32xx_irq_enable.field.sic_1 = 0x0; + lpc32xx_irq_enable.field.mic = 0xc0000003; + lpc32xx.sic_1.er = 0x0; + lpc32xx.sic_2.er = 0x0; + lpc32xx.mic.er = 0xc0000003; + + /* Set interrupt types to IRQ */ + lpc32xx.mic.itr = 0x0; + lpc32xx.sic_1.itr = 0x0; + lpc32xx.sic_2.itr = 0x0; + + /* Set interrupt activation polarities */ + lpc32xx.mic.apr = 0x3ff0efe0; + lpc32xx.sic_1.apr = 0xfbd27184; + lpc32xx.sic_2.apr = 0x801810c0; + + /* Set interrupt activation types */ + lpc32xx.mic.atr = 0x0; + lpc32xx.sic_1.atr = 0x26000; + lpc32xx.sic_2.atr = 0x0; + + lpc32xx_set_exception_handler(ARM_EXCEPTION_IRQ, _ARMV4_Exception_interrupt); + + return RTEMS_SUCCESSFUL; +} diff --git a/bsps/arm/raspberrypi/irq/irq.c b/bsps/arm/raspberrypi/irq/irq.c new file mode 100644 index 0000000000..5b10385bfe --- /dev/null +++ b/bsps/arm/raspberrypi/irq/irq.c @@ -0,0 +1,168 @@ +/** + * @file irq.c + * + * @ingroup raspberrypi_interrupt + * + * @brief Interrupt support. + */ + +/* + * Copyright (c) 2014 Andre Marques + * + * Copyright (c) 2009 + * embedded brains GmbH + * Obere Lagerstr. 30 + * D-82178 Puchheim + * Germany + * + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.org/license/LICENSE. + */ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef RTEMS_SMP +#include +#include +#endif + +typedef struct { + unsigned long enable_reg_addr; + unsigned long disable_reg_addr; +} bcm2835_irq_ctrl_reg_t; + +static const bcm2835_irq_ctrl_reg_t bcm2835_irq_ctrl_reg_table[] = { + { BCM2835_IRQ_ENABLE1, BCM2835_IRQ_DISABLE1 }, + { BCM2835_IRQ_ENABLE2, BCM2835_IRQ_DISABLE2 }, + { BCM2835_IRQ_ENABLE_BASIC, BCM2835_IRQ_DISABLE_BASIC } +}; + +static inline const bcm2835_irq_ctrl_reg_t * +bsp_vector_to_reg(rtems_vector_number vector) +{ + return bcm2835_irq_ctrl_reg_table + (vector >> 5); +} + +static inline uint32_t +bsp_vector_to_mask(rtems_vector_number vector) +{ + return 1 << (vector & 0x1f); +} + +static const int bcm2835_irq_speedup_table[] = +{ + /* 0 */ BCM2835_IRQ_ID_BASIC_BASE_ID + 0, + /* 1 */ BCM2835_IRQ_ID_BASIC_BASE_ID + 1, + /* 2 */ BCM2835_IRQ_ID_BASIC_BASE_ID + 2, + /* 3 */ BCM2835_IRQ_ID_BASIC_BASE_ID + 3, + /* 4 */ BCM2835_IRQ_ID_BASIC_BASE_ID + 4, + /* 5 */ BCM2835_IRQ_ID_BASIC_BASE_ID + 5, + /* 6 */ BCM2835_IRQ_ID_BASIC_BASE_ID + 6, + /* 7 */ BCM2835_IRQ_ID_BASIC_BASE_ID + 7, + /* 8 */ -1, /* One or more bits set in pending register 1 */ + /* 9 */ -2, /* One or more bits set in pending register 2 */ + /* 10 */ 7, /* GPU IRQ 7 */ + /* 11 */ 9, /* GPU IRQ 9 */ + /* 12 */ 10, /* GPU IRQ 10 */ + /* 13 */ 18, /* GPU IRQ 18 */ + /* 14 */ 19, /* GPU IRQ 19 */ + /* 15 */ 53, /* GPU IRQ 53 */ + /* 16 */ 54, /* GPU IRQ 54 */ + /* 17 */ 55, /* GPU IRQ 55 */ + /* 18 */ 56, /* GPU IRQ 56 */ + /* 19 */ 57, /* GPU IRQ 57 */ + /* 20 */ 62, /* GPU IRQ 62 */ +}; + +/* + * Define which basic peding register (BCM2835_IRQ_BASIC) bits + * should be processed through bcm2835_irq_speedup_table + */ + +#define BCM2835_IRQ_BASIC_SPEEDUP_USED_BITS 0x1ffcff + +/* + * Determine the source of the interrupt and dispatch the correct handler. + */ +void bsp_interrupt_dispatch(void) +{ + unsigned int pend; + unsigned int pend_bit; + + rtems_vector_number vector = 255; + +#ifdef RTEMS_SMP + uint32_t cpu_index_self = _SMP_Get_current_processor(); + uint32_t local_source = BCM2835_REG(BCM2836_IRQ_SOURCE_REG(cpu_index_self)); + + if ( local_source & BCM2836_IRQ_SOURCE_MBOX3 ) { + /* reset mailbox 3 contents to zero */ + BCM2835_REG(BCM2836_MAILBOX_3_READ_CLEAR_BASE + 0x10 * cpu_index_self) = 0xffffffff; + _SMP_Inter_processor_interrupt_handler(); + } + if ( cpu_index_self != 0 ) + return; +#endif /* RTEMS_SMP */ + + pend = BCM2835_REG(BCM2835_IRQ_BASIC); + if ( pend & BCM2835_IRQ_BASIC_SPEEDUP_USED_BITS ) { + pend_bit = ffs(pend) - 1; + vector = bcm2835_irq_speedup_table[pend_bit]; + } else { + pend = BCM2835_REG(BCM2835_IRQ_PENDING1); + if ( pend != 0 ) { + pend_bit = ffs(pend) - 1; + vector = pend_bit; + } else { + pend = BCM2835_REG(BCM2835_IRQ_PENDING2); + if ( pend != 0 ) { + pend_bit = ffs(pend) - 1; + vector = pend_bit + 32; + } + } + } + + if ( vector < 255 ) + { + bsp_interrupt_handler_dispatch(vector); + } +} + +void bsp_interrupt_vector_enable(rtems_vector_number vector) +{ + bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector)); + BCM2835_REG(bsp_vector_to_reg(vector)->enable_reg_addr) = + bsp_vector_to_mask(vector); +} + +void bsp_interrupt_vector_disable(rtems_vector_number vector) +{ + bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector)); + BCM2835_REG(bsp_vector_to_reg(vector)->disable_reg_addr) = + bsp_vector_to_mask(vector); +} + +void bsp_interrupt_handler_default(rtems_vector_number vector) +{ + printk("spurious interrupt: %lu\n", vector); +} + +rtems_status_code bsp_interrupt_facility_initialize(void) +{ + BCM2835_REG(BCM2835_IRQ_DISABLE1) = 0xffffffff; + BCM2835_REG(BCM2835_IRQ_DISABLE2) = 0xffffffff; + BCM2835_REG(BCM2835_IRQ_DISABLE_BASIC) = 0xffffffff; + BCM2835_REG(BCM2835_IRQ_FIQ_CTRL) = 0; + return RTEMS_SUCCESSFUL; +} diff --git a/bsps/arm/rtl22xx/irq/irq.c b/bsps/arm/rtl22xx/irq/irq.c new file mode 100644 index 0000000000..83e140bd7b --- /dev/null +++ b/bsps/arm/rtl22xx/irq/irq.c @@ -0,0 +1,70 @@ +/* + * Philps LPC22XX Interrupt handler + * + * Copyright (c) 2010 embedded brains GmbH. + * + * Copyright (c) 2006 by Ray to support LPC ARM + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.org/license/LICENSE. + */ + +#include + +#include +#include +#include + +#include + +void bsp_interrupt_dispatch(void) +{ + rtems_vector_number vector = 31 - __builtin_clz(VICIRQStatus); + + bsp_interrupt_handler_dispatch(vector); + + VICVectAddr = 0; +} + +void bsp_interrupt_vector_enable(rtems_vector_number vector) +{ + bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector)); + VICIntEnable |= 1 << vector; +} + +void bsp_interrupt_vector_disable(rtems_vector_number vector) +{ + bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector)); + VICIntEnClr = 1 << vector; +} + +rtems_status_code bsp_interrupt_facility_initialize(void) +{ + volatile uint32_t *ctrl = (volatile uint32_t *) VICVectCntlBase; + size_t i = 0; + + /* Disable all interrupts */ + VICIntEnClr = 0xffffffff; + + /* Use IRQ category */ + VICIntSelect = 0; + + /* Enable access in USER mode */ + VICProtection = 0; + + for (i = 0; i < 16; ++i) { + /* Disable vector mode */ + ctrl [i] = 0; + + /* Acknowledge interrupts for all priorities */ + VICVectAddr = 0; + } + + /* Acknowledge interrupts for all priorities */ + VICVectAddr = 0; + + /* Install the IRQ exception handler */ + _CPU_ISR_install_vector(ARM_EXCEPTION_IRQ, _ARMV4_Exception_interrupt, NULL); + + return RTEMS_SUCCESSFUL; +} diff --git a/bsps/arm/shared/irq/irq-armv7m.c b/bsps/arm/shared/irq/irq-armv7m.c new file mode 100644 index 0000000000..99c0e373bf --- /dev/null +++ b/bsps/arm/shared/irq/irq-armv7m.c @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2011-2012 Sebastian Huber. All rights reserved. + * + * embedded brains GmbH + * Obere Lagerstr. 30 + * 82178 Puchheim + * Germany + * + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.org/license/LICENSE. + */ + +#include + +#include + +#include +#include +#include +#include +#include + +#ifdef ARM_MULTILIB_ARCH_V7M + +void bsp_interrupt_vector_enable(rtems_vector_number vector) +{ + bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector)); + _ARMV7M_NVIC_Set_enable((int) vector); +} + +void bsp_interrupt_vector_disable(rtems_vector_number vector) +{ + bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector)); + _ARMV7M_NVIC_Clear_enable((int) vector); +} + +rtems_status_code bsp_interrupt_facility_initialize(void) +{ + int i; + ARMV7M_Exception_handler *vector_table = + (ARMV7M_Exception_handler *) bsp_vector_table_begin; + + if (bsp_vector_table_begin != bsp_start_vector_table_begin) { + memcpy( + vector_table, + bsp_start_vector_table_begin, + (size_t) bsp_vector_table_size + ); + } + + _ARMV7M_SCB->icsr = ARMV7M_SCB_ICSR_PENDSVCLR | ARMV7M_SCB_ICSR_PENDSTCLR; + + for (i = BSP_INTERRUPT_VECTOR_MIN; i <= BSP_INTERRUPT_VECTOR_MAX; ++i) { + vector_table [ARMV7M_VECTOR_IRQ(i)] = _ARMV7M_NVIC_Interrupt_dispatch; + _ARMV7M_NVIC_Clear_enable(i); + _ARMV7M_NVIC_Clear_pending(i); + _ARMV7M_NVIC_Set_priority(i, BSP_ARMV7M_IRQ_PRIORITY_DEFAULT); + } + + _ARMV7M_SCB->vtor = vector_table; + + return RTEMS_SUCCESSFUL; +} + +#endif /* ARM_MULTILIB_ARCH_V7M */ diff --git a/bsps/arm/shared/irq/irq-dispatch-armv7m.c b/bsps/arm/shared/irq/irq-dispatch-armv7m.c new file mode 100644 index 0000000000..c810a9784a --- /dev/null +++ b/bsps/arm/shared/irq/irq-dispatch-armv7m.c @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2011-2012 Sebastian Huber. All rights reserved. + * + * embedded brains GmbH + * Obere Lagerstr. 30 + * 82178 Puchheim + * Germany + * + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.org/license/LICENSE. + */ + +#include + +#include +#include + +#ifdef ARM_MULTILIB_ARCH_V7M + +void _ARMV7M_NVIC_Interrupt_dispatch(void) +{ + rtems_vector_number vector = + ARMV7M_SCB_ICSR_VECTACTIVE_GET(_ARMV7M_SCB->icsr); + + _ARMV7M_Interrupt_service_enter(); + bsp_interrupt_handler_dispatch(ARMV7M_IRQ_OF_VECTOR(vector)); + _ARMV7M_Interrupt_service_leave(); +} + +#endif /* ARM_MULTILIB_ARCH_V7M */ diff --git a/bsps/arm/shared/irq/irq-gic.c b/bsps/arm/shared/irq/irq-gic.c new file mode 100644 index 0000000000..ea4b6ef06a --- /dev/null +++ b/bsps/arm/shared/irq/irq-gic.c @@ -0,0 +1,180 @@ +/* + * Copyright (c) 2013 embedded brains GmbH. All rights reserved. + * + * embedded brains GmbH + * Dornierstr. 4 + * 82178 Puchheim + * Germany + * + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.org/license/LICENSE. + */ + +#include + +#include + +#include + +#include +#include +#include + +#define GIC_CPUIF ((volatile gic_cpuif *) BSP_ARM_GIC_CPUIF_BASE) + +#define PRIORITY_DEFAULT 127 + +void bsp_interrupt_dispatch(void) +{ + volatile gic_cpuif *cpuif = GIC_CPUIF; + uint32_t icciar = cpuif->icciar; + rtems_vector_number vector = GIC_CPUIF_ICCIAR_ACKINTID_GET(icciar); + rtems_vector_number spurious = 1023; + + if (vector != spurious) { + uint32_t psr = _ARMV4_Status_irq_enable(); + + bsp_interrupt_handler_dispatch(vector); + + _ARMV4_Status_restore(psr); + + cpuif->icceoir = icciar; + } +} + +void bsp_interrupt_vector_enable(rtems_vector_number vector) +{ + volatile gic_dist *dist = ARM_GIC_DIST; + + bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector)); + + gic_id_enable(dist, vector); +} + +void bsp_interrupt_vector_disable(rtems_vector_number vector) +{ + volatile gic_dist *dist = ARM_GIC_DIST; + + bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector)); + + gic_id_disable(dist, vector); +} + +static inline uint32_t get_id_count(volatile gic_dist *dist) +{ + uint32_t id_count = GIC_DIST_ICDICTR_IT_LINES_NUMBER_GET(dist->icdictr); + + id_count = 32 * (id_count + 1); + id_count = id_count <= 1020 ? id_count : 1020; + + return id_count; +} + +rtems_status_code bsp_interrupt_facility_initialize(void) +{ + volatile gic_cpuif *cpuif = GIC_CPUIF; + volatile gic_dist *dist = ARM_GIC_DIST; + uint32_t id_count = get_id_count(dist); + uint32_t id; + + arm_cp15_set_exception_handler( + ARM_EXCEPTION_IRQ, + _ARMV4_Exception_interrupt + ); + + for (id = 0; id < id_count; id += 32) { + dist->icdicer[id / 32] = 0xffffffff; + } + + for (id = 0; id < id_count; ++id) { + gic_id_set_priority(dist, id, PRIORITY_DEFAULT); + } + + for (id = 32; id < id_count; ++id) { + gic_id_set_targets(dist, id, 0x01); + } + + cpuif->iccpmr = GIC_CPUIF_ICCPMR_PRIORITY(0xff); + cpuif->iccbpr = GIC_CPUIF_ICCBPR_BINARY_POINT(0x0); + cpuif->iccicr = GIC_CPUIF_ICCICR_ENABLE; + + dist->icddcr = GIC_DIST_ICDDCR_ENABLE; + + return RTEMS_SUCCESSFUL; +} + +#ifdef RTEMS_SMP +BSP_START_TEXT_SECTION void arm_gic_irq_initialize_secondary_cpu(void) +{ + volatile gic_cpuif *cpuif = GIC_CPUIF; + volatile gic_dist *dist = ARM_GIC_DIST; + + while ((dist->icddcr & GIC_DIST_ICDDCR_ENABLE) == 0) { + /* Wait */ + } + + cpuif->iccpmr = GIC_CPUIF_ICCPMR_PRIORITY(0xff); + cpuif->iccbpr = GIC_CPUIF_ICCBPR_BINARY_POINT(0x0); + cpuif->iccicr = GIC_CPUIF_ICCICR_ENABLE; +} +#endif + +rtems_status_code arm_gic_irq_set_priority( + rtems_vector_number vector, + uint8_t priority +) +{ + rtems_status_code sc = RTEMS_SUCCESSFUL; + + if (bsp_interrupt_is_valid_vector(vector)) { + volatile gic_dist *dist = ARM_GIC_DIST; + + gic_id_set_priority(dist, vector, priority); + } else { + sc = RTEMS_INVALID_ID; + } + + return sc; +} + +rtems_status_code arm_gic_irq_get_priority( + rtems_vector_number vector, + uint8_t *priority +) +{ + rtems_status_code sc = RTEMS_SUCCESSFUL; + + if (bsp_interrupt_is_valid_vector(vector)) { + volatile gic_dist *dist = ARM_GIC_DIST; + + *priority = gic_id_get_priority(dist, vector); + } else { + sc = RTEMS_INVALID_ID; + } + + return sc; +} + +void bsp_interrupt_set_affinity( + rtems_vector_number vector, + const Processor_mask *affinity +) +{ + volatile gic_dist *dist = ARM_GIC_DIST; + uint8_t targets = (uint8_t) _Processor_mask_To_uint32_t(affinity, 0); + + gic_id_set_targets(dist, vector, targets); +} + +void bsp_interrupt_get_affinity( + rtems_vector_number vector, + Processor_mask *affinity +) +{ + volatile gic_dist *dist = ARM_GIC_DIST; + uint8_t targets = gic_id_get_targets(dist, vector); + + _Processor_mask_From_uint32_t(affinity, targets, 0); +} diff --git a/bsps/arm/smdk2410/irq/irq.c b/bsps/arm/smdk2410/irq/irq.c new file mode 100644 index 0000000000..ea8f610353 --- /dev/null +++ b/bsps/arm/smdk2410/irq/irq.c @@ -0,0 +1,45 @@ +/* irq.c + * + * This file contains the implementation of the function described in irq.h + * + * Copyright (c) 2010 embedded brains GmbH. + * + * CopyRight (C) 2000 Canon Research France SA. + * Emmanuel Raguet, mailto:raguet@crf.canon.fr + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.org/license/LICENSE. + */ + +#include + +#include +#include +#include + +#include + +void bsp_interrupt_dispatch(void) +{ + rtems_vector_number vector = *((uint32_t *) rINTOFFSET_ADDR); + + bsp_interrupt_handler_dispatch(vector); +} + +void bsp_interrupt_vector_enable(rtems_vector_number vector) +{ + bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector)); +} + +void bsp_interrupt_vector_disable(rtems_vector_number vector) +{ + bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector)); +} + +rtems_status_code bsp_interrupt_facility_initialize(void) +{ + _CPU_ISR_install_vector(ARM_EXCEPTION_IRQ, _ARMV4_Exception_interrupt, NULL); + + return RTEMS_SUCCESSFUL; +} diff --git a/bsps/arm/tms570/irq/irq.c b/bsps/arm/tms570/irq/irq.c new file mode 100644 index 0000000000..579c11ed2a --- /dev/null +++ b/bsps/arm/tms570/irq/irq.c @@ -0,0 +1,202 @@ +/** + * @file irq.c + * + * @ingroup tms570 + * + * @brief TMS570 interrupt support functions definitions. + */ + +/* + * Copyright (c) 2014 Premysl Houdek + * + * Google Summer of Code 2014 at + * Czech Technical University in Prague + * Zikova 1903/4 + * 166 36 Praha 6 + * Czech Republic + * + * Based on LPC24xx and LPC1768 BSP + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.org/license/LICENSE. + */ + +#include +#include +#include +#include +#include + +unsigned int priorityTable[BSP_INTERRUPT_VECTOR_MAX+1]; + +/** + * @brief Set priority of the interrupt vector. + * + * This function is here because of compability. It should set + * priority of the interrupt vector. + * @warning It does not set any priority at HW layer. It is nearly imposible to + * @warning set priority of the interrupt on TMS570 in a nice way. + * @param[in] vector vector of isr + * @param[in] priority new priority assigned to the vector + * @return Void + */ +void tms570_irq_set_priority( + rtems_vector_number vector, + unsigned priority +) +{ + if ( bsp_interrupt_is_valid_vector(vector) ) { + priorityTable[vector] = priority; + } +} + +/** + * @brief Gets priority of the interrupt vector. + * + * This function is here because of compability. It returns priority + * of the isr vector last set by tms570_irq_set_priority function. + * + * @warning It does not return any real priority of the HW layer. + * @param[in] vector vector of isr + * @retval 0 vector is invalid. + * @retval priority priority of the interrupt + */ +unsigned tms570_irq_get_priority( + rtems_vector_number vector +) +{ + if ( bsp_interrupt_is_valid_vector(vector) ) { + return priorityTable[vector]; + } + return 0; +} + +/** + * @brief Interrupt dispatch + * + * Called by OS to determine which interrupt occured. + * Function passes control to interrupt handler. + * + * @return Void + */ +void bsp_interrupt_dispatch(void) +{ + rtems_vector_number vector = TMS570_VIM.IRQINDEX-1; + + bsp_interrupt_handler_dispatch(vector); +} + +/** + * @brief enables interrupt vector in the HW + * + * Enables HW interrupt for specified vector + * + * @param[in] vector vector of the isr which needs to be enabled. + * @retval RTEMS_INVALID_ID vector is invalid. + * @retval RTEMS_SUCCESSFUL interrupt source enabled. + */ +void bsp_interrupt_vector_enable( + rtems_vector_number vector +) +{ + bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector)); + TMS570_VIM.REQENASET[vector >> 5] = 1 << (vector & 0x1f); +} + +/** + * @brief disables interrupt vector in the HW + * + * Disables HW interrupt for specified vector + * + * @param[in] vector vector of the isr which needs to be disabled. + * @retval RTEMS_INVALID_ID vector is invalid. + * @retval RTEMS_SUCCESSFUL interrupt source disabled. + */ +void bsp_interrupt_vector_disable( + rtems_vector_number vector +) +{ + bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector)); + TMS570_VIM.REQENACLR[vector >> 5] = 1 << (vector & 0x1f); +} + +/** + * @brief Init function of interrupt module + * + * Resets vectored interrupt interface to default state. + * Disables all interrupts. + * Set all sources as IRQ (not FIR). + * + * @retval RTEMS_SUCCESSFUL All is set + */ +rtems_status_code bsp_interrupt_facility_initialize(void) +{ + void (**vim_vec)(void) = (void (**)(void)) 0xFFF82000; + unsigned int value = 0x00010203; + unsigned int i = 0; + uint32_t sctlr; + + /* Disable interrupts */ + for ( i = 0; i < 3; i++ ) { + TMS570_VIM.REQENACLR[i] = 0xffffffff; + } + /* Map default events on interrupt vectors */ + for ( i = 0; i < 24; i += 1, value += 0x04040404) { + TMS570_VIM.CHANCTRL[i] = value; + } + /* Set all vectors as IRQ (not FIR) */ + TMS570_VIM.FIRQPR[0] = 3; + TMS570_VIM.FIRQPR[1] = 0; + TMS570_VIM.FIRQPR[2] = 0; + + /* + _CPU_ISR_install_vector( + ARM_EXCEPTION_IRQ, + _ARMV4_Exception_interrupt, + NULL + ); + + Call to setup of interrupt entry in CPU level exception vectors table + is not used (necessary/possible) because the table is provided + by c/src/lib/libbsp/arm/shared/start/start.S and POM overlay + solution remaps that to address zero. + */ + + for ( i = 0; i <= 94; ++i ) { + vim_vec[i] = _ARMV4_Exception_interrupt; + } + /* Clear bit VE in SCTLR register to not use VIM IRQ exception bypass*/ + asm volatile ("mrc p15, 0, %0, c1, c0, 0\n": "=r" (sctlr)); + /* + * Disable bypass of CPU level exception table for interrupt entry which + * can be provided by VIM hardware + */ + sctlr &= ~(1 << 24); + #if 0 + /* + * Option to enable exception table bypass for interrupts + * + * Because RTEMS requires all interrupts to be serviced through + * common _ARMV4_Exception_interrupt handler to allow task switching + * on exit from interrupt working correctly, vim_vec cannot point + * directly to individual vector handlers and need to point + * to single entry path. But if TMS570_VIM.IRQINDEX is then used + * to target execution to corresponding service then for some + * peripherals (i.e. EMAC) interrupt is already acknowledged + * by VIM and IRQINDEX is read as zero which leads to spurious + * interrupt and peripheral not serviced/blocked. + * + * To analyze this behavior we used trampolines which setup + * bsp_interrupt_vector_inject and pass execution to + * _ARMV4_Exception_interrupt. It works but is more ugly than + * use of POM remap for these cases where application does not + * start at address 0x00000000. If RTEMS image is placed at + * memory space beginning then no of these constructs is necessary. + */ + sctlr |= 1 << 24; + #endif + asm volatile ("mcr p15, 0, %0, c1, c0, 0\n": : "r" (sctlr)); + + return RTEMS_SUCCESSFUL; +} diff --git a/bsps/epiphany/epiphany_sim/irq/irq.c b/bsps/epiphany/epiphany_sim/irq/irq.c new file mode 100644 index 0000000000..994e25bf0e --- /dev/null +++ b/bsps/epiphany/epiphany_sim/irq/irq.c @@ -0,0 +1,64 @@ +/** + * @file + * + * @ingroup epiphany_interrupt + * + * @brief Interrupt support. + */ + +/* + * Epiphany CPU Dependent Source + * + * Copyright (c) 2015 University of York. + * Hesham ALMatary + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +#include + +#include + +/* Almost all of the jobs that the following functions should + * do are implemented in cpukit + */ + +void bsp_interrupt_handler_default(rtems_vector_number vector) +{ + printk("spurious interrupt: %" PRIdrtems_vector_number "\n", vector); +} + +rtems_status_code bsp_interrupt_facility_initialize() +{ + return 0; +} + +void bsp_interrupt_vector_enable(rtems_vector_number vector) +{ + bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector)); +} + +void bsp_interrupt_vector_disable(rtems_vector_number vector) +{ + bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector)); +} diff --git a/bsps/i386/shared/irq/elcr.c b/bsps/i386/shared/irq/elcr.c new file mode 100644 index 0000000000..f72e36c33f --- /dev/null +++ b/bsps/i386/shared/irq/elcr.c @@ -0,0 +1,170 @@ +/*- + * Copyright (c) 2004 John Baldwin + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +#ifndef __rtems__ +__FBSDID("$FreeBSD$"); +#endif /* __rtems__ */ + +/* + * The ELCR is a register that controls the trigger mode and polarity of + * EISA and ISA interrupts. In FreeBSD 3.x and 4.x, the ELCR was only + * consulted for determining the appropriate trigger mode of EISA + * interrupts when using an APIC. However, it seems that almost all + * systems that include PCI also include an ELCR that manages the ISA + * IRQs 0 through 15. Thus, we check for the presence of an ELCR on + * every machine by checking to see if the values found at bootup are + * sane. Note that the polarity of ISA and EISA IRQs are linked to the + * trigger mode. All edge triggered IRQs use active-hi polarity, and + * all level triggered interrupts use active-lo polarity. + * + * The format of the ELCR is simple: it is a 16-bit bitmap where bit 0 + * controls IRQ 0, bit 1 controls IRQ 1, etc. If the bit is zero, the + * associated IRQ is edge triggered. If the bit is one, the IRQ is + * level triggered. + */ + +#ifndef __rtems__ +#include +#include +#include +#include +#endif /* __rtems__ */ + +#ifdef __rtems__ +#include +#include "i386_io.h" +#include +#include "elcr.h" +#endif /* __rtems__ */ + +#define ELCR_PORT 0x4d0 +#define ELCR_MASK(irq) (1 << (irq)) + +static int elcr_status; +#ifdef __rtems__ +static +#endif /* __rtems__ */ +int elcr_found; + +#ifdef __rtems__ +#undef printf +#define printf printk +#define bootverbose 1 +#define KASSERT(...) +#endif /* __rtems__ */ + +/* + * Check to see if we have what looks like a valid ELCR. We do this by + * verifying that IRQs 0, 1, 2, and 13 are all edge triggered. + */ +int +elcr_probe(void) +{ + int i; + + elcr_status = inb(ELCR_PORT) | inb(ELCR_PORT + 1) << 8; + if ((elcr_status & (ELCR_MASK(0) | ELCR_MASK(1) | ELCR_MASK(2) | + ELCR_MASK(8) | ELCR_MASK(13))) != 0) + return (ENXIO); + if (bootverbose) { + printf("ELCR Found. ISA IRQs programmed as:\n"); + for (i = 0; i < 16; i++) + printf(" %2d", i); + printf("\n"); + for (i = 0; i < 16; i++) + if (elcr_status & ELCR_MASK(i)) + printf(" L"); + else + printf(" E"); + printf("\n"); + } +#ifndef __rtems__ + if (resource_disabled("elcr", 0)) + return (ENXIO); +#endif /* __rtems__ */ + elcr_found = 1; + return (0); +} + +/* + * Returns 1 for level trigger, 0 for edge. + */ +enum intr_trigger +elcr_read_trigger(u_int irq) +{ +#ifdef __rtems__ + if (!elcr_found) + return INTR_TRIGGER_EDGE; +#endif /* __rtems__ */ + KASSERT(elcr_found, ("%s: no ELCR was found!", __func__)); + KASSERT(irq <= 15, ("%s: invalid IRQ %u", __func__, irq)); + if (elcr_status & ELCR_MASK(irq)) + return (INTR_TRIGGER_LEVEL); + else + return (INTR_TRIGGER_EDGE); +} + +/* + * Set the trigger mode for a specified IRQ. Mode of 0 means edge triggered, + * and a mode of 1 means level triggered. + */ +void +elcr_write_trigger(u_int irq, enum intr_trigger trigger) +{ + int new_status; + +#ifdef __rtems__ + if (!elcr_found) + return; +#endif /* __rtems__ */ + KASSERT(elcr_found, ("%s: no ELCR was found!", __func__)); + KASSERT(irq <= 15, ("%s: invalid IRQ %u", __func__, irq)); + if (trigger == INTR_TRIGGER_LEVEL) + new_status = elcr_status | ELCR_MASK(irq); + else + new_status = elcr_status & ~ELCR_MASK(irq); + if (new_status == elcr_status) + return; + elcr_status = new_status; + if (irq >= 8) + outb(ELCR_PORT + 1, elcr_status >> 8); + else + outb(ELCR_PORT, elcr_status & 0xff); +} + +void +elcr_resume(void) +{ +#ifdef __rtems__ + if (!elcr_found) + return; +#endif /* __rtems__ */ + + KASSERT(elcr_found, ("%s: no ELCR was found!", __func__)); + outb(ELCR_PORT, elcr_status & 0xff); + outb(ELCR_PORT + 1, elcr_status >> 8); +} diff --git a/bsps/i386/shared/irq/elcr.h b/bsps/i386/shared/irq/elcr.h new file mode 100644 index 0000000000..a006d4f149 --- /dev/null +++ b/bsps/i386/shared/irq/elcr.h @@ -0,0 +1,37 @@ +/* + * Copyright 2016 Chris Johns + * + * Header for the FreeBSD ported elcr.c + */ + +#ifndef _IRQ_ELCR_H_ +#define _IRQ_ELCR_H_ + +#include + +enum intr_trigger { + INTR_TRIGGER_EDGE, + INTR_TRIGGER_LEVEL +}; + +/* + * Check to see if we have what looks like a valid ELCR. We do this by + * verifying that IRQs 0, 1, 2, and 13 are all edge triggered. + */ +int elcr_probe(void); + +/* + * Returns 1 for level trigger, 0 for edge. + */ +enum intr_trigger elcr_read_trigger(u_int irq); + +/* + * Set the trigger mode for a specified IRQ. Mode of 0 means edge triggered, + * and a mode of 1 means level triggered. + */ +void elcr_write_trigger(u_int irq, enum intr_trigger trigger); + +void elcr_resume(void); + + +#endif diff --git a/bsps/i386/shared/irq/idt.c b/bsps/i386/shared/irq/idt.c new file mode 100644 index 0000000000..d3adbc4f05 --- /dev/null +++ b/bsps/i386/shared/irq/idt.c @@ -0,0 +1,381 @@ +/* + * cpu.c - This file contains implementation of C function to + * instantiate IDT entries. More detailled information can be found + * on Intel site and more precisely in the following book : + * + * Pentium Processor family + * Developper's Manual + * + * Volume 3 : Architecture and Programming Manual + * + * Copyright (C) 1998 Eric Valette (valette@crf.canon.fr) + * Canon Centre Recherche France. + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.org/license/LICENSE. + */ + +#include +#include +#include + +/* + * This locking is not enough if IDT is changed at runtime + * and entry can be changed for vector which is enabled + * at change time. But such use is broken anyway. + * Protect code only against concurrent changes. + * Even that is probably unnecessary if different + * entries are changed concurrently. + */ +RTEMS_INTERRUPT_LOCK_DEFINE( static, rtems_idt_access_lock, "rtems_idt_access_lock" ); + +static rtems_raw_irq_connect_data* raw_irq_table; +static rtems_raw_irq_connect_data default_raw_irq_entry; +static interrupt_gate_descriptor default_idt_entry; +static rtems_raw_irq_global_settings* local_settings; + +void create_interrupt_gate_descriptor (interrupt_gate_descriptor* idtEntry, + rtems_raw_irq_hdl hdl) +{ + idtEntry->low_offsets_bits = (((unsigned) hdl) & 0xffff); + idtEntry->segment_selector = i386_get_cs(); + idtEntry->fixed_value_bits = 0; + idtEntry->gate_type = 0xe; + idtEntry->privilege = 0; + idtEntry->present = 1; + idtEntry->high_offsets_bits = ((((unsigned) hdl) >> 16) & 0xffff); +} + +rtems_raw_irq_hdl get_hdl_from_vector(rtems_vector_offset index) +{ + uint32_t hdl; + interrupt_gate_descriptor* idt_entry_tbl; + unsigned limit; + + i386_get_info_from_IDTR (&idt_entry_tbl, &limit); + + /* Convert limit into number of entries */ + limit = (limit + 1) / sizeof(interrupt_gate_descriptor); + + if(index >= limit) { + return 0; + } + + hdl = (idt_entry_tbl[index].low_offsets_bits | + (idt_entry_tbl[index].high_offsets_bits << 16)); + return (rtems_raw_irq_hdl) hdl; +} + +int i386_set_idt_entry (const rtems_raw_irq_connect_data* irq) +{ + interrupt_gate_descriptor* idt_entry_tbl; + unsigned limit; + rtems_interrupt_lock_context lock_context; + + i386_get_info_from_IDTR (&idt_entry_tbl, &limit); + + /* Convert limit into number of entries */ + limit = (limit + 1) / sizeof(interrupt_gate_descriptor); + + if (irq->idtIndex >= limit) { + return 0; + } + /* + * Check if default handler is actually connected. If not issue an error. + * You must first get the current handler via i386_get_current_idt_entry + * and then disconnect it using i386_delete_idt_entry. + * RATIONALE : to always have the same transition by forcing the user + * to get the previous handler before accepting to disconnect. + */ + if (get_hdl_from_vector(irq->idtIndex) != default_raw_irq_entry.hdl) { + return 0; + } + + rtems_interrupt_lock_acquire(&rtems_idt_access_lock, &lock_context); + + raw_irq_table [irq->idtIndex] = *irq; + create_interrupt_gate_descriptor (&idt_entry_tbl[irq->idtIndex], irq->hdl); + if (irq->on) + irq->on(irq); + + rtems_interrupt_lock_release(&rtems_idt_access_lock, &lock_context); + return 1; +} + +void _CPU_ISR_install_vector (uint32_t vector, + proc_ptr hdl, + proc_ptr * oldHdl) +{ + interrupt_gate_descriptor* idt_entry_tbl; + unsigned limit; + interrupt_gate_descriptor new; + rtems_interrupt_lock_context lock_context; + + i386_get_info_from_IDTR (&idt_entry_tbl, &limit); + + /* Convert limit into number of entries */ + limit = (limit + 1) / sizeof(interrupt_gate_descriptor); + + if (vector >= limit) { + return; + } + rtems_interrupt_lock_acquire(&rtems_idt_access_lock, &lock_context); + * ((unsigned int *) oldHdl) = idt_entry_tbl[vector].low_offsets_bits | + (idt_entry_tbl[vector].high_offsets_bits << 16); + + create_interrupt_gate_descriptor(&new, hdl); + idt_entry_tbl[vector] = new; + + rtems_interrupt_lock_release(&rtems_idt_access_lock, &lock_context); +} + +int i386_get_current_idt_entry (rtems_raw_irq_connect_data* irq) +{ + interrupt_gate_descriptor* idt_entry_tbl; + unsigned limit; + + i386_get_info_from_IDTR (&idt_entry_tbl, &limit); + + /* Convert limit into number of entries */ + limit = (limit + 1) / sizeof(interrupt_gate_descriptor); + + if (irq->idtIndex >= limit) { + return 0; + } + raw_irq_table [irq->idtIndex].hdl = get_hdl_from_vector(irq->idtIndex); + + *irq = raw_irq_table [irq->idtIndex]; + + return 1; +} + +int i386_delete_idt_entry (const rtems_raw_irq_connect_data* irq) +{ + interrupt_gate_descriptor* idt_entry_tbl; + unsigned limit; + rtems_interrupt_lock_context lock_context; + + i386_get_info_from_IDTR (&idt_entry_tbl, &limit); + + /* Convert limit into number of entries */ + limit = (limit + 1) / sizeof(interrupt_gate_descriptor); + + if (irq->idtIndex >= limit) { + return 0; + } + /* + * Check if handler passed is actually connected. If not issue an error. + * You must first get the current handler via i386_get_current_idt_entry + * and then disconnect it using i386_delete_idt_entry. + * RATIONALE : to always have the same transition by forcing the user + * to get the previous handler before accepting to disconnect. + */ + if (get_hdl_from_vector(irq->idtIndex) != irq->hdl){ + return 0; + } + rtems_interrupt_lock_acquire(&rtems_idt_access_lock, &lock_context); + + idt_entry_tbl[irq->idtIndex] = default_idt_entry; + + if (irq->off) + irq->off(irq); + + raw_irq_table[irq->idtIndex] = default_raw_irq_entry; + raw_irq_table[irq->idtIndex].idtIndex = irq->idtIndex; + + rtems_interrupt_lock_release(&rtems_idt_access_lock, &lock_context); + + return 1; +} + +/* + * Caution this function assumes the IDTR has been already set. + */ +int i386_init_idt (rtems_raw_irq_global_settings* config) +{ + unsigned limit; + unsigned i; + rtems_interrupt_lock_context lock_context; + interrupt_gate_descriptor* idt_entry_tbl; + + i386_get_info_from_IDTR (&idt_entry_tbl, &limit); + + /* Convert limit into number of entries */ + limit = (limit + 1) / sizeof(interrupt_gate_descriptor); + + if (config->idtSize != limit) { + return 0; + } + /* + * store various accelarators + */ + raw_irq_table = config->rawIrqHdlTbl; + local_settings = config; + default_raw_irq_entry = config->defaultRawEntry; + + rtems_interrupt_lock_acquire(&rtems_idt_access_lock, &lock_context); + + create_interrupt_gate_descriptor (&default_idt_entry, default_raw_irq_entry.hdl); + + for (i=0; i < limit; i++) { + interrupt_gate_descriptor new; + create_interrupt_gate_descriptor (&new, raw_irq_table[i].hdl); + idt_entry_tbl[i] = new; + if (raw_irq_table[i].hdl != default_raw_irq_entry.hdl) { + raw_irq_table[i].on(&raw_irq_table[i]); + } + else { + raw_irq_table[i].off(&raw_irq_table[i]); + } + } + rtems_interrupt_lock_release(&rtems_idt_access_lock, &lock_context); + + return 1; +} + +int i386_get_idt_config (rtems_raw_irq_global_settings** config) +{ + *config = local_settings; + return 1; +} + +uint32_t i386_raw_gdt_entry (uint16_t segment_selector_index, + segment_descriptors* sd) +{ + uint16_t gdt_limit; + uint16_t tmp_segment = 0; + segment_descriptors* gdt_entry_tbl; + uint8_t present; + + i386_get_info_from_GDTR (&gdt_entry_tbl, &gdt_limit); + + if (segment_selector_index >= (gdt_limit+1)/8) { + /* index to GDT table out of bounds */ + return 0; + } + if (segment_selector_index == 0) { + /* index 0 is not usable */ + return 0; + } + + /* put prepared descriptor into the GDT */ + present = sd->present; + sd->present = 0; + gdt_entry_tbl[segment_selector_index].present = 0; + RTEMS_COMPILER_MEMORY_BARRIER(); + gdt_entry_tbl[segment_selector_index] = *sd; + RTEMS_COMPILER_MEMORY_BARRIER(); + gdt_entry_tbl[segment_selector_index].present = present; + sd->present = present; + /* + * Now, reload all segment registers so that the possible changes takes effect. + */ + __asm__ volatile( "movw %%ds,%0 ; movw %0,%%ds\n\t" + "movw %%es,%0 ; movw %0,%%es\n\t" + "movw %%fs,%0 ; movw %0,%%fs\n\t" + "movw %%gs,%0 ; movw %0,%%gs\n\t" + "movw %%ss,%0 ; movw %0,%%ss" + : "=r" (tmp_segment) + : "0" (tmp_segment) + ); + return 1; +} + +void i386_fill_segment_desc_base(uint32_t base, + segment_descriptors* sd) +{ + sd->base_address_15_0 = base & 0xffff; + sd->base_address_23_16 = (base >> 16) & 0xff; + sd->base_address_31_24 = (base >> 24) & 0xff; +} + +void i386_fill_segment_desc_limit(uint32_t limit, + segment_descriptors* sd) +{ + sd->granularity = 0; + if (limit > 65535) { + sd->granularity = 1; + limit /= 4096; + } + sd->limit_15_0 = limit & 0xffff; + sd->limit_19_16 = (limit >> 16) & 0xf; +} + +/* + * Caution this function assumes the GDTR has been already set. + */ +uint32_t i386_set_gdt_entry (uint16_t segment_selector_index, uint32_t base, + uint32_t limit) +{ + segment_descriptors gdt_entry; + memset(&gdt_entry, 0, sizeof(gdt_entry)); + + i386_fill_segment_desc_limit(limit, &gdt_entry); + i386_fill_segment_desc_base(base, &gdt_entry); + /* + * set up descriptor type (this may well becomes a parameter if needed) + */ + gdt_entry.type = 2; /* Data R/W */ + gdt_entry.descriptor_type = 1; /* Code or Data */ + gdt_entry.privilege = 0; /* ring 0 */ + gdt_entry.present = 1; /* not present */ + + /* + * Now, reload all segment registers so the limit takes effect. + */ + return i386_raw_gdt_entry(segment_selector_index, &gdt_entry); +} + +uint16_t i386_next_empty_gdt_entry () +{ + uint16_t gdt_limit; + segment_descriptors* gdt_entry_tbl; + /* initial amount of filled descriptors */ + static uint16_t segment_selector_index = NUM_SYSTEM_GDT_DESCRIPTORS - 1; + + segment_selector_index += 1; + i386_get_info_from_GDTR (&gdt_entry_tbl, &gdt_limit); + if (segment_selector_index >= (gdt_limit+1)/8) { + return 0; + } + return segment_selector_index; +} + +uint16_t i386_cpy_gdt_entry(uint16_t segment_selector_index, + segment_descriptors* struct_to_fill) +{ + uint16_t gdt_limit; + segment_descriptors* gdt_entry_tbl; + + i386_get_info_from_GDTR (&gdt_entry_tbl, &gdt_limit); + + if (segment_selector_index >= (gdt_limit+1)/8) { + return 0; + } + + *struct_to_fill = gdt_entry_tbl[segment_selector_index]; + return segment_selector_index; +} + +segment_descriptors* i386_get_gdt_entry(uint16_t segment_selector_index) +{ + uint16_t gdt_limit; + segment_descriptors* gdt_entry_tbl; + + i386_get_info_from_GDTR (&gdt_entry_tbl, &gdt_limit); + + if (segment_selector_index >= (gdt_limit+1)/8) { + return 0; + } + return &gdt_entry_tbl[segment_selector_index]; +} + +uint32_t i386_limit_gdt_entry(segment_descriptors* gdt_entry) +{ + uint32_t lim = (gdt_entry->limit_15_0 + (gdt_entry->limit_19_16<<16)); + if (gdt_entry->granularity) { + return lim*4096+4095; + } + return lim; +} diff --git a/bsps/i386/shared/irq/irq.c b/bsps/i386/shared/irq/irq.c new file mode 100644 index 0000000000..ac08f1f7be --- /dev/null +++ b/bsps/i386/shared/irq/irq.c @@ -0,0 +1,405 @@ +/* + * This file contains the implementation of the function described in irq.h + */ + +/* + * Copyright (c) 2009 embedded brains GmbH + * Copyright (C) 1998 valette@crf.canon.fr + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.org/license/LICENSE. + */ + +#include +#include +#include +#include + +#include +#include +#include + + +#include "elcr.h" + +RTEMS_INTERRUPT_LOCK_DEFINE( static, rtems_i8259_access_lock, "rtems_i8259_access_lock" ); + +/* + * pointer to the mask representing the additionnal irq vectors + * that must be disabled when a particular entry is activated. + * They will be dynamically computed from teh prioruty table given + * in BSP_rtems_irq_mngt_set(); + * CAUTION : this table is accessed directly by interrupt routine + * prologue. + */ +static rtems_i8259_masks irq_mask_or_tbl[BSP_IRQ_LINES_NUMBER]; + +/* + * Stats of interrupts dispatched. + */ +static uint32_t irq_count[BSP_IRQ_VECTOR_NUMBER] = {0}; +static uint32_t spurious_count; + +/* + * Edge or level trigger interrupts. + */ +static enum intr_trigger irq_trigger[BSP_IRQ_LINES_NUMBER]; + +/*-------------------------------------------------------------------------+ +| Cache for 1st and 2nd PIC IRQ line's mssk (enabled or disabled) register. ++--------------------------------------------------------------------------*/ +/* + * lower byte is interrupt mask on the master PIC. + * while upper bits are interrupt on the slave PIC. + * This cache is initialized in ldseg.s + */ +static rtems_i8259_masks i8259a_imr_cache = 0xFFFB; +static rtems_i8259_masks i8259a_in_progress = 0; + +static inline +void BSP_i8259a_irq_update_master_imr( void ) +{ + rtems_i8259_masks mask = i8259a_in_progress | i8259a_imr_cache; + outport_byte( PIC_MASTER_IMR_IO_PORT, mask & 0xff ); +} + +static inline +void BSP_i8259a_irq_update_slave_imr( void ) +{ + rtems_i8259_masks mask = i8259a_in_progress | i8259a_imr_cache; + outport_byte( PIC_SLAVE_IMR_IO_PORT, ( mask >> 8 ) & 0xff ); +} + +/* + * Print the stats. + */ +uint32_t BSP_irq_count_dump(FILE *f) +{ + uint32_t tot = 0; + int i; + if ( !f ) + f = stdout; + fprintf(f,"SPURIOUS: %9"PRIu32"\n", spurious_count); + for ( i = 0; i < BSP_IRQ_VECTOR_NUMBER; i++ ) { + char type = '-'; + if (i < BSP_IRQ_LINES_NUMBER) + type = irq_trigger[i] == INTR_TRIGGER_EDGE ? 'E' : 'L'; + tot += irq_count[i]; + fprintf(f,"IRQ %2u: %c %9"PRIu32"\n", i, type, irq_count[i]); + } + return tot; +} + +/* + * Is the IRQ valid? + */ +static inline bool BSP_i8259a_irq_valid(const rtems_irq_number irqLine) +{ + return ((int)irqLine >= BSP_IRQ_VECTOR_LOWEST_OFFSET) && + ((int)irqLine <= BSP_IRQ_MAX_ON_i8259A); +} + +/* + * Read the IRR register. The default. + */ +static inline uint8_t BSP_i8259a_irq_int_request_reg(uint32_t ioport) +{ + uint8_t isr; + inport_byte(ioport, isr); + return isr; +} + +/* + * Read the ISR register. Keep the default of the IRR. + */ +static inline uint8_t BSP_i8259a_irq_in_service_reg(uint32_t ioport) +{ + uint8_t isr; + outport_byte(ioport, PIC_OCW3_SEL | PIC_OCW3_RR | PIC_OCW3_RIS); + inport_byte(ioport, isr); + outport_byte(ioport, PIC_OCW3_SEL | PIC_OCW3_RR); + return isr; +} + +/*-------------------------------------------------------------------------+ +| Function: BSP_irq_disable_at_i8259a +| Description: Mask IRQ line in appropriate PIC chip. +| Global Variables: i8259a_imr_cache, i8259a_in_progress +| Arguments: vector_offset - number of IRQ line to mask. +| Returns: 0 is OK. ++--------------------------------------------------------------------------*/ +static int BSP_irq_disable_at_i8259a(const rtems_irq_number irqLine) +{ + unsigned short mask; + rtems_interrupt_lock_context lock_context; + + rtems_interrupt_lock_acquire(&rtems_i8259_access_lock, &lock_context); + + mask = 1 << irqLine; + i8259a_imr_cache |= mask; + + if (irqLine < 8) + { + BSP_i8259a_irq_update_master_imr(); + } + else + { + BSP_i8259a_irq_update_slave_imr(); + } + + rtems_interrupt_lock_release(&rtems_i8259_access_lock, &lock_context); + + return 0; +} + +/*-------------------------------------------------------------------------+ +| Function: BSP_irq_enable_at_i8259a +| Description: Unmask IRQ line in appropriate PIC chip. +| Global Variables: i8259a_imr_cache, i8259a_in_progress +| Arguments: irqLine - number of IRQ line to mask. +| Returns: Nothing. ++--------------------------------------------------------------------------*/ +static int BSP_irq_enable_at_i8259a(const rtems_irq_number irqLine) +{ + unsigned short mask; + rtems_interrupt_lock_context lock_context; + uint8_t isr; + uint8_t irr; + + rtems_interrupt_lock_acquire(&rtems_i8259_access_lock, &lock_context); + + mask = 1 << irqLine; + i8259a_imr_cache &= ~mask; + + if (irqLine < 8) + { + isr = BSP_i8259a_irq_in_service_reg(PIC_MASTER_COMMAND_IO_PORT); + irr = BSP_i8259a_irq_int_request_reg(PIC_MASTER_COMMAND_IO_PORT); + BSP_i8259a_irq_update_master_imr(); + } + else + { + isr = BSP_i8259a_irq_in_service_reg(PIC_SLAVE_COMMAND_IO_PORT); + irr = BSP_i8259a_irq_int_request_reg(PIC_SLAVE_COMMAND_IO_PORT); + BSP_i8259a_irq_update_slave_imr(); + } + + if (((isr ^ irr) & mask) != 0) + printk("i386: isr=%x irr=%x\n", isr, irr); + + rtems_interrupt_lock_release(&rtems_i8259_access_lock, &lock_context); + + return 0; +} /* mask_irq */ + +/*-------------------------------------------------------------------------+ +| Function: BSP_irq_ack_at_i8259a +| Description: Signal generic End Of Interrupt (EOI) to appropriate PIC. +| Global Variables: None. +| Arguments: irqLine - number of IRQ line to acknowledge. +| Returns: Nothing. ++--------------------------------------------------------------------------*/ +static int BSP_irq_ack_at_i8259a(const rtems_irq_number irqLine) +{ + uint8_t slave_isr = 0; + + if (irqLine >= 8) { + outport_byte(PIC_SLAVE_COMMAND_IO_PORT, PIC_EOI); + slave_isr = BSP_i8259a_irq_in_service_reg(PIC_SLAVE_COMMAND_IO_PORT); + } + + /* + * Only issue the EOI to the master if there are no more interrupts in + * service for the slave. i8259a data sheet page 18, The Special Fully Nested + * Mode, b. + */ + if (slave_isr == 0) + outport_byte(PIC_MASTER_COMMAND_IO_PORT, PIC_EOI); + + return 0; + +} /* ackIRQ */ + +/* + * ------------------------ RTEMS Irq helper functions ---------------- + */ + +static rtems_irq_prio irqPrioTable[BSP_IRQ_LINES_NUMBER]={ + /* + * actual priorities for each interrupt source: + * 0 means that only current interrupt is masked + * 255 means all other interrupts are masked + * The second entry has a priority of 255 because + * it is the slave pic entry and is should always remain + * unmasked. + */ + 0,0, + 255, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static void compute_i8259_masks_from_prio (void) +{ + rtems_interrupt_lock_context lock_context; + unsigned int i; + unsigned int j; + + rtems_interrupt_lock_acquire(&rtems_i8259_access_lock, &lock_context); + + /* + * Always mask at least current interrupt to prevent re-entrance + */ + for (i=0; i < BSP_IRQ_LINES_NUMBER; i++) { + * ((unsigned short*) &irq_mask_or_tbl[i]) = (1 << i); + for (j = 0; j < BSP_IRQ_LINES_NUMBER; j++) { + /* + * Mask interrupts at i8259 level that have a lower priority + */ + if (irqPrioTable [i] > irqPrioTable [j]) { + * ((unsigned short*) &irq_mask_or_tbl[i]) |= (1 << j); + } + } + } + + rtems_interrupt_lock_release(&rtems_i8259_access_lock, &lock_context); +} + +static inline bool bsp_interrupt_vector_is_valid(rtems_vector_number vector) +{ + return BSP_i8259a_irq_valid((const rtems_irq_number) vector); +} + +void bsp_interrupt_vector_enable(rtems_vector_number vector) +{ + bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector)); + BSP_irq_enable_at_i8259a(vector); +} + +void bsp_interrupt_vector_disable(rtems_vector_number vector) +{ + bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector)); + BSP_irq_disable_at_i8259a(vector); +} + +rtems_status_code bsp_interrupt_facility_initialize(void) +{ + int i; + + /* + * set up internal tables used by rtems interrupt prologue + */ + compute_i8259_masks_from_prio(); + + /* + * must enable slave pic anyway + */ + BSP_irq_enable_at_i8259a(2); + + /* + * Probe the ELCR. + */ + elcr_probe(); + + for (i = 0; i < BSP_IRQ_LINES_NUMBER; i++) + irq_trigger[i] = elcr_read_trigger(i); + + return RTEMS_SUCCESSFUL; +} + +/* + * Global so the asm handler can call it. + */ +void BSP_dispatch_isr(int vector); + +void BSP_dispatch_isr(int vector) +{ + rtems_interrupt_lock_context lock_context; + rtems_i8259_masks in_progress_save = 0; + + if (vector < BSP_IRQ_VECTOR_NUMBER) { + /* + * Hardware? + */ + if (vector <= BSP_IRQ_MAX_ON_i8259A) { + + rtems_interrupt_lock_acquire_isr(&rtems_i8259_access_lock, &lock_context); + + /* + * See if this is a spurious interrupt. + */ + if ((vector == 7 || vector == 15)) { + /* + * Only check it there no handler for 7 or 15. + */ + if (bsp_interrupt_handler_is_empty(vector)) { + /* + * Read the ISR register to see if IRQ 7/15 is really pending. + */ + uint8_t isr = BSP_i8259a_irq_in_service_reg(PIC_MASTER_COMMAND_IO_PORT); + if ((isr & (1 << 7)) == 0) { + ++spurious_count; + rtems_interrupt_lock_release_isr(&rtems_i8259_access_lock, &lock_context); + return; + } + } + } + + /* + * Save the current cached value for the IMR. It will have the bit for this + * vector clear. + */ + if (vector <= BSP_IRQ_MAX_ON_i8259A) { + in_progress_save = i8259a_in_progress; + i8259a_in_progress |= irq_mask_or_tbl[vector]; + BSP_i8259a_irq_update_master_imr(); + BSP_i8259a_irq_update_slave_imr(); + } + + /* + * Do not use auto-EOI as some slave PIC do not work correctly. + */ + BSP_irq_ack_at_i8259a(vector); + + rtems_interrupt_lock_release_isr(&rtems_i8259_access_lock, &lock_context); + } + + /* + * Count the interrupt. + */ + irq_count[vector]++; + + RTEMS_COMPILER_MEMORY_BARRIER(); + /* + * Allow nesting. + */ + __asm__ __volatile__("sti"); + + bsp_interrupt_handler_dispatch(vector); + + /* + * Disallow nesting. + */ + __asm__ __volatile__("cli"); + + RTEMS_COMPILER_MEMORY_BARRIER(); + + if (vector <= BSP_IRQ_MAX_ON_i8259A) { + + rtems_interrupt_lock_acquire_isr(&rtems_i8259_access_lock, &lock_context); + + /* + * Put the mask back but keep this vector masked if the trigger type is + * level. The driver or a thread level interrupt server needs to enable it + * again. + */ + if (vector <= BSP_IRQ_MAX_ON_i8259A) { + i8259a_in_progress = in_progress_save; + BSP_i8259a_irq_update_master_imr(); + BSP_i8259a_irq_update_slave_imr(); + } + + rtems_interrupt_lock_release_isr(&rtems_i8259_access_lock, &lock_context); + } + } +} diff --git a/bsps/i386/shared/irq/irq_asm.S b/bsps/i386/shared/irq/irq_asm.S new file mode 100644 index 0000000000..181293351e --- /dev/null +++ b/bsps/i386/shared/irq/irq_asm.S @@ -0,0 +1,268 @@ +/* + * This file contains the implementation of the function described in irq.h + */ + +/* + * Copyright (C) 1998 valette@crf.canon.fr + * + * COPYRIGHT (c) 1989-2011. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in found in the file LICENSE in this distribution or at + * http://www.rtems.org/license/LICENSE. + */ + +#include +#include +#include +#include +#include + +#include /* to establish dependency on prototype */ + +#ifndef CPU_STACK_ALIGNMENT +#error "Missing header? CPU_STACK_ALIGNMENT is not defined here" +#endif + +/* Stack frame we use for intermediate storage */ +#define ARG_OFF 0 +#define MSK_OFF 4 /* not used any more */ +#define EBX_OFF 8 /* ebx */ +#define EBP_OFF 12 /* code restoring ebp/esp relies on */ +#define ESP_OFF 16 /* esp being on top of ebp! */ +#ifdef __SSE__ +/* need to be on 16 byte boundary for SSE, add 12 to do that */ +#define FRM_SIZ (20+12+512) +#define SSE_OFF 32 +#else +#define FRM_SIZ 20 +#endif + + BEGIN_CODE + +SYM (_ISR_Handler): + /* + * Before this was point is reached the vectors unique + * entry point did the following: + * + * 1. saved scratch registers registers eax edx ecx" + * 2. put the vector number in ecx. + * + * BEGINNING OF ESTABLISH SEGMENTS + * + * WARNING: If an interrupt can occur when the segments are + * not correct, then this is where we should establish + * the segments. In addition to establishing the + * segments, it may be necessary to establish a stack + * in the current data area on the outermost interrupt. + * + * NOTE: If the previous values of the segment registers are + * pushed, do not forget to adjust SAVED_REGS. + * + * NOTE: Make sure the exit code which restores these + * when this type of code is needed. + */ + + /***** ESTABLISH SEGMENTS CODE GOES HERE ******/ + + /* + * END OF ESTABLISH SEGMENTS + */ + + /* + * Establish an aligned stack frame + * original sp + * saved ebx + * saved ebp + * saved irq mask + * vector arg to BSP_dispatch_isr <- aligned SP + */ + movl esp, eax + subl $FRM_SIZ, esp + andl $ - CPU_STACK_ALIGNMENT, esp + movl ebx, EBX_OFF(esp) + movl eax, ESP_OFF(esp) + movl ebp, EBP_OFF(esp) + + /* + * GCC versions starting with 4.3 no longer place the cld + * instruction before string operations. We need to ensure + * it is set correctly for ISR handlers. + */ + cld + +#ifdef __SSE__ + /* NOTE: SSE only is supported if the BSP enables fxsave/fxrstor + * to save/restore SSE context! This is so far only implemented + * for pc386!. + */ + + /* We save SSE here (on the task stack) because we possibly + * call other C-code (besides the ISR, namely _Thread_Dispatch()) + */ + /* don't wait here; a possible exception condition will eventually be + * detected when the task resumes control and executes a FP instruction + fwait + */ + fxsave SSE_OFF(esp) + fninit /* clean-slate FPU */ + movl $0x1f80, ARG_OFF(esp) /* use ARG_OFF as scratch space */ + ldmxcsr ARG_OFF(esp) /* clean-slate MXCSR */ +#endif + + /* + * Now switch stacks if necessary + */ + +PUBLIC (ISR_STOP) +ISR_STOP: +.check_stack_switch: + movl esp, ebp /* ebp = previous stack pointer */ + +#ifdef RTEMS_SMP + call SYM(_CPU_SMP_Get_current_processor) + sall $PER_CPU_CONTROL_SIZE_LOG2, eax + addl $SYM(_Per_CPU_Information), eax + movl eax, ebx +#else + movl $SYM(_Per_CPU_Information), ebx +#endif + + /* is this the outermost interrupt? */ + cmpl $0, PER_CPU_ISR_NEST_LEVEL(ebx) + jne nested /* No, then continue */ + movl PER_CPU_INTERRUPT_STACK_HIGH(ebx), esp + + /* + * We want to insure that the old stack pointer is in ebp + * By saving it on every interrupt, all we have to do is + * movl ebp->esp near the end of every interrupt. + */ + +nested: + incl PER_CPU_ISR_NEST_LEVEL(ebx) /* one nest level deeper */ + incl PER_CPU_THREAD_DISPATCH_DISABLE_LEVEL(ebx) /* disable + multitasking */ + /* + * ECX is preloaded with the vector number; store as arg + * on top of stack. Note that _CPU_Interrupt_stack_high + * was adjusted in _CPU_Interrupt_stack_setup() (score/rtems/cpu.h) + * to make sure there is space. + */ + + movl ecx, ARG_OFF(esp) /* store vector arg in stack */ + call BSP_dispatch_isr + + movl ARG_OFF(esp), ecx /* grab vector arg from stack */ + + /* + * Restore stack. This moves back to the task stack + * when all interrupts are unnested. + */ + movl ebp, esp + + decl PER_CPU_ISR_NEST_LEVEL(ebx) /* one less ISR nest level */ + /* If interrupts are nested, */ + /* then dispatching is disabled */ + + decl PER_CPU_THREAD_DISPATCH_DISABLE_LEVEL(ebx) + /* unnest multitasking */ + /* Is dispatch disabled */ + jne .exit /* Yes, then exit */ + + cmpb $0, PER_CPU_DISPATCH_NEEDED(ebx) + /* Is task switch necessary? */ + jne .schedule /* Yes, then call the scheduler */ + jmp .exit /* No, exit */ + +.schedule: + /* + * the scratch registers have already been saved and we are already + * back on the thread system stack. So we can call _Thread_Dispatch + * directly + */ + call _Thread_Dispatch + /* + * fall through exit to restore complete contex (scratch registers + * eip, CS, Flags). + */ +.exit: + +#ifdef __SSE__ + fwait + fxrstor SSE_OFF(esp) +#endif + + /* restore ebx, ebp and original esp */ + addl $EBX_OFF, esp + popl ebx + popl ebp + popl esp + + /* + * BEGINNING OF DE-ESTABLISH SEGMENTS + * + * NOTE: Make sure there is code here if code is added to + * load the segment registers. + * + */ + + /******* DE-ESTABLISH SEGMENTS CODE GOES HERE ********/ + + /* + * END OF DE-ESTABLISH SEGMENTS + */ + popl edx + popl ecx + popl eax + iret + +#define DISTINCT_INTERRUPT_ENTRY(_vector) \ + .p2align 4 ; \ + PUBLIC (rtems_irq_prologue_ ## _vector ) ; \ +SYM (rtems_irq_prologue_ ## _vector ): \ + pushl eax ; \ + pushl ecx ; \ + pushl edx ; \ + movl $ _vector, ecx ; \ + jmp SYM (_ISR_Handler) ; + +DISTINCT_INTERRUPT_ENTRY(0) +DISTINCT_INTERRUPT_ENTRY(1) +DISTINCT_INTERRUPT_ENTRY(2) +DISTINCT_INTERRUPT_ENTRY(3) +DISTINCT_INTERRUPT_ENTRY(4) +DISTINCT_INTERRUPT_ENTRY(5) +DISTINCT_INTERRUPT_ENTRY(6) +DISTINCT_INTERRUPT_ENTRY(7) +DISTINCT_INTERRUPT_ENTRY(8) +DISTINCT_INTERRUPT_ENTRY(9) +DISTINCT_INTERRUPT_ENTRY(10) +DISTINCT_INTERRUPT_ENTRY(11) +DISTINCT_INTERRUPT_ENTRY(12) +DISTINCT_INTERRUPT_ENTRY(13) +DISTINCT_INTERRUPT_ENTRY(14) +DISTINCT_INTERRUPT_ENTRY(15) +DISTINCT_INTERRUPT_ENTRY(16) + + /* + * routine used to initialize the IDT by default + */ + +PUBLIC (default_raw_idt_handler) +PUBLIC (raw_idt_notify) + +SYM (default_raw_idt_handler): + pusha + cld + mov esp, ebp + andl $ - CPU_STACK_ALIGNMENT, esp + call raw_idt_notify + mov ebp, esp + popa + iret + +END_CODE + +END diff --git a/bsps/i386/shared/irq/irq_init.c b/bsps/i386/shared/irq/irq_init.c new file mode 100644 index 0000000000..fdf4801a5a --- /dev/null +++ b/bsps/i386/shared/irq/irq_init.c @@ -0,0 +1,191 @@ +/* irq_init.c + * + * This file contains the implementation of rtems initialization + * related to interrupt handling. + * + * Copyright (c) 2009 embedded brains GmbH + * CopyRight (C) 1998 valette@crf.canon.fr + * + * COPYRIGHT (c) 2011. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.org/license/LICENSE. + */ + +#include + +#include + +#include +#include +#include + +/* + * rtems prologue generated in irq_asm.S + */ +extern void rtems_irq_prologue_0(void); +extern void rtems_irq_prologue_1(void); +extern void rtems_irq_prologue_2(void); +extern void rtems_irq_prologue_3(void); +extern void rtems_irq_prologue_4(void); +extern void rtems_irq_prologue_5(void); +extern void rtems_irq_prologue_6(void); +extern void rtems_irq_prologue_7(void); +extern void rtems_irq_prologue_8(void); +extern void rtems_irq_prologue_9(void); +extern void rtems_irq_prologue_10(void); +extern void rtems_irq_prologue_11(void); +extern void rtems_irq_prologue_12(void); +extern void rtems_irq_prologue_13(void); +extern void rtems_irq_prologue_14(void); +extern void rtems_irq_prologue_15(void); +extern void rtems_irq_prologue_16(void); +/* + * default vectors + */ +extern void default_raw_idt_handler(void); + +/* + * default raw on/off function + */ +static void raw_nop_func(const struct __rtems_raw_irq_connect_data__ *unused) +{ +} + +/* + * default raw isOn function + */ +static int raw_not_connected( + const struct __rtems_raw_irq_connect_data__ *unused +) +{ + return 0; +} + +static rtems_raw_irq_connect_data idtHdl[IDT_SIZE]; + +static rtems_raw_irq_hdl rtemsIrq[BSP_IRQ_VECTOR_NUMBER] = { + rtems_irq_prologue_0, + rtems_irq_prologue_1, + rtems_irq_prologue_2, + rtems_irq_prologue_3, + rtems_irq_prologue_4, + rtems_irq_prologue_5, + rtems_irq_prologue_6, + rtems_irq_prologue_7, + rtems_irq_prologue_8, + rtems_irq_prologue_9, + rtems_irq_prologue_10, + rtems_irq_prologue_11, + rtems_irq_prologue_12, + rtems_irq_prologue_13, + rtems_irq_prologue_14, + rtems_irq_prologue_15, + rtems_irq_prologue_16, +}; + +static rtems_raw_irq_connect_data defaultRawIrq = { + 0, /* vectorIdex */ + default_raw_idt_handler, /* hdl */ + raw_nop_func, /* on */ + raw_nop_func, /* off */ + raw_not_connected /* isOn */ +}; + +static interrupt_gate_descriptor idtEntry; + +static rtems_raw_irq_global_settings raw_initial_config; + + +/* + * This method is called from irq_asm.S and cannot be static. + */ +void raw_idt_notify(void) +{ + printk("raw_idt_notify has been called \n"); +} + +void rtems_irq_mngt_init(void) +{ + int i; + interrupt_gate_descriptor* idt_entry_tbl; + unsigned int limit; + rtems_interrupt_level level; + + i386_get_info_from_IDTR(&idt_entry_tbl, &limit); + + /* Convert into number of entries */ + limit = (limit + 1)/sizeof(interrupt_gate_descriptor); + + if(limit != IDT_SIZE) { + printk("IDT table size mismatch !!! System locked\n"); + while(1); + } + + /* + * The interrupt management can be initialized only once + * during system bootup and that should happen on boot + * CPU so there is no need to synchronize with others CPUs. + */ + rtems_interrupt_local_disable(level); + + /* + * Init the complete IDT vector table with defaultRawIrq value + */ + for (i = 0; i < IDT_SIZE ; i++) { + idtHdl[i] = defaultRawIrq; + idtHdl[i].idtIndex = i; + } + + raw_initial_config.idtSize = IDT_SIZE; + raw_initial_config.defaultRawEntry = defaultRawIrq; + raw_initial_config.rawIrqHdlTbl = idtHdl; + + if (!i386_init_idt (&raw_initial_config)) { + /* + * put something here that will show the failure... + */ + printk("Unable to initialize IDT!!! System locked\n"); + while (1); + } + /* + * Patch the entry that will be used by RTEMS for interrupt management + * with RTEMS prologue. + */ + for (i = 0; i < BSP_IRQ_VECTOR_NUMBER; i++) { + create_interrupt_gate_descriptor(&idtEntry, rtemsIrq[i]); + idt_entry_tbl[i + BSP_ASM_IRQ_VECTOR_BASE] = idtEntry; + } + /* + * At this point we have completed the initialization of IDT + * with raw handlers. We must now initialize the higher level + * interrupt management. + */ + + /* + * Init initial Interrupt management config + */ + bsp_interrupt_initialize(); + + /* + * #define DEBUG + */ +#ifdef DEBUG + { + /* + * following adresses should be the same + */ + unsigned tmp; + + printk("idt_entry_tbl = %x Interrupt_descriptor_table addr = %x\n", + idt_entry_tbl, &Interrupt_descriptor_table); + tmp = (unsigned) get_hdl_from_vector (BSP_ASM_IRQ_VECTOR_BASE + BSP_PERIODIC_TIMER); + printk("clock isr address from idt = %x should be %x\n", + tmp, (unsigned) rtems_irq_prologue_0); + } + printk("i8259s_cache = %x\n", * (unsigned short*) &i8259s_cache); + BSP_wait_polled_input(); +#endif +} diff --git a/bsps/lm32/shared/irq/irq.c b/bsps/lm32/shared/irq/irq.c new file mode 100644 index 0000000000..79626ee449 --- /dev/null +++ b/bsps/lm32/shared/irq/irq.c @@ -0,0 +1,30 @@ +/* irq.c + * + * Copyright (c) 2010 Sebastien Bourdeauducq + * + * The license and distribution terms for this file may be + * found in found in the file LICENSE in this distribution or at + * http://www.rtems.org/license/LICENSE. + */ + +#include +#include +#include +#include + +rtems_status_code bsp_interrupt_facility_initialize(void) +{ + return RTEMS_SUCCESSFUL; +} + +void bsp_interrupt_vector_enable(rtems_vector_number vector) +{ + bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector)); + lm32_interrupt_unmask(1 << vector); +} + +void bsp_interrupt_vector_disable(rtems_vector_number vector) +{ + bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector)); + lm32_interrupt_mask(1 << vector); +} diff --git a/bsps/m68k/genmcf548x/irq/intc-icr-init-values.c b/bsps/m68k/genmcf548x/irq/intc-icr-init-values.c new file mode 100644 index 0000000000..afc58224ea --- /dev/null +++ b/bsps/m68k/genmcf548x/irq/intc-icr-init-values.c @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2013 embedded brains GmbH. All rights reserved. + * + * embedded brains GmbH + * Dornierstr. 4 + * 82178 Puchheim + * Germany + * + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.org/license/LICENSE. + */ + +#include +#include + +#define ICR(lvl, prio) (MCF548X_INTC_ICRn_IL(lvl) | MCF548X_INTC_ICRn_IP(prio)) + +const uint8_t mcf548x_intc_icr_init_values[64] = { + [MCF548X_IRQ_SLT0] = ICR(4, 7), + [MCF548X_IRQ_SLT1] = ICR(4, 6), + [MCF548X_IRQ_PSC0] = ICR(3, 7), + [MCF548X_IRQ_PSC1] = ICR(3, 6), + [MCF548X_IRQ_PSC2] = ICR(3, 5), + [MCF548X_IRQ_PSC3] = ICR(3, 4), + [MCF548X_IRQ_FEC0] = ICR(2, 7), + [MCF548X_IRQ_FEC1] = ICR(2, 6) +}; diff --git a/bsps/m68k/genmcf548x/irq/irq.c b/bsps/m68k/genmcf548x/irq/irq.c new file mode 100644 index 0000000000..f02231b67c --- /dev/null +++ b/bsps/m68k/genmcf548x/irq/irq.c @@ -0,0 +1,229 @@ +/* + * Copyright (c) 2013 embedded brains GmbH. All rights reserved. + * + * embedded brains GmbH + * Dornierstr. 4 + * 82178 Puchheim + * Germany + * + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.org/license/LICENSE. + */ + +#include + +#include + +void asm_default_interrupt(void); + +typedef void (*void_func)(void); + +typedef struct { + rtems_interrupt_handler handler; + void *arg; + const char *info; +} interrupt_control; + +static interrupt_control interrupt_controls[BSP_INTERRUPT_VECTOR_MAX + 1]; + +static uint32_t vector_to_reg(rtems_vector_number vector) +{ + return ((vector + 32U) >> 5) & 0x1; +} + +static uint32_t vector_to_bit(rtems_vector_number vector) +{ + return 1U << (vector & 0x1fU); +} + +static volatile uint32_t *vector_to_imr(rtems_vector_number vector) +{ + volatile uint32_t *imr = &MCF548X_INTC_IMRH; + + return &imr[vector_to_reg(vector)]; +} + +static rtems_vector_number exception_vector_to_vector( + rtems_vector_number exception_vector +) +{ + return exception_vector - 64U; +} + +static rtems_vector_number vector_to_exception_vector( + rtems_vector_number vector +) +{ + return vector + 64U; +} + +void bsp_interrupt_vector_enable(rtems_vector_number vector) +{ + volatile uint32_t *imr = vector_to_imr(vector); + uint32_t bit = vector_to_bit(vector); + rtems_interrupt_level level; + + bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector)); + + rtems_interrupt_disable(level); + *imr &= ~bit; + rtems_interrupt_enable(level); +} + +void bsp_interrupt_vector_disable(rtems_vector_number vector) +{ + volatile uint32_t *imr = vector_to_imr(vector); + uint32_t bit = vector_to_bit(vector); + rtems_interrupt_level level; + + bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector)); + + rtems_interrupt_disable(level); + *imr |= bit; + rtems_interrupt_enable(level); +} + +static void_func get_exception_handler(rtems_vector_number vector) +{ + void **vbr; + void_func *exception_table; + + m68k_get_vbr(vbr); + + exception_table = (void_func *)vbr; + + return exception_table[vector_to_exception_vector(vector)]; +} + +static void set_exception_handler(rtems_vector_number vector, void_func handler) +{ + void **vbr; + void_func *exception_table; + + m68k_get_vbr(vbr); + + exception_table = (void_func *)vbr; + + exception_table[vector_to_exception_vector(vector)] = handler; +} + +static void dispatch_handler(rtems_vector_number exception_vector) +{ + const interrupt_control *ic = + &interrupt_controls[exception_vector_to_vector(exception_vector)]; + + (*ic->handler)(ic->arg); +} + +static uint8_t get_intc_icr(rtems_vector_number vector) +{ + volatile uint8_t *icr = &MCF548X_INTC_ICR0; + + return icr[vector]; +} + +rtems_status_code rtems_interrupt_handler_install( + rtems_vector_number vector, + const char *info, + rtems_option options, + rtems_interrupt_handler handler, + void *arg +) +{ + rtems_status_code sc = RTEMS_SUCCESSFUL; + + if (bsp_interrupt_is_valid_vector(vector)) { + rtems_interrupt_level level; + + rtems_interrupt_disable(level); + + if ( + get_exception_handler(vector) == asm_default_interrupt + && get_intc_icr(vector) != 0 + ) { + interrupt_control *ic = &interrupt_controls[vector]; + + ic->handler = handler; + ic->arg = arg; + ic->info = info; + + _ISR_Vector_table[vector_to_exception_vector(vector)] + = dispatch_handler; + set_exception_handler(vector, _ISR_Handler); + bsp_interrupt_vector_enable(vector); + } else { + sc = RTEMS_RESOURCE_IN_USE; + } + + rtems_interrupt_enable(level); + } else { + sc = RTEMS_INVALID_ID; + } + + return sc; +} + +static bool is_occupied_by_us(rtems_vector_number vector) +{ + return get_exception_handler(vector) == _ISR_Handler + && _ISR_Vector_table[vector_to_exception_vector(vector)] + == dispatch_handler; +} + +rtems_status_code rtems_interrupt_handler_remove( + rtems_vector_number vector, + rtems_interrupt_handler handler, + void *arg +) +{ + rtems_status_code sc = RTEMS_SUCCESSFUL; + + if (bsp_interrupt_is_valid_vector(vector)) { + rtems_interrupt_level level; + interrupt_control *ic = &interrupt_controls[vector]; + + rtems_interrupt_disable(level); + + if ( + is_occupied_by_us(vector) + && ic->handler == handler + && ic->arg == arg + ) { + bsp_interrupt_vector_disable(vector); + set_exception_handler(vector, asm_default_interrupt); + + memset(ic, 0, sizeof(*ic)); + } else { + sc = RTEMS_UNSATISFIED; + } + + rtems_interrupt_enable(level); + } else { + sc = RTEMS_INVALID_ID; + } + + return sc; +} + +rtems_status_code rtems_interrupt_handler_iterate( + rtems_vector_number vector, + rtems_interrupt_per_handler_routine routine, + void *arg +) +{ + rtems_status_code sc = RTEMS_SUCCESSFUL; + + if (bsp_interrupt_is_valid_vector(vector)) { + if (is_occupied_by_us(vector)) { + const interrupt_control *ic = &interrupt_controls[vector]; + + (*routine)(arg, ic->info, RTEMS_INTERRUPT_UNIQUE, ic->handler, ic->arg); + } + } else { + sc = RTEMS_INVALID_ID; + } + + return sc; +} diff --git a/bsps/mips/csb350/irq/vectorisrs.c b/bsps/mips/csb350/irq/vectorisrs.c new file mode 100644 index 0000000000..d8e071281e --- /dev/null +++ b/bsps/mips/csb350/irq/vectorisrs.c @@ -0,0 +1,168 @@ +/** + * @file + * + * Au1x00 Interrupt Vectoring + */ + +/* + * Copyright (c) 2005 by Cogent Computer Systems + * Written by Jay Monkman + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.org/license/LICENSE. + */ + +#include +#include +#include +#include +#include +#include +#include + +static void call_vectored_isr(CPU_Interrupt_frame *, uint32_t , void *); + +#include /* for printk */ + +void mips_vector_isr_handlers( CPU_Interrupt_frame *frame ) +{ + unsigned int sr; + unsigned int cause; + + mips_get_sr( sr ); + mips_get_cause( cause ); + + cause &= (sr & SR_IMASK); + cause >>= CAUSE_IPSHIFT; + + /* count/compare interrupt */ + if ( cause & 0x80 ) { + unsigned long zero = 0; + /* + * I don't see a good way to disable the compare + * interrupt, so let's just ignore it. + */ + __asm__ volatile ("mtc0 %0, $11\n" :: "r" (zero)); + } + + /* Performance counter */ + if ( cause & 0x40 ) { + bsp_interrupt_handler_dispatch(AU1X00_IRQ_PERF); + } + + /* Interrupt controller 0 */ + if ( cause & 0x0c ) { + call_vectored_isr(frame, cause, (void *)AU1X00_IC0_ADDR); + } + + /* Interrupt controller 1 */ + if ( cause & 0x30 ) { + call_vectored_isr(frame, cause, (void *)AU1X00_IC1_ADDR); + } + + /* SW[0] */ + if ( cause & 0x01 ) + bsp_interrupt_handler_dispatch( AU1X00_IRQ_SW0 ); + + /* SW[1] */ + if ( cause & 0x02 ) + bsp_interrupt_handler_dispatch( AU1X00_IRQ_SW1 ); +} + +void mips_default_isr( int vector ) +{ + unsigned int sr; + unsigned int cause; + + mips_get_sr( sr ); + mips_get_cause( cause ); + + printk( "Unhandled isr exception: vector 0x%02x, cause 0x%08X, sr 0x%08X\n", + vector, cause, sr ); + rtems_fatal_error_occurred(1); +} + +static void call_vectored_isr( + CPU_Interrupt_frame *frame, + uint32_t cause, + void *ctrlr + ) +{ + uint32_t src; + uint32_t mask; + int index; + + /* get mask register */ + mask = AU1X00_IC_MASKRD(ctrlr); + + /* check request 0 */ + src = AU1X00_IC_REQ0INT(ctrlr); + src = src & mask; + index = 0; + while (src) { + /* check LSB */ + if (src & 1) { + /* clear rising/falling edge detects */ + AU1X00_IC_RISINGCLR(ctrlr) = (1 << index); + AU1X00_IC_FALLINGCLR(ctrlr) = (1 << index); + au_sync(); + bsp_interrupt_handler_dispatch(AU1X00_IRQ_IC0_BASE + index); + } + index ++; + + /* shift, and make sure MSB is clear */ + src = (src >> 1) & 0x7fffffff; + } + + /* check request 1 */ + src = AU1X00_IC_REQ1INT(ctrlr); + src = src & mask; + index = 0; + while (src) { + /* check LSB */ + if (src & 1) { + /* clear rising/falling edge detects */ + AU1X00_IC_RISINGCLR(ctrlr) = (1 << index); + AU1X00_IC_FALLINGCLR(ctrlr) = (1 << index); + au_sync(); + bsp_interrupt_handler_dispatch(AU1X00_IRQ_IC0_BASE + index); + } + index ++; + + /* shift, and make sure MSB is clear */ + src = (src >> 1) & 0x7fffffff; + } +} + +/* Generate a software interrupt */ +int assert_sw_irq(uint32_t irqnum) +{ + uint32_t cause; + + if (irqnum <= 1) { + mips_get_cause(cause); + cause = cause | ((irqnum + 1) << CAUSE_IPSHIFT); + mips_set_cause(cause); + + return irqnum; + } else { + return -1; + } +} + +/* Clear a software interrupt */ +int negate_sw_irq(uint32_t irqnum) +{ + uint32_t cause; + + if (irqnum <= 1) { + mips_get_cause(cause); + cause = cause & ~((irqnum + 1) << CAUSE_IPSHIFT); + mips_set_cause(cause); + + return irqnum; + } else { + return -1; + } +} diff --git a/bsps/mips/hurricane/irq/vectorisrs.c b/bsps/mips/hurricane/irq/vectorisrs.c new file mode 100644 index 0000000000..e55566697d --- /dev/null +++ b/bsps/mips/hurricane/irq/vectorisrs.c @@ -0,0 +1,58 @@ +/** + * @file + * + * RM5231 Interrupt Vectoring + */ + +/* + * COPYRIGHT (c) 1989-2012. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.org/license/LICENSE. + */ + +#include +#include +#include +#include +#include +#include + +#include /* for printk */ + +void mips_default_isr( int vector ); + +void mips_vector_isr_handlers( CPU_Interrupt_frame *frame ) +{ + unsigned int sr; + unsigned int cause; + unsigned int i; + unsigned int mask; + + mips_get_sr( sr ); + mips_get_cause( cause ); + + cause &= (sr & SR_IMASK); + cause >>= CAUSE_IPSHIFT; + + for ( i=1, mask=0x80 ; i<=8 ; i++, mask >>= 1 ) { + if ( cause & mask ) + bsp_interrupt_handler_dispatch( MIPS_INTERRUPT_BASE + 8 - i ); + } +} + +void mips_default_isr( int vector ) +{ + unsigned int sr; + unsigned int cause; + + mips_get_sr( sr ); + mips_get_cause( cause ); + + printk( "Unhandled isr exception: vector 0x%02x, cause 0x%08X, sr 0x%08X\n", + vector, cause, sr ); + rtems_fatal_error_occurred(1); +} + diff --git a/bsps/mips/jmr3904/irq/vectorisrs.c b/bsps/mips/jmr3904/irq/vectorisrs.c new file mode 100644 index 0000000000..629c4c45f8 --- /dev/null +++ b/bsps/mips/jmr3904/irq/vectorisrs.c @@ -0,0 +1,47 @@ +/** + * @file + * + * TX3904 Interrupt Vectoring + */ + +/* + * COPYRIGHT (c) 1989-2012. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.org/license/LICENSE. + */ + +#include +#include +#include +#include /* for printk */ +#include +#include + +void mips_vector_isr_handlers( CPU_Interrupt_frame *frame ) +{ + unsigned int sr; + unsigned int cause; + + mips_get_sr( sr ); + mips_get_cause( cause ); + + cause &= (sr & SR_IMASK); + cause >>= CAUSE_IPSHIFT; + + if ( cause & 0x80 ) /* IP[5] ==> INT0 */ + bsp_interrupt_handler_dispatch( TX3904_IRQ_INT0 ); + + if ( cause & 0x40 ) { /* (IP[4] == 1) ==> IP[0-3] are valid */ + unsigned int v = (cause >> 2) & 0x0f; + bsp_interrupt_handler_dispatch( MIPS_INTERRUPT_BASE + v ); + } + + if ( cause & 0x02 ) /* SW[0] */ + bsp_interrupt_handler_dispatch( TX3904_IRQ_SOFTWARE_1 ); + + if ( cause & 0x01 ) /* IP[1] */ + bsp_interrupt_handler_dispatch( TX3904_IRQ_SOFTWARE_2 ); +} diff --git a/bsps/mips/malta/irq/interruptmask.c b/bsps/mips/malta/irq/interruptmask.c new file mode 100644 index 0000000000..d639ab17a9 --- /dev/null +++ b/bsps/mips/malta/irq/interruptmask.c @@ -0,0 +1,36 @@ +/** + * @file + * + * This file contains the implementation of the MIPS port + * support routine which provides the BSP specific default + * interrupt mask. + */ + +/* + * COPYRIGHT (c) 1989-2012. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.org/license/LICENSE. + */ + +#include + +/* + * This function returns a mask value which is used to select the bits + * in the processor status register that can be set to enable interrupts. + * The mask value should not include the 2 software interrupt enable bits. + */ + +uint32_t mips_interrupt_mask( void ) +{ + uint32_t interrupt_mask; + + /* + * This has only been tested with qemu for the mips malta and + * may not be correct for the 24k on real hardware. + */ + interrupt_mask = 0x0000ff00; + return(interrupt_mask); +} diff --git a/bsps/mips/malta/irq/vectorisrs.c b/bsps/mips/malta/irq/vectorisrs.c new file mode 100644 index 0000000000..a2b9288646 --- /dev/null +++ b/bsps/mips/malta/irq/vectorisrs.c @@ -0,0 +1,90 @@ +/** + * @file + * + */ + +/* + * COPYRIGHT (c) 1989-2012. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.org/license/LICENSE. + */ + +#include +#include +#include +#include +#include +#include +#include + +void mips_default_isr( int vector ); + +#include /* for printk */ + +void mips_vector_isr_handlers( CPU_Interrupt_frame *frame ) +{ + unsigned int sr; + unsigned int cause; + unsigned int pending; + + mips_get_sr( sr ); + mips_get_cause( cause ); + + pending = (cause & sr & 0xff00) >> CAUSE_IPSHIFT; + + /* SW Bits */ + if ( pending & 0x01) { + printk("Pending IRQ Q 0x%x\n", pending ); + } + + if ( pending & 0x02) { + printk("Pending IRQ Q 0x%x\n", pending ); + } + + /* South Bridge Interrupt */ + if ( pending & 0x04) { + BSP_i8259s_int_process(); + } + + /* South Bridge SMI */ + if (pending & 0x08){ + printk( "Pending IRQ 0x%x\n", pending ); + } + + /* TTY 2 */ + if (pending & 0x10) { + printk( "Pending IRQ 0x%x\n", pending ); + } + /* Core HI */ + if (pending & 0x20) { + printk( "Pending IRQ 0x%x\n", pending ); + } + /* Core LO */ + if (pending & 0x40) { + printk( "Pending IRQ 0x%x\n", pending ); + } + + if ( pending & 0x80 ) { + bsp_interrupt_handler_dispatch( MALTA_INT_TICKER ); + } +} + +void mips_default_isr( int vector ) +{ + unsigned int sr; + unsigned int cause; + + mips_get_sr( sr ); + mips_get_cause( cause ); + + printk( "Unhandled isr exception: vector 0x%02x, cause 0x%08X, sr 0x%08X\n", + vector, cause, sr ); + + while(1); /* Lock it up */ + + rtems_fatal_error_occurred(1); +} + diff --git a/bsps/mips/rbtx4925/irq/vectorisrs.c b/bsps/mips/rbtx4925/irq/vectorisrs.c new file mode 100644 index 0000000000..09020c5020 --- /dev/null +++ b/bsps/mips/rbtx4925/irq/vectorisrs.c @@ -0,0 +1,64 @@ +/** + * @file + * + * TX4925 Interrupt Vectoring + */ + +/* + * COPYRIGHT (c) 1989-2012. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.org/license/LICENSE. + */ + +#include +#include +#include +#include +#include +#include +#include /* for printk */ + +void mips_default_isr( int vector ); + +void mips_vector_isr_handlers( CPU_Interrupt_frame *frame ) +{ + unsigned int sr; + unsigned int cause; + unsigned int pending; + + mips_get_sr( sr ); + mips_get_cause( cause ); + + pending = (cause & sr & 0x700) >> CAUSE_IPSHIFT; + + if ( pending & 0x4 ) { /* (IP[2] == 1) ==> IP[3-7] are valid */ + unsigned int v = (cause >> (CAUSE_IPSHIFT + 3)) & 0x1f; + bsp_interrupt_handler_dispatch( MIPS_INTERRUPT_BASE + v ); + } + + if ( pending & 0x01 ) /* IP[0] */ + bsp_interrupt_handler_dispatch( TX4925_IRQ_SOFTWARE_1 ); + + if ( pending & 0x02 ) /* IP[1] */ + bsp_interrupt_handler_dispatch( TX4925_IRQ_SOFTWARE_2 ); +} + +void mips_default_isr( int vector ) +{ + unsigned int sr; + unsigned int cause; + + mips_get_sr( sr ); + mips_get_cause( cause ); + + printk( "Unhandled isr exception: vector 0x%02x, cause 0x%08X, sr 0x%08X\n", + vector, cause, sr ); + + while(1); /* Lock it up */ + + rtems_fatal_error_occurred(1); +} + diff --git a/bsps/mips/rbtx4938/irq/vectorisrs.c b/bsps/mips/rbtx4938/irq/vectorisrs.c new file mode 100644 index 0000000000..d38e4f81c2 --- /dev/null +++ b/bsps/mips/rbtx4938/irq/vectorisrs.c @@ -0,0 +1,64 @@ +/** + * @file + * + * TX4925 Interrupt Vectoring + */ + +/* + * COPYRIGHT (c) 1989-2012. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.org/license/LICENSE. + */ + +#include +#include +#include +#include +#include +#include +#include /* for printk */ + +void mips_default_isr( int vector ); + +void mips_vector_isr_handlers( CPU_Interrupt_frame *frame ) +{ + unsigned int sr; + unsigned int cause; + unsigned int pending; + + mips_get_sr( sr ); + mips_get_cause( cause ); + + pending = (cause & sr & 0x700) >> CAUSE_IPSHIFT; + + if ( pending & 0x4 ) { /* (IP[2] == 1) ==> IP[3-7] are valid */ + unsigned int v = (cause >> (CAUSE_IPSHIFT + 3)) & 0x1f; + bsp_interrupt_handler_dispatch( MIPS_INTERRUPT_BASE + v ); + } + + if ( pending & 0x01 ) /* IP[0] */ + bsp_interrupt_handler_dispatch( TX4938_IRQ_SOFTWARE_1 ); + + if ( pending & 0x02 ) /* IP[1] */ + bsp_interrupt_handler_dispatch( TX4938_IRQ_SOFTWARE_2 ); +} + +void mips_default_isr( int vector ) +{ + unsigned int sr; + unsigned int cause; + + mips_get_sr( sr ); + mips_get_cause( cause ); + + printk( "Unhandled isr exception: vector 0x%02x, cause 0x%08X, sr 0x%08X\n", + vector, cause, sr ); + + while(1); /* Lock it up */ + + rtems_fatal_error_occurred(1); +} + diff --git a/bsps/mips/shared/irq/exception.S b/bsps/mips/shared/irq/exception.S new file mode 100644 index 0000000000..e916ae55fe --- /dev/null +++ b/bsps/mips/shared/irq/exception.S @@ -0,0 +1,661 @@ +/* + * This file contains a customized MIPS exception handler. + * It hooks into the exception handler present in the resident + * PMON debug monitor. + */ + +/* + * Author: Bruce Robinson + * + * This code was derived from cpu_asm.S with the following copyright: + * + * COPYRIGHT (c) 1996 by Transition Networks Inc. + * + * To anyone who acknowledges that this file is provided "AS IS" + * without any express or implied warranty: + * permission to use, copy, modify, and distribute this file + * for any purpose is hereby granted without fee, provided that + * the above copyright notice and this notice appears in all + * copies, and that the name of Transition Networks not be used in + * advertising or publicity pertaining to distribution of the + * software without specific, written prior permission. + * Transition Networks makes no representations about the suitability + * of this software for any purpose. + * + * Derived from c/src/exec/score/cpu/no_cpu/cpu_asm.s: + * + * COPYRIGHT (c) 1989-2010. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.org/license/LICENSE. + */ + +#include +#include +#include +#include +#include +#if BSP_HAS_USC320 + #include +#endif + +#if __mips == 3 +/* 64 bit register operations */ +#define NOP nop +#define ADD dadd +#define STREG sd +#define LDREG ld +#define ADDU addu +#define ADDIU addiu +#define STREGC1 sdc1 +#define LDREGC1 ldc1 +#define R_SZ 8 +#define F_SZ 8 +#define SZ_INT 8 +#define SZ_INT_POW2 3 + +/* XXX if we don't always want 64 bit register ops, then another ifdef */ + +#elif __mips == 1 +/* 32 bit register operations*/ +#define NOP nop +#define ADD add +#define STREG sw +#define LDREG lw +#define ADDU add +#define ADDIU addi +#define STREGC1 swc1 +#define LDREGC1 lwc1 +#define R_SZ 4 +#define F_SZ 4 +#define SZ_INT 4 +#define SZ_INT_POW2 2 +#else +#error "mips assembly: what size registers do I deal with?" +#endif + + +#define ISR_VEC_SIZE 4 +#define EXCP_STACK_SIZE (NREGS*R_SZ) + +.extern _Thread_Dispatch + +/* void __ISR_Handler() + * + * This routine provides the RTEMS interrupt management. + * + */ + +#if 0 +void _ISR_Handler() +{ + /* + * This discussion ignores a lot of the ugly details in a real + * implementation such as saving enough registers/state to be + * able to do something real. Keep in mind that the goal is + * to invoke a user's ISR handler which is written in C and + * uses a certain set of registers. + * + * Also note that the exact order is to a large extent flexible. + * Hardware will dictate a sequence for a certain subset of + * _ISR_Handler while requirements for setting + */ + + /* + * At entry to "common" _ISR_Handler, the vector number must be + * available. On some CPUs the hardware puts either the vector + * number or the offset into the vector table for this ISR in a + * known place. If the hardware does not give us this information, + * then the assembly portion of RTEMS for this port will contain + * a set of distinct interrupt entry points which somehow place + * the vector number in a known place (which is safe if another + * interrupt nests this one) and branches to _ISR_Handler. + * + */ +#endif +FRAME(bsp_ISR_Handler,sp,0,ra) + .set noreorder + +#if 0 +/* Activate TX49xx PIO19 signal for diagnostics */ + lui k0,0xff1f + ori k0,k0,0xf500 + lw k0,(k0) + lui k1,0x8 + or k1,k1,k0 + lui k0,0xff1f + ori k0,k0,0xf500 + sw k1,(k0) +#endif + mfc0 k0,C0_CAUSE /* Determine if an interrupt generated this exception */ + nop + and k1,k0,CAUSE_EXCMASK + beq k1,zero,_chk_int /* If so, branch to service here */ + nop + la k0,_int_esr_link /* Otherwise, jump to next exception handler in PMON exception chain */ + lw k0,(k0) + lw k0,4(k0) + j k0 + nop +_chk_int: + mfc0 k1,C0_SR + nop + and k0,k1 +#if HAS_RM52xx + and k0,CAUSE_IPMASK +#elif HAS_TX49xx + and k0,(SR_IBIT1 | SR_IBIT2 | SR_IBIT3) +#endif + /* external interrupt not enabled, ignore */ + beq k0,zero,_ISR_Handler_quick_exit + nop + +/* For debugging interrupts, clear EXL to allow breakpoints */ +#if 0 + MFC0 k0, C0_SR +#if __mips == 3 + li k1,SR_EXL /* Clear EXL and Set IE to enable interrupts */ + not k1 + and k0,k1 + li k1,SR_IE +#elif __mips == 1 + li k1,SR_IEC +#endif + or k0, k1 + mtc0 k0, C0_SR + NOP +#endif + + + /* + * save some or all context on stack + * may need to save some special interrupt information for exit + */ + + /* Q: _ISR_Handler, not using IDT/SIM ...save extra regs? */ + + /* wastes a lot of stack space for context?? */ + ADDIU sp,sp,-EXCP_STACK_SIZE + + STREG ra, R_RA*R_SZ(sp) /* store ra on the stack */ + STREG v0, R_V0*R_SZ(sp) + STREG v1, R_V1*R_SZ(sp) + STREG a0, R_A0*R_SZ(sp) + STREG a1, R_A1*R_SZ(sp) + STREG a2, R_A2*R_SZ(sp) + STREG a3, R_A3*R_SZ(sp) + STREG t0, R_T0*R_SZ(sp) + STREG t1, R_T1*R_SZ(sp) + STREG t2, R_T2*R_SZ(sp) + STREG t3, R_T3*R_SZ(sp) + STREG t4, R_T4*R_SZ(sp) + STREG t5, R_T5*R_SZ(sp) + STREG t6, R_T6*R_SZ(sp) + STREG t7, R_T7*R_SZ(sp) + mflo t0 + STREG t8, R_T8*R_SZ(sp) + STREG t0, R_MDLO*R_SZ(sp) + STREG t9, R_T9*R_SZ(sp) + mfhi t0 + STREG gp, R_GP*R_SZ(sp) + STREG t0, R_MDHI*R_SZ(sp) + STREG fp, R_FP*R_SZ(sp) + + .set noat + STREG AT, R_AT*R_SZ(sp) + .set at + + mfc0 t0,C0_SR + dmfc0 t1,C0_EPC + STREG t0,R_SR*R_SZ(sp) + STREG t1,R_EPC*R_SZ(sp) + + /* + * + * #if ( CPU_HAS_SOFTWARE_INTERRUPT_STACK == TRUE ) + * if ( _ISR_Nest_level == 0 ) + * switch to software interrupt stack + * #endif + */ + + /* + * _ISR_Nest_level++; + */ + lw t0,ISR_NEST_LEVEL + NOP + add t0,t0,1 + sw t0,ISR_NEST_LEVEL + /* + * _Thread_Dispatch_disable_level++; + */ + lw t1,THREAD_DISPATCH_DISABLE_LEVEL + NOP + add t1,t1,1 + sw t1,THREAD_DISPATCH_DISABLE_LEVEL + + /* DEBUG - Add the following code to disable interrupts and clear + * EXL in status register, this will allow memory + * exceptions to occur while servicing the current interrupt + */ +#if 0 + /* Disable interrupts from internal interrupt controller */ + li t0,~CAUSE_IP2_MASK + mfc0 t1,C0_SR + nop + and t1,t0 + mtc0 t1,C0_SR + nop + /* Clear EXL in status register to allow memory exceptions to occur */ + li t0,~SR_EXL + mfc0 t1,C0_SR + nop + and t1,t0 + mtc0 t1,C0_SR + nop +#endif + + /* + * Call the CPU model or BSP specific routine to decode the + * interrupt source and actually vector to device ISR handlers. + */ + move a0,sp + jal mips_vector_isr_handlers + NOP + + /* Add the following code to disable interrupts (see DEBUG above) */ +#if 0 + li t0,SR_EXL /* Set EXL to hold off interrupts */ + mfc0 t1,C0_SR + nop + or t1,t0 + mtc0 t1,C0_SR + nop + /* Enable interrupts from internal interrupt controller */ + li t0,CAUSE_IP2_MASK + mfc0 t1,C0_SR + nop + or t1,t0 + mtc0 t1,C0_SR + nop +#endif + +_ISR_Handler_cleanup: + + /* + * --_ISR_Nest_level; + */ + lw t2,ISR_NEST_LEVEL + NOP + add t2,t2,-1 + sw t2,ISR_NEST_LEVEL + /* + * --_Thread_Dispatch_disable_level; + */ + lw t1,THREAD_DISPATCH_DISABLE_LEVEL + NOP + add t1,t1,-1 + sw t1,THREAD_DISPATCH_DISABLE_LEVEL + /* + * if ( _Thread_Dispatch_disable_level || _ISR_Nest_level ) + * goto the label "exit interrupt (simple case)" + */ + or t0,t2,t1 + bne t0,zero,_ISR_Handler_exit + NOP + + + /* + * #if ( CPU_HAS_SOFTWARE_INTERRUPT_STACK == TRUE ) + * restore stack + * #endif + * + * if ( !_Thread_Dispatch_necessary ) + * goto the label "exit interrupt (simple case)" + */ + lb t0,DISPATCH_NEEDED + NOP + or t0,t0,t0 + beq t0,zero,_ISR_Handler_exit + NOP + +/* +** Turn on interrupts before entering Thread_Dispatch which +** will run for a while, thus allowing new interrupts to +** be serviced. Observe the Thread_Dispatch_disable_level interlock +** that prevents recursive entry into Thread_Dispatch. +*/ + + mfc0 t0, C0_SR +#if __mips == 3 + li t1,SR_EXL /* Clear EXL and Set IE to enable interrupts */ + not t1 + and t0,t1 + li t1,SR_IE +#elif __mips == 1 + li t1,SR_IEC +#endif + or t0, t1 + mtc0 t0, C0_SR + NOP + + /* save off our stack frame so the context switcher can get to it */ + la t0,__exceptionStackFrame + STREG sp,(t0) + + jal _Thread_Dispatch + NOP + + /* and make sure its clear in case we didn't dispatch. if we did, its + ** already cleared */ + la t0,__exceptionStackFrame + STREG zero,(t0) + NOP + +/* +** turn interrupts back off while we restore context so +** a badly timed interrupt won't accidentally mess things up +*/ + mfc0 t0, C0_SR +#if __mips == 3 + li t1,SR_IE /* Clear IE first (recommended) */ + not t1 + and t0,t1 + mtc0 t0, C0_SR + li t1,SR_EXL | SR_IE /* Set EXL and IE, this puts status register bits back to interrupted state */ + or t0,t1 +#elif __mips == 1 + /* ints off, current & prev kernel mode on (kernel mode enabled is bit clear..argh!) */ + li t1,SR_IEC | SR_KUP | SR_KUC + not t1 + and t0, t1 +#endif + mtc0 t0, C0_SR + NOP + + /* + * prepare to get out of interrupt + * return from interrupt (maybe to _ISR_Dispatch) + * + * LABEL "exit interrupt (simple case):" + * prepare to get out of interrupt + * return from interrupt + */ + +_ISR_Handler_exit: + +/* restore interrupt context from stack */ + LDREG t8, R_MDLO*R_SZ(sp) + LDREG t0, R_T0*R_SZ(sp) + mtlo t8 + LDREG t8, R_MDHI*R_SZ(sp) + LDREG t1, R_T1*R_SZ(sp) + mthi t8 + LDREG t2, R_T2*R_SZ(sp) + LDREG t3, R_T3*R_SZ(sp) + LDREG t4, R_T4*R_SZ(sp) + LDREG t5, R_T5*R_SZ(sp) + LDREG t6, R_T6*R_SZ(sp) + LDREG t7, R_T7*R_SZ(sp) + LDREG t8, R_T8*R_SZ(sp) + LDREG t9, R_T9*R_SZ(sp) + LDREG gp, R_GP*R_SZ(sp) + LDREG fp, R_FP*R_SZ(sp) + LDREG ra, R_RA*R_SZ(sp) + LDREG a0, R_A0*R_SZ(sp) + LDREG a1, R_A1*R_SZ(sp) + LDREG a2, R_A2*R_SZ(sp) + LDREG a3, R_A3*R_SZ(sp) + LDREG v1, R_V1*R_SZ(sp) + LDREG v0, R_V0*R_SZ(sp) + + LDREG k1, R_EPC*R_SZ(sp) + mtc0 k1,C0_EPC + + .set noat + LDREG AT, R_AT*R_SZ(sp) + .set at + + ADDIU sp,sp,EXCP_STACK_SIZE + +_ISR_Handler_quick_exit: + eret + nop + + +#if BSP_HAS_USC320 + /* Interrupts from USC320 are serviced here */ + .global USC_isr + .extern Clock_isr +USC_isr: + /* check if it's a USC320 heartbeat interrupt */ + la k0,INT_STAT /* read INT_STAT register */ + lw k0,(k0) + nop /* reading from external device */ + sll k0,(31-21) /* test bit 21 (HBI) */ + + bgez k0,USC_isr2 /* branch if not a heartbeat interrupt */ + NOP + + /* clear the heartbeat interrupt */ + la k0,INT_STAT + li t0,HBI_MASK + sw t0,(k0) + /* wait for interrupt to clear */ +USC_isr1: + la k0,INT_STAT /* read INT_STAT register */ + lw k0,(k0) + nop /* reading from external device */ + sll k0,(31-21) /* test bit 21 (HBI) */ + bltz k0,USC_isr1 /* branch if bit set */ + nop + j Clock_isr /* Jump to clock isr */ + nop +USC_isr2: + j ra /* no serviceable interrupt, return without doing anything */ + nop +#endif + +#if 0 + .global int7_isr + .extern Interrupt_7_isr +int7_isr: + /* Verify interrupt is from Timer */ + la k0,IRCS /* read Interrupt Current Status register */ + lw k0,(k0) + nop /* reading from external device */ + li k1,IRCS_CAUSE_MASK + and k0,k0,k1 /* isolate interrupt cause */ + + li k1,INT7INT /* test for interrupt 7 */ + subu k1,k0,k1 + beq k1,zero,int7_isr1 + nop + j ra /* interrupt 7 no longer valid, return without doing anything */ + nop +int7_isr1: + j Interrupt_7_isr /* Jump to Interrupt 7 isr */ + nop +#endif + + .set reorder + +ENDFRAME(bsp_ISR_Handler) + + +FRAME(_BRK_Handler,sp,0,ra) + .set noreorder + +#if BSP_HAS_USC320 + la k0,INT_CFG3 /* Disable heartbeat interrupt in USC320, it interferes with PMON exception handler */ + lw k1,(k0) + li k0,~HBI_MASK + and k1,k1,k0 + la k0,INT_CFG3 + sw k1,(k0) +#endif + + la k0,_brk_esr_link /* Jump to next exception handler in PMON exception chain */ + lw k0,(k0) + lw k0,4(k0) + j k0 + nop + + .set reorder +ENDFRAME(_BRK_Handler) + + +/************************************************************************** +** +** init_exc_vecs() - moves the exception code into the addresses +** reserved for exception vectors +** +** UTLB Miss exception vector at address 0x80000000 +** +** General exception vector at address 0x80000080 +** +** RESET exception vector is at address 0xbfc00000 +** +***************************************************************************/ + +FRAME(init_exc_vecs,sp,0,ra) + .set noreorder + + .extern mon_onintr + +/* Install interrupt handler in PMON exception handling chain */ + + addiu sp,sp,-8 + sw ra,(sp) /* Save ra contents on stack */ + move a0,zero + la a1,_int_esr_link + jal mon_onintr /* Make PMON system call to install interrupt exception handler */ + nop + li a0,9 + la a1,_brk_esr_link + jal mon_onintr /* Make PMON system call to install break exception handler */ + nop + lw ra,(sp) + addiu sp,sp,8 /* Restore ra contents from stack */ + j ra + nop + + .set reorder +ENDFRAME(init_exc_vecs) + + +#if 0 /* Unused code below */ + +/************************************************************* +* enable_int7(ints) +* Enable interrupt 7 +*/ +FRAME(enable_int7,sp,0,ra) + .set noreorder + + la t0,IRDM1 # Set interrupt controller detection mode (bits 2-3 = 0 for int 7 active low) + li t1,0x0 + sw t1,(t0) + + la t0,IRLVL4 # Set interrupt controller level (bit 8-10 = 2 for int 7 at level 2) + li t1,0x200 + sw t1,(t0) + + la t0,IRMSK # Set interrupt controller mask + li t1,0x0 + sw t1,(t0) + + la t0,IRDEN # Enable interrupts from controller + li t1,0x1 + sw t1,(t0) + + j ra + nop + .set reorder +ENDFRAME(enable_int7) + +/************************************************************* +* disable_int7(ints) +* Disable interrupt 7 +*/ +FRAME(disable_int7,sp,0,ra) + .set noreorder + + la t0,IRLVL4 # Set interrupt controller level (bit 8-10 = 0 to diasble int 7) + li t1,0x200 + sw t1,(t0) + + j ra + nop + .set reorder +ENDFRAME(disable_int7) +#endif + +/************************************************************* +* exception: +* Diagnostic code that can be hooked to PMON interrupt handler. +* Generates pulse on PIO22 pin. +* Called from _exception code in PMON (see mips.s of PMON). +* Return address is located in k1. +*/ +FRAME(tx49xxexception,sp,0,ra) + .set noreorder + la k0,k1tmp + sw k1,(k0) + +/* Activate TX49xx PIO22 signal for diagnostics */ + lui k0,0xff1f + ori k0,k0,0xf500 + lw k0,(k0) + lui k1,0x40 + or k1,k1,k0 + lui k0,0xff1f + ori k0,k0,0xf500 + sw k1,(k0) + nop + +/* De-activate TX49xx PIO22 signal for diagnostics */ + lui k0,0xff1f + ori k0,k0,0xf500 + lw k0,(k0) + lui k1,0x40 + not k1 + and k1,k1,k0 + lui k0,0xff1f + ori k0,k0,0xf500 + sw k1,(k0) + nop + + la k0,k1tmp + lw k1,(k0) + j k1 + .set reorder +ENDFRAME(tx49xxexception) + + + + + .data + +k1tmp: .word 0 /* Temporary strage for K1 during interrupt service */ + +/************************************************************* +* +* Exception handler links, used in PMON exception handler chains +*/ + /* Interrupt exception service routine link */ + .global _int_esr_link +_int_esr_link: + .word 0 + .word bsp_ISR_Handler + + /* Break exception service routine link */ + .global _brk_esr_link +_brk_esr_link: + .word 0 + .word _BRK_Handler + + + + diff --git a/bsps/mips/shared/irq/i8259.c b/bsps/mips/shared/irq/i8259.c new file mode 100644 index 0000000000..d92b5400a9 --- /dev/null +++ b/bsps/mips/shared/irq/i8259.c @@ -0,0 +1,332 @@ +/** + * @file + * + * This file was based upon the powerpc and the i386. + */ + +/* + * COPYRIGHT (c) 1989-2012. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.org/license/LICENSE. + */ + +/* + * Copyright (C) 1998, 1999 valette@crf.canon.fr + */ + +#include +#include +#include +#include +#include +#include + + +#define DEBUG_8259 1 + +#define ValidateIrqLine( _irq ) \ + if ( ((int)_irq < 0) ||((int)_irq > 16)) return 1; + +/*-------------------------------------------------------------------------+ +| Cache for 1st and 2nd PIC IRQ line's status (enabled or disabled) register. ++--------------------------------------------------------------------------*/ +/* + * lower byte is interrupt mask on the master PIC. + * while upper bits are interrupt on the slave PIC. + */ +volatile rtems_i8259_masks i8259s_cache = 0xfffb; + +/*-------------------------------------------------------------------------+ +| Function: BSP_irq_disable_at_i8259s +| Description: Mask IRQ line in appropriate PIC chip. +| Global Variables: i8259s_cache +| Arguments: vector_offset - number of IRQ line to mask. +| Returns: original state or -1 on error. ++--------------------------------------------------------------------------*/ +int BSP_irq_disable_at_i8259s (const rtems_irq_number irqLine) +{ + unsigned short mask; + rtems_interrupt_level level; + int rval; + + ValidateIrqLine(irqLine); + + rtems_interrupt_disable(level); + + /* Recalculate the value */ + mask = 1 << irqLine; + rval = i8259s_cache & mask ? 0 : 1; + i8259s_cache |= mask; + + /* Determine which chip and write the value. */ + if (irqLine < 8) { + simple_out_8( + BSP_8259_BASE_ADDRESS, + PIC_MASTER_IMR_IO_PORT, + i8259s_cache & 0xff + ); + } else { + simple_out_8( + BSP_8259_BASE_ADDRESS, + PIC_SLAVE_IMR_IO_PORT, + ((i8259s_cache & 0xff00) >> 8) + ); + } + + rtems_interrupt_enable(level); + + return rval; +} + +/*-------------------------------------------------------------------------+ +| Function: BSP_irq_enable_at_i8259s +| Description: Unmask IRQ line in appropriate PIC chip. +| Global Variables: i8259s_cache +| Arguments: irqLine - number of IRQ line to mask. +| Returns: Nothing. ++--------------------------------------------------------------------------*/ +int BSP_irq_enable_at_i8259s (const rtems_irq_number irqLine) +{ + unsigned short mask; + rtems_interrupt_level level; + + ValidateIrqLine( irqLine ); + + rtems_interrupt_disable(level); + + /* Calculate the value */ + mask = ~(1 << irqLine); + i8259s_cache &= mask; + + /* Determine which chip and write the value */ + if (irqLine < 8) { + simple_out_8( + BSP_8259_BASE_ADDRESS, + PIC_MASTER_IMR_IO_PORT, + i8259s_cache & 0xff + ); + } else { + simple_out_8( + BSP_8259_BASE_ADDRESS, + PIC_SLAVE_IMR_IO_PORT, + ((i8259s_cache & 0xff00) >> 8) + ); + } + + rtems_interrupt_enable(level); + + return 0; +} /* mask_irq */ + + +int BSP_irq_enabled_at_i8259s(const rtems_irq_number irqLine) +{ + unsigned short mask; + + ValidateIrqLine( irqLine ); + + mask = (1 << irqLine); + + return (~(i8259s_cache & mask)); +} + +/*-------------------------------------------------------------------------+ +| Function: BSP_irq_ack_at_i8259s +| Description: Signal generic End Of Interrupt (EOI) to appropriate PIC. +| Global Variables: None. +| Arguments: irqLine - number of IRQ line to acknowledge. +| Returns: Nothing. ++--------------------------------------------------------------------------*/ +int BSP_irq_ack_at_i8259s (const rtems_irq_number irqLine) +{ + if (irqLine >= 8) { + simple_out_8( + BSP_8259_BASE_ADDRESS, + PIC_MASTER_COMMAND_IO_PORT, + SLAVE_PIC_EOSI + ); + simple_out_8( + BSP_8259_BASE_ADDRESS, + PIC_SLAVE_COMMAND_IO_PORT, + (PIC_EOSI | (irqLine - 8)) + ); + }else { + simple_out_8( + BSP_8259_BASE_ADDRESS, + PIC_MASTER_COMMAND_IO_PORT, + (PIC_EOSI | irqLine) + ); + } + + return 0; + +} /* ackIRQ */ + +void BSP_i8259s_init(void) +{ + volatile uint32_t i; + + simple_out_8(BSP_8259_BASE_ADDRESS, PIC_MASTER_IMR_IO_PORT, 0xff ); + simple_out_8(BSP_8259_BASE_ADDRESS, PIC_SLAVE_IMR_IO_PORT, 0xff ); + + + /* + * init master 8259 interrupt controller + */ + + /* Start init sequence */ + simple_out_8( + BSP_8259_BASE_ADDRESS, + PIC_MASTER_COMMAND_IO_PORT, + 0x11 + ); + /* Vector base = 0 */ + simple_out_8( + BSP_8259_BASE_ADDRESS, + PIC_MASTER_IMR_IO_PORT, + 0x00 + ); + + /* edge tiggered, Cascade (slave) on IRQ2 */ + simple_out_8( + BSP_8259_BASE_ADDRESS, + PIC_MASTER_IMR_IO_PORT, + 0x04 + ); + + /* Select 8086 mode */ + simple_out_8( + BSP_8259_BASE_ADDRESS, + PIC_MASTER_IMR_IO_PORT, + 0x01 + ); + + /* + * init slave interrupt controller + */ + + /* Start init sequence */ + simple_out_8(BSP_8259_BASE_ADDRESS, PIC_SLAVE_COMMAND_IO_PORT, 0x11); + + /* Vector base = 8 */ + simple_out_8(BSP_8259_BASE_ADDRESS, PIC_SLAVE_IMR_IO_PORT, 0x08); + + /* edge triggered, Cascade (slave) on IRQ2 */ + simple_out_8(BSP_8259_BASE_ADDRESS, PIC_SLAVE_IMR_IO_PORT, 0x02); + + /* Select 8086 mode */ + simple_out_8(BSP_8259_BASE_ADDRESS, PIC_SLAVE_IMR_IO_PORT, 0x01); + + /* Mask all except cascade */ + simple_out_8(BSP_8259_BASE_ADDRESS, PIC_MASTER_IMR_IO_PORT, 0xFB); + + /* Mask all */ + simple_out_8(BSP_8259_BASE_ADDRESS, PIC_SLAVE_IMR_IO_PORT, 0xFF); + + /* + * Enable all interrupts in debug mode. + */ + + if ( DEBUG_8259 ) { + i8259s_cache = 0x0101; + } + + simple_out_8( + BSP_8259_BASE_ADDRESS, + PIC_MASTER_IMR_IO_PORT, + i8259s_cache & 0xff + ); + simple_out_8( + BSP_8259_BASE_ADDRESS, + PIC_SLAVE_IMR_IO_PORT, + ((i8259s_cache & 0xff00) >> 8) + ); + + for (i=0; i<10000; i++); +} + +#define PCI__GEN(bus, off, num) (((off)^((bus) << 7))+((num) << 4)) +#define PCI_INTR_ACK(bus) PCI__GEN(bus, 0x0c34, 0) + +volatile uint8_t master; +volatile uint8_t slave; +volatile uint8_t temp; + +void bsp_show_interrupt_regs(void); +void bsp_show_interrupt_regs() { + unsigned int sr; + unsigned int cause; + unsigned int pending; + + mips_get_sr( sr ); + mips_get_cause( cause ); + pending = (cause & sr & 0xff00) >> CAUSE_IPSHIFT; + + master = simple_in_8(BSP_8259_BASE_ADDRESS, PIC_MASTER_COMMAND_IO_PORT); + slave = simple_in_8(BSP_8259_BASE_ADDRESS, PIC_SLAVE_COMMAND_IO_PORT); + + printk("sr: 0x%x cause: 0x%x pending: 0x%x master: 0x%x slave: 0x%x\n", + sr, cause, pending, master, slave + ); +} + +int BSP_i8259s_int_process() +{ + uint8_t irq; + volatile uint32_t temp; + + /* Get the Interrupt */ + irq = simple_in_le32(BSP_PCI_BASE_ADDRESS, PCI_INTR_ACK(0) ); + + /* + * Mask interrupts + * + Mask all except cascade on master + * + Mask all on slave + */ + simple_out_8(BSP_8259_BASE_ADDRESS, PIC_MASTER_IMR_IO_PORT, 0xFB); + simple_out_8(BSP_8259_BASE_ADDRESS, PIC_SLAVE_IMR_IO_PORT, 0xFF); + + /* Call the Handler */ + temp = irq + MALTA_SB_IRQ_0; + bsp_interrupt_handler_dispatch( temp ); + + /* Reset the interrupt on the 8259 either the master or the slave chip */ + if (irq & 8) { + temp = simple_in_8(BSP_8259_BASE_ADDRESS, PIC_SLAVE_IMR_IO_PORT); + + /* Mask all */ + simple_out_8(BSP_8259_BASE_ADDRESS, PIC_SLAVE_IMR_IO_PORT, 0xFF); + simple_out_8( + BSP_8259_BASE_ADDRESS, + PIC_SLAVE_COMMAND_IO_PORT, + (PIC_EOSI + (irq&7)) + ); + simple_out_8( + BSP_8259_BASE_ADDRESS, + PIC_MASTER_COMMAND_IO_PORT, + SLAVE_PIC_EOSI + ); + } else { + temp = simple_in_8(BSP_8259_BASE_ADDRESS, PIC_MASTER_IMR_IO_PORT); + /* Mask all except cascade */ + simple_out_8(BSP_8259_BASE_ADDRESS, PIC_MASTER_IMR_IO_PORT, 0xFB); + simple_out_8( + BSP_8259_BASE_ADDRESS, + PIC_MASTER_COMMAND_IO_PORT, + (PIC_EOSI+irq) + ); + } + + /* Restore the interrupts */ + simple_out_8(BSP_8259_BASE_ADDRESS,PIC_MASTER_IMR_IO_PORT,i8259s_cache&0xff); + simple_out_8( + BSP_8259_BASE_ADDRESS, + PIC_SLAVE_IMR_IO_PORT, + ((i8259s_cache & 0xff00) >> 8) + ); + + return 0; +} diff --git a/bsps/mips/shared/irq/interruptmask.c b/bsps/mips/shared/irq/interruptmask.c new file mode 100644 index 0000000000..c63421e569 --- /dev/null +++ b/bsps/mips/shared/irq/interruptmask.c @@ -0,0 +1,29 @@ +/** + * @file + * + */ + +/* + * COPYRIGHT (c) 1989-2012. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.org/license/LICENSE. + */ + +#include + +/* + * This function returns a mask value which is used to select the bits + * in the processor status register that can be set to enable interrupts. + * The mask value should not include the 2 software interrupt enable bits. + */ + +uint32_t mips_interrupt_mask( void ) +{ + uint32_t interrupt_mask; + + interrupt_mask = 0x0000fc00; + return(interrupt_mask); +} diff --git a/bsps/mips/shared/irq/interruptmask_TX49.c b/bsps/mips/shared/irq/interruptmask_TX49.c new file mode 100644 index 0000000000..5b1daa57c3 --- /dev/null +++ b/bsps/mips/shared/irq/interruptmask_TX49.c @@ -0,0 +1,29 @@ +/** + * @file + * + */ + +/* + * COPYRIGHT (c) 1989-2012. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.org/license/LICENSE. + */ + +#include + +/* + * This function returns a mask value which is used to select the bits + * in the processor status register that can be set to enable interrupts. + * The mask value should not include the 2 software interrupt enable bits. + */ + +uint32_t mips_interrupt_mask( void ) +{ + uint32_t interrupt_mask; + + interrupt_mask = 0x00000400; /* Toshiba TX49 processors have a non-standard interrupt mask */ + return(interrupt_mask); +} diff --git a/bsps/mips/shared/irq/irq.c b/bsps/mips/shared/irq/irq.c new file mode 100644 index 0000000000..1c2d3b8c5b --- /dev/null +++ b/bsps/mips/shared/irq/irq.c @@ -0,0 +1,101 @@ +/** + * @file + * + * @ingroup bsp_interrupt + * + * @brief Interrupt support. + */ + +/* + * Copyright (c) 2005 by Cogent Computer Systems + * Written by Jay Monkman + * + * COPYRIGHT (c) 1989-2012. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.org/license/LICENSE. + */ + + +#include + +#include +#include +#include +#include +#include + +static const char *const cause_strings[32] = { + /* 0 */ "Int", + /* 1 */ "TLB Mods", + /* 2 */ "TLB Load", + /* 3 */ "TLB Store", + /* 4 */ "Address Load", + /* 5 */ "Address Store", + /* 6 */ "Instruction Bus Error", + /* 7 */ "Data Bus Error", + /* 8 */ "Syscall", + /* 9 */ "Breakpoint", + /* 10 */ "Reserved Instruction", + /* 11 */ "Coprocessor Unuseable", + /* 12 */ "Overflow", + /* 13 */ "Trap", + /* 14 */ "Instruction Virtual Coherency Error", + /* 15 */ "FP Exception", + /* 16 */ "Reserved 16", + /* 17 */ "Reserved 17", + /* 18 */ "Reserved 18", + /* 19 */ "Reserved 19", + /* 20 */ "Reserved 20", + /* 21 */ "Reserved 21", + /* 22 */ "Reserved 22", + /* 23 */ "Watch", + /* 24 */ "Reserved 24", + /* 25 */ "Reserved 25", + /* 26 */ "Reserved 26", + /* 27 */ "Reserved 27", + /* 28 */ "Reserved 28", + /* 29 */ "Reserved 29", + /* 30 */ "Reserved 30", + /* 31 */ "Data Virtual Coherency Error" +}; + +static inline bool bsp_irq_is_valid(rtems_vector_number vector) +{ + return vector <= BSP_INTERRUPT_VECTOR_MAX; +} + +void bsp_interrupt_vector_enable(rtems_vector_number vector) +{ + bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector)); +} + +void bsp_interrupt_vector_disable(rtems_vector_number vector) +{ + bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector)); +} + +rtems_status_code bsp_interrupt_facility_initialize(void) +{ + mips_install_isr_entries(); + return RTEMS_SUCCESSFUL; +} + +void bsp_interrupt_handler_default(rtems_vector_number vector) +{ + uint32_t sr; + uint32_t cause; + + mips_get_sr( sr ); + mips_get_cause( cause ); + + printk( "Unhandled exception %" PRId32 "\n", vector ); + printk( "sr: 0x%08" PRIu32 " cause: 0x%08" PRIu32 " --> %s\n", sr, cause, + cause_strings[(cause >> 2) &0x1f] ); + #if 0 + mips_dump_exception_frame( frame ); + #endif + rtems_fatal_error_occurred(1); +} diff --git a/bsps/mips/shared/irq/vectorexceptions.c b/bsps/mips/shared/irq/vectorexceptions.c new file mode 100644 index 0000000000..cdfd94c136 --- /dev/null +++ b/bsps/mips/shared/irq/vectorexceptions.c @@ -0,0 +1,81 @@ +/** + * @file + * + * Common Code for Vectoring MIPS Exceptions + * + * The actual decoding of the cause register and vector number assignment + * is CPU model specific. + */ + +/* + * COPYRIGHT (c) 1989-2012. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.org/license/LICENSE. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +struct regdef +{ + int offset; + char *name; +}; + +static const struct regdef dumpregs[]= { + { R_RA, "R_RA" }, { R_V0, "R_V0" }, { R_V1, "R_V1" }, + { R_A0, "R_A0" }, { R_A1, "R_A1" }, { R_A2, "R_A2" }, + { R_A3, "R_A3" }, { R_T0, "R_T0" }, { R_T1, "R_T1" }, + { R_T2, "R_T2" }, { R_T3, "R_T3" }, { R_T4, "R_T4" }, + { R_T5, "R_T5" }, { R_T6, "R_T6" }, { R_T7, "R_T7" }, + { R_T8, "R_T8" }, { R_MDLO, "R_MDLO" }, { R_MDHI, "R_MDHI" }, + { R_GP, "R_GP" }, { R_FP, "R_FP" }, { R_AT, "R_AT" }, + { R_EPC,"R_EPC"}, { -1, NULL } +}; + +void _CPU_Exception_frame_print( const CPU_Exception_frame *frame ) +{ + uint32_t *frame_u32; + int i, j; + + frame_u32 = (uint32_t *)frame; + for(i=0; dumpregs[i].offset > -1; i++) + { + printk(" %s", dumpregs[i].name); + for(j=0; j< 7-strlen(dumpregs[i].name); j++) printk(" "); +#if (__mips == 1 ) || (__mips == 32) + printk(" %08" PRIu32 "%c", + frame_u32[dumpregs[i].offset], (i%3) ? '\t' : '\n' ); +#elif __mips == 3 + printk(" %08" PRIu32 "", frame_u32[2 * dumpregs[i].offset + 1] ); + printk("%08" PRIu32 "%c", + frame_u32[2 * dumpregs[i].offset], (i%2) ? '\t' : '\n' ); +#endif + } + printk( "\n" ); +} + +/* + * There are constants defined for these but they should basically + * all be close to the same set. + */ + +void mips_vector_exceptions( CPU_Interrupt_frame *frame ) +{ + uint32_t cause; + uint32_t exc; + + mips_get_cause( cause ); + exc = (cause >> 2) & 0x1f; + + bsp_interrupt_handler_dispatch( exc ); +} diff --git a/bsps/or1k/generic_or1k/irq/irq.c b/bsps/or1k/generic_or1k/irq/irq.c new file mode 100644 index 0000000000..f9a7b6426d --- /dev/null +++ b/bsps/or1k/generic_or1k/irq/irq.c @@ -0,0 +1,43 @@ +/** + * @file + * + * @ingroup or1k_interrupt + * + * @brief Interrupt support. + */ + +/* + * Copyright (c) 2014 Hesham ALMatary + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.org/license/LICENSE. + */ + +#include +#include +#include + +/* Almost all of the jobs that the following functions should + * do are implemented in cpukit + */ + +void bsp_interrupt_handler_default(rtems_vector_number vector) +{ + printk("spurious interrupt: %" PRIdrtems_vector_number "\n", vector); +} + +rtems_status_code bsp_interrupt_facility_initialize() +{ + return 0; +} + +void bsp_interrupt_vector_enable(rtems_vector_number vector) +{ + bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector)); +} + +void bsp_interrupt_vector_disable(rtems_vector_number vector) +{ + bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector)); +} diff --git a/bsps/powerpc/beatnik/irq/discovery_pic.c b/bsps/powerpc/beatnik/irq/discovery_pic.c new file mode 100644 index 0000000000..f77125c4a7 --- /dev/null +++ b/bsps/powerpc/beatnik/irq/discovery_pic.c @@ -0,0 +1,993 @@ +/* Interrupt driver + dispatcher for the discovery host controller */ + +/* Author: T. Straumann, 2005-2007 + * + * Acknowledgements: + * Valuable information was obtained from the following drivers + * netbsd: (C) Allegro Networks Inc; Wasabi Systems Inc. + * linux: (C) MontaVista, Software, Inc; Chris Zankel, Mark A. Greer. + * rtems: (C) Brookhaven National Laboratory; K. Feng + * but this implementation is original work by the author. + */ + +/* + * 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 +#include + +/* dont change the order (main_lo, main_hi, gpp) which + * matches the interrupt numbers! + */ +#define MAIN_LO_IDX 0 +#define MAIN_HI_IDX 1 +#define GPP_IDX 2 +#define NUM_INTR_REGS 3 + + +#define SYNC() __asm__ volatile("sync") + +/* How many times should the ISR dispatcher check for + * pending interrupts until it decides that something's + * fishy (i.e., a user ISR fails to clear the interrupt + * source) + */ +#define MAX_SPIN_LOOPS 100 + +/* If FASTER is defined, a few obscure I/O statements found in the linux + * driver are removed + */ +#define FASTER + +/* Array helper */ +#define NumberOf(arr) (sizeof(arr)/sizeof((arr)[0])) + + +/* MVME6100 specific; re-define watchdog NMI pin to be a normal output + * so we have a way to raise an interrupt in software (GPP[26] is wired to + * GPP[6] on the MVME6100). + */ +#define MVME6100_IRQ_DEBUG 4 + +#define GPP_WIRED_OUT_BIT_6100 26 /* CAVEAT: this is bit 26 on the 6100 */ +#define GPP_WIRED_OUT_BIT_5500 24 /* CAVEAT: this is bit 24 on the 5500 */ +#define GPP_WIRED_IN_BIT 6 + +/* Ored mask of debugging features to enable */ +#define IRQ_DEBUG_BASIC 1 +/* This is _very_ lowlevel */ +#define IRQ_DEBUG_DISPATCHER 2 +/* Record maximal dispatching latency */ +#define IRQ_DEBUG_MAXLAT 8 /* PPC only */ + +#define IRQ_DEBUG (0 /*|(IRQ_DEBUG_BASIC)*/|(MVME6100_IRQ_DEBUG)|(IRQ_DEBUG_MAXLAT)) + +/********** + * Typedefs + **********/ + +/* Set of the three relevant cause registers */ +typedef volatile unsigned IrqMask[NUM_INTR_REGS]; + +#define REGP(x) ((volatile uint32_t *)(x)) + +/* Information we keep about the PIC */ +typedef struct _Mv64x60PicRec { + /* base address as seen from CPU */ + uintptr_t reg_base; + + /* addresses of 'cause' registers */ + volatile uint32_t *causes[NUM_INTR_REGS]; + + /* addresses of 'mask' registers */ + volatile uint32_t *masks[NUM_INTR_REGS]; + + /* masks for all priorities. If an + * interrupt source has priority X, + * its corresponding bit is set + * (enabled) in mcache[i] for all + * i < X and cleared for i >= X + */ + volatile IrqMask mcache[BSP_IRQ_MAX_PRIO+1]; + + /* Priority we're executing at. + * Thread-level is priority 0, + * ISRs range from 1..MAX_PRIO + */ + volatile rtems_irq_prio current_priority; +} Mv64x60PicRec, *Mv64x60Pic; + +/********** + * Globals + **********/ + + +/* Copy of the configuration */ +static rtems_irq_global_settings theConfig; +/* PIC description */ +static Mv64x60PicRec thePic; + +#if (IRQ_DEBUG) & MVME6100_IRQ_DEBUG +static unsigned long gpp_out_bit = 0; +#endif + +#if (IRQ_DEBUG) & IRQ_DEBUG_MAXLAT +unsigned long discovery_pic_max_dispatching_latency = 0; +#ifdef __PPC__ +static inline unsigned long mftb(void) +{ +unsigned long rval; + asm volatile("mftb %0":"=r"(rval)); + return rval; +} +#else +#define mftb() 0 +#endif +#endif + +/********** + * Functions + **********/ + +/* Debugging helper routines */ +static void pregs(volatile uint32_t **p) +{ +int i; + for (i=NUM_INTR_REGS-1; i>=0; i--) { + printk(" 0x%08x", ld_le32(p[i])); + printk( i ? " --":"\n"); + } +} + +static void pmsks(volatile IrqMask p) +{ +int i; + for (i=NUM_INTR_REGS-1; i>=0; i--) { + printk(" 0x%08x", p[i]); + printk( i ? " --":"\n"); + } +} + +static void discovery_dump_picregs(void) +{ + printk(" ..GPP_IRQ. -- ..MAIN_HI. -- ..MAIN_LO.\n"); + printk("Cause:"); pregs(thePic.causes); + printk("Mask: "); pregs(thePic.masks); +} + +/* Small inline helpers */ + +/* return 0 if this PIC is not 'responsible' for a given irq number + * we also 'ignore' the GPP summary bits - these must always remain + * enabled. + */ +static inline int +validIrqNo(rtems_irq_number irq) +{ + return + irq >= BSP_PCI_IRQ_LOWEST_OFFSET + && irq <= BSP_PCI_IRQ_MAX_OFFSET + && ! (IMH_GPP_SUM & (1<<(irq-32))); +} + +/* return 0 if a given priority is outside the valid range */ +static inline int +validPri(rtems_irq_prio pri) +{ + /* silence compiler warning about limited range of type; + * hope it never changes... + */ + return /* pri>=0 && */ pri <=BSP_IRQ_MAX_PRIO; +} + +/* Return position of the most significant bit that is set in 'x' */ +static inline int +__ilog2(unsigned x) +{ + asm volatile("cntlzw %0, %0":"=&r"(x):"0"(x)); + return 31-x; +} + +/* Convert irq number to cause register index + * (array of handles in the PicRec). + * ASSUMES: 'irq' within valid range. + */ +static inline unsigned +irqDiv32(unsigned irq) +{ + return (irq-BSP_PCI_IRQ_LOWEST_OFFSET)>>5; +} + +/* Convert irq number to cause/mask bit number. + * ASSUMES: 'irq' within valid range. + */ + +static inline unsigned +irqMod32(unsigned irq) +{ + return (irq-BSP_PCI_IRQ_LOWEST_OFFSET)&31; +} + +/* NON-ATOMICALLY set/clear bits in a MV64x60 register + * + * register contents at offset 'off' are ANDed with + * complement of the 'clr' mask and ORed with 'set' mask: + * + * *off = (*off & ~clr) | set + * + * ASSUMES: executed from IRQ-disabled section + */ +static inline void +gt_bitmod(unsigned off, unsigned set, unsigned clr) +{ + st_le32(REGP(thePic.reg_base + off), + (ld_le32(REGP(thePic.reg_base+off)) & ~clr) | set); +} + +static inline unsigned +gt_read(unsigned off) +{ + return ld_le32(REGP(thePic.reg_base + off)); +} + +static inline void +gt_write(unsigned off, unsigned val) +{ + st_le32(REGP(thePic.reg_base + off), val); +} + +/* Enable interrupt number 'irq' at the PIC. + * + * Checks for valid arguments but has no way of + * communicating violation; prints to console + * if illegal arguments are given. + * + * This routine may be called from ISR level. + * + * Algorithm: set corresponding bit in masks + * for all priorities lower than the + * target irq's priority and push + * mask for the currently executing + * priority out to the PIC. + */ + +void +BSP_enable_irq_at_pic(rtems_irq_number irq) +{ +unsigned i,j; +unsigned long flags; +volatile uint32_t *p; +uint32_t v,m; + + if ( !validIrqNo(irq) ) { +/* API change - must silently ignore... + printk("BSP_enable_irq_at_pic: Invalid argument (irq #%i)\n",irq); + */ + return; + } + +#if (IRQ_DEBUG) & IRQ_DEBUG_BASIC + printk("IRQ: Enable #%i;",irq); +#endif + + if ( (i=irqDiv32(irq)) > NUM_INTR_REGS ) { + /* This is probably a more serious error; don't ignore silently */ + printk("BSP_enable_irq_at_pic: illegal argument\n"); + return; + } + /* compute register pointer and bit mask */ + p = thePic.masks[i]; + m = 1< 0x%08x\n",i,v,ld_le32(p)); + +#endif +} + +/* Disable interrupt number 'irq' at the PIC. + * + * Checks for valid arguments but has no way of + * communicating violation; prints to console + * if illegal arguments are given. + * + * This routine may be called from ISR level. + * + * Algorithm: clear corresponding bit in masks + * for all priorities and push the + * mask for the currently executing + * priority out to the PIC. + */ + +int +BSP_disable_irq_at_pic(rtems_irq_number irq) +{ +unsigned i,j; +unsigned long flags; +volatile uint32_t *p; +uint32_t v,m; +int rval; + + if ( !validIrqNo(irq) ) { +/* API change - must silently ignore... + printk("BSP_disable_irq_at_pic: Invalid argument (irq #%i)\n",irq); + */ + return -1; + } + +#if (IRQ_DEBUG) & IRQ_DEBUG_BASIC + printk("IRQ: Disable #%i;",irq); +#endif + + if ( (i=irqDiv32(irq)) > NUM_INTR_REGS ) { + /* This is probably a more serious error; don't ignore silently */ + printk("BSP_enable_irq_at_pic: illegal argument\n"); + return -1; + } + + /* compute register pointer and bit mask */ + p = thePic.masks[i]; + m = (1< 0x%08x\n",i,v,ld_le32(p)); +#endif + + return rval ? 1 : 0; +} + +int +BSP_irq_is_enabled_at_pic(rtems_irq_number irq) +{ +unsigned i; + if ( !validIrqNo(irq) ) { + printk("BSP_irq_is_enabled_at_pic: Invalid argument (irq #%i)\n",irq); + return -1; + } + + if ( (i=irqDiv32(irq)) > NUM_INTR_REGS ) { + printk("BSP_enable_irq_at_pic: illegal argument\n"); + return -1; + } + return ld_le32(thePic.masks[i]) & (1<=pri + */ +int +BSP_irq_set_priority(rtems_irq_number irq, rtems_irq_prio pri) +{ +unsigned long flags; +volatile uint32_t *p; +uint32_t v,m; +unsigned i,j; + + if ( thePic.current_priority > 0 ) { + printk("BSP_irq_set_priority: must not be called from ISR level\n"); + return -1; + } + + if ( !validPri(pri) ) { + printk("BSP_irq_set_priority: invalid argument (pri #%i)\n",pri); + return -1; + } + + if ( BSP_DECREMENTER != irq ) { + if ( !validIrqNo(irq) ) { + printk("BSP_irq_set_priority: invalid argument (irq #%i)\n",irq); + return -1; + } + + if ( (i=irqDiv32(irq)) > NUM_INTR_REGS ) { + printk("BSP_irq_set_priority: illegal argument (irq #%i not PCI?)\n", irq); + return -1; + } + } + +#if (IRQ_DEBUG) & IRQ_DEBUG_BASIC + printk("IRQ: Set Priority #%i -> %i;",irq,pri); +#endif + + if ( BSP_DECREMENTER == irq ) { + theConfig.irqPrioTbl[irq] = pri; + return 0; + } + + /* compute register pointer and bit mask */ + p = thePic.masks[i]; + m = 1< 0x%08x\n",i,v,ld_le32(p)); +#endif + + return 0; +} + +/* Initialize the PIC; routine needed by BSP framework + * + * RETURNS: NONZERO on SUCCESS, 0 on error! + */ +int +BSP_setup_the_pic(rtems_irq_global_settings* config) +{ +int i; + /* + * Store copy of configuration + */ + theConfig = *config; + + /* check config */ + if ( theConfig.irqNb <= BSP_PCI_IRQ_MAX_OFFSET ) { + printk("BSP_setup_the_pic: FATAL ERROR: configured IRQ table too small???\n"); + return 0; + } + + for ( i=0; i highest priority source is found quickly. It takes at most + * + * BSP_IRQ_MAX_PRIO * ( ~3 reg-only instructions + 2 memory access ) + * + 2 reg-only instructions + 1 I/O + 1 memory access. + * + * + */ + +static unsigned mlc, mhc, gpc; + +static int decrementerPending = 0; +#if (IRQ_DEBUG) & IRQ_DEBUG_DISPATCHER +int decrementerIrqs = 0; +#endif + +static inline unsigned +find_highest_priority_pending_irq(rtems_irq_prio *ppri) +{ +register int rval = -1; +register rtems_irq_prio *pt = theConfig.irqPrioTbl + BSP_PCI_IRQ_LOWEST_OFFSET; +register rtems_irq_prio pmax = *ppri; +register unsigned cse,ocse; + +#if (IRQ_DEBUG) & IRQ_DEBUG_DISPATCHER + discovery_dump_picregs(); +#endif + + if ( decrementerPending ) { +/* Don't flood +#if (IRQ_DEBUG) & IRQ_DEBUG_DISPATCHER + printk("Decrementer IRQ pending\n"); +#endif +*/ + if ( theConfig.irqPrioTbl[BSP_DECREMENTER] > pmax ) { + pmax = theConfig.irqPrioTbl[BSP_DECREMENTER]; + rval = BSP_DECREMENTER; + } + } + + mlc = cse = ld_le32(thePic.causes[MAIN_LO_IDX]); +#if (IRQ_DEBUG) & IRQ_DEBUG_DISPATCHER + printk("MAIN_LO; cse: 0x%08x, msk 0x%08x\n", cse ,thePic.mcache[pmax][MAIN_LO_IDX]); +#endif + while ( cse &= thePic.mcache[pmax][MAIN_LO_IDX] ) { + rval = __ilog2(cse); + pmax = pt[rval]; +#if (IRQ_DEBUG) & IRQ_DEBUG_DISPATCHER + printk("Max pri IRQ now %i\n",rval); +#endif + } + mhc = cse = ocse = ld_le32(thePic.causes[MAIN_HI_IDX]); +#if (IRQ_DEBUG) & IRQ_DEBUG_DISPATCHER + printk("MAIN_HI; cse: 0x%08x, msk 0x%08x\n", cse, thePic.mcache[pmax][MAIN_HI_IDX]); +#endif + /* don't look at the GPP summary; only check for 'real' MAIN_HI sources */ + cse &= ~IMH_GPP_SUM; + while ( cse &= thePic.mcache[pmax][MAIN_HI_IDX] ) { + rval = __ilog2(cse) + 32; + pmax = pt[rval]; +#if (IRQ_DEBUG) & IRQ_DEBUG_DISPATCHER + printk("Max pri IRQ now %i\n",rval); +#endif + } + gpc = cse = ld_le32(thePic.causes[GPP_IDX ]); + /* if there were GPP ints, scan the GPP cause now */ + if ( ocse & IMH_GPP_SUM ) { +#if (IRQ_DEBUG) & IRQ_DEBUG_DISPATCHER + printk("GPP; cse: 0x%08x, msk 0x%08x\n", cse, thePic.mcache[pmax][GPP_IDX ]); +#endif + cse &= thePic.mcache[pmax][GPP_IDX ]; + ocse = cse; + while ( cse ) { + rval = __ilog2(cse) + 64; + pmax = pt[rval]; + cse &= thePic.mcache[pmax][GPP_IDX ]; +#if (IRQ_DEBUG) & IRQ_DEBUG_DISPATCHER + printk("Max pri IRQ now %i\n",rval); +#endif + } +#ifndef FASTER + /* this doesn't seem to be necessary -- however, the linux people do it... */ + out_le32(thePic.causes[GPP_IDX], ~ocse); +#endif + } +#ifndef FASTER + /* this doesn't seem to be necessary -- however, the linux people do it... */ + (void)in_le32(thePic.causes[GPP_IDX]); +#endif + + *ppri = pmax; + + if ( BSP_DECREMENTER == rval ) { +#if (IRQ_DEBUG) & IRQ_DEBUG_DISPATCHER + decrementerIrqs++; +#endif + decrementerPending = 0; + } + + return rval; +} + +#if 0 /* TODO: should this be cleaned up ? */ +#define _IRQ_DEBUG IRQ_DEBUG_DISPATCHER +static inline unsigned +ffind_highest_priority_pending_irq(rtems_irq_prio *ppri) +{ +register int rval = -1; +register rtems_irq_prio *pt = theConfig.irqPrioTbl + BSP_PCI_IRQ_LOWEST_OFFSET; +register rtems_irq_prio pmax = *ppri; +register unsigned cse,ocse; + +#if (_IRQ_DEBUG) & IRQ_DEBUG_DISPATCHER + discovery_dump_picregs(); +#endif + + cse = in_le32(thePic.causes[MAIN_LO_IDX]); +#if (_IRQ_DEBUG) & IRQ_DEBUG_DISPATCHER + printk("MAIN_LO; cse: 0x%08x, msk 0x%08x\n", cse ,thePic.mcache[pmax][MAIN_LO_IDX]); +#endif + while ( cse &= thePic.mcache[pmax][MAIN_LO_IDX] ) { + rval = __ilog2(cse); + pmax = pt[rval]; +#if (_IRQ_DEBUG) & IRQ_DEBUG_DISPATCHER + printk("Max pri IRQ now %i\n",rval); +#endif + } + cse = ocse = in_le32(thePic.causes[MAIN_HI_IDX]); +#if (_IRQ_DEBUG) & IRQ_DEBUG_DISPATCHER + printk("MAIN_HI; cse: 0x%08x, msk 0x%08x\n", cse, thePic.mcache[pmax][MAIN_HI_IDX]); +#endif + /* don't look at the GPP summary; only check for 'real' MAIN_HI sources */ + cse &= ~IMH_GPP_SUM; + while ( cse &= thePic.mcache[pmax][MAIN_HI_IDX] ) { + rval = __ilog2(cse) + 32; + pmax = pt[rval]; +#if (_IRQ_DEBUG) & IRQ_DEBUG_DISPATCHER + printk("Max pri IRQ now %i\n",rval); +#endif + } + /* if there were GPP ints, scan the GPP cause now */ + if ( ocse & IMH_GPP_SUM ) { + cse = in_le32(thePic.causes[GPP_IDX ]); +#if (_IRQ_DEBUG) & IRQ_DEBUG_DISPATCHER + printk("GPP; cse: 0x%08x, msk 0x%08x\n", cse, thePic.mcache[pmax][GPP_IDX ]); +#endif + cse &= thePic.mcache[pmax][GPP_IDX ]; + ocse = cse; + while ( cse ) { + rval = __ilog2(cse) + 64; + pmax = pt[rval]; + cse &= thePic.mcache[pmax][GPP_IDX ]; +#if (_IRQ_DEBUG) & IRQ_DEBUG_DISPATCHER + printk("Max pri IRQ now %i\n",rval); +#endif + } + /* this doesn't seem to be necessary -- however, the linux people do it... */ + out_le32(thePic.causes[GPP_IDX], ~ocse); + } + /* this doesn't seem to be necessary -- however, the linux people do it... */ + (void)in_le32(thePic.causes[GPP_IDX]); + + *ppri = pmax; + return rval; +} +#endif + + +/* Here's our dispatcher; the BSP framework uses the same one for EE and decrementer + * exceptions... + */ +int C_dispatch_irq_handler (BSP_Exception_frame *frame, unsigned int excNum) +{ +register int irq; +int loop, last_irq; +rtems_irq_prio pri; +#if (IRQ_DEBUG) & IRQ_DEBUG_MAXLAT +unsigned long diff; +#endif + +#if (IRQ_DEBUG) & IRQ_DEBUG_MAXLAT + diff = mftb(); +#endif + + if (excNum == ASM_DEC_VECTOR) { + decrementerPending = 1; + } + + /* Tradeoff: EITHER we loop as long as interrupts are pending + * incurring the overhead of one extra run of the 'find_pending_irq' routine. + * OR we do rely on the handler just being invoked again if multiple + * interrupts are pending. + * + * The first solution gives better worst-case behavior + * the second slightly better average performance. + * --> we go for the first solution. This also enables us to catch + * runaway interrupts, i.e., bad drivers that don't clear interrupts + * at the device. Can be very handy during driver development... + */ + for ( loop=0, last_irq=-1, pri = thePic.current_priority; + (irq=find_highest_priority_pending_irq(&pri)) >=0; + loop++, last_irq = irq ) { + + /* raise priority level and remember current one */ + pri = change_executing_prio_level(pri); + + SYNC(); + +#if (IRQ_DEBUG) & IRQ_DEBUG_MAXLAT + if ( 0 == loop ) { + diff = mftb()-diff; + if ( diff > discovery_pic_max_dispatching_latency ) + discovery_pic_max_dispatching_latency = diff; + } +#endif + +#if (IRQ_DEBUG) & IRQ_DEBUG_DISPATCHER + if ( BSP_DECREMENTER == irq ) { + printk("IRQ: dispatching DECREMENTER\n"); + } else { + int idx = irqDiv32(irq); + printk("IRQ: dispatching #%i; causes[%i]=0x%08x\n", irq, idx, ld_le32(thePic.causes[idx])); + } +#endif + + bsp_irq_dispatch_list( theConfig.irqHdlTbl, irq, theConfig.defaultEntry.hdl ); + + /* restore executing priority level */ + (void)change_executing_prio_level(pri); + + if ( (loop > MAX_SPIN_LOOPS) && (last_irq == irq) ) { + /* try to catch run-away interrupts without disabling a 'legal' one; + * this should never happen with the decrementer (and + * BSP_disable_irq_at_pic(BSP_DECREMENTER) would fail) + */ + printk("Runaway IRQ #%i; disabling\n", irq); + BSP_disable_irq_at_pic(irq); + loop = 0; + } + } + + if (!loop) { + if ( decrementerPending && pri >= theConfig.irqPrioTbl[BSP_DECREMENTER] ) { + /* we cannot mask the decrementer interrupt so it is possible that it + * gets delivered even though it has a lower priority than what we're + * currently executing at. + * In this case, we ignore the zero loop count and return; + * the interrupted instance of C_dispatch_irq_handler() will eventually + * lower the executing priority and catch the 'decrementerPending' flag + * we just set. + */ + } else { + printk("Discovery: Spurious interrupt; causes were gpp: 0x%x, mhc: 0x%x, mlc: 0x%x\n", gpc, mhc, mlc); + printk("Current priority level %i, decrementerPending %i\n", pri, decrementerPending); + { + rtems_irq_prio p=pri; + printk("PIC register dump:\n"); + discovery_dump_picregs(); + printk("Current Priority: %i, found %i\n",pri,find_highest_priority_pending_irq(&p)); + discovery_dump_picregs(); + for (p=0; p<=BSP_IRQ_MAX_PRIO; p++) { + printk("M[%i] :",p);pmsks(thePic.mcache[p]); + } + } + } + } + else if (loop>discovery_pic_max_loops) + discovery_pic_max_loops = loop; + + return 0; +} + + +#if (IRQ_DEBUG) & MVME6100_IRQ_DEBUG +void +discovery_pic_install_debug_irq(void) +{ + switch ( BSP_getBoardType() ) { + case MVME6100: gpp_out_bit = GPP_WIRED_OUT_BIT_6100; break; + case MVME5500: gpp_out_bit = GPP_WIRED_OUT_BIT_5500; break; + default: + gpp_out_bit = 0; break; + break; + } + if ( gpp_out_bit ) { + unsigned mppoff; + switch (gpp_out_bit / 8) { + default: /* silence warning; this is never reached */ + case 0: mppoff = GT_MPP_Control0; break; + case 1: mppoff = GT_MPP_Control1; break; + case 2: mppoff = GT_MPP_Control2; break; + case 3: mppoff = GT_MPP_Control3; break; + } + + /* switch GPP pin allocated to watchdog (value 4) to + * GPP I/O (value 0 ??; have no doc, found out by experimenting) + */ + gt_bitmod(mppoff, 0, (0xf<<(4*(gpp_out_bit % 8)))); + + /* make it an output */ + gt_bitmod(GT_GPP_IO_Control, (1< GPP_WIRED_IN pins + */ +void +discovery_pic_set_debug_irq(int on) +{ +unsigned long flags, clr; + if ( !gpp_out_bit ) { + printk("discovery_pic_set_debug_irq(): unknown wire output\n"); + return; + } + if (on) { + on = 1< + * to make it valid for MVME2300 Motorola boards. + * + * Modified by T. Straumann for the 'beatnik' BSP. + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.org/license/LICENSE. + */ + +#include +#include +#include +#include +#include + +#if 0 +#include +#include +#include +#include +#include +#include +#include +#include +#endif + +/* +#define SHOW_ISA_PCI_BRIDGE_SETTINGS +*/ + +extern unsigned int external_exception_vector_prolog_code_size[]; +extern void external_exception_vector_prolog_code(void); +extern unsigned int decrementer_exception_vector_prolog_code_size[]; +extern void decrementer_exception_vector_prolog_code(void); + +/* + * default handler + */ +static void nop_func(void *arg){} + +static rtems_irq_connect_data rtemsIrq[BSP_IRQ_NUMBER]; +static rtems_irq_global_settings initial_config; +static rtems_irq_prio rtemsPrioTbl[BSP_IRQ_NUMBER]; +static rtems_irq_connect_data defaultIrq = { + name: 0, + hdl: nop_func, + handle: 0, + on: 0, + off: 0, + isOn: 0 +}; + + + /* + * This code assumes the exceptions management setup has already + * been done. We just need to replace the exceptions that will + * be handled like interrupt. On mcp750/mpc750 and many PPC processors + * this means the decrementer exception and the external exception. + */ + +void BSP_rtems_irq_mng_init(unsigned cpuId) +{ +int i; + + /* + * First initialize the Interrupt management hardware + */ + + /* + * Initialize Rtems management interrupt table + */ + + /* + * re-init the rtemsIrq table + */ + for (i = BSP_LOWEST_OFFSET; i <= BSP_MAX_OFFSET; i++) { + rtemsIrq[i] = defaultIrq; + rtemsIrq[i].name = i; + rtemsPrioTbl[i] = BSP_IRQ_DEFAULT_PRIORITY; + } + + /* + * Init initial Interrupt management config + */ + initial_config.irqNb = BSP_IRQ_NUMBER; + initial_config.defaultEntry = defaultIrq; + initial_config.irqHdlTbl = rtemsIrq; + initial_config.irqBase = BSP_LOWEST_OFFSET; + initial_config.irqPrioTbl = rtemsPrioTbl; + + if (!BSP_rtems_irq_mngt_set(&initial_config)) { + /* + * put something here that will show the failure... + */ + rtems_panic("Unable to initialize RTEMS interrupt Management!!! System locked\n"); + } + +#ifdef TRACE_IRQ_INIT + printk("RTEMS IRQ management is now operationnal\n"); +#endif +} + diff --git a/bsps/powerpc/beatnik/irq/irq_test_app.c b/bsps/powerpc/beatnik/irq/irq_test_app.c new file mode 100644 index 0000000000..cb9ff146ad --- /dev/null +++ b/bsps/powerpc/beatnik/irq/irq_test_app.c @@ -0,0 +1,164 @@ +/* Init + * + * This routine is the initialization task for this test program. + * It is called from init_exec and has the responsibility for creating + * and starting the tasks that make up the test. If the time of day + * clock is required for the test, it should also be set to a known + * value by this function. + * + * Input parameters: NONE + * + * Output parameters: NONE + * + * COPYRIGHT (c) 1989-1999. + * On-Line Applications Research Corporation (OAR). + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.org/license/LICENSE. + * + * OAR init.c Template modified by T. Straumann who provided + * the implementation of this application. + */ + +#define CONFIGURE_INIT + +#include + +/* functions */ +rtems_task Init( + rtems_task_argument argument +); + +/* configuration information */ +#include /* for device driver prototypes */ +#define CONFIGURE_APPLICATION_NEEDS_CONSOLE_DRIVER +#define CONFIGURE_APPLICATION_NEEDS_CLOCK_DRIVER +#define CONFIGURE_MAXIMUM_TASKS 1 +#define CONFIGURE_RTEMS_INIT_TASKS_TABLE +#include + +#include +#include + +#include +#include + + +void noop(){} +int connected() {return 1;} + +rtems_irq_connect_data blah = { 0, 0, noop, noop, connected }; +extern void discovery_pic_set_debug_irq(); + +#define WIRE_IRQ (BSP_IRQ_GPP_0 + 6) +#define ABRT_IRQ (BSP_IRQ_GPP_0 + 2) + +static volatile int testno=0; +static volatile int wloops =0; +static volatile int aloops =0; + +void wire_hdl() +{ + if ( 1 == testno ) { + BSP_disable_irq_at_pic(WIRE_IRQ); + } + + if ( 2 == testno || 3 == testno ) { + discovery_pic_set_debug_irq(0); + printk("WIRE -- this message should be printed %s\n", 3==testno ? "FIRST":"SECOND"); + } else { + } + + /* assume the driver checks for less than 1000 loops */ + if ( ++wloops > 1000) { + printk("wire IRQ. FAILURE -- driver couldn't catch runaway ISR. Disabling IRQ source.\n"); + discovery_pic_set_debug_irq(0); + BSP_disable_irq_at_pic(WIRE_IRQ); + } + /* + */ +} + +void abrt_hdl() +{ + aloops++; + if ( 2 == testno || 3 == testno ) { + discovery_pic_set_debug_irq(1); + printk("ABRT -- this message should be printed %s\n", 2==testno ? "FIRST":"SECOND"); + } else + printk("ABRT IRQ\n"); + + if ( 1== testno ) { + BSP_enable_irq_at_pic(WIRE_IRQ); + } + BSP_disable_irq_at_pic(ABRT_IRQ); +} + + +rtems_task Init( + rtems_task_argument ignored +) +{ + blah.name = WIRE_IRQ; + blah.hdl = wire_hdl; + if (!BSP_install_rtems_irq_handler(&blah)) { + fprintf(stderr,"installing handler 1 failed\n"); + } + blah.name = ABRT_IRQ; + blah.hdl = abrt_hdl; + if (!BSP_install_rtems_irq_handler(&blah)) { + fprintf(stderr,"installing handler 2 failed\n"); + } + printf("Hello, testing the ISR dispatcher...\n"); + printf(" 1. Trying to catch runaway interrupt\n"); + printf(" If the system freezes, the test failed!\n"); + fflush(stdout); sleep(1); + aloops = wloops = 0; + discovery_pic_set_debug_irq(1); + printf(" >>> %s\n", wloops<1000 ? "SUCCESS" : "FAILED"); + discovery_pic_set_debug_irq(0); + + testno++; + printf(" 2. Testing enabling / disabling interrupt from ISR\n"); + printf(" Hit the ABORT key for this test\n"); + fflush(stdout); sleep(1); + aloops = wloops = 0; + BSP_disable_irq_at_pic(WIRE_IRQ); + BSP_irq_set_priority(ABRT_IRQ,1); + BSP_enable_irq_at_pic(ABRT_IRQ); + discovery_pic_set_debug_irq(1); + while (!aloops) + ; + discovery_pic_set_debug_irq(0); + sleep(2); + printf(" >>> disabling ABRT IRQ from isr %s\n", 1==aloops ? "SUCCESS":"FAILURE"); + printf(" flashing WIRE IRQ from isr %s\n", 1==wloops ? "SUCCESS":"FAILURE"); + + + testno++; + printf(" 3. Testing interrupt priorities\n"); + BSP_irq_set_priority(ABRT_IRQ,2); + BSP_irq_set_priority(WIRE_IRQ,2); + BSP_enable_irq_at_pic(ABRT_IRQ); + BSP_enable_irq_at_pic(WIRE_IRQ); + printf(" Hit the ABORT key for this test\n"); + fflush(stdout); sleep(1); + aloops = wloops = 0; + while (!aloops) + ; + sleep(2); + testno++; + printf(" Now we are raising the priority of the wire interrupt\n"); + BSP_irq_set_priority(WIRE_IRQ,3); + BSP_enable_irq_at_pic(ABRT_IRQ); + printf(" Hit the ABORT key for this test\n"); + fflush(stdout); sleep(1); + aloops = wloops = 0; + while (!aloops) + ; + + sleep(2); + printf( "That's it; we're done...\n" ); + exit( 0 ); +} diff --git a/bsps/powerpc/gen5200/irq/irq.c b/bsps/powerpc/gen5200/irq/irq.c new file mode 100644 index 0000000000..11d9e3992e --- /dev/null +++ b/bsps/powerpc/gen5200/irq/irq.c @@ -0,0 +1,722 @@ +/*===============================================================*\ +| Project: RTEMS generic MPC5200 BSP | ++-----------------------------------------------------------------+ +| Partially based on the code references which are named below. | +| Adaptions, modifications, enhancements and any recent parts of | +| the code are: | +| Copyright (c) 2005 | +| Embedded Brains GmbH | +| Obere Lagerstr. 30 | +| D-82178 Puchheim | +| Germany | +| rtems@embedded-brains.de | ++-----------------------------------------------------------------+ +| The license and distribution terms for this file may be | +| found in the file LICENSE in this distribution or at | +| | +| http://www.rtems.org/license/LICENSE. | +| | ++-----------------------------------------------------------------+ +| this file contains the irq controller handler | +\*===============================================================*/ +/***********************************************************************/ +/* */ +/* Module: irq.c */ +/* Date: 07/17/2003 */ +/* Purpose: RTEMS MPC5x00 CPU main interrupt handler & routines */ +/* */ +/*---------------------------------------------------------------------*/ +/* */ +/* Description: This file contains the implementation of the */ +/* functions described in irq.h */ +/* */ +/*---------------------------------------------------------------------*/ +/* */ +/* Code */ +/* References: MPC8260ads main interrupt handler & routines */ +/* Module: irc.c */ +/* Project: RTEMS 4.6.0pre1 / MCF8260ads BSP */ +/* Version 1.2 */ +/* Date: 04/18/2002 */ +/* */ +/* Author(s) / Copyright(s): */ +/* */ +/* Copyright (C) 1998, 1999 valette@crf.canon.fr */ +/* */ +/* Modified for mpc8260 Andy Dachs */ +/* Surrey Satellite Technology Limited, 2000 */ +/* Nested exception handlers not working yet. */ +/* */ +/* The license and distribution terms for this file may be */ +/* found in the file LICENSE in this distribution or at */ +/* http://www.rtems.org/license/LICENSE. */ +/* */ +/*---------------------------------------------------------------------*/ +/* */ +/* Partially based on the code references which are named above. */ +/* Adaptions, modifications, enhancements and any recent parts of */ +/* the code are under the right of */ +/* */ +/* IPR Engineering, Dachauer Straße 38, D-80335 München */ +/* Copyright(C) 2003 */ +/* */ +/*---------------------------------------------------------------------*/ +/* */ +/* IPR Engineering makes no representation or warranties with */ +/* respect to the performance of this computer program, and */ +/* specifically disclaims any responsibility for any damages, */ +/* special or consequential, connected with the use of this program. */ +/* */ +/*---------------------------------------------------------------------*/ +/* */ +/* Version history: 1.0 */ +/* */ +/***********************************************************************/ + +#include + +#include + +#include +#include + +#include +#include +#include +#include + +/* + * bit in the SIU mask registers (PPC bit numbering) that should + * be set to enable the relevant interrupt, mask of 32 is for unused entries + * + */ +const static unsigned int SIU_MaskBit [BSP_SIU_IRQ_NUMBER] = { + 0, 1, 2, 3, /* smart_comm, psc1, psc2, psc3 */ + 4, 5, 6, 7, /* irda/psc6, eth, usb, ata */ + 8, 9, 10, 11, /* pci_ctrl, pci_sc_rx, pci_sc_tx, psc4 */ + 12, 13, 14, 15, /* psc5,spi_modf, spi_spif, i2c1 */ + 16, 17, 18, 19, /* i2c, can1, can2, ir_rx */ + 20, 21, 15, 16, /* ir_rx, xlb_arb, slice_tim2, irq1, */ + 17, 18, 19, 20, /* irq2, irq3, lo_int, rtc_pint */ + 21, 22, 23, 24, /* rtc_sint, gpio_std, gpio_wkup, tmr0 */ + 25, 26, 27, 28, /* tmr1, tmr2, tmr3, tmr4 */ + 29, 30, 31, 32, /* tmr5, tmr6, tmr7, res */ + 32, 32, 32 /* res, res, res */ +}; + +static unsigned char irqPrioTable [BSP_SIU_IRQ_NUMBER] = { +/* per. int. priorities (0-7) / 4bit coding / msb is HI/LO selection */ +/* msb = 0 -> non-critical per. int. is routed to main int. (LO_int) */ +/* msb = 1 -> critical per. int. is routed to critical int. (HI_int) */ + 0xF, 0, 0, 0, /* smart_comm (do not change!), psc1, psc2, psc3 */ + 0, 0, 0, 0, /* irda, eth, usb, ata */ + 0, 0, 0, 0, /* pci_ctrl, pci_sc_rx, pci_sc_tx, res */ + 0, 0, 0, 0, /* res, spi_modf, spi_spif, i2c1 */ + 0, 0, 0, 0, /* i2c, can1, can2, ir_rx */ + 0, 0, /* ir_rx, xlb_arb */ +/* main interrupt priorities (0-7) / 4bit coding / msb is INT/SMI selection */ +/* msb = 0 -> main int. is routed to processor INT (low vector base 0x500 ) */ +/* msb = 1 -> main int. is routed to processor SMI (low vector base 0x1400 ) */ + 0, 0, /* slice_tim2, irq1 */ + 0, 0, 0, 0, /* irq2, irq3, lo_int, rtc_pint */ + 0, 0, 0, 0, /* rtc_sint, gpio_std, gpio_wkup, tmr0 */ + 0, 0, 0, 0, /* tmr1, tmr2, tmr3, tmr4 */ + 0, 0, 0, /* tmr5, tmr6, tmr7 */ + /* critical interrupt priorities (0-3) / 2bit coding / no special purpose of msb */ + 0, /* irq0 */ + 0, 0, 0 /* slice_tim1, hi_int, ccs_wkup */ +}; + +static uint32_t irqMaskTable [BSP_PER_IRQ_NUMBER + BSP_MAIN_IRQ_NUMBER]; + +/* + * Check if symbolic IRQ name is a Processor IRQ + */ +static inline bool is_processor_irq( rtems_vector_number irqLine) +{ + + return ((irqLine <= BSP_PROCESSOR_IRQ_MAX_OFFSET) + && (irqLine >= BSP_PROCESSOR_IRQ_LOWEST_OFFSET)); +} + +/* + * Check for SIU IRQ and return base index + */ +static inline bool is_siu_irq( rtems_vector_number irqLine) +{ + + return ((irqLine <= BSP_SIU_IRQ_MAX_OFFSET) + && (irqLine >= BSP_SIU_IRQ_LOWEST_OFFSET)); +} + +/* + * Check for SIU IRQ and return base index + */ +static inline int get_siu_irq_base_index( rtems_vector_number irqLine) +{ + if (irqLine <= BSP_PER_IRQ_MAX_OFFSET) + return BSP_PER_IRQ_LOWEST_OFFSET; + + if (irqLine <= BSP_MAIN_IRQ_MAX_OFFSET) + return BSP_MAIN_IRQ_LOWEST_OFFSET; + + if (irqLine <= BSP_CRIT_IRQ_MAX_OFFSET) + return BSP_CRIT_IRQ_LOWEST_OFFSET; + + return -1; +} + +static inline void BSP_enable_per_irq_at_siu( + rtems_vector_number irqLine +) +{ + uint8_t lo_hi_ind = 0, + prio_index_offset; + uint32_t *reg; + + /* calculate the index offset of priority value bit field */ + prio_index_offset = (irqLine - BSP_PER_IRQ_LOWEST_OFFSET) % 8; + + /* set interrupt priorities */ + if (irqPrioTable [irqLine] <= 15) { + + /* set peripheral int priority */ + reg = (uint32_t *) (&(mpc5200.per_pri_1)); + + /* choose proper register */ + reg += (irqLine >> 3); + + /* set priority as given in priority table */ + *reg |= (irqPrioTable [irqLine] << (28 - (prio_index_offset << 2))); + + /* test msb (hash-bit) and set LO_/HI_int indicator */ + if ((lo_hi_ind = (irqPrioTable [irqLine] >> 3))) { + + /* set critical HI_int priority */ + reg = (uint32_t *) (&(mpc5200.crit_pri_main_mask)); + *reg |= (irqPrioTable [BSP_SIU_IRQ_HI_INT] << 26); + + /* + * critical interrupt handling for the 603le core is not + * yet supported, routing of critical interrupts is forced + * to core_int (bit 31 / CEb) + */ + mpc5200.ext_en_type |= 1; + + } else { + if (irqPrioTable [irqLine] <= 15) { + /* set main LO_int priority */ + reg = (uint32_t *) (&(mpc5200.main_pri_1)); + *reg |= (irqPrioTable [BSP_SIU_IRQ_LO_INT] << 16); + } + } + } + + /* if LO_int ind., enable (unmask) main interrupt */ + if (!lo_hi_ind) { + mpc5200.crit_pri_main_mask &= + ~(0x80000000 >> SIU_MaskBit [BSP_SIU_IRQ_LO_INT]); + } + + /* enable (unmask) peripheral interrupt */ + mpc5200.per_mask &= ~(0x80000000 >> SIU_MaskBit [irqLine]); + + /* FIXME: Why? */ + mpc5200.main_pri_1; + mpc5200.crit_pri_main_mask; + mpc5200.per_pri_1; + mpc5200.per_mask; +} + +static inline void BSP_enable_main_irq_at_siu( + rtems_vector_number irqLine +) +{ + + uint8_t prio_index_offset; + uint32_t *reg; + + /* calculate the index offset of priority value bit field */ + prio_index_offset = (irqLine - BSP_MAIN_IRQ_LOWEST_OFFSET) % 8; + + /* set main interrupt priority */ + if (irqPrioTable [irqLine] <= 15) { + + /* set main int priority */ + reg = (uint32_t *) (&(mpc5200.main_pri_1)); + + /* choose proper register */ + reg += (irqLine >> 3); + + /* set priority as given in priority table */ + *reg |= (irqPrioTable [irqLine] << (28 - (prio_index_offset << 2))); + + if ((irqLine >= BSP_SIU_IRQ_IRQ1) && (irqLine <= BSP_SIU_IRQ_IRQ3)) { + /* enable external irq-pin */ + mpc5200.ext_en_type |= (0x80000000 >> (20 + prio_index_offset)); + } + } + + /* enable (unmask) main interrupt */ + mpc5200.crit_pri_main_mask &= ~(0x80000000 >> SIU_MaskBit [irqLine]); + +} + +static inline void BSP_enable_crit_irq_at_siu( + rtems_vector_number irqLine +) +{ + uint8_t prio_index_offset; + uint32_t *reg; + + prio_index_offset = irqLine - BSP_CRIT_IRQ_LOWEST_OFFSET; + + /* + * critical interrupt handling for the 603Le core is not + * yet supported, routing of critical interrupts is forced + * to core_int (bit 31 / CEb) + */ + mpc5200.ext_en_type |= 1; + + /* set critical interrupt priorities */ + if (irqPrioTable [irqLine] <= 3) { + + /* choose proper register */ + reg = (uint32_t *) (&(mpc5200.crit_pri_main_mask)); + + /* set priority as given in priority table */ + *reg |= (irqPrioTable [irqLine] << (30 - (prio_index_offset << 1))); + + /* external irq0-pin */ + if (irqLine == BSP_SIU_IRQ_IRQ1) { + /* enable external irq-pin */ + mpc5200.ext_en_type |= (0x80000000 >> (20 + prio_index_offset)); + } + } +} + +static inline void BSP_disable_per_irq_at_siu( + rtems_vector_number irqLine +) +{ + uint8_t prio_index_offset; + uint32_t *reg; + + /* calculate the index offset of priority value bit field */ + prio_index_offset = (irqLine - BSP_PER_IRQ_LOWEST_OFFSET) % 8; + + /* disable (mask) peripheral interrupt */ + mpc5200.per_mask |= (0x80000000 >> SIU_MaskBit [irqLine]); + + /* reset priority to lowest level (reset value) */ + reg = (uint32_t *) (&(mpc5200.per_pri_1)); + reg += (irqLine >> 3); + *reg &= ~(15 << (28 - (prio_index_offset << 2))); +} + +static inline void BSP_disable_main_irq_at_siu( + rtems_vector_number irqLine +) +{ + uint8_t prio_index_offset; + uint32_t *reg; + + /* calculate the index offset of priority value bit field */ + prio_index_offset = (irqLine - BSP_MAIN_IRQ_LOWEST_OFFSET) % 8; + + /* disable (mask) main interrupt */ + mpc5200.crit_pri_main_mask |= (0x80000000 >> SIU_MaskBit [irqLine]); + + if ((irqLine >= BSP_SIU_IRQ_IRQ1) && (irqLine <= BSP_SIU_IRQ_IRQ3)) { + /* disable external irq-pin */ + mpc5200.ext_en_type &= ~(0x80000000 >> (20 + prio_index_offset)); + } + + /* reset priority to lowest level (reset value) */ + reg = (uint32_t *) (&(mpc5200.main_pri_1)); + reg += (irqLine >> 3); + *reg &= ~(15 << (28 - (prio_index_offset << 2))); +} + +static inline void BSP_disable_crit_irq_at_siu( rtems_vector_number + irqLine) +{ + uint8_t prio_index_offset; + uint32_t *reg; + + prio_index_offset = irqLine - BSP_CRIT_IRQ_LOWEST_OFFSET; + + /* reset critical int priority to lowest level (reset value) */ + reg = (uint32_t *) (&(mpc5200.crit_pri_main_mask)); + *reg &= ~(3 << (30 - (prio_index_offset << 1))); + + if (irqLine == BSP_SIU_IRQ_IRQ1) { + /* disable external irq0-pin */ + mpc5200.ext_en_type &= ~(0x80000000 >> (20 + prio_index_offset)); + } +} + +/* + * This function enables a given siu interrupt + */ +void bsp_interrupt_vector_enable( rtems_vector_number vector) +{ + int base_index = get_siu_irq_base_index( vector); + + bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector)); + + if (is_siu_irq( vector)) { + rtems_interrupt_level level; + + rtems_interrupt_disable( level); + + switch (base_index) { + case BSP_PER_IRQ_LOWEST_OFFSET: + BSP_enable_per_irq_at_siu( vector); + break; + case BSP_MAIN_IRQ_LOWEST_OFFSET: + BSP_enable_main_irq_at_siu( vector); + break; + case BSP_CRIT_IRQ_LOWEST_OFFSET: + BSP_enable_crit_irq_at_siu( vector); + break; + default: + bsp_interrupt_assert(0); + break; + } + + rtems_interrupt_enable( level); + } +} + +/* + * This function disables a given siu interrupt + */ +void bsp_interrupt_vector_disable( rtems_vector_number vector) +{ + int base_index = get_siu_irq_base_index( vector); + + bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector)); + + if (is_siu_irq( vector)) { + rtems_interrupt_level level; + + rtems_interrupt_disable( level); + + switch (base_index) { + case BSP_PER_IRQ_LOWEST_OFFSET: + BSP_disable_per_irq_at_siu( vector); + break; + case BSP_MAIN_IRQ_LOWEST_OFFSET: + BSP_disable_main_irq_at_siu( vector); + break; + case BSP_CRIT_IRQ_LOWEST_OFFSET: + BSP_disable_crit_irq_at_siu( vector); + break; + default: + bsp_interrupt_assert(0); + break; + } + + rtems_interrupt_enable( level); + } +} + +#if (BENCHMARK_IRQ_PROCESSING == 0) +void BSP_IRQ_Benchmarking_Reset( void) +{ +} +void BSP_IRQ_Benchmarking_Report( void) +{ +} +#else +#include +uint64_t BSP_Starting_TBR; +uint64_t BSP_Total_in_ISR; +uint32_t BSP_ISR_Count; +uint32_t BSP_Worst_ISR; + +#define BSP_COUNTED_IRQ 16 +uint32_t BSP_ISR_Count_Per [BSP_COUNTED_IRQ + 1]; + +void BSP_IRQ_Benchmarking_Reset( void) +{ + int i; + + BSP_Starting_TBR = PPC_Get_timebase_register(); + BSP_Total_in_ISR = 0; + BSP_ISR_Count = 0; + BSP_Worst_ISR = 0; + for (i = 0; i < BSP_COUNTED_IRQ; i++) + BSP_ISR_Count_Per [i] = 0; +} + +static const char *u64tostring( char *buffer, uint64_t v) +{ + sprintf( buffer, "%lld cycles %lld usecs", v, (v / 33)); + return buffer; +} + +void BSP_IRQ_Benchmarking_Report( void) +{ + uint64_t now; + char buffer [96]; + int i; + + now = PPC_Get_timebase_register(); + printk( "Started at: %s\n", u64tostring( buffer, BSP_Starting_TBR)); + printk( "Current : %s\n", u64tostring( buffer, now)); + printk( "System up : %s\n", u64tostring( buffer, now - BSP_Starting_TBR)); + printk( "ISRs : %d\n", BSP_ISR_Count); + printk( "ISRs ran : %s\n", u64tostring( buffer, BSP_Total_in_ISR)); + printk( "Worst ISR : %s\n", u64tostring( buffer, BSP_Worst_ISR)); + for (i = 0; i < BSP_COUNTED_IRQ; i++) + printk( "IRQ %d: %d\n", i, BSP_ISR_Count_Per [i]); + printk( "Ticks : %d\n", Clock_driver_ticks); +} +#endif + +static void dispatch(uint32_t irq, uint32_t offset, volatile uint32_t *maskreg) +{ + #if (ALLOW_IRQ_NESTING == 1) + uint32_t msr; + uint32_t mask = *maskreg; + #endif + + irq += offset; + + #if (ALLOW_IRQ_NESTING == 1) + *maskreg = mask | irqMaskTable [irq]; + /* Make sure that the write operation completed (cache inhibited area) */ + *maskreg; + msr = ppc_external_exceptions_enable(); + #endif + + bsp_interrupt_handler_dispatch(irq); + + #if (ALLOW_IRQ_NESTING == 1) + ppc_external_exceptions_disable(msr); + *maskreg = mask; + #endif +} + +/* + * High level IRQ handler called from shared_raw_irq_code_entry + */ +static int C_dispatch_irq_handler(BSP_Exception_frame *frame, unsigned excNum) +{ + uint32_t irq; + uint32_t pmce; + +#if (BENCHMARK_IRQ_PROCESSING == 1) + uint64_t start, + stop, + thisTime; + + start = PPC_Get_timebase_register(); + BSP_ISR_Count++; + if (excNum < BSP_COUNTED_IRQ) + BSP_ISR_Count_Per [excNum]++; + else + printk( "not counting %d\n", excNum); +#endif + + /* get the content of main interrupt status register */ + pmce = mpc5200.pmce; + + /* critical interrupts are routed to the core_int, see premature + * initialization + */ + while ((pmce & (PMCE_CSE_STICKY | PMCE_MSE_STICKY)) != 0) { + /* first: check for critical interrupt sources (hierarchical order) + * -> HI_int indicates peripheral sources + */ + if ((pmce & PMCE_CSE_STICKY) != 0) { + /* get source of critical interrupt */ + irq = PMCE_CSE_SOURCE(pmce); + + switch (irq) { + /* peripheral HI_int interrupt source detected */ + case 2: + /* check for valid peripheral interrupt source */ + if ((pmce & PMCE_PSE_STICKY) != 0) { + /* get source of peripheral interrupt */ + irq = PMCE_PSE_SOURCE(pmce); + + dispatch(irq, BSP_PER_IRQ_LOWEST_OFFSET, &mpc5200.per_mask); + } else { + /* this case may not occur: no valid peripheral + * interrupt source */ + printk( "No valid peripheral HI_int interrupt source\n"); + } + break; + + /* irq0, slice timer 1 or ccs wakeup detected */ + case 0: + case 1: + case 3: + + /* add proper offset for critical interrupts in the siu + * handler array */ + irq += BSP_CRIT_IRQ_LOWEST_OFFSET; + + /* Dispatch interrupt handlers */ + bsp_interrupt_handler_dispatch( irq); + + break; + + default: + /* error: unknown interrupt source */ + printk( "Unknown HI_int interrupt source\n"); + break; + } + } + + /* second: check for main interrupt sources (hierarchical order) + * -> LO_int indicates peripheral sources */ + if ((pmce & PMCE_MSE_STICKY) != 0) { + /* get source of main interrupt */ + irq = PMCE_MSE_SOURCE(pmce); + + if (irq == 4) { + /* peripheral LO_int interrupt source detected */ + /* check for valid peripheral interrupt source */ + if ((pmce & PMCE_PSE_STICKY) != 0) { + /* get source of peripheral interrupt */ + irq = PMCE_PSE_SOURCE(pmce); + + dispatch(irq, BSP_PER_IRQ_LOWEST_OFFSET, &mpc5200.per_mask); + } else { + /* this case may not occur: no valid peripheral + * interrupt source */ + printk( "No valid peripheral LO_int interrupt source\n"); + } + } else if (irq <= 16) { + /* irq1-3, RTC, GPIO, TMR0-7 detected (attention: slice timer + * 2 is always routed to SMI) */ + dispatch(irq, BSP_MAIN_IRQ_LOWEST_OFFSET, &mpc5200.crit_pri_main_mask); + } else { + /* error: unknown interrupt source */ + printk( "Unknown peripheral LO_int interrupt source\n"); + } + } + + /* force re-evaluation of interrupts */ + mpc5200.pmce = PMCE_CSE_STICKY | PMCE_MSE_STICKY | PMCE_PSE_STICKY; + + /* get the content of main interrupt status register */ + pmce = mpc5200.pmce; + } + +#if (BENCHMARK_IRQ_PROCESSING == 1) + stop = PPC_Get_timebase_register(); + thisTime = stop - start; + BSP_Total_in_ISR += thisTime; + if (thisTime > BSP_Worst_ISR) + BSP_Worst_ISR = thisTime; +#endif + + return 0; +} + +/* + * setup irqMaskTable to support a priorized/nested interrupt environment + */ +static void setup_irqMaskTable( void) +{ + rtems_irq_prio prio = 0; + uint32_t i = 0, + j = 0, + mask = 0; + + /* set up the priority dependent masks for peripheral interrupts */ + for (i = BSP_PER_IRQ_LOWEST_OFFSET; i <= BSP_PER_IRQ_MAX_OFFSET; i++) { + prio = irqPrioTable [i]; + mask = 0; + + for (j = BSP_PER_IRQ_LOWEST_OFFSET; j <= BSP_PER_IRQ_MAX_OFFSET; j++) { + if (prio > irqPrioTable [j]) { + mask |= (1 << (31 - j + BSP_PER_IRQ_LOWEST_OFFSET)); + } + + if ((prio == irqPrioTable [j]) && (j >= i)) { + mask |= (1 << (31 - j + BSP_PER_IRQ_LOWEST_OFFSET)); + } + } + + irqMaskTable [i] = mask; + } + + /* set up the priority dependent masks for main interrupts */ + for (i = BSP_MAIN_IRQ_LOWEST_OFFSET; i <= BSP_MAIN_IRQ_MAX_OFFSET; i++) { + prio = irqPrioTable [i]; + mask = 0; + + for (j = BSP_MAIN_IRQ_LOWEST_OFFSET; j <= BSP_MAIN_IRQ_MAX_OFFSET; j++) { + if (prio > irqPrioTable [j]) { + mask |= (1 << (16 - j + BSP_MAIN_IRQ_LOWEST_OFFSET)); + } + + if ((prio == irqPrioTable [j]) && (j >= i)) { + mask |= (1 << (16 - j + BSP_MAIN_IRQ_LOWEST_OFFSET)); + } + } + + irqMaskTable [i] = mask; + } +} + +/* + * Initialize MPC5x00 SIU interrupt management + */ +static void BSP_SIU_irq_init( void) +{ + + /* disable all peripheral interrupts */ + mpc5200.per_mask = 0xFFFFFC00; + + /* peripheral interrupt priorities according to reset value */ + mpc5200.per_pri_1 = 0xF0000000; + mpc5200.per_pri_2 = 0x00000000; + mpc5200.per_pri_3 = 0x00000000; + + /* disable external interrupts IRQ0-4 / critical interrupts are routed to core_int */ + mpc5200.ext_en_type = 0x0F000001; + + /* disable main interrupts / crit. int. priorities according to reset values */ + mpc5200.crit_pri_main_mask = 0x0001FFFF; + + /* main priorities according to reset value */ + mpc5200.main_pri_1 = 0; + mpc5200.main_pri_2 = 0; + + /* reset all status indicators */ + mpc5200.csa = 0x0001FFFF; + mpc5200.msa = 0x0001FFFF; + mpc5200.psa = 0x003FFFFF; + mpc5200.psa_be = 0x03000000; + + setup_irqMaskTable(); +} + +rtems_status_code bsp_interrupt_facility_initialize( void) +{ + BSP_SIU_irq_init(); + + /* Install exception handler */ + if (ppc_exc_set_handler( ASM_EXT_VECTOR, C_dispatch_irq_handler)) { + return RTEMS_IO_ERROR; + } + if (ppc_exc_set_handler( ASM_E300_SYSMGMT_VECTOR, C_dispatch_irq_handler)) { + return RTEMS_IO_ERROR; + } + + return RTEMS_SUCCESSFUL; +} + +void bsp_interrupt_handler_default( rtems_vector_number vector) +{ + if (vector != BSP_DECREMENTER) { + printk( "Spurious interrupt: 0x%08" PRIx32 "\n", vector); + } +} diff --git a/bsps/powerpc/gen83xx/irq/irq.c b/bsps/powerpc/gen83xx/irq/irq.c new file mode 100644 index 0000000000..7a8ce3cc0b --- /dev/null +++ b/bsps/powerpc/gen83xx/irq/irq.c @@ -0,0 +1,596 @@ +/*===============================================================*\ +| Project: RTEMS generic MPC83xx BSP | ++-----------------------------------------------------------------+ +| Copyright (c) 2007 | +| Embedded Brains GmbH | +| Obere Lagerstr. 30 | +| D-82178 Puchheim | +| Germany | +| rtems@embedded-brains.de | ++-----------------------------------------------------------------+ +| The license and distribution terms for this file may be | +| found in the file LICENSE in this distribution or at | +| | +| http://www.rtems.org/license/LICENSE. | +| | ++-----------------------------------------------------------------+ +| this file integrates the IPIC irq controller | +\*===============================================================*/ + +#include + +#include + +#include +#include + +#include +#include +#include + +#define MPC83XX_IPIC_VECTOR_NUMBER 92 + +#define MPC83XX_IPIC_IS_VALID_VECTOR( vector) ((vector) >= 0 && (vector) < MPC83XX_IPIC_VECTOR_NUMBER) + +#define MPC83XX_IPIC_INVALID_MASK_POSITION 255 + +typedef struct { + volatile uint32_t *pend_reg; + volatile uint32_t *mask_reg; + const uint32_t bit_num; +} BSP_isrc_rsc_t; + +/* + * data structure to handle all mask registers in the IPIC + * + * Mask positions: + * simsr [0] : 0 .. 31 + * simsr [1] : 32 .. 63 + * semsr : 64 .. 95 + * sermr : 96 .. 127 + */ +typedef struct { + uint32_t simsr_mask [2]; + uint32_t semsr_mask; + uint32_t sermr_mask; +} mpc83xx_ipic_mask_t; + +static const BSP_isrc_rsc_t mpc83xx_ipic_isrc_rsc [MPC83XX_IPIC_VECTOR_NUMBER] = { + /* vector 0 */ + {&mpc83xx.ipic.sersr, &mpc83xx.ipic.sermr, 31}, + {NULL, NULL, 0}, + {NULL, NULL, 0}, + {NULL, NULL, 0}, + {NULL, NULL, 0}, + {NULL, NULL, 0}, + {NULL, NULL, 0}, + {NULL, NULL, 0}, + /* vector 8 */ + {NULL, NULL, 0}, /* reserved vector 8 */ + /* vector 9: UART1 SIxxR_H, Bit 24 */ + {&mpc83xx.ipic.sipnr [0], &mpc83xx.ipic.simsr [0], 24}, + /* vector 10: UART2 SIxxR_H, Bit 25 */ + {&mpc83xx.ipic.sipnr [0], &mpc83xx.ipic.simsr [0], 25}, + /* vector 11: SEC SIxxR_H, Bit 26 */ + {&mpc83xx.ipic.sipnr [0], &mpc83xx.ipic.simsr [0], 26}, + {NULL, NULL, 0}, /* reserved vector 12 */ + {NULL, NULL, 0}, /* reserved vector 13 */ + /* vector 14: I2C1 SIxxR_H, Bit 29 */ + {&mpc83xx.ipic.sipnr [0], &mpc83xx.ipic.simsr [0], 29}, + /* vector 15: I2C2 SIxxR_H, Bit 30 */ + {&mpc83xx.ipic.sipnr [0], &mpc83xx.ipic.simsr [0], 30}, + /* vector 16: SPI SIxxR_H, Bit 31 */ + {&mpc83xx.ipic.sipnr [0], &mpc83xx.ipic.simsr [0], 31}, + /* vector 17: IRQ1 SExxR , Bit 1 */ + {&mpc83xx.ipic.sepnr, &mpc83xx.ipic.semsr, 1}, + /* vector 18: IRQ2 SExxR , Bit 2 */ + {&mpc83xx.ipic.sepnr, &mpc83xx.ipic.semsr, 2}, + /* vector 19: IRQ3 SExxR , Bit 3 */ + {&mpc83xx.ipic.sepnr, &mpc83xx.ipic.semsr, 3}, + /* vector 20: IRQ4 SExxR , Bit 4 */ + {&mpc83xx.ipic.sepnr, &mpc83xx.ipic.semsr, 4}, + /* vector 21: IRQ5 SExxR , Bit 5 */ + {&mpc83xx.ipic.sepnr, &mpc83xx.ipic.semsr, 5}, + /* vector 22: IRQ6 SExxR , Bit 6 */ + {&mpc83xx.ipic.sepnr, &mpc83xx.ipic.semsr, 6}, + /* vector 23: IRQ7 SExxR , Bit 7 */ + {&mpc83xx.ipic.sepnr, &mpc83xx.ipic.semsr, 7}, + {NULL, NULL, 0}, /* reserved vector 24 */ + {NULL, NULL, 0}, /* reserved vector 25 */ + {NULL, NULL, 0}, /* reserved vector 26 */ + {NULL, NULL, 0}, /* reserved vector 27 */ + {NULL, NULL, 0}, /* reserved vector 28 */ + {NULL, NULL, 0}, /* reserved vector 29 */ + {NULL, NULL, 0}, /* reserved vector 30 */ + {NULL, NULL, 0}, /* reserved vector 31 */ + /* vector 32: TSEC1 Tx SIxxR_H , Bit 0 */ + {&mpc83xx.ipic.sipnr [0], &mpc83xx.ipic.simsr [0], 0}, + /* vector 33: TSEC1 Rx SIxxR_H , Bit 1 */ + {&mpc83xx.ipic.sipnr [0], &mpc83xx.ipic.simsr [0], 1}, + /* vector 34: TSEC1 Err SIxxR_H , Bit 2 */ + {&mpc83xx.ipic.sipnr [0], &mpc83xx.ipic.simsr [0], 2}, + /* vector 35: TSEC2 Tx SIxxR_H , Bit 3 */ + {&mpc83xx.ipic.sipnr [0], &mpc83xx.ipic.simsr [0], 3}, + /* vector 36: TSEC2 Rx SIxxR_H , Bit 4 */ + {&mpc83xx.ipic.sipnr [0], &mpc83xx.ipic.simsr [0], 4}, + /* vector 37: TSEC2 Err SIxxR_H , Bit 5 */ + {&mpc83xx.ipic.sipnr [0], &mpc83xx.ipic.simsr [0], 5}, + /* vector 38: USB DR SIxxR_H , Bit 6 */ + {&mpc83xx.ipic.sipnr [0], &mpc83xx.ipic.simsr [0], 6}, + /* vector 39: USB MPH SIxxR_H , Bit 7 */ + {&mpc83xx.ipic.sipnr [0], &mpc83xx.ipic.simsr [0], 7}, + {NULL, NULL, 0}, /* reserved vector 40 */ + {NULL, NULL, 0}, /* reserved vector 41 */ + {NULL, NULL, 0}, /* reserved vector 42 */ + {NULL, NULL, 0}, /* reserved vector 43 */ + {NULL, NULL, 0}, /* reserved vector 44 */ + {NULL, NULL, 0}, /* reserved vector 45 */ + {NULL, NULL, 0}, /* reserved vector 46 */ + {NULL, NULL, 0}, /* reserved vector 47 */ + /* vector 48: IRQ0 SExxR , Bit 0 */ + {&mpc83xx.ipic.sepnr, &mpc83xx.ipic.semsr, 0}, + {NULL, NULL, 0}, /* reserved vector 49 */ + {NULL, NULL, 0}, /* reserved vector 50 */ + {NULL, NULL, 0}, /* reserved vector 51 */ + {NULL, NULL, 0}, /* reserved vector 52 */ + {NULL, NULL, 0}, /* reserved vector 53 */ + {NULL, NULL, 0}, /* reserved vector 54 */ + {NULL, NULL, 0}, /* reserved vector 55 */ + {NULL, NULL, 0}, /* reserved vector 56 */ + {NULL, NULL, 0}, /* reserved vector 57 */ + {NULL, NULL, 0}, /* reserved vector 58 */ + {NULL, NULL, 0}, /* reserved vector 59 */ + {NULL, NULL, 0}, /* reserved vector 60 */ + {NULL, NULL, 0}, /* reserved vector 61 */ + {NULL, NULL, 0}, /* reserved vector 62 */ + {NULL, NULL, 0}, /* reserved vector 63 */ + /* vector 64: RTC SEC SIxxR_L , Bit 0 */ + {&mpc83xx.ipic.sipnr [1], &mpc83xx.ipic.simsr [1], 0}, + /* vector 65: PIT SIxxR_L , Bit 1 */ + {&mpc83xx.ipic.sipnr [1], &mpc83xx.ipic.simsr [1], 1}, + /* vector 66: PCI1 SIxxR_L , Bit 2 */ + {&mpc83xx.ipic.sipnr [1], &mpc83xx.ipic.simsr [1], 2}, + /* vector 67: PCI2 SIxxR_L , Bit 3 */ + {&mpc83xx.ipic.sipnr [1], &mpc83xx.ipic.simsr [1], 3}, + /* vector 68: RTC ALR SIxxR_L , Bit 4 */ + {&mpc83xx.ipic.sipnr [1], &mpc83xx.ipic.simsr [1], 4}, + /* vector 69: MU SIxxR_L , Bit 5 */ + {&mpc83xx.ipic.sipnr [1], &mpc83xx.ipic.simsr [1], 5}, + /* vector 70: SBA SIxxR_L , Bit 6 */ + {&mpc83xx.ipic.sipnr [1], &mpc83xx.ipic.simsr [1], 6}, + /* vector 71: DMA SIxxR_L , Bit 7 */ + {&mpc83xx.ipic.sipnr [1], &mpc83xx.ipic.simsr [1], 7}, + /* vector 72: GTM4 SIxxR_L , Bit 8 */ + {&mpc83xx.ipic.sipnr [1], &mpc83xx.ipic.simsr [1], 8}, + /* vector 73: GTM8 SIxxR_L , Bit 9 */ + {&mpc83xx.ipic.sipnr [1], &mpc83xx.ipic.simsr [1], 9}, + /* vector 74: GPIO1 SIxxR_L , Bit 10 */ + {&mpc83xx.ipic.sipnr [1], &mpc83xx.ipic.simsr [1], 10}, + /* vector 75: GPIO2 SIxxR_L , Bit 11 */ + {&mpc83xx.ipic.sipnr [1], &mpc83xx.ipic.simsr [1], 11}, + /* vector 76: DDR SIxxR_L , Bit 12 */ + {&mpc83xx.ipic.sipnr [1], &mpc83xx.ipic.simsr [1], 12}, + /* vector 77: LBC SIxxR_L , Bit 13 */ + {&mpc83xx.ipic.sipnr [1], &mpc83xx.ipic.simsr [1], 13}, + /* vector 78: GTM2 SIxxR_L , Bit 14 */ + {&mpc83xx.ipic.sipnr [1], &mpc83xx.ipic.simsr [1], 14}, + /* vector 79: GTM6 SIxxR_L , Bit 15 */ + {&mpc83xx.ipic.sipnr [1], &mpc83xx.ipic.simsr [1], 15}, + /* vector 80: PMC SIxxR_L , Bit 16 */ + {&mpc83xx.ipic.sipnr [1], &mpc83xx.ipic.simsr [1], 16}, + {NULL, NULL, 0}, /* reserved vector 81 */ + {NULL, NULL, 0}, /* reserved vector 82 */ + {NULL, NULL, 0}, /* reserved vector 63 */ + /* vector 84: GTM3 SIxxR_L , Bit 20 */ + {&mpc83xx.ipic.sipnr [1], &mpc83xx.ipic.simsr [1], 20}, + /* vector 85: GTM7 SIxxR_L , Bit 21 */ + {&mpc83xx.ipic.sipnr [1], &mpc83xx.ipic.simsr [1], 21}, + {NULL, NULL, 0}, /* reserved vector 81 */ + {NULL, NULL, 0}, /* reserved vector 82 */ + {NULL, NULL, 0}, /* reserved vector 63 */ + {NULL, NULL, 0}, /* reserved vector 63 */ + /* vector 90: GTM1 SIxxR_L , Bit 26 */ + {&mpc83xx.ipic.sipnr [1], &mpc83xx.ipic.simsr [1], 26}, + /* vector 91: GTM5 SIxxR_L , Bit 27 */ + {&mpc83xx.ipic.sipnr [1], &mpc83xx.ipic.simsr [1], 27} +}; + +static const uint8_t + mpc83xx_ipic_mask_position_table [MPC83XX_IPIC_VECTOR_NUMBER] = { + MPC83XX_IPIC_INVALID_MASK_POSITION, + MPC83XX_IPIC_INVALID_MASK_POSITION, + MPC83XX_IPIC_INVALID_MASK_POSITION, + MPC83XX_IPIC_INVALID_MASK_POSITION, + MPC83XX_IPIC_INVALID_MASK_POSITION, + MPC83XX_IPIC_INVALID_MASK_POSITION, + MPC83XX_IPIC_INVALID_MASK_POSITION, + MPC83XX_IPIC_INVALID_MASK_POSITION, + MPC83XX_IPIC_INVALID_MASK_POSITION, + 7, + 6, + 5, + MPC83XX_IPIC_INVALID_MASK_POSITION, + MPC83XX_IPIC_INVALID_MASK_POSITION, + 2, + 1, + 0, + 94, + 93, + 92, + 91, + 90, + 89, + 88, + MPC83XX_IPIC_INVALID_MASK_POSITION, + MPC83XX_IPIC_INVALID_MASK_POSITION, + MPC83XX_IPIC_INVALID_MASK_POSITION, + MPC83XX_IPIC_INVALID_MASK_POSITION, + MPC83XX_IPIC_INVALID_MASK_POSITION, + MPC83XX_IPIC_INVALID_MASK_POSITION, + MPC83XX_IPIC_INVALID_MASK_POSITION, + MPC83XX_IPIC_INVALID_MASK_POSITION, + 31, + 30, + 29, + 28, + 27, + 26, + 25, + 24, + MPC83XX_IPIC_INVALID_MASK_POSITION, + MPC83XX_IPIC_INVALID_MASK_POSITION, + MPC83XX_IPIC_INVALID_MASK_POSITION, + MPC83XX_IPIC_INVALID_MASK_POSITION, + MPC83XX_IPIC_INVALID_MASK_POSITION, + MPC83XX_IPIC_INVALID_MASK_POSITION, + MPC83XX_IPIC_INVALID_MASK_POSITION, + MPC83XX_IPIC_INVALID_MASK_POSITION, + 95, + MPC83XX_IPIC_INVALID_MASK_POSITION, + MPC83XX_IPIC_INVALID_MASK_POSITION, + MPC83XX_IPIC_INVALID_MASK_POSITION, + MPC83XX_IPIC_INVALID_MASK_POSITION, + MPC83XX_IPIC_INVALID_MASK_POSITION, + MPC83XX_IPIC_INVALID_MASK_POSITION, + MPC83XX_IPIC_INVALID_MASK_POSITION, + MPC83XX_IPIC_INVALID_MASK_POSITION, + MPC83XX_IPIC_INVALID_MASK_POSITION, + MPC83XX_IPIC_INVALID_MASK_POSITION, + MPC83XX_IPIC_INVALID_MASK_POSITION, + MPC83XX_IPIC_INVALID_MASK_POSITION, + MPC83XX_IPIC_INVALID_MASK_POSITION, + MPC83XX_IPIC_INVALID_MASK_POSITION, + MPC83XX_IPIC_INVALID_MASK_POSITION, + 63, + 62, + 61, + 60, + 59, + 58, + 57, + 56, + 55, + 54, + 53, + 52, + 51, + 50, + 49, + 48, + 47, + MPC83XX_IPIC_INVALID_MASK_POSITION, + MPC83XX_IPIC_INVALID_MASK_POSITION, + MPC83XX_IPIC_INVALID_MASK_POSITION, + 43, + 42, + MPC83XX_IPIC_INVALID_MASK_POSITION, + MPC83XX_IPIC_INVALID_MASK_POSITION, + MPC83XX_IPIC_INVALID_MASK_POSITION, + MPC83XX_IPIC_INVALID_MASK_POSITION, + 37, + 36 +}; + +/* + * this array will be filled with mask values needed + * to temporarily disable all IRQ soures with lower or same + * priority of the current source (whose vector is the array index) + */ +static mpc83xx_ipic_mask_t mpc83xx_ipic_prio2mask [MPC83XX_IPIC_VECTOR_NUMBER]; + +rtems_status_code mpc83xx_ipic_set_mask( + rtems_vector_number vector, + rtems_vector_number mask_vector, + bool mask +) +{ + uint8_t pos = 0; + mpc83xx_ipic_mask_t *mask_entry; + uint32_t *mask_reg; + rtems_interrupt_level level; + + /* Parameter check */ + if (!MPC83XX_IPIC_IS_VALID_VECTOR( vector) || + !MPC83XX_IPIC_IS_VALID_VECTOR( mask_vector)) { + return RTEMS_INVALID_NUMBER; + } else if (vector == mask_vector) { + return RTEMS_RESOURCE_IN_USE; + } + + /* Position and mask entry */ + pos = mpc83xx_ipic_mask_position_table [mask_vector]; + mask_entry = &mpc83xx_ipic_prio2mask [vector]; + + /* Mask register and position */ + if (pos < 32) { + mask_reg = &mask_entry->simsr_mask [0]; + } else if (pos < 64) { + pos -= 32; + mask_reg = &mask_entry->simsr_mask [1]; + } else if (pos < 96) { + pos -= 64; + mask_reg = &mask_entry->semsr_mask; + } else if (pos < 128) { + pos -= 96; + mask_reg = &mask_entry->sermr_mask; + } else { + return RTEMS_NOT_IMPLEMENTED; + } + + /* Mask or unmask */ + if (mask) { + rtems_interrupt_disable( level); + *mask_reg &= ~(1 << pos); + rtems_interrupt_enable( level); + } else { + rtems_interrupt_disable( level); + *mask_reg |= 1 << pos; + rtems_interrupt_enable( level); + } + + return RTEMS_SUCCESSFUL; +} + +rtems_status_code mpc83xx_ipic_set_highest_priority_interrupt( + rtems_vector_number vector, + int type +) +{ + rtems_interrupt_level level; + uint32_t reg = 0; + + if (!MPC83XX_IPIC_IS_VALID_VECTOR( vector)) { + return RTEMS_INVALID_NUMBER; + } else if (type < 0 || type > MPC83XX_IPIC_INTERRUPT_CRITICAL) { + return RTEMS_INVALID_NUMBER; + } + + rtems_interrupt_disable( level); + reg = mpc83xx.ipic.sicfr; + mpc83xx.ipic.sicfr = (reg & ~0x7f000300) | (vector << 24) | (type << 8); + rtems_interrupt_enable( level); + + return RTEMS_SUCCESSFUL; +} + +/* + * functions to enable/disable a source at the ipic + */ +void bsp_interrupt_vector_enable( rtems_vector_number vector) +{ + rtems_vector_number vecnum = vector - BSP_IPIC_IRQ_LOWEST_OFFSET; + const BSP_isrc_rsc_t *rsc_ptr; + + bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector)); + + if (MPC83XX_IPIC_IS_VALID_VECTOR( vecnum)) { + rsc_ptr = &mpc83xx_ipic_isrc_rsc [vecnum]; + if (rsc_ptr->mask_reg != NULL) { + uint32_t bit = 1U << (31 - rsc_ptr->bit_num); + rtems_interrupt_level level; + + rtems_interrupt_disable(level); + *(rsc_ptr->mask_reg) |= bit; + rtems_interrupt_enable(level); + } + } +} + +void bsp_interrupt_vector_disable( rtems_vector_number vector) +{ + rtems_vector_number vecnum = vector - BSP_IPIC_IRQ_LOWEST_OFFSET; + const BSP_isrc_rsc_t *rsc_ptr; + + bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector)); + + if (MPC83XX_IPIC_IS_VALID_VECTOR( vecnum)) { + rsc_ptr = &mpc83xx_ipic_isrc_rsc [vecnum]; + if (rsc_ptr->mask_reg != NULL) { + uint32_t bit = 1U << (31 - rsc_ptr->bit_num); + rtems_interrupt_level level; + + rtems_interrupt_disable(level); + *(rsc_ptr->mask_reg) &= ~bit; + rtems_interrupt_enable(level); + } + } +} + +/* + * IRQ Handler: this is called from the primary exception dispatcher + */ +static int BSP_irq_handle_at_ipic( unsigned excNum) +{ + int32_t vecnum; +#ifdef GEN83XX_ENABLE_INTERRUPT_NESTING + mpc83xx_ipic_mask_t mask_save; + const mpc83xx_ipic_mask_t *mask_ptr; + uint32_t msr = 0; + rtems_interrupt_level level; +#endif + + /* Get vector number */ + switch (excNum) { + case ASM_EXT_VECTOR: + vecnum = MPC83xx_VCR_TO_VEC( mpc83xx.ipic.sivcr); + break; + case ASM_E300_SYSMGMT_VECTOR: + vecnum = MPC83xx_VCR_TO_VEC( mpc83xx.ipic.smvcr); + break; + case ASM_E300_CRIT_VECTOR: + vecnum = MPC83xx_VCR_TO_VEC( mpc83xx.ipic.scvcr); + break; + default: + return 1; + } + + /* + * Check the vector number, mask lower priority interrupts, enable + * exceptions and dispatch the handler. + */ + if (MPC83XX_IPIC_IS_VALID_VECTOR( vecnum)) { +#ifdef GEN83XX_ENABLE_INTERRUPT_NESTING + mask_ptr = &mpc83xx_ipic_prio2mask [vecnum]; + + rtems_interrupt_disable( level); + + /* Save current mask registers */ + mask_save.simsr_mask [0] = mpc83xx.ipic.simsr [0]; + mask_save.simsr_mask [1] = mpc83xx.ipic.simsr [1]; + mask_save.semsr_mask = mpc83xx.ipic.semsr; + mask_save.sermr_mask = mpc83xx.ipic.sermr; + + /* Mask all lower priority interrupts */ + mpc83xx.ipic.simsr [0] &= mask_ptr->simsr_mask [0]; + mpc83xx.ipic.simsr [1] &= mask_ptr->simsr_mask [1]; + mpc83xx.ipic.semsr &= mask_ptr->semsr_mask; + mpc83xx.ipic.sermr &= mask_ptr->sermr_mask; + + rtems_interrupt_enable( level); + + /* Enable all interrupts */ + if (excNum != ASM_E300_CRIT_VECTOR) { + msr = ppc_external_exceptions_enable(); + } +#endif /* GEN83XX_ENABLE_INTERRUPT_NESTING */ + + /* Dispatch interrupt handlers */ + bsp_interrupt_handler_dispatch( vecnum + BSP_IPIC_IRQ_LOWEST_OFFSET); + +#ifdef GEN83XX_ENABLE_INTERRUPT_NESTING + /* Restore machine state */ + if (excNum != ASM_E300_CRIT_VECTOR) { + ppc_external_exceptions_disable( msr); + } + + /* Restore initial masks */ + rtems_interrupt_disable( level); + mpc83xx.ipic.simsr [0] = mask_save.simsr_mask [0]; + mpc83xx.ipic.simsr [1] = mask_save.simsr_mask [1]; + mpc83xx.ipic.semsr = mask_save.semsr_mask; + mpc83xx.ipic.sermr = mask_save.sermr_mask; + rtems_interrupt_enable( level); +#endif /* GEN83XX_ENABLE_INTERRUPT_NESTING */ + } else { + bsp_interrupt_handler_default( vecnum); + } + + return 0; +} + +/* + * Fill the array mpc83xx_ipic_prio2mask to allow masking of lower prio sources + * to implement nested interrupts. + */ +static rtems_status_code mpc83xx_ipic_calc_prio2mask(void) +{ + rtems_status_code rc = RTEMS_SUCCESSFUL; + + /* + * FIXME: fill the array + */ + return rc; +} + +/* + * Activate the interrupt controller + */ +static rtems_status_code mpc83xx_ipic_initialize(void) +{ + /* + * mask off all interrupts + */ + mpc83xx.ipic.simsr [0] = 0; + mpc83xx.ipic.simsr [1] = 0; + mpc83xx.ipic.semsr = 0; + mpc83xx.ipic.sermr = 0; + /* + * set desired configuration as defined in bspopts.h + * normally, the default values should be fine + */ +#if defined( BSP_SICFR_VAL) /* defined in bspopts.h ? */ + mpc83xx.ipic.sicfr = BSP_SICFR_VAL; +#endif + + /* + * set desired priorities as defined in bspopts.h + * normally, the default values should be fine + */ +#if defined( BSP_SIPRR0_VAL) /* defined in bspopts.h ? */ + mpc83xx.ipic.siprr [0] = BSP_SIPRR0_VAL; +#endif + +#if defined( BSP_SIPRR1_VAL) /* defined in bspopts.h ? */ + mpc83xx.ipic.siprr [1] = BSP_SIPRR1_VAL; +#endif + +#if defined( BSP_SIPRR2_VAL) /* defined in bspopts.h ? */ + mpc83xx.ipic.siprr [2] = BSP_SIPRR2_VAL; +#endif + +#if defined( BSP_SIPRR3_VAL) /* defined in bspopts.h ? */ + mpc83xx.ipic.siprr [3] = BSP_SIPRR3_VAL; +#endif + +#if defined( BSP_SMPRR0_VAL) /* defined in bspopts.h ? */ + mpc83xx.ipic.smprr [0] = BSP_SMPRR0_VAL; +#endif + +#if defined( BSP_SMPRR1_VAL) /* defined in bspopts.h ? */ + mpc83xx.ipic.smprr [1] = BSP_SMPRR1_VAL; +#endif + +#if defined( BSP_SECNR_VAL) /* defined in bspopts.h ? */ + mpc83xx.ipic.secnr = BSP_SECNR_VAL; +#endif + + /* + * calculate priority masks + */ + return mpc83xx_ipic_calc_prio2mask(); +} + +static int mpc83xx_exception_handler( + BSP_Exception_frame *frame, + unsigned exception_number +) +{ + return BSP_irq_handle_at_ipic( exception_number); +} + +rtems_status_code bsp_interrupt_facility_initialize() +{ + /* Install exception handler */ + if (ppc_exc_set_handler( ASM_EXT_VECTOR, mpc83xx_exception_handler)) { + return RTEMS_IO_ERROR; + } + if (ppc_exc_set_handler( ASM_E300_SYSMGMT_VECTOR, mpc83xx_exception_handler)) { + return RTEMS_IO_ERROR; + } + if (ppc_exc_set_handler( ASM_E300_CRIT_VECTOR, mpc83xx_exception_handler)) { + return RTEMS_IO_ERROR; + } + + /* Initialize the interrupt controller */ + return mpc83xx_ipic_initialize(); +} diff --git a/bsps/powerpc/haleakala/irq/irq.c b/bsps/powerpc/haleakala/irq/irq.c new file mode 100644 index 0000000000..c9607a032d --- /dev/null +++ b/bsps/powerpc/haleakala/irq/irq.c @@ -0,0 +1,237 @@ +/* + * + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.org/license/LICENSE. + * + * Middleware support for PPC405 by M.Hamel ADInstruments Ltd 2008 + */ + +#include +#include +#include +#include +#include +#include + + +/* PPC405EX UIC numbers */ +#define UIC_DCR_BASE 0xc0 +#define UIC0_SR (UIC_DCR_BASE+0x0) /* UIC status */ +#define UIC0_SRS (UIC_DCR_BASE+0x1) /* UIC status set */ +#define UIC0_ER (UIC_DCR_BASE+0x2) /* UIC enable */ +#define UIC0_CR (UIC_DCR_BASE+0x3) /* UIC critical */ +#define UIC0_PR (UIC_DCR_BASE+0x4) /* UIC polarity */ +#define UIC0_TR (UIC_DCR_BASE+0x5) /* UIC triggering */ +#define UIC0_MSR (UIC_DCR_BASE+0x6) /* UIC masked status */ +#define UIC0_VR (UIC_DCR_BASE+0x7) /* UIC vector */ +#define UIC0_VCR (UIC_DCR_BASE+0x8) /* UIC vector configuration */ + +#define UIC1_SR (UIC_DCR_BASE+0x10) /* UIC status */ +#define UIC1_SRS (UIC_DCR_BASE+0x11) /* UIC status set */ +#define UIC1_ER (UIC_DCR_BASE+0x12) /* UIC enable */ +#define UIC1_CR (UIC_DCR_BASE+0x13) /* UIC critical */ +#define UIC1_PR (UIC_DCR_BASE+0x14) /* UIC polarity */ +#define UIC1_TR (UIC_DCR_BASE+0x15) /* UIC triggering */ +#define UIC1_MSR (UIC_DCR_BASE+0x16) /* UIC masked status */ +#define UIC1_VR (UIC_DCR_BASE+0x17) /* UIC vector */ +#define UIC1_VCR (UIC_DCR_BASE+0x18) /* UIC vector configuration */ + +#define UIC2_SR (UIC_DCR_BASE+0x20) /* UIC status */ +#define UIC2_SRS (UIC_DCR_BASE+0x21) /* UIC status set */ +#define UIC2_ER (UIC_DCR_BASE+0x22) /* UIC enable */ +#define UIC2_CR (UIC_DCR_BASE+0x23) /* UIC critical */ +#define UIC2_PR (UIC_DCR_BASE+0x24) /* UIC polarity */ +#define UIC2_TR (UIC_DCR_BASE+0x25) /* UIC triggering */ +#define UIC2_MSR (UIC_DCR_BASE+0x26) /* UIC masked status */ +#define UIC2_VR (UIC_DCR_BASE+0x27) /* UIC vector */ +#define UIC2_VCR (UIC_DCR_BASE+0x28) /* UIC vector configuration */ + +enum { kUICWords = 3 }; + +static rtems_irq_connect_data* rtems_hdl_tblP; +static rtems_irq_connect_data dflt_entry; + +static uint32_t gEnabledInts[kUICWords]; /* 1-bits mean enabled */ +static uint32_t gIntInhibited[kUICWords]; /* 1-bits disable, overriding gEnabledInts because the interrupt + is being processed in C_dispatch_irq_handler */ + +static inline int IsUICIRQ(const rtems_irq_number irqLine) +{ + return (((int) irqLine <= BSP_UIC_IRQ_MAX_OFFSET) && + ((int) irqLine >= BSP_UIC_IRQ_LOWEST_OFFSET) + ); +} + +static void WriteIState(void) +/* Write the gEnabledInts state masked by gIntInhibited to the hardware */ +{ + PPC_SET_DEVICE_CONTROL_REGISTER(UIC0_ER, + gEnabledInts[0] & ~gIntInhibited[0]); + PPC_SET_DEVICE_CONTROL_REGISTER(UIC1_ER, + gEnabledInts[1] & ~gIntInhibited[1]); + PPC_SET_DEVICE_CONTROL_REGISTER(UIC2_ER, + gEnabledInts[2] & ~gIntInhibited[2]); +} + +void +BSP_enable_irq_at_pic(const rtems_irq_number irq) +/* Enable an interrupt; this can be called from inside C_dispatch_irq_handler */ +{ + if (IsUICIRQ(irq)) { + /* Set relevant bit in the state, write state to the UIC */ + gEnabledInts[irq>>5] |= (0x80000000 >> (irq & 0x1F)); + WriteIState(); + } +} + +int +BSP_disable_irq_at_pic(const rtems_irq_number irq) +/* Enable an interrupt; this can be called from inside C_dispatch_irq_handler */ +{ + if (IsUICIRQ(irq)) { + uint32_t oldState; + int iword = irq>>5; + uint32_t mask = (0x80000000 >> (irq & 0x1F)); + + oldState = gEnabledInts[iword] & mask; + gEnabledInts[iword] &= ~mask; + WriteIState(); + return oldState ? 1 : 0; + } else + return -1; +} + +int +BSP_setup_the_pic(rtems_irq_global_settings* config) +{ + int i; + + dflt_entry = config->defaultEntry; + rtems_hdl_tblP = config->irqHdlTbl; + for (i=0; i> bit; + switch (index) { + case 0: + PPC_SET_DEVICE_CONTROL_REGISTER(UIC0_SR, bmask); + break; + case 1: + PPC_SET_DEVICE_CONTROL_REGISTER(UIC1_SR, bmask); + break; + case 2: + PPC_SET_DEVICE_CONTROL_REGISTER(UIC2_SR, bmask); + break; + } + + /* Clear in the active record and gIntInhibited */ + active[index] &= ~bmask; + gIntInhibited[index] &= ~bmask; + }; + + /* Update the hardware again so the interrupts we have handled are unmasked */ + WriteIState(); + return 0; + + } else if (excNum == ASM_DEC_VECTOR) { /* 0x1000 remapped by C_dispatch_dec_handler_bookE */ + bsp_irq_dispatch_list(rtems_hdl_tblP, BSP_PIT, dflt_entry.hdl); + return 0; + + } else if (excNum == ASM_BOOKE_FIT_VECTOR) { /* 0x1010 mapped to 0x13 by ppc_get_vector_addr */ + bsp_irq_dispatch_list(rtems_hdl_tblP, BSP_FIT, dflt_entry.hdl); + return 0; + + } else if (excNum == ASM_BOOKE_WDOG_VECTOR) { /* 0x1020 mapped to 0x14 by ppc_get_vector_addr */ + bsp_irq_dispatch_list(rtems_hdl_tblP, BSP_WDOG, dflt_entry.hdl); + return 0; + + } else + return -1; /* unhandled interrupt, panic time */ +} + diff --git a/bsps/powerpc/haleakala/irq/irq_init.c b/bsps/powerpc/haleakala/irq/irq_init.c new file mode 100644 index 0000000000..d48855a979 --- /dev/null +++ b/bsps/powerpc/haleakala/irq/irq_init.c @@ -0,0 +1,96 @@ +/*===============================================================*\ +| Project: RTEMS Haleakala BSP | +| * by Michael Hamel ADInstruments Ltd 2008 | ++-----------------------------------------------------------------+ +| The license and distribution terms for this file may be | +| found in the file LICENSE in this distribution or at | +| | +| http://www.rtems.org/license/LICENSE. | +| | ++-----------------------------------------------------------------+ +| this file contains the irq controller handler | +\*===============================================================*/ +#include +#include +#include +#include +#include +#include + + +/* + * default on/off function + */ +static void nop_func(void) +{ +} + +/* + * default isOn function + */ +static int not_connected(void) +{ + return 0; +} + +static rtems_irq_connect_data rtemsIrq[BSP_IRQ_NUMBER]; +static rtems_irq_global_settings initial_config; +static rtems_irq_connect_data defaultIrq = { + .name = 0, + .hdl = NULL, + .handle = NULL, + .on = (rtems_irq_enable) nop_func, + .off = (rtems_irq_disable) nop_func, + .isOn = (rtems_irq_is_enabled) not_connected, +#ifdef BSP_SHARED_HANDLER_SUPPORT + .next_handler = NULL +#endif +}; + +static rtems_irq_prio irqPrioTable[BSP_IRQ_NUMBER]={ + /* + * Processor exceptions handled as interrupts + */ + 0 +}; + + /* + * This code assumes the exceptions management setup has already + * been done. We just need to replace the exceptions that will + * be handled like interrupt. On mcp750/mpc750 and many PPC processors + * this means the decrementer exception and the external exception. + */ + +void BSP_rtems_irq_mng_init(unsigned cpuId) +{ + int i; + + /* + * re-init the rtemsIrq table + */ + for (i = 0; i < BSP_IRQ_NUMBER; i++) { + rtemsIrq[i] = defaultIrq; + rtemsIrq[i].name = i; + } + /* + * Init initial Interrupt management config + */ + initial_config.irqNb = BSP_IRQ_NUMBER; + initial_config.defaultEntry = defaultIrq; + initial_config.irqHdlTbl = rtemsIrq; + initial_config.irqBase = BSP_LOWEST_OFFSET; + initial_config.irqPrioTbl = irqPrioTable; + + if (!BSP_rtems_irq_mngt_set(&initial_config)) { + /* + * put something here that will show the failure... + */ + rtems_panic( + "Unable to initialize RTEMS interrupt management!!! System locked\n" + ); + } + + #ifdef TRACE_IRQ_INIT + printk("RTEMS IRQ management is now operational\n"); + #endif +} diff --git a/bsps/powerpc/mpc8260ads/irq/irq.c b/bsps/powerpc/mpc8260ads/irq/irq.c new file mode 100644 index 0000000000..baca1e0e05 --- /dev/null +++ b/bsps/powerpc/mpc8260ads/irq/irq.c @@ -0,0 +1,372 @@ +/* + * + * This file contains the implementation of the function described in irq.h + * + * Copyright (C) 1998, 1999 valette@crf.canon.fr + * + * Modified for mpc8260 Andy Dachs + * Surrey Satellite Technology Limited, 2000 + * 21/4/2002 Added support for nested interrupts and improved + * masking operations. Now we compute priority mask based + * on table in irq_init.c + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.org/license/LICENSE. + */ + +#include +#include +#include +#include +#include +#include +#include + +/* + * Check if symbolic IRQ name is an CPM IRQ + */ +static inline int is_cpm_irq(const rtems_irq_number irqLine) +{ + return (((int) irqLine <= BSP_CPM_IRQ_MAX_OFFSET) & + ((int) irqLine >= BSP_CPM_IRQ_LOWEST_OFFSET) + ); +} + +typedef struct { + uint32_t mask_h; /* mask for sipnr_h and simr_h */ + uint32_t mask_l; /* mask for sipnr_l and simr_l */ + uint32_t priority_h; /* mask this and lower priority ints */ + uint32_t priority_l; +} m82xxIrqMasks_t; + +static unsigned char irqPrioTable[BSP_CPM_IRQ_NUMBER]={ + /* + * actual priorities for interrupt : + */ + /* + * CPM Interrupts + */ + 0, 45, 63, 44, 66, 68, 35, 39, 50, 62, 34, 0, 30, 40, 52, 58, + 2, 3, 0, 5, 15, 16, 17, 18, 49, 51, 0, 0, 0, 0, 0, 0, + 6, 7, 8, 0, 11, 12, 0, 0, 20, 21, 22, 23, 0, 0, 0, 0, + 29, 31, 33, 37, 38, 41, 47, 48, 55, 56, 57, 60, 64, 65, 69, 70, + +}; + +/* + * Mask fields should have a '1' in the bit position for that + * interrupt. + * Priority masks calculated later based on priority table + */ + +static m82xxIrqMasks_t SIU_MaskBit[BSP_CPM_IRQ_NUMBER] = +{ + { 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, /* err */ + { 0x00000000, 0x00008000, 0x00000000, 0x00000000 }, /* i2c */ + { 0x00000000, 0x00004000, 0x00000000, 0x00000000 }, /* spi */ + { 0x00000000, 0x00002000, 0x00000000, 0x00000000 }, /* rtt */ + { 0x00000000, 0x00001000, 0x00000000, 0x00000000 }, /* smc1 */ + { 0x00000000, 0x00000800, 0x00000000, 0x00000000 }, /* smc2 */ + { 0x00000000, 0x00000400, 0x00000000, 0x00000000 }, /* idma1 */ + { 0x00000000, 0x00000200, 0x00000000, 0x00000000 }, /* idma2 */ + { 0x00000000, 0x00000100, 0x00000000, 0x00000000 }, /* idma3 */ + { 0x00000000, 0x00000080, 0x00000000, 0x00000000 }, /* idma4 */ + { 0x00000000, 0x00000040, 0x00000000, 0x00000000 }, /* sdma */ + { 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, /* reserved */ + { 0x00000000, 0x00000010, 0x00000000, 0x00000000 }, /* tmr1 */ + { 0x00000000, 0x00000008, 0x00000000, 0x00000000 }, /* tmr2 */ + { 0x00000000, 0x00000004, 0x00000000, 0x00000000 }, /* tmr3 */ + { 0x00000000, 0x00000002, 0x00000000, 0x00000000 }, /* tmr4 */ + { 0x00000004, 0x00000000, 0x00000000, 0x00000000 }, /* tmcnt */ + { 0x00000002, 0x00000000, 0x00000000, 0x00000000 }, /* pit */ + { 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, /* reserved */ + { 0x00004000, 0x00000000, 0x00000000, 0x00000000 }, /* irq1 */ + { 0x00002000, 0x00000000, 0x00000000, 0x00000000 }, /* irq2 */ + { 0x00001000, 0x00000000, 0x00000000, 0x00000000 }, /* irq3 */ + { 0x00000800, 0x00000000, 0x00000000, 0x00000000 }, /* irq4 */ + { 0x00000400, 0x00000000, 0x00000000, 0x00000000 }, /* irq5 */ + { 0x00000200, 0x00000000, 0x00000000, 0x00000000 }, /* irq6 */ + { 0x00000100, 0x00000000, 0x00000000, 0x00000000 }, /* irq7 */ + { 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, /* reserved */ + { 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, /* reserved */ + { 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, /* reserved */ + { 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, /* reserved */ + { 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, /* reserved */ + { 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, /* reserved */ + { 0x00000000, 0x80000000, 0x00000000, 0x00000000 }, /* fcc1 */ + { 0x00000000, 0x40000000, 0x00000000, 0x00000000 }, /* fcc2 */ + { 0x00000000, 0x20000000, 0x00000000, 0x00000000 }, /* fcc3 */ + { 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, /* reserved */ + { 0x00000000, 0x08000000, 0x00000000, 0x00000000 }, /* mcc1 */ + { 0x00000000, 0x04000000, 0x00000000, 0x00000000 }, /* mcc2 */ + { 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, /* reserved */ + { 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, /* reserved */ + { 0x00000000, 0x00800000, 0x00000000, 0x00000000 }, /* scc1 */ + { 0x00000000, 0x00400000, 0x00000000, 0x00000000 }, /* scc2 */ + { 0x00000000, 0x00200000, 0x00000000, 0x00000000 }, /* scc3 */ + { 0x00000000, 0x00100000, 0x00000000, 0x00000000 }, /* scc4 */ + { 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, /* reserved */ + { 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, /* reserved */ + { 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, /* reserved */ + { 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, /* reserved */ + { 0x00010000, 0x00000000, 0x00000000, 0x00000000 }, /* pc15 */ + { 0x00020000, 0x00000000, 0x00000000, 0x00000000 }, /* pc14 */ + { 0x00040000, 0x00000000, 0x00000000, 0x00000000 }, /* pc13 */ + { 0x00080000, 0x00000000, 0x00000000, 0x00000000 }, /* pc12 */ + { 0x00100000, 0x00000000, 0x00000000, 0x00000000 }, /* pc11 */ + { 0x00200000, 0x00000000, 0x00000000, 0x00000000 }, /* pc10 */ + { 0x00400000, 0x00000000, 0x00000000, 0x00000000 }, /* pc9 */ + { 0x00800000, 0x00000000, 0x00000000, 0x00000000 }, /* pc8 */ + { 0x01000000, 0x00000000, 0x00000000, 0x00000000 }, /* pc7 */ + { 0x02000000, 0x00000000, 0x00000000, 0x00000000 }, /* pc6 */ + { 0x04000000, 0x00000000, 0x00000000, 0x00000000 }, /* pc5 */ + { 0x08000000, 0x00000000, 0x00000000, 0x00000000 }, /* pc4 */ + { 0x10000000, 0x00000000, 0x00000000, 0x00000000 }, /* pc3 */ + { 0x20000000, 0x00000000, 0x00000000, 0x00000000 }, /* pc2 */ + { 0x40000000, 0x00000000, 0x00000000, 0x00000000 }, /* pc1 */ + { 0x80000000, 0x00000000, 0x00000000, 0x00000000 }, /* pc0 */ + +}; + +/* + * ------------------------ RTEMS Irq helper functions ---------------- + */ + +/* + * Caution : this function assumes the variable "internal_config" + * is already set and that the tables it contains are still valid + * and accessible. + */ +static void compute_SIU_IvectMask_from_prio (void) +{ + /* + * The actual masks defined + * correspond to the priorities defined + * for the SIU in irq_init.c. + */ + + int i,j; + + for( i=0; i maxLoop) maxLoop = loopCounter; +#endif + break; + } + + irq = (m8260.sivec >> 26) + BSP_CPM_IRQ_LOWEST_OFFSET; + + /* Clear mask and pending register */ + if( irq <= BSP_CPM_IRQ_MAX_OFFSET ) { + /* save interrupt masks */ + old_simr_h = m8260.simr_h; + old_simr_l = m8260.simr_l; + + /* mask off current interrupt and lower priority ones */ + m8260.simr_h &= SIU_MaskBit[irq].priority_h; + m8260.simr_l &= SIU_MaskBit[irq].priority_l; + + /* clear pending bit */ + m8260.sipnr_h |= SIU_MaskBit[irq].mask_h; + m8260.sipnr_l |= SIU_MaskBit[irq].mask_l; + + /* + * make sure, that the masking operations in + * ICTL and MSR are executed in order + */ + __asm__ volatile("sync":::"memory"); + + /* re-enable external exceptions */ + _CPU_MSR_GET(msr); + new_msr = msr | MSR_EE; + _CPU_MSR_SET(new_msr); + + /* call handler */ + bsp_interrupt_handler_dispatch(irq); + + /* disable exceptions again */ + _CPU_MSR_SET(msr); + + /* + * make sure, that the masking operations in + * ICTL and MSR are executed in order + */ + __asm__ volatile("sync":::"memory"); + + /* restore interrupt masks */ + m8260.simr_h = old_simr_h; + m8260.simr_l = old_simr_l; + + } +#ifdef DISPATCH_HANDLER_STAT + ++ loopCounter; +#endif + } + return 0; +} + +/* + * Initialize CPM interrupt management + */ +static void +BSP_CPM_irq_init(void) +{ + m8260.simr_l = 0; + m8260.simr_h = 0; + m8260.sipnr_l = 0xffffffff; + m8260.sipnr_h = 0xffffffff; + m8260.sicr = 0; + + /* + * Initialize the interrupt priorities. + */ + m8260.siprr = 0x05309770; /* reset value */ + m8260.scprr_h = 0x05309770; /* reset value */ + m8260.scprr_l = 0x05309770; /* reset value */ + +} + +void bsp_interrupt_vector_enable( rtems_vector_number irqnum) +{ + bsp_interrupt_assert(bsp_interrupt_is_valid_vector(irqnum)); + + if (is_cpm_irq(irqnum)) { + /* + * Enable interrupt at PIC level + */ + BSP_irq_enable_at_cpm (irqnum); + } +} + +void bsp_interrupt_vector_disable( rtems_vector_number irqnum) +{ + bsp_interrupt_assert(bsp_interrupt_is_valid_vector(irqnum)); + + if (is_cpm_irq(irqnum)) { + /* + * disable interrupt at PIC level + */ + BSP_irq_disable_at_cpm (irqnum); + } +} + +rtems_status_code bsp_interrupt_facility_initialize() +{ + /* Install exception handler */ + if (ppc_exc_set_handler( ASM_EXT_VECTOR, C_dispatch_irq_handler)) { + return RTEMS_IO_ERROR; + } + if (ppc_exc_set_handler( ASM_DEC_VECTOR, C_dispatch_irq_handler)) { + return RTEMS_IO_ERROR; + } + + /* Fill in priority masks */ + compute_SIU_IvectMask_from_prio(); + + /* Initialize the interrupt controller */ + BSP_CPM_irq_init(); + + return RTEMS_SUCCESSFUL; +} diff --git a/bsps/powerpc/mvme3100/irq/irq_init.c b/bsps/powerpc/mvme3100/irq/irq_init.c new file mode 100644 index 0000000000..c40692e688 --- /dev/null +++ b/bsps/powerpc/mvme3100/irq/irq_init.c @@ -0,0 +1,138 @@ +/* irq_init.c + * + * This file contains the implementation of rtems initialization + * related to interrupt handling. + * + * CopyRight (C) 1999 valette@crf.canon.fr + * + * Enhanced by Jay Kulpinski + * to make it valid for MVME2300 Motorola boards. + * + * Till Straumann , 12/20/2001: + * Use the new interface to openpic_init + * + * Adapted for the mvme3100 BSP by T. Straumann, 2007. + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.org/license/LICENSE. + */ + +#include +#include +#include +#include +#include +#include +#include + +static void nop_func(void *unused) +{ + printk("Unhandled IRQ\n"); +} + +static rtems_irq_connect_data rtemsIrq[BSP_IRQ_NUMBER]; +static rtems_irq_global_settings initial_config; +static rtems_irq_connect_data defaultIrq = { + /* vectorIdex, hdl , handle , on , off , isOn */ + 0, nop_func , NULL , 0 , 0 , 0 +}; + +static rtems_irq_prio irqPrioTable[BSP_IRQ_NUMBER]={ + /* + * actual priorities for interrupt : + * 0 means that only current interrupt is masked + * 255 means all other interrupts are masked + */ + /* + * PCI Interrupts + */ + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, /* for raven prio 0 means unactive... */ + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, /* for raven prio 0 means unactive... */ + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, /* for raven prio 0 means unactive... */ + /* + * Processor exceptions handled as interrupts + */ + 0 +}; + + /* + * This code assumes the exceptions management setup has already + * been done. We just need to replace the exceptions that will + * be handled like interrupt. On mcp750/mpc750 and many PPC processors + * this means the decrementer exception and the external exception. + */ +void BSP_rtems_irq_mng_init(unsigned cpuId) +{ + /* We should really have a way to find the number of sources + * the driver will use so that the size of the polarity-array + * matches the driver's idea of it. + */ + unsigned char pol[56]; + int i; + + /* Note: The openpic driver initializes only as many + * 'pic-external' interrupt sources as reported + * by the feature register. + * The 8540's openpic supports 12 core-external + * and 23 core-internal (both of these groups + * are external to the PIC, i.e., 'pic-external') + * interrupts but between the corresponding + * banks of vector/priority registers there is + * a gap leaving space for 4 (unsupported) irqs. + * The driver, not knowing of this gap, would + * initialize the 12 core-external sources + * followed by 4 unsupported sources and 19 + * core-internal sources thus leaving the last + * four core-internal sources uninitialized. + * Luckily, the feature register reports + * too many sources: + * - the 4 IPI plus 4 timer plus 4 messaging + * sources are included with the count + * - there are unused core-internal sources 24..32 + * which are also supported by the pic + * bringing the reported number of sources to + * a count of 56 (12+32+4+4+4) which is enough + * so that all pic-external sources are covered + * and initialized. + * + * NOTE: All core-internal sources are active-high. + * The manual says that setting the polarity + * to 'low/0' will disable the interrupt but + * I found this not to be true: on the device + * I tested the interrupt was asserted hard. + */ + + /* core-external sources on the mvme3100 are active-low, + * core-internal sources are active high. + */ + for (i=0; i, Sept. 2, 2007 + +As per implementation in shared PPC code, +the BSPirqPrioTable[96] listed in irq_init.c is where the +software developers can change the levels of priority +for all the interrupts based on the need of their +applications. The IRQs can be eanbled dynamically via the +BSP_enable_pic_irq(), or disbaled dynamically via the +BSP_disable_pic_irq(). + + +Support for run-time priority setup could be +added easily, but there is no action taken yet due to concerns +over computer security at VME CPU level. + + +The software developers are forbidden to setup picIsrTable[], +as it is a powerful engine for the BSP to find the pending +highest priority IRQ at run time. It ensures the fastest/faster +interrupt service to the highest/higher priority IRQ, if pending. diff --git a/bsps/powerpc/mvme5500/irq/BSP_irq.c b/bsps/powerpc/mvme5500/irq/BSP_irq.c new file mode 100644 index 0000000000..eb36cc2a80 --- /dev/null +++ b/bsps/powerpc/mvme5500/irq/BSP_irq.c @@ -0,0 +1,483 @@ +/* + * This file contains the implementation of the function described in irq.h + */ + +/* + * Copyright (C) 1998, 1999 valette@crf.canon.fr + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.OARcorp.com/rtems/license.html. + * + * Acknowledgement May 2004, to Till Straumann + * for some inputs. + * + * Copyright 2003, 2004, 2005, 2007 Shuchen Kate Feng , + * NSLS, Brookhaven National Laboratory. All rights reserved. + * + * 1) Used GT_GPP_Value register instead of the GT_GPP_Interrupt_Cause + * register to monitor the cause of the level sensitive interrupts. + * (Copyright : NDA item) + * 2) The implementation of picPrioTable[] is an original work by the + * author to optimize the software IRQ priority scheduling because + * Discovery controller does not provide H/W IRQ priority schedule. + * It ensures the fastest/faster interrupt service to the + * highest/higher priority IRQ, if pendig. + * 3) _CPU_MSR_SET() needs RTEMS_COMPILER_MEMORY_BARRIER() + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include /* for printk */ +#include "bsp/gtreg.h" + +#define HI_INT_CAUSE 0x40000000 + +#define MAX_IRQ_LOOP 20 + +/* #define DEBUG_IRQ*/ + +/* + * pointer to the mask representing the additionnal irq vectors + * that must be disabled when a particular entry is activated. + * They will be dynamically computed from the table given + * in BSP_rtems_irq_mngt_set(); + * CAUTION : this table is accessed directly by interrupt routine + * prologue. + */ +static unsigned int BSP_irq_prio_mask_tbl[3][BSP_PIC_IRQ_NUMBER]; + +/* + * location used to store initial tables used for interrupt + * management.BSP copy of the configuration + */ +static rtems_irq_global_settings BSP_config; +static rtems_irq_connect_data* rtems_hdl_tbl; + +/* + * default handler connected on each irq after bsp initialization + * (locally cached copy) + */ +void (*default_rtems_hdl)(rtems_irq_hdl_param) = (void(*)(rtems_irq_hdl_param)) -1; + + +static volatile unsigned *BSP_irqMask_reg[3]; +static volatile unsigned *BSP_irqCause_reg[3]; +static volatile unsigned BSP_irqMask_cache[3]={0,0,0}; + +static int picPrioTblPtr=0; +static unsigned int GPPIrqInTbl=0; +static unsigned long long MainIrqInTbl=0; + +/* + * The software developers are forbidden to setup picPrioTable[], + * as it is a powerful engine for the BSP to find the pending + * highest priority IRQ at run time. It ensures the fastest/faster + * interrupt service to the highest/higher priority IRQ, if pendig. + * + * The picPrioTable[96] is updated dynamically at run time + * based on the priority levels set at BSPirqPrioTable[96], + * while the BSP_enable_irq_at_pic(), and BSP_disable_irq_at_pic() + * commands are invoked. + * + * The picPrioTable[96] lists the enabled CPU main and GPP external interrupt + * numbers [0 (lowest)- 95 (highest)] starting from the highest priority + * one to the lowest priority one. The highest priority interrupt is + * located at picPrioTable[0], and the lowest priority interrupt is located + * at picPrioTable[picPrioTblPtr-1]. + * + * + */ +#define DynamicIsrTable +#ifdef DynamicIsrTable +/* BitNums for Main Interrupt Lo/High Cause, -1 means invalid bit */ +static unsigned int picPrioTable[BSP_PIC_IRQ_NUMBER]={ + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1 }; +#else +static unsigned int picPrioTable[BSP_PIC_IRQ_NUMBER]={ + 80, 84, 76, 77, 32, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1 }; +#endif + +/* + * Check if IRQ is a MAIN CPU internal IRQ or GPP external IRQ + */ +static inline int is_pic_irq(const rtems_irq_number irqLine) +{ + return (((int) irqLine <= BSP_GPP_IRQ_MAX_OFFSET) & + ((int) irqLine >= BSP_MICL_IRQ_LOWEST_OFFSET) + ); +} + +/* + * Check if IRQ is a Porcessor IRQ + */ +static inline int is_processor_irq(const rtems_irq_number irqLine) +{ + return (((int) irqLine <= BSP_PROCESSOR_IRQ_MAX_OFFSET) & + ((int) irqLine >= BSP_PROCESSOR_IRQ_LOWEST_OFFSET) + ); +} + +/* + * ------------------------ RTEMS Irq helper functions ---------------- + */ + +/* + * Caution : this function assumes the variable "BSP_config" + * is already set and that the tables it contains are still valid + * and accessible. + */ +static void compute_pic_masks_from_prio(void) +{ + int i,j, k, isGppMain; + unsigned long long irq_prio_mask=0; + + /* + * Always mask at least current interrupt to prevent re-entrance + */ + for (i=0; i a equal priority. + */ + if (BSP_config.irqPrioTbl [i] >= BSP_config.irqPrioTbl [j]) + irq_prio_mask |= (unsigned long long)(1LLU << j); + } + + + BSP_irq_prio_mask_tbl[0][i] = irq_prio_mask & 0xffffffff; + BSP_irq_prio_mask_tbl[1][i] = (irq_prio_mask>>32) & 0xffffffff; +#if 0 + printk("irq_mask_prio_tbl[%d]:0x%8x%8x\n",i,BSP_irq_prio_mask_tbl[1][i], + BSP_irq_prio_mask_tbl[0][i]); +#endif + + BSP_irq_prio_mask_tbl[2][i] = 1<= BSP_config.irqPrioTbl [j]) + BSP_irq_prio_mask_tbl[2][i] |= 1 << (j-BSP_GPP_IRQ_LOWEST_OFFSET); + } +#if 0 + printk("GPPirq_mask_prio_tbl[%d]:0x%8x\n",i,BSP_irq_prio_mask_tbl[2][i]); +#endif + } +} + +static void UpdateMainIrqTbl(int irqNum) +{ + int i=0, j, shifted=0; + + switch (irqNum) { + case BSP_MAIN_GPP7_0_IRQ: + case BSP_MAIN_GPP15_8_IRQ: + case BSP_MAIN_GPP23_16_IRQ: + case BSP_MAIN_GPP31_24_IRQ: + return; /* Do nothing, let GPP take care of it */ + break; + } +#ifdef SHOW_MORE_INIT_SETTINGS + unsigned long val2, val1; +#endif + + /* If entry not in table*/ + if ( ((irqNumBSP_MICH_IRQ_MAX_OFFSET) && + (!(( 1 << (irqNum-BSP_GPP_IRQ_LOWEST_OFFSET)) & GPPIrqInTbl)))) + { + while ( picPrioTable[i]!=-1) { + if (BSP_config.irqPrioTbl[irqNum]>BSP_config.irqPrioTbl[picPrioTable[i]]) { + /* all other lower priority entries shifted right */ + for (j=picPrioTblPtr;j>i; j--) { + picPrioTable[j]=picPrioTable[j-1]; + } + picPrioTable[i]=irqNum; + shifted=1; + break; + } + i++; + } + if (!shifted) picPrioTable[picPrioTblPtr] =irqNum; + + if (irqNum >BSP_MICH_IRQ_MAX_OFFSET) + GPPIrqInTbl |= (1<< (irqNum-BSP_GPP_IRQ_LOWEST_OFFSET)); + else + MainIrqInTbl |= (unsigned long long)(1LLU << irqNum); + picPrioTblPtr++; + } +#ifdef SHOW_MORE_INIT_SETTINGS + val2 = (MainIrqInTbl>>32) & 0xffffffff; + val1 = MainIrqInTbl&0xffffffff; + printk("irqNum %d, MainIrqInTbl 0x%x%x\n", irqNum, val2, val1); + BSP_printPicIsrTbl(); +#endif + +} + + +static void CleanMainIrqTbl(int irqNum) +{ + int i, j; + + switch (irqNum) { + case BSP_MAIN_GPP7_0_IRQ: + case BSP_MAIN_GPP15_8_IRQ: + case BSP_MAIN_GPP23_16_IRQ: + case BSP_MAIN_GPP31_24_IRQ: + return; /* Do nothing, let GPP take care of it */ + break; + } + if ( ((irqNumBSP_MICH_IRQ_MAX_OFFSET) && + (( 1 << (irqNum-BSP_GPP_IRQ_LOWEST_OFFSET)) & GPPIrqInTbl))) + { /* If entry in table*/ + for (i=0; i<64; i++) { + if (picPrioTable[i]==irqNum) {/*remove it from the entry */ + /* all other lower priority entries shifted left */ + for (j=i;jBSP_MICH_IRQ_MAX_OFFSET) + GPPIrqInTbl &= ~(1<< (irqNum-BSP_GPP_IRQ_LOWEST_OFFSET)); + else + MainIrqInTbl &= ~(1LLU << irqNum); + picPrioTblPtr--; + break; + } + } + } +} + +void BSP_enable_irq_at_pic(const rtems_irq_number irqNum) +{ + unsigned bitNum, regNum; + unsigned int level; + + if ( !is_pic_irq(irqNum) ) + return; + + bitNum = (((unsigned int)irqNum) - BSP_MICL_IRQ_LOWEST_OFFSET)%32; + regNum = (((unsigned int)irqNum) - BSP_MICL_IRQ_LOWEST_OFFSET)>>5; + + rtems_interrupt_disable(level); + +#ifdef DynamicIsrTable + UpdateMainIrqTbl((int) irqNum); +#endif + BSP_irqMask_cache[regNum] |= (1 << bitNum); + + out_le32((volatile uint32_t *)BSP_irqMask_reg[regNum], BSP_irqMask_cache[regNum]); + while (in_le32((volatile uint32_t *)BSP_irqMask_reg[regNum]) != BSP_irqMask_cache[regNum]); + + rtems_interrupt_enable(level); +} + +int BSP_disable_irq_at_pic(const rtems_irq_number irqNum) +{ + int rval; + unsigned bitNum, regNum; + unsigned int level; + + if ( ! is_pic_irq(irqNum) ) + return -1; + + bitNum = (((unsigned int)irqNum) - BSP_MICL_IRQ_LOWEST_OFFSET)%32; + regNum = (((unsigned int)irqNum) - BSP_MICL_IRQ_LOWEST_OFFSET)>>5; + + rtems_interrupt_disable(level); + +#ifdef DynamicIsrTable + CleanMainIrqTbl((int) irqNum); +#endif + + rval = BSP_irqMask_cache[regNum] & (1<defaultEntry.hdl; + rtems_hdl_tbl = config->irqHdlTbl; + + /* Get ready for discovery BSP */ + BSP_irqMask_reg[0]= (volatile unsigned int *) (GT64x60_REG_BASE + GT64260_CPU_INT_MASK_LO); + BSP_irqMask_reg[1]= (volatile unsigned int *) (GT64x60_REG_BASE + GT64260_CPU_INT_MASK_HI); + BSP_irqCause_reg[0]= (volatile unsigned int *) (GT64x60_REG_BASE + GT64260_MAIN_INT_CAUSE_LO); + BSP_irqCause_reg[1]= (volatile unsigned int *) (GT64x60_REG_BASE + GT64260_MAIN_INT_CAUSE_HI); + BSP_irqMask_reg[2]= (volatile unsigned int *) (GT64x60_REG_BASE + GT_GPP_Interrupt_Mask); + BSP_irqCause_reg[2]= (volatile unsigned int *) (GT64x60_REG_BASE + GT_GPP_Value); + + /* Page 401, Table 598: + * Comm Unit Arbiter Control register : + * bit 10:GPP interrupts as level sensitive(1) or edge sensitive(0). + * MOTload default is set as level sensitive(1). Set it agin to make sure. + */ + out_le32((volatile uint32_t *)GT_CommUnitArb_Ctrl, + (in_le32((volatile uint32_t *)GT_CommUnitArb_Ctrl)| (1<<10))); + +#if 0 + printk("BSP_irqMask_reg[0] = 0x%" PRIx32 ", BSP_irqCause_reg[0] 0x%" PRIx32 "\n", + in_le32((volatile uint32_t *)BSP_irqMask_reg[0]), + in_le32((volatile uint32_t *)BSP_irqCause_reg[0])); + printk("BSP_irqMask_reg[1] = 0x%" PRIx32 ", BSP_irqCause_reg[1] 0x%" PRIx32 "\n", + in_le32((volatile uint32_t *)BSP_irqMask_reg[1]), + in_le32((volatile uint32_t *)BSP_irqCause_reg[1])); + printk("BSP_irqMask_reg[2] = 0x%" PRIx32 ", BSP_irqCause_reg[2] 0x%" PRIx32 "\n", + in_le32((volatile uint32_t *)BSP_irqMask_reg[2]), + in_le32((volatile uint32_t *)BSP_irqCause_reg[2])); +#endif + + /* Initialize the interrupt related registers */ + for (i=0; i<3; i++) { + out_le32((volatile uint32_t *)BSP_irqCause_reg[i], 0); + out_le32((volatile uint32_t *)BSP_irqMask_reg[i], 0); + } + in_le32((volatile uint32_t *)BSP_irqMask_reg[2]); + compute_pic_masks_from_prio(); + +#if 0 + printk("BSP_irqMask_reg[0] = 0x%" PRIx32 ", BSP_irqCause_reg[0] 0x%" PRIx32 "\n", + in_le32((volatile uint32_t *)BSP_irqMask_reg[0]), + in_le32((volatile uint32_t *)BSP_irqCause_reg[0])); + printk("BSP_irqMask_reg[1] = 0x%" PRIx32 ", BSP_irqCause_reg[1] 0x%" PRIx32 "\n", + in_le32((volatile uint32_t *)BSP_irqMask_reg[1]), + in_le32((volatile uint32_t *)BSP_irqCause_reg[1])); + printk("BSP_irqMask_reg[2] = 0x%" PRIx32 ", BSP_irqCause_reg[2] 0x%" PRIx32 "\n", + in_le32((volatile uint32_t *)BSP_irqMask_reg[2]), + in_le32((volatile uint32_t *)BSP_irqCause_reg[2])); +#endif + + /* + * + */ + for (i=BSP_MICL_IRQ_LOWEST_OFFSET; i < BSP_PROCESSOR_IRQ_LOWEST_OFFSET ; i++) { + if ( BSP_config.irqHdlTbl[i].hdl != BSP_config.defaultEntry.hdl) { + BSP_enable_irq_at_pic(i); + BSP_config.irqHdlTbl[i].on(&BSP_config.irqHdlTbl[i]); + } + else { + BSP_config.irqHdlTbl[i].off(&BSP_config.irqHdlTbl[i]); + BSP_disable_irq_at_pic(i); + } + } + for (i= BSP_MAIN_GPP7_0_IRQ; i < BSP_MAIN_GPP31_24_IRQ; i++) + BSP_enable_irq_at_pic(i); + + return(1); +} + +/* + * High level IRQ handler called from shared_raw_irq_code_entry + */ +int C_dispatch_irq_handler (BSP_Exception_frame *frame, unsigned int excNum) +{ + unsigned long irqCause[3]={0, 0,0}; + unsigned oldMask[3]={0,0,0}; + int loop=0, i=0, j; + int irq=0, group=0; + + if (excNum == ASM_DEC_VECTOR) { + bsp_irq_dispatch_list( rtems_hdl_tbl, BSP_DECREMENTER, default_rtems_hdl); + return 0; + } + + for (j=0; j<3; j++ ) oldMask[j] = BSP_irqMask_cache[j]; + for (j=0; j<3; j++) irqCause[j] = in_le32((volatile uint32_t *)BSP_irqCause_reg[j]) & in_le32((volatile uint32_t *)BSP_irqMask_reg[j]); + + while (((irq = picPrioTable[i++])!=-1)&& (loop++ < MAX_IRQ_LOOP)) + { + if (irqCause[group= irq/32] & ( 1<<(irq % 32))) { + for (j=0; j<3; j++) + BSP_irqMask_cache[j] &= (~ BSP_irq_prio_mask_tbl[j][irq]); + + out_le32((volatile uint32_t *)BSP_irqMask_reg[0], BSP_irqMask_cache[0]); + out_le32((volatile uint32_t *)BSP_irqMask_reg[1], BSP_irqMask_cache[1]); + out_le32((volatile uint32_t *)BSP_irqMask_reg[2], BSP_irqMask_cache[2]); + in_le32((volatile uint32_t *)BSP_irqMask_reg[2]); + + bsp_irq_dispatch_list( rtems_hdl_tbl, irq, default_rtems_hdl); + + for (j=0; j<3; j++ ) BSP_irqMask_cache[j] = oldMask[j]; + + out_le32((volatile uint32_t *)BSP_irqMask_reg[0], oldMask[0]); + out_le32((volatile uint32_t *)BSP_irqMask_reg[1], oldMask[1]); + out_le32((volatile uint32_t *)BSP_irqMask_reg[2], oldMask[2]); + in_le32((volatile uint32_t *)BSP_irqMask_reg[2]); + } + } + + return 0; +} + +/* Only print part of the entries for now */ +void BSP_printPicIsrTbl(void) +{ + int i; + + printf("picPrioTable[12]={ {irq# : "); + for (i=0; i<12; i++) + printf("%d,", picPrioTable[i]); + printf("}\n"); + + printf("GPPIrqInTbl: 0x%x :\n", GPPIrqInTbl); +} diff --git a/bsps/powerpc/mvme5500/irq/irq_init.c b/bsps/powerpc/mvme5500/irq/irq_init.c new file mode 100644 index 0000000000..ede4014f22 --- /dev/null +++ b/bsps/powerpc/mvme5500/irq/irq_init.c @@ -0,0 +1,148 @@ +/* irq_init.c + * + * This file contains the implementation of rtems initialization + * related to interrupt handling. + * + * CopyRight (C) 1999 valette@crf.canon.fr + * + * Modified and added support for the MVME5500. + * Copyright 2003, 2004, 2005, Brookhaven National Laboratory and + * Shuchen Kate Feng + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.org/license/LICENSE + * + */ +#include +#include +#include +#include +#include /* ASM_EXT_VECTOR, ASM_DEC_VECTOR ... */ +/*#define TRACE_IRQ_INIT*/ + +/* + * default on/off function + */ +static void nop_func(void){} +/* + * default isOn function + */ +static int not_connected(void) {return 0;} + +static rtems_irq_connect_data rtemsIrq[BSP_IRQ_NUMBER]; +static rtems_irq_global_settings initial_config; + +static rtems_irq_connect_data defaultIrq = { + .name = 0, + .hdl = NULL, + .handle = NULL, + .on = (rtems_irq_enable) nop_func, + .off = (rtems_irq_disable) nop_func, + .isOn = (rtems_irq_is_enabled) not_connected, +#ifdef BSP_SHARED_HANDLER_SUPPORT + .next_handler = NULL +#endif +}; + +rtems_irq_prio BSPirqPrioTable[BSP_PIC_IRQ_NUMBER] = { + /* + * This table is where the developers can change the levels of priority + * based on the need of their applications. + * + * actual priorities for CPU MAIN and GPP interrupts (0-95) + * + * 0 means that only current interrupt is masked (lowest priority) + * 255 is only used by bits 24, 25, 26 and 27 of the CPU high + * interrupt Mask: (e.g. GPP7_0, GPP15_8, GPP23_16, GPP31_24). + * The IRQs of those four bits are always enabled. When it's used, + * the IRQ number is never listed in the dynamic picIsrTable[96]. + * + * The priorities of GPP interrupts were decided by their own + * value set at BSPirqPrioTable. + * + */ + /* CPU Main cause low interrupt */ + /* 0-15 */ + 0, 0, 0, 0, 0, 0, 0, 0, 64/*Timer*/, 0, 0, 0, 0, 0, 0, 0, + /* 16-31 */ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + /* CPU Main cause high interrupt */ + /* 32-47 */ + 2/*10/100MHZ*/, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + /* 48-63 */ + 0, 0, 0, 0, 0, 0, 0, 0, + 255 /*GPP0-7*/, 255/*GPP8-15*/, 255/*GPP16-23*/, 255/*GPP24-31*/, 0, 0, 0, 0, + /* GPP interrupts */ + /* GPP0-7 */ + 1/*serial*/,0, 0, 0, 0, 0, 0, 0, + /* GPP8-15 */ + 47/*PMC1A*/,46/*PMC1B*/,45/*PMC1C*/,44/*PMC1D*/,30/*VME0*/, 29/*VME1*/,3,1, + /* GPP16-23 */ + 37/*PMC2A*/,36/*PMC2B*/,35/*PMC2C*/,34/*PMC2D*/,23/*1GHZ*/, 0,0,0, + /* GPP24-31 */ + 7/*watchdog*/, 0,0,0,0,0,0,0 +}; + +/* + * This code assumes the exceptions management setup has already + * been done. We just need to replace the exceptions that will + * be handled like interrupt. On MPC7455 and many PPC processors + * this means the decrementer exception and the external exception. + */ +void BSP_rtems_irq_mng_init(unsigned cpuId) +{ + int i; + rtems_interrupt_level level; + + /* + * First initialize the Interrupt management hardware + */ +#ifdef TRACE_IRQ_INIT + printk("Initializing the interrupt controller of the GT64260\n"); +#endif + +#ifdef TRACE_IRQ_INIT + printk("Going to re-initialize the rtemsIrq table %d\n",BSP_IRQ_NUMBER); +#endif + /* + * Initialize Rtems management interrupt table + */ + /* + * re-init the rtemsIrq table + */ + for (i = 0; i < BSP_IRQ_NUMBER; i++) { + rtemsIrq[i] = defaultIrq; + rtemsIrq[i].name = i; + } + + /* + * Init initial Interrupt management config + */ + initial_config.irqNb = BSP_IRQ_NUMBER; + initial_config.defaultEntry = defaultIrq; + initial_config.irqHdlTbl = rtemsIrq; + initial_config.irqBase = BSP_LOWEST_OFFSET; + initial_config.irqPrioTbl = BSPirqPrioTable; + +#ifdef TRACE_IRQ_INIT + printk("Going to setup irq mngt configuration\n"); +#endif + + rtems_interrupt_disable(level); + (void) level; /* avoid set but not used warning */ + + if (!BSP_rtems_irq_mngt_set(&initial_config)) { + /* + * put something here that will show the failure... + */ + rtems_panic("Unable to initialize RTEMS interrupt Management!!! System locked\n"); + } +#ifdef TRACE_IRQ_INIT + printk("Done setup irq mngt configuration\n"); +#endif + +#ifdef TRACE_IRQ_INIT + printk("RTEMS IRQ management is now operationnal\n"); +#endif +} diff --git a/bsps/powerpc/psim/irq/irq_init.c b/bsps/powerpc/psim/irq/irq_init.c new file mode 100644 index 0000000000..3d2a82f2c0 --- /dev/null +++ b/bsps/powerpc/psim/irq/irq_init.c @@ -0,0 +1,125 @@ +/* + * This file contains the implementation of rtems initialization + * related to interrupt handling + */ + +/* + * Copyright (C) 1999 valette@crf.canon.fr + * + * Enhanced by Jay Kulpinski + * to make it valid for MVME2300 Motorola boards. + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.org/license/LICENSE. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static rtems_irq_connect_data rtemsIrq[BSP_IRQ_NUMBER]; +static rtems_irq_global_settings initial_config; +static rtems_irq_connect_data defaultIrq = { + /* vectorIdex, hdl , handle , on , off , isOn */ + 0, NULL, NULL , NULL, NULL, NULL +}; +static rtems_irq_prio irqPrioTable[BSP_IRQ_NUMBER]={ + /* + * Processor exceptions handled as interrupts + */ + 0 +}; + + /* + * This code assumes the exceptions management setup has already + * been done. We just need to replace the exceptions that will + * be handled like interrupt. On mcp750/mpc750 and many PPC processors + * this means the decrementer exception and the external exception. + */ +void BSP_rtems_irq_mng_init(unsigned cpuId) +{ + int i; + + /* + * First initialize the Interrupt management hardware + */ + OpenPIC = (void*)PSIM.OpenPIC; + openpic_init(1,0,0,16,0,0); + + /* + * Initialize Rtems management interrupt table + */ + /* + * re-init the rtemsIrq table + */ + for (i = 0; i < BSP_IRQ_NUMBER; i++) { + rtemsIrq[i] = defaultIrq; + rtemsIrq[i].name = i; + } + /* + * Init initial Interrupt management config + */ + initial_config.irqNb = BSP_IRQ_NUMBER; + initial_config.defaultEntry = defaultIrq; + initial_config.irqHdlTbl = rtemsIrq; + initial_config.irqBase = BSP_LOWEST_OFFSET; + initial_config.irqPrioTbl = irqPrioTable; + + for (i = BSP_PCI_IRQ_LOWEST_OFFSET; i< BSP_PCI_IRQ_NUMBER; i++ ) { + irqPrioTable[i] = 8; + } + + if (!BSP_rtems_irq_mngt_set(&initial_config)) { + /* + * put something here that will show the failure... + */ + rtems_panic( + "Unable to initialize RTEMS interrupt Management!!! System locked\n" + ); + } + + #ifdef TRACE_IRQ_INIT + printk("RTEMS IRQ management is now operationnal\n"); + #endif +} + +static int psim_exception_handler( + BSP_Exception_frame *frame, + unsigned exception_number +) +{ + rtems_panic("Unexpected interrupt occured"); + return 0; +} + +/* + * functions to enable/disable a source at the ipic + */ +void bsp_interrupt_vector_enable( rtems_vector_number irqnum) +{ + /* FIXME: do something */ + bsp_interrupt_assert(bsp_interrupt_is_valid_vector(irqnum)); +} + +void bsp_interrupt_vector_disable( rtems_vector_number irqnum) +{ + /* FIXME: do something */ + bsp_interrupt_assert(bsp_interrupt_is_valid_vector(irqnum)); +} + +rtems_status_code bsp_interrupt_facility_initialize(void) +{ + /* Install exception handler */ + if (ppc_exc_set_handler( ASM_EXT_VECTOR, psim_exception_handler)) { + return RTEMS_IO_ERROR; + } + + return RTEMS_SUCCESSFUL; +} diff --git a/bsps/powerpc/qemuppc/irq/irq_init.c b/bsps/powerpc/qemuppc/irq/irq_init.c new file mode 100644 index 0000000000..24b15dcd49 --- /dev/null +++ b/bsps/powerpc/qemuppc/irq/irq_init.c @@ -0,0 +1,61 @@ +/*===============================================================*\ +| Project: RTEMS generic MPC83xx BSP | ++-----------------------------------------------------------------+ +| Copyright (c) 2007 | +| Embedded Brains GmbH | +| Obere Lagerstr. 30 | +| D-82178 Puchheim | +| Germany | +| rtems@embedded-brains.de | ++-----------------------------------------------------------------+ +| The license and distribution terms for this file may be | +| found in the file LICENSE in this distribution or at | +| | +| http://www.rtems.org/license/LICENSE. | +| | ++-----------------------------------------------------------------+ +| this file integrates the IPIC irq controller | +\*===============================================================*/ + +#include + +#include + +#include +#include +#include +#include + +static int qemuppc_exception_handler( + BSP_Exception_frame *frame, + unsigned exception_number +) +{ + rtems_panic("Unexpected interrupt occured"); + return 0; +} + +/* + * functions to enable/disable a source at the ipic + */ +void bsp_interrupt_vector_enable( rtems_vector_number irqnum) +{ + /* FIXME: do something */ + bsp_interrupt_assert(bsp_interrupt_is_valid_vector(irqnum)); +} + +void bsp_interrupt_vector_disable( rtems_vector_number irqnum) +{ + /* FIXME: do something */ + bsp_interrupt_assert(bsp_interrupt_is_valid_vector(irqnum)); +} + +rtems_status_code bsp_interrupt_facility_initialize(void) +{ + /* Install exception handler */ + if (ppc_exc_set_handler( ASM_EXT_VECTOR, qemuppc_exception_handler)) { + return RTEMS_IO_ERROR; + } + + return RTEMS_SUCCESSFUL; +} diff --git a/bsps/powerpc/qoriq/irq/irq.c b/bsps/powerpc/qoriq/irq/irq.c new file mode 100644 index 0000000000..625b9fce1b --- /dev/null +++ b/bsps/powerpc/qoriq/irq/irq.c @@ -0,0 +1,387 @@ +/** + * @file + * + * @ingroup QorIQ + * + * @brief Interrupt implementation. + */ + +/* + * Copyright (c) 2010, 2017 embedded brains GmbH. All rights reserved. + * + * embedded brains GmbH + * Dornierstr. 4 + * 82178 Puchheim + * Germany + * + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.org/license/LICENSE. + */ + +#include + +#include + +#include + +#include + +#include +#include +#include +#include +#include +#include + +#ifdef RTEMS_SMP +#include +#endif + +RTEMS_INTERRUPT_LOCK_DEFINE(static, lock, "QorIQ IRQ") + +#define SPURIOUS 0xffff + +#ifdef QORIQ_IS_HYPERVISOR_GUEST + +void bsp_interrupt_set_affinity( + rtems_vector_number vector, + const Processor_mask *affinity +) +{ + uint32_t config; + unsigned int priority; + uint32_t destination; + uint32_t new_destination; + rtems_interrupt_lock_context lock_context; + + new_destination = _Processor_mask_Find_last_set(affinity) - 1; + + rtems_interrupt_lock_acquire(&lock, &lock_context); + ev_int_get_config(vector, &config, &priority, &destination); + ev_int_set_config(vector, config, priority, new_destination); + rtems_interrupt_lock_release(&lock, &lock_context); +} + +void bsp_interrupt_get_affinity( + rtems_vector_number vector, + Processor_mask *affinity +) +{ + uint32_t config; + unsigned int priority; + uint32_t destination; + + ev_int_get_config(vector, &config, &priority, &destination); + _Processor_mask_From_uint32_t(affinity, destination, 0); +} + +void bsp_interrupt_vector_enable(rtems_vector_number vector) +{ + bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector)); + ev_int_set_mask(vector, 0); +} + +void bsp_interrupt_vector_disable(rtems_vector_number vector) +{ + bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector)); + ev_int_set_mask(vector, 1); +} + +void bsp_interrupt_dispatch(uintptr_t exception_number) +{ + unsigned int vector; + + if (exception_number == 10) { + qoriq_decrementer_dispatch(); + return; + } + +#ifdef RTEMS_SMP + if (exception_number == 36) { + _SMP_Inter_processor_interrupt_handler(); + return; + } +#endif + + /* + * This works only if the "has-external-proxy" property is present in the + * "epapr,hv-pic" device tree node. + */ + vector = PPC_SPECIAL_PURPOSE_REGISTER(FSL_EIS_EPR); + + if (vector != SPURIOUS) { + uint32_t msr; + + msr = ppc_external_exceptions_enable(); + bsp_interrupt_handler_dispatch(vector); + ppc_external_exceptions_disable(msr); + + ev_int_eoi(vector); + } else { + bsp_interrupt_handler_default(vector); + } +} + +rtems_status_code bsp_interrupt_facility_initialize(void) +{ + unsigned int i; + + for (i = BSP_INTERRUPT_VECTOR_MIN; i <= BSP_INTERRUPT_VECTOR_MAX; ++i) { + uint32_t config; + unsigned int priority; + uint32_t destination; + unsigned int err; + + err = ev_int_get_config(i, &config, &priority, &destination); + if (err != EV_SUCCESS) + continue; + + priority = QORIQ_PIC_PRIORITY_DEFAULT; + + ev_int_set_config(i, config, priority, destination); + } + + return RTEMS_SUCCESSFUL; +} + +#else /* !QORIQ_IS_HYPERVISOR_GUEST */ + +#define VPR_MSK BSP_BBIT32(0) +#define VPR_A BSP_BBIT32(1) +#define VPR_P BSP_BBIT32(8) +#define VPR_S BSP_BBIT32(9) +#define VPR_PRIORITY(val) BSP_BFLD32(val, 12, 15) +#define VPR_PRIORITY_GET(reg) BSP_BFLD32GET(reg, 12, 15) +#define VPR_PRIORITY_SET(reg, val) BSP_BFLD32SET(reg, val, 12, 15) +#define VPR_VECTOR(val) BSP_BFLD32(val, 16, 31) +#define VPR_VECTOR_GET(reg) BSP_BFLD32GET(reg, 16, 31) +#define VPR_VECTOR_SET(reg, val) BSP_BFLD32SET(reg, val, 16, 31) + +#define GCR_RST BSP_BBIT32(0) +#define GCR_M BSP_BBIT32(2) + +#define SRC_CFG_IDX(i) ((i) - QORIQ_IRQ_EXT_BASE) + +static const uint16_t src_cfg_offsets [] = { + [SRC_CFG_IDX(QORIQ_IRQ_EXT_0)] = 0x10000 >> 4, + [SRC_CFG_IDX(QORIQ_IRQ_EXT_1)] = 0x10020 >> 4, + [SRC_CFG_IDX(QORIQ_IRQ_EXT_2)] = 0x10040 >> 4, + [SRC_CFG_IDX(QORIQ_IRQ_EXT_3)] = 0x10060 >> 4, + [SRC_CFG_IDX(QORIQ_IRQ_EXT_4)] = 0x10080 >> 4, + [SRC_CFG_IDX(QORIQ_IRQ_EXT_5)] = 0x100a0 >> 4, + [SRC_CFG_IDX(QORIQ_IRQ_EXT_6)] = 0x100c0 >> 4, + [SRC_CFG_IDX(QORIQ_IRQ_EXT_7)] = 0x100e0 >> 4, + [SRC_CFG_IDX(QORIQ_IRQ_EXT_8)] = 0x10100 >> 4, + [SRC_CFG_IDX(QORIQ_IRQ_EXT_9)] = 0x10120 >> 4, + [SRC_CFG_IDX(QORIQ_IRQ_EXT_10)] = 0x10140 >> 4, + [SRC_CFG_IDX(QORIQ_IRQ_EXT_11)] = 0x10160 >> 4, + [SRC_CFG_IDX(QORIQ_IRQ_IPI_0)] = 0x010a0 >> 4, + [SRC_CFG_IDX(QORIQ_IRQ_IPI_1)] = 0x010b0 >> 4, + [SRC_CFG_IDX(QORIQ_IRQ_IPI_2)] = 0x010c0 >> 4, + [SRC_CFG_IDX(QORIQ_IRQ_IPI_3)] = 0x010d0 >> 4, + [SRC_CFG_IDX(QORIQ_IRQ_MI_0)] = 0x11600 >> 4, + [SRC_CFG_IDX(QORIQ_IRQ_MI_1)] = 0x11620 >> 4, + [SRC_CFG_IDX(QORIQ_IRQ_MI_2)] = 0x11640 >> 4, + [SRC_CFG_IDX(QORIQ_IRQ_MI_3)] = 0x11660 >> 4, + [SRC_CFG_IDX(QORIQ_IRQ_MI_4)] = 0x11680 >> 4, + [SRC_CFG_IDX(QORIQ_IRQ_MI_5)] = 0x116a0 >> 4, + [SRC_CFG_IDX(QORIQ_IRQ_MI_6)] = 0x116c0 >> 4, + [SRC_CFG_IDX(QORIQ_IRQ_MI_7)] = 0x116e0 >> 4, + [SRC_CFG_IDX(QORIQ_IRQ_MSI_0)] = 0x11c00 >> 4, + [SRC_CFG_IDX(QORIQ_IRQ_MSI_1)] = 0x11c20 >> 4, + [SRC_CFG_IDX(QORIQ_IRQ_MSI_2)] = 0x11c40 >> 4, + [SRC_CFG_IDX(QORIQ_IRQ_MSI_3)] = 0x11c60 >> 4, + [SRC_CFG_IDX(QORIQ_IRQ_MSI_4)] = 0x11c80 >> 4, + [SRC_CFG_IDX(QORIQ_IRQ_MSI_5)] = 0x11ca0 >> 4, + [SRC_CFG_IDX(QORIQ_IRQ_MSI_6)] = 0x11cc0 >> 4, + [SRC_CFG_IDX(QORIQ_IRQ_MSI_7)] = 0x11ce0 >> 4, + [SRC_CFG_IDX(QORIQ_IRQ_GT_A_0)] = 0x01120 >> 4, + [SRC_CFG_IDX(QORIQ_IRQ_GT_A_1)] = 0x01160 >> 4, + [SRC_CFG_IDX(QORIQ_IRQ_GT_A_2)] = 0x011a0 >> 4, + [SRC_CFG_IDX(QORIQ_IRQ_GT_A_3)] = 0x011e0 >> 4, + [SRC_CFG_IDX(QORIQ_IRQ_GT_B_0)] = 0x02120 >> 4, + [SRC_CFG_IDX(QORIQ_IRQ_GT_B_1)] = 0x02160 >> 4, + [SRC_CFG_IDX(QORIQ_IRQ_GT_B_2)] = 0x021a0 >> 4, + [SRC_CFG_IDX(QORIQ_IRQ_GT_B_3)] = 0x021e0 >> 4 +}; + +static volatile qoriq_pic_src_cfg *get_src_cfg(rtems_vector_number vector) +{ + uint32_t n = MIN(RTEMS_ARRAY_SIZE(qoriq.pic.ii_0), QORIQ_IRQ_EXT_BASE); + + if (vector < n) { + return &qoriq.pic.ii_0 [vector]; + } else if (vector < QORIQ_IRQ_EXT_BASE) { + return &qoriq.pic.ii_1 [vector - n]; + } else { + uintptr_t offs = ((uintptr_t) + src_cfg_offsets [vector - QORIQ_IRQ_EXT_BASE]) << 4; + + return (volatile qoriq_pic_src_cfg *) ((uintptr_t) &qoriq.pic + offs); + } +} + +rtems_status_code qoriq_pic_set_priority( + rtems_vector_number vector, + int new_priority, + int *old_priority +) +{ + rtems_status_code sc = RTEMS_SUCCESSFUL; + uint32_t old_vpr = 0; + + if (bsp_interrupt_is_valid_vector(vector)) { + volatile qoriq_pic_src_cfg *src_cfg = get_src_cfg(vector); + + if (QORIQ_PIC_PRIORITY_IS_VALID(new_priority)) { + rtems_interrupt_lock_context lock_context; + + rtems_interrupt_lock_acquire(&lock, &lock_context); + old_vpr = src_cfg->vpr; + src_cfg->vpr = VPR_PRIORITY_SET(old_vpr, (uint32_t) new_priority); + rtems_interrupt_lock_release(&lock, &lock_context); + } else if (new_priority < 0) { + old_vpr = src_cfg->vpr; + } else { + sc = RTEMS_INVALID_PRIORITY; + } + } else { + sc = RTEMS_INVALID_ID; + } + + if (old_priority != NULL) { + *old_priority = (int) VPR_PRIORITY_GET(old_vpr); + } + + return sc; +} + +void bsp_interrupt_set_affinity( + rtems_vector_number vector, + const Processor_mask *affinity +) +{ + volatile qoriq_pic_src_cfg *src_cfg = get_src_cfg(vector); + + src_cfg->dr = _Processor_mask_To_uint32_t(affinity, 0); +} + +void bsp_interrupt_get_affinity( + rtems_vector_number vector, + Processor_mask *affinity +) +{ + volatile qoriq_pic_src_cfg *src_cfg = get_src_cfg(vector); + + _Processor_mask_From_uint32_t(affinity, src_cfg->dr, 0); +} + +static void pic_vector_enable(rtems_vector_number vector, uint32_t msk) +{ + volatile qoriq_pic_src_cfg *src_cfg = get_src_cfg(vector); + rtems_interrupt_lock_context lock_context; + + bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector)); + + rtems_interrupt_lock_acquire(&lock, &lock_context); + src_cfg->vpr = (src_cfg->vpr & ~VPR_MSK) | msk; + rtems_interrupt_lock_release(&lock, &lock_context); +} + +void bsp_interrupt_vector_enable(rtems_vector_number vector) +{ + pic_vector_enable(vector, 0); +} + +void bsp_interrupt_vector_disable(rtems_vector_number vector) +{ + pic_vector_enable(vector, VPR_MSK); +} + +void bsp_interrupt_dispatch(uintptr_t exception_number) +{ + rtems_vector_number vector = qoriq.pic.iack; + + if (vector != SPURIOUS) { + uint32_t msr = ppc_external_exceptions_enable(); + + bsp_interrupt_handler_dispatch(vector); + + ppc_external_exceptions_disable(msr); + + qoriq.pic.eoi = 0; + qoriq.pic.whoami; + } else { + bsp_interrupt_handler_default(vector); + } +} + +static bool pic_is_ipi(rtems_vector_number vector) +{ + return QORIQ_IRQ_IPI_0 <= vector && vector <= QORIQ_IRQ_IPI_3; +} + +static void pic_reset(void) +{ + qoriq.pic.gcr = GCR_RST; + while ((qoriq.pic.gcr & GCR_RST) != 0) { + /* Wait */ + } +} + +static void pic_global_timer_init(void) +{ + int i = 0; + + qoriq.pic.tcra = 0; + qoriq.pic.tcrb = 0; + + for (i = 0; i < 4; ++i) { + qoriq.pic.gta [0].bcr = GTBCR_CI; + qoriq.pic.gtb [0].bcr = GTBCR_CI; + } +} + +rtems_status_code bsp_interrupt_facility_initialize(void) +{ + rtems_vector_number i = 0; + uint32_t processor_id = ppc_processor_id(); + + if (processor_id == 0) { + /* Core 0 must do the basic initialization */ + + pic_reset(); + + for (i = BSP_INTERRUPT_VECTOR_MIN; i <= BSP_INTERRUPT_VECTOR_MAX; ++i) { + volatile qoriq_pic_src_cfg *src_cfg = get_src_cfg(i); + + src_cfg->vpr = VPR_MSK | VPR_P + | VPR_PRIORITY(QORIQ_PIC_PRIORITY_DEFAULT) | VPR_VECTOR(i); + + if (!pic_is_ipi(i)) { + src_cfg->dr = 0x1; + } + } + + qoriq.pic.mer03 = 0xf; + qoriq.pic.mer47 = 0xf; + qoriq.pic.svr = SPURIOUS; + qoriq.pic.gcr = GCR_M; + + pic_global_timer_init(); + } + + qoriq.pic.ctpr = 0; + + for (i = BSP_INTERRUPT_VECTOR_MIN; i <= BSP_INTERRUPT_VECTOR_MAX; ++i) { + qoriq.pic.iack; + qoriq.pic.eoi = 0; + qoriq.pic.whoami; + } + + return RTEMS_SUCCESSFUL; +} + +#endif /* QORIQ_IS_HYPERVISOR_GUEST */ diff --git a/bsps/powerpc/shared/irq/i8259.c b/bsps/powerpc/shared/irq/i8259.c new file mode 100644 index 0000000000..7363e87ba0 --- /dev/null +++ b/bsps/powerpc/shared/irq/i8259.c @@ -0,0 +1,149 @@ +/* + * This file contains the implementation of the function described in irq.h + * related to Intel 8259 Programmable Interrupt controller. + * + * Copyright (C) 1998, 1999 valette@crf.canon.fr + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.org/license/LICENSE. + */ + +#include +#include + +/*-------------------------------------------------------------------------+ +| Cache for 1st and 2nd PIC IRQ line's status (enabled or disabled) register. ++--------------------------------------------------------------------------*/ +/* + * lower byte is interrupt mask on the master PIC. + * while upper bits are interrupt on the slave PIC. + */ +volatile rtems_i8259_masks i8259s_cache = 0xfffb; + +/*-------------------------------------------------------------------------+ +| Function: BSP_irq_disable_at_i8259s +| Description: Mask IRQ line in appropriate PIC chip. +| Global Variables: i8259s_cache +| Arguments: vector_offset - number of IRQ line to mask. +| Returns: original state or -1 on error. ++--------------------------------------------------------------------------*/ +int BSP_irq_disable_at_i8259s (const rtems_irq_number irqLine) +{ + unsigned short mask; + rtems_interrupt_level level; + int rval; + + if ( ((int)irqLine < BSP_ISA_IRQ_LOWEST_OFFSET) || + ((int)irqLine > BSP_ISA_IRQ_MAX_OFFSET) + ) + return -1; + + rtems_interrupt_disable(level); + + mask = 1 << irqLine; + rval = i8259s_cache & mask ? 0 : 1; + i8259s_cache |= mask; + + if (irqLine < 8) + { + outport_byte(PIC_MASTER_IMR_IO_PORT, i8259s_cache & 0xff); + } + else + { + outport_byte(PIC_SLAVE_IMR_IO_PORT, ((i8259s_cache & 0xff00) >> 8)); + } + rtems_interrupt_enable(level); + + return rval; +} + +/*-------------------------------------------------------------------------+ +| Function: BSP_irq_enable_at_i8259s +| Description: Unmask IRQ line in appropriate PIC chip. +| Global Variables: i8259s_cache +| Arguments: irqLine - number of IRQ line to mask. +| Returns: Nothing. ++--------------------------------------------------------------------------*/ +int BSP_irq_enable_at_i8259s (const rtems_irq_number irqLine) +{ + unsigned short mask; + rtems_interrupt_level level; + + if ( ((int)irqLine < BSP_ISA_IRQ_LOWEST_OFFSET) || + ((int)irqLine > BSP_ISA_IRQ_MAX_OFFSET ) + ) + return 1; + + rtems_interrupt_disable(level); + + mask = ~(1 << irqLine); + i8259s_cache &= mask; + + if (irqLine < 8) + { + outport_byte(PIC_MASTER_IMR_IO_PORT, i8259s_cache & 0xff); + } + else + { + outport_byte(PIC_SLAVE_IMR_IO_PORT, ((i8259s_cache & 0xff00) >> 8)); + } + rtems_interrupt_enable(level); + + return 0; +} /* mask_irq */ + +int BSP_irq_enabled_at_i8259s (const rtems_irq_number irqLine) +{ + unsigned short mask; + + if ( ((int)irqLine < BSP_ISA_IRQ_LOWEST_OFFSET) || + ((int)irqLine > BSP_ISA_IRQ_MAX_OFFSET) + ) + return 1; + + mask = (1 << irqLine); + return (~(i8259s_cache & mask)); +} + +/*-------------------------------------------------------------------------+ +| Function: BSP_irq_ack_at_i8259s +| Description: Signal generic End Of Interrupt (EOI) to appropriate PIC. +| Global Variables: None. +| Arguments: irqLine - number of IRQ line to acknowledge. +| Returns: Nothing. ++--------------------------------------------------------------------------*/ +int BSP_irq_ack_at_i8259s (const rtems_irq_number irqLine) +{ + if (irqLine >= 8) { + outport_byte(PIC_MASTER_COMMAND_IO_PORT, SLAVE_PIC_EOSI); + outport_byte(PIC_SLAVE_COMMAND_IO_PORT, (PIC_EOSI | (irqLine - 8))); + } + else { + outport_byte(PIC_MASTER_COMMAND_IO_PORT, (PIC_EOSI | irqLine)); + } + + return 0; + +} /* ackIRQ */ + +void BSP_i8259s_init(void) +{ + /* + * init master 8259 interrupt controller + */ + outport_byte(PIC_MASTER_COMMAND_IO_PORT, 0x11); /* Start init sequence */ + outport_byte(PIC_MASTER_IMR_IO_PORT, 0x00);/* Vector base = 0 */ + outport_byte(PIC_MASTER_IMR_IO_PORT, 0x04);/* edge tiggered, Cascade (slave) on IRQ2 */ + outport_byte(PIC_MASTER_IMR_IO_PORT, 0x01);/* Select 8086 mode */ + outport_byte(PIC_MASTER_IMR_IO_PORT, 0xFB); /* Mask all except cascade */ + /* + * init slave interrupt controller + */ + outport_byte(PIC_SLAVE_COMMAND_IO_PORT, 0x11); /* Start init sequence */ + outport_byte(PIC_SLAVE_IMR_IO_PORT, 0x08);/* Vector base = 8 */ + outport_byte(PIC_SLAVE_IMR_IO_PORT, 0x02);/* edge triggered, Cascade (slave) on IRQ2 */ + outport_byte(PIC_SLAVE_IMR_IO_PORT, 0x01); /* Select 8086 mode */ + outport_byte(PIC_SLAVE_IMR_IO_PORT, 0xFF); /* Mask all */ + +} diff --git a/bsps/powerpc/shared/irq/irq_init.c b/bsps/powerpc/shared/irq/irq_init.c new file mode 100644 index 0000000000..1a44992a5b --- /dev/null +++ b/bsps/powerpc/shared/irq/irq_init.c @@ -0,0 +1,364 @@ +/* irq_init.c + * + * This file contains the implementation of rtems initialization + * related to interrupt handling. + * + * CopyRight (C) 1999 valette@crf.canon.fr + * + * Enhanced by Jay Kulpinski + * to make it valid for MVME2300 Motorola boards. + * + * Till Straumann , 12/20/2001: + * Use the new interface to openpic_init + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.org/license/LICENSE. + */ + +#include +#include +#include +#include +#include +#if BSP_PCI_IRQ_NUMBER > 0 +#include +#endif +#include +#include +#include +#include + +typedef struct { + unsigned char bus; /* few chance the PCI/ISA bridge is not on first bus but ... */ + unsigned char device; + unsigned char function; +} pci_isa_bridge_device; + +pci_isa_bridge_device* via_82c586 = 0; +#ifndef qemu +static pci_isa_bridge_device bridge; +#endif + +/* + * default methods + */ +static void nop_hdl(rtems_irq_hdl_param ignored) +{ +} + +static void nop_irq_enable(const struct __rtems_irq_connect_data__*ignored) +{ +} + +static int irq_is_connected(const struct __rtems_irq_connect_data__*ignored) +{ + return 0; +} + + +static rtems_irq_connect_data rtemsIrq[BSP_IRQ_NUMBER]; +static rtems_irq_global_settings initial_config; +static rtems_irq_connect_data defaultIrq = { + 0, /* vector */ + nop_hdl, /* hdl */ + NULL, /* handle */ + nop_irq_enable, /* on */ + nop_irq_enable, /* off */ + irq_is_connected /* isOn */ +#ifdef BSP_SHARED_HANDLER_SUPPORT + , NULL /* next_handler */ +#endif +}; +static rtems_irq_prio irqPrioTable[BSP_IRQ_NUMBER]={ + /* + * actual priorities for interrupt : + * 0 means that only current interrupt is masked + * 255 means all other interrupts are masked + */ + /* + * ISA interrupts. + * The second entry has a priority of 255 because + * it is the slave pic entry and should always remain + * unmasked. + */ + 0,0, + 255, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +#if BSP_PCI_IRQ_NUMBER > 0 + /* + * PCI Interrupts + */ + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, /* for raven prio 0 means unactive... */ +#endif + /* + * Processor exceptions handled as interrupts + */ + 0 +}; + +#if BSP_PCI_IRQ_NUMBER > 0 +#if defined(mvme2100) +static unsigned char mvme2100_openpic_initpolarities[16] = { + 0, /* Not used - should be disabled */ + 0, /* DEC21143 Controller */ + 0, /* PMC/PC-MIP Type I Slot 0 */ + 0, /* PC-MIP Type I Slot 1 */ + 0, /* PC-MIP Type II Slot 0 */ + 0, /* PC-MIP Type II Slot 1 */ + 0, /* Not used - should be disabled */ + 0, /* PCI Expansion Interrupt A/Universe II (LINT0) */ + 0, /* PCI Expansion Interrupt B/Universe II (LINT1) */ + 0, /* PCI Expansion Interrupt C/Universe II (LINT2) */ + 0, /* PCI Expansion Interrupt D/Universe II (LINT3) */ + 0, /* Not used - should be disabled */ + 0, /* Not used - should be disabled */ + 1, /* 16550 UART */ + 0, /* Front panel Abort Switch */ + 0, /* RTC IRQ */ +}; + +static unsigned char mvme2100_openpic_initsenses[] = { + 0, /* Not used - should be disabled */ + 1, /* DEC21143 Controller */ + 1, /* PMC/PC-MIP Type I Slot 0 */ + 1, /* PC-MIP Type I Slot 1 */ + 1, /* PC-MIP Type II Slot 0 */ + 1, /* PC-MIP Type II Slot 1 */ + 0, /* Not used - should be disabled */ + 1, /* PCI Expansion Interrupt A/Universe II (LINT0) */ + 1, /* PCI Expansion Interrupt B/Universe II (LINT1) */ + 1, /* PCI Expansion Interrupt C/Universe II (LINT2) */ + 1, /* PCI Expansion Interrupt D/Universe II (LINT3) */ + 0, /* Not used - should be disabled */ + 0, /* Not used - should be disabled */ + 1, /* 16550 UART */ + 0, /* Front panel Abort Switch */ + 1, /* RTC IRQ */ +}; +#else +static unsigned char mcp750_openpic_initpolarities[16] = { + 1, /* 8259 cascade */ + 0, /* all the rest of them */ +}; + +static unsigned char mcp750_openpic_initsenses[] = { + 1, /* MCP750_INT_PCB(8259) */ + 0, /* MCP750_INT_FALCON_ECC_ERR */ + 1, /* MCP750_INT_PCI_ETHERNET */ + 1, /* MCP750_INT_PCI_PMC */ + 1, /* MCP750_INT_PCI_WATCHDOG_TIMER1 */ + 1, /* MCP750_INT_PCI_PRST_SIGNAL */ + 1, /* MCP750_INT_PCI_FALL_SIGNAL */ + 1, /* MCP750_INT_PCI_DEG_SIGNAL */ + 1, /* MCP750_INT_PCI_BUS1_INTA */ + 1, /* MCP750_INT_PCI_BUS1_INTB */ + 1, /* MCP750_INT_PCI_BUS1_INTC */ + 1, /* MCP750_INT_PCI_BUS1_INTD */ + 1, /* MCP750_INT_PCI_BUS2_INTA */ + 1, /* MCP750_INT_PCI_BUS2_INTB */ + 1, /* MCP750_INT_PCI_BUS2_INTC */ + 1, /* MCP750_INT_PCI_BUS2_INTD */ +}; +#endif +#endif + +#if BSP_ISA_IRQ_NUMBER > 0 && !defined(qemu) +void VIA_isa_bridge_interrupts_setup(void) +{ + pci_isa_bridge_device pci_dev; + uint32_t temp; + unsigned char tmp; + unsigned char maxBus; + unsigned found = 0; + + maxBus = pci_bus_count(); + pci_dev.function = 0; /* Assumes the bidge is the first function */ + + for (pci_dev.bus = 0; pci_dev.bus < maxBus; pci_dev.bus++) { +#ifdef SCAN_PCI_PRINT + printk("isa_bridge_interrupts_setup: Scanning bus %d\n", pci_dev.bus); +#endif + for (pci_dev.device = 0; pci_dev.device < PCI_MAX_DEVICES; pci_dev.device++) { +#ifdef SCAN_PCI_PRINT + printk("isa_bridge_interrupts_setup: Scanning device %d\n", pci_dev.device); +#endif + pci_read_config_dword(pci_dev.bus, pci_dev.device, pci_dev.function, + PCI_VENDOR_ID, &temp); +#ifdef SCAN_PCI_PRINT + printk("Vendor/device = %x\n", temp); +#endif + if ((temp == (((unsigned short) PCI_VENDOR_ID_VIA) | (PCI_DEVICE_ID_VIA_82C586_0 << 16))) + ) { + bridge = pci_dev; + via_82c586 = &bridge; +#ifdef SHOW_ISA_PCI_BRIDGE_SETTINGS + /* + * Should print : bus = 0, device = 11, function = 0 on a MCP750. + */ + printk("Via PCI/ISA bridge found at bus = %d, device = %d, function = %d\n", + via_82c586->bus, + via_82c586->device, + via_82c586->function); +#endif + found = 1; + goto loop_exit; + + } + } + } +loop_exit: + if (!found) rtems_panic("VIA_82C586 PCI/ISA bridge not found!n"); + + tmp = inb(0x810); + if ( !(tmp & 0x2)) { +#ifdef SHOW_ISA_PCI_BRIDGE_SETTINGS + printk("This is a second generation MCP750 board\n"); + printk("We must reprogram the PCI/ISA bridge...\n"); +#endif + pci_read_config_byte(via_82c586->bus, via_82c586->device, via_82c586->function, + 0x47, &tmp); +#ifdef SHOW_ISA_PCI_BRIDGE_SETTINGS + printk(" PCI ISA bridge control2 = %x\n", (unsigned) tmp); +#endif + /* + * Enable 4D0/4D1 ISA interrupt level/edge config registers + */ + tmp |= 0x20; + pci_write_config_byte(via_82c586->bus, via_82c586->device, via_82c586->function, + 0x47, tmp); + /* + * Now program the ISA interrupt edge/level + */ + tmp = ELCRS_INT9_LVL | ELCRS_INT10_LVL | ELCRS_INT11_LVL; + outb(tmp, ISA8259_S_ELCR); + tmp = ELCRM_INT5_LVL; + outb(tmp, ISA8259_M_ELCR); + /* + * Set the Interrupt inputs to non-inverting level interrupt + */ + pci_read_config_byte(via_82c586->bus, via_82c586->device, via_82c586->function, + 0x54, &tmp); +#ifdef SHOW_ISA_PCI_BRIDGE_SETTINGS + printk(" PCI ISA bridge PCI/IRQ Edge/Level Select = %x\n", (unsigned) tmp); +#endif + tmp = 0; + pci_write_config_byte(via_82c586->bus, via_82c586->device, via_82c586->function, + 0x54, tmp); + } + else { +#ifdef SHOW_ISA_PCI_BRIDGE_SETTINGS + printk("This is a first generation MCP750 board\n"); + printk("We just show the actual value used by PCI/ISA bridge\n"); +#endif + pci_read_config_byte(via_82c586->bus, via_82c586->device, via_82c586->function, + 0x47, &tmp); +#ifdef SHOW_ISA_PCI_BRIDGE_SETTINGS + printk(" PCI ISA bridge control2 = %x\n", (unsigned) tmp); +#endif + /* + * Show the Interrupt inputs inverting/non-inverting level status + */ + pci_read_config_byte(via_82c586->bus, via_82c586->device, via_82c586->function, + 0x54, &tmp); +#ifdef SHOW_ISA_PCI_BRIDGE_SETTINGS + printk(" PCI ISA bridge PCI/IRQ Edge/Level Select = %x\n", (unsigned) tmp); +#endif + } +} +#endif + + /* + * This code assumes the exceptions management setup has already + * been done. We just need to replace the exceptions that will + * be handled like interrupt. On mcp750/mpc750 and many PPC processors + * this means the decrementer exception and the external exception. + */ +void BSP_rtems_irq_mng_init(unsigned cpuId) +{ +#if BSP_ISA_IRQ_NUMBER > 0 && !defined(mvme2100) + int known_cpi_isa_bridge = 0; +#endif + int i; + + /* + * First initialize the Interrupt management hardware + */ +#if defined(mvme2100) +#ifdef TRACE_IRQ_INIT + printk("Going to initialize EPIC interrupt controller (openpic compliant)\n"); +#endif + /* EPIC sources don't start at the regular place; define appropriate offset + * prior to initializing the PIC. + */ + openpic_init(1, mvme2100_openpic_initpolarities, mvme2100_openpic_initsenses, 16, 16, BSP_bus_frequency); +#else +#if BSP_PCI_IRQ_NUMBER > 0 +#ifdef TRACE_IRQ_INIT + printk("Going to initialize raven interrupt controller (openpic compliant)\n"); +#endif + openpic_init(1, mcp750_openpic_initpolarities, mcp750_openpic_initsenses, 0, 0, 0); +#ifdef TRACE_IRQ_INIT + printk("Going to initialize the PCI/ISA bridge IRQ related setting (VIA 82C586)\n"); +#endif +#endif + +#if BSP_ISA_IRQ_NUMBER > 0 + if ( currentBoard == MESQUITE ) { +#ifndef qemu + VIA_isa_bridge_interrupts_setup(); +#endif + known_cpi_isa_bridge = 1; + } + if ( currentBoard == MVME_2300 ) { + /* nothing to do for W83C553 bridge */ + known_cpi_isa_bridge = 1; + } + if ( currentBoard == MTX_WO_PP || currentBoard == MTX_W_PP ) { + /* W83C554, don't to anything at the moment. gregm 11/6/2002 */ + known_cpi_isa_bridge = 1; + } + + if (!known_cpi_isa_bridge) { + printk("Please add code for PCI/ISA bridge init to libbsp/powerpc/shared/irq/irq_init.c\n"); + printk("If your card works correctly please add a test and set known_cpi_isa_bridge to true\n"); + printk("currentBoard = %i\n", currentBoard); + } +#ifdef TRACE_IRQ_INIT + printk("Going to initialize the ISA PC legacy IRQ management hardware\n"); +#endif + BSP_i8259s_init(); +#endif + +#endif + + /* + * Initialize RTEMS management interrupt table + */ + /* + * re-init the rtemsIrq table + */ + for (i = 0; i < BSP_IRQ_NUMBER; i++) { + rtemsIrq[i] = defaultIrq; + rtemsIrq[i].name = i; + } + /* + * Init initial Interrupt management config + */ + initial_config.irqNb = BSP_IRQ_NUMBER; + initial_config.defaultEntry = defaultIrq; + initial_config.irqHdlTbl = rtemsIrq; + initial_config.irqBase = BSP_LOWEST_OFFSET; + initial_config.irqPrioTbl = irqPrioTable; + + if (!BSP_rtems_irq_mngt_set(&initial_config)) { + /* + * put something here that will show the failure... + */ + rtems_panic("Unable to initialize RTEMS interrupt Management!!! System locked\n"); + } + +#ifdef TRACE_IRQ_INIT + printk("RTEMS IRQ management is now operational\n"); +#endif +} diff --git a/bsps/powerpc/shared/irq/openpic.c b/bsps/powerpc/shared/irq/openpic.c new file mode 100644 index 0000000000..556014964b --- /dev/null +++ b/bsps/powerpc/shared/irq/openpic.c @@ -0,0 +1,622 @@ +/* + * openpic.c -- OpenPIC Interrupt Handling + * + * Copyright (C) 1997 Geert Uytterhoeven + * + * Modified to compile in RTEMS development environment + * by Eric Valette + * + * Copyright (C) 1999 Eric Valette. valette@crf.canon.fr + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.org/license/LICENSE. + */ + +/* + * Note: Interprocessor Interrupt (IPI) and Timer support is incomplete + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifndef NULL +#define NULL 0 +#endif +#define REGISTER_DEBUG +#undef REGISTER_DEBUG + +volatile struct OpenPIC *OpenPIC = NULL; + +static unsigned int NumProcessors; +static unsigned int NumSources; + +static unsigned int openpic_eoi_delay = 0; +static int openpic_src_offst = 0; +#define SOURCE(irq) Source[ (irq) + openpic_src_offst ] + + /* + * Accesses to the current processor's registers + */ + +#define THIS_CPU Processor[cpu] +#define CHECK_THIS_CPU check_arg_cpu(cpu) + + /* + * Sanity checks + */ + +#if 1 +/* This software deliberately uses non-zero values to the method + * __builtin_return_address() and we want to avoid the GCC warning. + */ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wframe-address" +#define check_arg_ipi(ipi) \ + if (ipi < 0 || ipi >= OPENPIC_NUM_IPI) \ + printk("openpic.c:%d: illegal ipi %d\n", __LINE__, ipi); +#define check_arg_timer(timer) \ + if (timer < 0 || timer >= OPENPIC_NUM_TIMERS) \ + printk("openpic.c:%d: illegal timer %d\n", __LINE__, timer); +#define check_arg_vec(vec) \ + if (vec < 0 || vec >= OPENPIC_NUM_VECTORS) \ + printk("openpic.c:%d: illegal vector %d\n", __LINE__, vec); +#define check_arg_pri(pri) \ + if (pri < 0 || pri >= OPENPIC_NUM_PRI) \ + printk("openpic.c:%d: illegal priority %d\n", __LINE__, pri); +#define check_arg_irq(irq) \ + if (irq < 0 || irq >= NumSources) \ + printk("openpic.c:%d: illegal irq %d from 0x%08" PRIxPTR ",[0x%08" PRIxPTR "],[[0x%08" PRIxPTR "]]\n", \ + __LINE__, irq, (uintptr_t) __builtin_return_address(0), \ + (uintptr_t) __builtin_return_address(1), (uintptr_t) __builtin_return_address(2) \ + ); +#define check_arg_cpu(cpu) \ + if (cpu < 0 || cpu >= NumProcessors) \ + printk("openpic.c:%d: illegal cpu %d\n", __LINE__, cpu); +#else +#define check_arg_ipi(ipi) do {} while (0) +#define check_arg_timer(timer) do {} while (0) +#define check_arg_vec(vec) do {} while (0) +#define check_arg_pri(pri) do {} while (0) +#define check_arg_irq(irq) do {} while (0) +#define check_arg_cpu(cpu) do {} while (0) +#endif + + /* + * I/O functions + */ + +static inline unsigned int openpic_read(volatile unsigned int *addr) +{ + unsigned int val; + +#ifdef BSP_OPEN_PIC_BIG_ENDIAN + val = in_be32((volatile uint32_t *)addr); +#else + val = in_le32((volatile uint32_t *)addr); +#endif +#ifdef REGISTER_DEBUG + printk("openpic_read(0x%08x) = 0x%08x\n", (unsigned int)addr, val); +#endif + return val; +} + +static inline void openpic_write(volatile unsigned int *addr, unsigned int val) +{ +#ifdef REGISTER_DEBUG + printk("openpic_write(0x%08x, 0x%08x)\n", (unsigned int)addr, val); +#endif +#ifdef BSP_OPEN_PIC_BIG_ENDIAN + out_be32((volatile uint32_t *)addr, val); +#else + out_le32((volatile uint32_t *)addr, val); +#endif +} + +static inline unsigned int openpic_readfield(volatile unsigned int *addr, unsigned int mask) +{ + unsigned int val = openpic_read(addr); + return val & mask; +} + +static inline void openpic_writefield(volatile unsigned int *addr, unsigned int mask, + unsigned int field) +{ + unsigned int val = openpic_read(addr); + openpic_write(addr, (val & ~mask) | (field & mask)); +} + +static inline void openpic_clearfield(volatile unsigned int *addr, unsigned int mask) +{ + openpic_writefield(addr, mask, 0); +} + +static inline void openpic_setfield(volatile unsigned int *addr, unsigned int mask) +{ + openpic_writefield(addr, mask, mask); +} + + /* + * Update a Vector/Priority register in a safe manner. The interrupt will + * be disabled. + */ + +static void openpic_safe_writefield(volatile unsigned int *addr, unsigned int mask, + unsigned int field) +{ + openpic_setfield(addr, OPENPIC_MASK); + /* wait until it's not in use */ + while (openpic_read(addr) & OPENPIC_ACTIVITY); + openpic_writefield(addr, mask | OPENPIC_MASK, field | OPENPIC_MASK); +} + +/* -------- Global Operations ---------------------------------------------- */ + + /* + * Initialize the OpenPIC + * + * Add some kludge to use the Motorola Raven OpenPIC which does not + * report vendor and device id, and gets the wrong number of interrupts. + * (Motorola did a great job on that one!) + * + * T. Straumann, 12/20/2001: polarities and senses are now passed as + * parameters, eliminated global vars. + * IRQ0 is no longer treated specially. + */ + +void openpic_init(int main_pic, unsigned char *polarities, unsigned char *senses, int num_sources, int source_offset, unsigned long epic_freq) +{ + unsigned int t, i; + unsigned int vendorid, devid, stepping, timerfreq; + const char *version, *vendor, *device; + + if (!OpenPIC) + rtems_panic("No OpenPIC found"); + + t = openpic_read(&OpenPIC->Global.Feature_Reporting0); + switch (t & OPENPIC_FEATURE_VERSION_MASK) { + case 1: + version = "1.0"; + break; + case 2: + version = "1.2"; + break; + default: + version = "?"; + break; + } + NumProcessors = ((t & OPENPIC_FEATURE_LAST_PROCESSOR_MASK) >> + OPENPIC_FEATURE_LAST_PROCESSOR_SHIFT) + 1; + NumSources = ((t & OPENPIC_FEATURE_LAST_SOURCE_MASK) >> + OPENPIC_FEATURE_LAST_SOURCE_SHIFT) + 1; + t = openpic_read(&OpenPIC->Global.Vendor_Identification); + + vendorid = t & OPENPIC_VENDOR_ID_VENDOR_ID_MASK; + devid = (t & OPENPIC_VENDOR_ID_DEVICE_ID_MASK) >> + OPENPIC_VENDOR_ID_DEVICE_ID_SHIFT; + stepping = (t & OPENPIC_VENDOR_ID_STEPPING_MASK) >> + OPENPIC_VENDOR_ID_STEPPING_SHIFT; + + /* Kludge for the Raven */ +/* + pci_read_config_dword(0, 0, 0, 0, &t); +*/ + if (t == PCI_VENDOR_ID_MOTOROLA + (PCI_DEVICE_ID_MOTOROLA_RAVEN<<16)) { + vendor = "Motorola"; + device = "Raven"; + NumSources += 1; + } + else if (t == PCI_VENDOR_ID_MOTOROLA + (PCI_DEVICE_ID_MOTOROLA_HAWK<<16)) { + vendor = "Motorola"; + device = "Hawk"; + NumSources += 1; + } else { + switch (vendorid) { + case OPENPIC_VENDOR_ID_APPLE: + vendor = "Apple"; + break; + default: + vendor = "Unknown"; + break; + } + switch (devid) { + case OPENPIC_DEVICE_ID_APPLE_HYDRA: + device = "Hydra"; + break; + default: + device = "Unknown"; + break; + } + } + printk("OpenPIC Version %s (%d CPUs and %d IRQ sources) at 0x%08" PRIuPTR "\n", version, + NumProcessors, NumSources, (uintptr_t) OpenPIC); + + printk("OpenPIC Vendor %d (%s), Device %d (%s), Stepping %d\n", vendorid, + vendor, devid, device, stepping); + + /* Override if they desire */ + if ( num_sources ) { + if ( NumSources != num_sources ) + printk("Overriding NumSources (%i) from configuration with %i\n", + NumSources, num_sources); + NumSources = num_sources; + } + + openpic_src_offst = source_offset; + + timerfreq = openpic_read(&OpenPIC->Global.Timer_Frequency); + printk("OpenPIC timer frequency is "); + if (timerfreq) + printk("%d Hz\n", timerfreq); + else + printk("not set\n"); + + if ( main_pic ) + { + /* Initialize timer interrupts */ + for (i = 0; i < OPENPIC_NUM_TIMERS; i++) { + /* Disabled, Priority 0 */ + openpic_inittimer(i, 0, OPENPIC_VEC_TIMER+i); + /* No processor */ + openpic_maptimer(i, 0); + } + + /* Initialize IPI interrupts */ + for (i = 0; i < OPENPIC_NUM_IPI; i++) { + /* Disabled, Priority 0 */ + openpic_initipi(i, 0, OPENPIC_VEC_IPI+i); + } + + /* Initialize external interrupts */ + for (i = 0; i < NumSources; i++) { + /* Enabled, Priority 8 */ + openpic_initirq(i, 8, OPENPIC_VEC_SOURCE+i, + polarities ? polarities[i] : 0, + senses ? senses[i] : 1); + /* Processor 0 */ + openpic_mapirq(i, 1<<0); + } + + /* Initialize the spurious interrupt */ + openpic_set_spurious(OPENPIC_VEC_SPURIOUS); +#if 0 + if (request_irq(IRQ_8259_CASCADE, no_action, SA_INTERRUPT, + "82c59 cascade", NULL)) + printk("Unable to get OpenPIC IRQ 0 for cascade\n"); +#endif + openpic_set_priority(0, 0); + openpic_disable_8259_pass_through(); + } + if ( epic_freq ) { + /* Speed up the serial interface; if it is too slow then we might get spurious + * interrupts: + * After an ISR clears the interrupt condition at the source/device, the wire + * remains asserted during the propagation delay introduced by the serial interface + * (something really stupid). If the ISR returns while the wire is not released + * yet, then a spurious interrupt happens. + * The book says we should be careful if the serial clock is > 33MHz. + * Empirically, it seems that running it at 33MHz is fast enough. Otherwise, + * we should introduce a delay in openpic_eoi(). + * The maximal delay are 16 (serial) clock cycles. If the divisor is 8 + * [power-up default] then the lag is 2us [66MHz SDRAM clock; I assume this + * is equal to the bus frequency]. + * FIXME: This should probably be a EPIC-specific piece in 'openpic.c' + * Unfortunately, there is no easy way of figuring out if the + * device is an EPIC or not. + */ + uint32_t eicr_val, ratio; + /* On the 8240 this is the EICR register */ + eicr_val = in_le32( (volatile uint32_t *)&OpenPIC->Global.Global_Configuration1 ) & ~(7<<28); + if ( (1<<27) & eicr_val ) { + /* serial interface mode enabled */ + + /* round to nearest integer: + * round(Bus_freq/33000000) = floor( 2*(Bus_freq/33e6) + 1 ) / 2 + */ + ratio = epic_freq / 16500000 + 1; + ratio >>= 2; /* EICR value is half actual divisor */ + if ( 0==ratio ) + ratio = 1; + out_le32((volatile uint32_t *)&OpenPIC->Global.Global_Configuration1, eicr_val | ((ratio &7) << 28)); + /* Delay in TB cycles (assuming TB runs at 1/4 of the bus frequency) */ + openpic_set_eoi_delay( 16 * (2*ratio) / 4 ); + } + } +} + + /* + * Reset the OpenPIC + */ + +void openpic_reset(void) +{ + openpic_setfield(&OpenPIC->Global.Global_Configuration0, + OPENPIC_CONFIG_RESET); +} + + /* + * Enable/disable 8259 Pass Through Mode + */ + +void openpic_enable_8259_pass_through(void) +{ + openpic_clearfield(&OpenPIC->Global.Global_Configuration0, + OPENPIC_CONFIG_8259_PASSTHROUGH_DISABLE); +} + +void openpic_disable_8259_pass_through(void) +{ + openpic_setfield(&OpenPIC->Global.Global_Configuration0, + OPENPIC_CONFIG_8259_PASSTHROUGH_DISABLE); +} + + /* + * Find out the current interrupt + */ + +unsigned int openpic_irq(unsigned int cpu) +{ + unsigned int vec; + + check_arg_cpu(cpu); + vec = openpic_readfield(&OpenPIC->THIS_CPU.Interrupt_Acknowledge, + OPENPIC_VECTOR_MASK); + return vec; +} + + /* + * Signal end of interrupt (EOI) processing + */ + +void openpic_eoi(unsigned int cpu) +{ + check_arg_cpu(cpu); + if ( openpic_eoi_delay ) + rtems_bsp_delay_in_bus_cycles(openpic_eoi_delay); + openpic_write(&OpenPIC->THIS_CPU.EOI, 0); +} + +unsigned openpic_set_eoi_delay(unsigned tb_cycles) +{ +unsigned rval = openpic_eoi_delay; + openpic_eoi_delay = tb_cycles; + return rval; +} + + /* + * Get/set the current task priority + */ + +unsigned int openpic_get_priority(unsigned int cpu) +{ + CHECK_THIS_CPU; + return openpic_readfield(&OpenPIC->THIS_CPU.Current_Task_Priority, + OPENPIC_CURRENT_TASK_PRIORITY_MASK); +} + +void openpic_set_priority(unsigned int cpu, unsigned int pri) +{ + CHECK_THIS_CPU; + check_arg_pri(pri); + openpic_writefield(&OpenPIC->THIS_CPU.Current_Task_Priority, + OPENPIC_CURRENT_TASK_PRIORITY_MASK, pri); +} + + /* + * Get/set the spurious vector + */ + +unsigned int openpic_get_spurious(void) +{ + return openpic_readfield(&OpenPIC->Global.Spurious_Vector, + OPENPIC_VECTOR_MASK); +} + +void openpic_set_spurious(unsigned int vec) +{ + check_arg_vec(vec); + openpic_writefield(&OpenPIC->Global.Spurious_Vector, OPENPIC_VECTOR_MASK, + vec); +} + + /* + * Initialize one or more CPUs + */ + +void openpic_init_processor(unsigned int cpumask) +{ + openpic_write(&OpenPIC->Global.Processor_Initialization, cpumask); +} + +/* -------- Interprocessor Interrupts -------------------------------------- */ + + /* + * Initialize an interprocessor interrupt (and disable it) + * + * ipi: OpenPIC interprocessor interrupt number + * pri: interrupt source priority + * vec: the vector it will produce + */ + +void openpic_initipi(unsigned int ipi, unsigned int pri, unsigned int vec) +{ + check_arg_timer(ipi); + check_arg_pri(pri); + check_arg_vec(vec); + openpic_safe_writefield(&OpenPIC->Global.IPI_Vector_Priority(ipi), + OPENPIC_PRIORITY_MASK | OPENPIC_VECTOR_MASK, + (pri << OPENPIC_PRIORITY_SHIFT) | vec); +} + + /* + * Send an IPI to one or more CPUs + */ + +void openpic_cause_IPI(unsigned int cpu, unsigned int ipi, unsigned int cpumask) +{ + CHECK_THIS_CPU; + check_arg_ipi(ipi); + openpic_write(&OpenPIC->THIS_CPU.IPI_Dispatch(ipi), cpumask); +} + +/* -------- Timer Interrupts ----------------------------------------------- */ + + /* + * Initialize a timer interrupt (and disable it) + * + * timer: OpenPIC timer number + * pri: interrupt source priority + * vec: the vector it will produce + */ + +void openpic_inittimer(unsigned int timer, unsigned int pri, unsigned int vec) +{ + check_arg_timer(timer); + check_arg_pri(pri); + check_arg_vec(vec); + openpic_safe_writefield(&OpenPIC->Global.Timer[timer].Vector_Priority, + OPENPIC_PRIORITY_MASK | OPENPIC_VECTOR_MASK, + (pri << OPENPIC_PRIORITY_SHIFT) | vec); +} + + /* + * Map a timer interrupt to one or more CPUs + */ + +void openpic_maptimer(unsigned int timer, unsigned int cpumask) +{ + check_arg_timer(timer); + openpic_write(&OpenPIC->Global.Timer[timer].Destination, cpumask); +} + + /* + * Set base count and / or enable / disable interrupt. + */ + + +void openpic_settimer(unsigned int timer, unsigned int base_count, int irq_enable) +{ + check_arg_timer(timer); + if ( base_count ) + openpic_write(&OpenPIC->Global.Timer[timer].Base_Count, base_count); + if ( irq_enable ) + openpic_clearfield(&OpenPIC->Global.Timer[timer].Vector_Priority, OPENPIC_MASK); + else + openpic_setfield(&OpenPIC->Global.Timer[timer].Vector_Priority, OPENPIC_MASK); +} + +unsigned int openpic_gettimer(unsigned int timer) +{ + check_arg_timer(timer); + return (openpic_read(&OpenPIC->Global.Timer[timer].Current_Count) & ~OPENPIC_MASK); +} + +/* -------- Interrupt Sources ---------------------------------------------- */ + + /* + * Enable/disable an interrupt source + */ + +void openpic_enable_irq(unsigned int irq) +{ +unsigned long flags; + check_arg_irq(irq); + rtems_interrupt_disable(flags); + openpic_clearfield(&OpenPIC->SOURCE(irq).Vector_Priority, OPENPIC_MASK); + rtems_interrupt_enable(flags); +} + +int openpic_disable_irq(unsigned int irq) +{ +int rval; +unsigned long flags; + check_arg_irq(irq); + if ( irq < 0 || irq >=NumSources ) + return -1; + rtems_interrupt_disable(flags); + rval = openpic_readfield(&OpenPIC->SOURCE(irq).Vector_Priority, OPENPIC_MASK) ? 0 : 1; + openpic_setfield(&OpenPIC->SOURCE(irq).Vector_Priority, OPENPIC_MASK); + rtems_interrupt_enable(flags); + return rval; +} + + /* + * Initialize an interrupt source (and disable it!) + * + * irq: OpenPIC interrupt number + * pri: interrupt source priority + * vec: the vector it will produce + * pol: polarity (1 for positive, 0 for negative) + * sense: 1 for level, 0 for edge + */ + +void openpic_initirq(unsigned int irq, unsigned int pri, unsigned int vec, int pol, int sense) +{ +#if 0 + printk("openpic_initirq: irq=%d pri=%d vec=%d pol=%d sense=%d\n", + irq, pri, vec, pol, sense); +#endif + + check_arg_irq(irq); + check_arg_pri(pri); + check_arg_vec(vec); + openpic_safe_writefield(&OpenPIC->SOURCE(irq).Vector_Priority, + OPENPIC_PRIORITY_MASK | OPENPIC_VECTOR_MASK | + OPENPIC_SENSE_POLARITY | OPENPIC_SENSE_LEVEL, + (pri << OPENPIC_PRIORITY_SHIFT) | vec | + (pol ? OPENPIC_SENSE_POLARITY : 0) | + (sense ? OPENPIC_SENSE_LEVEL : 0)); +} + + /* + * Map an interrupt source to one or more CPUs + */ + +void openpic_mapirq(unsigned int irq, unsigned int cpumask) +{ + check_arg_irq(irq); + openpic_write(&OpenPIC->SOURCE(irq).Destination, cpumask); +} + + /* + * Get the current priority of an external interrupt + */ +unsigned int openpic_get_source_priority(unsigned int irq) +{ + check_arg_irq(irq); + return openpic_readfield(&OpenPIC->SOURCE(irq).Vector_Priority, + OPENPIC_PRIORITY_MASK) >> OPENPIC_PRIORITY_SHIFT; +} + +void openpic_set_source_priority(unsigned int irq, unsigned int pri) +{ +unsigned long flags; + check_arg_irq(irq); + check_arg_pri(pri); + rtems_interrupt_disable(flags); + openpic_writefield( + &OpenPIC->SOURCE(irq).Vector_Priority, + OPENPIC_PRIORITY_MASK, + pri << OPENPIC_PRIORITY_SHIFT); + rtems_interrupt_enable(flags); +} + /* + * Set the sense for an interrupt source (and disable it!) + * + * sense: 1 for level, 0 for edge + */ + +void openpic_set_sense(unsigned int irq, int sense) +{ + check_arg_irq(irq); + openpic_safe_writefield(&OpenPIC->SOURCE(irq).Vector_Priority, + OPENPIC_SENSE_LEVEL, + (sense ? OPENPIC_SENSE_LEVEL : 0)); +} diff --git a/bsps/powerpc/shared/irq/openpic_i8259_irq.c b/bsps/powerpc/shared/irq/openpic_i8259_irq.c new file mode 100644 index 0000000000..4a9c393f7f --- /dev/null +++ b/bsps/powerpc/shared/irq/openpic_i8259_irq.c @@ -0,0 +1,331 @@ +/* + * + * This file contains the i8259/openpic-specific implementation of + * the function described in irq.h + * + * Copyright (C) 1998, 1999 valette@crf.canon.fr + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.org/license/LICENSE. + */ + +#include + +#include +#include +#include +#ifndef BSP_HAS_NO_VME +#include +#endif +#if BSP_PCI_IRQ_NUMBER > 0 +#include +#endif +#include +#include +#include + +#include /* for printk */ + +#ifndef qemu +#define RAVEN_INTR_ACK_REG 0xfeff0030 +#else +#define RAVEN_INTR_ACK_REG 0xbffffff0 +#endif + +#if BSP_ISA_IRQ_NUMBER > 0 +/* + * pointer to the mask representing the additionnal irq vectors + * that must be disabled when a particular entry is activated. + * They will be dynamically computed from the priority table given + * in BSP_rtems_irq_mngt_set(); + * CAUTION : this table is accessed directly by interrupt routine + * prologue. + */ +rtems_i8259_masks irq_mask_or_tbl[BSP_IRQ_NUMBER]; +#endif + +/* + * default handler connected on each irq after bsp initialization + */ +static rtems_irq_connect_data default_rtems_entry; + +static rtems_irq_connect_data* rtems_hdl_tbl; + +#if BSP_ISA_IRQ_NUMBER > 0 +/* + * Check if IRQ is an ISA IRQ + */ +static inline int is_isa_irq(const rtems_irq_number irqLine) +{ + return (((int) irqLine <= BSP_ISA_IRQ_MAX_OFFSET) && + ((int) irqLine >= BSP_ISA_IRQ_LOWEST_OFFSET) + ); +} +#endif + +#if BSP_PCI_IRQ_NUMBER > 0 +/* + * Check if IRQ is an OPENPIC IRQ + */ +static inline int is_pci_irq(const rtems_irq_number irqLine) +{ + return OpenPIC && (((int) irqLine <= BSP_PCI_IRQ_MAX_OFFSET) && + ((int) irqLine >= BSP_PCI_IRQ_LOWEST_OFFSET) + ); +} +#endif + +/* + * ------------------------ RTEMS Irq helper functions ---------------- + */ + +#if BSP_ISA_IRQ_NUMBER > 0 +/* + * Caution : this function assumes the variable "*config" + * is already set and that the tables it contains are still valid + * and accessible. + */ +static void compute_i8259_masks_from_prio (rtems_irq_global_settings* config) +{ + int i; + int j; + /* + * Always mask at least current interrupt to prevent re-entrance + */ + for (i=BSP_ISA_IRQ_LOWEST_OFFSET; i < BSP_ISA_IRQ_LOWEST_OFFSET + BSP_ISA_IRQ_NUMBER; i++) { + * ((unsigned short*) &irq_mask_or_tbl[i]) = (1 << i); + for (j = BSP_ISA_IRQ_LOWEST_OFFSET; j < BSP_ISA_IRQ_LOWEST_OFFSET + BSP_ISA_IRQ_NUMBER; j++) { + /* + * Mask interrupts at i8259 level that have a lower priority + */ + if (config->irqPrioTbl [i] > config->irqPrioTbl [j]) { + * ((unsigned short*) &irq_mask_or_tbl[i]) |= (1 << j); + } + } + } +} +#endif + +void +BSP_enable_irq_at_pic(const rtems_irq_number name) +{ +#if BSP_ISA_IRQ_NUMBER > 0 + if (is_isa_irq(name)) { + /* + * Enable interrupt at PIC level + */ + BSP_irq_enable_at_i8259s ((int) name - BSP_ISA_IRQ_LOWEST_OFFSET); + } +#endif + +#if BSP_PCI_IRQ_NUMBER > 0 + if (is_pci_irq(name)) { + /* + * Enable interrupt at OPENPIC level + */ + openpic_enable_irq ((int) name - BSP_PCI_IRQ_LOWEST_OFFSET); + } +#endif +} + +int +BSP_disable_irq_at_pic(const rtems_irq_number name) +{ +#if BSP_ISA_IRQ_NUMBER > 0 + if (is_isa_irq(name)) { + /* + * disable interrupt at PIC level + */ + return BSP_irq_disable_at_i8259s ((int) name - BSP_ISA_IRQ_LOWEST_OFFSET); + } +#endif +#if BSP_PCI_IRQ_NUMBER > 0 + if (is_pci_irq(name)) { + /* + * disable interrupt at OPENPIC level + */ + return openpic_disable_irq ((int) name - BSP_PCI_IRQ_LOWEST_OFFSET); + } +#endif + return -1; +} + +/* + * RTEMS Global Interrupt Handler Management Routines + */ +int BSP_setup_the_pic(rtems_irq_global_settings* config) +{ + int i; + /* + * Store various code accelerators + */ + default_rtems_entry = config->defaultEntry; + rtems_hdl_tbl = config->irqHdlTbl; + + /* + * set up internal tables used by rtems interrupt prologue + */ + +#if BSP_ISA_IRQ_NUMBER > 0 + /* + * start with ISA IRQ + */ + compute_i8259_masks_from_prio (config); + + for (i=BSP_ISA_IRQ_LOWEST_OFFSET; i < BSP_ISA_IRQ_LOWEST_OFFSET + BSP_ISA_IRQ_NUMBER; i++) { + if (rtems_hdl_tbl[i].hdl != default_rtems_entry.hdl) { + BSP_irq_enable_at_i8259s (i); + } + else { + BSP_irq_disable_at_i8259s (i); + } + } + + if ( BSP_ISA_IRQ_NUMBER > 0 ) { + /* + * must enable slave pic anyway + */ + BSP_irq_enable_at_i8259s (2); + } +#endif + +#if BSP_PCI_IRQ_NUMBER > 0 + if ( ! OpenPIC ) + return 1; + /* + * continue with PCI IRQ + */ + for (i=BSP_PCI_IRQ_LOWEST_OFFSET; i < BSP_PCI_IRQ_LOWEST_OFFSET + BSP_PCI_IRQ_NUMBER ; i++) { + /* + * Note that openpic_set_priority() sets the TASK priority of the PIC + */ + openpic_set_source_priority(i - BSP_PCI_IRQ_LOWEST_OFFSET, + config->irqPrioTbl[i]); + if (rtems_hdl_tbl[i].hdl != default_rtems_entry.hdl) { + openpic_enable_irq ((int) i - BSP_PCI_IRQ_LOWEST_OFFSET); + } + else { + openpic_disable_irq ((int) i - BSP_PCI_IRQ_LOWEST_OFFSET); + } + } + +#ifdef BSP_PCI_ISA_BRIDGE_IRQ + /* + * Must enable PCI/ISA bridge IRQ + */ + openpic_enable_irq (BSP_PCI_ISA_BRIDGE_IRQ); +#endif +#endif + + return 1; +} + +int _BSP_vme_bridge_irq = -1; + +unsigned BSP_spuriousIntr = 0; + +/* + * High level IRQ handler called from shared_raw_irq_code_entry + */ +int C_dispatch_irq_handler (BSP_Exception_frame *frame, unsigned int excNum) +{ + register unsigned int irq; +#if BSP_ISA_IRQ_NUMBER > 0 + register unsigned isaIntr; /* boolean */ + register unsigned oldMask = 0; /* old isa pic masks */ + register unsigned newMask; /* new isa pic masks */ +#endif + + if (excNum == ASM_DEC_VECTOR) { + + bsp_irq_dispatch_list(rtems_hdl_tbl, BSP_DECREMENTER, default_rtems_entry.hdl); + + return 0; + + } + +#if BSP_PCI_IRQ_NUMBER > 0 + if ( OpenPIC ) { + irq = openpic_irq(0); + if (irq == OPENPIC_VEC_SPURIOUS) { + ++BSP_spuriousIntr; + return 0; + } + + /* some BSPs might want to use a different numbering... */ + irq = irq - OPENPIC_VEC_SOURCE + BSP_PCI_IRQ_LOWEST_OFFSET; + } else { +#if BSP_ISA_IRQ_NUMBER > 0 +#ifdef BSP_PCI_ISA_BRIDGE_IRQ + irq = BSP_PCI_ISA_BRIDGE_IRQ; +#else +#error "Configuration Error -- BSP with ISA + PCI IRQs MUST define BSP_PCI_ISA_BRIDGE_IRQ" +#endif +#else + rtems_panic("MUST have an OpenPIC if BSP has PCI IRQs but no ISA IRQs"); + /* rtems_panic() never returns but the 'return' statement silences + * a compiler warning about 'irq' possibly being used w/o initialization. + */ + return -1; +#endif + } +#endif + +#if BSP_ISA_IRQ_NUMBER > 0 +#ifdef BSP_PCI_ISA_BRIDGE_IRQ +#if 0 == BSP_PCI_IRQ_NUMBER +#error "Configuration Error -- BSP w/o PCI IRQs MUST NOT define BSP_PCI_ISA_BRIDGE_IRQ" +#endif + isaIntr = (irq == BSP_PCI_ISA_BRIDGE_IRQ); +#else + isaIntr = 1; +#endif + if (isaIntr) { + /* + * Acknowledge and read 8259 vector + */ + irq = (unsigned int) (*(unsigned char *) RAVEN_INTR_ACK_REG); + /* + * store current PIC mask + */ + oldMask = i8259s_cache; + newMask = oldMask | irq_mask_or_tbl [irq]; + i8259s_cache = newMask; + outport_byte(PIC_MASTER_IMR_IO_PORT, i8259s_cache & 0xff); + outport_byte(PIC_SLAVE_IMR_IO_PORT, ((i8259s_cache & 0xff00) >> 8)); + BSP_irq_ack_at_i8259s (irq); +#if BSP_PCI_IRQ_NUMBER > 0 + if ( OpenPIC ) + openpic_eoi(0); +#endif + } +#endif + + /* dispatch handlers */ + bsp_irq_dispatch_list(rtems_hdl_tbl, irq, default_rtems_entry.hdl); + +#if BSP_ISA_IRQ_NUMBER > 0 + if (isaIntr) { + i8259s_cache = oldMask; + outport_byte(PIC_MASTER_IMR_IO_PORT, i8259s_cache & 0xff); + outport_byte(PIC_SLAVE_IMR_IO_PORT, ((i8259s_cache & 0xff00) >> 8)); + } + else +#endif + { +#if BSP_PCI_IRQ_NUMBER > 0 +#ifdef BSP_PCI_VME_DRIVER_DOES_EOI + /* leave it to the VME bridge driver to do EOI, so + * it can re-enable the openpic while handling + * VME interrupts (-> VME priorities in software) + */ + if (_BSP_vme_bridge_irq != irq && OpenPIC) +#endif + openpic_eoi(0); +#else + do {} while (0); +#endif + } + return 0; +} diff --git a/bsps/powerpc/t32mppc/irq/irq.c b/bsps/powerpc/t32mppc/irq/irq.c new file mode 100644 index 0000000000..5b2c34d2c9 --- /dev/null +++ b/bsps/powerpc/t32mppc/irq/irq.c @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2012, 2017 embedded brains GmbH. All rights reserved. + * + * embedded brains GmbH + * Dornierstr. 4 + * 82178 Puchheim + * Germany + * + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.org/license/LICENSE. + */ + +#include +#include +#include + +void bsp_interrupt_vector_enable(rtems_vector_number vector) +{ + bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector)); +} + +void bsp_interrupt_dispatch(uintptr_t exception_number) +{ + if (exception_number == 10) { + t32mppc_decrementer_dispatch(); + } else { + bsp_interrupt_handler_default(0); + } +} + +void bsp_interrupt_vector_disable(rtems_vector_number vector) +{ + bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector)); +} + +rtems_status_code bsp_interrupt_facility_initialize(void) +{ + return RTEMS_SUCCESSFUL; +} diff --git a/bsps/powerpc/tqm8xx/irq/irq.c b/bsps/powerpc/tqm8xx/irq/irq.c new file mode 100644 index 0000000000..2a94c27d1b --- /dev/null +++ b/bsps/powerpc/tqm8xx/irq/irq.c @@ -0,0 +1,231 @@ +/*===============================================================*\ +| Project: RTEMS TQM8xx BSP | ++-----------------------------------------------------------------+ +| This file has been adapted to MPC8xx by | +| Thomas Doerfler | +| Copyright (c) 2008 | +| Embedded Brains GmbH | +| Obere Lagerstr. 30 | +| D-82178 Puchheim | +| Germany | +| rtems@embedded-brains.de | +| | +| See the other copyright notice below for the original parts. | ++-----------------------------------------------------------------+ +| The license and distribution terms for this file may be | +| found in the file LICENSE in this distribution or at | +| | +| http://www.rtems.org/license/LICENSE. | +| | ++-----------------------------------------------------------------+ +| this file contains the console driver | +\*===============================================================*/ +/* derived from: generic MPC83xx BSP */ + +#include +#include + +#include +#include + +#include +#include +#include +/* + * functions to enable/disable a source at the SIU/CPM irq controller + */ + +static rtems_status_code bsp_irq_disable_at_SIU(rtems_vector_number irqnum) +{ + rtems_vector_number vecnum = irqnum - BSP_SIU_IRQ_LOWEST_OFFSET; + m8xx.simask &= ~(1 << (31 - vecnum)); + return RTEMS_SUCCESSFUL; +} + +static rtems_status_code bsp_irq_enable_at_SIU(rtems_vector_number irqnum) +{ + rtems_vector_number vecnum = irqnum - BSP_SIU_IRQ_LOWEST_OFFSET; + m8xx.simask |= (1 << (31 - vecnum)); + return RTEMS_SUCCESSFUL; +} + +static rtems_status_code bsp_irq_disable_at_CPM(rtems_vector_number irqnum) +{ + rtems_vector_number vecnum = irqnum - BSP_CPM_IRQ_LOWEST_OFFSET; + m8xx.cimr &= ~(1 << (vecnum)); + return RTEMS_SUCCESSFUL; +} + +static rtems_status_code bsp_irq_enable_at_CPM(rtems_vector_number irqnum) +{ + rtems_vector_number vecnum = irqnum - BSP_CPM_IRQ_LOWEST_OFFSET; + m8xx.cimr |= (1 << (vecnum)); + return RTEMS_SUCCESSFUL; +} + +void bsp_interrupt_vector_enable(rtems_vector_number vector) +{ + bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector)); + + if (BSP_IS_CPM_IRQ(vector)) { + bsp_irq_enable_at_CPM(vector); + } else if (BSP_IS_SIU_IRQ(vector)) { + bsp_irq_enable_at_SIU(vector); + } +} + +void bsp_interrupt_vector_disable(rtems_vector_number vector) +{ + bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector)); + + if (BSP_IS_CPM_IRQ(vector)) { + bsp_irq_disable_at_CPM(vector); + } else if (BSP_IS_SIU_IRQ(vector)) { + bsp_irq_disable_at_SIU(vector); + } +} + +/* + * IRQ Handler: this is called from the primary exception dispatcher + */ +static int BSP_irq_handle_at_cpm(void) +{ + int32_t cpvecnum; + uint32_t msr; + + /* Get vector number: write IACK=1, then read vectir */ + m8xx.civr = 1; + cpvecnum = (m8xx.civr >> 11) + BSP_CPM_IRQ_LOWEST_OFFSET; + + /* + * Check the vector number, + * enable exceptions and dispatch the handler. + * NOTE: lower-prio interrupts are automatically masked in CPIC + */ + if (BSP_IS_CPM_IRQ(cpvecnum)) { + /* Enable all interrupts */ + msr = ppc_external_exceptions_enable(); + /* Dispatch interrupt handlers */ + bsp_interrupt_handler_dispatch(cpvecnum); + /* Restore machine state */ + ppc_external_exceptions_disable(msr); + } + else { + /* not valid vector */ + bsp_interrupt_handler_default(cpvecnum); + } + /* + * clear "in-service" bit + */ + m8xx.cisr = 1 << (cpvecnum - BSP_CPM_IRQ_LOWEST_OFFSET); + + return 0; +} + +static int BSP_irq_handle_at_siu( unsigned excNum) +{ + int32_t sivecnum; + uint32_t msr; + bool is_cpm_irq; + uint32_t simask_save; + /* + * check, if interrupt is pending + * and repeat as long as valid interrupts are pending + */ + while (0 != (m8xx.simask & m8xx.sipend)) { + /* Get vector number */ + sivecnum = (m8xx.sivec >> 26); + is_cpm_irq = (sivecnum == BSP_CPM_INTERRUPT); + /* + * Check the vector number, mask lower priority interrupts, enable + * exceptions and dispatch the handler. + */ + if (BSP_IS_SIU_IRQ(sivecnum)) { + simask_save = m8xx.simask; + /* + * if this is the CPM interrupt, mask lower prio interrupts at SIU + * else mask lower and same priority interrupts + */ + m8xx.simask &= ~0 << (32 + - sivecnum + - ((is_cpm_irq) ? 1 : 0)); + + if (is_cpm_irq) { + BSP_irq_handle_at_cpm(); + } + else { + /* Enable all interrupts */ + msr = ppc_external_exceptions_enable(); + /* Dispatch interrupt handlers */ + bsp_interrupt_handler_dispatch(sivecnum + BSP_SIU_IRQ_LOWEST_OFFSET); + /* Restore machine state */ + ppc_external_exceptions_disable(msr); + /* + * clear pending bit, if edge triggered interrupt input + */ + m8xx.sipend = 1 << (31 - sivecnum); + } + + + /* Restore initial masks */ + m8xx.simask = simask_save; + } else { + /* not valid vector */ + bsp_interrupt_handler_default(sivecnum); + } + } + return 0; +} + +/* + * Activate the CPIC + */ +static rtems_status_code mpc8xx_cpic_initialize( void) +{ + /* + * mask off all interrupts + */ + m8xx.cimr = 0; + /* + * make sure CPIC request proper level at SIU interrupt controller + */ + m8xx.cicr = (0x00e41f80 | + ((BSP_CPM_INTERRUPT/2) << 13)); + /* + * enable CPIC interrupt in SIU interrupt controller + */ + return bsp_irq_enable_at_SIU(BSP_CPM_INTERRUPT); +} + +/* + * Activate the SIU interrupt controller + */ +static rtems_status_code mpc8xx_siu_int_initialize( void) +{ + /* + * mask off all interrupts + */ + m8xx.simask = 0; + + return RTEMS_SUCCESSFUL; +} + +static int mpc8xx_exception_handler(BSP_Exception_frame *frame, + unsigned exception_number) +{ + return BSP_irq_handle_at_siu(exception_number); +} + +rtems_status_code bsp_interrupt_facility_initialize() +{ + /* Install exception handler */ + if (ppc_exc_set_handler(ASM_EXT_VECTOR, mpc8xx_exception_handler)) { + return RTEMS_IO_ERROR; + } + /* Initialize the SIU interrupt controller */ + if (mpc8xx_siu_int_initialize()) { + return RTEMS_IO_ERROR; + } + /* Initialize the CPIC interrupt controller */ + return mpc8xx_cpic_initialize(); +} diff --git a/bsps/powerpc/virtex/irq/irq_init.c b/bsps/powerpc/virtex/irq/irq_init.c new file mode 100644 index 0000000000..55194cb1e6 --- /dev/null +++ b/bsps/powerpc/virtex/irq/irq_init.c @@ -0,0 +1,167 @@ +/*===============================================================*\ +| Project: RTEMS virtex BSP | ++-----------------------------------------------------------------+ +| Partially based on the code references which are named below. | +| Adaptions, modifications, enhancements and any recent parts of | +| the code are: | +| Copyright (c) 2007 | +| Embedded Brains GmbH | +| Obere Lagerstr. 30 | +| D-82178 Puchheim | +| Germany | +| rtems@embedded-brains.de | ++-----------------------------------------------------------------+ +| The license and distribution terms for this file may be | +| found in the file LICENSE in this distribution or at | +| | +| http://www.rtems.org/license/LICENSE. | +| | ++-----------------------------------------------------------------+ +| this file contains the irq controller handler | +\*===============================================================*/ + +/* Content moved from opbintctrl.c: + * + * This file contains definitions and declarations for the + * Xilinx Off Processor Bus (OPB) Interrupt Controller + * + * Author: Keith Robertson + * COPYRIGHT (c) 2005 Linn Products Ltd, Scotland. + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.org/license/LICENSE. + */ + +#include +#include +#include +#include + +#include + +/* + * Acknowledge a mask of interrupts. + */ +static void set_iar(uint32_t mask) +{ + *((volatile uint32_t *) (OPB_INTC_BASE + OPB_INTC_IAR)) = mask; +} + +/* + * Set IER state. Used to (dis)enable a mask of vectors. + * If you only have to do one, use enable/disable_vector. + */ +static void set_ier(uint32_t mask) +{ + *((volatile uint32_t *) (OPB_INTC_BASE + OPB_INTC_IER)) = mask; +} + +/* + * Retrieve contents of Interrupt Pending Register + */ +static uint32_t get_ipr(void) +{ + uint32_t c = *((volatile uint32_t *) (OPB_INTC_BASE + OPB_INTC_IPR)); + return c; +} + +static void BSP_irq_enable_at_opbintc (rtems_irq_number irqnum) +{ + *((volatile uint32_t *) (OPB_INTC_BASE + OPB_INTC_SIE)) + = 1 << (irqnum - BSP_OPBINTC_IRQ_LOWEST_OFFSET); +} + +static void BSP_irq_disable_at_opbintc (rtems_irq_number irqnum) +{ + *((volatile uint32_t *) (OPB_INTC_BASE + OPB_INTC_CIE)) + = 1 << (irqnum - BSP_OPBINTC_IRQ_LOWEST_OFFSET); +} + +/* + * IRQ Handler: this is called from the primary exception dispatcher + */ +static void BSP_irq_handle_at_opbintc(void) +{ + uint32_t ipr; + + /* Get pending interrupts */ + ipr = get_ipr(); + + if (ipr != 0) { + /* Acknowledge all pending interrupts now and service them afterwards */ + set_iar(ipr); + + do { + /* Get highest priority pending interrupt */ + uint32_t i = 31 - ppc_count_leading_zeros(ipr); + + ipr &= ~(1U << i); + + bsp_interrupt_handler_dispatch(i+BSP_OPBINTC_IRQ_LOWEST_OFFSET); + } while (ipr != 0); + } +} + +/* + * activate the interrupt controller + */ +static void opb_intc_init(void) +{ + uint32_t i, mask = 0; + + /* mask off all interrupts */ + set_ier(0x0); + + for (i = 0; i < OPB_INTC_IRQ_MAX; i++) { + mask |= (1 << i); + } + + /* make sure interupt status register is clear before we enable the interrupt controller */ + *((volatile uint32_t *) (OPB_INTC_BASE + OPB_INTC_ISR)) = 0; + + /* acknowledge all interrupt sources */ + set_iar(mask); + + /* Turn on normal hardware operation of interrupt controller */ + *((volatile uint32_t *) (OPB_INTC_BASE + OPB_INTC_MER)) = + (OPB_INTC_MER_HIE); + + /* Enable master interrupt switch for the interrupt controller */ + *((volatile uint32_t *) (OPB_INTC_BASE + OPB_INTC_MER)) = + (OPB_INTC_MER_HIE | OPB_INTC_MER_ME); +} + +void bsp_interrupt_vector_enable(rtems_vector_number vector) +{ + bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector)); + + if (BSP_IS_OPBINTC_IRQ(vector)) { + BSP_irq_enable_at_opbintc(vector); + } +} + +void bsp_interrupt_vector_disable(rtems_vector_number vector) +{ + bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector)); + + if (BSP_IS_OPBINTC_IRQ(vector)) { + BSP_irq_disable_at_opbintc(vector); + } +} + +static int C_dispatch_irq_handler(BSP_Exception_frame *frame, unsigned int excNum) +{ + BSP_irq_handle_at_opbintc(); + + return 0; +} + +rtems_status_code bsp_interrupt_facility_initialize(void) +{ + opb_intc_init(); + + ppc_exc_set_handler(ASM_EXT_VECTOR, C_dispatch_irq_handler); + + return RTEMS_SUCCESSFUL; +} diff --git a/bsps/powerpc/virtex4/irq/irq_init.c b/bsps/powerpc/virtex4/irq/irq_init.c new file mode 100644 index 0000000000..5feafaf4b6 --- /dev/null +++ b/bsps/powerpc/virtex4/irq/irq_init.c @@ -0,0 +1,326 @@ +/*===============================================================*\ +| Project: RTEMS virtex BSP | ++-----------------------------------------------------------------+ +| Partially based on the code references which are named below. | +| Adaptions, modifications, enhancements and any recent parts of | +| the code are: | +| Copyright (c) 2007 | +| Embedded Brains GmbH | +| Obere Lagerstr. 30 | +| D-82178 Puchheim | +| Germany | +| rtems@embedded-brains.de | ++-----------------------------------------------------------------+ +| The license and distribution terms for this file may be | +| found in the file LICENSE in this distribution or at | +| | +| http://www.rtems.org/license/LICENSE. | +| | ++-----------------------------------------------------------------+ +| this file contains the irq controller handler | +\*===============================================================*/ +#include +#include +#include +#include +#include +#include + +static rtems_irq_connect_data rtemsIrqTbl[BSP_IRQ_NUMBER]; +rtems_irq_connect_data *BSP_rtems_irq_tbl; +rtems_irq_global_settings* BSP_rtems_irq_config; + +/*********************************************************** + * dummy functions for on/off/isOn calls + * these functions just do nothing fulfill the semantic + * requirements to enable/disable a certain interrupt or exception + */ +static void BSP_irq_nop_func(const rtems_irq_connect_data *unused) +{ + /* + * nothing to do + */ +} + +static void BSP_irq_nop_hdl(void *hdl) +{ + /* + * nothing to do + */ +} + +static int BSP_irq_isOn_func(const rtems_irq_connect_data *unused) +{ + /* + * nothing to do + */ + return 0; +} + +/*********************************************************** + * interrupt handler and its enable/disable functions + ***********************************************************/ + +/*********************************************************** + * functions to enable/disable/query external/critical interrupts + */ +void BSP_irqexc_on_fnc(const rtems_irq_connect_data *conn_data) +{ + uint32_t msr_value; + /* + * get current MSR value + */ + _CPU_MSR_GET(msr_value); + + msr_value |= PPC_MSR_EE; + _CPU_MSR_SET(msr_value); +} + +void BSP_irqexc_off_fnc(const rtems_irq_connect_data *unused) +{ + uint32_t msr_value; + /* + * get current MSR value + */ + _CPU_MSR_GET(msr_value); + + msr_value &= ~PPC_MSR_EE; + _CPU_MSR_SET(msr_value); +} + +/*********************************************************** + * High level IRQ handler called from shared_raw_irq_code_entry + */ +static int C_dispatch_irq_handler (BSP_Exception_frame *frame, unsigned int excNum) +{ + /* + * Handle interrupt + */ + switch(excNum) { + case ASM_EXT_VECTOR: + BSP_rtems_irq_tbl[BSP_EXT].hdl(BSP_rtems_irq_tbl[BSP_EXT].handle); + break; + case ASM_BOOKE_DEC_VECTOR: + BSP_rtems_irq_tbl[BSP_PIT].hdl(BSP_rtems_irq_tbl[BSP_PIT].handle); + break; +#if 0 /* Critical interrupts not yet supported */ + case ASM_BOOKE_CRIT_VECTOR: + BSP_rtems_irq_tbl[BSP_CRIT].hdl(BSP_rtems_irq_tbl[BSP_CRIT].handle); + break; +#endif + } + + return 0; +} + +/*********************************************************** + * functions to set/get/remove interrupt handlers + ***********************************************************/ +int BSP_install_rtems_irq_handler (const rtems_irq_connect_data* irq) +{ + rtems_interrupt_level level; + + /* + * check for valid irq name + * if invalid, print error and return 0 + */ + if (!BSP_IS_VALID_IRQ(irq->name)) { + printk("Invalid interrupt vector %d\n",irq->name); + return 0; + } + + /* + * disable interrupts + */ + rtems_interrupt_disable(level); + + /* + * check, that default handler is installed now + */ + if (rtemsIrqTbl[irq->name].hdl != BSP_rtems_irq_config->defaultEntry.hdl) { + rtems_interrupt_enable(level); + printk("IRQ vector %d already connected\n",irq->name); + return 0; + } + + /* + * store new handler data + */ + rtemsIrqTbl[irq->name] = *irq; + + /* + * call "on" function to enable interrupt at device + */ + irq->on(irq); + + /* + * reenable interrupts + */ + rtems_interrupt_enable(level); + + return 1; +} + +int BSP_get_current_rtems_irq_handler (rtems_irq_connect_data* irq) +{ + rtems_interrupt_level level; + + /* + * check for valid IRQ name + */ + if (!BSP_IS_VALID_IRQ(irq->name)) { + return 0; + } + rtems_interrupt_disable(level); + + /* + * return current IRQ entry + */ + *irq = rtemsIrqTbl[irq->name]; + rtems_interrupt_enable(level); + return 1; +} + +int BSP_remove_rtems_irq_handler (const rtems_irq_connect_data* irq) +{ + rtems_interrupt_level level; + + /* + * check for valid IRQ name + */ + if (!BSP_IS_VALID_IRQ(irq->name)) { + return 0; + } + rtems_interrupt_disable(level); + + /* + * check, that specified handler is really connected now + */ + if (rtemsIrqTbl[irq->name].hdl != irq->hdl) { + rtems_interrupt_enable(level); + return 0; + } + + /* + * disable interrupt at source + */ + irq->off(irq); + + /* + * restore default interrupt handler + */ + rtemsIrqTbl[irq->name] = BSP_rtems_irq_config->defaultEntry; + + /* + * reenable interrupts + */ + rtems_interrupt_enable(level); + + return 1; +} + +/*********************************************************** + * functions to set/get the basic interrupt management setup + ***********************************************************/ +/* + * (Re) get info on current RTEMS interrupt management. + */ +int BSP_rtems_irq_mngt_get(rtems_irq_global_settings** ret_ptr) +{ + *ret_ptr = BSP_rtems_irq_config; + return 0; +} + + +/* + * set management stuff + */ +int BSP_rtems_irq_mngt_set(rtems_irq_global_settings* config) +{ + int i; + rtems_interrupt_level level; + + rtems_interrupt_disable(level); + + /* + * store given configuration + */ + BSP_rtems_irq_config = config; + BSP_rtems_irq_tbl = BSP_rtems_irq_config->irqHdlTbl; + + /* + * store any irq-like processor exceptions + */ + for (i = BSP_PROCESSOR_IRQ_LOWEST_OFFSET; + i < BSP_PROCESSOR_IRQ_MAX_OFFSET; + i++) { + if (BSP_rtems_irq_tbl[i].hdl != config->defaultEntry.hdl) { + if (BSP_rtems_irq_tbl[i].on != NULL) { + BSP_rtems_irq_tbl[i].on + (&(BSP_rtems_irq_tbl[i])); + } + } + else { + if (BSP_rtems_irq_tbl[i].off != NULL) { + BSP_rtems_irq_tbl[i].off + (&(BSP_rtems_irq_tbl[i])); + } + } + } + rtems_interrupt_enable(level); + return 1; +} + +/* + * dummy for an empty IRQ handler entry + */ +static rtems_irq_connect_data emptyIrq = { + 0, /* IRQ Name */ + BSP_irq_nop_hdl, /* handler function */ + NULL, /* handle passed to handler */ + BSP_irq_nop_func, /* on function */ + BSP_irq_nop_func, /* off function */ + BSP_irq_isOn_func /* isOn function */ +}; + +static rtems_irq_global_settings initialConfig = { + BSP_IRQ_NUMBER, /* IRQ Number */ + { 0, /* IRQ Name */ + BSP_irq_nop_hdl, /* handler function */ + NULL, /* handle passed to handler */ + BSP_irq_nop_func, /* on function */ + BSP_irq_nop_func, /* off function */ + BSP_irq_isOn_func /* isOn function */ + }, /* emptyIrq */ + rtemsIrqTbl, /* irqHdlTbl */ + 0, /* irqBase */ + NULL /* irqPrioTbl */ +}; + +void BSP_rtems_irq_mngt_init(unsigned cpuId) +{ + int i; + + /* + * connect all exception vectors needed + */ + ppc_exc_set_handler(ASM_EXT_VECTOR, C_dispatch_irq_handler); + ppc_exc_set_handler(ASM_BOOKE_DEC_VECTOR, C_dispatch_irq_handler); + + /* + * setup interrupt handlers table + */ + for (i = 0; + i < BSP_IRQ_NUMBER; + i++) { + rtemsIrqTbl[i] = emptyIrq; + rtemsIrqTbl[i].name = i; + } + + /* + * initialize interrupt management + */ + if (!BSP_rtems_irq_mngt_set(&initialConfig)) { + rtems_panic("Unable to initialize RTEMS interrupt Management!!! System locked\n"); + } +} diff --git a/bsps/powerpc/virtex5/irq/irq_init.c b/bsps/powerpc/virtex5/irq/irq_init.c new file mode 100644 index 0000000000..1fea9214aa --- /dev/null +++ b/bsps/powerpc/virtex5/irq/irq_init.c @@ -0,0 +1,343 @@ +/*===============================================================*\ +| Project: RTEMS virtex BSP | ++-----------------------------------------------------------------+ +| Partially based on the code references which are named below. | +| Adaptions, modifications, enhancements and any recent parts of | +| the code are: | +| Copyright (c) 2007 | +| Embedded Brains GmbH | +| Obere Lagerstr. 30 | +| D-82178 Puchheim | +| Germany | +| rtems@embedded-brains.de | ++-----------------------------------------------------------------+ +| The license and distribution terms for this file may be | +| found in the file LICENSE in this distribution or at | +| | +| http://www.rtems.org/license/LICENSE. | +| | ++-----------------------------------------------------------------+ +| this file contains the irq controller handler | +\*===============================================================*/ +#include +#include +#include +#include +#include +#include + +static rtems_irq_connect_data rtemsIrqTbl[BSP_IRQ_NUMBER]; +rtems_irq_connect_data *BSP_rtems_irq_tbl; +rtems_irq_global_settings* BSP_rtems_irq_config; + +/*********************************************************** + * dummy functions for on/off/isOn calls + * these functions just do nothing fulfill the semantic + * requirements to enable/disable a certain interrupt or exception + */ +static void BSP_irq_nop_func(const rtems_irq_connect_data *unused) +{ + /* + * nothing to do + */ +} + +static void BSP_irq_nop_hdl(void *hdl) +{ + /* + * nothing to do + */ +} + +static int BSP_irq_isOn_func(const rtems_irq_connect_data *unused) +{ + /* + * nothing to do + */ + return 0; +} + +/*********************************************************** + * interrupt handler and its enable/disable functions + ***********************************************************/ + +/*********************************************************** + * functions to enable/disable/query external/critical interrupts + */ +void BSP_irqexc_on_fnc(const rtems_irq_connect_data *conn_data) +{ + uint32_t msr_value; + /* + * get current MSR value + */ + _CPU_MSR_GET(msr_value); + + msr_value |= PPC_MSR_EE; + _CPU_MSR_SET(msr_value); +} + +void BSP_irqexc_off_fnc(const rtems_irq_connect_data *unused) +{ + uint32_t msr_value; + /* + * get current MSR value + */ + _CPU_MSR_GET(msr_value); + + msr_value &= ~PPC_MSR_EE; + _CPU_MSR_SET(msr_value); +} + +SPR_RW(BOOKE_TSR) + +static int C_dispatch_dec_handler (BSP_Exception_frame *frame, unsigned int excNum) +{ + /* Acknowledge the interrupt */ + _write_BOOKE_TSR( BOOKE_TSR_DIS ); + + /* Handle the interrupt */ + BSP_rtems_irq_tbl[BSP_DEC].hdl(BSP_rtems_irq_tbl[BSP_DEC].handle); + + return 0; +} + + +/*********************************************************** + * High level IRQ handler called from shared_raw_irq_code_entry + */ +static int C_dispatch_irq_handler (BSP_Exception_frame *frame, unsigned int excNum) +{ + /* + * Handle interrupt + */ + switch(excNum) { + case ASM_EXT_VECTOR: + BSP_rtems_irq_tbl[BSP_EXT].hdl(BSP_rtems_irq_tbl[BSP_EXT].handle); + break; +#if 0 /* Dealt with by C_dispatch_dec_handler(), above */ + case ASM_BOOKE_DEC_VECTOR: + _write_BOOKE_TSR( BOOKE_TSR_DIS ); + BSP_rtems_irq_tbl[BSP_DEC].hdl(BSP_rtems_irq_tbl[BSP_DEC].handle); + break; +#endif +#if 0 /* Critical interrupts not yet supported */ + case ASM_BOOKE_CRIT_VECTOR: + BSP_rtems_irq_tbl[BSP_CRIT].hdl(BSP_rtems_irq_tbl[BSP_CRIT].handle); + break; +#endif + } + + return 0; +} + +/*********************************************************** + * functions to set/get/remove interrupt handlers + ***********************************************************/ +int BSP_install_rtems_irq_handler (const rtems_irq_connect_data* irq) +{ + rtems_interrupt_level level; + + /* + * check for valid irq name + * if invalid, print error and return 0 + */ + if (!BSP_IS_VALID_IRQ(irq->name)) { + printk("Invalid interrupt vector %d\n",irq->name); + return 0; + } + + /* + * disable interrupts + */ + rtems_interrupt_disable(level); + + /* + * check, that default handler is installed now + */ + if (rtemsIrqTbl[irq->name].hdl != BSP_rtems_irq_config->defaultEntry.hdl) { + rtems_interrupt_enable(level); + printk("IRQ vector %d already connected\n",irq->name); + return 0; + } + + /* + * store new handler data + */ + rtemsIrqTbl[irq->name] = *irq; + + /* + * call "on" function to enable interrupt at device + */ + irq->on(irq); + + /* + * reenable interrupts + */ + rtems_interrupt_enable(level); + + return 1; +} + +int BSP_get_current_rtems_irq_handler (rtems_irq_connect_data* irq) +{ + rtems_interrupt_level level; + + /* + * check for valid IRQ name + */ + if (!BSP_IS_VALID_IRQ(irq->name)) { + return 0; + } + rtems_interrupt_disable(level); + + /* + * return current IRQ entry + */ + *irq = rtemsIrqTbl[irq->name]; + rtems_interrupt_enable(level); + return 1; +} + +int BSP_remove_rtems_irq_handler (const rtems_irq_connect_data* irq) +{ + rtems_interrupt_level level; + + /* + * check for valid IRQ name + */ + if (!BSP_IS_VALID_IRQ(irq->name)) { + return 0; + } + rtems_interrupt_disable(level); + + /* + * check, that specified handler is really connected now + */ + if (rtemsIrqTbl[irq->name].hdl != irq->hdl) { + rtems_interrupt_enable(level); + return 0; + } + + /* + * disable interrupt at source + */ + irq->off(irq); + + /* + * restore default interrupt handler + */ + rtemsIrqTbl[irq->name] = BSP_rtems_irq_config->defaultEntry; + + /* + * reenable interrupts + */ + rtems_interrupt_enable(level); + + return 1; +} + +/*********************************************************** + * functions to set/get the basic interrupt management setup + ***********************************************************/ +/* + * (Re) get info on current RTEMS interrupt management. + */ +int BSP_rtems_irq_mngt_get(rtems_irq_global_settings** ret_ptr) +{ + *ret_ptr = BSP_rtems_irq_config; + return 0; +} + + +/* + * set management stuff + */ +int BSP_rtems_irq_mngt_set(rtems_irq_global_settings* config) +{ + int i; + rtems_interrupt_level level; + + rtems_interrupt_disable(level); + + /* + * store given configuration + */ + BSP_rtems_irq_config = config; + BSP_rtems_irq_tbl = BSP_rtems_irq_config->irqHdlTbl; + + /* + * store any irq-like processor exceptions + */ + for (i = BSP_PROCESSOR_IRQ_LOWEST_OFFSET; + i < BSP_PROCESSOR_IRQ_MAX_OFFSET; + i++) { + if (BSP_rtems_irq_tbl[i].hdl != config->defaultEntry.hdl) { + if (BSP_rtems_irq_tbl[i].on != NULL) { + BSP_rtems_irq_tbl[i].on + (&(BSP_rtems_irq_tbl[i])); + } + } + else { + if (BSP_rtems_irq_tbl[i].off != NULL) { + BSP_rtems_irq_tbl[i].off + (&(BSP_rtems_irq_tbl[i])); + } + } + } + rtems_interrupt_enable(level); + return 1; +} + +/* + * dummy for an empty IRQ handler entry + */ +static rtems_irq_connect_data emptyIrq = { + 0, /* IRQ Name */ + BSP_irq_nop_hdl, /* handler function */ + NULL, /* handle passed to handler */ + BSP_irq_nop_func, /* on function */ + BSP_irq_nop_func, /* off function */ + BSP_irq_isOn_func /* isOn function */ +}; + +static rtems_irq_global_settings initialConfig = { + BSP_IRQ_NUMBER, /* IRQ number */ + { 0, /* IRQ Name */ + BSP_irq_nop_hdl, /* handler function */ + NULL, /* handle passed to handler */ + BSP_irq_nop_func, /* on function */ + BSP_irq_nop_func, /* off function */ + BSP_irq_isOn_func /* isOn function */ + }, /* emptyIrq */ + rtemsIrqTbl, /* irqHdlTbl */ + 0, /* irqBase */ + NULL /* irqPrioTbl */ +}; + +void BSP_rtems_irq_mngt_init(unsigned cpuId) +{ + int i; + + /* + * connect all exception vectors needed + */ + ppc_exc_set_handler(ASM_EXT_VECTOR, C_dispatch_irq_handler); + ppc_exc_set_handler(ASM_BOOKE_DEC_VECTOR, C_dispatch_dec_handler); + + /* + * setup interrupt handlers table + */ + for (i = 0; + i < BSP_IRQ_NUMBER; + i++) { + rtemsIrqTbl[i] = emptyIrq; + rtemsIrqTbl[i].name = i; + } + + /* + * initialize interrupt management + */ + if (!BSP_rtems_irq_mngt_set(&initialConfig)) { + rtems_panic("Unable to initialize RTEMS interrupt Management!!! System locked\n"); + } +} diff --git a/bsps/riscv/riscv_generic/irq/irq.c b/bsps/riscv/riscv_generic/irq/irq.c new file mode 100644 index 0000000000..8090dcea98 --- /dev/null +++ b/bsps/riscv/riscv_generic/irq/irq.c @@ -0,0 +1,60 @@ +/** + * @file + * + * @ingroup riscv_interrupt + * + * @brief Interrupt support. + */ + +/* + * RISCV CPU Dependent Source + * + * Copyright (c) 2015 University of York. + * Hesham Almatary + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +#include + +/* Almost all of the jobs that the following functions should + * do are implemented in cpukit + */ + +void bsp_interrupt_handler_default(rtems_vector_number vector) +{ + printk("spurious interrupt: %u\n", vector); +} + +rtems_status_code bsp_interrupt_facility_initialize() +{ + return RTEMS_NOT_IMPLEMENTED; +} + +void bsp_interrupt_vector_enable(rtems_vector_number vector) +{ +} + +void bsp_interrupt_vector_disable(rtems_vector_number vector) +{ +} diff --git a/c/src/lib/libbsp/arm/altera-cyclone-v/Makefile.am b/c/src/lib/libbsp/arm/altera-cyclone-v/Makefile.am index d3a48806ea..1b9f584a5a 100644 --- a/c/src/lib/libbsp/arm/altera-cyclone-v/Makefile.am +++ b/c/src/lib/libbsp/arm/altera-cyclone-v/Makefile.am @@ -66,7 +66,7 @@ endif # IRQ librtemsbsp_a_SOURCES += ../../../../../../bsps/shared/irq/irq-default-handler.c -librtemsbsp_a_SOURCES += ../shared/arm-gic-irq.c +librtemsbsp_a_SOURCES += ../../../../../../bsps/arm/shared/irq/irq-gic.c # Console librtemsbsp_a_SOURCES += ../../../../../../bsps/shared/dev/serial/console-termios-init.c diff --git a/c/src/lib/libbsp/arm/atsam/Makefile.am b/c/src/lib/libbsp/arm/atsam/Makefile.am index af0185a41e..5aab0b2bb2 100644 --- a/c/src/lib/libbsp/arm/atsam/Makefile.am +++ b/c/src/lib/libbsp/arm/atsam/Makefile.am @@ -107,8 +107,8 @@ librtemsbsp_a_SOURCES += ../../../../../../bsps/arm/atsam/start/sdram-config.c # IRQ librtemsbsp_a_SOURCES += ../../../../../../bsps/shared/irq/irq-default-handler.c -librtemsbsp_a_SOURCES += ../shared/armv7m/irq/armv7m-irq.c -librtemsbsp_a_SOURCES += ../shared/armv7m/irq/armv7m-irq-dispatch.c +librtemsbsp_a_SOURCES += ../../../../../../bsps/arm/shared/irq/irq-armv7m.c +librtemsbsp_a_SOURCES += ../../../../../../bsps/arm/shared/irq/irq-dispatch-armv7m.c # Console librtemsbsp_a_SOURCES += ../../../../../../bsps/shared/dev/serial/console-termios.c diff --git a/c/src/lib/libbsp/arm/beagle/Makefile.am b/c/src/lib/libbsp/arm/beagle/Makefile.am index 72a80b0b35..eaff46c48a 100644 --- a/c/src/lib/libbsp/arm/beagle/Makefile.am +++ b/c/src/lib/libbsp/arm/beagle/Makefile.am @@ -59,7 +59,7 @@ librtemsbsp_a_SOURCES += ../../../../../../bsps/arm/beagle/start/bspstartmmu.c # IRQ librtemsbsp_a_SOURCES += ../../../../../../bsps/shared/irq/irq-default-handler.c -librtemsbsp_a_SOURCES += irq.c +librtemsbsp_a_SOURCES += ../../../../../../bsps/arm/beagle/irq/irq.c # Console librtemsbsp_a_SOURCES += ../../../../../../bsps/shared/dev/serial/legacy-console.c diff --git a/c/src/lib/libbsp/arm/beagle/irq.c b/c/src/lib/libbsp/arm/beagle/irq.c deleted file mode 100644 index 2fa1a5b0f0..0000000000 --- a/c/src/lib/libbsp/arm/beagle/irq.c +++ /dev/null @@ -1,144 +0,0 @@ -/** - * @file - * - * @ingroup bsp_interrupt - * @ingroup arm_beagle - * - * @brief Interrupt support. - */ - -/* - * Copyright (c) 2014 Ben Gras . All rights reserved. - * - * The license and distribution terms for this file may be - * found in the file LICENSE in this distribution or at - * http://www.rtems.org/license/LICENSE. - */ - -#include -#include -#include -#include - -#include - -#include - -struct omap_intr -{ - uint32_t base; - int size; -}; - -#if IS_DM3730 -static struct omap_intr omap_intr = { - .base = OMAP3_DM37XX_INTR_BASE, - .size = 0x1000, -}; -#endif - -#if IS_AM335X -static struct omap_intr omap_intr = { - .base = OMAP3_AM335X_INTR_BASE, - .size = 0x1000, -}; -#endif - -/* Enables interrupts at the Interrupt Controller side. */ -static inline void omap_irq_ack(void) -{ - mmio_write(omap_intr.base + OMAP3_INTCPS_CONTROL, OMAP3_INTR_NEWIRQAGR); - - /* Flush data cache to make sure all the previous writes are done - before re-enabling interrupts. */ - flush_data_cache(); -} - -void bsp_interrupt_dispatch(void) -{ - const uint32_t reg = mmio_read(omap_intr.base + OMAP3_INTCPS_SIR_IRQ); - - if ((reg & OMAP3_INTR_SPURIOUSIRQ_MASK) != OMAP3_INTR_SPURIOUSIRQ_MASK) { - const rtems_vector_number irq = reg & OMAP3_INTR_ACTIVEIRQ_MASK; - - bsp_interrupt_handler_dispatch(irq); - } else { - /* Ignore spurious interrupts. We'll still ACK it so new interrupts - can be generated. */ - } - - omap_irq_ack(); -} - -/* There are 4 32-bit interrupt mask registers for a total of 128 interrupts. - The IRQ number tells us which register to use. */ -static uint32_t omap_get_mir_reg(rtems_vector_number vector, uint32_t *const mask) -{ - uint32_t mir_reg; - - /* Select which bit to set/clear in the MIR register. */ - *mask = 1ul << (vector % 32u); - - if (vector < 32u) { - mir_reg = OMAP3_INTCPS_MIR0; - } else if (vector < 64u) { - mir_reg = OMAP3_INTCPS_MIR1; - } else if (vector < 96u) { - mir_reg = OMAP3_INTCPS_MIR2; - } else if (vector < 128u) { - mir_reg = OMAP3_INTCPS_MIR3; - } else { - /* Invalid IRQ number. This should never happen. */ - bsp_fatal(0); - } - - return mir_reg; -} - -void bsp_interrupt_vector_enable(rtems_vector_number vector) -{ - uint32_t mask, cur; - uint32_t mir_reg = omap_get_mir_reg(vector, &mask); - - bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector)); - - cur = mmio_read(omap_intr.base + mir_reg); - mmio_write(omap_intr.base + mir_reg, cur & ~mask); - flush_data_cache(); -} - -void bsp_interrupt_vector_disable(rtems_vector_number vector) -{ - uint32_t mask, cur; - uint32_t mir_reg = omap_get_mir_reg(vector, &mask); - - bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector)); - - cur = mmio_read(omap_intr.base + mir_reg); - mmio_write(omap_intr.base + mir_reg, cur | mask); - flush_data_cache(); -} - -rtems_status_code bsp_interrupt_facility_initialize(void) -{ - int i; - uint32_t intc_ilrx; - - /* AM335X TRM 6.2.1 Initialization Sequence */ - mmio_write(omap_intr.base + OMAP3_INTCPS_SYSCONFIG, OMAP3_SYSCONFIG_AUTOIDLE); - mmio_write(omap_intr.base + OMAP3_INTCPS_IDLE, 0); - /* priority 0 to all IRQs */ - for(intc_ilrx = 0x100; intc_ilrx <= 0x2fc; intc_ilrx += 4) { - mmio_write(omap_intr.base + intc_ilrx, 0); - } - - /* Mask all interrupts */ - for(i = BSP_INTERRUPT_VECTOR_MIN; i <= BSP_INTERRUPT_VECTOR_MAX; i++) - bsp_interrupt_vector_disable(i); - - /* Install generic interrupt handler */ - arm_cp15_set_exception_handler(ARM_EXCEPTION_IRQ, _ARMV4_Exception_interrupt); - arm_cp15_set_vector_base_address(bsp_vector_table_begin); - - return RTEMS_SUCCESSFUL; -} diff --git a/c/src/lib/libbsp/arm/csb336/Makefile.am b/c/src/lib/libbsp/arm/csb336/Makefile.am index 8702c2cbb6..78ea9d1f3d 100644 --- a/c/src/lib/libbsp/arm/csb336/Makefile.am +++ b/c/src/lib/libbsp/arm/csb336/Makefile.am @@ -33,7 +33,7 @@ librtemsbsp_a_SOURCES += ../../../../../../bsps/arm/csb336/btimer/btimer.c librtemsbsp_a_SOURCES += ../../../../../../bsps/arm/csb336/console/uart.c # IRQ librtemsbsp_a_SOURCES += ../../../../../../bsps/shared/irq/irq-default-handler.c -librtemsbsp_a_SOURCES += irq/irq.c +librtemsbsp_a_SOURCES += ../../../../../../bsps/arm/csb336/irq/irq.c # Cache librtemsbsp_a_SOURCES += ../../../../../../bsps/arm/shared/cache/cache-cp15.c diff --git a/c/src/lib/libbsp/arm/csb336/irq/irq.c b/c/src/lib/libbsp/arm/csb336/irq/irq.c deleted file mode 100644 index e5887b9717..0000000000 --- a/c/src/lib/libbsp/arm/csb336/irq/irq.c +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Motorola MC9328MXL Interrupt handler - * - * Copyright (c) 2010 embedded brains GmbH. - * - * Copyright (c) 2004 by Jay Monkman - * - * The license and distribution terms for this file may be - * found in the file LICENSE in this distribution or at - * http://www.rtems.org/license/LICENSE. - */ - -#include - -#include -#include -#include - -#include - -void bsp_interrupt_dispatch(void) -{ - - rtems_vector_number vector = MC9328MXL_AITC_NIVECSR >> 16; - - bsp_interrupt_handler_dispatch(vector); -} - -void bsp_interrupt_vector_enable(rtems_vector_number vector) -{ - bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector)); - - if (vector < MC9328MXL_NUM_INTS) - MC9328MXL_AITC_INTENNUM = vector; -} - -void bsp_interrupt_vector_disable(rtems_vector_number vector) -{ - bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector)); - - if (vector < MC9328MXL_NUM_INTS) - MC9328MXL_AITC_INTDISNUM = vector; -} - -rtems_status_code bsp_interrupt_facility_initialize(void) -{ - - _CPU_ISR_install_vector(ARM_EXCEPTION_IRQ, _ARMV4_Exception_interrupt, NULL); - - return RTEMS_SUCCESSFUL; -} diff --git a/c/src/lib/libbsp/arm/csb337/Makefile.am b/c/src/lib/libbsp/arm/csb337/Makefile.am index 2d9394965c..945ea01a89 100644 --- a/c/src/lib/libbsp/arm/csb337/Makefile.am +++ b/c/src/lib/libbsp/arm/csb337/Makefile.am @@ -48,7 +48,7 @@ librtemsbsp_a_SOURCES += ../../../../../../bsps/arm/csb337/console/dbgu.c librtemsbsp_a_SOURCES += ../../../../../../bsps/arm/csb337/console/usart.c # IRQ librtemsbsp_a_SOURCES += ../../../../../../bsps/shared/irq/irq-default-handler.c -librtemsbsp_a_SOURCES += irq/irq.c +librtemsbsp_a_SOURCES += ../../../../../../bsps/arm/csb337/irq/irq.c if ENABLE_LCD librtemsbsp_a_SOURCES += ../../../../../../bsps/arm/csb337/console/sed1356.c librtemsbsp_a_SOURCES += ../../../../../../bsps/arm/csb337/console/fbcons.c diff --git a/c/src/lib/libbsp/arm/csb337/irq/irq.c b/c/src/lib/libbsp/arm/csb337/irq/irq.c deleted file mode 100644 index 95e93845b9..0000000000 --- a/c/src/lib/libbsp/arm/csb337/irq/irq.c +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Atmel AT91RM9200 Interrupt handler - * - * Copyright (c) 2010 embedded brains GmbH. - * - * Copyright (c) 2004 by Jay Monkman - * - * The license and distribution terms for this file may be - * found in the file LICENSE in this distribution or at - * http://www.rtems.org/license/LICENSE. - */ - -#include - -#include -#include -#include - -#include - -void bsp_interrupt_dispatch(void) -{ - rtems_vector_number vector = AIC_CTL_REG(AIC_IVR); - - bsp_interrupt_handler_dispatch(vector); - - AIC_CTL_REG(AIC_EOICR) = 0; -} - -void bsp_interrupt_vector_enable(rtems_vector_number vector) -{ - bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector)); - AIC_CTL_REG(AIC_IECR) = 1 << vector; -} - -void bsp_interrupt_vector_disable(rtems_vector_number vector) -{ - bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector)); - AIC_CTL_REG(AIC_IDCR) = 1 << vector; -} - -rtems_status_code bsp_interrupt_facility_initialize(void) -{ - unsigned long i = 0; - - for (i = 0; i < 32; ++i) { - AIC_SVR_REG(i<<2) = i; - } - - /* disable all interrupts */ - AIC_CTL_REG(AIC_IDCR) = 0xffffffff; - - _CPU_ISR_install_vector(ARM_EXCEPTION_IRQ, _ARMV4_Exception_interrupt, NULL); - - return RTEMS_SUCCESSFUL; -} diff --git a/c/src/lib/libbsp/arm/edb7312/Makefile.am b/c/src/lib/libbsp/arm/edb7312/Makefile.am index eb15e50200..1b53e8c6ff 100644 --- a/c/src/lib/libbsp/arm/edb7312/Makefile.am +++ b/c/src/lib/libbsp/arm/edb7312/Makefile.am @@ -38,8 +38,8 @@ librtemsbsp_a_SOURCES += ../../../../../../bsps/arm/edb7312/btimer/btimer.c # irq librtemsbsp_a_SOURCES += ../../../../../../bsps/shared/irq/irq-default-handler.c -librtemsbsp_a_SOURCES += irq/irq.c -librtemsbsp_a_SOURCES += irq/bsp_irq_asm.S +librtemsbsp_a_SOURCES += ../../../../../../bsps/arm/edb7312/irq/irq.c +librtemsbsp_a_SOURCES += ../../../../../../bsps/arm/edb7312/irq/bsp_irq_asm.S # Cache librtemsbsp_a_SOURCES += ../../../../../../bsps/shared/cache/nocache.c diff --git a/c/src/lib/libbsp/arm/edb7312/irq/bsp_irq_asm.S b/c/src/lib/libbsp/arm/edb7312/irq/bsp_irq_asm.S deleted file mode 100644 index c48466967b..0000000000 --- a/c/src/lib/libbsp/arm/edb7312/irq/bsp_irq_asm.S +++ /dev/null @@ -1,323 +0,0 @@ -/* - * Cirrus EP7312 Intererrupt handler - */ - -/* - * Copyright (c) 2002 by Jay Monkman - * - * Copyright (c) 2002 by Charlie Steader - * - * The license and distribution terms for this file may be - * found in the file LICENSE in this distribution or at - * http://www.rtems.org/license/LICENSE. -*/ - -#define __asm__ -#include -#include - - .extern edb7312_interrupt_dispatch - -/* - * Function to obtain, execute an IT handler and acknowledge the IT - */ - - .globl bsp_interrupt_dispatch -bsp_interrupt_dispatch : -/* - * Look at interrupt status register to determine source. - * From source, determine offset into expanded vector table - * and load handler address into r0. - */ - - ldr r1, =0x80000000 /* close to interrupt status/mask registers 1 */ - ldr r2, =0x80001000 /* close to interrupt status/mask registers 2 */ - ldr r3, =0x80002000 /* close to interrupt status/mask registers 3 */ - - stmdb sp!,{r4, r5, r6} - -/* - * INTSR3 - */ -check_dai: - ldr r4, [r3, #0x240] - ldr r5, [r3, #0x280] - and r6, r4, r5 /* only look at interrupts which are enabled */ - tst r6, #0x0001 - beq check_extfiq - mov r0, #BSP_DAIINT - b get_handler - -/* - * INTSR1 - */ -check_extfiq: - ldr r4, [r1, #0x240] - ldr r5, [r1, #0x280] - and r6, r4, r5 /* only look at interrupts which are enabled */ - tst r6, #0x0001 - beq check_bl - mov r0, #BSP_EXTFIQ - b get_handler - -check_bl: -#if 0 -MUST REMEMBER TO UNCOMMENT IF THIS HANDLER MOVES - ldr r4, [r1, #0x240] - ldr r5, [r1, #0x280] - and r6, r4, r5 /* only look at interrupts which are enabled */ -#endif - tst r6, #0x0002 - beq check_we - mov r0, #BSP_BLINT - b get_handler - -check_we: -#if 0 -MUST REMEMBER TO UNCOMMENT IF THIS HANDLER MOVES - ldr r4, [r1, #0x240] - ldr r5, [r1, #0x280] - and r6, r4, r5 /* only look at interrupts which are enabled */ -#endif - tst r6, #0x0004 - beq check_mc - mov r0, #BSP_WEINT - b get_handler - -check_mc: -#if 0 -MUST REMEMBER TO UNCOMMENT IF THIS HANDLER MOVES - ldr r4, [r1, #0x240] - ldr r5, [r1, #0x280] - and r6, r4, r5 /* only look at interrupts which are enabled */ -#endif - tst r6, #0x0008 - beq check_cs - mov r0, #BSP_MCINT - b get_handler - -check_cs: -#if 0 -MUST REMEMBER TO UNCOMMENT IF THIS HANDLER MOVES - ldr r4, [r1, #0x240] - ldr r5, [r1, #0x280] - and r6, r4, r5 /* only look at interrupts which are enabled */ -#endif - tst r6, #0x0010 - beq check_e1 - mov r0, #BSP_CSINT - b get_handler - -check_e1: -#if 0 -MUST REMEMBER TO UNCOMMENT IF THIS HANDLER MOVES - ldr r4, [r1, #0x240] - ldr r5, [r1, #0x280] - and r6, r4, r5 /* only look at interrupts which are enabled */ -#endif - tst r6, #0x0020 - beq check_e2 - mov r0, #BSP_EINT1 - b get_handler - -check_e2: -#if 0 -MUST REMEMBER TO UNCOMMENT IF THIS HANDLER MOVES - ldr r4, [r1, #0x240] - ldr r5, [r1, #0x280] - and r6, r4, r5 /* only look at interrupts which are enabled */ -#endif - tst r6, #0x0040 - beq check_e3 - mov r0, #BSP_EINT2 - b get_handler - -check_e3: -#if 0 -MUST REMEMBER TO UNCOMMENT IF THIS HANDLER MOVES - ldr r4, [r1, #0x240] - ldr r5, [r1, #0x280] - and r6, r4, r5 /* only look at interrupts which are enabled */ -#endif - tst r6, #0x0080 - beq check_tc1 - mov r0, #BSP_EINT3 - b get_handler - -check_tc1: -#if 0 -MUST REMEMBER TO UNCOMMENT IF THIS HANDLER MOVES - ldr r4, [r1, #0x240] - ldr r5, [r1, #0x280] - and r6, r4, r5 /* only look at interrupts which are enabled */ -#endif - tst r6, #0x0100 - beq check_tc2 - mov r0, #BSP_TC1OI - b get_handler - -check_tc2: -#if 0 -MUST REMEMBER TO UNCOMMENT IF THIS HANDLER MOVES - ldr r4, [r1, #0x240] - ldr r5, [r1, #0x280] - and r6, r4, r5 /* only look at interrupts which are enabled */ -#endif - tst r6, #0x0200 - beq check_rtc - mov r0, #BSP_TC2OI - b get_handler - -check_rtc: -#if 0 -MUST REMEMBER TO UNCOMMENT IF THIS HANDLER MOVES - ldr r4, [r1, #0x240] - ldr r5, [r1, #0x280] - and r6, r4, r5 /* only look at interrupts which are enabled */ -#endif - tst r6, #0x0400 - beq check_tick - mov r0, #BSP_RTCMI - b get_handler - -check_tick: -#if 0 -MUST REMEMBER TO UNCOMMENT IF THIS HANDLER MOVES - ldr r4, [r1, #0x240] - ldr r5, [r1, #0x280] - and r6, r4, r5 /* only look at interrupts which are enabled */ -#endif - tst r6, #0x0800 - beq check_utx1 - mov r0, #BSP_TINT - b get_handler - -check_utx1: -#if 0 -MUST REMEMBER TO UNCOMMENT IF THIS HANDLER MOVES - ldr r4, [r1, #0x240] - ldr r5, [r1, #0x280] - and r6, r4, r5 /* only look at interrupts which are enabled */ -#endif - tst r6, #0x1000 - beq check_urx1 - mov r0, #BSP_UTXINT1 - b get_handler - -check_urx1: -#if 0 -MUST REMEMBER TO UNCOMMENT IF THIS HANDLER MOVES - ldr r4, [r1, #0x240] - ldr r5, [r1, #0x280] - and r6, r4, r5 /* only look at interrupts which are enabled */ -#endif - tst r6, #0x2000 - beq check_ums - mov r0, #BSP_URXINT1 - b get_handler - -check_ums: -#if 0 -MUST REMEMBER TO UNCOMMENT IF THIS HANDLER MOVES - ldr r4, [r1, #0x240] - ldr r5, [r1, #0x280] - and r6, r4, r5 /* only look at interrupts which are enabled */ -#endif - tst r6, #0x4000 - beq check_sse - mov r0, #BSP_UMSINT - b get_handler - -check_sse: -#if 0 -MUST REMEMBER TO UNCOMMENT IF THIS HANDLER MOVES - ldr r4, [r1, #0x240] - ldr r5, [r1, #0x280] - and r6, r4, r5 /* only look at interrupts which are enabled */ -#endif - tst r6, #0x8000 - beq check_kbd - mov r0, #BSP_SSEOTI - b get_handler - -/* - * INTSR2 - */ -check_kbd: - ldr r4, [r2, #0x240] - ldr r5, [r2, #0x280] - and r6, r4, r5 /* only look at interrupts which are enabled */ - tst r6, #0x0001 - beq check_ss2rx - mov r0, #BSP_KBDINT - b get_handler - -check_ss2rx: -#if 0 -MUST REMEMBER TO UNCOMMENT IF THIS HANDLER MOVES - ldr r4, [r2, #0x240] - ldr r5, [r2, #0x280] - and r6, r4, r5 /* only look at interrupts which are enabled */ -#endif - tst r6, #0x0002 - beq check_ss2tx - mov r0, #BSP_SS2RX - b get_handler - -check_ss2tx: -#if 0 -MUST REMEMBER TO UNCOMMENT IF THIS HANDLER MOVES - ldr r4, [r2, #0x240] - ldr r5, [r2, #0x280] - and r6, r4, r5 /* only look at interrupts which are enabled */ -#endif - tst r6, #0x0004 - beq check_utx2 - mov r0, #BSP_SS2TX - b get_handler - -check_utx2: -#if 0 -MUST REMEMBER TO UNCOMMENT IF THIS HANDLER MOVES - ldr r4, [r2, #0x240] - ldr r5, [r2, #0x280] - and r6, r4, r5 /* only look at interrupts which are enabled */ -#endif - tst r6, #0x1000 - beq check_urx2 - mov r0, #BSP_UTXINT2 - b get_handler - -check_urx2: -#if 0 -MUST REMEMBER TO UNCOMMENT IF THIS HANDLER MOVES - ldr r4, [r2, #0x240] - ldr r5, [r2, #0x280] - and r6, r4, r5 /* only look at interrupts which are enabled */ -#endif - tst r6, #0x2000 - beq IRQ_NoInterrupt - mov r0, #BSP_URXINT2 - b get_handler - -get_handler: - - ldmia sp!,{r4, r5, r6} - - /* - * re-enable interrupts at processor level as the current - * interrupt source is now masked via VEGA logic - */ -/* - mrs r1, cpsr - and r1, r1, #0xFFFFFF3F - msr cpsr, r1 -*/ - - stmdb sp!,{lr} - bl edb7312_interrupt_dispatch - ldmia sp!,{lr} - -IRQ_NoInterrupt: - /* return to the "main" interrupt handler */ - mov pc, lr diff --git a/c/src/lib/libbsp/arm/edb7312/irq/irq.c b/c/src/lib/libbsp/arm/edb7312/irq/irq.c deleted file mode 100644 index 1d9151a1bd..0000000000 --- a/c/src/lib/libbsp/arm/edb7312/irq/irq.c +++ /dev/null @@ -1,180 +0,0 @@ -/* - * Cirrus EP7312 Intererrupt handler - */ - -/* - * Copyright (c) 2010 embedded brains GmbH. - * - * Copyright (c) 2002 by Jay Monkman - * - * Copyright (c) 2002 by Charlie Steader - * - * The license and distribution terms for this file may be - * found in the file LICENSE in this distribution or at - * http://www.rtems.org/license/LICENSE. -*/ - -#include - -#include -#include -#include - -#include - -void edb7312_interrupt_dispatch(rtems_vector_number vector) -{ - bsp_interrupt_handler_dispatch(vector); -} - -void bsp_interrupt_vector_enable(rtems_vector_number vector) -{ - bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector)); - - if(vector >= BSP_EXTFIQ && vector <= BSP_SSEOTI) - { - /* interrupt managed by INTMR1 and INTSR1 */ - *EP7312_INTMR1 |= (1 << vector); - } - else if(vector >= BSP_KBDINT && vector <= BSP_SS2TX) - { - /* interrupt managed by INTMR2 and INTSR2 */ - *EP7312_INTMR2 |= (1 << (vector - 16)); - } - else if(vector >= BSP_UTXINT2 && vector <= BSP_URXINT2) - { - /* interrupt managed by INTMR2 and INTSR2 */ - *EP7312_INTMR2 |= (1 << (vector - 7)); - } - else if(vector == BSP_DAIINT) - { - /* interrupt managed by INTMR3 and INTSR3 */ - *EP7312_INTMR3 |= (1 << (vector - 21)); - } -} - -void bsp_interrupt_vector_disable(rtems_vector_number vector) -{ - bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector)); - - if(vector >= BSP_EXTFIQ && vector <= BSP_SSEOTI) - { - /* interrupt managed by INTMR1 and INTSR1 */ - *EP7312_INTMR1 &= ~(1 << vector); - } - else if(vector >= BSP_KBDINT && vector <= BSP_SS2TX) - { - /* interrupt managed by INTMR2 and INTSR2 */ - *EP7312_INTMR2 &= ~(1 << (vector - 16)); - } - else if(vector >= BSP_UTXINT2 && vector <= BSP_URXINT2) - { - /* interrupt managed by INTMR2 and INTSR2 */ - *EP7312_INTMR2 &= ~(1 << (vector - 7)); - } - else if(vector == BSP_DAIINT) - { - /* interrupt managed by INTMR3 and INTSR3 */ - *EP7312_INTMR3 &= ~(1 << (vector - 21)); - } -} - -rtems_status_code bsp_interrupt_facility_initialize(void) -{ - uint32_t int_stat = 0; - - /* mask all interrupts */ - *EP7312_INTMR1 = 0x0; - *EP7312_INTMR2 = 0x0; - *EP7312_INTMR3 = 0x0; - - /* clear all pending interrupt status' */ - int_stat = *EP7312_INTSR1; - if(int_stat & EP7312_INTR1_EXTFIQ) - { - } - if(int_stat & EP7312_INTR1_BLINT) - { - *EP7312_BLEOI = 0xFFFFFFFF; - } - if(int_stat & EP7312_INTR1_WEINT) - { - *EP7312_TEOI = 0xFFFFFFFF; - } - if(int_stat & EP7312_INTR1_MCINT) - { - } - if(int_stat & EP7312_INTR1_CSINT) - { - *EP7312_COEOI = 0xFFFFFFFF; - } - if(int_stat & EP7312_INTR1_EINT1) - { - } - if(int_stat & EP7312_INTR1_EINT2) - { - } - if(int_stat & EP7312_INTR1_EINT3) - { - } - if(int_stat & EP7312_INTR1_TC1OI) - { - *EP7312_TC1EOI = 0xFFFFFFFF; - } - if(int_stat & EP7312_INTR1_TC2OI) - { - *EP7312_TC2EOI = 0xFFFFFFFF; - } - if(int_stat & EP7312_INTR1_RTCMI) - { - *EP7312_RTCEOI = 0xFFFFFFFF; - } - if(int_stat & EP7312_INTR1_TINT) - { - *EP7312_TEOI = 0xFFFFFFFF; - } - if(int_stat & EP7312_INTR1_URXINT1) - { - } - if(int_stat & EP7312_INTR1_UTXINT1) - { - } - if(int_stat & EP7312_INTR1_UMSINT) - { - *EP7312_UMSEOI = 0xFFFFFFFF; - } - if(int_stat & EP7312_INTR1_SSEOTI) - { - *EP7312_SYNCIO; - } - int_stat = *EP7312_INTSR1; - - int_stat = *EP7312_INTSR2; - if(int_stat & EP7312_INTR2_KBDINT) - { - *EP7312_KBDEOI = 0xFFFFFFFF; - } - if(int_stat & EP7312_INTR2_SS2RX) - { - } - if(int_stat & EP7312_INTR2_SS2TX) - { - } - if(int_stat & EP7312_INTR2_URXINT2) - { - } - if(int_stat & EP7312_INTR2_UTXINT2) - { - } - int_stat = *EP7312_INTSR2; - - int_stat = *EP7312_INTSR3; - if(int_stat & EP7312_INTR2_DAIINT) - { - } - int_stat = *EP7312_INTSR3; - - _CPU_ISR_install_vector(ARM_EXCEPTION_IRQ, _ARMV4_Exception_interrupt, NULL); - - return RTEMS_SUCCESSFUL; -} diff --git a/c/src/lib/libbsp/arm/gdbarmsim/Makefile.am b/c/src/lib/libbsp/arm/gdbarmsim/Makefile.am index cefe752a62..630e508797 100644 --- a/c/src/lib/libbsp/arm/gdbarmsim/Makefile.am +++ b/c/src/lib/libbsp/arm/gdbarmsim/Makefile.am @@ -39,8 +39,8 @@ librtemsbsp_a_SOURCES += ../../../../../../bsps/arm/gdbarmsim/start/bspstarthook librtemsbsp_a_SOURCES += ../../../../../../bsps/arm/shared/start/bsp-start-memcpy.S # IRQ -librtemsbsp_a_SOURCES += irq/irq.c -librtemsbsp_a_SOURCES += irq/irq-dispatch.c +librtemsbsp_a_SOURCES += ../../../../../../bsps/arm/gdbarmsim/irq/irq.c +librtemsbsp_a_SOURCES += ../../../../../../bsps/arm/gdbarmsim/irq/irq-dispatch.c librtemsbsp_a_SOURCES += ../../../../../../bsps/shared/irq/irq-default-handler.c # Cache diff --git a/c/src/lib/libbsp/arm/gdbarmsim/irq/irq-dispatch.c b/c/src/lib/libbsp/arm/gdbarmsim/irq/irq-dispatch.c deleted file mode 100644 index f045fb8149..0000000000 --- a/c/src/lib/libbsp/arm/gdbarmsim/irq/irq-dispatch.c +++ /dev/null @@ -1,50 +0,0 @@ -/** - * @file - * - * @ingroup bsp_interrupt - * - * @brief GDB ARM Simulator interrupt support. - */ - -/* - * Copyright (c) 2008-2012 embedded brains GmbH. All rights reserved. - * - * embedded brains GmbH - * Obere Lagerstr. 30 - * 82178 Puchheim - * Germany - * - * - * The license and distribution terms for this file may be - * found in the file LICENSE in this distribution or at - * http://www.rtems.org/license/LICENSE. - */ - -#include - -#include -#include -#include - -#ifdef ARM_MULTILIB_ARCH_V4 - -void bsp_interrupt_dispatch(void) -{ - /* Read current vector number */ - /* rtems_vector_number vector = VICVectAddr; */ - rtems_vector_number vector = 0; - - /* Enable interrupts in program status register */ - uint32_t psr = _ARMV4_Status_irq_enable(); - - /* Dispatch interrupt handlers */ - bsp_interrupt_handler_dispatch(vector); - - /* Restore program status register */ - _ARMV4_Status_restore(psr); - - /* Acknowledge interrupt */ - //VICVectAddr = 0; -} - -#endif /* ARM_MULTILIB_ARCH_V4 */ diff --git a/c/src/lib/libbsp/arm/gdbarmsim/irq/irq.c b/c/src/lib/libbsp/arm/gdbarmsim/irq/irq.c deleted file mode 100644 index 886f928d2d..0000000000 --- a/c/src/lib/libbsp/arm/gdbarmsim/irq/irq.c +++ /dev/null @@ -1,71 +0,0 @@ -/** - * @file - * - * @ingroup bsp_interrupt - * - * @brief GDB ARM Simulator interrupt support. - */ - -/* - * Copyright (c) 2008-2012 embedded brains GmbH. All rights reserved. - * - * embedded brains GmbH - * Obere Lagerstr. 30 - * 82178 Puchheim - * Germany - * - * - * The license and distribution terms for this file may be - * found in the file LICENSE in this distribution or at - * http://www.rtems.org/license/LICENSE. - */ - -#include -#include - -#include -#include -#include -#include - -/* - * Prototypes - */ -void lpc24xx_irq_set_priority(rtems_vector_number, unsigned); -unsigned lpc24xx_irq_get_priority(rtems_vector_number); - -static inline bool lpc24xx_irq_is_valid(rtems_vector_number vector) -{ - return vector <= BSP_INTERRUPT_VECTOR_MAX; -} - -void lpc24xx_irq_set_priority(rtems_vector_number vector, unsigned priority) -{ -} - -unsigned lpc24xx_irq_get_priority(rtems_vector_number vector) -{ - return 0; /* bogus value to avoid warning */ -} - -#ifdef ARM_MULTILIB_ARCH_V4 - -void bsp_interrupt_vector_enable(rtems_vector_number vector) -{ - bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector)); -} - -void bsp_interrupt_vector_disable(rtems_vector_number vector) -{ - bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector)); -} - -rtems_status_code bsp_interrupt_facility_initialize(void) -{ - /* Install the IRQ exception handler */ - _CPU_ISR_install_vector(ARM_EXCEPTION_IRQ, _ARMV4_Exception_interrupt, NULL); - - return RTEMS_SUCCESSFUL; -} - -#endif /* ARM_MULTILIB_ARCH_V4 */ diff --git a/c/src/lib/libbsp/arm/gumstix/Makefile.am b/c/src/lib/libbsp/arm/gumstix/Makefile.am index 6eac30b7c9..c39d886ca8 100644 --- a/c/src/lib/libbsp/arm/gumstix/Makefile.am +++ b/c/src/lib/libbsp/arm/gumstix/Makefile.am @@ -37,7 +37,7 @@ librtemsbsp_a_SOURCES += ../../../../../../bsps/arm/gumstix/console/uarts.c librtemsbsp_a_SOURCES += ../../../../../../bsps/arm/gumstix/console/ffuart.c # IRQ librtemsbsp_a_SOURCES += ../../../../../../bsps/shared/irq/irq-default-handler.c -librtemsbsp_a_SOURCES += irq/irq.c +librtemsbsp_a_SOURCES += ../../../../../../bsps/arm/gumstix/irq/irq.c # Cache librtemsbsp_a_SOURCES += ../../../../../../bsps/shared/cache/nocache.c diff --git a/c/src/lib/libbsp/arm/gumstix/irq/irq.c b/c/src/lib/libbsp/arm/gumstix/irq/irq.c deleted file mode 100644 index 425795b165..0000000000 --- a/c/src/lib/libbsp/arm/gumstix/irq/irq.c +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright (c) 2010 embedded brains GmbH. - * - * PXA255 Interrupt handler by Yang Xi - * Copyright (c) 2004 by Jay Monkman - * - * The license and distribution terms for this file may be - * found in the file LICENSE in this distribution or at - * http://www.rtems.org/license/LICENSE. - */ - -#include - -#include -#include -#include - -#include - -void bsp_interrupt_dispatch(void) -{ - rtems_vector_number vector = 31 - __builtin_clz(XSCALE_INT_ICIP); - - bsp_interrupt_handler_dispatch(vector); -} - -void bsp_interrupt_vector_enable(rtems_vector_number vector) -{ - bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector)); - XSCALE_INT_ICMR |= 1 << vector; -} - -void bsp_interrupt_vector_disable(rtems_vector_number vector) -{ - bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector)); - XSCALE_INT_ICMR &= ~(1 << vector); -} - -rtems_status_code bsp_interrupt_facility_initialize(void) -{ - /* disable all interrupts */ - XSCALE_INT_ICMR = 0x0; - - /* Direct the interrupt to IRQ*/ - XSCALE_INT_ICLR = 0x0; - - /* Install the IRQ exception handler */ - _CPU_ISR_install_vector(ARM_EXCEPTION_IRQ, _ARMV4_Exception_interrupt, NULL); - - return RTEMS_SUCCESSFUL; -} diff --git a/c/src/lib/libbsp/arm/imx/Makefile.am b/c/src/lib/libbsp/arm/imx/Makefile.am index 5d151d693f..84e043281b 100644 --- a/c/src/lib/libbsp/arm/imx/Makefile.am +++ b/c/src/lib/libbsp/arm/imx/Makefile.am @@ -53,7 +53,7 @@ endif # IRQ librtemsbsp_a_SOURCES += ../../../../../../bsps/shared/irq/irq-default-handler.c -librtemsbsp_a_SOURCES += ../shared/arm-gic-irq.c +librtemsbsp_a_SOURCES += ../../../../../../bsps/arm/shared/irq/irq-gic.c # Console librtemsbsp_a_SOURCES += ../../../../../../bsps/shared/dev/serial/console-termios.c diff --git a/c/src/lib/libbsp/arm/lm3s69xx/Makefile.am b/c/src/lib/libbsp/arm/lm3s69xx/Makefile.am index 10ce313f81..cfdcb79190 100644 --- a/c/src/lib/libbsp/arm/lm3s69xx/Makefile.am +++ b/c/src/lib/libbsp/arm/lm3s69xx/Makefile.am @@ -49,8 +49,8 @@ librtemsbsp_a_SOURCES += ../../../../../../bsps/arm/lm3s69xx/start/syscon.c # IRQ librtemsbsp_a_SOURCES += ../../../../../../bsps/shared/irq/irq-default-handler.c -librtemsbsp_a_SOURCES += ../shared/armv7m/irq/armv7m-irq.c -librtemsbsp_a_SOURCES += ../shared/armv7m/irq/armv7m-irq-dispatch.c +librtemsbsp_a_SOURCES += ../../../../../../bsps/arm/shared/irq/irq-armv7m.c +librtemsbsp_a_SOURCES += ../../../../../../bsps/arm/shared/irq/irq-dispatch-armv7m.c # Console librtemsbsp_a_SOURCES += ../../../../../../bsps/shared/dev/serial/legacy-console.c diff --git a/c/src/lib/libbsp/arm/lpc176x/Makefile.am b/c/src/lib/libbsp/arm/lpc176x/Makefile.am index 1437b12ea3..383bbfd51d 100644 --- a/c/src/lib/libbsp/arm/lpc176x/Makefile.am +++ b/c/src/lib/libbsp/arm/lpc176x/Makefile.am @@ -54,9 +54,9 @@ librtemsbsp_a_SOURCES += ../../../../../../bsps/arm/lpc176x/start/bspstart.c # IRQ librtemsbsp_a_SOURCES += ../../../../../../bsps/shared/irq/irq-default-handler.c -librtemsbsp_a_SOURCES += ../shared/armv7m/irq/armv7m-irq.c -librtemsbsp_a_SOURCES += ../shared/armv7m/irq/armv7m-irq-dispatch.c -librtemsbsp_a_SOURCES += irq/irq.c +librtemsbsp_a_SOURCES += ../../../../../../bsps/arm/shared/irq/irq-armv7m.c +librtemsbsp_a_SOURCES += ../../../../../../bsps/arm/shared/irq/irq-dispatch-armv7m.c +librtemsbsp_a_SOURCES += ../../../../../../bsps/arm/lpc176x/irq/irq.c # Console librtemsbsp_a_SOURCES += ../../../../../../bsps/shared/dev/serial/console-termios-init.c diff --git a/c/src/lib/libbsp/arm/lpc176x/irq/irq.c b/c/src/lib/libbsp/arm/lpc176x/irq/irq.c deleted file mode 100644 index e05fd59e6c..0000000000 --- a/c/src/lib/libbsp/arm/lpc176x/irq/irq.c +++ /dev/null @@ -1,75 +0,0 @@ -/** - * @file - * - * @ingroup bsp_interrupt - * - * @brief LPC176X interrupt support. - */ - -/* - * Copyright (c) 2008-2012 embedded brains GmbH. All rights reserved. - * - * embedded brains GmbH - * Obere Lagerstr. 30 - * 82178 Puchheim - * Germany - * - * - * The license and distribution terms for this file may be - * found in the file LICENSE in this distribution or at - * http://www.rtems.org/license/LICENSE. - */ - -#include -#include - -#include -#include -#include -#include -#include - -/** - * @brief Checks if the current interrupt vector length is valid or not. - * - * @param vector The current interrupt vector length. - * @return TRUE if valid. - * FALSE otherwise. - */ -static inline bool lpc176x_irq_is_valid( const rtems_vector_number vector ) -{ - return vector <= BSP_INTERRUPT_VECTOR_MAX; -} - -void lpc176x_irq_set_priority( - const rtems_vector_number vector, - unsigned priority -) -{ - if ( lpc176x_irq_is_valid( vector ) ) { - if ( priority > LPC176X_IRQ_PRIORITY_VALUE_MAX ) { - priority = LPC176X_IRQ_PRIORITY_VALUE_MAX; - } - - /* else implies that the priority is unlocked. Also, - there is nothing to do. */ - - _ARMV7M_NVIC_Set_priority( (int) vector, (int) ( priority << 3u ) ); - } - - /* else implies that the rtems vector number is invalid. Also, - there is nothing to do. */ -} - -unsigned lpc176x_irq_get_priority( const rtems_vector_number vector ) -{ - unsigned priority; - - if ( lpc176x_irq_is_valid( vector ) ) { - priority = (unsigned) ( _ARMV7M_NVIC_Get_priority( (int) vector ) >> 3u ); - } else { - priority = LPC176X_IRQ_PRIORITY_VALUE_MIN - 1u; - } - - return priority; -} diff --git a/c/src/lib/libbsp/arm/lpc24xx/Makefile.am b/c/src/lib/libbsp/arm/lpc24xx/Makefile.am index c1f33ae67f..57ffe00383 100644 --- a/c/src/lib/libbsp/arm/lpc24xx/Makefile.am +++ b/c/src/lib/libbsp/arm/lpc24xx/Makefile.am @@ -65,10 +65,10 @@ librtemsbsp_a_SOURCES += ../../../../../../bsps/arm/lpc24xx/start/bspstart.c # IRQ librtemsbsp_a_SOURCES += ../../../../../../bsps/shared/irq/irq-default-handler.c -librtemsbsp_a_SOURCES += ../shared/armv7m/irq/armv7m-irq.c -librtemsbsp_a_SOURCES += ../shared/armv7m/irq/armv7m-irq-dispatch.c -librtemsbsp_a_SOURCES += irq/irq.c -librtemsbsp_a_SOURCES += irq/irq-dispatch.c +librtemsbsp_a_SOURCES += ../../../../../../bsps/arm/shared/irq/irq-armv7m.c +librtemsbsp_a_SOURCES += ../../../../../../bsps/arm/shared/irq/irq-dispatch-armv7m.c +librtemsbsp_a_SOURCES += ../../../../../../bsps/arm/lpc24xx/irq/irq.c +librtemsbsp_a_SOURCES += ../../../../../../bsps/arm/lpc24xx/irq/irq-dispatch.c # Console librtemsbsp_a_SOURCES += ../../../../../../bsps/shared/dev/serial/console-termios-init.c diff --git a/c/src/lib/libbsp/arm/lpc24xx/irq/irq-dispatch.c b/c/src/lib/libbsp/arm/lpc24xx/irq/irq-dispatch.c deleted file mode 100644 index 66d05fdf9d..0000000000 --- a/c/src/lib/libbsp/arm/lpc24xx/irq/irq-dispatch.c +++ /dev/null @@ -1,50 +0,0 @@ -/** - * @file - * - * @ingroup bsp_interrupt - * - * @brief LPC24XX interrupt support. - */ - -/* - * Copyright (c) 2008-2012 embedded brains GmbH. All rights reserved. - * - * embedded brains GmbH - * Obere Lagerstr. 30 - * 82178 Puchheim - * Germany - * - * - * The license and distribution terms for this file may be - * found in the file LICENSE in this distribution or at - * http://www.rtems.org/license/LICENSE. - */ - -#include - -#include -#include -#include -#include - -#ifdef ARM_MULTILIB_ARCH_V4 - -void bsp_interrupt_dispatch(void) -{ - /* Read current vector number */ - rtems_vector_number vector = VICVectAddr; - - /* Enable interrupts in program status register */ - uint32_t psr = _ARMV4_Status_irq_enable(); - - /* Dispatch interrupt handlers */ - bsp_interrupt_handler_dispatch(vector); - - /* Restore program status register */ - _ARMV4_Status_restore(psr); - - /* Acknowledge interrupt */ - VICVectAddr = 0; -} - -#endif /* ARM_MULTILIB_ARCH_V4 */ diff --git a/c/src/lib/libbsp/arm/lpc24xx/irq/irq.c b/c/src/lib/libbsp/arm/lpc24xx/irq/irq.c deleted file mode 100644 index 7801c37843..0000000000 --- a/c/src/lib/libbsp/arm/lpc24xx/irq/irq.c +++ /dev/null @@ -1,120 +0,0 @@ -/** - * @file - * - * @ingroup bsp_interrupt - * - * @brief LPC24XX interrupt support. - */ - -/* - * Copyright (c) 2008-2012 embedded brains GmbH. All rights reserved. - * - * embedded brains GmbH - * Obere Lagerstr. 30 - * 82178 Puchheim - * Germany - * - * - * The license and distribution terms for this file may be - * found in the file LICENSE in this distribution or at - * http://www.rtems.org/license/LICENSE. - */ - -#include -#include - -#include -#include -#include -#include -#include - -static inline bool lpc24xx_irq_is_valid(rtems_vector_number vector) -{ - return vector <= BSP_INTERRUPT_VECTOR_MAX; -} - -void lpc24xx_irq_set_priority(rtems_vector_number vector, unsigned priority) -{ - if (lpc24xx_irq_is_valid(vector)) { - if (priority > LPC24XX_IRQ_PRIORITY_VALUE_MAX) { - priority = LPC24XX_IRQ_PRIORITY_VALUE_MAX; - } - - #ifdef ARM_MULTILIB_ARCH_V4 - VICVectPriorityBase [vector] = priority; - #else - _ARMV7M_NVIC_Set_priority((int) vector, (int) (priority << 3)); - #endif - } -} - -unsigned lpc24xx_irq_get_priority(rtems_vector_number vector) -{ - if (lpc24xx_irq_is_valid(vector)) { - #ifdef ARM_MULTILIB_ARCH_V4 - return VICVectPriorityBase [vector]; - #else - return (unsigned) (_ARMV7M_NVIC_Get_priority((int) vector) >> 3); - #endif - } else { - return LPC24XX_IRQ_PRIORITY_VALUE_MIN - 1U; - } -} - -#ifdef ARM_MULTILIB_ARCH_V4 - -void bsp_interrupt_vector_enable(rtems_vector_number vector) -{ - bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector)); - VICIntEnable = 1U << vector; -} - -void bsp_interrupt_vector_disable(rtems_vector_number vector) -{ - bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector)); - VICIntEnClear = 1U << vector; -} - -rtems_status_code bsp_interrupt_facility_initialize(void) -{ - volatile uint32_t *addr = VICVectAddrBase; - volatile uint32_t *prio = VICVectPriorityBase; - rtems_vector_number i = 0; - - /* Disable all interrupts */ - VICIntEnClear = 0xffffffff; - - /* Clear all software interrupts */ - VICSoftIntClear = 0xffffffff; - - /* Use IRQ category */ - VICIntSelect = 0; - - for (i = BSP_INTERRUPT_VECTOR_MIN; i <= BSP_INTERRUPT_VECTOR_MAX; ++i) { - /* Use the vector address register to store the vector number */ - addr [i] = i; - - /* Give vector lowest priority */ - prio [i] = 15; - } - - /* Reset priority mask register */ - VICSWPrioMask = 0xffff; - - /* Acknowledge interrupts for all priorities */ - for ( - i = LPC24XX_IRQ_PRIORITY_VALUE_MIN; - i <= LPC24XX_IRQ_PRIORITY_VALUE_MAX; - ++i - ) { - VICVectAddr = 0; - } - - /* Install the IRQ exception handler */ - _CPU_ISR_install_vector(ARM_EXCEPTION_IRQ, _ARMV4_Exception_interrupt, NULL); - - return RTEMS_SUCCESSFUL; -} - -#endif /* ARM_MULTILIB_ARCH_V4 */ diff --git a/c/src/lib/libbsp/arm/lpc32xx/Makefile.am b/c/src/lib/libbsp/arm/lpc32xx/Makefile.am index f11cd6ac48..4fa17d3361 100644 --- a/c/src/lib/libbsp/arm/lpc32xx/Makefile.am +++ b/c/src/lib/libbsp/arm/lpc32xx/Makefile.am @@ -56,7 +56,7 @@ librtemsbsp_a_SOURCES += ../../../../../../bsps/arm/lpc32xx/start/bspstart.c # IRQ librtemsbsp_a_SOURCES += ../../../../../../bsps/shared/irq/irq-default-handler.c -librtemsbsp_a_SOURCES += irq/irq.c +librtemsbsp_a_SOURCES += ../../../../../../bsps/arm/lpc32xx/irq/irq.c # Console librtemsbsp_a_SOURCES += ../../../../../../bsps/shared/dev/serial/console-termios-init.c diff --git a/c/src/lib/libbsp/arm/lpc32xx/irq/irq.c b/c/src/lib/libbsp/arm/lpc32xx/irq/irq.c deleted file mode 100755 index eac320000b..0000000000 --- a/c/src/lib/libbsp/arm/lpc32xx/irq/irq.c +++ /dev/null @@ -1,344 +0,0 @@ -/** - * @file - * - * @ingroup lpc32xx_interrupt - * - * @brief Interrupt support. - */ - -/* - * Copyright (c) 2009 - * embedded brains GmbH - * Obere Lagerstr. 30 - * D-82178 Puchheim - * Germany - * - * - * The license and distribution terms for this file may be - * found in the file LICENSE in this distribution or at - * http://www.rtems.org/license/LICENSE. - */ - -#include - -#include -#include -#include -#include -#include -#include - -/* - * Mask out SIC 1 and 2 IRQ request. There is no need to mask out the FIQ, - * since a pending FIQ would be a fatal error. The default handler will be - * invoked in this case. - */ -#define LPC32XX_MIC_STATUS_MASK (~0x3U) - -typedef union { - struct { - uint32_t mic; - uint32_t sic_1; - uint32_t sic_2; - } field; - uint32_t fields_table [LPC32XX_IRQ_MODULE_COUNT]; -} lpc32xx_irq_fields; - -static uint8_t lpc32xx_irq_priority_table [LPC32XX_IRQ_COUNT]; - -static lpc32xx_irq_fields lpc32xx_irq_priority_masks [LPC32XX_IRQ_PRIORITY_COUNT]; - -static lpc32xx_irq_fields lpc32xx_irq_enable; - -static inline bool lpc32xx_irq_priority_is_valid(unsigned priority) -{ - return priority <= LPC32XX_IRQ_PRIORITY_LOWEST; -} - -#define LPC32XX_IRQ_BIT_OPS_DEFINE \ - unsigned bit = index & 0x1fU; \ - unsigned module = index >> 5 - -#define LPC32XX_IRQ_BIT_OPS_FOR_REG_DEFINE \ - LPC32XX_IRQ_BIT_OPS_DEFINE; \ - unsigned module_offset = module << 14; \ - volatile uint32_t *reg = (volatile uint32_t *) \ - ((volatile char *) &lpc32xx.mic + module_offset + register_offset) - -#define LPC32XX_IRQ_OFFSET_ER 0U -#define LPC32XX_IRQ_OFFSET_RSR 4U -#define LPC32XX_IRQ_OFFSET_SR 8U -#define LPC32XX_IRQ_OFFSET_APR 12U -#define LPC32XX_IRQ_OFFSET_ATR 16U -#define LPC32XX_IRQ_OFFSET_ITR 20U - -static inline bool lpc32xx_irq_is_bit_set_in_register(unsigned index, unsigned register_offset) -{ - LPC32XX_IRQ_BIT_OPS_FOR_REG_DEFINE; - - return *reg & (1U << bit); -} - -static inline void lpc32xx_irq_set_bit_in_register(unsigned index, unsigned register_offset) -{ - LPC32XX_IRQ_BIT_OPS_FOR_REG_DEFINE; - - *reg |= 1U << bit; -} - -static inline void lpc32xx_irq_clear_bit_in_register(unsigned index, unsigned register_offset) -{ - LPC32XX_IRQ_BIT_OPS_FOR_REG_DEFINE; - - *reg &= ~(1U << bit); -} - -static inline void lpc32xx_irq_set_bit_in_field(unsigned index, lpc32xx_irq_fields *fields) -{ - LPC32XX_IRQ_BIT_OPS_DEFINE; - - fields->fields_table [module] |= 1U << bit; -} - -static inline void lpc32xx_irq_clear_bit_in_field(unsigned index, lpc32xx_irq_fields *fields) -{ - LPC32XX_IRQ_BIT_OPS_DEFINE; - - fields->fields_table [module] &= ~(1U << bit); -} - -static inline unsigned lpc32xx_irq_get_index(uint32_t val) -{ - ARM_SWITCH_REGISTERS; - - __asm__ volatile ( - ARM_SWITCH_TO_ARM - "clz %[val], %[val]\n" - "rsb %[val], %[val], #31\n" - ARM_SWITCH_BACK - : [val] "=r" (val) ARM_SWITCH_ADDITIONAL_OUTPUT - : "[val]" (val) - ); - - return val; -} - -void lpc32xx_irq_set_priority(rtems_vector_number vector, unsigned priority) -{ - if (bsp_interrupt_is_valid_vector(vector)) { - rtems_interrupt_level level; - unsigned i = 0; - - if (priority > LPC32XX_IRQ_PRIORITY_LOWEST) { - priority = LPC32XX_IRQ_PRIORITY_LOWEST; - } - - lpc32xx_irq_priority_table [vector] = (uint8_t) priority; - - for (i = LPC32XX_IRQ_PRIORITY_HIGHEST; i <= priority; ++i) { - rtems_interrupt_disable(level); - lpc32xx_irq_clear_bit_in_field(vector, &lpc32xx_irq_priority_masks [i]); - rtems_interrupt_enable(level); - } - - for (i = priority + 1; i <= LPC32XX_IRQ_PRIORITY_LOWEST; ++i) { - rtems_interrupt_disable(level); - lpc32xx_irq_set_bit_in_field(vector, &lpc32xx_irq_priority_masks [i]); - rtems_interrupt_enable(level); - } - } -} - -unsigned lpc32xx_irq_get_priority(rtems_vector_number vector) -{ - if (bsp_interrupt_is_valid_vector(vector)) { - return lpc32xx_irq_priority_table [vector]; - } else { - return LPC32XX_IRQ_PRIORITY_LOWEST; - } -} - -void lpc32xx_irq_set_activation_polarity(rtems_vector_number vector, lpc32xx_irq_activation_polarity activation_polarity) -{ - if (bsp_interrupt_is_valid_vector(vector)) { - rtems_interrupt_level level; - - rtems_interrupt_disable(level); - if (activation_polarity == LPC32XX_IRQ_ACTIVE_HIGH_OR_RISING_EDGE) { - lpc32xx_irq_set_bit_in_register(vector, LPC32XX_IRQ_OFFSET_APR); - } else { - lpc32xx_irq_clear_bit_in_register(vector, LPC32XX_IRQ_OFFSET_APR); - } - rtems_interrupt_enable(level); - } -} - -lpc32xx_irq_activation_polarity lpc32xx_irq_get_activation_polarity(rtems_vector_number vector) -{ - if (bsp_interrupt_is_valid_vector(vector)) { - if (lpc32xx_irq_is_bit_set_in_register(vector, LPC32XX_IRQ_OFFSET_APR)) { - return LPC32XX_IRQ_ACTIVE_HIGH_OR_RISING_EDGE; - } else { - return LPC32XX_IRQ_ACTIVE_LOW_OR_FALLING_EDGE; - } - } else { - return LPC32XX_IRQ_ACTIVE_LOW_OR_FALLING_EDGE; - } -} - -void lpc32xx_irq_set_activation_type(rtems_vector_number vector, lpc32xx_irq_activation_type activation_type) -{ - if (bsp_interrupt_is_valid_vector(vector)) { - rtems_interrupt_level level; - - rtems_interrupt_disable(level); - if (activation_type == LPC32XX_IRQ_EDGE_SENSITIVE) { - lpc32xx_irq_set_bit_in_register(vector, LPC32XX_IRQ_OFFSET_ATR); - } else { - lpc32xx_irq_clear_bit_in_register(vector, LPC32XX_IRQ_OFFSET_ATR); - } - rtems_interrupt_enable(level); - } -} - -lpc32xx_irq_activation_type lpc32xx_irq_get_activation_type(rtems_vector_number vector) -{ - if (bsp_interrupt_is_valid_vector(vector)) { - if (lpc32xx_irq_is_bit_set_in_register(vector, LPC32XX_IRQ_OFFSET_ATR)) { - return LPC32XX_IRQ_EDGE_SENSITIVE; - } else { - return LPC32XX_IRQ_LEVEL_SENSITIVE; - } - } else { - return LPC32XX_IRQ_LEVEL_SENSITIVE; - } -} - -void bsp_interrupt_dispatch(void) -{ - uint32_t status = lpc32xx.mic.sr & LPC32XX_MIC_STATUS_MASK; - uint32_t er_mic = lpc32xx.mic.er; - uint32_t er_sic_1 = lpc32xx.sic_1.er; - uint32_t er_sic_2 = lpc32xx.sic_2.er; - uint32_t psr = 0; - lpc32xx_irq_fields *masks = NULL; - rtems_vector_number vector = 0; - unsigned priority = 0; - - if (status != 0) { - vector = lpc32xx_irq_get_index(status); - } else { - status = lpc32xx.sic_1.sr; - if (status != 0) { - vector = lpc32xx_irq_get_index(status) + LPC32XX_IRQ_MODULE_SIC_1; - } else { - status = lpc32xx.sic_2.sr; - if (status != 0) { - vector = lpc32xx_irq_get_index(status) + LPC32XX_IRQ_MODULE_SIC_2; - } else { - return; - } - } - } - - priority = lpc32xx_irq_priority_table [vector]; - - masks = &lpc32xx_irq_priority_masks [priority]; - - lpc32xx.mic.er = er_mic & masks->field.mic; - lpc32xx.sic_1.er = er_sic_1 & masks->field.sic_1; - lpc32xx.sic_2.er = er_sic_2 & masks->field.sic_2; - - psr = _ARMV4_Status_irq_enable(); - - bsp_interrupt_handler_dispatch(vector); - - _ARMV4_Status_restore(psr); - - lpc32xx.mic.er = er_mic & lpc32xx_irq_enable.field.mic; - lpc32xx.sic_1.er = er_sic_1 & lpc32xx_irq_enable.field.sic_1; - lpc32xx.sic_2.er = er_sic_2 & lpc32xx_irq_enable.field.sic_2; -} - -void bsp_interrupt_vector_enable(rtems_vector_number vector) -{ - rtems_interrupt_level level; - - bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector)); - - rtems_interrupt_disable(level); - lpc32xx_irq_set_bit_in_register(vector, LPC32XX_IRQ_OFFSET_ER); - lpc32xx_irq_set_bit_in_field(vector, &lpc32xx_irq_enable); - rtems_interrupt_enable(level); -} - -void bsp_interrupt_vector_disable(rtems_vector_number vector) -{ - rtems_interrupt_level level; - - bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector)); - - rtems_interrupt_disable(level); - lpc32xx_irq_clear_bit_in_field(vector, &lpc32xx_irq_enable); - lpc32xx_irq_clear_bit_in_register(vector, LPC32XX_IRQ_OFFSET_ER); - rtems_interrupt_enable(level); -} - -void lpc32xx_set_exception_handler( - Arm_symbolic_exception_name exception, - void (*handler)(void) -) -{ - if ((unsigned) exception < MAX_EXCEPTIONS) { - uint32_t *table = (uint32_t *) bsp_vector_table_begin + MAX_EXCEPTIONS; - - table [exception] = (uint32_t) handler; - - #ifndef LPC32XX_DISABLE_MMU - rtems_cache_flush_multiple_data_lines(table, 64); - rtems_cache_invalidate_multiple_instruction_lines(NULL, 64); - #endif - } -} - -rtems_status_code bsp_interrupt_facility_initialize(void) -{ - size_t i = 0; - - /* Set default priority */ - for (i = 0; i < LPC32XX_IRQ_COUNT; ++i) { - lpc32xx_irq_priority_table [i] = LPC32XX_IRQ_PRIORITY_LOWEST; - } - - /* Enable SIC 1 and 2 at all priorities */ - for (i = 0; i < LPC32XX_IRQ_PRIORITY_COUNT; ++i) { - lpc32xx_irq_priority_masks [i].field.mic = 0xc0000003; - } - - /* Disable all interrupts except SIC 1 and 2 */ - lpc32xx_irq_enable.field.sic_2 = 0x0; - lpc32xx_irq_enable.field.sic_1 = 0x0; - lpc32xx_irq_enable.field.mic = 0xc0000003; - lpc32xx.sic_1.er = 0x0; - lpc32xx.sic_2.er = 0x0; - lpc32xx.mic.er = 0xc0000003; - - /* Set interrupt types to IRQ */ - lpc32xx.mic.itr = 0x0; - lpc32xx.sic_1.itr = 0x0; - lpc32xx.sic_2.itr = 0x0; - - /* Set interrupt activation polarities */ - lpc32xx.mic.apr = 0x3ff0efe0; - lpc32xx.sic_1.apr = 0xfbd27184; - lpc32xx.sic_2.apr = 0x801810c0; - - /* Set interrupt activation types */ - lpc32xx.mic.atr = 0x0; - lpc32xx.sic_1.atr = 0x26000; - lpc32xx.sic_2.atr = 0x0; - - lpc32xx_set_exception_handler(ARM_EXCEPTION_IRQ, _ARMV4_Exception_interrupt); - - return RTEMS_SUCCESSFUL; -} diff --git a/c/src/lib/libbsp/arm/raspberrypi/Makefile.am b/c/src/lib/libbsp/arm/raspberrypi/Makefile.am index a2ca41b2c1..1e70a2b657 100644 --- a/c/src/lib/libbsp/arm/raspberrypi/Makefile.am +++ b/c/src/lib/libbsp/arm/raspberrypi/Makefile.am @@ -63,7 +63,7 @@ librtemsbsp_a_SOURCES += ../../../../../../bsps/arm/raspberrypi/start/bspreset.c # IRQ librtemsbsp_a_SOURCES += ../shared/arm-cp15-set-exception-handler.c -librtemsbsp_a_SOURCES += irq/irq.c +librtemsbsp_a_SOURCES += ../../../../../../bsps/arm/raspberrypi/irq/irq.c # Console librtemsbsp_a_SOURCES += ../../../../../../bsps/shared/dev/serial/legacy-console.c diff --git a/c/src/lib/libbsp/arm/raspberrypi/irq/irq.c b/c/src/lib/libbsp/arm/raspberrypi/irq/irq.c deleted file mode 100644 index 5b10385bfe..0000000000 --- a/c/src/lib/libbsp/arm/raspberrypi/irq/irq.c +++ /dev/null @@ -1,168 +0,0 @@ -/** - * @file irq.c - * - * @ingroup raspberrypi_interrupt - * - * @brief Interrupt support. - */ - -/* - * Copyright (c) 2014 Andre Marques - * - * Copyright (c) 2009 - * embedded brains GmbH - * Obere Lagerstr. 30 - * D-82178 Puchheim - * Germany - * - * - * The license and distribution terms for this file may be - * found in the file LICENSE in this distribution or at - * http://www.rtems.org/license/LICENSE. - */ - -#include - -#include -#include -#include -#include -#include -#include -#include -#include - -#ifdef RTEMS_SMP -#include -#include -#endif - -typedef struct { - unsigned long enable_reg_addr; - unsigned long disable_reg_addr; -} bcm2835_irq_ctrl_reg_t; - -static const bcm2835_irq_ctrl_reg_t bcm2835_irq_ctrl_reg_table[] = { - { BCM2835_IRQ_ENABLE1, BCM2835_IRQ_DISABLE1 }, - { BCM2835_IRQ_ENABLE2, BCM2835_IRQ_DISABLE2 }, - { BCM2835_IRQ_ENABLE_BASIC, BCM2835_IRQ_DISABLE_BASIC } -}; - -static inline const bcm2835_irq_ctrl_reg_t * -bsp_vector_to_reg(rtems_vector_number vector) -{ - return bcm2835_irq_ctrl_reg_table + (vector >> 5); -} - -static inline uint32_t -bsp_vector_to_mask(rtems_vector_number vector) -{ - return 1 << (vector & 0x1f); -} - -static const int bcm2835_irq_speedup_table[] = -{ - /* 0 */ BCM2835_IRQ_ID_BASIC_BASE_ID + 0, - /* 1 */ BCM2835_IRQ_ID_BASIC_BASE_ID + 1, - /* 2 */ BCM2835_IRQ_ID_BASIC_BASE_ID + 2, - /* 3 */ BCM2835_IRQ_ID_BASIC_BASE_ID + 3, - /* 4 */ BCM2835_IRQ_ID_BASIC_BASE_ID + 4, - /* 5 */ BCM2835_IRQ_ID_BASIC_BASE_ID + 5, - /* 6 */ BCM2835_IRQ_ID_BASIC_BASE_ID + 6, - /* 7 */ BCM2835_IRQ_ID_BASIC_BASE_ID + 7, - /* 8 */ -1, /* One or more bits set in pending register 1 */ - /* 9 */ -2, /* One or more bits set in pending register 2 */ - /* 10 */ 7, /* GPU IRQ 7 */ - /* 11 */ 9, /* GPU IRQ 9 */ - /* 12 */ 10, /* GPU IRQ 10 */ - /* 13 */ 18, /* GPU IRQ 18 */ - /* 14 */ 19, /* GPU IRQ 19 */ - /* 15 */ 53, /* GPU IRQ 53 */ - /* 16 */ 54, /* GPU IRQ 54 */ - /* 17 */ 55, /* GPU IRQ 55 */ - /* 18 */ 56, /* GPU IRQ 56 */ - /* 19 */ 57, /* GPU IRQ 57 */ - /* 20 */ 62, /* GPU IRQ 62 */ -}; - -/* - * Define which basic peding register (BCM2835_IRQ_BASIC) bits - * should be processed through bcm2835_irq_speedup_table - */ - -#define BCM2835_IRQ_BASIC_SPEEDUP_USED_BITS 0x1ffcff - -/* - * Determine the source of the interrupt and dispatch the correct handler. - */ -void bsp_interrupt_dispatch(void) -{ - unsigned int pend; - unsigned int pend_bit; - - rtems_vector_number vector = 255; - -#ifdef RTEMS_SMP - uint32_t cpu_index_self = _SMP_Get_current_processor(); - uint32_t local_source = BCM2835_REG(BCM2836_IRQ_SOURCE_REG(cpu_index_self)); - - if ( local_source & BCM2836_IRQ_SOURCE_MBOX3 ) { - /* reset mailbox 3 contents to zero */ - BCM2835_REG(BCM2836_MAILBOX_3_READ_CLEAR_BASE + 0x10 * cpu_index_self) = 0xffffffff; - _SMP_Inter_processor_interrupt_handler(); - } - if ( cpu_index_self != 0 ) - return; -#endif /* RTEMS_SMP */ - - pend = BCM2835_REG(BCM2835_IRQ_BASIC); - if ( pend & BCM2835_IRQ_BASIC_SPEEDUP_USED_BITS ) { - pend_bit = ffs(pend) - 1; - vector = bcm2835_irq_speedup_table[pend_bit]; - } else { - pend = BCM2835_REG(BCM2835_IRQ_PENDING1); - if ( pend != 0 ) { - pend_bit = ffs(pend) - 1; - vector = pend_bit; - } else { - pend = BCM2835_REG(BCM2835_IRQ_PENDING2); - if ( pend != 0 ) { - pend_bit = ffs(pend) - 1; - vector = pend_bit + 32; - } - } - } - - if ( vector < 255 ) - { - bsp_interrupt_handler_dispatch(vector); - } -} - -void bsp_interrupt_vector_enable(rtems_vector_number vector) -{ - bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector)); - BCM2835_REG(bsp_vector_to_reg(vector)->enable_reg_addr) = - bsp_vector_to_mask(vector); -} - -void bsp_interrupt_vector_disable(rtems_vector_number vector) -{ - bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector)); - BCM2835_REG(bsp_vector_to_reg(vector)->disable_reg_addr) = - bsp_vector_to_mask(vector); -} - -void bsp_interrupt_handler_default(rtems_vector_number vector) -{ - printk("spurious interrupt: %lu\n", vector); -} - -rtems_status_code bsp_interrupt_facility_initialize(void) -{ - BCM2835_REG(BCM2835_IRQ_DISABLE1) = 0xffffffff; - BCM2835_REG(BCM2835_IRQ_DISABLE2) = 0xffffffff; - BCM2835_REG(BCM2835_IRQ_DISABLE_BASIC) = 0xffffffff; - BCM2835_REG(BCM2835_IRQ_FIQ_CTRL) = 0; - return RTEMS_SUCCESSFUL; -} diff --git a/c/src/lib/libbsp/arm/realview-pbx-a9/Makefile.am b/c/src/lib/libbsp/arm/realview-pbx-a9/Makefile.am index 64b89754a2..2eb2cec443 100644 --- a/c/src/lib/libbsp/arm/realview-pbx-a9/Makefile.am +++ b/c/src/lib/libbsp/arm/realview-pbx-a9/Makefile.am @@ -58,7 +58,7 @@ endif # IRQ librtemsbsp_a_SOURCES += ../../../../../../bsps/shared/irq/irq-default-handler.c -librtemsbsp_a_SOURCES += ../shared/arm-gic-irq.c +librtemsbsp_a_SOURCES += ../../../../../../bsps/arm/shared/irq/irq-gic.c # Console librtemsbsp_a_SOURCES += ../../../../../../bsps/shared/dev/serial/console-termios-init.c diff --git a/c/src/lib/libbsp/arm/rtl22xx/Makefile.am b/c/src/lib/libbsp/arm/rtl22xx/Makefile.am index 7a8ff9e58e..94fadf0507 100644 --- a/c/src/lib/libbsp/arm/rtl22xx/Makefile.am +++ b/c/src/lib/libbsp/arm/rtl22xx/Makefile.am @@ -36,7 +36,7 @@ librtemsbsp_a_SOURCES += ../../../../../../bsps/shared/dev/serial/legacy-console librtemsbsp_a_SOURCES += ../../../../../../bsps/arm/rtl22xx/console/uart.c # IRQ librtemsbsp_a_SOURCES += ../../../../../../bsps/shared/irq/irq-default-handler.c -librtemsbsp_a_SOURCES += irq/irq.c +librtemsbsp_a_SOURCES += ../../../../../../bsps/arm/rtl22xx/irq/irq.c # Cache librtemsbsp_a_SOURCES += ../../../../../../bsps/shared/cache/nocache.c diff --git a/c/src/lib/libbsp/arm/rtl22xx/irq/irq.c b/c/src/lib/libbsp/arm/rtl22xx/irq/irq.c deleted file mode 100644 index 83e140bd7b..0000000000 --- a/c/src/lib/libbsp/arm/rtl22xx/irq/irq.c +++ /dev/null @@ -1,70 +0,0 @@ -/* - * Philps LPC22XX Interrupt handler - * - * Copyright (c) 2010 embedded brains GmbH. - * - * Copyright (c) 2006 by Ray to support LPC ARM - * The license and distribution terms for this file may be - * found in the file LICENSE in this distribution or at - * http://www.rtems.org/license/LICENSE. - */ - -#include - -#include -#include -#include - -#include - -void bsp_interrupt_dispatch(void) -{ - rtems_vector_number vector = 31 - __builtin_clz(VICIRQStatus); - - bsp_interrupt_handler_dispatch(vector); - - VICVectAddr = 0; -} - -void bsp_interrupt_vector_enable(rtems_vector_number vector) -{ - bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector)); - VICIntEnable |= 1 << vector; -} - -void bsp_interrupt_vector_disable(rtems_vector_number vector) -{ - bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector)); - VICIntEnClr = 1 << vector; -} - -rtems_status_code bsp_interrupt_facility_initialize(void) -{ - volatile uint32_t *ctrl = (volatile uint32_t *) VICVectCntlBase; - size_t i = 0; - - /* Disable all interrupts */ - VICIntEnClr = 0xffffffff; - - /* Use IRQ category */ - VICIntSelect = 0; - - /* Enable access in USER mode */ - VICProtection = 0; - - for (i = 0; i < 16; ++i) { - /* Disable vector mode */ - ctrl [i] = 0; - - /* Acknowledge interrupts for all priorities */ - VICVectAddr = 0; - } - - /* Acknowledge interrupts for all priorities */ - VICVectAddr = 0; - - /* Install the IRQ exception handler */ - _CPU_ISR_install_vector(ARM_EXCEPTION_IRQ, _ARMV4_Exception_interrupt, NULL); - - return RTEMS_SUCCESSFUL; -} diff --git a/c/src/lib/libbsp/arm/shared/arm-gic-irq.c b/c/src/lib/libbsp/arm/shared/arm-gic-irq.c deleted file mode 100644 index ea4b6ef06a..0000000000 --- a/c/src/lib/libbsp/arm/shared/arm-gic-irq.c +++ /dev/null @@ -1,180 +0,0 @@ -/* - * Copyright (c) 2013 embedded brains GmbH. All rights reserved. - * - * embedded brains GmbH - * Dornierstr. 4 - * 82178 Puchheim - * Germany - * - * - * The license and distribution terms for this file may be - * found in the file LICENSE in this distribution or at - * http://www.rtems.org/license/LICENSE. - */ - -#include - -#include - -#include - -#include -#include -#include - -#define GIC_CPUIF ((volatile gic_cpuif *) BSP_ARM_GIC_CPUIF_BASE) - -#define PRIORITY_DEFAULT 127 - -void bsp_interrupt_dispatch(void) -{ - volatile gic_cpuif *cpuif = GIC_CPUIF; - uint32_t icciar = cpuif->icciar; - rtems_vector_number vector = GIC_CPUIF_ICCIAR_ACKINTID_GET(icciar); - rtems_vector_number spurious = 1023; - - if (vector != spurious) { - uint32_t psr = _ARMV4_Status_irq_enable(); - - bsp_interrupt_handler_dispatch(vector); - - _ARMV4_Status_restore(psr); - - cpuif->icceoir = icciar; - } -} - -void bsp_interrupt_vector_enable(rtems_vector_number vector) -{ - volatile gic_dist *dist = ARM_GIC_DIST; - - bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector)); - - gic_id_enable(dist, vector); -} - -void bsp_interrupt_vector_disable(rtems_vector_number vector) -{ - volatile gic_dist *dist = ARM_GIC_DIST; - - bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector)); - - gic_id_disable(dist, vector); -} - -static inline uint32_t get_id_count(volatile gic_dist *dist) -{ - uint32_t id_count = GIC_DIST_ICDICTR_IT_LINES_NUMBER_GET(dist->icdictr); - - id_count = 32 * (id_count + 1); - id_count = id_count <= 1020 ? id_count : 1020; - - return id_count; -} - -rtems_status_code bsp_interrupt_facility_initialize(void) -{ - volatile gic_cpuif *cpuif = GIC_CPUIF; - volatile gic_dist *dist = ARM_GIC_DIST; - uint32_t id_count = get_id_count(dist); - uint32_t id; - - arm_cp15_set_exception_handler( - ARM_EXCEPTION_IRQ, - _ARMV4_Exception_interrupt - ); - - for (id = 0; id < id_count; id += 32) { - dist->icdicer[id / 32] = 0xffffffff; - } - - for (id = 0; id < id_count; ++id) { - gic_id_set_priority(dist, id, PRIORITY_DEFAULT); - } - - for (id = 32; id < id_count; ++id) { - gic_id_set_targets(dist, id, 0x01); - } - - cpuif->iccpmr = GIC_CPUIF_ICCPMR_PRIORITY(0xff); - cpuif->iccbpr = GIC_CPUIF_ICCBPR_BINARY_POINT(0x0); - cpuif->iccicr = GIC_CPUIF_ICCICR_ENABLE; - - dist->icddcr = GIC_DIST_ICDDCR_ENABLE; - - return RTEMS_SUCCESSFUL; -} - -#ifdef RTEMS_SMP -BSP_START_TEXT_SECTION void arm_gic_irq_initialize_secondary_cpu(void) -{ - volatile gic_cpuif *cpuif = GIC_CPUIF; - volatile gic_dist *dist = ARM_GIC_DIST; - - while ((dist->icddcr & GIC_DIST_ICDDCR_ENABLE) == 0) { - /* Wait */ - } - - cpuif->iccpmr = GIC_CPUIF_ICCPMR_PRIORITY(0xff); - cpuif->iccbpr = GIC_CPUIF_ICCBPR_BINARY_POINT(0x0); - cpuif->iccicr = GIC_CPUIF_ICCICR_ENABLE; -} -#endif - -rtems_status_code arm_gic_irq_set_priority( - rtems_vector_number vector, - uint8_t priority -) -{ - rtems_status_code sc = RTEMS_SUCCESSFUL; - - if (bsp_interrupt_is_valid_vector(vector)) { - volatile gic_dist *dist = ARM_GIC_DIST; - - gic_id_set_priority(dist, vector, priority); - } else { - sc = RTEMS_INVALID_ID; - } - - return sc; -} - -rtems_status_code arm_gic_irq_get_priority( - rtems_vector_number vector, - uint8_t *priority -) -{ - rtems_status_code sc = RTEMS_SUCCESSFUL; - - if (bsp_interrupt_is_valid_vector(vector)) { - volatile gic_dist *dist = ARM_GIC_DIST; - - *priority = gic_id_get_priority(dist, vector); - } else { - sc = RTEMS_INVALID_ID; - } - - return sc; -} - -void bsp_interrupt_set_affinity( - rtems_vector_number vector, - const Processor_mask *affinity -) -{ - volatile gic_dist *dist = ARM_GIC_DIST; - uint8_t targets = (uint8_t) _Processor_mask_To_uint32_t(affinity, 0); - - gic_id_set_targets(dist, vector, targets); -} - -void bsp_interrupt_get_affinity( - rtems_vector_number vector, - Processor_mask *affinity -) -{ - volatile gic_dist *dist = ARM_GIC_DIST; - uint8_t targets = gic_id_get_targets(dist, vector); - - _Processor_mask_From_uint32_t(affinity, targets, 0); -} diff --git a/c/src/lib/libbsp/arm/shared/armv7m/irq/armv7m-irq-dispatch.c b/c/src/lib/libbsp/arm/shared/armv7m/irq/armv7m-irq-dispatch.c deleted file mode 100644 index c810a9784a..0000000000 --- a/c/src/lib/libbsp/arm/shared/armv7m/irq/armv7m-irq-dispatch.c +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright (c) 2011-2012 Sebastian Huber. All rights reserved. - * - * embedded brains GmbH - * Obere Lagerstr. 30 - * 82178 Puchheim - * Germany - * - * - * The license and distribution terms for this file may be - * found in the file LICENSE in this distribution or at - * http://www.rtems.org/license/LICENSE. - */ - -#include - -#include -#include - -#ifdef ARM_MULTILIB_ARCH_V7M - -void _ARMV7M_NVIC_Interrupt_dispatch(void) -{ - rtems_vector_number vector = - ARMV7M_SCB_ICSR_VECTACTIVE_GET(_ARMV7M_SCB->icsr); - - _ARMV7M_Interrupt_service_enter(); - bsp_interrupt_handler_dispatch(ARMV7M_IRQ_OF_VECTOR(vector)); - _ARMV7M_Interrupt_service_leave(); -} - -#endif /* ARM_MULTILIB_ARCH_V7M */ diff --git a/c/src/lib/libbsp/arm/shared/armv7m/irq/armv7m-irq.c b/c/src/lib/libbsp/arm/shared/armv7m/irq/armv7m-irq.c deleted file mode 100644 index 99c0e373bf..0000000000 --- a/c/src/lib/libbsp/arm/shared/armv7m/irq/armv7m-irq.c +++ /dev/null @@ -1,67 +0,0 @@ -/* - * Copyright (c) 2011-2012 Sebastian Huber. All rights reserved. - * - * embedded brains GmbH - * Obere Lagerstr. 30 - * 82178 Puchheim - * Germany - * - * - * The license and distribution terms for this file may be - * found in the file LICENSE in this distribution or at - * http://www.rtems.org/license/LICENSE. - */ - -#include - -#include - -#include -#include -#include -#include -#include - -#ifdef ARM_MULTILIB_ARCH_V7M - -void bsp_interrupt_vector_enable(rtems_vector_number vector) -{ - bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector)); - _ARMV7M_NVIC_Set_enable((int) vector); -} - -void bsp_interrupt_vector_disable(rtems_vector_number vector) -{ - bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector)); - _ARMV7M_NVIC_Clear_enable((int) vector); -} - -rtems_status_code bsp_interrupt_facility_initialize(void) -{ - int i; - ARMV7M_Exception_handler *vector_table = - (ARMV7M_Exception_handler *) bsp_vector_table_begin; - - if (bsp_vector_table_begin != bsp_start_vector_table_begin) { - memcpy( - vector_table, - bsp_start_vector_table_begin, - (size_t) bsp_vector_table_size - ); - } - - _ARMV7M_SCB->icsr = ARMV7M_SCB_ICSR_PENDSVCLR | ARMV7M_SCB_ICSR_PENDSTCLR; - - for (i = BSP_INTERRUPT_VECTOR_MIN; i <= BSP_INTERRUPT_VECTOR_MAX; ++i) { - vector_table [ARMV7M_VECTOR_IRQ(i)] = _ARMV7M_NVIC_Interrupt_dispatch; - _ARMV7M_NVIC_Clear_enable(i); - _ARMV7M_NVIC_Clear_pending(i); - _ARMV7M_NVIC_Set_priority(i, BSP_ARMV7M_IRQ_PRIORITY_DEFAULT); - } - - _ARMV7M_SCB->vtor = vector_table; - - return RTEMS_SUCCESSFUL; -} - -#endif /* ARM_MULTILIB_ARCH_V7M */ diff --git a/c/src/lib/libbsp/arm/smdk2410/Makefile.am b/c/src/lib/libbsp/arm/smdk2410/Makefile.am index 6fe9190c4b..b51434df50 100644 --- a/c/src/lib/libbsp/arm/smdk2410/Makefile.am +++ b/c/src/lib/libbsp/arm/smdk2410/Makefile.am @@ -37,7 +37,7 @@ librtemsbsp_a_SOURCES += ../../../../../../bsps/shared/dev/serial/legacy-console librtemsbsp_a_SOURCES += ../../../../../../bsps/arm/smdk2410/console/uart.c # IRQ librtemsbsp_a_SOURCES += ../../../../../../bsps/shared/irq/irq-default-handler.c -librtemsbsp_a_SOURCES += irq/irq.c +librtemsbsp_a_SOURCES += ../../../../../../bsps/arm/smdk2410/irq/irq.c # smc librtemsbsp_a_SOURCES += smc/smc.c diff --git a/c/src/lib/libbsp/arm/smdk2410/irq/irq.c b/c/src/lib/libbsp/arm/smdk2410/irq/irq.c deleted file mode 100644 index ea8f610353..0000000000 --- a/c/src/lib/libbsp/arm/smdk2410/irq/irq.c +++ /dev/null @@ -1,45 +0,0 @@ -/* irq.c - * - * This file contains the implementation of the function described in irq.h - * - * Copyright (c) 2010 embedded brains GmbH. - * - * CopyRight (C) 2000 Canon Research France SA. - * Emmanuel Raguet, mailto:raguet@crf.canon.fr - * - * The license and distribution terms for this file may be - * found in the file LICENSE in this distribution or at - * http://www.rtems.org/license/LICENSE. - */ - -#include - -#include -#include -#include - -#include - -void bsp_interrupt_dispatch(void) -{ - rtems_vector_number vector = *((uint32_t *) rINTOFFSET_ADDR); - - bsp_interrupt_handler_dispatch(vector); -} - -void bsp_interrupt_vector_enable(rtems_vector_number vector) -{ - bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector)); -} - -void bsp_interrupt_vector_disable(rtems_vector_number vector) -{ - bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector)); -} - -rtems_status_code bsp_interrupt_facility_initialize(void) -{ - _CPU_ISR_install_vector(ARM_EXCEPTION_IRQ, _ARMV4_Exception_interrupt, NULL); - - return RTEMS_SUCCESSFUL; -} diff --git a/c/src/lib/libbsp/arm/stm32f4/Makefile.am b/c/src/lib/libbsp/arm/stm32f4/Makefile.am index 4671386696..5f4be7dc71 100644 --- a/c/src/lib/libbsp/arm/stm32f4/Makefile.am +++ b/c/src/lib/libbsp/arm/stm32f4/Makefile.am @@ -49,8 +49,8 @@ librtemsbsp_a_SOURCES += ../../../../../../bsps/arm/stm32f4/start/start-config-i # IRQ librtemsbsp_a_SOURCES += ../../../../../../bsps/shared/irq/irq-default-handler.c -librtemsbsp_a_SOURCES += ../shared/armv7m/irq/armv7m-irq.c -librtemsbsp_a_SOURCES += ../shared/armv7m/irq/armv7m-irq-dispatch.c +librtemsbsp_a_SOURCES += ../../../../../../bsps/arm/shared/irq/irq-armv7m.c +librtemsbsp_a_SOURCES += ../../../../../../bsps/arm/shared/irq/irq-dispatch-armv7m.c # Console librtemsbsp_a_SOURCES += ../../../../../../bsps/shared/dev/serial/legacy-console.c diff --git a/c/src/lib/libbsp/arm/tms570/Makefile.am b/c/src/lib/libbsp/arm/tms570/Makefile.am index 4532449623..57762d0314 100644 --- a/c/src/lib/libbsp/arm/tms570/Makefile.am +++ b/c/src/lib/libbsp/arm/tms570/Makefile.am @@ -59,7 +59,7 @@ librtemsbsp_a_SOURCES += ../../../../../../bsps/arm/tms570/start/tms570-pom.c # IRQ librtemsbsp_a_SOURCES += ../../../../../../bsps/shared/irq/irq-default-handler.c -librtemsbsp_a_SOURCES += irq/irq.c +librtemsbsp_a_SOURCES += ../../../../../../bsps/arm/tms570/irq/irq.c # Console librtemsbsp_a_SOURCES += ../../../../../../bsps/shared/dev/serial/console-termios.c diff --git a/c/src/lib/libbsp/arm/tms570/irq/irq.c b/c/src/lib/libbsp/arm/tms570/irq/irq.c deleted file mode 100644 index 579c11ed2a..0000000000 --- a/c/src/lib/libbsp/arm/tms570/irq/irq.c +++ /dev/null @@ -1,202 +0,0 @@ -/** - * @file irq.c - * - * @ingroup tms570 - * - * @brief TMS570 interrupt support functions definitions. - */ - -/* - * Copyright (c) 2014 Premysl Houdek - * - * Google Summer of Code 2014 at - * Czech Technical University in Prague - * Zikova 1903/4 - * 166 36 Praha 6 - * Czech Republic - * - * Based on LPC24xx and LPC1768 BSP - * - * The license and distribution terms for this file may be - * found in the file LICENSE in this distribution or at - * http://www.rtems.org/license/LICENSE. - */ - -#include -#include -#include -#include -#include - -unsigned int priorityTable[BSP_INTERRUPT_VECTOR_MAX+1]; - -/** - * @brief Set priority of the interrupt vector. - * - * This function is here because of compability. It should set - * priority of the interrupt vector. - * @warning It does not set any priority at HW layer. It is nearly imposible to - * @warning set priority of the interrupt on TMS570 in a nice way. - * @param[in] vector vector of isr - * @param[in] priority new priority assigned to the vector - * @return Void - */ -void tms570_irq_set_priority( - rtems_vector_number vector, - unsigned priority -) -{ - if ( bsp_interrupt_is_valid_vector(vector) ) { - priorityTable[vector] = priority; - } -} - -/** - * @brief Gets priority of the interrupt vector. - * - * This function is here because of compability. It returns priority - * of the isr vector last set by tms570_irq_set_priority function. - * - * @warning It does not return any real priority of the HW layer. - * @param[in] vector vector of isr - * @retval 0 vector is invalid. - * @retval priority priority of the interrupt - */ -unsigned tms570_irq_get_priority( - rtems_vector_number vector -) -{ - if ( bsp_interrupt_is_valid_vector(vector) ) { - return priorityTable[vector]; - } - return 0; -} - -/** - * @brief Interrupt dispatch - * - * Called by OS to determine which interrupt occured. - * Function passes control to interrupt handler. - * - * @return Void - */ -void bsp_interrupt_dispatch(void) -{ - rtems_vector_number vector = TMS570_VIM.IRQINDEX-1; - - bsp_interrupt_handler_dispatch(vector); -} - -/** - * @brief enables interrupt vector in the HW - * - * Enables HW interrupt for specified vector - * - * @param[in] vector vector of the isr which needs to be enabled. - * @retval RTEMS_INVALID_ID vector is invalid. - * @retval RTEMS_SUCCESSFUL interrupt source enabled. - */ -void bsp_interrupt_vector_enable( - rtems_vector_number vector -) -{ - bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector)); - TMS570_VIM.REQENASET[vector >> 5] = 1 << (vector & 0x1f); -} - -/** - * @brief disables interrupt vector in the HW - * - * Disables HW interrupt for specified vector - * - * @param[in] vector vector of the isr which needs to be disabled. - * @retval RTEMS_INVALID_ID vector is invalid. - * @retval RTEMS_SUCCESSFUL interrupt source disabled. - */ -void bsp_interrupt_vector_disable( - rtems_vector_number vector -) -{ - bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector)); - TMS570_VIM.REQENACLR[vector >> 5] = 1 << (vector & 0x1f); -} - -/** - * @brief Init function of interrupt module - * - * Resets vectored interrupt interface to default state. - * Disables all interrupts. - * Set all sources as IRQ (not FIR). - * - * @retval RTEMS_SUCCESSFUL All is set - */ -rtems_status_code bsp_interrupt_facility_initialize(void) -{ - void (**vim_vec)(void) = (void (**)(void)) 0xFFF82000; - unsigned int value = 0x00010203; - unsigned int i = 0; - uint32_t sctlr; - - /* Disable interrupts */ - for ( i = 0; i < 3; i++ ) { - TMS570_VIM.REQENACLR[i] = 0xffffffff; - } - /* Map default events on interrupt vectors */ - for ( i = 0; i < 24; i += 1, value += 0x04040404) { - TMS570_VIM.CHANCTRL[i] = value; - } - /* Set all vectors as IRQ (not FIR) */ - TMS570_VIM.FIRQPR[0] = 3; - TMS570_VIM.FIRQPR[1] = 0; - TMS570_VIM.FIRQPR[2] = 0; - - /* - _CPU_ISR_install_vector( - ARM_EXCEPTION_IRQ, - _ARMV4_Exception_interrupt, - NULL - ); - - Call to setup of interrupt entry in CPU level exception vectors table - is not used (necessary/possible) because the table is provided - by c/src/lib/libbsp/arm/shared/start/start.S and POM overlay - solution remaps that to address zero. - */ - - for ( i = 0; i <= 94; ++i ) { - vim_vec[i] = _ARMV4_Exception_interrupt; - } - /* Clear bit VE in SCTLR register to not use VIM IRQ exception bypass*/ - asm volatile ("mrc p15, 0, %0, c1, c0, 0\n": "=r" (sctlr)); - /* - * Disable bypass of CPU level exception table for interrupt entry which - * can be provided by VIM hardware - */ - sctlr &= ~(1 << 24); - #if 0 - /* - * Option to enable exception table bypass for interrupts - * - * Because RTEMS requires all interrupts to be serviced through - * common _ARMV4_Exception_interrupt handler to allow task switching - * on exit from interrupt working correctly, vim_vec cannot point - * directly to individual vector handlers and need to point - * to single entry path. But if TMS570_VIM.IRQINDEX is then used - * to target execution to corresponding service then for some - * peripherals (i.e. EMAC) interrupt is already acknowledged - * by VIM and IRQINDEX is read as zero which leads to spurious - * interrupt and peripheral not serviced/blocked. - * - * To analyze this behavior we used trampolines which setup - * bsp_interrupt_vector_inject and pass execution to - * _ARMV4_Exception_interrupt. It works but is more ugly than - * use of POM remap for these cases where application does not - * start at address 0x00000000. If RTEMS image is placed at - * memory space beginning then no of these constructs is necessary. - */ - sctlr |= 1 << 24; - #endif - asm volatile ("mcr p15, 0, %0, c1, c0, 0\n": : "r" (sctlr)); - - return RTEMS_SUCCESSFUL; -} diff --git a/c/src/lib/libbsp/arm/xilinx-zynq/Makefile.am b/c/src/lib/libbsp/arm/xilinx-zynq/Makefile.am index 411819841f..aebb25c13f 100644 --- a/c/src/lib/libbsp/arm/xilinx-zynq/Makefile.am +++ b/c/src/lib/libbsp/arm/xilinx-zynq/Makefile.am @@ -56,7 +56,7 @@ endif # IRQ librtemsbsp_a_SOURCES += ../../../../../../bsps/shared/irq/irq-default-handler.c -librtemsbsp_a_SOURCES += ../shared/arm-gic-irq.c +librtemsbsp_a_SOURCES += ../../../../../../bsps/arm/shared/irq/irq-gic.c # Console librtemsbsp_a_SOURCES += ../../../../../../bsps/shared/dev/serial/console-termios.c diff --git a/c/src/lib/libbsp/epiphany/epiphany_sim/Makefile.am b/c/src/lib/libbsp/epiphany/epiphany_sim/Makefile.am index 271dc7f089..b51e76e444 100644 --- a/c/src/lib/libbsp/epiphany/epiphany_sim/Makefile.am +++ b/c/src/lib/libbsp/epiphany/epiphany_sim/Makefile.am @@ -52,7 +52,7 @@ librtemsbsp_a_SOURCES += ../../../../../../bsps/shared/dev/serial/console-polled # IRQ librtemsbsp_a_SOURCES += ../../../../../../bsps/shared/irq/irq-default-handler.c -librtemsbsp_a_SOURCES += irq/irq.c +librtemsbsp_a_SOURCES += ../../../../../../bsps/epiphany/epiphany_sim/irq/irq.c # Cache librtemsbsp_a_SOURCES += ../../../../../../bsps/shared/cache/nocache.c diff --git a/c/src/lib/libbsp/epiphany/epiphany_sim/irq/irq.c b/c/src/lib/libbsp/epiphany/epiphany_sim/irq/irq.c deleted file mode 100644 index 994e25bf0e..0000000000 --- a/c/src/lib/libbsp/epiphany/epiphany_sim/irq/irq.c +++ /dev/null @@ -1,64 +0,0 @@ -/** - * @file - * - * @ingroup epiphany_interrupt - * - * @brief Interrupt support. - */ - -/* - * Epiphany CPU Dependent Source - * - * Copyright (c) 2015 University of York. - * Hesham ALMatary - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#include -#include - -#include - -/* Almost all of the jobs that the following functions should - * do are implemented in cpukit - */ - -void bsp_interrupt_handler_default(rtems_vector_number vector) -{ - printk("spurious interrupt: %" PRIdrtems_vector_number "\n", vector); -} - -rtems_status_code bsp_interrupt_facility_initialize() -{ - return 0; -} - -void bsp_interrupt_vector_enable(rtems_vector_number vector) -{ - bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector)); -} - -void bsp_interrupt_vector_disable(rtems_vector_number vector) -{ - bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector)); -} diff --git a/c/src/lib/libbsp/i386/pc386/Makefile.am b/c/src/lib/libbsp/i386/pc386/Makefile.am index 2e9441e5bc..8cd12e3430 100644 --- a/c/src/lib/libbsp/i386/pc386/Makefile.am +++ b/c/src/lib/libbsp/i386/pc386/Makefile.am @@ -111,14 +111,14 @@ librtemsbsp_a_SOURCES += ../../../../../../bsps/i386/pc386/start/bspstart.c librtemsbsp_a_SOURCES += ../../../../../../bsps/i386/pc386/start/bspcmdline.c librtemsbsp_a_SOURCES += ../../../../../../bsps/shared/start/bspfatal-default.c librtemsbsp_a_SOURCES += ../../../../../../bsps/i386/pc386/start/bspreset.c -librtemsbsp_a_SOURCES += ../shared/irq/idt.c -librtemsbsp_a_SOURCES += ../shared/irq/irq.c -librtemsbsp_a_SOURCES += ../shared/irq/irq_init.c -librtemsbsp_a_SOURCES += ../shared/irq/elcr.c +librtemsbsp_a_SOURCES += ../../../../../../bsps/i386/shared/irq/idt.c +librtemsbsp_a_SOURCES += ../../../../../../bsps/i386/shared/irq/irq.c +librtemsbsp_a_SOURCES += ../../../../../../bsps/i386/shared/irq/irq_init.c +librtemsbsp_a_SOURCES += ../../../../../../bsps/i386/shared/irq/elcr.c librtemsbsp_a_SOURCES += ../../../../../../bsps/shared/dev/getentropy/getentropy-cpucounter.c librtemsbsp_a_SOURCES += ../../../../../../bsps/shared/start/sbrk.c librtemsbsp_a_SOURCES += ../../../../../../bsps/i386/pc386/start/ldsegs.S -librtemsbsp_a_SOURCES += ../shared/irq/irq_asm.S +librtemsbsp_a_SOURCES += ../../../../../../bsps/i386/shared/irq/irq_asm.S librtemsbsp_a_SOURCES += ../../../../../../bsps/shared/irq/irq-default-handler.c # timer diff --git a/c/src/lib/libbsp/i386/shared/irq/elcr.c b/c/src/lib/libbsp/i386/shared/irq/elcr.c deleted file mode 100644 index f72e36c33f..0000000000 --- a/c/src/lib/libbsp/i386/shared/irq/elcr.c +++ /dev/null @@ -1,170 +0,0 @@ -/*- - * Copyright (c) 2004 John Baldwin - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#include -#ifndef __rtems__ -__FBSDID("$FreeBSD$"); -#endif /* __rtems__ */ - -/* - * The ELCR is a register that controls the trigger mode and polarity of - * EISA and ISA interrupts. In FreeBSD 3.x and 4.x, the ELCR was only - * consulted for determining the appropriate trigger mode of EISA - * interrupts when using an APIC. However, it seems that almost all - * systems that include PCI also include an ELCR that manages the ISA - * IRQs 0 through 15. Thus, we check for the presence of an ELCR on - * every machine by checking to see if the values found at bootup are - * sane. Note that the polarity of ISA and EISA IRQs are linked to the - * trigger mode. All edge triggered IRQs use active-hi polarity, and - * all level triggered interrupts use active-lo polarity. - * - * The format of the ELCR is simple: it is a 16-bit bitmap where bit 0 - * controls IRQ 0, bit 1 controls IRQ 1, etc. If the bit is zero, the - * associated IRQ is edge triggered. If the bit is one, the IRQ is - * level triggered. - */ - -#ifndef __rtems__ -#include -#include -#include -#include -#endif /* __rtems__ */ - -#ifdef __rtems__ -#include -#include "i386_io.h" -#include -#include "elcr.h" -#endif /* __rtems__ */ - -#define ELCR_PORT 0x4d0 -#define ELCR_MASK(irq) (1 << (irq)) - -static int elcr_status; -#ifdef __rtems__ -static -#endif /* __rtems__ */ -int elcr_found; - -#ifdef __rtems__ -#undef printf -#define printf printk -#define bootverbose 1 -#define KASSERT(...) -#endif /* __rtems__ */ - -/* - * Check to see if we have what looks like a valid ELCR. We do this by - * verifying that IRQs 0, 1, 2, and 13 are all edge triggered. - */ -int -elcr_probe(void) -{ - int i; - - elcr_status = inb(ELCR_PORT) | inb(ELCR_PORT + 1) << 8; - if ((elcr_status & (ELCR_MASK(0) | ELCR_MASK(1) | ELCR_MASK(2) | - ELCR_MASK(8) | ELCR_MASK(13))) != 0) - return (ENXIO); - if (bootverbose) { - printf("ELCR Found. ISA IRQs programmed as:\n"); - for (i = 0; i < 16; i++) - printf(" %2d", i); - printf("\n"); - for (i = 0; i < 16; i++) - if (elcr_status & ELCR_MASK(i)) - printf(" L"); - else - printf(" E"); - printf("\n"); - } -#ifndef __rtems__ - if (resource_disabled("elcr", 0)) - return (ENXIO); -#endif /* __rtems__ */ - elcr_found = 1; - return (0); -} - -/* - * Returns 1 for level trigger, 0 for edge. - */ -enum intr_trigger -elcr_read_trigger(u_int irq) -{ -#ifdef __rtems__ - if (!elcr_found) - return INTR_TRIGGER_EDGE; -#endif /* __rtems__ */ - KASSERT(elcr_found, ("%s: no ELCR was found!", __func__)); - KASSERT(irq <= 15, ("%s: invalid IRQ %u", __func__, irq)); - if (elcr_status & ELCR_MASK(irq)) - return (INTR_TRIGGER_LEVEL); - else - return (INTR_TRIGGER_EDGE); -} - -/* - * Set the trigger mode for a specified IRQ. Mode of 0 means edge triggered, - * and a mode of 1 means level triggered. - */ -void -elcr_write_trigger(u_int irq, enum intr_trigger trigger) -{ - int new_status; - -#ifdef __rtems__ - if (!elcr_found) - return; -#endif /* __rtems__ */ - KASSERT(elcr_found, ("%s: no ELCR was found!", __func__)); - KASSERT(irq <= 15, ("%s: invalid IRQ %u", __func__, irq)); - if (trigger == INTR_TRIGGER_LEVEL) - new_status = elcr_status | ELCR_MASK(irq); - else - new_status = elcr_status & ~ELCR_MASK(irq); - if (new_status == elcr_status) - return; - elcr_status = new_status; - if (irq >= 8) - outb(ELCR_PORT + 1, elcr_status >> 8); - else - outb(ELCR_PORT, elcr_status & 0xff); -} - -void -elcr_resume(void) -{ -#ifdef __rtems__ - if (!elcr_found) - return; -#endif /* __rtems__ */ - - KASSERT(elcr_found, ("%s: no ELCR was found!", __func__)); - outb(ELCR_PORT, elcr_status & 0xff); - outb(ELCR_PORT + 1, elcr_status >> 8); -} diff --git a/c/src/lib/libbsp/i386/shared/irq/elcr.h b/c/src/lib/libbsp/i386/shared/irq/elcr.h deleted file mode 100644 index a006d4f149..0000000000 --- a/c/src/lib/libbsp/i386/shared/irq/elcr.h +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright 2016 Chris Johns - * - * Header for the FreeBSD ported elcr.c - */ - -#ifndef _IRQ_ELCR_H_ -#define _IRQ_ELCR_H_ - -#include - -enum intr_trigger { - INTR_TRIGGER_EDGE, - INTR_TRIGGER_LEVEL -}; - -/* - * Check to see if we have what looks like a valid ELCR. We do this by - * verifying that IRQs 0, 1, 2, and 13 are all edge triggered. - */ -int elcr_probe(void); - -/* - * Returns 1 for level trigger, 0 for edge. - */ -enum intr_trigger elcr_read_trigger(u_int irq); - -/* - * Set the trigger mode for a specified IRQ. Mode of 0 means edge triggered, - * and a mode of 1 means level triggered. - */ -void elcr_write_trigger(u_int irq, enum intr_trigger trigger); - -void elcr_resume(void); - - -#endif diff --git a/c/src/lib/libbsp/i386/shared/irq/idt.c b/c/src/lib/libbsp/i386/shared/irq/idt.c deleted file mode 100644 index d3adbc4f05..0000000000 --- a/c/src/lib/libbsp/i386/shared/irq/idt.c +++ /dev/null @@ -1,381 +0,0 @@ -/* - * cpu.c - This file contains implementation of C function to - * instantiate IDT entries. More detailled information can be found - * on Intel site and more precisely in the following book : - * - * Pentium Processor family - * Developper's Manual - * - * Volume 3 : Architecture and Programming Manual - * - * Copyright (C) 1998 Eric Valette (valette@crf.canon.fr) - * Canon Centre Recherche France. - * - * The license and distribution terms for this file may be - * found in the file LICENSE in this distribution or at - * http://www.rtems.org/license/LICENSE. - */ - -#include -#include -#include - -/* - * This locking is not enough if IDT is changed at runtime - * and entry can be changed for vector which is enabled - * at change time. But such use is broken anyway. - * Protect code only against concurrent changes. - * Even that is probably unnecessary if different - * entries are changed concurrently. - */ -RTEMS_INTERRUPT_LOCK_DEFINE( static, rtems_idt_access_lock, "rtems_idt_access_lock" ); - -static rtems_raw_irq_connect_data* raw_irq_table; -static rtems_raw_irq_connect_data default_raw_irq_entry; -static interrupt_gate_descriptor default_idt_entry; -static rtems_raw_irq_global_settings* local_settings; - -void create_interrupt_gate_descriptor (interrupt_gate_descriptor* idtEntry, - rtems_raw_irq_hdl hdl) -{ - idtEntry->low_offsets_bits = (((unsigned) hdl) & 0xffff); - idtEntry->segment_selector = i386_get_cs(); - idtEntry->fixed_value_bits = 0; - idtEntry->gate_type = 0xe; - idtEntry->privilege = 0; - idtEntry->present = 1; - idtEntry->high_offsets_bits = ((((unsigned) hdl) >> 16) & 0xffff); -} - -rtems_raw_irq_hdl get_hdl_from_vector(rtems_vector_offset index) -{ - uint32_t hdl; - interrupt_gate_descriptor* idt_entry_tbl; - unsigned limit; - - i386_get_info_from_IDTR (&idt_entry_tbl, &limit); - - /* Convert limit into number of entries */ - limit = (limit + 1) / sizeof(interrupt_gate_descriptor); - - if(index >= limit) { - return 0; - } - - hdl = (idt_entry_tbl[index].low_offsets_bits | - (idt_entry_tbl[index].high_offsets_bits << 16)); - return (rtems_raw_irq_hdl) hdl; -} - -int i386_set_idt_entry (const rtems_raw_irq_connect_data* irq) -{ - interrupt_gate_descriptor* idt_entry_tbl; - unsigned limit; - rtems_interrupt_lock_context lock_context; - - i386_get_info_from_IDTR (&idt_entry_tbl, &limit); - - /* Convert limit into number of entries */ - limit = (limit + 1) / sizeof(interrupt_gate_descriptor); - - if (irq->idtIndex >= limit) { - return 0; - } - /* - * Check if default handler is actually connected. If not issue an error. - * You must first get the current handler via i386_get_current_idt_entry - * and then disconnect it using i386_delete_idt_entry. - * RATIONALE : to always have the same transition by forcing the user - * to get the previous handler before accepting to disconnect. - */ - if (get_hdl_from_vector(irq->idtIndex) != default_raw_irq_entry.hdl) { - return 0; - } - - rtems_interrupt_lock_acquire(&rtems_idt_access_lock, &lock_context); - - raw_irq_table [irq->idtIndex] = *irq; - create_interrupt_gate_descriptor (&idt_entry_tbl[irq->idtIndex], irq->hdl); - if (irq->on) - irq->on(irq); - - rtems_interrupt_lock_release(&rtems_idt_access_lock, &lock_context); - return 1; -} - -void _CPU_ISR_install_vector (uint32_t vector, - proc_ptr hdl, - proc_ptr * oldHdl) -{ - interrupt_gate_descriptor* idt_entry_tbl; - unsigned limit; - interrupt_gate_descriptor new; - rtems_interrupt_lock_context lock_context; - - i386_get_info_from_IDTR (&idt_entry_tbl, &limit); - - /* Convert limit into number of entries */ - limit = (limit + 1) / sizeof(interrupt_gate_descriptor); - - if (vector >= limit) { - return; - } - rtems_interrupt_lock_acquire(&rtems_idt_access_lock, &lock_context); - * ((unsigned int *) oldHdl) = idt_entry_tbl[vector].low_offsets_bits | - (idt_entry_tbl[vector].high_offsets_bits << 16); - - create_interrupt_gate_descriptor(&new, hdl); - idt_entry_tbl[vector] = new; - - rtems_interrupt_lock_release(&rtems_idt_access_lock, &lock_context); -} - -int i386_get_current_idt_entry (rtems_raw_irq_connect_data* irq) -{ - interrupt_gate_descriptor* idt_entry_tbl; - unsigned limit; - - i386_get_info_from_IDTR (&idt_entry_tbl, &limit); - - /* Convert limit into number of entries */ - limit = (limit + 1) / sizeof(interrupt_gate_descriptor); - - if (irq->idtIndex >= limit) { - return 0; - } - raw_irq_table [irq->idtIndex].hdl = get_hdl_from_vector(irq->idtIndex); - - *irq = raw_irq_table [irq->idtIndex]; - - return 1; -} - -int i386_delete_idt_entry (const rtems_raw_irq_connect_data* irq) -{ - interrupt_gate_descriptor* idt_entry_tbl; - unsigned limit; - rtems_interrupt_lock_context lock_context; - - i386_get_info_from_IDTR (&idt_entry_tbl, &limit); - - /* Convert limit into number of entries */ - limit = (limit + 1) / sizeof(interrupt_gate_descriptor); - - if (irq->idtIndex >= limit) { - return 0; - } - /* - * Check if handler passed is actually connected. If not issue an error. - * You must first get the current handler via i386_get_current_idt_entry - * and then disconnect it using i386_delete_idt_entry. - * RATIONALE : to always have the same transition by forcing the user - * to get the previous handler before accepting to disconnect. - */ - if (get_hdl_from_vector(irq->idtIndex) != irq->hdl){ - return 0; - } - rtems_interrupt_lock_acquire(&rtems_idt_access_lock, &lock_context); - - idt_entry_tbl[irq->idtIndex] = default_idt_entry; - - if (irq->off) - irq->off(irq); - - raw_irq_table[irq->idtIndex] = default_raw_irq_entry; - raw_irq_table[irq->idtIndex].idtIndex = irq->idtIndex; - - rtems_interrupt_lock_release(&rtems_idt_access_lock, &lock_context); - - return 1; -} - -/* - * Caution this function assumes the IDTR has been already set. - */ -int i386_init_idt (rtems_raw_irq_global_settings* config) -{ - unsigned limit; - unsigned i; - rtems_interrupt_lock_context lock_context; - interrupt_gate_descriptor* idt_entry_tbl; - - i386_get_info_from_IDTR (&idt_entry_tbl, &limit); - - /* Convert limit into number of entries */ - limit = (limit + 1) / sizeof(interrupt_gate_descriptor); - - if (config->idtSize != limit) { - return 0; - } - /* - * store various accelarators - */ - raw_irq_table = config->rawIrqHdlTbl; - local_settings = config; - default_raw_irq_entry = config->defaultRawEntry; - - rtems_interrupt_lock_acquire(&rtems_idt_access_lock, &lock_context); - - create_interrupt_gate_descriptor (&default_idt_entry, default_raw_irq_entry.hdl); - - for (i=0; i < limit; i++) { - interrupt_gate_descriptor new; - create_interrupt_gate_descriptor (&new, raw_irq_table[i].hdl); - idt_entry_tbl[i] = new; - if (raw_irq_table[i].hdl != default_raw_irq_entry.hdl) { - raw_irq_table[i].on(&raw_irq_table[i]); - } - else { - raw_irq_table[i].off(&raw_irq_table[i]); - } - } - rtems_interrupt_lock_release(&rtems_idt_access_lock, &lock_context); - - return 1; -} - -int i386_get_idt_config (rtems_raw_irq_global_settings** config) -{ - *config = local_settings; - return 1; -} - -uint32_t i386_raw_gdt_entry (uint16_t segment_selector_index, - segment_descriptors* sd) -{ - uint16_t gdt_limit; - uint16_t tmp_segment = 0; - segment_descriptors* gdt_entry_tbl; - uint8_t present; - - i386_get_info_from_GDTR (&gdt_entry_tbl, &gdt_limit); - - if (segment_selector_index >= (gdt_limit+1)/8) { - /* index to GDT table out of bounds */ - return 0; - } - if (segment_selector_index == 0) { - /* index 0 is not usable */ - return 0; - } - - /* put prepared descriptor into the GDT */ - present = sd->present; - sd->present = 0; - gdt_entry_tbl[segment_selector_index].present = 0; - RTEMS_COMPILER_MEMORY_BARRIER(); - gdt_entry_tbl[segment_selector_index] = *sd; - RTEMS_COMPILER_MEMORY_BARRIER(); - gdt_entry_tbl[segment_selector_index].present = present; - sd->present = present; - /* - * Now, reload all segment registers so that the possible changes takes effect. - */ - __asm__ volatile( "movw %%ds,%0 ; movw %0,%%ds\n\t" - "movw %%es,%0 ; movw %0,%%es\n\t" - "movw %%fs,%0 ; movw %0,%%fs\n\t" - "movw %%gs,%0 ; movw %0,%%gs\n\t" - "movw %%ss,%0 ; movw %0,%%ss" - : "=r" (tmp_segment) - : "0" (tmp_segment) - ); - return 1; -} - -void i386_fill_segment_desc_base(uint32_t base, - segment_descriptors* sd) -{ - sd->base_address_15_0 = base & 0xffff; - sd->base_address_23_16 = (base >> 16) & 0xff; - sd->base_address_31_24 = (base >> 24) & 0xff; -} - -void i386_fill_segment_desc_limit(uint32_t limit, - segment_descriptors* sd) -{ - sd->granularity = 0; - if (limit > 65535) { - sd->granularity = 1; - limit /= 4096; - } - sd->limit_15_0 = limit & 0xffff; - sd->limit_19_16 = (limit >> 16) & 0xf; -} - -/* - * Caution this function assumes the GDTR has been already set. - */ -uint32_t i386_set_gdt_entry (uint16_t segment_selector_index, uint32_t base, - uint32_t limit) -{ - segment_descriptors gdt_entry; - memset(&gdt_entry, 0, sizeof(gdt_entry)); - - i386_fill_segment_desc_limit(limit, &gdt_entry); - i386_fill_segment_desc_base(base, &gdt_entry); - /* - * set up descriptor type (this may well becomes a parameter if needed) - */ - gdt_entry.type = 2; /* Data R/W */ - gdt_entry.descriptor_type = 1; /* Code or Data */ - gdt_entry.privilege = 0; /* ring 0 */ - gdt_entry.present = 1; /* not present */ - - /* - * Now, reload all segment registers so the limit takes effect. - */ - return i386_raw_gdt_entry(segment_selector_index, &gdt_entry); -} - -uint16_t i386_next_empty_gdt_entry () -{ - uint16_t gdt_limit; - segment_descriptors* gdt_entry_tbl; - /* initial amount of filled descriptors */ - static uint16_t segment_selector_index = NUM_SYSTEM_GDT_DESCRIPTORS - 1; - - segment_selector_index += 1; - i386_get_info_from_GDTR (&gdt_entry_tbl, &gdt_limit); - if (segment_selector_index >= (gdt_limit+1)/8) { - return 0; - } - return segment_selector_index; -} - -uint16_t i386_cpy_gdt_entry(uint16_t segment_selector_index, - segment_descriptors* struct_to_fill) -{ - uint16_t gdt_limit; - segment_descriptors* gdt_entry_tbl; - - i386_get_info_from_GDTR (&gdt_entry_tbl, &gdt_limit); - - if (segment_selector_index >= (gdt_limit+1)/8) { - return 0; - } - - *struct_to_fill = gdt_entry_tbl[segment_selector_index]; - return segment_selector_index; -} - -segment_descriptors* i386_get_gdt_entry(uint16_t segment_selector_index) -{ - uint16_t gdt_limit; - segment_descriptors* gdt_entry_tbl; - - i386_get_info_from_GDTR (&gdt_entry_tbl, &gdt_limit); - - if (segment_selector_index >= (gdt_limit+1)/8) { - return 0; - } - return &gdt_entry_tbl[segment_selector_index]; -} - -uint32_t i386_limit_gdt_entry(segment_descriptors* gdt_entry) -{ - uint32_t lim = (gdt_entry->limit_15_0 + (gdt_entry->limit_19_16<<16)); - if (gdt_entry->granularity) { - return lim*4096+4095; - } - return lim; -} diff --git a/c/src/lib/libbsp/i386/shared/irq/irq.c b/c/src/lib/libbsp/i386/shared/irq/irq.c deleted file mode 100644 index ac08f1f7be..0000000000 --- a/c/src/lib/libbsp/i386/shared/irq/irq.c +++ /dev/null @@ -1,405 +0,0 @@ -/* - * This file contains the implementation of the function described in irq.h - */ - -/* - * Copyright (c) 2009 embedded brains GmbH - * Copyright (C) 1998 valette@crf.canon.fr - * - * The license and distribution terms for this file may be - * found in the file LICENSE in this distribution or at - * http://www.rtems.org/license/LICENSE. - */ - -#include -#include -#include -#include - -#include -#include -#include - - -#include "elcr.h" - -RTEMS_INTERRUPT_LOCK_DEFINE( static, rtems_i8259_access_lock, "rtems_i8259_access_lock" ); - -/* - * pointer to the mask representing the additionnal irq vectors - * that must be disabled when a particular entry is activated. - * They will be dynamically computed from teh prioruty table given - * in BSP_rtems_irq_mngt_set(); - * CAUTION : this table is accessed directly by interrupt routine - * prologue. - */ -static rtems_i8259_masks irq_mask_or_tbl[BSP_IRQ_LINES_NUMBER]; - -/* - * Stats of interrupts dispatched. - */ -static uint32_t irq_count[BSP_IRQ_VECTOR_NUMBER] = {0}; -static uint32_t spurious_count; - -/* - * Edge or level trigger interrupts. - */ -static enum intr_trigger irq_trigger[BSP_IRQ_LINES_NUMBER]; - -/*-------------------------------------------------------------------------+ -| Cache for 1st and 2nd PIC IRQ line's mssk (enabled or disabled) register. -+--------------------------------------------------------------------------*/ -/* - * lower byte is interrupt mask on the master PIC. - * while upper bits are interrupt on the slave PIC. - * This cache is initialized in ldseg.s - */ -static rtems_i8259_masks i8259a_imr_cache = 0xFFFB; -static rtems_i8259_masks i8259a_in_progress = 0; - -static inline -void BSP_i8259a_irq_update_master_imr( void ) -{ - rtems_i8259_masks mask = i8259a_in_progress | i8259a_imr_cache; - outport_byte( PIC_MASTER_IMR_IO_PORT, mask & 0xff ); -} - -static inline -void BSP_i8259a_irq_update_slave_imr( void ) -{ - rtems_i8259_masks mask = i8259a_in_progress | i8259a_imr_cache; - outport_byte( PIC_SLAVE_IMR_IO_PORT, ( mask >> 8 ) & 0xff ); -} - -/* - * Print the stats. - */ -uint32_t BSP_irq_count_dump(FILE *f) -{ - uint32_t tot = 0; - int i; - if ( !f ) - f = stdout; - fprintf(f,"SPURIOUS: %9"PRIu32"\n", spurious_count); - for ( i = 0; i < BSP_IRQ_VECTOR_NUMBER; i++ ) { - char type = '-'; - if (i < BSP_IRQ_LINES_NUMBER) - type = irq_trigger[i] == INTR_TRIGGER_EDGE ? 'E' : 'L'; - tot += irq_count[i]; - fprintf(f,"IRQ %2u: %c %9"PRIu32"\n", i, type, irq_count[i]); - } - return tot; -} - -/* - * Is the IRQ valid? - */ -static inline bool BSP_i8259a_irq_valid(const rtems_irq_number irqLine) -{ - return ((int)irqLine >= BSP_IRQ_VECTOR_LOWEST_OFFSET) && - ((int)irqLine <= BSP_IRQ_MAX_ON_i8259A); -} - -/* - * Read the IRR register. The default. - */ -static inline uint8_t BSP_i8259a_irq_int_request_reg(uint32_t ioport) -{ - uint8_t isr; - inport_byte(ioport, isr); - return isr; -} - -/* - * Read the ISR register. Keep the default of the IRR. - */ -static inline uint8_t BSP_i8259a_irq_in_service_reg(uint32_t ioport) -{ - uint8_t isr; - outport_byte(ioport, PIC_OCW3_SEL | PIC_OCW3_RR | PIC_OCW3_RIS); - inport_byte(ioport, isr); - outport_byte(ioport, PIC_OCW3_SEL | PIC_OCW3_RR); - return isr; -} - -/*-------------------------------------------------------------------------+ -| Function: BSP_irq_disable_at_i8259a -| Description: Mask IRQ line in appropriate PIC chip. -| Global Variables: i8259a_imr_cache, i8259a_in_progress -| Arguments: vector_offset - number of IRQ line to mask. -| Returns: 0 is OK. -+--------------------------------------------------------------------------*/ -static int BSP_irq_disable_at_i8259a(const rtems_irq_number irqLine) -{ - unsigned short mask; - rtems_interrupt_lock_context lock_context; - - rtems_interrupt_lock_acquire(&rtems_i8259_access_lock, &lock_context); - - mask = 1 << irqLine; - i8259a_imr_cache |= mask; - - if (irqLine < 8) - { - BSP_i8259a_irq_update_master_imr(); - } - else - { - BSP_i8259a_irq_update_slave_imr(); - } - - rtems_interrupt_lock_release(&rtems_i8259_access_lock, &lock_context); - - return 0; -} - -/*-------------------------------------------------------------------------+ -| Function: BSP_irq_enable_at_i8259a -| Description: Unmask IRQ line in appropriate PIC chip. -| Global Variables: i8259a_imr_cache, i8259a_in_progress -| Arguments: irqLine - number of IRQ line to mask. -| Returns: Nothing. -+--------------------------------------------------------------------------*/ -static int BSP_irq_enable_at_i8259a(const rtems_irq_number irqLine) -{ - unsigned short mask; - rtems_interrupt_lock_context lock_context; - uint8_t isr; - uint8_t irr; - - rtems_interrupt_lock_acquire(&rtems_i8259_access_lock, &lock_context); - - mask = 1 << irqLine; - i8259a_imr_cache &= ~mask; - - if (irqLine < 8) - { - isr = BSP_i8259a_irq_in_service_reg(PIC_MASTER_COMMAND_IO_PORT); - irr = BSP_i8259a_irq_int_request_reg(PIC_MASTER_COMMAND_IO_PORT); - BSP_i8259a_irq_update_master_imr(); - } - else - { - isr = BSP_i8259a_irq_in_service_reg(PIC_SLAVE_COMMAND_IO_PORT); - irr = BSP_i8259a_irq_int_request_reg(PIC_SLAVE_COMMAND_IO_PORT); - BSP_i8259a_irq_update_slave_imr(); - } - - if (((isr ^ irr) & mask) != 0) - printk("i386: isr=%x irr=%x\n", isr, irr); - - rtems_interrupt_lock_release(&rtems_i8259_access_lock, &lock_context); - - return 0; -} /* mask_irq */ - -/*-------------------------------------------------------------------------+ -| Function: BSP_irq_ack_at_i8259a -| Description: Signal generic End Of Interrupt (EOI) to appropriate PIC. -| Global Variables: None. -| Arguments: irqLine - number of IRQ line to acknowledge. -| Returns: Nothing. -+--------------------------------------------------------------------------*/ -static int BSP_irq_ack_at_i8259a(const rtems_irq_number irqLine) -{ - uint8_t slave_isr = 0; - - if (irqLine >= 8) { - outport_byte(PIC_SLAVE_COMMAND_IO_PORT, PIC_EOI); - slave_isr = BSP_i8259a_irq_in_service_reg(PIC_SLAVE_COMMAND_IO_PORT); - } - - /* - * Only issue the EOI to the master if there are no more interrupts in - * service for the slave. i8259a data sheet page 18, The Special Fully Nested - * Mode, b. - */ - if (slave_isr == 0) - outport_byte(PIC_MASTER_COMMAND_IO_PORT, PIC_EOI); - - return 0; - -} /* ackIRQ */ - -/* - * ------------------------ RTEMS Irq helper functions ---------------- - */ - -static rtems_irq_prio irqPrioTable[BSP_IRQ_LINES_NUMBER]={ - /* - * actual priorities for each interrupt source: - * 0 means that only current interrupt is masked - * 255 means all other interrupts are masked - * The second entry has a priority of 255 because - * it is the slave pic entry and is should always remain - * unmasked. - */ - 0,0, - 255, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 -}; - -static void compute_i8259_masks_from_prio (void) -{ - rtems_interrupt_lock_context lock_context; - unsigned int i; - unsigned int j; - - rtems_interrupt_lock_acquire(&rtems_i8259_access_lock, &lock_context); - - /* - * Always mask at least current interrupt to prevent re-entrance - */ - for (i=0; i < BSP_IRQ_LINES_NUMBER; i++) { - * ((unsigned short*) &irq_mask_or_tbl[i]) = (1 << i); - for (j = 0; j < BSP_IRQ_LINES_NUMBER; j++) { - /* - * Mask interrupts at i8259 level that have a lower priority - */ - if (irqPrioTable [i] > irqPrioTable [j]) { - * ((unsigned short*) &irq_mask_or_tbl[i]) |= (1 << j); - } - } - } - - rtems_interrupt_lock_release(&rtems_i8259_access_lock, &lock_context); -} - -static inline bool bsp_interrupt_vector_is_valid(rtems_vector_number vector) -{ - return BSP_i8259a_irq_valid((const rtems_irq_number) vector); -} - -void bsp_interrupt_vector_enable(rtems_vector_number vector) -{ - bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector)); - BSP_irq_enable_at_i8259a(vector); -} - -void bsp_interrupt_vector_disable(rtems_vector_number vector) -{ - bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector)); - BSP_irq_disable_at_i8259a(vector); -} - -rtems_status_code bsp_interrupt_facility_initialize(void) -{ - int i; - - /* - * set up internal tables used by rtems interrupt prologue - */ - compute_i8259_masks_from_prio(); - - /* - * must enable slave pic anyway - */ - BSP_irq_enable_at_i8259a(2); - - /* - * Probe the ELCR. - */ - elcr_probe(); - - for (i = 0; i < BSP_IRQ_LINES_NUMBER; i++) - irq_trigger[i] = elcr_read_trigger(i); - - return RTEMS_SUCCESSFUL; -} - -/* - * Global so the asm handler can call it. - */ -void BSP_dispatch_isr(int vector); - -void BSP_dispatch_isr(int vector) -{ - rtems_interrupt_lock_context lock_context; - rtems_i8259_masks in_progress_save = 0; - - if (vector < BSP_IRQ_VECTOR_NUMBER) { - /* - * Hardware? - */ - if (vector <= BSP_IRQ_MAX_ON_i8259A) { - - rtems_interrupt_lock_acquire_isr(&rtems_i8259_access_lock, &lock_context); - - /* - * See if this is a spurious interrupt. - */ - if ((vector == 7 || vector == 15)) { - /* - * Only check it there no handler for 7 or 15. - */ - if (bsp_interrupt_handler_is_empty(vector)) { - /* - * Read the ISR register to see if IRQ 7/15 is really pending. - */ - uint8_t isr = BSP_i8259a_irq_in_service_reg(PIC_MASTER_COMMAND_IO_PORT); - if ((isr & (1 << 7)) == 0) { - ++spurious_count; - rtems_interrupt_lock_release_isr(&rtems_i8259_access_lock, &lock_context); - return; - } - } - } - - /* - * Save the current cached value for the IMR. It will have the bit for this - * vector clear. - */ - if (vector <= BSP_IRQ_MAX_ON_i8259A) { - in_progress_save = i8259a_in_progress; - i8259a_in_progress |= irq_mask_or_tbl[vector]; - BSP_i8259a_irq_update_master_imr(); - BSP_i8259a_irq_update_slave_imr(); - } - - /* - * Do not use auto-EOI as some slave PIC do not work correctly. - */ - BSP_irq_ack_at_i8259a(vector); - - rtems_interrupt_lock_release_isr(&rtems_i8259_access_lock, &lock_context); - } - - /* - * Count the interrupt. - */ - irq_count[vector]++; - - RTEMS_COMPILER_MEMORY_BARRIER(); - /* - * Allow nesting. - */ - __asm__ __volatile__("sti"); - - bsp_interrupt_handler_dispatch(vector); - - /* - * Disallow nesting. - */ - __asm__ __volatile__("cli"); - - RTEMS_COMPILER_MEMORY_BARRIER(); - - if (vector <= BSP_IRQ_MAX_ON_i8259A) { - - rtems_interrupt_lock_acquire_isr(&rtems_i8259_access_lock, &lock_context); - - /* - * Put the mask back but keep this vector masked if the trigger type is - * level. The driver or a thread level interrupt server needs to enable it - * again. - */ - if (vector <= BSP_IRQ_MAX_ON_i8259A) { - i8259a_in_progress = in_progress_save; - BSP_i8259a_irq_update_master_imr(); - BSP_i8259a_irq_update_slave_imr(); - } - - rtems_interrupt_lock_release_isr(&rtems_i8259_access_lock, &lock_context); - } - } -} diff --git a/c/src/lib/libbsp/i386/shared/irq/irq_asm.S b/c/src/lib/libbsp/i386/shared/irq/irq_asm.S deleted file mode 100644 index 181293351e..0000000000 --- a/c/src/lib/libbsp/i386/shared/irq/irq_asm.S +++ /dev/null @@ -1,268 +0,0 @@ -/* - * This file contains the implementation of the function described in irq.h - */ - -/* - * Copyright (C) 1998 valette@crf.canon.fr - * - * COPYRIGHT (c) 1989-2011. - * On-Line Applications Research Corporation (OAR). - * - * The license and distribution terms for this file may be - * found in found in the file LICENSE in this distribution or at - * http://www.rtems.org/license/LICENSE. - */ - -#include -#include -#include -#include -#include - -#include /* to establish dependency on prototype */ - -#ifndef CPU_STACK_ALIGNMENT -#error "Missing header? CPU_STACK_ALIGNMENT is not defined here" -#endif - -/* Stack frame we use for intermediate storage */ -#define ARG_OFF 0 -#define MSK_OFF 4 /* not used any more */ -#define EBX_OFF 8 /* ebx */ -#define EBP_OFF 12 /* code restoring ebp/esp relies on */ -#define ESP_OFF 16 /* esp being on top of ebp! */ -#ifdef __SSE__ -/* need to be on 16 byte boundary for SSE, add 12 to do that */ -#define FRM_SIZ (20+12+512) -#define SSE_OFF 32 -#else -#define FRM_SIZ 20 -#endif - - BEGIN_CODE - -SYM (_ISR_Handler): - /* - * Before this was point is reached the vectors unique - * entry point did the following: - * - * 1. saved scratch registers registers eax edx ecx" - * 2. put the vector number in ecx. - * - * BEGINNING OF ESTABLISH SEGMENTS - * - * WARNING: If an interrupt can occur when the segments are - * not correct, then this is where we should establish - * the segments. In addition to establishing the - * segments, it may be necessary to establish a stack - * in the current data area on the outermost interrupt. - * - * NOTE: If the previous values of the segment registers are - * pushed, do not forget to adjust SAVED_REGS. - * - * NOTE: Make sure the exit code which restores these - * when this type of code is needed. - */ - - /***** ESTABLISH SEGMENTS CODE GOES HERE ******/ - - /* - * END OF ESTABLISH SEGMENTS - */ - - /* - * Establish an aligned stack frame - * original sp - * saved ebx - * saved ebp - * saved irq mask - * vector arg to BSP_dispatch_isr <- aligned SP - */ - movl esp, eax - subl $FRM_SIZ, esp - andl $ - CPU_STACK_ALIGNMENT, esp - movl ebx, EBX_OFF(esp) - movl eax, ESP_OFF(esp) - movl ebp, EBP_OFF(esp) - - /* - * GCC versions starting with 4.3 no longer place the cld - * instruction before string operations. We need to ensure - * it is set correctly for ISR handlers. - */ - cld - -#ifdef __SSE__ - /* NOTE: SSE only is supported if the BSP enables fxsave/fxrstor - * to save/restore SSE context! This is so far only implemented - * for pc386!. - */ - - /* We save SSE here (on the task stack) because we possibly - * call other C-code (besides the ISR, namely _Thread_Dispatch()) - */ - /* don't wait here; a possible exception condition will eventually be - * detected when the task resumes control and executes a FP instruction - fwait - */ - fxsave SSE_OFF(esp) - fninit /* clean-slate FPU */ - movl $0x1f80, ARG_OFF(esp) /* use ARG_OFF as scratch space */ - ldmxcsr ARG_OFF(esp) /* clean-slate MXCSR */ -#endif - - /* - * Now switch stacks if necessary - */ - -PUBLIC (ISR_STOP) -ISR_STOP: -.check_stack_switch: - movl esp, ebp /* ebp = previous stack pointer */ - -#ifdef RTEMS_SMP - call SYM(_CPU_SMP_Get_current_processor) - sall $PER_CPU_CONTROL_SIZE_LOG2, eax - addl $SYM(_Per_CPU_Information), eax - movl eax, ebx -#else - movl $SYM(_Per_CPU_Information), ebx -#endif - - /* is this the outermost interrupt? */ - cmpl $0, PER_CPU_ISR_NEST_LEVEL(ebx) - jne nested /* No, then continue */ - movl PER_CPU_INTERRUPT_STACK_HIGH(ebx), esp - - /* - * We want to insure that the old stack pointer is in ebp - * By saving it on every interrupt, all we have to do is - * movl ebp->esp near the end of every interrupt. - */ - -nested: - incl PER_CPU_ISR_NEST_LEVEL(ebx) /* one nest level deeper */ - incl PER_CPU_THREAD_DISPATCH_DISABLE_LEVEL(ebx) /* disable - multitasking */ - /* - * ECX is preloaded with the vector number; store as arg - * on top of stack. Note that _CPU_Interrupt_stack_high - * was adjusted in _CPU_Interrupt_stack_setup() (score/rtems/cpu.h) - * to make sure there is space. - */ - - movl ecx, ARG_OFF(esp) /* store vector arg in stack */ - call BSP_dispatch_isr - - movl ARG_OFF(esp), ecx /* grab vector arg from stack */ - - /* - * Restore stack. This moves back to the task stack - * when all interrupts are unnested. - */ - movl ebp, esp - - decl PER_CPU_ISR_NEST_LEVEL(ebx) /* one less ISR nest level */ - /* If interrupts are nested, */ - /* then dispatching is disabled */ - - decl PER_CPU_THREAD_DISPATCH_DISABLE_LEVEL(ebx) - /* unnest multitasking */ - /* Is dispatch disabled */ - jne .exit /* Yes, then exit */ - - cmpb $0, PER_CPU_DISPATCH_NEEDED(ebx) - /* Is task switch necessary? */ - jne .schedule /* Yes, then call the scheduler */ - jmp .exit /* No, exit */ - -.schedule: - /* - * the scratch registers have already been saved and we are already - * back on the thread system stack. So we can call _Thread_Dispatch - * directly - */ - call _Thread_Dispatch - /* - * fall through exit to restore complete contex (scratch registers - * eip, CS, Flags). - */ -.exit: - -#ifdef __SSE__ - fwait - fxrstor SSE_OFF(esp) -#endif - - /* restore ebx, ebp and original esp */ - addl $EBX_OFF, esp - popl ebx - popl ebp - popl esp - - /* - * BEGINNING OF DE-ESTABLISH SEGMENTS - * - * NOTE: Make sure there is code here if code is added to - * load the segment registers. - * - */ - - /******* DE-ESTABLISH SEGMENTS CODE GOES HERE ********/ - - /* - * END OF DE-ESTABLISH SEGMENTS - */ - popl edx - popl ecx - popl eax - iret - -#define DISTINCT_INTERRUPT_ENTRY(_vector) \ - .p2align 4 ; \ - PUBLIC (rtems_irq_prologue_ ## _vector ) ; \ -SYM (rtems_irq_prologue_ ## _vector ): \ - pushl eax ; \ - pushl ecx ; \ - pushl edx ; \ - movl $ _vector, ecx ; \ - jmp SYM (_ISR_Handler) ; - -DISTINCT_INTERRUPT_ENTRY(0) -DISTINCT_INTERRUPT_ENTRY(1) -DISTINCT_INTERRUPT_ENTRY(2) -DISTINCT_INTERRUPT_ENTRY(3) -DISTINCT_INTERRUPT_ENTRY(4) -DISTINCT_INTERRUPT_ENTRY(5) -DISTINCT_INTERRUPT_ENTRY(6) -DISTINCT_INTERRUPT_ENTRY(7) -DISTINCT_INTERRUPT_ENTRY(8) -DISTINCT_INTERRUPT_ENTRY(9) -DISTINCT_INTERRUPT_ENTRY(10) -DISTINCT_INTERRUPT_ENTRY(11) -DISTINCT_INTERRUPT_ENTRY(12) -DISTINCT_INTERRUPT_ENTRY(13) -DISTINCT_INTERRUPT_ENTRY(14) -DISTINCT_INTERRUPT_ENTRY(15) -DISTINCT_INTERRUPT_ENTRY(16) - - /* - * routine used to initialize the IDT by default - */ - -PUBLIC (default_raw_idt_handler) -PUBLIC (raw_idt_notify) - -SYM (default_raw_idt_handler): - pusha - cld - mov esp, ebp - andl $ - CPU_STACK_ALIGNMENT, esp - call raw_idt_notify - mov ebp, esp - popa - iret - -END_CODE - -END diff --git a/c/src/lib/libbsp/i386/shared/irq/irq_init.c b/c/src/lib/libbsp/i386/shared/irq/irq_init.c deleted file mode 100644 index fdf4801a5a..0000000000 --- a/c/src/lib/libbsp/i386/shared/irq/irq_init.c +++ /dev/null @@ -1,191 +0,0 @@ -/* irq_init.c - * - * This file contains the implementation of rtems initialization - * related to interrupt handling. - * - * Copyright (c) 2009 embedded brains GmbH - * CopyRight (C) 1998 valette@crf.canon.fr - * - * COPYRIGHT (c) 2011. - * On-Line Applications Research Corporation (OAR). - * - * The license and distribution terms for this file may be - * found in the file LICENSE in this distribution or at - * http://www.rtems.org/license/LICENSE. - */ - -#include - -#include - -#include -#include -#include - -/* - * rtems prologue generated in irq_asm.S - */ -extern void rtems_irq_prologue_0(void); -extern void rtems_irq_prologue_1(void); -extern void rtems_irq_prologue_2(void); -extern void rtems_irq_prologue_3(void); -extern void rtems_irq_prologue_4(void); -extern void rtems_irq_prologue_5(void); -extern void rtems_irq_prologue_6(void); -extern void rtems_irq_prologue_7(void); -extern void rtems_irq_prologue_8(void); -extern void rtems_irq_prologue_9(void); -extern void rtems_irq_prologue_10(void); -extern void rtems_irq_prologue_11(void); -extern void rtems_irq_prologue_12(void); -extern void rtems_irq_prologue_13(void); -extern void rtems_irq_prologue_14(void); -extern void rtems_irq_prologue_15(void); -extern void rtems_irq_prologue_16(void); -/* - * default vectors - */ -extern void default_raw_idt_handler(void); - -/* - * default raw on/off function - */ -static void raw_nop_func(const struct __rtems_raw_irq_connect_data__ *unused) -{ -} - -/* - * default raw isOn function - */ -static int raw_not_connected( - const struct __rtems_raw_irq_connect_data__ *unused -) -{ - return 0; -} - -static rtems_raw_irq_connect_data idtHdl[IDT_SIZE]; - -static rtems_raw_irq_hdl rtemsIrq[BSP_IRQ_VECTOR_NUMBER] = { - rtems_irq_prologue_0, - rtems_irq_prologue_1, - rtems_irq_prologue_2, - rtems_irq_prologue_3, - rtems_irq_prologue_4, - rtems_irq_prologue_5, - rtems_irq_prologue_6, - rtems_irq_prologue_7, - rtems_irq_prologue_8, - rtems_irq_prologue_9, - rtems_irq_prologue_10, - rtems_irq_prologue_11, - rtems_irq_prologue_12, - rtems_irq_prologue_13, - rtems_irq_prologue_14, - rtems_irq_prologue_15, - rtems_irq_prologue_16, -}; - -static rtems_raw_irq_connect_data defaultRawIrq = { - 0, /* vectorIdex */ - default_raw_idt_handler, /* hdl */ - raw_nop_func, /* on */ - raw_nop_func, /* off */ - raw_not_connected /* isOn */ -}; - -static interrupt_gate_descriptor idtEntry; - -static rtems_raw_irq_global_settings raw_initial_config; - - -/* - * This method is called from irq_asm.S and cannot be static. - */ -void raw_idt_notify(void) -{ - printk("raw_idt_notify has been called \n"); -} - -void rtems_irq_mngt_init(void) -{ - int i; - interrupt_gate_descriptor* idt_entry_tbl; - unsigned int limit; - rtems_interrupt_level level; - - i386_get_info_from_IDTR(&idt_entry_tbl, &limit); - - /* Convert into number of entries */ - limit = (limit + 1)/sizeof(interrupt_gate_descriptor); - - if(limit != IDT_SIZE) { - printk("IDT table size mismatch !!! System locked\n"); - while(1); - } - - /* - * The interrupt management can be initialized only once - * during system bootup and that should happen on boot - * CPU so there is no need to synchronize with others CPUs. - */ - rtems_interrupt_local_disable(level); - - /* - * Init the complete IDT vector table with defaultRawIrq value - */ - for (i = 0; i < IDT_SIZE ; i++) { - idtHdl[i] = defaultRawIrq; - idtHdl[i].idtIndex = i; - } - - raw_initial_config.idtSize = IDT_SIZE; - raw_initial_config.defaultRawEntry = defaultRawIrq; - raw_initial_config.rawIrqHdlTbl = idtHdl; - - if (!i386_init_idt (&raw_initial_config)) { - /* - * put something here that will show the failure... - */ - printk("Unable to initialize IDT!!! System locked\n"); - while (1); - } - /* - * Patch the entry that will be used by RTEMS for interrupt management - * with RTEMS prologue. - */ - for (i = 0; i < BSP_IRQ_VECTOR_NUMBER; i++) { - create_interrupt_gate_descriptor(&idtEntry, rtemsIrq[i]); - idt_entry_tbl[i + BSP_ASM_IRQ_VECTOR_BASE] = idtEntry; - } - /* - * At this point we have completed the initialization of IDT - * with raw handlers. We must now initialize the higher level - * interrupt management. - */ - - /* - * Init initial Interrupt management config - */ - bsp_interrupt_initialize(); - - /* - * #define DEBUG - */ -#ifdef DEBUG - { - /* - * following adresses should be the same - */ - unsigned tmp; - - printk("idt_entry_tbl = %x Interrupt_descriptor_table addr = %x\n", - idt_entry_tbl, &Interrupt_descriptor_table); - tmp = (unsigned) get_hdl_from_vector (BSP_ASM_IRQ_VECTOR_BASE + BSP_PERIODIC_TIMER); - printk("clock isr address from idt = %x should be %x\n", - tmp, (unsigned) rtems_irq_prologue_0); - } - printk("i8259s_cache = %x\n", * (unsigned short*) &i8259s_cache); - BSP_wait_polled_input(); -#endif -} diff --git a/c/src/lib/libbsp/lm32/milkymist/Makefile.am b/c/src/lib/libbsp/lm32/milkymist/Makefile.am index 99f530bd5a..617ad7781b 100644 --- a/c/src/lib/libbsp/lm32/milkymist/Makefile.am +++ b/c/src/lib/libbsp/lm32/milkymist/Makefile.am @@ -28,7 +28,7 @@ librtemsbsp_a_SOURCES += ../../../../../../bsps/shared/dev/getentropy/getentropy librtemsbsp_a_SOURCES += ../../../../../../bsps/shared/start/sbrk.c # irq -librtemsbsp_a_SOURCES += ../shared/irq/irq.c +librtemsbsp_a_SOURCES += ../../../../../../bsps/lm32/shared/irq/irq.c # clock librtemsbsp_a_SOURCES += ../shared/milkymist_clock/ckinit.c diff --git a/c/src/lib/libbsp/lm32/shared/irq/irq.c b/c/src/lib/libbsp/lm32/shared/irq/irq.c deleted file mode 100644 index 79626ee449..0000000000 --- a/c/src/lib/libbsp/lm32/shared/irq/irq.c +++ /dev/null @@ -1,30 +0,0 @@ -/* irq.c - * - * Copyright (c) 2010 Sebastien Bourdeauducq - * - * The license and distribution terms for this file may be - * found in found in the file LICENSE in this distribution or at - * http://www.rtems.org/license/LICENSE. - */ - -#include -#include -#include -#include - -rtems_status_code bsp_interrupt_facility_initialize(void) -{ - return RTEMS_SUCCESSFUL; -} - -void bsp_interrupt_vector_enable(rtems_vector_number vector) -{ - bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector)); - lm32_interrupt_unmask(1 << vector); -} - -void bsp_interrupt_vector_disable(rtems_vector_number vector) -{ - bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector)); - lm32_interrupt_mask(1 << vector); -} diff --git a/c/src/lib/libbsp/m68k/genmcf548x/Makefile.am b/c/src/lib/libbsp/m68k/genmcf548x/Makefile.am index a031241dc9..b84cda2236 100644 --- a/c/src/lib/libbsp/m68k/genmcf548x/Makefile.am +++ b/c/src/lib/libbsp/m68k/genmcf548x/Makefile.am @@ -39,8 +39,8 @@ librtemsbsp_a_SOURCES += ../../../../../../bsps/m68k/genmcf548x/btimer/btimer.c # IRQ librtemsbsp_a_SOURCES += ../../../../../../bsps/shared/irq/irq-default-handler.c -librtemsbsp_a_SOURCES += irq/irq.c -librtemsbsp_a_SOURCES += irq/intc-icr-init-values.c +librtemsbsp_a_SOURCES += ../../../../../../bsps/m68k/genmcf548x/irq/irq.c +librtemsbsp_a_SOURCES += ../../../../../../bsps/m68k/genmcf548x/irq/intc-icr-init-values.c librtemsbsp_a_SOURCES += ../../../../../../bsps/m68k/shared/m68kidle.c librtemsbsp_a_SOURCES += ../../../../../../bsps/m68k/shared/memProbe.c diff --git a/c/src/lib/libbsp/m68k/genmcf548x/irq/intc-icr-init-values.c b/c/src/lib/libbsp/m68k/genmcf548x/irq/intc-icr-init-values.c deleted file mode 100644 index afc58224ea..0000000000 --- a/c/src/lib/libbsp/m68k/genmcf548x/irq/intc-icr-init-values.c +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Copyright (c) 2013 embedded brains GmbH. All rights reserved. - * - * embedded brains GmbH - * Dornierstr. 4 - * 82178 Puchheim - * Germany - * - * - * The license and distribution terms for this file may be - * found in the file LICENSE in this distribution or at - * http://www.rtems.org/license/LICENSE. - */ - -#include -#include - -#define ICR(lvl, prio) (MCF548X_INTC_ICRn_IL(lvl) | MCF548X_INTC_ICRn_IP(prio)) - -const uint8_t mcf548x_intc_icr_init_values[64] = { - [MCF548X_IRQ_SLT0] = ICR(4, 7), - [MCF548X_IRQ_SLT1] = ICR(4, 6), - [MCF548X_IRQ_PSC0] = ICR(3, 7), - [MCF548X_IRQ_PSC1] = ICR(3, 6), - [MCF548X_IRQ_PSC2] = ICR(3, 5), - [MCF548X_IRQ_PSC3] = ICR(3, 4), - [MCF548X_IRQ_FEC0] = ICR(2, 7), - [MCF548X_IRQ_FEC1] = ICR(2, 6) -}; diff --git a/c/src/lib/libbsp/m68k/genmcf548x/irq/irq.c b/c/src/lib/libbsp/m68k/genmcf548x/irq/irq.c deleted file mode 100644 index f02231b67c..0000000000 --- a/c/src/lib/libbsp/m68k/genmcf548x/irq/irq.c +++ /dev/null @@ -1,229 +0,0 @@ -/* - * Copyright (c) 2013 embedded brains GmbH. All rights reserved. - * - * embedded brains GmbH - * Dornierstr. 4 - * 82178 Puchheim - * Germany - * - * - * The license and distribution terms for this file may be - * found in the file LICENSE in this distribution or at - * http://www.rtems.org/license/LICENSE. - */ - -#include - -#include - -void asm_default_interrupt(void); - -typedef void (*void_func)(void); - -typedef struct { - rtems_interrupt_handler handler; - void *arg; - const char *info; -} interrupt_control; - -static interrupt_control interrupt_controls[BSP_INTERRUPT_VECTOR_MAX + 1]; - -static uint32_t vector_to_reg(rtems_vector_number vector) -{ - return ((vector + 32U) >> 5) & 0x1; -} - -static uint32_t vector_to_bit(rtems_vector_number vector) -{ - return 1U << (vector & 0x1fU); -} - -static volatile uint32_t *vector_to_imr(rtems_vector_number vector) -{ - volatile uint32_t *imr = &MCF548X_INTC_IMRH; - - return &imr[vector_to_reg(vector)]; -} - -static rtems_vector_number exception_vector_to_vector( - rtems_vector_number exception_vector -) -{ - return exception_vector - 64U; -} - -static rtems_vector_number vector_to_exception_vector( - rtems_vector_number vector -) -{ - return vector + 64U; -} - -void bsp_interrupt_vector_enable(rtems_vector_number vector) -{ - volatile uint32_t *imr = vector_to_imr(vector); - uint32_t bit = vector_to_bit(vector); - rtems_interrupt_level level; - - bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector)); - - rtems_interrupt_disable(level); - *imr &= ~bit; - rtems_interrupt_enable(level); -} - -void bsp_interrupt_vector_disable(rtems_vector_number vector) -{ - volatile uint32_t *imr = vector_to_imr(vector); - uint32_t bit = vector_to_bit(vector); - rtems_interrupt_level level; - - bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector)); - - rtems_interrupt_disable(level); - *imr |= bit; - rtems_interrupt_enable(level); -} - -static void_func get_exception_handler(rtems_vector_number vector) -{ - void **vbr; - void_func *exception_table; - - m68k_get_vbr(vbr); - - exception_table = (void_func *)vbr; - - return exception_table[vector_to_exception_vector(vector)]; -} - -static void set_exception_handler(rtems_vector_number vector, void_func handler) -{ - void **vbr; - void_func *exception_table; - - m68k_get_vbr(vbr); - - exception_table = (void_func *)vbr; - - exception_table[vector_to_exception_vector(vector)] = handler; -} - -static void dispatch_handler(rtems_vector_number exception_vector) -{ - const interrupt_control *ic = - &interrupt_controls[exception_vector_to_vector(exception_vector)]; - - (*ic->handler)(ic->arg); -} - -static uint8_t get_intc_icr(rtems_vector_number vector) -{ - volatile uint8_t *icr = &MCF548X_INTC_ICR0; - - return icr[vector]; -} - -rtems_status_code rtems_interrupt_handler_install( - rtems_vector_number vector, - const char *info, - rtems_option options, - rtems_interrupt_handler handler, - void *arg -) -{ - rtems_status_code sc = RTEMS_SUCCESSFUL; - - if (bsp_interrupt_is_valid_vector(vector)) { - rtems_interrupt_level level; - - rtems_interrupt_disable(level); - - if ( - get_exception_handler(vector) == asm_default_interrupt - && get_intc_icr(vector) != 0 - ) { - interrupt_control *ic = &interrupt_controls[vector]; - - ic->handler = handler; - ic->arg = arg; - ic->info = info; - - _ISR_Vector_table[vector_to_exception_vector(vector)] - = dispatch_handler; - set_exception_handler(vector, _ISR_Handler); - bsp_interrupt_vector_enable(vector); - } else { - sc = RTEMS_RESOURCE_IN_USE; - } - - rtems_interrupt_enable(level); - } else { - sc = RTEMS_INVALID_ID; - } - - return sc; -} - -static bool is_occupied_by_us(rtems_vector_number vector) -{ - return get_exception_handler(vector) == _ISR_Handler - && _ISR_Vector_table[vector_to_exception_vector(vector)] - == dispatch_handler; -} - -rtems_status_code rtems_interrupt_handler_remove( - rtems_vector_number vector, - rtems_interrupt_handler handler, - void *arg -) -{ - rtems_status_code sc = RTEMS_SUCCESSFUL; - - if (bsp_interrupt_is_valid_vector(vector)) { - rtems_interrupt_level level; - interrupt_control *ic = &interrupt_controls[vector]; - - rtems_interrupt_disable(level); - - if ( - is_occupied_by_us(vector) - && ic->handler == handler - && ic->arg == arg - ) { - bsp_interrupt_vector_disable(vector); - set_exception_handler(vector, asm_default_interrupt); - - memset(ic, 0, sizeof(*ic)); - } else { - sc = RTEMS_UNSATISFIED; - } - - rtems_interrupt_enable(level); - } else { - sc = RTEMS_INVALID_ID; - } - - return sc; -} - -rtems_status_code rtems_interrupt_handler_iterate( - rtems_vector_number vector, - rtems_interrupt_per_handler_routine routine, - void *arg -) -{ - rtems_status_code sc = RTEMS_SUCCESSFUL; - - if (bsp_interrupt_is_valid_vector(vector)) { - if (is_occupied_by_us(vector)) { - const interrupt_control *ic = &interrupt_controls[vector]; - - (*routine)(arg, ic->info, RTEMS_INTERRUPT_UNIQUE, ic->handler, ic->arg); - } - } else { - sc = RTEMS_INVALID_ID; - } - - return sc; -} diff --git a/c/src/lib/libbsp/mips/csb350/Makefile.am b/c/src/lib/libbsp/mips/csb350/Makefile.am index f8a6874390..cda24059e0 100644 --- a/c/src/lib/libbsp/mips/csb350/Makefile.am +++ b/c/src/lib/libbsp/mips/csb350/Makefile.am @@ -33,10 +33,10 @@ librtemsbsp_a_SOURCES += ../../../../../../bsps/shared/dev/serial/console-polled # timer librtemsbsp_a_SOURCES += ../../../../../../bsps/mips/csb350/btimer/btimer.c #isr -librtemsbsp_a_SOURCES += ../shared/irq/vectorexceptions.c -librtemsbsp_a_SOURCES += ../shared/irq/irq.c -librtemsbsp_a_SOURCES += irq/vectorisrs.c -librtemsbsp_a_SOURCES += ../shared/irq/interruptmask.c +librtemsbsp_a_SOURCES += ../../../../../../bsps/mips/shared/irq/vectorexceptions.c +librtemsbsp_a_SOURCES += ../../../../../../bsps/mips/shared/irq/irq.c +librtemsbsp_a_SOURCES += ../../../../../../bsps/mips/csb350/irq/vectorisrs.c +librtemsbsp_a_SOURCES += ../../../../../../bsps/mips/shared/irq/interruptmask.c if HAS_NETWORKING librtemsbsp_a_SOURCES += network/network.c diff --git a/c/src/lib/libbsp/mips/csb350/irq/vectorisrs.c b/c/src/lib/libbsp/mips/csb350/irq/vectorisrs.c deleted file mode 100644 index d8e071281e..0000000000 --- a/c/src/lib/libbsp/mips/csb350/irq/vectorisrs.c +++ /dev/null @@ -1,168 +0,0 @@ -/** - * @file - * - * Au1x00 Interrupt Vectoring - */ - -/* - * Copyright (c) 2005 by Cogent Computer Systems - * Written by Jay Monkman - * - * The license and distribution terms for this file may be - * found in the file LICENSE in this distribution or at - * http://www.rtems.org/license/LICENSE. - */ - -#include -#include -#include -#include -#include -#include -#include - -static void call_vectored_isr(CPU_Interrupt_frame *, uint32_t , void *); - -#include /* for printk */ - -void mips_vector_isr_handlers( CPU_Interrupt_frame *frame ) -{ - unsigned int sr; - unsigned int cause; - - mips_get_sr( sr ); - mips_get_cause( cause ); - - cause &= (sr & SR_IMASK); - cause >>= CAUSE_IPSHIFT; - - /* count/compare interrupt */ - if ( cause & 0x80 ) { - unsigned long zero = 0; - /* - * I don't see a good way to disable the compare - * interrupt, so let's just ignore it. - */ - __asm__ volatile ("mtc0 %0, $11\n" :: "r" (zero)); - } - - /* Performance counter */ - if ( cause & 0x40 ) { - bsp_interrupt_handler_dispatch(AU1X00_IRQ_PERF); - } - - /* Interrupt controller 0 */ - if ( cause & 0x0c ) { - call_vectored_isr(frame, cause, (void *)AU1X00_IC0_ADDR); - } - - /* Interrupt controller 1 */ - if ( cause & 0x30 ) { - call_vectored_isr(frame, cause, (void *)AU1X00_IC1_ADDR); - } - - /* SW[0] */ - if ( cause & 0x01 ) - bsp_interrupt_handler_dispatch( AU1X00_IRQ_SW0 ); - - /* SW[1] */ - if ( cause & 0x02 ) - bsp_interrupt_handler_dispatch( AU1X00_IRQ_SW1 ); -} - -void mips_default_isr( int vector ) -{ - unsigned int sr; - unsigned int cause; - - mips_get_sr( sr ); - mips_get_cause( cause ); - - printk( "Unhandled isr exception: vector 0x%02x, cause 0x%08X, sr 0x%08X\n", - vector, cause, sr ); - rtems_fatal_error_occurred(1); -} - -static void call_vectored_isr( - CPU_Interrupt_frame *frame, - uint32_t cause, - void *ctrlr - ) -{ - uint32_t src; - uint32_t mask; - int index; - - /* get mask register */ - mask = AU1X00_IC_MASKRD(ctrlr); - - /* check request 0 */ - src = AU1X00_IC_REQ0INT(ctrlr); - src = src & mask; - index = 0; - while (src) { - /* check LSB */ - if (src & 1) { - /* clear rising/falling edge detects */ - AU1X00_IC_RISINGCLR(ctrlr) = (1 << index); - AU1X00_IC_FALLINGCLR(ctrlr) = (1 << index); - au_sync(); - bsp_interrupt_handler_dispatch(AU1X00_IRQ_IC0_BASE + index); - } - index ++; - - /* shift, and make sure MSB is clear */ - src = (src >> 1) & 0x7fffffff; - } - - /* check request 1 */ - src = AU1X00_IC_REQ1INT(ctrlr); - src = src & mask; - index = 0; - while (src) { - /* check LSB */ - if (src & 1) { - /* clear rising/falling edge detects */ - AU1X00_IC_RISINGCLR(ctrlr) = (1 << index); - AU1X00_IC_FALLINGCLR(ctrlr) = (1 << index); - au_sync(); - bsp_interrupt_handler_dispatch(AU1X00_IRQ_IC0_BASE + index); - } - index ++; - - /* shift, and make sure MSB is clear */ - src = (src >> 1) & 0x7fffffff; - } -} - -/* Generate a software interrupt */ -int assert_sw_irq(uint32_t irqnum) -{ - uint32_t cause; - - if (irqnum <= 1) { - mips_get_cause(cause); - cause = cause | ((irqnum + 1) << CAUSE_IPSHIFT); - mips_set_cause(cause); - - return irqnum; - } else { - return -1; - } -} - -/* Clear a software interrupt */ -int negate_sw_irq(uint32_t irqnum) -{ - uint32_t cause; - - if (irqnum <= 1) { - mips_get_cause(cause); - cause = cause & ~((irqnum + 1) << CAUSE_IPSHIFT); - mips_set_cause(cause); - - return irqnum; - } else { - return -1; - } -} diff --git a/c/src/lib/libbsp/mips/hurricane/Makefile.am b/c/src/lib/libbsp/mips/hurricane/Makefile.am index ed952418d0..ae8e599f4f 100644 --- a/c/src/lib/libbsp/mips/hurricane/Makefile.am +++ b/c/src/lib/libbsp/mips/hurricane/Makefile.am @@ -28,7 +28,7 @@ librtemsbsp_a_SOURCES += ../../../../../../bsps/shared/start/sbrk.c librtemsbsp_a_SOURCES += ../../../../../../bsps/mips/hurricane/start/inittlb.c librtemsbsp_a_SOURCES += ../../../../../../bsps/mips/shared/start/idtmem.S librtemsbsp_a_SOURCES += ../../../../../../bsps/mips/shared/start/idttlb.S -librtemsbsp_a_SOURCES += ../shared/irq/exception.S +librtemsbsp_a_SOURCES += ../../../../../../bsps/mips/shared/irq/exception.S librtemsbsp_a_SOURCES += ../../../../../../bsps/mips/hurricane/start/usc.S # clock librtemsbsp_a_SOURCES +=../../../../../../bsps/mips/hurricane/clock/ckinit.c @@ -39,10 +39,10 @@ librtemsbsp_a_SOURCES += ../../../../../../bsps/mips/hurricane/console/console.c librtemsbsp_a_SOURCES += ../shared/liblnk/lnklib.S librtemsbsp_a_SOURCES += ../shared/liblnk/pmon.S #isr -librtemsbsp_a_SOURCES += ../shared/irq/vectorexceptions.c -librtemsbsp_a_SOURCES += ../shared/irq/irq.c -librtemsbsp_a_SOURCES += irq/vectorisrs.c -librtemsbsp_a_SOURCES += ../shared/irq/interruptmask.c +librtemsbsp_a_SOURCES += ../../../../../../bsps/mips/shared/irq/vectorexceptions.c +librtemsbsp_a_SOURCES += ../../../../../../bsps/mips/shared/irq/irq.c +librtemsbsp_a_SOURCES += ../../../../../../bsps/mips/hurricane/irq/vectorisrs.c +librtemsbsp_a_SOURCES += ../../../../../../bsps/mips/shared/irq/interruptmask.c librtemsbsp_a_SOURCES += ../../../../../../bsps/shared/cache/nocache.c librtemsbsp_a_SOURCES += ../../../../../../bsps/mips/shared/irq/installisrentries.c diff --git a/c/src/lib/libbsp/mips/hurricane/irq/vectorisrs.c b/c/src/lib/libbsp/mips/hurricane/irq/vectorisrs.c deleted file mode 100644 index e55566697d..0000000000 --- a/c/src/lib/libbsp/mips/hurricane/irq/vectorisrs.c +++ /dev/null @@ -1,58 +0,0 @@ -/** - * @file - * - * RM5231 Interrupt Vectoring - */ - -/* - * COPYRIGHT (c) 1989-2012. - * On-Line Applications Research Corporation (OAR). - * - * The license and distribution terms for this file may be - * found in the file LICENSE in this distribution or at - * http://www.rtems.org/license/LICENSE. - */ - -#include -#include -#include -#include -#include -#include - -#include /* for printk */ - -void mips_default_isr( int vector ); - -void mips_vector_isr_handlers( CPU_Interrupt_frame *frame ) -{ - unsigned int sr; - unsigned int cause; - unsigned int i; - unsigned int mask; - - mips_get_sr( sr ); - mips_get_cause( cause ); - - cause &= (sr & SR_IMASK); - cause >>= CAUSE_IPSHIFT; - - for ( i=1, mask=0x80 ; i<=8 ; i++, mask >>= 1 ) { - if ( cause & mask ) - bsp_interrupt_handler_dispatch( MIPS_INTERRUPT_BASE + 8 - i ); - } -} - -void mips_default_isr( int vector ) -{ - unsigned int sr; - unsigned int cause; - - mips_get_sr( sr ); - mips_get_cause( cause ); - - printk( "Unhandled isr exception: vector 0x%02x, cause 0x%08X, sr 0x%08X\n", - vector, cause, sr ); - rtems_fatal_error_occurred(1); -} - diff --git a/c/src/lib/libbsp/mips/jmr3904/Makefile.am b/c/src/lib/libbsp/mips/jmr3904/Makefile.am index ccffd01669..84dabfd775 100644 --- a/c/src/lib/libbsp/mips/jmr3904/Makefile.am +++ b/c/src/lib/libbsp/mips/jmr3904/Makefile.am @@ -32,10 +32,10 @@ librtemsbsp_a_SOURCES += ../../../../../../bsps/mips/jmr3904/console/console-io. # timer librtemsbsp_a_SOURCES += ../../../../../../bsps/mips/jmr3904/btimer/btimer.c #isr -librtemsbsp_a_SOURCES += ../shared/irq/vectorexceptions.c -librtemsbsp_a_SOURCES += ../shared/irq/irq.c -librtemsbsp_a_SOURCES += irq/vectorisrs.c -librtemsbsp_a_SOURCES += ../shared/irq/interruptmask.c +librtemsbsp_a_SOURCES += ../../../../../../bsps/mips/shared/irq/vectorexceptions.c +librtemsbsp_a_SOURCES += ../../../../../../bsps/mips/shared/irq/irq.c +librtemsbsp_a_SOURCES += ../../../../../../bsps/mips/jmr3904/irq/vectorisrs.c +librtemsbsp_a_SOURCES += ../../../../../../bsps/mips/shared/irq/interruptmask.c librtemsbsp_a_SOURCES += ../../../../../../bsps/shared/cache/nocache.c librtemsbsp_a_SOURCES += ../../../../../../bsps/mips/shared/irq/installisrentries.c diff --git a/c/src/lib/libbsp/mips/jmr3904/irq/vectorisrs.c b/c/src/lib/libbsp/mips/jmr3904/irq/vectorisrs.c deleted file mode 100644 index 629c4c45f8..0000000000 --- a/c/src/lib/libbsp/mips/jmr3904/irq/vectorisrs.c +++ /dev/null @@ -1,47 +0,0 @@ -/** - * @file - * - * TX3904 Interrupt Vectoring - */ - -/* - * COPYRIGHT (c) 1989-2012. - * On-Line Applications Research Corporation (OAR). - * - * The license and distribution terms for this file may be - * found in the file LICENSE in this distribution or at - * http://www.rtems.org/license/LICENSE. - */ - -#include -#include -#include -#include /* for printk */ -#include -#include - -void mips_vector_isr_handlers( CPU_Interrupt_frame *frame ) -{ - unsigned int sr; - unsigned int cause; - - mips_get_sr( sr ); - mips_get_cause( cause ); - - cause &= (sr & SR_IMASK); - cause >>= CAUSE_IPSHIFT; - - if ( cause & 0x80 ) /* IP[5] ==> INT0 */ - bsp_interrupt_handler_dispatch( TX3904_IRQ_INT0 ); - - if ( cause & 0x40 ) { /* (IP[4] == 1) ==> IP[0-3] are valid */ - unsigned int v = (cause >> 2) & 0x0f; - bsp_interrupt_handler_dispatch( MIPS_INTERRUPT_BASE + v ); - } - - if ( cause & 0x02 ) /* SW[0] */ - bsp_interrupt_handler_dispatch( TX3904_IRQ_SOFTWARE_1 ); - - if ( cause & 0x01 ) /* IP[1] */ - bsp_interrupt_handler_dispatch( TX3904_IRQ_SOFTWARE_2 ); -} diff --git a/c/src/lib/libbsp/mips/malta/Makefile.am b/c/src/lib/libbsp/mips/malta/Makefile.am index ce78801123..3240ea9ea2 100644 --- a/c/src/lib/libbsp/mips/malta/Makefile.am +++ b/c/src/lib/libbsp/mips/malta/Makefile.am @@ -55,11 +55,11 @@ librtemsbsp_a_SOURCES += pci/pci.c librtemsbsp_a_SOURCES += ../../../../../../bsps/shared/dev/pci/pci_find_device.c #isr -librtemsbsp_a_SOURCES += ../shared/irq/vectorexceptions.c -librtemsbsp_a_SOURCES += ../shared/irq/irq.c -librtemsbsp_a_SOURCES += irq/vectorisrs.c -librtemsbsp_a_SOURCES += irq/interruptmask.c -librtemsbsp_a_SOURCES += ../shared/irq/i8259.c +librtemsbsp_a_SOURCES += ../../../../../../bsps/mips/shared/irq/vectorexceptions.c +librtemsbsp_a_SOURCES += ../../../../../../bsps/mips/shared/irq/irq.c +librtemsbsp_a_SOURCES += ../../../../../../bsps/mips/malta/irq/vectorisrs.c +librtemsbsp_a_SOURCES += ../../../../../../bsps/mips/malta/irq/interruptmask.c +librtemsbsp_a_SOURCES += ../../../../../../bsps/mips/shared/irq/i8259.c include $(top_srcdir)/../../../../automake/local.am include $(srcdir)/../../../../../../bsps/shared/irq-sources.am diff --git a/c/src/lib/libbsp/mips/malta/irq/interruptmask.c b/c/src/lib/libbsp/mips/malta/irq/interruptmask.c deleted file mode 100644 index d639ab17a9..0000000000 --- a/c/src/lib/libbsp/mips/malta/irq/interruptmask.c +++ /dev/null @@ -1,36 +0,0 @@ -/** - * @file - * - * This file contains the implementation of the MIPS port - * support routine which provides the BSP specific default - * interrupt mask. - */ - -/* - * COPYRIGHT (c) 1989-2012. - * On-Line Applications Research Corporation (OAR). - * - * The license and distribution terms for this file may be - * found in the file LICENSE in this distribution or at - * http://www.rtems.org/license/LICENSE. - */ - -#include - -/* - * This function returns a mask value which is used to select the bits - * in the processor status register that can be set to enable interrupts. - * The mask value should not include the 2 software interrupt enable bits. - */ - -uint32_t mips_interrupt_mask( void ) -{ - uint32_t interrupt_mask; - - /* - * This has only been tested with qemu for the mips malta and - * may not be correct for the 24k on real hardware. - */ - interrupt_mask = 0x0000ff00; - return(interrupt_mask); -} diff --git a/c/src/lib/libbsp/mips/malta/irq/vectorisrs.c b/c/src/lib/libbsp/mips/malta/irq/vectorisrs.c deleted file mode 100644 index a2b9288646..0000000000 --- a/c/src/lib/libbsp/mips/malta/irq/vectorisrs.c +++ /dev/null @@ -1,90 +0,0 @@ -/** - * @file - * - */ - -/* - * COPYRIGHT (c) 1989-2012. - * On-Line Applications Research Corporation (OAR). - * - * The license and distribution terms for this file may be - * found in the file LICENSE in this distribution or at - * http://www.rtems.org/license/LICENSE. - */ - -#include -#include -#include -#include -#include -#include -#include - -void mips_default_isr( int vector ); - -#include /* for printk */ - -void mips_vector_isr_handlers( CPU_Interrupt_frame *frame ) -{ - unsigned int sr; - unsigned int cause; - unsigned int pending; - - mips_get_sr( sr ); - mips_get_cause( cause ); - - pending = (cause & sr & 0xff00) >> CAUSE_IPSHIFT; - - /* SW Bits */ - if ( pending & 0x01) { - printk("Pending IRQ Q 0x%x\n", pending ); - } - - if ( pending & 0x02) { - printk("Pending IRQ Q 0x%x\n", pending ); - } - - /* South Bridge Interrupt */ - if ( pending & 0x04) { - BSP_i8259s_int_process(); - } - - /* South Bridge SMI */ - if (pending & 0x08){ - printk( "Pending IRQ 0x%x\n", pending ); - } - - /* TTY 2 */ - if (pending & 0x10) { - printk( "Pending IRQ 0x%x\n", pending ); - } - /* Core HI */ - if (pending & 0x20) { - printk( "Pending IRQ 0x%x\n", pending ); - } - /* Core LO */ - if (pending & 0x40) { - printk( "Pending IRQ 0x%x\n", pending ); - } - - if ( pending & 0x80 ) { - bsp_interrupt_handler_dispatch( MALTA_INT_TICKER ); - } -} - -void mips_default_isr( int vector ) -{ - unsigned int sr; - unsigned int cause; - - mips_get_sr( sr ); - mips_get_cause( cause ); - - printk( "Unhandled isr exception: vector 0x%02x, cause 0x%08X, sr 0x%08X\n", - vector, cause, sr ); - - while(1); /* Lock it up */ - - rtems_fatal_error_occurred(1); -} - diff --git a/c/src/lib/libbsp/mips/rbtx4925/Makefile.am b/c/src/lib/libbsp/mips/rbtx4925/Makefile.am index b483b2413e..42be304001 100644 --- a/c/src/lib/libbsp/mips/rbtx4925/Makefile.am +++ b/c/src/lib/libbsp/mips/rbtx4925/Makefile.am @@ -29,7 +29,7 @@ librtemsbsp_a_SOURCES += ../../../../../../bsps/shared/start/sbrk.c librtemsbsp_a_SOURCES += ../../../../../../bsps/mips/rbtx4925/start/inittlb.c librtemsbsp_a_SOURCES += ../../../../../../bsps/mips/shared/start/idttlb.S librtemsbsp_a_SOURCES += ../../../../../../bsps/mips/shared/start/idtmem.S -librtemsbsp_a_SOURCES += ../shared/irq/exception.S +librtemsbsp_a_SOURCES += ../../../../../../bsps/mips/shared/irq/exception.S # clock librtemsbsp_a_SOURCES +=../../../../../../bsps/mips/rbtx4925/clock/clockdrv.c # console @@ -38,10 +38,10 @@ librtemsbsp_a_SOURCES += ../../../../../../bsps/mips/rbtx4925/console/console-io librtemsbsp_a_SOURCES += ../shared/liblnk/lnklib.S librtemsbsp_a_SOURCES += ../shared/liblnk/pmon.S #isr -librtemsbsp_a_SOURCES += ../shared/irq/vectorexceptions.c -librtemsbsp_a_SOURCES += ../shared/irq/irq.c -librtemsbsp_a_SOURCES += irq/vectorisrs.c -librtemsbsp_a_SOURCES += ../shared/irq/interruptmask_TX49.c +librtemsbsp_a_SOURCES += ../../../../../../bsps/mips/shared/irq/vectorexceptions.c +librtemsbsp_a_SOURCES += ../../../../../../bsps/mips/shared/irq/irq.c +librtemsbsp_a_SOURCES += ../../../../../../bsps/mips/rbtx4925/irq/vectorisrs.c +librtemsbsp_a_SOURCES += ../../../../../../bsps/mips/shared/irq/interruptmask_TX49.c librtemsbsp_a_SOURCES += ../../../../../../bsps/shared/cache/nocache.c librtemsbsp_a_SOURCES += ../../../../../../bsps/mips/shared/irq/installisrentries.c diff --git a/c/src/lib/libbsp/mips/rbtx4925/irq/vectorisrs.c b/c/src/lib/libbsp/mips/rbtx4925/irq/vectorisrs.c deleted file mode 100644 index 09020c5020..0000000000 --- a/c/src/lib/libbsp/mips/rbtx4925/irq/vectorisrs.c +++ /dev/null @@ -1,64 +0,0 @@ -/** - * @file - * - * TX4925 Interrupt Vectoring - */ - -/* - * COPYRIGHT (c) 1989-2012. - * On-Line Applications Research Corporation (OAR). - * - * The license and distribution terms for this file may be - * found in the file LICENSE in this distribution or at - * http://www.rtems.org/license/LICENSE. - */ - -#include -#include -#include -#include -#include -#include -#include /* for printk */ - -void mips_default_isr( int vector ); - -void mips_vector_isr_handlers( CPU_Interrupt_frame *frame ) -{ - unsigned int sr; - unsigned int cause; - unsigned int pending; - - mips_get_sr( sr ); - mips_get_cause( cause ); - - pending = (cause & sr & 0x700) >> CAUSE_IPSHIFT; - - if ( pending & 0x4 ) { /* (IP[2] == 1) ==> IP[3-7] are valid */ - unsigned int v = (cause >> (CAUSE_IPSHIFT + 3)) & 0x1f; - bsp_interrupt_handler_dispatch( MIPS_INTERRUPT_BASE + v ); - } - - if ( pending & 0x01 ) /* IP[0] */ - bsp_interrupt_handler_dispatch( TX4925_IRQ_SOFTWARE_1 ); - - if ( pending & 0x02 ) /* IP[1] */ - bsp_interrupt_handler_dispatch( TX4925_IRQ_SOFTWARE_2 ); -} - -void mips_default_isr( int vector ) -{ - unsigned int sr; - unsigned int cause; - - mips_get_sr( sr ); - mips_get_cause( cause ); - - printk( "Unhandled isr exception: vector 0x%02x, cause 0x%08X, sr 0x%08X\n", - vector, cause, sr ); - - while(1); /* Lock it up */ - - rtems_fatal_error_occurred(1); -} - diff --git a/c/src/lib/libbsp/mips/rbtx4938/Makefile.am b/c/src/lib/libbsp/mips/rbtx4938/Makefile.am index d8b53efe8b..2eeb2d39b5 100644 --- a/c/src/lib/libbsp/mips/rbtx4938/Makefile.am +++ b/c/src/lib/libbsp/mips/rbtx4938/Makefile.am @@ -30,7 +30,7 @@ librtemsbsp_a_SOURCES += ../../../../../../bsps/shared/start/sbrk.c librtemsbsp_a_SOURCES += ../../../../../../bsps/mips/rbtx4938/start/inittlb.c librtemsbsp_a_SOURCES += ../../../../../../bsps/mips/shared/start/idttlb.S librtemsbsp_a_SOURCES += ../../../../../../bsps/mips/shared/start/idtmem.S -librtemsbsp_a_SOURCES += ../shared/irq/exception.S +librtemsbsp_a_SOURCES += ../../../../../../bsps/mips/shared/irq/exception.S # clock librtemsbsp_a_SOURCES +=../../../../../../bsps/mips/rbtx4938/clock/clockdrv.c # console @@ -39,10 +39,10 @@ librtemsbsp_a_SOURCES += ../../../../../../bsps/mips/rbtx4938/console/console-io librtemsbsp_a_SOURCES += ../shared/liblnk/lnklib.S librtemsbsp_a_SOURCES += ../shared/liblnk/pmon.S #isr -librtemsbsp_a_SOURCES += ../shared/irq/vectorexceptions.c -librtemsbsp_a_SOURCES += ../shared/irq/irq.c -librtemsbsp_a_SOURCES += irq/vectorisrs.c -librtemsbsp_a_SOURCES += ../shared/irq/interruptmask_TX49.c +librtemsbsp_a_SOURCES += ../../../../../../bsps/mips/shared/irq/vectorexceptions.c +librtemsbsp_a_SOURCES += ../../../../../../bsps/mips/shared/irq/irq.c +librtemsbsp_a_SOURCES += ../../../../../../bsps/mips/rbtx4938/irq/vectorisrs.c +librtemsbsp_a_SOURCES += ../../../../../../bsps/mips/shared/irq/interruptmask_TX49.c librtemsbsp_a_SOURCES += ../../../../../../bsps/shared/cache/nocache.c librtemsbsp_a_SOURCES += ../../../../../../bsps/mips/shared/irq/installisrentries.c diff --git a/c/src/lib/libbsp/mips/rbtx4938/irq/vectorisrs.c b/c/src/lib/libbsp/mips/rbtx4938/irq/vectorisrs.c deleted file mode 100644 index d38e4f81c2..0000000000 --- a/c/src/lib/libbsp/mips/rbtx4938/irq/vectorisrs.c +++ /dev/null @@ -1,64 +0,0 @@ -/** - * @file - * - * TX4925 Interrupt Vectoring - */ - -/* - * COPYRIGHT (c) 1989-2012. - * On-Line Applications Research Corporation (OAR). - * - * The license and distribution terms for this file may be - * found in the file LICENSE in this distribution or at - * http://www.rtems.org/license/LICENSE. - */ - -#include -#include -#include -#include -#include -#include -#include /* for printk */ - -void mips_default_isr( int vector ); - -void mips_vector_isr_handlers( CPU_Interrupt_frame *frame ) -{ - unsigned int sr; - unsigned int cause; - unsigned int pending; - - mips_get_sr( sr ); - mips_get_cause( cause ); - - pending = (cause & sr & 0x700) >> CAUSE_IPSHIFT; - - if ( pending & 0x4 ) { /* (IP[2] == 1) ==> IP[3-7] are valid */ - unsigned int v = (cause >> (CAUSE_IPSHIFT + 3)) & 0x1f; - bsp_interrupt_handler_dispatch( MIPS_INTERRUPT_BASE + v ); - } - - if ( pending & 0x01 ) /* IP[0] */ - bsp_interrupt_handler_dispatch( TX4938_IRQ_SOFTWARE_1 ); - - if ( pending & 0x02 ) /* IP[1] */ - bsp_interrupt_handler_dispatch( TX4938_IRQ_SOFTWARE_2 ); -} - -void mips_default_isr( int vector ) -{ - unsigned int sr; - unsigned int cause; - - mips_get_sr( sr ); - mips_get_cause( cause ); - - printk( "Unhandled isr exception: vector 0x%02x, cause 0x%08X, sr 0x%08X\n", - vector, cause, sr ); - - while(1); /* Lock it up */ - - rtems_fatal_error_occurred(1); -} - diff --git a/c/src/lib/libbsp/mips/shared/irq/exception.S b/c/src/lib/libbsp/mips/shared/irq/exception.S deleted file mode 100644 index e916ae55fe..0000000000 --- a/c/src/lib/libbsp/mips/shared/irq/exception.S +++ /dev/null @@ -1,661 +0,0 @@ -/* - * This file contains a customized MIPS exception handler. - * It hooks into the exception handler present in the resident - * PMON debug monitor. - */ - -/* - * Author: Bruce Robinson - * - * This code was derived from cpu_asm.S with the following copyright: - * - * COPYRIGHT (c) 1996 by Transition Networks Inc. - * - * To anyone who acknowledges that this file is provided "AS IS" - * without any express or implied warranty: - * permission to use, copy, modify, and distribute this file - * for any purpose is hereby granted without fee, provided that - * the above copyright notice and this notice appears in all - * copies, and that the name of Transition Networks not be used in - * advertising or publicity pertaining to distribution of the - * software without specific, written prior permission. - * Transition Networks makes no representations about the suitability - * of this software for any purpose. - * - * Derived from c/src/exec/score/cpu/no_cpu/cpu_asm.s: - * - * COPYRIGHT (c) 1989-2010. - * On-Line Applications Research Corporation (OAR). - * - * The license and distribution terms for this file may be - * found in the file LICENSE in this distribution or at - * http://www.rtems.org/license/LICENSE. - */ - -#include -#include -#include -#include -#include -#if BSP_HAS_USC320 - #include -#endif - -#if __mips == 3 -/* 64 bit register operations */ -#define NOP nop -#define ADD dadd -#define STREG sd -#define LDREG ld -#define ADDU addu -#define ADDIU addiu -#define STREGC1 sdc1 -#define LDREGC1 ldc1 -#define R_SZ 8 -#define F_SZ 8 -#define SZ_INT 8 -#define SZ_INT_POW2 3 - -/* XXX if we don't always want 64 bit register ops, then another ifdef */ - -#elif __mips == 1 -/* 32 bit register operations*/ -#define NOP nop -#define ADD add -#define STREG sw -#define LDREG lw -#define ADDU add -#define ADDIU addi -#define STREGC1 swc1 -#define LDREGC1 lwc1 -#define R_SZ 4 -#define F_SZ 4 -#define SZ_INT 4 -#define SZ_INT_POW2 2 -#else -#error "mips assembly: what size registers do I deal with?" -#endif - - -#define ISR_VEC_SIZE 4 -#define EXCP_STACK_SIZE (NREGS*R_SZ) - -.extern _Thread_Dispatch - -/* void __ISR_Handler() - * - * This routine provides the RTEMS interrupt management. - * - */ - -#if 0 -void _ISR_Handler() -{ - /* - * This discussion ignores a lot of the ugly details in a real - * implementation such as saving enough registers/state to be - * able to do something real. Keep in mind that the goal is - * to invoke a user's ISR handler which is written in C and - * uses a certain set of registers. - * - * Also note that the exact order is to a large extent flexible. - * Hardware will dictate a sequence for a certain subset of - * _ISR_Handler while requirements for setting - */ - - /* - * At entry to "common" _ISR_Handler, the vector number must be - * available. On some CPUs the hardware puts either the vector - * number or the offset into the vector table for this ISR in a - * known place. If the hardware does not give us this information, - * then the assembly portion of RTEMS for this port will contain - * a set of distinct interrupt entry points which somehow place - * the vector number in a known place (which is safe if another - * interrupt nests this one) and branches to _ISR_Handler. - * - */ -#endif -FRAME(bsp_ISR_Handler,sp,0,ra) - .set noreorder - -#if 0 -/* Activate TX49xx PIO19 signal for diagnostics */ - lui k0,0xff1f - ori k0,k0,0xf500 - lw k0,(k0) - lui k1,0x8 - or k1,k1,k0 - lui k0,0xff1f - ori k0,k0,0xf500 - sw k1,(k0) -#endif - mfc0 k0,C0_CAUSE /* Determine if an interrupt generated this exception */ - nop - and k1,k0,CAUSE_EXCMASK - beq k1,zero,_chk_int /* If so, branch to service here */ - nop - la k0,_int_esr_link /* Otherwise, jump to next exception handler in PMON exception chain */ - lw k0,(k0) - lw k0,4(k0) - j k0 - nop -_chk_int: - mfc0 k1,C0_SR - nop - and k0,k1 -#if HAS_RM52xx - and k0,CAUSE_IPMASK -#elif HAS_TX49xx - and k0,(SR_IBIT1 | SR_IBIT2 | SR_IBIT3) -#endif - /* external interrupt not enabled, ignore */ - beq k0,zero,_ISR_Handler_quick_exit - nop - -/* For debugging interrupts, clear EXL to allow breakpoints */ -#if 0 - MFC0 k0, C0_SR -#if __mips == 3 - li k1,SR_EXL /* Clear EXL and Set IE to enable interrupts */ - not k1 - and k0,k1 - li k1,SR_IE -#elif __mips == 1 - li k1,SR_IEC -#endif - or k0, k1 - mtc0 k0, C0_SR - NOP -#endif - - - /* - * save some or all context on stack - * may need to save some special interrupt information for exit - */ - - /* Q: _ISR_Handler, not using IDT/SIM ...save extra regs? */ - - /* wastes a lot of stack space for context?? */ - ADDIU sp,sp,-EXCP_STACK_SIZE - - STREG ra, R_RA*R_SZ(sp) /* store ra on the stack */ - STREG v0, R_V0*R_SZ(sp) - STREG v1, R_V1*R_SZ(sp) - STREG a0, R_A0*R_SZ(sp) - STREG a1, R_A1*R_SZ(sp) - STREG a2, R_A2*R_SZ(sp) - STREG a3, R_A3*R_SZ(sp) - STREG t0, R_T0*R_SZ(sp) - STREG t1, R_T1*R_SZ(sp) - STREG t2, R_T2*R_SZ(sp) - STREG t3, R_T3*R_SZ(sp) - STREG t4, R_T4*R_SZ(sp) - STREG t5, R_T5*R_SZ(sp) - STREG t6, R_T6*R_SZ(sp) - STREG t7, R_T7*R_SZ(sp) - mflo t0 - STREG t8, R_T8*R_SZ(sp) - STREG t0, R_MDLO*R_SZ(sp) - STREG t9, R_T9*R_SZ(sp) - mfhi t0 - STREG gp, R_GP*R_SZ(sp) - STREG t0, R_MDHI*R_SZ(sp) - STREG fp, R_FP*R_SZ(sp) - - .set noat - STREG AT, R_AT*R_SZ(sp) - .set at - - mfc0 t0,C0_SR - dmfc0 t1,C0_EPC - STREG t0,R_SR*R_SZ(sp) - STREG t1,R_EPC*R_SZ(sp) - - /* - * - * #if ( CPU_HAS_SOFTWARE_INTERRUPT_STACK == TRUE ) - * if ( _ISR_Nest_level == 0 ) - * switch to software interrupt stack - * #endif - */ - - /* - * _ISR_Nest_level++; - */ - lw t0,ISR_NEST_LEVEL - NOP - add t0,t0,1 - sw t0,ISR_NEST_LEVEL - /* - * _Thread_Dispatch_disable_level++; - */ - lw t1,THREAD_DISPATCH_DISABLE_LEVEL - NOP - add t1,t1,1 - sw t1,THREAD_DISPATCH_DISABLE_LEVEL - - /* DEBUG - Add the following code to disable interrupts and clear - * EXL in status register, this will allow memory - * exceptions to occur while servicing the current interrupt - */ -#if 0 - /* Disable interrupts from internal interrupt controller */ - li t0,~CAUSE_IP2_MASK - mfc0 t1,C0_SR - nop - and t1,t0 - mtc0 t1,C0_SR - nop - /* Clear EXL in status register to allow memory exceptions to occur */ - li t0,~SR_EXL - mfc0 t1,C0_SR - nop - and t1,t0 - mtc0 t1,C0_SR - nop -#endif - - /* - * Call the CPU model or BSP specific routine to decode the - * interrupt source and actually vector to device ISR handlers. - */ - move a0,sp - jal mips_vector_isr_handlers - NOP - - /* Add the following code to disable interrupts (see DEBUG above) */ -#if 0 - li t0,SR_EXL /* Set EXL to hold off interrupts */ - mfc0 t1,C0_SR - nop - or t1,t0 - mtc0 t1,C0_SR - nop - /* Enable interrupts from internal interrupt controller */ - li t0,CAUSE_IP2_MASK - mfc0 t1,C0_SR - nop - or t1,t0 - mtc0 t1,C0_SR - nop -#endif - -_ISR_Handler_cleanup: - - /* - * --_ISR_Nest_level; - */ - lw t2,ISR_NEST_LEVEL - NOP - add t2,t2,-1 - sw t2,ISR_NEST_LEVEL - /* - * --_Thread_Dispatch_disable_level; - */ - lw t1,THREAD_DISPATCH_DISABLE_LEVEL - NOP - add t1,t1,-1 - sw t1,THREAD_DISPATCH_DISABLE_LEVEL - /* - * if ( _Thread_Dispatch_disable_level || _ISR_Nest_level ) - * goto the label "exit interrupt (simple case)" - */ - or t0,t2,t1 - bne t0,zero,_ISR_Handler_exit - NOP - - - /* - * #if ( CPU_HAS_SOFTWARE_INTERRUPT_STACK == TRUE ) - * restore stack - * #endif - * - * if ( !_Thread_Dispatch_necessary ) - * goto the label "exit interrupt (simple case)" - */ - lb t0,DISPATCH_NEEDED - NOP - or t0,t0,t0 - beq t0,zero,_ISR_Handler_exit - NOP - -/* -** Turn on interrupts before entering Thread_Dispatch which -** will run for a while, thus allowing new interrupts to -** be serviced. Observe the Thread_Dispatch_disable_level interlock -** that prevents recursive entry into Thread_Dispatch. -*/ - - mfc0 t0, C0_SR -#if __mips == 3 - li t1,SR_EXL /* Clear EXL and Set IE to enable interrupts */ - not t1 - and t0,t1 - li t1,SR_IE -#elif __mips == 1 - li t1,SR_IEC -#endif - or t0, t1 - mtc0 t0, C0_SR - NOP - - /* save off our stack frame so the context switcher can get to it */ - la t0,__exceptionStackFrame - STREG sp,(t0) - - jal _Thread_Dispatch - NOP - - /* and make sure its clear in case we didn't dispatch. if we did, its - ** already cleared */ - la t0,__exceptionStackFrame - STREG zero,(t0) - NOP - -/* -** turn interrupts back off while we restore context so -** a badly timed interrupt won't accidentally mess things up -*/ - mfc0 t0, C0_SR -#if __mips == 3 - li t1,SR_IE /* Clear IE first (recommended) */ - not t1 - and t0,t1 - mtc0 t0, C0_SR - li t1,SR_EXL | SR_IE /* Set EXL and IE, this puts status register bits back to interrupted state */ - or t0,t1 -#elif __mips == 1 - /* ints off, current & prev kernel mode on (kernel mode enabled is bit clear..argh!) */ - li t1,SR_IEC | SR_KUP | SR_KUC - not t1 - and t0, t1 -#endif - mtc0 t0, C0_SR - NOP - - /* - * prepare to get out of interrupt - * return from interrupt (maybe to _ISR_Dispatch) - * - * LABEL "exit interrupt (simple case):" - * prepare to get out of interrupt - * return from interrupt - */ - -_ISR_Handler_exit: - -/* restore interrupt context from stack */ - LDREG t8, R_MDLO*R_SZ(sp) - LDREG t0, R_T0*R_SZ(sp) - mtlo t8 - LDREG t8, R_MDHI*R_SZ(sp) - LDREG t1, R_T1*R_SZ(sp) - mthi t8 - LDREG t2, R_T2*R_SZ(sp) - LDREG t3, R_T3*R_SZ(sp) - LDREG t4, R_T4*R_SZ(sp) - LDREG t5, R_T5*R_SZ(sp) - LDREG t6, R_T6*R_SZ(sp) - LDREG t7, R_T7*R_SZ(sp) - LDREG t8, R_T8*R_SZ(sp) - LDREG t9, R_T9*R_SZ(sp) - LDREG gp, R_GP*R_SZ(sp) - LDREG fp, R_FP*R_SZ(sp) - LDREG ra, R_RA*R_SZ(sp) - LDREG a0, R_A0*R_SZ(sp) - LDREG a1, R_A1*R_SZ(sp) - LDREG a2, R_A2*R_SZ(sp) - LDREG a3, R_A3*R_SZ(sp) - LDREG v1, R_V1*R_SZ(sp) - LDREG v0, R_V0*R_SZ(sp) - - LDREG k1, R_EPC*R_SZ(sp) - mtc0 k1,C0_EPC - - .set noat - LDREG AT, R_AT*R_SZ(sp) - .set at - - ADDIU sp,sp,EXCP_STACK_SIZE - -_ISR_Handler_quick_exit: - eret - nop - - -#if BSP_HAS_USC320 - /* Interrupts from USC320 are serviced here */ - .global USC_isr - .extern Clock_isr -USC_isr: - /* check if it's a USC320 heartbeat interrupt */ - la k0,INT_STAT /* read INT_STAT register */ - lw k0,(k0) - nop /* reading from external device */ - sll k0,(31-21) /* test bit 21 (HBI) */ - - bgez k0,USC_isr2 /* branch if not a heartbeat interrupt */ - NOP - - /* clear the heartbeat interrupt */ - la k0,INT_STAT - li t0,HBI_MASK - sw t0,(k0) - /* wait for interrupt to clear */ -USC_isr1: - la k0,INT_STAT /* read INT_STAT register */ - lw k0,(k0) - nop /* reading from external device */ - sll k0,(31-21) /* test bit 21 (HBI) */ - bltz k0,USC_isr1 /* branch if bit set */ - nop - j Clock_isr /* Jump to clock isr */ - nop -USC_isr2: - j ra /* no serviceable interrupt, return without doing anything */ - nop -#endif - -#if 0 - .global int7_isr - .extern Interrupt_7_isr -int7_isr: - /* Verify interrupt is from Timer */ - la k0,IRCS /* read Interrupt Current Status register */ - lw k0,(k0) - nop /* reading from external device */ - li k1,IRCS_CAUSE_MASK - and k0,k0,k1 /* isolate interrupt cause */ - - li k1,INT7INT /* test for interrupt 7 */ - subu k1,k0,k1 - beq k1,zero,int7_isr1 - nop - j ra /* interrupt 7 no longer valid, return without doing anything */ - nop -int7_isr1: - j Interrupt_7_isr /* Jump to Interrupt 7 isr */ - nop -#endif - - .set reorder - -ENDFRAME(bsp_ISR_Handler) - - -FRAME(_BRK_Handler,sp,0,ra) - .set noreorder - -#if BSP_HAS_USC320 - la k0,INT_CFG3 /* Disable heartbeat interrupt in USC320, it interferes with PMON exception handler */ - lw k1,(k0) - li k0,~HBI_MASK - and k1,k1,k0 - la k0,INT_CFG3 - sw k1,(k0) -#endif - - la k0,_brk_esr_link /* Jump to next exception handler in PMON exception chain */ - lw k0,(k0) - lw k0,4(k0) - j k0 - nop - - .set reorder -ENDFRAME(_BRK_Handler) - - -/************************************************************************** -** -** init_exc_vecs() - moves the exception code into the addresses -** reserved for exception vectors -** -** UTLB Miss exception vector at address 0x80000000 -** -** General exception vector at address 0x80000080 -** -** RESET exception vector is at address 0xbfc00000 -** -***************************************************************************/ - -FRAME(init_exc_vecs,sp,0,ra) - .set noreorder - - .extern mon_onintr - -/* Install interrupt handler in PMON exception handling chain */ - - addiu sp,sp,-8 - sw ra,(sp) /* Save ra contents on stack */ - move a0,zero - la a1,_int_esr_link - jal mon_onintr /* Make PMON system call to install interrupt exception handler */ - nop - li a0,9 - la a1,_brk_esr_link - jal mon_onintr /* Make PMON system call to install break exception handler */ - nop - lw ra,(sp) - addiu sp,sp,8 /* Restore ra contents from stack */ - j ra - nop - - .set reorder -ENDFRAME(init_exc_vecs) - - -#if 0 /* Unused code below */ - -/************************************************************* -* enable_int7(ints) -* Enable interrupt 7 -*/ -FRAME(enable_int7,sp,0,ra) - .set noreorder - - la t0,IRDM1 # Set interrupt controller detection mode (bits 2-3 = 0 for int 7 active low) - li t1,0x0 - sw t1,(t0) - - la t0,IRLVL4 # Set interrupt controller level (bit 8-10 = 2 for int 7 at level 2) - li t1,0x200 - sw t1,(t0) - - la t0,IRMSK # Set interrupt controller mask - li t1,0x0 - sw t1,(t0) - - la t0,IRDEN # Enable interrupts from controller - li t1,0x1 - sw t1,(t0) - - j ra - nop - .set reorder -ENDFRAME(enable_int7) - -/************************************************************* -* disable_int7(ints) -* Disable interrupt 7 -*/ -FRAME(disable_int7,sp,0,ra) - .set noreorder - - la t0,IRLVL4 # Set interrupt controller level (bit 8-10 = 0 to diasble int 7) - li t1,0x200 - sw t1,(t0) - - j ra - nop - .set reorder -ENDFRAME(disable_int7) -#endif - -/************************************************************* -* exception: -* Diagnostic code that can be hooked to PMON interrupt handler. -* Generates pulse on PIO22 pin. -* Called from _exception code in PMON (see mips.s of PMON). -* Return address is located in k1. -*/ -FRAME(tx49xxexception,sp,0,ra) - .set noreorder - la k0,k1tmp - sw k1,(k0) - -/* Activate TX49xx PIO22 signal for diagnostics */ - lui k0,0xff1f - ori k0,k0,0xf500 - lw k0,(k0) - lui k1,0x40 - or k1,k1,k0 - lui k0,0xff1f - ori k0,k0,0xf500 - sw k1,(k0) - nop - -/* De-activate TX49xx PIO22 signal for diagnostics */ - lui k0,0xff1f - ori k0,k0,0xf500 - lw k0,(k0) - lui k1,0x40 - not k1 - and k1,k1,k0 - lui k0,0xff1f - ori k0,k0,0xf500 - sw k1,(k0) - nop - - la k0,k1tmp - lw k1,(k0) - j k1 - .set reorder -ENDFRAME(tx49xxexception) - - - - - .data - -k1tmp: .word 0 /* Temporary strage for K1 during interrupt service */ - -/************************************************************* -* -* Exception handler links, used in PMON exception handler chains -*/ - /* Interrupt exception service routine link */ - .global _int_esr_link -_int_esr_link: - .word 0 - .word bsp_ISR_Handler - - /* Break exception service routine link */ - .global _brk_esr_link -_brk_esr_link: - .word 0 - .word _BRK_Handler - - - - diff --git a/c/src/lib/libbsp/mips/shared/irq/i8259.c b/c/src/lib/libbsp/mips/shared/irq/i8259.c deleted file mode 100644 index d92b5400a9..0000000000 --- a/c/src/lib/libbsp/mips/shared/irq/i8259.c +++ /dev/null @@ -1,332 +0,0 @@ -/** - * @file - * - * This file was based upon the powerpc and the i386. - */ - -/* - * COPYRIGHT (c) 1989-2012. - * On-Line Applications Research Corporation (OAR). - * - * The license and distribution terms for this file may be - * found in the file LICENSE in this distribution or at - * http://www.rtems.org/license/LICENSE. - */ - -/* - * Copyright (C) 1998, 1999 valette@crf.canon.fr - */ - -#include -#include -#include -#include -#include -#include - - -#define DEBUG_8259 1 - -#define ValidateIrqLine( _irq ) \ - if ( ((int)_irq < 0) ||((int)_irq > 16)) return 1; - -/*-------------------------------------------------------------------------+ -| Cache for 1st and 2nd PIC IRQ line's status (enabled or disabled) register. -+--------------------------------------------------------------------------*/ -/* - * lower byte is interrupt mask on the master PIC. - * while upper bits are interrupt on the slave PIC. - */ -volatile rtems_i8259_masks i8259s_cache = 0xfffb; - -/*-------------------------------------------------------------------------+ -| Function: BSP_irq_disable_at_i8259s -| Description: Mask IRQ line in appropriate PIC chip. -| Global Variables: i8259s_cache -| Arguments: vector_offset - number of IRQ line to mask. -| Returns: original state or -1 on error. -+--------------------------------------------------------------------------*/ -int BSP_irq_disable_at_i8259s (const rtems_irq_number irqLine) -{ - unsigned short mask; - rtems_interrupt_level level; - int rval; - - ValidateIrqLine(irqLine); - - rtems_interrupt_disable(level); - - /* Recalculate the value */ - mask = 1 << irqLine; - rval = i8259s_cache & mask ? 0 : 1; - i8259s_cache |= mask; - - /* Determine which chip and write the value. */ - if (irqLine < 8) { - simple_out_8( - BSP_8259_BASE_ADDRESS, - PIC_MASTER_IMR_IO_PORT, - i8259s_cache & 0xff - ); - } else { - simple_out_8( - BSP_8259_BASE_ADDRESS, - PIC_SLAVE_IMR_IO_PORT, - ((i8259s_cache & 0xff00) >> 8) - ); - } - - rtems_interrupt_enable(level); - - return rval; -} - -/*-------------------------------------------------------------------------+ -| Function: BSP_irq_enable_at_i8259s -| Description: Unmask IRQ line in appropriate PIC chip. -| Global Variables: i8259s_cache -| Arguments: irqLine - number of IRQ line to mask. -| Returns: Nothing. -+--------------------------------------------------------------------------*/ -int BSP_irq_enable_at_i8259s (const rtems_irq_number irqLine) -{ - unsigned short mask; - rtems_interrupt_level level; - - ValidateIrqLine( irqLine ); - - rtems_interrupt_disable(level); - - /* Calculate the value */ - mask = ~(1 << irqLine); - i8259s_cache &= mask; - - /* Determine which chip and write the value */ - if (irqLine < 8) { - simple_out_8( - BSP_8259_BASE_ADDRESS, - PIC_MASTER_IMR_IO_PORT, - i8259s_cache & 0xff - ); - } else { - simple_out_8( - BSP_8259_BASE_ADDRESS, - PIC_SLAVE_IMR_IO_PORT, - ((i8259s_cache & 0xff00) >> 8) - ); - } - - rtems_interrupt_enable(level); - - return 0; -} /* mask_irq */ - - -int BSP_irq_enabled_at_i8259s(const rtems_irq_number irqLine) -{ - unsigned short mask; - - ValidateIrqLine( irqLine ); - - mask = (1 << irqLine); - - return (~(i8259s_cache & mask)); -} - -/*-------------------------------------------------------------------------+ -| Function: BSP_irq_ack_at_i8259s -| Description: Signal generic End Of Interrupt (EOI) to appropriate PIC. -| Global Variables: None. -| Arguments: irqLine - number of IRQ line to acknowledge. -| Returns: Nothing. -+--------------------------------------------------------------------------*/ -int BSP_irq_ack_at_i8259s (const rtems_irq_number irqLine) -{ - if (irqLine >= 8) { - simple_out_8( - BSP_8259_BASE_ADDRESS, - PIC_MASTER_COMMAND_IO_PORT, - SLAVE_PIC_EOSI - ); - simple_out_8( - BSP_8259_BASE_ADDRESS, - PIC_SLAVE_COMMAND_IO_PORT, - (PIC_EOSI | (irqLine - 8)) - ); - }else { - simple_out_8( - BSP_8259_BASE_ADDRESS, - PIC_MASTER_COMMAND_IO_PORT, - (PIC_EOSI | irqLine) - ); - } - - return 0; - -} /* ackIRQ */ - -void BSP_i8259s_init(void) -{ - volatile uint32_t i; - - simple_out_8(BSP_8259_BASE_ADDRESS, PIC_MASTER_IMR_IO_PORT, 0xff ); - simple_out_8(BSP_8259_BASE_ADDRESS, PIC_SLAVE_IMR_IO_PORT, 0xff ); - - - /* - * init master 8259 interrupt controller - */ - - /* Start init sequence */ - simple_out_8( - BSP_8259_BASE_ADDRESS, - PIC_MASTER_COMMAND_IO_PORT, - 0x11 - ); - /* Vector base = 0 */ - simple_out_8( - BSP_8259_BASE_ADDRESS, - PIC_MASTER_IMR_IO_PORT, - 0x00 - ); - - /* edge tiggered, Cascade (slave) on IRQ2 */ - simple_out_8( - BSP_8259_BASE_ADDRESS, - PIC_MASTER_IMR_IO_PORT, - 0x04 - ); - - /* Select 8086 mode */ - simple_out_8( - BSP_8259_BASE_ADDRESS, - PIC_MASTER_IMR_IO_PORT, - 0x01 - ); - - /* - * init slave interrupt controller - */ - - /* Start init sequence */ - simple_out_8(BSP_8259_BASE_ADDRESS, PIC_SLAVE_COMMAND_IO_PORT, 0x11); - - /* Vector base = 8 */ - simple_out_8(BSP_8259_BASE_ADDRESS, PIC_SLAVE_IMR_IO_PORT, 0x08); - - /* edge triggered, Cascade (slave) on IRQ2 */ - simple_out_8(BSP_8259_BASE_ADDRESS, PIC_SLAVE_IMR_IO_PORT, 0x02); - - /* Select 8086 mode */ - simple_out_8(BSP_8259_BASE_ADDRESS, PIC_SLAVE_IMR_IO_PORT, 0x01); - - /* Mask all except cascade */ - simple_out_8(BSP_8259_BASE_ADDRESS, PIC_MASTER_IMR_IO_PORT, 0xFB); - - /* Mask all */ - simple_out_8(BSP_8259_BASE_ADDRESS, PIC_SLAVE_IMR_IO_PORT, 0xFF); - - /* - * Enable all interrupts in debug mode. - */ - - if ( DEBUG_8259 ) { - i8259s_cache = 0x0101; - } - - simple_out_8( - BSP_8259_BASE_ADDRESS, - PIC_MASTER_IMR_IO_PORT, - i8259s_cache & 0xff - ); - simple_out_8( - BSP_8259_BASE_ADDRESS, - PIC_SLAVE_IMR_IO_PORT, - ((i8259s_cache & 0xff00) >> 8) - ); - - for (i=0; i<10000; i++); -} - -#define PCI__GEN(bus, off, num) (((off)^((bus) << 7))+((num) << 4)) -#define PCI_INTR_ACK(bus) PCI__GEN(bus, 0x0c34, 0) - -volatile uint8_t master; -volatile uint8_t slave; -volatile uint8_t temp; - -void bsp_show_interrupt_regs(void); -void bsp_show_interrupt_regs() { - unsigned int sr; - unsigned int cause; - unsigned int pending; - - mips_get_sr( sr ); - mips_get_cause( cause ); - pending = (cause & sr & 0xff00) >> CAUSE_IPSHIFT; - - master = simple_in_8(BSP_8259_BASE_ADDRESS, PIC_MASTER_COMMAND_IO_PORT); - slave = simple_in_8(BSP_8259_BASE_ADDRESS, PIC_SLAVE_COMMAND_IO_PORT); - - printk("sr: 0x%x cause: 0x%x pending: 0x%x master: 0x%x slave: 0x%x\n", - sr, cause, pending, master, slave - ); -} - -int BSP_i8259s_int_process() -{ - uint8_t irq; - volatile uint32_t temp; - - /* Get the Interrupt */ - irq = simple_in_le32(BSP_PCI_BASE_ADDRESS, PCI_INTR_ACK(0) ); - - /* - * Mask interrupts - * + Mask all except cascade on master - * + Mask all on slave - */ - simple_out_8(BSP_8259_BASE_ADDRESS, PIC_MASTER_IMR_IO_PORT, 0xFB); - simple_out_8(BSP_8259_BASE_ADDRESS, PIC_SLAVE_IMR_IO_PORT, 0xFF); - - /* Call the Handler */ - temp = irq + MALTA_SB_IRQ_0; - bsp_interrupt_handler_dispatch( temp ); - - /* Reset the interrupt on the 8259 either the master or the slave chip */ - if (irq & 8) { - temp = simple_in_8(BSP_8259_BASE_ADDRESS, PIC_SLAVE_IMR_IO_PORT); - - /* Mask all */ - simple_out_8(BSP_8259_BASE_ADDRESS, PIC_SLAVE_IMR_IO_PORT, 0xFF); - simple_out_8( - BSP_8259_BASE_ADDRESS, - PIC_SLAVE_COMMAND_IO_PORT, - (PIC_EOSI + (irq&7)) - ); - simple_out_8( - BSP_8259_BASE_ADDRESS, - PIC_MASTER_COMMAND_IO_PORT, - SLAVE_PIC_EOSI - ); - } else { - temp = simple_in_8(BSP_8259_BASE_ADDRESS, PIC_MASTER_IMR_IO_PORT); - /* Mask all except cascade */ - simple_out_8(BSP_8259_BASE_ADDRESS, PIC_MASTER_IMR_IO_PORT, 0xFB); - simple_out_8( - BSP_8259_BASE_ADDRESS, - PIC_MASTER_COMMAND_IO_PORT, - (PIC_EOSI+irq) - ); - } - - /* Restore the interrupts */ - simple_out_8(BSP_8259_BASE_ADDRESS,PIC_MASTER_IMR_IO_PORT,i8259s_cache&0xff); - simple_out_8( - BSP_8259_BASE_ADDRESS, - PIC_SLAVE_IMR_IO_PORT, - ((i8259s_cache & 0xff00) >> 8) - ); - - return 0; -} diff --git a/c/src/lib/libbsp/mips/shared/irq/interruptmask.c b/c/src/lib/libbsp/mips/shared/irq/interruptmask.c deleted file mode 100644 index c63421e569..0000000000 --- a/c/src/lib/libbsp/mips/shared/irq/interruptmask.c +++ /dev/null @@ -1,29 +0,0 @@ -/** - * @file - * - */ - -/* - * COPYRIGHT (c) 1989-2012. - * On-Line Applications Research Corporation (OAR). - * - * The license and distribution terms for this file may be - * found in the file LICENSE in this distribution or at - * http://www.rtems.org/license/LICENSE. - */ - -#include - -/* - * This function returns a mask value which is used to select the bits - * in the processor status register that can be set to enable interrupts. - * The mask value should not include the 2 software interrupt enable bits. - */ - -uint32_t mips_interrupt_mask( void ) -{ - uint32_t interrupt_mask; - - interrupt_mask = 0x0000fc00; - return(interrupt_mask); -} diff --git a/c/src/lib/libbsp/mips/shared/irq/interruptmask_TX49.c b/c/src/lib/libbsp/mips/shared/irq/interruptmask_TX49.c deleted file mode 100644 index 5b1daa57c3..0000000000 --- a/c/src/lib/libbsp/mips/shared/irq/interruptmask_TX49.c +++ /dev/null @@ -1,29 +0,0 @@ -/** - * @file - * - */ - -/* - * COPYRIGHT (c) 1989-2012. - * On-Line Applications Research Corporation (OAR). - * - * The license and distribution terms for this file may be - * found in the file LICENSE in this distribution or at - * http://www.rtems.org/license/LICENSE. - */ - -#include - -/* - * This function returns a mask value which is used to select the bits - * in the processor status register that can be set to enable interrupts. - * The mask value should not include the 2 software interrupt enable bits. - */ - -uint32_t mips_interrupt_mask( void ) -{ - uint32_t interrupt_mask; - - interrupt_mask = 0x00000400; /* Toshiba TX49 processors have a non-standard interrupt mask */ - return(interrupt_mask); -} diff --git a/c/src/lib/libbsp/mips/shared/irq/irq.c b/c/src/lib/libbsp/mips/shared/irq/irq.c deleted file mode 100644 index 1c2d3b8c5b..0000000000 --- a/c/src/lib/libbsp/mips/shared/irq/irq.c +++ /dev/null @@ -1,101 +0,0 @@ -/** - * @file - * - * @ingroup bsp_interrupt - * - * @brief Interrupt support. - */ - -/* - * Copyright (c) 2005 by Cogent Computer Systems - * Written by Jay Monkman - * - * COPYRIGHT (c) 1989-2012. - * On-Line Applications Research Corporation (OAR). - * - * The license and distribution terms for this file may be - * found in the file LICENSE in this distribution or at - * http://www.rtems.org/license/LICENSE. - */ - - -#include - -#include -#include -#include -#include -#include - -static const char *const cause_strings[32] = { - /* 0 */ "Int", - /* 1 */ "TLB Mods", - /* 2 */ "TLB Load", - /* 3 */ "TLB Store", - /* 4 */ "Address Load", - /* 5 */ "Address Store", - /* 6 */ "Instruction Bus Error", - /* 7 */ "Data Bus Error", - /* 8 */ "Syscall", - /* 9 */ "Breakpoint", - /* 10 */ "Reserved Instruction", - /* 11 */ "Coprocessor Unuseable", - /* 12 */ "Overflow", - /* 13 */ "Trap", - /* 14 */ "Instruction Virtual Coherency Error", - /* 15 */ "FP Exception", - /* 16 */ "Reserved 16", - /* 17 */ "Reserved 17", - /* 18 */ "Reserved 18", - /* 19 */ "Reserved 19", - /* 20 */ "Reserved 20", - /* 21 */ "Reserved 21", - /* 22 */ "Reserved 22", - /* 23 */ "Watch", - /* 24 */ "Reserved 24", - /* 25 */ "Reserved 25", - /* 26 */ "Reserved 26", - /* 27 */ "Reserved 27", - /* 28 */ "Reserved 28", - /* 29 */ "Reserved 29", - /* 30 */ "Reserved 30", - /* 31 */ "Data Virtual Coherency Error" -}; - -static inline bool bsp_irq_is_valid(rtems_vector_number vector) -{ - return vector <= BSP_INTERRUPT_VECTOR_MAX; -} - -void bsp_interrupt_vector_enable(rtems_vector_number vector) -{ - bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector)); -} - -void bsp_interrupt_vector_disable(rtems_vector_number vector) -{ - bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector)); -} - -rtems_status_code bsp_interrupt_facility_initialize(void) -{ - mips_install_isr_entries(); - return RTEMS_SUCCESSFUL; -} - -void bsp_interrupt_handler_default(rtems_vector_number vector) -{ - uint32_t sr; - uint32_t cause; - - mips_get_sr( sr ); - mips_get_cause( cause ); - - printk( "Unhandled exception %" PRId32 "\n", vector ); - printk( "sr: 0x%08" PRIu32 " cause: 0x%08" PRIu32 " --> %s\n", sr, cause, - cause_strings[(cause >> 2) &0x1f] ); - #if 0 - mips_dump_exception_frame( frame ); - #endif - rtems_fatal_error_occurred(1); -} diff --git a/c/src/lib/libbsp/mips/shared/irq/vectorexceptions.c b/c/src/lib/libbsp/mips/shared/irq/vectorexceptions.c deleted file mode 100644 index cdfd94c136..0000000000 --- a/c/src/lib/libbsp/mips/shared/irq/vectorexceptions.c +++ /dev/null @@ -1,81 +0,0 @@ -/** - * @file - * - * Common Code for Vectoring MIPS Exceptions - * - * The actual decoding of the cause register and vector number assignment - * is CPU model specific. - */ - -/* - * COPYRIGHT (c) 1989-2012. - * On-Line Applications Research Corporation (OAR). - * - * The license and distribution terms for this file may be - * found in the file LICENSE in this distribution or at - * http://www.rtems.org/license/LICENSE. - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -struct regdef -{ - int offset; - char *name; -}; - -static const struct regdef dumpregs[]= { - { R_RA, "R_RA" }, { R_V0, "R_V0" }, { R_V1, "R_V1" }, - { R_A0, "R_A0" }, { R_A1, "R_A1" }, { R_A2, "R_A2" }, - { R_A3, "R_A3" }, { R_T0, "R_T0" }, { R_T1, "R_T1" }, - { R_T2, "R_T2" }, { R_T3, "R_T3" }, { R_T4, "R_T4" }, - { R_T5, "R_T5" }, { R_T6, "R_T6" }, { R_T7, "R_T7" }, - { R_T8, "R_T8" }, { R_MDLO, "R_MDLO" }, { R_MDHI, "R_MDHI" }, - { R_GP, "R_GP" }, { R_FP, "R_FP" }, { R_AT, "R_AT" }, - { R_EPC,"R_EPC"}, { -1, NULL } -}; - -void _CPU_Exception_frame_print( const CPU_Exception_frame *frame ) -{ - uint32_t *frame_u32; - int i, j; - - frame_u32 = (uint32_t *)frame; - for(i=0; dumpregs[i].offset > -1; i++) - { - printk(" %s", dumpregs[i].name); - for(j=0; j< 7-strlen(dumpregs[i].name); j++) printk(" "); -#if (__mips == 1 ) || (__mips == 32) - printk(" %08" PRIu32 "%c", - frame_u32[dumpregs[i].offset], (i%3) ? '\t' : '\n' ); -#elif __mips == 3 - printk(" %08" PRIu32 "", frame_u32[2 * dumpregs[i].offset + 1] ); - printk("%08" PRIu32 "%c", - frame_u32[2 * dumpregs[i].offset], (i%2) ? '\t' : '\n' ); -#endif - } - printk( "\n" ); -} - -/* - * There are constants defined for these but they should basically - * all be close to the same set. - */ - -void mips_vector_exceptions( CPU_Interrupt_frame *frame ) -{ - uint32_t cause; - uint32_t exc; - - mips_get_cause( cause ); - exc = (cause >> 2) & 0x1f; - - bsp_interrupt_handler_dispatch( exc ); -} diff --git a/c/src/lib/libbsp/or1k/generic_or1k/Makefile.am b/c/src/lib/libbsp/or1k/generic_or1k/Makefile.am index 629e72bdaf..d9e14c56ed 100644 --- a/c/src/lib/libbsp/or1k/generic_or1k/Makefile.am +++ b/c/src/lib/libbsp/or1k/generic_or1k/Makefile.am @@ -62,7 +62,7 @@ librtemsbsp_a_SOURCES +=../../../../../../bsps/or1k/generic_or1k/clock/clockdrv. # IRQ librtemsbsp_a_SOURCES += ../../../../../../bsps/shared/irq/irq-default-handler.c -librtemsbsp_a_SOURCES += irq/irq.c +librtemsbsp_a_SOURCES += ../../../../../../bsps/or1k/generic_or1k/irq/irq.c # Cache librtemsbsp_a_SOURCES += ../../../../../../bsps/or1k/shared/cache/cache.c diff --git a/c/src/lib/libbsp/or1k/generic_or1k/irq/irq.c b/c/src/lib/libbsp/or1k/generic_or1k/irq/irq.c deleted file mode 100644 index f9a7b6426d..0000000000 --- a/c/src/lib/libbsp/or1k/generic_or1k/irq/irq.c +++ /dev/null @@ -1,43 +0,0 @@ -/** - * @file - * - * @ingroup or1k_interrupt - * - * @brief Interrupt support. - */ - -/* - * Copyright (c) 2014 Hesham ALMatary - * - * The license and distribution terms for this file may be - * found in the file LICENSE in this distribution or at - * http://www.rtems.org/license/LICENSE. - */ - -#include -#include -#include - -/* Almost all of the jobs that the following functions should - * do are implemented in cpukit - */ - -void bsp_interrupt_handler_default(rtems_vector_number vector) -{ - printk("spurious interrupt: %" PRIdrtems_vector_number "\n", vector); -} - -rtems_status_code bsp_interrupt_facility_initialize() -{ - return 0; -} - -void bsp_interrupt_vector_enable(rtems_vector_number vector) -{ - bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector)); -} - -void bsp_interrupt_vector_disable(rtems_vector_number vector) -{ - bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector)); -} diff --git a/c/src/lib/libbsp/powerpc/beatnik/Makefile.am b/c/src/lib/libbsp/powerpc/beatnik/Makefile.am index a2910c7fbb..e5c57f8dc3 100644 --- a/c/src/lib/libbsp/powerpc/beatnik/Makefile.am +++ b/c/src/lib/libbsp/powerpc/beatnik/Makefile.am @@ -62,8 +62,8 @@ librtemsbsp_a_SOURCES += ../../../../../../bsps/powerpc/shared/console/uart.c librtemsbsp_a_SOURCES += ../../../../../../bsps/powerpc/shared/console/console.c #irq -librtemsbsp_a_SOURCES += irq/irq_init.c -librtemsbsp_a_SOURCES += irq/discovery_pic.c +librtemsbsp_a_SOURCES += ../../../../../../bsps/powerpc/beatnik/irq/irq_init.c +librtemsbsp_a_SOURCES += ../../../../../../bsps/powerpc/beatnik/irq/discovery_pic.c #marvell librtemsbsp_a_SOURCES += marvell/discovery.c diff --git a/c/src/lib/libbsp/powerpc/beatnik/irq/discovery_pic.c b/c/src/lib/libbsp/powerpc/beatnik/irq/discovery_pic.c deleted file mode 100644 index f77125c4a7..0000000000 --- a/c/src/lib/libbsp/powerpc/beatnik/irq/discovery_pic.c +++ /dev/null @@ -1,993 +0,0 @@ -/* Interrupt driver + dispatcher for the discovery host controller */ - -/* Author: T. Straumann, 2005-2007 - * - * Acknowledgements: - * Valuable information was obtained from the following drivers - * netbsd: (C) Allegro Networks Inc; Wasabi Systems Inc. - * linux: (C) MontaVista, Software, Inc; Chris Zankel, Mark A. Greer. - * rtems: (C) Brookhaven National Laboratory; K. Feng - * but this implementation is original work by the author. - */ - -/* - * 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 -#include - -/* dont change the order (main_lo, main_hi, gpp) which - * matches the interrupt numbers! - */ -#define MAIN_LO_IDX 0 -#define MAIN_HI_IDX 1 -#define GPP_IDX 2 -#define NUM_INTR_REGS 3 - - -#define SYNC() __asm__ volatile("sync") - -/* How many times should the ISR dispatcher check for - * pending interrupts until it decides that something's - * fishy (i.e., a user ISR fails to clear the interrupt - * source) - */ -#define MAX_SPIN_LOOPS 100 - -/* If FASTER is defined, a few obscure I/O statements found in the linux - * driver are removed - */ -#define FASTER - -/* Array helper */ -#define NumberOf(arr) (sizeof(arr)/sizeof((arr)[0])) - - -/* MVME6100 specific; re-define watchdog NMI pin to be a normal output - * so we have a way to raise an interrupt in software (GPP[26] is wired to - * GPP[6] on the MVME6100). - */ -#define MVME6100_IRQ_DEBUG 4 - -#define GPP_WIRED_OUT_BIT_6100 26 /* CAVEAT: this is bit 26 on the 6100 */ -#define GPP_WIRED_OUT_BIT_5500 24 /* CAVEAT: this is bit 24 on the 5500 */ -#define GPP_WIRED_IN_BIT 6 - -/* Ored mask of debugging features to enable */ -#define IRQ_DEBUG_BASIC 1 -/* This is _very_ lowlevel */ -#define IRQ_DEBUG_DISPATCHER 2 -/* Record maximal dispatching latency */ -#define IRQ_DEBUG_MAXLAT 8 /* PPC only */ - -#define IRQ_DEBUG (0 /*|(IRQ_DEBUG_BASIC)*/|(MVME6100_IRQ_DEBUG)|(IRQ_DEBUG_MAXLAT)) - -/********** - * Typedefs - **********/ - -/* Set of the three relevant cause registers */ -typedef volatile unsigned IrqMask[NUM_INTR_REGS]; - -#define REGP(x) ((volatile uint32_t *)(x)) - -/* Information we keep about the PIC */ -typedef struct _Mv64x60PicRec { - /* base address as seen from CPU */ - uintptr_t reg_base; - - /* addresses of 'cause' registers */ - volatile uint32_t *causes[NUM_INTR_REGS]; - - /* addresses of 'mask' registers */ - volatile uint32_t *masks[NUM_INTR_REGS]; - - /* masks for all priorities. If an - * interrupt source has priority X, - * its corresponding bit is set - * (enabled) in mcache[i] for all - * i < X and cleared for i >= X - */ - volatile IrqMask mcache[BSP_IRQ_MAX_PRIO+1]; - - /* Priority we're executing at. - * Thread-level is priority 0, - * ISRs range from 1..MAX_PRIO - */ - volatile rtems_irq_prio current_priority; -} Mv64x60PicRec, *Mv64x60Pic; - -/********** - * Globals - **********/ - - -/* Copy of the configuration */ -static rtems_irq_global_settings theConfig; -/* PIC description */ -static Mv64x60PicRec thePic; - -#if (IRQ_DEBUG) & MVME6100_IRQ_DEBUG -static unsigned long gpp_out_bit = 0; -#endif - -#if (IRQ_DEBUG) & IRQ_DEBUG_MAXLAT -unsigned long discovery_pic_max_dispatching_latency = 0; -#ifdef __PPC__ -static inline unsigned long mftb(void) -{ -unsigned long rval; - asm volatile("mftb %0":"=r"(rval)); - return rval; -} -#else -#define mftb() 0 -#endif -#endif - -/********** - * Functions - **********/ - -/* Debugging helper routines */ -static void pregs(volatile uint32_t **p) -{ -int i; - for (i=NUM_INTR_REGS-1; i>=0; i--) { - printk(" 0x%08x", ld_le32(p[i])); - printk( i ? " --":"\n"); - } -} - -static void pmsks(volatile IrqMask p) -{ -int i; - for (i=NUM_INTR_REGS-1; i>=0; i--) { - printk(" 0x%08x", p[i]); - printk( i ? " --":"\n"); - } -} - -static void discovery_dump_picregs(void) -{ - printk(" ..GPP_IRQ. -- ..MAIN_HI. -- ..MAIN_LO.\n"); - printk("Cause:"); pregs(thePic.causes); - printk("Mask: "); pregs(thePic.masks); -} - -/* Small inline helpers */ - -/* return 0 if this PIC is not 'responsible' for a given irq number - * we also 'ignore' the GPP summary bits - these must always remain - * enabled. - */ -static inline int -validIrqNo(rtems_irq_number irq) -{ - return - irq >= BSP_PCI_IRQ_LOWEST_OFFSET - && irq <= BSP_PCI_IRQ_MAX_OFFSET - && ! (IMH_GPP_SUM & (1<<(irq-32))); -} - -/* return 0 if a given priority is outside the valid range */ -static inline int -validPri(rtems_irq_prio pri) -{ - /* silence compiler warning about limited range of type; - * hope it never changes... - */ - return /* pri>=0 && */ pri <=BSP_IRQ_MAX_PRIO; -} - -/* Return position of the most significant bit that is set in 'x' */ -static inline int -__ilog2(unsigned x) -{ - asm volatile("cntlzw %0, %0":"=&r"(x):"0"(x)); - return 31-x; -} - -/* Convert irq number to cause register index - * (array of handles in the PicRec). - * ASSUMES: 'irq' within valid range. - */ -static inline unsigned -irqDiv32(unsigned irq) -{ - return (irq-BSP_PCI_IRQ_LOWEST_OFFSET)>>5; -} - -/* Convert irq number to cause/mask bit number. - * ASSUMES: 'irq' within valid range. - */ - -static inline unsigned -irqMod32(unsigned irq) -{ - return (irq-BSP_PCI_IRQ_LOWEST_OFFSET)&31; -} - -/* NON-ATOMICALLY set/clear bits in a MV64x60 register - * - * register contents at offset 'off' are ANDed with - * complement of the 'clr' mask and ORed with 'set' mask: - * - * *off = (*off & ~clr) | set - * - * ASSUMES: executed from IRQ-disabled section - */ -static inline void -gt_bitmod(unsigned off, unsigned set, unsigned clr) -{ - st_le32(REGP(thePic.reg_base + off), - (ld_le32(REGP(thePic.reg_base+off)) & ~clr) | set); -} - -static inline unsigned -gt_read(unsigned off) -{ - return ld_le32(REGP(thePic.reg_base + off)); -} - -static inline void -gt_write(unsigned off, unsigned val) -{ - st_le32(REGP(thePic.reg_base + off), val); -} - -/* Enable interrupt number 'irq' at the PIC. - * - * Checks for valid arguments but has no way of - * communicating violation; prints to console - * if illegal arguments are given. - * - * This routine may be called from ISR level. - * - * Algorithm: set corresponding bit in masks - * for all priorities lower than the - * target irq's priority and push - * mask for the currently executing - * priority out to the PIC. - */ - -void -BSP_enable_irq_at_pic(rtems_irq_number irq) -{ -unsigned i,j; -unsigned long flags; -volatile uint32_t *p; -uint32_t v,m; - - if ( !validIrqNo(irq) ) { -/* API change - must silently ignore... - printk("BSP_enable_irq_at_pic: Invalid argument (irq #%i)\n",irq); - */ - return; - } - -#if (IRQ_DEBUG) & IRQ_DEBUG_BASIC - printk("IRQ: Enable #%i;",irq); -#endif - - if ( (i=irqDiv32(irq)) > NUM_INTR_REGS ) { - /* This is probably a more serious error; don't ignore silently */ - printk("BSP_enable_irq_at_pic: illegal argument\n"); - return; - } - /* compute register pointer and bit mask */ - p = thePic.masks[i]; - m = 1< 0x%08x\n",i,v,ld_le32(p)); - -#endif -} - -/* Disable interrupt number 'irq' at the PIC. - * - * Checks for valid arguments but has no way of - * communicating violation; prints to console - * if illegal arguments are given. - * - * This routine may be called from ISR level. - * - * Algorithm: clear corresponding bit in masks - * for all priorities and push the - * mask for the currently executing - * priority out to the PIC. - */ - -int -BSP_disable_irq_at_pic(rtems_irq_number irq) -{ -unsigned i,j; -unsigned long flags; -volatile uint32_t *p; -uint32_t v,m; -int rval; - - if ( !validIrqNo(irq) ) { -/* API change - must silently ignore... - printk("BSP_disable_irq_at_pic: Invalid argument (irq #%i)\n",irq); - */ - return -1; - } - -#if (IRQ_DEBUG) & IRQ_DEBUG_BASIC - printk("IRQ: Disable #%i;",irq); -#endif - - if ( (i=irqDiv32(irq)) > NUM_INTR_REGS ) { - /* This is probably a more serious error; don't ignore silently */ - printk("BSP_enable_irq_at_pic: illegal argument\n"); - return -1; - } - - /* compute register pointer and bit mask */ - p = thePic.masks[i]; - m = (1< 0x%08x\n",i,v,ld_le32(p)); -#endif - - return rval ? 1 : 0; -} - -int -BSP_irq_is_enabled_at_pic(rtems_irq_number irq) -{ -unsigned i; - if ( !validIrqNo(irq) ) { - printk("BSP_irq_is_enabled_at_pic: Invalid argument (irq #%i)\n",irq); - return -1; - } - - if ( (i=irqDiv32(irq)) > NUM_INTR_REGS ) { - printk("BSP_enable_irq_at_pic: illegal argument\n"); - return -1; - } - return ld_le32(thePic.masks[i]) & (1<=pri - */ -int -BSP_irq_set_priority(rtems_irq_number irq, rtems_irq_prio pri) -{ -unsigned long flags; -volatile uint32_t *p; -uint32_t v,m; -unsigned i,j; - - if ( thePic.current_priority > 0 ) { - printk("BSP_irq_set_priority: must not be called from ISR level\n"); - return -1; - } - - if ( !validPri(pri) ) { - printk("BSP_irq_set_priority: invalid argument (pri #%i)\n",pri); - return -1; - } - - if ( BSP_DECREMENTER != irq ) { - if ( !validIrqNo(irq) ) { - printk("BSP_irq_set_priority: invalid argument (irq #%i)\n",irq); - return -1; - } - - if ( (i=irqDiv32(irq)) > NUM_INTR_REGS ) { - printk("BSP_irq_set_priority: illegal argument (irq #%i not PCI?)\n", irq); - return -1; - } - } - -#if (IRQ_DEBUG) & IRQ_DEBUG_BASIC - printk("IRQ: Set Priority #%i -> %i;",irq,pri); -#endif - - if ( BSP_DECREMENTER == irq ) { - theConfig.irqPrioTbl[irq] = pri; - return 0; - } - - /* compute register pointer and bit mask */ - p = thePic.masks[i]; - m = 1< 0x%08x\n",i,v,ld_le32(p)); -#endif - - return 0; -} - -/* Initialize the PIC; routine needed by BSP framework - * - * RETURNS: NONZERO on SUCCESS, 0 on error! - */ -int -BSP_setup_the_pic(rtems_irq_global_settings* config) -{ -int i; - /* - * Store copy of configuration - */ - theConfig = *config; - - /* check config */ - if ( theConfig.irqNb <= BSP_PCI_IRQ_MAX_OFFSET ) { - printk("BSP_setup_the_pic: FATAL ERROR: configured IRQ table too small???\n"); - return 0; - } - - for ( i=0; i highest priority source is found quickly. It takes at most - * - * BSP_IRQ_MAX_PRIO * ( ~3 reg-only instructions + 2 memory access ) - * + 2 reg-only instructions + 1 I/O + 1 memory access. - * - * - */ - -static unsigned mlc, mhc, gpc; - -static int decrementerPending = 0; -#if (IRQ_DEBUG) & IRQ_DEBUG_DISPATCHER -int decrementerIrqs = 0; -#endif - -static inline unsigned -find_highest_priority_pending_irq(rtems_irq_prio *ppri) -{ -register int rval = -1; -register rtems_irq_prio *pt = theConfig.irqPrioTbl + BSP_PCI_IRQ_LOWEST_OFFSET; -register rtems_irq_prio pmax = *ppri; -register unsigned cse,ocse; - -#if (IRQ_DEBUG) & IRQ_DEBUG_DISPATCHER - discovery_dump_picregs(); -#endif - - if ( decrementerPending ) { -/* Don't flood -#if (IRQ_DEBUG) & IRQ_DEBUG_DISPATCHER - printk("Decrementer IRQ pending\n"); -#endif -*/ - if ( theConfig.irqPrioTbl[BSP_DECREMENTER] > pmax ) { - pmax = theConfig.irqPrioTbl[BSP_DECREMENTER]; - rval = BSP_DECREMENTER; - } - } - - mlc = cse = ld_le32(thePic.causes[MAIN_LO_IDX]); -#if (IRQ_DEBUG) & IRQ_DEBUG_DISPATCHER - printk("MAIN_LO; cse: 0x%08x, msk 0x%08x\n", cse ,thePic.mcache[pmax][MAIN_LO_IDX]); -#endif - while ( cse &= thePic.mcache[pmax][MAIN_LO_IDX] ) { - rval = __ilog2(cse); - pmax = pt[rval]; -#if (IRQ_DEBUG) & IRQ_DEBUG_DISPATCHER - printk("Max pri IRQ now %i\n",rval); -#endif - } - mhc = cse = ocse = ld_le32(thePic.causes[MAIN_HI_IDX]); -#if (IRQ_DEBUG) & IRQ_DEBUG_DISPATCHER - printk("MAIN_HI; cse: 0x%08x, msk 0x%08x\n", cse, thePic.mcache[pmax][MAIN_HI_IDX]); -#endif - /* don't look at the GPP summary; only check for 'real' MAIN_HI sources */ - cse &= ~IMH_GPP_SUM; - while ( cse &= thePic.mcache[pmax][MAIN_HI_IDX] ) { - rval = __ilog2(cse) + 32; - pmax = pt[rval]; -#if (IRQ_DEBUG) & IRQ_DEBUG_DISPATCHER - printk("Max pri IRQ now %i\n",rval); -#endif - } - gpc = cse = ld_le32(thePic.causes[GPP_IDX ]); - /* if there were GPP ints, scan the GPP cause now */ - if ( ocse & IMH_GPP_SUM ) { -#if (IRQ_DEBUG) & IRQ_DEBUG_DISPATCHER - printk("GPP; cse: 0x%08x, msk 0x%08x\n", cse, thePic.mcache[pmax][GPP_IDX ]); -#endif - cse &= thePic.mcache[pmax][GPP_IDX ]; - ocse = cse; - while ( cse ) { - rval = __ilog2(cse) + 64; - pmax = pt[rval]; - cse &= thePic.mcache[pmax][GPP_IDX ]; -#if (IRQ_DEBUG) & IRQ_DEBUG_DISPATCHER - printk("Max pri IRQ now %i\n",rval); -#endif - } -#ifndef FASTER - /* this doesn't seem to be necessary -- however, the linux people do it... */ - out_le32(thePic.causes[GPP_IDX], ~ocse); -#endif - } -#ifndef FASTER - /* this doesn't seem to be necessary -- however, the linux people do it... */ - (void)in_le32(thePic.causes[GPP_IDX]); -#endif - - *ppri = pmax; - - if ( BSP_DECREMENTER == rval ) { -#if (IRQ_DEBUG) & IRQ_DEBUG_DISPATCHER - decrementerIrqs++; -#endif - decrementerPending = 0; - } - - return rval; -} - -#if 0 /* TODO: should this be cleaned up ? */ -#define _IRQ_DEBUG IRQ_DEBUG_DISPATCHER -static inline unsigned -ffind_highest_priority_pending_irq(rtems_irq_prio *ppri) -{ -register int rval = -1; -register rtems_irq_prio *pt = theConfig.irqPrioTbl + BSP_PCI_IRQ_LOWEST_OFFSET; -register rtems_irq_prio pmax = *ppri; -register unsigned cse,ocse; - -#if (_IRQ_DEBUG) & IRQ_DEBUG_DISPATCHER - discovery_dump_picregs(); -#endif - - cse = in_le32(thePic.causes[MAIN_LO_IDX]); -#if (_IRQ_DEBUG) & IRQ_DEBUG_DISPATCHER - printk("MAIN_LO; cse: 0x%08x, msk 0x%08x\n", cse ,thePic.mcache[pmax][MAIN_LO_IDX]); -#endif - while ( cse &= thePic.mcache[pmax][MAIN_LO_IDX] ) { - rval = __ilog2(cse); - pmax = pt[rval]; -#if (_IRQ_DEBUG) & IRQ_DEBUG_DISPATCHER - printk("Max pri IRQ now %i\n",rval); -#endif - } - cse = ocse = in_le32(thePic.causes[MAIN_HI_IDX]); -#if (_IRQ_DEBUG) & IRQ_DEBUG_DISPATCHER - printk("MAIN_HI; cse: 0x%08x, msk 0x%08x\n", cse, thePic.mcache[pmax][MAIN_HI_IDX]); -#endif - /* don't look at the GPP summary; only check for 'real' MAIN_HI sources */ - cse &= ~IMH_GPP_SUM; - while ( cse &= thePic.mcache[pmax][MAIN_HI_IDX] ) { - rval = __ilog2(cse) + 32; - pmax = pt[rval]; -#if (_IRQ_DEBUG) & IRQ_DEBUG_DISPATCHER - printk("Max pri IRQ now %i\n",rval); -#endif - } - /* if there were GPP ints, scan the GPP cause now */ - if ( ocse & IMH_GPP_SUM ) { - cse = in_le32(thePic.causes[GPP_IDX ]); -#if (_IRQ_DEBUG) & IRQ_DEBUG_DISPATCHER - printk("GPP; cse: 0x%08x, msk 0x%08x\n", cse, thePic.mcache[pmax][GPP_IDX ]); -#endif - cse &= thePic.mcache[pmax][GPP_IDX ]; - ocse = cse; - while ( cse ) { - rval = __ilog2(cse) + 64; - pmax = pt[rval]; - cse &= thePic.mcache[pmax][GPP_IDX ]; -#if (_IRQ_DEBUG) & IRQ_DEBUG_DISPATCHER - printk("Max pri IRQ now %i\n",rval); -#endif - } - /* this doesn't seem to be necessary -- however, the linux people do it... */ - out_le32(thePic.causes[GPP_IDX], ~ocse); - } - /* this doesn't seem to be necessary -- however, the linux people do it... */ - (void)in_le32(thePic.causes[GPP_IDX]); - - *ppri = pmax; - return rval; -} -#endif - - -/* Here's our dispatcher; the BSP framework uses the same one for EE and decrementer - * exceptions... - */ -int C_dispatch_irq_handler (BSP_Exception_frame *frame, unsigned int excNum) -{ -register int irq; -int loop, last_irq; -rtems_irq_prio pri; -#if (IRQ_DEBUG) & IRQ_DEBUG_MAXLAT -unsigned long diff; -#endif - -#if (IRQ_DEBUG) & IRQ_DEBUG_MAXLAT - diff = mftb(); -#endif - - if (excNum == ASM_DEC_VECTOR) { - decrementerPending = 1; - } - - /* Tradeoff: EITHER we loop as long as interrupts are pending - * incurring the overhead of one extra run of the 'find_pending_irq' routine. - * OR we do rely on the handler just being invoked again if multiple - * interrupts are pending. - * - * The first solution gives better worst-case behavior - * the second slightly better average performance. - * --> we go for the first solution. This also enables us to catch - * runaway interrupts, i.e., bad drivers that don't clear interrupts - * at the device. Can be very handy during driver development... - */ - for ( loop=0, last_irq=-1, pri = thePic.current_priority; - (irq=find_highest_priority_pending_irq(&pri)) >=0; - loop++, last_irq = irq ) { - - /* raise priority level and remember current one */ - pri = change_executing_prio_level(pri); - - SYNC(); - -#if (IRQ_DEBUG) & IRQ_DEBUG_MAXLAT - if ( 0 == loop ) { - diff = mftb()-diff; - if ( diff > discovery_pic_max_dispatching_latency ) - discovery_pic_max_dispatching_latency = diff; - } -#endif - -#if (IRQ_DEBUG) & IRQ_DEBUG_DISPATCHER - if ( BSP_DECREMENTER == irq ) { - printk("IRQ: dispatching DECREMENTER\n"); - } else { - int idx = irqDiv32(irq); - printk("IRQ: dispatching #%i; causes[%i]=0x%08x\n", irq, idx, ld_le32(thePic.causes[idx])); - } -#endif - - bsp_irq_dispatch_list( theConfig.irqHdlTbl, irq, theConfig.defaultEntry.hdl ); - - /* restore executing priority level */ - (void)change_executing_prio_level(pri); - - if ( (loop > MAX_SPIN_LOOPS) && (last_irq == irq) ) { - /* try to catch run-away interrupts without disabling a 'legal' one; - * this should never happen with the decrementer (and - * BSP_disable_irq_at_pic(BSP_DECREMENTER) would fail) - */ - printk("Runaway IRQ #%i; disabling\n", irq); - BSP_disable_irq_at_pic(irq); - loop = 0; - } - } - - if (!loop) { - if ( decrementerPending && pri >= theConfig.irqPrioTbl[BSP_DECREMENTER] ) { - /* we cannot mask the decrementer interrupt so it is possible that it - * gets delivered even though it has a lower priority than what we're - * currently executing at. - * In this case, we ignore the zero loop count and return; - * the interrupted instance of C_dispatch_irq_handler() will eventually - * lower the executing priority and catch the 'decrementerPending' flag - * we just set. - */ - } else { - printk("Discovery: Spurious interrupt; causes were gpp: 0x%x, mhc: 0x%x, mlc: 0x%x\n", gpc, mhc, mlc); - printk("Current priority level %i, decrementerPending %i\n", pri, decrementerPending); - { - rtems_irq_prio p=pri; - printk("PIC register dump:\n"); - discovery_dump_picregs(); - printk("Current Priority: %i, found %i\n",pri,find_highest_priority_pending_irq(&p)); - discovery_dump_picregs(); - for (p=0; p<=BSP_IRQ_MAX_PRIO; p++) { - printk("M[%i] :",p);pmsks(thePic.mcache[p]); - } - } - } - } - else if (loop>discovery_pic_max_loops) - discovery_pic_max_loops = loop; - - return 0; -} - - -#if (IRQ_DEBUG) & MVME6100_IRQ_DEBUG -void -discovery_pic_install_debug_irq(void) -{ - switch ( BSP_getBoardType() ) { - case MVME6100: gpp_out_bit = GPP_WIRED_OUT_BIT_6100; break; - case MVME5500: gpp_out_bit = GPP_WIRED_OUT_BIT_5500; break; - default: - gpp_out_bit = 0; break; - break; - } - if ( gpp_out_bit ) { - unsigned mppoff; - switch (gpp_out_bit / 8) { - default: /* silence warning; this is never reached */ - case 0: mppoff = GT_MPP_Control0; break; - case 1: mppoff = GT_MPP_Control1; break; - case 2: mppoff = GT_MPP_Control2; break; - case 3: mppoff = GT_MPP_Control3; break; - } - - /* switch GPP pin allocated to watchdog (value 4) to - * GPP I/O (value 0 ??; have no doc, found out by experimenting) - */ - gt_bitmod(mppoff, 0, (0xf<<(4*(gpp_out_bit % 8)))); - - /* make it an output */ - gt_bitmod(GT_GPP_IO_Control, (1< GPP_WIRED_IN pins - */ -void -discovery_pic_set_debug_irq(int on) -{ -unsigned long flags, clr; - if ( !gpp_out_bit ) { - printk("discovery_pic_set_debug_irq(): unknown wire output\n"); - return; - } - if (on) { - on = 1< - * to make it valid for MVME2300 Motorola boards. - * - * Modified by T. Straumann for the 'beatnik' BSP. - * - * The license and distribution terms for this file may be - * found in the file LICENSE in this distribution or at - * http://www.rtems.org/license/LICENSE. - */ - -#include -#include -#include -#include -#include - -#if 0 -#include -#include -#include -#include -#include -#include -#include -#include -#endif - -/* -#define SHOW_ISA_PCI_BRIDGE_SETTINGS -*/ - -extern unsigned int external_exception_vector_prolog_code_size[]; -extern void external_exception_vector_prolog_code(void); -extern unsigned int decrementer_exception_vector_prolog_code_size[]; -extern void decrementer_exception_vector_prolog_code(void); - -/* - * default handler - */ -static void nop_func(void *arg){} - -static rtems_irq_connect_data rtemsIrq[BSP_IRQ_NUMBER]; -static rtems_irq_global_settings initial_config; -static rtems_irq_prio rtemsPrioTbl[BSP_IRQ_NUMBER]; -static rtems_irq_connect_data defaultIrq = { - name: 0, - hdl: nop_func, - handle: 0, - on: 0, - off: 0, - isOn: 0 -}; - - - /* - * This code assumes the exceptions management setup has already - * been done. We just need to replace the exceptions that will - * be handled like interrupt. On mcp750/mpc750 and many PPC processors - * this means the decrementer exception and the external exception. - */ - -void BSP_rtems_irq_mng_init(unsigned cpuId) -{ -int i; - - /* - * First initialize the Interrupt management hardware - */ - - /* - * Initialize Rtems management interrupt table - */ - - /* - * re-init the rtemsIrq table - */ - for (i = BSP_LOWEST_OFFSET; i <= BSP_MAX_OFFSET; i++) { - rtemsIrq[i] = defaultIrq; - rtemsIrq[i].name = i; - rtemsPrioTbl[i] = BSP_IRQ_DEFAULT_PRIORITY; - } - - /* - * Init initial Interrupt management config - */ - initial_config.irqNb = BSP_IRQ_NUMBER; - initial_config.defaultEntry = defaultIrq; - initial_config.irqHdlTbl = rtemsIrq; - initial_config.irqBase = BSP_LOWEST_OFFSET; - initial_config.irqPrioTbl = rtemsPrioTbl; - - if (!BSP_rtems_irq_mngt_set(&initial_config)) { - /* - * put something here that will show the failure... - */ - rtems_panic("Unable to initialize RTEMS interrupt Management!!! System locked\n"); - } - -#ifdef TRACE_IRQ_INIT - printk("RTEMS IRQ management is now operationnal\n"); -#endif -} - diff --git a/c/src/lib/libbsp/powerpc/beatnik/irq/irq_test_app.c b/c/src/lib/libbsp/powerpc/beatnik/irq/irq_test_app.c deleted file mode 100644 index cb9ff146ad..0000000000 --- a/c/src/lib/libbsp/powerpc/beatnik/irq/irq_test_app.c +++ /dev/null @@ -1,164 +0,0 @@ -/* Init - * - * This routine is the initialization task for this test program. - * It is called from init_exec and has the responsibility for creating - * and starting the tasks that make up the test. If the time of day - * clock is required for the test, it should also be set to a known - * value by this function. - * - * Input parameters: NONE - * - * Output parameters: NONE - * - * COPYRIGHT (c) 1989-1999. - * On-Line Applications Research Corporation (OAR). - * - * The license and distribution terms for this file may be - * found in the file LICENSE in this distribution or at - * http://www.rtems.org/license/LICENSE. - * - * OAR init.c Template modified by T. Straumann who provided - * the implementation of this application. - */ - -#define CONFIGURE_INIT - -#include - -/* functions */ -rtems_task Init( - rtems_task_argument argument -); - -/* configuration information */ -#include /* for device driver prototypes */ -#define CONFIGURE_APPLICATION_NEEDS_CONSOLE_DRIVER -#define CONFIGURE_APPLICATION_NEEDS_CLOCK_DRIVER -#define CONFIGURE_MAXIMUM_TASKS 1 -#define CONFIGURE_RTEMS_INIT_TASKS_TABLE -#include - -#include -#include - -#include -#include - - -void noop(){} -int connected() {return 1;} - -rtems_irq_connect_data blah = { 0, 0, noop, noop, connected }; -extern void discovery_pic_set_debug_irq(); - -#define WIRE_IRQ (BSP_IRQ_GPP_0 + 6) -#define ABRT_IRQ (BSP_IRQ_GPP_0 + 2) - -static volatile int testno=0; -static volatile int wloops =0; -static volatile int aloops =0; - -void wire_hdl() -{ - if ( 1 == testno ) { - BSP_disable_irq_at_pic(WIRE_IRQ); - } - - if ( 2 == testno || 3 == testno ) { - discovery_pic_set_debug_irq(0); - printk("WIRE -- this message should be printed %s\n", 3==testno ? "FIRST":"SECOND"); - } else { - } - - /* assume the driver checks for less than 1000 loops */ - if ( ++wloops > 1000) { - printk("wire IRQ. FAILURE -- driver couldn't catch runaway ISR. Disabling IRQ source.\n"); - discovery_pic_set_debug_irq(0); - BSP_disable_irq_at_pic(WIRE_IRQ); - } - /* - */ -} - -void abrt_hdl() -{ - aloops++; - if ( 2 == testno || 3 == testno ) { - discovery_pic_set_debug_irq(1); - printk("ABRT -- this message should be printed %s\n", 2==testno ? "FIRST":"SECOND"); - } else - printk("ABRT IRQ\n"); - - if ( 1== testno ) { - BSP_enable_irq_at_pic(WIRE_IRQ); - } - BSP_disable_irq_at_pic(ABRT_IRQ); -} - - -rtems_task Init( - rtems_task_argument ignored -) -{ - blah.name = WIRE_IRQ; - blah.hdl = wire_hdl; - if (!BSP_install_rtems_irq_handler(&blah)) { - fprintf(stderr,"installing handler 1 failed\n"); - } - blah.name = ABRT_IRQ; - blah.hdl = abrt_hdl; - if (!BSP_install_rtems_irq_handler(&blah)) { - fprintf(stderr,"installing handler 2 failed\n"); - } - printf("Hello, testing the ISR dispatcher...\n"); - printf(" 1. Trying to catch runaway interrupt\n"); - printf(" If the system freezes, the test failed!\n"); - fflush(stdout); sleep(1); - aloops = wloops = 0; - discovery_pic_set_debug_irq(1); - printf(" >>> %s\n", wloops<1000 ? "SUCCESS" : "FAILED"); - discovery_pic_set_debug_irq(0); - - testno++; - printf(" 2. Testing enabling / disabling interrupt from ISR\n"); - printf(" Hit the ABORT key for this test\n"); - fflush(stdout); sleep(1); - aloops = wloops = 0; - BSP_disable_irq_at_pic(WIRE_IRQ); - BSP_irq_set_priority(ABRT_IRQ,1); - BSP_enable_irq_at_pic(ABRT_IRQ); - discovery_pic_set_debug_irq(1); - while (!aloops) - ; - discovery_pic_set_debug_irq(0); - sleep(2); - printf(" >>> disabling ABRT IRQ from isr %s\n", 1==aloops ? "SUCCESS":"FAILURE"); - printf(" flashing WIRE IRQ from isr %s\n", 1==wloops ? "SUCCESS":"FAILURE"); - - - testno++; - printf(" 3. Testing interrupt priorities\n"); - BSP_irq_set_priority(ABRT_IRQ,2); - BSP_irq_set_priority(WIRE_IRQ,2); - BSP_enable_irq_at_pic(ABRT_IRQ); - BSP_enable_irq_at_pic(WIRE_IRQ); - printf(" Hit the ABORT key for this test\n"); - fflush(stdout); sleep(1); - aloops = wloops = 0; - while (!aloops) - ; - sleep(2); - testno++; - printf(" Now we are raising the priority of the wire interrupt\n"); - BSP_irq_set_priority(WIRE_IRQ,3); - BSP_enable_irq_at_pic(ABRT_IRQ); - printf(" Hit the ABORT key for this test\n"); - fflush(stdout); sleep(1); - aloops = wloops = 0; - while (!aloops) - ; - - sleep(2); - printf( "That's it; we're done...\n" ); - exit( 0 ); -} diff --git a/c/src/lib/libbsp/powerpc/gen5200/Makefile.am b/c/src/lib/libbsp/powerpc/gen5200/Makefile.am index afa2c53b00..66c7379c36 100644 --- a/c/src/lib/libbsp/powerpc/gen5200/Makefile.am +++ b/c/src/lib/libbsp/powerpc/gen5200/Makefile.am @@ -69,7 +69,7 @@ librtemsbsp_a_SOURCES += ide/ata-instance.c librtemsbsp_a_SOURCES += ide/ata-dma-pio-single.c # irq -librtemsbsp_a_SOURCES += irq/irq.c +librtemsbsp_a_SOURCES += ../../../../../../bsps/powerpc/gen5200/irq/irq.c # mscan librtemsbsp_a_SOURCES += mscan/mscan.c diff --git a/c/src/lib/libbsp/powerpc/gen5200/irq/irq.c b/c/src/lib/libbsp/powerpc/gen5200/irq/irq.c deleted file mode 100644 index 11d9e3992e..0000000000 --- a/c/src/lib/libbsp/powerpc/gen5200/irq/irq.c +++ /dev/null @@ -1,722 +0,0 @@ -/*===============================================================*\ -| Project: RTEMS generic MPC5200 BSP | -+-----------------------------------------------------------------+ -| Partially based on the code references which are named below. | -| Adaptions, modifications, enhancements and any recent parts of | -| the code are: | -| Copyright (c) 2005 | -| Embedded Brains GmbH | -| Obere Lagerstr. 30 | -| D-82178 Puchheim | -| Germany | -| rtems@embedded-brains.de | -+-----------------------------------------------------------------+ -| The license and distribution terms for this file may be | -| found in the file LICENSE in this distribution or at | -| | -| http://www.rtems.org/license/LICENSE. | -| | -+-----------------------------------------------------------------+ -| this file contains the irq controller handler | -\*===============================================================*/ -/***********************************************************************/ -/* */ -/* Module: irq.c */ -/* Date: 07/17/2003 */ -/* Purpose: RTEMS MPC5x00 CPU main interrupt handler & routines */ -/* */ -/*---------------------------------------------------------------------*/ -/* */ -/* Description: This file contains the implementation of the */ -/* functions described in irq.h */ -/* */ -/*---------------------------------------------------------------------*/ -/* */ -/* Code */ -/* References: MPC8260ads main interrupt handler & routines */ -/* Module: irc.c */ -/* Project: RTEMS 4.6.0pre1 / MCF8260ads BSP */ -/* Version 1.2 */ -/* Date: 04/18/2002 */ -/* */ -/* Author(s) / Copyright(s): */ -/* */ -/* Copyright (C) 1998, 1999 valette@crf.canon.fr */ -/* */ -/* Modified for mpc8260 Andy Dachs */ -/* Surrey Satellite Technology Limited, 2000 */ -/* Nested exception handlers not working yet. */ -/* */ -/* The license and distribution terms for this file may be */ -/* found in the file LICENSE in this distribution or at */ -/* http://www.rtems.org/license/LICENSE. */ -/* */ -/*---------------------------------------------------------------------*/ -/* */ -/* Partially based on the code references which are named above. */ -/* Adaptions, modifications, enhancements and any recent parts of */ -/* the code are under the right of */ -/* */ -/* IPR Engineering, Dachauer Straße 38, D-80335 München */ -/* Copyright(C) 2003 */ -/* */ -/*---------------------------------------------------------------------*/ -/* */ -/* IPR Engineering makes no representation or warranties with */ -/* respect to the performance of this computer program, and */ -/* specifically disclaims any responsibility for any damages, */ -/* special or consequential, connected with the use of this program. */ -/* */ -/*---------------------------------------------------------------------*/ -/* */ -/* Version history: 1.0 */ -/* */ -/***********************************************************************/ - -#include - -#include - -#include -#include - -#include -#include -#include -#include - -/* - * bit in the SIU mask registers (PPC bit numbering) that should - * be set to enable the relevant interrupt, mask of 32 is for unused entries - * - */ -const static unsigned int SIU_MaskBit [BSP_SIU_IRQ_NUMBER] = { - 0, 1, 2, 3, /* smart_comm, psc1, psc2, psc3 */ - 4, 5, 6, 7, /* irda/psc6, eth, usb, ata */ - 8, 9, 10, 11, /* pci_ctrl, pci_sc_rx, pci_sc_tx, psc4 */ - 12, 13, 14, 15, /* psc5,spi_modf, spi_spif, i2c1 */ - 16, 17, 18, 19, /* i2c, can1, can2, ir_rx */ - 20, 21, 15, 16, /* ir_rx, xlb_arb, slice_tim2, irq1, */ - 17, 18, 19, 20, /* irq2, irq3, lo_int, rtc_pint */ - 21, 22, 23, 24, /* rtc_sint, gpio_std, gpio_wkup, tmr0 */ - 25, 26, 27, 28, /* tmr1, tmr2, tmr3, tmr4 */ - 29, 30, 31, 32, /* tmr5, tmr6, tmr7, res */ - 32, 32, 32 /* res, res, res */ -}; - -static unsigned char irqPrioTable [BSP_SIU_IRQ_NUMBER] = { -/* per. int. priorities (0-7) / 4bit coding / msb is HI/LO selection */ -/* msb = 0 -> non-critical per. int. is routed to main int. (LO_int) */ -/* msb = 1 -> critical per. int. is routed to critical int. (HI_int) */ - 0xF, 0, 0, 0, /* smart_comm (do not change!), psc1, psc2, psc3 */ - 0, 0, 0, 0, /* irda, eth, usb, ata */ - 0, 0, 0, 0, /* pci_ctrl, pci_sc_rx, pci_sc_tx, res */ - 0, 0, 0, 0, /* res, spi_modf, spi_spif, i2c1 */ - 0, 0, 0, 0, /* i2c, can1, can2, ir_rx */ - 0, 0, /* ir_rx, xlb_arb */ -/* main interrupt priorities (0-7) / 4bit coding / msb is INT/SMI selection */ -/* msb = 0 -> main int. is routed to processor INT (low vector base 0x500 ) */ -/* msb = 1 -> main int. is routed to processor SMI (low vector base 0x1400 ) */ - 0, 0, /* slice_tim2, irq1 */ - 0, 0, 0, 0, /* irq2, irq3, lo_int, rtc_pint */ - 0, 0, 0, 0, /* rtc_sint, gpio_std, gpio_wkup, tmr0 */ - 0, 0, 0, 0, /* tmr1, tmr2, tmr3, tmr4 */ - 0, 0, 0, /* tmr5, tmr6, tmr7 */ - /* critical interrupt priorities (0-3) / 2bit coding / no special purpose of msb */ - 0, /* irq0 */ - 0, 0, 0 /* slice_tim1, hi_int, ccs_wkup */ -}; - -static uint32_t irqMaskTable [BSP_PER_IRQ_NUMBER + BSP_MAIN_IRQ_NUMBER]; - -/* - * Check if symbolic IRQ name is a Processor IRQ - */ -static inline bool is_processor_irq( rtems_vector_number irqLine) -{ - - return ((irqLine <= BSP_PROCESSOR_IRQ_MAX_OFFSET) - && (irqLine >= BSP_PROCESSOR_IRQ_LOWEST_OFFSET)); -} - -/* - * Check for SIU IRQ and return base index - */ -static inline bool is_siu_irq( rtems_vector_number irqLine) -{ - - return ((irqLine <= BSP_SIU_IRQ_MAX_OFFSET) - && (irqLine >= BSP_SIU_IRQ_LOWEST_OFFSET)); -} - -/* - * Check for SIU IRQ and return base index - */ -static inline int get_siu_irq_base_index( rtems_vector_number irqLine) -{ - if (irqLine <= BSP_PER_IRQ_MAX_OFFSET) - return BSP_PER_IRQ_LOWEST_OFFSET; - - if (irqLine <= BSP_MAIN_IRQ_MAX_OFFSET) - return BSP_MAIN_IRQ_LOWEST_OFFSET; - - if (irqLine <= BSP_CRIT_IRQ_MAX_OFFSET) - return BSP_CRIT_IRQ_LOWEST_OFFSET; - - return -1; -} - -static inline void BSP_enable_per_irq_at_siu( - rtems_vector_number irqLine -) -{ - uint8_t lo_hi_ind = 0, - prio_index_offset; - uint32_t *reg; - - /* calculate the index offset of priority value bit field */ - prio_index_offset = (irqLine - BSP_PER_IRQ_LOWEST_OFFSET) % 8; - - /* set interrupt priorities */ - if (irqPrioTable [irqLine] <= 15) { - - /* set peripheral int priority */ - reg = (uint32_t *) (&(mpc5200.per_pri_1)); - - /* choose proper register */ - reg += (irqLine >> 3); - - /* set priority as given in priority table */ - *reg |= (irqPrioTable [irqLine] << (28 - (prio_index_offset << 2))); - - /* test msb (hash-bit) and set LO_/HI_int indicator */ - if ((lo_hi_ind = (irqPrioTable [irqLine] >> 3))) { - - /* set critical HI_int priority */ - reg = (uint32_t *) (&(mpc5200.crit_pri_main_mask)); - *reg |= (irqPrioTable [BSP_SIU_IRQ_HI_INT] << 26); - - /* - * critical interrupt handling for the 603le core is not - * yet supported, routing of critical interrupts is forced - * to core_int (bit 31 / CEb) - */ - mpc5200.ext_en_type |= 1; - - } else { - if (irqPrioTable [irqLine] <= 15) { - /* set main LO_int priority */ - reg = (uint32_t *) (&(mpc5200.main_pri_1)); - *reg |= (irqPrioTable [BSP_SIU_IRQ_LO_INT] << 16); - } - } - } - - /* if LO_int ind., enable (unmask) main interrupt */ - if (!lo_hi_ind) { - mpc5200.crit_pri_main_mask &= - ~(0x80000000 >> SIU_MaskBit [BSP_SIU_IRQ_LO_INT]); - } - - /* enable (unmask) peripheral interrupt */ - mpc5200.per_mask &= ~(0x80000000 >> SIU_MaskBit [irqLine]); - - /* FIXME: Why? */ - mpc5200.main_pri_1; - mpc5200.crit_pri_main_mask; - mpc5200.per_pri_1; - mpc5200.per_mask; -} - -static inline void BSP_enable_main_irq_at_siu( - rtems_vector_number irqLine -) -{ - - uint8_t prio_index_offset; - uint32_t *reg; - - /* calculate the index offset of priority value bit field */ - prio_index_offset = (irqLine - BSP_MAIN_IRQ_LOWEST_OFFSET) % 8; - - /* set main interrupt priority */ - if (irqPrioTable [irqLine] <= 15) { - - /* set main int priority */ - reg = (uint32_t *) (&(mpc5200.main_pri_1)); - - /* choose proper register */ - reg += (irqLine >> 3); - - /* set priority as given in priority table */ - *reg |= (irqPrioTable [irqLine] << (28 - (prio_index_offset << 2))); - - if ((irqLine >= BSP_SIU_IRQ_IRQ1) && (irqLine <= BSP_SIU_IRQ_IRQ3)) { - /* enable external irq-pin */ - mpc5200.ext_en_type |= (0x80000000 >> (20 + prio_index_offset)); - } - } - - /* enable (unmask) main interrupt */ - mpc5200.crit_pri_main_mask &= ~(0x80000000 >> SIU_MaskBit [irqLine]); - -} - -static inline void BSP_enable_crit_irq_at_siu( - rtems_vector_number irqLine -) -{ - uint8_t prio_index_offset; - uint32_t *reg; - - prio_index_offset = irqLine - BSP_CRIT_IRQ_LOWEST_OFFSET; - - /* - * critical interrupt handling for the 603Le core is not - * yet supported, routing of critical interrupts is forced - * to core_int (bit 31 / CEb) - */ - mpc5200.ext_en_type |= 1; - - /* set critical interrupt priorities */ - if (irqPrioTable [irqLine] <= 3) { - - /* choose proper register */ - reg = (uint32_t *) (&(mpc5200.crit_pri_main_mask)); - - /* set priority as given in priority table */ - *reg |= (irqPrioTable [irqLine] << (30 - (prio_index_offset << 1))); - - /* external irq0-pin */ - if (irqLine == BSP_SIU_IRQ_IRQ1) { - /* enable external irq-pin */ - mpc5200.ext_en_type |= (0x80000000 >> (20 + prio_index_offset)); - } - } -} - -static inline void BSP_disable_per_irq_at_siu( - rtems_vector_number irqLine -) -{ - uint8_t prio_index_offset; - uint32_t *reg; - - /* calculate the index offset of priority value bit field */ - prio_index_offset = (irqLine - BSP_PER_IRQ_LOWEST_OFFSET) % 8; - - /* disable (mask) peripheral interrupt */ - mpc5200.per_mask |= (0x80000000 >> SIU_MaskBit [irqLine]); - - /* reset priority to lowest level (reset value) */ - reg = (uint32_t *) (&(mpc5200.per_pri_1)); - reg += (irqLine >> 3); - *reg &= ~(15 << (28 - (prio_index_offset << 2))); -} - -static inline void BSP_disable_main_irq_at_siu( - rtems_vector_number irqLine -) -{ - uint8_t prio_index_offset; - uint32_t *reg; - - /* calculate the index offset of priority value bit field */ - prio_index_offset = (irqLine - BSP_MAIN_IRQ_LOWEST_OFFSET) % 8; - - /* disable (mask) main interrupt */ - mpc5200.crit_pri_main_mask |= (0x80000000 >> SIU_MaskBit [irqLine]); - - if ((irqLine >= BSP_SIU_IRQ_IRQ1) && (irqLine <= BSP_SIU_IRQ_IRQ3)) { - /* disable external irq-pin */ - mpc5200.ext_en_type &= ~(0x80000000 >> (20 + prio_index_offset)); - } - - /* reset priority to lowest level (reset value) */ - reg = (uint32_t *) (&(mpc5200.main_pri_1)); - reg += (irqLine >> 3); - *reg &= ~(15 << (28 - (prio_index_offset << 2))); -} - -static inline void BSP_disable_crit_irq_at_siu( rtems_vector_number - irqLine) -{ - uint8_t prio_index_offset; - uint32_t *reg; - - prio_index_offset = irqLine - BSP_CRIT_IRQ_LOWEST_OFFSET; - - /* reset critical int priority to lowest level (reset value) */ - reg = (uint32_t *) (&(mpc5200.crit_pri_main_mask)); - *reg &= ~(3 << (30 - (prio_index_offset << 1))); - - if (irqLine == BSP_SIU_IRQ_IRQ1) { - /* disable external irq0-pin */ - mpc5200.ext_en_type &= ~(0x80000000 >> (20 + prio_index_offset)); - } -} - -/* - * This function enables a given siu interrupt - */ -void bsp_interrupt_vector_enable( rtems_vector_number vector) -{ - int base_index = get_siu_irq_base_index( vector); - - bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector)); - - if (is_siu_irq( vector)) { - rtems_interrupt_level level; - - rtems_interrupt_disable( level); - - switch (base_index) { - case BSP_PER_IRQ_LOWEST_OFFSET: - BSP_enable_per_irq_at_siu( vector); - break; - case BSP_MAIN_IRQ_LOWEST_OFFSET: - BSP_enable_main_irq_at_siu( vector); - break; - case BSP_CRIT_IRQ_LOWEST_OFFSET: - BSP_enable_crit_irq_at_siu( vector); - break; - default: - bsp_interrupt_assert(0); - break; - } - - rtems_interrupt_enable( level); - } -} - -/* - * This function disables a given siu interrupt - */ -void bsp_interrupt_vector_disable( rtems_vector_number vector) -{ - int base_index = get_siu_irq_base_index( vector); - - bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector)); - - if (is_siu_irq( vector)) { - rtems_interrupt_level level; - - rtems_interrupt_disable( level); - - switch (base_index) { - case BSP_PER_IRQ_LOWEST_OFFSET: - BSP_disable_per_irq_at_siu( vector); - break; - case BSP_MAIN_IRQ_LOWEST_OFFSET: - BSP_disable_main_irq_at_siu( vector); - break; - case BSP_CRIT_IRQ_LOWEST_OFFSET: - BSP_disable_crit_irq_at_siu( vector); - break; - default: - bsp_interrupt_assert(0); - break; - } - - rtems_interrupt_enable( level); - } -} - -#if (BENCHMARK_IRQ_PROCESSING == 0) -void BSP_IRQ_Benchmarking_Reset( void) -{ -} -void BSP_IRQ_Benchmarking_Report( void) -{ -} -#else -#include -uint64_t BSP_Starting_TBR; -uint64_t BSP_Total_in_ISR; -uint32_t BSP_ISR_Count; -uint32_t BSP_Worst_ISR; - -#define BSP_COUNTED_IRQ 16 -uint32_t BSP_ISR_Count_Per [BSP_COUNTED_IRQ + 1]; - -void BSP_IRQ_Benchmarking_Reset( void) -{ - int i; - - BSP_Starting_TBR = PPC_Get_timebase_register(); - BSP_Total_in_ISR = 0; - BSP_ISR_Count = 0; - BSP_Worst_ISR = 0; - for (i = 0; i < BSP_COUNTED_IRQ; i++) - BSP_ISR_Count_Per [i] = 0; -} - -static const char *u64tostring( char *buffer, uint64_t v) -{ - sprintf( buffer, "%lld cycles %lld usecs", v, (v / 33)); - return buffer; -} - -void BSP_IRQ_Benchmarking_Report( void) -{ - uint64_t now; - char buffer [96]; - int i; - - now = PPC_Get_timebase_register(); - printk( "Started at: %s\n", u64tostring( buffer, BSP_Starting_TBR)); - printk( "Current : %s\n", u64tostring( buffer, now)); - printk( "System up : %s\n", u64tostring( buffer, now - BSP_Starting_TBR)); - printk( "ISRs : %d\n", BSP_ISR_Count); - printk( "ISRs ran : %s\n", u64tostring( buffer, BSP_Total_in_ISR)); - printk( "Worst ISR : %s\n", u64tostring( buffer, BSP_Worst_ISR)); - for (i = 0; i < BSP_COUNTED_IRQ; i++) - printk( "IRQ %d: %d\n", i, BSP_ISR_Count_Per [i]); - printk( "Ticks : %d\n", Clock_driver_ticks); -} -#endif - -static void dispatch(uint32_t irq, uint32_t offset, volatile uint32_t *maskreg) -{ - #if (ALLOW_IRQ_NESTING == 1) - uint32_t msr; - uint32_t mask = *maskreg; - #endif - - irq += offset; - - #if (ALLOW_IRQ_NESTING == 1) - *maskreg = mask | irqMaskTable [irq]; - /* Make sure that the write operation completed (cache inhibited area) */ - *maskreg; - msr = ppc_external_exceptions_enable(); - #endif - - bsp_interrupt_handler_dispatch(irq); - - #if (ALLOW_IRQ_NESTING == 1) - ppc_external_exceptions_disable(msr); - *maskreg = mask; - #endif -} - -/* - * High level IRQ handler called from shared_raw_irq_code_entry - */ -static int C_dispatch_irq_handler(BSP_Exception_frame *frame, unsigned excNum) -{ - uint32_t irq; - uint32_t pmce; - -#if (BENCHMARK_IRQ_PROCESSING == 1) - uint64_t start, - stop, - thisTime; - - start = PPC_Get_timebase_register(); - BSP_ISR_Count++; - if (excNum < BSP_COUNTED_IRQ) - BSP_ISR_Count_Per [excNum]++; - else - printk( "not counting %d\n", excNum); -#endif - - /* get the content of main interrupt status register */ - pmce = mpc5200.pmce; - - /* critical interrupts are routed to the core_int, see premature - * initialization - */ - while ((pmce & (PMCE_CSE_STICKY | PMCE_MSE_STICKY)) != 0) { - /* first: check for critical interrupt sources (hierarchical order) - * -> HI_int indicates peripheral sources - */ - if ((pmce & PMCE_CSE_STICKY) != 0) { - /* get source of critical interrupt */ - irq = PMCE_CSE_SOURCE(pmce); - - switch (irq) { - /* peripheral HI_int interrupt source detected */ - case 2: - /* check for valid peripheral interrupt source */ - if ((pmce & PMCE_PSE_STICKY) != 0) { - /* get source of peripheral interrupt */ - irq = PMCE_PSE_SOURCE(pmce); - - dispatch(irq, BSP_PER_IRQ_LOWEST_OFFSET, &mpc5200.per_mask); - } else { - /* this case may not occur: no valid peripheral - * interrupt source */ - printk( "No valid peripheral HI_int interrupt source\n"); - } - break; - - /* irq0, slice timer 1 or ccs wakeup detected */ - case 0: - case 1: - case 3: - - /* add proper offset for critical interrupts in the siu - * handler array */ - irq += BSP_CRIT_IRQ_LOWEST_OFFSET; - - /* Dispatch interrupt handlers */ - bsp_interrupt_handler_dispatch( irq); - - break; - - default: - /* error: unknown interrupt source */ - printk( "Unknown HI_int interrupt source\n"); - break; - } - } - - /* second: check for main interrupt sources (hierarchical order) - * -> LO_int indicates peripheral sources */ - if ((pmce & PMCE_MSE_STICKY) != 0) { - /* get source of main interrupt */ - irq = PMCE_MSE_SOURCE(pmce); - - if (irq == 4) { - /* peripheral LO_int interrupt source detected */ - /* check for valid peripheral interrupt source */ - if ((pmce & PMCE_PSE_STICKY) != 0) { - /* get source of peripheral interrupt */ - irq = PMCE_PSE_SOURCE(pmce); - - dispatch(irq, BSP_PER_IRQ_LOWEST_OFFSET, &mpc5200.per_mask); - } else { - /* this case may not occur: no valid peripheral - * interrupt source */ - printk( "No valid peripheral LO_int interrupt source\n"); - } - } else if (irq <= 16) { - /* irq1-3, RTC, GPIO, TMR0-7 detected (attention: slice timer - * 2 is always routed to SMI) */ - dispatch(irq, BSP_MAIN_IRQ_LOWEST_OFFSET, &mpc5200.crit_pri_main_mask); - } else { - /* error: unknown interrupt source */ - printk( "Unknown peripheral LO_int interrupt source\n"); - } - } - - /* force re-evaluation of interrupts */ - mpc5200.pmce = PMCE_CSE_STICKY | PMCE_MSE_STICKY | PMCE_PSE_STICKY; - - /* get the content of main interrupt status register */ - pmce = mpc5200.pmce; - } - -#if (BENCHMARK_IRQ_PROCESSING == 1) - stop = PPC_Get_timebase_register(); - thisTime = stop - start; - BSP_Total_in_ISR += thisTime; - if (thisTime > BSP_Worst_ISR) - BSP_Worst_ISR = thisTime; -#endif - - return 0; -} - -/* - * setup irqMaskTable to support a priorized/nested interrupt environment - */ -static void setup_irqMaskTable( void) -{ - rtems_irq_prio prio = 0; - uint32_t i = 0, - j = 0, - mask = 0; - - /* set up the priority dependent masks for peripheral interrupts */ - for (i = BSP_PER_IRQ_LOWEST_OFFSET; i <= BSP_PER_IRQ_MAX_OFFSET; i++) { - prio = irqPrioTable [i]; - mask = 0; - - for (j = BSP_PER_IRQ_LOWEST_OFFSET; j <= BSP_PER_IRQ_MAX_OFFSET; j++) { - if (prio > irqPrioTable [j]) { - mask |= (1 << (31 - j + BSP_PER_IRQ_LOWEST_OFFSET)); - } - - if ((prio == irqPrioTable [j]) && (j >= i)) { - mask |= (1 << (31 - j + BSP_PER_IRQ_LOWEST_OFFSET)); - } - } - - irqMaskTable [i] = mask; - } - - /* set up the priority dependent masks for main interrupts */ - for (i = BSP_MAIN_IRQ_LOWEST_OFFSET; i <= BSP_MAIN_IRQ_MAX_OFFSET; i++) { - prio = irqPrioTable [i]; - mask = 0; - - for (j = BSP_MAIN_IRQ_LOWEST_OFFSET; j <= BSP_MAIN_IRQ_MAX_OFFSET; j++) { - if (prio > irqPrioTable [j]) { - mask |= (1 << (16 - j + BSP_MAIN_IRQ_LOWEST_OFFSET)); - } - - if ((prio == irqPrioTable [j]) && (j >= i)) { - mask |= (1 << (16 - j + BSP_MAIN_IRQ_LOWEST_OFFSET)); - } - } - - irqMaskTable [i] = mask; - } -} - -/* - * Initialize MPC5x00 SIU interrupt management - */ -static void BSP_SIU_irq_init( void) -{ - - /* disable all peripheral interrupts */ - mpc5200.per_mask = 0xFFFFFC00; - - /* peripheral interrupt priorities according to reset value */ - mpc5200.per_pri_1 = 0xF0000000; - mpc5200.per_pri_2 = 0x00000000; - mpc5200.per_pri_3 = 0x00000000; - - /* disable external interrupts IRQ0-4 / critical interrupts are routed to core_int */ - mpc5200.ext_en_type = 0x0F000001; - - /* disable main interrupts / crit. int. priorities according to reset values */ - mpc5200.crit_pri_main_mask = 0x0001FFFF; - - /* main priorities according to reset value */ - mpc5200.main_pri_1 = 0; - mpc5200.main_pri_2 = 0; - - /* reset all status indicators */ - mpc5200.csa = 0x0001FFFF; - mpc5200.msa = 0x0001FFFF; - mpc5200.psa = 0x003FFFFF; - mpc5200.psa_be = 0x03000000; - - setup_irqMaskTable(); -} - -rtems_status_code bsp_interrupt_facility_initialize( void) -{ - BSP_SIU_irq_init(); - - /* Install exception handler */ - if (ppc_exc_set_handler( ASM_EXT_VECTOR, C_dispatch_irq_handler)) { - return RTEMS_IO_ERROR; - } - if (ppc_exc_set_handler( ASM_E300_SYSMGMT_VECTOR, C_dispatch_irq_handler)) { - return RTEMS_IO_ERROR; - } - - return RTEMS_SUCCESSFUL; -} - -void bsp_interrupt_handler_default( rtems_vector_number vector) -{ - if (vector != BSP_DECREMENTER) { - printk( "Spurious interrupt: 0x%08" PRIx32 "\n", vector); - } -} diff --git a/c/src/lib/libbsp/powerpc/gen83xx/Makefile.am b/c/src/lib/libbsp/powerpc/gen83xx/Makefile.am index eb2abcc4ca..7f5131c4a0 100644 --- a/c/src/lib/libbsp/powerpc/gen83xx/Makefile.am +++ b/c/src/lib/libbsp/powerpc/gen83xx/Makefile.am @@ -48,7 +48,7 @@ librtemsbsp_a_SOURCES +=../../../../../../bsps/powerpc/shared/clock/clock.c # irq librtemsbsp_a_SOURCES += ../../../../../../bsps/shared/irq/irq-default-handler.c -librtemsbsp_a_SOURCES += irq/irq.c +librtemsbsp_a_SOURCES += ../../../../../../bsps/powerpc/gen83xx/irq/irq.c # console librtemsbsp_a_SOURCES += ../../../../../../bsps/shared/dev/serial/console-termios-init.c diff --git a/c/src/lib/libbsp/powerpc/gen83xx/irq/irq.c b/c/src/lib/libbsp/powerpc/gen83xx/irq/irq.c deleted file mode 100644 index 7a8ce3cc0b..0000000000 --- a/c/src/lib/libbsp/powerpc/gen83xx/irq/irq.c +++ /dev/null @@ -1,596 +0,0 @@ -/*===============================================================*\ -| Project: RTEMS generic MPC83xx BSP | -+-----------------------------------------------------------------+ -| Copyright (c) 2007 | -| Embedded Brains GmbH | -| Obere Lagerstr. 30 | -| D-82178 Puchheim | -| Germany | -| rtems@embedded-brains.de | -+-----------------------------------------------------------------+ -| The license and distribution terms for this file may be | -| found in the file LICENSE in this distribution or at | -| | -| http://www.rtems.org/license/LICENSE. | -| | -+-----------------------------------------------------------------+ -| this file integrates the IPIC irq controller | -\*===============================================================*/ - -#include - -#include - -#include -#include - -#include -#include -#include - -#define MPC83XX_IPIC_VECTOR_NUMBER 92 - -#define MPC83XX_IPIC_IS_VALID_VECTOR( vector) ((vector) >= 0 && (vector) < MPC83XX_IPIC_VECTOR_NUMBER) - -#define MPC83XX_IPIC_INVALID_MASK_POSITION 255 - -typedef struct { - volatile uint32_t *pend_reg; - volatile uint32_t *mask_reg; - const uint32_t bit_num; -} BSP_isrc_rsc_t; - -/* - * data structure to handle all mask registers in the IPIC - * - * Mask positions: - * simsr [0] : 0 .. 31 - * simsr [1] : 32 .. 63 - * semsr : 64 .. 95 - * sermr : 96 .. 127 - */ -typedef struct { - uint32_t simsr_mask [2]; - uint32_t semsr_mask; - uint32_t sermr_mask; -} mpc83xx_ipic_mask_t; - -static const BSP_isrc_rsc_t mpc83xx_ipic_isrc_rsc [MPC83XX_IPIC_VECTOR_NUMBER] = { - /* vector 0 */ - {&mpc83xx.ipic.sersr, &mpc83xx.ipic.sermr, 31}, - {NULL, NULL, 0}, - {NULL, NULL, 0}, - {NULL, NULL, 0}, - {NULL, NULL, 0}, - {NULL, NULL, 0}, - {NULL, NULL, 0}, - {NULL, NULL, 0}, - /* vector 8 */ - {NULL, NULL, 0}, /* reserved vector 8 */ - /* vector 9: UART1 SIxxR_H, Bit 24 */ - {&mpc83xx.ipic.sipnr [0], &mpc83xx.ipic.simsr [0], 24}, - /* vector 10: UART2 SIxxR_H, Bit 25 */ - {&mpc83xx.ipic.sipnr [0], &mpc83xx.ipic.simsr [0], 25}, - /* vector 11: SEC SIxxR_H, Bit 26 */ - {&mpc83xx.ipic.sipnr [0], &mpc83xx.ipic.simsr [0], 26}, - {NULL, NULL, 0}, /* reserved vector 12 */ - {NULL, NULL, 0}, /* reserved vector 13 */ - /* vector 14: I2C1 SIxxR_H, Bit 29 */ - {&mpc83xx.ipic.sipnr [0], &mpc83xx.ipic.simsr [0], 29}, - /* vector 15: I2C2 SIxxR_H, Bit 30 */ - {&mpc83xx.ipic.sipnr [0], &mpc83xx.ipic.simsr [0], 30}, - /* vector 16: SPI SIxxR_H, Bit 31 */ - {&mpc83xx.ipic.sipnr [0], &mpc83xx.ipic.simsr [0], 31}, - /* vector 17: IRQ1 SExxR , Bit 1 */ - {&mpc83xx.ipic.sepnr, &mpc83xx.ipic.semsr, 1}, - /* vector 18: IRQ2 SExxR , Bit 2 */ - {&mpc83xx.ipic.sepnr, &mpc83xx.ipic.semsr, 2}, - /* vector 19: IRQ3 SExxR , Bit 3 */ - {&mpc83xx.ipic.sepnr, &mpc83xx.ipic.semsr, 3}, - /* vector 20: IRQ4 SExxR , Bit 4 */ - {&mpc83xx.ipic.sepnr, &mpc83xx.ipic.semsr, 4}, - /* vector 21: IRQ5 SExxR , Bit 5 */ - {&mpc83xx.ipic.sepnr, &mpc83xx.ipic.semsr, 5}, - /* vector 22: IRQ6 SExxR , Bit 6 */ - {&mpc83xx.ipic.sepnr, &mpc83xx.ipic.semsr, 6}, - /* vector 23: IRQ7 SExxR , Bit 7 */ - {&mpc83xx.ipic.sepnr, &mpc83xx.ipic.semsr, 7}, - {NULL, NULL, 0}, /* reserved vector 24 */ - {NULL, NULL, 0}, /* reserved vector 25 */ - {NULL, NULL, 0}, /* reserved vector 26 */ - {NULL, NULL, 0}, /* reserved vector 27 */ - {NULL, NULL, 0}, /* reserved vector 28 */ - {NULL, NULL, 0}, /* reserved vector 29 */ - {NULL, NULL, 0}, /* reserved vector 30 */ - {NULL, NULL, 0}, /* reserved vector 31 */ - /* vector 32: TSEC1 Tx SIxxR_H , Bit 0 */ - {&mpc83xx.ipic.sipnr [0], &mpc83xx.ipic.simsr [0], 0}, - /* vector 33: TSEC1 Rx SIxxR_H , Bit 1 */ - {&mpc83xx.ipic.sipnr [0], &mpc83xx.ipic.simsr [0], 1}, - /* vector 34: TSEC1 Err SIxxR_H , Bit 2 */ - {&mpc83xx.ipic.sipnr [0], &mpc83xx.ipic.simsr [0], 2}, - /* vector 35: TSEC2 Tx SIxxR_H , Bit 3 */ - {&mpc83xx.ipic.sipnr [0], &mpc83xx.ipic.simsr [0], 3}, - /* vector 36: TSEC2 Rx SIxxR_H , Bit 4 */ - {&mpc83xx.ipic.sipnr [0], &mpc83xx.ipic.simsr [0], 4}, - /* vector 37: TSEC2 Err SIxxR_H , Bit 5 */ - {&mpc83xx.ipic.sipnr [0], &mpc83xx.ipic.simsr [0], 5}, - /* vector 38: USB DR SIxxR_H , Bit 6 */ - {&mpc83xx.ipic.sipnr [0], &mpc83xx.ipic.simsr [0], 6}, - /* vector 39: USB MPH SIxxR_H , Bit 7 */ - {&mpc83xx.ipic.sipnr [0], &mpc83xx.ipic.simsr [0], 7}, - {NULL, NULL, 0}, /* reserved vector 40 */ - {NULL, NULL, 0}, /* reserved vector 41 */ - {NULL, NULL, 0}, /* reserved vector 42 */ - {NULL, NULL, 0}, /* reserved vector 43 */ - {NULL, NULL, 0}, /* reserved vector 44 */ - {NULL, NULL, 0}, /* reserved vector 45 */ - {NULL, NULL, 0}, /* reserved vector 46 */ - {NULL, NULL, 0}, /* reserved vector 47 */ - /* vector 48: IRQ0 SExxR , Bit 0 */ - {&mpc83xx.ipic.sepnr, &mpc83xx.ipic.semsr, 0}, - {NULL, NULL, 0}, /* reserved vector 49 */ - {NULL, NULL, 0}, /* reserved vector 50 */ - {NULL, NULL, 0}, /* reserved vector 51 */ - {NULL, NULL, 0}, /* reserved vector 52 */ - {NULL, NULL, 0}, /* reserved vector 53 */ - {NULL, NULL, 0}, /* reserved vector 54 */ - {NULL, NULL, 0}, /* reserved vector 55 */ - {NULL, NULL, 0}, /* reserved vector 56 */ - {NULL, NULL, 0}, /* reserved vector 57 */ - {NULL, NULL, 0}, /* reserved vector 58 */ - {NULL, NULL, 0}, /* reserved vector 59 */ - {NULL, NULL, 0}, /* reserved vector 60 */ - {NULL, NULL, 0}, /* reserved vector 61 */ - {NULL, NULL, 0}, /* reserved vector 62 */ - {NULL, NULL, 0}, /* reserved vector 63 */ - /* vector 64: RTC SEC SIxxR_L , Bit 0 */ - {&mpc83xx.ipic.sipnr [1], &mpc83xx.ipic.simsr [1], 0}, - /* vector 65: PIT SIxxR_L , Bit 1 */ - {&mpc83xx.ipic.sipnr [1], &mpc83xx.ipic.simsr [1], 1}, - /* vector 66: PCI1 SIxxR_L , Bit 2 */ - {&mpc83xx.ipic.sipnr [1], &mpc83xx.ipic.simsr [1], 2}, - /* vector 67: PCI2 SIxxR_L , Bit 3 */ - {&mpc83xx.ipic.sipnr [1], &mpc83xx.ipic.simsr [1], 3}, - /* vector 68: RTC ALR SIxxR_L , Bit 4 */ - {&mpc83xx.ipic.sipnr [1], &mpc83xx.ipic.simsr [1], 4}, - /* vector 69: MU SIxxR_L , Bit 5 */ - {&mpc83xx.ipic.sipnr [1], &mpc83xx.ipic.simsr [1], 5}, - /* vector 70: SBA SIxxR_L , Bit 6 */ - {&mpc83xx.ipic.sipnr [1], &mpc83xx.ipic.simsr [1], 6}, - /* vector 71: DMA SIxxR_L , Bit 7 */ - {&mpc83xx.ipic.sipnr [1], &mpc83xx.ipic.simsr [1], 7}, - /* vector 72: GTM4 SIxxR_L , Bit 8 */ - {&mpc83xx.ipic.sipnr [1], &mpc83xx.ipic.simsr [1], 8}, - /* vector 73: GTM8 SIxxR_L , Bit 9 */ - {&mpc83xx.ipic.sipnr [1], &mpc83xx.ipic.simsr [1], 9}, - /* vector 74: GPIO1 SIxxR_L , Bit 10 */ - {&mpc83xx.ipic.sipnr [1], &mpc83xx.ipic.simsr [1], 10}, - /* vector 75: GPIO2 SIxxR_L , Bit 11 */ - {&mpc83xx.ipic.sipnr [1], &mpc83xx.ipic.simsr [1], 11}, - /* vector 76: DDR SIxxR_L , Bit 12 */ - {&mpc83xx.ipic.sipnr [1], &mpc83xx.ipic.simsr [1], 12}, - /* vector 77: LBC SIxxR_L , Bit 13 */ - {&mpc83xx.ipic.sipnr [1], &mpc83xx.ipic.simsr [1], 13}, - /* vector 78: GTM2 SIxxR_L , Bit 14 */ - {&mpc83xx.ipic.sipnr [1], &mpc83xx.ipic.simsr [1], 14}, - /* vector 79: GTM6 SIxxR_L , Bit 15 */ - {&mpc83xx.ipic.sipnr [1], &mpc83xx.ipic.simsr [1], 15}, - /* vector 80: PMC SIxxR_L , Bit 16 */ - {&mpc83xx.ipic.sipnr [1], &mpc83xx.ipic.simsr [1], 16}, - {NULL, NULL, 0}, /* reserved vector 81 */ - {NULL, NULL, 0}, /* reserved vector 82 */ - {NULL, NULL, 0}, /* reserved vector 63 */ - /* vector 84: GTM3 SIxxR_L , Bit 20 */ - {&mpc83xx.ipic.sipnr [1], &mpc83xx.ipic.simsr [1], 20}, - /* vector 85: GTM7 SIxxR_L , Bit 21 */ - {&mpc83xx.ipic.sipnr [1], &mpc83xx.ipic.simsr [1], 21}, - {NULL, NULL, 0}, /* reserved vector 81 */ - {NULL, NULL, 0}, /* reserved vector 82 */ - {NULL, NULL, 0}, /* reserved vector 63 */ - {NULL, NULL, 0}, /* reserved vector 63 */ - /* vector 90: GTM1 SIxxR_L , Bit 26 */ - {&mpc83xx.ipic.sipnr [1], &mpc83xx.ipic.simsr [1], 26}, - /* vector 91: GTM5 SIxxR_L , Bit 27 */ - {&mpc83xx.ipic.sipnr [1], &mpc83xx.ipic.simsr [1], 27} -}; - -static const uint8_t - mpc83xx_ipic_mask_position_table [MPC83XX_IPIC_VECTOR_NUMBER] = { - MPC83XX_IPIC_INVALID_MASK_POSITION, - MPC83XX_IPIC_INVALID_MASK_POSITION, - MPC83XX_IPIC_INVALID_MASK_POSITION, - MPC83XX_IPIC_INVALID_MASK_POSITION, - MPC83XX_IPIC_INVALID_MASK_POSITION, - MPC83XX_IPIC_INVALID_MASK_POSITION, - MPC83XX_IPIC_INVALID_MASK_POSITION, - MPC83XX_IPIC_INVALID_MASK_POSITION, - MPC83XX_IPIC_INVALID_MASK_POSITION, - 7, - 6, - 5, - MPC83XX_IPIC_INVALID_MASK_POSITION, - MPC83XX_IPIC_INVALID_MASK_POSITION, - 2, - 1, - 0, - 94, - 93, - 92, - 91, - 90, - 89, - 88, - MPC83XX_IPIC_INVALID_MASK_POSITION, - MPC83XX_IPIC_INVALID_MASK_POSITION, - MPC83XX_IPIC_INVALID_MASK_POSITION, - MPC83XX_IPIC_INVALID_MASK_POSITION, - MPC83XX_IPIC_INVALID_MASK_POSITION, - MPC83XX_IPIC_INVALID_MASK_POSITION, - MPC83XX_IPIC_INVALID_MASK_POSITION, - MPC83XX_IPIC_INVALID_MASK_POSITION, - 31, - 30, - 29, - 28, - 27, - 26, - 25, - 24, - MPC83XX_IPIC_INVALID_MASK_POSITION, - MPC83XX_IPIC_INVALID_MASK_POSITION, - MPC83XX_IPIC_INVALID_MASK_POSITION, - MPC83XX_IPIC_INVALID_MASK_POSITION, - MPC83XX_IPIC_INVALID_MASK_POSITION, - MPC83XX_IPIC_INVALID_MASK_POSITION, - MPC83XX_IPIC_INVALID_MASK_POSITION, - MPC83XX_IPIC_INVALID_MASK_POSITION, - 95, - MPC83XX_IPIC_INVALID_MASK_POSITION, - MPC83XX_IPIC_INVALID_MASK_POSITION, - MPC83XX_IPIC_INVALID_MASK_POSITION, - MPC83XX_IPIC_INVALID_MASK_POSITION, - MPC83XX_IPIC_INVALID_MASK_POSITION, - MPC83XX_IPIC_INVALID_MASK_POSITION, - MPC83XX_IPIC_INVALID_MASK_POSITION, - MPC83XX_IPIC_INVALID_MASK_POSITION, - MPC83XX_IPIC_INVALID_MASK_POSITION, - MPC83XX_IPIC_INVALID_MASK_POSITION, - MPC83XX_IPIC_INVALID_MASK_POSITION, - MPC83XX_IPIC_INVALID_MASK_POSITION, - MPC83XX_IPIC_INVALID_MASK_POSITION, - MPC83XX_IPIC_INVALID_MASK_POSITION, - MPC83XX_IPIC_INVALID_MASK_POSITION, - 63, - 62, - 61, - 60, - 59, - 58, - 57, - 56, - 55, - 54, - 53, - 52, - 51, - 50, - 49, - 48, - 47, - MPC83XX_IPIC_INVALID_MASK_POSITION, - MPC83XX_IPIC_INVALID_MASK_POSITION, - MPC83XX_IPIC_INVALID_MASK_POSITION, - 43, - 42, - MPC83XX_IPIC_INVALID_MASK_POSITION, - MPC83XX_IPIC_INVALID_MASK_POSITION, - MPC83XX_IPIC_INVALID_MASK_POSITION, - MPC83XX_IPIC_INVALID_MASK_POSITION, - 37, - 36 -}; - -/* - * this array will be filled with mask values needed - * to temporarily disable all IRQ soures with lower or same - * priority of the current source (whose vector is the array index) - */ -static mpc83xx_ipic_mask_t mpc83xx_ipic_prio2mask [MPC83XX_IPIC_VECTOR_NUMBER]; - -rtems_status_code mpc83xx_ipic_set_mask( - rtems_vector_number vector, - rtems_vector_number mask_vector, - bool mask -) -{ - uint8_t pos = 0; - mpc83xx_ipic_mask_t *mask_entry; - uint32_t *mask_reg; - rtems_interrupt_level level; - - /* Parameter check */ - if (!MPC83XX_IPIC_IS_VALID_VECTOR( vector) || - !MPC83XX_IPIC_IS_VALID_VECTOR( mask_vector)) { - return RTEMS_INVALID_NUMBER; - } else if (vector == mask_vector) { - return RTEMS_RESOURCE_IN_USE; - } - - /* Position and mask entry */ - pos = mpc83xx_ipic_mask_position_table [mask_vector]; - mask_entry = &mpc83xx_ipic_prio2mask [vector]; - - /* Mask register and position */ - if (pos < 32) { - mask_reg = &mask_entry->simsr_mask [0]; - } else if (pos < 64) { - pos -= 32; - mask_reg = &mask_entry->simsr_mask [1]; - } else if (pos < 96) { - pos -= 64; - mask_reg = &mask_entry->semsr_mask; - } else if (pos < 128) { - pos -= 96; - mask_reg = &mask_entry->sermr_mask; - } else { - return RTEMS_NOT_IMPLEMENTED; - } - - /* Mask or unmask */ - if (mask) { - rtems_interrupt_disable( level); - *mask_reg &= ~(1 << pos); - rtems_interrupt_enable( level); - } else { - rtems_interrupt_disable( level); - *mask_reg |= 1 << pos; - rtems_interrupt_enable( level); - } - - return RTEMS_SUCCESSFUL; -} - -rtems_status_code mpc83xx_ipic_set_highest_priority_interrupt( - rtems_vector_number vector, - int type -) -{ - rtems_interrupt_level level; - uint32_t reg = 0; - - if (!MPC83XX_IPIC_IS_VALID_VECTOR( vector)) { - return RTEMS_INVALID_NUMBER; - } else if (type < 0 || type > MPC83XX_IPIC_INTERRUPT_CRITICAL) { - return RTEMS_INVALID_NUMBER; - } - - rtems_interrupt_disable( level); - reg = mpc83xx.ipic.sicfr; - mpc83xx.ipic.sicfr = (reg & ~0x7f000300) | (vector << 24) | (type << 8); - rtems_interrupt_enable( level); - - return RTEMS_SUCCESSFUL; -} - -/* - * functions to enable/disable a source at the ipic - */ -void bsp_interrupt_vector_enable( rtems_vector_number vector) -{ - rtems_vector_number vecnum = vector - BSP_IPIC_IRQ_LOWEST_OFFSET; - const BSP_isrc_rsc_t *rsc_ptr; - - bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector)); - - if (MPC83XX_IPIC_IS_VALID_VECTOR( vecnum)) { - rsc_ptr = &mpc83xx_ipic_isrc_rsc [vecnum]; - if (rsc_ptr->mask_reg != NULL) { - uint32_t bit = 1U << (31 - rsc_ptr->bit_num); - rtems_interrupt_level level; - - rtems_interrupt_disable(level); - *(rsc_ptr->mask_reg) |= bit; - rtems_interrupt_enable(level); - } - } -} - -void bsp_interrupt_vector_disable( rtems_vector_number vector) -{ - rtems_vector_number vecnum = vector - BSP_IPIC_IRQ_LOWEST_OFFSET; - const BSP_isrc_rsc_t *rsc_ptr; - - bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector)); - - if (MPC83XX_IPIC_IS_VALID_VECTOR( vecnum)) { - rsc_ptr = &mpc83xx_ipic_isrc_rsc [vecnum]; - if (rsc_ptr->mask_reg != NULL) { - uint32_t bit = 1U << (31 - rsc_ptr->bit_num); - rtems_interrupt_level level; - - rtems_interrupt_disable(level); - *(rsc_ptr->mask_reg) &= ~bit; - rtems_interrupt_enable(level); - } - } -} - -/* - * IRQ Handler: this is called from the primary exception dispatcher - */ -static int BSP_irq_handle_at_ipic( unsigned excNum) -{ - int32_t vecnum; -#ifdef GEN83XX_ENABLE_INTERRUPT_NESTING - mpc83xx_ipic_mask_t mask_save; - const mpc83xx_ipic_mask_t *mask_ptr; - uint32_t msr = 0; - rtems_interrupt_level level; -#endif - - /* Get vector number */ - switch (excNum) { - case ASM_EXT_VECTOR: - vecnum = MPC83xx_VCR_TO_VEC( mpc83xx.ipic.sivcr); - break; - case ASM_E300_SYSMGMT_VECTOR: - vecnum = MPC83xx_VCR_TO_VEC( mpc83xx.ipic.smvcr); - break; - case ASM_E300_CRIT_VECTOR: - vecnum = MPC83xx_VCR_TO_VEC( mpc83xx.ipic.scvcr); - break; - default: - return 1; - } - - /* - * Check the vector number, mask lower priority interrupts, enable - * exceptions and dispatch the handler. - */ - if (MPC83XX_IPIC_IS_VALID_VECTOR( vecnum)) { -#ifdef GEN83XX_ENABLE_INTERRUPT_NESTING - mask_ptr = &mpc83xx_ipic_prio2mask [vecnum]; - - rtems_interrupt_disable( level); - - /* Save current mask registers */ - mask_save.simsr_mask [0] = mpc83xx.ipic.simsr [0]; - mask_save.simsr_mask [1] = mpc83xx.ipic.simsr [1]; - mask_save.semsr_mask = mpc83xx.ipic.semsr; - mask_save.sermr_mask = mpc83xx.ipic.sermr; - - /* Mask all lower priority interrupts */ - mpc83xx.ipic.simsr [0] &= mask_ptr->simsr_mask [0]; - mpc83xx.ipic.simsr [1] &= mask_ptr->simsr_mask [1]; - mpc83xx.ipic.semsr &= mask_ptr->semsr_mask; - mpc83xx.ipic.sermr &= mask_ptr->sermr_mask; - - rtems_interrupt_enable( level); - - /* Enable all interrupts */ - if (excNum != ASM_E300_CRIT_VECTOR) { - msr = ppc_external_exceptions_enable(); - } -#endif /* GEN83XX_ENABLE_INTERRUPT_NESTING */ - - /* Dispatch interrupt handlers */ - bsp_interrupt_handler_dispatch( vecnum + BSP_IPIC_IRQ_LOWEST_OFFSET); - -#ifdef GEN83XX_ENABLE_INTERRUPT_NESTING - /* Restore machine state */ - if (excNum != ASM_E300_CRIT_VECTOR) { - ppc_external_exceptions_disable( msr); - } - - /* Restore initial masks */ - rtems_interrupt_disable( level); - mpc83xx.ipic.simsr [0] = mask_save.simsr_mask [0]; - mpc83xx.ipic.simsr [1] = mask_save.simsr_mask [1]; - mpc83xx.ipic.semsr = mask_save.semsr_mask; - mpc83xx.ipic.sermr = mask_save.sermr_mask; - rtems_interrupt_enable( level); -#endif /* GEN83XX_ENABLE_INTERRUPT_NESTING */ - } else { - bsp_interrupt_handler_default( vecnum); - } - - return 0; -} - -/* - * Fill the array mpc83xx_ipic_prio2mask to allow masking of lower prio sources - * to implement nested interrupts. - */ -static rtems_status_code mpc83xx_ipic_calc_prio2mask(void) -{ - rtems_status_code rc = RTEMS_SUCCESSFUL; - - /* - * FIXME: fill the array - */ - return rc; -} - -/* - * Activate the interrupt controller - */ -static rtems_status_code mpc83xx_ipic_initialize(void) -{ - /* - * mask off all interrupts - */ - mpc83xx.ipic.simsr [0] = 0; - mpc83xx.ipic.simsr [1] = 0; - mpc83xx.ipic.semsr = 0; - mpc83xx.ipic.sermr = 0; - /* - * set desired configuration as defined in bspopts.h - * normally, the default values should be fine - */ -#if defined( BSP_SICFR_VAL) /* defined in bspopts.h ? */ - mpc83xx.ipic.sicfr = BSP_SICFR_VAL; -#endif - - /* - * set desired priorities as defined in bspopts.h - * normally, the default values should be fine - */ -#if defined( BSP_SIPRR0_VAL) /* defined in bspopts.h ? */ - mpc83xx.ipic.siprr [0] = BSP_SIPRR0_VAL; -#endif - -#if defined( BSP_SIPRR1_VAL) /* defined in bspopts.h ? */ - mpc83xx.ipic.siprr [1] = BSP_SIPRR1_VAL; -#endif - -#if defined( BSP_SIPRR2_VAL) /* defined in bspopts.h ? */ - mpc83xx.ipic.siprr [2] = BSP_SIPRR2_VAL; -#endif - -#if defined( BSP_SIPRR3_VAL) /* defined in bspopts.h ? */ - mpc83xx.ipic.siprr [3] = BSP_SIPRR3_VAL; -#endif - -#if defined( BSP_SMPRR0_VAL) /* defined in bspopts.h ? */ - mpc83xx.ipic.smprr [0] = BSP_SMPRR0_VAL; -#endif - -#if defined( BSP_SMPRR1_VAL) /* defined in bspopts.h ? */ - mpc83xx.ipic.smprr [1] = BSP_SMPRR1_VAL; -#endif - -#if defined( BSP_SECNR_VAL) /* defined in bspopts.h ? */ - mpc83xx.ipic.secnr = BSP_SECNR_VAL; -#endif - - /* - * calculate priority masks - */ - return mpc83xx_ipic_calc_prio2mask(); -} - -static int mpc83xx_exception_handler( - BSP_Exception_frame *frame, - unsigned exception_number -) -{ - return BSP_irq_handle_at_ipic( exception_number); -} - -rtems_status_code bsp_interrupt_facility_initialize() -{ - /* Install exception handler */ - if (ppc_exc_set_handler( ASM_EXT_VECTOR, mpc83xx_exception_handler)) { - return RTEMS_IO_ERROR; - } - if (ppc_exc_set_handler( ASM_E300_SYSMGMT_VECTOR, mpc83xx_exception_handler)) { - return RTEMS_IO_ERROR; - } - if (ppc_exc_set_handler( ASM_E300_CRIT_VECTOR, mpc83xx_exception_handler)) { - return RTEMS_IO_ERROR; - } - - /* Initialize the interrupt controller */ - return mpc83xx_ipic_initialize(); -} diff --git a/c/src/lib/libbsp/powerpc/haleakala/Makefile.am b/c/src/lib/libbsp/powerpc/haleakala/Makefile.am index b617fd5f11..8c2f7fb5c4 100644 --- a/c/src/lib/libbsp/powerpc/haleakala/Makefile.am +++ b/c/src/lib/libbsp/powerpc/haleakala/Makefile.am @@ -34,8 +34,8 @@ librtemsbsp_a_SOURCES += ../../../../../../bsps/powerpc/shared/console/uart.c librtemsbsp_a_SOURCES += ../../../../../../bsps/powerpc/shared/console/console.c # irq -librtemsbsp_a_SOURCES += irq/irq_init.c -librtemsbsp_a_SOURCES += irq/irq.c +librtemsbsp_a_SOURCES += ../../../../../../bsps/powerpc/haleakala/irq/irq_init.c +librtemsbsp_a_SOURCES += ../../../../../../bsps/powerpc/haleakala/irq/irq.c if HAS_NETWORKING librtemsbsp_a_SOURCES += network/network.c diff --git a/c/src/lib/libbsp/powerpc/haleakala/irq/irq.c b/c/src/lib/libbsp/powerpc/haleakala/irq/irq.c deleted file mode 100644 index c9607a032d..0000000000 --- a/c/src/lib/libbsp/powerpc/haleakala/irq/irq.c +++ /dev/null @@ -1,237 +0,0 @@ -/* - * - * - * The license and distribution terms for this file may be - * found in the file LICENSE in this distribution or at - * http://www.rtems.org/license/LICENSE. - * - * Middleware support for PPC405 by M.Hamel ADInstruments Ltd 2008 - */ - -#include -#include -#include -#include -#include -#include - - -/* PPC405EX UIC numbers */ -#define UIC_DCR_BASE 0xc0 -#define UIC0_SR (UIC_DCR_BASE+0x0) /* UIC status */ -#define UIC0_SRS (UIC_DCR_BASE+0x1) /* UIC status set */ -#define UIC0_ER (UIC_DCR_BASE+0x2) /* UIC enable */ -#define UIC0_CR (UIC_DCR_BASE+0x3) /* UIC critical */ -#define UIC0_PR (UIC_DCR_BASE+0x4) /* UIC polarity */ -#define UIC0_TR (UIC_DCR_BASE+0x5) /* UIC triggering */ -#define UIC0_MSR (UIC_DCR_BASE+0x6) /* UIC masked status */ -#define UIC0_VR (UIC_DCR_BASE+0x7) /* UIC vector */ -#define UIC0_VCR (UIC_DCR_BASE+0x8) /* UIC vector configuration */ - -#define UIC1_SR (UIC_DCR_BASE+0x10) /* UIC status */ -#define UIC1_SRS (UIC_DCR_BASE+0x11) /* UIC status set */ -#define UIC1_ER (UIC_DCR_BASE+0x12) /* UIC enable */ -#define UIC1_CR (UIC_DCR_BASE+0x13) /* UIC critical */ -#define UIC1_PR (UIC_DCR_BASE+0x14) /* UIC polarity */ -#define UIC1_TR (UIC_DCR_BASE+0x15) /* UIC triggering */ -#define UIC1_MSR (UIC_DCR_BASE+0x16) /* UIC masked status */ -#define UIC1_VR (UIC_DCR_BASE+0x17) /* UIC vector */ -#define UIC1_VCR (UIC_DCR_BASE+0x18) /* UIC vector configuration */ - -#define UIC2_SR (UIC_DCR_BASE+0x20) /* UIC status */ -#define UIC2_SRS (UIC_DCR_BASE+0x21) /* UIC status set */ -#define UIC2_ER (UIC_DCR_BASE+0x22) /* UIC enable */ -#define UIC2_CR (UIC_DCR_BASE+0x23) /* UIC critical */ -#define UIC2_PR (UIC_DCR_BASE+0x24) /* UIC polarity */ -#define UIC2_TR (UIC_DCR_BASE+0x25) /* UIC triggering */ -#define UIC2_MSR (UIC_DCR_BASE+0x26) /* UIC masked status */ -#define UIC2_VR (UIC_DCR_BASE+0x27) /* UIC vector */ -#define UIC2_VCR (UIC_DCR_BASE+0x28) /* UIC vector configuration */ - -enum { kUICWords = 3 }; - -static rtems_irq_connect_data* rtems_hdl_tblP; -static rtems_irq_connect_data dflt_entry; - -static uint32_t gEnabledInts[kUICWords]; /* 1-bits mean enabled */ -static uint32_t gIntInhibited[kUICWords]; /* 1-bits disable, overriding gEnabledInts because the interrupt - is being processed in C_dispatch_irq_handler */ - -static inline int IsUICIRQ(const rtems_irq_number irqLine) -{ - return (((int) irqLine <= BSP_UIC_IRQ_MAX_OFFSET) && - ((int) irqLine >= BSP_UIC_IRQ_LOWEST_OFFSET) - ); -} - -static void WriteIState(void) -/* Write the gEnabledInts state masked by gIntInhibited to the hardware */ -{ - PPC_SET_DEVICE_CONTROL_REGISTER(UIC0_ER, - gEnabledInts[0] & ~gIntInhibited[0]); - PPC_SET_DEVICE_CONTROL_REGISTER(UIC1_ER, - gEnabledInts[1] & ~gIntInhibited[1]); - PPC_SET_DEVICE_CONTROL_REGISTER(UIC2_ER, - gEnabledInts[2] & ~gIntInhibited[2]); -} - -void -BSP_enable_irq_at_pic(const rtems_irq_number irq) -/* Enable an interrupt; this can be called from inside C_dispatch_irq_handler */ -{ - if (IsUICIRQ(irq)) { - /* Set relevant bit in the state, write state to the UIC */ - gEnabledInts[irq>>5] |= (0x80000000 >> (irq & 0x1F)); - WriteIState(); - } -} - -int -BSP_disable_irq_at_pic(const rtems_irq_number irq) -/* Enable an interrupt; this can be called from inside C_dispatch_irq_handler */ -{ - if (IsUICIRQ(irq)) { - uint32_t oldState; - int iword = irq>>5; - uint32_t mask = (0x80000000 >> (irq & 0x1F)); - - oldState = gEnabledInts[iword] & mask; - gEnabledInts[iword] &= ~mask; - WriteIState(); - return oldState ? 1 : 0; - } else - return -1; -} - -int -BSP_setup_the_pic(rtems_irq_global_settings* config) -{ - int i; - - dflt_entry = config->defaultEntry; - rtems_hdl_tblP = config->irqHdlTbl; - for (i=0; i> bit; - switch (index) { - case 0: - PPC_SET_DEVICE_CONTROL_REGISTER(UIC0_SR, bmask); - break; - case 1: - PPC_SET_DEVICE_CONTROL_REGISTER(UIC1_SR, bmask); - break; - case 2: - PPC_SET_DEVICE_CONTROL_REGISTER(UIC2_SR, bmask); - break; - } - - /* Clear in the active record and gIntInhibited */ - active[index] &= ~bmask; - gIntInhibited[index] &= ~bmask; - }; - - /* Update the hardware again so the interrupts we have handled are unmasked */ - WriteIState(); - return 0; - - } else if (excNum == ASM_DEC_VECTOR) { /* 0x1000 remapped by C_dispatch_dec_handler_bookE */ - bsp_irq_dispatch_list(rtems_hdl_tblP, BSP_PIT, dflt_entry.hdl); - return 0; - - } else if (excNum == ASM_BOOKE_FIT_VECTOR) { /* 0x1010 mapped to 0x13 by ppc_get_vector_addr */ - bsp_irq_dispatch_list(rtems_hdl_tblP, BSP_FIT, dflt_entry.hdl); - return 0; - - } else if (excNum == ASM_BOOKE_WDOG_VECTOR) { /* 0x1020 mapped to 0x14 by ppc_get_vector_addr */ - bsp_irq_dispatch_list(rtems_hdl_tblP, BSP_WDOG, dflt_entry.hdl); - return 0; - - } else - return -1; /* unhandled interrupt, panic time */ -} - diff --git a/c/src/lib/libbsp/powerpc/haleakala/irq/irq_init.c b/c/src/lib/libbsp/powerpc/haleakala/irq/irq_init.c deleted file mode 100644 index d48855a979..0000000000 --- a/c/src/lib/libbsp/powerpc/haleakala/irq/irq_init.c +++ /dev/null @@ -1,96 +0,0 @@ -/*===============================================================*\ -| Project: RTEMS Haleakala BSP | -| * by Michael Hamel ADInstruments Ltd 2008 | -+-----------------------------------------------------------------+ -| The license and distribution terms for this file may be | -| found in the file LICENSE in this distribution or at | -| | -| http://www.rtems.org/license/LICENSE. | -| | -+-----------------------------------------------------------------+ -| this file contains the irq controller handler | -\*===============================================================*/ -#include -#include -#include -#include -#include -#include - - -/* - * default on/off function - */ -static void nop_func(void) -{ -} - -/* - * default isOn function - */ -static int not_connected(void) -{ - return 0; -} - -static rtems_irq_connect_data rtemsIrq[BSP_IRQ_NUMBER]; -static rtems_irq_global_settings initial_config; -static rtems_irq_connect_data defaultIrq = { - .name = 0, - .hdl = NULL, - .handle = NULL, - .on = (rtems_irq_enable) nop_func, - .off = (rtems_irq_disable) nop_func, - .isOn = (rtems_irq_is_enabled) not_connected, -#ifdef BSP_SHARED_HANDLER_SUPPORT - .next_handler = NULL -#endif -}; - -static rtems_irq_prio irqPrioTable[BSP_IRQ_NUMBER]={ - /* - * Processor exceptions handled as interrupts - */ - 0 -}; - - /* - * This code assumes the exceptions management setup has already - * been done. We just need to replace the exceptions that will - * be handled like interrupt. On mcp750/mpc750 and many PPC processors - * this means the decrementer exception and the external exception. - */ - -void BSP_rtems_irq_mng_init(unsigned cpuId) -{ - int i; - - /* - * re-init the rtemsIrq table - */ - for (i = 0; i < BSP_IRQ_NUMBER; i++) { - rtemsIrq[i] = defaultIrq; - rtemsIrq[i].name = i; - } - /* - * Init initial Interrupt management config - */ - initial_config.irqNb = BSP_IRQ_NUMBER; - initial_config.defaultEntry = defaultIrq; - initial_config.irqHdlTbl = rtemsIrq; - initial_config.irqBase = BSP_LOWEST_OFFSET; - initial_config.irqPrioTbl = irqPrioTable; - - if (!BSP_rtems_irq_mngt_set(&initial_config)) { - /* - * put something here that will show the failure... - */ - rtems_panic( - "Unable to initialize RTEMS interrupt management!!! System locked\n" - ); - } - - #ifdef TRACE_IRQ_INIT - printk("RTEMS IRQ management is now operational\n"); - #endif -} diff --git a/c/src/lib/libbsp/powerpc/motorola_powerpc/Makefile.am b/c/src/lib/libbsp/powerpc/motorola_powerpc/Makefile.am index b0bea03813..ac5cc2c73c 100644 --- a/c/src/lib/libbsp/powerpc/motorola_powerpc/Makefile.am +++ b/c/src/lib/libbsp/powerpc/motorola_powerpc/Makefile.am @@ -59,15 +59,15 @@ librtemsbsp_a_SOURCES += ../../../../../../bsps/powerpc/shared/console/uart.c librtemsbsp_a_SOURCES += ../../../../../../bsps/powerpc/shared/console/console.c # irq -librtemsbsp_a_SOURCES += ../shared/irq/irq_init.c -librtemsbsp_a_SOURCES += ../shared/irq/openpic_i8259_irq.c -librtemsbsp_a_SOURCES += ../shared/irq/i8259.c +librtemsbsp_a_SOURCES += ../../../../../../bsps/powerpc/shared/irq/irq_init.c +librtemsbsp_a_SOURCES += ../../../../../../bsps/powerpc/shared/irq/openpic_i8259_irq.c +librtemsbsp_a_SOURCES += ../../../../../../bsps/powerpc/shared/irq/i8259.c # motorola librtemsbsp_a_SOURCES += ../shared/motorola/motorola.c # openpic -librtemsbsp_a_SOURCES += ../shared/openpic/openpic.c +librtemsbsp_a_SOURCES += ../../../../../../bsps/powerpc/shared/irq/openpic.c # pci librtemsbsp_a_SOURCES += ../shared/pci/pci.c diff --git a/c/src/lib/libbsp/powerpc/mpc8260ads/Makefile.am b/c/src/lib/libbsp/powerpc/mpc8260ads/Makefile.am index 4e10602377..6fe77e9ed4 100644 --- a/c/src/lib/libbsp/powerpc/mpc8260ads/Makefile.am +++ b/c/src/lib/libbsp/powerpc/mpc8260ads/Makefile.am @@ -29,7 +29,7 @@ librtemsbsp_a_SOURCES += ../../../../../../bsps/powerpc/mpc8260ads/console/conso # irq librtemsbsp_a_SOURCES += ../../../../../../bsps/shared/irq/irq-default-handler.c -librtemsbsp_a_SOURCES += irq/irq.c +librtemsbsp_a_SOURCES += ../../../../../../bsps/powerpc/mpc8260ads/irq/irq.c # startup librtemsbsp_a_SOURCES += ../../../../../../bsps/shared/start/bspfatal-default.c diff --git a/c/src/lib/libbsp/powerpc/mpc8260ads/irq/irq.c b/c/src/lib/libbsp/powerpc/mpc8260ads/irq/irq.c deleted file mode 100644 index baca1e0e05..0000000000 --- a/c/src/lib/libbsp/powerpc/mpc8260ads/irq/irq.c +++ /dev/null @@ -1,372 +0,0 @@ -/* - * - * This file contains the implementation of the function described in irq.h - * - * Copyright (C) 1998, 1999 valette@crf.canon.fr - * - * Modified for mpc8260 Andy Dachs - * Surrey Satellite Technology Limited, 2000 - * 21/4/2002 Added support for nested interrupts and improved - * masking operations. Now we compute priority mask based - * on table in irq_init.c - * - * The license and distribution terms for this file may be - * found in the file LICENSE in this distribution or at - * http://www.rtems.org/license/LICENSE. - */ - -#include -#include -#include -#include -#include -#include -#include - -/* - * Check if symbolic IRQ name is an CPM IRQ - */ -static inline int is_cpm_irq(const rtems_irq_number irqLine) -{ - return (((int) irqLine <= BSP_CPM_IRQ_MAX_OFFSET) & - ((int) irqLine >= BSP_CPM_IRQ_LOWEST_OFFSET) - ); -} - -typedef struct { - uint32_t mask_h; /* mask for sipnr_h and simr_h */ - uint32_t mask_l; /* mask for sipnr_l and simr_l */ - uint32_t priority_h; /* mask this and lower priority ints */ - uint32_t priority_l; -} m82xxIrqMasks_t; - -static unsigned char irqPrioTable[BSP_CPM_IRQ_NUMBER]={ - /* - * actual priorities for interrupt : - */ - /* - * CPM Interrupts - */ - 0, 45, 63, 44, 66, 68, 35, 39, 50, 62, 34, 0, 30, 40, 52, 58, - 2, 3, 0, 5, 15, 16, 17, 18, 49, 51, 0, 0, 0, 0, 0, 0, - 6, 7, 8, 0, 11, 12, 0, 0, 20, 21, 22, 23, 0, 0, 0, 0, - 29, 31, 33, 37, 38, 41, 47, 48, 55, 56, 57, 60, 64, 65, 69, 70, - -}; - -/* - * Mask fields should have a '1' in the bit position for that - * interrupt. - * Priority masks calculated later based on priority table - */ - -static m82xxIrqMasks_t SIU_MaskBit[BSP_CPM_IRQ_NUMBER] = -{ - { 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, /* err */ - { 0x00000000, 0x00008000, 0x00000000, 0x00000000 }, /* i2c */ - { 0x00000000, 0x00004000, 0x00000000, 0x00000000 }, /* spi */ - { 0x00000000, 0x00002000, 0x00000000, 0x00000000 }, /* rtt */ - { 0x00000000, 0x00001000, 0x00000000, 0x00000000 }, /* smc1 */ - { 0x00000000, 0x00000800, 0x00000000, 0x00000000 }, /* smc2 */ - { 0x00000000, 0x00000400, 0x00000000, 0x00000000 }, /* idma1 */ - { 0x00000000, 0x00000200, 0x00000000, 0x00000000 }, /* idma2 */ - { 0x00000000, 0x00000100, 0x00000000, 0x00000000 }, /* idma3 */ - { 0x00000000, 0x00000080, 0x00000000, 0x00000000 }, /* idma4 */ - { 0x00000000, 0x00000040, 0x00000000, 0x00000000 }, /* sdma */ - { 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, /* reserved */ - { 0x00000000, 0x00000010, 0x00000000, 0x00000000 }, /* tmr1 */ - { 0x00000000, 0x00000008, 0x00000000, 0x00000000 }, /* tmr2 */ - { 0x00000000, 0x00000004, 0x00000000, 0x00000000 }, /* tmr3 */ - { 0x00000000, 0x00000002, 0x00000000, 0x00000000 }, /* tmr4 */ - { 0x00000004, 0x00000000, 0x00000000, 0x00000000 }, /* tmcnt */ - { 0x00000002, 0x00000000, 0x00000000, 0x00000000 }, /* pit */ - { 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, /* reserved */ - { 0x00004000, 0x00000000, 0x00000000, 0x00000000 }, /* irq1 */ - { 0x00002000, 0x00000000, 0x00000000, 0x00000000 }, /* irq2 */ - { 0x00001000, 0x00000000, 0x00000000, 0x00000000 }, /* irq3 */ - { 0x00000800, 0x00000000, 0x00000000, 0x00000000 }, /* irq4 */ - { 0x00000400, 0x00000000, 0x00000000, 0x00000000 }, /* irq5 */ - { 0x00000200, 0x00000000, 0x00000000, 0x00000000 }, /* irq6 */ - { 0x00000100, 0x00000000, 0x00000000, 0x00000000 }, /* irq7 */ - { 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, /* reserved */ - { 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, /* reserved */ - { 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, /* reserved */ - { 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, /* reserved */ - { 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, /* reserved */ - { 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, /* reserved */ - { 0x00000000, 0x80000000, 0x00000000, 0x00000000 }, /* fcc1 */ - { 0x00000000, 0x40000000, 0x00000000, 0x00000000 }, /* fcc2 */ - { 0x00000000, 0x20000000, 0x00000000, 0x00000000 }, /* fcc3 */ - { 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, /* reserved */ - { 0x00000000, 0x08000000, 0x00000000, 0x00000000 }, /* mcc1 */ - { 0x00000000, 0x04000000, 0x00000000, 0x00000000 }, /* mcc2 */ - { 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, /* reserved */ - { 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, /* reserved */ - { 0x00000000, 0x00800000, 0x00000000, 0x00000000 }, /* scc1 */ - { 0x00000000, 0x00400000, 0x00000000, 0x00000000 }, /* scc2 */ - { 0x00000000, 0x00200000, 0x00000000, 0x00000000 }, /* scc3 */ - { 0x00000000, 0x00100000, 0x00000000, 0x00000000 }, /* scc4 */ - { 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, /* reserved */ - { 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, /* reserved */ - { 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, /* reserved */ - { 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, /* reserved */ - { 0x00010000, 0x00000000, 0x00000000, 0x00000000 }, /* pc15 */ - { 0x00020000, 0x00000000, 0x00000000, 0x00000000 }, /* pc14 */ - { 0x00040000, 0x00000000, 0x00000000, 0x00000000 }, /* pc13 */ - { 0x00080000, 0x00000000, 0x00000000, 0x00000000 }, /* pc12 */ - { 0x00100000, 0x00000000, 0x00000000, 0x00000000 }, /* pc11 */ - { 0x00200000, 0x00000000, 0x00000000, 0x00000000 }, /* pc10 */ - { 0x00400000, 0x00000000, 0x00000000, 0x00000000 }, /* pc9 */ - { 0x00800000, 0x00000000, 0x00000000, 0x00000000 }, /* pc8 */ - { 0x01000000, 0x00000000, 0x00000000, 0x00000000 }, /* pc7 */ - { 0x02000000, 0x00000000, 0x00000000, 0x00000000 }, /* pc6 */ - { 0x04000000, 0x00000000, 0x00000000, 0x00000000 }, /* pc5 */ - { 0x08000000, 0x00000000, 0x00000000, 0x00000000 }, /* pc4 */ - { 0x10000000, 0x00000000, 0x00000000, 0x00000000 }, /* pc3 */ - { 0x20000000, 0x00000000, 0x00000000, 0x00000000 }, /* pc2 */ - { 0x40000000, 0x00000000, 0x00000000, 0x00000000 }, /* pc1 */ - { 0x80000000, 0x00000000, 0x00000000, 0x00000000 }, /* pc0 */ - -}; - -/* - * ------------------------ RTEMS Irq helper functions ---------------- - */ - -/* - * Caution : this function assumes the variable "internal_config" - * is already set and that the tables it contains are still valid - * and accessible. - */ -static void compute_SIU_IvectMask_from_prio (void) -{ - /* - * The actual masks defined - * correspond to the priorities defined - * for the SIU in irq_init.c. - */ - - int i,j; - - for( i=0; i maxLoop) maxLoop = loopCounter; -#endif - break; - } - - irq = (m8260.sivec >> 26) + BSP_CPM_IRQ_LOWEST_OFFSET; - - /* Clear mask and pending register */ - if( irq <= BSP_CPM_IRQ_MAX_OFFSET ) { - /* save interrupt masks */ - old_simr_h = m8260.simr_h; - old_simr_l = m8260.simr_l; - - /* mask off current interrupt and lower priority ones */ - m8260.simr_h &= SIU_MaskBit[irq].priority_h; - m8260.simr_l &= SIU_MaskBit[irq].priority_l; - - /* clear pending bit */ - m8260.sipnr_h |= SIU_MaskBit[irq].mask_h; - m8260.sipnr_l |= SIU_MaskBit[irq].mask_l; - - /* - * make sure, that the masking operations in - * ICTL and MSR are executed in order - */ - __asm__ volatile("sync":::"memory"); - - /* re-enable external exceptions */ - _CPU_MSR_GET(msr); - new_msr = msr | MSR_EE; - _CPU_MSR_SET(new_msr); - - /* call handler */ - bsp_interrupt_handler_dispatch(irq); - - /* disable exceptions again */ - _CPU_MSR_SET(msr); - - /* - * make sure, that the masking operations in - * ICTL and MSR are executed in order - */ - __asm__ volatile("sync":::"memory"); - - /* restore interrupt masks */ - m8260.simr_h = old_simr_h; - m8260.simr_l = old_simr_l; - - } -#ifdef DISPATCH_HANDLER_STAT - ++ loopCounter; -#endif - } - return 0; -} - -/* - * Initialize CPM interrupt management - */ -static void -BSP_CPM_irq_init(void) -{ - m8260.simr_l = 0; - m8260.simr_h = 0; - m8260.sipnr_l = 0xffffffff; - m8260.sipnr_h = 0xffffffff; - m8260.sicr = 0; - - /* - * Initialize the interrupt priorities. - */ - m8260.siprr = 0x05309770; /* reset value */ - m8260.scprr_h = 0x05309770; /* reset value */ - m8260.scprr_l = 0x05309770; /* reset value */ - -} - -void bsp_interrupt_vector_enable( rtems_vector_number irqnum) -{ - bsp_interrupt_assert(bsp_interrupt_is_valid_vector(irqnum)); - - if (is_cpm_irq(irqnum)) { - /* - * Enable interrupt at PIC level - */ - BSP_irq_enable_at_cpm (irqnum); - } -} - -void bsp_interrupt_vector_disable( rtems_vector_number irqnum) -{ - bsp_interrupt_assert(bsp_interrupt_is_valid_vector(irqnum)); - - if (is_cpm_irq(irqnum)) { - /* - * disable interrupt at PIC level - */ - BSP_irq_disable_at_cpm (irqnum); - } -} - -rtems_status_code bsp_interrupt_facility_initialize() -{ - /* Install exception handler */ - if (ppc_exc_set_handler( ASM_EXT_VECTOR, C_dispatch_irq_handler)) { - return RTEMS_IO_ERROR; - } - if (ppc_exc_set_handler( ASM_DEC_VECTOR, C_dispatch_irq_handler)) { - return RTEMS_IO_ERROR; - } - - /* Fill in priority masks */ - compute_SIU_IvectMask_from_prio(); - - /* Initialize the interrupt controller */ - BSP_CPM_irq_init(); - - return RTEMS_SUCCESSFUL; -} diff --git a/c/src/lib/libbsp/powerpc/mvme3100/Makefile.am b/c/src/lib/libbsp/powerpc/mvme3100/Makefile.am index bd453ee559..6cd02dceab 100644 --- a/c/src/lib/libbsp/powerpc/mvme3100/Makefile.am +++ b/c/src/lib/libbsp/powerpc/mvme3100/Makefile.am @@ -56,11 +56,11 @@ librtemsbsp_a_SOURCES += ../../../../../../bsps/powerpc/shared/console/uart.c librtemsbsp_a_SOURCES += ../../../../../../bsps/powerpc/shared/console/console.c # irq -librtemsbsp_a_SOURCES += irq/irq_init.c -librtemsbsp_a_SOURCES += ../shared/irq/openpic_i8259_irq.c +librtemsbsp_a_SOURCES += ../../../../../../bsps/powerpc/mvme3100/irq/irq_init.c +librtemsbsp_a_SOURCES += ../../../../../../bsps/powerpc/shared/irq/openpic_i8259_irq.c # openpic -librtemsbsp_a_SOURCES += ../shared/openpic/openpic.c +librtemsbsp_a_SOURCES += ../../../../../../bsps/powerpc/shared/irq/openpic.c # pci librtemsbsp_a_SOURCES += ../shared/pci/pci.c diff --git a/c/src/lib/libbsp/powerpc/mvme3100/irq/irq_init.c b/c/src/lib/libbsp/powerpc/mvme3100/irq/irq_init.c deleted file mode 100644 index c40692e688..0000000000 --- a/c/src/lib/libbsp/powerpc/mvme3100/irq/irq_init.c +++ /dev/null @@ -1,138 +0,0 @@ -/* irq_init.c - * - * This file contains the implementation of rtems initialization - * related to interrupt handling. - * - * CopyRight (C) 1999 valette@crf.canon.fr - * - * Enhanced by Jay Kulpinski - * to make it valid for MVME2300 Motorola boards. - * - * Till Straumann , 12/20/2001: - * Use the new interface to openpic_init - * - * Adapted for the mvme3100 BSP by T. Straumann, 2007. - * - * The license and distribution terms for this file may be - * found in the file LICENSE in this distribution or at - * http://www.rtems.org/license/LICENSE. - */ - -#include -#include -#include -#include -#include -#include -#include - -static void nop_func(void *unused) -{ - printk("Unhandled IRQ\n"); -} - -static rtems_irq_connect_data rtemsIrq[BSP_IRQ_NUMBER]; -static rtems_irq_global_settings initial_config; -static rtems_irq_connect_data defaultIrq = { - /* vectorIdex, hdl , handle , on , off , isOn */ - 0, nop_func , NULL , 0 , 0 , 0 -}; - -static rtems_irq_prio irqPrioTable[BSP_IRQ_NUMBER]={ - /* - * actual priorities for interrupt : - * 0 means that only current interrupt is masked - * 255 means all other interrupts are masked - */ - /* - * PCI Interrupts - */ - 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, /* for raven prio 0 means unactive... */ - 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, /* for raven prio 0 means unactive... */ - 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, /* for raven prio 0 means unactive... */ - /* - * Processor exceptions handled as interrupts - */ - 0 -}; - - /* - * This code assumes the exceptions management setup has already - * been done. We just need to replace the exceptions that will - * be handled like interrupt. On mcp750/mpc750 and many PPC processors - * this means the decrementer exception and the external exception. - */ -void BSP_rtems_irq_mng_init(unsigned cpuId) -{ - /* We should really have a way to find the number of sources - * the driver will use so that the size of the polarity-array - * matches the driver's idea of it. - */ - unsigned char pol[56]; - int i; - - /* Note: The openpic driver initializes only as many - * 'pic-external' interrupt sources as reported - * by the feature register. - * The 8540's openpic supports 12 core-external - * and 23 core-internal (both of these groups - * are external to the PIC, i.e., 'pic-external') - * interrupts but between the corresponding - * banks of vector/priority registers there is - * a gap leaving space for 4 (unsupported) irqs. - * The driver, not knowing of this gap, would - * initialize the 12 core-external sources - * followed by 4 unsupported sources and 19 - * core-internal sources thus leaving the last - * four core-internal sources uninitialized. - * Luckily, the feature register reports - * too many sources: - * - the 4 IPI plus 4 timer plus 4 messaging - * sources are included with the count - * - there are unused core-internal sources 24..32 - * which are also supported by the pic - * bringing the reported number of sources to - * a count of 56 (12+32+4+4+4) which is enough - * so that all pic-external sources are covered - * and initialized. - * - * NOTE: All core-internal sources are active-high. - * The manual says that setting the polarity - * to 'low/0' will disable the interrupt but - * I found this not to be true: on the device - * I tested the interrupt was asserted hard. - */ - - /* core-external sources on the mvme3100 are active-low, - * core-internal sources are active high. - */ - for (i=0; i, Sept. 2, 2007 - -As per implementation in shared PPC code, -the BSPirqPrioTable[96] listed in irq_init.c is where the -software developers can change the levels of priority -for all the interrupts based on the need of their -applications. The IRQs can be eanbled dynamically via the -BSP_enable_pic_irq(), or disbaled dynamically via the -BSP_disable_pic_irq(). - - -Support for run-time priority setup could be -added easily, but there is no action taken yet due to concerns -over computer security at VME CPU level. - - -The software developers are forbidden to setup picIsrTable[], -as it is a powerful engine for the BSP to find the pending -highest priority IRQ at run time. It ensures the fastest/faster -interrupt service to the highest/higher priority IRQ, if pending. diff --git a/c/src/lib/libbsp/powerpc/mvme5500/irq/BSP_irq.c b/c/src/lib/libbsp/powerpc/mvme5500/irq/BSP_irq.c deleted file mode 100644 index eb36cc2a80..0000000000 --- a/c/src/lib/libbsp/powerpc/mvme5500/irq/BSP_irq.c +++ /dev/null @@ -1,483 +0,0 @@ -/* - * This file contains the implementation of the function described in irq.h - */ - -/* - * Copyright (C) 1998, 1999 valette@crf.canon.fr - * - * The license and distribution terms for this file may be - * found in the file LICENSE in this distribution or at - * http://www.OARcorp.com/rtems/license.html. - * - * Acknowledgement May 2004, to Till Straumann - * for some inputs. - * - * Copyright 2003, 2004, 2005, 2007 Shuchen Kate Feng , - * NSLS, Brookhaven National Laboratory. All rights reserved. - * - * 1) Used GT_GPP_Value register instead of the GT_GPP_Interrupt_Cause - * register to monitor the cause of the level sensitive interrupts. - * (Copyright : NDA item) - * 2) The implementation of picPrioTable[] is an original work by the - * author to optimize the software IRQ priority scheduling because - * Discovery controller does not provide H/W IRQ priority schedule. - * It ensures the fastest/faster interrupt service to the - * highest/higher priority IRQ, if pendig. - * 3) _CPU_MSR_SET() needs RTEMS_COMPILER_MEMORY_BARRIER() - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include /* for printk */ -#include "bsp/gtreg.h" - -#define HI_INT_CAUSE 0x40000000 - -#define MAX_IRQ_LOOP 20 - -/* #define DEBUG_IRQ*/ - -/* - * pointer to the mask representing the additionnal irq vectors - * that must be disabled when a particular entry is activated. - * They will be dynamically computed from the table given - * in BSP_rtems_irq_mngt_set(); - * CAUTION : this table is accessed directly by interrupt routine - * prologue. - */ -static unsigned int BSP_irq_prio_mask_tbl[3][BSP_PIC_IRQ_NUMBER]; - -/* - * location used to store initial tables used for interrupt - * management.BSP copy of the configuration - */ -static rtems_irq_global_settings BSP_config; -static rtems_irq_connect_data* rtems_hdl_tbl; - -/* - * default handler connected on each irq after bsp initialization - * (locally cached copy) - */ -void (*default_rtems_hdl)(rtems_irq_hdl_param) = (void(*)(rtems_irq_hdl_param)) -1; - - -static volatile unsigned *BSP_irqMask_reg[3]; -static volatile unsigned *BSP_irqCause_reg[3]; -static volatile unsigned BSP_irqMask_cache[3]={0,0,0}; - -static int picPrioTblPtr=0; -static unsigned int GPPIrqInTbl=0; -static unsigned long long MainIrqInTbl=0; - -/* - * The software developers are forbidden to setup picPrioTable[], - * as it is a powerful engine for the BSP to find the pending - * highest priority IRQ at run time. It ensures the fastest/faster - * interrupt service to the highest/higher priority IRQ, if pendig. - * - * The picPrioTable[96] is updated dynamically at run time - * based on the priority levels set at BSPirqPrioTable[96], - * while the BSP_enable_irq_at_pic(), and BSP_disable_irq_at_pic() - * commands are invoked. - * - * The picPrioTable[96] lists the enabled CPU main and GPP external interrupt - * numbers [0 (lowest)- 95 (highest)] starting from the highest priority - * one to the lowest priority one. The highest priority interrupt is - * located at picPrioTable[0], and the lowest priority interrupt is located - * at picPrioTable[picPrioTblPtr-1]. - * - * - */ -#define DynamicIsrTable -#ifdef DynamicIsrTable -/* BitNums for Main Interrupt Lo/High Cause, -1 means invalid bit */ -static unsigned int picPrioTable[BSP_PIC_IRQ_NUMBER]={ - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1 }; -#else -static unsigned int picPrioTable[BSP_PIC_IRQ_NUMBER]={ - 80, 84, 76, 77, 32, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1 }; -#endif - -/* - * Check if IRQ is a MAIN CPU internal IRQ or GPP external IRQ - */ -static inline int is_pic_irq(const rtems_irq_number irqLine) -{ - return (((int) irqLine <= BSP_GPP_IRQ_MAX_OFFSET) & - ((int) irqLine >= BSP_MICL_IRQ_LOWEST_OFFSET) - ); -} - -/* - * Check if IRQ is a Porcessor IRQ - */ -static inline int is_processor_irq(const rtems_irq_number irqLine) -{ - return (((int) irqLine <= BSP_PROCESSOR_IRQ_MAX_OFFSET) & - ((int) irqLine >= BSP_PROCESSOR_IRQ_LOWEST_OFFSET) - ); -} - -/* - * ------------------------ RTEMS Irq helper functions ---------------- - */ - -/* - * Caution : this function assumes the variable "BSP_config" - * is already set and that the tables it contains are still valid - * and accessible. - */ -static void compute_pic_masks_from_prio(void) -{ - int i,j, k, isGppMain; - unsigned long long irq_prio_mask=0; - - /* - * Always mask at least current interrupt to prevent re-entrance - */ - for (i=0; i a equal priority. - */ - if (BSP_config.irqPrioTbl [i] >= BSP_config.irqPrioTbl [j]) - irq_prio_mask |= (unsigned long long)(1LLU << j); - } - - - BSP_irq_prio_mask_tbl[0][i] = irq_prio_mask & 0xffffffff; - BSP_irq_prio_mask_tbl[1][i] = (irq_prio_mask>>32) & 0xffffffff; -#if 0 - printk("irq_mask_prio_tbl[%d]:0x%8x%8x\n",i,BSP_irq_prio_mask_tbl[1][i], - BSP_irq_prio_mask_tbl[0][i]); -#endif - - BSP_irq_prio_mask_tbl[2][i] = 1<= BSP_config.irqPrioTbl [j]) - BSP_irq_prio_mask_tbl[2][i] |= 1 << (j-BSP_GPP_IRQ_LOWEST_OFFSET); - } -#if 0 - printk("GPPirq_mask_prio_tbl[%d]:0x%8x\n",i,BSP_irq_prio_mask_tbl[2][i]); -#endif - } -} - -static void UpdateMainIrqTbl(int irqNum) -{ - int i=0, j, shifted=0; - - switch (irqNum) { - case BSP_MAIN_GPP7_0_IRQ: - case BSP_MAIN_GPP15_8_IRQ: - case BSP_MAIN_GPP23_16_IRQ: - case BSP_MAIN_GPP31_24_IRQ: - return; /* Do nothing, let GPP take care of it */ - break; - } -#ifdef SHOW_MORE_INIT_SETTINGS - unsigned long val2, val1; -#endif - - /* If entry not in table*/ - if ( ((irqNumBSP_MICH_IRQ_MAX_OFFSET) && - (!(( 1 << (irqNum-BSP_GPP_IRQ_LOWEST_OFFSET)) & GPPIrqInTbl)))) - { - while ( picPrioTable[i]!=-1) { - if (BSP_config.irqPrioTbl[irqNum]>BSP_config.irqPrioTbl[picPrioTable[i]]) { - /* all other lower priority entries shifted right */ - for (j=picPrioTblPtr;j>i; j--) { - picPrioTable[j]=picPrioTable[j-1]; - } - picPrioTable[i]=irqNum; - shifted=1; - break; - } - i++; - } - if (!shifted) picPrioTable[picPrioTblPtr] =irqNum; - - if (irqNum >BSP_MICH_IRQ_MAX_OFFSET) - GPPIrqInTbl |= (1<< (irqNum-BSP_GPP_IRQ_LOWEST_OFFSET)); - else - MainIrqInTbl |= (unsigned long long)(1LLU << irqNum); - picPrioTblPtr++; - } -#ifdef SHOW_MORE_INIT_SETTINGS - val2 = (MainIrqInTbl>>32) & 0xffffffff; - val1 = MainIrqInTbl&0xffffffff; - printk("irqNum %d, MainIrqInTbl 0x%x%x\n", irqNum, val2, val1); - BSP_printPicIsrTbl(); -#endif - -} - - -static void CleanMainIrqTbl(int irqNum) -{ - int i, j; - - switch (irqNum) { - case BSP_MAIN_GPP7_0_IRQ: - case BSP_MAIN_GPP15_8_IRQ: - case BSP_MAIN_GPP23_16_IRQ: - case BSP_MAIN_GPP31_24_IRQ: - return; /* Do nothing, let GPP take care of it */ - break; - } - if ( ((irqNumBSP_MICH_IRQ_MAX_OFFSET) && - (( 1 << (irqNum-BSP_GPP_IRQ_LOWEST_OFFSET)) & GPPIrqInTbl))) - { /* If entry in table*/ - for (i=0; i<64; i++) { - if (picPrioTable[i]==irqNum) {/*remove it from the entry */ - /* all other lower priority entries shifted left */ - for (j=i;jBSP_MICH_IRQ_MAX_OFFSET) - GPPIrqInTbl &= ~(1<< (irqNum-BSP_GPP_IRQ_LOWEST_OFFSET)); - else - MainIrqInTbl &= ~(1LLU << irqNum); - picPrioTblPtr--; - break; - } - } - } -} - -void BSP_enable_irq_at_pic(const rtems_irq_number irqNum) -{ - unsigned bitNum, regNum; - unsigned int level; - - if ( !is_pic_irq(irqNum) ) - return; - - bitNum = (((unsigned int)irqNum) - BSP_MICL_IRQ_LOWEST_OFFSET)%32; - regNum = (((unsigned int)irqNum) - BSP_MICL_IRQ_LOWEST_OFFSET)>>5; - - rtems_interrupt_disable(level); - -#ifdef DynamicIsrTable - UpdateMainIrqTbl((int) irqNum); -#endif - BSP_irqMask_cache[regNum] |= (1 << bitNum); - - out_le32((volatile uint32_t *)BSP_irqMask_reg[regNum], BSP_irqMask_cache[regNum]); - while (in_le32((volatile uint32_t *)BSP_irqMask_reg[regNum]) != BSP_irqMask_cache[regNum]); - - rtems_interrupt_enable(level); -} - -int BSP_disable_irq_at_pic(const rtems_irq_number irqNum) -{ - int rval; - unsigned bitNum, regNum; - unsigned int level; - - if ( ! is_pic_irq(irqNum) ) - return -1; - - bitNum = (((unsigned int)irqNum) - BSP_MICL_IRQ_LOWEST_OFFSET)%32; - regNum = (((unsigned int)irqNum) - BSP_MICL_IRQ_LOWEST_OFFSET)>>5; - - rtems_interrupt_disable(level); - -#ifdef DynamicIsrTable - CleanMainIrqTbl((int) irqNum); -#endif - - rval = BSP_irqMask_cache[regNum] & (1<defaultEntry.hdl; - rtems_hdl_tbl = config->irqHdlTbl; - - /* Get ready for discovery BSP */ - BSP_irqMask_reg[0]= (volatile unsigned int *) (GT64x60_REG_BASE + GT64260_CPU_INT_MASK_LO); - BSP_irqMask_reg[1]= (volatile unsigned int *) (GT64x60_REG_BASE + GT64260_CPU_INT_MASK_HI); - BSP_irqCause_reg[0]= (volatile unsigned int *) (GT64x60_REG_BASE + GT64260_MAIN_INT_CAUSE_LO); - BSP_irqCause_reg[1]= (volatile unsigned int *) (GT64x60_REG_BASE + GT64260_MAIN_INT_CAUSE_HI); - BSP_irqMask_reg[2]= (volatile unsigned int *) (GT64x60_REG_BASE + GT_GPP_Interrupt_Mask); - BSP_irqCause_reg[2]= (volatile unsigned int *) (GT64x60_REG_BASE + GT_GPP_Value); - - /* Page 401, Table 598: - * Comm Unit Arbiter Control register : - * bit 10:GPP interrupts as level sensitive(1) or edge sensitive(0). - * MOTload default is set as level sensitive(1). Set it agin to make sure. - */ - out_le32((volatile uint32_t *)GT_CommUnitArb_Ctrl, - (in_le32((volatile uint32_t *)GT_CommUnitArb_Ctrl)| (1<<10))); - -#if 0 - printk("BSP_irqMask_reg[0] = 0x%" PRIx32 ", BSP_irqCause_reg[0] 0x%" PRIx32 "\n", - in_le32((volatile uint32_t *)BSP_irqMask_reg[0]), - in_le32((volatile uint32_t *)BSP_irqCause_reg[0])); - printk("BSP_irqMask_reg[1] = 0x%" PRIx32 ", BSP_irqCause_reg[1] 0x%" PRIx32 "\n", - in_le32((volatile uint32_t *)BSP_irqMask_reg[1]), - in_le32((volatile uint32_t *)BSP_irqCause_reg[1])); - printk("BSP_irqMask_reg[2] = 0x%" PRIx32 ", BSP_irqCause_reg[2] 0x%" PRIx32 "\n", - in_le32((volatile uint32_t *)BSP_irqMask_reg[2]), - in_le32((volatile uint32_t *)BSP_irqCause_reg[2])); -#endif - - /* Initialize the interrupt related registers */ - for (i=0; i<3; i++) { - out_le32((volatile uint32_t *)BSP_irqCause_reg[i], 0); - out_le32((volatile uint32_t *)BSP_irqMask_reg[i], 0); - } - in_le32((volatile uint32_t *)BSP_irqMask_reg[2]); - compute_pic_masks_from_prio(); - -#if 0 - printk("BSP_irqMask_reg[0] = 0x%" PRIx32 ", BSP_irqCause_reg[0] 0x%" PRIx32 "\n", - in_le32((volatile uint32_t *)BSP_irqMask_reg[0]), - in_le32((volatile uint32_t *)BSP_irqCause_reg[0])); - printk("BSP_irqMask_reg[1] = 0x%" PRIx32 ", BSP_irqCause_reg[1] 0x%" PRIx32 "\n", - in_le32((volatile uint32_t *)BSP_irqMask_reg[1]), - in_le32((volatile uint32_t *)BSP_irqCause_reg[1])); - printk("BSP_irqMask_reg[2] = 0x%" PRIx32 ", BSP_irqCause_reg[2] 0x%" PRIx32 "\n", - in_le32((volatile uint32_t *)BSP_irqMask_reg[2]), - in_le32((volatile uint32_t *)BSP_irqCause_reg[2])); -#endif - - /* - * - */ - for (i=BSP_MICL_IRQ_LOWEST_OFFSET; i < BSP_PROCESSOR_IRQ_LOWEST_OFFSET ; i++) { - if ( BSP_config.irqHdlTbl[i].hdl != BSP_config.defaultEntry.hdl) { - BSP_enable_irq_at_pic(i); - BSP_config.irqHdlTbl[i].on(&BSP_config.irqHdlTbl[i]); - } - else { - BSP_config.irqHdlTbl[i].off(&BSP_config.irqHdlTbl[i]); - BSP_disable_irq_at_pic(i); - } - } - for (i= BSP_MAIN_GPP7_0_IRQ; i < BSP_MAIN_GPP31_24_IRQ; i++) - BSP_enable_irq_at_pic(i); - - return(1); -} - -/* - * High level IRQ handler called from shared_raw_irq_code_entry - */ -int C_dispatch_irq_handler (BSP_Exception_frame *frame, unsigned int excNum) -{ - unsigned long irqCause[3]={0, 0,0}; - unsigned oldMask[3]={0,0,0}; - int loop=0, i=0, j; - int irq=0, group=0; - - if (excNum == ASM_DEC_VECTOR) { - bsp_irq_dispatch_list( rtems_hdl_tbl, BSP_DECREMENTER, default_rtems_hdl); - return 0; - } - - for (j=0; j<3; j++ ) oldMask[j] = BSP_irqMask_cache[j]; - for (j=0; j<3; j++) irqCause[j] = in_le32((volatile uint32_t *)BSP_irqCause_reg[j]) & in_le32((volatile uint32_t *)BSP_irqMask_reg[j]); - - while (((irq = picPrioTable[i++])!=-1)&& (loop++ < MAX_IRQ_LOOP)) - { - if (irqCause[group= irq/32] & ( 1<<(irq % 32))) { - for (j=0; j<3; j++) - BSP_irqMask_cache[j] &= (~ BSP_irq_prio_mask_tbl[j][irq]); - - out_le32((volatile uint32_t *)BSP_irqMask_reg[0], BSP_irqMask_cache[0]); - out_le32((volatile uint32_t *)BSP_irqMask_reg[1], BSP_irqMask_cache[1]); - out_le32((volatile uint32_t *)BSP_irqMask_reg[2], BSP_irqMask_cache[2]); - in_le32((volatile uint32_t *)BSP_irqMask_reg[2]); - - bsp_irq_dispatch_list( rtems_hdl_tbl, irq, default_rtems_hdl); - - for (j=0; j<3; j++ ) BSP_irqMask_cache[j] = oldMask[j]; - - out_le32((volatile uint32_t *)BSP_irqMask_reg[0], oldMask[0]); - out_le32((volatile uint32_t *)BSP_irqMask_reg[1], oldMask[1]); - out_le32((volatile uint32_t *)BSP_irqMask_reg[2], oldMask[2]); - in_le32((volatile uint32_t *)BSP_irqMask_reg[2]); - } - } - - return 0; -} - -/* Only print part of the entries for now */ -void BSP_printPicIsrTbl(void) -{ - int i; - - printf("picPrioTable[12]={ {irq# : "); - for (i=0; i<12; i++) - printf("%d,", picPrioTable[i]); - printf("}\n"); - - printf("GPPIrqInTbl: 0x%x :\n", GPPIrqInTbl); -} diff --git a/c/src/lib/libbsp/powerpc/mvme5500/irq/irq_init.c b/c/src/lib/libbsp/powerpc/mvme5500/irq/irq_init.c deleted file mode 100644 index ede4014f22..0000000000 --- a/c/src/lib/libbsp/powerpc/mvme5500/irq/irq_init.c +++ /dev/null @@ -1,148 +0,0 @@ -/* irq_init.c - * - * This file contains the implementation of rtems initialization - * related to interrupt handling. - * - * CopyRight (C) 1999 valette@crf.canon.fr - * - * Modified and added support for the MVME5500. - * Copyright 2003, 2004, 2005, Brookhaven National Laboratory and - * Shuchen Kate Feng - * - * The license and distribution terms for this file may be - * found in the file LICENSE in this distribution or at - * http://www.rtems.org/license/LICENSE - * - */ -#include -#include -#include -#include -#include /* ASM_EXT_VECTOR, ASM_DEC_VECTOR ... */ -/*#define TRACE_IRQ_INIT*/ - -/* - * default on/off function - */ -static void nop_func(void){} -/* - * default isOn function - */ -static int not_connected(void) {return 0;} - -static rtems_irq_connect_data rtemsIrq[BSP_IRQ_NUMBER]; -static rtems_irq_global_settings initial_config; - -static rtems_irq_connect_data defaultIrq = { - .name = 0, - .hdl = NULL, - .handle = NULL, - .on = (rtems_irq_enable) nop_func, - .off = (rtems_irq_disable) nop_func, - .isOn = (rtems_irq_is_enabled) not_connected, -#ifdef BSP_SHARED_HANDLER_SUPPORT - .next_handler = NULL -#endif -}; - -rtems_irq_prio BSPirqPrioTable[BSP_PIC_IRQ_NUMBER] = { - /* - * This table is where the developers can change the levels of priority - * based on the need of their applications. - * - * actual priorities for CPU MAIN and GPP interrupts (0-95) - * - * 0 means that only current interrupt is masked (lowest priority) - * 255 is only used by bits 24, 25, 26 and 27 of the CPU high - * interrupt Mask: (e.g. GPP7_0, GPP15_8, GPP23_16, GPP31_24). - * The IRQs of those four bits are always enabled. When it's used, - * the IRQ number is never listed in the dynamic picIsrTable[96]. - * - * The priorities of GPP interrupts were decided by their own - * value set at BSPirqPrioTable. - * - */ - /* CPU Main cause low interrupt */ - /* 0-15 */ - 0, 0, 0, 0, 0, 0, 0, 0, 64/*Timer*/, 0, 0, 0, 0, 0, 0, 0, - /* 16-31 */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - /* CPU Main cause high interrupt */ - /* 32-47 */ - 2/*10/100MHZ*/, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - /* 48-63 */ - 0, 0, 0, 0, 0, 0, 0, 0, - 255 /*GPP0-7*/, 255/*GPP8-15*/, 255/*GPP16-23*/, 255/*GPP24-31*/, 0, 0, 0, 0, - /* GPP interrupts */ - /* GPP0-7 */ - 1/*serial*/,0, 0, 0, 0, 0, 0, 0, - /* GPP8-15 */ - 47/*PMC1A*/,46/*PMC1B*/,45/*PMC1C*/,44/*PMC1D*/,30/*VME0*/, 29/*VME1*/,3,1, - /* GPP16-23 */ - 37/*PMC2A*/,36/*PMC2B*/,35/*PMC2C*/,34/*PMC2D*/,23/*1GHZ*/, 0,0,0, - /* GPP24-31 */ - 7/*watchdog*/, 0,0,0,0,0,0,0 -}; - -/* - * This code assumes the exceptions management setup has already - * been done. We just need to replace the exceptions that will - * be handled like interrupt. On MPC7455 and many PPC processors - * this means the decrementer exception and the external exception. - */ -void BSP_rtems_irq_mng_init(unsigned cpuId) -{ - int i; - rtems_interrupt_level level; - - /* - * First initialize the Interrupt management hardware - */ -#ifdef TRACE_IRQ_INIT - printk("Initializing the interrupt controller of the GT64260\n"); -#endif - -#ifdef TRACE_IRQ_INIT - printk("Going to re-initialize the rtemsIrq table %d\n",BSP_IRQ_NUMBER); -#endif - /* - * Initialize Rtems management interrupt table - */ - /* - * re-init the rtemsIrq table - */ - for (i = 0; i < BSP_IRQ_NUMBER; i++) { - rtemsIrq[i] = defaultIrq; - rtemsIrq[i].name = i; - } - - /* - * Init initial Interrupt management config - */ - initial_config.irqNb = BSP_IRQ_NUMBER; - initial_config.defaultEntry = defaultIrq; - initial_config.irqHdlTbl = rtemsIrq; - initial_config.irqBase = BSP_LOWEST_OFFSET; - initial_config.irqPrioTbl = BSPirqPrioTable; - -#ifdef TRACE_IRQ_INIT - printk("Going to setup irq mngt configuration\n"); -#endif - - rtems_interrupt_disable(level); - (void) level; /* avoid set but not used warning */ - - if (!BSP_rtems_irq_mngt_set(&initial_config)) { - /* - * put something here that will show the failure... - */ - rtems_panic("Unable to initialize RTEMS interrupt Management!!! System locked\n"); - } -#ifdef TRACE_IRQ_INIT - printk("Done setup irq mngt configuration\n"); -#endif - -#ifdef TRACE_IRQ_INIT - printk("RTEMS IRQ management is now operationnal\n"); -#endif -} diff --git a/c/src/lib/libbsp/powerpc/psim/Makefile.am b/c/src/lib/libbsp/powerpc/psim/Makefile.am index c9560601cb..fc9ee6eec8 100644 --- a/c/src/lib/libbsp/powerpc/psim/Makefile.am +++ b/c/src/lib/libbsp/powerpc/psim/Makefile.am @@ -38,9 +38,9 @@ librtemsbsp_a_SOURCES += ../../../../../../bsps/powerpc/psim/console/console-io. librtemsbsp_a_SOURCES += ../../../../../../bsps/powerpc/psim/console/consupp.S # irq -librtemsbsp_a_SOURCES += irq/irq_init.c -librtemsbsp_a_SOURCES += ../shared/irq/openpic_i8259_irq.c -librtemsbsp_a_SOURCES += ../shared/openpic/openpic.c +librtemsbsp_a_SOURCES += ../../../../../../bsps/powerpc/psim/irq/irq_init.c +librtemsbsp_a_SOURCES += ../../../../../../bsps/powerpc/shared/irq/openpic_i8259_irq.c +librtemsbsp_a_SOURCES += ../../../../../../bsps/powerpc/shared/irq/openpic.c librtemsbsp_a_SOURCES += ../../../../../../bsps/shared/irq/irq-default-handler.c # vectors diff --git a/c/src/lib/libbsp/powerpc/psim/irq/irq_init.c b/c/src/lib/libbsp/powerpc/psim/irq/irq_init.c deleted file mode 100644 index 3d2a82f2c0..0000000000 --- a/c/src/lib/libbsp/powerpc/psim/irq/irq_init.c +++ /dev/null @@ -1,125 +0,0 @@ -/* - * This file contains the implementation of rtems initialization - * related to interrupt handling - */ - -/* - * Copyright (C) 1999 valette@crf.canon.fr - * - * Enhanced by Jay Kulpinski - * to make it valid for MVME2300 Motorola boards. - * - * The license and distribution terms for this file may be - * found in the file LICENSE in this distribution or at - * http://www.rtems.org/license/LICENSE. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -static rtems_irq_connect_data rtemsIrq[BSP_IRQ_NUMBER]; -static rtems_irq_global_settings initial_config; -static rtems_irq_connect_data defaultIrq = { - /* vectorIdex, hdl , handle , on , off , isOn */ - 0, NULL, NULL , NULL, NULL, NULL -}; -static rtems_irq_prio irqPrioTable[BSP_IRQ_NUMBER]={ - /* - * Processor exceptions handled as interrupts - */ - 0 -}; - - /* - * This code assumes the exceptions management setup has already - * been done. We just need to replace the exceptions that will - * be handled like interrupt. On mcp750/mpc750 and many PPC processors - * this means the decrementer exception and the external exception. - */ -void BSP_rtems_irq_mng_init(unsigned cpuId) -{ - int i; - - /* - * First initialize the Interrupt management hardware - */ - OpenPIC = (void*)PSIM.OpenPIC; - openpic_init(1,0,0,16,0,0); - - /* - * Initialize Rtems management interrupt table - */ - /* - * re-init the rtemsIrq table - */ - for (i = 0; i < BSP_IRQ_NUMBER; i++) { - rtemsIrq[i] = defaultIrq; - rtemsIrq[i].name = i; - } - /* - * Init initial Interrupt management config - */ - initial_config.irqNb = BSP_IRQ_NUMBER; - initial_config.defaultEntry = defaultIrq; - initial_config.irqHdlTbl = rtemsIrq; - initial_config.irqBase = BSP_LOWEST_OFFSET; - initial_config.irqPrioTbl = irqPrioTable; - - for (i = BSP_PCI_IRQ_LOWEST_OFFSET; i< BSP_PCI_IRQ_NUMBER; i++ ) { - irqPrioTable[i] = 8; - } - - if (!BSP_rtems_irq_mngt_set(&initial_config)) { - /* - * put something here that will show the failure... - */ - rtems_panic( - "Unable to initialize RTEMS interrupt Management!!! System locked\n" - ); - } - - #ifdef TRACE_IRQ_INIT - printk("RTEMS IRQ management is now operationnal\n"); - #endif -} - -static int psim_exception_handler( - BSP_Exception_frame *frame, - unsigned exception_number -) -{ - rtems_panic("Unexpected interrupt occured"); - return 0; -} - -/* - * functions to enable/disable a source at the ipic - */ -void bsp_interrupt_vector_enable( rtems_vector_number irqnum) -{ - /* FIXME: do something */ - bsp_interrupt_assert(bsp_interrupt_is_valid_vector(irqnum)); -} - -void bsp_interrupt_vector_disable( rtems_vector_number irqnum) -{ - /* FIXME: do something */ - bsp_interrupt_assert(bsp_interrupt_is_valid_vector(irqnum)); -} - -rtems_status_code bsp_interrupt_facility_initialize(void) -{ - /* Install exception handler */ - if (ppc_exc_set_handler( ASM_EXT_VECTOR, psim_exception_handler)) { - return RTEMS_IO_ERROR; - } - - return RTEMS_SUCCESSFUL; -} diff --git a/c/src/lib/libbsp/powerpc/qemuppc/Makefile.am b/c/src/lib/libbsp/powerpc/qemuppc/Makefile.am index d87eb49b56..a7facf5712 100644 --- a/c/src/lib/libbsp/powerpc/qemuppc/Makefile.am +++ b/c/src/lib/libbsp/powerpc/qemuppc/Makefile.am @@ -36,7 +36,7 @@ librtemsbsp_a_SOURCES += ../../../../../../bsps/powerpc/qemuppc/console/console- # irq librtemsbsp_a_SOURCES += ../../../../../../bsps/shared/irq/irq-default-handler.c -librtemsbsp_a_SOURCES += irq/irq_init.c +librtemsbsp_a_SOURCES += ../../../../../../bsps/powerpc/qemuppc/irq/irq_init.c librtemsbsp_a_SOURCES += ../../../../../../bsps/powerpc/shared/cache/cache.c librtemsbsp_a_SOURCES += ../../../../../../bsps/powerpc/shared/btimer/btimer-ppc-dec.c diff --git a/c/src/lib/libbsp/powerpc/qemuppc/irq/irq_init.c b/c/src/lib/libbsp/powerpc/qemuppc/irq/irq_init.c deleted file mode 100644 index 24b15dcd49..0000000000 --- a/c/src/lib/libbsp/powerpc/qemuppc/irq/irq_init.c +++ /dev/null @@ -1,61 +0,0 @@ -/*===============================================================*\ -| Project: RTEMS generic MPC83xx BSP | -+-----------------------------------------------------------------+ -| Copyright (c) 2007 | -| Embedded Brains GmbH | -| Obere Lagerstr. 30 | -| D-82178 Puchheim | -| Germany | -| rtems@embedded-brains.de | -+-----------------------------------------------------------------+ -| The license and distribution terms for this file may be | -| found in the file LICENSE in this distribution or at | -| | -| http://www.rtems.org/license/LICENSE. | -| | -+-----------------------------------------------------------------+ -| this file integrates the IPIC irq controller | -\*===============================================================*/ - -#include - -#include - -#include -#include -#include -#include - -static int qemuppc_exception_handler( - BSP_Exception_frame *frame, - unsigned exception_number -) -{ - rtems_panic("Unexpected interrupt occured"); - return 0; -} - -/* - * functions to enable/disable a source at the ipic - */ -void bsp_interrupt_vector_enable( rtems_vector_number irqnum) -{ - /* FIXME: do something */ - bsp_interrupt_assert(bsp_interrupt_is_valid_vector(irqnum)); -} - -void bsp_interrupt_vector_disable( rtems_vector_number irqnum) -{ - /* FIXME: do something */ - bsp_interrupt_assert(bsp_interrupt_is_valid_vector(irqnum)); -} - -rtems_status_code bsp_interrupt_facility_initialize(void) -{ - /* Install exception handler */ - if (ppc_exc_set_handler( ASM_EXT_VECTOR, qemuppc_exception_handler)) { - return RTEMS_IO_ERROR; - } - - return RTEMS_SUCCESSFUL; -} diff --git a/c/src/lib/libbsp/powerpc/qoriq/Makefile.am b/c/src/lib/libbsp/powerpc/qoriq/Makefile.am index 6f6972ca2b..3e18139f32 100644 --- a/c/src/lib/libbsp/powerpc/qoriq/Makefile.am +++ b/c/src/lib/libbsp/powerpc/qoriq/Makefile.am @@ -62,7 +62,7 @@ librtemsbsp_a_SOURCES += ../../../../../../bsps/powerpc/qoriq/btimer/btimer.c # IRQ librtemsbsp_a_SOURCES += ../../../../../../bsps/shared/irq/irq-default-handler.c -librtemsbsp_a_SOURCES += irq/irq.c +librtemsbsp_a_SOURCES += ../../../../../../bsps/powerpc/qoriq/irq/irq.c # Console librtemsbsp_a_SOURCES += ../../../../../../bsps/shared/dev/serial/console-termios-init.c diff --git a/c/src/lib/libbsp/powerpc/qoriq/irq/irq.c b/c/src/lib/libbsp/powerpc/qoriq/irq/irq.c deleted file mode 100644 index 625b9fce1b..0000000000 --- a/c/src/lib/libbsp/powerpc/qoriq/irq/irq.c +++ /dev/null @@ -1,387 +0,0 @@ -/** - * @file - * - * @ingroup QorIQ - * - * @brief Interrupt implementation. - */ - -/* - * Copyright (c) 2010, 2017 embedded brains GmbH. All rights reserved. - * - * embedded brains GmbH - * Dornierstr. 4 - * 82178 Puchheim - * Germany - * - * - * The license and distribution terms for this file may be - * found in the file LICENSE in this distribution or at - * http://www.rtems.org/license/LICENSE. - */ - -#include - -#include - -#include - -#include - -#include -#include -#include -#include -#include -#include - -#ifdef RTEMS_SMP -#include -#endif - -RTEMS_INTERRUPT_LOCK_DEFINE(static, lock, "QorIQ IRQ") - -#define SPURIOUS 0xffff - -#ifdef QORIQ_IS_HYPERVISOR_GUEST - -void bsp_interrupt_set_affinity( - rtems_vector_number vector, - const Processor_mask *affinity -) -{ - uint32_t config; - unsigned int priority; - uint32_t destination; - uint32_t new_destination; - rtems_interrupt_lock_context lock_context; - - new_destination = _Processor_mask_Find_last_set(affinity) - 1; - - rtems_interrupt_lock_acquire(&lock, &lock_context); - ev_int_get_config(vector, &config, &priority, &destination); - ev_int_set_config(vector, config, priority, new_destination); - rtems_interrupt_lock_release(&lock, &lock_context); -} - -void bsp_interrupt_get_affinity( - rtems_vector_number vector, - Processor_mask *affinity -) -{ - uint32_t config; - unsigned int priority; - uint32_t destination; - - ev_int_get_config(vector, &config, &priority, &destination); - _Processor_mask_From_uint32_t(affinity, destination, 0); -} - -void bsp_interrupt_vector_enable(rtems_vector_number vector) -{ - bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector)); - ev_int_set_mask(vector, 0); -} - -void bsp_interrupt_vector_disable(rtems_vector_number vector) -{ - bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector)); - ev_int_set_mask(vector, 1); -} - -void bsp_interrupt_dispatch(uintptr_t exception_number) -{ - unsigned int vector; - - if (exception_number == 10) { - qoriq_decrementer_dispatch(); - return; - } - -#ifdef RTEMS_SMP - if (exception_number == 36) { - _SMP_Inter_processor_interrupt_handler(); - return; - } -#endif - - /* - * This works only if the "has-external-proxy" property is present in the - * "epapr,hv-pic" device tree node. - */ - vector = PPC_SPECIAL_PURPOSE_REGISTER(FSL_EIS_EPR); - - if (vector != SPURIOUS) { - uint32_t msr; - - msr = ppc_external_exceptions_enable(); - bsp_interrupt_handler_dispatch(vector); - ppc_external_exceptions_disable(msr); - - ev_int_eoi(vector); - } else { - bsp_interrupt_handler_default(vector); - } -} - -rtems_status_code bsp_interrupt_facility_initialize(void) -{ - unsigned int i; - - for (i = BSP_INTERRUPT_VECTOR_MIN; i <= BSP_INTERRUPT_VECTOR_MAX; ++i) { - uint32_t config; - unsigned int priority; - uint32_t destination; - unsigned int err; - - err = ev_int_get_config(i, &config, &priority, &destination); - if (err != EV_SUCCESS) - continue; - - priority = QORIQ_PIC_PRIORITY_DEFAULT; - - ev_int_set_config(i, config, priority, destination); - } - - return RTEMS_SUCCESSFUL; -} - -#else /* !QORIQ_IS_HYPERVISOR_GUEST */ - -#define VPR_MSK BSP_BBIT32(0) -#define VPR_A BSP_BBIT32(1) -#define VPR_P BSP_BBIT32(8) -#define VPR_S BSP_BBIT32(9) -#define VPR_PRIORITY(val) BSP_BFLD32(val, 12, 15) -#define VPR_PRIORITY_GET(reg) BSP_BFLD32GET(reg, 12, 15) -#define VPR_PRIORITY_SET(reg, val) BSP_BFLD32SET(reg, val, 12, 15) -#define VPR_VECTOR(val) BSP_BFLD32(val, 16, 31) -#define VPR_VECTOR_GET(reg) BSP_BFLD32GET(reg, 16, 31) -#define VPR_VECTOR_SET(reg, val) BSP_BFLD32SET(reg, val, 16, 31) - -#define GCR_RST BSP_BBIT32(0) -#define GCR_M BSP_BBIT32(2) - -#define SRC_CFG_IDX(i) ((i) - QORIQ_IRQ_EXT_BASE) - -static const uint16_t src_cfg_offsets [] = { - [SRC_CFG_IDX(QORIQ_IRQ_EXT_0)] = 0x10000 >> 4, - [SRC_CFG_IDX(QORIQ_IRQ_EXT_1)] = 0x10020 >> 4, - [SRC_CFG_IDX(QORIQ_IRQ_EXT_2)] = 0x10040 >> 4, - [SRC_CFG_IDX(QORIQ_IRQ_EXT_3)] = 0x10060 >> 4, - [SRC_CFG_IDX(QORIQ_IRQ_EXT_4)] = 0x10080 >> 4, - [SRC_CFG_IDX(QORIQ_IRQ_EXT_5)] = 0x100a0 >> 4, - [SRC_CFG_IDX(QORIQ_IRQ_EXT_6)] = 0x100c0 >> 4, - [SRC_CFG_IDX(QORIQ_IRQ_EXT_7)] = 0x100e0 >> 4, - [SRC_CFG_IDX(QORIQ_IRQ_EXT_8)] = 0x10100 >> 4, - [SRC_CFG_IDX(QORIQ_IRQ_EXT_9)] = 0x10120 >> 4, - [SRC_CFG_IDX(QORIQ_IRQ_EXT_10)] = 0x10140 >> 4, - [SRC_CFG_IDX(QORIQ_IRQ_EXT_11)] = 0x10160 >> 4, - [SRC_CFG_IDX(QORIQ_IRQ_IPI_0)] = 0x010a0 >> 4, - [SRC_CFG_IDX(QORIQ_IRQ_IPI_1)] = 0x010b0 >> 4, - [SRC_CFG_IDX(QORIQ_IRQ_IPI_2)] = 0x010c0 >> 4, - [SRC_CFG_IDX(QORIQ_IRQ_IPI_3)] = 0x010d0 >> 4, - [SRC_CFG_IDX(QORIQ_IRQ_MI_0)] = 0x11600 >> 4, - [SRC_CFG_IDX(QORIQ_IRQ_MI_1)] = 0x11620 >> 4, - [SRC_CFG_IDX(QORIQ_IRQ_MI_2)] = 0x11640 >> 4, - [SRC_CFG_IDX(QORIQ_IRQ_MI_3)] = 0x11660 >> 4, - [SRC_CFG_IDX(QORIQ_IRQ_MI_4)] = 0x11680 >> 4, - [SRC_CFG_IDX(QORIQ_IRQ_MI_5)] = 0x116a0 >> 4, - [SRC_CFG_IDX(QORIQ_IRQ_MI_6)] = 0x116c0 >> 4, - [SRC_CFG_IDX(QORIQ_IRQ_MI_7)] = 0x116e0 >> 4, - [SRC_CFG_IDX(QORIQ_IRQ_MSI_0)] = 0x11c00 >> 4, - [SRC_CFG_IDX(QORIQ_IRQ_MSI_1)] = 0x11c20 >> 4, - [SRC_CFG_IDX(QORIQ_IRQ_MSI_2)] = 0x11c40 >> 4, - [SRC_CFG_IDX(QORIQ_IRQ_MSI_3)] = 0x11c60 >> 4, - [SRC_CFG_IDX(QORIQ_IRQ_MSI_4)] = 0x11c80 >> 4, - [SRC_CFG_IDX(QORIQ_IRQ_MSI_5)] = 0x11ca0 >> 4, - [SRC_CFG_IDX(QORIQ_IRQ_MSI_6)] = 0x11cc0 >> 4, - [SRC_CFG_IDX(QORIQ_IRQ_MSI_7)] = 0x11ce0 >> 4, - [SRC_CFG_IDX(QORIQ_IRQ_GT_A_0)] = 0x01120 >> 4, - [SRC_CFG_IDX(QORIQ_IRQ_GT_A_1)] = 0x01160 >> 4, - [SRC_CFG_IDX(QORIQ_IRQ_GT_A_2)] = 0x011a0 >> 4, - [SRC_CFG_IDX(QORIQ_IRQ_GT_A_3)] = 0x011e0 >> 4, - [SRC_CFG_IDX(QORIQ_IRQ_GT_B_0)] = 0x02120 >> 4, - [SRC_CFG_IDX(QORIQ_IRQ_GT_B_1)] = 0x02160 >> 4, - [SRC_CFG_IDX(QORIQ_IRQ_GT_B_2)] = 0x021a0 >> 4, - [SRC_CFG_IDX(QORIQ_IRQ_GT_B_3)] = 0x021e0 >> 4 -}; - -static volatile qoriq_pic_src_cfg *get_src_cfg(rtems_vector_number vector) -{ - uint32_t n = MIN(RTEMS_ARRAY_SIZE(qoriq.pic.ii_0), QORIQ_IRQ_EXT_BASE); - - if (vector < n) { - return &qoriq.pic.ii_0 [vector]; - } else if (vector < QORIQ_IRQ_EXT_BASE) { - return &qoriq.pic.ii_1 [vector - n]; - } else { - uintptr_t offs = ((uintptr_t) - src_cfg_offsets [vector - QORIQ_IRQ_EXT_BASE]) << 4; - - return (volatile qoriq_pic_src_cfg *) ((uintptr_t) &qoriq.pic + offs); - } -} - -rtems_status_code qoriq_pic_set_priority( - rtems_vector_number vector, - int new_priority, - int *old_priority -) -{ - rtems_status_code sc = RTEMS_SUCCESSFUL; - uint32_t old_vpr = 0; - - if (bsp_interrupt_is_valid_vector(vector)) { - volatile qoriq_pic_src_cfg *src_cfg = get_src_cfg(vector); - - if (QORIQ_PIC_PRIORITY_IS_VALID(new_priority)) { - rtems_interrupt_lock_context lock_context; - - rtems_interrupt_lock_acquire(&lock, &lock_context); - old_vpr = src_cfg->vpr; - src_cfg->vpr = VPR_PRIORITY_SET(old_vpr, (uint32_t) new_priority); - rtems_interrupt_lock_release(&lock, &lock_context); - } else if (new_priority < 0) { - old_vpr = src_cfg->vpr; - } else { - sc = RTEMS_INVALID_PRIORITY; - } - } else { - sc = RTEMS_INVALID_ID; - } - - if (old_priority != NULL) { - *old_priority = (int) VPR_PRIORITY_GET(old_vpr); - } - - return sc; -} - -void bsp_interrupt_set_affinity( - rtems_vector_number vector, - const Processor_mask *affinity -) -{ - volatile qoriq_pic_src_cfg *src_cfg = get_src_cfg(vector); - - src_cfg->dr = _Processor_mask_To_uint32_t(affinity, 0); -} - -void bsp_interrupt_get_affinity( - rtems_vector_number vector, - Processor_mask *affinity -) -{ - volatile qoriq_pic_src_cfg *src_cfg = get_src_cfg(vector); - - _Processor_mask_From_uint32_t(affinity, src_cfg->dr, 0); -} - -static void pic_vector_enable(rtems_vector_number vector, uint32_t msk) -{ - volatile qoriq_pic_src_cfg *src_cfg = get_src_cfg(vector); - rtems_interrupt_lock_context lock_context; - - bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector)); - - rtems_interrupt_lock_acquire(&lock, &lock_context); - src_cfg->vpr = (src_cfg->vpr & ~VPR_MSK) | msk; - rtems_interrupt_lock_release(&lock, &lock_context); -} - -void bsp_interrupt_vector_enable(rtems_vector_number vector) -{ - pic_vector_enable(vector, 0); -} - -void bsp_interrupt_vector_disable(rtems_vector_number vector) -{ - pic_vector_enable(vector, VPR_MSK); -} - -void bsp_interrupt_dispatch(uintptr_t exception_number) -{ - rtems_vector_number vector = qoriq.pic.iack; - - if (vector != SPURIOUS) { - uint32_t msr = ppc_external_exceptions_enable(); - - bsp_interrupt_handler_dispatch(vector); - - ppc_external_exceptions_disable(msr); - - qoriq.pic.eoi = 0; - qoriq.pic.whoami; - } else { - bsp_interrupt_handler_default(vector); - } -} - -static bool pic_is_ipi(rtems_vector_number vector) -{ - return QORIQ_IRQ_IPI_0 <= vector && vector <= QORIQ_IRQ_IPI_3; -} - -static void pic_reset(void) -{ - qoriq.pic.gcr = GCR_RST; - while ((qoriq.pic.gcr & GCR_RST) != 0) { - /* Wait */ - } -} - -static void pic_global_timer_init(void) -{ - int i = 0; - - qoriq.pic.tcra = 0; - qoriq.pic.tcrb = 0; - - for (i = 0; i < 4; ++i) { - qoriq.pic.gta [0].bcr = GTBCR_CI; - qoriq.pic.gtb [0].bcr = GTBCR_CI; - } -} - -rtems_status_code bsp_interrupt_facility_initialize(void) -{ - rtems_vector_number i = 0; - uint32_t processor_id = ppc_processor_id(); - - if (processor_id == 0) { - /* Core 0 must do the basic initialization */ - - pic_reset(); - - for (i = BSP_INTERRUPT_VECTOR_MIN; i <= BSP_INTERRUPT_VECTOR_MAX; ++i) { - volatile qoriq_pic_src_cfg *src_cfg = get_src_cfg(i); - - src_cfg->vpr = VPR_MSK | VPR_P - | VPR_PRIORITY(QORIQ_PIC_PRIORITY_DEFAULT) | VPR_VECTOR(i); - - if (!pic_is_ipi(i)) { - src_cfg->dr = 0x1; - } - } - - qoriq.pic.mer03 = 0xf; - qoriq.pic.mer47 = 0xf; - qoriq.pic.svr = SPURIOUS; - qoriq.pic.gcr = GCR_M; - - pic_global_timer_init(); - } - - qoriq.pic.ctpr = 0; - - for (i = BSP_INTERRUPT_VECTOR_MIN; i <= BSP_INTERRUPT_VECTOR_MAX; ++i) { - qoriq.pic.iack; - qoriq.pic.eoi = 0; - qoriq.pic.whoami; - } - - return RTEMS_SUCCESSFUL; -} - -#endif /* QORIQ_IS_HYPERVISOR_GUEST */ diff --git a/c/src/lib/libbsp/powerpc/shared/irq/i8259.c b/c/src/lib/libbsp/powerpc/shared/irq/i8259.c deleted file mode 100644 index 7363e87ba0..0000000000 --- a/c/src/lib/libbsp/powerpc/shared/irq/i8259.c +++ /dev/null @@ -1,149 +0,0 @@ -/* - * This file contains the implementation of the function described in irq.h - * related to Intel 8259 Programmable Interrupt controller. - * - * Copyright (C) 1998, 1999 valette@crf.canon.fr - * - * The license and distribution terms for this file may be - * found in the file LICENSE in this distribution or at - * http://www.rtems.org/license/LICENSE. - */ - -#include -#include - -/*-------------------------------------------------------------------------+ -| Cache for 1st and 2nd PIC IRQ line's status (enabled or disabled) register. -+--------------------------------------------------------------------------*/ -/* - * lower byte is interrupt mask on the master PIC. - * while upper bits are interrupt on the slave PIC. - */ -volatile rtems_i8259_masks i8259s_cache = 0xfffb; - -/*-------------------------------------------------------------------------+ -| Function: BSP_irq_disable_at_i8259s -| Description: Mask IRQ line in appropriate PIC chip. -| Global Variables: i8259s_cache -| Arguments: vector_offset - number of IRQ line to mask. -| Returns: original state or -1 on error. -+--------------------------------------------------------------------------*/ -int BSP_irq_disable_at_i8259s (const rtems_irq_number irqLine) -{ - unsigned short mask; - rtems_interrupt_level level; - int rval; - - if ( ((int)irqLine < BSP_ISA_IRQ_LOWEST_OFFSET) || - ((int)irqLine > BSP_ISA_IRQ_MAX_OFFSET) - ) - return -1; - - rtems_interrupt_disable(level); - - mask = 1 << irqLine; - rval = i8259s_cache & mask ? 0 : 1; - i8259s_cache |= mask; - - if (irqLine < 8) - { - outport_byte(PIC_MASTER_IMR_IO_PORT, i8259s_cache & 0xff); - } - else - { - outport_byte(PIC_SLAVE_IMR_IO_PORT, ((i8259s_cache & 0xff00) >> 8)); - } - rtems_interrupt_enable(level); - - return rval; -} - -/*-------------------------------------------------------------------------+ -| Function: BSP_irq_enable_at_i8259s -| Description: Unmask IRQ line in appropriate PIC chip. -| Global Variables: i8259s_cache -| Arguments: irqLine - number of IRQ line to mask. -| Returns: Nothing. -+--------------------------------------------------------------------------*/ -int BSP_irq_enable_at_i8259s (const rtems_irq_number irqLine) -{ - unsigned short mask; - rtems_interrupt_level level; - - if ( ((int)irqLine < BSP_ISA_IRQ_LOWEST_OFFSET) || - ((int)irqLine > BSP_ISA_IRQ_MAX_OFFSET ) - ) - return 1; - - rtems_interrupt_disable(level); - - mask = ~(1 << irqLine); - i8259s_cache &= mask; - - if (irqLine < 8) - { - outport_byte(PIC_MASTER_IMR_IO_PORT, i8259s_cache & 0xff); - } - else - { - outport_byte(PIC_SLAVE_IMR_IO_PORT, ((i8259s_cache & 0xff00) >> 8)); - } - rtems_interrupt_enable(level); - - return 0; -} /* mask_irq */ - -int BSP_irq_enabled_at_i8259s (const rtems_irq_number irqLine) -{ - unsigned short mask; - - if ( ((int)irqLine < BSP_ISA_IRQ_LOWEST_OFFSET) || - ((int)irqLine > BSP_ISA_IRQ_MAX_OFFSET) - ) - return 1; - - mask = (1 << irqLine); - return (~(i8259s_cache & mask)); -} - -/*-------------------------------------------------------------------------+ -| Function: BSP_irq_ack_at_i8259s -| Description: Signal generic End Of Interrupt (EOI) to appropriate PIC. -| Global Variables: None. -| Arguments: irqLine - number of IRQ line to acknowledge. -| Returns: Nothing. -+--------------------------------------------------------------------------*/ -int BSP_irq_ack_at_i8259s (const rtems_irq_number irqLine) -{ - if (irqLine >= 8) { - outport_byte(PIC_MASTER_COMMAND_IO_PORT, SLAVE_PIC_EOSI); - outport_byte(PIC_SLAVE_COMMAND_IO_PORT, (PIC_EOSI | (irqLine - 8))); - } - else { - outport_byte(PIC_MASTER_COMMAND_IO_PORT, (PIC_EOSI | irqLine)); - } - - return 0; - -} /* ackIRQ */ - -void BSP_i8259s_init(void) -{ - /* - * init master 8259 interrupt controller - */ - outport_byte(PIC_MASTER_COMMAND_IO_PORT, 0x11); /* Start init sequence */ - outport_byte(PIC_MASTER_IMR_IO_PORT, 0x00);/* Vector base = 0 */ - outport_byte(PIC_MASTER_IMR_IO_PORT, 0x04);/* edge tiggered, Cascade (slave) on IRQ2 */ - outport_byte(PIC_MASTER_IMR_IO_PORT, 0x01);/* Select 8086 mode */ - outport_byte(PIC_MASTER_IMR_IO_PORT, 0xFB); /* Mask all except cascade */ - /* - * init slave interrupt controller - */ - outport_byte(PIC_SLAVE_COMMAND_IO_PORT, 0x11); /* Start init sequence */ - outport_byte(PIC_SLAVE_IMR_IO_PORT, 0x08);/* Vector base = 8 */ - outport_byte(PIC_SLAVE_IMR_IO_PORT, 0x02);/* edge triggered, Cascade (slave) on IRQ2 */ - outport_byte(PIC_SLAVE_IMR_IO_PORT, 0x01); /* Select 8086 mode */ - outport_byte(PIC_SLAVE_IMR_IO_PORT, 0xFF); /* Mask all */ - -} diff --git a/c/src/lib/libbsp/powerpc/shared/irq/irq_init.c b/c/src/lib/libbsp/powerpc/shared/irq/irq_init.c deleted file mode 100644 index 1a44992a5b..0000000000 --- a/c/src/lib/libbsp/powerpc/shared/irq/irq_init.c +++ /dev/null @@ -1,364 +0,0 @@ -/* irq_init.c - * - * This file contains the implementation of rtems initialization - * related to interrupt handling. - * - * CopyRight (C) 1999 valette@crf.canon.fr - * - * Enhanced by Jay Kulpinski - * to make it valid for MVME2300 Motorola boards. - * - * Till Straumann , 12/20/2001: - * Use the new interface to openpic_init - * - * The license and distribution terms for this file may be - * found in the file LICENSE in this distribution or at - * http://www.rtems.org/license/LICENSE. - */ - -#include -#include -#include -#include -#include -#if BSP_PCI_IRQ_NUMBER > 0 -#include -#endif -#include -#include -#include -#include - -typedef struct { - unsigned char bus; /* few chance the PCI/ISA bridge is not on first bus but ... */ - unsigned char device; - unsigned char function; -} pci_isa_bridge_device; - -pci_isa_bridge_device* via_82c586 = 0; -#ifndef qemu -static pci_isa_bridge_device bridge; -#endif - -/* - * default methods - */ -static void nop_hdl(rtems_irq_hdl_param ignored) -{ -} - -static void nop_irq_enable(const struct __rtems_irq_connect_data__*ignored) -{ -} - -static int irq_is_connected(const struct __rtems_irq_connect_data__*ignored) -{ - return 0; -} - - -static rtems_irq_connect_data rtemsIrq[BSP_IRQ_NUMBER]; -static rtems_irq_global_settings initial_config; -static rtems_irq_connect_data defaultIrq = { - 0, /* vector */ - nop_hdl, /* hdl */ - NULL, /* handle */ - nop_irq_enable, /* on */ - nop_irq_enable, /* off */ - irq_is_connected /* isOn */ -#ifdef BSP_SHARED_HANDLER_SUPPORT - , NULL /* next_handler */ -#endif -}; -static rtems_irq_prio irqPrioTable[BSP_IRQ_NUMBER]={ - /* - * actual priorities for interrupt : - * 0 means that only current interrupt is masked - * 255 means all other interrupts are masked - */ - /* - * ISA interrupts. - * The second entry has a priority of 255 because - * it is the slave pic entry and should always remain - * unmasked. - */ - 0,0, - 255, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -#if BSP_PCI_IRQ_NUMBER > 0 - /* - * PCI Interrupts - */ - 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, /* for raven prio 0 means unactive... */ -#endif - /* - * Processor exceptions handled as interrupts - */ - 0 -}; - -#if BSP_PCI_IRQ_NUMBER > 0 -#if defined(mvme2100) -static unsigned char mvme2100_openpic_initpolarities[16] = { - 0, /* Not used - should be disabled */ - 0, /* DEC21143 Controller */ - 0, /* PMC/PC-MIP Type I Slot 0 */ - 0, /* PC-MIP Type I Slot 1 */ - 0, /* PC-MIP Type II Slot 0 */ - 0, /* PC-MIP Type II Slot 1 */ - 0, /* Not used - should be disabled */ - 0, /* PCI Expansion Interrupt A/Universe II (LINT0) */ - 0, /* PCI Expansion Interrupt B/Universe II (LINT1) */ - 0, /* PCI Expansion Interrupt C/Universe II (LINT2) */ - 0, /* PCI Expansion Interrupt D/Universe II (LINT3) */ - 0, /* Not used - should be disabled */ - 0, /* Not used - should be disabled */ - 1, /* 16550 UART */ - 0, /* Front panel Abort Switch */ - 0, /* RTC IRQ */ -}; - -static unsigned char mvme2100_openpic_initsenses[] = { - 0, /* Not used - should be disabled */ - 1, /* DEC21143 Controller */ - 1, /* PMC/PC-MIP Type I Slot 0 */ - 1, /* PC-MIP Type I Slot 1 */ - 1, /* PC-MIP Type II Slot 0 */ - 1, /* PC-MIP Type II Slot 1 */ - 0, /* Not used - should be disabled */ - 1, /* PCI Expansion Interrupt A/Universe II (LINT0) */ - 1, /* PCI Expansion Interrupt B/Universe II (LINT1) */ - 1, /* PCI Expansion Interrupt C/Universe II (LINT2) */ - 1, /* PCI Expansion Interrupt D/Universe II (LINT3) */ - 0, /* Not used - should be disabled */ - 0, /* Not used - should be disabled */ - 1, /* 16550 UART */ - 0, /* Front panel Abort Switch */ - 1, /* RTC IRQ */ -}; -#else -static unsigned char mcp750_openpic_initpolarities[16] = { - 1, /* 8259 cascade */ - 0, /* all the rest of them */ -}; - -static unsigned char mcp750_openpic_initsenses[] = { - 1, /* MCP750_INT_PCB(8259) */ - 0, /* MCP750_INT_FALCON_ECC_ERR */ - 1, /* MCP750_INT_PCI_ETHERNET */ - 1, /* MCP750_INT_PCI_PMC */ - 1, /* MCP750_INT_PCI_WATCHDOG_TIMER1 */ - 1, /* MCP750_INT_PCI_PRST_SIGNAL */ - 1, /* MCP750_INT_PCI_FALL_SIGNAL */ - 1, /* MCP750_INT_PCI_DEG_SIGNAL */ - 1, /* MCP750_INT_PCI_BUS1_INTA */ - 1, /* MCP750_INT_PCI_BUS1_INTB */ - 1, /* MCP750_INT_PCI_BUS1_INTC */ - 1, /* MCP750_INT_PCI_BUS1_INTD */ - 1, /* MCP750_INT_PCI_BUS2_INTA */ - 1, /* MCP750_INT_PCI_BUS2_INTB */ - 1, /* MCP750_INT_PCI_BUS2_INTC */ - 1, /* MCP750_INT_PCI_BUS2_INTD */ -}; -#endif -#endif - -#if BSP_ISA_IRQ_NUMBER > 0 && !defined(qemu) -void VIA_isa_bridge_interrupts_setup(void) -{ - pci_isa_bridge_device pci_dev; - uint32_t temp; - unsigned char tmp; - unsigned char maxBus; - unsigned found = 0; - - maxBus = pci_bus_count(); - pci_dev.function = 0; /* Assumes the bidge is the first function */ - - for (pci_dev.bus = 0; pci_dev.bus < maxBus; pci_dev.bus++) { -#ifdef SCAN_PCI_PRINT - printk("isa_bridge_interrupts_setup: Scanning bus %d\n", pci_dev.bus); -#endif - for (pci_dev.device = 0; pci_dev.device < PCI_MAX_DEVICES; pci_dev.device++) { -#ifdef SCAN_PCI_PRINT - printk("isa_bridge_interrupts_setup: Scanning device %d\n", pci_dev.device); -#endif - pci_read_config_dword(pci_dev.bus, pci_dev.device, pci_dev.function, - PCI_VENDOR_ID, &temp); -#ifdef SCAN_PCI_PRINT - printk("Vendor/device = %x\n", temp); -#endif - if ((temp == (((unsigned short) PCI_VENDOR_ID_VIA) | (PCI_DEVICE_ID_VIA_82C586_0 << 16))) - ) { - bridge = pci_dev; - via_82c586 = &bridge; -#ifdef SHOW_ISA_PCI_BRIDGE_SETTINGS - /* - * Should print : bus = 0, device = 11, function = 0 on a MCP750. - */ - printk("Via PCI/ISA bridge found at bus = %d, device = %d, function = %d\n", - via_82c586->bus, - via_82c586->device, - via_82c586->function); -#endif - found = 1; - goto loop_exit; - - } - } - } -loop_exit: - if (!found) rtems_panic("VIA_82C586 PCI/ISA bridge not found!n"); - - tmp = inb(0x810); - if ( !(tmp & 0x2)) { -#ifdef SHOW_ISA_PCI_BRIDGE_SETTINGS - printk("This is a second generation MCP750 board\n"); - printk("We must reprogram the PCI/ISA bridge...\n"); -#endif - pci_read_config_byte(via_82c586->bus, via_82c586->device, via_82c586->function, - 0x47, &tmp); -#ifdef SHOW_ISA_PCI_BRIDGE_SETTINGS - printk(" PCI ISA bridge control2 = %x\n", (unsigned) tmp); -#endif - /* - * Enable 4D0/4D1 ISA interrupt level/edge config registers - */ - tmp |= 0x20; - pci_write_config_byte(via_82c586->bus, via_82c586->device, via_82c586->function, - 0x47, tmp); - /* - * Now program the ISA interrupt edge/level - */ - tmp = ELCRS_INT9_LVL | ELCRS_INT10_LVL | ELCRS_INT11_LVL; - outb(tmp, ISA8259_S_ELCR); - tmp = ELCRM_INT5_LVL; - outb(tmp, ISA8259_M_ELCR); - /* - * Set the Interrupt inputs to non-inverting level interrupt - */ - pci_read_config_byte(via_82c586->bus, via_82c586->device, via_82c586->function, - 0x54, &tmp); -#ifdef SHOW_ISA_PCI_BRIDGE_SETTINGS - printk(" PCI ISA bridge PCI/IRQ Edge/Level Select = %x\n", (unsigned) tmp); -#endif - tmp = 0; - pci_write_config_byte(via_82c586->bus, via_82c586->device, via_82c586->function, - 0x54, tmp); - } - else { -#ifdef SHOW_ISA_PCI_BRIDGE_SETTINGS - printk("This is a first generation MCP750 board\n"); - printk("We just show the actual value used by PCI/ISA bridge\n"); -#endif - pci_read_config_byte(via_82c586->bus, via_82c586->device, via_82c586->function, - 0x47, &tmp); -#ifdef SHOW_ISA_PCI_BRIDGE_SETTINGS - printk(" PCI ISA bridge control2 = %x\n", (unsigned) tmp); -#endif - /* - * Show the Interrupt inputs inverting/non-inverting level status - */ - pci_read_config_byte(via_82c586->bus, via_82c586->device, via_82c586->function, - 0x54, &tmp); -#ifdef SHOW_ISA_PCI_BRIDGE_SETTINGS - printk(" PCI ISA bridge PCI/IRQ Edge/Level Select = %x\n", (unsigned) tmp); -#endif - } -} -#endif - - /* - * This code assumes the exceptions management setup has already - * been done. We just need to replace the exceptions that will - * be handled like interrupt. On mcp750/mpc750 and many PPC processors - * this means the decrementer exception and the external exception. - */ -void BSP_rtems_irq_mng_init(unsigned cpuId) -{ -#if BSP_ISA_IRQ_NUMBER > 0 && !defined(mvme2100) - int known_cpi_isa_bridge = 0; -#endif - int i; - - /* - * First initialize the Interrupt management hardware - */ -#if defined(mvme2100) -#ifdef TRACE_IRQ_INIT - printk("Going to initialize EPIC interrupt controller (openpic compliant)\n"); -#endif - /* EPIC sources don't start at the regular place; define appropriate offset - * prior to initializing the PIC. - */ - openpic_init(1, mvme2100_openpic_initpolarities, mvme2100_openpic_initsenses, 16, 16, BSP_bus_frequency); -#else -#if BSP_PCI_IRQ_NUMBER > 0 -#ifdef TRACE_IRQ_INIT - printk("Going to initialize raven interrupt controller (openpic compliant)\n"); -#endif - openpic_init(1, mcp750_openpic_initpolarities, mcp750_openpic_initsenses, 0, 0, 0); -#ifdef TRACE_IRQ_INIT - printk("Going to initialize the PCI/ISA bridge IRQ related setting (VIA 82C586)\n"); -#endif -#endif - -#if BSP_ISA_IRQ_NUMBER > 0 - if ( currentBoard == MESQUITE ) { -#ifndef qemu - VIA_isa_bridge_interrupts_setup(); -#endif - known_cpi_isa_bridge = 1; - } - if ( currentBoard == MVME_2300 ) { - /* nothing to do for W83C553 bridge */ - known_cpi_isa_bridge = 1; - } - if ( currentBoard == MTX_WO_PP || currentBoard == MTX_W_PP ) { - /* W83C554, don't to anything at the moment. gregm 11/6/2002 */ - known_cpi_isa_bridge = 1; - } - - if (!known_cpi_isa_bridge) { - printk("Please add code for PCI/ISA bridge init to libbsp/powerpc/shared/irq/irq_init.c\n"); - printk("If your card works correctly please add a test and set known_cpi_isa_bridge to true\n"); - printk("currentBoard = %i\n", currentBoard); - } -#ifdef TRACE_IRQ_INIT - printk("Going to initialize the ISA PC legacy IRQ management hardware\n"); -#endif - BSP_i8259s_init(); -#endif - -#endif - - /* - * Initialize RTEMS management interrupt table - */ - /* - * re-init the rtemsIrq table - */ - for (i = 0; i < BSP_IRQ_NUMBER; i++) { - rtemsIrq[i] = defaultIrq; - rtemsIrq[i].name = i; - } - /* - * Init initial Interrupt management config - */ - initial_config.irqNb = BSP_IRQ_NUMBER; - initial_config.defaultEntry = defaultIrq; - initial_config.irqHdlTbl = rtemsIrq; - initial_config.irqBase = BSP_LOWEST_OFFSET; - initial_config.irqPrioTbl = irqPrioTable; - - if (!BSP_rtems_irq_mngt_set(&initial_config)) { - /* - * put something here that will show the failure... - */ - rtems_panic("Unable to initialize RTEMS interrupt Management!!! System locked\n"); - } - -#ifdef TRACE_IRQ_INIT - printk("RTEMS IRQ management is now operational\n"); -#endif -} diff --git a/c/src/lib/libbsp/powerpc/shared/irq/openpic_i8259_irq.c b/c/src/lib/libbsp/powerpc/shared/irq/openpic_i8259_irq.c deleted file mode 100644 index 4a9c393f7f..0000000000 --- a/c/src/lib/libbsp/powerpc/shared/irq/openpic_i8259_irq.c +++ /dev/null @@ -1,331 +0,0 @@ -/* - * - * This file contains the i8259/openpic-specific implementation of - * the function described in irq.h - * - * Copyright (C) 1998, 1999 valette@crf.canon.fr - * - * The license and distribution terms for this file may be - * found in the file LICENSE in this distribution or at - * http://www.rtems.org/license/LICENSE. - */ - -#include - -#include -#include -#include -#ifndef BSP_HAS_NO_VME -#include -#endif -#if BSP_PCI_IRQ_NUMBER > 0 -#include -#endif -#include -#include -#include - -#include /* for printk */ - -#ifndef qemu -#define RAVEN_INTR_ACK_REG 0xfeff0030 -#else -#define RAVEN_INTR_ACK_REG 0xbffffff0 -#endif - -#if BSP_ISA_IRQ_NUMBER > 0 -/* - * pointer to the mask representing the additionnal irq vectors - * that must be disabled when a particular entry is activated. - * They will be dynamically computed from the priority table given - * in BSP_rtems_irq_mngt_set(); - * CAUTION : this table is accessed directly by interrupt routine - * prologue. - */ -rtems_i8259_masks irq_mask_or_tbl[BSP_IRQ_NUMBER]; -#endif - -/* - * default handler connected on each irq after bsp initialization - */ -static rtems_irq_connect_data default_rtems_entry; - -static rtems_irq_connect_data* rtems_hdl_tbl; - -#if BSP_ISA_IRQ_NUMBER > 0 -/* - * Check if IRQ is an ISA IRQ - */ -static inline int is_isa_irq(const rtems_irq_number irqLine) -{ - return (((int) irqLine <= BSP_ISA_IRQ_MAX_OFFSET) && - ((int) irqLine >= BSP_ISA_IRQ_LOWEST_OFFSET) - ); -} -#endif - -#if BSP_PCI_IRQ_NUMBER > 0 -/* - * Check if IRQ is an OPENPIC IRQ - */ -static inline int is_pci_irq(const rtems_irq_number irqLine) -{ - return OpenPIC && (((int) irqLine <= BSP_PCI_IRQ_MAX_OFFSET) && - ((int) irqLine >= BSP_PCI_IRQ_LOWEST_OFFSET) - ); -} -#endif - -/* - * ------------------------ RTEMS Irq helper functions ---------------- - */ - -#if BSP_ISA_IRQ_NUMBER > 0 -/* - * Caution : this function assumes the variable "*config" - * is already set and that the tables it contains are still valid - * and accessible. - */ -static void compute_i8259_masks_from_prio (rtems_irq_global_settings* config) -{ - int i; - int j; - /* - * Always mask at least current interrupt to prevent re-entrance - */ - for (i=BSP_ISA_IRQ_LOWEST_OFFSET; i < BSP_ISA_IRQ_LOWEST_OFFSET + BSP_ISA_IRQ_NUMBER; i++) { - * ((unsigned short*) &irq_mask_or_tbl[i]) = (1 << i); - for (j = BSP_ISA_IRQ_LOWEST_OFFSET; j < BSP_ISA_IRQ_LOWEST_OFFSET + BSP_ISA_IRQ_NUMBER; j++) { - /* - * Mask interrupts at i8259 level that have a lower priority - */ - if (config->irqPrioTbl [i] > config->irqPrioTbl [j]) { - * ((unsigned short*) &irq_mask_or_tbl[i]) |= (1 << j); - } - } - } -} -#endif - -void -BSP_enable_irq_at_pic(const rtems_irq_number name) -{ -#if BSP_ISA_IRQ_NUMBER > 0 - if (is_isa_irq(name)) { - /* - * Enable interrupt at PIC level - */ - BSP_irq_enable_at_i8259s ((int) name - BSP_ISA_IRQ_LOWEST_OFFSET); - } -#endif - -#if BSP_PCI_IRQ_NUMBER > 0 - if (is_pci_irq(name)) { - /* - * Enable interrupt at OPENPIC level - */ - openpic_enable_irq ((int) name - BSP_PCI_IRQ_LOWEST_OFFSET); - } -#endif -} - -int -BSP_disable_irq_at_pic(const rtems_irq_number name) -{ -#if BSP_ISA_IRQ_NUMBER > 0 - if (is_isa_irq(name)) { - /* - * disable interrupt at PIC level - */ - return BSP_irq_disable_at_i8259s ((int) name - BSP_ISA_IRQ_LOWEST_OFFSET); - } -#endif -#if BSP_PCI_IRQ_NUMBER > 0 - if (is_pci_irq(name)) { - /* - * disable interrupt at OPENPIC level - */ - return openpic_disable_irq ((int) name - BSP_PCI_IRQ_LOWEST_OFFSET); - } -#endif - return -1; -} - -/* - * RTEMS Global Interrupt Handler Management Routines - */ -int BSP_setup_the_pic(rtems_irq_global_settings* config) -{ - int i; - /* - * Store various code accelerators - */ - default_rtems_entry = config->defaultEntry; - rtems_hdl_tbl = config->irqHdlTbl; - - /* - * set up internal tables used by rtems interrupt prologue - */ - -#if BSP_ISA_IRQ_NUMBER > 0 - /* - * start with ISA IRQ - */ - compute_i8259_masks_from_prio (config); - - for (i=BSP_ISA_IRQ_LOWEST_OFFSET; i < BSP_ISA_IRQ_LOWEST_OFFSET + BSP_ISA_IRQ_NUMBER; i++) { - if (rtems_hdl_tbl[i].hdl != default_rtems_entry.hdl) { - BSP_irq_enable_at_i8259s (i); - } - else { - BSP_irq_disable_at_i8259s (i); - } - } - - if ( BSP_ISA_IRQ_NUMBER > 0 ) { - /* - * must enable slave pic anyway - */ - BSP_irq_enable_at_i8259s (2); - } -#endif - -#if BSP_PCI_IRQ_NUMBER > 0 - if ( ! OpenPIC ) - return 1; - /* - * continue with PCI IRQ - */ - for (i=BSP_PCI_IRQ_LOWEST_OFFSET; i < BSP_PCI_IRQ_LOWEST_OFFSET + BSP_PCI_IRQ_NUMBER ; i++) { - /* - * Note that openpic_set_priority() sets the TASK priority of the PIC - */ - openpic_set_source_priority(i - BSP_PCI_IRQ_LOWEST_OFFSET, - config->irqPrioTbl[i]); - if (rtems_hdl_tbl[i].hdl != default_rtems_entry.hdl) { - openpic_enable_irq ((int) i - BSP_PCI_IRQ_LOWEST_OFFSET); - } - else { - openpic_disable_irq ((int) i - BSP_PCI_IRQ_LOWEST_OFFSET); - } - } - -#ifdef BSP_PCI_ISA_BRIDGE_IRQ - /* - * Must enable PCI/ISA bridge IRQ - */ - openpic_enable_irq (BSP_PCI_ISA_BRIDGE_IRQ); -#endif -#endif - - return 1; -} - -int _BSP_vme_bridge_irq = -1; - -unsigned BSP_spuriousIntr = 0; - -/* - * High level IRQ handler called from shared_raw_irq_code_entry - */ -int C_dispatch_irq_handler (BSP_Exception_frame *frame, unsigned int excNum) -{ - register unsigned int irq; -#if BSP_ISA_IRQ_NUMBER > 0 - register unsigned isaIntr; /* boolean */ - register unsigned oldMask = 0; /* old isa pic masks */ - register unsigned newMask; /* new isa pic masks */ -#endif - - if (excNum == ASM_DEC_VECTOR) { - - bsp_irq_dispatch_list(rtems_hdl_tbl, BSP_DECREMENTER, default_rtems_entry.hdl); - - return 0; - - } - -#if BSP_PCI_IRQ_NUMBER > 0 - if ( OpenPIC ) { - irq = openpic_irq(0); - if (irq == OPENPIC_VEC_SPURIOUS) { - ++BSP_spuriousIntr; - return 0; - } - - /* some BSPs might want to use a different numbering... */ - irq = irq - OPENPIC_VEC_SOURCE + BSP_PCI_IRQ_LOWEST_OFFSET; - } else { -#if BSP_ISA_IRQ_NUMBER > 0 -#ifdef BSP_PCI_ISA_BRIDGE_IRQ - irq = BSP_PCI_ISA_BRIDGE_IRQ; -#else -#error "Configuration Error -- BSP with ISA + PCI IRQs MUST define BSP_PCI_ISA_BRIDGE_IRQ" -#endif -#else - rtems_panic("MUST have an OpenPIC if BSP has PCI IRQs but no ISA IRQs"); - /* rtems_panic() never returns but the 'return' statement silences - * a compiler warning about 'irq' possibly being used w/o initialization. - */ - return -1; -#endif - } -#endif - -#if BSP_ISA_IRQ_NUMBER > 0 -#ifdef BSP_PCI_ISA_BRIDGE_IRQ -#if 0 == BSP_PCI_IRQ_NUMBER -#error "Configuration Error -- BSP w/o PCI IRQs MUST NOT define BSP_PCI_ISA_BRIDGE_IRQ" -#endif - isaIntr = (irq == BSP_PCI_ISA_BRIDGE_IRQ); -#else - isaIntr = 1; -#endif - if (isaIntr) { - /* - * Acknowledge and read 8259 vector - */ - irq = (unsigned int) (*(unsigned char *) RAVEN_INTR_ACK_REG); - /* - * store current PIC mask - */ - oldMask = i8259s_cache; - newMask = oldMask | irq_mask_or_tbl [irq]; - i8259s_cache = newMask; - outport_byte(PIC_MASTER_IMR_IO_PORT, i8259s_cache & 0xff); - outport_byte(PIC_SLAVE_IMR_IO_PORT, ((i8259s_cache & 0xff00) >> 8)); - BSP_irq_ack_at_i8259s (irq); -#if BSP_PCI_IRQ_NUMBER > 0 - if ( OpenPIC ) - openpic_eoi(0); -#endif - } -#endif - - /* dispatch handlers */ - bsp_irq_dispatch_list(rtems_hdl_tbl, irq, default_rtems_entry.hdl); - -#if BSP_ISA_IRQ_NUMBER > 0 - if (isaIntr) { - i8259s_cache = oldMask; - outport_byte(PIC_MASTER_IMR_IO_PORT, i8259s_cache & 0xff); - outport_byte(PIC_SLAVE_IMR_IO_PORT, ((i8259s_cache & 0xff00) >> 8)); - } - else -#endif - { -#if BSP_PCI_IRQ_NUMBER > 0 -#ifdef BSP_PCI_VME_DRIVER_DOES_EOI - /* leave it to the VME bridge driver to do EOI, so - * it can re-enable the openpic while handling - * VME interrupts (-> VME priorities in software) - */ - if (_BSP_vme_bridge_irq != irq && OpenPIC) -#endif - openpic_eoi(0); -#else - do {} while (0); -#endif - } - return 0; -} diff --git a/c/src/lib/libbsp/powerpc/shared/openpic/openpic.c b/c/src/lib/libbsp/powerpc/shared/openpic/openpic.c deleted file mode 100644 index 556014964b..0000000000 --- a/c/src/lib/libbsp/powerpc/shared/openpic/openpic.c +++ /dev/null @@ -1,622 +0,0 @@ -/* - * openpic.c -- OpenPIC Interrupt Handling - * - * Copyright (C) 1997 Geert Uytterhoeven - * - * Modified to compile in RTEMS development environment - * by Eric Valette - * - * Copyright (C) 1999 Eric Valette. valette@crf.canon.fr - * - * The license and distribution terms for this file may be - * found in the file LICENSE in this distribution or at - * http://www.rtems.org/license/LICENSE. - */ - -/* - * Note: Interprocessor Interrupt (IPI) and Timer support is incomplete - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#ifndef NULL -#define NULL 0 -#endif -#define REGISTER_DEBUG -#undef REGISTER_DEBUG - -volatile struct OpenPIC *OpenPIC = NULL; - -static unsigned int NumProcessors; -static unsigned int NumSources; - -static unsigned int openpic_eoi_delay = 0; -static int openpic_src_offst = 0; -#define SOURCE(irq) Source[ (irq) + openpic_src_offst ] - - /* - * Accesses to the current processor's registers - */ - -#define THIS_CPU Processor[cpu] -#define CHECK_THIS_CPU check_arg_cpu(cpu) - - /* - * Sanity checks - */ - -#if 1 -/* This software deliberately uses non-zero values to the method - * __builtin_return_address() and we want to avoid the GCC warning. - */ -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wframe-address" -#define check_arg_ipi(ipi) \ - if (ipi < 0 || ipi >= OPENPIC_NUM_IPI) \ - printk("openpic.c:%d: illegal ipi %d\n", __LINE__, ipi); -#define check_arg_timer(timer) \ - if (timer < 0 || timer >= OPENPIC_NUM_TIMERS) \ - printk("openpic.c:%d: illegal timer %d\n", __LINE__, timer); -#define check_arg_vec(vec) \ - if (vec < 0 || vec >= OPENPIC_NUM_VECTORS) \ - printk("openpic.c:%d: illegal vector %d\n", __LINE__, vec); -#define check_arg_pri(pri) \ - if (pri < 0 || pri >= OPENPIC_NUM_PRI) \ - printk("openpic.c:%d: illegal priority %d\n", __LINE__, pri); -#define check_arg_irq(irq) \ - if (irq < 0 || irq >= NumSources) \ - printk("openpic.c:%d: illegal irq %d from 0x%08" PRIxPTR ",[0x%08" PRIxPTR "],[[0x%08" PRIxPTR "]]\n", \ - __LINE__, irq, (uintptr_t) __builtin_return_address(0), \ - (uintptr_t) __builtin_return_address(1), (uintptr_t) __builtin_return_address(2) \ - ); -#define check_arg_cpu(cpu) \ - if (cpu < 0 || cpu >= NumProcessors) \ - printk("openpic.c:%d: illegal cpu %d\n", __LINE__, cpu); -#else -#define check_arg_ipi(ipi) do {} while (0) -#define check_arg_timer(timer) do {} while (0) -#define check_arg_vec(vec) do {} while (0) -#define check_arg_pri(pri) do {} while (0) -#define check_arg_irq(irq) do {} while (0) -#define check_arg_cpu(cpu) do {} while (0) -#endif - - /* - * I/O functions - */ - -static inline unsigned int openpic_read(volatile unsigned int *addr) -{ - unsigned int val; - -#ifdef BSP_OPEN_PIC_BIG_ENDIAN - val = in_be32((volatile uint32_t *)addr); -#else - val = in_le32((volatile uint32_t *)addr); -#endif -#ifdef REGISTER_DEBUG - printk("openpic_read(0x%08x) = 0x%08x\n", (unsigned int)addr, val); -#endif - return val; -} - -static inline void openpic_write(volatile unsigned int *addr, unsigned int val) -{ -#ifdef REGISTER_DEBUG - printk("openpic_write(0x%08x, 0x%08x)\n", (unsigned int)addr, val); -#endif -#ifdef BSP_OPEN_PIC_BIG_ENDIAN - out_be32((volatile uint32_t *)addr, val); -#else - out_le32((volatile uint32_t *)addr, val); -#endif -} - -static inline unsigned int openpic_readfield(volatile unsigned int *addr, unsigned int mask) -{ - unsigned int val = openpic_read(addr); - return val & mask; -} - -static inline void openpic_writefield(volatile unsigned int *addr, unsigned int mask, - unsigned int field) -{ - unsigned int val = openpic_read(addr); - openpic_write(addr, (val & ~mask) | (field & mask)); -} - -static inline void openpic_clearfield(volatile unsigned int *addr, unsigned int mask) -{ - openpic_writefield(addr, mask, 0); -} - -static inline void openpic_setfield(volatile unsigned int *addr, unsigned int mask) -{ - openpic_writefield(addr, mask, mask); -} - - /* - * Update a Vector/Priority register in a safe manner. The interrupt will - * be disabled. - */ - -static void openpic_safe_writefield(volatile unsigned int *addr, unsigned int mask, - unsigned int field) -{ - openpic_setfield(addr, OPENPIC_MASK); - /* wait until it's not in use */ - while (openpic_read(addr) & OPENPIC_ACTIVITY); - openpic_writefield(addr, mask | OPENPIC_MASK, field | OPENPIC_MASK); -} - -/* -------- Global Operations ---------------------------------------------- */ - - /* - * Initialize the OpenPIC - * - * Add some kludge to use the Motorola Raven OpenPIC which does not - * report vendor and device id, and gets the wrong number of interrupts. - * (Motorola did a great job on that one!) - * - * T. Straumann, 12/20/2001: polarities and senses are now passed as - * parameters, eliminated global vars. - * IRQ0 is no longer treated specially. - */ - -void openpic_init(int main_pic, unsigned char *polarities, unsigned char *senses, int num_sources, int source_offset, unsigned long epic_freq) -{ - unsigned int t, i; - unsigned int vendorid, devid, stepping, timerfreq; - const char *version, *vendor, *device; - - if (!OpenPIC) - rtems_panic("No OpenPIC found"); - - t = openpic_read(&OpenPIC->Global.Feature_Reporting0); - switch (t & OPENPIC_FEATURE_VERSION_MASK) { - case 1: - version = "1.0"; - break; - case 2: - version = "1.2"; - break; - default: - version = "?"; - break; - } - NumProcessors = ((t & OPENPIC_FEATURE_LAST_PROCESSOR_MASK) >> - OPENPIC_FEATURE_LAST_PROCESSOR_SHIFT) + 1; - NumSources = ((t & OPENPIC_FEATURE_LAST_SOURCE_MASK) >> - OPENPIC_FEATURE_LAST_SOURCE_SHIFT) + 1; - t = openpic_read(&OpenPIC->Global.Vendor_Identification); - - vendorid = t & OPENPIC_VENDOR_ID_VENDOR_ID_MASK; - devid = (t & OPENPIC_VENDOR_ID_DEVICE_ID_MASK) >> - OPENPIC_VENDOR_ID_DEVICE_ID_SHIFT; - stepping = (t & OPENPIC_VENDOR_ID_STEPPING_MASK) >> - OPENPIC_VENDOR_ID_STEPPING_SHIFT; - - /* Kludge for the Raven */ -/* - pci_read_config_dword(0, 0, 0, 0, &t); -*/ - if (t == PCI_VENDOR_ID_MOTOROLA + (PCI_DEVICE_ID_MOTOROLA_RAVEN<<16)) { - vendor = "Motorola"; - device = "Raven"; - NumSources += 1; - } - else if (t == PCI_VENDOR_ID_MOTOROLA + (PCI_DEVICE_ID_MOTOROLA_HAWK<<16)) { - vendor = "Motorola"; - device = "Hawk"; - NumSources += 1; - } else { - switch (vendorid) { - case OPENPIC_VENDOR_ID_APPLE: - vendor = "Apple"; - break; - default: - vendor = "Unknown"; - break; - } - switch (devid) { - case OPENPIC_DEVICE_ID_APPLE_HYDRA: - device = "Hydra"; - break; - default: - device = "Unknown"; - break; - } - } - printk("OpenPIC Version %s (%d CPUs and %d IRQ sources) at 0x%08" PRIuPTR "\n", version, - NumProcessors, NumSources, (uintptr_t) OpenPIC); - - printk("OpenPIC Vendor %d (%s), Device %d (%s), Stepping %d\n", vendorid, - vendor, devid, device, stepping); - - /* Override if they desire */ - if ( num_sources ) { - if ( NumSources != num_sources ) - printk("Overriding NumSources (%i) from configuration with %i\n", - NumSources, num_sources); - NumSources = num_sources; - } - - openpic_src_offst = source_offset; - - timerfreq = openpic_read(&OpenPIC->Global.Timer_Frequency); - printk("OpenPIC timer frequency is "); - if (timerfreq) - printk("%d Hz\n", timerfreq); - else - printk("not set\n"); - - if ( main_pic ) - { - /* Initialize timer interrupts */ - for (i = 0; i < OPENPIC_NUM_TIMERS; i++) { - /* Disabled, Priority 0 */ - openpic_inittimer(i, 0, OPENPIC_VEC_TIMER+i); - /* No processor */ - openpic_maptimer(i, 0); - } - - /* Initialize IPI interrupts */ - for (i = 0; i < OPENPIC_NUM_IPI; i++) { - /* Disabled, Priority 0 */ - openpic_initipi(i, 0, OPENPIC_VEC_IPI+i); - } - - /* Initialize external interrupts */ - for (i = 0; i < NumSources; i++) { - /* Enabled, Priority 8 */ - openpic_initirq(i, 8, OPENPIC_VEC_SOURCE+i, - polarities ? polarities[i] : 0, - senses ? senses[i] : 1); - /* Processor 0 */ - openpic_mapirq(i, 1<<0); - } - - /* Initialize the spurious interrupt */ - openpic_set_spurious(OPENPIC_VEC_SPURIOUS); -#if 0 - if (request_irq(IRQ_8259_CASCADE, no_action, SA_INTERRUPT, - "82c59 cascade", NULL)) - printk("Unable to get OpenPIC IRQ 0 for cascade\n"); -#endif - openpic_set_priority(0, 0); - openpic_disable_8259_pass_through(); - } - if ( epic_freq ) { - /* Speed up the serial interface; if it is too slow then we might get spurious - * interrupts: - * After an ISR clears the interrupt condition at the source/device, the wire - * remains asserted during the propagation delay introduced by the serial interface - * (something really stupid). If the ISR returns while the wire is not released - * yet, then a spurious interrupt happens. - * The book says we should be careful if the serial clock is > 33MHz. - * Empirically, it seems that running it at 33MHz is fast enough. Otherwise, - * we should introduce a delay in openpic_eoi(). - * The maximal delay are 16 (serial) clock cycles. If the divisor is 8 - * [power-up default] then the lag is 2us [66MHz SDRAM clock; I assume this - * is equal to the bus frequency]. - * FIXME: This should probably be a EPIC-specific piece in 'openpic.c' - * Unfortunately, there is no easy way of figuring out if the - * device is an EPIC or not. - */ - uint32_t eicr_val, ratio; - /* On the 8240 this is the EICR register */ - eicr_val = in_le32( (volatile uint32_t *)&OpenPIC->Global.Global_Configuration1 ) & ~(7<<28); - if ( (1<<27) & eicr_val ) { - /* serial interface mode enabled */ - - /* round to nearest integer: - * round(Bus_freq/33000000) = floor( 2*(Bus_freq/33e6) + 1 ) / 2 - */ - ratio = epic_freq / 16500000 + 1; - ratio >>= 2; /* EICR value is half actual divisor */ - if ( 0==ratio ) - ratio = 1; - out_le32((volatile uint32_t *)&OpenPIC->Global.Global_Configuration1, eicr_val | ((ratio &7) << 28)); - /* Delay in TB cycles (assuming TB runs at 1/4 of the bus frequency) */ - openpic_set_eoi_delay( 16 * (2*ratio) / 4 ); - } - } -} - - /* - * Reset the OpenPIC - */ - -void openpic_reset(void) -{ - openpic_setfield(&OpenPIC->Global.Global_Configuration0, - OPENPIC_CONFIG_RESET); -} - - /* - * Enable/disable 8259 Pass Through Mode - */ - -void openpic_enable_8259_pass_through(void) -{ - openpic_clearfield(&OpenPIC->Global.Global_Configuration0, - OPENPIC_CONFIG_8259_PASSTHROUGH_DISABLE); -} - -void openpic_disable_8259_pass_through(void) -{ - openpic_setfield(&OpenPIC->Global.Global_Configuration0, - OPENPIC_CONFIG_8259_PASSTHROUGH_DISABLE); -} - - /* - * Find out the current interrupt - */ - -unsigned int openpic_irq(unsigned int cpu) -{ - unsigned int vec; - - check_arg_cpu(cpu); - vec = openpic_readfield(&OpenPIC->THIS_CPU.Interrupt_Acknowledge, - OPENPIC_VECTOR_MASK); - return vec; -} - - /* - * Signal end of interrupt (EOI) processing - */ - -void openpic_eoi(unsigned int cpu) -{ - check_arg_cpu(cpu); - if ( openpic_eoi_delay ) - rtems_bsp_delay_in_bus_cycles(openpic_eoi_delay); - openpic_write(&OpenPIC->THIS_CPU.EOI, 0); -} - -unsigned openpic_set_eoi_delay(unsigned tb_cycles) -{ -unsigned rval = openpic_eoi_delay; - openpic_eoi_delay = tb_cycles; - return rval; -} - - /* - * Get/set the current task priority - */ - -unsigned int openpic_get_priority(unsigned int cpu) -{ - CHECK_THIS_CPU; - return openpic_readfield(&OpenPIC->THIS_CPU.Current_Task_Priority, - OPENPIC_CURRENT_TASK_PRIORITY_MASK); -} - -void openpic_set_priority(unsigned int cpu, unsigned int pri) -{ - CHECK_THIS_CPU; - check_arg_pri(pri); - openpic_writefield(&OpenPIC->THIS_CPU.Current_Task_Priority, - OPENPIC_CURRENT_TASK_PRIORITY_MASK, pri); -} - - /* - * Get/set the spurious vector - */ - -unsigned int openpic_get_spurious(void) -{ - return openpic_readfield(&OpenPIC->Global.Spurious_Vector, - OPENPIC_VECTOR_MASK); -} - -void openpic_set_spurious(unsigned int vec) -{ - check_arg_vec(vec); - openpic_writefield(&OpenPIC->Global.Spurious_Vector, OPENPIC_VECTOR_MASK, - vec); -} - - /* - * Initialize one or more CPUs - */ - -void openpic_init_processor(unsigned int cpumask) -{ - openpic_write(&OpenPIC->Global.Processor_Initialization, cpumask); -} - -/* -------- Interprocessor Interrupts -------------------------------------- */ - - /* - * Initialize an interprocessor interrupt (and disable it) - * - * ipi: OpenPIC interprocessor interrupt number - * pri: interrupt source priority - * vec: the vector it will produce - */ - -void openpic_initipi(unsigned int ipi, unsigned int pri, unsigned int vec) -{ - check_arg_timer(ipi); - check_arg_pri(pri); - check_arg_vec(vec); - openpic_safe_writefield(&OpenPIC->Global.IPI_Vector_Priority(ipi), - OPENPIC_PRIORITY_MASK | OPENPIC_VECTOR_MASK, - (pri << OPENPIC_PRIORITY_SHIFT) | vec); -} - - /* - * Send an IPI to one or more CPUs - */ - -void openpic_cause_IPI(unsigned int cpu, unsigned int ipi, unsigned int cpumask) -{ - CHECK_THIS_CPU; - check_arg_ipi(ipi); - openpic_write(&OpenPIC->THIS_CPU.IPI_Dispatch(ipi), cpumask); -} - -/* -------- Timer Interrupts ----------------------------------------------- */ - - /* - * Initialize a timer interrupt (and disable it) - * - * timer: OpenPIC timer number - * pri: interrupt source priority - * vec: the vector it will produce - */ - -void openpic_inittimer(unsigned int timer, unsigned int pri, unsigned int vec) -{ - check_arg_timer(timer); - check_arg_pri(pri); - check_arg_vec(vec); - openpic_safe_writefield(&OpenPIC->Global.Timer[timer].Vector_Priority, - OPENPIC_PRIORITY_MASK | OPENPIC_VECTOR_MASK, - (pri << OPENPIC_PRIORITY_SHIFT) | vec); -} - - /* - * Map a timer interrupt to one or more CPUs - */ - -void openpic_maptimer(unsigned int timer, unsigned int cpumask) -{ - check_arg_timer(timer); - openpic_write(&OpenPIC->Global.Timer[timer].Destination, cpumask); -} - - /* - * Set base count and / or enable / disable interrupt. - */ - - -void openpic_settimer(unsigned int timer, unsigned int base_count, int irq_enable) -{ - check_arg_timer(timer); - if ( base_count ) - openpic_write(&OpenPIC->Global.Timer[timer].Base_Count, base_count); - if ( irq_enable ) - openpic_clearfield(&OpenPIC->Global.Timer[timer].Vector_Priority, OPENPIC_MASK); - else - openpic_setfield(&OpenPIC->Global.Timer[timer].Vector_Priority, OPENPIC_MASK); -} - -unsigned int openpic_gettimer(unsigned int timer) -{ - check_arg_timer(timer); - return (openpic_read(&OpenPIC->Global.Timer[timer].Current_Count) & ~OPENPIC_MASK); -} - -/* -------- Interrupt Sources ---------------------------------------------- */ - - /* - * Enable/disable an interrupt source - */ - -void openpic_enable_irq(unsigned int irq) -{ -unsigned long flags; - check_arg_irq(irq); - rtems_interrupt_disable(flags); - openpic_clearfield(&OpenPIC->SOURCE(irq).Vector_Priority, OPENPIC_MASK); - rtems_interrupt_enable(flags); -} - -int openpic_disable_irq(unsigned int irq) -{ -int rval; -unsigned long flags; - check_arg_irq(irq); - if ( irq < 0 || irq >=NumSources ) - return -1; - rtems_interrupt_disable(flags); - rval = openpic_readfield(&OpenPIC->SOURCE(irq).Vector_Priority, OPENPIC_MASK) ? 0 : 1; - openpic_setfield(&OpenPIC->SOURCE(irq).Vector_Priority, OPENPIC_MASK); - rtems_interrupt_enable(flags); - return rval; -} - - /* - * Initialize an interrupt source (and disable it!) - * - * irq: OpenPIC interrupt number - * pri: interrupt source priority - * vec: the vector it will produce - * pol: polarity (1 for positive, 0 for negative) - * sense: 1 for level, 0 for edge - */ - -void openpic_initirq(unsigned int irq, unsigned int pri, unsigned int vec, int pol, int sense) -{ -#if 0 - printk("openpic_initirq: irq=%d pri=%d vec=%d pol=%d sense=%d\n", - irq, pri, vec, pol, sense); -#endif - - check_arg_irq(irq); - check_arg_pri(pri); - check_arg_vec(vec); - openpic_safe_writefield(&OpenPIC->SOURCE(irq).Vector_Priority, - OPENPIC_PRIORITY_MASK | OPENPIC_VECTOR_MASK | - OPENPIC_SENSE_POLARITY | OPENPIC_SENSE_LEVEL, - (pri << OPENPIC_PRIORITY_SHIFT) | vec | - (pol ? OPENPIC_SENSE_POLARITY : 0) | - (sense ? OPENPIC_SENSE_LEVEL : 0)); -} - - /* - * Map an interrupt source to one or more CPUs - */ - -void openpic_mapirq(unsigned int irq, unsigned int cpumask) -{ - check_arg_irq(irq); - openpic_write(&OpenPIC->SOURCE(irq).Destination, cpumask); -} - - /* - * Get the current priority of an external interrupt - */ -unsigned int openpic_get_source_priority(unsigned int irq) -{ - check_arg_irq(irq); - return openpic_readfield(&OpenPIC->SOURCE(irq).Vector_Priority, - OPENPIC_PRIORITY_MASK) >> OPENPIC_PRIORITY_SHIFT; -} - -void openpic_set_source_priority(unsigned int irq, unsigned int pri) -{ -unsigned long flags; - check_arg_irq(irq); - check_arg_pri(pri); - rtems_interrupt_disable(flags); - openpic_writefield( - &OpenPIC->SOURCE(irq).Vector_Priority, - OPENPIC_PRIORITY_MASK, - pri << OPENPIC_PRIORITY_SHIFT); - rtems_interrupt_enable(flags); -} - /* - * Set the sense for an interrupt source (and disable it!) - * - * sense: 1 for level, 0 for edge - */ - -void openpic_set_sense(unsigned int irq, int sense) -{ - check_arg_irq(irq); - openpic_safe_writefield(&OpenPIC->SOURCE(irq).Vector_Priority, - OPENPIC_SENSE_LEVEL, - (sense ? OPENPIC_SENSE_LEVEL : 0)); -} diff --git a/c/src/lib/libbsp/powerpc/t32mppc/Makefile.am b/c/src/lib/libbsp/powerpc/t32mppc/Makefile.am index 71dc32b321..a8a35824e2 100644 --- a/c/src/lib/libbsp/powerpc/t32mppc/Makefile.am +++ b/c/src/lib/libbsp/powerpc/t32mppc/Makefile.am @@ -44,7 +44,7 @@ librtemsbsp_a_SOURCES += ../../../../../../bsps/shared/dev/btimer/btimer-stub.c # IRQ librtemsbsp_a_SOURCES += ../../../../../../bsps/shared/irq/irq-default-handler.c -librtemsbsp_a_SOURCES += irq/irq.c +librtemsbsp_a_SOURCES += ../../../../../../bsps/powerpc/t32mppc/irq/irq.c # Console librtemsbsp_a_SOURCES += ../../../../../../bsps/shared/dev/serial/console-termios.c diff --git a/c/src/lib/libbsp/powerpc/t32mppc/irq/irq.c b/c/src/lib/libbsp/powerpc/t32mppc/irq/irq.c deleted file mode 100644 index 5b2c34d2c9..0000000000 --- a/c/src/lib/libbsp/powerpc/t32mppc/irq/irq.c +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright (c) 2012, 2017 embedded brains GmbH. All rights reserved. - * - * embedded brains GmbH - * Dornierstr. 4 - * 82178 Puchheim - * Germany - * - * - * The license and distribution terms for this file may be - * found in the file LICENSE in this distribution or at - * http://www.rtems.org/license/LICENSE. - */ - -#include -#include -#include - -void bsp_interrupt_vector_enable(rtems_vector_number vector) -{ - bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector)); -} - -void bsp_interrupt_dispatch(uintptr_t exception_number) -{ - if (exception_number == 10) { - t32mppc_decrementer_dispatch(); - } else { - bsp_interrupt_handler_default(0); - } -} - -void bsp_interrupt_vector_disable(rtems_vector_number vector) -{ - bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector)); -} - -rtems_status_code bsp_interrupt_facility_initialize(void) -{ - return RTEMS_SUCCESSFUL; -} diff --git a/c/src/lib/libbsp/powerpc/tqm8xx/Makefile.am b/c/src/lib/libbsp/powerpc/tqm8xx/Makefile.am index 3775b32268..b95f56f26a 100644 --- a/c/src/lib/libbsp/powerpc/tqm8xx/Makefile.am +++ b/c/src/lib/libbsp/powerpc/tqm8xx/Makefile.am @@ -25,7 +25,7 @@ librtemsbsp_a_SOURCES = # irq librtemsbsp_a_SOURCES += ../../../../../../bsps/shared/irq/irq-default-handler.c -librtemsbsp_a_SOURCES += irq/irq.c +librtemsbsp_a_SOURCES += ../../../../../../bsps/powerpc/tqm8xx/irq/irq.c # clock librtemsbsp_a_SOURCES +=../../../../../../bsps/powerpc/shared/clock/clock.c diff --git a/c/src/lib/libbsp/powerpc/tqm8xx/irq/irq.c b/c/src/lib/libbsp/powerpc/tqm8xx/irq/irq.c deleted file mode 100644 index 2a94c27d1b..0000000000 --- a/c/src/lib/libbsp/powerpc/tqm8xx/irq/irq.c +++ /dev/null @@ -1,231 +0,0 @@ -/*===============================================================*\ -| Project: RTEMS TQM8xx BSP | -+-----------------------------------------------------------------+ -| This file has been adapted to MPC8xx by | -| Thomas Doerfler | -| Copyright (c) 2008 | -| Embedded Brains GmbH | -| Obere Lagerstr. 30 | -| D-82178 Puchheim | -| Germany | -| rtems@embedded-brains.de | -| | -| See the other copyright notice below for the original parts. | -+-----------------------------------------------------------------+ -| The license and distribution terms for this file may be | -| found in the file LICENSE in this distribution or at | -| | -| http://www.rtems.org/license/LICENSE. | -| | -+-----------------------------------------------------------------+ -| this file contains the console driver | -\*===============================================================*/ -/* derived from: generic MPC83xx BSP */ - -#include -#include - -#include -#include - -#include -#include -#include -/* - * functions to enable/disable a source at the SIU/CPM irq controller - */ - -static rtems_status_code bsp_irq_disable_at_SIU(rtems_vector_number irqnum) -{ - rtems_vector_number vecnum = irqnum - BSP_SIU_IRQ_LOWEST_OFFSET; - m8xx.simask &= ~(1 << (31 - vecnum)); - return RTEMS_SUCCESSFUL; -} - -static rtems_status_code bsp_irq_enable_at_SIU(rtems_vector_number irqnum) -{ - rtems_vector_number vecnum = irqnum - BSP_SIU_IRQ_LOWEST_OFFSET; - m8xx.simask |= (1 << (31 - vecnum)); - return RTEMS_SUCCESSFUL; -} - -static rtems_status_code bsp_irq_disable_at_CPM(rtems_vector_number irqnum) -{ - rtems_vector_number vecnum = irqnum - BSP_CPM_IRQ_LOWEST_OFFSET; - m8xx.cimr &= ~(1 << (vecnum)); - return RTEMS_SUCCESSFUL; -} - -static rtems_status_code bsp_irq_enable_at_CPM(rtems_vector_number irqnum) -{ - rtems_vector_number vecnum = irqnum - BSP_CPM_IRQ_LOWEST_OFFSET; - m8xx.cimr |= (1 << (vecnum)); - return RTEMS_SUCCESSFUL; -} - -void bsp_interrupt_vector_enable(rtems_vector_number vector) -{ - bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector)); - - if (BSP_IS_CPM_IRQ(vector)) { - bsp_irq_enable_at_CPM(vector); - } else if (BSP_IS_SIU_IRQ(vector)) { - bsp_irq_enable_at_SIU(vector); - } -} - -void bsp_interrupt_vector_disable(rtems_vector_number vector) -{ - bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector)); - - if (BSP_IS_CPM_IRQ(vector)) { - bsp_irq_disable_at_CPM(vector); - } else if (BSP_IS_SIU_IRQ(vector)) { - bsp_irq_disable_at_SIU(vector); - } -} - -/* - * IRQ Handler: this is called from the primary exception dispatcher - */ -static int BSP_irq_handle_at_cpm(void) -{ - int32_t cpvecnum; - uint32_t msr; - - /* Get vector number: write IACK=1, then read vectir */ - m8xx.civr = 1; - cpvecnum = (m8xx.civr >> 11) + BSP_CPM_IRQ_LOWEST_OFFSET; - - /* - * Check the vector number, - * enable exceptions and dispatch the handler. - * NOTE: lower-prio interrupts are automatically masked in CPIC - */ - if (BSP_IS_CPM_IRQ(cpvecnum)) { - /* Enable all interrupts */ - msr = ppc_external_exceptions_enable(); - /* Dispatch interrupt handlers */ - bsp_interrupt_handler_dispatch(cpvecnum); - /* Restore machine state */ - ppc_external_exceptions_disable(msr); - } - else { - /* not valid vector */ - bsp_interrupt_handler_default(cpvecnum); - } - /* - * clear "in-service" bit - */ - m8xx.cisr = 1 << (cpvecnum - BSP_CPM_IRQ_LOWEST_OFFSET); - - return 0; -} - -static int BSP_irq_handle_at_siu( unsigned excNum) -{ - int32_t sivecnum; - uint32_t msr; - bool is_cpm_irq; - uint32_t simask_save; - /* - * check, if interrupt is pending - * and repeat as long as valid interrupts are pending - */ - while (0 != (m8xx.simask & m8xx.sipend)) { - /* Get vector number */ - sivecnum = (m8xx.sivec >> 26); - is_cpm_irq = (sivecnum == BSP_CPM_INTERRUPT); - /* - * Check the vector number, mask lower priority interrupts, enable - * exceptions and dispatch the handler. - */ - if (BSP_IS_SIU_IRQ(sivecnum)) { - simask_save = m8xx.simask; - /* - * if this is the CPM interrupt, mask lower prio interrupts at SIU - * else mask lower and same priority interrupts - */ - m8xx.simask &= ~0 << (32 - - sivecnum - - ((is_cpm_irq) ? 1 : 0)); - - if (is_cpm_irq) { - BSP_irq_handle_at_cpm(); - } - else { - /* Enable all interrupts */ - msr = ppc_external_exceptions_enable(); - /* Dispatch interrupt handlers */ - bsp_interrupt_handler_dispatch(sivecnum + BSP_SIU_IRQ_LOWEST_OFFSET); - /* Restore machine state */ - ppc_external_exceptions_disable(msr); - /* - * clear pending bit, if edge triggered interrupt input - */ - m8xx.sipend = 1 << (31 - sivecnum); - } - - - /* Restore initial masks */ - m8xx.simask = simask_save; - } else { - /* not valid vector */ - bsp_interrupt_handler_default(sivecnum); - } - } - return 0; -} - -/* - * Activate the CPIC - */ -static rtems_status_code mpc8xx_cpic_initialize( void) -{ - /* - * mask off all interrupts - */ - m8xx.cimr = 0; - /* - * make sure CPIC request proper level at SIU interrupt controller - */ - m8xx.cicr = (0x00e41f80 | - ((BSP_CPM_INTERRUPT/2) << 13)); - /* - * enable CPIC interrupt in SIU interrupt controller - */ - return bsp_irq_enable_at_SIU(BSP_CPM_INTERRUPT); -} - -/* - * Activate the SIU interrupt controller - */ -static rtems_status_code mpc8xx_siu_int_initialize( void) -{ - /* - * mask off all interrupts - */ - m8xx.simask = 0; - - return RTEMS_SUCCESSFUL; -} - -static int mpc8xx_exception_handler(BSP_Exception_frame *frame, - unsigned exception_number) -{ - return BSP_irq_handle_at_siu(exception_number); -} - -rtems_status_code bsp_interrupt_facility_initialize() -{ - /* Install exception handler */ - if (ppc_exc_set_handler(ASM_EXT_VECTOR, mpc8xx_exception_handler)) { - return RTEMS_IO_ERROR; - } - /* Initialize the SIU interrupt controller */ - if (mpc8xx_siu_int_initialize()) { - return RTEMS_IO_ERROR; - } - /* Initialize the CPIC interrupt controller */ - return mpc8xx_cpic_initialize(); -} diff --git a/c/src/lib/libbsp/powerpc/virtex/Makefile.am b/c/src/lib/libbsp/powerpc/virtex/Makefile.am index e884c8f0e3..c16d057bb5 100644 --- a/c/src/lib/libbsp/powerpc/virtex/Makefile.am +++ b/c/src/lib/libbsp/powerpc/virtex/Makefile.am @@ -45,7 +45,7 @@ librtemsbsp_a_SOURCES += ../../../../../../bsps/powerpc/virtex/console/consoleli # irq librtemsbsp_a_SOURCES += ../../../../../../bsps/shared/irq/irq-default-handler.c -librtemsbsp_a_SOURCES += irq/irq_init.c +librtemsbsp_a_SOURCES += ../../../../../../bsps/powerpc/virtex/irq/irq_init.c # clock librtemsbsp_a_SOURCES +=../../../../../../bsps/powerpc/shared/clock/clock.c diff --git a/c/src/lib/libbsp/powerpc/virtex/irq/irq_init.c b/c/src/lib/libbsp/powerpc/virtex/irq/irq_init.c deleted file mode 100644 index 55194cb1e6..0000000000 --- a/c/src/lib/libbsp/powerpc/virtex/irq/irq_init.c +++ /dev/null @@ -1,167 +0,0 @@ -/*===============================================================*\ -| Project: RTEMS virtex BSP | -+-----------------------------------------------------------------+ -| Partially based on the code references which are named below. | -| Adaptions, modifications, enhancements and any recent parts of | -| the code are: | -| Copyright (c) 2007 | -| Embedded Brains GmbH | -| Obere Lagerstr. 30 | -| D-82178 Puchheim | -| Germany | -| rtems@embedded-brains.de | -+-----------------------------------------------------------------+ -| The license and distribution terms for this file may be | -| found in the file LICENSE in this distribution or at | -| | -| http://www.rtems.org/license/LICENSE. | -| | -+-----------------------------------------------------------------+ -| this file contains the irq controller handler | -\*===============================================================*/ - -/* Content moved from opbintctrl.c: - * - * This file contains definitions and declarations for the - * Xilinx Off Processor Bus (OPB) Interrupt Controller - * - * Author: Keith Robertson - * COPYRIGHT (c) 2005 Linn Products Ltd, Scotland. - * - * The license and distribution terms for this file may be - * found in the file LICENSE in this distribution or at - * http://www.rtems.org/license/LICENSE. - */ - -#include -#include -#include -#include - -#include - -/* - * Acknowledge a mask of interrupts. - */ -static void set_iar(uint32_t mask) -{ - *((volatile uint32_t *) (OPB_INTC_BASE + OPB_INTC_IAR)) = mask; -} - -/* - * Set IER state. Used to (dis)enable a mask of vectors. - * If you only have to do one, use enable/disable_vector. - */ -static void set_ier(uint32_t mask) -{ - *((volatile uint32_t *) (OPB_INTC_BASE + OPB_INTC_IER)) = mask; -} - -/* - * Retrieve contents of Interrupt Pending Register - */ -static uint32_t get_ipr(void) -{ - uint32_t c = *((volatile uint32_t *) (OPB_INTC_BASE + OPB_INTC_IPR)); - return c; -} - -static void BSP_irq_enable_at_opbintc (rtems_irq_number irqnum) -{ - *((volatile uint32_t *) (OPB_INTC_BASE + OPB_INTC_SIE)) - = 1 << (irqnum - BSP_OPBINTC_IRQ_LOWEST_OFFSET); -} - -static void BSP_irq_disable_at_opbintc (rtems_irq_number irqnum) -{ - *((volatile uint32_t *) (OPB_INTC_BASE + OPB_INTC_CIE)) - = 1 << (irqnum - BSP_OPBINTC_IRQ_LOWEST_OFFSET); -} - -/* - * IRQ Handler: this is called from the primary exception dispatcher - */ -static void BSP_irq_handle_at_opbintc(void) -{ - uint32_t ipr; - - /* Get pending interrupts */ - ipr = get_ipr(); - - if (ipr != 0) { - /* Acknowledge all pending interrupts now and service them afterwards */ - set_iar(ipr); - - do { - /* Get highest priority pending interrupt */ - uint32_t i = 31 - ppc_count_leading_zeros(ipr); - - ipr &= ~(1U << i); - - bsp_interrupt_handler_dispatch(i+BSP_OPBINTC_IRQ_LOWEST_OFFSET); - } while (ipr != 0); - } -} - -/* - * activate the interrupt controller - */ -static void opb_intc_init(void) -{ - uint32_t i, mask = 0; - - /* mask off all interrupts */ - set_ier(0x0); - - for (i = 0; i < OPB_INTC_IRQ_MAX; i++) { - mask |= (1 << i); - } - - /* make sure interupt status register is clear before we enable the interrupt controller */ - *((volatile uint32_t *) (OPB_INTC_BASE + OPB_INTC_ISR)) = 0; - - /* acknowledge all interrupt sources */ - set_iar(mask); - - /* Turn on normal hardware operation of interrupt controller */ - *((volatile uint32_t *) (OPB_INTC_BASE + OPB_INTC_MER)) = - (OPB_INTC_MER_HIE); - - /* Enable master interrupt switch for the interrupt controller */ - *((volatile uint32_t *) (OPB_INTC_BASE + OPB_INTC_MER)) = - (OPB_INTC_MER_HIE | OPB_INTC_MER_ME); -} - -void bsp_interrupt_vector_enable(rtems_vector_number vector) -{ - bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector)); - - if (BSP_IS_OPBINTC_IRQ(vector)) { - BSP_irq_enable_at_opbintc(vector); - } -} - -void bsp_interrupt_vector_disable(rtems_vector_number vector) -{ - bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector)); - - if (BSP_IS_OPBINTC_IRQ(vector)) { - BSP_irq_disable_at_opbintc(vector); - } -} - -static int C_dispatch_irq_handler(BSP_Exception_frame *frame, unsigned int excNum) -{ - BSP_irq_handle_at_opbintc(); - - return 0; -} - -rtems_status_code bsp_interrupt_facility_initialize(void) -{ - opb_intc_init(); - - ppc_exc_set_handler(ASM_EXT_VECTOR, C_dispatch_irq_handler); - - return RTEMS_SUCCESSFUL; -} diff --git a/c/src/lib/libbsp/powerpc/virtex4/Makefile.am b/c/src/lib/libbsp/powerpc/virtex4/Makefile.am index 350807f1de..1cb8b3a269 100644 --- a/c/src/lib/libbsp/powerpc/virtex4/Makefile.am +++ b/c/src/lib/libbsp/powerpc/virtex4/Makefile.am @@ -35,7 +35,7 @@ librtemsbsp_a_SOURCES += ../../../../../../bsps/powerpc/virtex4/start/dummy_cons librtemsbsp_a_SOURCES += ../../../../../../bsps/shared/dev/serial/printk-dummy.c # irq -librtemsbsp_a_SOURCES += irq/irq_init.c +librtemsbsp_a_SOURCES += ../../../../../../bsps/powerpc/virtex4/irq/irq_init.c # mmu librtemsbsp_a_SOURCES += mmu/mmu.c diff --git a/c/src/lib/libbsp/powerpc/virtex4/irq/irq_init.c b/c/src/lib/libbsp/powerpc/virtex4/irq/irq_init.c deleted file mode 100644 index 5feafaf4b6..0000000000 --- a/c/src/lib/libbsp/powerpc/virtex4/irq/irq_init.c +++ /dev/null @@ -1,326 +0,0 @@ -/*===============================================================*\ -| Project: RTEMS virtex BSP | -+-----------------------------------------------------------------+ -| Partially based on the code references which are named below. | -| Adaptions, modifications, enhancements and any recent parts of | -| the code are: | -| Copyright (c) 2007 | -| Embedded Brains GmbH | -| Obere Lagerstr. 30 | -| D-82178 Puchheim | -| Germany | -| rtems@embedded-brains.de | -+-----------------------------------------------------------------+ -| The license and distribution terms for this file may be | -| found in the file LICENSE in this distribution or at | -| | -| http://www.rtems.org/license/LICENSE. | -| | -+-----------------------------------------------------------------+ -| this file contains the irq controller handler | -\*===============================================================*/ -#include -#include -#include -#include -#include -#include - -static rtems_irq_connect_data rtemsIrqTbl[BSP_IRQ_NUMBER]; -rtems_irq_connect_data *BSP_rtems_irq_tbl; -rtems_irq_global_settings* BSP_rtems_irq_config; - -/*********************************************************** - * dummy functions for on/off/isOn calls - * these functions just do nothing fulfill the semantic - * requirements to enable/disable a certain interrupt or exception - */ -static void BSP_irq_nop_func(const rtems_irq_connect_data *unused) -{ - /* - * nothing to do - */ -} - -static void BSP_irq_nop_hdl(void *hdl) -{ - /* - * nothing to do - */ -} - -static int BSP_irq_isOn_func(const rtems_irq_connect_data *unused) -{ - /* - * nothing to do - */ - return 0; -} - -/*********************************************************** - * interrupt handler and its enable/disable functions - ***********************************************************/ - -/*********************************************************** - * functions to enable/disable/query external/critical interrupts - */ -void BSP_irqexc_on_fnc(const rtems_irq_connect_data *conn_data) -{ - uint32_t msr_value; - /* - * get current MSR value - */ - _CPU_MSR_GET(msr_value); - - msr_value |= PPC_MSR_EE; - _CPU_MSR_SET(msr_value); -} - -void BSP_irqexc_off_fnc(const rtems_irq_connect_data *unused) -{ - uint32_t msr_value; - /* - * get current MSR value - */ - _CPU_MSR_GET(msr_value); - - msr_value &= ~PPC_MSR_EE; - _CPU_MSR_SET(msr_value); -} - -/*********************************************************** - * High level IRQ handler called from shared_raw_irq_code_entry - */ -static int C_dispatch_irq_handler (BSP_Exception_frame *frame, unsigned int excNum) -{ - /* - * Handle interrupt - */ - switch(excNum) { - case ASM_EXT_VECTOR: - BSP_rtems_irq_tbl[BSP_EXT].hdl(BSP_rtems_irq_tbl[BSP_EXT].handle); - break; - case ASM_BOOKE_DEC_VECTOR: - BSP_rtems_irq_tbl[BSP_PIT].hdl(BSP_rtems_irq_tbl[BSP_PIT].handle); - break; -#if 0 /* Critical interrupts not yet supported */ - case ASM_BOOKE_CRIT_VECTOR: - BSP_rtems_irq_tbl[BSP_CRIT].hdl(BSP_rtems_irq_tbl[BSP_CRIT].handle); - break; -#endif - } - - return 0; -} - -/*********************************************************** - * functions to set/get/remove interrupt handlers - ***********************************************************/ -int BSP_install_rtems_irq_handler (const rtems_irq_connect_data* irq) -{ - rtems_interrupt_level level; - - /* - * check for valid irq name - * if invalid, print error and return 0 - */ - if (!BSP_IS_VALID_IRQ(irq->name)) { - printk("Invalid interrupt vector %d\n",irq->name); - return 0; - } - - /* - * disable interrupts - */ - rtems_interrupt_disable(level); - - /* - * check, that default handler is installed now - */ - if (rtemsIrqTbl[irq->name].hdl != BSP_rtems_irq_config->defaultEntry.hdl) { - rtems_interrupt_enable(level); - printk("IRQ vector %d already connected\n",irq->name); - return 0; - } - - /* - * store new handler data - */ - rtemsIrqTbl[irq->name] = *irq; - - /* - * call "on" function to enable interrupt at device - */ - irq->on(irq); - - /* - * reenable interrupts - */ - rtems_interrupt_enable(level); - - return 1; -} - -int BSP_get_current_rtems_irq_handler (rtems_irq_connect_data* irq) -{ - rtems_interrupt_level level; - - /* - * check for valid IRQ name - */ - if (!BSP_IS_VALID_IRQ(irq->name)) { - return 0; - } - rtems_interrupt_disable(level); - - /* - * return current IRQ entry - */ - *irq = rtemsIrqTbl[irq->name]; - rtems_interrupt_enable(level); - return 1; -} - -int BSP_remove_rtems_irq_handler (const rtems_irq_connect_data* irq) -{ - rtems_interrupt_level level; - - /* - * check for valid IRQ name - */ - if (!BSP_IS_VALID_IRQ(irq->name)) { - return 0; - } - rtems_interrupt_disable(level); - - /* - * check, that specified handler is really connected now - */ - if (rtemsIrqTbl[irq->name].hdl != irq->hdl) { - rtems_interrupt_enable(level); - return 0; - } - - /* - * disable interrupt at source - */ - irq->off(irq); - - /* - * restore default interrupt handler - */ - rtemsIrqTbl[irq->name] = BSP_rtems_irq_config->defaultEntry; - - /* - * reenable interrupts - */ - rtems_interrupt_enable(level); - - return 1; -} - -/*********************************************************** - * functions to set/get the basic interrupt management setup - ***********************************************************/ -/* - * (Re) get info on current RTEMS interrupt management. - */ -int BSP_rtems_irq_mngt_get(rtems_irq_global_settings** ret_ptr) -{ - *ret_ptr = BSP_rtems_irq_config; - return 0; -} - - -/* - * set management stuff - */ -int BSP_rtems_irq_mngt_set(rtems_irq_global_settings* config) -{ - int i; - rtems_interrupt_level level; - - rtems_interrupt_disable(level); - - /* - * store given configuration - */ - BSP_rtems_irq_config = config; - BSP_rtems_irq_tbl = BSP_rtems_irq_config->irqHdlTbl; - - /* - * store any irq-like processor exceptions - */ - for (i = BSP_PROCESSOR_IRQ_LOWEST_OFFSET; - i < BSP_PROCESSOR_IRQ_MAX_OFFSET; - i++) { - if (BSP_rtems_irq_tbl[i].hdl != config->defaultEntry.hdl) { - if (BSP_rtems_irq_tbl[i].on != NULL) { - BSP_rtems_irq_tbl[i].on - (&(BSP_rtems_irq_tbl[i])); - } - } - else { - if (BSP_rtems_irq_tbl[i].off != NULL) { - BSP_rtems_irq_tbl[i].off - (&(BSP_rtems_irq_tbl[i])); - } - } - } - rtems_interrupt_enable(level); - return 1; -} - -/* - * dummy for an empty IRQ handler entry - */ -static rtems_irq_connect_data emptyIrq = { - 0, /* IRQ Name */ - BSP_irq_nop_hdl, /* handler function */ - NULL, /* handle passed to handler */ - BSP_irq_nop_func, /* on function */ - BSP_irq_nop_func, /* off function */ - BSP_irq_isOn_func /* isOn function */ -}; - -static rtems_irq_global_settings initialConfig = { - BSP_IRQ_NUMBER, /* IRQ Number */ - { 0, /* IRQ Name */ - BSP_irq_nop_hdl, /* handler function */ - NULL, /* handle passed to handler */ - BSP_irq_nop_func, /* on function */ - BSP_irq_nop_func, /* off function */ - BSP_irq_isOn_func /* isOn function */ - }, /* emptyIrq */ - rtemsIrqTbl, /* irqHdlTbl */ - 0, /* irqBase */ - NULL /* irqPrioTbl */ -}; - -void BSP_rtems_irq_mngt_init(unsigned cpuId) -{ - int i; - - /* - * connect all exception vectors needed - */ - ppc_exc_set_handler(ASM_EXT_VECTOR, C_dispatch_irq_handler); - ppc_exc_set_handler(ASM_BOOKE_DEC_VECTOR, C_dispatch_irq_handler); - - /* - * setup interrupt handlers table - */ - for (i = 0; - i < BSP_IRQ_NUMBER; - i++) { - rtemsIrqTbl[i] = emptyIrq; - rtemsIrqTbl[i].name = i; - } - - /* - * initialize interrupt management - */ - if (!BSP_rtems_irq_mngt_set(&initialConfig)) { - rtems_panic("Unable to initialize RTEMS interrupt Management!!! System locked\n"); - } -} diff --git a/c/src/lib/libbsp/powerpc/virtex5/Makefile.am b/c/src/lib/libbsp/powerpc/virtex5/Makefile.am index 8bb9be4c7e..d7cef6eee4 100644 --- a/c/src/lib/libbsp/powerpc/virtex5/Makefile.am +++ b/c/src/lib/libbsp/powerpc/virtex5/Makefile.am @@ -37,7 +37,7 @@ librtemsbsp_a_SOURCES += ../../../../../../bsps/powerpc/virtex5/start/dummy_cons librtemsbsp_a_SOURCES += ../../../../../../bsps/shared/dev/serial/printk-dummy.c # irq -librtemsbsp_a_SOURCES += irq/irq_init.c +librtemsbsp_a_SOURCES += ../../../../../../bsps/powerpc/virtex5/irq/irq_init.c # mmu librtemsbsp_a_SOURCES += mmu/mmu.c diff --git a/c/src/lib/libbsp/powerpc/virtex5/irq/irq_init.c b/c/src/lib/libbsp/powerpc/virtex5/irq/irq_init.c deleted file mode 100644 index 1fea9214aa..0000000000 --- a/c/src/lib/libbsp/powerpc/virtex5/irq/irq_init.c +++ /dev/null @@ -1,343 +0,0 @@ -/*===============================================================*\ -| Project: RTEMS virtex BSP | -+-----------------------------------------------------------------+ -| Partially based on the code references which are named below. | -| Adaptions, modifications, enhancements and any recent parts of | -| the code are: | -| Copyright (c) 2007 | -| Embedded Brains GmbH | -| Obere Lagerstr. 30 | -| D-82178 Puchheim | -| Germany | -| rtems@embedded-brains.de | -+-----------------------------------------------------------------+ -| The license and distribution terms for this file may be | -| found in the file LICENSE in this distribution or at | -| | -| http://www.rtems.org/license/LICENSE. | -| | -+-----------------------------------------------------------------+ -| this file contains the irq controller handler | -\*===============================================================*/ -#include -#include -#include -#include -#include -#include - -static rtems_irq_connect_data rtemsIrqTbl[BSP_IRQ_NUMBER]; -rtems_irq_connect_data *BSP_rtems_irq_tbl; -rtems_irq_global_settings* BSP_rtems_irq_config; - -/*********************************************************** - * dummy functions for on/off/isOn calls - * these functions just do nothing fulfill the semantic - * requirements to enable/disable a certain interrupt or exception - */ -static void BSP_irq_nop_func(const rtems_irq_connect_data *unused) -{ - /* - * nothing to do - */ -} - -static void BSP_irq_nop_hdl(void *hdl) -{ - /* - * nothing to do - */ -} - -static int BSP_irq_isOn_func(const rtems_irq_connect_data *unused) -{ - /* - * nothing to do - */ - return 0; -} - -/*********************************************************** - * interrupt handler and its enable/disable functions - ***********************************************************/ - -/*********************************************************** - * functions to enable/disable/query external/critical interrupts - */ -void BSP_irqexc_on_fnc(const rtems_irq_connect_data *conn_data) -{ - uint32_t msr_value; - /* - * get current MSR value - */ - _CPU_MSR_GET(msr_value); - - msr_value |= PPC_MSR_EE; - _CPU_MSR_SET(msr_value); -} - -void BSP_irqexc_off_fnc(const rtems_irq_connect_data *unused) -{ - uint32_t msr_value; - /* - * get current MSR value - */ - _CPU_MSR_GET(msr_value); - - msr_value &= ~PPC_MSR_EE; - _CPU_MSR_SET(msr_value); -} - -SPR_RW(BOOKE_TSR) - -static int C_dispatch_dec_handler (BSP_Exception_frame *frame, unsigned int excNum) -{ - /* Acknowledge the interrupt */ - _write_BOOKE_TSR( BOOKE_TSR_DIS ); - - /* Handle the interrupt */ - BSP_rtems_irq_tbl[BSP_DEC].hdl(BSP_rtems_irq_tbl[BSP_DEC].handle); - - return 0; -} - - -/*********************************************************** - * High level IRQ handler called from shared_raw_irq_code_entry - */ -static int C_dispatch_irq_handler (BSP_Exception_frame *frame, unsigned int excNum) -{ - /* - * Handle interrupt - */ - switch(excNum) { - case ASM_EXT_VECTOR: - BSP_rtems_irq_tbl[BSP_EXT].hdl(BSP_rtems_irq_tbl[BSP_EXT].handle); - break; -#if 0 /* Dealt with by C_dispatch_dec_handler(), above */ - case ASM_BOOKE_DEC_VECTOR: - _write_BOOKE_TSR( BOOKE_TSR_DIS ); - BSP_rtems_irq_tbl[BSP_DEC].hdl(BSP_rtems_irq_tbl[BSP_DEC].handle); - break; -#endif -#if 0 /* Critical interrupts not yet supported */ - case ASM_BOOKE_CRIT_VECTOR: - BSP_rtems_irq_tbl[BSP_CRIT].hdl(BSP_rtems_irq_tbl[BSP_CRIT].handle); - break; -#endif - } - - return 0; -} - -/*********************************************************** - * functions to set/get/remove interrupt handlers - ***********************************************************/ -int BSP_install_rtems_irq_handler (const rtems_irq_connect_data* irq) -{ - rtems_interrupt_level level; - - /* - * check for valid irq name - * if invalid, print error and return 0 - */ - if (!BSP_IS_VALID_IRQ(irq->name)) { - printk("Invalid interrupt vector %d\n",irq->name); - return 0; - } - - /* - * disable interrupts - */ - rtems_interrupt_disable(level); - - /* - * check, that default handler is installed now - */ - if (rtemsIrqTbl[irq->name].hdl != BSP_rtems_irq_config->defaultEntry.hdl) { - rtems_interrupt_enable(level); - printk("IRQ vector %d already connected\n",irq->name); - return 0; - } - - /* - * store new handler data - */ - rtemsIrqTbl[irq->name] = *irq; - - /* - * call "on" function to enable interrupt at device - */ - irq->on(irq); - - /* - * reenable interrupts - */ - rtems_interrupt_enable(level); - - return 1; -} - -int BSP_get_current_rtems_irq_handler (rtems_irq_connect_data* irq) -{ - rtems_interrupt_level level; - - /* - * check for valid IRQ name - */ - if (!BSP_IS_VALID_IRQ(irq->name)) { - return 0; - } - rtems_interrupt_disable(level); - - /* - * return current IRQ entry - */ - *irq = rtemsIrqTbl[irq->name]; - rtems_interrupt_enable(level); - return 1; -} - -int BSP_remove_rtems_irq_handler (const rtems_irq_connect_data* irq) -{ - rtems_interrupt_level level; - - /* - * check for valid IRQ name - */ - if (!BSP_IS_VALID_IRQ(irq->name)) { - return 0; - } - rtems_interrupt_disable(level); - - /* - * check, that specified handler is really connected now - */ - if (rtemsIrqTbl[irq->name].hdl != irq->hdl) { - rtems_interrupt_enable(level); - return 0; - } - - /* - * disable interrupt at source - */ - irq->off(irq); - - /* - * restore default interrupt handler - */ - rtemsIrqTbl[irq->name] = BSP_rtems_irq_config->defaultEntry; - - /* - * reenable interrupts - */ - rtems_interrupt_enable(level); - - return 1; -} - -/*********************************************************** - * functions to set/get the basic interrupt management setup - ***********************************************************/ -/* - * (Re) get info on current RTEMS interrupt management. - */ -int BSP_rtems_irq_mngt_get(rtems_irq_global_settings** ret_ptr) -{ - *ret_ptr = BSP_rtems_irq_config; - return 0; -} - - -/* - * set management stuff - */ -int BSP_rtems_irq_mngt_set(rtems_irq_global_settings* config) -{ - int i; - rtems_interrupt_level level; - - rtems_interrupt_disable(level); - - /* - * store given configuration - */ - BSP_rtems_irq_config = config; - BSP_rtems_irq_tbl = BSP_rtems_irq_config->irqHdlTbl; - - /* - * store any irq-like processor exceptions - */ - for (i = BSP_PROCESSOR_IRQ_LOWEST_OFFSET; - i < BSP_PROCESSOR_IRQ_MAX_OFFSET; - i++) { - if (BSP_rtems_irq_tbl[i].hdl != config->defaultEntry.hdl) { - if (BSP_rtems_irq_tbl[i].on != NULL) { - BSP_rtems_irq_tbl[i].on - (&(BSP_rtems_irq_tbl[i])); - } - } - else { - if (BSP_rtems_irq_tbl[i].off != NULL) { - BSP_rtems_irq_tbl[i].off - (&(BSP_rtems_irq_tbl[i])); - } - } - } - rtems_interrupt_enable(level); - return 1; -} - -/* - * dummy for an empty IRQ handler entry - */ -static rtems_irq_connect_data emptyIrq = { - 0, /* IRQ Name */ - BSP_irq_nop_hdl, /* handler function */ - NULL, /* handle passed to handler */ - BSP_irq_nop_func, /* on function */ - BSP_irq_nop_func, /* off function */ - BSP_irq_isOn_func /* isOn function */ -}; - -static rtems_irq_global_settings initialConfig = { - BSP_IRQ_NUMBER, /* IRQ number */ - { 0, /* IRQ Name */ - BSP_irq_nop_hdl, /* handler function */ - NULL, /* handle passed to handler */ - BSP_irq_nop_func, /* on function */ - BSP_irq_nop_func, /* off function */ - BSP_irq_isOn_func /* isOn function */ - }, /* emptyIrq */ - rtemsIrqTbl, /* irqHdlTbl */ - 0, /* irqBase */ - NULL /* irqPrioTbl */ -}; - -void BSP_rtems_irq_mngt_init(unsigned cpuId) -{ - int i; - - /* - * connect all exception vectors needed - */ - ppc_exc_set_handler(ASM_EXT_VECTOR, C_dispatch_irq_handler); - ppc_exc_set_handler(ASM_BOOKE_DEC_VECTOR, C_dispatch_dec_handler); - - /* - * setup interrupt handlers table - */ - for (i = 0; - i < BSP_IRQ_NUMBER; - i++) { - rtemsIrqTbl[i] = emptyIrq; - rtemsIrqTbl[i].name = i; - } - - /* - * initialize interrupt management - */ - if (!BSP_rtems_irq_mngt_set(&initialConfig)) { - rtems_panic("Unable to initialize RTEMS interrupt Management!!! System locked\n"); - } -} diff --git a/c/src/lib/libbsp/riscv/riscv_generic/Makefile.am b/c/src/lib/libbsp/riscv/riscv_generic/Makefile.am index 80afe8dd39..31d1cf2d49 100644 --- a/c/src/lib/libbsp/riscv/riscv_generic/Makefile.am +++ b/c/src/lib/libbsp/riscv/riscv_generic/Makefile.am @@ -52,7 +52,7 @@ librtemsbsp_a_SOURCES += ../../../../../../bsps/shared/dev/serial/console-polled # IRQ librtemsbsp_a_SOURCES += ../../../../../../bsps/shared/irq/irq-default-handler.c -librtemsbsp_a_SOURCES += irq/irq.c +librtemsbsp_a_SOURCES += ../../../../../../bsps/riscv/riscv_generic/irq/irq.c # Cache librtemsbsp_a_SOURCES += ../../../../../../bsps/shared/cache/nocache.c diff --git a/c/src/lib/libbsp/riscv/riscv_generic/irq/irq.c b/c/src/lib/libbsp/riscv/riscv_generic/irq/irq.c deleted file mode 100644 index 8090dcea98..0000000000 --- a/c/src/lib/libbsp/riscv/riscv_generic/irq/irq.c +++ /dev/null @@ -1,60 +0,0 @@ -/** - * @file - * - * @ingroup riscv_interrupt - * - * @brief Interrupt support. - */ - -/* - * RISCV CPU Dependent Source - * - * Copyright (c) 2015 University of York. - * Hesham Almatary - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#include -#include - -/* Almost all of the jobs that the following functions should - * do are implemented in cpukit - */ - -void bsp_interrupt_handler_default(rtems_vector_number vector) -{ - printk("spurious interrupt: %u\n", vector); -} - -rtems_status_code bsp_interrupt_facility_initialize() -{ - return RTEMS_NOT_IMPLEMENTED; -} - -void bsp_interrupt_vector_enable(rtems_vector_number vector) -{ -} - -void bsp_interrupt_vector_disable(rtems_vector_number vector) -{ -} -- cgit v1.2.3