From d60d303cf1fbf352e5d40eba472183b402069bc2 Mon Sep 17 00:00:00 2001 From: Sebastian Huber Date: Fri, 20 Apr 2018 13:33:24 +0200 Subject: bsps/sparc: Move shared files to bsps This patch is a part of the BSP source reorganization. Update #3285. --- c/src/lib/libbsp/sparc/configure.ac | 2 +- c/src/lib/libbsp/sparc/erc32/Makefile.am | 6 +- c/src/lib/libbsp/sparc/leon2/Makefile.am | 120 +- c/src/lib/libbsp/sparc/leon3/Makefile.am | 134 +- c/src/lib/libbsp/sparc/shared/1553/b1553brm.c | 1548 --------- c/src/lib/libbsp/sparc/shared/1553/b1553rt.c | 856 ----- c/src/lib/libbsp/sparc/shared/1553/gr1553b.c | 310 -- c/src/lib/libbsp/sparc/shared/1553/gr1553bc.c | 1719 ---------- c/src/lib/libbsp/sparc/shared/1553/gr1553bm.c | 544 ---- c/src/lib/libbsp/sparc/shared/1553/gr1553rt.c | 1218 ------- c/src/lib/libbsp/sparc/shared/amba/ahbstat.c | 245 -- c/src/lib/libbsp/sparc/shared/amba/ambapp.c | 455 --- c/src/lib/libbsp/sparc/shared/amba/ambapp_alloc.c | 25 - c/src/lib/libbsp/sparc/shared/amba/ambapp_count.c | 23 - c/src/lib/libbsp/sparc/shared/amba/ambapp_depth.c | 25 - .../libbsp/sparc/shared/amba/ambapp_find_by_idx.c | 39 - c/src/lib/libbsp/sparc/shared/amba/ambapp_freq.c | 109 - c/src/lib/libbsp/sparc/shared/amba/ambapp_names.c | 447 --- c/src/lib/libbsp/sparc/shared/amba/ambapp_old.c | 112 - c/src/lib/libbsp/sparc/shared/amba/ambapp_parent.c | 23 - c/src/lib/libbsp/sparc/shared/amba/ambapp_show.c | 68 - c/src/lib/libbsp/sparc/shared/analog/gradcdac.c | 579 ---- c/src/lib/libbsp/sparc/shared/ascs/grascs.c | 616 ---- c/src/lib/libbsp/sparc/shared/can/canmux.c | 197 -- c/src/lib/libbsp/sparc/shared/can/grcan.c | 2001 ------------ c/src/lib/libbsp/sparc/shared/can/occan.c | 1984 ------------ c/src/lib/libbsp/sparc/shared/can/satcan.c | 714 ----- c/src/lib/libbsp/sparc/shared/drvmgr/ambapp_bus.c | 840 ----- .../libbsp/sparc/shared/drvmgr/ambapp_bus_grlib.c | 250 -- .../libbsp/sparc/shared/drvmgr/ambapp_bus_leon2.c | 266 -- .../sparc/shared/drvmgr/get_resarray_count.c | 20 - .../libbsp/sparc/shared/drvmgr/leon2_amba_bus.c | 449 --- c/src/lib/libbsp/sparc/shared/gnatcommon.c | 117 - c/src/lib/libbsp/sparc/shared/gpio/gpiolib.c | 271 -- c/src/lib/libbsp/sparc/shared/gpio/grgpio.c | 449 --- c/src/lib/libbsp/sparc/shared/i2c/i2cmst.c | 415 --- c/src/lib/libbsp/sparc/shared/iommu/griommu.c | 1455 --------- .../lib/libbsp/sparc/shared/irq/bsp_isr_handler.c | 35 - c/src/lib/libbsp/sparc/shared/irq/genirq.c | 243 -- c/src/lib/libbsp/sparc/shared/irq/irq-shared.c | 103 - c/src/lib/libbsp/sparc/shared/l2c/l2c.c | 2110 ------------- c/src/lib/libbsp/sparc/shared/mem/mctrl.c | 212 -- c/src/lib/libbsp/sparc/shared/net/README | 7 - c/src/lib/libbsp/sparc/shared/net/greth.c | 1568 --------- .../sparc/shared/net/network_interface_add.c | 62 - c/src/lib/libbsp/sparc/shared/pci/gr_701.c | 623 ---- c/src/lib/libbsp/sparc/shared/pci/gr_cpci_gr740.c | 772 ----- c/src/lib/libbsp/sparc/shared/pci/gr_leon4_n2x.c | 795 ----- .../lib/libbsp/sparc/shared/pci/gr_rasta_adcdac.c | 699 ---- c/src/lib/libbsp/sparc/shared/pci/gr_rasta_io.c | 897 ------ .../libbsp/sparc/shared/pci/gr_rasta_spw_router.c | 703 ----- c/src/lib/libbsp/sparc/shared/pci/gr_rasta_tmtc.c | 901 ------ c/src/lib/libbsp/sparc/shared/pci/gr_tmtc_1553.c | 602 ---- c/src/lib/libbsp/sparc/shared/pci/grpci.c | 722 ----- c/src/lib/libbsp/sparc/shared/pci/grpci2.c | 1000 ------ c/src/lib/libbsp/sparc/shared/pci/grpci2dma.c | 2059 ------------ .../libbsp/sparc/shared/pci/pci_memreg_sparc_be.c | 27 - .../libbsp/sparc/shared/pci/pci_memreg_sparc_le.c | 28 - c/src/lib/libbsp/sparc/shared/pci/pcif.c | 586 ---- c/src/lib/libbsp/sparc/shared/pwm/grpwm.c | 853 ----- c/src/lib/libbsp/sparc/shared/scrub/memscrub.c | 692 ---- c/src/lib/libbsp/sparc/shared/slink/grslink.c | 661 ---- c/src/lib/libbsp/sparc/shared/spi/spictrl.c | 1017 ------ c/src/lib/libbsp/sparc/shared/spw/grspw.c | 2035 ------------ c/src/lib/libbsp/sparc/shared/spw/grspw_pkt.c | 3327 -------------------- c/src/lib/libbsp/sparc/shared/spw/grspw_router.c | 1988 ------------ c/src/lib/libbsp/sparc/shared/stat/l4stat.c | 626 ---- c/src/lib/libbsp/sparc/shared/time/grctm.c | 410 --- c/src/lib/libbsp/sparc/shared/time/spwcuc.c | 370 --- c/src/lib/libbsp/sparc/shared/tmtc/grtc.c | 1998 ------------ c/src/lib/libbsp/sparc/shared/tmtc/grtm.c | 1623 ---------- c/src/lib/libbsp/sparc/shared/uart/apbuart_cons.c | 867 ----- .../lib/libbsp/sparc/shared/uart/apbuart_termios.c | 311 -- c/src/lib/libbsp/sparc/shared/uart/cons.c | 136 - 74 files changed, 131 insertions(+), 50188 deletions(-) delete mode 100644 c/src/lib/libbsp/sparc/shared/1553/b1553brm.c delete mode 100644 c/src/lib/libbsp/sparc/shared/1553/b1553rt.c delete mode 100644 c/src/lib/libbsp/sparc/shared/1553/gr1553b.c delete mode 100644 c/src/lib/libbsp/sparc/shared/1553/gr1553bc.c delete mode 100644 c/src/lib/libbsp/sparc/shared/1553/gr1553bm.c delete mode 100644 c/src/lib/libbsp/sparc/shared/1553/gr1553rt.c delete mode 100644 c/src/lib/libbsp/sparc/shared/amba/ahbstat.c delete mode 100644 c/src/lib/libbsp/sparc/shared/amba/ambapp.c delete mode 100644 c/src/lib/libbsp/sparc/shared/amba/ambapp_alloc.c delete mode 100644 c/src/lib/libbsp/sparc/shared/amba/ambapp_count.c delete mode 100644 c/src/lib/libbsp/sparc/shared/amba/ambapp_depth.c delete mode 100644 c/src/lib/libbsp/sparc/shared/amba/ambapp_find_by_idx.c delete mode 100644 c/src/lib/libbsp/sparc/shared/amba/ambapp_freq.c delete mode 100644 c/src/lib/libbsp/sparc/shared/amba/ambapp_names.c delete mode 100644 c/src/lib/libbsp/sparc/shared/amba/ambapp_old.c delete mode 100644 c/src/lib/libbsp/sparc/shared/amba/ambapp_parent.c delete mode 100644 c/src/lib/libbsp/sparc/shared/amba/ambapp_show.c delete mode 100644 c/src/lib/libbsp/sparc/shared/analog/gradcdac.c delete mode 100644 c/src/lib/libbsp/sparc/shared/ascs/grascs.c delete mode 100644 c/src/lib/libbsp/sparc/shared/can/canmux.c delete mode 100644 c/src/lib/libbsp/sparc/shared/can/grcan.c delete mode 100644 c/src/lib/libbsp/sparc/shared/can/occan.c delete mode 100644 c/src/lib/libbsp/sparc/shared/can/satcan.c delete mode 100644 c/src/lib/libbsp/sparc/shared/drvmgr/ambapp_bus.c delete mode 100644 c/src/lib/libbsp/sparc/shared/drvmgr/ambapp_bus_grlib.c delete mode 100644 c/src/lib/libbsp/sparc/shared/drvmgr/ambapp_bus_leon2.c delete mode 100644 c/src/lib/libbsp/sparc/shared/drvmgr/get_resarray_count.c delete mode 100644 c/src/lib/libbsp/sparc/shared/drvmgr/leon2_amba_bus.c delete mode 100644 c/src/lib/libbsp/sparc/shared/gnatcommon.c delete mode 100644 c/src/lib/libbsp/sparc/shared/gpio/gpiolib.c delete mode 100644 c/src/lib/libbsp/sparc/shared/gpio/grgpio.c delete mode 100644 c/src/lib/libbsp/sparc/shared/i2c/i2cmst.c delete mode 100644 c/src/lib/libbsp/sparc/shared/iommu/griommu.c delete mode 100644 c/src/lib/libbsp/sparc/shared/irq/bsp_isr_handler.c delete mode 100644 c/src/lib/libbsp/sparc/shared/irq/genirq.c delete mode 100644 c/src/lib/libbsp/sparc/shared/irq/irq-shared.c delete mode 100644 c/src/lib/libbsp/sparc/shared/l2c/l2c.c delete mode 100644 c/src/lib/libbsp/sparc/shared/mem/mctrl.c delete mode 100644 c/src/lib/libbsp/sparc/shared/net/README delete mode 100644 c/src/lib/libbsp/sparc/shared/net/greth.c delete mode 100644 c/src/lib/libbsp/sparc/shared/net/network_interface_add.c delete mode 100644 c/src/lib/libbsp/sparc/shared/pci/gr_701.c delete mode 100644 c/src/lib/libbsp/sparc/shared/pci/gr_cpci_gr740.c delete mode 100644 c/src/lib/libbsp/sparc/shared/pci/gr_leon4_n2x.c delete mode 100644 c/src/lib/libbsp/sparc/shared/pci/gr_rasta_adcdac.c delete mode 100644 c/src/lib/libbsp/sparc/shared/pci/gr_rasta_io.c delete mode 100644 c/src/lib/libbsp/sparc/shared/pci/gr_rasta_spw_router.c delete mode 100644 c/src/lib/libbsp/sparc/shared/pci/gr_rasta_tmtc.c delete mode 100644 c/src/lib/libbsp/sparc/shared/pci/gr_tmtc_1553.c delete mode 100644 c/src/lib/libbsp/sparc/shared/pci/grpci.c delete mode 100644 c/src/lib/libbsp/sparc/shared/pci/grpci2.c delete mode 100644 c/src/lib/libbsp/sparc/shared/pci/grpci2dma.c delete mode 100644 c/src/lib/libbsp/sparc/shared/pci/pci_memreg_sparc_be.c delete mode 100644 c/src/lib/libbsp/sparc/shared/pci/pci_memreg_sparc_le.c delete mode 100644 c/src/lib/libbsp/sparc/shared/pci/pcif.c delete mode 100644 c/src/lib/libbsp/sparc/shared/pwm/grpwm.c delete mode 100644 c/src/lib/libbsp/sparc/shared/scrub/memscrub.c delete mode 100644 c/src/lib/libbsp/sparc/shared/slink/grslink.c delete mode 100644 c/src/lib/libbsp/sparc/shared/spi/spictrl.c delete mode 100644 c/src/lib/libbsp/sparc/shared/spw/grspw.c delete mode 100644 c/src/lib/libbsp/sparc/shared/spw/grspw_pkt.c delete mode 100644 c/src/lib/libbsp/sparc/shared/spw/grspw_router.c delete mode 100644 c/src/lib/libbsp/sparc/shared/stat/l4stat.c delete mode 100644 c/src/lib/libbsp/sparc/shared/time/grctm.c delete mode 100644 c/src/lib/libbsp/sparc/shared/time/spwcuc.c delete mode 100644 c/src/lib/libbsp/sparc/shared/tmtc/grtc.c delete mode 100644 c/src/lib/libbsp/sparc/shared/tmtc/grtm.c delete mode 100644 c/src/lib/libbsp/sparc/shared/uart/apbuart_cons.c delete mode 100644 c/src/lib/libbsp/sparc/shared/uart/apbuart_termios.c delete mode 100644 c/src/lib/libbsp/sparc/shared/uart/cons.c (limited to 'c/src/lib/libbsp') diff --git a/c/src/lib/libbsp/sparc/configure.ac b/c/src/lib/libbsp/sparc/configure.ac index 330345ccff..e51b28f25d 100644 --- a/c/src/lib/libbsp/sparc/configure.ac +++ b/c/src/lib/libbsp/sparc/configure.ac @@ -3,7 +3,7 @@ AC_PREREQ([2.69]) AC_INIT([rtems-c-src-lib-libbsp-sparc], [_RTEMS_VERSION],[https://devel.rtems.org/newticket]) -AC_CONFIG_SRCDIR([shared]) +AC_CONFIG_SRCDIR([leon3]) RTEMS_TOP(../../../../..) RTEMS_SOURCE_TOP RTEMS_BUILD_TOP diff --git a/c/src/lib/libbsp/sparc/erc32/Makefile.am b/c/src/lib/libbsp/sparc/erc32/Makefile.am index d0933076a9..10f72b2901 100644 --- a/c/src/lib/libbsp/sparc/erc32/Makefile.am +++ b/c/src/lib/libbsp/sparc/erc32/Makefile.am @@ -36,7 +36,7 @@ librtemsbsp_a_SOURCES += ../../../../../../bsps/sparc/shared/start/bsp_fatal_exi librtemsbsp_a_SOURCES += ../../../../../../bsps/sparc/shared/start/bsp_fatal_halt.c # gnatsupp librtemsbsp_a_SOURCES += gnatsupp/gnatsupp.c -librtemsbsp_a_SOURCES += ../shared/gnatcommon.c +librtemsbsp_a_SOURCES += ../../../../../../bsps/sparc/shared/gnatcommon.c # console librtemsbsp_a_SOURCES += ../../../../../../bsps/shared/dev/serial/legacy-console.c librtemsbsp_a_SOURCES += ../../../../../../bsps/shared/dev/serial/legacy-console-control.c @@ -50,8 +50,8 @@ librtemsbsp_a_SOURCES +=../../../../../../bsps/sparc/erc32/clock/ckinit.c librtemsbsp_a_SOURCES += ../../../../../../bsps/sparc/erc32/btimer/btimer.c # IRQ -librtemsbsp_a_SOURCES += ../shared/irq/irq-shared.c -librtemsbsp_a_SOURCES += ../shared/irq/bsp_isr_handler.c +librtemsbsp_a_SOURCES += ../../../../../../bsps/sparc/shared/irq/irq-shared.c +librtemsbsp_a_SOURCES += ../../../../../../bsps/sparc/shared/irq/bsp_isr_handler.c librtemsbsp_a_SOURCES += ../../../../../../bsps/shared/irq/irq-default-handler.c if HAS_SMP diff --git a/c/src/lib/libbsp/sparc/leon2/Makefile.am b/c/src/lib/libbsp/sparc/leon2/Makefile.am index 5a6d14903f..862cc536c2 100644 --- a/c/src/lib/libbsp/sparc/leon2/Makefile.am +++ b/c/src/lib/libbsp/sparc/leon2/Makefile.am @@ -37,119 +37,119 @@ librtemsbsp_a_SOURCES += ../../../../../../bsps/sparc/shared/start/bsp_fatal_hal # gnatsupp librtemsbsp_a_SOURCES += gnatsupp/gnatsupp.c -librtemsbsp_a_SOURCES += ../shared/gnatcommon.c +librtemsbsp_a_SOURCES += ../../../../../../bsps/sparc/shared/gnatcommon.c # console librtemsbsp_a_SOURCES += ../../../../../../bsps/sparc/leon2/console/console.c librtemsbsp_a_SOURCES += ../../../../../../bsps/sparc/leon2/console/debugputs.c # clock librtemsbsp_a_SOURCES +=../../../../../../bsps/sparc/leon2/clock/ckinit.c # IRQ -librtemsbsp_a_SOURCES += ../shared/irq/genirq.c -librtemsbsp_a_SOURCES += ../shared/irq/irq-shared.c -librtemsbsp_a_SOURCES += ../shared/irq/bsp_isr_handler.c +librtemsbsp_a_SOURCES += ../../../../../../bsps/sparc/shared/irq/genirq.c +librtemsbsp_a_SOURCES += ../../../../../../bsps/sparc/shared/irq/irq-shared.c +librtemsbsp_a_SOURCES += ../../../../../../bsps/sparc/shared/irq/bsp_isr_handler.c librtemsbsp_a_SOURCES += ../../../../../../bsps/shared/irq/irq-default-handler.c # AMBA bus -librtemsbsp_a_SOURCES += ../shared/amba/ambapp.c -librtemsbsp_a_SOURCES += ../shared/amba/ambapp_alloc.c -librtemsbsp_a_SOURCES += ../shared/amba/ambapp_count.c -librtemsbsp_a_SOURCES += ../shared/amba/ambapp_depth.c -librtemsbsp_a_SOURCES += ../shared/amba/ambapp_find_by_idx.c -librtemsbsp_a_SOURCES += ../shared/amba/ambapp_freq.c -librtemsbsp_a_SOURCES += ../shared/amba/ambapp_parent.c -librtemsbsp_a_SOURCES += ../shared/amba/ambapp_old.c -librtemsbsp_a_SOURCES += ../shared/amba/ambapp_names.c -librtemsbsp_a_SOURCES += ../shared/amba/ambapp_show.c -librtemsbsp_a_SOURCES += ../shared/amba/ahbstat.c +librtemsbsp_a_SOURCES += ../../../../../../bsps/sparc/shared/amba/ambapp.c +librtemsbsp_a_SOURCES += ../../../../../../bsps/sparc/shared/amba/ambapp_alloc.c +librtemsbsp_a_SOURCES += ../../../../../../bsps/sparc/shared/amba/ambapp_count.c +librtemsbsp_a_SOURCES += ../../../../../../bsps/sparc/shared/amba/ambapp_depth.c +librtemsbsp_a_SOURCES += ../../../../../../bsps/sparc/shared/amba/ambapp_find_by_idx.c +librtemsbsp_a_SOURCES += ../../../../../../bsps/sparc/shared/amba/ambapp_freq.c +librtemsbsp_a_SOURCES += ../../../../../../bsps/sparc/shared/amba/ambapp_parent.c +librtemsbsp_a_SOURCES += ../../../../../../bsps/sparc/shared/amba/ambapp_old.c +librtemsbsp_a_SOURCES += ../../../../../../bsps/sparc/shared/amba/ambapp_names.c +librtemsbsp_a_SOURCES += ../../../../../../bsps/sparc/shared/amba/ambapp_show.c +librtemsbsp_a_SOURCES += ../../../../../../bsps/sparc/shared/amba/ahbstat.c # Clock Driver and Timer Library librtemsbsp_a_SOURCES += ../../../../../../bsps/sparc/shared/btimer/gptimer.c librtemsbsp_a_SOURCES += ../../../../../../bsps/sparc/shared/btimer/tlib.c # PCI -librtemsbsp_a_SOURCES += ../shared/pci/grpci2.c -librtemsbsp_a_SOURCES += ../shared/pci/grpci2dma.c -librtemsbsp_a_SOURCES += ../shared/pci/grpci.c -librtemsbsp_a_SOURCES += ../shared/pci/pcif.c -librtemsbsp_a_SOURCES += ../shared/pci/pci_memreg_sparc_le.c -librtemsbsp_a_SOURCES += ../shared/pci/pci_memreg_sparc_be.c +librtemsbsp_a_SOURCES += ../../../../../../bsps/sparc/shared/pci/grpci2.c +librtemsbsp_a_SOURCES += ../../../../../../bsps/sparc/shared/pci/grpci2dma.c +librtemsbsp_a_SOURCES += ../../../../../../bsps/sparc/shared/pci/grpci.c +librtemsbsp_a_SOURCES += ../../../../../../bsps/sparc/shared/pci/pcif.c +librtemsbsp_a_SOURCES += ../../../../../../bsps/sparc/shared/pci/pci_memreg_sparc_le.c +librtemsbsp_a_SOURCES += ../../../../../../bsps/sparc/shared/pci/pci_memreg_sparc_be.c librtemsbsp_a_SOURCES += pci/at697_pci.c # PCI target devices -librtemsbsp_a_SOURCES += ../shared/pci/gr_701.c -librtemsbsp_a_SOURCES += ../shared/pci/gr_rasta_adcdac.c -librtemsbsp_a_SOURCES += ../shared/pci/gr_rasta_io.c -librtemsbsp_a_SOURCES += ../shared/pci/gr_rasta_spw_router.c -librtemsbsp_a_SOURCES += ../shared/pci/gr_rasta_tmtc.c -librtemsbsp_a_SOURCES += ../shared/pci/gr_leon4_n2x.c -librtemsbsp_a_SOURCES += ../shared/pci/gr_cpci_gr740.c +librtemsbsp_a_SOURCES += ../../../../../../bsps/sparc/shared/pci/gr_701.c +librtemsbsp_a_SOURCES += ../../../../../../bsps/sparc/shared/pci/gr_rasta_adcdac.c +librtemsbsp_a_SOURCES += ../../../../../../bsps/sparc/shared/pci/gr_rasta_io.c +librtemsbsp_a_SOURCES += ../../../../../../bsps/sparc/shared/pci/gr_rasta_spw_router.c +librtemsbsp_a_SOURCES += ../../../../../../bsps/sparc/shared/pci/gr_rasta_tmtc.c +librtemsbsp_a_SOURCES += ../../../../../../bsps/sparc/shared/pci/gr_leon4_n2x.c +librtemsbsp_a_SOURCES += ../../../../../../bsps/sparc/shared/pci/gr_cpci_gr740.c # B1553BRM -librtemsbsp_a_SOURCES += ../shared/1553/b1553brm.c -librtemsbsp_a_SOURCES += ../shared/1553/b1553rt.c +librtemsbsp_a_SOURCES += ../../../../../../bsps/sparc/shared/1553/b1553brm.c +librtemsbsp_a_SOURCES += ../../../../../../bsps/sparc/shared/1553/b1553rt.c # GR1553B -librtemsbsp_a_SOURCES += ../shared/1553/gr1553b.c -librtemsbsp_a_SOURCES += ../shared/1553/gr1553bc.c -librtemsbsp_a_SOURCES += ../shared/1553/gr1553bm.c -librtemsbsp_a_SOURCES += ../shared/1553/gr1553rt.c +librtemsbsp_a_SOURCES += ../../../../../../bsps/sparc/shared/1553/gr1553b.c +librtemsbsp_a_SOURCES += ../../../../../../bsps/sparc/shared/1553/gr1553bc.c +librtemsbsp_a_SOURCES += ../../../../../../bsps/sparc/shared/1553/gr1553bm.c +librtemsbsp_a_SOURCES += ../../../../../../bsps/sparc/shared/1553/gr1553rt.c # CAN -librtemsbsp_a_SOURCES += ../shared/can/occan.c -librtemsbsp_a_SOURCES += ../shared/can/grcan.c +librtemsbsp_a_SOURCES += ../../../../../../bsps/sparc/shared/can/occan.c +librtemsbsp_a_SOURCES += ../../../../../../bsps/sparc/shared/can/grcan.c # SpaceWire if !HAS_SMP -librtemsbsp_a_SOURCES += ../shared/spw/grspw.c +librtemsbsp_a_SOURCES += ../../../../../../bsps/sparc/shared/spw/grspw.c endif -librtemsbsp_a_SOURCES += ../shared/spw/grspw_pkt.c -librtemsbsp_a_SOURCES += ../shared/spw/grspw_router.c +librtemsbsp_a_SOURCES += ../../../../../../bsps/sparc/shared/spw/grspw_pkt.c +librtemsbsp_a_SOURCES += ../../../../../../bsps/sparc/shared/spw/grspw_router.c # UART (RAW) # I2CMST -librtemsbsp_a_SOURCES += ../shared/i2c/i2cmst.c +librtemsbsp_a_SOURCES += ../../../../../../bsps/sparc/shared/i2c/i2cmst.c # SPI -librtemsbsp_a_SOURCES += ../shared/spi/spictrl.c +librtemsbsp_a_SOURCES += ../../../../../../bsps/sparc/shared/spi/spictrl.c # TIME -librtemsbsp_a_SOURCES += ../shared/time/spwcuc.c -librtemsbsp_a_SOURCES += ../shared/time/grctm.c +librtemsbsp_a_SOURCES += ../../../../../../bsps/sparc/shared/time/spwcuc.c +librtemsbsp_a_SOURCES += ../../../../../../bsps/sparc/shared/time/grctm.c # GPIO -librtemsbsp_a_SOURCES += ../shared/gpio/grgpio.c -librtemsbsp_a_SOURCES += ../shared/gpio/gpiolib.c +librtemsbsp_a_SOURCES += ../../../../../../bsps/sparc/shared/gpio/grgpio.c +librtemsbsp_a_SOURCES += ../../../../../../bsps/sparc/shared/gpio/gpiolib.c # PWM -librtemsbsp_a_SOURCES += ../shared/pwm/grpwm.c +librtemsbsp_a_SOURCES += ../../../../../../bsps/sparc/shared/pwm/grpwm.c # ADC and DAC -librtemsbsp_a_SOURCES += ../shared/analog/gradcdac.c +librtemsbsp_a_SOURCES += ../../../../../../bsps/sparc/shared/analog/gradcdac.c # Memory controllers -librtemsbsp_a_SOURCES += ../shared/mem/mctrl.c +librtemsbsp_a_SOURCES += ../../../../../../bsps/sparc/shared/mem/mctrl.c # l2cache -librtemsbsp_a_SOURCES += ../shared/l2c/l2c.c +librtemsbsp_a_SOURCES += ../../../../../../bsps/sparc/shared/l2c/l2c.c librtemsbsp_a_SOURCES += ../../../../../../bsps/sparc/leon2/start/cache.c # griommu -librtemsbsp_a_SOURCES += ../shared/iommu/griommu.c +librtemsbsp_a_SOURCES += ../../../../../../bsps/sparc/shared/iommu/griommu.c # timer librtemsbsp_a_SOURCES += ../../../../../../bsps/sparc/leon2/btimer/btimer.c # TM/TC -librtemsbsp_a_SOURCES += ../shared/tmtc/grtc.c -librtemsbsp_a_SOURCES += ../shared/tmtc/grtm.c +librtemsbsp_a_SOURCES += ../../../../../../bsps/sparc/shared/tmtc/grtc.c +librtemsbsp_a_SOURCES += ../../../../../../bsps/sparc/shared/tmtc/grtm.c # MEMSCRUB -librtemsbsp_a_SOURCES += ../shared/scrub/memscrub.c +librtemsbsp_a_SOURCES += ../../../../../../bsps/sparc/shared/scrub/memscrub.c # L4STAT -librtemsbsp_a_SOURCES += ../shared/stat/l4stat.c +librtemsbsp_a_SOURCES += ../../../../../../bsps/sparc/shared/stat/l4stat.c # Driver Manager -librtemsbsp_a_SOURCES += ../shared/drvmgr/ambapp_bus.c -librtemsbsp_a_SOURCES += ../shared/drvmgr/ambapp_bus_leon2.c -librtemsbsp_a_SOURCES += ../shared/drvmgr/leon2_amba_bus.c -librtemsbsp_a_SOURCES += ../shared/drvmgr/get_resarray_count.c +librtemsbsp_a_SOURCES += ../../../../../../bsps/sparc/shared/drvmgr/ambapp_bus.c +librtemsbsp_a_SOURCES += ../../../../../../bsps/sparc/shared/drvmgr/ambapp_bus_leon2.c +librtemsbsp_a_SOURCES += ../../../../../../bsps/sparc/shared/drvmgr/leon2_amba_bus.c +librtemsbsp_a_SOURCES += ../../../../../../bsps/sparc/shared/drvmgr/get_resarray_count.c if HAS_SMP librtemsbsp_a_SOURCES += ../../../../../../bsps/shared/start/bspsmp-dummy.c @@ -159,8 +159,8 @@ endif if HAS_NETWORKING librtemsbsp_a_SOURCES += leon_smc91111/leon_smc91111.c librtemsbsp_a_SOURCES += leon_open_eth/leon_open_eth.c -librtemsbsp_a_SOURCES += ../shared/net/greth.c -librtemsbsp_a_SOURCES += ../shared/net/network_interface_add.c +librtemsbsp_a_SOURCES += ../../../../../../bsps/sparc/shared/net/greth.c +librtemsbsp_a_SOURCES += ../../../../../../bsps/sparc/shared/net/network_interface_add.c endif diff --git a/c/src/lib/libbsp/sparc/leon3/Makefile.am b/c/src/lib/libbsp/sparc/leon3/Makefile.am index 994a1d97dd..54d0549f8d 100644 --- a/c/src/lib/libbsp/sparc/leon3/Makefile.am +++ b/c/src/lib/libbsp/sparc/leon3/Makefile.am @@ -41,20 +41,20 @@ librtemsbsp_a_SOURCES += ../../../../../../bsps/sparc/leon3/start/bsp_fatal_halt # gnatsupp librtemsbsp_a_SOURCES += gnatsupp/gnatsupp.c -librtemsbsp_a_SOURCES += ../shared/gnatcommon.c +librtemsbsp_a_SOURCES += ../../../../../../bsps/sparc/shared/gnatcommon.c # AMBA bus librtemsbsp_a_SOURCES += amba/amba.c -librtemsbsp_a_SOURCES += ../shared/amba/ambapp.c -librtemsbsp_a_SOURCES += ../shared/amba/ambapp_alloc.c -librtemsbsp_a_SOURCES += ../shared/amba/ambapp_count.c -librtemsbsp_a_SOURCES += ../shared/amba/ambapp_depth.c -librtemsbsp_a_SOURCES += ../shared/amba/ambapp_find_by_idx.c -librtemsbsp_a_SOURCES += ../shared/amba/ambapp_freq.c -librtemsbsp_a_SOURCES += ../shared/amba/ambapp_parent.c -librtemsbsp_a_SOURCES += ../shared/amba/ambapp_old.c -librtemsbsp_a_SOURCES += ../shared/amba/ambapp_names.c -librtemsbsp_a_SOURCES += ../shared/amba/ambapp_show.c -librtemsbsp_a_SOURCES += ../shared/amba/ahbstat.c +librtemsbsp_a_SOURCES += ../../../../../../bsps/sparc/shared/amba/ambapp.c +librtemsbsp_a_SOURCES += ../../../../../../bsps/sparc/shared/amba/ambapp_alloc.c +librtemsbsp_a_SOURCES += ../../../../../../bsps/sparc/shared/amba/ambapp_count.c +librtemsbsp_a_SOURCES += ../../../../../../bsps/sparc/shared/amba/ambapp_depth.c +librtemsbsp_a_SOURCES += ../../../../../../bsps/sparc/shared/amba/ambapp_find_by_idx.c +librtemsbsp_a_SOURCES += ../../../../../../bsps/sparc/shared/amba/ambapp_freq.c +librtemsbsp_a_SOURCES += ../../../../../../bsps/sparc/shared/amba/ambapp_parent.c +librtemsbsp_a_SOURCES += ../../../../../../bsps/sparc/shared/amba/ambapp_old.c +librtemsbsp_a_SOURCES += ../../../../../../bsps/sparc/shared/amba/ambapp_names.c +librtemsbsp_a_SOURCES += ../../../../../../bsps/sparc/shared/amba/ambapp_show.c +librtemsbsp_a_SOURCES += ../../../../../../bsps/sparc/shared/amba/ahbstat.c # Clock Driver and Timer Library librtemsbsp_a_SOURCES += ../../../../../../bsps/sparc/shared/btimer/gptimer.c @@ -66,109 +66,109 @@ librtemsbsp_a_SOURCES +=../../../../../../bsps/sparc/leon3/clock/ckinit.c # console librtemsbsp_a_SOURCES += ../../../../../../bsps/shared/dev/serial/console-termios.c librtemsbsp_a_SOURCES += ../../../../../../bsps/sparc/leon3/console/console.c -librtemsbsp_a_SOURCES += ../shared/uart/cons.c -librtemsbsp_a_SOURCES += ../shared/uart/apbuart_cons.c +librtemsbsp_a_SOURCES += ../../../../../../bsps/sparc/shared/uart/cons.c +librtemsbsp_a_SOURCES += ../../../../../../bsps/sparc/shared/uart/apbuart_cons.c # debugio librtemsbsp_a_SOURCES += ../../../../../../bsps/sparc/leon3/console/printk_support.c # IRQ librtemsbsp_a_SOURCES += ../../../../../../bsps/sparc/leon3/start/eirq.c -librtemsbsp_a_SOURCES += ../shared/irq/genirq.c -librtemsbsp_a_SOURCES += ../shared/irq/irq-shared.c -librtemsbsp_a_SOURCES += ../shared/irq/bsp_isr_handler.c +librtemsbsp_a_SOURCES += ../../../../../../bsps/sparc/shared/irq/genirq.c +librtemsbsp_a_SOURCES += ../../../../../../bsps/sparc/shared/irq/irq-shared.c +librtemsbsp_a_SOURCES += ../../../../../../bsps/sparc/shared/irq/bsp_isr_handler.c librtemsbsp_a_SOURCES += ../../../../../../bsps/shared/irq/irq-default-handler.c # PCI -librtemsbsp_a_SOURCES += ../shared/pci/grpci.c -librtemsbsp_a_SOURCES += ../shared/pci/grpci2.c -librtemsbsp_a_SOURCES += ../shared/pci/grpci2dma.c -librtemsbsp_a_SOURCES += ../shared/pci/pcif.c -librtemsbsp_a_SOURCES += ../shared/pci/pci_memreg_sparc_le.c -librtemsbsp_a_SOURCES += ../shared/pci/pci_memreg_sparc_be.c +librtemsbsp_a_SOURCES += ../../../../../../bsps/sparc/shared/pci/grpci.c +librtemsbsp_a_SOURCES += ../../../../../../bsps/sparc/shared/pci/grpci2.c +librtemsbsp_a_SOURCES += ../../../../../../bsps/sparc/shared/pci/grpci2dma.c +librtemsbsp_a_SOURCES += ../../../../../../bsps/sparc/shared/pci/pcif.c +librtemsbsp_a_SOURCES += ../../../../../../bsps/sparc/shared/pci/pci_memreg_sparc_le.c +librtemsbsp_a_SOURCES += ../../../../../../bsps/sparc/shared/pci/pci_memreg_sparc_be.c # PCI target devices -librtemsbsp_a_SOURCES += ../shared/pci/gr_701.c -librtemsbsp_a_SOURCES += ../shared/pci/gr_rasta_adcdac.c -librtemsbsp_a_SOURCES += ../shared/pci/gr_rasta_io.c -librtemsbsp_a_SOURCES += ../shared/pci/gr_rasta_spw_router.c -librtemsbsp_a_SOURCES += ../shared/pci/gr_rasta_tmtc.c -librtemsbsp_a_SOURCES += ../shared/pci/gr_tmtc_1553.c -librtemsbsp_a_SOURCES += ../shared/pci/gr_leon4_n2x.c -librtemsbsp_a_SOURCES += ../shared/pci/gr_cpci_gr740.c +librtemsbsp_a_SOURCES += ../../../../../../bsps/sparc/shared/pci/gr_701.c +librtemsbsp_a_SOURCES += ../../../../../../bsps/sparc/shared/pci/gr_rasta_adcdac.c +librtemsbsp_a_SOURCES += ../../../../../../bsps/sparc/shared/pci/gr_rasta_io.c +librtemsbsp_a_SOURCES += ../../../../../../bsps/sparc/shared/pci/gr_rasta_spw_router.c +librtemsbsp_a_SOURCES += ../../../../../../bsps/sparc/shared/pci/gr_rasta_tmtc.c +librtemsbsp_a_SOURCES += ../../../../../../bsps/sparc/shared/pci/gr_tmtc_1553.c +librtemsbsp_a_SOURCES += ../../../../../../bsps/sparc/shared/pci/gr_leon4_n2x.c +librtemsbsp_a_SOURCES += ../../../../../../bsps/sparc/shared/pci/gr_cpci_gr740.c # B1553BRM -librtemsbsp_a_SOURCES += ../shared/1553/b1553brm.c -librtemsbsp_a_SOURCES += ../shared/1553/b1553rt.c +librtemsbsp_a_SOURCES += ../../../../../../bsps/sparc/shared/1553/b1553brm.c +librtemsbsp_a_SOURCES += ../../../../../../bsps/sparc/shared/1553/b1553rt.c # GR1553B -librtemsbsp_a_SOURCES += ../shared/1553/gr1553b.c -librtemsbsp_a_SOURCES += ../shared/1553/gr1553bc.c -librtemsbsp_a_SOURCES += ../shared/1553/gr1553bm.c -librtemsbsp_a_SOURCES += ../shared/1553/gr1553rt.c +librtemsbsp_a_SOURCES += ../../../../../../bsps/sparc/shared/1553/gr1553b.c +librtemsbsp_a_SOURCES += ../../../../../../bsps/sparc/shared/1553/gr1553bc.c +librtemsbsp_a_SOURCES += ../../../../../../bsps/sparc/shared/1553/gr1553bm.c +librtemsbsp_a_SOURCES += ../../../../../../bsps/sparc/shared/1553/gr1553rt.c # CAN -librtemsbsp_a_SOURCES += ../shared/can/occan.c -librtemsbsp_a_SOURCES += ../shared/can/grcan.c +librtemsbsp_a_SOURCES += ../../../../../../bsps/sparc/shared/can/occan.c +librtemsbsp_a_SOURCES += ../../../../../../bsps/sparc/shared/can/grcan.c # SpaceWire if !HAS_SMP -librtemsbsp_a_SOURCES += ../shared/spw/grspw.c +librtemsbsp_a_SOURCES += ../../../../../../bsps/sparc/shared/spw/grspw.c endif -librtemsbsp_a_SOURCES += ../shared/spw/grspw_pkt.c -librtemsbsp_a_SOURCES += ../shared/spw/grspw_router.c +librtemsbsp_a_SOURCES += ../../../../../../bsps/sparc/shared/spw/grspw_pkt.c +librtemsbsp_a_SOURCES += ../../../../../../bsps/sparc/shared/spw/grspw_router.c # UART -librtemsbsp_a_SOURCES += ../shared/uart/apbuart_termios.c +librtemsbsp_a_SOURCES += ../../../../../../bsps/sparc/shared/uart/apbuart_termios.c # I2CMST -librtemsbsp_a_SOURCES += ../shared/i2c/i2cmst.c +librtemsbsp_a_SOURCES += ../../../../../../bsps/sparc/shared/i2c/i2cmst.c # SPI -librtemsbsp_a_SOURCES += ../shared/spi/spictrl.c +librtemsbsp_a_SOURCES += ../../../../../../bsps/sparc/shared/spi/spictrl.c # TIME -librtemsbsp_a_SOURCES += ../shared/time/spwcuc.c -librtemsbsp_a_SOURCES += ../shared/time/grctm.c +librtemsbsp_a_SOURCES += ../../../../../../bsps/sparc/shared/time/spwcuc.c +librtemsbsp_a_SOURCES += ../../../../../../bsps/sparc/shared/time/grctm.c # GPIO -librtemsbsp_a_SOURCES += ../shared/gpio/grgpio.c -librtemsbsp_a_SOURCES += ../shared/gpio/gpiolib.c +librtemsbsp_a_SOURCES += ../../../../../../bsps/sparc/shared/gpio/grgpio.c +librtemsbsp_a_SOURCES += ../../../../../../bsps/sparc/shared/gpio/gpiolib.c # PWM -librtemsbsp_a_SOURCES += ../shared/pwm/grpwm.c +librtemsbsp_a_SOURCES += ../../../../../../bsps/sparc/shared/pwm/grpwm.c # ADC and DAC -librtemsbsp_a_SOURCES += ../shared/analog/gradcdac.c +librtemsbsp_a_SOURCES += ../../../../../../bsps/sparc/shared/analog/gradcdac.c # Memory controllers -librtemsbsp_a_SOURCES += ../shared/mem/mctrl.c +librtemsbsp_a_SOURCES += ../../../../../../bsps/sparc/shared/mem/mctrl.c # l2cache -librtemsbsp_a_SOURCES += ../shared/l2c/l2c.c +librtemsbsp_a_SOURCES += ../../../../../../bsps/sparc/shared/l2c/l2c.c librtemsbsp_a_SOURCES += ../../../../../../bsps/sparc/leon3/start/cache.c # griommu -librtemsbsp_a_SOURCES += ../shared/iommu/griommu.c +librtemsbsp_a_SOURCES += ../../../../../../bsps/sparc/shared/iommu/griommu.c # timer librtemsbsp_a_SOURCES += ../../../../../../bsps/sparc/leon3/btimer/btimer.c librtemsbsp_a_SOURCES += ../../../../../../bsps/sparc/leon3/btimer/watchdog.c # GR712 -librtemsbsp_a_SOURCES += ../shared/ascs/grascs.c -librtemsbsp_a_SOURCES += ../shared/can/satcan.c -librtemsbsp_a_SOURCES += ../shared/can/canmux.c -librtemsbsp_a_SOURCES += ../shared/slink/grslink.c +librtemsbsp_a_SOURCES += ../../../../../../bsps/sparc/shared/ascs/grascs.c +librtemsbsp_a_SOURCES += ../../../../../../bsps/sparc/shared/can/satcan.c +librtemsbsp_a_SOURCES += ../../../../../../bsps/sparc/shared/can/canmux.c +librtemsbsp_a_SOURCES += ../../../../../../bsps/sparc/shared/slink/grslink.c # TM/TC -librtemsbsp_a_SOURCES += ../shared/tmtc/grtc.c -librtemsbsp_a_SOURCES += ../shared/tmtc/grtm.c +librtemsbsp_a_SOURCES += ../../../../../../bsps/sparc/shared/tmtc/grtc.c +librtemsbsp_a_SOURCES += ../../../../../../bsps/sparc/shared/tmtc/grtm.c # MEMSCRUB -librtemsbsp_a_SOURCES += ../shared/scrub/memscrub.c +librtemsbsp_a_SOURCES += ../../../../../../bsps/sparc/shared/scrub/memscrub.c # L4STAT -librtemsbsp_a_SOURCES += ../shared/stat/l4stat.c +librtemsbsp_a_SOURCES += ../../../../../../bsps/sparc/shared/stat/l4stat.c # Driver Manager -librtemsbsp_a_SOURCES += ../shared/drvmgr/ambapp_bus.c -librtemsbsp_a_SOURCES += ../shared/drvmgr/ambapp_bus_grlib.c -librtemsbsp_a_SOURCES += ../shared/drvmgr/get_resarray_count.c +librtemsbsp_a_SOURCES += ../../../../../../bsps/sparc/shared/drvmgr/ambapp_bus.c +librtemsbsp_a_SOURCES += ../../../../../../bsps/sparc/shared/drvmgr/ambapp_bus_grlib.c +librtemsbsp_a_SOURCES += ../../../../../../bsps/sparc/shared/drvmgr/get_resarray_count.c if HAS_SMP librtemsbsp_a_SOURCES += ../../../../../../bsps/sparc/leon3/start/bspsmp.c @@ -177,8 +177,8 @@ endif if HAS_NETWORKING librtemsbsp_a_SOURCES += leon_smc91111/leon_smc91111.c librtemsbsp_a_SOURCES += leon_open_eth/leon_open_eth.c -librtemsbsp_a_SOURCES += ../shared/net/greth.c -librtemsbsp_a_SOURCES += ../shared/net/network_interface_add.c +librtemsbsp_a_SOURCES += ../../../../../../bsps/sparc/shared/net/greth.c +librtemsbsp_a_SOURCES += ../../../../../../bsps/sparc/shared/net/network_interface_add.c if !HAS_SMP librtemsbsp_a_SOURCES += leon_greth/leon_greth.c endif diff --git a/c/src/lib/libbsp/sparc/shared/1553/b1553brm.c b/c/src/lib/libbsp/sparc/shared/1553/b1553brm.c deleted file mode 100644 index 8a5efaf9df..0000000000 --- a/c/src/lib/libbsp/sparc/shared/1553/b1553brm.c +++ /dev/null @@ -1,1548 +0,0 @@ -/* - * BRM driver - * - * COPYRIGHT (c) 2006. - * Cobham Gaisler AB. - * - * 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. - */ - -/********** Set defaults **********/ - -/* default to 16K memory layout */ -#define DMA_MEM_128K -#if !defined(DMA_MEM_128K) - #define DMA_MEM_16K -#endif - -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -/* Uncomment for debug output */ -/*#define DEBUG 1 -#define FUNCDEBUG 1*/ -#undef DEBUG -#undef FUNCDEBUG - -/* EVENT_QUEUE_SIZE sets the size of the event queue - */ -#define EVENT_QUEUE_SIZE 1024 - - -#define INDEX(x) ( x&(EVENT_QUEUE_SIZE-1) ) - -#if 0 -#define DBG(x...) printk(x) -#else -#define DBG(x...) -#endif - -#ifdef FUNCDEBUG -#define FUNCDBG(x...) printk(x) -#else -#define FUNCDBG(x...) -#endif - -#define READ_REG(address) (*(volatile unsigned int *)address) -#define READ_DMA(address) _BRM_REG_READ16((unsigned int)address) -static __inline__ unsigned short _BRM_REG_READ16(unsigned int addr) { - unsigned short tmp; - __asm__ (" lduha [%1]1, %0 " - : "=r"(tmp) - : "r"(addr) - ); - return tmp; -} - -static rtems_device_driver brm_initialize(rtems_device_major_number major, rtems_device_minor_number minor, void *arg); -static rtems_device_driver brm_open(rtems_device_major_number major, rtems_device_minor_number minor, void *arg); -static rtems_device_driver brm_close(rtems_device_major_number major, rtems_device_minor_number minor, void *arg); -static rtems_device_driver brm_read(rtems_device_major_number major, rtems_device_minor_number minor, void *arg); -static rtems_device_driver brm_write(rtems_device_major_number major, rtems_device_minor_number minor, void *arg); -static rtems_device_driver brm_control(rtems_device_major_number major, rtems_device_minor_number minor, void *arg); - -#define BRM_DRIVER_TABLE_ENTRY { brm_initialize, brm_open, brm_close, brm_read, brm_write, brm_control } - -static rtems_driver_address_table b1553brm_driver = BRM_DRIVER_TABLE_ENTRY; - -struct msg { - unsigned short miw; - unsigned short time; - unsigned short data[32]; -}; -#if defined(DMA_MEM_128K) -struct circ_buf { - struct msg msgs[9]; -}; -#elif defined(DMA_MEM_16K) -/* two message queue */ -struct circ_buf_2 { - struct msg msgs[2]; -}; -/* one message queue */ -struct circ_buf_1 { - struct msg msgs[1]; -}; -#endif - -struct irq_log_list { - volatile unsigned short iiw; - volatile unsigned short iaw; -}; - -typedef struct { - - struct drvmgr_dev *dev; /* Driver manager device */ - char devName[32]; /* Device Name */ - struct brm_reg *regs; - - unsigned int memarea_base; - unsigned int memarea_base_remote; - unsigned int cfg_clksel; - unsigned int cfg_clkdiv; - unsigned int cfg_freq; - - /* BRM descriptors */ - struct desc_table { - volatile unsigned short ctrl; - volatile unsigned short top; - volatile unsigned short cur; - volatile unsigned short bot; - } *desc; - - volatile unsigned short *mem; - /* bc mem struct */ - struct { - /* BC Descriptors */ - struct { - unsigned short ctrl; /* control */ - unsigned short cw1; /* Command word 1*/ - unsigned short cw2; /* Command word 1*/ - unsigned short dptr; /* Data pointer in halfword offset from bcmem */ - unsigned short tsw[2]; /* status word 1 & 2 */ - unsigned short ba; /* branch address */ - unsigned short timer; /* timer value */ - } descs[128]; /* 2k (1024 half words) */ - - /* message data */ - struct { - unsigned short data[32]; /* 1 message's data */ - } msg_data[128]; /* 8k */ - -#if defined(DMA_MEM_128K) - /* offset to last 64bytes of 128k */ - unsigned short unused[(64*1024-(128*8+128*32))-16*2]; -#elif defined(DMA_MEM_16K) - unsigned short unused[(8*1024-(128*8+128*32))-16*2]; -#endif - /* interrupt log at 64 bytes from end */ - struct irq_log_list irq_logs[16]; - } *bcmem; - -#if defined(DMA_MEM_128K) - /* Memory structure of a RT being inited, just used - * for RT initialization. - * - * *mesgs[32] fit each minimally 8 messages per sub address. - */ - struct { - /* RX Sub Address descriptors */ - struct desc_table rxsubs[32]; - /* TX Sub Address descriptors */ - struct desc_table txsubs[32]; - /* RX mode code descriptors */ - struct desc_table rxmodes[32]; - /* TX mode code descriptors */ - struct desc_table txmodes[32]; - - /* RX Sub Address messages */ - struct circ_buf rxsuba_msgs[32]; - /* TX Sub Address messages */ - struct circ_buf txsuba_msgs[32]; - /* RX Mode Code messages */ - struct circ_buf rxmode_msgs[32]; - /* RX Mode Code messages */ - struct circ_buf txmode_msgs[32]; - - /* offset to last 64bytes of 128k: tot-used-needed */ - unsigned short unused[(64*1024-(4*32*4+4*32*9*34))-16*2]; - - /* interrupt log at 64 bytes from end */ - struct irq_log_list irq_logs[16]; - } *rtmem; -#elif defined(DMA_MEM_16K) - /* Memory structure of a RT being inited, just used - * for RT initialization. - * - * circ_buf_2 *mesgs[32] fit each minimally 2 messages per queue. - * circ_buf_1 *mesgs[32] fit each minimally 1 messages per queue. - */ - struct { - /* RX Sub Address descriptors */ - struct desc_table rxsubs[32]; - /* TX Sub Address descriptors */ - struct desc_table txsubs[32]; - /* RX mode code descriptors */ - struct desc_table rxmodes[32]; - /* TX mode code descriptors */ - struct desc_table txmodes[32]; - - /* RX Sub Address messages */ - struct circ_buf_2 rxsuba_msgs[32]; - /* TX Sub Address messages */ - struct circ_buf_2 txsuba_msgs[32]; - /* RX Mode Code messages */ - struct circ_buf_2 rxmode_msgs[32]; - /* RX Mode Code messages */ - struct circ_buf_1 txmode_msgs[32]; - - /* offset to last 64bytes of 16k: tot-used-needed */ - unsigned short unused[8*1024 -(4*32*4 +3*32*2*34 +1*32*1*34) -16*2]; - - /* interrupt log at 64 bytes from end */ - struct irq_log_list irq_logs[16]; - } *rtmem; -#else - #error You must define one DMA_MEM_???K -#endif - - /* Interrupt log list */ - struct irq_log_list *irq_log; - unsigned int irq; - - /* Received events waiting to be read */ - struct rt_msg *rt_event; - struct bm_msg *bm_event; - - unsigned int head, tail; - - unsigned int last_read[128]; - unsigned int written[32]; - - struct bc_msg *cur_list; - - int tx_blocking, rx_blocking; - - rtems_id rx_sem, tx_sem, dev_sem; - int minor; - int irqno; - unsigned int mode; -#ifdef DEBUG - unsigned int log[EVENT_QUEUE_SIZE*4]; - unsigned int log_i; -#endif - - rtems_id event_id; /* event that may be signalled upon errors, needs to be set through ioctl command BRM_SET_EVENTID */ - unsigned int status; - int bc_list_fail; -} brm_priv; - -static void b1553brm_interrupt(void *arg); -static rtems_device_driver rt_init(brm_priv *brm); - -#define OFS(ofs) (((unsigned int)&ofs & 0x1ffff)>>1) - -static int b1553brm_driver_io_registered = 0; -static rtems_device_major_number b1553brm_driver_io_major = 0; - -/******************* Driver manager interface ***********************/ - -/* Driver prototypes */ -int b1553brm_register_io(rtems_device_major_number *m); -int b1553brm_device_init(brm_priv *pDev); - -int b1553brm_init2(struct drvmgr_dev *dev); -int b1553brm_init3(struct drvmgr_dev *dev); -int b1553brm_remove(struct drvmgr_dev *dev); - -struct drvmgr_drv_ops b1553brm_ops = -{ - .init = {NULL, b1553brm_init2, b1553brm_init3, NULL}, - .remove = b1553brm_remove, - .info = NULL -}; - -struct amba_dev_id b1553brm_ids[] = -{ - {VENDOR_GAISLER, GAISLER_B1553BRM}, - {0, 0} /* Mark end of table */ -}; - -struct amba_drv_info b1553brm_drv_info = -{ - { - DRVMGR_OBJ_DRV, /* Driver */ - NULL, /* Next driver */ - NULL, /* Device list */ - DRIVER_AMBAPP_GAISLER_B1553BRM_ID, /* Driver ID */ - "B1553BRM_DRV", /* Driver Name */ - DRVMGR_BUS_TYPE_AMBAPP, /* Bus Type */ - &b1553brm_ops, - NULL, /* Funcs */ - 0, /* No devices yet */ - 0, - }, - &b1553brm_ids[0] -}; - -void b1553brm_register_drv (void) -{ - DBG("Registering B1553BRM driver\n"); - drvmgr_drv_register(&b1553brm_drv_info.general); -} - -int b1553brm_init2(struct drvmgr_dev *dev) -{ - brm_priv *priv; - - DBG("B1553BRM[%d] on bus %s\n", dev->minor_drv, dev->parent->dev->name); - priv = dev->priv = malloc(sizeof(brm_priv)); - if ( !priv ) - return DRVMGR_NOMEM; - memset(priv, 0, sizeof(*priv)); - priv->dev = dev; - - /* This core will not find other cores, so we wait for init2() */ - - return DRVMGR_OK; -} - -int b1553brm_init3(struct drvmgr_dev *dev) -{ - brm_priv *priv; - char prefix[32]; - rtems_status_code status; - - priv = dev->priv; - - /* Do initialization */ - - if ( b1553brm_driver_io_registered == 0) { - /* Register the I/O driver only once for all cores */ - if ( b1553brm_register_io(&b1553brm_driver_io_major) ) { - /* Failed to register I/O driver */ - dev->priv = NULL; - return DRVMGR_FAIL; - } - - b1553brm_driver_io_registered = 1; - } - - /* I/O system registered and initialized - * Now we take care of device initialization. - */ - - if ( b1553brm_device_init(priv) ) { - return DRVMGR_FAIL; - } - - /* Get Filesystem name prefix */ - prefix[0] = '\0'; - if ( drvmgr_get_dev_prefix(dev, prefix) ) { - /* Failed to get prefix, make sure of a unique FS name - * by using the driver minor. - */ - sprintf(priv->devName, "/dev/b1553brm%d", dev->minor_drv); - } else { - /* Got special prefix, this means we have a bus prefix - * And we should use our "bus minor" - */ - sprintf(priv->devName, "/dev/%sb1553brm%d", prefix, dev->minor_bus); - } - - /* Register Device */ - status = rtems_io_register_name(priv->devName, b1553brm_driver_io_major, dev->minor_drv); - if (status != RTEMS_SUCCESSFUL) { - return DRVMGR_FAIL; - } - - return DRVMGR_OK; -} - -int b1553brm_remove(struct drvmgr_dev *dev) -{ - /* Stop more tasks to open driver */ - - /* Throw out all tasks using this driver */ - - /* Unregister I/O node */ - - /* Unregister and disable Interrupt */ - - /* Free device memory */ - - /* Return sucessfully */ - - return DRVMGR_OK; -} - -/******************* Driver Implementation ***********************/ - -int b1553brm_register_io(rtems_device_major_number *m) -{ - rtems_status_code r; - - if ((r = rtems_io_register_driver(0, &b1553brm_driver, m)) == RTEMS_SUCCESSFUL) { - DBG("B1553BRM driver successfully registered, major: %d\n", *m); - } else { - switch(r) { - case RTEMS_TOO_MANY: - printk("B1553BRM rtems_io_register_driver failed: RTEMS_TOO_MANY\n"); - return -1; - case RTEMS_INVALID_NUMBER: - printk("B1553BRM rtems_io_register_driver failed: RTEMS_INVALID_NUMBER\n"); - return -1; - case RTEMS_RESOURCE_IN_USE: - printk("B1553BRM rtems_io_register_driver failed: RTEMS_RESOURCE_IN_USE\n"); - return -1; - default: - printk("B1553BRM rtems_io_register_driver failed\n"); - return -1; - } - } - return 0; -} - -int b1553brm_device_init(brm_priv *pDev) -{ - struct amba_dev_info *ambadev; - struct ambapp_core *pnpinfo; - union drvmgr_key_value *value; - unsigned int mem; - int size; - - /* Get device information from AMBA PnP information */ - ambadev = (struct amba_dev_info *)pDev->dev->businfo; - if ( ambadev == NULL ) { - return -1; - } - pnpinfo = &ambadev->info; - pDev->irqno = pnpinfo->irq; - /* Two versions of the BRM core. One where the registers are accessed using the AHB bus - * and one where the APB bus is used - */ - if ( pnpinfo->ahb_slv ) { - /* Registers accessed over AHB */ - pDev->regs = (struct brm_reg *)pnpinfo->ahb_slv->start[0]; - } else { - /* Registers accessed over APB */ - pDev->regs = (struct brm_reg *)pnpinfo->apb_slv->start; - } - pDev->minor = pDev->dev->minor_drv; -#ifdef DEBUG - pDev->log_i = 0; - memset(pDev->log,0,sizeof(pDev->log)); -#endif - -#ifdef DMA_MEM_128K - size = 128 * 1024; -#else - size = 16 * 1024; -#endif - - /* Get memory configuration from bus resources */ - value = drvmgr_dev_key_get(pDev->dev, "dmaBaseAdr", DRVMGR_KT_POINTER); - if (value) - mem = (unsigned int)value->ptr; - - if (value && (mem & 1)) { - /* Remote address, address as BRM looks at it. */ - - /* Translate the base address into an address that the the CPU can understand */ - pDev->memarea_base_remote = mem & ~1; - drvmgr_translate_check(pDev->dev, DMAMEM_TO_CPU, - (void *)pDev->memarea_base_remote, - (void **)&pDev->memarea_base, - size); - } else { - if (!value) { - /* Use dynamically allocated memory + 128k for - * alignment - */ - mem = (unsigned int)malloc(size + 128 * 1024); - if (!mem){ - printk("BRM: Failed to allocate HW memory\n\r"); - return -1; - } - /* align memory to 128k boundary */ - pDev->memarea_base = (mem + 0x1ffff) & ~0x1ffff; - } else { - pDev->memarea_base = mem; - } - - /* Translate the base address into an address that the BRM core can understand */ - drvmgr_translate_check(pDev->dev, CPUMEM_TO_DMA, - (void *)pDev->memarea_base, - (void **)&pDev->memarea_base_remote, - size); - } - - /* clear the used memory */ - memset((char *)pDev->memarea_base, 0, size); - - /* Set base address of all descriptors */ - pDev->desc = (struct desc_table *) pDev->memarea_base; - pDev->mem = (volatile unsigned short *) pDev->memarea_base; - pDev->irq_log = (struct irq_log_list *)(pDev->memarea_base + (0xFFE0<<1)); /* last 64byte */ - - pDev->bm_event = NULL; - pDev->rt_event = NULL; - - pDev->cfg_clksel = 0; - pDev->cfg_clkdiv = 0; - pDev->cfg_freq = BRM_FREQ_24MHZ; - - value = drvmgr_dev_key_get(pDev->dev, "clkSel", DRVMGR_KT_INT); - if ( value ) { - pDev->cfg_clksel = value->i & CLKSEL_MASK; - } - - value = drvmgr_dev_key_get(pDev->dev, "clkDiv", DRVMGR_KT_INT); - if ( value ) { - pDev->cfg_clkdiv = value->i & CLKDIV_MASK; - } - - value = drvmgr_dev_key_get(pDev->dev, "coreFreq", DRVMGR_KT_INT); - if ( value ) { - pDev->cfg_freq = value->i & BRM_FREQ_MASK; - } - - /* Sel clock so that we can write to BRM's registers */ - pDev->regs->w_ctrl = (pDev->cfg_clksel<<9) | (pDev->cfg_clkdiv<<5); - /* Reset BRM core */ - pDev->regs->w_ctrl = 1<<10 | READ_REG(&pDev->regs->w_ctrl); - - /* RX Semaphore created with count = 0 */ - if ( rtems_semaphore_create(rtems_build_name('B', 'M', 'R', '0' + pDev->minor), - 0, - RTEMS_FIFO|RTEMS_SIMPLE_BINARY_SEMAPHORE|RTEMS_NO_INHERIT_PRIORITY|RTEMS_LOCAL|RTEMS_NO_PRIORITY_CEILING, - 0, - &pDev->rx_sem) != RTEMS_SUCCESSFUL ) { - printk("BRM: Failed to create rx semaphore\n"); - return RTEMS_INTERNAL_ERROR; - } - - /* TX Semaphore created with count = 1 */ - if ( rtems_semaphore_create(rtems_build_name('B', 'M', 'T', '0' + pDev->minor), - 1, - RTEMS_FIFO|RTEMS_SIMPLE_BINARY_SEMAPHORE|RTEMS_NO_INHERIT_PRIORITY|RTEMS_LOCAL|RTEMS_NO_PRIORITY_CEILING, - 0, - &pDev->tx_sem) != RTEMS_SUCCESSFUL ){ - printk("BRM: Failed to create tx semaphore\n"); - return RTEMS_INTERNAL_ERROR; - } - - /* Device Semaphore created with count = 1 */ - if ( rtems_semaphore_create(rtems_build_name('B', 'M', 'D', '0' + pDev->minor), - 1, - RTEMS_FIFO|RTEMS_SIMPLE_BINARY_SEMAPHORE|RTEMS_NO_INHERIT_PRIORITY|RTEMS_LOCAL|RTEMS_NO_PRIORITY_CEILING, - 0, - &pDev->dev_sem) != RTEMS_SUCCESSFUL ){ - printk("BRM: Failed to create device semaphore\n"); - return RTEMS_INTERNAL_ERROR; - } - - /* Default to RT-mode */ - rt_init(pDev); - - return 0; -} - -static int odd_parity(unsigned int data) { - unsigned int i=0; - - while(data) - { - i++; - data &= (data - 1); - } - - return !(i&1); -} - -static void start_operation(brm_priv *brm) { - unsigned int ctrl = READ_REG(&brm->regs->ctrl); - brm->regs->ctrl = ctrl | 0x8000; -} - -static void stop_operation(brm_priv *brm) { - unsigned int ctrl = READ_REG(&brm->regs->ctrl); - brm->regs->ctrl = ctrl & ~0x8000; -} - -static int is_executing(brm_priv *brm) { - unsigned int ctrl = READ_REG(&brm->regs->ctrl); - return ((ctrl>>15) & 1); -} - -static void clr_int_logs(struct irq_log_list *logs){ - int i; - for(i=0; i<16; i++){ - logs[i].iiw = 0xffff; - logs[i].iaw = 0x0; - } -} - -unsigned short b1553brm_rt_cmd_legalize[16] = { - 0, - 0, - 0, - 0, - 0, - 0, - 0xffff, - 0xffff, - 0xffff, - 0xfffd, - 0xfe01, - 0xfff2, - 0xffff, - 0xfffd, - 0xfe05, - 0xffff, -}; - -static rtems_device_driver rt_init(brm_priv *brm) { - unsigned int i; - - brm->head = brm->tail = 0; - brm->rx_blocking = brm->tx_blocking = 1; - - if ( brm->bm_event ) - free(brm->bm_event); - brm->bm_event = NULL; - - if ( brm->rt_event ) - free(brm->rt_event); - - brm->bcmem = NULL; - brm->rtmem = (void *)brm->mem; - - brm->rt_event = (struct rt_msg *) malloc(EVENT_QUEUE_SIZE*sizeof(struct rt_msg)); - - if (brm->rt_event == NULL) { - DBG("BRM driver failed to allocated memory."); - return RTEMS_NO_MEMORY; - } - - brm->irq_log = (struct irq_log_list *)&brm->rtmem->irq_logs[0]; - - brm->regs->ctrl = 0x1912; /* enable both buses, circular 1 bufmode, broadcast, interrupt log */ - brm->regs->oper = 0x0900; /* configure as RT, with addr 1 */ - brm->regs->imask = BRM_RT_ILLCMD_IRQ|BRM_SUBAD_IRQ|BRM_TAPF_IRQ|BRM_DMAF_IRQ|BRM_WRAPF_IRQ|BRM_MERR_IRQ; - brm->regs->dpoint = 0; - brm->regs->ipoint = OFS(brm->rtmem->irq_logs[0]); - brm->regs->enhanced = 0x0000 | brm->cfg_freq; /* BRM clocked with freq = 12,16,20 or 24MHz */ - brm->regs->w_ctrl = (brm->cfg_clksel<<9) | (brm->cfg_clkdiv<<5) | 1; - brm->regs->w_irqctrl = 6; - brm->regs->w_ahbaddr = brm->memarea_base_remote; - - clr_int_logs(brm->irq_log); - - /* Initialize the Legalize register with standard values */ - for (i = 0; i < 16; i++) { - brm->regs->rt_cmd_leg[i] = b1553brm_rt_cmd_legalize[i]; - } - - /* Init descriptor table - * - * Each circular buffer has room for 8 messages with up to 34 (32 data + miw + time) words (16b) in each. - * The buffers must separated by 34 words. - */ - - - /* RX Sub-address 0 - 31 */ - for (i = 0; i < 32; i++) { - brm->rtmem->rxsubs[i].ctrl = 0x00E0; /* Interrupt: INTX, IWA, and IBRD */ - brm->rtmem->rxsubs[i].top = OFS(brm->rtmem->rxsuba_msgs[i]); /* Top address */ - brm->rtmem->rxsubs[i].cur = OFS(brm->rtmem->rxsuba_msgs[i]); /* Current address */ - brm->rtmem->rxsubs[i].bot = OFS(brm->rtmem->rxsuba_msgs[i+1]) - sizeof(struct msg)/2; /* Bottom address */ - brm->last_read[i] = OFS(brm->rtmem->rxsuba_msgs[i]); - } - /* TX Sub-address 0 - 31 */ - for (i = 0; i < 32; i++) { - brm->rtmem->txsubs[i].ctrl = 0x0060; /* Interrupt: IWA and IBRD */ - brm->rtmem->txsubs[i].top = OFS(brm->rtmem->txsuba_msgs[i]); /* Top address */ - brm->rtmem->txsubs[i].cur = OFS(brm->rtmem->txsuba_msgs[i]); /* Current address */ - brm->rtmem->txsubs[i].bot = OFS(brm->rtmem->txsuba_msgs[i+1]) - sizeof(struct msg)/2; /* Bottom address */ - brm->last_read[i+32] = OFS(brm->rtmem->txsuba_msgs[i]); - brm->written[i] = OFS(brm->rtmem->txsuba_msgs[i]); - } - /* RX mode code 0 - 31 */ - for (i = 0; i < 32; i++) { - brm->rtmem->rxmodes[i].ctrl = 0x00E0; /* Interrupt: INTX, IWA, and IBRD */ - brm->rtmem->rxmodes[i].top = OFS(brm->rtmem->rxmode_msgs[i]); /* Top address */ - brm->rtmem->rxmodes[i].cur = OFS(brm->rtmem->rxmode_msgs[i]); /* Current address */ - brm->rtmem->rxmodes[i].bot = OFS(brm->rtmem->rxmode_msgs[i+1]) - sizeof(struct msg)/2; /* Bottom address */ - brm->last_read[i+64] = OFS(brm->rtmem->rxmode_msgs[i]); - } - /* TX mode code 0 - 31 */ - for (i = 0; i < 32; i++) { - brm->rtmem->txmodes[i].ctrl = 0x0060; /* Interrupt: IWA and IBRD */ - brm->rtmem->txmodes[i].top = OFS(brm->rtmem->txmode_msgs[i]); /* Top address */ - brm->rtmem->txmodes[i].cur = OFS(brm->rtmem->txmode_msgs[i]); /* Current address */ - brm->rtmem->txmodes[i].bot = OFS(brm->rtmem->txmode_msgs[i+1]) - sizeof(struct msg)/2; /* Bottom address */ - brm->last_read[i+96] = OFS(brm->rtmem->txmode_msgs[i]); - } - -#ifdef DEBUG - printk("b1553BRM DMA_AREA: 0x%x\n", (unsigned int)brm->rtmem); - printk("LOG: 0x%x\n", &brm->log[0]); - printk("LOG_I: 0x%x\n", &brm->log_i); -#endif - - brm->mode = BRM_MODE_RT; - - return RTEMS_SUCCESSFUL; -} - -static rtems_device_driver bc_init(brm_priv *brm){ - - if ( brm->bm_event ) - free(brm->bm_event); - brm->bm_event = NULL; - - if ( brm->rt_event ) - free(brm->rt_event); - brm->rt_event = NULL; - - brm->bcmem = (void *)brm->mem; - brm->rtmem = NULL; - brm->irq_log = (struct irq_log_list *)&brm->bcmem->irq_logs[0]; - - brm->head = brm->tail = 0; - brm->rx_blocking = brm->tx_blocking = 1; - - brm->regs->ctrl = 0x0006; /* ping pong enable and enable interrupt log */ - brm->regs->oper = 0x0800; /* configure as BC */ - brm->regs->imask = BRM_EOL_IRQ|BRM_BC_ILLCMD_IRQ|BRM_ILLOP_IRQ|BRM_DMAF_IRQ|BRM_WRAPF_IRQ|BRM_MERR_IRQ; - brm->regs->dpoint = 0; - brm->regs->ipoint = OFS(brm->bcmem->irq_logs[0]); - brm->regs->enhanced = 0x0000 | (brm->cfg_freq&BRM_FREQ_MASK); /* freq = 24 */ - brm->regs->w_ctrl = (brm->cfg_clksel<<9) | (brm->cfg_clkdiv<<5) | 1; - brm->regs->w_irqctrl = 6; - brm->regs->w_ahbaddr = brm->memarea_base_remote; - - clr_int_logs(brm->irq_log); - - brm->mode = BRM_MODE_BC; - - return RTEMS_SUCCESSFUL; -} - -static rtems_device_driver bm_init(brm_priv *brm) { - - - brm->head = brm->tail = 0; - brm->rx_blocking = brm->tx_blocking = 1; - - if ( brm->rt_event ) - free(brm->rt_event); - brm->rt_event = NULL; - - if ( brm->bm_event ) - free(brm->bm_event); - - brm->bcmem = NULL; - brm->rtmem = NULL; - - brm->bm_event = (struct bm_msg *) malloc(EVENT_QUEUE_SIZE*sizeof(struct bm_msg)); - - if (brm->bm_event == NULL) { - DBG("BRM driver failed to allocated memory."); - return RTEMS_NO_MEMORY; - } - - /* end of 16K, fits all current modes (128K, 16K) */ - brm->irq_log = (struct irq_log_list *)&brm->mem[8*1024-16*2]; - - brm->regs->ctrl = 0x0006; /* ping pong enable and enable interrupt log */ - brm->regs->oper = 0x0A00; /* configure as BM */ - brm->regs->imask = BRM_MBC_IRQ|BRM_MERR_IRQ|BRM_DMAF_IRQ; - brm->regs->dpoint = 0; - brm->regs->ipoint = OFS(brm->mem[8*1024-16*2]); - brm->regs->mcpoint = 0; /* Command pointer */ - brm->regs->mdpoint = 0x100; /* Data pointer */ - brm->regs->mbc = 1; /* Block count */ - brm->regs->enhanced = 0x0000 | (brm->cfg_freq&BRM_FREQ_MASK); /* freq = 24 */ - brm->regs->w_ctrl = (brm->cfg_clksel<<9) | (brm->cfg_clkdiv<<5) | 1; - brm->regs->w_irqctrl = 6; - brm->regs->w_ahbaddr = brm->memarea_base_remote; - - clr_int_logs(brm->irq_log); - - brm->mode = BRM_MODE_BM; - - return RTEMS_SUCCESSFUL; -} - - -static rtems_device_driver brm_initialize(rtems_device_major_number major, rtems_device_minor_number minor, void *arg) -{ - return RTEMS_SUCCESSFUL; -} - -static rtems_device_driver brm_open(rtems_device_major_number major, rtems_device_minor_number minor, void *arg) { - brm_priv *brm; - struct drvmgr_dev *dev; - - FUNCDBG("brm_open\n"); - - if ( drvmgr_get_dev(&b1553brm_drv_info.general, minor, &dev) ) { - DBG("Wrong minor %d\n", minor); - return RTEMS_UNSATISFIED; - } - brm = (brm_priv *)dev->priv; - - if (rtems_semaphore_obtain(brm->dev_sem, RTEMS_NO_WAIT, RTEMS_NO_TIMEOUT) != RTEMS_SUCCESSFUL) { - DBG("brm_open: resource in use\n"); - return RTEMS_RESOURCE_IN_USE; /* EBUSY */ - } - - /* Set defaults */ - brm->event_id = 0; - - start_operation(brm); - - /* Register interrupt routine */ - if ( drvmgr_interrupt_register(brm->dev, 0, "b1553brm", b1553brm_interrupt, brm) ) { - rtems_semaphore_release(brm->dev_sem); - return RTEMS_UNSATISFIED; - } - - return RTEMS_SUCCESSFUL; -} - -static rtems_device_driver brm_close(rtems_device_major_number major, rtems_device_minor_number minor, void *arg) -{ - brm_priv *brm; - struct drvmgr_dev *dev; - - FUNCDBG("brm_close"); - - if ( drvmgr_get_dev(&b1553brm_drv_info.general, minor, &dev) ) { - return RTEMS_UNSATISFIED; - } - brm = (brm_priv *)dev->priv; - - drvmgr_interrupt_unregister(brm->dev, 0, b1553brm_interrupt, brm); - - stop_operation(brm); - rtems_semaphore_release(brm->dev_sem); - - return RTEMS_SUCCESSFUL; -} - -static int get_rt_messages(brm_priv *brm, void *buf, unsigned int msg_count) -{ - struct rt_msg *dest = (struct rt_msg *) buf; - int count = 0; - - if (brm->head == brm->tail) { - return 0; - } - - do { - - DBG("rt read - head: %d, tail: %d\n", brm->head, brm->tail); - dest[count++] = brm->rt_event[INDEX(brm->tail++)]; - } while (brm->head != brm->tail && count < msg_count); - - return count; -} - -static int get_bm_messages(brm_priv *brm, void *buf, unsigned int msg_count) -{ - struct bm_msg *dest = (struct bm_msg *) buf; - int count = 0; - - if (brm->head == brm->tail) { - return 0; - } - - do { - - DBG("bm read - head: %d, tail: %d\n", brm->head, brm->tail); - dest[count++] = brm->bm_event[INDEX(brm->tail++)]; - - } while (brm->head != brm->tail && count < msg_count); - - return count; -} - -static rtems_device_driver brm_read(rtems_device_major_number major, rtems_device_minor_number minor, void *arg) -{ - rtems_libio_rw_args_t *rw_args; - int count = 0; - brm_priv *brm; - struct drvmgr_dev *dev; - int (*get_messages)(brm_priv *brm, void *buf, unsigned int count); - - if ( drvmgr_get_dev(&b1553brm_drv_info.general, minor, &dev) ) { - return RTEMS_UNSATISFIED; - } - brm = (brm_priv *)dev->priv; - - if ( ! (brm->mode & (BRM_MODE_RT | BRM_MODE_BM)) ){ - return RTEMS_INVALID_NAME; - } - - rw_args = (rtems_libio_rw_args_t *) arg; - - if ( ((READ_REG(&brm->regs->oper)>>8) & 3) == 1 ) { /* RT */ - get_messages = get_rt_messages; - } else { /* BM */ - get_messages = get_bm_messages; - } - - FUNCDBG("brm_read [%i,%i]: buf: 0x%x len: %i\n",major, minor, (unsigned int)rw_args->buffer,rw_args->count); - - while ( (count=get_messages(brm,rw_args->buffer, rw_args->count)) == 0 ) { - if (brm->rx_blocking) { - rtems_semaphore_obtain(brm->rx_sem, RTEMS_WAIT, RTEMS_NO_TIMEOUT); - } else { - /* Translates to EBUSY */ - return RTEMS_RESOURCE_IN_USE; - } - } - - rw_args->bytes_moved = count; - return RTEMS_SUCCESSFUL; -} - -static rtems_device_driver brm_write(rtems_device_major_number major, rtems_device_minor_number minor, void *arg) -{ - rtems_libio_rw_args_t *rw_args; - struct rt_msg *source; - unsigned int count=0, current, next, descriptor, wc, suba; - brm_priv *brm; - struct drvmgr_dev *dev; - - if ( drvmgr_get_dev(&b1553brm_drv_info.general, minor, &dev) ) { - return RTEMS_UNSATISFIED; - } - brm = (brm_priv *)dev->priv; - - if ( ! (brm->mode & BRM_MODE_RT) ){ - return RTEMS_INVALID_NAME; - } - - rw_args = (rtems_libio_rw_args_t *) arg; - source = (struct rt_msg *) rw_args->buffer; - - FUNCDBG("brm_write [%i,%i]: buf: 0x%x len: %i\n",major, minor, (unsigned int)rw_args->buffer,rw_args->count); - - do { - - descriptor = source[count].desc & 0x7F; - suba = descriptor-32; - wc = source[count].miw >> 11; - wc = wc ? wc : 32; - - /* Only subaddress transmission is allowed with write */ - if (descriptor < 32 || descriptor >= 64) - return RTEMS_INVALID_NAME; - - current = brm->desc[descriptor].cur; - next = brm->written[suba] + 2 + wc; - - if (brm->written[suba] < current) { - - if (next > current) { - - /* No room in transmission buffer */ - if (brm->tx_blocking && count == 0) { - rtems_semaphore_obtain(brm->tx_sem, RTEMS_WAIT, RTEMS_NO_TIMEOUT); - } else if ( count > 0 ) { - /* return the number of messages sent so far */ - break; - } else { - /* Translates to posix EBUSY */ - return RTEMS_RESOURCE_IN_USE; - } - } - } - - memcpy((void *)&brm->mem[brm->written[suba]], &source[count], (2+wc)*2); - - count++; - - if (next >= brm->desc[descriptor].bot) { - next = brm->desc[descriptor].top; - } - brm->written[suba] = next; - - } while (count < rw_args->count); - - rw_args->bytes_moved = count; - - if (count >= 0) { - return RTEMS_SUCCESSFUL; - } - return RTEMS_UNSATISFIED; -} - -static rtems_device_driver brm_control(rtems_device_major_number major, rtems_device_minor_number minor, void *arg) -{ - - unsigned int i=0; - unsigned short ctrl, oper, cw1, cw2; - rtems_libio_ioctl_args_t *ioarg = (rtems_libio_ioctl_args_t *) arg; - unsigned int *data = ioarg->buffer; - struct bc_msg *cmd_list = (struct bc_msg *) ioarg->buffer; - brm_priv *brm; - struct drvmgr_dev *dev; - rtems_device_driver ret; - int len, msglen; - - FUNCDBG("brm_control[%d]: [%i,%i]\n", minor, major, minor); - - if ( drvmgr_get_dev(&b1553brm_drv_info.general, minor, &dev) ) { - return RTEMS_UNSATISFIED; - } - brm = (brm_priv *)dev->priv; - - if (!ioarg) { - DBG("brm_control: invalid argument\n"); - return RTEMS_INVALID_NAME; - } - - ioarg->ioctl_return = 0; - switch (ioarg->command) { - - case BRM_SET_MODE: - if ( data[0] > 2 ) - return RTEMS_INVALID_NAME; - stop_operation(brm); - if (data[0] == 0) { - ret = bc_init(brm); - } else if (data[0] == 1) { - ret = rt_init(brm); - } else if (data[0] == 2) { - ret = bm_init(brm); - } else { - ret = RTEMS_INVALID_NAME; - } - if ( ret != RTEMS_SUCCESSFUL) - return ret; - - if ( brm->mode & (BRM_MODE_RT | BRM_MODE_BM ) ) - start_operation(brm); - break; - - case BRM_SET_BUS: - stop_operation(brm); - ctrl = READ_REG(&brm->regs->ctrl); - ctrl &= 0xE7FF; /* Clear bit 12-11 ... */ - ctrl |= (data[0]&0x3)<<11; /* ... OR in new bus status */ - brm->regs->ctrl = ctrl; - start_operation(brm); - break; - - case BRM_SET_MSGTO: - stop_operation(brm); - ctrl = READ_REG(&brm->regs->ctrl); - ctrl &= 0xFDFF; /* Clear bit 9 ... */ - ctrl |= (data[0]&1)<<9; /* ... OR in new MSGTO */ - brm->regs->ctrl = ctrl; - start_operation(brm); - break; - - case BRM_SET_RT_ADDR: - stop_operation(brm); - oper = READ_REG(&brm->regs->oper); - oper &= 0x03FF; /* Clear bit 15-10 ... */ - oper |= (data[0]&0x1f)<<11; /* ... OR in new address */ - oper |= odd_parity(data[0]&0x1f)<<10; /* ... OR in parity */ - brm->regs->oper = oper; - start_operation(brm); - break; - - case BRM_SET_STD: - stop_operation(brm); - ctrl = READ_REG(&brm->regs->ctrl); - ctrl &= 0xFF7F; /* Clear bit 7 ... */ - ctrl |= (data[0]&1)<<7; /* ... OR in new ABSTD (1=A) */ - brm->regs->ctrl = ctrl; - start_operation(brm); - break; - - case BRM_SET_BCE: - stop_operation(brm); - ctrl = READ_REG(&brm->regs->ctrl); - ctrl &= 0xFFEF; /* Clear bit 4 ... */ - ctrl |= (data[0]&1)<<4; /* ... OR in new BCE */ - brm->regs->ctrl = ctrl; - start_operation(brm); - break; - - case BRM_TX_BLOCK: - brm->tx_blocking = data[0]; - break; - - case BRM_RX_BLOCK: - brm->rx_blocking = data[0]; - break; - - case BRM_DO_LIST: - if ( brm->mode != BRM_MODE_BC ){ - return RTEMS_INVALID_NAME; - } - - /* Check if we are bus controller */ - if ( ((READ_REG(&brm->regs->oper)>>8) & 3) != 0 ) { - return RTEMS_INVALID_NAME; - } - - /* Already processing list? */ - if (is_executing(brm)) { - return RTEMS_RESOURCE_IN_USE; - } - - /* clear any earlier releases */ - rtems_semaphore_obtain(brm->tx_sem, RTEMS_NO_WAIT, RTEMS_NO_TIMEOUT); - - brm->bc_list_fail = 0; - brm->cur_list = cmd_list; - brm->regs->dpoint = 0; - - i = 0; - while ( (cmd_list[i].ctrl & BC_EOL) == 0) { - - ctrl = (4<<12) | (((cmd_list[i].ctrl&BC_BUSA)==BC_BUSA)<<9) | (((cmd_list[i].ctrl&BC_RTRT)==BC_RTRT)<<8); - - if (cmd_list[i].ctrl&BC_RTRT) { - cw1 = (cmd_list[i].rtaddr[0]<<11) | (0<<10) | (cmd_list[i].subaddr[0]<<5) | (cmd_list[i].wc & 0x1f); /* receive cw */ - cw2 = (cmd_list[i].rtaddr[1]<<11) | (1<<10) | (cmd_list[i].subaddr[1]<<5) | (cmd_list[i].wc & 0x1f); /* transmit cw */ - } else { - cw1 = (cmd_list[i].rtaddr[0]<<11) | (((cmd_list[i].ctrl&BC_TR)==BC_TR)<<10) | (cmd_list[i].subaddr[0]<<5) | (cmd_list[i].wc&0x1f); - cw2 = 0; - } - - /* Set up command block */ - brm->bcmem->descs[i].ctrl = ctrl; - brm->bcmem->descs[i].cw1 = cw1; - brm->bcmem->descs[i].cw2 = cw2; - /* data pointer: - * (&brm->bcmem->msg_data[i].data[0] & 0x1ffff) / 2 - */ - brm->bcmem->descs[i].dptr = 1024+i*32; /* data pointer */ - brm->bcmem->descs[i].tsw[0] = 0; - brm->bcmem->descs[i].tsw[1] = 0; - brm->bcmem->descs[i].ba = 0; - brm->bcmem->descs[i].timer = 0; - - msglen = cmd_list[i].wc; - if ( msglen == 0 ) - msglen = 32; - memcpy((void *)&brm->bcmem->msg_data[i].data[0], &cmd_list[i].data[0], msglen*2); - - i++; - } - - brm->bcmem->descs[i].ctrl = 0; /* end of list */ - - start_operation(brm); - break; - - case BRM_LIST_DONE: - - if ( brm->mode != BRM_MODE_BC ){ - return RTEMS_INVALID_NAME; - } - - /* Check if we are bus controller */ - if ( ((READ_REG(&brm->regs->oper)>>8) & 3) != 0 ) { - return RTEMS_INVALID_NAME; - } - - if (is_executing(brm)) { - - data[0] = 0; - if (brm->tx_blocking) { - rtems_semaphore_obtain(brm->tx_sem, RTEMS_WAIT, RTEMS_NO_TIMEOUT); - data[0] = 1; - if ( brm->bc_list_fail ){ - return RTEMS_INVALID_NAME; - } - } else { - return RTEMS_RESOURCE_IN_USE; - } - } else { - data[0] = 1; /* done */ - } - - /* copy finished list results back into bc_msg array */ - i = 0; - while ( (brm->cur_list[i].ctrl & BC_EOL) == 0) { - if (READ_DMA(&brm->bcmem->descs[i].ctrl) & 1) { - brm->cur_list[i].ctrl |= 0x8000; /* Set BAME */ - } - if (brm->cur_list[i].ctrl & BC_TR) { - /* RT Transmit command, copy received data */ - len = brm->cur_list[i].wc; - if ( len == 0 ) - len = 32; - while ( len-- > 0) { - brm->cur_list[i].data[len] = READ_DMA(&brm->bcmem->msg_data[i].data[len]); - } - } - brm->cur_list[i].tsw[0] = READ_DMA(&brm->bcmem->descs[i].tsw[0]); - brm->cur_list[i].tsw[1] = READ_DMA(&brm->bcmem->descs[i].tsw[1]); - - i++; - } - break; - - case BRM_CLR_STATUS: - brm->status = 0; - break; - - case BRM_GET_STATUS: /* copy status */ - if ( !ioarg->buffer ) - return RTEMS_INVALID_NAME; - - *(unsigned int *)ioarg->buffer = brm->status; - break; - - case BRM_SET_EVENTID: - brm->event_id = (rtems_id)ioarg->buffer; - break; - - default: - return RTEMS_NOT_DEFINED; - } - return RTEMS_SUCCESSFUL; -} - -static void b1553brm_interrupt(void *arg) -{ - brm_priv *brm = arg; - unsigned short descriptor, current, pending, miw, wc, tmp, ctrl; - unsigned short msgadr, iaw, iiw; - int len; - int signal_event=0, wake_rx_task=0, wake_tx_task=0; - unsigned int event_status=0; - int accessed; - #define SET_ERROR_DESCRIPTOR(descriptor) (event_status = (event_status & 0x0000ffff) | descriptor<<16) - - while( (iiw=READ_DMA(&brm->irq_log[brm->irq].iiw)) != 0xffff ){ - iaw=READ_DMA(&brm->irq_log[brm->irq].iaw); - - /* indicate that the interrupt log entry has been processed */ - brm->irq_log[brm->irq].iiw = 0xffff; - - /* Interpret interrupt log entry */ - descriptor = iaw >> 2; - pending = iiw; - brm->irq = (brm->irq + 1) % 16; - - /* Clear the log so that we */ - - - /* Subaddress accessed irq (RT only) - * - * Can be either a receive or transmit command - * as well as a mode code. - */ - if (pending & BRM_SUBAD_IRQ) { - - /* Pointer to next free message in circular buffer */ - current = READ_DMA(&brm->desc[descriptor].cur); - ctrl = READ_DMA(&brm->desc[descriptor].ctrl); -#ifdef DEBUG - brm->log[brm->log_i++ % EVENT_QUEUE_SIZE] = (0xff<<16); - brm->log[brm->log_i++ % EVENT_QUEUE_SIZE] = current; - brm->log[brm->log_i++ % EVENT_QUEUE_SIZE] = ctrl; - brm->log[brm->log_i++ % EVENT_QUEUE_SIZE] = 0; -#endif - accessed = ctrl & 0x10; - /* Note that current may be equal to bot and top when - * circular buffer one can handle one message. - */ - if ( accessed ) - do { - msgadr = brm->last_read[descriptor]; - - /* Get word count */ - miw = READ_DMA(&brm->mem[msgadr]); - wc = miw >> 11; - - /* Data received */ - if (descriptor < 32) { - wc = wc ? wc : 32; - } - /* Data transmitted */ - else if (descriptor < 64) { - wc = wc ? wc : 32; - wake_tx_task=1; - } - /* RX Mode code */ - else if (descriptor < 96) { - wc = (wc>>4); - } - /* TX Mode code */ - else if (descriptor < 128) { - wc = (wc>>4); - } - -#ifdef DEBUG - brm->log[brm->log_i++ % EVENT_QUEUE_SIZE] = (descriptor << 16) | wc; - brm->log[brm->log_i++ % EVENT_QUEUE_SIZE] = current; - brm->log[brm->log_i++ % EVENT_QUEUE_SIZE] = msgadr; -#endif - - /* If there is room in the event queue, copy the event there */ - if (brm->head - brm->tail != EVENT_QUEUE_SIZE) { - - /* Copy to event queue */ - brm->rt_event[INDEX(brm->head)].miw = READ_DMA(&brm->mem[msgadr]); - brm->rt_event[INDEX(brm->head)].time = READ_DMA(&brm->mem[msgadr+1]); - len = wc; - while( len-- > 0){ - brm->rt_event[INDEX(brm->head)].data[len] = READ_DMA(&brm->mem[msgadr+2+len]); - } - brm->rt_event[INDEX(brm->head)].desc = descriptor; - brm->head++; - } - else { - /* Indicate overrun */ - brm->rt_event[INDEX(brm->head)].desc |= 0x8000; - } - - msgadr += (2+wc); - - if (msgadr >= READ_DMA(&brm->desc[descriptor].bot)) { - msgadr = READ_DMA(&brm->desc[descriptor].top); - } - brm->last_read[descriptor] = msgadr; - -#ifdef DEBUG - brm->log[brm->log_i++ % EVENT_QUEUE_SIZE] = msgadr; -#endif - wake_rx_task = 1; - } while ( (msgadr=brm->last_read[descriptor]) != current ); - } - - if (pending & BRM_EOL_IRQ) { - wake_tx_task = 1; - } - - if (pending & BRM_BC_ILLCMD_IRQ) { - brm->bc_list_fail = 1; - wake_tx_task = 1; - SET_ERROR_DESCRIPTOR(descriptor); - FUNCDBG("BRM: ILLCMD IRQ\n\r"); - } - - /* Monitor irq */ - if (pending & BRM_MBC_IRQ) { - - stop_operation(brm); - brm->regs->mbc = 1; - start_operation(brm); - - /* If there is room in the event queue, copy the event there */ - if (brm->head - brm->tail != EVENT_QUEUE_SIZE) { - - /* Copy to event queue */ - - brm->bm_event[INDEX(brm->head)].miw = READ_DMA(&brm->mem[0]); - brm->bm_event[INDEX(brm->head)].cw1 = READ_DMA(&brm->mem[1]); - brm->bm_event[INDEX(brm->head)].cw2 = READ_DMA(&brm->mem[2]); - brm->bm_event[INDEX(brm->head)].sw1 = READ_DMA(&brm->mem[4]); - brm->bm_event[INDEX(brm->head)].sw2 = READ_DMA(&brm->mem[5]); - brm->bm_event[INDEX(brm->head)].time = READ_DMA(&brm->mem[6]); - - len = 32; - while ( len-- ){ - brm->bm_event[INDEX(brm->head)].data[len] = READ_DMA(&brm->mem[0x100+len]); - len--; - brm->bm_event[INDEX(brm->head)].data[len] = READ_DMA(&brm->mem[0x100+len]); - len--; - brm->bm_event[INDEX(brm->head)].data[len] = READ_DMA(&brm->mem[0x100+len]); - len--; - brm->bm_event[INDEX(brm->head)].data[len] = READ_DMA(&brm->mem[0x100+len]); - } -/* memcpy((void *)brm->bm_event[INDEX(brm->head)].data, &brm->mem[0x100], 32);*/ - -#ifdef DEBUG - brm->log[brm->log_i++ % EVENT_QUEUE_SIZE] = READ_REG(&brm->regs->mbc) & 0xffff; - brm->log[brm->log_i++ % EVENT_QUEUE_SIZE] = READ_DMA(&brm->mem[0]); - brm->log[brm->log_i++ % EVENT_QUEUE_SIZE] = READ_DMA(&brm->mem[1]); - brm->log[brm->log_i++ % EVENT_QUEUE_SIZE] = READ_DMA(&brm->mem[4]); -#endif - - brm->head++; - - } - else { - /* Indicate overrun */ - brm->bm_event[INDEX(brm->head)].miw |= 0x8000; - } - - /* Wake any blocking thread */ - wake_rx_task = 1; - } - - /* The reset of the interrupts - * cause a event to be signalled - * so that user can handle error. - */ - if ( pending & BRM_RT_ILLCMD_IRQ){ - FUNCDBG("BRM: BRM_RT_ILLCMD_IRQ\n\r"); - brm->status |= BRM_RT_ILLCMD_IRQ; - event_status |= BRM_RT_ILLCMD_IRQ; - SET_ERROR_DESCRIPTOR(descriptor); - signal_event=1; - } - - if ( pending & BRM_ILLOP_IRQ){ - FUNCDBG("BRM: BRM_ILLOP_IRQ\n\r"); - brm->bc_list_fail = 1; - wake_tx_task = 1; - event_status |= BRM_ILLOP_IRQ; - SET_ERROR_DESCRIPTOR(descriptor); - signal_event=1; - } - - if ( pending & BRM_MERR_IRQ){ - FUNCDBG("BRM: BRM_MERR_IRQ\n\r"); - event_status |= BRM_MERR_IRQ; - SET_ERROR_DESCRIPTOR(descriptor); - signal_event=1; - } - /* Clear Block Accessed Bit */ - tmp = READ_DMA(&brm->desc[descriptor].ctrl); - brm->desc[descriptor].ctrl = tmp & ~0x10; -#ifdef DEBUG - brm->log[brm->log_i++ % EVENT_QUEUE_SIZE] = (0xfe<<16); - brm->log[brm->log_i++ % EVENT_QUEUE_SIZE] = 0; - brm->log[brm->log_i++ % EVENT_QUEUE_SIZE] = tmp & ~0x10; - brm->log[brm->log_i++ % EVENT_QUEUE_SIZE] = tmp; -#endif - } /* While */ - - /* clear interrupt flags & handle Hardware errors */ - pending = READ_REG(&brm->regs->ipend); - - if ( pending & BRM_DMAF_IRQ){ - FUNCDBG("BRM: BRM_DMAF_IRQ\n\r"); - event_status |= BRM_DMAF_IRQ; - signal_event=1; - } - - if ( pending & BRM_WRAPF_IRQ){ - FUNCDBG("BRM: BRM_WRAPF_IRQ\n\r"); - event_status |= BRM_WRAPF_IRQ; - signal_event=1; - } - - if ( pending & BRM_TAPF_IRQ){ - FUNCDBG("BRM: BRM_TAPF_IRQ\n\r"); - event_status |= BRM_TAPF_IRQ; - signal_event=1; - } - - /* Copy current mask to status mask */ - if ( event_status ){ - if ( event_status & 0xffff0000 ) - brm->status &= 0x0000ffff; - brm->status |= event_status; - } - - /* Wake any blocked rx thread only on receive interrupts */ - if ( wake_rx_task ) { - rtems_semaphore_release(brm->rx_sem); - } - - /* Wake any blocked tx thread only on transmit interrupts */ - if ( wake_tx_task ) { - rtems_semaphore_release(brm->tx_sem); - } - - /* signal event once */ - if ( signal_event && (brm->event_id!=0) ){ - rtems_event_send(brm->event_id, event_status); - } - -} - -void b1553brm_print_dev(struct drvmgr_dev *dev, int options) -{ - brm_priv *pDev = dev->priv; - struct brm_reg *regs = pDev->regs; - - /* Print */ - printf("--- B1553BRM[%d] %s ---\n", pDev->minor, pDev->devName); - printf(" REGS: 0x%x\n", (unsigned int)pDev->regs); - printf(" IRQ: %d\n", pDev->irqno); - switch (pDev->mode) { - case BRM_MODE_BC: - printf(" MODE: BC\n"); - printf(" DESCS: 0x%x\n", (unsigned int)&pDev->bcmem->descs[0]); - printf(" DATA: 0x%x\n", (unsigned int)&pDev->bcmem->msg_data[0].data[0]); - printf(" IRQLOG: 0x%x\n", (unsigned int)&pDev->bcmem->irq_logs[0]); - break; - case BRM_MODE_BM: - printf(" MODE: BM\n"); - break; - case BRM_MODE_RT: - printf(" MODE: RT\n"); - printf(" RXSUBS: 0x%x\n", (unsigned int)&pDev->rtmem->rxsubs[0]); - printf(" TXSUBS: 0x%x\n", (unsigned int)&pDev->rtmem->txsubs[0]); - printf(" RXMODES: 0x%x\n", (unsigned int)&pDev->rtmem->rxmodes[0]); - printf(" TXOMODES: 0x%x\n", (unsigned int)&pDev->rtmem->txmodes[0]); - printf(" RXSUBS MSGS: 0x%x\n", (unsigned int)&pDev->rtmem->rxsuba_msgs[0]); - printf(" TXSUBS MSGS: 0x%x\n", (unsigned int)&pDev->rtmem->txsuba_msgs[0]); - printf(" RXMODES MSGS: 0x%x\n", (unsigned int)&pDev->rtmem->rxmode_msgs[0]); - printf(" TXMODES MSGS: 0x%x\n", (unsigned int)&pDev->rtmem->txmode_msgs[0]); - printf(" IRQLOG: 0x%x\n", (unsigned int)&pDev->rtmem->irq_logs[0]); - break; - } - printf(" CTRL: 0x%x\n", regs->ctrl); - printf(" OPER: 0x%x\n", regs->oper); - printf(" CUR_CMD: 0x%x\n", regs->cur_cmd); - printf(" IMASK: 0x%x\n", regs->imask); - printf(" IPEND: 0x%x\n", regs->ipend); - printf(" IPOINT: 0x%x\n", regs->ipoint); - printf(" BIT_REG: 0x%x\n", regs->bit_reg); - printf(" TTAG: 0x%x\n", regs->ttag); - printf(" DPOINT: 0x%x\n", regs->dpoint); - printf(" SW: 0x%x\n", regs->sw); - printf(" INITCOUNT: 0x%x\n", regs->initcount); - printf(" MCPOINT: 0x%x\n", regs->mcpoint); - printf(" MDPOINT: 0x%x\n", regs->mdpoint); - printf(" MBC: 0x%x\n", regs->mbc); - printf(" MFILTA: 0x%x\n", regs->mfilta); - printf(" MFILTB: 0x%x\n", regs->mfiltb); - printf(" ENHANCED: 0x%x\n", regs->enhanced); - printf(" W_CTRL: 0x%x\n", regs->w_ctrl); - printf(" W_IRQCTRL: 0x%x\n", regs->w_irqctrl); - printf(" W_AHBADDR: 0x%x\n", regs->w_ahbaddr); -} - -void b1553brm_print(int options) -{ - struct amba_drv_info *drv = &b1553brm_drv_info; - struct drvmgr_dev *dev; - - dev = drv->general.dev; - while(dev) { - b1553brm_print_dev(dev, options); - dev = dev->next_in_drv; - } -} diff --git a/c/src/lib/libbsp/sparc/shared/1553/b1553rt.c b/c/src/lib/libbsp/sparc/shared/1553/b1553rt.c deleted file mode 100644 index b076abdc5d..0000000000 --- a/c/src/lib/libbsp/sparc/shared/1553/b1553rt.c +++ /dev/null @@ -1,856 +0,0 @@ -/* - * B1553RT driver implmenetation - * - * COPYRIGHT (c) 2009. - * Cobham Gaisler AB. - * - * 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 -#include -#include - -/* Uncomment for debug output */ -/*#define DEBUG 1*/ - -/* - #define FUNCDEBUG 1*/ -/*#undef DEBUG*/ -#undef FUNCDEBUG - -/* EVENT_QUEUE_SIZE sets the size of the event queue - */ -#define EVENT_QUEUE_SIZE 1024 - - -#define INDEX(x) ( x&(EVENT_QUEUE_SIZE-1) ) - -#if 0 -#define DBG(x...) printk(x) -#else -#define DBG(x...) -#endif - -#ifdef FUNCDEBUG -#define FUNCDBG(x...) printk(x) -#else -#define FUNCDBG(x...) -#endif - -#define READ_DMA(address) _READ16((unsigned int)address) - -static __inline__ unsigned short _READ16(unsigned int addr) { - unsigned short tmp; - asm(" lduha [%1]1, %0 " - : "=r"(tmp) - : "r"(addr) - ); - return tmp; -} - -static rtems_device_driver rt_initialize(rtems_device_major_number major, rtems_device_minor_number minor, void *arg); -static rtems_device_driver rt_open(rtems_device_major_number major, rtems_device_minor_number minor, void *arg); -static rtems_device_driver rt_close(rtems_device_major_number major, rtems_device_minor_number minor, void *arg); -static rtems_device_driver rt_read(rtems_device_major_number major, rtems_device_minor_number minor, void *arg); -static rtems_device_driver rt_write(rtems_device_major_number major, rtems_device_minor_number minor, void *arg); -static rtems_device_driver rt_control(rtems_device_major_number major, rtems_device_minor_number minor, void *arg); - -#define RT_DRIVER_TABLE_ENTRY { rt_initialize, rt_open, rt_close, rt_read, rt_write, rt_control } - -static rtems_driver_address_table b1553rt_driver = RT_DRIVER_TABLE_ENTRY; - -typedef struct { - - struct drvmgr_dev *dev; /* Driver manager device */ - char devName[32]; /* Device Name */ - - struct rt_reg *regs; - unsigned int ctrl_copy; /* Local copy of config register */ - - unsigned int cfg_freq; - - unsigned int memarea_base; - unsigned int memarea_base_remote; - - volatile unsigned short *mem; - - /* Received events waiting to be read */ - struct rt_msg *rt_event; - unsigned int head, tail; - - int rx_blocking; - - rtems_id rx_sem, tx_sem, dev_sem; - int minor; - int irqno; - -#ifdef DEBUG - unsigned int log[EVENT_QUEUE_SIZE*4]; - unsigned int log_i; -#endif - - unsigned int status; - rtems_id event_id; /* event that may be signalled upon errors, needs to be set through ioctl command RT_SET_EVENTID */ - -} rt_priv; - -static void b1553rt_interrupt(void *arg); -static rtems_device_driver rt_init(rt_priv *rt); - -#define OFS(ofs) (((unsigned int)&ofs & 0x1ffff)>>1) - -static int b1553rt_driver_io_registered = 0; -static rtems_device_major_number b1553rt_driver_io_major = 0; - -/******************* Driver manager interface ***********************/ - -/* Driver prototypes */ -int b1553rt_register_io(rtems_device_major_number *m); -int b1553rt_device_init(rt_priv *pDev); - -int b1553rt_init2(struct drvmgr_dev *dev); -int b1553rt_init3(struct drvmgr_dev *dev); -int b1553rt_remove(struct drvmgr_dev *dev); - -struct drvmgr_drv_ops b1553rt_ops = -{ - .init = {NULL, b1553rt_init2, b1553rt_init3, NULL}, - .remove = b1553rt_remove, - .info = NULL -}; - -struct amba_dev_id b1553rt_ids[] = -{ - {VENDOR_GAISLER, GAISLER_B1553RT}, - {0, 0} /* Mark end of table */ -}; - -struct amba_drv_info b1553rt_drv_info = -{ - { - DRVMGR_OBJ_DRV, /* Driver */ - NULL, /* Next driver */ - NULL, /* Device list */ - DRIVER_AMBAPP_GAISLER_B1553RT_ID, /* Driver ID */ - "B1553RT_DRV", /* Driver Name */ - DRVMGR_BUS_TYPE_AMBAPP, /* Bus Type */ - &b1553rt_ops, - NULL, /* Funcs */ - 0, /* No devices yet */ - 0, - - }, - &b1553rt_ids[0] -}; - -void b1553rt_register_drv (void) -{ - DBG("Registering B1553RT driver\n"); - drvmgr_drv_register(&b1553rt_drv_info.general); -} - -int b1553rt_init2(struct drvmgr_dev *dev) -{ - rt_priv *priv; - - DBG("B1553RT[%d] on bus %s\n", dev->minor_drv, dev->parent->dev->name); - priv = dev->priv = malloc(sizeof(rt_priv)); - if ( !priv ) - return DRVMGR_NOMEM; - memset(priv, 0, sizeof(*priv)); - priv->dev = dev; - - /* This core will not find other cores, so we wait for init2() */ - - return DRVMGR_OK; -} - -int b1553rt_init3(struct drvmgr_dev *dev) -{ - rt_priv *priv; - char prefix[32]; - rtems_status_code status; - - priv = dev->priv; - - /* Do initialization */ - - if ( b1553rt_driver_io_registered == 0) { - /* Register the I/O driver only once for all cores */ - if ( b1553rt_register_io(&b1553rt_driver_io_major) ) { - /* Failed to register I/O driver */ - dev->priv = NULL; - return DRVMGR_FAIL; - } - - b1553rt_driver_io_registered = 1; - } - - /* I/O system registered and initialized - * Now we take care of device initialization. - */ - - if ( b1553rt_device_init(priv) ) { - return DRVMGR_FAIL; - } - - /* Get Filesystem name prefix */ - prefix[0] = '\0'; - if ( drvmgr_get_dev_prefix(dev, prefix) ) { - /* Failed to get prefix, make sure of a unique FS name - * by using the driver minor. - */ - sprintf(priv->devName, "/dev/b1553rt%d", dev->minor_drv); - } else { - /* Got special prefix, this means we have a bus prefix - * And we should use our "bus minor" - */ - sprintf(priv->devName, "/dev/%sb1553rt%d", prefix, dev->minor_bus); - } - - /* Register Device */ - status = rtems_io_register_name(priv->devName, b1553rt_driver_io_major, dev->minor_drv); - if (status != RTEMS_SUCCESSFUL) { - return DRVMGR_FAIL; - } - - return DRVMGR_OK; -} - -int b1553rt_remove(struct drvmgr_dev *dev) -{ - /* Stop more tasks to open driver */ - - /* Throw out all tasks using this driver */ - - /* Unregister I/O node */ - - /* Unregister and disable Interrupt */ - - /* Free device memory */ - - /* Return sucessfully */ - - return DRVMGR_FAIL; -} - -/******************* Driver Implementation ***********************/ - -int b1553rt_register_io(rtems_device_major_number *m) -{ - rtems_status_code r; - - if ((r = rtems_io_register_driver(0, &b1553rt_driver, m)) == RTEMS_SUCCESSFUL) { - DBG("B1553RT driver successfully registered, major: %d\n", *m); - } else { - switch(r) { - case RTEMS_TOO_MANY: - printk("B1553RT rtems_io_register_driver failed: RTEMS_TOO_MANY\n"); - return -1; - case RTEMS_INVALID_NUMBER: - printk("B1553RT rtems_io_register_driver failed: RTEMS_INVALID_NUMBER\n"); - return -1; - case RTEMS_RESOURCE_IN_USE: - printk("B1553RT rtems_io_register_driver failed: RTEMS_RESOURCE_IN_USE\n"); - return -1; - default: - printk("B1553RT rtems_io_register_driver failed\n"); - return -1; - } - } - return 0; -} - -int b1553rt_device_init(rt_priv *pDev) -{ - struct amba_dev_info *ambadev; - struct ambapp_core *pnpinfo; - union drvmgr_key_value *value; - unsigned int mem; - unsigned int sys_freq_hz; - - /* Get device information from AMBA PnP information */ - ambadev = (struct amba_dev_info *)pDev->dev->businfo; - if ( ambadev == NULL ) { - return -1; - } - pnpinfo = &ambadev->info; - pDev->irqno = pnpinfo->irq; - pDev->regs = (struct rt_reg *)pnpinfo->apb_slv->start; - pDev->minor = pDev->dev->minor_drv; - -#ifdef DEBUG - pDev->log_i = 0; - memset(pDev->log,0,sizeof(pDev->log)); - printf("LOG: 0x%x\n", &pDev->log[0]); - printf("LOG_I: 0x%x\n", &pDev->log_i); -#endif - - /* Get memory configuration from bus resources */ - value = drvmgr_dev_key_get(pDev->dev, "dmaBaseAdr", DRVMGR_KT_POINTER); - if (value) - mem = (unsigned int)value->ptr; - - if (value && (mem & 1)) { - /* Remote address, address as RT looks at it. */ - - /* Translate the base address into an address that the the CPU can understand */ - pDev->memarea_base = mem & ~1; - drvmgr_translate_check(pDev->dev, DMAMEM_TO_CPU, - (void *)pDev->memarea_base_remote, - (void **)&pDev->memarea_base, - 4 * 1024); - } else { - if (!value) { - /* Use dynamically allocated memory, - * 4k DMA memory + 4k for alignment - */ - mem = (unsigned int)malloc(4 * 1024 * 2); - if ( !mem ){ - printk("RT: Failed to allocate HW memory\n\r"); - return -1; - } - /* align memory to 4k boundary */ - pDev->memarea_base = (mem + 0xfff) & ~0xfff; - } else { - pDev->memarea_base = mem; - } - - /* Translate the base address into an address that the RT core can understand */ - drvmgr_translate_check(pDev->dev, CPUMEM_TO_DMA, - (void *)pDev->memarea_base, - (void **)&pDev->memarea_base_remote, - 4 * 1024); - } - - /* clear the used memory */ - memset((char *)pDev->memarea_base, 0, 4 * 1024); - - /* Set base address of all descriptors */ - pDev->memarea_base = (unsigned int)mem; - pDev->mem = (volatile unsigned short *)pDev->memarea_base; - - pDev->rt_event = NULL; - - /* The RT is always clocked at the same frequency as the bus - * If the frequency doesnt match it is defaulted to 24MHz, - * user can always override it. - */ - pDev->cfg_freq = RT_FREQ_24MHZ; - - /* Get frequency in Hz */ - if ( drvmgr_freq_get(pDev->dev, DEV_APB_SLV, &sys_freq_hz) == 0 ) { - if ( sys_freq_hz == 20000000 ) { - pDev->cfg_freq = RT_FREQ_20MHZ; - } else if ( sys_freq_hz == 16000000 ) { - pDev->cfg_freq = RT_FREQ_16MHZ; - } else if ( sys_freq_hz == 12000000 ) { - pDev->cfg_freq = RT_FREQ_12MHZ; - } - } - - value = drvmgr_dev_key_get(pDev->dev, "coreFreq", DRVMGR_KT_INT); - if ( value ) { - pDev->cfg_freq = value->i & RT_FREQ_MASK; - } - - /* RX Semaphore created with count = 0 */ - if ( rtems_semaphore_create(rtems_build_name('R', 'T', '0', '0' + pDev->minor), - 0, - RTEMS_FIFO|RTEMS_SIMPLE_BINARY_SEMAPHORE|RTEMS_NO_INHERIT_PRIORITY|RTEMS_LOCAL|RTEMS_NO_PRIORITY_CEILING, - 0, - &pDev->rx_sem) != RTEMS_SUCCESSFUL ) { - printk("RT: Failed to create rx semaphore\n"); - return RTEMS_INTERNAL_ERROR; - } - - /* Device Semaphore created with count = 1 */ - if ( rtems_semaphore_create(rtems_build_name('R', 'T', '0', '0' + pDev->minor), - 1, - RTEMS_FIFO|RTEMS_SIMPLE_BINARY_SEMAPHORE|RTEMS_NO_INHERIT_PRIORITY|RTEMS_LOCAL|RTEMS_NO_PRIORITY_CEILING, - 0, - &pDev->dev_sem) != RTEMS_SUCCESSFUL ){ - printk("RT: Failed to create device semaphore\n"); - return RTEMS_INTERNAL_ERROR; - } - - /* Default to RT-mode */ - rt_init(pDev); - - return 0; -} - -static int odd_parity(unsigned int data) -{ - unsigned int i=0; - - while(data) - { - i++; - data &= (data - 1); - } - - return !(i&1); -} - -static void start_operation(rt_priv *rt) -{ - -} - -static void stop_operation(rt_priv *rt) -{ - -} - -static void set_extmdata_en(rt_priv *rt, int extmdata) -{ - if ( extmdata ) - extmdata = 1; - rt->ctrl_copy = (rt->ctrl_copy & ~(1<<16)) | (extmdata<<16); - rt->regs->ctrl = rt->ctrl_copy; -} - -static void set_vector_word(rt_priv *rt, unsigned short vword) -{ - rt->regs->vword = vword; -} - -/* Set clock speed */ -static void set_clkspd(rt_priv *rt, int spd) -{ - rt->ctrl_copy = (rt->ctrl_copy & ~0xC0) | (spd<<6); - rt->regs->ctrl = rt->ctrl_copy; - asm volatile("nop"::); - rt->regs->ctrl = rt->ctrl_copy | (1<<20); -} - -static void set_rtaddr(rt_priv *rt, int addr) -{ - rt->ctrl_copy = (rt->ctrl_copy & ~0x3F00) | (addr << 8) | (odd_parity(addr)<<13); - rt->regs->ctrl = rt->ctrl_copy; -} - -static void set_broadcast_en(rt_priv *rt, int data) -{ - rt->ctrl_copy = (rt->ctrl_copy & ~0x40000) | (data<<18); - rt->regs->ctrl = rt->ctrl_copy; -} - -static rtems_device_driver rt_init(rt_priv *rt) -{ - rt->rx_blocking = 1; - - if ( rt->rt_event ) - free(rt->rt_event); - rt->rt_event = NULL; - - rt->rt_event = (struct rt_msg *) malloc(EVENT_QUEUE_SIZE*sizeof(struct rt_msg)); - - if (rt->rt_event == NULL) { - DBG("RT driver failed to allocated memory."); - return RTEMS_NO_MEMORY; - } - - rt->ctrl_copy = rt->regs->ctrl & 0x3F00; /* Keep rtaddr and rtaddrp */ - rt->ctrl_copy |= 0x3C0D0; /* broadcast disabled, extmdata=1, writetsw = writecmd = 1 */ - rt->regs->ctrl = rt->ctrl_copy; - - /* Set Clock speed */ - set_clkspd(rt, rt->cfg_freq); - - rt->regs->addr = rt->memarea_base_remote; - rt->regs->ipm = 0x70000; /* Enable RT RX, MEM Failure and AHB Error interrupts */ - - DBG("B1553RT DMA_AREA: 0x%x\n", (unsigned int)rt->mem); - - return RTEMS_SUCCESSFUL; -} - - -static rtems_device_driver rt_initialize(rtems_device_major_number major, rtems_device_minor_number minor, void *arg) -{ - return RTEMS_SUCCESSFUL; -} - -static rtems_device_driver rt_open(rtems_device_major_number major, rtems_device_minor_number minor, void *arg) { - rt_priv *rt; - struct drvmgr_dev *dev; - - FUNCDBG("rt_open\n"); - - if ( drvmgr_get_dev(&b1553rt_drv_info.general, minor, &dev) ) { - DBG("Wrong minor %d\n", minor); - return RTEMS_UNSATISFIED; - } - rt = (rt_priv *)dev->priv; - - if (rtems_semaphore_obtain(rt->dev_sem, RTEMS_NO_WAIT, RTEMS_NO_TIMEOUT) != RTEMS_SUCCESSFUL) { - DBG("rt_open: resource in use\n"); - return RTEMS_RESOURCE_IN_USE; /* EBUSY */ - } - - /* Set defaults */ - rt->event_id = 0; - - start_operation(rt); - - /* Register interrupt routine */ - if (drvmgr_interrupt_register(rt->dev, 0, "b1553rt", b1553rt_interrupt, rt)) { - rtems_semaphore_release(rt->dev_sem); - return -1; - } - - - return RTEMS_SUCCESSFUL; -} - -static rtems_device_driver rt_close(rtems_device_major_number major, rtems_device_minor_number minor, void *arg) -{ - rt_priv *rt; - struct drvmgr_dev *dev; - - FUNCDBG("rt_close"); - - if ( drvmgr_get_dev(&b1553rt_drv_info.general, minor, &dev) ) { - return RTEMS_UNSATISFIED; - } - rt = (rt_priv *)dev->priv; - - drvmgr_interrupt_unregister(rt->dev, 0, b1553rt_interrupt, rt); - - stop_operation(rt); - rtems_semaphore_release(rt->dev_sem); - - return RTEMS_SUCCESSFUL; -} - -static int get_messages(rt_priv *rt, void *buf, unsigned int msg_count) -{ - - struct rt_msg *dest = (struct rt_msg *) buf; - int count = 0; - - if (rt->head == rt->tail) { - return 0; - } - - do { - - DBG("rt read - head: %d, tail: %d\n", rt->head, rt->tail); - dest[count++] = rt->rt_event[INDEX(rt->tail++)]; - - } while (rt->head != rt->tail && count < msg_count); - - return count; - -} -static rtems_device_driver rt_read(rtems_device_major_number major, rtems_device_minor_number minor, void *arg) -{ - rtems_libio_rw_args_t *rw_args; - int count = 0; - rt_priv *rt; - struct drvmgr_dev *dev; - - if ( drvmgr_get_dev(&b1553rt_drv_info.general, minor, &dev) ) { - return RTEMS_UNSATISFIED; - } - rt = (rt_priv *)dev->priv; - - rw_args = (rtems_libio_rw_args_t *) arg; - - FUNCDBG("rt_read [%i,%i]: buf: 0x%x, len: %i\n",major, minor, (unsigned int)rw_args->buffer, rw_args->count); - - while ( (count = get_messages(rt,rw_args->buffer, rw_args->count)) == 0 ) { - - if (rt->rx_blocking) { - rtems_semaphore_obtain(rt->rx_sem, RTEMS_WAIT, RTEMS_NO_TIMEOUT); - } else { - /* Translates to EBUSY */ - return RTEMS_RESOURCE_IN_USE; - } - } - - rw_args->bytes_moved = count; - return RTEMS_SUCCESSFUL; -} - -static rtems_device_driver rt_write(rtems_device_major_number major, rtems_device_minor_number minor, void *arg) -{ - rtems_libio_rw_args_t *rw_args; - struct rt_msg *source; - rt_priv *rt; - struct drvmgr_dev *dev; - unsigned int descriptor, suba, wc; - - if ( drvmgr_get_dev(&b1553rt_drv_info.general, minor, &dev) ) { - return RTEMS_UNSATISFIED; - } - rt = (rt_priv *)dev->priv; - - rw_args = (rtems_libio_rw_args_t *) arg; - - if ( rw_args->count != 1 ) { - return RTEMS_INVALID_NAME; - } - - source = (struct rt_msg *) rw_args->buffer; - - descriptor = source[0].desc & 0x7F; - suba = descriptor-32; - wc = source[0].miw >> 11; - wc = wc ? wc : 32; - - FUNCDBG("rt_write [%i,%i]: buf: 0x%x\n",major, minor, (unsigned int)rw_args->buffer); - - memcpy((void *)&rt->mem[0x400 + suba*32], &source[0].data[0], wc*2); - - rw_args->bytes_moved = 1; - - return RTEMS_SUCCESSFUL; - -} - -static rtems_device_driver rt_control(rtems_device_major_number major, rtems_device_minor_number minor, void *arg) -{ - rtems_libio_ioctl_args_t *ioarg = (rtems_libio_ioctl_args_t *) arg; - unsigned int *data = ioarg->buffer; - - rt_priv *rt; - struct drvmgr_dev *dev; - - FUNCDBG("rt_control[%d]: [%i,%i]\n", minor, major, minor); - - if ( drvmgr_get_dev(&b1553rt_drv_info.general, minor, &dev) ) { - return RTEMS_UNSATISFIED; - } - rt = (rt_priv *)dev->priv; - - if (!ioarg) { - DBG("rt_control: invalid argument\n"); - return RTEMS_INVALID_NAME; - } - - ioarg->ioctl_return = 0; - switch (ioarg->command) { - - case RT_SET_ADDR: - set_rtaddr(rt, data[0]); - break; - - case RT_SET_BCE: - set_broadcast_en(rt, data[0]); - break; - - case RT_SET_VECTORW: - set_vector_word(rt, data[0]); - break; - - case RT_SET_EXTMDATA: - set_extmdata_en(rt, data[0]); - break; - - case RT_RX_BLOCK: - rt->rx_blocking = data[0]; - break; - - case RT_CLR_STATUS: - rt->status = 0; - break; - - case RT_GET_STATUS: /* copy status */ - if ( !ioarg->buffer ) - return RTEMS_INVALID_NAME; - - *(unsigned int *)ioarg->buffer = rt->status; - break; - - case RT_SET_EVENTID: - rt->event_id = (rtems_id)ioarg->buffer; - break; - - default: - return RTEMS_NOT_IMPLEMENTED; - } - - return RTEMS_SUCCESSFUL; -} - -static void b1553rt_interrupt(void *arg) -{ - rt_priv *rt = arg; - unsigned short descriptor; - int signal_event=0, wake_rx_task=0; - unsigned int event_status=0; - unsigned int wc, irqv, cmd, tsw, suba, tx, miw, i; - unsigned int ipend; - - #define SET_ERROR_DESCRIPTOR(descriptor) (event_status = (event_status & 0x0000ffff) | descriptor<<16) - ipend = rt->regs->ipm; - - if (ipend == 0) { - /* IRQ mask has been cleared, we must have been reset */ - /* Restore ctrl registers */ - rt->regs->ctrl = rt->ctrl_copy; - rt->regs->addr = rt->memarea_base_remote; - rt->regs->ipm = 0x70000; - /* Send reset mode code event */ - if (rt->head - rt->tail != EVENT_QUEUE_SIZE) { - miw = (8<<11); - descriptor = 64 + 32 + 8; - rt->rt_event[INDEX(rt->head)].miw = miw; - rt->rt_event[INDEX(rt->head)].time = 0; - rt->rt_event[INDEX(rt->head)].desc = descriptor; - rt->head++; - } - } - - if ( ipend & 0x1 ) { - /* RT IRQ */ - if (rt->head - rt->tail != EVENT_QUEUE_SIZE) { - - irqv = rt->regs->irq; - cmd = irqv >> 7; - wc = cmd & 0x1F; /* word count / mode code */ - suba = irqv & 0x1F; /* sub address (0-31) */ - tx = (irqv >> 5) & 1; - - /* read status word */ - tsw = READ_DMA(&rt->mem[tx*0x3E0+suba]); - - /* Build Message Information Word (B1553BRM-style) */ - miw = (wc<<11) | (tsw&RT_TSW_BUS)>>4 | !(tsw&RT_TSW_OK)>>7 | (tsw&RT_TSW_ILL)>>5 | - (tsw&RT_TSW_PAR)>>5 | (tsw&RT_TSW_MAN)>>7; - - descriptor = (tx << 5) | suba; - - /* Mode codes */ - if (suba == 0 || suba == 31) { - descriptor = 64 + (tx*32) + wc; - } - - /* Data received or transmitted */ - if (descriptor < 64) { - wc = wc ? wc : 32; /* wc = 0 means 32 words transmitted */ - } - /* RX Mode code */ - else if (descriptor < 96) { - wc = (wc>>4); - } - /* TX Mode code */ - else if (descriptor < 128) { - wc = (wc>>4); - } - - /* Copy to event queue */ - rt->rt_event[INDEX(rt->head)].miw = miw; - rt->rt_event[INDEX(rt->head)].time = 0; - - for (i = 0; i < wc; i++) { - rt->rt_event[INDEX(rt->head)].data[i] = READ_DMA(&rt->mem[tx*0x400 + suba*32 + i]); - } - rt->rt_event[INDEX(rt->head)].desc = descriptor; - rt->head++; - - - /* Handle errors */ - if ( tsw & RT_TSW_ILL){ - FUNCDBG("RT: RT_ILLCMD\n\r"); - rt->status |= RT_ILLCMD_IRQ; - event_status |= RT_ILLCMD_IRQ; - SET_ERROR_DESCRIPTOR(descriptor); - signal_event=1; - } - - if ( !(tsw & RT_TSW_OK) ) { - FUNCDBG("RT: RT_MERR_IRQ\n\r"); - rt->status |= RT_MERR_IRQ; - event_status |= RT_MERR_IRQ; - SET_ERROR_DESCRIPTOR(descriptor); - signal_event=1; - } - - } - else { - /* Indicate overrun */ - rt->rt_event[INDEX(rt->head)].desc |= 0x8000; - } - } - - if ( ipend & 0x2 ) { - /* Memory failure IRQ */ - FUNCDBG("B1553RT: Memory failure\n"); - event_status |= RT_DMAF_IRQ; - signal_event=1; - } - - if ( ipend & 0x4 ) { - /* AHB Error */ - FUNCDBG("B1553RT: AHB ERROR\n"); - event_status |= RT_DMAF_IRQ; - signal_event=1; - } - -#ifdef DEBUG - rt->log[rt->log_i++ % EVENT_QUEUE_SIZE] = descriptor; - rt->log[rt->log_i++ % EVENT_QUEUE_SIZE] = cmd; - rt->log[rt->log_i++ % EVENT_QUEUE_SIZE] = miw; - rt->log[rt->log_i++ % EVENT_QUEUE_SIZE] = tsw; -#endif - - wake_rx_task = 1; - - /* Wake any blocked rx thread only on receive interrupts */ - if ( wake_rx_task ) { - rtems_semaphore_release(rt->rx_sem); - } - - /* Copy current mask to status mask */ - if ( event_status ) { - if ( event_status & 0xffff0000 ) - rt->status &= 0x0000ffff; - rt->status |= event_status; - } - - /* signal event once */ - if ( signal_event && (rt->event_id != 0) ) { - rtems_event_send(rt->event_id, event_status); - } - -} - -void b1553rt_print_dev(struct drvmgr_dev *dev, int options) -{ - rt_priv *pDev = dev->priv; - - /* Print */ - printf("--- B1553RT[%d] %s ---\n", pDev->minor, pDev->devName); - printf(" REGS: 0x%x\n", (unsigned int)pDev->regs); - printf(" IRQ: %d\n", pDev->irqno); - -} - -void b1553rt_print(int options) -{ - struct amba_drv_info *drv = &b1553rt_drv_info; - struct drvmgr_dev *dev; - - dev = drv->general.dev; - while(dev) { - b1553rt_print_dev(dev, options); - dev = dev->next_in_drv; - } -} diff --git a/c/src/lib/libbsp/sparc/shared/1553/gr1553b.c b/c/src/lib/libbsp/sparc/shared/1553/gr1553b.c deleted file mode 100644 index c05d53a4f9..0000000000 --- a/c/src/lib/libbsp/sparc/shared/1553/gr1553b.c +++ /dev/null @@ -1,310 +0,0 @@ -/* GR1553B driver, used by BC, RT and/or BM driver - * - * COPYRIGHT (c) 2010. - * Cobham Gaisler AB. - * - * 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 - -/* Driver Manager interface for BC, RT, BM, BRM, BC-BM and RT-BM */ - -#define GR1553B_WRITE_REG(adr, val) *(volatile uint32_t *)(adr) = (val) -#define GR1553B_READ_REG(adr) (*(volatile uint32_t *)(adr)) - -#define FEAT_BC 0x1 -#define FEAT_RT 0x2 -#define FEAT_BM 0x4 - -#define ALLOC_BC 0x1 -#define ALLOC_RT 0x2 -#define ALLOC_BM 0x4 - -struct gr1553_device { - struct drvmgr_dev *dev; - int features; - int alloc; -}; - -struct gr1553_device_feature { - struct gr1553_device_feature *next; - struct gr1553_device *dev; - int minor; -}; - -/* Device lists */ -static struct gr1553_device_feature *gr1553_bm_root = NULL; -static struct gr1553_device_feature *gr1553_rt_root = NULL; -static struct gr1553_device_feature *gr1553_bc_root = NULL; - -/* Driver registered */ -static int gr1553_driver_registerd = 0; - -/* Add 'feat' to linked list pointed to by 'root'. A minor is also assigned. */ -static void gr1553_list_add - ( - struct gr1553_device_feature **root, - struct gr1553_device_feature *feat - ) -{ - int minor; - struct gr1553_device_feature *curr; - - if ( *root == NULL ) { - *root = feat; - feat->next = NULL; - feat->minor = 0; - return; - } - - minor = 0; -retry_new_minor: - curr = *root; - while ( curr->next ) { - if ( curr->minor == minor ) { - minor++; - goto retry_new_minor; - } - curr = curr->next; - } - - feat->next = NULL; - feat->minor = minor; - curr->next = feat; -} - -static struct gr1553_device_feature *gr1553_list_find - ( - struct gr1553_device_feature *root, - int minor - ) -{ - struct gr1553_device_feature *curr = root; - while ( curr ) { - if ( curr->minor == minor ) { - return curr; - } - curr = curr->next; - } - return NULL; -} - -struct drvmgr_dev **gr1553_bc_open(int minor) -{ - struct gr1553_device_feature *feat; - - feat = gr1553_list_find(gr1553_bc_root, minor); - if ( feat == NULL ) - return NULL; - - /* Only possible to allocate is RT and BC is free, - * this is beacuse it is not possible to use the - * RT and the BC at the same time. - */ - if ( feat->dev->alloc & (ALLOC_BC|ALLOC_RT) ) - return NULL; - - /* Alloc BC device */ - feat->dev->alloc |= ALLOC_BC; - - return &feat->dev->dev; -} - -void gr1553_bc_close(struct drvmgr_dev **dev) -{ - struct gr1553_device *d = (struct gr1553_device *)dev; - - d->alloc &= ~ALLOC_BC; -} - -struct drvmgr_dev **gr1553_rt_open(int minor) -{ - struct gr1553_device_feature *feat; - - feat = gr1553_list_find(gr1553_rt_root, minor); - if ( feat == NULL ) - return NULL; - - /* Only possible to allocate is RT and BC is free, - * this is beacuse it is not possible to use the - * RT and the BC at the same time. - */ - if ( feat->dev->alloc & (ALLOC_BC|ALLOC_RT) ) - return NULL; - - /* Alloc RT device */ - feat->dev->alloc |= ALLOC_RT; - - return &feat->dev->dev; -} - -void gr1553_rt_close(struct drvmgr_dev **dev) -{ - struct gr1553_device *d = (struct gr1553_device *)dev; - - d->alloc &= ~ALLOC_RT; -} - -struct drvmgr_dev **gr1553_bm_open(int minor) -{ - struct gr1553_device_feature *feat; - - feat = gr1553_list_find(gr1553_bm_root, minor); - if ( feat == NULL ) - return NULL; - - /* Only possible to allocate is RT and BC is free, - * this is beacuse it is not possible to use the - * RT and the BC at the same time. - */ - if ( feat->dev->alloc & ALLOC_BM ) - return NULL; - - /* Alloc BM device */ - feat->dev->alloc |= ALLOC_BM; - - return &feat->dev->dev; -} - -void gr1553_bm_close(struct drvmgr_dev **dev) -{ - struct gr1553_device *d = (struct gr1553_device *)dev; - - d->alloc &= ~ALLOC_BM; -} - -static int gr1553_init2(struct drvmgr_dev *dev) -{ - struct amba_dev_info *ambadev; - struct ambapp_core *pnpinfo; - struct gr1553b_regs *regs; - - /* Get device information from AMBA PnP information */ - ambadev = (struct amba_dev_info *)dev->businfo; - if ( ambadev == NULL ) { - return DRVMGR_FAIL; - } - pnpinfo = &ambadev->info; - if ( pnpinfo->apb_slv == NULL ) - return DRVMGR_EIO; - regs = (struct gr1553b_regs *)pnpinfo->apb_slv->start; - - /* Stop IRQ */ - GR1553B_WRITE_REG(®s->imask, 0); - GR1553B_WRITE_REG(®s->irq, 0xffffffff); - /* Stop BC if not already stopped (just in case) */ - GR1553B_WRITE_REG(®s->bc_ctrl, 0x15520204); - /* Stop RT rx (just in case) */ - GR1553B_WRITE_REG(®s->rt_cfg, 0x15530000); - /* Stop BM logging (just in case) */ - GR1553B_WRITE_REG(®s->bm_ctrl, 0); - - return DRVMGR_OK; -} - -/* Register the different functionalities that the - * core supports. - */ -static int gr1553_init3(struct drvmgr_dev *dev) -{ - struct amba_dev_info *ambadev; - struct ambapp_core *pnpinfo; - struct gr1553_device *priv; - struct gr1553_device_feature *feat; - struct gr1553b_regs *regs; - - priv = malloc(sizeof(struct gr1553_device)); - if ( priv == NULL ) - return DRVMGR_NOMEM; - priv->dev = dev; - priv->alloc = 0; - priv->features = 0; - dev->priv = NULL; /* Let higher level driver handle this */ - - /* Get device information from AMBA PnP information */ - ambadev = (struct amba_dev_info *)dev->businfo; - pnpinfo = &ambadev->info; - regs = (struct gr1553b_regs *)pnpinfo->apb_slv->start; - - if ( GR1553B_READ_REG(®s->bm_stat) & GR1553B_BM_STAT_BMSUP ) { - priv->features |= FEAT_BM; - feat = malloc(sizeof(struct gr1553_device_feature)); - feat->dev = priv; - /* Init Minor and Next */ - gr1553_list_add(&gr1553_bm_root, feat); - } - - if ( GR1553B_READ_REG(®s->bc_stat) & GR1553B_BC_STAT_BCSUP ) { - priv->features |= FEAT_BC; - feat = malloc(sizeof(struct gr1553_device_feature)); - feat->dev = priv; - /* Init Minor and Next */ - gr1553_list_add(&gr1553_bc_root, feat); - } - - if ( GR1553B_READ_REG(®s->rt_stat) & GR1553B_RT_STAT_RTSUP ) { - priv->features |= FEAT_RT; - feat = malloc(sizeof(struct gr1553_device_feature)); - feat->dev = priv; - /* Init Minor and Next */ - gr1553_list_add(&gr1553_rt_root, feat); - } - - if ( priv->features == 0 ) { - /* no features in HW should never happen.. an I/O error? */ - free(priv); - return DRVMGR_EIO; - } - - return DRVMGR_OK; -} - -struct drvmgr_drv_ops gr1553_ops = -{ - {NULL, gr1553_init2, gr1553_init3, NULL}, - NULL, - NULL -}; - -struct amba_dev_id gr1553_ids[] = -{ - {VENDOR_GAISLER, GAISLER_GR1553B}, - {0, 0} /* Mark end of table */ -}; - -struct amba_drv_info gr1553_drv_info = -{ - { - DRVMGR_OBJ_DRV, /* Driver */ - NULL, /* Next driver */ - NULL, /* Device list */ - DRIVER_AMBAPP_GAISLER_GR1553B_ID,/* Driver ID */ - "GR1553_DRV", /* Driver Name */ - DRVMGR_BUS_TYPE_AMBAPP, /* Bus Type */ - &gr1553_ops, - NULL, /* Funcs */ - 0, /* No devices yet */ - 0, - }, - &gr1553_ids[0] -}; - -/* Multiple drivers may call this function. The drivers that depends on - * this driver: - * - BM driver - * - BC driver - * - RT driver - */ -void gr1553_register(void) -{ - if ( gr1553_driver_registerd == 0 ) { - gr1553_driver_registerd = 1; - drvmgr_drv_register(&gr1553_drv_info.general); - } -} diff --git a/c/src/lib/libbsp/sparc/shared/1553/gr1553bc.c b/c/src/lib/libbsp/sparc/shared/1553/gr1553bc.c deleted file mode 100644 index 3b967d0f37..0000000000 --- a/c/src/lib/libbsp/sparc/shared/1553/gr1553bc.c +++ /dev/null @@ -1,1719 +0,0 @@ -/* GR1553B BC driver - * - * COPYRIGHT (c) 2010. - * Cobham Gaisler AB. - * - * 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 - -/* Use interrupt lock privmitives compatible with SMP defined in - * RTEMS 4.11.99 and higher. - */ -#if (((__RTEMS_MAJOR__ << 16) | (__RTEMS_MINOR__ << 8) | __RTEMS_REVISION__) >= 0x040b63) - -/* map via rtems_interrupt_lock_* API: */ -#define SPIN_DECLARE(lock) RTEMS_INTERRUPT_LOCK_MEMBER(lock) -#define SPIN_INIT(lock, name) rtems_interrupt_lock_initialize(lock, name) -#define SPIN_LOCK(lock, level) rtems_interrupt_lock_acquire_isr(lock, &level) -#define SPIN_LOCK_IRQ(lock, level) rtems_interrupt_lock_acquire(lock, &level) -#define SPIN_UNLOCK(lock, level) rtems_interrupt_lock_release_isr(lock, &level) -#define SPIN_UNLOCK_IRQ(lock, level) rtems_interrupt_lock_release(lock, &level) -#define SPIN_IRQFLAGS(k) rtems_interrupt_lock_context k -#define SPIN_ISR_IRQFLAGS(k) SPIN_IRQFLAGS(k) -#define SPIN_FREE(lock) rtems_interrupt_lock_destroy(lock) - -#else - -/* maintain single-core compatibility with older versions of RTEMS: */ -#define SPIN_DECLARE(name) -#define SPIN_INIT(lock, name) -#define SPIN_LOCK(lock, level) -#define SPIN_LOCK_IRQ(lock, level) rtems_interrupt_disable(level) -#define SPIN_UNLOCK(lock, level) -#define SPIN_UNLOCK_IRQ(lock, level) rtems_interrupt_enable(level) -#define SPIN_IRQFLAGS(k) rtems_interrupt_level k -#define SPIN_ISR_IRQFLAGS(k) -#define SPIN_FREE(lock) - -#ifdef RTEMS_SMP -#error SMP mode not compatible with these interrupt lock primitives -#endif - -#endif - -#define GR1553BC_WRITE_MEM(adr, val) *(volatile uint32_t *)(adr) = (uint32_t)(val) -#define GR1553BC_READ_MEM(adr) (*(volatile uint32_t *)(adr)) - -#define GR1553BC_WRITE_REG(adr, val) *(volatile uint32_t *)(adr) = (uint32_t)(val) -#define GR1553BC_READ_REG(adr) (*(volatile uint32_t *)(adr)) - -/* Needed by list for data pinter and BD translation */ -struct gr1553bc_priv { - struct drvmgr_dev **pdev; - struct gr1553b_regs *regs; - struct gr1553bc_list *list; - struct gr1553bc_list *alist; - int started; - SPIN_DECLARE(devlock); - - /* IRQ log management */ - void *irq_log_p; - uint32_t *irq_log_base; - uint32_t *irq_log_curr; - uint32_t *irq_log_end; - uint32_t *irq_log_base_hw; - - /* Standard IRQ handler function */ - bcirq_func_t irq_func; - void *irq_data; -}; - - -/*************** LIST HANDLING ROUTINES ***************/ - -/* This marks that the jump is a jump to next Minor. - * It is important that it sets one of the two LSB - * so that we can separate it from a JUMP-IRQ function, - * function pointers must be aligned to 4bytes. - * - * This marker is used to optimize the INDICATION process, - * from a descriptor pointer we can step to next Jump that - * has this MARKER set, then we know that the MID is stored - * there. - * - * The marker is limited to 1 byte. - */ -#define NEXT_MINOR_MARKER 0x01 - -/* To separate ASYNC list from SYNC list we mark them differently, but with - * LSB always set. This can be used to get the list the descriptor is a part - * of. - */ -#define NEXT_MINOR_MARKER_ASYNC 0x80 - -struct gr1553bc_list_cfg gr1553bc_def_cfg = -{ - .rt_timeout = - { - 20, 20, 20, 20, - 20, 20, 20, 20, - 20, 20, 20, 20, - 20, 20, 20, 20, - 20, 20, 20, 20, - 20, 20, 20, 20, - 20, 20, 20, 20, - 20, 20, 20 - }, - .bc_timeout = 30, - .tropt_irq_on_err = 0, - .tropt_pause_on_err = 0, - .async_list = 0, -}; - -int gr1553bc_list_alloc(struct gr1553bc_list **list, int max_major) -{ - int size; - struct gr1553bc_list *l; - - size = sizeof(struct gr1553bc_list) + max_major * sizeof(void *); - l = malloc(size); - if ( l == NULL ) - return -1; - memset(l, 0, size); - - l->major_cnt = max_major; - *list = l; - - /* Set default options: - * - RT timeout tolerance 20us - * - Global transfer options used when generating transfer descriptors - * - No BC device, note that this only works when no translation is - * required - */ - if ( gr1553bc_list_config(l, &gr1553bc_def_cfg, NULL) ) { - free(l); - return -1; - } - - return 0; -} - -void gr1553bc_list_free(struct gr1553bc_list *list) -{ - gr1553bc_list_table_free(list); - free(list); -} - -int gr1553bc_list_config - ( - struct gr1553bc_list *list, - struct gr1553bc_list_cfg *cfg, - void *bc - ) -{ - int timeout, i, tropts; - - /* RT Time Tolerances */ - for (i=0; i<31; i++) { - /* 0=14us, 1=18us ... 0xf=74us - * round upwards: 15us will be 18us - */ - timeout = ((cfg->rt_timeout[i] + 1) - 14) / 4; - if ( (timeout > 0xf) || (timeout < 0) ) - return -1; - list->rt_timeout[i] = timeout; - } - timeout = ((cfg->bc_timeout + 1) - 14) / 4; - if ( timeout > 0xf ) - return -1; - list->rt_timeout[i] = timeout; - - /* Transfer descriptor generation options */ - tropts = 0; - if ( cfg->tropt_irq_on_err ) - tropts |= 1<<28; - if ( cfg->tropt_pause_on_err ) - tropts |= 1<<26; - list->tropts = tropts; - - list->async_list = cfg->async_list; - list->bc = bc; - - return 0; -} - -void gr1553bc_list_link_major( - struct gr1553bc_major *major, - struct gr1553bc_major *next - ) -{ - if ( major ) { - major->next = next; - if ( next ) { - major->minors[major->cfg->minor_cnt-1]->next = - next->minors[0]; - } else { - major->minors[major->cfg->minor_cnt-1]->next = NULL; - } - } -} - -int gr1553bc_list_set_major( - struct gr1553bc_list *list, - struct gr1553bc_major *major, - int no) -{ - struct gr1553bc_major *prev, *next; - - if ( no >= list->major_cnt ) - return -1; - - list->majors[no] = major; - - /* Link previous Major frame with this one */ - if ( no > 0 ) { - prev = list->majors[no-1]; - } else { - /* First Major is linked with last major */ - prev = list->majors[list->major_cnt-1]; - } - - /* Link to next Major if not the last one and if there is - * a next major - */ - if ( no == list->major_cnt-1 ) { - /* The last major, assume that it is connected with the first */ - next = list->majors[0]; - } else { - next = list->majors[no+1]; - } - - /* Link previous frame to jump into this */ - gr1553bc_list_link_major(prev, major); - - /* Link This frame to jump into the next */ - gr1553bc_list_link_major(major, next); - - return 0; -} - -/* Translate Descriptor address from CPU-address to Hardware Address */ -static inline union gr1553bc_bd *gr1553bc_bd_cpu2hw - ( - struct gr1553bc_list *list, - union gr1553bc_bd *bd - ) -{ - return (union gr1553bc_bd *)(((unsigned int)bd - list->table_cpu) + - list->table_hw); -} - -/* Translate Descriptor address from HW-address to CPU Address */ -static inline union gr1553bc_bd *gr1553bc_bd_hw2cpu - ( - struct gr1553bc_list *list, - union gr1553bc_bd *bd - ) -{ - return (union gr1553bc_bd *)(((unsigned int)bd - list->table_hw) + - list->table_cpu); -} - -int gr1553bc_minor_table_size(struct gr1553bc_minor *minor) -{ - struct gr1553bc_minor_cfg *mincfg = minor->cfg; - int slot_cnt; - - /* SLOTS + JUMP */ - slot_cnt = mincfg->slot_cnt + 1; - if ( mincfg->timeslot ) { - /* time management requires 1 extra slot */ - slot_cnt++; - } - - return slot_cnt * GR1553BC_BD_SIZE; -} - -int gr1553bc_list_table_size(struct gr1553bc_list *list) -{ - struct gr1553bc_major *major; - int i, j, minor_cnt, size; - - size = 0; - for (i=0; imajor_cnt; i++) { - major = list->majors[i]; - minor_cnt = major->cfg->minor_cnt; - for (j=0; jminors[j]); - } - } - - return size; -} - -int gr1553bc_list_table_alloc - ( - struct gr1553bc_list *list, - void *bdtab_custom - ) -{ - struct gr1553bc_major *major; - int i, j, minor_cnt, size; - unsigned int table; - struct gr1553bc_priv *bcpriv = list->bc; - - /* Free previous allocated descriptor table */ - gr1553bc_list_table_free(list); - - /* Remember user's settings for uninitialization */ - list->_table_custom = bdtab_custom; - - /* Get Size required for descriptors */ - size = gr1553bc_list_table_size(list); - - if ((unsigned int)bdtab_custom & 0x1) { - /* Address given in Hardware accessible address, we - * convert it into CPU-accessible address. - */ - list->table_hw = (unsigned int)bdtab_custom & ~0x1; - list->_table = bdtab_custom; - drvmgr_translate_check( - *bcpriv->pdev, - DMAMEM_TO_CPU, - (void *)list->table_hw, - (void **)&list->table_cpu, - size); - } else { - if (bdtab_custom == NULL) { - /* Allocate descriptors */ - list->_table = malloc(size + (GR1553BC_BD_ALIGN-1)); - if ( list->_table == NULL ) - return -1; - } else { - /* Custom address, given in CPU-accessible address */ - list->_table = bdtab_custom; - } - /* 128-bit Alignment required by HW */ - list->table_cpu = - (((unsigned int)list->_table + (GR1553BC_BD_ALIGN-1)) & - ~(GR1553BC_BD_ALIGN-1)); - - /* We got CPU accessible descriptor table address, now we - * translate that into an address that the Hardware can - * understand - */ - if (bcpriv) { - drvmgr_translate_check( - *bcpriv->pdev, - CPUMEM_TO_DMA, - (void *)list->table_cpu, - (void **)&list->table_hw, - size - ); - } else { - list->table_hw = list->table_cpu; - } - } - - /* Write End-Of-List all over the descriptor table here, - * For debugging/safety? - */ - - /* Assign descriptors to all minor frames. The addresses is - * CPU-accessible addresses. - */ - table = list->table_cpu; - for (i=0; imajor_cnt; i++) { - major = list->majors[i]; - minor_cnt = major->cfg->minor_cnt; - for (j=0; jminors[j]->bds = (union gr1553bc_bd *)table; - - /* Calc size required by descriptors */ - table += gr1553bc_minor_table_size(major->minors[j]); - } - } - - return 0; -} - -void gr1553bc_list_table_free(struct gr1553bc_list *list) -{ - if ( (list->_table_custom == NULL) && list->_table ) { - free(list->_table); - } - list->_table = NULL; - list->_table_custom = NULL; - list->table_cpu = 0; - list->table_hw = 0; -} - -/* Init descriptor table provided by each minor frame, - * we link them together using unconditional JUMP. - */ -int gr1553bc_list_table_build(struct gr1553bc_list *list) -{ - struct gr1553bc_major *major; - struct gr1553bc_minor *minor; - struct gr1553bc_minor_cfg *mincfg; - int i, j, k, minor_cnt, marker; - union gr1553bc_bd *bds, *hwbd; - - marker = NEXT_MINOR_MARKER; - if ( list->async_list ) - marker |= NEXT_MINOR_MARKER_ASYNC; - - /* Create Major linking */ - for (i=0; imajor_cnt; i++) { - major = list->majors[i]; - minor_cnt = major->cfg->minor_cnt; - for (j=0; jminors[j]; - mincfg = minor->cfg; - bds = minor->bds; - - /* BD[0..SLOTCNT-1] = message slots - * BD[SLOTCNT+0] = END - * BD[SLOTCNT+1] = JUMP - * - * or if no optional time slot handling: - * - * BD[0..SLOTCNT-1] = message slots - * BD[SLOTCNT] = JUMP - */ - - /* BD[0..SLOTCNT-1] */ - for (k=0; kslot_cnt; k++) { - gr1553bc_bd_tr_init( - &bds[k].tr, - GR1553BC_TR_DUMMY_0, - GR1553BC_TR_DUMMY_1, - 0, - 0); - } - - /* BD[SLOTCNT] (OPTIONAL) - * If a minor frame is configured to be executed in - * certain time (given a time slot), this descriptor - * sums up all unused time. The time slot is - * decremented when messages are inserted into the - * minor frame and increased when messages are removed. - */ - if ( mincfg->timeslot > 0 ) { - gr1553bc_bd_tr_init( - &bds[k].tr, - GR1553BC_TR_DUMMY_0 | (mincfg->timeslot >> 2), - GR1553BC_TR_DUMMY_1, - 0, - 0); - k++; - } - - /* Last descriptor is a jump to next minor frame, to a - * synchronization point. If chain ends here, the list - * is marked with a "end-of-list" marker. - * - */ - if ( minor->next ) { - /* Translate CPU address of BD into HW address */ - hwbd = gr1553bc_bd_cpu2hw( - list, - &minor->next->bds[0] - ); - gr1553bc_bd_init( - &bds[k], - 0xf, - GR1553BC_UNCOND_JMP, - (uint32_t)hwbd, - ((GR1553BC_ID(i,j,k) << 8) | marker), - 0 - ); - } else { - gr1553bc_bd_init( - &bds[k], - 0xf, - GR1553BC_TR_EOL, - 0, - ((GR1553BC_ID(i,j,k) << 8) | marker), - 0); - } - } - } - - return 0; -} - -void gr1553bc_bd_init( - union gr1553bc_bd *bd, - unsigned int flags, - uint32_t word0, - uint32_t word1, - uint32_t word2, - uint32_t word3 - ) -{ - struct gr1553bc_bd_raw *raw = &bd->raw; - - if ( flags & 0x1 ) { - if ( (flags & KEEP_TIMESLOT) && - ((word0 & GR1553BC_BD_TYPE) == 0) ) { - /* Don't touch timeslot previously allocated */ - word0 &= ~GR1553BC_TR_TIME; - word0 |= GR1553BC_READ_MEM(&raw->words[0]) & - GR1553BC_TR_TIME; - } - GR1553BC_WRITE_MEM(&raw->words[0], word0); - } - if ( flags & 0x2 ) - GR1553BC_WRITE_MEM(&raw->words[1], word1); - if ( flags & 0x4 ) - GR1553BC_WRITE_MEM(&raw->words[2], word2); - if ( flags & 0x8 ) - GR1553BC_WRITE_MEM(&raw->words[3], word3); -} - -/* Alloc a Major frame according to the configuration structure */ -int gr1553bc_major_alloc_skel - ( - struct gr1553bc_major **major, - struct gr1553bc_major_cfg *cfg - ) -{ - struct gr1553bc_major *maj; - struct gr1553bc_minor *minor; - int size, i; - - if ( (cfg == NULL) || (major == NULL) || (cfg->minor_cnt <= 0) ) - return -1; - - /* Allocate Major Frame description, but no descriptors */ - size = sizeof(struct gr1553bc_major) + cfg->minor_cnt * - (sizeof(struct gr1553bc_minor) + sizeof(void *)); - maj = (struct gr1553bc_major *)malloc(size); - if ( maj == NULL ) - return -1; - - maj->cfg = cfg; - maj->next = NULL; - - /* Create links between minor frames, and from minor frames - * to configuration structure. - */ - minor = (struct gr1553bc_minor *)&maj->minors[cfg->minor_cnt]; - for (i=0; iminor_cnt; i++, minor++) { - maj->minors[i] = minor; - minor->next = minor + 1; - minor->cfg = &cfg->minor_cfgs[i]; - minor->alloc = 0; - minor->bds = NULL; - } - /* last Minor should point to next Major frame's first minor, - * we do that somewhere else. - */ - (minor - 1)->next = NULL; - - *major = maj; - - return 0; -} - -struct gr1553bc_major *gr1553bc_major_from_id - ( - struct gr1553bc_list *list, - int mid - ) -{ - int major_no; - - /* Find Minor Frame from MID */ - major_no = GR1553BC_MAJID_FROM_ID(mid); - - if ( major_no >= list->major_cnt ) - return NULL; - return list->majors[major_no]; -} - -struct gr1553bc_minor *gr1553bc_minor_from_id - ( - struct gr1553bc_list *list, - int mid - ) -{ - int minor_no; - struct gr1553bc_major *major; - - /* Get Major from ID */ - major = gr1553bc_major_from_id(list, mid); - if ( major == NULL ) - return NULL; - - /* Find Minor Frame from MID */ - minor_no = GR1553BC_MINID_FROM_ID(mid); - - if ( minor_no >= major->cfg->minor_cnt ) - return NULL; - return major->minors[minor_no]; -} - -union gr1553bc_bd *gr1553bc_slot_bd - ( - struct gr1553bc_list *list, - int mid - ) -{ - struct gr1553bc_minor *minor; - int slot_no; - - /*** look up BD ***/ - - /* Get minor */ - minor = gr1553bc_minor_from_id(list, mid); - if ( minor == NULL ) - return NULL; - - /* Get Slot */ - slot_no = GR1553BC_SLOTID_FROM_ID(mid); - if ( slot_no >= 0xff ) - slot_no = 0; - - /* Get BD address */ - return &minor->bds[slot_no]; -} - -static int gr1553bc_minor_first_avail(struct gr1553bc_minor *minor) -{ - int slot_num; - uint32_t alloc; - - alloc = minor->alloc; - if ( alloc == 0xffffffff ) { - /* No free */ - return -1; - } - slot_num = 0; - while ( alloc & 1 ) { - alloc = alloc >> 1; - slot_num++; - } - if ( slot_num >= minor->cfg->slot_cnt ) { - /* no free */ - return -1; - } - return slot_num; -} - -int gr1553bc_slot_alloc( - struct gr1553bc_list *list, - int *mid, - int timeslot, - union gr1553bc_bd **bd - ) -{ - struct gr1553bc_minor *minor = gr1553bc_minor_from_id(list, *mid); - - return gr1553bc_slot_alloc2(minor, mid, timeslot, bd); -} - -/* Same as gr1553bc_slot_alloc but identifies a minor instead of list. - * The major/minor part of MID is ignored. - */ -int gr1553bc_slot_alloc2( - struct gr1553bc_minor *minor, - int *mid, - int timeslot, - union gr1553bc_bd **bd - ) -{ - int slot_no; - uint32_t set0; - int timefree; - struct gr1553bc_bd_tr *trbd; - struct gr1553bc_minor_cfg *mincfg; - - if ( minor == NULL ) - return -1; - - mincfg = minor->cfg; - - /* Find first free slot if not a certain slot is requested */ - slot_no = GR1553BC_SLOTID_FROM_ID(*mid); - if ( slot_no == 0xff ) { - slot_no = gr1553bc_minor_first_avail(minor); - if ( slot_no < 0 ) - return -1; - } else { - /* Allocate a certain slot, check that it is free */ - if ( slot_no >= mincfg->slot_cnt ) - return -1; - if ( (1<alloc ) - return -1; - } - - /* Ok, we got our slot. Lets allocate time for slot if requested by user - * and time management is enabled for this Minor Frame. - */ - if ( timeslot > 0 ) { - /* Make timeslot on a 4us boundary (time resolution of core) */ - timeslot = (timeslot + 0x3) >> 2; - - if ( mincfg->timeslot ) { - /* Subtract requested time from free time */ - trbd = &minor->bds[mincfg->slot_cnt].tr; - set0 = GR1553BC_READ_MEM(&trbd->settings[0]); - timefree = set0 & GR1553BC_TR_TIME; - if ( timefree < timeslot ) { - /* Not enough time left to schedule slot in minor */ - return -1; - } - /* Store back the time left */ - timefree -= timeslot; - set0 = (set0 & ~GR1553BC_TR_TIME) | timefree; - GR1553BC_WRITE_MEM(&trbd->settings[0], set0); - /* Note: at the moment the minor frame can be executed faster - * than expected, we hurry up writing requested - * descriptor. - */ - } - } - - /* Make the allocated descriptor be an empty slot with the - * timeslot requested. - */ - trbd = &minor->bds[slot_no].tr; - gr1553bc_bd_tr_init( - trbd, - GR1553BC_TR_DUMMY_0 | timeslot, - GR1553BC_TR_DUMMY_1, - 0, - 0); - - /* Allocate slot */ - minor->alloc |= 1<alloc & (1<bds[slot_no]; - - /* If the driver handles time for this minor frame, return - * time if previuosly requested. - */ - timeslot = 0; - mincfg = minor->cfg; - if ( mincfg->timeslot > 0 ) { - /* Find out if message slot had time allocated */ - word0 = GR1553BC_READ_MEM(&bd->raw.words[0]); - if ( word0 & GR1553BC_BD_TYPE ) { - /* Condition ==> no time slot allocated */ - } else { - /* Transfer descriptor, may have time slot */ - timeslot = word0 & GR1553BC_TR_TIME; - if ( timeslot > 0 ) { - /* Return previously allocated time to END - * TIME descriptor. - */ - endbd = &minor->bds[mincfg->slot_cnt].tr; - set0 = GR1553BC_READ_MEM(&endbd->settings[0]); - timefree = set0 & GR1553BC_TR_TIME; - timefree += timeslot; - set0 = (set0 & ~GR1553BC_TR_TIME) | timefree; - GR1553BC_WRITE_MEM(&endbd->settings[0], set0); - /* Note: at the moment the minor frame can be - * executed slower than expected, the - * timeslot is at two locations. - */ - } - } - } - - /* Make slot an empty message */ - gr1553bc_bd_tr_init( - &bd->tr, - GR1553BC_TR_DUMMY_0, - GR1553BC_TR_DUMMY_1, - 0, - 0); - - /* unallocate descriptor */ - minor->alloc &= ~(1<cfg; - if ( mincfg->timeslot > 0 ) { - /* Return previously allocated time to END - * TIME descriptor. - */ - endbd = &minor->bds[mincfg->slot_cnt].tr; - set0 = GR1553BC_READ_MEM(&endbd->settings[0]); - timefree = (set0 & GR1553BC_TR_TIME) << 2; - } - - /* Return time freed */ - return timefree; -} - -int gr1553bc_slot_raw - ( - struct gr1553bc_list *list, - int mid, - unsigned int flags, - uint32_t word0, - uint32_t word1, - uint32_t word2, - uint32_t word3 - ) -{ - struct gr1553bc_minor *minor; - union gr1553bc_bd *bd; - int slot_no; - - minor = gr1553bc_minor_from_id(list, mid); - if ( minor == NULL ) - return -1; - - /* Get Slot */ - slot_no = GR1553BC_SLOTID_FROM_ID(mid); - if ( slot_no >= minor->cfg->slot_cnt ) { - return -1; - } - - /* Get descriptor */ - bd = &minor->bds[slot_no]; - - /* Build empty descriptor. */ - gr1553bc_bd_init( - bd, - flags, - word0, - word1, - word2, - word3); - - return 0; -} - -/* Create unconditional IRQ customly defined location - * The IRQ is disabled, enable it with gr1553bc_slot_irq_enable(). - */ -int gr1553bc_slot_irq_prepare - ( - struct gr1553bc_list *list, - int mid, - bcirq_func_t func, - void *data - ) -{ - union gr1553bc_bd *bd; - int slot_no, to_mid; - - /* Build unconditional IRQ descriptor. The padding is used - * for identifying the MINOR frame and function and custom data. - * - * The IRQ is disabled at first, a unconditional jump to next - * descriptor in table. - */ - - /* Get BD address of jump destination */ - slot_no = GR1553BC_SLOTID_FROM_ID(mid); - to_mid = GR1553BC_ID_SET_SLOT(mid, slot_no + 1); - bd = gr1553bc_slot_bd(list, to_mid); - if ( bd == NULL ) - return -1; - bd = gr1553bc_bd_cpu2hw(list, bd); - - return gr1553bc_slot_raw( - list, - mid, - 0xF, - GR1553BC_UNCOND_JMP, - (uint32_t)bd, - (uint32_t)func, - (uint32_t)data - ); -} - -/* Enable previously prepared unconditional IRQ */ -int gr1553bc_slot_irq_enable(struct gr1553bc_list *list, int mid) -{ - /* Leave word1..3 untouched: - * 1. Unconditional Jump address - * 2. Function - * 3. Custom Data - * - * Since only one bit is changed in word0 (Condition word), - * no hardware/software races will exist ==> it is safe - * to enable/disable IRQ at any time independent of where - * hardware is in table. - */ - return gr1553bc_slot_raw( - list, - mid, - 0x1, /* change only WORD0 */ - GR1553BC_UNCOND_IRQ, - 0, - 0, - 0); -} - -/* Disable unconditional IRQ point, changed to unconditional JUMP - * to descriptor following. - * After disabling it it can be enabled again, or freed. - */ -int gr1553bc_slot_irq_disable(struct gr1553bc_list *list, int mid) -{ - return gr1553bc_slot_raw( - list, - mid, - 0x1, /* change only WORD0, JUMP address already set */ - GR1553BC_UNCOND_JMP, - 0, - 0, - 0); -} - -int gr1553bc_slot_empty(struct gr1553bc_list *list, int mid) -{ - return gr1553bc_slot_raw( - list, - mid, - 0xF | KEEP_TIMESLOT, - GR1553BC_TR_DUMMY_0, - GR1553BC_TR_DUMMY_1, - 0, - 0); -} - -int gr1553bc_slot_exttrig(struct gr1553bc_list *list, int mid) -{ - return gr1553bc_slot_raw( - list, - mid, - 0xF | KEEP_TIMESLOT, - GR1553BC_TR_DUMMY_0 | GR1553BC_TR_EXTTRIG, - GR1553BC_TR_DUMMY_1, - 0, - 0); -} - -int gr1553bc_slot_jump - ( - struct gr1553bc_list *list, - int mid, - uint32_t condition, - int to_mid - ) -{ - union gr1553bc_bd *bd; - - /* Get BD address */ - bd = gr1553bc_slot_bd(list, to_mid); - if ( bd == NULL ) - return -1; - /* Convert into an address that the HW understand */ - bd = gr1553bc_bd_cpu2hw(list, bd); - - return gr1553bc_slot_raw( - list, - mid, - 0xF, - condition, - (uint32_t)bd, - 0, - 0); -} - -int gr1553bc_slot_transfer( - struct gr1553bc_list *list, - int mid, - int options, - int tt, - uint16_t *dptr) -{ - uint32_t set0, set1; - union gr1553bc_bd *bd; - int rx_rtadr, tx_rtadr, timeout; - - /* Get BD address */ - bd = gr1553bc_slot_bd(list, mid); - if ( bd == NULL ) - return -1; - - /* Translate Data pointer from CPU-local to 1553-core accessible - * address if user wants that. This may be useful for AMBA-over-PCI - * cores. - */ - if ( (unsigned int)dptr & 0x1 ) { - struct gr1553bc_priv *bcpriv = list->bc; - - drvmgr_translate( - *bcpriv->pdev, - CPUMEM_TO_DMA, - (void *)((unsigned int)dptr & ~0x1), - (void **)&dptr); - } - - /* It is assumed that the descriptor has already been initialized - * as a empty slot (Dummy bit set), so to avoid races the dummy - * bit is cleared last. - * - * If we knew that the write would do a burst (for example over SpW) - * it would be safe to write in order. - */ - - /* Preserve timeslot */ - set0 = GR1553BC_READ_MEM(&bd->tr.settings[0]); - set0 &= GR1553BC_TR_TIME; - set0 |= options & 0x61f00000; - set0 |= list->tropts; /* Global options */ - - /* Set transfer type, bus and let RT tolerance table descide - * responce tolerance. - * - * If a destination address is specified the longest timeout - * tolerance is taken. - */ - rx_rtadr = (tt >> 22) & 0x1f; - tx_rtadr = (tt >> 12) & 0x1f; - if ( (tx_rtadr != 0x1f) && - (list->rt_timeout[rx_rtadr] < list->rt_timeout[tx_rtadr]) ) { - timeout = list->rt_timeout[tx_rtadr]; - } else { - timeout = list->rt_timeout[rx_rtadr]; - } - set1 = ((timeout & 0xf) << 27) | (tt & 0x27ffffff) | ((options & 0x3)<<30); - - GR1553BC_WRITE_MEM(&bd->tr.settings[0], set0); - GR1553BC_WRITE_MEM(&bd->tr.dptr, (uint32_t)dptr); - /* Write UNUSED BIT, when cleared it Indicates that BC has written it */ - GR1553BC_WRITE_MEM(&bd->tr.status, 0x80000000); - GR1553BC_WRITE_MEM(&bd->tr.settings[1], set1); - - return 0; -} - -int gr1553bc_slot_update - ( - struct gr1553bc_list *list, - int mid, - uint16_t *dptr, - unsigned int *stat - ) -{ - union gr1553bc_bd *bd; - unsigned int status; - unsigned int dataptr = (unsigned int)dptr; - - /* Get BD address */ - bd = gr1553bc_slot_bd(list, mid); - if ( bd == NULL ) - return -1; - - /* Write new Data Pointer if needed */ - if ( dataptr ) { - struct gr1553bc_priv *bcpriv = list->bc; - - /* Translate Data pointer from CPU-local to 1553-core accessible - * address if user wants that. This may be useful for AMBA-over-PCI - * cores. - */ - if ( dataptr & 0x1 ) { - drvmgr_translate( - *bcpriv->pdev, - CPUMEM_TO_DMA, - (void *)(dataptr & ~0x1), - (void **)&dptr - ); - } - - /* Update Data Pointer */ - GR1553BC_WRITE_MEM(&bd->tr.dptr, dataptr); - } - - /* Get status of transfer descriptor */ - if ( stat ) { - status = *stat; - *stat = GR1553BC_READ_MEM(&bd->tr.status); - if ( status ) { - /* Clear status fields user selects, then - * or bit31 if user wants that. The bit31 - * may be used to indicate if the BC has - * performed the access. - */ - status = (*stat & (status & 0xffffff)) | - (status & (1<<31)); - GR1553BC_WRITE_MEM(&bd->tr.status, status); - } - } - - return 0; -} - -int gr1553bc_slot_dummy( - struct gr1553bc_list *list, - int mid, - unsigned int *dummy) -{ - union gr1553bc_bd *bd; - unsigned int set1, new_set1; - - /* Get BD address */ - bd = gr1553bc_slot_bd(list, mid); - if ( bd == NULL ) - return -1; - /* Update the Dummy Bit */ - set1 = GR1553BC_READ_MEM(&bd->tr.settings[1]); - new_set1 = (set1 & ~GR1553BC_TR_DUMMY_1) | (*dummy & GR1553BC_TR_DUMMY_1); - GR1553BC_WRITE_MEM(&bd->tr.settings[1], new_set1); - - *dummy = set1; - - return 0; -} - -/* Find MID from Descriptor pointer */ -int gr1553bc_mid_from_bd( - union gr1553bc_bd *bd, - int *mid, - int *async - ) -{ - int i, bdmid, slot_no; - uint32_t word0, word2; - - /* Find Jump to next Minor Frame or End-Of-List, - * at those locations we have stored a MID - * - * GR1553BC_SLOT_MAX+2 = Worst case, BD is max distance from jump - * descriptor. 2=END and Jump descriptors. - */ - for (i=0; iraw.words[0]); - if ( word0 & GR1553BC_BD_TYPE ) { - if ( word0 == GR1553BC_UNCOND_JMP ) { - /* May be a unconditional IRQ set by user. In - * that case the function is stored in WORD3, - * functions must be aligned to 4 byte boudary. - */ - word2 = GR1553BC_READ_MEM(&bd->raw.words[2]); - if ( word2 & NEXT_MINOR_MARKER ) { - goto found_mid; - } - } else if ( word0 == GR1553BC_TR_EOL ) { - /* End-Of-List, does contain a MID */ - word2 = GR1553BC_READ_MEM(&bd->raw.words[2]); - goto found_mid; - } - } - bd++; - } - - return -1; - -found_mid: - /* Get MID of JUMP descriptor */ - bdmid = word2 >> 8; - /* Subtract distance from JUMP descriptor to find MID - * of requested BD. - */ - slot_no = GR1553BC_SLOTID_FROM_ID(bdmid); - slot_no -= i; - bdmid = GR1553BC_ID_SET_SLOT(bdmid, slot_no); - - if ( mid ) - *mid = bdmid; - - /* Determine which list BD belongs to: async or sync */ - if ( async ) - *async = word2 & NEXT_MINOR_MARKER_ASYNC; - - return 0; -} - -/*************** END OF LIST HANDLING ROUTINES ***************/ - -/*************** DEVICE HANDLING ROUTINES ***************/ - -void gr1553bc_device_init(struct gr1553bc_priv *priv); -void gr1553bc_device_uninit(struct gr1553bc_priv *priv); -void gr1553bc_isr(void *data); - -/*** GR1553BC driver ***/ - -void gr1553bc_register(void) -{ - /* The BC driver rely on the GR1553B Driver */ - gr1553_register(); -} - -static void gr1553bc_isr_std(union gr1553bc_bd *bd, void *data) -{ - /* Do nothing */ -} - -/* Take a GR1553BC hardware device identified by minor. - * A pointer is returned that is used internally by the GR1553BC - * driver, it is used as an input paramter 'bc' to all other - * functions that manipulate the hardware. - */ -void *gr1553bc_open(int minor) -{ - struct drvmgr_dev **pdev = NULL; - struct gr1553bc_priv *priv = NULL; - struct amba_dev_info *ambadev; - struct ambapp_core *pnpinfo; - void *irq_log_p = NULL; - - /* Allocate requested device */ - pdev = gr1553_bc_open(minor); - if ( pdev == NULL ) - goto fail; - - irq_log_p = malloc(GR1553BC_IRQLOG_SIZE*2); - if ( irq_log_p == NULL ) - goto fail; - - priv = malloc(sizeof(struct gr1553bc_priv)); - if ( priv == NULL ) - goto fail; - memset(priv, 0, sizeof(struct gr1553bc_priv)); - - /* Init BC device */ - priv->pdev = pdev; - (*pdev)->priv = priv; - priv->irq_log_p = irq_log_p; - priv->started = 0; - - /* Get device information from AMBA PnP information */ - ambadev = (struct amba_dev_info *)(*pdev)->businfo; - pnpinfo = &ambadev->info; - priv->regs = (struct gr1553b_regs *)pnpinfo->apb_slv->start; - - SPIN_INIT(&priv->devlock, "gr1553bc"); - - gr1553bc_device_init(priv); - - /* Register ISR handler (unmask at IRQ controller) */ - if ( drvmgr_interrupt_register(*priv->pdev, 0, "gr1553bc", - gr1553bc_isr, priv) ) { - goto fail; - } - - return priv; - -fail: - if ( pdev ) - gr1553_bc_close(pdev); - if ( irq_log_p ) - free(irq_log_p); - if ( priv ) - free(priv); - return NULL; -} - -void gr1553bc_close(void *bc) -{ - struct gr1553bc_priv *priv = bc; - - /* Stop Hardware */ - gr1553bc_stop(bc, 0x3); - - gr1553bc_device_uninit(priv); - - /* Remove interrupt handler (mask IRQ at IRQ controller) */ - drvmgr_interrupt_unregister(*priv->pdev, 0, gr1553bc_isr, priv); - - /* Free device */ - gr1553_bc_close(priv->pdev); - SPIN_FREE(&priv->devlock); - free(priv->irq_log_p); - free(priv); -} - -/* Return Current Minor frame number */ -int gr1553bc_indication(void *bc, int async, int *mid) -{ - struct gr1553bc_priv *priv = bc; - union gr1553bc_bd *bd; - - /* Get current descriptor pointer */ - if ( async ) { - bd = (union gr1553bc_bd *) - GR1553BC_READ_REG(&priv->regs->bc_aslot); - bd = gr1553bc_bd_hw2cpu(priv->alist, bd); - } else { - bd = (union gr1553bc_bd *) - GR1553BC_READ_REG(&priv->regs->bc_slot); - bd = gr1553bc_bd_hw2cpu(priv->list, bd); - } - - return gr1553bc_mid_from_bd(bd, mid, NULL); -} - -/* Start major frame processing, wait for TimerManager tick or start directly */ -int gr1553bc_start(void *bc, struct gr1553bc_list *list, struct gr1553bc_list *list_async) -{ - struct gr1553bc_priv *priv = bc; - union gr1553bc_bd *bd = NULL, *bd_async = NULL; - uint32_t ctrl, irqmask; - SPIN_IRQFLAGS(irqflags); - - if ( (list == NULL) && (list_async == NULL) ) - return 0; - - /* Find first descriptor in list, the descriptor - * first to be executed. - */ - ctrl = GR1553BC_KEY; - if ( list ) { - bd = gr1553bc_slot_bd(list, GR1553BC_ID(0,0,0)); - if ( bd == NULL ) - return -1; - bd = gr1553bc_bd_cpu2hw(list, bd); - ctrl |= GR1553B_BC_ACT_SCSRT; - } - if ( list_async ) { - bd_async = gr1553bc_slot_bd(list_async, GR1553BC_ID(0,0,0)); - if ( bd_async == NULL ) - return -1; - bd_async = gr1553bc_bd_cpu2hw(list_async, bd_async); - ctrl |= GR1553B_BC_ACT_ASSRT; - } - - /* Do "hot-swapping" of lists */ - SPIN_LOCK_IRQ(&priv->devlock, irqflags); - - if ( list ) { - priv->list = list; - GR1553BC_WRITE_REG(&priv->regs->bc_bd, (uint32_t)bd); - } - if ( list_async ) { - priv->alist = list_async; - GR1553BC_WRITE_REG(&priv->regs->bc_abd, (uint32_t)bd_async); - } - - /* If not enabled before, we enable it now. */ - GR1553BC_WRITE_REG(&priv->regs->bc_ctrl, ctrl); - - /* Enable IRQ */ - if ( priv->started == 0 ) { - priv->started = 1; - irqmask = GR1553BC_READ_REG(&priv->regs->imask); - irqmask |= GR1553B_IRQEN_BCEVE|GR1553B_IRQEN_BCDE|GR1553B_IRQEN_BCWKE; - GR1553BC_WRITE_REG(&priv->regs->imask, irqmask); - } - - SPIN_UNLOCK_IRQ(&priv->devlock, irqflags); - - return 0; -} - -/* Pause GR1553 BC transfers */ -int gr1553bc_pause(void *bc) -{ - struct gr1553bc_priv *priv = bc; - uint32_t ctrl; - SPIN_IRQFLAGS(irqflags); - - /* Do "hot-swapping" of lists */ - SPIN_LOCK_IRQ(&priv->devlock, irqflags); - ctrl = GR1553BC_KEY | GR1553B_BC_ACT_SCSUS; - GR1553BC_WRITE_REG(&priv->regs->bc_ctrl, ctrl); - SPIN_UNLOCK_IRQ(&priv->devlock, irqflags); - - return 0; -} - -/* Restart GR1553 BC transfers, after being paused */ -int gr1553bc_restart(void *bc) -{ - struct gr1553bc_priv *priv = bc; - uint32_t ctrl; - SPIN_IRQFLAGS(irqflags); - - SPIN_LOCK_IRQ(&priv->devlock, irqflags); - ctrl = GR1553BC_KEY | GR1553B_BC_ACT_SCSRT; - GR1553BC_WRITE_REG(&priv->regs->bc_ctrl, ctrl); - SPIN_UNLOCK_IRQ(&priv->devlock, irqflags); - - return 0; -} - -/* Stop BC transmission */ -int gr1553bc_stop(void *bc, int options) -{ - struct gr1553bc_priv *priv = bc; - uint32_t ctrl; - SPIN_IRQFLAGS(irqflags); - - ctrl = GR1553BC_KEY; - if ( options & 0x1 ) - ctrl |= GR1553B_BC_ACT_SCSTP; - if ( options & 0x2 ) - ctrl |= GR1553B_BC_ACT_ASSTP; - - SPIN_LOCK_IRQ(&priv->devlock, irqflags); - GR1553BC_WRITE_REG(&priv->regs->bc_ctrl, ctrl); - priv->started = 0; - SPIN_UNLOCK_IRQ(&priv->devlock, irqflags); - - return 0; -} - -/* Reset software and BC hardware into a known "unused/init" state */ -void gr1553bc_device_init(struct gr1553bc_priv *priv) -{ -/* RESET HARDWARE REGISTERS */ - /* Stop BC if not already stopped */ - GR1553BC_WRITE_REG(&priv->regs->bc_ctrl, GR1553BC_KEY | 0x0204); - - /* Since RT can not be used at the same time as BC, we stop - * RT rx, it should already be stopped... - */ - GR1553BC_WRITE_REG(&priv->regs->rt_cfg, GR1553RT_KEY); - - /* Clear some registers */ - GR1553BC_WRITE_REG(&priv->regs->bc_bd, 0); - GR1553BC_WRITE_REG(&priv->regs->bc_abd, 0); - GR1553BC_WRITE_REG(&priv->regs->bc_timer, 0); - GR1553BC_WRITE_REG(&priv->regs->bc_wake, 0); - GR1553BC_WRITE_REG(&priv->regs->bc_irqptr, 0); - GR1553BC_WRITE_REG(&priv->regs->bc_busmsk, 0); - -/* PUT SOFTWARE INTO INITIAL STATE */ - priv->list = NULL; - priv->alist = NULL; - - priv->irq_log_base = (uint32_t *) - (((uint32_t)priv->irq_log_p + (GR1553BC_IRQLOG_SIZE-1)) & - ~(GR1553BC_IRQLOG_SIZE-1)); - /* Translate into a hardware accessible address */ - drvmgr_translate_check( - *priv->pdev, - CPUMEM_TO_DMA, - (void *)priv->irq_log_base, - (void **)&priv->irq_log_base_hw, - GR1553BC_IRQLOG_SIZE); - priv->irq_log_curr = priv->irq_log_base; - priv->irq_log_end = &priv->irq_log_base[GR1553BC_IRQLOG_CNT-1]; - priv->irq_func = gr1553bc_isr_std; - priv->irq_data = NULL; - - GR1553BC_WRITE_REG(&priv->regs->bc_irqptr,(uint32_t)priv->irq_log_base_hw); -} - -void gr1553bc_device_uninit(struct gr1553bc_priv *priv) -{ - uint32_t irqmask; - - /* Stop BC if not already stopped */ - GR1553BC_WRITE_REG(&priv->regs->bc_ctrl, GR1553BC_KEY | 0x0204); - - /* Since RT can not be used at the same time as BC, we stop - * RT rx, it should already be stopped... - */ - GR1553BC_WRITE_REG(&priv->regs->rt_cfg, GR1553RT_KEY); - - /* Turn off IRQ generation */ - irqmask=GR1553BC_READ_REG(&priv->regs->imask); - irqmask&=~(GR1553B_IRQEN_BCEVE|GR1553B_IRQEN_BCDE|GR1553B_IRQEN_BCWKE); - GR1553BC_WRITE_REG(&priv->regs->irq, irqmask); -} - -/* Interrupt handler */ -void gr1553bc_isr(void *arg) -{ - struct gr1553bc_priv *priv = arg; - uint32_t *curr, *pos, word0, word2; - union gr1553bc_bd *bd; - bcirq_func_t func; - void *data; - int handled, irq; - SPIN_ISR_IRQFLAGS(irqflags); - - /* Did core make IRQ */ - irq = GR1553BC_READ_REG(&priv->regs->irq); - irq &= (GR1553B_IRQEN_BCEVE|GR1553B_IRQEN_BCDE|GR1553B_IRQEN_BCWKE); - if ( irq == 0 ) - return; /* Shared IRQ: some one else may have caused the IRQ */ - - /* Clear handled IRQs */ - GR1553BC_WRITE_REG(&priv->regs->irq, irq); - - /* DMA error. This IRQ does not affect the IRQ log. - * We let standard IRQ handle handle it. - */ - if ( irq & GR1553B_IRQEN_BCDE ) { - priv->irq_func(NULL, priv->irq_data); - } - - /* Get current posistion in hardware */ - pos = (uint32_t *)GR1553BC_READ_REG(&priv->regs->bc_irqptr); - /* Converting into CPU address */ - pos = priv->irq_log_base + - ((unsigned int)pos - (unsigned int)priv->irq_log_base_hw)/4; - - /* Step in IRQ log until we reach the end. */ - handled = 0; - curr = priv->irq_log_curr; - while ( curr != pos ) { - bd = (union gr1553bc_bd *)(GR1553BC_READ_MEM(curr) & ~1); - GR1553BC_WRITE_MEM(curr, 0x2); /* Mark Handled */ - - /* Convert Descriptor in IRQ log into CPU address. In order - * to convert we must know which list the descriptor belongs - * to, we compare the address of the bd to the ASYNC list - * descriptor table area. - */ - SPIN_LOCK(&priv->devlock, irqflags); - if ( priv->alist && ((unsigned int)bd>=priv->alist->table_hw) && - ((unsigned int)bd < - (priv->alist->table_hw + priv->alist->table_size))) { - /* BD in async list */ - bd = gr1553bc_bd_hw2cpu(priv->alist, bd); - } else if (priv->list && - ((unsigned int)bd >= priv->list->table_hw) && - ((unsigned int)bd < - (priv->list->table_hw + priv->list->table_size))) { - /* BD in sync list */ - bd = gr1553bc_bd_hw2cpu(priv->list, bd); - } else { - /* error - unknown BD. Should not happen but could - * if user has switched list. Ignore IRQ entry and - * continue to next entry. - */ - bd = NULL; - } - - /* Handle Descriptor that cased IRQ - * - * If someone have inserted an IRQ descriptor and tied - * that to a custom function we call that function, otherwise - * we let the standard IRQ handle handle it. - */ - if ( bd ) { - word0 = GR1553BC_READ_MEM(&bd->raw.words[0]); - word2 = GR1553BC_READ_MEM(&bd->raw.words[2]); - SPIN_UNLOCK(&priv->devlock, irqflags); - if ( word0 == GR1553BC_UNCOND_IRQ ) { - if ( (word2 & 0x3) == 0 ) { - func = (bcirq_func_t)(word2 & ~0x3); - data = (void *) - GR1553BC_READ_MEM(&bd->raw.words[3]); - func(bd, data); - handled = 1; - } - } - - if ( handled == 0 ) { - /* Let standard IRQ handle handle it */ - priv->irq_func(bd, priv->irq_data); - } else { - handled = 0; - } - } else { - SPIN_UNLOCK(&priv->devlock, irqflags); - } - - /* Increment to next entry in IRQ LOG */ - if ( curr == priv->irq_log_end ) - curr = priv->irq_log_base; - else - curr++; - } - priv->irq_log_curr = curr; -} - -int gr1553bc_irq_setup - ( - void *bc, - bcirq_func_t func, - void *data - ) -{ - struct gr1553bc_priv *priv = bc; - - if ( func == NULL ) - priv->irq_func = gr1553bc_isr_std; - else - priv->irq_func = func; - priv->irq_data = data; - - return 0; -} - -void gr1553bc_ext_trig(void *bc, int trig) -{ - struct gr1553bc_priv *priv = bc; - unsigned int trigger; - - if ( trig ) - trigger = GR1553B_BC_ACT_SETT; - else - trigger = GR1553B_BC_ACT_CLRT; - - GR1553BC_WRITE_REG(&priv->regs->bc_ctrl, GR1553BC_KEY | trigger); -} - -void gr1553bc_status(void *bc, struct gr1553bc_status *status) -{ - struct gr1553bc_priv *priv = bc; - - status->status = GR1553BC_READ_REG(&priv->regs->bc_stat); - status->time = GR1553BC_READ_REG(&priv->regs->bc_timer); -} - -/*** DEBUGGING HELP FUNCTIONS ***/ - -#include - -void gr1553bc_show_list(struct gr1553bc_list *list, int options) -{ - struct gr1553bc_major *major; - struct gr1553bc_minor *minor; - int i, j, minor_cnt, timefree; - - printf("LIST\n"); - printf(" major cnt: %d\n", list->major_cnt); - for (i=0; i<32; i++) { - printf(" RT[%d] timeout: %d\n", i, 14+(list->rt_timeout[i]*4)); - } - - for (i=0; imajor_cnt; i++) { - major = list->majors[i]; - minor_cnt = major->cfg->minor_cnt; - printf(" MAJOR[%d]\n", i); - printf(" minor count: %d\n", minor_cnt); - - for (j=0; jminors[j]; - - printf(" MINOR[%d]\n", j); - printf(" bd: 0x%08x (HW:0x%08x)\n", - (unsigned int)&minor->bds[0], - (unsigned int)gr1553bc_bd_cpu2hw(list, - &minor->bds[0])); - printf(" slot cnt: %d\n", minor->cfg->slot_cnt); - if ( minor->cfg->timeslot ) { - timefree = gr1553bc_minor_freetime(minor); - printf(" timefree: %d\n", timefree); - printf(" timetotal: %d\n", - minor->cfg->timeslot); - } else { - printf(" no time mgr\n"); - } - } - } -} diff --git a/c/src/lib/libbsp/sparc/shared/1553/gr1553bm.c b/c/src/lib/libbsp/sparc/shared/1553/gr1553bm.c deleted file mode 100644 index d63983bda9..0000000000 --- a/c/src/lib/libbsp/sparc/shared/1553/gr1553bm.c +++ /dev/null @@ -1,544 +0,0 @@ -/* GR1553B BM driver - * - * COPYRIGHT (c) 2010. - * Cobham Gaisler AB. - * - * 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 GR1553BM_WRITE_MEM(adr, val) *(volatile uint32_t *)(adr) = (uint32_t)(val) -#define GR1553BM_READ_MEM(adr) (*(volatile uint32_t *)(adr)) - -#define GR1553BM_WRITE_REG(adr, val) *(volatile uint32_t *)(adr) = (uint32_t)(val) -#define GR1553BM_READ_REG(adr) (*(volatile uint32_t *)(adr)) - -/* Use interrupt lock privmitives compatible with SMP defined in - * RTEMS 4.11.99 and higher. - */ -#if (((__RTEMS_MAJOR__ << 16) | (__RTEMS_MINOR__ << 8) | __RTEMS_REVISION__) >= 0x040b63) - -/* map via rtems_interrupt_lock_* API: */ -#define SPIN_DECLARE(lock) RTEMS_INTERRUPT_LOCK_MEMBER(lock) -#define SPIN_INIT(lock, name) rtems_interrupt_lock_initialize(lock, name) -#define SPIN_LOCK(lock, level) rtems_interrupt_lock_acquire_isr(lock, &level) -#define SPIN_LOCK_IRQ(lock, level) rtems_interrupt_lock_acquire(lock, &level) -#define SPIN_UNLOCK(lock, level) rtems_interrupt_lock_release_isr(lock, &level) -#define SPIN_UNLOCK_IRQ(lock, level) rtems_interrupt_lock_release(lock, &level) -#define SPIN_IRQFLAGS(k) rtems_interrupt_lock_context k -#define SPIN_ISR_IRQFLAGS(k) SPIN_IRQFLAGS(k) -#define SPIN_FREE(lock) rtems_interrupt_lock_destroy(lock) - -#else - -/* maintain single-core compatibility with older versions of RTEMS: */ -#define SPIN_DECLARE(name) -#define SPIN_INIT(lock, name) -#define SPIN_LOCK(lock, level) -#define SPIN_LOCK_IRQ(lock, level) rtems_interrupt_disable(level) -#define SPIN_UNLOCK(lock, level) -#define SPIN_UNLOCK_IRQ(lock, level) rtems_interrupt_enable(level) -#define SPIN_IRQFLAGS(k) rtems_interrupt_level k -#define SPIN_ISR_IRQFLAGS(k) -#define SPIN_FREE(lock) - -#ifdef RTEMS_SMP -#error SMP mode not compatible with these interrupt lock primitives -#endif - -#endif - -struct gr1553bm_priv { - struct drvmgr_dev **pdev; - struct gr1553b_regs *regs; - SPIN_DECLARE(devlock); - - void *buffer; - unsigned int buffer_base_hw; - unsigned int buffer_base; - unsigned int buffer_end; - unsigned int buffer_size; - unsigned int read_pos; - int started; - struct gr1553bm_config cfg; - - /* Time updated by IRQ when 24-bit Time counter overflows */ - volatile uint64_t time; -}; - -void gr1553bm_isr(void *data); - -/* Default Driver configuration */ -struct gr1553bm_config gr1553bm_default_config = -{ - /* Highest resolution, use Time overflow IRQ to track */ - .time_resolution = 0, - .time_ovf_irq = 1, - - /* No filtering, log all */ - .filt_error_options = GR1553BM_ERROPTS_ALL, - .filt_rtadr = 0xffffffff, - .filt_subadr = 0xffffffff, - .filt_mc = 0x0007ffff, - - /* 128Kbyte dynamically allocated buffer. */ - .buffer_size = 128*1024, - .buffer_custom = NULL, -}; - -void gr1553bm_register(void) -{ - /* The BM driver rely on the GR1553B Driver */ - gr1553_register(); -} - -static void gr1553bm_hw_start(struct gr1553bm_priv *priv) -{ - SPIN_IRQFLAGS(irqflags); - - /* Enable IRQ source and mark running state */ - SPIN_LOCK_IRQ(&priv->devlock, irqflags); - - priv->started = 1; - - /* Clear old IRQ flags */ - priv->regs->irq = GR1553B_IRQ_BMD | GR1553B_IRQ_BMTOF; - - /* Unmask IRQ sources */ - if ( priv->cfg.time_ovf_irq ) { - priv->regs->imask |= GR1553B_IRQEN_BMDE | GR1553B_IRQEN_BMTOE; - } else { - priv->regs->imask |= GR1553B_IRQEN_BMDE; - } - - /* Start logging */ - priv->regs->bm_ctrl = - (priv->cfg.filt_error_options & - (GR1553B_BM_CTRL_MANL|GR1553B_BM_CTRL_UDWL|GR1553B_BM_CTRL_IMCL)) - | GR1553B_BM_CTRL_BMEN; - - SPIN_UNLOCK_IRQ(&priv->devlock, irqflags); -} - -static void gr1553bm_hw_stop(struct gr1553bm_priv *priv) -{ - SPIN_IRQFLAGS(irqflags); - - SPIN_LOCK_IRQ(&priv->devlock, irqflags); - - /* Stop Logging */ - priv->regs->bm_ctrl = 0; - - /* Stop IRQ source */ - priv->regs->imask &= ~(GR1553B_IRQEN_BMDE|GR1553B_IRQEN_BMTOE); - - /* Clear IRQ flags */ - priv->regs->irq = GR1553B_IRQ_BMD | GR1553B_IRQ_BMTOF; - - priv->started = 0; - - SPIN_UNLOCK_IRQ(&priv->devlock, irqflags); -} - -/* Open device by number */ -void *gr1553bm_open(int minor) -{ - struct drvmgr_dev **pdev = NULL; - struct gr1553bm_priv *priv = NULL; - struct amba_dev_info *ambadev; - struct ambapp_core *pnpinfo; - - /* Allocate requested device */ - pdev = gr1553_bm_open(minor); - if ( pdev == NULL ) - goto fail; - - priv = malloc(sizeof(struct gr1553bm_priv)); - if ( priv == NULL ) - goto fail; - memset(priv, 0, sizeof(struct gr1553bm_priv)); - - /* Init BC device */ - priv->pdev = pdev; - (*pdev)->priv = priv; - - /* Get device information from AMBA PnP information */ - ambadev = (struct amba_dev_info *)(*pdev)->businfo; - pnpinfo = &ambadev->info; - priv->regs = (struct gr1553b_regs *)pnpinfo->apb_slv->start; - SPIN_INIT(&priv->devlock, "gr1553bm"); - - /* Start with default configuration */ - priv->cfg = gr1553bm_default_config; - - /* Unmask IRQs */ - gr1553bm_hw_stop(priv); - - return priv; - -fail: - if ( pdev ) - gr1553_bm_close(pdev); - if ( priv ) - free(priv); - return NULL; -} - -/* Close previously */ -void gr1553bm_close(void *bm) -{ - struct gr1553bm_priv *priv = bm; - - if ( priv->started ) { - gr1553bm_stop(bm); - } - - if ( (priv->cfg.buffer_custom == NULL) && priv->buffer ) - free(priv->buffer); - - gr1553_bm_close(priv->pdev); - free(priv); -} - -/* Configure the BM driver */ -int gr1553bm_config(void *bm, struct gr1553bm_config *cfg) -{ - struct gr1553bm_priv *priv = bm; - - if ( priv->started ) - return -1; - - /* Check Config validity? */ -/*#warning IMPLEMENT.*/ - - /* Free old buffer if dynamically allocated */ - if ( (priv->cfg.buffer_custom == NULL) && priv->buffer ) { - free(priv->buffer); - priv->buffer = NULL; - } - priv->buffer_size = cfg->buffer_size & ~0x7; /* on 8 byte bounadry */ - if ((unsigned int)cfg->buffer_custom & 1) { - /* Custom Address Given in Remote address. We need - * to convert it intoTranslate into Hardware a - * hardware accessible address - */ - priv->buffer_base_hw = (unsigned int)cfg->buffer_custom & ~1; - priv->buffer = cfg->buffer_custom; - drvmgr_translate_check( - *priv->pdev, - DMAMEM_TO_CPU, - (void *)priv->buffer_base_hw, - (void **)&priv->buffer_base, - priv->buffer_size); - } else { - if (cfg->buffer_custom == NULL) { - /* Allocate new buffer dynamically */ - priv->buffer = malloc(priv->buffer_size + 8); - if (priv->buffer == NULL) - return -1; - } else { - /* Address given in CPU accessible address, no - * translation required. - */ - priv->buffer = cfg->buffer_custom; - } - /* Align to 16 bytes */ - priv->buffer_base = ((unsigned int)priv->buffer + (8-1)) & - ~(8-1); - /* Translate address of buffer base into address that Hardware must - * use to access the buffer. - */ - drvmgr_translate_check( - *priv->pdev, - CPUMEM_TO_DMA, - (void *)priv->buffer_base, - (void **)&priv->buffer_base_hw, - priv->buffer_size); - - } - - /* Copy valid config */ - priv->cfg = *cfg; - - return 0; -} - -/* Start logging */ -int gr1553bm_start(void *bm) -{ - struct gr1553bm_priv *priv = bm; - - if ( priv->started ) - return -1; - if ( priv->buffer == NULL ) - return -2; - - /* Start at Time = 0 */ - priv->regs->bm_ttag = - priv->cfg.time_resolution << GR1553B_BM_TTAG_RES_BIT; - - /* Configure Filters */ - priv->regs->bm_adr = priv->cfg.filt_rtadr; - priv->regs->bm_subadr = priv->cfg.filt_subadr; - priv->regs->bm_mc = priv->cfg.filt_mc; - - /* Set up buffer */ - priv->regs->bm_start = priv->buffer_base_hw; - priv->regs->bm_end = priv->buffer_base_hw + priv->cfg.buffer_size - 4; - priv->regs->bm_pos = priv->buffer_base_hw; - priv->read_pos = priv->buffer_base; - priv->buffer_end = priv->buffer_base + priv->cfg.buffer_size; - - /* Register ISR handler and unmask IRQ source at IRQ controller */ - if (drvmgr_interrupt_register(*priv->pdev, 0, "gr1553bm", gr1553bm_isr, priv)) - return -3; - - /* Start hardware and set priv->started */ - gr1553bm_hw_start(priv); - - return 0; -} - -/* Stop logging */ -void gr1553bm_stop(void *bm) -{ - struct gr1553bm_priv *priv = bm; - - /* Stop Hardware */ - gr1553bm_hw_stop(priv); - - /* At this point the hardware must be stopped and IRQ - * sources unmasked. - */ - - /* Unregister ISR handler and unmask 1553 IRQ source at IRQ ctrl */ - drvmgr_interrupt_unregister(*priv->pdev, 0, gr1553bm_isr, priv); -} - -int gr1553bm_started(void *bm) -{ - return ((struct gr1553bm_priv *)bm)->started; -} - -/* Get 64-bit 1553 Time. - * - * Update software time counters and return the current time. - */ -void gr1553bm_time(void *bm, uint64_t *time) -{ - struct gr1553bm_priv *priv = bm; - unsigned int hwtime, hwtime2; - -resample: - if ( priv->started && (priv->cfg.time_ovf_irq == 0) ) { - /* Update Time overflow counter. The carry bit from Time counter - * is located in IRQ Flag. - * - * When IRQ is not used this function must be called often - * enough to avoid that the Time overflows and the carry - * bit is already set. The frequency depends on the Time - * resolution. - */ - if ( priv->regs->irq & GR1553B_IRQ_BMTOF ) { - /* Clear carry bit */ - priv->regs->irq = GR1553B_IRQ_BMTOF; - priv->time += (GR1553B_BM_TTAG_VAL + 1); - } - } - - /* Report current Time, even if stopped */ - hwtime = priv->regs->bm_ttag & GR1553B_BM_TTAG_VAL; - if ( time ) - *time = priv->time | hwtime; - - if ( priv->cfg.time_ovf_irq ) { - /* Detect wrap around */ - hwtime2 = priv->regs->bm_ttag & GR1553B_BM_TTAG_VAL; - if ( hwtime > hwtime2 ) { - /* priv->time and hwtime may be out of sync if - * IRQ updated priv->time just after bm_ttag was read - * here, we resample if we detect inconsistancy. - */ - goto resample; - } - } -} - -/* Number of entries available in DMA buffer */ -int gr1553bm_available(void *bm, int *nentries) -{ - struct gr1553bm_priv *priv = bm; - unsigned int top, bot, pos; - - if ( !priv->started ) - return -1; - - /* Get BM posistion in log */ - pos = priv->regs->bm_pos; - - /* Convert into CPU accessible address */ - pos = priv->buffer_base + (pos - priv->buffer_base_hw); - - if ( pos >= priv->read_pos ) { - top = (pos - priv->read_pos)/sizeof(struct gr1553bm_entry); - bot = 0; - } else { - top = (priv->buffer_end - priv->read_pos)/sizeof(struct gr1553bm_entry); - bot = (pos - priv->buffer_base)/sizeof(struct gr1553bm_entry); - } - - if ( nentries ) - *nentries = top+bot; - - return 0; -} - -/* Read a maximum number of entries from LOG buffer. */ -int gr1553bm_read(void *bm, struct gr1553bm_entry *dst, int *max) -{ - struct gr1553bm_priv *priv = bm; - unsigned int dest, pos, left, newPos, len; - unsigned int topAdr, botAdr, topLen, botLen; - - if ( !priv || !priv->started ) - return -1; - - left = *max; - pos = priv->regs->bm_pos & ~0x7; - - /* Convert into CPU accessible address */ - pos = priv->buffer_base + (pos - priv->buffer_base_hw); - - if ( (pos == priv->read_pos) || (left < 1) ) { - /* No data available */ - *max = 0; - return 0; - } - newPos = 0; - - /* Addresses and lengths of BM log buffer */ - if ( pos >= priv->read_pos ) { - /* Read Top only */ - topAdr = priv->read_pos; - botAdr = 0; - topLen = (pos - priv->read_pos)/sizeof(struct gr1553bm_entry); - botLen = 0; - } else { - /* Read Top and Bottom */ - topAdr = priv->read_pos; - botAdr = priv->buffer_base; - topLen = (priv->buffer_end - priv->read_pos)/sizeof(struct gr1553bm_entry); - botLen = (pos - priv->buffer_base)/sizeof(struct gr1553bm_entry); - } - - dest = (unsigned int)dst; - if ( topLen > 0 ) { - /* Copy from top area first */ - if ( topLen > left ) { - len = left; - left = 0; - } else { - len = topLen; - left -= topLen; - } - newPos = topAdr + (len * sizeof(struct gr1553bm_entry)); - if ( newPos >= priv->buffer_end ) - newPos -= priv->buffer_size; - if ( priv->cfg.copy_func ) { - dest += priv->cfg.copy_func( - dest, /*Optional Destination*/ - (void *)topAdr, /* DMA start address */ - len, /* Number of entries */ - priv->cfg.copy_func_arg /* Custom ARG */ - ); - } else { - memcpy( (void *)dest, - (void *)topAdr, - len * sizeof(struct gr1553bm_entry)); - dest += len * sizeof(struct gr1553bm_entry); - } - } - - if ( (botLen > 0) && (left > 0) ) { - /* Copy bottom area last */ - if ( botLen > left ) { - len = left; - left = 0; - } else { - len = botLen; - left -= botLen; - } - newPos = botAdr + (len * sizeof(struct gr1553bm_entry)); - - if ( priv->cfg.copy_func ) { - priv->cfg.copy_func( - dest, /*Optional Destination*/ - (void *)botAdr, /* DMA start address */ - len, /* Number of entries */ - priv->cfg.copy_func_arg /* Custom ARG */ - ); - } else { - memcpy( (void *)dest, - (void *)botAdr, - len * sizeof(struct gr1553bm_entry)); - } - } - - /* Remember last read posistion in buffer */ - /*printf("New pos: 0x%08x (0x%08x), %d\n", newPos, priv->read_pos, *max - left);*/ - priv->read_pos = newPos; - - /* Return number of entries read */ - *max = *max - left; - - return 0; -} - -/* Note: This is a shared interrupt handler, with BC/RT driver - * we must determine the cause of IRQ before handling it. - */ -void gr1553bm_isr(void *data) -{ - struct gr1553bm_priv *priv = data; - uint32_t irqflag; - - /* Get Causes */ - irqflag = priv->regs->irq & (GR1553B_IRQ_BMD | GR1553B_IRQ_BMTOF); - - /* Check spurious IRQs */ - if ( (irqflag == 0) || (priv->started == 0) ) - return; - - if ( (irqflag & GR1553B_IRQ_BMTOF) && priv->cfg.time_ovf_irq ) { - /* 1553 Time Over flow. Time is 24-bits */ - priv->time += (GR1553B_BM_TTAG_VAL + 1); - - /* Clear cause handled */ - priv->regs->irq = GR1553B_IRQ_BMTOF; - } - - if ( irqflag & GR1553B_IRQ_BMD ) { - /* BM DMA ERROR. Fatal error, we stop BM hardware and let - * user take care of it. From now on all calls will result - * in an error because the BM is stopped (priv->started=0). - */ - - /* Clear cause handled */ - priv->regs->irq = GR1553B_IRQ_BMD; - - if ( priv->cfg.dma_error_isr ) - priv->cfg.dma_error_isr(data, priv->cfg.dma_error_arg); - - gr1553bm_hw_stop(priv); - } -} diff --git a/c/src/lib/libbsp/sparc/shared/1553/gr1553rt.c b/c/src/lib/libbsp/sparc/shared/1553/gr1553rt.c deleted file mode 100644 index 932e8494f1..0000000000 --- a/c/src/lib/libbsp/sparc/shared/1553/gr1553rt.c +++ /dev/null @@ -1,1218 +0,0 @@ -/* GR1553B RT driver - * - * COPYRIGHT (c) 2010. - * Cobham Gaisler AB. - * - * 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 - -#define GR1553RT_WRITE_MEM(adr, val) *(volatile uint32_t *)(adr) = (uint32_t)(val) -#define GR1553RT_READ_MEM(adr) (*(volatile uint32_t *)(adr)) - -#define GR1553RT_WRITE_REG(adr, val) *(volatile uint32_t *)(adr) = (uint32_t)(val) -#define GR1553RT_READ_REG(adr) (*(volatile uint32_t *)(adr)) - -/* map via rtems_interrupt_lock_* API: */ -#define SPIN_DECLARE(lock) RTEMS_INTERRUPT_LOCK_MEMBER(lock) -#define SPIN_INIT(lock, name) rtems_interrupt_lock_initialize(lock, name) -#define SPIN_LOCK(lock, level) rtems_interrupt_lock_acquire_isr(lock, &level) -#define SPIN_LOCK_IRQ(lock, level) rtems_interrupt_lock_acquire(lock, &level) -#define SPIN_UNLOCK(lock, level) rtems_interrupt_lock_release_isr(lock, &level) -#define SPIN_UNLOCK_IRQ(lock, level) rtems_interrupt_lock_release(lock, &level) -#define SPIN_IRQFLAGS(k) rtems_interrupt_lock_context k -#define SPIN_ISR_IRQFLAGS(k) SPIN_IRQFLAGS(k) -#define SPIN_FREE(lock) rtems_interrupt_lock_destroy(lock) - -/* Software representation of one hardware descriptor */ -struct gr1553rt_sw_bd { - unsigned short this_next;/* Next entry or this entry. 0xffff: no next */ - unsigned char listid; /* ListID of List the descriptor is attached */ - char unused; -} __attribute__((packed)); - -/* Software description of a subaddress */ -struct gr1553rt_subadr { - /* RX LIST */ - unsigned char rxlistid; - /* TX LIST */ - unsigned char txlistid; -}; - -struct gr1553rt_irqerr { - gr1553rt_irqerr_t func; - void *data; -}; - -struct gr1553rt_irqmc { - gr1553rt_irqmc_t func; - void *data; -}; - -struct gr1553rt_irq { - gr1553rt_irq_t func; - void *data; -}; - -struct gr1553rt_priv { - /* Pointer to Hardware registers */ - struct gr1553b_regs *regs; - - /* Software State */ - int started; - struct gr1553rt_cfg cfg; - SPIN_DECLARE(devlock); - - /* Handle to GR1553B RT device layer */ - struct drvmgr_dev **pdev; - - /* Each Index represents one RT Subaddress. 31 = Broadcast */ - struct gr1553rt_subadr subadrs[32]; - - /* Pointer to array of Software's description of a hardware - * descriptor. - */ -#if (RTBD_MAX == 0) - struct gr1553rt_sw_bd *swbds; -#else - struct gr1553rt_sw_bd swbds[RTBD_MAX]; -#endif - - /* List of Free descriptors */ - unsigned short swbd_free; - int swbd_free_cnt; - - /* Hardware SubAddress descriptors given for CPU and Hardware */ - void *satab_buffer; - struct gr1553rt_sa *sas_cpu; /* Translated for CPU */ - struct gr1553rt_sa *sas_hw; /* Translated for Hardware */ - - /* Hardware descriptors address given for CPU and hardware */ - void *bd_buffer; - int bds_cnt; /* Number of descriptors */ - struct gr1553rt_bd *bds_cpu; /* Translated for CPU */ - struct gr1553rt_bd *bds_hw; /* Translated for Hardware */ - - - /* Event Log buffer in */ - void *evlog_buffer; - unsigned int *evlog_cpu_next; /* Next LOG entry to be handled */ - unsigned int *evlog_cpu_base; /* First Entry in LOG */ - unsigned int *evlog_cpu_end; /* Last+1 Entry in LOG */ - unsigned int *evlog_hw_base; /* Translated for Hardware */ - - /* Each Index represents a LIST ID */ - struct gr1553rt_list *lists[RTLISTID_MAX]; - - /* IRQ handlers, one per SUBADDRESS */ - struct gr1553rt_irq irq_rx[32]; - struct gr1553rt_irq irq_tx[32]; - - /* ISR called when an ERROR IRQ is received */ - struct gr1553rt_irqerr irq_err; - - /* ISR called when an Mode Code is received */ - struct gr1553rt_irqmc irq_mc; -}; - -void gr1553rt_sw_init(struct gr1553rt_priv *priv); -void gr1553rt_sw_free(struct gr1553rt_priv *priv); -void gr1553rt_isr(void *data); - -/* Assign and ID to the list. An LIST ID is needed before scheduling list - * on an RT subaddress. - * - * Only 64 lists can be registered at a time on the same device. - */ -static int gr1553rt_list_reg(struct gr1553rt_list *list) -{ - struct gr1553rt_priv *priv = list->rt; - int i; - - /* Find first free list ID */ - for ( i=0; ilists[i] == NULL ) { - priv->lists[i] = list; - list->listid = i; - return i; - } - } - - /* No available LIST IDs */ - list->listid = -1; - - return -1; -} - -#if 0 /* unused for now */ -/* Unregister List from device */ -static void gr1553rt_list_unreg(struct gr1553rt_list *list) -{ - struct gr1553rt_priv *priv = list->rt; - - priv->lists[list->listid] = NULL; - list->listid = -1; -} -#endif - -static int gr1553rt_bdid(void *rt, struct gr1553rt_sw_bd *bd) -{ - struct gr1553rt_priv *priv = rt; - - unsigned short index; - - /* Get Index of Software BD */ - index = ((unsigned int)bd - (unsigned int)&priv->swbds[0]) / - sizeof(struct gr1553rt_sw_bd); - - return index; -} - -static void gr1553rt_bd_alloc_init(void *rt, int count) -{ - struct gr1553rt_priv *priv = rt; - int i; - - for (i=0; iswbds[i].this_next = i+1; - } - priv->swbds[count-1].this_next = 0xffff; - priv->swbd_free = 0; - priv->swbd_free_cnt = count; -} - -/* Allocate a Chain of descriptors */ -static int gr1553rt_bd_alloc(void *rt, struct gr1553rt_sw_bd **bd, int cnt) -{ - struct gr1553rt_priv *priv = rt; - struct gr1553rt_sw_bd *curr; - int i; - - if ((priv->swbd_free_cnt < cnt) || (cnt <= 0)) { - *bd = NULL; - return -1; - } - - *bd = &priv->swbds[priv->swbd_free]; - for (i=0; iswbds[priv->swbd_free]; - } else { - curr = &priv->swbds[curr->this_next]; - } - if ( curr->this_next == 0xffff ) { - *bd = NULL; - return -1; - } - } - priv->swbd_free = curr->this_next; - priv->swbd_free_cnt -= cnt; - curr->this_next = 0xffff; /* Mark end of chain on last entry */ - - return 0; -} - -#if 0 /* unused for now */ -static void gr1553rt_bd_free(void *rt, struct gr1553rt_sw_bd *bd) -{ - struct gr1553rt_priv *priv = rt; - unsigned short index; - - /* Get Index of Software BD */ - index = gr1553rt_bdid(priv, bd); - - /* Insert first in list */ - bd->this_next = priv->swbd_free; - priv->swbd_free = index; - priv->swbd_free_cnt++; -} -#endif - -int gr1553rt_list_init - ( - void *rt, - struct gr1553rt_list **plist, - struct gr1553rt_list_cfg *cfg - ) -{ - struct gr1553rt_priv *priv = rt; - int i, size; - struct gr1553rt_sw_bd *swbd; - unsigned short index; - struct gr1553rt_list *list; - - /* The user may provide a pre allocated LIST, or - * let the driver handle allocation by using malloc() - * - * If the IN/OUT plist argument points to NULL a list - * dynamically allocated here. - */ - list = *plist; - if ( list == NULL ) { - /* Dynamically allocate LIST */ - size = offsetof(struct gr1553rt_list, bds) + - (cfg->bd_cnt * sizeof(unsigned short)); - list = (struct gr1553rt_list *)malloc(size); - if ( list == NULL ) - return -1; - *plist = list; - } - - list->rt = rt; - list->subadr = -1; - list->listid = gr1553rt_list_reg(list); - if ( list->listid == -1 ) - return -2; /* Too many lists */ - list->cfg = cfg; - list->bd_cnt = cfg->bd_cnt; - - /* Allocate all BDs needed by list */ - if ( gr1553rt_bd_alloc(rt, &swbd, list->bd_cnt) ) { - return -3; /* Too few descriptors */ - } - - /* Get ID/INDEX of Software BDs */ - index = gr1553rt_bdid(rt, swbd); - list->bds[0] = index; - for (i=1; ibd_cnt; i++) { - list->bds[i] = priv->swbds[list->bds[i-1]].this_next; - } - - /* Now that the next pointer has fullfilled it's job and not - * needed anymore, we use it as list entry pointer instead. - * The this_next pointer is a list entry number. - */ - for (i=0; ibd_cnt; i++) { - priv->swbds[list->bds[i]].this_next = i; - } - - return 0; -} - -int gr1553rt_bd_init( - struct gr1553rt_list *list, - unsigned short entry_no, - unsigned int flags, - uint16_t *dptr, - unsigned short next - ) -{ - struct gr1553rt_priv *priv; - unsigned short bdid; - struct gr1553rt_bd *bd; - unsigned int nextbd, dataptr; - SPIN_IRQFLAGS(irqflags); - - if ( entry_no >= list->bd_cnt ) - return -1; - - /* Find Descriptor */ - bdid = list->bds[entry_no]; - priv = list->rt; - bd = &priv->bds_cpu[bdid]; - - if ( next == 0xfffe ) { - next = entry_no + 1; - if ( next >= list->bd_cnt ) - next = 0; - } - - /* Find next descriptor in address space that the - * Hardware understand. - */ - if ( next >= 0xffff ) { - nextbd = 0x3; /* End of list */ - } else if ( next >= list->bd_cnt ) { - return -1; - } else { - bdid = list->bds[next]; - nextbd = (unsigned int)&priv->bds_hw[bdid]; - } - - dataptr = (unsigned int)dptr; - if ( dataptr & 1 ) { - /* Translate address from CPU-local into remote */ - dataptr &= ~1; - drvmgr_translate( - *priv->pdev, - CPUMEM_TO_DMA, - (void *)dataptr, - (void **)&dataptr - ); - } - - /* Init BD */ - SPIN_LOCK_IRQ(&priv->devlock, irqflags); - bd->ctrl = flags & GR1553RT_BD_FLAGS_IRQEN; - bd->dptr = (unsigned int)dptr; - bd->next = nextbd; - SPIN_UNLOCK_IRQ(&priv->devlock, irqflags); - - return 0; -} - -int gr1553rt_bd_update( - struct gr1553rt_list *list, - int entry_no, - unsigned int *status, - uint16_t **dptr - ) -{ - struct gr1553rt_priv *priv; - unsigned short bdid; - struct gr1553rt_bd *bd; - unsigned int tmp, dataptr; - SPIN_IRQFLAGS(irqflags); - - if ( entry_no >= list->bd_cnt ) - return -1; - - /* Find Descriptor */ - bdid = list->bds[entry_no]; - priv = list->rt; - bd = &priv->bds_cpu[bdid]; - - /* Prepare translation if needed */ - if ( dptr && (dataptr=(unsigned int)*dptr) ) { - if ( dataptr & 1 ) { - /* Translate address from CPU-local into remote. May - * be used when RT core is accessed over the PCI bus. - */ - dataptr &= ~1; - drvmgr_translate( - *priv->pdev, - CPUMEM_TO_DMA, - (void *)dataptr, - (void **)&dataptr - ); - } - } - - /* Get current values and then set new values in BD */ - SPIN_LOCK_IRQ(&priv->devlock, irqflags); - /* READ/WRITE Status/Control word */ - if ( status ) { - tmp = bd->ctrl; - if ( *status ) { - bd->ctrl = *status; - } - *status = tmp; - } - /* READ/WRITE Data-Pointer word */ - if ( dptr ) { - tmp = bd->dptr; - if ( dataptr ) { - bd->dptr = dataptr; - } - *dptr = (uint16_t *)tmp; - } - SPIN_LOCK_IRQ(&priv->devlock, irqflags); - - return 0; -} - -int gr1553rt_irq_err - ( - void *rt, - gr1553rt_irqerr_t func, - void *data - ) -{ - struct gr1553rt_priv *priv = rt; - SPIN_IRQFLAGS(irqflags); - - SPIN_LOCK_IRQ(&priv->devlock, irqflags); - priv->irq_err.func = func; - priv->irq_err.data = data; - SPIN_UNLOCK_IRQ(&priv->devlock, irqflags); - - return 0; -} - -int gr1553rt_irq_mc - ( - void *rt, - gr1553rt_irqmc_t func, - void *data - ) -{ - struct gr1553rt_priv *priv = rt; - SPIN_IRQFLAGS(irqflags); - - SPIN_LOCK_IRQ(&priv->devlock, irqflags); - priv->irq_mc.func = func; - priv->irq_mc.data = data; - SPIN_UNLOCK_IRQ(&priv->devlock, irqflags); - - return 0; -} - -int gr1553rt_irq_sa - ( - void *rt, - int subadr, - int tx, - gr1553rt_irq_t func, - void *data - ) -{ - struct gr1553rt_priv *priv = rt; - SPIN_IRQFLAGS(irqflags); - - SPIN_LOCK_IRQ(&priv->devlock, irqflags); - if ( tx ) { - priv->irq_tx[subadr].func = func; - priv->irq_tx[subadr].data = data; - } else { - priv->irq_rx[subadr].func = func; - priv->irq_rx[subadr].data = data; - } - SPIN_UNLOCK_IRQ(&priv->devlock, irqflags); - - return 0; -} - -/* GR1553-RT Interrupt Service Routine */ -void gr1553rt_isr(void *data) -{ - struct gr1553rt_priv *priv = data; - unsigned int firstirq, lastpos; - int index; - unsigned int *last, *curr, entry, hwbd; - int type, samc, mcode, subadr; - int listid; - struct gr1553rt_irq *pisr, isr; - struct gr1553rt_irqerr isrerr; - struct gr1553rt_irqmc isrmc; - unsigned int irq; - SPIN_ISR_IRQFLAGS(irqflags); - - /* Ack IRQ before reading current write pointer, but after - * reading current IRQ pointer. This is because RT_EVIRQ - * may be updated after we ACK the IRQ source. - */ - irq = priv->regs->irq & - (GR1553B_IRQ_RTTE|GR1553B_IRQ_RTD|GR1553B_IRQ_RTEV); - if ( irq == 0 ) - return; - - firstirq = priv->regs->rt_evirq; - priv->regs->irq = irq; - lastpos = priv->regs->rt_evlog; - - /* Quit if nothing has been added to the log */ - if ( lastpos == firstirq ) - return; - - if ( irq & (GR1553B_IRQ_RTTE|GR1553B_IRQ_RTD) ) { - /* copy func and arg while owning lock */ - SPIN_LOCK(&priv->devlock, irqflags); - isrerr = priv->irq_err; - SPIN_UNLOCK(&priv->devlock, irqflags); - if ( isrerr.func ) { - isrerr.func(irq, isrerr.data); - } - - /* Stop Hardware and enter non-started mode. This will - * make all future calls to driver result in an error. - */ - gr1553rt_stop(priv); - } - - /* Step between first log entry causing an IRQ to last - * entry. Each entry that has caused an IRQ will be handled - * by calling user-defined function. - * - * We convert hardware addresses into CPU accessable addresses - * first. - */ - index = (firstirq - (unsigned int)priv->evlog_hw_base) / - sizeof(unsigned int); - curr = priv->evlog_cpu_base + index; - index = (lastpos - (unsigned int)priv->evlog_hw_base) / - sizeof(unsigned int); - last = priv->evlog_cpu_base + index; - - do { - /* Process one entry */ - entry = *curr; - - if ( entry & 0x80000000 ) { - /* Entry caused IRQ */ - type = (entry >> 29) & 0x3; - samc = (entry >> 24) & 0x1f; - if ( (type & 0x2) == 0 ) { - /* Transmit/Receive Data */ - subadr = samc; - if ( type ) { - /* Receive */ - listid = priv->subadrs[subadr].rxlistid; - hwbd = priv->sas_cpu[subadr].rxptr; - pisr = &priv->irq_rx[subadr]; - } else { - /* Transmit */ - listid = priv->subadrs[subadr].txlistid; - hwbd = priv->sas_cpu[subadr].txptr; - pisr = &priv->irq_tx[subadr]; - } - - index = ((unsigned int)hwbd - (unsigned int) - priv->bds_hw)/sizeof(struct gr1553rt_bd); - - /* copy func and arg while owning lock */ - SPIN_LOCK(&priv->devlock, irqflags); - isr = *pisr; - SPIN_UNLOCK(&priv->devlock, irqflags); - - /* Call user ISR of RX/TX transfer */ - if ( isr.func ) { - isr.func( - priv->lists[listid], - entry, - priv->swbds[index].this_next, - isr.data - ); - } - } else if ( type == 0x2) { - /* Modecode */ - mcode = samc; - - /* copy func and arg while owning lock */ - SPIN_LOCK(&priv->devlock, irqflags); - isrmc = priv->irq_mc; - SPIN_UNLOCK(&priv->devlock, irqflags); - - /* Call user ISR of ModeCodes RX/TX */ - if ( isrmc.func ) { - isrmc.func( - mcode, - entry, - isrmc.data - ); - } - } else { - /* ERROR OF SOME KIND, EVLOG OVERWRITTEN? */ - rtems_fatal_error_occurred(RTEMS_IO_ERROR); - } - } - - /* Calc next entry posistion */ - curr++; - if ( curr == priv->evlog_cpu_end ) - curr = priv->evlog_cpu_base; - - } while ( curr != last ); -} - -int gr1553rt_indication(void *rt, int subadr, int *txeno, int *rxeno) -{ - struct gr1553rt_priv *priv = rt; - struct gr1553rt_sa *sa; - unsigned int bd, index; - - /* Sub address valid */ - if ( (subadr < 0) || (subadr > 31) ) - return -1; - - /* Get SubAddress Descriptor address as accessed from CPU */ - sa = &priv->sas_cpu[subadr]; - - /* Indication of TX descriptor? */ - if ( txeno ) { - bd = sa->txptr; - /* Get Index of Hardware BD */ - index = ((unsigned int)bd - (unsigned int)&priv->bds_hw[0]) / - sizeof(struct gr1553rt_bd); - *txeno = priv->swbds[index].this_next; - } - - /* Indication of RX descriptor? */ - if ( rxeno ) { - bd = sa->rxptr; - /* Get Index of Hardware BD */ - index = ((unsigned int)bd - (unsigned int)&priv->bds_hw[0]) / - sizeof(struct gr1553rt_bd); - *rxeno = priv->swbds[index].this_next; - } - - return 0; -} - -void gr1553rt_hw_stop(struct gr1553rt_priv *priv); - -void gr1553rt_register(void) -{ - /* The RT driver rely on the GR1553B Driver */ - gr1553_register(); -} - -void *gr1553rt_open(int minor) -{ - struct drvmgr_dev **pdev = NULL; - struct gr1553rt_priv *priv = NULL; - struct amba_dev_info *ambadev; - struct ambapp_core *pnpinfo; - - /* Allocate requested device */ - pdev = gr1553_rt_open(minor); - if ( pdev == NULL ) - goto fail; - - priv = malloc(sizeof(struct gr1553rt_priv)); - if ( priv == NULL ) - goto fail; - memset(priv, 0, sizeof(struct gr1553rt_priv)); - - /* Assign a device private to RT device */ - priv->pdev = pdev; - (*pdev)->priv = priv; - - /* Get device information from AMBA PnP information */ - ambadev = (struct amba_dev_info *)(*pdev)->businfo; - pnpinfo = &ambadev->info; - priv->regs = (struct gr1553b_regs *)pnpinfo->apb_slv->start; - - SPIN_INIT(&priv->devlock, "gr1553rt"); - - /* Start with default configuration */ - /*priv->cfg = gr1553rt_default_config;*/ - - /* Unmask IRQs and so */ - gr1553rt_hw_stop(priv); - - /* Register ISR handler. hardware mask IRQ, so it is safe to unmask - * at IRQ controller. - */ - if (drvmgr_interrupt_register(*priv->pdev, 0, "gr1553rt", gr1553rt_isr, priv)) - goto fail; - - return priv; - -fail: - if ( pdev ) - gr1553_rt_close(pdev); - if ( priv ) - free(priv); - return NULL; -} - -void gr1553rt_close(void *rt) -{ - struct gr1553rt_priv *priv = rt; - - if ( priv->started ) { - gr1553rt_stop(priv); - } - - /* Remove ISR handler */ - drvmgr_interrupt_unregister(*priv->pdev, 0, gr1553rt_isr, priv); - - /* Free dynamically allocated buffers if any */ - gr1553rt_sw_free(priv); - SPIN_FREE(&priv->devlock); - - /* Return RT/BC device */ - gr1553_rt_close(priv->pdev); -} - -/* Stop Hardware and disable IRQ */ -void gr1553rt_hw_stop(struct gr1553rt_priv *priv) -{ - uint32_t irqmask; - - /* Disable RT */ - GR1553RT_WRITE_REG(&priv->regs->rt_cfg, GR1553RT_KEY); - - /* Stop BC if not already stopped: BC can not be used simultaneously - * as the RT anyway - */ - GR1553RT_WRITE_REG(&priv->regs->bc_ctrl, GR1553BC_KEY | 0x0204); - - /* Turn off RT IRQ generation */ - irqmask=GR1553RT_READ_REG(&priv->regs->imask); - irqmask&=~(GR1553B_IRQEN_RTEVE|GR1553B_IRQEN_RTDE); - GR1553RT_WRITE_REG(&priv->regs->irq, irqmask); -} - -/* Free dynamically allocated buffers, if any */ -void gr1553rt_sw_free(struct gr1553rt_priv *priv) -{ - /* Event log */ - if ( (priv->cfg.evlog_buffer == NULL) && priv->evlog_buffer ) { - free(priv->evlog_buffer); - priv->evlog_buffer = NULL; - } - - /* RX/TX Descriptors */ - if ( (priv->cfg.bd_buffer == NULL) && priv->bd_buffer ) { - free(priv->bd_buffer); - priv->bd_buffer = NULL; - } - -#if (RTBD_MAX == 0) - if ( priv->swbds ) { - free(priv->swbds); - priv->swbds = NULL; - } -#endif - - /* Sub address table */ - if ( (priv->cfg.satab_buffer == NULL) && priv->satab_buffer ) { - free(priv->satab_buffer); - priv->satab_buffer = NULL; - } -} - -/* Free dynamically allocated buffers, if any */ -static int gr1553rt_sw_alloc(struct gr1553rt_priv *priv) -{ - int size; - - /* Allocate Event log */ - if ((unsigned int)priv->cfg.evlog_buffer & 1) { - /* Translate Address from HARDWARE (REMOTE) to CPU-LOCAL */ - priv->evlog_hw_base = (unsigned int *) - ((unsigned int)priv->cfg.evlog_buffer & ~0x1); - priv->evlog_buffer = priv->cfg.evlog_buffer; - drvmgr_translate_check( - *priv->pdev, - DMAMEM_TO_CPU, - (void *)priv->evlog_hw_base, - (void **)&priv->evlog_cpu_base, - priv->cfg.evlog_size - ); - } else { - if (priv->cfg.evlog_buffer == NULL) { - priv->evlog_buffer = malloc(priv->cfg.evlog_size * 2); - if (priv->evlog_buffer == NULL) - return -1; - } else { - /* Addess already CPU-LOCAL */ - priv->evlog_buffer = priv->cfg.evlog_buffer; - } - /* Align to SIZE bytes boundary */ - priv->evlog_cpu_base = (unsigned int *) - (((unsigned int)priv->evlog_buffer + - (priv->cfg.evlog_size-1)) & ~(priv->cfg.evlog_size-1)); - - drvmgr_translate_check( - *priv->pdev, - CPUMEM_TO_DMA, - (void *)priv->evlog_cpu_base, - (void **)&priv->evlog_hw_base, - priv->cfg.evlog_size - ); - } - priv->evlog_cpu_end = priv->evlog_cpu_base + - priv->cfg.evlog_size/sizeof(unsigned int *); - - /* Allocate Transfer Descriptors */ - priv->bds_cnt = priv->cfg.bd_count; - size = priv->bds_cnt * sizeof(struct gr1553rt_bd); - if ((unsigned int)priv->cfg.bd_buffer & 1) { - /* Translate Address from HARDWARE (REMOTE) to CPU-LOCAL */ - priv->bds_hw = (struct gr1553rt_bd *) - ((unsigned int)priv->cfg.bd_buffer & ~0x1); - priv->bd_buffer = priv->cfg.bd_buffer; - drvmgr_translate_check( - *priv->pdev, - DMAMEM_TO_CPU, - (void *)priv->bds_hw, - (void **)&priv->bds_cpu, - size - ); - } else { - if ( priv->cfg.bd_buffer == NULL ) { - priv->bd_buffer = malloc(size + 0xf); - if (priv->bd_buffer == NULL) - return -1; - } else { - /* Addess already CPU-LOCAL */ - priv->bd_buffer = priv->cfg.bd_buffer; - } - /* Align to 16 bytes boundary */ - priv->bds_cpu = (struct gr1553rt_bd *) - (((unsigned int)priv->bd_buffer + 0xf) & ~0xf); - - /* Translate from CPU address to hardware address */ - drvmgr_translate_check( - *priv->pdev, - CPUMEM_TO_DMA, - (void *)priv->bds_cpu, - (void **)&priv->bds_hw, - size - ); - } - -#if (RTBD_MAX == 0) - /* Allocate software description of */ - priv->swbds = malloc(priv->cfg.bd_count * sizeof(struct gr1553rt_sw_bd)); - if ( priv->swbds == NULL ) { - return -1; - } -#endif - - /* Allocate Sub address table */ - if ((unsigned int)priv->cfg.satab_buffer & 1) { - /* Translate Address from HARDWARE (REMOTE) to CPU-LOCAL */ - priv->sas_hw = (struct gr1553rt_sa *) - ((unsigned int)priv->cfg.satab_buffer & ~0x1); - priv->satab_buffer = priv->cfg.satab_buffer; - drvmgr_translate_check( - *priv->pdev, - DMAMEM_TO_CPU, - (void *)priv->sas_hw, - (void **)&priv->sas_cpu, - 16 * 32); - } else { - if (priv->cfg.satab_buffer == NULL) { - priv->satab_buffer = malloc((16 * 32) * 2); - if (priv->satab_buffer == NULL) - return -1; - } else { - /* Addess already CPU-LOCAL */ - priv->satab_buffer = priv->cfg.satab_buffer; - } - /* Align to 512 bytes boundary */ - priv->sas_cpu = (struct gr1553rt_sa *) - (((unsigned int)priv->satab_buffer + 0x1ff) & - ~0x1ff); - - /* Translate Address from CPU-LOCAL to HARDWARE (REMOTE) */ - drvmgr_translate_check( - *priv->pdev, - CPUMEM_TO_DMA, - (void *)priv->sas_cpu, - (void **)&priv->sas_hw, - 16 * 32); - } - - return 0; -} - -void gr1553rt_sw_init(struct gr1553rt_priv *priv) -{ - int i; - - /* Clear Sub Address table */ - memset(priv->sas_cpu, 0, 512); - - /* Clear Transfer descriptors */ - memset(priv->bds_cpu, 0, priv->bds_cnt * 16); - - /* Clear the Event log */ - memset(priv->evlog_cpu_base, 0, priv->cfg.evlog_size); - - /* Init descriptor allocation algorithm */ - gr1553rt_bd_alloc_init(priv, priv->bds_cnt); - - /* Init table used to convert from sub address to list. - * Currently non assigned. - */ - for (i=0; i<32; i++) { - priv->subadrs[i].rxlistid = 0xff; - priv->subadrs[i].txlistid = 0xff; - } - - /* Clear all previous IRQ handlers */ - for (i=0; i<32; i++) { - priv->irq_rx[i].func = NULL; - priv->irq_tx[i].data = NULL; - } - priv->irq_err.func = NULL; - priv->irq_err.data = NULL; - priv->irq_mc.func = NULL; - priv->irq_mc.data = NULL; - - /* Clear LIST to LISTID table */ - for (i=0; ilists[i] = NULL; - } -} - -int gr1553rt_config(void *rt, struct gr1553rt_cfg *cfg) -{ - struct gr1553rt_priv *priv = rt; - - if ( priv->started ) - return -1; - - /*** Free dynamically allocated buffers ***/ - - gr1553rt_sw_free(priv); - - /*** Check new config ***/ - if ( cfg->rtaddress > 30 ) - return -1; - if ( (cfg->evlog_size & (cfg->evlog_size-1)) != 0) - return -1; /* SIZE: Not aligned to a power of 2 */ - if ( ((unsigned int)priv->cfg.evlog_buffer & (cfg->evlog_size-1)) != 0 ) - return -1; /* Buffer: Not aligned to size */ -#if (RTBD_MAX > 0) - if ( cfg->bd_count > RTBD_MAX ) - return -1; -#endif - - /*** Make new config current ***/ - priv->cfg = *cfg; - - /*** Adapt to new config ***/ - - if ( gr1553rt_sw_alloc(priv) != 0 ) - return -1; - - gr1553rt_sw_init(priv); - - return 0; -} - -int gr1553rt_start(void *rt) -{ - struct gr1553rt_priv *priv = rt; - SPIN_IRQFLAGS(irqflags); - - if ( priv->started ) - return -1; - - /*** Initialize software Pointers and stuff ***/ - - if ( !priv->satab_buffer || !priv->bd_buffer || !priv->evlog_buffer ) - return -2; - - priv->evlog_cpu_next = priv->evlog_cpu_base; - - /*** Initialize Registers ***/ - - /* Subaddress table base */ - priv->regs->rt_tab = (unsigned int)priv->sas_hw; - - /* Mode code configuration */ - priv->regs->rt_mcctrl = priv->cfg.modecode; - - /* RT Time Tag resolution */ - priv->regs->rt_ttag = priv->cfg.time_res << 16; - - /* Event LOG base and size */ - priv->regs->rt_evsz = ~(priv->cfg.evlog_size - 1); - priv->regs->rt_evlog = (unsigned int)priv->evlog_hw_base; - priv->regs->rt_evirq = 0; - - /* Clear and old IRQ flag and Enable IRQ */ - SPIN_LOCK_IRQ(&priv->devlock, irqflags); - priv->regs->irq = GR1553B_IRQ_RTEV|GR1553B_IRQ_RTD|GR1553B_IRQ_RTTE; - priv->regs->imask |= GR1553B_IRQEN_RTEVE | GR1553B_IRQEN_RTDE | - GR1553B_IRQEN_RTTEE; - - /* Enable and Set RT address */ - priv->regs->rt_cfg = GR1553RT_KEY | - (priv->cfg.rtaddress << GR1553B_RT_CFG_RTADDR_BIT) | - GR1553B_RT_CFG_RTEN; - - /* Tell software RT is started */ - priv->started = 1; - SPIN_UNLOCK_IRQ(&priv->devlock, irqflags); - - return 0; -} - -void gr1553rt_stop(void *rt) -{ - struct gr1553rt_priv *priv = rt; - SPIN_IRQFLAGS(irqflags); - - SPIN_LOCK_IRQ(&priv->devlock, irqflags); - - /* Stop Hardware */ - gr1553rt_hw_stop(priv); - - /* Software state */ - priv->started = 0; - - SPIN_UNLOCK_IRQ(&priv->devlock, irqflags); -} - -void gr1553rt_sa_schedule( - void *rt, - int subadr, - int tx, - struct gr1553rt_list *list - ) -{ - struct gr1553rt_priv *priv = rt; - unsigned short bdid; - struct gr1553rt_bd *bd; - - if ( !list || (list->listid == -1) ) - return; - - /* Get Hardware address of first descriptor in list */ - bdid = list->bds[0]; - if ( bdid == 0xffff ) - return; - bd = &priv->bds_hw[bdid]; - - list->subadr = subadr; - - /* Update Sub address table */ - if ( tx ) { - list->subadr |= 0x100; - priv->subadrs[subadr].txlistid = list->listid; - priv->sas_cpu[subadr].txptr = (unsigned int)bd; - } else { - priv->subadrs[subadr].rxlistid = list->listid; - priv->sas_cpu[subadr].rxptr = (unsigned int)bd; - } -} - -void gr1553rt_sa_setopts( - void *rt, - int subadr, - unsigned int mask, - unsigned int options - ) -{ - struct gr1553rt_priv *priv = rt; - unsigned int ctrl; - - if ( (subadr > 31) || (priv->sas_cpu == NULL) ) - return; - - ctrl = priv->sas_cpu[subadr].ctrl; - priv->sas_cpu[subadr].ctrl = (ctrl & ~mask) | options; -} - -void gr1553rt_set_vecword(void *rt, unsigned int mask, unsigned int words) -{ - struct gr1553rt_priv *priv = rt; - unsigned int vword; - - if ( mask == 0 ) - return; - - vword = priv->regs->rt_statw; - - priv->regs->rt_statw = (vword & ~mask) | (words & mask); -} - -void gr1553rt_set_bussts(void *rt, unsigned int mask, unsigned int sts) -{ - struct gr1553rt_priv *priv = rt; - unsigned int stat; - - stat = priv->regs->rt_stat2; - priv->regs->rt_stat2 = (stat & ~mask) | (mask & sts); -} - -void gr1553rt_status(void *rt, struct gr1553rt_status *status) -{ - struct gr1553rt_priv *priv = rt; - struct gr1553b_regs *regs = priv->regs; - unsigned int tmp; - SPIN_IRQFLAGS(irqflags); - - SPIN_LOCK_IRQ(&priv->devlock, irqflags); - status->status = regs->rt_stat; - status->bus_status = regs->rt_stat2; - - tmp = regs->rt_sync; - status->synctime = tmp >> 16; - status->syncword = tmp & 0xffff; - - tmp = regs->rt_ttag; - status->time_res = tmp >> 16; - status->time = tmp & 0xffff; - - SPIN_UNLOCK_IRQ(&priv->devlock, irqflags); -} - -void gr1553rt_list_sa(struct gr1553rt_list *list, int *subadr, int *tx) -{ - int sa, trt; - - if ( list->subadr == -1 ) { - sa = -1; - trt = -1; - } else { - sa = list->subadr & 0xff; - trt = (list->subadr & 0x100) >> 8; - } - - if ( subadr ) - *subadr = sa; - if ( tx ) - *tx = trt; -} - -int gr1553rt_evlog_read(void *rt, unsigned int *dst, int max) -{ - struct gr1553rt_priv *priv = rt; - int cnt, top, bot, left; - unsigned int *hwpos; - - /* Get address of hardware's current working entry */ - hwpos = (unsigned int *)priv->regs->rt_evlog; - - /* Convert into CPU address */ - hwpos = (unsigned int *) - ((unsigned int)hwpos - (unsigned int)priv->evlog_hw_base + - (unsigned int)priv->evlog_cpu_base); - - if ( priv->evlog_cpu_next == hwpos ) - return 0; - - if ( priv->evlog_cpu_next > hwpos ) { - top = (unsigned int)priv->evlog_cpu_end - - (unsigned int)priv->evlog_cpu_next; - bot = (unsigned int)hwpos - (unsigned int)priv->evlog_cpu_base; - } else { - top = (unsigned int)hwpos - (unsigned int)priv->evlog_cpu_next; - bot = 0; - } - top = top / 4; - bot = bot / 4; - - left = max; - if ( top > 0 ) { - if ( top > left ) { - cnt = left; - } else { - cnt = top; - } - memcpy(dst, priv->evlog_cpu_next, cnt*4); - dst += cnt; - left -= cnt; - } - - if ( (bot > 0) && (left > 0) ) { - if ( bot > left ) { - cnt = left; - } else { - cnt = bot; - } - memcpy(dst, priv->evlog_cpu_base, cnt*4); - left -= cnt; - } - - cnt = max - left; - priv->evlog_cpu_next += cnt; - if ( priv->evlog_cpu_next >= priv->evlog_cpu_end ) { - priv->evlog_cpu_next = (unsigned int *) - ((unsigned int)priv->evlog_cpu_base + - ((unsigned int)priv->evlog_cpu_next - - (unsigned int)priv->evlog_cpu_end )); - } - - return max - left; -} diff --git a/c/src/lib/libbsp/sparc/shared/amba/ahbstat.c b/c/src/lib/libbsp/sparc/shared/amba/ahbstat.c deleted file mode 100644 index e624301975..0000000000 --- a/c/src/lib/libbsp/sparc/shared/amba/ahbstat.c +++ /dev/null @@ -1,245 +0,0 @@ -/* AHB Status register driver - * - * COPYRIGHT (c) 2009 - 2017. - * Cobham Gaisler AB. - * - * 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 - -#define SPIN_IRQ_DECLARE(name) RTEMS_INTERRUPT_LOCK_DECLARE(, name) -#define SPIN_IRQ_INIT(lock, name) rtems_interrupt_lock_initialize(lock, name) -#define SPIN_IRQ_LOCK(lock, ctx) rtems_interrupt_lock_acquire(lock, &(ctx)) -#define SPIN_IRQ_UNLOCK(lock, ctx) rtems_interrupt_lock_release(lock, &(ctx)) -#define SPIN_IRQ_LOCK_ISR(lock, ctx) rtems_interrupt_lock_acquire_isr(lock, &(ctx)) -#define SPIN_IRQ_UNLOCK_ISR(lock, ctx) rtems_interrupt_lock_release_isr(lock, &(ctx)) -#define SPIN_IRQ_CTX rtems_interrupt_lock_context - -#define REG_WRITE(addr, val) (*(volatile uint32_t *)(addr) = (uint32_t)(val)) -#define REG_READ(addr) (*(volatile uint32_t *)(addr)) - -void ahbstat_isr(void *arg); - -/* AHB fail interrupt callback to user. This function is declared weak so that - * the user can define a function pointer variable containing the address - * responsible for handling errors - * - * minor Index of AHBSTAT hardware - * regs Register address of AHBSTAT - * status AHBSTAT status register at IRQ - * failing_address AHBSTAT Failing address register at IRQ - * - * * User return - * 0: print error onto terminal with printk and reenable AHBSTAT - * 1: just re-enable AHBSTAT - * 2: just print error - * 3: do nothing, let user do custom handling - */ -int (*ahbstat_error)( - int minor, - struct ahbstat_regs *regs, - uint32_t status, - uint32_t failing_address - ) __attribute__((weak)) = NULL; - -#define AHBSTAT_STS_CE_BIT 9 -#define AHBSTAT_STS_NE_BIT 8 -#define AHBSTAT_STS_HW_BIT 7 -#define AHBSTAT_STS_HM_BIT 3 -#define AHBSTAT_STS_HS_BIT 0 - -#define AHBSTAT_STS_CE (1 << AHBSTAT_STS_CE_BIT) -#define AHBSTAT_STS_NE (1 << AHBSTAT_STS_NE_BIT) -#define AHBSTAT_STS_HW (1 << AHBSTAT_STS_HW_BIT) -#define AHBSTAT_STS_HM (0xf << AHBSTAT_STS_HM_BIT) -#define AHBSTAT_STS_HS (0x7 << AHBSTAT_STS_HS_BIT) - -enum { DEVNAME_LEN = 9 }; -struct ahbstat_priv { - struct drvmgr_dev *dev; - struct ahbstat_regs *regs; - char devname[DEVNAME_LEN]; - int minor; - /* Cached error */ - uint32_t last_status; - uint32_t last_address; - /* Spin-lock ISR protection */ - SPIN_IRQ_DECLARE(devlock); -}; - -static int ahbstat_init2(struct drvmgr_dev *dev); - -struct drvmgr_drv_ops ahbstat_ops = -{ - .init = {NULL, ahbstat_init2, NULL, NULL}, - .remove = NULL, - .info = NULL -}; - -struct amba_dev_id ahbstat_ids[] = -{ - {VENDOR_GAISLER, GAISLER_AHBSTAT}, - {0, 0} /* Mark end of table */ -}; - -struct amba_drv_info ahbstat_drv_info = -{ - { - DRVMGR_OBJ_DRV, /* Driver */ - NULL, /* Next driver */ - NULL, /* Device list */ - DRIVER_AMBAPP_GAISLER_AHBSTAT_ID,/* Driver ID */ - "AHBSTAT_DRV", /* Driver Name */ - DRVMGR_BUS_TYPE_AMBAPP, /* Bus Type */ - &ahbstat_ops, - NULL, /* Funcs */ - 0, /* No devices yet */ - sizeof(struct ahbstat_priv), - }, - &ahbstat_ids[0] -}; - -void ahbstat_register_drv (void) -{ - drvmgr_drv_register(&ahbstat_drv_info.general); -} - -static int ahbstat_init2(struct drvmgr_dev *dev) -{ - struct ahbstat_priv *priv; - struct amba_dev_info *ambadev; - - priv = dev->priv; - if (!priv) - return DRVMGR_NOMEM; - priv->dev = dev; - - /* Get device information from AMBA PnP information */ - ambadev = (struct amba_dev_info *)dev->businfo; - if (ambadev == NULL) - return DRVMGR_FAIL; - priv->regs = (struct ahbstat_regs *)ambadev->info.apb_slv->start; - priv->minor = dev->minor_drv; - - strncpy(&priv->devname[0], "ahbstat0", DEVNAME_LEN); - priv->devname[7] += priv->minor; - /* - * Initialize spinlock for AHBSTAT Device. It is used to protect user - * API calls involivng priv structure from updates in ISR. - */ - SPIN_IRQ_INIT(&priv->devlock, priv->devname); - - /* Initialize hardware */ - REG_WRITE(&priv->regs->status, 0); - - /* Install IRQ handler */ - drvmgr_interrupt_register(dev, 0, priv->devname, ahbstat_isr, priv); - - return DRVMGR_OK; -} - -void ahbstat_isr(void *arg) -{ - struct ahbstat_priv *priv = arg; - uint32_t fadr, status; - int rc; - SPIN_IRQ_CTX lock_context; - - /* Get hardware status */ - status = REG_READ(&priv->regs->status); - if ((status & AHBSTAT_STS_NE) == 0) - return; - - /* IRQ generated by AHBSTAT core... handle it here */ - - /* Get Failing address */ - fadr = REG_READ(&priv->regs->failing); - - SPIN_IRQ_LOCK_ISR(&priv->devlock, lock_context); - priv->last_status = status; - priv->last_address = fadr; - SPIN_IRQ_UNLOCK_ISR(&priv->devlock, lock_context); - - /* Let user handle error, default to print the error and reenable HW - * - * User return - * 0: print error and reenable AHBSTAT - * 1: just reenable AHBSTAT - * 2: just print error - * 3: do nothing - */ - rc = 0; - if (ahbstat_error != NULL) - rc = ahbstat_error(priv->minor, priv->regs, status, fadr); - - if ((rc & 0x1) == 0) { - printk("\n### AHBSTAT: %s %s error of size %ld by master %ld" - " at 0x%08lx\n", - status & AHBSTAT_STS_CE ? "single" : "non-correctable", - status & AHBSTAT_STS_HW ? "write" : "read", - (status & AHBSTAT_STS_HS) >> AHBSTAT_STS_HS_BIT, - (status & AHBSTAT_STS_HM) >> AHBSTAT_STS_HM_BIT, - fadr); - } - - if ((rc & 0x2) == 0) { - /* Trigger new interrupts */ - REG_WRITE(&priv->regs->status, 0); - } -} - -/* Get Last received AHB Error - * - * Return - * 0: No error received - * 1: Error Received, last status and address stored into argument pointers - * -1: No such AHBSTAT device - */ -int ahbstat_last_error(int minor, uint32_t *status, uint32_t *address) -{ - struct drvmgr_dev *dev; - struct ahbstat_priv *priv; - uint32_t last_status; - uint32_t last_address; - SPIN_IRQ_CTX lock_context; - - if (drvmgr_get_dev(&ahbstat_drv_info.general, minor, &dev)) { - return -1; - } - priv = (struct ahbstat_priv *)dev->priv; - - /* Read information cached by ISR */ - SPIN_IRQ_LOCK(&priv->devlock, lock_context); - last_status = REG_READ(&priv->last_status); - last_address = REG_READ(&priv->last_address); - SPIN_IRQ_UNLOCK(&priv->devlock, lock_context); - - *status = last_status; - *address = last_address; - - return (last_status & AHBSTAT_STS_NE) >> AHBSTAT_STS_NE_BIT; -} - -/* Get AHBSTAT registers address from minor. NULL returned if no such device */ -struct ahbstat_regs *ahbstat_get_regs(int minor) -{ - struct drvmgr_dev *dev; - struct ahbstat_priv *priv; - - if (drvmgr_get_dev(&ahbstat_drv_info.general, minor, &dev)) { - return NULL; - } - priv = (struct ahbstat_priv *)dev->priv; - - return priv->regs; -} diff --git a/c/src/lib/libbsp/sparc/shared/amba/ambapp.c b/c/src/lib/libbsp/sparc/shared/amba/ambapp.c deleted file mode 100644 index e3c777a5f5..0000000000 --- a/c/src/lib/libbsp/sparc/shared/amba/ambapp.c +++ /dev/null @@ -1,455 +0,0 @@ -/* - * AMBA Plug & Play routines - * - * COPYRIGHT (c) 2011. - * Aeroflex Gaisler. - * - * 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 - -#define AMBA_CONF_AREA 0xff000 -#define AMBA_AHB_SLAVE_CONF_AREA (1 << 11) -#define AMBA_APB_SLAVES 16 - -/* Allocate one AMBA device */ -static struct ambapp_dev *ambapp_alloc_dev_struct(int dev_type) -{ - struct ambapp_dev *dev; - size_t size = sizeof(*dev); - - if (dev_type == DEV_APB_SLV) - size += sizeof(struct ambapp_apb_info); - else - size += sizeof(struct ambapp_ahb_info); /* AHB */ - dev = (struct ambapp_dev *)calloc(1, size); - if (dev != NULL) - dev->dev_type = dev_type; - return dev; -} - -static unsigned int -ambapp_addr_from (struct ambapp_mmap *mmaps, unsigned int address) -{ - /* no translation? */ - if (!mmaps) - return address; - - while (mmaps->size) { - if ((address >= mmaps->remote_adr) && - (address <= (mmaps->remote_adr + (mmaps->size - 1)))) { - return (address - mmaps->remote_adr) + mmaps->local_adr; - } - mmaps++; - } - return 1; -} - -static void ambapp_ahb_dev_init( - unsigned int ioarea, - struct ambapp_mmap *mmaps, - struct ambapp_pnp_ahb *ahb, - struct ambapp_dev *dev, - int ahbidx - ) -{ - int bar; - struct ambapp_ahb_info *ahb_info; - unsigned int addr, mask, mbar; - - /* Setup device struct */ - dev->vendor = ambapp_pnp_vendor(ahb->id); - dev->device = ambapp_pnp_device(ahb->id); - ahb_info = DEV_TO_AHB(dev); - ahb_info->ver = ambapp_pnp_ver(ahb->id); - ahb_info->irq = ambapp_pnp_irq(ahb->id); - ahb_info->ahbidx = ahbidx; - ahb_info->custom[0] = (unsigned int)ahb->custom[0]; - ahb_info->custom[1] = (unsigned int)ahb->custom[1]; - ahb_info->custom[2] = (unsigned int)ahb->custom[2]; - - /* Memory BARs */ - for (bar=0; bar<4; bar++) { - mbar = ahb->mbar[bar]; - if (mbar == 0) { - addr = 0; - mask = 0; - } else { - addr = ambapp_pnp_start(mbar); - if (ambapp_pnp_mbar_type(mbar) == AMBA_TYPE_AHBIO) { - /* AHB I/O area is releative IO_AREA */ - addr = AMBA_TYPE_AHBIO_ADDR(addr, ioarea); - mask = (((unsigned int)(ambapp_pnp_mbar_mask(~mbar) << 8) | 0xff)) + 1; - } else { - /* AHB memory area, absolute address */ - addr = ambapp_addr_from(mmaps, addr); - mask = (~((unsigned int)(ambapp_pnp_mbar_mask(mbar) << 20))) + 1; - } - } - ahb_info->start[bar] = addr; - ahb_info->mask[bar] = mask; - ahb_info->type[bar] = ambapp_pnp_mbar_type(mbar); - } -} - -static void ambapp_apb_dev_init( - unsigned int base, - struct ambapp_mmap *mmaps, - struct ambapp_pnp_apb *apb, - struct ambapp_dev *dev, - int ahbidx - ) -{ - struct ambapp_apb_info *apb_info; - - /* Setup device struct */ - dev->vendor = ambapp_pnp_vendor(apb->id); - dev->device = ambapp_pnp_device(apb->id); - apb_info = DEV_TO_APB(dev); - apb_info->ver = ambapp_pnp_ver(apb->id); - apb_info->irq = ambapp_pnp_irq(apb->id); - apb_info->ahbidx = ahbidx; - apb_info->start = ambapp_pnp_apb_start(apb->iobar, base); - apb_info->mask = ambapp_pnp_apb_mask(apb->iobar); -} - -static int ambapp_add_ahbbus( - struct ambapp_bus *abus, - unsigned int ioarea - ) -{ - int i; - for (i=0; iahbs[i].ioarea == 0) { - abus->ahbs[i].ioarea = ioarea; - return i; - } else if (abus->ahbs[i].ioarea == ioarea) { - /* Bus already added */ - return -1; - } - } - return -1; -} - -/* Internal AMBA Scanning Function */ -static int ambapp_scan2( - struct ambapp_bus *abus, - unsigned int ioarea, - ambapp_memcpy_t memfunc, - struct ambapp_dev *parent, - struct ambapp_dev **root - ) -{ - struct ambapp_pnp_ahb *ahb, ahb_buf; - struct ambapp_pnp_apb *apb, apb_buf; - struct ambapp_dev *dev, *prev, *prevapb, *apbdev; - struct ambapp_ahb_info *ahb_info; - int maxloops = 64; - unsigned int apbbase, bridge_adr; - int i, j, ahbidx; - - *root = NULL; - - if (parent) { - /* scan first bus for 64 devices, rest for 16 devices */ - maxloops = 16; - } - - ahbidx = ambapp_add_ahbbus(abus, ioarea); - if (ahbidx < 0) { - /* Bus already scanned, stop */ - return 0; - } - - prev = parent; - - /* AHB MASTERS */ - ahb = (struct ambapp_pnp_ahb *) (ioarea | AMBA_CONF_AREA); - for (i = 0; i < maxloops; i++, ahb++) { - memfunc(&ahb_buf, ahb, sizeof(struct ambapp_pnp_ahb), abus); - if (ahb_buf.id == 0) - continue; - - /* An AHB device present here */ - dev = ambapp_alloc_dev_struct(DEV_AHB_MST); - if (!dev) - return -1; - - ambapp_ahb_dev_init(ioarea, abus->mmaps, &ahb_buf, dev, ahbidx); - - if (*root == NULL) - *root = dev; - - if (prev != parent) - prev->next = dev; - dev->prev = prev; - prev = dev; - } - - /* AHB SLAVES */ - ahb = (struct ambapp_pnp_ahb *) - (ioarea | AMBA_CONF_AREA | AMBA_AHB_SLAVE_CONF_AREA); - for (i = 0; i < maxloops; i++, ahb++) { - memfunc(&ahb_buf, ahb, sizeof(struct ambapp_pnp_ahb), abus); - if (ahb_buf.id == 0) - continue; - - /* An AHB device present here */ - dev = ambapp_alloc_dev_struct(DEV_AHB_SLV); - if (!dev) - return -1; - - ambapp_ahb_dev_init(ioarea, abus->mmaps, &ahb_buf, dev, ahbidx); - - if (*root == NULL) - *root = dev; - - if (prev != parent) - prev->next = dev; - dev->prev = prev; - prev = dev; - - ahb_info = DEV_TO_AHB(dev); - - /* Is it a AHB/AHB Bridge ? */ - if (((dev->device == GAISLER_AHB2AHB) && - (dev->vendor == VENDOR_GAISLER) && (ahb_info->ver > 0)) || - ((dev->device == GAISLER_L2CACHE) && - (dev->vendor == VENDOR_GAISLER)) || - ((dev->device == GAISLER_GRIOMMU) && - (dev->vendor == VENDOR_GAISLER))) { - /* AHB/AHB Bridge Found, recurse down the - * Bridge - */ - if (ahb_info->custom[1] != 0) { - bridge_adr = ambapp_addr_from(abus->mmaps, - ahb_info->custom[1]); - /* Scan next bus if not already scanned */ - if (ambapp_scan2(abus, bridge_adr, memfunc, dev, - &dev->children)) - return -1; - } - } else if ((dev->device == GAISLER_APBMST) && - (dev->vendor == VENDOR_GAISLER)) { - /* AHB/APB Bridge Found, add the APB devices to this - * AHB Slave's children - */ - prevapb = dev; - apbbase = ahb_info->start[0]; - - /* APB SLAVES */ - apb = (struct ambapp_pnp_apb *) - (apbbase | AMBA_CONF_AREA); - for (j=0; jmmaps, - &apb_buf, apbdev, ahbidx); - - if (prevapb != dev) - prevapb->next = apbdev; - else - dev->children = apbdev; - apbdev->prev = prevapb; - prevapb = apbdev; - } - } - } - - /* Remember first AHB MST/SLV device on bus and Parent Bridge */ - abus->ahbs[ahbidx].dev = *root; - abus->ahbs[ahbidx].bridge = parent; - - return 0; -} - -/* Build AMBA Plug & Play device graph */ -int ambapp_scan( - struct ambapp_bus *abus, - unsigned int ioarea, - ambapp_memcpy_t memfunc, - struct ambapp_mmap *mmaps - ) -{ - memset(abus, 0, sizeof(*abus)); - abus->mmaps = mmaps; - - /* Default to memcpy() */ - if (!memfunc) - memfunc = (ambapp_memcpy_t)memcpy; - - return ambapp_scan2(abus, ioarea, memfunc, NULL, &abus->root); -} - -/* Match search options againt device */ -static int ambapp_dev_match_options(struct ambapp_dev *dev, unsigned int options, int vendor, int device) -{ - if ((((options & (OPTIONS_ALL_DEVS)) == OPTIONS_ALL_DEVS) || /* TYPE */ - ((options & OPTIONS_AHB_MSTS) && (dev->dev_type == DEV_AHB_MST)) || - ((options & OPTIONS_AHB_SLVS) && (dev->dev_type == DEV_AHB_SLV)) || - ((options & OPTIONS_APB_SLVS) && (dev->dev_type == DEV_APB_SLV))) && - ((vendor == -1) || (vendor == dev->vendor)) && /* VENDOR/DEV ID */ - ((device == -1) || (device == dev->device)) && - (((options & OPTIONS_ALL) == OPTIONS_ALL) || /* Allocated State */ - ((options & OPTIONS_FREE) && DEV_IS_FREE(dev)) || - ((options & OPTIONS_ALLOCATED) && DEV_IS_ALLOCATED(dev)))) { - return 1; - } - return 0; -} - -/* If device is an APB bridge all devices on the APB bridge is processed */ -static int ambapp_for_each_apb( - struct ambapp_dev *dev, - unsigned int options, - int vendor, - int device, - ambapp_func_t func, - void *arg) -{ - int index, ret; - struct ambapp_dev *apbslv; - - ret = 0; - if (dev->children && (dev->children->dev_type == DEV_APB_SLV)) { - /* Found a APB Bridge */ - index = 0; - apbslv = dev->children; - while (apbslv) { - if (ambapp_dev_match_options(apbslv, options, - vendor, device) == 1) { - ret = func(apbslv, index, arg); - if (ret != 0) - break; /* Signalled stopped */ - } - index++; - apbslv = apbslv->next; - } - } - - return ret; -} - -/* Traverse the prescanned device information */ -static int ambapp_for_each_dev( - struct ambapp_dev *root, - unsigned int options, - int vendor, - int device, - ambapp_func_t func, - void *arg) -{ - struct ambapp_dev *dev; - int ahb_slave = 0; - int index, ret; - - /* Start at device 'root' and process downwards. - * - * Breadth first search, search order - * 1. AHB MSTS - * 2. AHB SLVS - * 3. APB SLVS on primary bus - * 4. AHB/AHB secondary... -> step to 1. - */ - - /* AHB MST / AHB SLV */ - if (options & (OPTIONS_AHB_MSTS|OPTIONS_AHB_SLVS|OPTIONS_DEPTH_FIRST)) { - index = 0; - dev = root; - while (dev) { - if ((dev->dev_type == DEV_AHB_SLV) && !ahb_slave) { - /* First AHB Slave */ - ahb_slave = 1; - index = 0; - } - - /* Conditions must be fullfilled for function to be - * called - */ - if (ambapp_dev_match_options(dev, options, vendor, device) == 1) { - /* Correct device and vendor ID */ - ret = func(dev, index, arg); - if (ret != 0) - return ret; /* Signalled stopped */ - } - - if ((options & OPTIONS_DEPTH_FIRST) && (options & OPTIONS_APB_SLVS)) { - /* Check is APB bridge, and process all APB - * Slaves in that case - */ - ret = ambapp_for_each_apb(dev, options, vendor, device, func, arg); - if (ret != 0) - return ret; /* Signalled stopped */ - } - - if (options & OPTIONS_DEPTH_FIRST) { - if (dev->children && (dev->children->dev_type != DEV_APB_SLV)) { - /* Found AHB Bridge, recurse */ - ret = ambapp_for_each_dev(dev->children, options, vendor, device, - func, arg); - if (ret != 0) - return ret; - } - } - - index++; - dev = dev->next; - } - } - - /* Find APB Bridges */ - if ((options & OPTIONS_APB_SLVS) && !(options & OPTIONS_DEPTH_FIRST)) { - dev = root; - while (dev) { - /* Check is APB bridge, and process all APB Slaves in - * that case - */ - ret = ambapp_for_each_apb(dev, options, vendor, device, func, arg); - if (ret != 0) - return ret; /* Signalled stopped */ - dev = dev->next; - } - } - - /* Find AHB Bridges */ - if (!(options & OPTIONS_DEPTH_FIRST)) { - dev = root; - while (dev) { - if (dev->children && (dev->children->dev_type != DEV_APB_SLV)) { - /* Found AHB Bridge, recurse */ - ret = ambapp_for_each_dev(dev->children, options, vendor, device, - func, arg); - if (ret != 0) - return ret; - } - dev = dev->next; - } - } - - return 0; -} - -int ambapp_for_each( - struct ambapp_bus *abus, - unsigned int options, - int vendor, - int device, - ambapp_func_t func, - void *arg) -{ - return ambapp_for_each_dev(abus->root, options, vendor, device, func, arg); -} diff --git a/c/src/lib/libbsp/sparc/shared/amba/ambapp_alloc.c b/c/src/lib/libbsp/sparc/shared/amba/ambapp_alloc.c deleted file mode 100644 index 2357f697b9..0000000000 --- a/c/src/lib/libbsp/sparc/shared/amba/ambapp_alloc.c +++ /dev/null @@ -1,25 +0,0 @@ -/* - * AMBA Plug & Play routines - * - * COPYRIGHT (c) 2011 - * Aeroflex Gaisler - * - * 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 - -int ambapp_alloc_dev(struct ambapp_dev *dev, void *owner) -{ - if (dev->owner) - return -1; - dev->owner = owner; - return 0; -} - -void ambapp_free_dev(struct ambapp_dev *dev) -{ - dev->owner = 0; -} diff --git a/c/src/lib/libbsp/sparc/shared/amba/ambapp_count.c b/c/src/lib/libbsp/sparc/shared/amba/ambapp_count.c deleted file mode 100644 index 4e3a1dc102..0000000000 --- a/c/src/lib/libbsp/sparc/shared/amba/ambapp_count.c +++ /dev/null @@ -1,23 +0,0 @@ -/* - * AMBA Plug & Play routines - * - * COPYRIGHT (c) 2011 - * Aeroflex Gaisler - * - * 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 - -/* Get number of devices matching search options */ -int ambapp_dev_count(struct ambapp_bus *abus, unsigned int options, - int vendor, int device) -{ - int count = 10000; - - ambapp_for_each(abus, options, vendor, device, ambapp_find_by_idx, &count); - - return 10000 - count; -} diff --git a/c/src/lib/libbsp/sparc/shared/amba/ambapp_depth.c b/c/src/lib/libbsp/sparc/shared/amba/ambapp_depth.c deleted file mode 100644 index 8a96afbee6..0000000000 --- a/c/src/lib/libbsp/sparc/shared/amba/ambapp_depth.c +++ /dev/null @@ -1,25 +0,0 @@ -/* - * AMBA Plug & Play routines - * - * COPYRIGHT (c) 2011 - * Aeroflex Gaisler - * - * 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 - -/* Get bus depth a device is located at */ -int ambapp_depth(struct ambapp_dev *dev) -{ - int depth = 0; - - do { - dev = ambapp_find_parent(dev); - depth++; - } while (dev); - - return depth - 1; -} diff --git a/c/src/lib/libbsp/sparc/shared/amba/ambapp_find_by_idx.c b/c/src/lib/libbsp/sparc/shared/amba/ambapp_find_by_idx.c deleted file mode 100644 index 6b2d28824c..0000000000 --- a/c/src/lib/libbsp/sparc/shared/amba/ambapp_find_by_idx.c +++ /dev/null @@ -1,39 +0,0 @@ -/* - * AMBA Plug & Play routines - * - * COPYRIGHT (c) 2011 - * Aeroflex Gaisler - * - * 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 - -/* AMBAPP helper routine to find a device by index. The function is given to - * ambapp_for_each, the argument may be NULL (find first device) or a pointer - * to a index which is downcounted until 0 is reached. If the int-pointer - * points to a value of: - * 0 - first device is returned - * 1 - second device is returned - * ... - * - * The matching device is returned, which will stop the ambapp_for_each search. - * If zero is returned from ambapp_for_each no device matching the index was - * found - */ -int ambapp_find_by_idx(struct ambapp_dev *dev, int index, void *pcount) -{ - int *pi = pcount; - - if (pi) { - if ((*pi)-- == 0) - return (int)dev; - else - return 0; - } else { - /* Satisfied with first matching device, stop search */ - return (int)dev; - } -} diff --git a/c/src/lib/libbsp/sparc/shared/amba/ambapp_freq.c b/c/src/lib/libbsp/sparc/shared/amba/ambapp_freq.c deleted file mode 100644 index 59db15f865..0000000000 --- a/c/src/lib/libbsp/sparc/shared/amba/ambapp_freq.c +++ /dev/null @@ -1,109 +0,0 @@ -/* - * AMBA Plug & Play routines - * - * COPYRIGHT (c) 2011 - * Aeroflex Gaisler - * - * 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 - -/* Calculate AHB Bus frequency of - * - Bus[0] (inverse=1), relative to the frequency of Bus[ahbidx] - * NOTE: set freq_hz to frequency of Bus[ahbidx]. - * or - * - Bus[ahbidx] (inverse=0), relative to the frequency of Bus[0] - * NOTE: set freq_hz to frequency of Bus[0]. - * - * If a unsupported bridge is found the invalid frequncy of 0Hz is - * returned. - */ -static unsigned int ambapp_freq_calc( - struct ambapp_bus *abus, - int ahbidx, - unsigned int freq_hz, - int inverse) -{ - struct ambapp_ahb_info *ahb; - struct ambapp_dev *bridge; - unsigned char ffact; - int dir; - - /* Found Bus0? */ - bridge = abus->ahbs[ahbidx].bridge; - if (!bridge) - return freq_hz; - - /* Find this bus frequency relative to freq_hz */ - if ((bridge->vendor == VENDOR_GAISLER) && - ((bridge->device == GAISLER_AHB2AHB) || - (bridge->device == GAISLER_L2CACHE))) { - ahb = DEV_TO_AHB(bridge); - ffact = (ahb->custom[0] & AMBAPP_FLAG_FFACT) >> 4; - if (ffact != 0) { - dir = ahb->custom[0] & AMBAPP_FLAG_FFACT_DIR; - - /* Calculate frequency by dividing or - * multiplying system frequency - */ - if ((dir && !inverse) || (!dir && inverse)) - freq_hz = freq_hz * ffact; - else - freq_hz = freq_hz / ffact; - } - return ambapp_freq_calc(abus, ahb->ahbidx, freq_hz, inverse); - } else { - /* Unknown bridge, impossible to calc frequency */ - return 0; - } -} - -/* Find the frequency of all AHB Buses from knowing the frequency of one - * particular APB/AHB Device. - */ -void ambapp_freq_init( - struct ambapp_bus *abus, - struct ambapp_dev *dev, - unsigned int freq_hz) -{ - struct ambapp_common_info *info; - int i; - - for (i=0; iahbs[i].freq_hz = 0; - - /* Register Frequency at the AHB bus that the device the user gave us - * is located at. - */ - if (dev) { - info = DEV_TO_COMMON(dev); - abus->ahbs[info->ahbidx].freq_hz = freq_hz; - - /* Find Frequency of Bus 0 */ - abus->ahbs[0].freq_hz = ambapp_freq_calc(abus, info->ahbidx, freq_hz, 1); - } else { - abus->ahbs[0].freq_hz = freq_hz; - } - - /* Find Frequency of all except for Bus0 and the bus which frequency - * was reported at - */ - for (i=1; iahbs[i].ioarea == 0) - break; - if (abus->ahbs[i].freq_hz != 0) - continue; - abus->ahbs[i].freq_hz = ambapp_freq_calc(abus, i, abus->ahbs[0].freq_hz, 0); - } -} - -/* Assign a AMBA Bus a frequency but reporting the frequency of a - * particular AHB/APB device */ -unsigned int ambapp_freq_get(struct ambapp_bus *abus, struct ambapp_dev *dev) -{ - struct ambapp_common_info *info = DEV_TO_COMMON(dev); - return abus->ahbs[info->ahbidx].freq_hz; -} diff --git a/c/src/lib/libbsp/sparc/shared/amba/ambapp_names.c b/c/src/lib/libbsp/sparc/shared/amba/ambapp_names.c deleted file mode 100644 index 5539d3c489..0000000000 --- a/c/src/lib/libbsp/sparc/shared/amba/ambapp_names.c +++ /dev/null @@ -1,447 +0,0 @@ -/* - * AMBA Plug & Play Device and Vendor name database: Created from GRLIB 3386. - * - * COPYRIGHT (c) 2009. - * Aeroflex Gaisler. - * - * The device and vendor definitions are extracted with a script from - * GRLIB. - * - * 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 - -#ifndef NULL -#define NULL 0 -#endif - -typedef struct { - int device_id; - char *name; -} ambapp_device_name; - -typedef struct { - unsigned int vendor_id; - char *name; - ambapp_device_name *devices; -} ambapp_vendor_devnames; - -/**************** AUTO GENERATED FROM devices.vhd ****************/ -static ambapp_device_name GAISLER_devices[] = -{ - {GAISLER_LEON2DSU, "LEON2DSU"}, - {GAISLER_LEON3, "LEON3"}, - {GAISLER_LEON3DSU, "LEON3DSU"}, - {GAISLER_ETHAHB, "ETHAHB"}, - {GAISLER_APBMST, "APBMST"}, - {GAISLER_AHBUART, "AHBUART"}, - {GAISLER_SRCTRL, "SRCTRL"}, - {GAISLER_SDCTRL, "SDCTRL"}, - {GAISLER_SSRCTRL, "SSRCTRL"}, - {GAISLER_I2C2AHB, "I2C2AHB"}, - {GAISLER_APBUART, "APBUART"}, - {GAISLER_IRQMP, "IRQMP"}, - {GAISLER_AHBRAM, "AHBRAM"}, - {GAISLER_AHBDPRAM, "AHBDPRAM"}, - {GAISLER_GRIOMMU2, "GRIOMMU2"}, - {GAISLER_GPTIMER, "GPTIMER"}, - {GAISLER_PCITRG, "PCITRG"}, - {GAISLER_PCISBRG, "PCISBRG"}, - {GAISLER_PCIFBRG, "PCIFBRG"}, - {GAISLER_PCITRACE, "PCITRACE"}, - {GAISLER_DMACTRL, "DMACTRL"}, - {GAISLER_AHBTRACE, "AHBTRACE"}, - {GAISLER_DSUCTRL, "DSUCTRL"}, - {GAISLER_CANAHB, "CANAHB"}, - {GAISLER_GPIO, "GPIO"}, - {GAISLER_AHBROM, "AHBROM"}, - {GAISLER_AHBJTAG, "AHBJTAG"}, - {GAISLER_ETHMAC, "ETHMAC"}, - {GAISLER_SWNODE, "SWNODE"}, - {GAISLER_SPW, "SPW"}, - {GAISLER_AHB2AHB, "AHB2AHB"}, - {GAISLER_USBDC, "USBDC"}, - {GAISLER_USB_DCL, "USB_DCL"}, - {GAISLER_DDRMP, "DDRMP"}, - {GAISLER_ATACTRL, "ATACTRL"}, - {GAISLER_DDRSP, "DDRSP"}, - {GAISLER_EHCI, "EHCI"}, - {GAISLER_UHCI, "UHCI"}, - {GAISLER_I2CMST, "I2CMST"}, - {GAISLER_SPW2, "SPW2"}, - {GAISLER_AHBDMA, "AHBDMA"}, - {GAISLER_NUHOSP3, "NUHOSP3"}, - {GAISLER_CLKGATE, "CLKGATE"}, - {GAISLER_SPICTRL, "SPICTRL"}, - {GAISLER_DDR2SP, "DDR2SP"}, - {GAISLER_SLINK, "SLINK"}, - {GAISLER_GRTM, "GRTM"}, - {GAISLER_GRTC, "GRTC"}, - {GAISLER_GRPW, "GRPW"}, - {GAISLER_GRCTM, "GRCTM"}, - {GAISLER_GRHCAN, "GRHCAN"}, - {GAISLER_GRFIFO, "GRFIFO"}, - {GAISLER_GRADCDAC, "GRADCDAC"}, - {GAISLER_GRPULSE, "GRPULSE"}, - {GAISLER_GRTIMER, "GRTIMER"}, - {GAISLER_AHB2PP, "AHB2PP"}, - {GAISLER_GRVERSION, "GRVERSION"}, - {GAISLER_APB2PW, "APB2PW"}, - {GAISLER_PW2APB, "PW2APB"}, - {GAISLER_GRCAN, "GRCAN"}, - {GAISLER_I2CSLV, "I2CSLV"}, - {GAISLER_U16550, "U16550"}, - {GAISLER_AHBMST_EM, "AHBMST_EM"}, - {GAISLER_AHBSLV_EM, "AHBSLV_EM"}, - {GAISLER_GRTESTMOD, "GRTESTMOD"}, - {GAISLER_ASCS, "ASCS"}, - {GAISLER_IPMVBCTRL, "IPMVBCTRL"}, - {GAISLER_SPIMCTRL, "SPIMCTRL"}, - {GAISLER_L4STAT, "L4STAT"}, - {GAISLER_LEON4, "LEON4"}, - {GAISLER_LEON4DSU, "LEON4DSU"}, - {GAISLER_PWM, "PWM"}, - {GAISLER_L2CACHE, "L2CACHE"}, - {GAISLER_SDCTRL64, "SDCTRL64"}, - {GAISLER_GR1553B, "GR1553B"}, - {GAISLER_1553TST, "1553TST"}, - {GAISLER_GRIOMMU, "GRIOMMU"}, - {GAISLER_FTAHBRAM, "FTAHBRAM"}, - {GAISLER_FTSRCTRL, "FTSRCTRL"}, - {GAISLER_AHBSTAT, "AHBSTAT"}, - {GAISLER_LEON3FT, "LEON3FT"}, - {GAISLER_FTMCTRL, "FTMCTRL"}, - {GAISLER_FTSDCTRL, "FTSDCTRL"}, - {GAISLER_FTSRCTRL8, "FTSRCTRL8"}, - {GAISLER_MEMSCRUB, "MEMSCRUB"}, - {GAISLER_FTSDCTRL64, "FTSDCTRL64"}, - {GAISLER_NANDFCTRL, "NANDFCTRL"}, - {GAISLER_N2DLLCTRL, "N2DLLCTRL"}, - {GAISLER_N2PLLCTRL, "N2PLLCTRL"}, - {GAISLER_SPI2AHB, "SPI2AHB"}, - {GAISLER_DDRSDMUX, "DDRSDMUX"}, - {GAISLER_AHBFROM, "AHBFROM"}, - {GAISLER_PCIEXP, "PCIEXP"}, - {GAISLER_APBPS2, "APBPS2"}, - {GAISLER_VGACTRL, "VGACTRL"}, - {GAISLER_LOGAN, "LOGAN"}, - {GAISLER_SVGACTRL, "SVGACTRL"}, - {GAISLER_T1AHB, "T1AHB"}, - {GAISLER_MP7WRAP, "MP7WRAP"}, - {GAISLER_GRSYSMON, "GRSYSMON"}, - {GAISLER_GRACECTRL, "GRACECTRL"}, - {GAISLER_ATAHBSLV, "ATAHBSLV"}, - {GAISLER_ATAHBMST, "ATAHBMST"}, - {GAISLER_ATAPBSLV, "ATAPBSLV"}, - {GAISLER_MIGDDR2, "MIGDDR2"}, - {GAISLER_LCDCTRL, "LCDCTRL"}, - {GAISLER_SWITCHOVER, "SWITCHOVER"}, - {GAISLER_FIFOUART, "FIFOUART"}, - {GAISLER_MUXCTRL, "MUXCTRL"}, - {GAISLER_B1553BC, "B1553BC"}, - {GAISLER_B1553RT, "B1553RT"}, - {GAISLER_B1553BRM, "B1553BRM"}, - {GAISLER_AES, "AES"}, - {GAISLER_ECC, "ECC"}, - {GAISLER_PCIF, "PCIF"}, - {GAISLER_CLKMOD, "CLKMOD"}, - {GAISLER_HAPSTRAK, "HAPSTRAK"}, - {GAISLER_TEST_1X2, "TEST_1X2"}, - {GAISLER_WILD2AHB, "WILD2AHB"}, - {GAISLER_BIO1, "BIO1"}, - {GAISLER_AESDMA, "AESDMA"}, - {GAISLER_GRPCI2, "GRPCI2"}, - {GAISLER_GRPCI2_DMA, "GRPCI2_DMA"}, - {GAISLER_GRPCI2_TB, "GRPCI2_TB"}, - {GAISLER_MMA, "MMA"}, - {GAISLER_SATCAN, "SATCAN"}, - {GAISLER_CANMUX, "CANMUX"}, - {GAISLER_GRTMRX, "GRTMRX"}, - {GAISLER_GRTCTX, "GRTCTX"}, - {GAISLER_GRTMDESC, "GRTMDESC"}, - {GAISLER_GRTMVC, "GRTMVC"}, - {GAISLER_GEFFE, "GEFFE"}, - {GAISLER_GPREG, "GPREG"}, - {GAISLER_GRTMPAHB, "GRTMPAHB"}, - {GAISLER_SPWCUC, "SPWCUC"}, - {GAISLER_SPW2_DMA, "SPW2_DMA"}, - {GAISLER_SPWROUTER, "SPWROUTER"}, - {GAISLER_EDCLMST, "EDCLMST"}, - {GAISLER_GRPWTX, "GRPWTX"}, - {GAISLER_GRPWRX, "GRPWRX"}, - {GAISLER_GPREGBANK, "GPREGBANK"}, - {GAISLER_MIG_7SERIES, "MIG_7SERIES"}, - {GAISLER_GRSPW2_SIST, "GRSPW2_SIST"}, - {GAISLER_SGMII, "SGMII"}, - {GAISLER_RGMII, "RGMII"}, - {GAISLER_IRQGEN, "IRQGEN"}, - {GAISLER_GRDMAC, "GRDMAC"}, - {GAISLER_AHB2AVLA, "AHB2AVLA"}, - {GAISLER_SPWTDP, "SPWTDP"}, - {GAISLER_L3STAT, "L3STAT"}, - {GAISLER_GR740THS, "GR740THS"}, - {GAISLER_GRRM, "GRRM"}, - {GAISLER_CMAP, "CMAP"}, - {GAISLER_CPGEN, "CPGEN"}, - {GAISLER_AMBAPROT, "AMBAPROT"}, - {GAISLER_IGLOO2_BRIDGE, "IGLOO2_BRIDGE"}, - {GAISLER_AHB2AXI, "AHB2AXI"}, - {GAISLER_AXI2AHB, "AXI2AHB"}, - {GAISLER_FDIR_RSTCTRL, "FDIR_RSTCTRL"}, - {GAISLER_APB3MST, "APB3MST"}, - {GAISLER_LRAM, "LRAM"}, - {GAISLER_BOOTSEQ, "BOOTSEQ"}, - {GAISLER_TCCOP, "TCCOP"}, - {GAISLER_SPIMASTER, "SPIMASTER"}, - {GAISLER_SPISLAVE, "SPISLAVE"}, - {GAISLER_GRSRIO, "GRSRIO"}, - {0, NULL} -}; - -static ambapp_device_name PENDER_devices[] = -{ - {0, NULL} -}; - -static ambapp_device_name ESA_devices[] = -{ - {ESA_LEON2, "LEON2"}, - {ESA_LEON2APB, "LEON2APB"}, - {ESA_IRQ, "IRQ"}, - {ESA_TIMER, "TIMER"}, - {ESA_UART, "UART"}, - {ESA_CFG, "CFG"}, - {ESA_IO, "IO"}, - {ESA_MCTRL, "MCTRL"}, - {ESA_PCIARB, "PCIARB"}, - {ESA_HURRICANE, "HURRICANE"}, - {ESA_SPW_RMAP, "SPW_RMAP"}, - {ESA_AHBUART, "AHBUART"}, - {ESA_SPWA, "SPWA"}, - {ESA_BOSCHCAN, "BOSCHCAN"}, - {ESA_IRQ2, "IRQ2"}, - {ESA_AHBSTAT, "AHBSTAT"}, - {ESA_WPROT, "WPROT"}, - {ESA_WPROT2, "WPROT2"}, - {ESA_PDEC3AMBA, "PDEC3AMBA"}, - {ESA_PTME3AMBA, "PTME3AMBA"}, - {0, NULL} -}; - -static ambapp_device_name ASTRIUM_devices[] = -{ - {0, NULL} -}; - -static ambapp_device_name OPENCHIP_devices[] = -{ - {OPENCHIP_APBGPIO, "APBGPIO"}, - {OPENCHIP_APBI2C, "APBI2C"}, - {OPENCHIP_APBSPI, "APBSPI"}, - {OPENCHIP_APBCHARLCD, "APBCHARLCD"}, - {OPENCHIP_APBPWM, "APBPWM"}, - {OPENCHIP_APBPS2, "APBPS2"}, - {OPENCHIP_APBMMCSD, "APBMMCSD"}, - {OPENCHIP_APBNAND, "APBNAND"}, - {OPENCHIP_APBLPC, "APBLPC"}, - {OPENCHIP_APBCF, "APBCF"}, - {OPENCHIP_APBSYSACE, "APBSYSACE"}, - {OPENCHIP_APB1WIRE, "APB1WIRE"}, - {OPENCHIP_APBJTAG, "APBJTAG"}, - {OPENCHIP_APBSUI, "APBSUI"}, - {0, NULL} -}; - -static ambapp_device_name OPENCORES_devices[] = -{ - {0, NULL} -}; - -static ambapp_device_name CONTRIB_devices[] = -{ - {CONTRIB_CORE1, "CORE1"}, - {CONTRIB_CORE2, "CORE2"}, - {0, NULL} -}; - -static ambapp_device_name EONIC_devices[] = -{ - {0, NULL} -}; - -static ambapp_device_name RADIONOR_devices[] = -{ - {0, NULL} -}; - -static ambapp_device_name GLEICHMANN_devices[] = -{ - {GLEICHMANN_CUSTOM, "CUSTOM"}, - {GLEICHMANN_GEOLCD01, "GEOLCD01"}, - {GLEICHMANN_DAC, "DAC"}, - {GLEICHMANN_HPI, "HPI"}, - {GLEICHMANN_SPI, "SPI"}, - {GLEICHMANN_HIFC, "HIFC"}, - {GLEICHMANN_ADCDAC, "ADCDAC"}, - {GLEICHMANN_SPIOC, "SPIOC"}, - {GLEICHMANN_AC97, "AC97"}, - {0, NULL} -}; - -static ambapp_device_name MENTA_devices[] = -{ - {0, NULL} -}; - -static ambapp_device_name SUN_devices[] = -{ - {SUN_T1, "SUN_T1"}, - {SUN_S1, "SUN_S1"}, - {0, NULL} -}; - -static ambapp_device_name MOVIDIA_devices[] = -{ - {0, NULL} -}; - -static ambapp_device_name ORBITA_devices[] = -{ - {ORBITA_1553B, "1553B"}, - {ORBITA_429, "429"}, - {ORBITA_SPI, "SPI"}, - {ORBITA_I2C, "I2C"}, - {ORBITA_SMARTCARD, "SMARTCARD"}, - {ORBITA_SDCARD, "SDCARD"}, - {ORBITA_UART16550, "UART16550"}, - {ORBITA_CRYPTO, "CRYPTO"}, - {ORBITA_SYSIF, "SYSIF"}, - {ORBITA_PIO, "PIO"}, - {ORBITA_RTC, "RTC"}, - {ORBITA_COLORLCD, "COLORLCD"}, - {ORBITA_PCI, "PCI"}, - {ORBITA_DSP, "DSP"}, - {ORBITA_USBHOST, "USBHOST"}, - {ORBITA_USBDEV, "USBDEV"}, - {0, NULL} -}; - -static ambapp_device_name SYNOPSYS_devices[] = -{ - {0, NULL} -}; - -static ambapp_device_name NASA_devices[] = -{ - {NASA_EP32, "EP32"}, - {0, NULL} -}; - -static ambapp_device_name CAL_devices[] = -{ - {CAL_DDRCTRL, "DDRCTRL"}, - {0, NULL} -}; - -static ambapp_device_name EMBEDDIT_devices[] = -{ - {0, NULL} -}; - -static ambapp_device_name CETON_devices[] = -{ - {0, NULL} -}; - -static ambapp_device_name ACTEL_devices[] = -{ - {ACTEL_COREMP7, "COREMP7"}, - {0, NULL} -}; - -static ambapp_vendor_devnames vendors[] = -{ - {VENDOR_GAISLER, "GAISLER", GAISLER_devices}, - {VENDOR_PENDER, "PENDER", PENDER_devices}, - {VENDOR_ESA, "ESA", ESA_devices}, - {VENDOR_ASTRIUM, "ASTRIUM", ASTRIUM_devices}, - {VENDOR_OPENCHIP, "OPENCHIP", OPENCHIP_devices}, - {VENDOR_OPENCORES, "OPENCORES", OPENCORES_devices}, - {VENDOR_CONTRIB, "CONTRIB", CONTRIB_devices}, - {VENDOR_EONIC, "EONIC", EONIC_devices}, - {VENDOR_RADIONOR, "RADIONOR", RADIONOR_devices}, - {VENDOR_GLEICHMANN, "GLEICHMANN", GLEICHMANN_devices}, - {VENDOR_MENTA, "MENTA", MENTA_devices}, - {VENDOR_SUN, "SUN", SUN_devices}, - {VENDOR_MOVIDIA, "MOVIDIA", MOVIDIA_devices}, - {VENDOR_ORBITA, "ORBITA", ORBITA_devices}, - {VENDOR_SYNOPSYS, "SYNOPSYS", SYNOPSYS_devices}, - {VENDOR_NASA, "NASA", NASA_devices}, - {VENDOR_CAL, "CAL", CAL_devices}, - {VENDOR_EMBEDDIT, "EMBEDDIT", EMBEDDIT_devices}, - {VENDOR_CETON, "CETON", CETON_devices}, - {VENDOR_ACTEL, "ACTEL", ACTEL_devices}, - {0, NULL, NULL} -}; - -/*****************************************************************/ - -static char *ambapp_get_devname(ambapp_device_name *devs, int id) -{ - while (devs->device_id > 0) { - if (devs->device_id == id) - return devs->name; - devs++; - } - return NULL; -} - -char *ambapp_device_id2str(int vendor, int id) -{ - ambapp_vendor_devnames *ven = &vendors[0]; - - while (ven->vendor_id > 0) { - if (ven->vendor_id == vendor) - return ambapp_get_devname(ven->devices, id); - ven++; - } - return NULL; -} - -char *ambapp_vendor_id2str(int vendor) -{ - ambapp_vendor_devnames *ven = &vendors[0]; - - while (ven->vendor_id > 0) { - if (ven->vendor_id == vendor) - return ven->name; - ven++; - } - return NULL; -} - -int ambapp_vendev_id2str(int vendor, int id, char *buf) -{ - char *dstr, *vstr; - - *buf = '\0'; - - vstr = ambapp_vendor_id2str(vendor); - if (vstr == NULL) - return 0; - - dstr = ambapp_device_id2str(vendor, id); - if (dstr == NULL) - return 0; - - strcpy(buf, vstr); - strcat(buf, "_"); - strcat(buf, dstr); - - return strlen(buf); -} diff --git a/c/src/lib/libbsp/sparc/shared/amba/ambapp_old.c b/c/src/lib/libbsp/sparc/shared/amba/ambapp_old.c deleted file mode 100644 index 2be77a484f..0000000000 --- a/c/src/lib/libbsp/sparc/shared/amba/ambapp_old.c +++ /dev/null @@ -1,112 +0,0 @@ -/* - * Old AMBA scanning Interface provided for backwards compability - * - * COPYRIGHT (c) 2011 - * Aeroflex Gaisler - * - * 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 - -struct ambapp_dev_find_match_arg { - int index; - int count; - int type; - void *dev; -}; - -/* AMBA PP find routines */ -static int ambapp_dev_find_match(struct ambapp_dev *dev, int index, void *arg) -{ - struct ambapp_dev_find_match_arg *p = arg; - - if (p->index == 0) { - /* Found controller, stop */ - if (p->type == DEV_APB_SLV) { - *(struct ambapp_apb_info *)p->dev = *DEV_TO_APB(dev); - p->dev = ((struct ambapp_apb_info *)p->dev)+1; - } else { - *(struct ambapp_ahb_info *)p->dev = *DEV_TO_AHB(dev); - p->dev = ((struct ambapp_ahb_info *)p->dev)+1; - } - p->count--; - if (p->count < 1) - return 1; - } else { - p->index--; - } - return 0; -} - -int ambapp_find_apbslvs_next(struct ambapp_bus *abus, int vendor, int device, struct ambapp_apb_info *dev, int index, int maxno) -{ - struct ambapp_dev_find_match_arg arg; - - arg.index = index; - arg.count = maxno; - arg.type = DEV_APB_SLV; /* APB */ - arg.dev = dev; - - ambapp_for_each(abus, (OPTIONS_ALL|OPTIONS_APB_SLVS), vendor, device, - ambapp_dev_find_match, &arg); - - return maxno - arg.count; -} - -int ambapp_find_apbslv(struct ambapp_bus *abus, int vendor, int device, struct ambapp_apb_info *dev) -{ - return ambapp_find_apbslvs_next(abus, vendor, device, dev, 0, 1); -} - -int ambapp_find_apbslv_next(struct ambapp_bus *abus, int vendor, int device, struct ambapp_apb_info *dev, int index) -{ - return ambapp_find_apbslvs_next(abus, vendor, device, dev, index, 1); -} - -int ambapp_find_apbslvs(struct ambapp_bus *abus, int vendor, int device, struct ambapp_apb_info *dev, int maxno) -{ - return ambapp_find_apbslvs_next(abus, vendor, device, dev, 0, maxno); -} - -int ambapp_get_number_apbslv_devices(struct ambapp_bus *abus, int vendor, int device) -{ - return ambapp_dev_count(abus, (OPTIONS_ALL|OPTIONS_APB_SLVS), vendor, device); -} - -int ambapp_find_ahbslvs_next(struct ambapp_bus *abus, int vendor, int device, struct ambapp_ahb_info *dev, int index, int maxno) -{ - struct ambapp_dev_find_match_arg arg; - - arg.index = index; - arg.count = maxno; - arg.type = DEV_AHB_SLV; /* AHB SLV */ - arg.dev = dev; - - ambapp_for_each(abus, (OPTIONS_ALL|OPTIONS_AHB_SLVS), vendor, device, - ambapp_dev_find_match, &arg); - - return maxno - arg.count; -} - -int ambapp_find_ahbslv_next(struct ambapp_bus *abus, int vendor, int device, struct ambapp_ahb_info *dev, int index) -{ - return ambapp_find_ahbslvs_next(abus, vendor, device, dev, index, 1); -} - -int ambapp_find_ahbslv(struct ambapp_bus *abus, int vendor, int device, struct ambapp_ahb_info *dev) -{ - return ambapp_find_ahbslvs_next(abus, vendor, device, dev, 0, 1); -} - -int ambapp_find_ahbslvs(struct ambapp_bus *abus, int vendor, int device, struct ambapp_ahb_info *dev, int maxno) -{ - return ambapp_find_ahbslvs_next(abus, vendor, device, dev, 0, maxno); -} - -int ambapp_get_number_ahbslv_devices(struct ambapp_bus *abus, int vendor, int device) -{ - return ambapp_dev_count(abus, (OPTIONS_ALL|OPTIONS_AHB_SLVS), vendor, device); -} diff --git a/c/src/lib/libbsp/sparc/shared/amba/ambapp_parent.c b/c/src/lib/libbsp/sparc/shared/amba/ambapp_parent.c deleted file mode 100644 index 6064b4a165..0000000000 --- a/c/src/lib/libbsp/sparc/shared/amba/ambapp_parent.c +++ /dev/null @@ -1,23 +0,0 @@ -/* - * AMBA Plug & Play routines - * - * COPYRIGHT (c) 2011 - * Aeroflex Gaisler - * - * 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 - -struct ambapp_dev *ambapp_find_parent(struct ambapp_dev *dev) -{ - while (dev->prev) { - if (dev == dev->prev->children) - return dev->prev; - dev = dev->prev; - } - return NULL; -} diff --git a/c/src/lib/libbsp/sparc/shared/amba/ambapp_show.c b/c/src/lib/libbsp/sparc/shared/amba/ambapp_show.c deleted file mode 100644 index 1ed15c643e..0000000000 --- a/c/src/lib/libbsp/sparc/shared/amba/ambapp_show.c +++ /dev/null @@ -1,68 +0,0 @@ -/* - * AMBA Plug & Play routines: device information printing. - * - * COPYRIGHT (c) 2009. - * Aeroflex Gaisler. - * - * 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 - -struct ambapp_dev_print_arg { - int show_depth; -}; - -static char *unknown = "unknown"; - -static int ambapp_dev_print(struct ambapp_dev *dev, int index, void *arg) -{ - char *dev_str, *ven_str, *type_str; - struct ambapp_dev_print_arg *p = arg; - char dp[32]; - int i=0; - unsigned int basereg; - - if (p->show_depth) { - for (i=0; ivendor); - if (!ven_str) { - ven_str = unknown; - dev_str = unknown; - } else { - dev_str = ambapp_device_id2str(dev->vendor, dev->device); - if (!dev_str) - dev_str = unknown; - } - if (dev->dev_type == DEV_APB_SLV) { - /* APB */ - basereg = DEV_TO_APB(dev)->start; - type_str = "apb"; - } else { - /* AHB */ - basereg = DEV_TO_AHB(dev)->start[0]; - type_str = "ahb"; - } - printf("%s |-> 0x%x:0x%x:0x%x: %s_%s, %s: 0x%x, 0x%x (OWNER: 0x%x)\n", - dp, index, dev->vendor, dev->device, ven_str, dev_str, type_str, - basereg, (unsigned int)dev, (unsigned int)dev->owner); - - return 0; -} - -void ambapp_print(struct ambapp_bus *abus, int show_depth) -{ - struct ambapp_dev_print_arg arg; - arg.show_depth = show_depth; - ambapp_for_each(abus, (OPTIONS_ALL_DEVS|OPTIONS_ALL|OPTIONS_DEPTH_FIRST), -1, - -1, ambapp_dev_print, &arg); -} diff --git a/c/src/lib/libbsp/sparc/shared/analog/gradcdac.c b/c/src/lib/libbsp/sparc/shared/analog/gradcdac.c deleted file mode 100644 index 07fb2ee9dd..0000000000 --- a/c/src/lib/libbsp/sparc/shared/analog/gradcdac.c +++ /dev/null @@ -1,579 +0,0 @@ -/* ADC / DAC (GRADCDAC) interface implementation - * - * COPYRIGHT (c) 2009. - * Cobham Gaisler AB. - * - * 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 - -/****************** DEBUG Definitions ********************/ -#define DBG_IOCTRL 1 -#define DBG_TX 2 -#define DBG_RX 4 - -#define DEBUG_FLAGS (DBG_IOCTRL | DBG_RX | DBG_TX ) -/* Uncomment for debug output */ -/* -#define DEBUG -#define DEBUGFUNCS -*/ -#include - -struct gradcdac_priv { - struct gradcdac_regs *regs; /* Must be first */ - struct drvmgr_dev *dev; - char devName[48]; - - unsigned int freq; - int irqno; - int minor; - - void (*isr_adc)(void *cookie, void *arg); - void (*isr_dac)(void *cookie, void *arg); - void *isr_adc_arg; - void *isr_dac_arg; - - int open; -}; - -/* Global variables */ - -/* Print Info routines */ -void gradcdac_print(void *cookie); - -int gradcdac_init2(struct drvmgr_dev *dev); -int gradcdac_init3(struct drvmgr_dev *dev); -int gradcadc_device_init(struct gradcdac_priv *pDev); -void gradcdac_adc_interrupt(void *arg); -void gradcdac_dac_interrupt(void *arg); - -struct drvmgr_drv_ops gradcdac_ops = -{ - .init = {NULL, gradcdac_init2, gradcdac_init3, NULL}, - .remove = NULL, - .info = NULL -}; - -struct amba_dev_id gradcdac_ids[] = -{ - {VENDOR_GAISLER, GAISLER_GRADCDAC}, - {0, 0} /* Mark end of table */ -}; - -struct amba_drv_info gradcdac_drv_info = -{ - { - DRVMGR_OBJ_DRV, /* Driver */ - NULL, /* Next driver */ - NULL, /* Device list */ - DRIVER_AMBAPP_GAISLER_GRADCDAC_ID, /* Driver ID */ - "GRADCDAC_DRV", /* Driver Name */ - DRVMGR_BUS_TYPE_AMBAPP, /* Bus Type */ - &gradcdac_ops, - NULL, /* Funcs */ - 0, /* No devices yet */ - 0, - }, - &gradcdac_ids[0] -}; - -void gradcdac_register_drv (void) -{ - DBG("Registering GRADCDAC driver\n"); - drvmgr_drv_register(&gradcdac_drv_info.general); -} - -int gradcdac_init2(struct drvmgr_dev *dev) -{ - struct gradcdac_priv *priv; - - DBG("GRADCDAC[%d] on bus %s\n", dev->minor_drv, dev->parent->dev->name); - - priv = dev->priv = malloc(sizeof(struct gradcdac_priv)); - if ( !priv ) - return DRVMGR_NOMEM; - memset(priv, 0, sizeof(*priv)); - priv->dev = dev; - - /* This core will not find other cores, so we wait for init2() */ - - return DRVMGR_OK; -} - - -int gradcdac_init3(struct drvmgr_dev *dev) -{ - struct gradcdac_priv *priv = dev->priv; - char prefix[32]; - - if ( !priv ) - return DRVMGR_FAIL; - - if ( gradcadc_device_init(priv) ) { - free(dev->priv); - dev->priv = NULL; - return DRVMGR_FAIL; - } - - /* Get Filesystem name prefix */ - prefix[0] = '\0'; - if ( drvmgr_get_dev_prefix(dev, prefix) ) { - /* Failed to get prefix, make sure of a unique FS name - * by using the driver minor. - */ - sprintf(priv->devName, "/dev/gradcdac%d", dev->minor_drv); - } else { - /* Got special prefix, this means we have a bus prefix - * And we should use our "bus minor" - */ - sprintf(priv->devName, "/dev/%sgradcdac%d", prefix, dev->minor_bus); - } - - return DRVMGR_OK; -} - -static void gradcdac_print_dev(struct gradcdac_priv *pDev) -{ - printf("======= GRADCDAC %p =======\n", pDev->regs); - printf(" Minor: %d\n", pDev->minor); - printf(" Dev Name: %s\n", pDev->devName); - printf(" RegBase: %p\n", pDev->regs); - printf(" IRQ: %d and %d\n", pDev->irqno, pDev->irqno+1); - printf(" Core Freq: %d kHz\n", pDev->freq / 1000); - printf(" Opened: %s\n", pDev->open ? "YES" : "NO"); - - printf(" CONFIG: 0x%x\n", pDev->regs->config); - printf(" STATUS: 0x%x\n", pDev->regs->status); -} - -void gradcdac_print(void *cookie) -{ - struct drvmgr_dev *dev; - struct gradcdac_priv *pDev; - - if ( cookie ) { - gradcdac_print_dev(cookie); - return; - } - - /* Show all */ - dev = gradcdac_drv_info.general.dev; - while (dev) { - pDev = (struct gradcdac_priv *)dev->priv; - gradcdac_print_dev(pDev); - dev = dev->next_in_drv; - } -} - -static void gradcdac_hw_reset(struct gradcdac_regs *regs) -{ - /* Reset core */ - regs->config = 0; - regs->adrdir = 0; - regs->adrout = 0; - regs->data_dir = 0; - regs->data_out = 0; -} - -/* Device initialization called once on startup */ -int gradcadc_device_init(struct gradcdac_priv *pDev) -{ - struct amba_dev_info *ambadev; - struct ambapp_core *pnpinfo; - - /* Get device information from AMBA PnP information */ - ambadev = (struct amba_dev_info *)pDev->dev->businfo; - if ( ambadev == NULL ) { - return -1; - } - pnpinfo = &ambadev->info; - pDev->irqno = pnpinfo->irq; - pDev->regs = (struct gradcdac_regs *)pnpinfo->apb_slv->start; - pDev->minor = pDev->dev->minor_drv; - - /* Reset Hardware before attaching IRQ handler */ - gradcdac_hw_reset(pDev->regs); - - pDev->open = 0; - - /* Get frequency in Hz */ - if ( drvmgr_freq_get(pDev->dev, DEV_APB_SLV, &pDev->freq) ) { - return -1; - } - - DBG("GRADCDAC frequency: %d Hz\n", pDev->freq); - - return 0; -} - -void gradcdac_dac_interrupt(void *arg) -{ - struct gradcdac_priv *pDev = arg; - if ( pDev->isr_dac ) - pDev->isr_dac(pDev, pDev->isr_dac_arg); -} - -void gradcdac_adc_interrupt(void *arg) -{ - struct gradcdac_priv *pDev = arg; - if ( pDev->isr_adc ) - pDev->isr_adc(pDev, pDev->isr_adc_arg); -} - -void *gradcdac_open(char *devname) -{ - struct gradcdac_priv *pDev; - struct drvmgr_dev *dev; - - /* Find device by name */ - dev = gradcdac_drv_info.general.dev; - while ( dev ) { - pDev = (struct gradcdac_priv *)dev->priv; - if ( pDev ) { - if ( strncmp(pDev->devName, devname, sizeof(pDev->devName)) == 0 ) { - /* Found matching device name */ - break; - } - } - dev = dev->next_in_drv; - } - - if ( !dev ) - return NULL; - - /* is device busy/taken? */ - if ( pDev->open ) - return NULL; - - /* Mark device taken */ - pDev->open = 1; - - return pDev; -} - -void gradcdac_set_config(void *cookie, struct gradcdac_config *cfg) -{ - struct gradcdac_priv *pDev = cookie; - unsigned int config=0; - - config = (cfg->dac_ws<wr_pol ) - config |= GRADCDAC_CFG_WRPOL; - - config |= (cfg->dac_dw<adc_ws<rc_pol ) - config |= GRADCDAC_CFG_RCPOL; - - config |= (cfg->cs_mode<cs_pol ) - config |= GRADCDAC_CFG_CSPOL; - - if ( cfg->ready_mode ) - config |= GRADCDAC_CFG_RDYMODE; - - if ( cfg->ready_pol ) - config |= GRADCDAC_CFG_RDYPOL; - - if ( cfg->trigg_pol ) - config |= GRADCDAC_CFG_TRIGPOL; - - config |= (cfg->trigg_mode<adc_dw<regs->config = config; -} - -void gradcdac_get_config(void *cookie, struct gradcdac_config *cfg) -{ - struct gradcdac_priv *pDev = cookie; - unsigned int config; - - if ( !cfg ) - return; - - /* Get config */ - config = pDev->regs->config; - - cfg->dac_ws = (config&GRADCDAC_CFG_DACWS)>>GRADCDAC_CFG_DACWS_BIT; - - cfg->wr_pol = (config&GRADCDAC_CFG_WRPOL)>>GRADCDAC_CFG_WRPOL_BIT; - - cfg->dac_dw = (config&GRADCDAC_CFG_DACDW)>>GRADCDAC_CFG_DACDW_BIT; - - cfg->adc_ws = (config&GRADCDAC_CFG_ADCWS)>>GRADCDAC_CFG_ADCWS_BIT; - - cfg->rc_pol = (config&GRADCDAC_CFG_RCPOL)>>GRADCDAC_CFG_RCPOL_BIT; - - cfg->cs_mode = (config&GRADCDAC_CFG_CSMODE)>>GRADCDAC_CFG_CSMODE_BIT; - - cfg->cs_pol = (config&GRADCDAC_CFG_CSPOL)>>GRADCDAC_CFG_CSPOL_BIT; - - cfg->ready_mode = (config&GRADCDAC_CFG_RDYMODE)>>GRADCDAC_CFG_RDYMODE_BIT; - - cfg->ready_pol = (config&GRADCDAC_CFG_RDYPOL)>>GRADCDAC_CFG_RDYPOL_BIT; - - cfg->trigg_pol = (config&GRADCDAC_CFG_TRIGPOL)>>GRADCDAC_CFG_TRIGPOL_BIT; - - cfg->trigg_mode = (config&GRADCDAC_CFG_TRIGMODE)>>GRADCDAC_CFG_TRIGMODE_BIT; - - cfg->adc_dw = (config&GRADCDAC_CFG_ADCDW)>>GRADCDAC_CFG_ADCDW_BIT; -} - -void gradcdac_set_cfg(void *cookie, unsigned int config) -{ - struct gradcdac_priv *pDev = cookie; - pDev->regs->config = config; -} - -unsigned int gradcdac_get_cfg(void *cookie) -{ - struct gradcdac_priv *pDev = cookie; - return pDev->regs->config; -} - -unsigned int gradcdac_get_status(void *cookie) -{ - struct gradcdac_priv *pDev = cookie; - return pDev->regs->status; -} - -/* Install IRQ handler for ADC and/or DAC interrupt. - * The installed IRQ handler(ISR) must read the status - * register to clear the pending interrupt avoiding multiple - * entries to the ISR caused by the same IRQ. - * - * \param adc 1=ADC interrupt, 2=ADC interrupt, 3=ADC and DAC interrupt - * \param isr Interrupt service routine called when IRQ is fired - * \param arg custom argument passed to ISR when called. - */ -int gradcdac_install_irq_handler(void *cookie, int adc, void (*isr)(void *cookie, void *arg), void *arg) -{ - struct gradcdac_priv *pDev = cookie; - - if ( (adc > 3) || !adc ) - return -1; - - if ( adc & GRADCDAC_ISR_ADC ){ - pDev->isr_adc_arg = arg; - pDev->isr_adc = isr; - drvmgr_interrupt_register(pDev->dev, GRADCDAC_IRQ_ADC, "gradcdac_adc", gradcdac_adc_interrupt, pDev); - } - - if ( adc & GRADCDAC_ISR_DAC ){ - pDev->isr_dac_arg = arg; - pDev->isr_dac = isr; - drvmgr_interrupt_register(pDev->dev, GRADCDAC_IRQ_DAC, "gradcdac_dac", gradcdac_dac_interrupt, pDev); - } - - return 0; -} - -void gradcdac_uninstall_irq_handler(void *cookie, int adc) -{ - struct gradcdac_priv *pDev = cookie; - - if ( (adc > 3) || !adc ) - return; - - if ( adc & GRADCDAC_ISR_ADC ){ - drvmgr_interrupt_unregister(pDev->dev, GRADCDAC_IRQ_ADC, gradcdac_adc_interrupt, pDev); - pDev->isr_adc = NULL; - pDev->isr_adc_arg = NULL; - } - - if ( adc & GRADCDAC_ISR_DAC ){ - drvmgr_interrupt_unregister(pDev->dev, GRADCDAC_IRQ_DAC, gradcdac_dac_interrupt, pDev); - pDev->isr_dac = NULL; - pDev->isr_dac_arg = NULL; - } -} - -/* Make the ADC circuitry initialize a analogue to digital - * conversion. The result can be read out by gradcdac_adc_convert_try - * or gradcdac_adc_convert. - */ -void gradcdac_adc_convert_start(void *cookie) -{ - struct gradcdac_priv *pDev = cookie; - - /* Write to ADC Data Input register to start a conversion */ - pDev->regs->adc_din = 0; -} - -/* Tries to read the conversion result. If the circuitry is busy - * converting the function return a non-zero value, if the conversion - * has successfully finished the function return zero. - * - * \param digital_value the resulting converted value is placed here - * \return zero = ADC conversion complete, digital_value contain current conversion result - * positive = ADC busy, digital_value contain previous conversion result - * negative = Conversion request failed. - */ -int gradcdac_adc_convert_try(void *cookie, unsigned short *digital_value) -{ - struct gradcdac_priv *pDev = cookie; - unsigned int status; - - status = pDev->regs->status; - - if ( digital_value ){ - *digital_value = pDev->regs->adc_din; - } - - if ( gradcdac_ADC_isOngoing(status) ) - return 1; - - if ( gradcdac_ADC_isCompleted(status) ) - return 0; - - /* Failure */ - return -1; -} - -/* Waits until the ADC circuity has finished a digital to analogue - * conversion. The Waiting is implemented as a busy loop utilizing - * 100% CPU load. - */ -int gradcdac_adc_convert(void *cookie, unsigned short *digital_value) -{ - struct gradcdac_priv *pDev = cookie; - unsigned int status; - - do { - status=gradcdac_get_status(pDev); - }while ( gradcdac_ADC_isOngoing(status) ); - - if ( digital_value ) - *digital_value = pDev->regs->adc_din; - - if ( gradcdac_ADC_isCompleted(status) ) - return 0; - - return -1; -} - -/* Try to make the DAC circuitry initialize a digital to analogue - * conversion. If the circuitry is busy by a previous conversion - * the function return a non-zero value, if the conversion is - * successfully initialized the function return zero. - */ -int gradcdac_dac_convert_try(void *cookie, unsigned short digital_value) -{ - struct gradcdac_priv *pDev = cookie; - unsigned int status = pDev->regs->status; - - if ( gradcdac_DAC_isOngoing(status) ) - return -1; - - /* Force a new conversion */ - pDev->regs->dac_dout = digital_value; - - /* Return success */ - return 0; -} - -/* Initializes a digital to analogue conversion by waiting until - * previous conversions is finished before proceeding with the - * conversion. The Waiting is implemented as a busy loop utilizing - * 100% CPU load. - */ -void gradcdac_dac_convert(void *cookie, unsigned short digital_value) -{ - struct gradcdac_priv *pDev = cookie; - unsigned int status; - - do { - status = gradcdac_get_status(pDev); - }while( gradcdac_DAC_isOngoing(status) ); - - pDev->regs->dac_dout = digital_value; -} - -unsigned int gradcdac_get_adrinput(void *cookie) -{ - struct gradcdac_priv *pDev = cookie; - return pDev->regs->adrin; -} - -void gradcdac_set_adrinput(void *cookie, unsigned int input) -{ - struct gradcdac_priv *pDev = cookie; - pDev->regs->adrin = input; -} - -unsigned int gradcdac_get_adroutput(void *cookie) -{ - struct gradcdac_priv *pDev = cookie; - return pDev->regs->adrout; -} - -void gradcdac_set_adroutput(void *cookie, unsigned int output) -{ - struct gradcdac_priv *pDev = cookie; - pDev->regs->adrout = output; -} - -unsigned int gradcdac_get_adrdir(void *cookie) -{ - struct gradcdac_priv *pDev = cookie; - return pDev->regs->adrdir; -} - -void gradcdac_set_adrdir(void *cookie, unsigned int dir) -{ - struct gradcdac_priv *pDev = cookie; - pDev->regs->adrdir = dir; -} - -unsigned int gradcdac_get_datainput(void *cookie) -{ - struct gradcdac_priv *pDev = cookie; - return pDev->regs->data_in; -} - -void gradcdac_set_datainput(void *cookie, unsigned int input) -{ - struct gradcdac_priv *pDev = cookie; - pDev->regs->data_in = input; -} - -unsigned int gradcdac_get_dataoutput(void *cookie) -{ - struct gradcdac_priv *pDev = cookie; - return pDev->regs->data_out; -} - -void gradcdac_set_dataoutput(void *cookie, unsigned int output) -{ - struct gradcdac_priv *pDev = cookie; - pDev->regs->data_out = output; -} - -unsigned int gradcdac_get_datadir(void *cookie) -{ - struct gradcdac_priv *pDev = cookie; - return pDev->regs->data_dir; -} - -void gradcdac_set_datadir(void *cookie, unsigned int dir) -{ - struct gradcdac_priv *pDev = cookie; - pDev->regs->data_dir = dir; -} diff --git a/c/src/lib/libbsp/sparc/shared/ascs/grascs.c b/c/src/lib/libbsp/sparc/shared/ascs/grascs.c deleted file mode 100644 index 11663b2ccc..0000000000 --- a/c/src/lib/libbsp/sparc/shared/ascs/grascs.c +++ /dev/null @@ -1,616 +0,0 @@ -/* This file contains the GRASCS RTEMS driver - * - * COPYRIGHT (c) 2008. - * Cobham Gaisler AB. - * - * 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 GAISLER_ASCS -#define GAISLER_ASCS 0x043 -#endif - -#ifdef DEBUG -#define DBG(x...) printk(x) -#else -#define DBG(x...) -#endif - -typedef struct { - volatile unsigned int cmd; - volatile unsigned int clk; - volatile unsigned int sts; - volatile unsigned int tcd; - volatile unsigned int tmd; -} GRASCS_regs; - -typedef struct { - unsigned char tmconf; - unsigned char usconf; - unsigned char nslaves; - unsigned char dbits; - int clkfreq; -} GRASCS_caps; - -typedef struct { - GRASCS_regs *regs; /* Pointer to core registers */ - GRASCS_caps *caps; /* Pointer to capability struct */ - rtems_id tcsem1, tcsem2; - rtems_id tmsem1, tmsem2; - volatile char running; - int tcptr; - int tmptr; - int tcwords; - int tmwords; -} GRASCS_cfg; - -static GRASCS_cfg *cfg = NULL; - -/*------------------------------------*/ -/* Start of internal helper functions */ -/*------------------------------------*/ - -/* Function: ASCS_getaddr - Arguments: base: Core's register base address - irq: Core's irq - Return values: 0 if successful, -1 if core is not found - Description: Assigns core's register base address and - irq to arguments. Uses AMBA plug and play to find the - core. -*/ -static int ASCS_get_addr(int *base, int *irq) { - - struct ambapp_apb_info core; - - if(ambapp_find_apbslv(&ambapp_plb, VENDOR_GAISLER, GAISLER_ASCS, &core) == 1) { - *base = core.start; - *irq = core.irq; - DBG("ASCS_get_addr: Registerd ASCS core at 0x%x with irq %i\n",core.start, core.irq); - return 0; - } - DBG("ASCS_get_addr: Failed to detect core\n"); - return -1; -} - -/* Function: ASCS_calc_clkreg - Arguments: sysfreq: System clock frequency in kHz - etrfreq: ETR frequency in Hz - Return values: Value of core's CLK-register - Description: Calculates value of core's CLK-register. See - GRASCS IP core documentation for details. -*/ -static int ASCS_calc_clkreg(int sysfreq, int etrfreq) { - - if(cfg->caps->usconf) - return 1000000/etrfreq; - else - return sysfreq*1000/etrfreq; -} - -/* Function: ASCS_get_sysfreq - Arguments: - - Return values: System clock frequency in kHz, -1 if failed - Description: Uses AMBA plug and play to lookup system frequency -*/ -static int ASCS_get_sysfreq(void) { - - struct ambapp_apb_info gpt; - struct gptimer_regs *tregs; - int tmp; - - if(ambapp_find_apbslv(&ambapp_plb, VENDOR_GAISLER, GAISLER_GPTIMER, &gpt) == 1) { - tregs = (struct gptimer_regs *) gpt.start; - tmp = (tregs->scaler_reload + 1)*1000; - DBG("ASCS_get_sysfreq: Detected system frequency %i kHz\n",tmp); - if((tmp < GRASCS_MIN_SFREQ) || (tmp > GRASCS_MAX_SFREQ)) { - DBG("ASCS_get_sysfreq: System frequency is invalid for ASCS core\n"); - return -1; - } - else - return (tregs->scaler_reload + 1)*1000; - } - DBG("ASCS_get_sysfreq: Failed to detect system frequency\n"); - return -1; -} - -/* Function: ASCS_irqhandler - Arguments: v: not used - Return values: - - Description: Determines the source of the interrupt, clears the - appropriate bits in the core's STS register and releases - the associated semaphore -*/ -static rtems_isr ASCS_irqhandler(rtems_vector_number v) { - - if(cfg->regs->sts & GRASCS_STS_TCDONE) { - /* Clear TC done bit */ - cfg->regs->sts |= GRASCS_STS_TCDONE; - - if(--cfg->tcwords == 0) - /* No more TCs to perform right now */ - rtems_semaphore_release(cfg->tcsem2); - else { - /* Block not sent yet, start next TC */ - if(cfg->caps->dbits == 8) { - cfg->tcptr++; - cfg->regs->tcd = *((unsigned char*)cfg->tcptr); - } - else if(cfg->caps->dbits == 16) { - cfg->tcptr += 2; - cfg->regs->tcd = *((unsigned short int*)cfg->tcptr); - } - else { - cfg->tcptr += 4; - cfg->regs->tcd = *((unsigned int*)cfg->tcptr); - } - } - } - - if(cfg->regs->sts & GRASCS_STS_TMDONE) { - /* Clear TM done bit */ - cfg->regs->sts |= GRASCS_STS_TMDONE; - - /* Store received data */ - if(cfg->caps->dbits == 8) { - *((unsigned char*)cfg->tmptr) = (unsigned char)(cfg->regs->tmd & 0xFF); - cfg->tmptr++; - } - else if(cfg->caps->dbits == 16) { - *((unsigned short int*)cfg->tmptr) = (unsigned short int)(cfg->regs->tmd & 0xFFFF); - cfg->tmptr += 2; - } - else { - *((unsigned int*)cfg->tmptr) = cfg->regs->tmd; - cfg->tmptr += 4; - } - - if(--cfg->tmwords == 0) - /* No more TMs to perform right now */ - rtems_semaphore_release(cfg->tmsem2); - else - /* Block not received yet, start next TM */ - cfg->regs->cmd |= GRASCS_CMD_SENDTM; - } -} - -/*---------------------------*/ -/* Start of driver interface */ -/*---------------------------*/ - -/* Function: ASCS_init - Arguments: - - Return values: 0 if successful, -1 if unsuccessful - Description: Initializes the ASCS core -*/ -int ASCS_init(void) { - - int base, irq, tmp; - - DBG("ASCS_init: Starting initialization of ASCS core\n"); - - /* Allocate memory for config, status and capability struct */ - if((cfg = (GRASCS_cfg*)malloc(sizeof(GRASCS_cfg))) == NULL) { - DBG("ASCS_init: Could not allocate memory for cfg struc\n"); - return -1; - } - - if((cfg->caps = (GRASCS_caps*)calloc(1,sizeof(GRASCS_caps))) == NULL) { - DBG("ASCS_init: Could not allocate memory for caps struc\n"); - goto init_error1; - } - - /* Create semaphores for blocking ASCS_TC/TM functions */ - if(rtems_semaphore_create(rtems_build_name('A','S','C','0'),1, - (RTEMS_FIFO|RTEMS_SIMPLE_BINARY_SEMAPHORE| - RTEMS_NO_INHERIT_PRIORITY|RTEMS_LOCAL| - RTEMS_NO_PRIORITY_CEILING), 0, - &cfg->tcsem1) != RTEMS_SUCCESSFUL) { - DBG("ASCS_init: Failed to create semaphore ASC0\n"); - goto init_error2; - } - if(rtems_semaphore_create(rtems_build_name('A','S','C','1'),1, - (RTEMS_FIFO|RTEMS_SIMPLE_BINARY_SEMAPHORE| - RTEMS_NO_INHERIT_PRIORITY|RTEMS_LOCAL| - RTEMS_NO_PRIORITY_CEILING), 0, - &cfg->tmsem1) != RTEMS_SUCCESSFUL) { - DBG("ASCS_init: Failed to create semaphore ASC1\n"); - goto init_error2; - } - /* Create semaphores for waiting on ASCS_TC/TM interrupt */ - if(rtems_semaphore_create(rtems_build_name('A','S','C','2'),0, - (RTEMS_FIFO|RTEMS_SIMPLE_BINARY_SEMAPHORE| - RTEMS_NO_INHERIT_PRIORITY|RTEMS_LOCAL| - RTEMS_NO_PRIORITY_CEILING), 0, - &cfg->tcsem2) != RTEMS_SUCCESSFUL) { - DBG("ASCS_init: Failed to create semaphore ASC2\n"); - goto init_error2; - } - if(rtems_semaphore_create(rtems_build_name('A','S','C','3'),0, - (RTEMS_FIFO|RTEMS_SIMPLE_BINARY_SEMAPHORE| - RTEMS_NO_INHERIT_PRIORITY|RTEMS_LOCAL| - RTEMS_NO_PRIORITY_CEILING), 0, - &cfg->tmsem2) != RTEMS_SUCCESSFUL) { - DBG("ASCS_init: Failed to create semaphore ASC3\n"); - goto init_error2; - } - - /* Set pointer to core registers */ - if(ASCS_get_addr(&base, &irq) == -1) - goto init_error2; - - cfg->regs = (GRASCS_regs*)base; - - /* Read core capabilities */ - tmp = cfg->regs->sts; - cfg->caps->dbits = ((tmp >> GRASCS_STS_DBITS_BITS) & 0x1F) + 1; - cfg->caps->nslaves = ((tmp >> GRASCS_STS_NSLAVES_BITS) & 0xF) + 1; - cfg->caps->tmconf = (tmp >> GRASCS_STS_TMCONF_BITS) & 0x1; - cfg->caps->usconf = (tmp >> GRASCS_STS_USCONF_BITS) & 0x1; - - /* Reset and configure core */ - cfg->running = 0; - cfg->regs->cmd |= GRASCS_CMD_RESET; - if((tmp = ASCS_get_sysfreq()) == -1) - goto init_error2; - cfg->caps->clkfreq = tmp; - while(ASCS_iface_status()) - ; - cfg->regs->clk = ASCS_calc_clkreg(tmp, GRASCS_DEFAULT_ETRFREQ); - cfg->regs->cmd = GRASCS_CMD_US1C; - cfg->regs->cmd |= (tmp/1000 << GRASCS_CMD_US1_BITS) | GRASCS_CMD_US1C | - GRASCS_CMD_TCDONE | GRASCS_CMD_TMDONE; - - /* Register interrupt routine */ - set_vector(ASCS_irqhandler,irq+0x10,2); - - return 0; - - init_error2: - free(cfg->caps); - init_error1: - free(cfg); - return -1; -} - -/* Function: ASCS_input_select - Arguments: slave: The number of the slave that is active, - numbered from 0-15 - Return values: 0 if successful, -GRASCS_ERROR_CAPFAULT if slave value - is negative or too big, -GRASCS_ERROR_TRANSACTIVE if - a TM is active. - Description: Sets the slave_sel bits in the core's CMD register. - they are used to choose which slave the core listens - to when performing a TM. The bits can't be set - during a TM, and the function will in such a case fail. -*/ -int ASCS_input_select(int slave) { - - if((slave < 0) || (slave > cfg->caps->nslaves)) { - /* Slave number is negative or too big */ - DBG("ASCS_input_select: Wrong slave number\n"); - return -GRASCS_ERROR_CAPFAULT; - } - - if(rtems_semaphore_obtain(cfg->tmsem1,RTEMS_NO_WAIT,RTEMS_NO_TIMEOUT) != - RTEMS_SUCCESSFUL) { - /* Can't change active slave during a TM */ - DBG("ASCS_input_select: Transaction active\n"); - return -GRASCS_ERROR_TRANSACTIVE; - } - - cfg->regs->cmd = ((cfg->regs->cmd &= ~GRASCS_CMD_SLAVESEL) | - (slave << GRASCS_CMD_SLAVESEL_BITS)); - - rtems_semaphore_release(cfg->tmsem1); - return 0; -} - -/* Function: ASCS_etr_select - Arguments: src: The source of the ETR signal, valid values are - 0-GRASCS_MAX_TMS (0 = internal source, 1-GRASCS_MAX_TMS = - external time markers 1-GRASCS_MAX_TMS). - freq: ETR frequency in Hz. Valid values are - GRASCS_MIN_ETRFREQ-GRASCS_MAX_ETRFREQ - Return values: 0 if successful, -GRASCS_ERROR_CAPFAULT if src or freq values - are invalid, -GRASCS_ERROR_STARTSTOP if synchronization interface - isn't stopped. - Description: Changes the source for the ETR signal. The frequency of source signal - is assumed to be the same as the frequency of the freq input -*/ -int ASCS_etr_select(int etr, int freq) { - - if((etr < 0) || (etr > GRASCS_MAX_TMS) || ((cfg->caps->tmconf == 0) && (etr > 0)) || - (freq < GRASCS_MIN_ETRFREQ) || (freq > GRASCS_MAX_ETRFREQ)) { - /* ETR source value or frequency is invalid */ - DBG("ASCS_etr_select: Wrong etr src number or wrong frequency\n"); - return -GRASCS_ERROR_CAPFAULT; - } - - if(cfg->regs->sts & GRASCS_STS_ERUNNING) { - /* Synchronization interface is running */ - DBG("ASCS_etr_select: Synch interface is running\n"); - return -GRASCS_ERROR_STARTSTOP; - } - - cfg->regs->clk = ASCS_calc_clkreg(cfg->caps->clkfreq,freq); - cfg->regs->cmd = ((cfg->regs->cmd &= ~GRASCS_CMD_ETRCTRL) | - (etr << GRASCS_CMD_ETRCTRL_BITS)); - - return 0; -} - -/* Function: ASCS_start - Arguments: - - Return values: - - Description: Enables the serial interface. -*/ -void ASCS_start(void) { - - /* Set register and internal status to running */ - cfg->regs->cmd |= GRASCS_CMD_STARTSTOP; - cfg->running = 1; -} - -/* Function: ASCS_stop - Arguments: - - Return values: - - Description: Disables the serial interface. This function will - block until possible calls to TC_send(_block) and - TM_recv(_block) has returned in order to be sure - that started transactions will be performed. -*/ -void ASCS_stop(void) { - - /* Set internal status to stopped */ - cfg->running = 0; - - /* Obtain semaphores to avoid possible situation where a - TC_send(_block) or TM_recv(_block) is aborted and driver is - waiting forever for an interrupt */ - rtems_semaphore_obtain(cfg->tcsem1,RTEMS_WAIT,RTEMS_NO_TIMEOUT); - rtems_semaphore_obtain(cfg->tmsem1,RTEMS_WAIT,RTEMS_NO_TIMEOUT); - - /* Change actual register value */ - cfg->regs->cmd &= ~GRASCS_CMD_STARTSTOP; - - /* Release the semaphores */ - rtems_semaphore_release(cfg->tcsem1); - rtems_semaphore_release(cfg->tmsem1); -} - -/* Function: ASCS_iface_status - Arguments: - - Return values: 0 if both serial interface and synch interface is stopped, - 1 if serial interface is running buth synch interface is - stopped, 2 if serial interface is stopped but synch interface - is running, 3 if both serial and synch interface is running - Description: Reads the core's STS register and reports the status of the - serial and synch interfaces -*/ -int ASCS_iface_status(void) { - - return ((cfg->regs->sts & 0x3) & (0x2 | cfg->running)); -} - -/* Function: ASCS_TC_send - Arguments: word: Pointer to a word that should be sent - Return values: 0 on success - -GRASCS_ERROR_STARTSTOP if serial interface is stopped, - -GRASCS_ERROR_TRANSACTIVE if another TC is in progress. - Description: Start a TC and sends the data that word points to. -*/ -int ASCS_TC_send(int *word) { - - int retval; - - if(rtems_semaphore_obtain(cfg->tcsem1,RTEMS_NO_WAIT,RTEMS_NO_TIMEOUT) != - RTEMS_SUCCESSFUL) { - /* Can't start a TC_send if another TC_send of TC_send_block is - in progress */ - DBG("ASCS_TC_send: Could not obtain semaphore, transcation probably in progress\n"); - return -GRASCS_ERROR_TRANSACTIVE; - } - - if(!cfg->running) { - /* Can't start a TC if serial interface isn't started */ - DBG("ASCS_TC_send: Serial interface is not started\n"); - retval = -GRASCS_ERROR_STARTSTOP; - } - else { - /* Start the transfer */ - cfg->tcwords = 1; - if(cfg->caps->dbits == 8) - cfg->regs->tcd = *((unsigned char*)word); - else if(cfg->caps->dbits == 16) - cfg->regs->tcd = *((unsigned short int*)((int)word & ~1)); - else - cfg->regs->tcd = *((unsigned int*)((int)word & ~3)); - - /* Wait until transfer is complete */ - rtems_semaphore_obtain(cfg->tcsem2,RTEMS_WAIT,RTEMS_NO_TIMEOUT); - retval = 0; - } - - rtems_semaphore_release(cfg->tcsem1); - - return retval; -} - -/* Function: ASCS_TC_send_block - Arguments: block: Pointer to the start of a datablock that - should be sent. - ntrans: Number of transfers needed to transfer - the block. - Return values: 0 if successfull, -GRASCS_ERROR_STARTSTOP if TC - couldn't be started because serial interface is - stopped, -GRASCS_ERROR_TRANSACTIVE if TC couldn't - be started because another TC isn't done yet. - Description: Starts ntrans TCs and sends the data that starts at the - address that block points to. The size of each - transaction will vary depending on whether the core is - configured for 8, 16, or 32 bits data transfers. -*/ -int ASCS_TC_send_block(int *block, int ntrans) { - - int retval; - - if(rtems_semaphore_obtain(cfg->tcsem1,RTEMS_NO_WAIT,RTEMS_NO_TIMEOUT) != - RTEMS_SUCCESSFUL) { - /* Can't start a TC_send_block if another TC_send of TC_send_block is - in progress */ - DBG("ASCS_TC_send_block: Could not obtain semaphore, transcation probably in progress\n"); - return -GRASCS_ERROR_TRANSACTIVE; - } - - if(!cfg->running) { - /* Can't start a TC if serial interface isn't started */ - DBG("ASCS_TC_send_block: Serial interface is not started\n"); - retval = -GRASCS_ERROR_STARTSTOP; - } - else { - /* Start the first transfer */ - cfg->tcwords = ntrans; - if(cfg->caps->dbits == 8) { - cfg->tcptr = (int)block; - cfg->regs->tcd = *((unsigned char*)cfg->tcptr); - } - else if(cfg->caps->dbits == 16) { - cfg->tcptr = (int)block & ~1; - cfg->regs->tcd = *((unsigned short int*)cfg->tcptr); - } - else { - cfg->tcptr = (int)block & ~3; - cfg->regs->tcd = *((unsigned int*)cfg->tcptr); - } - - /* Wait until all transfers are complete */ - rtems_semaphore_obtain(cfg->tcsem2,RTEMS_WAIT,RTEMS_NO_TIMEOUT); - retval = 0; - } - - rtems_semaphore_release(cfg->tcsem1); - - return retval; -} - -/* Function: ASCS_TC_sync_start - Arguments: - - Return values: - - Description: Starts synchronization interface. Might - be delayed if a TM is in progress. SW can poll - ASCS_iface_status() to find out when synch interface is - started. First ETR pulse can be delay up to one ETR - period depending on the source of the ETR and - activity on the TM line. -*/ -void ASCS_TC_sync_start(void) { - - cfg->regs->cmd |= GRASCS_CMD_ESTARTSTOP; -} - -/* Function: ASCS_TC_sync_stop - Arguments: - - Return values: - - Description: Stops the synchronization interface. Might - be delayed for 1 us if a ETR pulse is being generated. SW - can determine when synch interface has stopped by polling - ASCS_iface_status(). -*/ -void ASCS_TC_sync_stop(void) { - - cfg->regs->cmd &= ~GRASCS_CMD_ESTARTSTOP; -} - -/* Function: ASCS_TM_recv - Arguments: word: Pointer to where the received word should be - placed - Return values: 0 if successful, -GRASCS_ERROR_STARTSTOP if serial - interface isn't started, -GRASCS_ERROR_TRANSACTIVE - if another TM is in progress - Description: Starts a TM and stores the incoming data in word. -*/ -int ASCS_TM_recv(int *word) { - - int retval; - - if(rtems_semaphore_obtain(cfg->tmsem1,RTEMS_NO_WAIT,RTEMS_NO_TIMEOUT) != - RTEMS_SUCCESSFUL) { - /* Can't start a TM_recv if another TM_recv of TM_recv_block is - in progress */ - DBG("ASCS_TM_recv: Could not obtain semaphore, transaction probably in progress\n"); - return -GRASCS_ERROR_TRANSACTIVE; - } - - if(!cfg->running) { - /* Can't start a TM if serial interface isn't started */ - DBG("ASCS_TM_recv: Serial interface is not started\n"); - retval = -GRASCS_ERROR_STARTSTOP; - } - else { - /* Start transfer */ - cfg->tmwords = 1; - cfg->tmptr = (int)word; - cfg->regs->cmd |= GRASCS_CMD_SENDTM; - - /* Wait until transfer finishes */ - rtems_semaphore_obtain(cfg->tmsem2,RTEMS_WAIT,RTEMS_NO_TIMEOUT); - retval = 0; - } - - rtems_semaphore_release(cfg->tmsem1); - - return retval; -} - -/* Function: ASCS_TM_recv_block - Arguments: block: Pointer to where the received datablock - should be stored. - ntrans: Number of transfers needed to transfer - the block. - Return values: 0 if successful, -GRASCS_ERROR_STARTSTOP if serial - interface isn't started, -GRASCS_ERROR_TRANSACTIVE if - a performed TM hasn't been processed yet - Description: Starts ntrans TMs and stores the data at the address - that block points to. The size of each transaction - will vary depending on whether the core is - configured for 8, 16, or 32 bits data transfers. -*/ -int ASCS_TM_recv_block(int *block, int ntrans) { - - int retval; - - if(rtems_semaphore_obtain(cfg->tmsem1,RTEMS_NO_WAIT,RTEMS_NO_TIMEOUT) != - RTEMS_SUCCESSFUL) { - /* Can't start a TM_recv_block if another TM_recv of TM_recv_block is - in progress */ - DBG("ASCS_TM_recv_block: Could not obtain semaphore, transaction probably in progress\n"); - return -GRASCS_ERROR_TRANSACTIVE; - } - - if(!cfg->running) { - /* Can't start a TM if serial interface isn't started */ - DBG("ASCS_TM_recv_block: Serial interface is not started\n"); - retval = -GRASCS_ERROR_STARTSTOP; - } - else { - /* Start transfer */ - cfg->tmwords = ntrans; - cfg->tmptr = (int)block; - cfg->regs->cmd |= GRASCS_CMD_SENDTM; - - /* Wait until transfer finishes */ - rtems_semaphore_obtain(cfg->tmsem2,RTEMS_WAIT,RTEMS_NO_TIMEOUT); - retval = 0; - } - - rtems_semaphore_release(cfg->tmsem1); - - return retval; -} diff --git a/c/src/lib/libbsp/sparc/shared/can/canmux.c b/c/src/lib/libbsp/sparc/shared/can/canmux.c deleted file mode 100644 index 1d9d371157..0000000000 --- a/c/src/lib/libbsp/sparc/shared/can/canmux.c +++ /dev/null @@ -1,197 +0,0 @@ -/* - * CAN_MUX driver. Present in GR712RC. - * - * COPYRIGHT (c) 2008. - * Cobham Gaisler AB. - * - * 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 /* printk */ - -#include -#include - -#ifndef GAISLER_CANMUX -#define GAISLER_CANMUX 0x081 -#endif - -#if !defined(CANMUX_DEVNAME) - #undef CANMUX_DEVNAME - #define CANMUX_DEVNAME "/dev/canmux" -#endif - -/* Enable debug output? */ -/* #define DEBUG */ - -#ifdef DEBUG -#define DBG(x...) printk(x) -#else -#define DBG(x...) -#endif - -#define BUSA_SELECT (1 << 0) -#define BUSB_SELECT (1 << 1) - -struct canmux_priv { - volatile unsigned int *muxreg; - rtems_id devsem; - int open; -}; - -static struct canmux_priv *priv; - -static rtems_device_driver canmux_ioctl(rtems_device_major_number major, rtems_device_minor_number minor, void *arg); -static rtems_device_driver canmux_write(rtems_device_major_number major, rtems_device_minor_number minor, void *arg); -static rtems_device_driver canmux_read(rtems_device_major_number major, rtems_device_minor_number minor, void *arg); -static rtems_device_driver canmux_close(rtems_device_major_number major, rtems_device_minor_number minor, void *arg); -static rtems_device_driver canmux_open(rtems_device_major_number major, rtems_device_minor_number minor, void *arg); -static rtems_device_driver canmux_initialize(rtems_device_major_number major, rtems_device_minor_number unused, void *arg); - - -static rtems_device_driver canmux_ioctl(rtems_device_major_number major, rtems_device_minor_number minor, void *arg) -{ - rtems_libio_ioctl_args_t *ioarg = (rtems_libio_ioctl_args_t*)arg; - - DBG("CAN_MUX: IOCTL %d\n\r", ioarg->command); - - ioarg->ioctl_return = 0; - switch(ioarg->command) { - case CANMUX_IOC_BUSA_SATCAN: *priv->muxreg &= ~BUSA_SELECT; break; - case CANMUX_IOC_BUSA_OCCAN1: *priv->muxreg |= BUSA_SELECT; break; - case CANMUX_IOC_BUSB_SATCAN: *priv->muxreg &= ~BUSB_SELECT; break; - case CANMUX_IOC_BUSB_OCCAN2: *priv->muxreg |= BUSB_SELECT; break; - default: return RTEMS_NOT_DEFINED; - } - - return RTEMS_SUCCESSFUL; -} - -static rtems_device_driver canmux_write(rtems_device_major_number major, rtems_device_minor_number minor, void *arg) -{ - rtems_libio_rw_args_t *rw_args=(rtems_libio_rw_args_t*)arg; - - rw_args->bytes_moved = 0; - - return RTEMS_SUCCESSFUL; -} - -static rtems_device_driver canmux_read(rtems_device_major_number major, rtems_device_minor_number minor, void *arg) -{ - rtems_libio_rw_args_t *rw_args = (rtems_libio_rw_args_t*)arg; - - rw_args->bytes_moved = 0; - - return RTEMS_SUCCESSFUL; -} - - -static rtems_device_driver canmux_close(rtems_device_major_number major, rtems_device_minor_number minor, void *arg) -{ - DBG("CAN_MUX: Closing %d\n\r",minor); - - priv->open = 0; - return RTEMS_SUCCESSFUL; -} - - -static rtems_device_driver canmux_open(rtems_device_major_number major, rtems_device_minor_number minor, void *arg) -{ - DBG("CAN_MUX: Opening %d\n\r",minor); - - rtems_semaphore_obtain(priv->devsem,RTEMS_WAIT, RTEMS_NO_TIMEOUT); - if (priv->open) { - rtems_semaphore_release(priv->devsem); - return RTEMS_RESOURCE_IN_USE; /* EBUSY */ - } - priv->open = 1; - rtems_semaphore_release(priv->devsem); - - DBG("CAN_MUX: Opening %d success\n\r",minor); - - return RTEMS_SUCCESSFUL; -} - -static rtems_device_driver canmux_initialize(rtems_device_major_number major, rtems_device_minor_number minor, void *arg) -{ - struct ambapp_apb_info d; - char fs_name[20]; - rtems_status_code status; - - DBG("CAN_MUX: Initialize..\n\r"); - - strcpy(fs_name, CANMUX_DEVNAME); - - /* Find core and initialize register pointer */ - if (!ambapp_find_apbslv(&ambapp_plb, VENDOR_GAISLER, GAISLER_CANMUX, &d)) { - printk("CAN_MUX: Failed to find CAN_MUX core\n\r"); - return -1; - } - - status = rtems_io_register_name(fs_name, major, minor); - if (RTEMS_SUCCESSFUL != status) - rtems_fatal_error_occurred(status); - - /* Create private structure */ - if ((priv = malloc(sizeof(struct canmux_priv))) == NULL) { - printk("CAN_MUX driver could not allocate memory for priv structure\n\r"); - return -1; - } - - priv->muxreg = (unsigned int*)d.start; - - status = rtems_semaphore_create( - rtems_build_name('M', 'd', 'v', '0'), - 1, - RTEMS_FIFO | RTEMS_SIMPLE_BINARY_SEMAPHORE | RTEMS_NO_INHERIT_PRIORITY | \ - RTEMS_NO_PRIORITY_CEILING, - 0, - &priv->devsem); - if (status != RTEMS_SUCCESSFUL) { - printk("CAN_MUX: Failed to create dev semaphore (%d)\n\r", status); - free(priv); - return RTEMS_UNSATISFIED; - } - - priv->open = 0; - - return RTEMS_SUCCESSFUL; -} - - -#define CANMUX_DRIVER_TABLE_ENTRY { canmux_initialize, canmux_open, canmux_close, canmux_read, canmux_write, canmux_ioctl } - -static rtems_driver_address_table canmux_driver = CANMUX_DRIVER_TABLE_ENTRY; - -int canmux_register(void) -{ - rtems_status_code r; - rtems_device_major_number m; - - DBG("CAN_MUX: canmux_register called\n\r"); - - if ((r = rtems_io_register_driver(0, &canmux_driver, &m)) == RTEMS_SUCCESSFUL) { - DBG("CAN_MUX driver successfully registered, major: %d\n\r", m); - } else { - switch(r) { - case RTEMS_TOO_MANY: - printk("CAN_MUX rtems_io_register_driver failed: RTEMS_TOO_MANY\n\r"); break; - case RTEMS_INVALID_NUMBER: - printk("CAN_MUX rtems_io_register_driver failed: RTEMS_INVALID_NUMBER\n\r"); break; - case RTEMS_RESOURCE_IN_USE: - printk("CAN_MUX rtems_io_register_driver failed: RTEMS_RESOURCE_IN_USE\n\r"); break; - default: - printk("CAN_MUX rtems_io_register_driver failed\n\r"); - } - return 1; - } - - return 0; -} diff --git a/c/src/lib/libbsp/sparc/shared/can/grcan.c b/c/src/lib/libbsp/sparc/shared/can/grcan.c deleted file mode 100644 index da236ef7cc..0000000000 --- a/c/src/lib/libbsp/sparc/shared/can/grcan.c +++ /dev/null @@ -1,2001 +0,0 @@ -/* - * GRCAN driver - * - * COPYRIGHT (c) 2007. - * Cobham Gaisler AB. - * - * 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 -#include - -#if (((__RTEMS_MAJOR__ << 16) | (__RTEMS_MINOR__ << 8) | __RTEMS_REVISION__) >= 0x040b63) - -/* Spin locks mapped via rtems_interrupt_lock_* API: */ -#define SPIN_DECLARE(lock) RTEMS_INTERRUPT_LOCK_MEMBER(lock) -#define SPIN_INIT(lock, name) rtems_interrupt_lock_initialize(lock, name) -#define SPIN_LOCK(lock, level) rtems_interrupt_lock_acquire_isr(lock, &level) -#define SPIN_LOCK_IRQ(lock, level) rtems_interrupt_lock_acquire(lock, &level) -#define SPIN_UNLOCK(lock, level) rtems_interrupt_lock_release_isr(lock, &level) -#define SPIN_UNLOCK_IRQ(lock, level) rtems_interrupt_lock_release(lock, &level) -#define SPIN_IRQFLAGS(k) rtems_interrupt_lock_context k -#define SPIN_ISR_IRQFLAGS(k) SPIN_IRQFLAGS(k) - -#else - -/* maintain compatibility with older versions of RTEMS: */ -#define SPIN_DECLARE(name) -#define SPIN_INIT(lock, name) -#define SPIN_LOCK(lock, level) -#define SPIN_LOCK_IRQ(lock, level) rtems_interrupt_disable(level) -#define SPIN_UNLOCK(lock, level) -#define SPIN_UNLOCK_IRQ(lock, level) rtems_interrupt_enable(level) -#define SPIN_IRQFLAGS(k) rtems_interrupt_level k -#define SPIN_ISR_IRQFLAGS(k) - -#endif - -/* Maximum number of GRCAN devices supported by driver */ -#define GRCAN_COUNT_MAX 8 - -#define WRAP_AROUND_TX_MSGS 1 -#define WRAP_AROUND_RX_MSGS 2 -#define GRCAN_MSG_SIZE sizeof(struct grcan_msg) -#define BLOCK_SIZE (16*4) - -/* grcan needs to have it buffers aligned to 1k boundaries */ -#define BUFFER_ALIGNMENT_NEEDS 1024 - -/* Default Maximium buffer size for statically allocated buffers */ -#ifndef TX_BUF_SIZE - #define TX_BUF_SIZE (BLOCK_SIZE*16) -#endif - -/* Make receiver buffers bigger than transmitt */ -#ifndef RX_BUF_SIZE - #define RX_BUF_SIZE ((3*BLOCK_SIZE)*16) -#endif - -#ifndef IRQ_CLEAR_PENDING - #define IRQ_CLEAR_PENDING(irqno) -#endif - -#ifndef IRQ_UNMASK - #define IRQ_UNMASK(irqno) -#endif - -#ifndef IRQ_MASK - #define IRQ_MASK(irqno) -#endif - -#ifndef GRCAN_DEFAULT_BAUD - /* default to 500kbits/s */ - #define GRCAN_DEFAULT_BAUD 500000 -#endif - -#ifndef GRCAN_SAMPLING_POINT - #define GRCAN_SAMPLING_POINT 80 -#endif - -/* Uncomment for debug output */ -/****************** DEBUG Definitions ********************/ -#define DBG_TX 2 -#define DBG_RX 4 -#define DBG_STATE 8 - -#define DEBUG_FLAGS (DBG_STATE | DBG_RX | DBG_TX ) -/* -#define DEBUG -#define DEBUGFUNCS -*/ -#include - -/*********************************************************/ - -int state2err[4] = { - /* STATE_STOPPED */ GRCAN_RET_NOTSTARTED, - /* STATE_STARTED */ GRCAN_RET_OK, - /* STATE_BUSOFF */ GRCAN_RET_BUSOFF, - /* STATE_AHBERR */ GRCAN_RET_AHBERR -}; - -struct grcan_msg { - unsigned int head[2]; - unsigned char data[8]; -}; - -struct grcan_config { - struct grcan_timing timing; - struct grcan_selection selection; - int abort; - int silent; -}; - -struct grcan_priv { - struct drvmgr_dev *dev; /* Driver manager device */ - char devName[32]; /* Device Name */ - unsigned int baseaddr, ram_base; - struct grcan_regs *regs; - int irq; - int minor; - int open; - int started; - unsigned int channel; - int flushing; - unsigned int corefreq_hz; - - /* Circular DMA buffers */ - void *_rx, *_rx_hw; - void *_tx, *_tx_hw; - void *txbuf_adr; - void *rxbuf_adr; - struct grcan_msg *rx; - struct grcan_msg *tx; - unsigned int rxbuf_size; /* requested RX buf size in bytes */ - unsigned int txbuf_size; /* requested TX buf size in bytes */ - - int txblock, rxblock; - int txcomplete, rxcomplete; - - struct grcan_filter sfilter; - struct grcan_filter afilter; - int config_changed; /* 0=no changes, 1=changes ==> a Core reset is needed */ - struct grcan_config config; - struct grcan_stats stats; - - rtems_id rx_sem, tx_sem, txempty_sem, dev_sem; - SPIN_DECLARE(devlock); -}; - -static void __inline__ grcan_hw_reset(struct grcan_regs *regs); - -static int grcan_hw_read_try( - struct grcan_priv *pDev, - struct grcan_regs *regs, - CANMsg *buffer, - int max); - -static int grcan_hw_write_try( - struct grcan_priv *pDev, - struct grcan_regs *regs, - CANMsg *buffer, - int count); - -static void grcan_hw_config( - struct grcan_regs *regs, - struct grcan_config *conf); - -static void grcan_hw_accept( - struct grcan_regs *regs, - struct grcan_filter *afilter); - -static void grcan_hw_sync( - struct grcan_regs *regs, - struct grcan_filter *sfilter); - -static void grcan_interrupt(void *arg); - -#ifdef GRCAN_REG_BYPASS_CACHE -#define READ_REG(address) _grcan_read_nocache((unsigned int)(address)) -#else -#define READ_REG(address) (*(volatile unsigned int *)(address)) -#endif - -#ifdef GRCAN_DMA_BYPASS_CACHE -#define READ_DMA_WORD(address) _grcan_read_nocache((unsigned int)(address)) -#define READ_DMA_BYTE(address) _grcan_read_nocache_byte((unsigned int)(address)) -static unsigned char __inline__ _grcan_read_nocache_byte(unsigned int address) -{ - unsigned char tmp; - __asm__ (" lduba [%1]1, %0 " - : "=r"(tmp) - : "r"(address) - ); - return tmp; -} -#else -#define READ_DMA_WORD(address) (*(volatile unsigned int *)(address)) -#define READ_DMA_BYTE(address) (*(volatile unsigned char *)(address)) -#endif - -#if defined(GRCAN_REG_BYPASS_CACHE) || defined(GRCAN_DMA_BYPASS_CACHE) -static unsigned int __inline__ _grcan_read_nocache(unsigned int address) -{ - unsigned int tmp; - __asm__ (" lda [%1]1, %0 " - : "=r"(tmp) - : "r"(address) - ); - return tmp; -} -#endif - -#define NELEM(a) ((int) (sizeof (a) / sizeof (a[0]))) - -static int grcan_count = 0; -static struct grcan_priv *priv_tab[GRCAN_COUNT_MAX]; - -/******************* Driver manager interface ***********************/ - -/* Driver prototypes */ -int grcan_device_init(struct grcan_priv *pDev); - -int grcan_init2(struct drvmgr_dev *dev); -int grcan_init3(struct drvmgr_dev *dev); - -struct drvmgr_drv_ops grcan_ops = -{ - .init = {NULL, grcan_init2, grcan_init3, NULL}, - .remove = NULL, - .info = NULL -}; - -struct amba_dev_id grcan_ids[] = -{ - {VENDOR_GAISLER, GAISLER_GRCAN}, - {VENDOR_GAISLER, GAISLER_GRHCAN}, - {0, 0} /* Mark end of table */ -}; - -struct amba_drv_info grcan_drv_info = -{ - { - DRVMGR_OBJ_DRV, /* Driver */ - NULL, /* Next driver */ - NULL, /* Device list */ - DRIVER_AMBAPP_GAISLER_GRCAN_ID, /* Driver ID */ - "GRCAN_DRV", /* Driver Name */ - DRVMGR_BUS_TYPE_AMBAPP, /* Bus Type */ - &grcan_ops, - NULL, /* Funcs */ - 0, /* No devices yet */ - 0, - }, - &grcan_ids[0] -}; - -void grcan_register_drv (void) -{ - DBG("Registering GRCAN driver\n"); - drvmgr_drv_register(&grcan_drv_info.general); -} - -int grcan_init2(struct drvmgr_dev *dev) -{ - struct grcan_priv *priv; - - DBG("GRCAN[%d] on bus %s\n", dev->minor_drv, dev->parent->dev->name); - if (GRCAN_COUNT_MAX <= grcan_count) - return DRVMGR_ENORES; - priv = dev->priv = malloc(sizeof(struct grcan_priv)); - if ( !priv ) - return DRVMGR_NOMEM; - memset(priv, 0, sizeof(*priv)); - priv->dev = dev; - - /* This core will not find other cores, so we wait for init2() */ - - return DRVMGR_OK; -} - -int grcan_init3(struct drvmgr_dev *dev) -{ - struct grcan_priv *priv; - char prefix[32]; - - priv = dev->priv; - - /* - * Now we take care of device initialization. - */ - - if ( grcan_device_init(priv) ) { - return DRVMGR_FAIL; - } - - priv_tab[grcan_count] = priv; - grcan_count++; - - /* Get Filesystem name prefix */ - prefix[0] = '\0'; - if ( drvmgr_get_dev_prefix(dev, prefix) ) { - /* Failed to get prefix, make sure of a unique FS name - * by using the driver minor. - */ - sprintf(priv->devName, "grcan%d", dev->minor_drv); - } else { - /* Got special prefix, this means we have a bus prefix - * And we should use our "bus minor" - */ - sprintf(priv->devName, "%sgrcan%d", prefix, dev->minor_bus); - } - - return DRVMGR_OK; -} - -int grcan_device_init(struct grcan_priv *pDev) -{ - struct amba_dev_info *ambadev; - struct ambapp_core *pnpinfo; - - /* Get device information from AMBA PnP information */ - ambadev = (struct amba_dev_info *)pDev->dev->businfo; - if ( ambadev == NULL ) { - return -1; - } - pnpinfo = &ambadev->info; - pDev->irq = pnpinfo->irq; - pDev->regs = (struct grcan_regs *)pnpinfo->apb_slv->start; - pDev->minor = pDev->dev->minor_drv; - - /* Get frequency in Hz */ - if ( drvmgr_freq_get(pDev->dev, DEV_APB_SLV, &pDev->corefreq_hz) ) { - return -1; - } - - DBG("GRCAN frequency: %d Hz\n", pDev->corefreq_hz); - - /* Reset Hardware before attaching IRQ handler */ - grcan_hw_reset(pDev->regs); - - /* RX Semaphore created with count = 0 */ - if ( rtems_semaphore_create(rtems_build_name('G', 'C', 'R', '0' + pDev->minor), - 0, - RTEMS_FIFO|RTEMS_SIMPLE_BINARY_SEMAPHORE|RTEMS_NO_INHERIT_PRIORITY|\ - RTEMS_LOCAL|RTEMS_NO_PRIORITY_CEILING, - 0, - &pDev->rx_sem) != RTEMS_SUCCESSFUL ) { - return RTEMS_INTERNAL_ERROR; - } - - /* TX Semaphore created with count = 0 */ - if ( rtems_semaphore_create(rtems_build_name('G', 'C', 'T', '0' + pDev->minor), - 0, - RTEMS_FIFO|RTEMS_SIMPLE_BINARY_SEMAPHORE|RTEMS_NO_INHERIT_PRIORITY|\ - RTEMS_LOCAL|RTEMS_NO_PRIORITY_CEILING, - 0, - &pDev->tx_sem) != RTEMS_SUCCESSFUL ) { - return RTEMS_INTERNAL_ERROR; - } - - /* TX Empty Semaphore created with count = 0 */ - if ( rtems_semaphore_create(rtems_build_name('G', 'C', 'E', '0' + pDev->minor), - 0, - RTEMS_FIFO|RTEMS_SIMPLE_BINARY_SEMAPHORE|RTEMS_NO_INHERIT_PRIORITY|\ - RTEMS_LOCAL|RTEMS_NO_PRIORITY_CEILING, - 0, - &pDev->txempty_sem) != RTEMS_SUCCESSFUL ) { - return RTEMS_INTERNAL_ERROR; - } - - /* Device Semaphore created with count = 1 */ - if ( rtems_semaphore_create(rtems_build_name('G', 'C', 'A', '0' + pDev->minor), - 1, - RTEMS_FIFO|RTEMS_SIMPLE_BINARY_SEMAPHORE|RTEMS_NO_INHERIT_PRIORITY|\ - RTEMS_LOCAL|RTEMS_NO_PRIORITY_CEILING, - 0, - &pDev->dev_sem) != RTEMS_SUCCESSFUL ) { - return RTEMS_INTERNAL_ERROR; - } - - return 0; -} - -static void __inline__ grcan_hw_reset(struct grcan_regs *regs) -{ - regs->ctrl = GRCAN_CTRL_RESET; -} - -static rtems_device_driver grcan_hw_start(struct grcan_priv *pDev) -{ - /* - * tmp is set but never used. GCC gives a warning for this - * and we need to tell GCC not to complain. - */ - unsigned int tmp RTEMS_UNUSED; - - SPIN_IRQFLAGS(oldLevel); - - FUNCDBG(); - - /* Check that memory has been allocated successfully */ - if (!pDev->tx || !pDev->rx) - return RTEMS_NO_MEMORY; - - /* Configure FIFO configuration register - * and Setup timing - */ - if (pDev->config_changed) { - grcan_hw_config(pDev->regs, &pDev->config); - pDev->config_changed = 0; - } - - /* Setup receiver */ - pDev->regs->rx0addr = (unsigned int)pDev->_rx_hw; - pDev->regs->rx0size = pDev->rxbuf_size; - - /* Setup Transmitter */ - pDev->regs->tx0addr = (unsigned int)pDev->_tx_hw; - pDev->regs->tx0size = pDev->txbuf_size; - - /* Setup acceptance filters */ - grcan_hw_accept(pDev->regs, &pDev->afilter); - - /* Sync filters */ - grcan_hw_sync(pDev->regs, &pDev->sfilter); - - /* Clear status bits */ - tmp = READ_REG(&pDev->regs->stat); - pDev->regs->stat = 0; - - /* Setup IRQ handling */ - - /* Clear all IRQs */ - tmp = READ_REG(&pDev->regs->pir); - pDev->regs->picr = 0x1ffff; - - /* unmask TxLoss|TxErrCntr|RxErrCntr|TxAHBErr|RxAHBErr|OR|OFF|PASS */ - pDev->regs->imr = 0x1601f; - - /* Enable routing of the IRQs */ - SPIN_LOCK_IRQ(&pDev->devlock, oldLevel); - IRQ_UNMASK(pDev->irq + GRCAN_IRQ_TXSYNC); - IRQ_UNMASK(pDev->irq + GRCAN_IRQ_RXSYNC); - IRQ_UNMASK(pDev->irq + GRCAN_IRQ_IRQ); - SPIN_UNLOCK_IRQ(&pDev->devlock, oldLevel); - - /* Enable receiver/transmitter */ - pDev->regs->rx0ctrl = GRCAN_RXCTRL_ENABLE; - pDev->regs->tx0ctrl = GRCAN_TXCTRL_ENABLE; - - /* Enable HurriCANe core */ - pDev->regs->ctrl = GRCAN_CTRL_ENABLE; - - /* Leave transmitter disabled, it is enabled when - * trying to send something. - */ - return RTEMS_SUCCESSFUL; -} - -static void grcan_hw_stop(struct grcan_priv *pDev) -{ - FUNCDBG(); - - /* Mask all IRQs */ - pDev->regs->imr = 0; - IRQ_MASK(pDev->irq + GRCAN_IRQ_TXSYNC); - IRQ_MASK(pDev->irq + GRCAN_IRQ_RXSYNC); - IRQ_MASK(pDev->irq + GRCAN_IRQ_IRQ); - - /* Disable receiver & transmitter */ - pDev->regs->rx0ctrl = 0; - pDev->regs->tx0ctrl = 0; -} - -static void grcan_sw_stop(struct grcan_priv *pDev) -{ - /* - * Release semaphores to wake all threads waiting for an IRQ. - * The threads that - * get woken up must check started state in - * order to determine that they should return to - * user space with error status. - * - * Entering into started mode again will reset the - * semaphore count. - */ - rtems_semaphore_release(pDev->rx_sem); - rtems_semaphore_release(pDev->tx_sem); - rtems_semaphore_release(pDev->txempty_sem); -} - -static void grcan_hw_config(struct grcan_regs *regs, struct grcan_config *conf) -{ - unsigned int config = 0; - - /* Reset HurriCANe Core */ - regs->ctrl = 0; - - if (conf->silent) - config |= GRCAN_CFG_SILENT; - - if (conf->abort) - config |= GRCAN_CFG_ABORT; - - if (conf->selection.selection) - config |= GRCAN_CFG_SELECTION; - - if (conf->selection.enable0) - config |= GRCAN_CFG_ENABLE0; - - if (conf->selection.enable1) - config |= GRCAN_CFG_ENABLE1; - - /* Timing */ - config |= (conf->timing.bpr << GRCAN_CFG_BPR_BIT) & GRCAN_CFG_BPR; - config |= (conf->timing.rsj << GRCAN_CFG_RSJ_BIT) & GRCAN_CFG_RSJ; - config |= (conf->timing.ps1 << GRCAN_CFG_PS1_BIT) & GRCAN_CFG_PS1; - config |= (conf->timing.ps2 << GRCAN_CFG_PS2_BIT) & GRCAN_CFG_PS2; - config |= - (conf->timing.scaler << GRCAN_CFG_SCALER_BIT) & GRCAN_CFG_SCALER; - - /* Write configuration */ - regs->conf = config; - - /* Enable HurriCANe Core */ - regs->ctrl = GRCAN_CTRL_ENABLE; -} - -static void grcan_hw_accept( - struct grcan_regs *regs, - struct grcan_filter *afilter -) -{ - /* Disable Sync mask totaly (if we change scode or smask - * in an unfortunate way we may trigger a sync match) - */ - regs->rx0mask = 0xffffffff; - - /* Set Sync Filter in a controlled way */ - regs->rx0code = afilter->code; - regs->rx0mask = afilter->mask; -} - -static void grcan_hw_sync(struct grcan_regs *regs, struct grcan_filter *sfilter) -{ - /* Disable Sync mask totaly (if we change scode or smask - * in an unfortunate way we may trigger a sync match) - */ - regs->smask = 0xffffffff; - - /* Set Sync Filter in a controlled way */ - regs->scode = sfilter->code; - regs->smask = sfilter->mask; -} - -static unsigned int grcan_hw_rxavail( - unsigned int rp, - unsigned int wp, unsigned int size -) -{ - if (rp == wp) { - /* read pointer and write pointer is equal only - * when RX buffer is empty. - */ - return 0; - } - - if (wp > rp) { - return (wp - rp) / GRCAN_MSG_SIZE; - } else { - return (size - (rp - wp)) / GRCAN_MSG_SIZE; - } -} - -static unsigned int grcan_hw_txspace( - unsigned int rp, - unsigned int wp, - unsigned int size -) -{ - unsigned int left; - - if (rp == wp) { - /* read pointer and write pointer is equal only - * when TX buffer is empty. - */ - return size / GRCAN_MSG_SIZE - WRAP_AROUND_TX_MSGS; - } - - /* size - 4 - abs(read-write) */ - if (wp > rp) { - left = size - (wp - rp); - } else { - left = rp - wp; - } - - return left / GRCAN_MSG_SIZE - WRAP_AROUND_TX_MSGS; -} - -#define MIN_TSEG1 1 -#define MIN_TSEG2 2 -#define MAX_TSEG1 14 -#define MAX_TSEG2 8 - -static int grcan_calc_timing( - unsigned int baud, /* The requested BAUD to calculate timing for */ - unsigned int core_hz, /* Frequency in Hz of GRCAN Core */ - unsigned int sampl_pt, - struct grcan_timing *timing /* result is placed here */ -) -{ - int best_error = 1000000000; - int error; - int best_tseg = 0, best_brp = 0, brp = 0; - int tseg = 0, tseg1 = 0, tseg2 = 0; - int sjw = 1; - - /* Default to 90% */ - if ((sampl_pt < 50) || (sampl_pt > 99)) { - sampl_pt = GRCAN_SAMPLING_POINT; - } - - if ((baud < 5000) || (baud > 1000000)) { - /* invalid speed mode */ - return -1; - } - - /* find best match, return -2 if no good reg - * combination is available for this frequency - */ - - /* some heuristic specials */ - if (baud > ((1000000 + 500000) / 2)) - sampl_pt = 75; - - if (baud < ((12500 + 10000) / 2)) - sampl_pt = 75; - - /* tseg even = round down, odd = round up */ - for ( - tseg = (MIN_TSEG1 + MIN_TSEG2 + 2) * 2; - tseg <= (MAX_TSEG2 + MAX_TSEG1 + 2) * 2 + 1; - tseg++ - ) { - brp = core_hz / ((1 + tseg / 2) * baud) + tseg % 2; - if ( - (brp <= 0) || - ((brp > 256 * 1) && (brp <= 256 * 2) && (brp & 0x1)) || - ((brp > 256 * 2) && (brp <= 256 * 4) && (brp & 0x3)) || - ((brp > 256 * 4) && (brp <= 256 * 8) && (brp & 0x7)) || - (brp > 256 * 8) - ) - continue; - - error = baud - core_hz / (brp * (1 + tseg / 2)); - if (error < 0) { - error = -error; - } - - if (error <= best_error) { - best_error = error; - best_tseg = tseg / 2; - best_brp = brp - 1; - } - } - - if (best_error && (baud / best_error < 10)) { - return -2; - } else if (!timing) - return 0; /* nothing to store result in, but a valid bitrate can be calculated */ - - tseg2 = best_tseg - (sampl_pt * (best_tseg + 1)) / 100; - - if (tseg2 < MIN_TSEG2) { - tseg2 = MIN_TSEG2; - } - - if (tseg2 > MAX_TSEG2) { - tseg2 = MAX_TSEG2; - } - - tseg1 = best_tseg - tseg2 - 2; - - if (tseg1 > MAX_TSEG1) { - tseg1 = MAX_TSEG1; - tseg2 = best_tseg - tseg1 - 2; - } - - /* Get scaler and BRP from pseudo BRP */ - if (best_brp <= 256) { - timing->scaler = best_brp; - timing->bpr = 0; - } else if (best_brp <= 256 * 2) { - timing->scaler = ((best_brp + 1) >> 1) - 1; - timing->bpr = 1; - } else if (best_brp <= 256 * 4) { - timing->scaler = ((best_brp + 1) >> 2) - 1; - timing->bpr = 2; - } else { - timing->scaler = ((best_brp + 1) >> 3) - 1; - timing->bpr = 3; - } - - timing->ps1 = tseg1 + 1; - timing->ps2 = tseg2; - timing->rsj = sjw; - - return 0; -} - -static int grcan_hw_read_try( - struct grcan_priv *pDev, - struct grcan_regs *regs, - CANMsg * buffer, - int max -) -{ - int i, j; - CANMsg *dest; - struct grcan_msg *source, tmp; - unsigned int wp, rp, size, rxmax, addr; - int trunk_msg_cnt; - - FUNCDBG(); - - wp = READ_REG(®s->rx0wr); - rp = READ_REG(®s->rx0rd); - - /* - * Due to hardware wrap around simplification write pointer will - * never reach the read pointer, at least a gap of 8 bytes. - * The only time they are equal is when the read pointer has - * reached the write pointer (empty buffer) - * - */ - if (wp != rp) { - /* Not empty, we have received chars... - * Read as much as possible from DMA buffer - */ - size = READ_REG(®s->rx0size); - - /* Get number of bytes available in RX buffer */ - trunk_msg_cnt = grcan_hw_rxavail(rp, wp, size); - - /* truncate size if user space buffer hasn't room for - * all received chars. - */ - if (trunk_msg_cnt > max) - trunk_msg_cnt = max; - - /* Read until i is 0 */ - i = trunk_msg_cnt; - - addr = (unsigned int)pDev->rx; - source = (struct grcan_msg *)(addr + rp); - dest = buffer; - rxmax = addr + (size - GRCAN_MSG_SIZE); - - /* Read as many can messages as possible */ - while (i > 0) { - /* Read CAN message from DMA buffer */ - tmp.head[0] = READ_DMA_WORD(&source->head[0]); - tmp.head[1] = READ_DMA_WORD(&source->head[1]); - if (tmp.head[1] & 0x4) { - DBGC(DBG_RX, "overrun\n"); - } - if (tmp.head[1] & 0x2) { - DBGC(DBG_RX, "bus-off mode\n"); - } - if (tmp.head[1] & 0x1) { - DBGC(DBG_RX, "error-passive mode\n"); - } - /* Convert one grcan CAN message to one "software" CAN message */ - dest->extended = tmp.head[0] >> 31; - dest->rtr = (tmp.head[0] >> 30) & 0x1; - if (dest->extended) { - dest->id = tmp.head[0] & 0x3fffffff; - } else { - dest->id = (tmp.head[0] >> 18) & 0xfff; - } - dest->len = tmp.head[1] >> 28; - for (j = 0; j < dest->len; j++) - dest->data[j] = READ_DMA_BYTE(&source->data[j]); - - /* wrap around if neccessary */ - source = - ((unsigned int)source >= rxmax) ? - (struct grcan_msg *)addr : source + 1; - dest++; /* straight user buffer */ - i--; - } - { - /* A bus off interrupt may have occured after checking pDev->started */ - SPIN_IRQFLAGS(oldLevel); - - SPIN_LOCK_IRQ(&pDev->devlock, oldLevel); - if (pDev->started == STATE_STARTED) { - regs->rx0rd = (unsigned int) source - addr; - regs->rx0ctrl = GRCAN_RXCTRL_ENABLE; - } else { - DBGC(DBG_STATE, "cancelled due to a BUS OFF error\n"); - trunk_msg_cnt = state2err[pDev->started]; - } - SPIN_UNLOCK_IRQ(&pDev->devlock, oldLevel); - } - return trunk_msg_cnt; - } - return 0; -} - -static int grcan_hw_write_try( - struct grcan_priv *pDev, - struct grcan_regs *regs, - CANMsg * buffer, - int count -) -{ - unsigned int rp, wp, size, txmax, addr; - int ret; - struct grcan_msg *dest; - CANMsg *source; - int space_left; - unsigned int tmp; - int i; - - DBGC(DBG_TX, "\n"); - /*FUNCDBG(); */ - - rp = READ_REG(®s->tx0rd); - wp = READ_REG(®s->tx0wr); - size = READ_REG(®s->tx0size); - - space_left = grcan_hw_txspace(rp, wp, size); - - /* is circular fifo full? */ - if (space_left < 1) - return 0; - - /* Truncate size */ - if (space_left > count) - space_left = count; - ret = space_left; - - addr = (unsigned int)pDev->tx; - - dest = (struct grcan_msg *)(addr + wp); - source = (CANMsg *) buffer; - txmax = addr + (size - GRCAN_MSG_SIZE); - - while (space_left > 0) { - /* Convert and write CAN message to DMA buffer */ - if (source->extended) { - tmp = (1 << 31) | (source->id & 0x3fffffff); - } else { - tmp = (source->id & 0xfff) << 18; - } - if (source->rtr) - tmp |= (1 << 30); - dest->head[0] = tmp; - dest->head[1] = source->len << 28; - for (i = 0; i < source->len; i++) - dest->data[i] = source->data[i]; - source++; /* straight user buffer */ - dest = - ((unsigned int)dest >= txmax) ? - (struct grcan_msg *)addr : dest + 1; - space_left--; - } - - { - /* A bus off interrupt may have occured after checking pDev->started */ - SPIN_IRQFLAGS(oldLevel); - - SPIN_LOCK_IRQ(&pDev->devlock, oldLevel); - if (pDev->started == STATE_STARTED) { - regs->tx0wr = (unsigned int) dest - addr; - regs->tx0ctrl = GRCAN_TXCTRL_ENABLE; - } else { - DBGC(DBG_STATE, "cancelled due to a BUS OFF error\n"); - ret = state2err[pDev->started]; - } - SPIN_UNLOCK_IRQ(&pDev->devlock, oldLevel); - } - return ret; -} - -static int grcan_wait_rxdata(struct grcan_priv *pDev, int min) -{ - unsigned int wp, rp, size, irq; - unsigned int irq_trunk, dataavail; - int wait, state; - SPIN_IRQFLAGS(oldLevel); - - FUNCDBG(); - - /*** block until receive IRQ received - * Set up a valid IRQ point so that an IRQ is received - * when one or more messages are received - */ - SPIN_LOCK_IRQ(&pDev->devlock, oldLevel); - state = pDev->started; - - /* A bus off interrupt may have occured after checking pDev->started */ - if (state != STATE_STARTED) { - SPIN_UNLOCK_IRQ(&pDev->devlock, oldLevel); - if (state == STATE_BUSOFF) { - DBGC(DBG_STATE, "cancelled due to a BUS OFF error\n"); - } else if (state == STATE_AHBERR) { - DBGC(DBG_STATE, "cancelled due to a AHB error\n"); - } else { - DBGC(DBG_STATE, "cancelled due to STOP (unexpected) \n"); - } - return state2err[state]; - } - - size = READ_REG(&pDev->regs->rx0size); - rp = READ_REG(&pDev->regs->rx0rd); - wp = READ_REG(&pDev->regs->rx0wr); - - /**** Calculate IRQ Pointer ****/ - irq = wp + min * GRCAN_MSG_SIZE; - /* wrap irq around */ - if (irq >= size) { - irq_trunk = irq - size; - } else - irq_trunk = irq; - - /* init IRQ HW */ - pDev->regs->rx0irq = irq_trunk; - - /* Clear pending Rx IRQ */ - pDev->regs->picr = GRCAN_RXIRQ_IRQ; - - wp = READ_REG(&pDev->regs->rx0wr); - - /* Calculate messages available */ - dataavail = grcan_hw_rxavail(rp, wp, size); - - if (dataavail < min) { - /* Still empty, proceed with sleep - Turn on IRQ (unmask irq) */ - pDev->regs->imr = READ_REG(&pDev->regs->imr) | GRCAN_RXIRQ_IRQ; - wait = 1; - } else { - /* enough message has been received, abort sleep - don't unmask interrupt */ - wait = 0; - } - SPIN_UNLOCK_IRQ(&pDev->devlock, oldLevel); - - /* Wait for IRQ to fire only if has been triggered */ - if (wait) { - rtems_semaphore_obtain(pDev->rx_sem, RTEMS_WAIT, RTEMS_NO_TIMEOUT); - /* - * The semaphore is released either due to the expected IRQ - * condition or by BUSOFF, AHBERROR or another thread calling - * grcan_stop(). In either case, state2err[] has the correnct - * return value. - */ - return state2err[pDev->started]; - } - - return 0; -} - -/* Wait for TX circular buffer to have room for min CAN messagges. TXIRQ is used to pin - * point the location of the CAN message corresponding to min. - * - * min must be at least WRAP_AROUND_TX_MSGS less than max buffer capacity - * (pDev->txbuf_size/GRCAN_MSG_SIZE) for this algo to work. - */ -static int grcan_wait_txspace(struct grcan_priv *pDev, int min) -{ - int wait, state; - unsigned int irq, rp, wp, size, space_left; - unsigned int irq_trunk; - SPIN_IRQFLAGS(oldLevel); - - DBGC(DBG_TX, "\n"); - /*FUNCDBG(); */ - - SPIN_LOCK_IRQ(&pDev->devlock, oldLevel); - state = pDev->started; - /* A bus off interrupt may have occured after checking pDev->started */ - if (state != STATE_STARTED) { - SPIN_UNLOCK_IRQ(&pDev->devlock, oldLevel); - if (state == STATE_BUSOFF) { - DBGC(DBG_STATE, "cancelled due to a BUS OFF error\n"); - } else if (state == STATE_AHBERR) { - DBGC(DBG_STATE, "cancelled due to a AHB error\n"); - } else { - DBGC(DBG_STATE, "cancelled due to STOP (unexpected)\n"); - } - return state2err[state]; - } - - pDev->regs->tx0ctrl = GRCAN_TXCTRL_ENABLE; - - size = READ_REG(&pDev->regs->tx0size); - wp = READ_REG(&pDev->regs->tx0wr); - - rp = READ_REG(&pDev->regs->tx0rd); - - /**** Calculate IRQ Pointer ****/ - irq = rp + min * GRCAN_MSG_SIZE; - /* wrap irq around */ - if (irq >= size) { - irq_trunk = irq - size; - } else - irq_trunk = irq; - - /* trigger HW to do a IRQ when enough room in buffer */ - pDev->regs->tx0irq = irq_trunk; - - /* Clear pending Tx IRQ */ - pDev->regs->picr = GRCAN_TXIRQ_IRQ; - - /* One problem, if HW already gone past IRQ place the IRQ will - * never be received resulting in a thread hang. We check if so - * before proceeding. - * - * has the HW already gone past the IRQ generation place? - * == does min fit info tx buffer? - */ - rp = READ_REG(&pDev->regs->tx0rd); - - space_left = grcan_hw_txspace(rp, wp, size); - - if (space_left < min) { - /* Still too full, proceed with sleep - Turn on IRQ (unmask irq) */ - pDev->regs->imr = READ_REG(&pDev->regs->imr) | GRCAN_TXIRQ_IRQ; - wait = 1; - } else { - /* There are enough room in buffer, abort wait - don't unmask interrupt */ - wait = 0; - } - SPIN_UNLOCK_IRQ(&pDev->devlock, oldLevel); - - /* Wait for IRQ to fire only if it has been triggered */ - if (wait) { - rtems_semaphore_obtain(pDev->tx_sem, RTEMS_WAIT, RTEMS_NO_TIMEOUT); - return state2err[pDev->started]; - } - - /* At this point the TxIRQ has been masked, we ned not to mask it */ - return 0; -} - -static int grcan_tx_flush(struct grcan_priv *pDev) -{ - int wait, state; - unsigned int rp, wp; - SPIN_IRQFLAGS(oldLevel); - FUNCDBG(); - - /* loop until all data in circular buffer has been read by hw. - * (write pointer != read pointer ) - * - * Hardware doesn't update write pointer - we do - */ - while ( - (wp = READ_REG(&pDev->regs->tx0wr)) != - (rp = READ_REG(&pDev->regs->tx0rd)) - ) { - /* Wait for TX empty IRQ */ - SPIN_LOCK_IRQ(&pDev->devlock, oldLevel); - state = pDev->started; - - /* A bus off interrupt may have occured after checking pDev->started */ - if (state != STATE_STARTED) { - SPIN_UNLOCK_IRQ(&pDev->devlock, oldLevel); - if (state == STATE_BUSOFF) { - DBGC(DBG_STATE, "cancelled due to a BUS OFF error\n"); - } else if (state == STATE_AHBERR) { - DBGC(DBG_STATE, "cancelled due to a AHB error\n"); - } else { - DBGC(DBG_STATE, "cancelled due to STOP (unexpected)\n"); - } - return state2err[state]; - } - - /* Clear pending TXEmpty IRQ */ - pDev->regs->picr = GRCAN_TXEMPTY_IRQ; - - if (wp != READ_REG(&pDev->regs->tx0rd)) { - /* Still not empty, proceed with sleep - Turn on IRQ (unmask irq) */ - pDev->regs->imr = - READ_REG(&pDev->regs->imr) | GRCAN_TXEMPTY_IRQ; - wait = 1; - } else { - /* TX fifo is empty */ - wait = 0; - } - SPIN_UNLOCK_IRQ(&pDev->devlock, oldLevel); - if (!wait) - break; - - /* Wait for IRQ to wake us */ - rtems_semaphore_obtain(pDev->txempty_sem, RTEMS_WAIT, RTEMS_NO_TIMEOUT); - state = pDev->started; - if (state != STATE_STARTED) { - return state2err[state]; - } - } - return 0; -} - -static int grcan_alloc_buffers(struct grcan_priv *pDev, int rx, int tx) -{ - unsigned int adr; - FUNCDBG(); - - if ( tx ) { - adr = (unsigned int)pDev->txbuf_adr; - if (adr & 0x1) { - /* User defined "remote" address. Translate it into - * a CPU accessible address - */ - pDev->_tx_hw = (void *)(adr & ~0x1); - drvmgr_translate_check( - pDev->dev, - DMAMEM_TO_CPU, - (void *)pDev->_tx_hw, - (void **)&pDev->_tx, - pDev->txbuf_size); - pDev->tx = (struct grcan_msg *)pDev->_tx; - } else { - if (adr == 0) { - pDev->_tx = malloc(pDev->txbuf_size + - BUFFER_ALIGNMENT_NEEDS); - if (!pDev->_tx) - return -1; - } else { - /* User defined "cou-local" address. Translate - * it into a CPU accessible address - */ - pDev->_tx = (void *)adr; - } - /* Align TX buffer */ - pDev->tx = (struct grcan_msg *) - (((unsigned int)pDev->_tx + - (BUFFER_ALIGNMENT_NEEDS-1)) & - ~(BUFFER_ALIGNMENT_NEEDS-1)); - - /* Translate address into an hardware accessible - * address - */ - drvmgr_translate_check( - pDev->dev, - CPUMEM_TO_DMA, - (void *)pDev->tx, - (void **)&pDev->_tx_hw, - pDev->txbuf_size); - } - } - - if ( rx ) { - adr = (unsigned int)pDev->rxbuf_adr; - if (adr & 0x1) { - /* User defined "remote" address. Translate it into - * a CPU accessible address - */ - pDev->_rx_hw = (void *)(adr & ~0x1); - drvmgr_translate_check( - pDev->dev, - DMAMEM_TO_CPU, - (void *)pDev->_rx_hw, - (void **)&pDev->_rx, - pDev->rxbuf_size); - pDev->rx = (struct grcan_msg *)pDev->_rx; - } else { - if (adr == 0) { - pDev->_rx = malloc(pDev->rxbuf_size + - BUFFER_ALIGNMENT_NEEDS); - if (!pDev->_rx) - return -1; - } else { - /* User defined "cou-local" address. Translate - * it into a CPU accessible address - */ - pDev->_rx = (void *)adr; - } - /* Align RX buffer */ - pDev->rx = (struct grcan_msg *) - (((unsigned int)pDev->_rx + - (BUFFER_ALIGNMENT_NEEDS-1)) & - ~(BUFFER_ALIGNMENT_NEEDS-1)); - - /* Translate address into an hardware accessible - * address - */ - drvmgr_translate_check( - pDev->dev, - CPUMEM_TO_DMA, - (void *)pDev->rx, - (void **)&pDev->_rx_hw, - pDev->rxbuf_size); - } - } - return 0; -} - -static void grcan_free_buffers(struct grcan_priv *pDev, int rx, int tx) -{ - FUNCDBG(); - - if (tx && pDev->_tx) { - free(pDev->_tx); - pDev->_tx = NULL; - pDev->tx = NULL; - } - - if (rx && pDev->_rx) { - free(pDev->_rx); - pDev->_rx = NULL; - pDev->rx = NULL; - } -} - -int grcan_dev_count(void) -{ - return grcan_count; -} - -void *grcan_open_by_name(char *name, int *dev_no) -{ - int i; - for (i = 0; i < grcan_count; i++){ - struct grcan_priv *pDev; - - pDev = priv_tab[i]; - if (NULL == pDev) { - continue; - } - if (strncmp(pDev->devName, name, NELEM(pDev->devName)) == 0) { - if (dev_no) - *dev_no = i; - return grcan_open(i); - } - } - return NULL; -} - -void *grcan_open(int dev_no) -{ - struct grcan_priv *pDev; - void *ret; - union drvmgr_key_value *value; - - FUNCDBG(); - - if (grcan_count == 0 || (grcan_count <= dev_no)) { - return NULL; - } - - pDev = priv_tab[dev_no]; - - /* Wait until we get semaphore */ - if (rtems_semaphore_obtain(pDev->dev_sem, RTEMS_WAIT, RTEMS_NO_TIMEOUT) - != RTEMS_SUCCESSFUL) { - return NULL; - } - - /* is device busy/taken? */ - if ( pDev->open ) { - ret = NULL; - goto out; - } - - SPIN_INIT(&pDev->devlock, pDev->devName); - - /* Mark device taken */ - pDev->open = 1; - - pDev->txblock = pDev->rxblock = 1; - pDev->txcomplete = pDev->rxcomplete = 0; - pDev->started = STATE_STOPPED; - pDev->config_changed = 1; - pDev->config.silent = 0; - pDev->config.abort = 0; - pDev->config.selection.selection = 0; - pDev->config.selection.enable0 = 0; - pDev->config.selection.enable1 = 1; - pDev->flushing = 0; - pDev->rx = pDev->_rx = NULL; - pDev->tx = pDev->_tx = NULL; - pDev->txbuf_adr = 0; - pDev->rxbuf_adr = 0; - pDev->txbuf_size = TX_BUF_SIZE; - pDev->rxbuf_size = RX_BUF_SIZE; - - /* Override default buffer sizes if available from bus resource */ - value = drvmgr_dev_key_get(pDev->dev, "txBufSize", DRVMGR_KT_INT); - if ( value ) - pDev->txbuf_size = value->i; - - value = drvmgr_dev_key_get(pDev->dev, "rxBufSize", DRVMGR_KT_INT); - if ( value ) - pDev->rxbuf_size = value->i; - - value = drvmgr_dev_key_get(pDev->dev, "txBufAdr", DRVMGR_KT_POINTER); - if ( value ) - pDev->txbuf_adr = value->ptr; - - value = drvmgr_dev_key_get(pDev->dev, "rxBufAdr", DRVMGR_KT_POINTER); - if ( value ) - pDev->rxbuf_adr = value->ptr; - - DBG("Defaulting to rxbufsize: %d, txbufsize: %d\n",RX_BUF_SIZE,TX_BUF_SIZE); - - /* Default to accept all messages */ - pDev->afilter.mask = 0x00000000; - pDev->afilter.code = 0x00000000; - - /* Default to disable sync messages (only trigger when id is set to all ones) */ - pDev->sfilter.mask = 0xffffffff; - pDev->sfilter.code = 0x00000000; - - /* Calculate default timing register values */ - grcan_calc_timing(GRCAN_DEFAULT_BAUD,pDev->corefreq_hz,GRCAN_SAMPLING_POINT,&pDev->config.timing); - - if ( grcan_alloc_buffers(pDev,1,1) ) { - ret = NULL; - goto out; - } - - /* Clear statistics */ - memset(&pDev->stats,0,sizeof(struct grcan_stats)); - - ret = pDev; -out: - rtems_semaphore_release(pDev->dev_sem); - return ret; -} - -int grcan_close(void *d) -{ - struct grcan_priv *pDev = d; - - FUNCDBG(); - - grcan_stop(d); - - grcan_hw_reset(pDev->regs); - - grcan_free_buffers(pDev,1,1); - - /* Mark Device as closed */ - pDev->open = 0; - - return 0; -} - -int grcan_read(void *d, CANMsg *msg, size_t ucount) -{ - struct grcan_priv *pDev = d; - CANMsg *dest; - unsigned int count, left; - int nread; - int req_cnt; - - FUNCDBG(); - - dest = msg; - req_cnt = ucount; - - if ( (!dest) || (req_cnt<1) ) - return GRCAN_RET_INVARG; - - if (pDev->started != STATE_STARTED) { - return GRCAN_RET_NOTSTARTED; - } - - DBGC(DBG_RX, "grcan_read [%p]: buf: %p len: %u\n", d, msg, (unsigned int) ucount); - - nread = grcan_hw_read_try(pDev,pDev->regs,dest,req_cnt); - if (nread < 0) { - return nread; - } - count = nread; - if ( !( pDev->rxblock && pDev->rxcomplete && (count!=req_cnt) ) ){ - if ( count > 0 ) { - /* Successfully received messages (at least one) */ - return count; - } - - /* nothing read, shall we block? */ - if ( !pDev->rxblock ) { - /* non-blocking mode */ - return GRCAN_RET_TIMEOUT; - } - } - - while (count == 0 || (pDev->rxcomplete && (count!=req_cnt))) { - if (!pDev->rxcomplete) { - left = 1; /* return as soon as there is one message available */ - } else { - left = req_cnt - count; /* return as soon as all data are available */ - - /* never wait for more than the half the maximum size of the receive buffer - * Why? We need some time to copy buffer before to catch up with hw, - * otherwise we would have to copy everything when the data has been - * received. - */ - if (left > ((pDev->rxbuf_size/GRCAN_MSG_SIZE) / 2)){ - left = (pDev->rxbuf_size/GRCAN_MSG_SIZE) / 2; - } - } - - nread = grcan_wait_rxdata(pDev, left); - if (nread) { - /* The wait has been aborted, probably due to - * the device driver has been closed by another - * thread or a bus-off. Return error code. - */ - return nread; - } - - /* Try read bytes from circular buffer */ - nread = grcan_hw_read_try( - pDev, - pDev->regs, - dest+count, - req_cnt-count); - - if (nread < 0) { - /* The read was aborted by bus-off. */ - return nread; - } - count += nread; - } - /* no need to unmask IRQ as IRQ Handler do that for us. */ - return count; -} - -int grcan_write(void *d, CANMsg *msg, size_t ucount) -{ - struct grcan_priv *pDev = d; - CANMsg *source; - unsigned int count, left; - int nwritten; - int req_cnt; - - DBGC(DBG_TX,"\n"); - - if ((pDev->started != STATE_STARTED) || pDev->config.silent || pDev->flushing) - return GRCAN_RET_NOTSTARTED; - - req_cnt = ucount; - source = (CANMsg *) msg; - - /* check proper length and buffer pointer */ - if (( req_cnt < 1) || (source == NULL) ){ - return GRCAN_RET_INVARG; - } - - nwritten = grcan_hw_write_try(pDev,pDev->regs,source,req_cnt); - if (nwritten < 0) { - return nwritten; - } - count = nwritten; - if ( !(pDev->txblock && pDev->txcomplete && (count!=req_cnt)) ) { - if ( count > 0 ) { - /* Successfully transmitted chars (at least one char) */ - return count; - } - - /* nothing written, shall we block? */ - if ( !pDev->txblock ) { - /* non-blocking mode */ - return GRCAN_RET_TIMEOUT; - } - } - - /* if in txcomplete mode we need to transmit all chars */ - while((count == 0) || (pDev->txcomplete && (count!=req_cnt)) ){ - /*** block until room to fit all or as much of transmit buffer as possible - * IRQ comes. Set up a valid IRQ point so that an IRQ is received - * when we can put a chunk of data into transmit fifo - */ - if ( !pDev->txcomplete ){ - left = 1; /* wait for anything to fit buffer */ - }else{ - left = req_cnt - count; /* wait for all data to fit in buffer */ - - /* never wait for more than the half the maximum size of the transmit - * buffer - * Why? We need some time to fill buffer before hw catches up. - */ - if ( left > ((pDev->txbuf_size/GRCAN_MSG_SIZE)/2) ){ - left = (pDev->txbuf_size/GRCAN_MSG_SIZE)/2; - } - } - - nwritten = grcan_wait_txspace(pDev,left); - /* Wait until more room in transmit buffer */ - if ( nwritten ) { - /* The wait has been aborted, probably due to - * the device driver has been closed by another - * thread. To avoid deadlock we return directly - * with error status. - */ - return nwritten; - } - - /* Try read bytes from circular buffer */ - nwritten = grcan_hw_write_try( - pDev, - pDev->regs, - source+count, - req_cnt-count); - - if (nwritten < 0) { - /* Write was aborted by bus-off. */ - return nwritten; - } - count += nwritten; - } - /* no need to unmask IRQ as IRQ Handler do that for us. */ - - return count; -} - -int grcan_start(void *d) -{ - struct grcan_priv *pDev = d; - - FUNCDBG(); - - if (grcan_get_state(d) == STATE_STARTED) { - return -1; - } - - if ( (grcan_hw_start(pDev)) != RTEMS_SUCCESSFUL ){ - return -2; - } - - /* Clear semaphore state. This is to avoid effects from previous - * bus-off/stop where semahpores where flushed() but the count remained. - */ - rtems_semaphore_obtain(pDev->rx_sem, RTEMS_NO_WAIT, 0); - rtems_semaphore_obtain(pDev->tx_sem, RTEMS_NO_WAIT, 0); - rtems_semaphore_obtain(pDev->txempty_sem, RTEMS_NO_WAIT, 0); - - /* Read and write are now open... */ - pDev->started = STATE_STARTED; - DBGC(DBG_STATE, "STOPPED|BUSOFF|AHBERR->STARTED\n"); - - /* Register interrupt routine and enable IRQ at IRQ ctrl */ - drvmgr_interrupt_register(pDev->dev, 0, pDev->devName, - grcan_interrupt, pDev); - - return 0; -} - -int grcan_stop(void *d) -{ - struct grcan_priv *pDev = d; - SPIN_IRQFLAGS(oldLevel); - int do_sw_stop; - - FUNCDBG(); - - if (pDev->started == STATE_STOPPED) - return -1; - - SPIN_LOCK_IRQ(&pDev->devlock, oldLevel); - if (pDev->started == STATE_STARTED) { - grcan_hw_stop(pDev); - do_sw_stop = 1; - DBGC(DBG_STATE, "STARTED->STOPPED\n"); - } else { - /* - * started == STATE_[STOPPED|BUSOFF|AHBERR] so grcan_hw_stop() - * might already been called from ISR. - */ - DBGC(DBG_STATE, "[STOPPED|BUSOFF|AHBERR]->STOPPED\n"); - do_sw_stop = 0; - } - pDev->started = STATE_STOPPED; - SPIN_UNLOCK_IRQ(&pDev->devlock, oldLevel); - - if (do_sw_stop) - grcan_sw_stop(pDev); - - /* Disable interrupts */ - drvmgr_interrupt_unregister(pDev->dev, 0, grcan_interrupt, pDev); - - return 0; -} - -int grcan_get_state(void *d) -{ - struct grcan_priv *pDev = d; - - FUNCDBG(); - - return pDev->started; -} - -int grcan_flush(void *d) -{ - struct grcan_priv *pDev = d; - int tmp; - - FUNCDBG(); - - if ((pDev->started != STATE_STARTED) || pDev->flushing || pDev->config.silent) - return -1; - - pDev->flushing = 1; - tmp = grcan_tx_flush(pDev); - pDev->flushing = 0; - if ( tmp ) { - /* The wait has been aborted, probably due to - * the device driver has been closed by another - * thread. - */ - return -1; - } - - return 0; -} - -int grcan_set_silent(void* d, int silent) -{ - struct grcan_priv *pDev = d; - - FUNCDBG(); - - if (pDev->started == STATE_STARTED) - return -1; - - pDev->config.silent = silent; - pDev->config_changed = 1; - - return 0; -} - -int grcan_set_abort(void* d, int abort) -{ - struct grcan_priv *pDev = d; - - FUNCDBG(); - - if (pDev->started == STATE_STARTED) - return -1; - - pDev->config.abort = abort; - /* This Configuration parameter doesn't need HurriCANe reset - * ==> no pDev->config_changed = 1; - */ - - return 0; -} - -int grcan_set_selection(void *d, const struct grcan_selection *selection) -{ - struct grcan_priv *pDev = d; - - FUNCDBG(); - - if (pDev->started == STATE_STARTED) - return -1; - - if ( !selection ) - return -2; - - pDev->config.selection = *selection; - pDev->config_changed = 1; - - return 0; -} - -int grcan_set_rxblock(void *d, int block) -{ - struct grcan_priv *pDev = d; - - FUNCDBG(); - - pDev->rxblock = block; - - return 0; -} - -int grcan_set_txblock(void *d, int block) -{ - struct grcan_priv *pDev = d; - - FUNCDBG(); - - pDev->txblock = block; - - return 0; -} - -int grcan_set_txcomplete(void *d, int complete) -{ - struct grcan_priv *pDev = d; - - FUNCDBG(); - - pDev->txcomplete = complete; - - return 0; -} - -int grcan_set_rxcomplete(void *d, int complete) -{ - struct grcan_priv *pDev = d; - - FUNCDBG(); - - pDev->rxcomplete = complete; - - return 0; -} - -int grcan_get_stats(void *d, struct grcan_stats *stats) -{ - struct grcan_priv *pDev = d; - SPIN_IRQFLAGS(oldLevel); - - FUNCDBG(); - - if ( !stats ) - return -1; - - SPIN_LOCK_IRQ(&pDev->devlock, oldLevel); - *stats = pDev->stats; - SPIN_UNLOCK_IRQ(&pDev->devlock, oldLevel); - - return 0; -} - -int grcan_clr_stats(void *d) -{ - struct grcan_priv *pDev = d; - SPIN_IRQFLAGS(oldLevel); - - FUNCDBG(); - - SPIN_LOCK_IRQ(&pDev->devlock, oldLevel); - memset(&pDev->stats,0,sizeof(struct grcan_stats)); - SPIN_UNLOCK_IRQ(&pDev->devlock, oldLevel); - - return 0; -} - -int grcan_set_speed(void *d, unsigned int speed) -{ - struct grcan_priv *pDev = d; - struct grcan_timing timing; - int ret; - - FUNCDBG(); - - /* cannot change speed during run mode */ - if (pDev->started == STATE_STARTED) - return -1; - - /* get speed rate from argument */ - ret = grcan_calc_timing(speed, pDev->corefreq_hz, GRCAN_SAMPLING_POINT, &timing); - if ( ret ) - return -2; - - /* save timing/speed */ - pDev->config.timing = timing; - pDev->config_changed = 1; - - return 0; -} - -int grcan_set_btrs(void *d, const struct grcan_timing *timing) -{ - struct grcan_priv *pDev = d; - - FUNCDBG(); - - /* Set BTR registers manually - * Read GRCAN/HurriCANe Manual. - */ - if (pDev->started == STATE_STARTED) - return -1; - - if ( !timing ) - return -2; - - pDev->config.timing = *timing; - pDev->config_changed = 1; - - return 0; -} - -int grcan_set_afilter(void *d, const struct grcan_filter *filter) -{ - struct grcan_priv *pDev = d; - - FUNCDBG(); - - if ( !filter ){ - /* Disable filtering - let all messages pass */ - pDev->afilter.mask = 0x0; - pDev->afilter.code = 0x0; - }else{ - /* Save filter */ - pDev->afilter = *filter; - } - /* Set hardware acceptance filter */ - grcan_hw_accept(pDev->regs,&pDev->afilter); - - return 0; -} - -int grcan_set_sfilter(void *d, const struct grcan_filter *filter) -{ - struct grcan_priv *pDev = d; - SPIN_IRQFLAGS(oldLevel); - - FUNCDBG(); - - if ( !filter ){ - /* disable TX/RX SYNC filtering */ - pDev->sfilter.mask = 0xffffffff; - pDev->sfilter.mask = 0; - - /* disable Sync interrupt */ - SPIN_LOCK_IRQ(&pDev->devlock, oldLevel); - pDev->regs->imr = READ_REG(&pDev->regs->imr) & ~(GRCAN_RXSYNC_IRQ|GRCAN_TXSYNC_IRQ); - SPIN_UNLOCK_IRQ(&pDev->devlock, oldLevel); - }else{ - /* Save filter */ - pDev->sfilter = *filter; - - /* Enable Sync interrupt */ - SPIN_LOCK_IRQ(&pDev->devlock, oldLevel); - pDev->regs->imr = READ_REG(&pDev->regs->imr) | (GRCAN_RXSYNC_IRQ|GRCAN_TXSYNC_IRQ); - SPIN_UNLOCK_IRQ(&pDev->devlock, oldLevel); - } - /* Set Sync RX/TX filter */ - grcan_hw_sync(pDev->regs,&pDev->sfilter); - - return 0; -} - -int grcan_get_status(void* d, unsigned int *data) -{ - struct grcan_priv *pDev = d; - - FUNCDBG(); - - if ( !data ) - return -1; - - /* Read out the statsu register from the GRCAN core */ - data[0] = READ_REG(&pDev->regs->stat); - - return 0; -} - -/* Error indicators */ -#define GRCAN_IRQ_ERRORS \ - (GRCAN_RXAHBERR_IRQ | GRCAN_TXAHBERR_IRQ | GRCAN_OFF_IRQ) -#define GRCAN_STAT_ERRORS (GRCAN_STAT_AHBERR | GRCAN_STAT_OFF) -/* Warning & RX/TX sync indicators */ -#define GRCAN_IRQ_WARNS \ - (GRCAN_ERR_IRQ | GRCAN_OR_IRQ | GRCAN_TXLOSS_IRQ | \ - GRCAN_RXSYNC_IRQ | GRCAN_TXSYNC_IRQ) -#define GRCAN_STAT_WARNS (GRCAN_STAT_OR | GRCAN_STAT_PASS) - -/* Handle the IRQ */ -static void grcan_interrupt(void *arg) -{ - struct grcan_priv *pDev = arg; - unsigned int status = READ_REG(&pDev->regs->pimsr); - unsigned int canstat = READ_REG(&pDev->regs->stat); - unsigned int imr_clear; - SPIN_ISR_IRQFLAGS(irqflags); - - /* Spurious IRQ call? */ - if ( !status && !canstat ) - return; - - if (pDev->started != STATE_STARTED) { - DBGC(DBG_STATE, "not STARTED (unexpected interrupt)\n"); - pDev->regs->picr = status; - return; - } - - FUNCDBG(); - - if ( (status & GRCAN_IRQ_ERRORS) || (canstat & GRCAN_STAT_ERRORS) ) { - /* Bus-off condition interrupt - * The link is brought down by hardware, we wake all threads - * that is blocked in read/write calls and stop futher calls - * to read/write until user has called ioctl(fd,START,0). - */ - SPIN_LOCK(&pDev->devlock, irqflags); - DBGC(DBG_STATE, "STARTED->BUSOFF|AHBERR\n"); - pDev->stats.ints++; - if ((status & GRCAN_OFF_IRQ) || (canstat & GRCAN_STAT_OFF)) { - /* CAN Bus-off interrupt */ - DBGC(DBG_STATE, "BUSOFF: status: 0x%x, canstat: 0x%x\n", - status, canstat); - pDev->started = STATE_BUSOFF; - pDev->stats.busoff_cnt++; - } else { - /* RX or Tx AHB Error interrupt */ - printk("AHBERROR: status: 0x%x, canstat: 0x%x\n", - status, canstat); - pDev->started = STATE_AHBERR; - pDev->stats.ahberr_cnt++; - } - grcan_hw_stop(pDev); /* this mask all IRQ sources */ - pDev->regs->picr = 0x1ffff; /* clear all interrupts */ - /* - * Prevent driver from affecting bus. Driver can be started - * again with grcan_start(). - */ - SPIN_UNLOCK(&pDev->devlock, irqflags); - - /* Release semaphores to wake blocked threads. */ - grcan_sw_stop(pDev); - - /* - * NOTE: Another interrupt may be pending now so ISR could be - * executed one more time aftert this (first) return. - */ - return; - } - - /* Mask interrupts in one place under spin-lock. */ - imr_clear = status & (GRCAN_RXIRQ_IRQ | GRCAN_TXIRQ_IRQ | GRCAN_TXEMPTY_IRQ); - - SPIN_LOCK(&pDev->devlock, irqflags); - - /* Increment number of interrupts counter */ - pDev->stats.ints++; - if ((status & GRCAN_IRQ_WARNS) || (canstat & GRCAN_STAT_WARNS)) { - - if ( (status & GRCAN_ERR_IRQ) || (canstat & GRCAN_STAT_PASS) ) { - /* Error-Passive interrupt */ - pDev->stats.passive_cnt++; - } - - if ( (status & GRCAN_OR_IRQ) || (canstat & GRCAN_STAT_OR) ) { - /* Over-run during reception interrupt */ - pDev->stats.overrun_cnt++; - } - - if ( status & GRCAN_TXLOSS_IRQ ) { - pDev->stats.txloss_cnt++; - } - - if ( status & GRCAN_TXSYNC_IRQ ) { - /* TxSync message transmitted interrupt */ - pDev->stats.txsync_cnt++; - } - - if ( status & GRCAN_RXSYNC_IRQ ) { - /* RxSync message received interrupt */ - pDev->stats.rxsync_cnt++; - } - } - - if (imr_clear) { - pDev->regs->imr = READ_REG(&pDev->regs->imr) & ~imr_clear; - - SPIN_UNLOCK(&pDev->devlock, irqflags); - - if ( status & GRCAN_RXIRQ_IRQ ) { - /* RX IRQ pointer interrupt */ - rtems_semaphore_release(pDev->rx_sem); - } - - if ( status & GRCAN_TXIRQ_IRQ ) { - /* TX IRQ pointer interrupt */ - rtems_semaphore_release(pDev->tx_sem); - } - - if (status & GRCAN_TXEMPTY_IRQ ) { - rtems_semaphore_release(pDev->txempty_sem); - } - } else { - SPIN_UNLOCK(&pDev->devlock, irqflags); - } - - /* Clear IRQs */ - pDev->regs->picr = status; -} diff --git a/c/src/lib/libbsp/sparc/shared/can/occan.c b/c/src/lib/libbsp/sparc/shared/can/occan.c deleted file mode 100644 index 2c0e49a2d5..0000000000 --- a/c/src/lib/libbsp/sparc/shared/can/occan.c +++ /dev/null @@ -1,1984 +0,0 @@ -/* OC_CAN driver - * - * COPYRIGHT (c) 2007. - * Cobham Gaisler AB. - * - * 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 /* printk */ - -#include -#include -#include - -/* RTEMS -> ERRNO decoding table - -rtems_assoc_t errno_assoc[] = { - { "OK", RTEMS_SUCCESSFUL, 0 }, - { "BUSY", RTEMS_RESOURCE_IN_USE, EBUSY }, - { "INVALID NAME", RTEMS_INVALID_NAME, EINVAL }, - { "NOT IMPLEMENTED", RTEMS_NOT_IMPLEMENTED, ENOSYS }, - { "TIMEOUT", RTEMS_TIMEOUT, ETIMEDOUT }, - { "NO MEMORY", RTEMS_NO_MEMORY, ENOMEM }, - { "NO DEVICE", RTEMS_UNSATISFIED, ENODEV }, - { "INVALID NUMBER", RTEMS_INVALID_NUMBER, EBADF}, - { "NOT RESOURCE OWNER", RTEMS_NOT_OWNER_OF_RESOURCE, EPERM}, - { "IO ERROR", RTEMS_IO_ERROR, EIO}, - { 0, 0, 0 }, -}; - -*/ - -/* -#undef DEBUG -#undef DEBUG_EXTRA -#undef DEBUG_PRINT_REGMAP -*/ - -/* default to byte regs */ -#ifndef OCCAN_WORD_REGS - #define OCCAN_BYTE_REGS -#else - #undef OCCAN_BYTE_REGS -#endif - -/* Enable Fixup code older OCCAN with a TX IRQ-FLAG bug */ -#define OCCAN_TX_IRQ_FLAG_FIXUP 1 - -#define OCCAN_WORD_REG_OFS 0x80 -#define OCCAN_NCORE_OFS 0x100 -#define DEFAULT_CLKDIV 0x7 -#define DEFAULT_EXTENDED_MODE 1 -#define DEFAULT_RX_FIFO_LEN 64 -#define DEFAULT_TX_FIFO_LEN 64 - -/* not implemented yet */ -#undef REDUNDANT_CHANNELS - -/* Define common debug macros */ -#ifdef DEBUG - #define DBG(fmt, vargs...) printk(fmt, ## vargs ) -#else - #define DBG(fmt, vargs...) -#endif - -/* Spin locks mapped via rtems_interrupt_lock_* API: */ -#define SPIN_DECLARE(lock) RTEMS_INTERRUPT_LOCK_MEMBER(lock) -#define SPIN_INIT(lock, name) rtems_interrupt_lock_initialize(lock, name) -#define SPIN_LOCK(lock, level) rtems_interrupt_lock_acquire_isr(lock, &level) -#define SPIN_LOCK_IRQ(lock, level) rtems_interrupt_lock_acquire(lock, &level) -#define SPIN_UNLOCK(lock, level) rtems_interrupt_lock_release_isr(lock, &level) -#define SPIN_UNLOCK_IRQ(lock, level) rtems_interrupt_lock_release(lock, &level) -#define SPIN_IRQFLAGS(k) rtems_interrupt_lock_context k -#define SPIN_ISR_IRQFLAGS(k) SPIN_IRQFLAGS(k) - -/* fifo interface */ -typedef struct { - int cnt; - int ovcnt; /* overwrite count */ - int full; /* 1 = base contain cnt CANMsgs, tail==head */ - CANMsg *tail, *head; - CANMsg *base; - char fifoarea[0]; -} occan_fifo; - -/* PELICAN */ - -typedef struct { - unsigned char - mode, - cmd, - status, - intflags, - inten, - resv0, - bustim0, - bustim1, - unused0[2], - resv1, - arbcode, - errcode, - errwarn, - rx_err_cnt, - tx_err_cnt, - rx_fi_xff; /* this is also acceptance code 0 in reset mode */ - union{ - struct { - unsigned char id[2]; - unsigned char data[8]; - unsigned char next_in_fifo[2]; - } rx_sff; - struct { - unsigned char id[4]; - unsigned char data[8]; - } rx_eff; - struct { - unsigned char id[2]; - unsigned char data[8]; - unsigned char unused[2]; - } tx_sff; - struct { - unsigned char id[4]; - unsigned char data[8]; - } tx_eff; - struct { - unsigned char code[3]; - unsigned char mask[4]; - } rst_accept; - } msg; - unsigned char rx_msg_cnt; - unsigned char unused1; - unsigned char clkdiv; -} pelican8_regs; - -typedef struct { - unsigned char - mode, unused0[3], - cmd, unused1[3], - status, unused2[3], - intflags, unused3[3], - inten, unused4[3], - resv0, unused5[3], - bustim0, unused6[3], - bustim1, unused7[3], - unused8[8], - resv1,unused9[3], - arbcode,unused10[3], - errcode,unused11[3], - errwarn,unused12[3], - rx_err_cnt,unused13[3], - tx_err_cnt,unused14[3], - rx_fi_xff, unused15[3]; /* this is also acceptance code 0 in reset mode */ - /* make sure to use pointers when writing (byte access) to these registers */ - union{ - struct { - unsigned int id[2]; - unsigned int data[8]; - unsigned int next_in_fifo[2]; - } rx_sff; - struct { - unsigned int id[4]; - unsigned int data[8]; - } rx_eff; - struct { - unsigned int id[2]; - unsigned int data[8]; - } tx_sff; - struct { - unsigned int id[4]; - unsigned int data[8]; - } tx_eff; - struct { - unsigned int code[3]; - unsigned int mask[4]; - } rst_accept; - } msg; - unsigned char rx_msg_cnt,unused16[3]; - unsigned char unused17[4]; - unsigned char clkdiv,unused18[3]; -} pelican32_regs; - -#ifdef OCCAN_BYTE_REGS -#define pelican_regs pelican8_regs -#else -#define pelican_regs pelican32_regs -#endif - - -#define MAX_TSEG2 7 -#define MAX_TSEG1 15 - -#if 0 -typedef struct { - unsigned char brp; - unsigned char sjw; - unsigned char tseg1; - unsigned char tseg2; - unsigned char sam; -} occan_speed_regs; -#endif -typedef struct { - unsigned char btr0; - unsigned char btr1; -} occan_speed_regs; - -typedef struct { - struct drvmgr_dev *dev; - char devName[32]; - SPIN_DECLARE(devlock); - - /* hardware shortcuts */ - pelican_regs *regs; - int byte_regs; - int irq; - occan_speed_regs timing; - int channel; /* 0=default, 1=second bus */ - int single_mode; - unsigned int sys_freq_hz; - - /* driver state */ - rtems_id devsem; - rtems_id txsem; - rtems_id rxsem; - int open; - int started; - int rxblk; - int txblk; - int sending; - unsigned int status; - occan_stats stats; - - /* rx&tx fifos */ - occan_fifo *rxfifo; - occan_fifo *txfifo; - - /* Config */ - unsigned int speed; /* speed in HZ */ - unsigned char acode[4]; - unsigned char amask[4]; -} occan_priv; - -/********** FIFO INTERFACE **********/ -static void occan_fifo_put(occan_fifo *fifo); -static CANMsg *occan_fifo_put_claim(occan_fifo *fifo, int force); -static occan_fifo *occan_fifo_create(int cnt); -static void occan_fifo_free(occan_fifo *fifo); -static int occan_fifo_full(occan_fifo *fifo); -static int occan_fifo_empty(occan_fifo *fifo); -static void occan_fifo_get(occan_fifo *fifo); -static CANMsg *occan_fifo_claim_get(occan_fifo *fifo); -static void occan_fifo_clr(occan_fifo *fifo); - -/**** Hardware related Interface ****/ -static int occan_calc_speedregs(unsigned int clock_hz, unsigned int rate, occan_speed_regs *result); -static int occan_set_speedregs(occan_priv *priv, occan_speed_regs *timing); -static void pelican_init(occan_priv *priv); -static void pelican_open(occan_priv *priv); -static int pelican_start(occan_priv *priv); -static void pelican_stop(occan_priv *priv); -static int pelican_send(occan_priv *can, CANMsg *msg); -static void pelican_set_accept(occan_priv *priv, unsigned char *acode, unsigned char *amask); -void occan_interrupt(void *arg); -#ifdef DEBUG_PRINT_REGMAP -static void pelican_regadr_print(pelican_regs *regs); -#endif - -/***** Driver related interface *****/ -static rtems_device_driver occan_ioctl(rtems_device_major_number major, rtems_device_minor_number minor, void *arg); -static rtems_device_driver occan_write(rtems_device_major_number major, rtems_device_minor_number minor, void *arg); -static rtems_device_driver occan_read(rtems_device_major_number major, rtems_device_minor_number minor, void *arg); -static rtems_device_driver occan_close(rtems_device_major_number major, rtems_device_minor_number minor, void *arg); -static rtems_device_driver occan_open(rtems_device_major_number major, rtems_device_minor_number minor, void *arg); -static rtems_device_driver occan_initialize(rtems_device_major_number major, rtems_device_minor_number unused, void *arg); - -#define OCCAN_DRIVER_TABLE_ENTRY { occan_initialize, occan_open, occan_close, occan_read, occan_write, occan_ioctl } -static rtems_driver_address_table occan_driver = OCCAN_DRIVER_TABLE_ENTRY; - - -/* Read byte bypassing */ - - -/* Bypass cache */ -#define READ_REG(priv, address) occan_reg_read(priv, (unsigned int)address) -#define WRITE_REG(priv, address, data) occan_reg_write(priv, (unsigned int)address, data) - -static unsigned int occan_reg_read(occan_priv *priv, unsigned int address) -{ - unsigned int adr; - if ( priv->byte_regs ) { - adr = address; - } else { - /* Word accessed registers */ - adr = (address & (~0x7f)) | ((address & 0x7f)<<2); - } - return *(volatile unsigned char *)adr; -} - -static void occan_reg_write( - occan_priv *priv, - unsigned int address, - unsigned char value) -{ - unsigned int adr; - if ( priv->byte_regs ) { - adr = address; - } else { - /* Word accessed registers */ - adr = (address & (~0x7f)) | ((address & 0x7f)<<2); - } - *(volatile unsigned char *)adr = value;; -} - -/* Mode register bit definitions */ -#define PELICAN_MOD_RESET 0x1 -#define PELICAN_MOD_LISTEN 0x2 -#define PELICAN_MOD_SELFTEST 0x4 -#define PELICAN_MOD_ACCEPT 0x8 - -/* Command register bit definitions */ -#define PELICAN_CMD_TXREQ 0x1 -#define PELICAN_CMD_ABORT 0x2 -#define PELICAN_CMD_RELRXBUF 0x4 -#define PELICAN_CMD_CLRDOVR 0x8 -#define PELICAN_CMD_SELFRXRQ 0x10 - -/* Status register bit definitions */ -#define PELICAN_STAT_RXBUF 0x1 -#define PELICAN_STAT_DOVR 0x2 -#define PELICAN_STAT_TXBUF 0x4 -#define PELICAN_STAT_TXOK 0x8 -#define PELICAN_STAT_RX 0x10 -#define PELICAN_STAT_TX 0x20 -#define PELICAN_STAT_ERR 0x40 -#define PELICAN_STAT_BUS 0x80 - -/* Interrupt register bit definitions */ -#define PELICAN_IF_RX 0x1 -#define PELICAN_IF_TX 0x2 -#define PELICAN_IF_ERRW 0x4 -#define PELICAN_IF_DOVR 0x8 -#define PELICAN_IF_ERRP 0x20 -#define PELICAN_IF_ARB 0x40 -#define PELICAN_IF_BUS 0x80 - -/* Interrupt Enable register bit definitions */ -#define PELICAN_IE_RX 0x1 -#define PELICAN_IE_TX 0x2 -#define PELICAN_IE_ERRW 0x4 -#define PELICAN_IE_DOVR 0x8 -#define PELICAN_IE_ERRP 0x20 -#define PELICAN_IE_ARB 0x40 -#define PELICAN_IE_BUS 0x80 - -/* Arbitration lost capture register bit definitions */ -#define PELICAN_ARB_BITS 0x1f - -/* register bit definitions */ -#define PELICAN_ECC_CODE_BIT 0x00 -#define PELICAN_ECC_CODE_FORM 0x40 -#define PELICAN_ECC_CODE_STUFF 0x80 -#define PELICAN_ECC_CODE_OTHER 0xc0 -#define PELICAN_ECC_CODE 0xc0 - -#define PELICAN_ECC_DIR 0x20 -#define PELICAN_ECC_SEG 0x1f - -/* Clock divider register bit definitions */ -#define PELICAN_CDR_DIV 0x7 -#define PELICAN_CDR_OFF 0x8 -#define PELICAN_CDR_MODE 0x80 -#define PELICAN_CDR_MODE_PELICAN 0x80 -#define PELICAN_CDR_MODE_BITS 7 -#define PELICAN_CDR_MODE_BASICAN 0x00 - - -/* register bit definitions */ -#define OCCAN_BUSTIM_SJW 0xc0 -#define OCCAN_BUSTIM_BRP 0x3f -#define OCCAN_BUSTIM_SJW_BIT 6 - -#define OCCAN_BUSTIM_SAM 0x80 -#define OCCAN_BUSTIM_TSEG2 0x70 -#define OCCAN_BUSTIM_TSEG2_BIT 4 -#define OCCAN_BUSTIM_TSEG1 0x0f - -/* register bit definitions */ -/* -#define PELICAN_S_ 0x1 -#define PELICAN_S_ 0x2 -#define PELICAN_S_ 0x4 -#define PELICAN_S_ 0x8 -#define PELICAN_S_ 0x10 -#define PELICAN_S_ 0x20 -#define PELICAN_S_ 0x40 -#define PELICAN_S_ 0x80 -*/ - -static int occan_driver_io_registered = 0; -static rtems_device_major_number occan_driver_io_major = 0; - -/******************* Driver manager interface ***********************/ - -/* Driver prototypes */ -int occan_register_io(rtems_device_major_number *m); -int occan_device_init(occan_priv *pDev); - -int occan_init2(struct drvmgr_dev *dev); -int occan_init3(struct drvmgr_dev *dev); - -struct drvmgr_drv_ops occan_ops = -{ - .init = {NULL, occan_init2, occan_init3, NULL}, - .remove = NULL, - .info = NULL -}; - -struct amba_dev_id occan_ids[] = -{ - {VENDOR_GAISLER, GAISLER_CANAHB}, - {0, 0} /* Mark end of table */ -}; - -struct amba_drv_info occan_drv_info = -{ - { - DRVMGR_OBJ_DRV, /* Driver */ - NULL, /* Next driver */ - NULL, /* Device list */ - DRIVER_AMBAPP_GAISLER_OCCAN_ID, /* Driver ID */ - "OCCAN_DRV", /* Driver Name */ - DRVMGR_BUS_TYPE_AMBAPP, /* Bus Type */ - &occan_ops, - NULL, /* Funcs */ - 0, /* No devices yet */ - 0, - }, - &occan_ids[0] -}; - -void occan_register_drv (void) -{ - DBG("Registering OCCAN driver\n"); - drvmgr_drv_register(&occan_drv_info.general); -} - -int occan_init2(struct drvmgr_dev *dev) -{ - occan_priv *priv; - - DBG("OCCAN[%d] on bus %s\n", dev->minor_drv, dev->parent->dev->name); - priv = dev->priv = malloc(sizeof(occan_priv)); - if ( !priv ) - return DRVMGR_NOMEM; - memset(priv, 0, sizeof(*priv)); - priv->dev = dev; - - return DRVMGR_OK; -} - -int occan_init3(struct drvmgr_dev *dev) -{ - occan_priv *priv; - char prefix[32]; - rtems_status_code status; - - priv = dev->priv; - - /* Do initialization */ - - if ( occan_driver_io_registered == 0) { - /* Register the I/O driver only once for all cores */ - if ( occan_register_io(&occan_driver_io_major) ) { - /* Failed to register I/O driver */ - dev->priv = NULL; - return DRVMGR_FAIL; - } - - occan_driver_io_registered = 1; - } - - /* I/O system registered and initialized - * Now we take care of device initialization. - */ - - if ( occan_device_init(priv) ) { - return DRVMGR_FAIL; - } - - /* Get Filesystem name prefix */ - prefix[0] = '\0'; - if ( drvmgr_get_dev_prefix(dev, prefix) ) { - /* Failed to get prefix, make sure of a unique FS name - * by using the driver minor. - */ - sprintf(priv->devName, "/dev/occan%d", dev->minor_drv); - } else { - /* Got special prefix, this means we have a bus prefix - * And we should use our "bus minor" - */ - sprintf(priv->devName, "/dev/%soccan%d", prefix, dev->minor_bus); - } - - /* Register Device */ - DBG("OCCAN[%d]: Registering %s\n", dev->minor_drv, priv->devName); - status = rtems_io_register_name(priv->devName, occan_driver_io_major, dev->minor_drv); - if (status != RTEMS_SUCCESSFUL) { - return DRVMGR_FAIL; - } - - return DRVMGR_OK; -} - -/******************* Driver Implementation ***********************/ - -int occan_register_io(rtems_device_major_number *m) -{ - rtems_status_code r; - - if ((r = rtems_io_register_driver(0, &occan_driver, m)) == RTEMS_SUCCESSFUL) { - DBG("OCCAN driver successfully registered, major: %d\n", *m); - } else { - switch(r) { - case RTEMS_TOO_MANY: - printk("OCCAN rtems_io_register_driver failed: RTEMS_TOO_MANY\n"); - return -1; - case RTEMS_INVALID_NUMBER: - printk("OCCAN rtems_io_register_driver failed: RTEMS_INVALID_NUMBER\n"); - return -1; - case RTEMS_RESOURCE_IN_USE: - printk("OCCAN rtems_io_register_driver failed: RTEMS_RESOURCE_IN_USE\n"); - return -1; - default: - printk("OCCAN rtems_io_register_driver failed\n"); - return -1; - } - } - return 0; -} - -int occan_device_init(occan_priv *pDev) -{ - struct amba_dev_info *ambadev; - struct ambapp_core *pnpinfo; - rtems_status_code status; - int minor; - - /* Get device information from AMBA PnP information */ - ambadev = (struct amba_dev_info *)pDev->dev->businfo; - if ( ambadev == NULL ) { - return -1; - } - pnpinfo = &ambadev->info; - pDev->irq = pnpinfo->irq; - pDev->regs = (pelican_regs *)(pnpinfo->ahb_slv->start[0] + OCCAN_NCORE_OFS*pnpinfo->index); - pDev->byte_regs = 1; - minor = pDev->dev->minor_drv; - - /* Get frequency in Hz */ - if ( drvmgr_freq_get(pDev->dev, DEV_AHB_SLV, &pDev->sys_freq_hz) ) { - return -1; - } - - DBG("OCCAN frequency: %d Hz\n", pDev->sys_freq_hz); - - /* initialize software */ - pDev->open = 0; - pDev->started = 0; /* Needed for spurious interrupts */ - pDev->rxfifo = NULL; - pDev->txfifo = NULL; - status = rtems_semaphore_create( - rtems_build_name('C', 'd', 'v', '0'+minor), - 1, - RTEMS_FIFO | RTEMS_SIMPLE_BINARY_SEMAPHORE | RTEMS_NO_INHERIT_PRIORITY | \ - RTEMS_NO_PRIORITY_CEILING, - 0, - &pDev->devsem); - if ( status != RTEMS_SUCCESSFUL ){ - printk("OCCAN[%d]: Failed to create dev semaphore, (%d)\n\r",minor, status); - return RTEMS_UNSATISFIED; - } - status = rtems_semaphore_create( - rtems_build_name('C', 't', 'x', '0'+minor), - 0, - RTEMS_FIFO | RTEMS_SIMPLE_BINARY_SEMAPHORE | RTEMS_NO_INHERIT_PRIORITY | \ - RTEMS_NO_PRIORITY_CEILING, - 0, - &pDev->txsem); - if ( status != RTEMS_SUCCESSFUL ){ - printk("OCCAN[%d]: Failed to create tx semaphore, (%d)\n\r",minor, status); - return RTEMS_UNSATISFIED; - } - status = rtems_semaphore_create( - rtems_build_name('C', 'r', 'x', '0'+minor), - 0, - RTEMS_FIFO | RTEMS_SIMPLE_BINARY_SEMAPHORE | RTEMS_NO_INHERIT_PRIORITY | \ - RTEMS_NO_PRIORITY_CEILING, - 0, - &pDev->rxsem); - if ( status != RTEMS_SUCCESSFUL ){ - printk("OCCAN[%d]: Failed to create rx semaphore, (%d)\n\r",minor, status); - return RTEMS_UNSATISFIED; - } - - /* hardware init/reset */ - pelican_init(pDev); - -#ifdef DEBUG_PRINT_REGMAP - pelican_regadr_print(pDev->regs); -#endif - - return 0; -} - - -#ifdef DEBUG -static void pelican_regs_print(occan_priv *pDev){ - pelican_regs *regs = pDev->regs; - printk("--- PELICAN 0x%lx ---\n\r",(unsigned int)regs); - printk(" MODE: 0x%02x\n\r",READ_REG(pDev, ®s->mode)); - printk(" CMD: 0x%02x\n\r",READ_REG(pDev, ®s->cmd)); - printk(" STATUS: 0x%02x\n\r",READ_REG(pDev, ®s->status)); - /*printk(" INTFLG: 0x%02x\n\r",READ_REG(pDev, ®s->intflags));*/ - printk(" INTEN: 0x%02x\n\r",READ_REG(pDev, ®s->inten)); - printk(" BTR0: 0x%02x\n\r",READ_REG(pDev, ®s->bustim0)); - printk(" BTR1: 0x%02x\n\r",READ_REG(pDev, ®s->bustim1)); - printk(" ARBCODE: 0x%02x\n\r",READ_REG(pDev, ®s->arbcode)); - printk(" ERRCODE: 0x%02x\n\r",READ_REG(pDev, ®s->errcode)); - printk(" ERRWARN: 0x%02x\n\r",READ_REG(pDev, ®s->errwarn)); - printk(" RX_ERR_CNT: 0x%02x\n\r",READ_REG(pDev, ®s->rx_err_cnt)); - printk(" TX_ERR_CNT: 0x%02x\n\r",READ_REG(pDev, ®s->tx_err_cnt)); - if ( READ_REG(pDev, ®s->mode) & PELICAN_MOD_RESET ){ - /* in reset mode it is possible to read acceptance filters */ - printk(" ACR0: 0x%02x (0x%lx)\n\r",READ_REG(pDev, ®s->rx_fi_xff),®s->rx_fi_xff); - printk(" ACR1: 0x%02x (0x%lx)\n\r",READ_REG(pDev, ®s->msg.rst_accept.code[0]),(unsigned int)®s->msg.rst_accept.code[0]); - printk(" ACR1: 0x%02x (0x%lx)\n\r",READ_REG(pDev, ®s->msg.rst_accept.code[1]),(unsigned int)®s->msg.rst_accept.code[1]); - printk(" ACR1: 0x%02x (0x%lx)\n\r",READ_REG(pDev, ®s->msg.rst_accept.code[2]),(unsigned int)®s->msg.rst_accept.code[2]); - printk(" AMR0: 0x%02x (0x%lx)\n\r",READ_REG(pDev, ®s->msg.rst_accept.mask[0]),(unsigned int)®s->msg.rst_accept.mask[0]); - printk(" AMR1: 0x%02x (0x%lx)\n\r",READ_REG(pDev, ®s->msg.rst_accept.mask[1]),(unsigned int)®s->msg.rst_accept.mask[1]); - printk(" AMR2: 0x%02x (0x%lx)\n\r",READ_REG(pDev, ®s->msg.rst_accept.mask[2]),(unsigned int)®s->msg.rst_accept.mask[2]); - printk(" AMR3: 0x%02x (0x%lx)\n\r",READ_REG(pDev, ®s->msg.rst_accept.mask[3]),(unsigned int)®s->msg.rst_accept.mask[3]); - - }else{ - printk(" RXFI_XFF: 0x%02x\n\r",READ_REG(pDev, ®s->rx_fi_xff)); - } - printk(" RX_MSG_CNT: 0x%02x\n\r",READ_REG(pDev, ®s->rx_msg_cnt)); - printk(" CLKDIV: 0x%02x\n\r",READ_REG(pDev, ®s->clkdiv)); - printk("-------------------\n\r"); -} -#endif - -#ifdef DEBUG_PRINT_REGMAP -static void pelican_regadr_print(pelican_regs *regs){ - printk("--- PELICAN 0x%lx ---\n\r",(unsigned int)regs); - printk(" MODE: 0x%lx\n\r",(unsigned int)®s->mode); - printk(" CMD: 0x%lx\n\r",(unsigned int)®s->cmd); - printk(" STATUS: 0x%lx\n\r",(unsigned int)®s->status); - /*printk(" INTFLG: 0x%lx\n\r",®s->intflags);*/ - printk(" INTEN: 0x%lx\n\r",(unsigned int)®s->inten); - printk(" BTR0: 0x%lx\n\r",(unsigned int)®s->bustim0); - printk(" BTR1: 0x%lx\n\r",(unsigned int)®s->bustim1); - printk(" ARBCODE: 0x%lx\n\r",(unsigned int)®s->arbcode); - printk(" ERRCODE: 0x%lx\n\r",(unsigned int)®s->errcode); - printk(" ERRWARN: 0x%lx\n\r",(unsigned int)®s->errwarn); - printk(" RX_ERR_CNT: 0x%lx\n\r",(unsigned int)®s->rx_err_cnt); - printk(" TX_ERR_CNT: 0x%lx\n\r",(unsigned int)®s->tx_err_cnt); - - /* in reset mode it is possible to read acceptance filters */ - printk(" RXFI_XFF: 0x%lx\n\r",(unsigned int)®s->rx_fi_xff); - - /* reset registers */ - printk(" ACR0: 0x%lx\n\r",(unsigned int)®s->rx_fi_xff); - printk(" ACR1: 0x%lx\n\r",(unsigned int)®s->msg.rst_accept.code[0]); - printk(" ACR2: 0x%lx\n\r",(unsigned int)®s->msg.rst_accept.code[1]); - printk(" ACR3: 0x%lx\n\r",(unsigned int)®s->msg.rst_accept.code[2]); - printk(" AMR0: 0x%lx\n\r",(unsigned int)®s->msg.rst_accept.mask[0]); - printk(" AMR1: 0x%lx\n\r",(unsigned int)®s->msg.rst_accept.mask[1]); - printk(" AMR2: 0x%lx\n\r",(unsigned int)®s->msg.rst_accept.mask[2]); - printk(" AMR3: 0x%lx\n\r",(unsigned int)®s->msg.rst_accept.mask[3]); - - /* TX Extended */ - printk(" EFFTX_ID[0]: 0x%lx\n\r",(unsigned int)®s->msg.tx_eff.id[0]); - printk(" EFFTX_ID[1]: 0x%lx\n\r",(unsigned int)®s->msg.tx_eff.id[1]); - printk(" EFFTX_ID[2]: 0x%lx\n\r",(unsigned int)®s->msg.tx_eff.id[2]); - printk(" EFFTX_ID[3]: 0x%lx\n\r",(unsigned int)®s->msg.tx_eff.id[3]); - - printk(" EFFTX_DATA[0]: 0x%lx\n\r",(unsigned int)®s->msg.tx_eff.data[0]); - printk(" EFFTX_DATA[1]: 0x%lx\n\r",(unsigned int)®s->msg.tx_eff.data[1]); - printk(" EFFTX_DATA[2]: 0x%lx\n\r",(unsigned int)®s->msg.tx_eff.data[2]); - printk(" EFFTX_DATA[3]: 0x%lx\n\r",(unsigned int)®s->msg.tx_eff.data[3]); - printk(" EFFTX_DATA[4]: 0x%lx\n\r",(unsigned int)®s->msg.tx_eff.data[4]); - printk(" EFFTX_DATA[5]: 0x%lx\n\r",(unsigned int)®s->msg.tx_eff.data[5]); - printk(" EFFTX_DATA[6]: 0x%lx\n\r",(unsigned int)®s->msg.tx_eff.data[6]); - printk(" EFFTX_DATA[7]: 0x%lx\n\r",(unsigned int)®s->msg.tx_eff.data[7]); - - /* RX Extended */ - printk(" EFFRX_ID[0]: 0x%lx\n\r",(unsigned int)®s->msg.rx_eff.id[0]); - printk(" EFFRX_ID[1]: 0x%lx\n\r",(unsigned int)®s->msg.rx_eff.id[1]); - printk(" EFFRX_ID[2]: 0x%lx\n\r",(unsigned int)®s->msg.rx_eff.id[2]); - printk(" EFFRX_ID[3]: 0x%lx\n\r",(unsigned int)®s->msg.rx_eff.id[3]); - - printk(" EFFRX_DATA[0]: 0x%lx\n\r",(unsigned int)®s->msg.rx_eff.data[0]); - printk(" EFFRX_DATA[1]: 0x%lx\n\r",(unsigned int)®s->msg.rx_eff.data[1]); - printk(" EFFRX_DATA[2]: 0x%lx\n\r",(unsigned int)®s->msg.rx_eff.data[2]); - printk(" EFFRX_DATA[3]: 0x%lx\n\r",(unsigned int)®s->msg.rx_eff.data[3]); - printk(" EFFRX_DATA[4]: 0x%lx\n\r",(unsigned int)®s->msg.rx_eff.data[4]); - printk(" EFFRX_DATA[5]: 0x%lx\n\r",(unsigned int)®s->msg.rx_eff.data[5]); - printk(" EFFRX_DATA[6]: 0x%lx\n\r",(unsigned int)®s->msg.rx_eff.data[6]); - printk(" EFFRX_DATA[7]: 0x%lx\n\r",(unsigned int)®s->msg.rx_eff.data[7]); - - - /* RX Extended */ - printk(" SFFRX_ID[0]: 0x%lx\n\r",(unsigned int)®s->msg.rx_sff.id[0]); - printk(" SFFRX_ID[1]: 0x%lx\n\r",(unsigned int)®s->msg.rx_sff.id[1]); - - printk(" SFFRX_DATA[0]: 0x%lx\n\r",(unsigned int)®s->msg.rx_sff.data[0]); - printk(" SFFRX_DATA[1]: 0x%lx\n\r",(unsigned int)®s->msg.rx_sff.data[1]); - printk(" SFFRX_DATA[2]: 0x%lx\n\r",(unsigned int)®s->msg.rx_sff.data[2]); - printk(" SFFRX_DATA[3]: 0x%lx\n\r",(unsigned int)®s->msg.rx_sff.data[3]); - printk(" SFFRX_DATA[4]: 0x%lx\n\r",(unsigned int)®s->msg.rx_sff.data[4]); - printk(" SFFRX_DATA[5]: 0x%lx\n\r",(unsigned int)®s->msg.rx_sff.data[5]); - printk(" SFFRX_DATA[6]: 0x%lx\n\r",(unsigned int)®s->msg.rx_sff.data[6]); - printk(" SFFRX_DATA[7]: 0x%lx\n\r",(unsigned int)®s->msg.rx_sff.data[7]); - - /* TX Extended */ - printk(" SFFTX_ID[0]: 0x%lx\n\r",(unsigned int)®s->msg.tx_sff.id[0]); - printk(" SFFTX_ID[1]: 0x%lx\n\r",(unsigned int)®s->msg.tx_sff.id[1]); - - printk(" SFFTX_DATA[0]: 0x%lx\n\r",(unsigned int)®s->msg.tx_sff.data[0]); - printk(" SFFTX_DATA[1]: 0x%lx\n\r",(unsigned int)®s->msg.tx_sff.data[1]); - printk(" SFFTX_DATA[2]: 0x%lx\n\r",(unsigned int)®s->msg.tx_sff.data[2]); - printk(" SFFTX_DATA[3]: 0x%lx\n\r",(unsigned int)®s->msg.tx_sff.data[3]); - printk(" SFFTX_DATA[4]: 0x%lx\n\r",(unsigned int)®s->msg.tx_sff.data[4]); - printk(" SFFTX_DATA[5]: 0x%lx\n\r",(unsigned int)®s->msg.tx_sff.data[5]); - printk(" SFFTX_DATA[6]: 0x%lx\n\r",(unsigned int)®s->msg.tx_sff.data[6]); - printk(" SFFTX_DATA[7]: 0x%lx\n\r",(unsigned int)®s->msg.tx_sff.data[7]); - - printk(" RX_MSG_CNT: 0x%lx\n\r",(unsigned int)®s->rx_msg_cnt); - printk(" CLKDIV: 0x%lx\n\r",(unsigned int)®s->clkdiv); - printk("-------------------\n\r"); -} -#endif - -#ifdef DEBUG -static void occan_stat_print(occan_stats *stats){ - printk("----Stats----\n\r"); - printk("rx_msgs: %d\n\r",stats->rx_msgs); - printk("tx_msgs: %d\n\r",stats->tx_msgs); - printk("err_warn: %d\n\r",stats->err_warn); - printk("err_dovr: %d\n\r",stats->err_dovr); - printk("err_errp: %d\n\r",stats->err_errp); - printk("err_arb: %d\n\r",stats->err_arb); - printk("err_bus: %d\n\r",stats->err_bus); - printk("Int cnt: %d\n\r",stats->ints); - printk("tx_buf_err: %d\n\r",stats->tx_buf_error); - printk("-------------\n\r"); -} -#endif - -static void pelican_init(occan_priv *priv){ - /* Reset core */ - WRITE_REG(priv, &priv->regs->mode, PELICAN_MOD_RESET); - - /* wait for core to reset complete */ - /*usleep(1);*/ -} - -static void pelican_open(occan_priv *priv){ - int ret; - - /* Set defaults */ - priv->speed = OCCAN_SPEED_250K; - - /* set acceptance filters to accept all messages */ - priv->acode[0] = 0; - priv->acode[1] = 0; - priv->acode[2] = 0; - priv->acode[3] = 0; - priv->amask[0] = 0xff; - priv->amask[1] = 0xff; - priv->amask[2] = 0xff; - priv->amask[3] = 0xff; - - /* Set clock divider to extended mode, clkdiv not connected - */ - WRITE_REG(priv, &priv->regs->clkdiv, (1<sys_freq_hz,priv->speed,&priv->timing); - if ( ret ){ - /* failed to set speed for this system freq, try with 50K instead */ - priv->speed = OCCAN_SPEED_50K; - occan_calc_speedregs(priv->sys_freq_hz, priv->speed, - &priv->timing); - } - - /* disable all interrupts */ - WRITE_REG(priv, &priv->regs->inten, 0); - - /* clear pending interrupts by reading */ - READ_REG(priv, &priv->regs->intflags); -} - -static int pelican_start(occan_priv *priv){ - /* Start HW communication */ - - if ( !priv->rxfifo || !priv->txfifo ) - return -1; - - /* In case we were started before and stopped we - * should empty the TX fifo or try to resend those - * messages. We make it simple... - */ - occan_fifo_clr(priv->txfifo); - - /* Clear status bits */ - priv->status = 0; - priv->sending = 0; - - /* clear pending interrupts */ - READ_REG(priv, &priv->regs->intflags); - - /* clear error counters */ - WRITE_REG(priv, &priv->regs->rx_err_cnt, 0); - WRITE_REG(priv, &priv->regs->tx_err_cnt, 0); - -#ifdef REDUNDANT_CHANNELS - if ( (priv->channel == 0) || (priv->channel >= REDUNDANT_CHANNELS) ){ - /* Select the first (default) channel */ - OCCAN_SET_CHANNEL(priv,0); - }else{ - /* set gpio bit, or something */ - OCCAN_SET_CHANNEL(priv,priv->channel); - } -#endif - /* set the speed regs of the CAN core */ - occan_set_speedregs(priv,&priv->timing); - - DBG("OCCAN: start: set timing regs btr0: 0x%x, btr1: 0x%x\n\r", - READ_REG(priv, &priv->regs->bustim0), - READ_REG(priv, &priv->regs->bustim1)); - - /* Set default acceptance filter */ - pelican_set_accept(priv,priv->acode,priv->amask); - - /* Nothing can fail from here, this must be set before interrupts are - * enabled */ - priv->started = 1; - - /* turn on interrupts */ - WRITE_REG(priv, &priv->regs->inten, - PELICAN_IE_RX | PELICAN_IE_TX | PELICAN_IE_ERRW | - PELICAN_IE_ERRP | PELICAN_IE_BUS); -#ifdef DEBUG - /* print setup before starting */ - pelican_regs_print(priv->regs); - occan_stat_print(&priv->stats); -#endif - - /* core already in reset mode, - * ¤ Exit reset mode - * ¤ Enter Single/Dual mode filtering. - */ - WRITE_REG(priv, &priv->regs->mode, (priv->single_mode << 3)); - - /* Register interrupt routine and unmask IRQ at IRQ controller */ - drvmgr_interrupt_register(priv->dev, 0, "occan", occan_interrupt, priv); - - return 0; -} - -static void pelican_stop(occan_priv *priv) -{ - /* stop HW */ - - drvmgr_interrupt_unregister(priv->dev, 0, occan_interrupt, priv); - -#ifdef DEBUG - /* print setup before stopping */ - pelican_regs_print(priv->regs); - occan_stat_print(&priv->stats); -#endif - - /* put core in reset mode */ - WRITE_REG(priv, &priv->regs->mode, PELICAN_MOD_RESET); - - /* turn off interrupts */ - WRITE_REG(priv, &priv->regs->inten, 0); - - priv->status |= OCCAN_STATUS_RESET; -} - -static inline int pelican_tx_ready(occan_priv *can) -{ - unsigned char status; - pelican_regs *regs = can->regs; - - /* is there room in send buffer? */ - status = READ_REG(can, ®s->status); - if ( !(status & PELICAN_STAT_TXBUF) ) { - /* tx fifo taken, we have to wait */ - return 0; - } - - return 1; -} - -/* Try to send message "msg", if hardware txfifo is - * full, then -1 is returned. - * - * Be sure to have disabled CAN interrupts when - * entering this function. - */ -static int pelican_send(occan_priv *can, CANMsg *msg){ - unsigned char tmp; - pelican_regs *regs = can->regs; - - /* is there room in send buffer? */ - if ( !pelican_tx_ready(can) ) { - /* tx fifo taken, we have to wait */ - return -1; - } - - tmp = msg->len & 0xf; - if ( msg->rtr ) - tmp |= 0x40; - - if ( msg->extended ){ - /* Extended Frame */ - WRITE_REG(can, ®s->rx_fi_xff, 0x80 | tmp); - WRITE_REG(can, ®s->msg.tx_eff.id[0],(msg->id >> (5+8+8)) & 0xff); - WRITE_REG(can, ®s->msg.tx_eff.id[1],(msg->id >> (5+8)) & 0xff); - WRITE_REG(can, ®s->msg.tx_eff.id[2],(msg->id >> (5)) & 0xff); - WRITE_REG(can, ®s->msg.tx_eff.id[3],(msg->id << 3) & 0xf8); - tmp = msg->len; - while(tmp--){ - WRITE_REG(can, ®s->msg.tx_eff.data[tmp], msg->data[tmp]); - } - }else{ - /* Standard Frame */ - WRITE_REG(can, ®s->rx_fi_xff, tmp); - WRITE_REG(can, ®s->msg.tx_sff.id[0],(msg->id >> 3) & 0xff); - WRITE_REG(can, ®s->msg.tx_sff.id[1],(msg->id << 5) & 0xe0); - tmp = msg->len; - while(tmp--){ - WRITE_REG(can, ®s->msg.tx_sff.data[tmp],msg->data[tmp]); - } - } - - /* let HW know of new message */ - if ( msg->sshot ){ - WRITE_REG(can, ®s->cmd, PELICAN_CMD_TXREQ | PELICAN_CMD_ABORT); - }else{ - /* normal case -- try resend until sent */ - WRITE_REG(can, ®s->cmd, PELICAN_CMD_TXREQ); - } - - return 0; -} - - -static void pelican_set_accept(occan_priv *priv, unsigned char *acode, unsigned char *amask) -{ - unsigned char *acode0, *acode1, *acode2, *acode3; - unsigned char *amask0, *amask1, *amask2, *amask3; - - acode0 = &priv->regs->rx_fi_xff; - acode1 = (unsigned char *)&priv->regs->msg.rst_accept.code[0]; - acode2 = (unsigned char *)&priv->regs->msg.rst_accept.code[1]; - acode3 = (unsigned char *)&priv->regs->msg.rst_accept.code[2]; - - amask0 = (unsigned char *)&priv->regs->msg.rst_accept.mask[0]; - amask1 = (unsigned char *)&priv->regs->msg.rst_accept.mask[1]; - amask2 = (unsigned char *)&priv->regs->msg.rst_accept.mask[2]; - amask3 = (unsigned char *)&priv->regs->msg.rst_accept.mask[3]; - - /* Set new mask & code */ - WRITE_REG(priv, acode0, acode[0]); - WRITE_REG(priv, acode1, acode[1]); - WRITE_REG(priv, acode2, acode[2]); - WRITE_REG(priv, acode3, acode[3]); - - WRITE_REG(priv, amask0, amask[0]); - WRITE_REG(priv, amask1, amask[1]); - WRITE_REG(priv, amask2, amask[2]); - WRITE_REG(priv, amask3, amask[3]); -} - - -/* This function calculates BTR0 and BTR1 values for a given bitrate. - * - * Set communication parameters. - * \param clock_hz OC_CAN Core frequency in Hz. - * \param rate Requested baud rate in bits/second. - * \param result Pointer to where resulting BTRs will be stored. - * \return zero if successful to calculate a baud rate. - */ -static int occan_calc_speedregs(unsigned int clock_hz, unsigned int rate, occan_speed_regs *result) -{ - int best_error = 1000000000; - int error; - int best_tseg=0, best_brp=0, brp=0; - int tseg=0, tseg1=0, tseg2=0; - int sjw = 0; - int clock = clock_hz / 2; - int sampl_pt = 90; - - if ( (rate<5000) || (rate>1000000) ){ - /* invalid speed mode */ - return -1; - } - - /* find best match, return -2 if no good reg - * combination is available for this frequency */ - - /* some heuristic specials */ - if (rate > ((1000000 + 500000) / 2)) - sampl_pt = 75; - - if (rate < ((12500 + 10000) / 2)) - sampl_pt = 75; - - if (rate < ((100000 + 125000) / 2)) - sjw = 1; - - /* tseg even = round down, odd = round up */ - for (tseg = (0 + 0 + 2) * 2; - tseg <= (MAX_TSEG2 + MAX_TSEG1 + 2) * 2 + 1; - tseg++) - { - brp = clock / ((1 + tseg / 2) * rate) + tseg % 2; - if ((brp == 0) || (brp > 64)) - continue; - - error = rate - clock / (brp * (1 + tseg / 2)); - if (error < 0) - { - error = -error; - } - - if (error <= best_error) - { - best_error = error; - best_tseg = tseg/2; - best_brp = brp-1; - } - } - - if (best_error && (rate / best_error < 10)) - { - printk("OCCAN: bitrate %d is not possible with %d Hz clock\n\r",rate, clock); - return -2; - }else if ( !result ) - return 0; /* nothing to store result in, but a valid bitrate can be calculated */ - - tseg2 = best_tseg - (sampl_pt * (best_tseg + 1)) / 100; - - if (tseg2 < 0) - { - tseg2 = 0; - } - - if (tseg2 > MAX_TSEG2) - { - tseg2 = MAX_TSEG2; - } - - tseg1 = best_tseg - tseg2 - 2; - - if (tseg1 > MAX_TSEG1) - { - tseg1 = MAX_TSEG1; - tseg2 = best_tseg - tseg1 - 2; - } - - result->btr0 = (sjw<btr1 = (0<<7) | (tseg2<regs) - return -1; - - WRITE_REG(priv, &priv->regs->bustim0, timing->btr0); - WRITE_REG(priv, &priv->regs->bustim1, timing->btr1); - - return 0; -} - -static rtems_device_driver occan_initialize(rtems_device_major_number major, rtems_device_minor_number unused, void *arg) -{ - return RTEMS_SUCCESSFUL; -} - -static rtems_device_driver occan_open(rtems_device_major_number major, rtems_device_minor_number minor, void *arg) -{ - occan_priv *can; - struct drvmgr_dev *dev; - - DBG("OCCAN: Opening %d\n\r",minor); - - /* get can device */ - if ( drvmgr_get_dev(&occan_drv_info.general, minor, &dev) ) { - DBG("Wrong minor %d\n", minor); - return RTEMS_UNSATISFIED; /* NODEV */ - } - can = (occan_priv *)dev->priv; - - /* already opened? */ - rtems_semaphore_obtain(can->devsem, RTEMS_WAIT, RTEMS_NO_TIMEOUT); - if ( can->open ){ - rtems_semaphore_release(can->devsem); - return RTEMS_RESOURCE_IN_USE; /* EBUSY */ - } - can->open = 1; - rtems_semaphore_release(can->devsem); - - SPIN_INIT(&can->devlock, can->devName); - - /* allocate fifos */ - can->rxfifo = occan_fifo_create(DEFAULT_RX_FIFO_LEN); - if ( !can->rxfifo ){ - can->open = 0; - return RTEMS_NO_MEMORY; /* ENOMEM */ - } - - can->txfifo = occan_fifo_create(DEFAULT_TX_FIFO_LEN); - if ( !can->txfifo ){ - occan_fifo_free(can->rxfifo); - can->rxfifo= NULL; - can->open = 0; - return RTEMS_NO_MEMORY; /* ENOMEM */ - } - - DBG("OCCAN: Opening %d success\n\r",minor); - - can->started = 0; - can->channel = 0; /* Default to first can link */ - can->txblk = 1; /* Default to Blocking mode */ - can->rxblk = 1; /* Default to Blocking mode */ - can->single_mode = 1; /* single mode acceptance filter */ - - /* reset stat counters */ - memset(&can->stats,0,sizeof(occan_stats)); - - /* HW must be in reset mode here (close and initializes resets core...) - * - * 1. set default modes/speeds - */ - pelican_open(can); - - return RTEMS_SUCCESSFUL; -} - -static rtems_device_driver occan_close(rtems_device_major_number major, rtems_device_minor_number minor, void *arg) -{ - occan_priv *can; - struct drvmgr_dev *dev; - - DBG("OCCAN: Closing %d\n\r",minor); - - if ( drvmgr_get_dev(&occan_drv_info.general, minor, &dev) ) { - return RTEMS_INVALID_NAME; - } - can = (occan_priv *)dev->priv; - - /* stop if running */ - if ( can->started ) - pelican_stop(can); - - /* Enter Reset Mode */ - WRITE_REG(can, &can->regs->mode, PELICAN_MOD_RESET); - - /* free fifo memory */ - occan_fifo_free(can->rxfifo); - occan_fifo_free(can->txfifo); - - can->rxfifo = NULL; - can->txfifo = NULL; - - can->open = 0; - - return RTEMS_SUCCESSFUL; -} - -static rtems_device_driver occan_read(rtems_device_major_number major, rtems_device_minor_number minor, void *arg) -{ - occan_priv *can; - struct drvmgr_dev *dev; - rtems_libio_rw_args_t *rw_args=(rtems_libio_rw_args_t *) arg; - CANMsg *dstmsg, *srcmsg; - SPIN_IRQFLAGS(oldLevel); - int left; - - if ( drvmgr_get_dev(&occan_drv_info.general, minor, &dev) ) { - return RTEMS_INVALID_NAME; - } - can = (occan_priv *)dev->priv; - - if ( !can->started ){ - DBG("OCCAN: cannot read from minor %d when not started\n\r",minor); - return RTEMS_RESOURCE_IN_USE; /* -EBUSY*/ - } - - /* does at least one message fit */ - left = rw_args->count; - if ( left < sizeof(CANMsg) ){ - DBG("OCCAN: minor %d length of buffer must be at least %d, our is %d\n\r",minor,sizeof(CANMsg),left); - return RTEMS_INVALID_NAME; /* -EINVAL */ - } - - /* get pointer to start where to put CAN messages */ - dstmsg = (CANMsg *)rw_args->buffer; - if ( !dstmsg ){ - DBG("OCCAN: minor %d read: input buffer is NULL\n\r",minor); - return RTEMS_INVALID_NAME; /* -EINVAL */ - } - - while (left >= sizeof(CANMsg) ){ - - /* turn off interrupts */ - SPIN_LOCK_IRQ(&can->devlock, oldLevel); - - /* A bus off interrupt may have occured after checking can->started */ - if ( can->status & (OCCAN_STATUS_ERR_BUSOFF|OCCAN_STATUS_RESET) ){ - SPIN_UNLOCK_IRQ(&can->devlock, oldLevel); - DBG("OCCAN: read is cancelled due to a BUS OFF error\n\r"); - rw_args->bytes_moved = rw_args->count-left; - return RTEMS_IO_ERROR; /* EIO */ - } - - srcmsg = occan_fifo_claim_get(can->rxfifo); - if ( !srcmsg ){ - /* no more messages in reception fifo. - * Wait for incoming packets only if in - * blocking mode AND no messages been - * read before. - */ - if ( !can->rxblk || (left != rw_args->count) ){ - /* turn on interrupts again */ - SPIN_UNLOCK_IRQ(&can->devlock, oldLevel); - break; - } - - /* turn on interrupts again */ - SPIN_UNLOCK_IRQ(&can->devlock, oldLevel); - - DBG("OCCAN: Waiting for RX int\n\r"); - - /* wait for incoming messages */ - rtems_semaphore_obtain(can->rxsem, RTEMS_WAIT, - RTEMS_NO_TIMEOUT); - - /* did we get woken up by a BUS OFF error? */ - if ( can->status & (OCCAN_STATUS_ERR_BUSOFF|OCCAN_STATUS_RESET) ){ - DBG("OCCAN: Blocking read got woken up by BUS OFF error\n\r"); - /* At this point it should not matter how many messages we handled */ - rw_args->bytes_moved = rw_args->count-left; - return RTEMS_IO_ERROR; /* EIO */ - } - - /* no errors detected, it must be a message */ - continue; - } - - /* got message, copy it to userspace buffer */ - *dstmsg = *srcmsg; - - /* Return borrowed message, RX interrupt can use it again */ - occan_fifo_get(can->rxfifo); - - /* turn on interrupts again */ - SPIN_UNLOCK_IRQ(&can->devlock, oldLevel); - - /* increase pointers */ - left -= sizeof(CANMsg); - dstmsg++; - } - - /* save number of read bytes. */ - rw_args->bytes_moved = rw_args->count-left; - if ( rw_args->bytes_moved == 0 ){ - DBG("OCCAN: minor %d read would block, returning\n\r",minor); - return RTEMS_TIMEOUT; /* ETIMEDOUT should be EAGAIN/EWOULDBLOCK */ - } - return RTEMS_SUCCESSFUL; -} - -static rtems_device_driver occan_write(rtems_device_major_number major, rtems_device_minor_number minor, void *arg) -{ - occan_priv *can; - struct drvmgr_dev *dev; - rtems_libio_rw_args_t *rw_args=(rtems_libio_rw_args_t *) arg; - CANMsg *msg,*fifo_msg; - SPIN_IRQFLAGS(oldLevel); - int left; - - DBG("OCCAN: Writing %d bytes from 0x%lx (%d)\n\r",rw_args->count,rw_args->buffer,sizeof(CANMsg)); - - if ( drvmgr_get_dev(&occan_drv_info.general, minor, &dev) ) { - return RTEMS_INVALID_NAME; - } - can = (occan_priv *)dev->priv; - - if ( !can->started ) - return RTEMS_RESOURCE_IN_USE; /* EBUSY */ - - left = rw_args->count; - if ( (left < sizeof(CANMsg)) || (!rw_args->buffer) ){ - return RTEMS_INVALID_NAME; /* EINVAL */ - } - - msg = (CANMsg *)rw_args->buffer; - - /* limit CAN message length to 8 */ - msg->len = (msg->len > 8) ? 8 : msg->len; - -#ifdef DEBUG_VERBOSE - pelican_regs_print(can->regs); - occan_stat_print(&can->stats); -#endif - - /* turn off interrupts */ - SPIN_LOCK_IRQ(&can->devlock, oldLevel); - - /* A bus off interrupt may have occured after checking can->started */ - if ( can->status & (OCCAN_STATUS_ERR_BUSOFF|OCCAN_STATUS_RESET) ){ - SPIN_UNLOCK_IRQ(&can->devlock, oldLevel); - rw_args->bytes_moved = 0; - return RTEMS_IO_ERROR; /* EIO */ - } - - /* If no messages in software tx fifo, we will - * try to send first message by putting it directly - * into the HW TX fifo. - */ - if ( occan_fifo_empty(can->txfifo) ){ - /*pelican_regs_print(cans[minor+1].regs);*/ - if ( !pelican_send(can,msg) ) { - /* First message put directly into HW TX fifo - * This will turn TX interrupt on. - */ - left -= sizeof(CANMsg); - msg++; - -#ifdef OCCAN_TX_IRQ_FLAG_FIXUP - /* Mark that we have put at least one msg in TX FIFO */ - can->sending = 1; -#endif - - /* bump stat counters */ - can->stats.tx_msgs++; - - DBG("OCCAN: Sending direct via HW\n\r"); - } - } - - /* Put messages into software fifo */ - while ( left >= sizeof(CANMsg) ){ - - /* limit CAN message length to 8 */ - msg->len = (msg->len > 8) ? 8 : msg->len; - - fifo_msg = occan_fifo_put_claim(can->txfifo,0); - if ( !fifo_msg ){ - - DBG("OCCAN: FIFO is full\n\r"); - /* Block only if no messages previously sent - * and no in blocking mode - */ - if ( !can->txblk || (left != rw_args->count) ) - break; - - /* turn on interupts again and wait - INT_ON - WAIT FOR FREE BUF; - INT_OFF; - CHECK_IF_FIFO_EMPTY ==> SEND DIRECT VIA HW; - */ - SPIN_UNLOCK_IRQ(&can->devlock, oldLevel); - - DBG("OCCAN: Waiting for tx int\n\r"); - - rtems_semaphore_obtain(can->txsem, RTEMS_WAIT, RTEMS_NO_TIMEOUT); - - /* did we get woken up by a BUS OFF error? */ - if ( can->status & (OCCAN_STATUS_ERR_BUSOFF|OCCAN_STATUS_RESET) ){ - DBG("OCCAN: Blocking write got woken up by BUS OFF error or RESET event\n\r"); - /* At this point it should not matter how many messages we handled */ - rw_args->bytes_moved = rw_args->count-left; - return RTEMS_IO_ERROR; /* EIO */ - } - - SPIN_LOCK_IRQ(&can->devlock, oldLevel); - - if ( occan_fifo_empty(can->txfifo) ){ - if ( !pelican_send(can,msg) ) { - /* First message put directly into HW TX fifo - * This will turn TX interrupt on. - */ - left -= sizeof(CANMsg); - msg++; - -#ifdef OCCAN_TX_IRQ_FLAG_FIXUP - /* Mark that we have put at least one msg in TX FIFO */ - can->sending = 1; -#endif - - /* bump stat counters */ - can->stats.tx_msgs++; - - DBG("OCCAN: Sending direct2 via HW\n\r"); - } - } - continue; - } - - /* copy message into fifo area */ - *fifo_msg = *msg; - - /* tell interrupt handler about the message */ - occan_fifo_put(can->txfifo); - - DBG("OCCAN: Put info fifo SW\n\r"); - - /* Prepare insert of next message */ - msg++; - left-=sizeof(CANMsg); - } - - SPIN_UNLOCK_IRQ(&can->devlock, oldLevel); - - rw_args->bytes_moved = rw_args->count-left; - DBG("OCCAN: Sent %d\n\r",rw_args->bytes_moved); - - if ( left == rw_args->count ) - return RTEMS_TIMEOUT; /* ETIMEDOUT should be EAGAIN/EWOULDBLOCK */ - return RTEMS_SUCCESSFUL; -} - -static rtems_device_driver occan_ioctl(rtems_device_major_number major, rtems_device_minor_number minor, void *arg) -{ - int ret; - occan_speed_regs timing; - occan_priv *can; - struct drvmgr_dev *dev; - unsigned int speed; - rtems_libio_ioctl_args_t *ioarg = (rtems_libio_ioctl_args_t *) arg; - struct occan_afilter *afilter; - occan_stats *dststats; - unsigned int rxcnt,txcnt; - - DBG("OCCAN: IOCTL %d\n\r",ioarg->command); - - if ( drvmgr_get_dev(&occan_drv_info.general, minor, &dev) ) { - return RTEMS_INVALID_NAME; - } - can = (occan_priv *)dev->priv; - - ioarg->ioctl_return = 0; - switch(ioarg->command){ - case OCCAN_IOC_SET_SPEED: - - /* cannot change speed during run mode */ - if ( can->started ) - return RTEMS_RESOURCE_IN_USE; /* EBUSY */ - - /* get speed rate from argument */ - speed = (unsigned int)ioarg->buffer; - ret = occan_calc_speedregs(can->sys_freq_hz,speed,&timing); - if ( ret ) - return RTEMS_INVALID_NAME; /* EINVAL */ - - /* set the speed regs of the CAN core */ - /* occan_set_speedregs(can,timing); */ - - /* save timing/speed */ - can->speed = speed; - can->timing = timing; - break; - - case OCCAN_IOC_SET_BTRS: - /* Set BTR registers manually - * Read OCCAN Manual. - */ - if ( can->started ) - return RTEMS_RESOURCE_IN_USE; /* EBUSY */ - - can->speed = 0; /* custom */ - can->timing.btr1 = (unsigned int)ioarg->buffer & 0xff; - can->timing.btr0 = ((unsigned int)ioarg->buffer>>8) & 0xff; -/* - can->timing.sjw = (btr0 >> OCCAN_BUSTIM_SJW_BIT) & 0x3; - can->timing.brp = btr0 & OCCAN_BUSTIM_BRP; - can->timing.tseg1 = btr1 & 0xf; - can->timing.tseg2 = (btr1 >> OCCAN_BUSTIM_TSEG2_BIT) & 0x7; - can->timing.sam = (btr1 >> 7) & 0x1; - */ - break; - - case OCCAN_IOC_SPEED_AUTO: - return RTEMS_NOT_IMPLEMENTED; - - case OCCAN_IOC_SET_BUFLEN: - /* set rx & tx fifo buffer length */ - if ( can->started ) - return RTEMS_RESOURCE_IN_USE; /* EBUSY */ - - rxcnt = (unsigned int)ioarg->buffer & 0x0000ffff; - txcnt = (unsigned int)ioarg->buffer >> 16; - - occan_fifo_free(can->rxfifo); - occan_fifo_free(can->txfifo); - - /* allocate new buffers */ - can->rxfifo = occan_fifo_create(rxcnt); - can->txfifo = occan_fifo_create(txcnt); - - if ( !can->rxfifo || !can->txfifo ) - return RTEMS_NO_MEMORY; /* ENOMEM */ - break; - - case OCCAN_IOC_GET_CONF: - return RTEMS_NOT_IMPLEMENTED; - break; - - case OCCAN_IOC_GET_STATS: - dststats = (occan_stats *)ioarg->buffer; - if ( !dststats ) - return RTEMS_INVALID_NAME; /* EINVAL */ - - /* copy data stats into userspace buffer */ - if ( can->rxfifo ) - can->stats.rx_sw_dovr = can->rxfifo->ovcnt; - *dststats = can->stats; - break; - - case OCCAN_IOC_GET_STATUS: - /* return the status of the */ - if ( !ioarg->buffer ) - return RTEMS_INVALID_NAME; - - *(unsigned int *)ioarg->buffer = can->status; - break; - - /* Set physical link */ - case OCCAN_IOC_SET_LINK: -#ifdef REDUNDANT_CHANNELS - if ( can->started ) - return RTEMS_RESOURCE_IN_USE; /* EBUSY */ - - /* switch HW channel */ - can->channel = (unsigned int)ioargs->buffer; -#else - return RTEMS_NOT_IMPLEMENTED; -#endif - break; - - case OCCAN_IOC_SET_FILTER: - if ( can->started ) - return RTEMS_RESOURCE_IN_USE; /* EBUSY */ - - afilter = (struct occan_afilter *)ioarg->buffer; - - if ( !afilter ) - return RTEMS_INVALID_NAME; /* EINVAL */ - - /* copy acceptance filter */ - can->acode[0] = afilter->code[0]; - can->acode[1] = afilter->code[1]; - can->acode[2] = afilter->code[2]; - can->acode[3] = afilter->code[3]; - - can->amask[0] = afilter->mask[0]; - can->amask[1] = afilter->mask[1]; - can->amask[2] = afilter->mask[2]; - can->amask[3] = afilter->mask[3]; - - can->single_mode = ( afilter->single_mode ) ? 1 : 0; - - /* Acceptance filter is written to hardware - * when starting. - */ - /* pelican_set_accept(can,can->acode,can->amask);*/ - break; - - case OCCAN_IOC_SET_BLK_MODE: - can->rxblk = (unsigned int)ioarg->buffer & OCCAN_BLK_MODE_RX; - can->txblk = ((unsigned int)ioarg->buffer & OCCAN_BLK_MODE_TX) >> 1; - break; - - case OCCAN_IOC_START: - if ( can->started ) - return RTEMS_RESOURCE_IN_USE; /* EBUSY */ - if ( pelican_start(can) ) - return RTEMS_NO_MEMORY; /* failed because of no memory, can happen if SET_BUFLEN failed */ - /* can->started = 1; -- Is set in pelican_start due to interrupt may occur before we - * get here. - */ - break; - - case OCCAN_IOC_STOP: - if ( !can->started ) - return RTEMS_RESOURCE_IN_USE; /* EBUSY */ - pelican_stop(can); - can->started = 0; - break; - - default: - return RTEMS_NOT_DEFINED; - } - return RTEMS_SUCCESSFUL; -} - -void occan_interrupt(void *arg) -{ - occan_priv *can = arg; - unsigned char iflags; - pelican_regs *regs = can->regs; - CANMsg *msg; - int signal_rx=0, signal_tx=0; - unsigned char tmp, errcode, arbcode; - int tx_error_cnt,rx_error_cnt; - SPIN_ISR_IRQFLAGS(irqflags); - - if ( !can->started ) - return; /* Spurious Interrupt, do nothing */ - - SPIN_LOCK(&can->devlock, irqflags); - while (1) { - - iflags = READ_REG(can, &can->regs->intflags); - -#ifdef OCCAN_TX_IRQ_FLAG_FIXUP - /* TX IRQ may be cleared when reading regs->intflags due - * to a bug in some chips. Instead of looking at the TX_IRQ_FLAG - * the TX-fifo emoty register is looked at when something has - * been scheduled for transmission. - */ - if ((iflags & PELICAN_IF_TX) == 0) { - if (can->sending && pelican_tx_ready(can)) { - can->sending = 0; - iflags |= PELICAN_IF_TX; - } - } -#endif - - if (iflags == 0) - break; - /* still interrupts to handle */ - - can->stats.ints++; - - if ( iflags & PELICAN_IF_RX ){ - /* the rx fifo is not empty - * put 1 message into rxfifo for later use - */ - - /* get empty (or make room) message */ - msg = occan_fifo_put_claim(can->rxfifo,1); - tmp = READ_REG(can, ®s->rx_fi_xff); - msg->extended = tmp >> 7; - msg->rtr = (tmp >> 6) & 1; - msg->len = tmp = tmp & 0x0f; - - if ( msg->extended ){ - /* extended message */ - msg->id = READ_REG(can, ®s->msg.rx_eff.id[0])<<(5+8+8) | - READ_REG(can, ®s->msg.rx_eff.id[1])<<(5+8) | - READ_REG(can, ®s->msg.rx_eff.id[2])<<5 | - READ_REG(can, ®s->msg.rx_eff.id[3])>>3; - - while(tmp--){ - msg->data[tmp] = READ_REG(can, ®s->msg.rx_eff.data[tmp]); - } - /* - msg->data[0] = READ_REG(can, ®s->msg.rx_eff.data[0]); - msg->data[1] = READ_REG(can, ®s->msg.rx_eff.data[1]); - msg->data[2] = READ_REG(can, ®s->msg.rx_eff.data[2]); - msg->data[3] = READ_REG(can, ®s->msg.rx_eff.data[3]); - msg->data[4] = READ_REG(can, ®s->msg.rx_eff.data[4]); - msg->data[5] = READ_REG(can, ®s->msg.rx_eff.data[5]); - msg->data[6] = READ_REG(can, ®s->msg.rx_eff.data[6]); - msg->data[7] = READ_REG(can, ®s->msg.rx_eff.data[7]); - */ - }else{ - /* standard message */ - msg->id = READ_REG(can, ®s->msg.rx_sff.id[0])<<3 | - READ_REG(can, ®s->msg.rx_sff.id[1])>>5; - - while(tmp--){ - msg->data[tmp] = READ_REG(can, ®s->msg.rx_sff.data[tmp]); - } - /* - msg->data[0] = READ_REG(can, ®s->msg.rx_sff.data[0]); - msg->data[1] = READ_REG(can, ®s->msg.rx_sff.data[1]); - msg->data[2] = READ_REG(can, ®s->msg.rx_sff.data[2]); - msg->data[3] = READ_REG(can, ®s->msg.rx_sff.data[3]); - msg->data[4] = READ_REG(can, ®s->msg.rx_sff.data[4]); - msg->data[5] = READ_REG(can, ®s->msg.rx_sff.data[5]); - msg->data[6] = READ_REG(can, ®s->msg.rx_sff.data[6]); - msg->data[7] = READ_REG(can, ®s->msg.rx_sff.data[7]); - */ - } - - /* Re-Enable RX buffer for a new message */ - WRITE_REG(can, ®s->cmd, PELICAN_CMD_RELRXBUF); - - /* make message available to the user */ - occan_fifo_put(can->rxfifo); - - /* bump stat counters */ - can->stats.rx_msgs++; - - /* signal the semaphore only once */ - signal_rx = 1; - } - - if ( iflags & PELICAN_IF_TX ) { - - /* there is room in tx fifo of HW */ - - if ( !occan_fifo_empty(can->txfifo) ){ - /* send 1 more messages */ - msg = occan_fifo_claim_get(can->txfifo); - - if ( pelican_send(can,msg) ){ - /* ERROR! We got an TX interrupt telling us - * tx fifo is empty, yet it is not. - * - * Complain about this max 10 times - */ - if ( can->stats.tx_buf_error < 10 ){ - printk("OCCAN: got TX interrupt but TX fifo in not empty (%d)\n\r",can->stats.tx_buf_error); - } - can->status |= OCCAN_STATUS_QUEUE_ERROR; - can->stats.tx_buf_error++; - } -#ifdef OCCAN_TX_IRQ_FLAG_FIXUP - can->sending = 1; -#endif - - /* free software-fifo space taken by sent message */ - occan_fifo_get(can->txfifo); - - /* bump stat counters */ - can->stats.tx_msgs++; - - /* wake any sleeping thread waiting for "fifo not full" */ - signal_tx = 1; - } - } - - if ( iflags & PELICAN_IF_ERRW ){ - tx_error_cnt = READ_REG(can, ®s->tx_err_cnt); - rx_error_cnt = READ_REG(can, ®s->rx_err_cnt); - - /* 1. if bus off tx error counter = 127 */ - if ( (tx_error_cnt > 96) || (rx_error_cnt > 96) ){ - /* in Error Active Warning area or BUS OFF */ - can->status |= OCCAN_STATUS_WARN; - - /* check reset bit for reset mode */ - if ( READ_REG(can, ®s->mode) & PELICAN_MOD_RESET ){ - /* in reset mode ==> bus off */ - can->status |= OCCAN_STATUS_ERR_BUSOFF | OCCAN_STATUS_RESET; - - /***** pelican_stop(can) ****** - * turn off interrupts - * enter reset mode (HW already done that for us) - */ - WRITE_REG(can, ®s->inten,0); - - /* Indicate that we are not started any more. - * This will make write/read return with EBUSY - * on read/write attempts. - * - * User must issue a ioctl(START) to get going again. - */ - can->started = 0; - - /* signal any waiting read/write threads, so that they - * can handle the bus error. - */ - signal_rx = 1; - signal_tx = 1; - - /* ingnore any old pending interrupt */ - break; - } - - }else{ - /* not in Upper Error Active area any more */ - can->status &= ~(OCCAN_STATUS_WARN); - } - can->stats.err_warn++; - } - - if ( iflags & PELICAN_IF_DOVR){ - can->status |= OCCAN_STATUS_OVERRUN; - can->stats.err_dovr++; - DBG("OCCAN_INT: DOVR\n\r"); - } - - if ( iflags & PELICAN_IF_ERRP){ - /* Let the error counters decide what kind of - * interrupt it was. In/Out of EPassive area. - */ - tx_error_cnt = READ_REG(can, ®s->tx_err_cnt); - rx_error_cnt = READ_REG(can, ®s->rx_err_cnt); - - if ( (tx_error_cnt > 127) || (rx_error_cnt > 127) ){ - can->status |= OCCAN_STATUS_ERR_PASSIVE; - }else{ - can->status &= ~(OCCAN_STATUS_ERR_PASSIVE); - } - - /* increase Error Passive In/out interrupt counter */ - can->stats.err_errp++; - } - - if ( iflags & PELICAN_IF_ARB){ - arbcode = READ_REG(can, ®s->arbcode); - can->stats.err_arb_bitnum[arbcode & PELICAN_ARB_BITS]++; - can->stats.err_arb++; - DBG("OCCAN_INT: ARB (0x%x)\n\r",arbcode & PELICAN_ARB_BITS); - } - - if ( iflags & PELICAN_IF_BUS){ - /* Some kind of BUS error, only used for - * statistics. Error Register is decoded - * and put into can->stats. - */ - errcode = READ_REG(can, ®s->errcode); - switch( errcode & PELICAN_ECC_CODE ){ - case PELICAN_ECC_CODE_BIT: - can->stats.err_bus_bit++; - break; - case PELICAN_ECC_CODE_FORM: - can->stats.err_bus_form++; - break; - case PELICAN_ECC_CODE_STUFF: - can->stats.err_bus_stuff++; - break; - case PELICAN_ECC_CODE_OTHER: - can->stats.err_bus_other++; - break; - } - - /* Get Direction (TX/RX) */ - if ( errcode & PELICAN_ECC_DIR ){ - can->stats.err_bus_rx++; - }else{ - can->stats.err_bus_tx++; - } - - /* Get Segment in frame that went wrong */ - can->stats.err_bus_segs[errcode & PELICAN_ECC_SEG]++; - - /* total number of bus errors */ - can->stats.err_bus++; - } - } - SPIN_UNLOCK(&can->devlock, irqflags); - - /* signal Binary semaphore, messages available! */ - if ( signal_rx ){ - rtems_semaphore_release(can->rxsem); - } - - if ( signal_tx ){ - rtems_semaphore_release(can->txsem); - } -} - -/******************************************************************************* - * FIFO IMPLEMENTATION - */ - -static occan_fifo *occan_fifo_create(int cnt) -{ - occan_fifo *fifo; - fifo = malloc(sizeof(occan_fifo)+cnt*sizeof(CANMsg)); - if ( fifo ){ - fifo->cnt = cnt; - fifo->full = 0; - fifo->ovcnt = 0; - fifo->base = (CANMsg *)&fifo->fifoarea[0]; - fifo->tail = fifo->head = fifo->base; - /* clear CAN Messages */ - memset(fifo->base,0,cnt * sizeof(CANMsg)); - } - return fifo; -} - -static void occan_fifo_free(occan_fifo *fifo) -{ - if ( fifo ) - free(fifo); -} - -static int occan_fifo_full(occan_fifo *fifo) -{ - return fifo->full; -} - -static int occan_fifo_empty(occan_fifo *fifo) -{ - return (!fifo->full) && (fifo->head == fifo->tail); -} - -/* Stage 1 - get buffer to fill (never fails if force!=0) */ -static CANMsg *occan_fifo_put_claim(occan_fifo *fifo, int force) -{ - if ( !fifo ) - return NULL; - - if ( occan_fifo_full(fifo) ){ - - if ( !force ) - return NULL; - - /* all buffers already used ==> overwrite the oldest */ - fifo->ovcnt++; - occan_fifo_get(fifo); - } - - return fifo->head; -} - -/* Stage 2 - increment indexes */ -static void occan_fifo_put(occan_fifo *fifo) -{ - if ( occan_fifo_full(fifo) ) - return; - - /* wrap around */ - fifo->head = (fifo->head >= &fifo->base[fifo->cnt-1])? fifo->base : fifo->head+1; - - if ( fifo->head == fifo->tail ) - fifo->full = 1; -} - -static CANMsg *occan_fifo_claim_get(occan_fifo *fifo) -{ - if ( occan_fifo_empty(fifo) ) - return NULL; - - /* return oldest message */ - return fifo->tail; -} - - -static void occan_fifo_get(occan_fifo *fifo) -{ - if ( !fifo ) - return; - - if ( occan_fifo_empty(fifo) ) - return; - - /* increment indexes */ - fifo->tail = (fifo->tail >= &fifo->base[fifo->cnt-1]) ? - fifo->base : fifo->tail+1; - fifo->full = 0; -} - -static void occan_fifo_clr(occan_fifo *fifo) -{ - fifo->full = 0; - fifo->ovcnt = 0; - fifo->head = fifo->tail = fifo->base; -} - -/******************************************************************************/ diff --git a/c/src/lib/libbsp/sparc/shared/can/satcan.c b/c/src/lib/libbsp/sparc/shared/can/satcan.c deleted file mode 100644 index 1655a36e36..0000000000 --- a/c/src/lib/libbsp/sparc/shared/can/satcan.c +++ /dev/null @@ -1,714 +0,0 @@ -/* - * SatCAN FPGA driver - * - * COPYRIGHT (c) 2008. - * Cobham Gaisler AB. - * - * 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 /* printk */ - -#include -#include - -#ifndef GAISLER_SATCAN -#define GAISLER_SATCAN 0x080 -#endif - -#if !defined(SATCAN_DEVNAME) - #undef SATCAN_DEVNAME - #define SATCAN_DEVNAME "/dev/satcan" -#endif - -/* Enable debug output? */ -/* #define DEBUG */ - -#ifdef DEBUG -#define DBG(x...) printk(x) -#else -#define DBG(x...) -#endif - - -/* Defines related to DMA */ -#define ALIGN_2KMEM 32*1024 -#define ALIGN_8KMEM 128*1024 - -#define OFFSET_2K_LOW_POS 15 -#define OFFSET_8K_LOW_POS 17 - -#define DMA_2K_DATA_SELECT (1 << 14) -#define DMA_8K_DATA_SELECT (1 << 16) - -#define DMA_2K_DATA_OFFSET 16*1024 -#define DMA_8K_DATA_OFFSET 64*1024 - -/* Core register structures and defines */ - -/* Indexes to SatCAN registers in satcan array are declared in satcan.h*/ -/* Fields for some of the SatCAN FPGA registers */ - -/* CmdReg0 */ -#define CAN_TODn_Int_sel (1 << 5) - -/* CmdReg1 */ -#define Sel_2k_8kN (1 << 0) - -/* Read FIFO */ -#define FIFO_Full (1 << 8) -#define FIFO_Empty (1 << 9) - -/* DMA Ch_Enable */ -#define DMA_AutoInitDmaTx (1 << 3) -#define DMA_EnTx2 (1 << 2) -#define DMA_EnTx1 (1 << 1) -#define DMA_EnRx (1 << 0) - -/* SatCAN wrapper register fields */ -#define CTRL_BT_P 9 -#define CTRL_NODENO_P 5 -#define CTRL_DIS (1 << 2) -#define CTRL_DPS_P 1 -#define CTRL_RST (1 << 0) - -#define IRQ_AHB (1 << 8) -#define IRQ_PPS (1 << 7) -#define IRQ_M5 (1 << 6) -#define IRQ_M4 (1 << 5) -#define IRQ_M3 (1 << 4) -#define IRQ_M2 (1 << 3) -#define IRQ_M1 (1 << 2) -#define IRQ_SYNC (1 << 1) -#define IRQ_CAN (1 << 0) - -#define MSK_AHB (1 << 8) -#define MSK_PPS (1 << 7) -#define MSK_M5 (1 << 6) -#define MSK_M4 (1 << 5) -#define MSK_M3 (1 << 4) -#define MSK_M2 (1 << 3) -#define MSK_M1 (1 << 2) -#define MSK_SYNC (1 << 1) -#define MSK_CAN (1 << 0) - - - -struct satcan_regs { - volatile unsigned int satcan[32]; - volatile unsigned int ctrl; - volatile unsigned int irqpend; - volatile unsigned int irqmask; - volatile unsigned int membase; -}; - - -struct satcan_priv { - /* config */ - void *dmaptr; - unsigned char *alptr; - satcan_config *cfg; - - /* driver state */ - rtems_id devsem; - rtems_id txsem; - int open; - int txactive; - int dmaen; - int doff; - rtems_interval timeout; - int dmamode; -}; - -static struct satcan_regs *regs; -static struct satcan_priv *priv; - -static rtems_device_driver satcan_ioctl(rtems_device_major_number major, rtems_device_minor_number minor, void *arg); -static rtems_device_driver satcan_write(rtems_device_major_number major, rtems_device_minor_number minor, void *arg); -static rtems_device_driver satcan_read(rtems_device_major_number major, rtems_device_minor_number minor, void *arg); -static rtems_device_driver satcan_close(rtems_device_major_number major, rtems_device_minor_number minor, void *arg); -static rtems_device_driver satcan_open(rtems_device_major_number major, rtems_device_minor_number minor, void *arg); -static rtems_device_driver satcan_initialize(rtems_device_major_number major, rtems_device_minor_number unused, void *arg); - - -/* - * almalloc: allocate memory area of size sz aligned on sz boundary - * alptr: Utilized to return aligned pointer - * ptr: Unaligned pointer - * sz: Size of memory area - */ -static void almalloc(unsigned char **alptr, void **ptr, int sz) -{ - *ptr = calloc(1,2*sz); - *alptr = (unsigned char *) (((int)*ptr+sz) & ~(sz-1)); -} - -static rtems_isr satcan_interrupt_handler(rtems_vector_number v) -{ - unsigned int irq; - unsigned int fifo; - - irq = regs->irqpend; - - if (irq & IRQ_AHB && priv->cfg->ahb_irq_callback) { - priv->cfg->ahb_irq_callback(); - } - if (irq & IRQ_PPS && priv->cfg->pps_irq_callback) { - priv->cfg->pps_irq_callback(); - } - if (irq & IRQ_M5 && priv->cfg->m5_irq_callback) { - priv->cfg->m5_irq_callback(); - } - if (irq & IRQ_M4 && priv->cfg->m4_irq_callback) { - priv->cfg->m4_irq_callback(); - } - if (irq & IRQ_M3 && priv->cfg->m3_irq_callback) { - priv->cfg->m3_irq_callback(); - } - if (irq & IRQ_M2 && priv->cfg->m2_irq_callback) { - priv->cfg->m2_irq_callback(); - } - if (irq & IRQ_M1 && priv->cfg->m1_irq_callback) { - priv->cfg->m1_irq_callback(); - } - if (irq & IRQ_SYNC && priv->cfg->sync_irq_callback) { - priv->cfg->sync_irq_callback(); - } - if (irq & IRQ_CAN) { - fifo = regs->satcan[SATCAN_FIFO]; - if (!(fifo & FIFO_Empty) && priv->txactive && - (((fifo & 0xff) == SATCAN_IRQ_EOD1) || ((fifo & 0xff) == SATCAN_IRQ_EOD2))) { - rtems_semaphore_release(priv->txsem); - } - if (priv->cfg->can_irq_callback) - priv->cfg->can_irq_callback(fifo); - } -} - - - -static rtems_device_driver satcan_ioctl(rtems_device_major_number major, rtems_device_minor_number minor, void *arg) -{ - rtems_libio_ioctl_args_t *ioarg = (rtems_libio_ioctl_args_t*)arg; - int *value; - rtems_interval *timeout; - satcan_regmod *regmod; - - DBG("SatCAN: IOCTL %d\n\r", ioarg->command); - - ioarg->ioctl_return = 0; - switch(ioarg->command) { - case SATCAN_IOC_DMA_2K: - DBG("SatCAN: ioctl: setting 2K DMA mode\n\r"); - free(priv->dmaptr); - almalloc(&priv->alptr, &priv->dmaptr, ALIGN_2KMEM); - if (priv->dmaptr == NULL) { - printk("SatCAN: Failed to allocate DMA memory\n\r"); - return RTEMS_NO_MEMORY; - } - - regs->membase = (unsigned int)priv->alptr; - regs->satcan[SATCAN_RAM_BASE] = (unsigned int)priv->alptr >> OFFSET_2K_LOW_POS; - regs->satcan[SATCAN_CMD1] = regs->satcan[SATCAN_CMD1] | Sel_2k_8kN; - break; - - case SATCAN_IOC_DMA_8K: - DBG("SatCAN: ioctl: setting 8K DMA mode\n\r"); - free(priv->dmaptr); - almalloc(&priv->alptr, &priv->dmaptr, ALIGN_8KMEM); - if (priv->dmaptr == NULL) { - printk("SatCAN: Failed to allocate DMA memory\n\r"); - return RTEMS_NO_MEMORY; - } - - regs->membase = (unsigned int)priv->alptr; - regs->satcan[SATCAN_RAM_BASE] = (unsigned int)priv->alptr >> OFFSET_8K_LOW_POS; - regs->satcan[SATCAN_CMD1] = regs->satcan[SATCAN_CMD1] & ~Sel_2k_8kN; - break; - - case SATCAN_IOC_GET_REG: - /* Get regmod structure from argument */ - regmod = (satcan_regmod*)ioarg->buffer; - DBG("SatCAN: ioctl: getting register %d\n\r", regmod->reg); - if (regmod->reg < 0) - return RTEMS_INVALID_NAME; - else if (regmod->reg <= SATCAN_FILTER_STOP) - regmod->val = regs->satcan[regmod->reg]; - else if (regmod->reg == SATCAN_WCTRL) - regmod->val = regs->ctrl; - else if (regmod->reg == SATCAN_WIPEND) - regmod->val = regs->irqpend; - else if (regmod->reg == SATCAN_WIMASK) - regmod->val = regs->irqmask; - else if (regmod->reg == SATCAN_WAHBADDR) - regmod->val = regs->membase; - else - return RTEMS_INVALID_NAME; - break; - - case SATCAN_IOC_SET_REG: - /* Get regmod structure from argument */ - regmod = (satcan_regmod*)ioarg->buffer; - DBG("SatCAN: ioctl: setting register %d, value %x\n\r", - regmod->reg, regmod->val); - if (regmod->reg < 0) - return RTEMS_INVALID_NAME; - else if (regmod->reg <= SATCAN_FILTER_STOP) - regs->satcan[regmod->reg] = regmod->val; - else if (regmod->reg == SATCAN_WCTRL) - regs->ctrl = regmod->val; - else if (regmod->reg == SATCAN_WIPEND) - regs->irqpend = regmod->val; - else if (regmod->reg == SATCAN_WIMASK) - regs->irqmask = regmod->val; - else if (regmod->reg == SATCAN_WAHBADDR) - regs->membase = regmod->val; - else - return RTEMS_INVALID_NAME; - break; - - case SATCAN_IOC_OR_REG: - /* Get regmod structure from argument */ - regmod = (satcan_regmod*)ioarg->buffer; - DBG("SatCAN: ioctl: or:ing register %d, with value %x\n\r", - regmod->reg, regmod->val); - if (regmod->reg < 0) - return RTEMS_INVALID_NAME; - else if (regmod->reg <= SATCAN_FILTER_STOP) - regs->satcan[regmod->reg] |= regmod->val; - else if (regmod->reg == SATCAN_WCTRL) - regs->ctrl |= regmod->val; - else if (regmod->reg == SATCAN_WIPEND) - regs->irqpend |= regmod->val; - else if (regmod->reg == SATCAN_WIMASK) - regs->irqmask |= regmod->val; - else if (regmod->reg == SATCAN_WAHBADDR) - regs->membase |= regmod->val; - else - return RTEMS_INVALID_NAME; - break; - - case SATCAN_IOC_AND_REG: - /* Get regmod structure from argument */ - regmod = (satcan_regmod*)ioarg->buffer; - DBG("SatCAN: ioctl: masking register %d, with value %x\n\r", - regmod->reg, regmod->val); - if (regmod->reg < 0) - return RTEMS_INVALID_NAME; - else if (regmod->reg <= SATCAN_FILTER_STOP) - regs->satcan[regmod->reg] &= regmod->val; - else if (regmod->reg == SATCAN_WCTRL) - regs->ctrl &= regmod->val; - else if (regmod->reg == SATCAN_WIPEND) - regs->irqpend &= regmod->val; - else if (regmod->reg == SATCAN_WIMASK) - regs->irqmask &= regmod->val; - else if (regmod->reg == SATCAN_WAHBADDR) - regs->membase &= regmod->val; - else - return RTEMS_INVALID_NAME; - break; - - case SATCAN_IOC_EN_TX1_DIS_TX2: - priv->dmaen = SATCAN_DMA_ENABLE_TX1; - break; - - case SATCAN_IOC_EN_TX2_DIS_TX1: - priv->dmaen = SATCAN_DMA_ENABLE_TX2; - break; - - case SATCAN_IOC_GET_DMA_MODE: - value = (int*)ioarg->buffer; - *value = priv->dmamode; - break; - - case SATCAN_IOC_SET_DMA_MODE: - value = (int*)ioarg->buffer; - if (*value != SATCAN_DMA_MODE_USER && *value != SATCAN_DMA_MODE_SYSTEM) { - DBG("SatCAN: ioctl: invalid DMA mode\n\r"); - return RTEMS_INVALID_NAME; - } - priv->dmamode = *value; - break; - - case SATCAN_IOC_ACTIVATE_DMA: - if (priv->dmamode != SATCAN_DMA_MODE_USER) { - DBG("SatCAN: ioctl: ACTIVATE_DMA: not in user mode\n\r"); - return RTEMS_INVALID_NAME; - } - value = (int*)ioarg->buffer; - if (*value != SATCAN_DMA_ENABLE_TX1 && *value != SATCAN_DMA_ENABLE_TX2) { - DBG("SatCAN: ioctl: ACTIVATE_DMA: Illegal channel\n\r"); - return RTEMS_INVALID_NAME; - } - regs->satcan[SATCAN_DMA] |= *value << 1; - break; - - case SATCAN_IOC_DEACTIVATE_DMA: - if (priv->dmamode != SATCAN_DMA_MODE_USER) { - DBG("SatCAN: ioctl: DEACTIVATE_DMA: not in user mode\n\r"); - return RTEMS_INVALID_NAME; - } - value = (int*)ioarg->buffer; - if (*value != SATCAN_DMA_ENABLE_TX1 && *value != SATCAN_DMA_ENABLE_TX2) { - DBG("SatCAN: ioctl: DEACTIVATE_DMA: Illegal channel\n\r"); - return RTEMS_INVALID_NAME; - } - regs->satcan[SATCAN_DMA] &= ~(*value << 1); - break; - - case SATCAN_IOC_GET_DOFFSET: - value = (int*)ioarg->buffer; - *value = priv->doff; - break; - - case SATCAN_IOC_SET_DOFFSET: - value = (int*)ioarg->buffer; - priv->doff = *value; - break; - - case SATCAN_IOC_GET_TIMEOUT: - timeout = (rtems_interval*)ioarg->buffer; - *timeout = priv->timeout; - break; - - case SATCAN_IOC_SET_TIMEOUT: - timeout = (rtems_interval*)ioarg->buffer; - priv->timeout = *timeout; - break; - - default: - return RTEMS_NOT_DEFINED; - } - - return RTEMS_SUCCESSFUL; -} - -static rtems_device_driver satcan_write(rtems_device_major_number major, rtems_device_minor_number minor, void *arg) -{ - int i; - int doff; - int msgindex; - int messages; - rtems_libio_rw_args_t *rw_args=(rtems_libio_rw_args_t *) arg; - satcan_msg *msgs; - rtems_status_code status; - - DBG("SatCAN: Writing %d bytes from %p\n\r",rw_args->count,rw_args->buffer); - - if ((rw_args->count < sizeof(satcan_msg)) || (!rw_args->buffer)) { - DBG("SatCAN: write: returning EINVAL\n\r"); - return RTEMS_INVALID_NAME; /* EINVAL */ - } - - messages = rw_args->count / sizeof(satcan_msg); - msgs = (satcan_msg*)rw_args->buffer; - - /* Check that size matches any number of satcan_msg */ - if (rw_args->count % sizeof(satcan_msg)) { - DBG("SatCAN: write: count can not be evenly divided with satcan_msg size\n\r"); - return RTEMS_INVALID_NAME; /* EINVAL */ - } - - - /* DMA channel must be set if we are in system DMA mode */ - DBG("SatCAN: write: dma channel select is %x\n\r", priv->dmaen); - if (!priv->dmaen && priv->dmamode == SATCAN_DMA_MODE_SYSTEM) - return RTEMS_INVALID_NAME; /* EINVAL */ - - /* DMA must not be active */ - if (regs->satcan[SATCAN_DMA] & (DMA_EnTx1 | DMA_EnTx2 | DMA_AutoInitDmaTx)) { - DBG("SatCAN: write: DMA was active\n\r"); - rw_args->bytes_moved = 0; - return RTEMS_IO_ERROR; /* EIO */ - } - - doff = regs->satcan[SATCAN_CMD1] & Sel_2k_8kN ? DMA_2K_DATA_OFFSET : DMA_8K_DATA_OFFSET; - - for (msgindex = 0; msgindex < messages; msgindex++) { - /* Place header in DMA area */ - for (i = 0; i < SATCAN_HEADER_SIZE; i++) { - priv->alptr[priv->doff+8*msgindex+i] = msgs[msgindex].header[i]; - } - - /* Place data in DMA area */ - for (i = 0; i < SATCAN_PAYLOAD_SIZE; i++) - priv->alptr[priv->doff+doff+8*msgindex+i] = msgs[msgindex].payload[i]; - } - - if ((priv->dmaen & SATCAN_DMA_ENABLE_TX1) || priv->dmamode == SATCAN_DMA_MODE_USER) { - regs->satcan[SATCAN_DMA_TX_1_CUR] = 0; - regs->satcan[SATCAN_DMA_TX_1_END] = messages<<3; - } - - if ((priv->dmaen & SATCAN_DMA_ENABLE_TX2) || priv->dmamode == SATCAN_DMA_MODE_USER) { - regs->satcan[SATCAN_DMA_TX_2_CUR] = 0; - regs->satcan[SATCAN_DMA_TX_2_END] = messages<<3; - } - - /* If we are in DMA user mode we are done here, otherwise we block */ - if (priv->dmamode == SATCAN_DMA_MODE_SYSTEM) { - priv->txactive = 1; - - /* Enable DMA */ - regs->satcan[SATCAN_DMA] |= priv->dmaen << 1; - - /* Wait for TX interrupt */ - status = rtems_semaphore_obtain(priv->txsem, RTEMS_WAIT, priv->timeout); - - priv->txactive = 0; - - /* Disable activated Tx DMA */ - regs->satcan[SATCAN_DMA] &= ~(priv->dmaen << 1); - - if (status != RTEMS_SUCCESSFUL) { - rw_args->bytes_moved = 0; - return status; - } - } - - rw_args->bytes_moved = rw_args->count; - - return RTEMS_SUCCESSFUL; -} - -static rtems_device_driver satcan_read(rtems_device_major_number major, rtems_device_minor_number minor, void *arg) -{ - char *buf; - int i; - int canid; - int messages; - rtems_libio_rw_args_t *rw_args = (rtems_libio_rw_args_t*)arg; - satcan_msg *ret; - - /* Check that there is room for the return */ - if (rw_args->count < sizeof(satcan_msg)) { - DBG("SatCAN: read: length of buffer must be at least %d, current is %d\n\r", - sizeof(satcan_msg) + sizeof(int), rw_args->count); - return RTEMS_INVALID_NAME; /* -EINVAL */ - } - - /* Check that size matches any number of satcan_msg */ - if (rw_args->count % sizeof(satcan_msg)) { - DBG("SatCAN: read: count can not be evenly divided with satcan_msg size\n\r"); - return RTEMS_INVALID_NAME; /* EINVAL */ - } - - messages = rw_args->count / sizeof(satcan_msg); - ret = (satcan_msg*)rw_args->buffer; - - DBG("SatCAN: read: reading %d messages to %p\n\r", messages, ret); - - for (i = 0; i < messages; i++) { - canid = (ret[i].header[1] << 8) | ret[i].header[0]; - - /* Copy message header from DMA header area to buffer */ - buf = (char*)((int)priv->alptr | (canid << 3)); - memcpy(ret[i].header, buf, SATCAN_HEADER_SIZE); - - DBG("SatCAN: read: copied header from %p to %p\n\r", buf, ret[i].header); - - /* Clear New Message Marker */ - buf[SATCAN_HEADER_NMM_POS] = 0; - - /* Copy message payload from DMA data area to buffer */ - buf = (char*)((int)buf | - (regs->satcan[SATCAN_CMD1] & Sel_2k_8kN ? DMA_2K_DATA_SELECT : DMA_8K_DATA_SELECT)); - memcpy(ret[i].payload, buf, SATCAN_PAYLOAD_SIZE); - - DBG("SatCAN: read: copied payload from %p to %p\n\r", buf, ret[i].payload); - } - rw_args->bytes_moved = rw_args->count; - - return RTEMS_SUCCESSFUL; -} - - -static rtems_device_driver satcan_close(rtems_device_major_number major, rtems_device_minor_number minor, void *arg) -{ - DBG("SatCAN: Closing %d\n\r",minor); - - if (priv->open) { - regs->irqmask = 0; - regs->satcan[SATCAN_INT_EN] = 0; - regs->satcan[SATCAN_RX] = 0; - regs->satcan[SATCAN_DMA] = 0; - priv->open = 0; - priv->dmaen = 0; - priv->doff = 0; - priv->timeout = RTEMS_NO_TIMEOUT; - priv->dmamode = SATCAN_DMA_MODE_SYSTEM; - } - - return RTEMS_SUCCESSFUL; -} - - -static rtems_device_driver satcan_open(rtems_device_major_number major, rtems_device_minor_number minor, void *arg) -{ - DBG("SatCAN: Opening %d\n\r",minor); - - rtems_semaphore_obtain(priv->devsem,RTEMS_WAIT, RTEMS_NO_TIMEOUT); - if (priv->open) { - rtems_semaphore_release(priv->devsem); - return RTEMS_RESOURCE_IN_USE; /* EBUSY */ - } - priv->open = 1; - rtems_semaphore_release(priv->devsem); - - /* Enable AHB and CAN IRQs in wrapper and EOD1, EOD2 and CAN critical IRQs in SatCAN core */ - regs->irqmask = MSK_AHB | MSK_CAN; - regs->satcan[SATCAN_INT_EN] = ((1 << SATCAN_IRQ_EOD1) | (1 << SATCAN_IRQ_EOD2) | - (1 << SATCAN_IRQ_CRITICAL)); - - /* Select can_int as IRQ source */ - regs->satcan[SATCAN_CMD0] = CAN_TODn_Int_sel; - /* CAN RX DMA Enable */ - regs->satcan[SATCAN_DMA] = 1; - /* CAN RX Enable */ - regs->satcan[SATCAN_RX] = 1; - - DBG("SatCAN: Opening %d success\n\r",minor); - - return RTEMS_SUCCESSFUL; -} - -static rtems_device_driver satcan_initialize(rtems_device_major_number major, rtems_device_minor_number minor, void *arg) -{ - struct ambapp_ahb_info d; - char fs_name[20]; - rtems_status_code status; - - DBG("SatCAN: Initialize..\n\r"); - - strcpy(fs_name, SATCAN_DEVNAME); - - /* Find core and initialize register pointer */ - if (!ambapp_find_ahbslv(&ambapp_plb, VENDOR_GAISLER, GAISLER_SATCAN, &d)) { - printk("SatCAN: Failed to find SatCAN core\n\r"); - return -1; - } - - status = rtems_io_register_name(fs_name, major, minor); - if (RTEMS_SUCCESSFUL != status) - rtems_fatal_error_occurred(status); - - regs = (struct satcan_regs*)d.start[0]; - - /* Set node number and DPS */ - regs->ctrl |= ((priv->cfg->nodeno & 0xf) << 5) | (priv->cfg->dps << 1); - - /* Reset core */ - regs->ctrl |= CTRL_RST; - - /* Allocate DMA area */ - almalloc(&priv->alptr, &priv->dmaptr, ALIGN_2KMEM); - if (priv->dmaptr == NULL) { - printk("SatCAN: Failed to allocate DMA memory\n\r"); - free(priv->cfg); - free(priv); - return -1; - } - - /* Wait until core reset has completed */ - while (regs->ctrl & CTRL_RST) - ; - - /* Initialize core registers, default is 2K messages */ - regs->membase = (unsigned int)priv->alptr; - regs->satcan[SATCAN_RAM_BASE] = (unsigned int)priv->alptr >> 15; - - DBG("regs->membase = %x\n\r", (unsigned int)priv->alptr); - DBG("regs->satcan[SATCAN_RAM_BASE] = %x\n\r", (unsigned int)priv->alptr >> 15); - - status = rtems_semaphore_create( - rtems_build_name('S', 'd', 'v', '0'), - 1, - RTEMS_FIFO | RTEMS_SIMPLE_BINARY_SEMAPHORE | RTEMS_NO_INHERIT_PRIORITY | \ - RTEMS_NO_PRIORITY_CEILING, - 0, - &priv->devsem); - if (status != RTEMS_SUCCESSFUL) { - printk("SatCAN: Failed to create dev semaphore (%d)\n\r", status); - free(priv->cfg); - free(priv); - return RTEMS_UNSATISFIED; - } - status = rtems_semaphore_create( - rtems_build_name('S', 't', 'x', '0'), - 0, - RTEMS_FIFO | RTEMS_SIMPLE_BINARY_SEMAPHORE | RTEMS_NO_INHERIT_PRIORITY | \ - RTEMS_NO_PRIORITY_CEILING, - 0, - &priv->txsem); - if (status != RTEMS_SUCCESSFUL) { - printk("SatCAN: Failed to create tx semaphore (%d)\n\r", status); - free(priv->cfg); - free(priv); - return RTEMS_UNSATISFIED; - } - - priv->txactive = 0; - priv->open = 0; - priv->dmaen = 0; - priv->doff = 0; - priv->timeout = RTEMS_NO_TIMEOUT; - priv->dmamode = SATCAN_DMA_MODE_SYSTEM; - - /* Register interrupt handler */ - set_vector(satcan_interrupt_handler, d.irq+0x10, 2); - - return RTEMS_SUCCESSFUL; -} - - - -#define SATCAN_DRIVER_TABLE_ENTRY { satcan_initialize, satcan_open, satcan_close, satcan_read, satcan_write, satcan_ioctl } - -static rtems_driver_address_table satcan_driver = SATCAN_DRIVER_TABLE_ENTRY; - -int satcan_register(satcan_config *conf) -{ - rtems_status_code r; - rtems_device_major_number m; - - DBG("SatCAN: satcan_register called\n\r"); - - /* Create private structure */ - if ((priv = malloc(sizeof(struct satcan_priv))) == NULL) { - printk("SatCAN driver could not allocate memory for priv structure\n\r"); - return -1; - } - - DBG("SatCAN: Creating local copy of config structure\n\r"); - if ((priv->cfg = malloc(sizeof(satcan_config))) == NULL) { - printk("SatCAN driver could not allocate memory for cfg structure\n\r"); - return 1; - } - memcpy(priv->cfg, conf, sizeof(satcan_config)); - - if ((r = rtems_io_register_driver(0, &satcan_driver, &m)) == RTEMS_SUCCESSFUL) { - DBG("SatCAN driver successfully registered, major: %d\n\r", m); - } else { - switch(r) { - case RTEMS_TOO_MANY: - printk("SatCAN rtems_io_register_driver failed: RTEMS_TOO_MANY\n\r"); break; - case RTEMS_INVALID_NUMBER: - printk("SatCAN rtems_io_register_driver failed: RTEMS_INVALID_NUMBER\n\r"); break; - case RTEMS_RESOURCE_IN_USE: - printk("SatCAN rtems_io_register_driver failed: RTEMS_RESOURCE_IN_USE\n\r"); break; - default: - printk("SatCAN rtems_io_register_driver failed\n\r"); - } - return 1; - } - - return 0; -} diff --git a/c/src/lib/libbsp/sparc/shared/drvmgr/ambapp_bus.c b/c/src/lib/libbsp/sparc/shared/drvmgr/ambapp_bus.c deleted file mode 100644 index 3787660a15..0000000000 --- a/c/src/lib/libbsp/sparc/shared/drvmgr/ambapp_bus.c +++ /dev/null @@ -1,840 +0,0 @@ -/* General part of a AMBA Plug & Play bus driver. - * - * COPYRIGHT (c) 2008. - * Cobham Gaisler AB. - * - * 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 is the general part of the different AMBA Plug & Play - * drivers. The drivers are wrappers around this driver, making - * the code size smaller for systems with multiple AMBA Plug & - * Play buses. - * - * The BSP define APBUART_INFO_AVAIL in order to add the info routine - * used for debugging. - */ - -#include -#include -#include - -#include -#include - -#include -#include -#include - -/*#define DEBUG 1*/ -#define DBG(args...) -/*#define DBG(args...) printk(args)*/ - -struct grlib_gptimer_regs { - volatile unsigned int scaler_value; /* common timer registers */ - volatile unsigned int scaler_reload; - volatile unsigned int status; - volatile unsigned int notused; -}; - -/* AMBA IMPLEMENTATION */ - -static int ambapp_bus_init1(struct drvmgr_bus *bus); -static int ambapp_bus_remove(struct drvmgr_bus *bus); -static int ambapp_unite(struct drvmgr_drv *drv, struct drvmgr_dev *dev); -static int ambapp_int_register( - struct drvmgr_dev *dev, - int index, - const char *info, - drvmgr_isr isr, - void *arg); -static int ambapp_int_unregister( - struct drvmgr_dev *dev, - int index, - drvmgr_isr isr, - void *arg); -static int ambapp_int_clear(struct drvmgr_dev *dev, int index); -static int ambapp_int_mask(struct drvmgr_dev *dev, int index); -static int ambapp_int_unmask(struct drvmgr_dev *dev, int index); -static int ambapp_get_params( - struct drvmgr_dev *dev, - struct drvmgr_bus_params *params); -static int ambapp_bus_freq_get( - struct drvmgr_dev *dev, - int options, - unsigned int *freq_hz); -#ifdef AMBAPPBUS_INFO_AVAIL -static void ambapp_dev_info( - struct drvmgr_dev *, - void (*print)(void *p, char *str), - void *p); -#endif - -#ifdef RTEMS_SMP -static int ambapp_int_set_affinity( - struct drvmgr_dev *dev, - int index, - const Processor_mask *cpus); -#endif - -static struct drvmgr_bus_ops ambapp_bus_ops = -{ - .init = - { - /* init1 */ ambapp_bus_init1, - /* init2 */ NULL, - /* init3 */ NULL, - /* init4 */ NULL - }, - .remove = ambapp_bus_remove, - .unite = ambapp_unite, - .int_register = ambapp_int_register, - .int_unregister = ambapp_int_unregister, - .int_clear = ambapp_int_clear, - .int_mask = ambapp_int_mask, -#ifdef RTEMS_SMP - .int_set_affinity = ambapp_int_set_affinity, -#endif - .int_unmask = ambapp_int_unmask, - .get_params = ambapp_get_params, - .get_freq = ambapp_bus_freq_get, -#ifdef AMBAPPBUS_INFO_AVAIL - .get_info_dev = ambapp_dev_info, -#endif -}; - -struct ambapp_priv { - struct ambapp_config *config; -}; - -static int ambapp_unite(struct drvmgr_drv *drv, struct drvmgr_dev *dev) -{ - struct amba_drv_info *adrv; - struct amba_dev_id *id; - struct amba_dev_info *amba; - - if ( !drv || !dev || !dev->parent ) - return 0; - - if ( ! (((drv->bus_type == DRVMGR_BUS_TYPE_AMBAPP) && (dev->parent->bus_type == DRVMGR_BUS_TYPE_AMBAPP)) || - ((drv->bus_type == DRVMGR_BUS_TYPE_AMBAPP_RMAP) && (dev->parent->bus_type == DRVMGR_BUS_TYPE_AMBAPP_RMAP)) || - ((drv->bus_type == DRVMGR_BUS_TYPE_AMBAPP_DIST) && (dev->parent->bus_type == DRVMGR_BUS_TYPE_AMBAPP_DIST))) - ) { - return 0; - } - - amba = (struct amba_dev_info *)dev->businfo; - if ( !amba ) - return 0; - - adrv = (struct amba_drv_info *)drv; - id = adrv->ids; - if ( !id ) - return 0; - while( id->vendor != 0 ) { - if ( (id->vendor == amba->id.vendor) && - (id->device == amba->id.device) ) { - /* Unite device and driver */ - DBG("DRV 0x%x and DEV 0x%x united\n", (unsigned int)drv, (unsigned int)dev); - return 1; - } - id++; - } - - return 0; -} - -static int ambapp_int_get(struct drvmgr_dev *dev, int index) -{ - int irq; - - /* Relative (positive) or absolute (negative) IRQ number */ - if ( index >= 0 ) { - /* IRQ Index relative to Cores base IRQ */ - - /* Get Base IRQ */ - irq = ((struct amba_dev_info *)dev->businfo)->info.irq; - if ( irq < 0 ) - return -1; - irq += index; - } else { - /* Absolute IRQ number */ - irq = -index; - } - return irq; -} - -static int ambapp_int_register( - struct drvmgr_dev *dev, - int index, - const char *info, - drvmgr_isr isr, - void *arg) -{ - struct ambapp_priv *priv; - int irq; - - priv = dev->parent->priv; - - /* Get IRQ number from index and device information */ - irq = ambapp_int_get(dev, index); - if ( irq < 0 ) - return DRVMGR_EINVAL; - - DBG("Register interrupt on 0x%x for dev 0x%x (IRQ: %d)\n", - (unsigned int)dev->parent->dev, (unsigned int)dev, irq); - - if ( priv->config->ops->int_register ) { - /* Let device override driver default */ - return priv->config->ops->int_register(dev, irq, info, isr, arg); - } else { - return DRVMGR_ENOSYS; - } -} - -static int ambapp_int_unregister( - struct drvmgr_dev *dev, - int index, - drvmgr_isr isr, - void *arg) -{ - struct ambapp_priv *priv; - int irq; - - priv = dev->parent->priv; - - /* Get IRQ number from index and device information */ - irq = ambapp_int_get(dev, index); - if ( irq < 0 ) - return DRVMGR_EINVAL; - - DBG("Unregister interrupt on 0x%x for dev 0x%x (IRQ: %d)\n", - (unsigned int)dev->parent->dev, (unsigned int)dev, irq); - - if ( priv->config->ops->int_unregister ) { - /* Let device override driver default */ - return priv->config->ops->int_unregister(dev, irq, isr, arg); - } else { - return DRVMGR_ENOSYS; - } -} - -static int ambapp_int_clear( - struct drvmgr_dev *dev, - int index) -{ - struct ambapp_priv *priv; - int irq; - - priv = dev->parent->priv; - - /* Get IRQ number from index and device information */ - irq = ambapp_int_get(dev, index); - if ( irq < 0 ) - return -1; - - DBG("Clear interrupt on 0x%x for dev 0x%x (IRQ: %d)\n", - (unsigned int)dev->parent->dev, (unsigned int)dev, irq); - - if ( priv->config->ops->int_clear ) { - /* Let device override driver default */ - return priv->config->ops->int_clear(dev, irq); - } else { - return DRVMGR_ENOSYS; - } -} - -static int ambapp_int_mask( - struct drvmgr_dev *dev, - int index) -{ - struct ambapp_priv *priv; - int irq; - - priv = dev->parent->priv; - - /* Get IRQ number from index and device information */ - irq = ambapp_int_get(dev, index); - if ( irq < 0 ) - return -1; - - DBG("MASK interrupt on 0x%x for dev 0x%x (IRQ: %d)\n", - (unsigned int)dev->parent->dev, (unsigned int)dev, irq); - - if ( priv->config->ops->int_mask ) { - /* Let device override driver default */ - return priv->config->ops->int_mask(dev, irq); - } else { - return DRVMGR_ENOSYS; - } -} - -static int ambapp_int_unmask( - struct drvmgr_dev *dev, - int index) -{ - struct ambapp_priv *priv; - int irq; - - priv = dev->parent->priv; - - /* Get IRQ number from index and device information */ - irq = ambapp_int_get(dev, index); - if ( irq < 0 ) - return DRVMGR_EINVAL; - - DBG("UNMASK interrupt on 0x%x for dev 0x%x (IRQ: %d)\n", - (unsigned int)dev->parent->dev, (unsigned int)dev, irq); - - if ( priv->config->ops->int_unmask ) { - /* Let device override driver default */ - return priv->config->ops->int_unmask(dev, irq); - } else { - return DRVMGR_ENOSYS; - } -} - -/* Assign frequency to an AMBA Bus */ -void ambapp_bus_freq_register( - struct drvmgr_dev *dev, - int amba_interface, - unsigned int freq_hz - ) -{ - struct ambapp_priv *priv = (struct ambapp_priv *)dev->parent->priv; - struct ambapp_dev *adev; - struct amba_dev_info *pnp = dev->businfo; - - if ( freq_hz == 0 ) - return; - - if ( amba_interface == DEV_AHB_MST ) { - adev = (struct ambapp_dev *) - ((unsigned int)pnp->info.ahb_mst - - sizeof(struct ambapp_dev)); - } else if ( amba_interface == DEV_AHB_SLV ) { - adev = (struct ambapp_dev *) - ((unsigned int)pnp->info.ahb_slv - - sizeof(struct ambapp_dev)); - } else if ( amba_interface == DEV_APB_SLV ) { - adev = (struct ambapp_dev *) - ((unsigned int)pnp->info.apb_slv - - sizeof(struct ambapp_dev)); - } else { - return; - } - - /* Calculate Top bus frequency from lower part. The frequency comes - * from some kind of hardware able to report local bus frequency. - */ - ambapp_freq_init(priv->config->abus, adev, freq_hz); -} - -static int ambapp_bus_freq_get( - struct drvmgr_dev *dev, - int options, - unsigned int *freq_hz) -{ - struct ambapp_priv *priv = (struct ambapp_priv *)dev->parent->priv; - struct ambapp_dev *adev; - struct amba_dev_info *pnp = dev->businfo; - - if ( options == DEV_AHB_MST ) { - adev = (struct ambapp_dev *) - ((unsigned int)pnp->info.ahb_mst - - sizeof(struct ambapp_dev)); - } else if ( options == DEV_AHB_SLV ) { - adev = (struct ambapp_dev *) - ((unsigned int)pnp->info.ahb_slv - - sizeof(struct ambapp_dev)); - } else if ( options == DEV_APB_SLV ) { - adev = (struct ambapp_dev *) - ((unsigned int)pnp->info.apb_slv - - sizeof(struct ambapp_dev)); - } else { - *freq_hz = 0; - return -1; - } - - /* Calculate core/bus frequency from top most bus frequency. */ - *freq_hz = ambapp_freq_get(priv->config->abus, adev); - if ( *freq_hz == 0 ) - return -1; - return 0; -} - -static int ambapp_get_params( - struct drvmgr_dev *dev, - struct drvmgr_bus_params *params) -{ - struct ambapp_priv *priv = dev->parent->priv; - - if ( priv->config->ops->get_params ) { - /* Let device override driver default */ - return priv->config->ops->get_params(dev, params); - } else { - return -1; - } -} - -#ifdef AMBAPPBUS_INFO_AVAIL -static void ambapp_dev_info( - struct drvmgr_dev *dev, - void (*print_line)(void *p, char *str), - void *p) -{ - struct amba_dev_info *devinfo; - struct ambapp_core *core; - char buf[64]; - int ver, i; - char *str1, *str2, *str3; - unsigned int ahbmst_freq, ahbslv_freq, apbslv_freq; - - if (!dev) - return; - - devinfo = (struct amba_dev_info *)dev->businfo; - if (!devinfo) - return; - core = &devinfo->info; - - print_line(p, "AMBA PnP DEVICE"); - - str1 = ambapp_vendor_id2str(devinfo->id.vendor); - if (str1 == NULL) - str1 = "unknown"; - sprintf(buf, "VENDOR ID: 0x%04x (%s)", devinfo->id.vendor, str1); - print_line(p, buf); - - str1 = ambapp_device_id2str(devinfo->id.vendor, devinfo->id.device); - if (str1 == NULL) - str1 = "unknown"; - sprintf(buf, "DEVICE ID: 0x%04x (%s)", devinfo->id.device, str1); - print_line(p, buf); - - ahbmst_freq = ahbslv_freq = apbslv_freq = 0; - ver = 0; - str1 = str2 = str3 = ""; - if (core->ahb_mst) { - str1 = "AHBMST "; - ver = core->ahb_mst->ver; - ambapp_bus_freq_get(dev, DEV_AHB_MST, &ahbmst_freq); - } - if (core->ahb_slv) { - str2 = "AHBSLV "; - ver = core->ahb_slv->ver; - ambapp_bus_freq_get(dev, DEV_AHB_SLV, &ahbslv_freq); - } - if (core->apb_slv) { - str3 = "APBSLV"; - ver = core->apb_slv->ver; - ambapp_bus_freq_get(dev, DEV_APB_SLV, &apbslv_freq); - } - - sprintf(buf, "IRQ: %d", ambapp_int_get(dev, 0)); - print_line(p, buf); - - sprintf(buf, "VERSION: 0x%x", ver); - print_line(p, buf); - - sprintf(buf, "ambapp_core: %p", core); - print_line(p, buf); - - sprintf(buf, "interfaces: %s%s%s", str1, str2, str3); - print_line(p, buf); - - if (ahbmst_freq != 0) { - sprintf(buf, "AHBMST FREQ: %dkHz", ahbmst_freq/1000); - print_line(p, buf); - } - - if (ahbslv_freq != 0) { - sprintf(buf, "AHBSLV FREQ: %dkHz", ahbslv_freq/1000); - print_line(p, buf); - } - - if (apbslv_freq != 0) { - sprintf(buf, "APBSLV FREQ: %dkHz", apbslv_freq/1000); - print_line(p, buf); - } - - if (core->ahb_slv) { - for(i=0; i<4; i++) { - if (core->ahb_slv->type[i] == AMBA_TYPE_AHBIO) - str1 = " ahbio"; - else if (core->ahb_slv->type[i] == AMBA_TYPE_MEM) - str1 = "ahbmem"; - else - continue; - sprintf(buf, " %s[%d]: 0x%08x-0x%08x", str1, i, - core->ahb_slv->start[i], - core->ahb_slv->start[i]+core->ahb_slv->mask[i]-1); - print_line(p, buf); - } - } - if (core->apb_slv) { - sprintf(buf, " apb: 0x%08x-0x%08x", - core->apb_slv->start, - core->apb_slv->start + core->apb_slv->mask - 1); - print_line(p, buf); - } -} -#endif - -/* Fix device in last stage and/or register additional devices. - * Function returns: - * 0 Register device as normal - * 1 Fixup function handles registration - */ -static int ambapp_dev_fixup(struct drvmgr_dev *dev, struct amba_dev_info *pnp) -{ - /* OCCAN speciality: - * Mulitple cores are supported through the same amba AHB interface. - * The number of "sub cores" can be detected by decoding the AMBA - * Plug&Play version information. verion = ncores. A maximum of 8 - * sub cores are supported, each separeated with 0x100 inbetween. - * - * Now, lets detect sub cores. - */ - if ( (pnp->info.device == GAISLER_CANAHB) && - (pnp->info.vendor == VENDOR_GAISLER) ) { - struct drvmgr_dev *newdev, *devs_to_register[8]; - struct amba_dev_info *pnpinfo; - int subcores; - int core; - - devs_to_register[0] = dev; - subcores = (pnp->info.ahb_slv->ver & 0x7) + 1; - for(core = 1; core < subcores; core++) { - drvmgr_alloc_dev(&newdev, sizeof(*pnpinfo)); - memcpy(newdev, dev, sizeof(*newdev)); - pnpinfo = (struct amba_dev_info *)(newdev+1); - memcpy(pnpinfo, pnp, sizeof(*pnp)); - pnpinfo->info.index = core; - pnpinfo->info.irq += core; - newdev->businfo = (void *)pnpinfo; - - devs_to_register[core] = newdev; - } - /* Register all CAN devices */ - for(core = 0; core < subcores; core++) - drvmgr_dev_register(devs_to_register[core]); - return 1; - } else if ( (pnp->info.device == GAISLER_GPIO) && - (pnp->info.vendor == VENDOR_GAISLER) ) { - /* PIO[N] is connected to IRQ[N]. */ - pnp->info.irq = 0; - } - return 0; -} - -struct ambapp_dev_reg_struct { - struct ambapp_bus *abus; - struct drvmgr_bus *bus; - struct ambapp_dev *ahb_mst; - struct ambapp_dev *ahb_slv; - struct ambapp_dev *apb_slv; -}; - -static void ambapp_core_register( - struct ambapp_dev *ahb_mst, - struct ambapp_dev *ahb_slv, - struct ambapp_dev *apb_slv, - struct ambapp_dev_reg_struct *arg - ) -{ - struct drvmgr_dev *newdev; - struct amba_dev_info *pnpinfo; - unsigned short device; - unsigned char vendor; - int namelen; - char buf[64]; - - if ( ahb_mst ) { - device = ahb_mst->device; - vendor = ahb_mst->vendor; - }else if ( ahb_slv ) { - device = ahb_slv->device; - vendor = ahb_slv->vendor; - }else if( apb_slv ) { - device = apb_slv->device; - vendor = apb_slv->vendor; - } else { - DBG("NO DEV!\n"); - return; - } - - DBG("CORE REGISTER DEV [%x:%x] MST: 0x%x, SLV: 0x%x, APB: 0x%x\n", vendor, device, (unsigned int)ahb_mst, (unsigned int)ahb_slv, (unsigned int)apb_slv); - - /* Get unique device name from AMBA data base by combining VENDOR and - * DEVICE short names - */ - namelen = ambapp_vendev_id2str(vendor, device, buf); - - /* Allocate a device */ - drvmgr_alloc_dev(&newdev, sizeof(struct amba_dev_info) + namelen); - pnpinfo = (struct amba_dev_info *)(newdev + 1); - newdev->parent = arg->bus; /* Ourselfs */ - newdev->minor_drv = 0; - newdev->minor_bus = 0; - newdev->priv = NULL; - newdev->drv = NULL; - if (namelen > 0) { - newdev->name = (char *)(pnpinfo + 1); - strcpy(newdev->name, buf); - } else { - newdev->name = NULL; - } - newdev->next_in_drv = NULL; - newdev->bus = NULL; - - /* Init PnP information, Assign Core interfaces with this device */ - pnpinfo->id.vendor = vendor; - pnpinfo->id.device = device; - pnpinfo->info.vendor = vendor; - pnpinfo->info.device = device; - pnpinfo->info.index = 0; - if ( ahb_mst ) { - pnpinfo->info.ahb_mst = (struct ambapp_ahb_info *) - ahb_mst->devinfo; - ambapp_alloc_dev(ahb_mst, (void *)newdev); - if ( pnpinfo->info.ahb_mst->irq ) - pnpinfo->info.irq = pnpinfo->info.ahb_mst->irq; - } - if ( ahb_slv ) { - pnpinfo->info.ahb_slv = (struct ambapp_ahb_info *) - ahb_slv->devinfo; - ambapp_alloc_dev(ahb_slv, (void *)newdev); - if ( pnpinfo->info.ahb_slv->irq ) - pnpinfo->info.irq = pnpinfo->info.ahb_slv->irq; - } - if ( apb_slv ) { - pnpinfo->info.apb_slv = (struct ambapp_apb_info *) - apb_slv->devinfo; - ambapp_alloc_dev(apb_slv, (void *)newdev); - if ( pnpinfo->info.apb_slv->irq ) - pnpinfo->info.irq = pnpinfo->info.apb_slv->irq; - } - if ( pnpinfo->info.irq == 0 ) - pnpinfo->info.irq = -1; /* indicate no IRQ */ - - /* Connect device with PnP information */ - newdev->businfo = (void *)pnpinfo; - - if ( ambapp_dev_fixup(newdev, pnpinfo) == 0 ) - drvmgr_dev_register(newdev); /* Register New Device */ -} - -/* Fix device registration. - * Function returns: - * 0 Register device as normal - * 1 Fixup function handles registration - */ -static int ambapp_dev_register_fixup(struct ambapp_dev *dev, struct ambapp_dev_reg_struct *p) -{ - /* GR740 GRPCI2 speciality: - * - In the GR740 the APB_SLV is detected before the AHB_SLV - * which makes the registration incorrect. We deal with it in - * this function. */ - if ( (dev->dev_type == DEV_APB_SLV) && - (dev->device == GAISLER_GRPCI2) && - (dev->vendor == VENDOR_GAISLER) && - (p->ahb_slv == NULL) ) { - DBG("GRPCI2 APB_SLV detected before AHB_SLV. Skipping APB_SLV registration.\n"); - return 1; - } - return 0; -} - -/* Register one AMBA device */ -static int ambapp_dev_register(struct ambapp_dev *dev, int index, void *arg) -{ - struct ambapp_dev_reg_struct *p = arg; - -#ifdef DEBUG - char *type; - - if ( dev->dev_type == DEV_AHB_MST ) - type = "AHB MST"; - else if ( dev->dev_type == DEV_AHB_SLV ) - type = "AHB SLV"; - else if ( dev->dev_type == DEV_APB_SLV ) - type = "APB SLV"; - - DBG("Found [%d:%x:%x], %s\n", index, dev->vendor, dev->device, type); -#endif - - /* Fixup for device registration */ - if (ambapp_dev_register_fixup(dev, p)){ - return 0; - } - - if ( dev->dev_type == DEV_AHB_MST ) { - if ( p->ahb_mst ) { - /* This should not happen */ - printk("ambapp_dev_register: ahb_mst not NULL!\n"); - exit(1); - } - - /* Remember AHB Master */ - p->ahb_mst = dev; - - /* Find AHB Slave and APB slave for this Core */ - ambapp_for_each(p->abus, (OPTIONS_AHB_SLVS|OPTIONS_APB_SLVS|OPTIONS_FREE), dev->vendor, dev->device, ambapp_dev_register, p); - - ambapp_core_register(p->ahb_mst, p->ahb_slv, p->apb_slv, p); - p->ahb_mst = p->ahb_slv = p->apb_slv = NULL; - return 0; - - } else if ( dev->dev_type == DEV_AHB_SLV ) { - if ( p->ahb_slv ) { - /* Already got our AHB Slave interface */ - return 0; - } - - /* Remember AHB Slave */ - p->ahb_slv = dev; - - if ( p->ahb_mst ) { - /* Continue searching for APB Slave */ - return 0; - } else { - /* Find APB Slave interface for this Core */ - ambapp_for_each(p->abus, (OPTIONS_APB_SLVS|OPTIONS_FREE), dev->vendor, dev->device, ambapp_dev_register, p); - - ambapp_core_register(p->ahb_mst, p->ahb_slv, p->apb_slv, p); - p->ahb_mst = p->ahb_slv = p->apb_slv = NULL; - return 0; - } - } else if ( dev->dev_type == DEV_APB_SLV ) { - if ( p->apb_slv ) { - /* This should not happen */ - printk("ambapp_dev_register: apb_slv not NULL!\n"); - exit(1); - } - /* Remember APB Slave */ - p->apb_slv = dev; - - if ( p->ahb_mst || p->ahb_slv ) { - /* Stop scanning */ - return 1; - } else { - ambapp_core_register(p->ahb_mst, p->ahb_slv, p->apb_slv, p); - p->ahb_mst = p->ahb_slv = p->apb_slv = NULL; - return 0; - } - } - - return 0; -} - -/* Register all AMBA devices available on the AMBAPP bus */ -static int ambapp_ids_register(struct drvmgr_bus *bus) -{ - struct ambapp_priv *priv = bus->priv; - struct ambapp_bus *abus; - struct ambapp_dev_reg_struct arg; - - DBG("ambapp_ids_register:\n"); - - memset(&arg, 0, sizeof(arg)); - - abus = priv->config->abus; - arg.abus = abus; - arg.bus = bus; - - /* Combine the AHB MST, AHB SLV and APB SLV interfaces of a core. A core has often more than - * one interface. A core can not have more than one interface of the same type. - */ - ambapp_for_each(abus, (OPTIONS_ALL_DEVS|OPTIONS_FREE), -1, -1, ambapp_dev_register, &arg); - -#ifdef DEBUG - ambapp_print(abus->root, 1); -#endif - - return DRVMGR_OK; -} - -/*** DEVICE FUNCTIONS ***/ - -int ambapp_bus_register(struct drvmgr_dev *dev, struct ambapp_config *config) -{ - struct ambapp_priv *priv; - - if ( !config || !config->ops ) - return DRVMGR_OK; - - DBG("AMBAPP BUS: initializing\n"); - - /* Register BUS */ - drvmgr_alloc_bus(&dev->bus, sizeof(struct ambapp_priv)); - priv = (struct ambapp_priv *)(dev->bus + 1); - priv->config = config; - if ( priv->config->bus_type == DRVMGR_BUS_TYPE_AMBAPP_DIST ) - dev->bus->bus_type = DRVMGR_BUS_TYPE_AMBAPP_DIST; - else if ( priv->config->bus_type == DRVMGR_BUS_TYPE_AMBAPP_RMAP ) - dev->bus->bus_type = DRVMGR_BUS_TYPE_AMBAPP_RMAP; - else - dev->bus->bus_type = DRVMGR_BUS_TYPE_AMBAPP; - dev->bus->next = NULL; - dev->bus->dev = dev; - dev->bus->priv = priv; - dev->bus->children = NULL; - dev->bus->ops = &ambapp_bus_ops; - dev->bus->funcs = config->funcs; - dev->bus->dev_cnt = 0; - dev->bus->reslist = NULL; - dev->bus->maps_up = config->maps_up; - dev->bus->maps_down = config->maps_down; - - /* Add resource configuration */ - if ( priv->config->resources ) - drvmgr_bus_res_add(dev->bus, priv->config->resources); - - drvmgr_bus_register(dev->bus); - - return DRVMGR_OK; -} - -/*** BUS INITIALIZE FUNCTIONS ***/ - -/* Initialize the bus, register devices on this bus */ -static int ambapp_bus_init1(struct drvmgr_bus *bus) -{ - /* Initialize the bus, register devices on this bus */ - return ambapp_ids_register(bus); -} - -static int ambapp_bus_remove(struct drvmgr_bus *bus) -{ - return DRVMGR_OK; -} - -#ifdef RTEMS_SMP -static int ambapp_int_set_affinity( - struct drvmgr_dev *dev, - int index, - const Processor_mask *cpus) -{ - struct ambapp_priv *priv; - int irq; - - priv = dev->parent->priv; - - /* Get IRQ number from index and device information */ - irq = ambapp_int_get(dev, index); - if (irq < 0) - return DRVMGR_EINVAL; - - DBG("Set interrupt affinity on 0x%x for dev 0x%x (IRQ: %d)\n", - (unsigned int)dev->parent->dev, (unsigned int)dev, irq); - - if (priv->config->ops->int_set_affinity) { - /* Let device override driver default */ - return priv->config->ops->int_set_affinity(dev, irq, cpus); - } else { - return DRVMGR_ENOSYS; - } -} -#endif diff --git a/c/src/lib/libbsp/sparc/shared/drvmgr/ambapp_bus_grlib.c b/c/src/lib/libbsp/sparc/shared/drvmgr/ambapp_bus_grlib.c deleted file mode 100644 index 73fd465aec..0000000000 --- a/c/src/lib/libbsp/sparc/shared/drvmgr/ambapp_bus_grlib.c +++ /dev/null @@ -1,250 +0,0 @@ -/* LEON3 GRLIB AMBA Plug & Play bus driver. - * - * COPYRIGHT (c) 2008. - * Cobham Gaisler AB. - * - * This is driver is a wrapper for the general AMBA Plug & Play bus - * driver. This is the root bus driver for GRLIB systems. - * - * 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 - -#define DBG(args...) -/*#define DBG(args...) printk(args)*/ - -static int ambapp_grlib_int_register( - struct drvmgr_dev *dev, - int irq, - const char *info, - drvmgr_isr isr, - void *arg); -static int ambapp_grlib_int_unregister( - struct drvmgr_dev *dev, - int irq, - drvmgr_isr isr, - void *arg); -static int ambapp_grlib_int_clear( - struct drvmgr_dev *dev, - int irq); -static int ambapp_grlib_int_mask( - struct drvmgr_dev *dev, - int irq); -static int ambapp_grlib_int_unmask( - struct drvmgr_dev *dev, - int irq); -#ifdef RTEMS_SMP -static int ambapp_grlib_int_set_affinity( - struct drvmgr_dev *dev, - int irq, - const Processor_mask *cpus); -#endif -static int ambapp_grlib_get_params( - struct drvmgr_dev *dev, - struct drvmgr_bus_params *params); - -static int ambapp_grlib_init1(struct drvmgr_dev *dev); -static int ambapp_grlib_init2(struct drvmgr_dev *dev); -static int ambapp_grlib_remove(struct drvmgr_dev *dev); - -/* READ/WRITE access to SpaceWire target over RMAP */ -static void *ambapp_grlib_rw_arg(struct drvmgr_dev *dev); - -static struct ambapp_ops ambapp_grlib_ops = { - .int_register = ambapp_grlib_int_register, - .int_unregister = ambapp_grlib_int_unregister, - .int_clear = ambapp_grlib_int_clear, - .int_mask = ambapp_grlib_int_mask, - .int_unmask = ambapp_grlib_int_unmask, -#ifdef RTEMS_SMP - .int_set_affinity = ambapp_grlib_int_set_affinity, -#endif - .get_params = ambapp_grlib_get_params -}; - -static void *ambapp_grlib_rw_arg(struct drvmgr_dev *dev) -{ - return dev; /* No argument really needed, but for debug? */ -} - -static struct drvmgr_func ambapp_grlib_funcs[] = -{ - DRVMGR_FUNC(AMBAPP_RW_ARG, ambapp_grlib_rw_arg), - - DRVMGR_FUNC(AMBAPP_R8, _ld8), - DRVMGR_FUNC(AMBAPP_R16, _ld16), - DRVMGR_FUNC(AMBAPP_R32, _ld32), - DRVMGR_FUNC(AMBAPP_R64, _ld64), - - DRVMGR_FUNC(AMBAPP_W8, _st8), - DRVMGR_FUNC(AMBAPP_W16, _st16), - DRVMGR_FUNC(AMBAPP_W32, _st32), - DRVMGR_FUNC(AMBAPP_W64, _st64), - - DRVMGR_FUNC(AMBAPP_RMEM, memcpy), - DRVMGR_FUNC(AMBAPP_WMEM, memcpy), - - DRVMGR_FUNC_END, -}; - -static struct drvmgr_drv_ops ambapp_grlib_drv_ops = -{ - .init = {ambapp_grlib_init1, ambapp_grlib_init2, NULL, NULL}, - .remove = ambapp_grlib_remove, - .info = NULL, -}; - -static struct drvmgr_drv ambapp_bus_drv_grlib = -{ - DRVMGR_OBJ_DRV, /* Driver */ - NULL, /* Next driver */ - NULL, /* Device list */ - DRIVER_GRLIB_AMBAPP_ID, /* Driver ID */ - "AMBAPP_GRLIB_DRV", /* Driver Name */ - DRVMGR_BUS_TYPE_ROOT, /* Bus Type */ - &ambapp_grlib_drv_ops, - NULL, /* Funcs */ - 0, - 0, -}; - -static struct grlib_config *drv_mgr_grlib_config = NULL; - -void ambapp_grlib_register(void) -{ - drvmgr_drv_register(&ambapp_bus_drv_grlib); -} - -int ambapp_grlib_root_register(struct grlib_config *config) -{ - - /* Save the configuration for later */ - drv_mgr_grlib_config = config; - - /* Register root device driver */ - drvmgr_root_drv_register(&ambapp_bus_drv_grlib); - - return 0; -} - -/* Function called from Driver Manager Initialization Stage 1 */ -static int ambapp_grlib_init1(struct drvmgr_dev *dev) -{ - struct ambapp_config *config; - - dev->priv = NULL; - dev->name = "GRLIB AMBA PnP"; - - DBG("AMBAPP GRLIB: intializing\n"); - - config = malloc(sizeof(struct ambapp_config)); - if ( !config ) - return RTEMS_NO_MEMORY; - - config->ops = &ambapp_grlib_ops; - config->maps_up = DRVMGR_TRANSLATE_ONE2ONE; - config->maps_down = DRVMGR_TRANSLATE_ONE2ONE; - config->abus = drv_mgr_grlib_config->abus; - config->resources = drv_mgr_grlib_config->resources; - config->funcs = ambapp_grlib_funcs; - config->bus_type = DRVMGR_BUS_TYPE_AMBAPP; - - /* Initialize the generic part of the AMBA Bus */ - return ambapp_bus_register(dev, config); -} - -static int ambapp_grlib_init2(struct drvmgr_dev *dev) -{ - return 0; -} - -static int ambapp_grlib_remove(struct drvmgr_dev *dev) -{ - return 0; -} - -static int ambapp_grlib_int_register - ( - struct drvmgr_dev *dev, - int irq, - const char *info, - drvmgr_isr isr, - void *arg - ) -{ - return BSP_shared_interrupt_register(irq, info, isr, arg); -} - -static int ambapp_grlib_int_unregister - ( - struct drvmgr_dev *dev, - int irq, - drvmgr_isr isr, - void *arg - ) -{ - return BSP_shared_interrupt_unregister(irq, isr, arg); -} - -static int ambapp_grlib_int_clear - ( - struct drvmgr_dev *dev, - int irq) -{ - BSP_shared_interrupt_clear(irq); - return DRVMGR_OK; -} - -static int ambapp_grlib_int_mask - ( - struct drvmgr_dev *dev, - int irq - ) -{ - BSP_shared_interrupt_mask(irq); - return DRVMGR_OK; -} - -static int ambapp_grlib_int_unmask - ( - struct drvmgr_dev *dev, - int irq - ) -{ - BSP_shared_interrupt_unmask(irq); - return DRVMGR_OK; -} - -#ifdef RTEMS_SMP -static int ambapp_grlib_int_set_affinity - ( - struct drvmgr_dev *dev, - int irq, - const Processor_mask *cpus - ) -{ - bsp_interrupt_set_affinity(irq, cpus); - return DRVMGR_OK; -} -#endif - -static int ambapp_grlib_get_params(struct drvmgr_dev *dev, struct drvmgr_bus_params *params) -{ - /* Leave params->freq_hz untouched for default */ - params->dev_prefix = ""; - return 0; -} diff --git a/c/src/lib/libbsp/sparc/shared/drvmgr/ambapp_bus_leon2.c b/c/src/lib/libbsp/sparc/shared/drvmgr/ambapp_bus_leon2.c deleted file mode 100644 index a2351377f7..0000000000 --- a/c/src/lib/libbsp/sparc/shared/drvmgr/ambapp_bus_leon2.c +++ /dev/null @@ -1,266 +0,0 @@ -/* LEON2 GRLIB AMBA Plug & Play bus driver. - * - * COPYRIGHT (c) 2008. - * Cobham Gaisler AB. - * - * This is driver is a wrapper for the general AMBA Plug & Play bus - * driver. This is a bus driver for LEON2-GRLIB systems providing a - * AMBA Plug & Play bus, the parent bus must be a LEON2 hardcoded - * Bus. All IRQs must be routed to this bus driver in order for IRQs - * to work. The PnP information is used to extract IRQs and base - * register addresses. - * - * 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 - -#ifdef LEON2 -#include -#include -#include -#include -#include -#include -#include - -#define DBG(args...) - -int ambapp_leon2_int_register( - struct drvmgr_dev *dev, - int index, - const char *info, - drvmgr_isr isr, - void *arg); -int ambapp_leon2_int_unregister( - struct drvmgr_dev *dev, - int index, - drvmgr_isr isr, - void *arg); -int ambapp_leon2_int_clear( - struct drvmgr_dev *dev, - int index); -int ambapp_leon2_int_mask( - struct drvmgr_dev *dev, - int irq); -int ambapp_leon2_int_unmask( - struct drvmgr_dev *dev, - int irq); -int ambapp_leon2_get_params( - struct drvmgr_dev *dev, - struct drvmgr_bus_params *params); - -int ambapp_leon2_init1(struct drvmgr_dev *dev); -int ambapp_leon2_init2(struct drvmgr_dev *dev); -int ambapp_leon2_remove(struct drvmgr_dev *dev); -void ambapp_leon2_register(void); - -/* READ/WRITE access to SpaceWire target over RMAP */ -void *ambapp_leon2_rw_arg(struct drvmgr_dev *dev); - -struct ambappl2_priv { - struct ambapp_bus abus; - struct ambapp_config config; -}; - -struct ambapp_ops ambapp_leon2_ops = { - .int_register = ambapp_leon2_int_register, - .int_unregister = ambapp_leon2_int_unregister, - .int_clear = ambapp_leon2_int_clear, - .int_mask = ambapp_leon2_int_mask, - .int_unmask = ambapp_leon2_int_unmask, - .get_params = ambapp_leon2_get_params -}; - -struct drvmgr_func ambapp_leon2_funcs[] = { - DRVMGR_FUNC(AMBAPP_RW_ARG, ambapp_leon2_rw_arg), - - DRVMGR_FUNC(AMBAPP_R8, _ld8), - DRVMGR_FUNC(AMBAPP_R16, _ld16), - DRVMGR_FUNC(AMBAPP_R32, _ld32), - DRVMGR_FUNC(AMBAPP_R64, _ld64), - - DRVMGR_FUNC(AMBAPP_W8, _st8), - DRVMGR_FUNC(AMBAPP_W16, _st16), - DRVMGR_FUNC(AMBAPP_W32, _st32), - DRVMGR_FUNC(AMBAPP_W64, _st64), - - DRVMGR_FUNC(AMBAPP_RMEM, memcpy), - DRVMGR_FUNC(AMBAPP_WMEM, memcpy), - - DRVMGR_FUNC_END -}; - -struct drvmgr_drv_ops ambapp_ops = { - .init = {ambapp_leon2_init1, ambapp_leon2_init2, NULL, NULL}, - .remove = ambapp_leon2_remove, - .info = NULL, -}; - -struct leon2_amba_dev_id ambapp_leon2_ids[] = { - {LEON2_AMBA_AMBAPP_ID}, - {0} -}; - -struct leon2_amba_drv_info ambapp_bus_drv_leon2 = { - { - DRVMGR_OBJ_DRV, /* Driver */ - NULL, /* Next driver */ - NULL, /* Device list */ - DRIVER_LEON2_AMBA_AMBAPP, /* Driver ID */ - "AMBAPP_LEON2_DRV", /* Driver Name */ - DRVMGR_BUS_TYPE_LEON2_AMBA, /* Bus Type */ - &ambapp_ops, - NULL, /* Funcs */ - 0, - sizeof(struct ambappl2_priv), /* Let DrvMgr allocate priv */ - }, - &ambapp_leon2_ids[0] -}; - -void ambapp_leon2_register(void) -{ - drvmgr_drv_register(&ambapp_bus_drv_leon2.general); -} - -/* Function called from a hard configuration */ -int ambapp_leon2_init1(struct drvmgr_dev *dev) -{ - union drvmgr_key_value *value; - struct ambappl2_priv *priv = dev->priv; - struct leon2_amba_dev_info *devinfo; - struct ambapp_config *config; - unsigned int ioarea; - unsigned int freq_hz; - LEON_Register_Map *regs; - - dev->name = "LEON2 AMBA PnP"; - - if (!priv) - return DRVMGR_NOMEM; - - config = &priv->config; - config->abus = &priv->abus; - config->ops = &ambapp_leon2_ops; - config->maps_up = DRVMGR_TRANSLATE_ONE2ONE; - config->maps_down = DRVMGR_TRANSLATE_ONE2ONE; - config->funcs = ambapp_leon2_funcs; - config->bus_type = DRVMGR_BUS_TYPE_LEON2_AMBA; - - /* Get AMBA PnP Area from REG0 */ - devinfo = (struct leon2_amba_dev_info *)dev->businfo; - ioarea = devinfo->reg_base; - - /* Scan AMBA PnP Bus. ABUS has already been cleared with memset() */ - ambapp_scan(&priv->abus, ioarea, NULL, NULL); - - /* Try to get Configuration from resource configuration */ - - value = drvmgr_dev_key_get(dev, "busFreq", DRVMGR_KT_INT); - if (value) { - /* Set frequency of AMBA bus if specified by user. The frequency - * must be for AHB bus which IOAREA matches (AHB bus 0). - */ - freq_hz = value->i; - } else { - /* Get Bus/LEON2 Frequency from timer prescaler, - * the hardcoded address is used to get to timer - */ - regs = (LEON_Register_Map *) 0x80000000; - freq_hz = (regs->Scaler_Reload + 1) * 1000 * 1000; - } - /* Note that this can be overrided by a driver on the AMBA PnP bus.*/ - ambapp_freq_init(&priv->abus, NULL, freq_hz); - - value = drvmgr_dev_key_get(dev, "drvRes", DRVMGR_KT_POINTER); - if (!value) { - DBG("ambapp_leon2_init1: Failed getting resource drvRes\n"); - config->resources = NULL; - } else { - DBG("ambapp_leon2_init1: drvRes: 0x%08x\n", (unsigned int)value->ptr); - config->resources = (struct drvmgr_bus_res *)value->ptr; - } - - /* Initialize the AMBA Bus */ - return ambapp_bus_register(dev, config); -} - -int ambapp_leon2_init2(struct drvmgr_dev *dev) -{ - return 0; -} - -int ambapp_leon2_remove(struct drvmgr_dev *dev) -{ - return 0; -} - -void *ambapp_leon2_rw_arg(struct drvmgr_dev *dev) -{ - return dev; /* No argument really needed, by for debug */ -} - -int ambapp_leon2_int_register - ( - struct drvmgr_dev *dev, - int index, - const char *info, - drvmgr_isr isr, - void *arg - ) -{ - /* Let LEON2 bus handle interrupt requests */ - return drvmgr_interrupt_register(dev->parent->dev, index, info, isr, arg); -} - -int ambapp_leon2_int_unregister - ( - struct drvmgr_dev *dev, - int index, - drvmgr_isr isr, - void *arg - ) -{ - /* Let LEON2 bus handle interrupt requests */ - return drvmgr_interrupt_unregister(dev->parent->dev, index, isr, arg); -} - -int ambapp_leon2_int_clear - ( - struct drvmgr_dev *dev, - int index - ) -{ - /* Let LEON2 bus handle interrupt requests */ - return drvmgr_interrupt_clear(dev->parent->dev, index); -} - -int ambapp_leon2_int_mask - ( - struct drvmgr_dev *dev, - int index - ) -{ - /* Let LEON2 bus handle interrupt requests */ - return drvmgr_interrupt_mask(dev->parent->dev, index); -} - -int ambapp_leon2_int_unmask - ( - struct drvmgr_dev *dev, - int index - ) -{ - /* Let LEON2 bus handle interrupt requests */ - return drvmgr_interrupt_unmask(dev->parent->dev, index); -} - -int ambapp_leon2_get_params(struct drvmgr_dev *dev, struct drvmgr_bus_params *params) -{ - params->dev_prefix = ""; - return 0; -} - -#endif diff --git a/c/src/lib/libbsp/sparc/shared/drvmgr/get_resarray_count.c b/c/src/lib/libbsp/sparc/shared/drvmgr/get_resarray_count.c deleted file mode 100644 index 4099fa6b0d..0000000000 --- a/c/src/lib/libbsp/sparc/shared/drvmgr/get_resarray_count.c +++ /dev/null @@ -1,20 +0,0 @@ -/* Common driver configuration routines. - * - * COPYRIGHT (c) 2015. - * Cobham Gaisler. - * - * 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 - -int get_resarray_count(struct drvmgr_bus_res **array) -{ - int i = 0; - while (array[i] != NULL) - i++; - return i; -} diff --git a/c/src/lib/libbsp/sparc/shared/drvmgr/leon2_amba_bus.c b/c/src/lib/libbsp/sparc/shared/drvmgr/leon2_amba_bus.c deleted file mode 100644 index aca776c753..0000000000 --- a/c/src/lib/libbsp/sparc/shared/drvmgr/leon2_amba_bus.c +++ /dev/null @@ -1,449 +0,0 @@ -/* LEON2 Hardcoded bus driver. - * - * COPYRIGHT (c) 2008. - * Cobham Gaisler AB. - * - * Bus driver for a hardcoded setup. LEON2 systems have some - * cores always present, here called "Standard Cores". In - * addtion to the standard cores there are often extra cores - * that can be defined using the "Custom Cores" mechanism. - * - * A Core is described by assigning a base register and - * IRQ0..IRQ15 using the leon2_core structure. - * - * 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 - -#define DBG(args...) -/*#define DBG(args...) printk(args)*/ - -struct drvmgr_drv leon2_bus_drv; - -int leon2_amba_bus_init1(struct drvmgr_bus *bus); -int leon2_amba_unite(struct drvmgr_drv *drv, struct drvmgr_dev *dev); -int leon2_amba_int_register( - struct drvmgr_dev *dev, - int index, - const char *info, - drvmgr_isr isr, - void *arg); -int leon2_amba_int_unregister( - struct drvmgr_dev *dev, - int index, - drvmgr_isr isr, - void *arg); -int leon2_amba_int_clear( - struct drvmgr_dev *dev, - int index); -int leon2_amba_int_mask( - struct drvmgr_dev *dev, - int index); -int leon2_amba_int_unmask( - struct drvmgr_dev *dev, - int index); - -/* LEON2 bus operations */ -struct drvmgr_bus_ops leon2_amba_bus_ops = -{ - .init = { - leon2_amba_bus_init1, - NULL, - NULL, - NULL - }, - .remove = NULL, - .unite = leon2_amba_unite, - .int_register = leon2_amba_int_register, - .int_unregister = leon2_amba_int_unregister, - .int_clear = leon2_amba_int_clear, - .int_mask = leon2_amba_int_mask, - .int_unmask = leon2_amba_int_unmask, - .get_params = NULL, -}; - -struct leon2_isr_handler { - void (*handler)(int irq, void *arg); - void *arg; -}; - -/* Standard LEON2 configuration */ - -struct drvmgr_key leon2_timers[] = -{ - {"REG0", DRVMGR_KT_INT, {0x80000040}}, - {"IRQ0", DRVMGR_KT_INT, {8}}, - {"IRQ1", DRVMGR_KT_INT, {9}}, - DRVMGR_KEY_EMPTY -}; - -struct drvmgr_key leon2_uart1[] = -{ - {"REG0", DRVMGR_KT_INT, {0x80000070}}, - {"IRQ0", DRVMGR_KT_INT, {3}}, - DRVMGR_KEY_EMPTY -}; - -struct drvmgr_key leon2_uart2[] = -{ - {"REG0", DRVMGR_KT_INT, {0x80000080}}, - {"IRQ0", DRVMGR_KT_INT, {2}}, - DRVMGR_KEY_EMPTY -}; - -struct drvmgr_key leon2_irqctrl[] = -{ - {"REG0", DRVMGR_KT_INT, {0x80000090}}, - DRVMGR_KEY_EMPTY -}; - -struct drvmgr_key leon2_gpio0[] = -{ - {"REG0", DRVMGR_KT_INT, {0x800000A0}}, - {"IRQ0", DRVMGR_KT_INT, {4}}, - {"IRQ1", DRVMGR_KT_INT, {5}}, - {"IRQ2", DRVMGR_KT_INT, {6}}, - {"IRQ3", DRVMGR_KT_INT, {7}}, - DRVMGR_KEY_EMPTY -}; - -struct leon2_core leon2_std_cores[] = -{ - {{LEON2_AMBA_TIMER_ID}, "Timers", &leon2_timers[0]}, - {{LEON2_AMBA_UART_ID}, "Uart1", &leon2_uart1[0]}, - {{LEON2_AMBA_UART_ID}, "Uart2", &leon2_uart2[0]}, - {{LEON2_AMBA_IRQCTRL_ID}, "IRQCtrl", &leon2_irqctrl[0]}, - {{LEON2_AMBA_GPIO_ID}, "GPIO", &leon2_gpio0[0]}, - EMPTY_LEON2_CORE -}; - -static struct leon2_bus *leon2_bus_config = NULL; -static struct drvmgr_bus_res *leon2_bus_res = NULL; - -int leon2_root_register( - struct leon2_bus *bus_config, - struct drvmgr_bus_res *resources) -{ - /* Save the configuration for later */ - leon2_bus_config = bus_config; - leon2_bus_res = resources; - - /* Register root device driver */ - drvmgr_root_drv_register(&leon2_bus_drv); - - return 0; -} - -static int leon2_amba_dev_register( - struct drvmgr_bus *bus, - struct leon2_core *core, - int index) -{ - struct drvmgr_dev *newdev; - struct leon2_amba_dev_info *info; - union drvmgr_key_value *value; - char irq_name[8]; - int i; - - /* Allocate new device and businfo */ - drvmgr_alloc_dev(&newdev, sizeof(struct leon2_amba_dev_info)); - info = (struct leon2_amba_dev_info *)(newdev + 1); - - /* Set Core ID */ - info->core_id = core->id.core_id; - - /* Get information from bus configuration */ - value = drvmgr_key_val_get(core->keys, "REG0", DRVMGR_KT_INT); - if ( !value ) { - printk("leon2_amba_dev_register: Failed getting resource REG0\n"); - info->reg_base = 0x00000000; - } else { - DBG("leon2_amba_dev_register: REG0: 0x%08x\n", value->i); - info->reg_base = value->i; - } - - strcpy(irq_name, "IRQ"); - for(i=0; i<16; i++){ - if ( i < 10 ){ - irq_name[3] = '0' + i; - irq_name[4] = '\0'; - } else { - irq_name[3] = '1'; - irq_name[4] = '0' + (i-10); - irq_name[5] = '\0'; - } - - value = drvmgr_key_val_get(core->keys, irq_name, DRVMGR_KT_INT); - if ( !value ) { - DBG("leon2_amba_dev_register: Failed getting resource IRQ%d for REG 0x%x\n", i, info->reg_base); - info->irqs[i] = 0; - } else { - DBG("leon2_amba_dev_register: IRQ%d: %d\n", i, value->i); - info->irqs[i] = value->i; - } - } - - /* Init new device */ - newdev->next = NULL; - newdev->parent = bus; /* Ourselfs */ - newdev->minor_drv = 0; - newdev->minor_bus = 0; - newdev->businfo = (void *)info; - newdev->priv = NULL; - newdev->drv = NULL; - newdev->name = core->name; - newdev->next_in_drv = NULL; - newdev->bus = NULL; - - /* Register new device */ - drvmgr_dev_register(newdev); - - return 0; -} - -static int leon2_amba_init1(struct drvmgr_dev *dev) -{ - /* Init our own device */ - dev->priv = NULL; - dev->name = "LEON2 AMBA"; - - /* Init the bus */ - drvmgr_alloc_bus(&dev->bus, 0); - dev->bus->bus_type = DRVMGR_BUS_TYPE_LEON2_AMBA; - dev->bus->next = NULL; - dev->bus->dev = dev; - dev->bus->priv = NULL; - dev->bus->children = NULL; - dev->bus->ops = &leon2_amba_bus_ops; - dev->bus->dev_cnt = 0; - dev->bus->reslist = NULL; - dev->bus->maps_up = leon2_bus_config->maps_up; - dev->bus->maps_down = leon2_bus_config->maps_down; - drvmgr_bus_register(dev->bus); - - return DRVMGR_OK; -} - -static int leon2_amba_init2(struct drvmgr_dev *dev) -{ - return DRVMGR_OK; -} - -static int leon2_amba_remove(struct drvmgr_dev *dev) -{ - return DRVMGR_OK; -} - -int leon2_amba_bus_init1(struct drvmgr_bus *bus) -{ - struct leon2_core *core; - int i; - - if ( leon2_bus_res ) - drvmgr_bus_res_add(bus, leon2_bus_res); - - /**** REGISTER NEW DEVICES ****/ - i=0; - core = leon2_bus_config->std_cores; - if ( core ) { - while ( core->id.core_id ) { - if ( leon2_amba_dev_register(bus, core, i) ) { - return RTEMS_UNSATISFIED; - } - i++; - core++; - } - } - core = leon2_bus_config->custom_cores; - if ( core ) { - while ( core->id.core_id ) { - if ( leon2_amba_dev_register(bus, core, i) ) { - return RTEMS_UNSATISFIED; - } - i++; - core++; - } - } - - return 0; -} - -int leon2_amba_unite(struct drvmgr_drv *drv, struct drvmgr_dev *dev) -{ - struct leon2_amba_dev_info *info; - struct leon2_amba_drv_info *adrv; - struct leon2_amba_dev_id *id; - - if ( !drv || !dev || !dev->parent ) - return 0; - - if ( (drv->bus_type!=DRVMGR_BUS_TYPE_LEON2_AMBA) || (dev->parent->bus_type != DRVMGR_BUS_TYPE_LEON2_AMBA) ) { - return 0; - } - - info = (struct leon2_amba_dev_info *)dev->businfo; - if ( !info ) - return 0; - - /* Get LEON2 AMBA driver info */ - adrv = (struct leon2_amba_drv_info *)drv; - id = adrv->ids; - if ( !id ) - return 0; - - while ( id->core_id ) { - if ( id->core_id == info->core_id ) { - /* Driver is suitable for device, Unite them */ - return 1; - } - id++; - } - - return 0; -} - -static int leon2_amba_get_irq(struct drvmgr_dev *dev, int index) -{ - int irq; - struct leon2_amba_dev_info *info; - - if ( !dev || (index > 15) ) - return -1; - - /* Relative (positive) or absolute (negative) IRQ number */ - if ( index >= 0 ) { - /* IRQ Index relative to Cores base IRQ */ - - /* Get IRQ array configured by user */ - info = (struct leon2_amba_dev_info *)dev->businfo; - irq = info->irqs[index]; - if ( irq == 0 ) - return -1; - } else { - /* Absolute IRQ number */ - irq = -index; - } - return irq; -} - -int leon2_amba_int_register - ( - struct drvmgr_dev *dev, - int index, - const char *info, - drvmgr_isr isr, - void *arg - ) -{ - int irq; - - irq = leon2_amba_get_irq(dev, index); - if ( irq < 0 ) - return -1; - - DBG("Registering IRQ %d to func 0x%x arg 0x%x\n", irq, (unsigned int)isr, (unsigned int)arg); - - return BSP_shared_interrupt_register(irq, info, isr, arg); -} - -int leon2_amba_int_unregister - ( - struct drvmgr_dev *dev, - int index, - drvmgr_isr isr, - void *arg - ) -{ - int irq; - - irq = leon2_amba_get_irq(dev, index); - if ( irq < 0 ) - return -1; - - DBG("Unregistering IRQ %d to func 0x%x arg 0x%x\n", irq, (unsigned int)handler, (unsigned int)arg); - - return BSP_shared_interrupt_unregister(irq, isr, arg); -} - -int leon2_amba_int_clear - ( - struct drvmgr_dev *dev, - int index - ) -{ - int irq; - - irq = leon2_amba_get_irq(dev, index); - if ( irq < 0 ) - return -1; - - BSP_shared_interrupt_clear(irq); - - return DRVMGR_OK; -} - -int leon2_amba_int_mask - ( - struct drvmgr_dev *dev, - int index - ) -{ - int irq; - - irq = leon2_amba_get_irq(dev, index); - if ( irq < 0 ) - return -1; - - BSP_shared_interrupt_mask(irq); - - return DRVMGR_OK; -} - -int leon2_amba_int_unmask - ( - struct drvmgr_dev *dev, - int index - ) -{ - int irq; - - irq = leon2_amba_get_irq(dev, index); - if ( irq < 0 ) - return -1; - - BSP_shared_interrupt_unmask(irq); - - return DRVMGR_OK; -} - -struct drvmgr_drv_ops leon2_amba_ops = -{ - .init = {leon2_amba_init1, leon2_amba_init2, NULL, NULL}, - .remove = leon2_amba_remove, - .info = NULL -}; - -struct drvmgr_drv leon2_bus_drv = -{ - DRVMGR_OBJ_DRV, /* Driver */ - NULL, /* Next driver */ - NULL, /* Device list */ - DRIVER_LEON2_AMBA_ID, /* Driver ID */ - "LEON2_AMBA_DRV", /* Must be placed at top bus */ - DRVMGR_BUS_TYPE_ROOT, /* Bus Type */ - &leon2_amba_ops, /* Bus Operations */ - NULL, /* Funcs */ - 0, /* Device Count */ - 0, /* Private structure size */ -}; diff --git a/c/src/lib/libbsp/sparc/shared/gnatcommon.c b/c/src/lib/libbsp/sparc/shared/gnatcommon.c deleted file mode 100644 index b8a276c240..0000000000 --- a/c/src/lib/libbsp/sparc/shared/gnatcommon.c +++ /dev/null @@ -1,117 +0,0 @@ -/* - * - * Support for gnat/rtems interrupts and exception handling. - * Jiri Gaisler, ESA/ESTEC, 17-02-1999. - * - */ - -#include /* getpid */ - -#include -#include -#include -#include -#include - -/* - * Synchronous trap handler. Map the trap number of SIGFPE, SIGSEGV - * or SIGILL to generate the corresponding Ada exception. - */ -static rtems_isr -__gnat_exception_handler(rtems_vector_number trap) -{ - uint32_t real_trap; - uint32_t signal; - - real_trap = SPARC_REAL_TRAP_NUMBER (trap); - switch (real_trap) - { - case 0x08: /* FPU exception */ - case 0x0A: /* TAG overflow */ - case 0x82: /* divide by zero */ - signal = SIGFPE; /* Will cause Constraint_Error */ - break; - case 0x01: /* Instruction access exception */ - case 0x09: /* Data access exception */ - signal = SIGSEGV; /* Will cause Storage_Error */ - break; - default: /* Anything else ... */ - signal = SIGILL; /* Will cause Program_Error */ - break; - } - kill (getpid (), signal); -} - -/* - * Asynchronous trap handler. As it happens, the interrupt trap numbers for - * SPARC is 17 - 31, so we just map then directly on the same signal number. - */ -static rtems_isr -__gnat_interrupt_handler (rtems_vector_number trap) -{ - uint32_t real_trap; - - real_trap = SPARC_REAL_TRAP_NUMBER (trap); - - kill (getpid (), real_trap); - -} - -/* - * Default signal handler with error reporting - */ - -static void -__gnat_signals_Abnormal_termination_handler (int signo) -{ - switch (signo) - { - case SIGFPE: - printk("\nConstraint_Error\n"); - break; - case SIGSEGV: - printk("\nStorage_Error\n"); - break; - default: - printk("\nProgram_Error\n"); - break; - } - exit (1); -} - -const struct sigaction __gnat_error_vector = -{0, -1, - {__gnat_signals_Abnormal_termination_handler}}; - -void -__gnat_install_handler_common (int t1, int t2) -{ - uint32_t trap; - rtems_isr_entry previous_isr; - - sigaction (SIGSEGV, &__gnat_error_vector, NULL); - sigaction (SIGFPE, &__gnat_error_vector, NULL); - sigaction (SIGILL, &__gnat_error_vector, NULL); - - for (trap = 0; trap < 256; trap++) - { - - /* - * Skip window overflow, underflow, and flush as well as software - * trap 0 which we will use as a shutdown. Also avoid trap 0x70 - 0x7f - * which cannot happen and where some of the space is used to pass - * paramaters to the program. 0x80 for system traps and - * 0x81 - 0x83 by the remote debugging stub. - * Avoid two bsp specific interrupts which normally are used - * by the real-time clock and UART B. - */ - - if ((trap >= 0x11) && (trap <= 0x1f)) - { - if ((trap != t1) && (trap != t2)) - rtems_interrupt_catch (__gnat_interrupt_handler, trap, &previous_isr); - } - else if ((trap != 5 && trap != 6) && ((trap < 0x70) || (trap > 0x83))) - set_vector (__gnat_exception_handler, SPARC_SYNCHRONOUS_TRAP (trap), 1); - } -} diff --git a/c/src/lib/libbsp/sparc/shared/gpio/gpiolib.c b/c/src/lib/libbsp/sparc/shared/gpio/gpiolib.c deleted file mode 100644 index 38bc9633d0..0000000000 --- a/c/src/lib/libbsp/sparc/shared/gpio/gpiolib.c +++ /dev/null @@ -1,271 +0,0 @@ -/* GPIOLIB interface implementation - * - * COPYRIGHT (c) 2009. - * Cobham Gaisler AB. - * - * 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 - -struct gpiolib_port; - -struct gpiolib_port { - struct gpiolib_port *next; - int minor; - struct gpiolib_drv *drv; - void *handle; - - int open; -}; - -/* Root of GPIO Ports */ -struct gpiolib_port *gpiolib_ports; - -/* Number of GPIO ports registered */ -static int port_nr; - -/* 1 if libraray initialized */ -static int gpiolib_initied = 0; - -/* Insert a port first in ports list */ -static void gpiolib_list_add(struct gpiolib_port *port) -{ - port->next = gpiolib_ports; - gpiolib_ports = port; -} - -static struct gpiolib_port *gpiolib_find(int minor) -{ - struct gpiolib_port *p; - - p = gpiolib_ports; - while ( p && (p->minor != minor) ) { - p = p->next; - } - return p; -} - -static struct gpiolib_port *gpiolib_find_by_name(char *name) -{ - struct gpiolib_port *p; - struct gpiolib_info info; - int (*get_info)(void *, struct gpiolib_info *); - - p = gpiolib_ports; - while ( p ) { - get_info = p->drv->ops->get_info; - if ( get_info && (get_info(p->handle, &info) == 0) ) { - if ( strncmp(name, (char *)&info.devName[0], 64) == 0 ) { - break; - } - } - p = p->next; - } - return p; -} - -int gpiolib_drv_register(struct gpiolib_drv *drv, void *handle) -{ - struct gpiolib_port *port; - - if ( !drv || !drv->ops ) - return -1; - - port = malloc(sizeof(*port)); - if ( port == NULL ) - return -1; - - memset(port, 0, sizeof(*port)); - port->handle = handle; - port->minor = port_nr++; - port->drv = drv; - - gpiolib_list_add(port); - - return 0; -} - -void gpiolib_show(int port, void *handle) -{ - struct gpiolib_port *p; - - if ( port == -1 ) { - p = gpiolib_ports; - while (p != NULL) { - if ( p->drv->ops->show ) - p->drv->ops->show(p->handle); - p = p->next; - } - } else { - if ( handle ) { - p = handle; - } else { - p = gpiolib_find(port); - } - if ( p == NULL ) { - printf("PORT %d NOT FOUND\n", port); - return; - } - if ( p->drv->ops->show ) - p->drv->ops->show(p->handle); - } -} - -static void *gpiolib_open_internal(int port, char *devName) -{ - struct gpiolib_port *p; - - if ( gpiolib_initied == 0 ) - return NULL; - - /* Find */ - if ( port >= 0 ) { - p = gpiolib_find(port); - } else { - p = gpiolib_find_by_name(devName); - } - if ( p == NULL ) - return NULL; - - if ( p->open ) - return NULL; - - p->open = 1; - return p; -} - -void *gpiolib_open(int port) -{ - return gpiolib_open_internal(port, NULL); -} - -void *gpiolib_open_by_name(char *devName) -{ - return gpiolib_open_internal(-1, devName); -} - -void gpiolib_close(void *handle) -{ - struct gpiolib_port *p = handle; - - if ( p && p->open ) { - p->open = 0; - } -} - -int gpiolib_set_config(void *handle, struct gpiolib_config *cfg) -{ - struct gpiolib_port *port = handle; - - if ( !port || !cfg ) - return -1; - - if ( !port->drv->ops->config ) - return -1; - - return port->drv->ops->config(port->handle, cfg); -} - -int gpiolib_set(void *handle, int dir, int outval) -{ - struct gpiolib_port *port = handle; - - if ( !port ) - return -1; - - if ( !port->drv->ops->set ) - return -1; - - return port->drv->ops->set(port->handle, dir, outval); -} - -int gpiolib_get(void *handle, int *inval) -{ - struct gpiolib_port *port = handle; - - if ( !port || !inval) - return -1; - - if ( !port->drv->ops->get ) - return -1; - - return port->drv->ops->get(port->handle, inval); -} - -/*** IRQ Functions ***/ -int gpiolib_irq_register(void *handle, void *func, void *arg) -{ - struct gpiolib_port *port = handle; - - if ( !port ) - return -1; - - if ( !port->drv->ops->irq_register ) - return -1; - - return port->drv->ops->irq_register(port->handle, func, arg); -} - -static int gpiolib_irq_opts(void *handle, unsigned int options) -{ - struct gpiolib_port *port = handle; - - if ( !port ) - return -1; - - if ( !port->drv->ops->irq_opts ) - return -1; - - return port->drv->ops->irq_opts(port->handle, options); -} - -int gpiolib_irq_clear(void *handle) -{ - return gpiolib_irq_opts(handle, GPIOLIB_IRQ_CLEAR); -} - -int gpiolib_irq_force(void *handle) -{ - return gpiolib_irq_opts(handle, GPIOLIB_IRQ_FORCE); -} - -int gpiolib_irq_enable(void *handle) -{ - return gpiolib_irq_opts(handle, GPIOLIB_IRQ_ENABLE); -} - -int gpiolib_irq_disable(void *handle) -{ - return gpiolib_irq_opts(handle, GPIOLIB_IRQ_DISABLE); -} - -int gpiolib_irq_mask(void *handle) -{ - return gpiolib_irq_opts(handle, GPIOLIB_IRQ_MASK); -} - -int gpiolib_irq_unmask(void *handle) -{ - return gpiolib_irq_opts(handle, GPIOLIB_IRQ_UNMASK); -} - - -/*** Initialization ***/ -int gpiolib_initialize(void) -{ - if ( gpiolib_initied != 0 ) - return 0; - - /* Initialize Libarary */ - port_nr = 0; - gpiolib_ports = 0; - gpiolib_initied = 1; - return 0; -} diff --git a/c/src/lib/libbsp/sparc/shared/gpio/grgpio.c b/c/src/lib/libbsp/sparc/shared/gpio/grgpio.c deleted file mode 100644 index 7b02298fa4..0000000000 --- a/c/src/lib/libbsp/sparc/shared/gpio/grgpio.c +++ /dev/null @@ -1,449 +0,0 @@ -/* GRGPIO GPIO Driver interface. - * - * COPYRIGHT (c) 2009. - * Cobham Gaisler AB. - * - * 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 -#include -#include -#include - -/*#define DEBUG 1*/ - -#ifdef DEBUG -#define DBG(x...) printk(x) -#define STATIC -#else -#define DBG(x...) -#define STATIC static -#endif - -struct grgpio_isr { - drvmgr_isr isr; - void *arg; -}; - -struct grgpio_priv { - struct drvmgr_dev *dev; - struct grgpio_regs *regs; - int irq; - int minor; - - /* Driver implementation */ - int port_cnt; - unsigned char port_handles[32]; - struct grgpio_isr isrs[32]; - struct gpiolib_drv gpiolib_desc; - unsigned int bypass; - unsigned int imask; -}; - -/******************* Driver Manager Part ***********************/ - -int grgpio_device_init(struct grgpio_priv *priv); - -int grgpio_init1(struct drvmgr_dev *dev); -int grgpio_init2(struct drvmgr_dev *dev); - -struct drvmgr_drv_ops grgpio_ops = -{ - .init = {grgpio_init1, NULL, NULL, NULL}, - .remove = NULL, - .info = NULL -}; - -struct amba_dev_id grgpio_ids[] = -{ - {VENDOR_GAISLER, GAISLER_GPIO}, - {0, 0} /* Mark end of table */ -}; - -struct amba_drv_info grgpio_drv_info = -{ - { - DRVMGR_OBJ_DRV, /* Driver */ - NULL, /* Next driver */ - NULL, /* Device list */ - DRIVER_AMBAPP_GAISLER_GRGPIO_ID, /* Driver ID */ - "GRGPIO_DRV", /* Driver Name */ - DRVMGR_BUS_TYPE_AMBAPP, /* Bus Type */ - &grgpio_ops, - NULL, /* Funcs */ - 0, /* No devices yet */ - 0, - }, - &grgpio_ids[0] -}; - -void grgpio_register_drv (void) -{ - DBG("Registering GRGPIO driver\n"); - drvmgr_drv_register(&grgpio_drv_info.general); -} - -/* Register GRGPIO pins as quick as possible to the GPIO library, - * other drivers may depend upon them in INIT LEVEL 2. - * Note that since IRQ may not be available in init1, it is assumed - * that the GPIOLibrary does not request IRQ routines until LEVEL 2. - */ -int grgpio_init1(struct drvmgr_dev *dev) -{ - struct grgpio_priv *priv; - int status, port; - - DBG("GRGPIO[%d] on bus %s\n", dev->minor_drv, dev->parent->dev->name); - - /* This core will not find other cores, but other driver may depend upon - * the GPIO library to function. So, we set up GPIO right away. - */ - - /* Initialize library if not already done */ - status = gpiolib_initialize(); - if ( status < 0 ) - return DRVMGR_FAIL; - - priv = dev->priv = malloc(sizeof(struct grgpio_priv)); - if ( !priv ) - return DRVMGR_NOMEM; - memset(priv, 0, sizeof(*priv)); - priv->dev = dev; - - if ( grgpio_device_init(priv) ) { - free(dev->priv); - dev->priv = NULL; - return DRVMGR_FAIL; - } - - /* Register all ports available on this core as GPIO port to - * upper layer - */ - for(port=0; portport_cnt; port++) { - priv->port_handles[port] = port; - gpiolib_drv_register(&priv->gpiolib_desc, - &priv->port_handles[port]); - } - - return DRVMGR_OK; -} - -/******************* Driver Implementation ***********************/ - -/* Find port from handle, returns -1 if not found */ -static int grgpio_find_port(void *handle, struct grgpio_priv **priv) -{ - unsigned char portnr; - - portnr = *(unsigned char *)handle; - if ( portnr > 31 ) - return -1; - *priv = (struct grgpio_priv *) - (((unsigned int)handle - portnr*sizeof(unsigned char)) - - offsetof(struct grgpio_priv, port_handles)); - return portnr; -} - -static int grgpio_gpiolib_open(void *handle) -{ - struct grgpio_priv *priv; - int portnr; - - portnr = grgpio_find_port(handle, &priv); - if ( portnr < 0 ) { - DBG("GRGPIO: FAILED OPENING HANDLE 0x%08x\n", handle); - return -1; - } - DBG("GRGPIO[0x%08x][%d]: OPENING\n", priv->regs, portnr); - - /* Open the device, nothing to be done... */ - - return 0; -} - -static int grgpio_grpiolib_config(void *handle, struct gpiolib_config *cfg) -{ - struct grgpio_priv *priv; - int portnr; - unsigned int mask; - - portnr = grgpio_find_port(handle, &priv); - if ( portnr < 0 ) { - return -1; - } - DBG("GRGPIO[0x%08x][%d]: CONFIG\n", priv->regs, portnr); - - /* Configure the device. And check that operation is supported, - * not all I/O Pins have IRQ support. - */ - mask = (1<imask) == 0) && cfg->mask ) - return -1; - - priv->regs->imask &= ~mask; /* Disable interrupt temporarily */ - - /* Configure settings before enabling interrupt */ - priv->regs->ipol = (priv->regs->ipol & ~mask) | (cfg->irq_polarity ? mask : 0); - priv->regs->iedge = (priv->regs->iedge & ~mask) | (cfg->irq_level ? 0 : mask); - priv->regs->imask |= cfg->mask ? mask : 0; - - return 0; -} - -static int grgpio_grpiolib_get(void *handle, int *inval) -{ - struct grgpio_priv *priv; - int portnr; - - portnr = grgpio_find_port(handle, &priv); - if ( portnr < 0 ) { - return -1; - } - DBG("GRGPIO[0x%08x][%d]: GET\n", priv->regs, portnr); - - /* Get current status of the port */ - if ( inval ) - *inval = (priv->regs->data >> portnr) & 0x1; - - return 0; -} - -static int grgpio_grpiolib_irq_opts(void *handle, unsigned int options) -{ - struct grgpio_priv *priv; - int portnr; - drvmgr_isr isr; - void *arg; - - portnr = grgpio_find_port(handle, &priv); - if ( portnr < 0 ) { - return -1; - } - DBG("GRGPIO[0x%08x][%d]: IRQ OPTS 0x%x\n", priv->regs, portnr, options); - - if ( options & GPIOLIB_IRQ_FORCE ) - return -1; - - isr = priv->isrs[portnr].isr; - arg = priv->isrs[portnr].arg; - - if ( options & GPIOLIB_IRQ_DISABLE ) { - /* Disable interrupt at interrupt controller */ - if ( drvmgr_interrupt_unregister(priv->dev, portnr, isr, arg) ) { - return -1; - } - } - if ( options & GPIOLIB_IRQ_CLEAR ) { - /* Clear interrupt at interrupt controller */ - if ( drvmgr_interrupt_clear(priv->dev, portnr) ) { - return -1; - } - } - if ( options & GPIOLIB_IRQ_ENABLE ) { - /* Enable interrupt at interrupt controller */ - if ( drvmgr_interrupt_register(priv->dev, portnr, "grgpio", isr, arg) ) { - return -1; - } - } - if ( options & GPIOLIB_IRQ_MASK ) { - /* Mask (disable) interrupt at interrupt controller */ - if ( drvmgr_interrupt_mask(priv->dev, portnr) ) { - return -1; - } - } - if ( options & GPIOLIB_IRQ_UNMASK ) { - /* Unmask (enable) interrupt at interrupt controller */ - if ( drvmgr_interrupt_unmask(priv->dev, portnr) ) { - return -1; - } - } - - return 0; -} - -static int grgpio_grpiolib_irq_register(void *handle, void *func, void *arg) -{ - struct grgpio_priv *priv; - int portnr; - - portnr = grgpio_find_port(handle, &priv); - if ( portnr < 0 ) { - DBG("GRGPIO: FAILED OPENING HANDLE 0x%08x\n", handle); - return -1; - } - DBG("GRGPIO: OPENING %d at [0x%08x]\n", portnr, priv->regs); - - /* Since the user doesn't provide the ISR and argument, we must... */ - priv->isrs[portnr].isr = func; - priv->isrs[portnr].arg = arg; - - return 0; -} - -static int grgpio_grpiolib_set(void *handle, int dir, int outval) -{ - struct grgpio_priv *priv; - int portnr; - unsigned int mask; - - portnr = grgpio_find_port(handle, &priv); - if ( portnr < 0 ) { - DBG("GRGPIO: FAILED OPENING HANDLE 0x%08x\n", handle); - return -1; - } - DBG("GRGPIO: OPENING %d at [0x%08x]\n", portnr, priv->regs); - - /* Set Direction and Output */ - mask = 1<regs->dir = (priv->regs->dir & ~mask) | (dir ? mask : 0); - priv->regs->output = (priv->regs->output & ~mask) | (outval ? mask : 0); - - return 0; -} - -static int grgpio_gpiolib_show(void *handle) -{ - struct grgpio_priv *priv; - int portnr, i, regs[7]; - volatile unsigned int *reg; - - portnr = grgpio_find_port(handle, &priv); - if ( portnr < 0 ) { - DBG("GRGPIO: FAILED SHOWING HANDLE 0x%08x\n", handle); - return -1; - } - for (i=0, reg=&priv->regs->data; i<7; i++, reg++) { - regs[i] = ( *reg >> portnr) & 1; - } - printf("GRGPIO[%p] PORT[%d]: IN/OUT/DIR: [%d,%d,%d], MASK/POL/EDGE: [%d,%d,%d], BYPASS: %d\n", - priv->regs, portnr, regs[0], regs[1], regs[2], regs[3], regs[4], regs[5], regs[6]); - return 0; -} - -static int grgpio_gpiolib_get_info(void *handle, struct gpiolib_info *pinfo) -{ - struct grgpio_priv *priv; - int portnr; - char prefix[48]; - struct drvmgr_dev *dev; - - if ( !pinfo ) - return -1; - - portnr = grgpio_find_port(handle, &priv); - if ( portnr < 0 ) { - DBG("GRGPIO: FAILED GET_INFO HANDLE 0x%08x\n", handle); - return -1; - } - - /* Get Filesystem name prefix */ - dev = priv->dev; - prefix[0] = '\0'; - if ( drvmgr_get_dev_prefix(dev, prefix) ) { - /* Failed to get prefix, make sure of a unique FS name - * by using the driver minor. - */ - snprintf(pinfo->devName, 64, "/dev/grgpio%d/%d", dev->minor_drv, portnr); - } else { - /* Got special prefix, this means we have a bus prefix - * And we should use our "bus minor" - */ - snprintf(pinfo->devName, 64, "/dev/%sgrgpio%d/%d", prefix, dev->minor_bus, portnr); - } - - return 0; -} - -static struct gpiolib_drv_ops grgpio_gpiolib_ops = -{ - .config = grgpio_grpiolib_config, - .get = grgpio_grpiolib_get, - .irq_opts = grgpio_grpiolib_irq_opts, - .irq_register = grgpio_grpiolib_irq_register, - .open = grgpio_gpiolib_open, - .set = grgpio_grpiolib_set, - .show = grgpio_gpiolib_show, - .get_info = grgpio_gpiolib_get_info, -}; - -int grgpio_device_init(struct grgpio_priv *priv) -{ - struct amba_dev_info *ambadev; - struct ambapp_core *pnpinfo; - union drvmgr_key_value *value; - unsigned int mask; - int port_cnt; - - /* Get device information from AMBA PnP information */ - ambadev = (struct amba_dev_info *)priv->dev->businfo; - if ( ambadev == NULL ) { - return -1; - } - pnpinfo = &ambadev->info; - priv->irq = pnpinfo->irq; - priv->regs = (struct grgpio_regs *)pnpinfo->apb_slv->start; - - DBG("GRGPIO: 0x%08x irq %d\n", (unsigned int)priv->regs, priv->irq); - - /* Mask all Interrupts */ - priv->regs->imask = 0; - - /* Make IRQ Rising edge triggered default */ - priv->regs->ipol = 0xfffffffe; - priv->regs->iedge = 0xfffffffe; - - /* Read what I/O lines have IRQ support */ - priv->imask = priv->regs->ipol; - - /* Let the user configure the port count, this might be needed - * when the GPIO lines must not be changed (assigned during bootup) - */ - value = drvmgr_dev_key_get(priv->dev, "nBits", DRVMGR_KT_INT); - if ( value ) { - priv->port_cnt = value->i; - } else { - /* Auto detect number of GPIO ports */ - priv->regs->dir = 0; - priv->regs->output = 0xffffffff; - mask = priv->regs->output; - priv->regs->output = 0; - - for(port_cnt=0; port_cnt<32; port_cnt++) - if ( (mask & (1<port_cnt = port_cnt; - } - - /* Let the user configure the BYPASS register, this might be needed - * to select which cores can do I/O on a pin. - */ - value = drvmgr_dev_key_get(priv->dev, "bypass", DRVMGR_KT_INT); - if ( value ) { - priv->bypass = value->i; - } else { - priv->bypass = 0; - } - priv->regs->bypass = priv->bypass; - - /* Prepare GPIOLIB layer */ - priv->gpiolib_desc.ops = &grgpio_gpiolib_ops; - - return 0; -} diff --git a/c/src/lib/libbsp/sparc/shared/i2c/i2cmst.c b/c/src/lib/libbsp/sparc/shared/i2c/i2cmst.c deleted file mode 100644 index 9e386f7cb6..0000000000 --- a/c/src/lib/libbsp/sparc/shared/i2c/i2cmst.c +++ /dev/null @@ -1,415 +0,0 @@ -/* - * Driver for GRLIB port of OpenCores I2C-master - * - * COPYRIGHT (c) 2007 Cobham Gaisler AB - * based on the RTEMS MPC83xx I2C driver (c) 2007 Embedded Brains GmbH. - * - * 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 driver and initialization code - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -/* Enable debug printks? */ -/*#define DEBUG*/ - -#ifdef DEBUG - #define DBG(args...) printk(args) -#else - #define DBG(args...) -#endif - -/* The OC I2C core will perform a write after a start unless the RD bit - in the command register has been set. Since the rtems framework has - a send_start function we buffer that command and use it when the first - data is written. The START is buffered in the sendstart member below */ -typedef struct gr_i2cmst_prv { - rtems_libi2c_bus_t i2clib_desc; - struct drvmgr_dev *dev; - gr_i2cmst_regs_t *reg_ptr; - unsigned int sysfreq; /* System clock frequency in kHz */ - int minor; - unsigned char sendstart; /* START events are buffered here */ - /* rtems_irq_number irq_number; */ - /* rtems_id irq_sema_id; */ -} gr_i2cmst_prv_t; - -/* Calculates the scaler value for 100 kHz operation */ -static int gr_i2cmst_calc_scaler(int sysfreq) -{ - return sysfreq/500 - 1; -} - -/* Wait for the current transfer to end */ -static int gr_i2cmst_wait(gr_i2cmst_prv_t *prv_ptr, uint8_t expected_sts) -{ - uint32_t tout = 0; - int current_sts; - - DBG("(gr_i2cmst_wait called..."); - - do { - if (tout++ > 1000000) { - DBG("gr_i2cmst_wait: TIMEOUT\n"); - return RTEMS_TIMEOUT; - } - } while (prv_ptr->reg_ptr->cmdsts & GRI2C_STS_TIP); - - current_sts = prv_ptr->reg_ptr->cmdsts & ~GRI2C_STS_IF & ~GRI2C_STS_BUSY; - - if (current_sts != expected_sts) { -#if defined(DEBUG) - if (prv_ptr->reg_ptr->cmdsts & GRI2C_STS_RXACK) { - DBG("Transfer NAKed.."); - } - if (prv_ptr->reg_ptr->cmdsts & GRI2C_STS_AL) { - DBG("arbitration lost.."); - } - if (prv_ptr->reg_ptr->cmdsts & GRI2C_STS_TIP) { - DBG("transfer still in progress, huh?.."); - } - DBG("exited with IO error..)"); -#endif - DBG("gr_i2cmst_wait: IO-ERROR\n"); - return RTEMS_IO_ERROR; - } - - DBG("exited...)"); - - return RTEMS_SUCCESSFUL; -} - -/* Initialize hardware core */ -static rtems_status_code gr_i2cmst_init(rtems_libi2c_bus_t *bushdl) -{ - gr_i2cmst_prv_t *prv_ptr = (gr_i2cmst_prv_t *)bushdl; - - DBG("gr_i2cmst_init called..."); - - /* Disable core before changing prescale register */ - prv_ptr->reg_ptr->ctrl = 0; - - /* Calculate and set prescale value */ - prv_ptr->reg_ptr->prescl = gr_i2cmst_calc_scaler(prv_ptr->sysfreq); - - /* Enable core, interrupts are not enabled */ - prv_ptr->reg_ptr->ctrl = GRI2C_CTRL_EN; - - /* Clear possible START condition */ - prv_ptr->sendstart = 0; - - DBG("exited\n"); - - return RTEMS_SUCCESSFUL; -} - -static rtems_status_code gr_i2cmst_send_start(rtems_libi2c_bus_t *bushdl) -{ - gr_i2cmst_prv_t *prv_ptr = (gr_i2cmst_prv_t *)bushdl; - - DBG("gr_i2cmst_send_start called..."); - - /* The OC I2C core does not work with stand alone START events, - instead the event is buffered */ - prv_ptr->sendstart = GRI2C_CMD_STA; - - DBG("exited\n"); - - return RTEMS_SUCCESSFUL; -} - -static rtems_status_code gr_i2cmst_send_stop(rtems_libi2c_bus_t *bushdl) -{ - gr_i2cmst_prv_t *prv_ptr = (gr_i2cmst_prv_t *)bushdl; - - DBG("gr_i2cmst_send_stop called..."); - - prv_ptr->reg_ptr->cmdsts = GRI2C_CMD_STO; - - DBG("exited\n"); - - return RTEMS_SUCCESSFUL; -} - -static rtems_status_code gr_i2cmst_send_addr(rtems_libi2c_bus_t *bushdl, - uint32_t addr, int rw) -{ - gr_i2cmst_prv_t *prv_ptr = (gr_i2cmst_prv_t *)bushdl; - uint8_t addr_byte; - rtems_status_code rc; - - DBG("gr_i2cmst_send_addr called, addr = 0x%x, rw = %d...", - addr, rw); - - /* Check if long address is needed */ - if (addr > 0x7f) { - addr_byte = ((addr >> 7) & 0x06) | (rw ? 1 : 0); - - prv_ptr->reg_ptr->tdrd = addr_byte; - prv_ptr->reg_ptr->cmdsts = GRI2C_CMD_WR | prv_ptr->sendstart; - prv_ptr->sendstart = 0; - - /* Wait for transfer to complete */ - rc = gr_i2cmst_wait(prv_ptr, GRI2C_STATUS_IDLE); - if (rc != RTEMS_SUCCESSFUL) { - - DBG("exited with error\n"); - - return -rc; - } - } - - /* For 10-bit adresses the last byte should only be written for a - write operation */ - rc = RTEMS_SUCCESSFUL; - if (addr <= 0x7f || rw == 0) { - addr_byte = (addr << 1) | (rw ? 1 : 0); - - prv_ptr->reg_ptr->tdrd = addr_byte; - prv_ptr->reg_ptr->cmdsts = GRI2C_CMD_WR | prv_ptr->sendstart; - prv_ptr->sendstart = 0; - - /* Wait for transfer to complete */ - rc = gr_i2cmst_wait(prv_ptr, GRI2C_STATUS_IDLE); - if (rc != RTEMS_SUCCESSFUL) { - DBG("exited with error\n"); - return -rc; - } - } - - DBG("exited\n"); - return rc; -} - - -static int gr_i2cmst_read_bytes(rtems_libi2c_bus_t *bushdl, - unsigned char *bytes, int nbytes) -{ - gr_i2cmst_prv_t *prv_ptr = (gr_i2cmst_prv_t *)bushdl; - unsigned char *buf = bytes; - rtems_status_code rc; - unsigned char expected_sts = GRI2C_STATUS_IDLE; - - DBG("gr_i2cmst_read_bytes called, nbytes = %d...", nbytes); - - while (nbytes-- > 0) { - if (nbytes == 0) { - /* Respond with NAK to end sequential read */ - prv_ptr->reg_ptr->cmdsts = (GRI2C_CMD_RD | GRI2C_CMD_ACK | - prv_ptr->sendstart); - expected_sts = GRI2C_STS_RXACK; - } else { - prv_ptr->reg_ptr->cmdsts = GRI2C_CMD_RD | prv_ptr->sendstart; - } - prv_ptr->sendstart = 0; - /* Wait until end of transfer */ - rc = gr_i2cmst_wait(prv_ptr, expected_sts); - if (rc != RTEMS_SUCCESSFUL) { - DBG("exited with error\n"); - return -rc; - } - *buf++ = prv_ptr->reg_ptr->tdrd; - } - - DBG("exited\n"); - - return buf - bytes; -} - -static int gr_i2cmst_write_bytes(rtems_libi2c_bus_t *bushdl, - unsigned char *bytes, int nbytes) -{ - gr_i2cmst_prv_t *prv_ptr = (gr_i2cmst_prv_t *)bushdl; - unsigned char *buf = bytes; - rtems_status_code rc; - - DBG("gr_i2cmst_write_bytes called, nbytes = %d...", nbytes); - - while (nbytes-- > 0) { - - DBG("writing byte 0x%02X...", *buf); - - prv_ptr->reg_ptr->tdrd = *buf++; - prv_ptr->reg_ptr->cmdsts = GRI2C_CMD_WR | prv_ptr->sendstart; - prv_ptr->sendstart = 0; - - /* Wait for transfer to complete */ - rc = gr_i2cmst_wait(prv_ptr, GRI2C_STATUS_IDLE); - - if (rc != RTEMS_SUCCESSFUL) { - DBG("exited with error\n"); - return -rc; - } - } - - DBG("exited\n"); - - return buf - bytes; -} - -static rtems_libi2c_bus_ops_t gr_i2cmst_ops = { - init: gr_i2cmst_init, - send_start: gr_i2cmst_send_start, - send_stop: gr_i2cmst_send_stop, - send_addr: gr_i2cmst_send_addr, - read_bytes: gr_i2cmst_read_bytes, - write_bytes: gr_i2cmst_write_bytes, -}; - -/* Get Hardware and disable it */ -static int i2cmst_device_init(gr_i2cmst_prv_t *priv) -{ - struct amba_dev_info *ambadev; - struct ambapp_core *pnpinfo; - - /* Get device information from AMBA PnP information */ - ambadev = (struct amba_dev_info *)priv->dev->businfo; - if ( ambadev == NULL ) { - return -1; - } - pnpinfo = &ambadev->info; - priv->reg_ptr = (gr_i2cmst_regs_t *)pnpinfo->apb_slv->start; - - /* Disable core */ - priv->reg_ptr->ctrl = 0; - - priv->i2clib_desc.ops = &gr_i2cmst_ops; - priv->i2clib_desc.size = sizeof(gr_i2cmst_ops); - return 0; -} - - -/******************* Driver Manager Part ***********************/ - -int i2cmst_init2(struct drvmgr_dev *dev); -int i2cmst_init3(struct drvmgr_dev *dev); - -struct drvmgr_drv_ops i2cmst_ops = -{ - .init = {NULL, i2cmst_init2, i2cmst_init3, NULL}, - .remove = NULL, - .info = NULL -}; - -struct amba_dev_id i2cmst_ids[] = -{ - {VENDOR_GAISLER, GAISLER_I2CMST}, - {0, 0} /* Mark end of table */ -}; - -struct amba_drv_info i2cmst_drv_info = -{ - { - DRVMGR_OBJ_DRV, /* Driver */ - NULL, /* Next driver */ - NULL, /* Device list */ - DRIVER_AMBAPP_GAISLER_I2CMST_ID, /* Driver ID */ - "I2CMST_DRV", /* Driver Name */ - DRVMGR_BUS_TYPE_AMBAPP, /* Bus Type */ - &i2cmst_ops, - NULL, /* Funcs */ - 0, /* No devices yet */ - 0, - }, - &i2cmst_ids[0] -}; - -void i2cmst_register_drv (void) -{ - DBG("Registering I2CMST driver\n"); - drvmgr_drv_register(&i2cmst_drv_info.general); -} - -/* The I2CMST Driver is informed about a new hardware device */ -int i2cmst_init2(struct drvmgr_dev *dev) -{ - gr_i2cmst_prv_t *priv; - - DBG("I2CMST[%d] on bus %s\n", dev->minor_drv, dev->parent->dev->name); - - priv = dev->priv = malloc(sizeof(gr_i2cmst_prv_t)); - if ( !priv ) - return DRVMGR_NOMEM; - memset(priv, 0, sizeof(*priv)); - priv->dev = dev; - - /* This core will not find other cores, so we wait for init2() */ - - return DRVMGR_OK; -} - -/* Init stage 2 */ -int i2cmst_init3(struct drvmgr_dev *dev) -{ - gr_i2cmst_prv_t *priv; - char prefix[32]; - char devName[32]; - int rc; - - priv = (gr_i2cmst_prv_t *)dev->priv; - - /* Do initialization */ - - /* Initialize i2c library */ - rc = rtems_libi2c_initialize(); - if (rc != 0) { - DBG("I2CMST: rtems_libi2c_initialize failed, exiting...\n"); - free(dev->priv); - dev->priv = NULL; - return DRVMGR_FAIL; - } - - /* I/O system registered and initialized - * Now we take care of device initialization. - */ - - /* Get frequency */ - if ( drvmgr_freq_get(dev, DEV_APB_SLV, &priv->sysfreq) ) { - return DRVMGR_FAIL; - } - priv->sysfreq = priv->sysfreq / 1000; /* Convert to kHz */ - - if ( i2cmst_device_init(priv) ) { - free(dev->priv); - dev->priv = NULL; - return DRVMGR_FAIL; - } - - /* Get Filesystem name prefix */ - prefix[0] = '\0'; - if ( drvmgr_get_dev_prefix(dev, prefix) ) { - /* Failed to get prefix, make sure of a unique FS name - * by using the driver minor. - */ - sprintf(devName, "/dev/i2c%d", dev->minor_drv+1); - } else { - /* Got special prefix, this means we have a bus prefix - * And we should use our "bus minor" - */ - sprintf(devName, "/dev/%si2c%d", prefix, dev->minor_bus+1); - } - - /* Register Bus for this Device */ - rc = rtems_libi2c_register_bus(devName, &priv->i2clib_desc); - if (rc < 0) { - DBG("I2CMST: rtems_libi2c_register_bus(%s) failed, exiting..\n", devName); - free(dev->priv); - dev->priv = NULL; - return DRVMGR_FAIL; - } - priv->minor = rc; - - return DRVMGR_OK; -} diff --git a/c/src/lib/libbsp/sparc/shared/iommu/griommu.c b/c/src/lib/libbsp/sparc/shared/iommu/griommu.c deleted file mode 100644 index c70219a944..0000000000 --- a/c/src/lib/libbsp/sparc/shared/iommu/griommu.c +++ /dev/null @@ -1,1455 +0,0 @@ -/* - * GRIOMMU Driver Interface - * - * COPYRIGHT (c) 2017 - * Cobham Gaisler AB - * - * 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 - -/*#define STATIC*/ -#define STATIC static - -/*#define INLINE*/ -#define INLINE inline - -#define UNUSED __attribute__((unused)) - -/*#define DEBUG 1*/ - -#ifdef DEBUG -#define DBG(x...) printf(x) -#else -#define DBG(x...) -#endif - -/* - * GRIOMMU CAP0 register fields - */ -#define CAP0_A (0x1 << CAP0_A_BIT) -#define CAP0_AC (0x1 << CAP0_AC_BIT) -#define CAP0_CA (0x1 << CAP0_CA_BIT) -#define CAP0_CP (0x1 << CAP0_CP_BIT) -#define CAP0_NARB (0xf << CAP0_NARB_BIT) -#define CAP0_CS (0x1 << CAP0_CS_BIT) -#define CAP0_FT (0x3 << CAP0_FT_BIT) -#define CAP0_ST (0x1 << CAP0_ST_BIT) -#define CAP0_I (0x1 << CAP0_I_BIT) -#define CAP0_IT (0x1 << CAP0_IT_BIT) -#define CAP0_IA (0x1 << CAP0_IA_BIT) -#define CAP0_IP (0x1 << CAP0_IP_BIT) -#define CAP0_MB (0x1 << CAP0_MB_BIT) -#define CAP0_GRPS (0xf << CAP0_GRPS_BIT) -#define CAP0_MSTS (0xf << CAP0_MSTS_BIT) - -#define CAP0_A_BIT 31 -#define CAP0_AC_BIT 30 -#define CAP0_CA_BIT 29 -#define CAP0_CP_BIT 28 -#define CAP0_NARB_BIT 20 -#define CAP0_CS_BIT 19 -#define CAP0_FT_BIT 17 -#define CAP0_ST_BIT 16 -#define CAP0_I_BIT 15 -#define CAP0_IT_BIT 14 -#define CAP0_IA_BIT 13 -#define CAP0_IP_BIT 12 -#define CAP0_MB_BIT 8 -#define CAP0_GRPS_BIT 4 -#define CAP0_MSTS_BIT 0 - -/* - * GRIOMMU CAP1 register fields - */ -#define CAP1_CADDR (0xfff << CAP1_CADDR_BIT) -#define CAP1_CMASK (0xf << CAP1_CMASK_BIT) -#define CAP1_CTAGBITS (0xff << CAP1_CTAGBITS_BIT) -#define CAP1_CISIZE (0x7 << CAP1_CISIZE_BIT) -#define CAP1_CLINES (0x1f << CAP1_CLINES_BIT) - -#define CAP1_CADDR_BIT 20 -#define CAP1_CMASK_BIT 16 -#define CAP1_CTAGBITS_BIT 8 -#define CAP1_CISIZE_BIT 5 -#define CAP1_CLINES_BIT 0 - -/* - * GRIOMMU CTRL register fields - * DEFINED IN HEADER FILE - */ - -/* - * GRIOMMU FLUSH register fields - */ -#define FLUSH_FGRP (0xf << FLUSH_FGRP_BIT) -#define FLUSH_GF (0x1 << FLUSH_GF_BIT) -#define FLUSH_F (0x1 << FLUSH_F_BIT) - -#define FLUSH_FGRP_BIT 4 -#define FLUSH_GF_BIT 1 -#define FLUSH_F_BIT 0 - -/* - * GRIOMMU STATUS register fields - */ -#define STS_PE (0x1 << STS_PE_BIT) -#define STS_DE (0x1 << STS_DE_BIT) -#define STS_FC (0x1 << STS_FC_BIT) -#define STS_FL (0x1 << STS_FL_BIT) -#define STS_AD (0x1 << STS_AD_BIT) -#define STS_TE (0x1 << STS_TE_BIT) -#define STS_ALL (STS_PE | STS_DE | STS_FC | STS_FL | STS_AD | STS_TE) - -#define STS_PE_BIT 5 -#define STS_DE_BIT 4 -#define STS_FC_BIT 3 -#define STS_FL_BIT 2 -#define STS_AD_BIT 1 -#define STS_TE_BIT 0 - -/* - * GRIOMMU IMASK register fields - */ -#define IMASK_PEI (0x1 << IMASK_PEI_BIT) -#define IMASK_FCI (0x1 << IMASK_FCI_BIT) -#define IMASK_FLI (0x1 << IMASK_FLI_BIT) -#define IMASK_ADI (0x1 << IMASK_ADI_BIT) -#define IMASK_TEI (0x1 << IMASK_TEI_BIT) -#define IMASK_ALL (IMASK_PEI | IMASK_FCI | IMASK_FLI | IMASK_ADI | IMASK_TEI) - -#define IMASK_PEI_BIT 5 -#define IMASK_FCI_BIT 3 -#define IMASK_FLI_BIT 2 -#define IMASK_ADI_BIT 1 -#define IMASK_TEI_BIT 0 - -/* - * GRIOMMU MASTER register fields - */ -/* DEFINED IN HEADER FILE -#define MASTER_VENDOR (0xff << MASTER_VENDOR_BIT) -#define MASTER_DEVICE (0xfff << MASTER_DEVICE_BIT) -#define MASTER_BS (0x1 << MASTER_BS_BIT) -#define MASTER_GROUP (0xf << MASTER_GROUP_BIT) - -#define MASTER_VENDOR_BIT 24 -#define MASTER_DEVICE_BIT 12 -#define MASTER_BS_BIT 4 -#define MASTER_GROUP_BIT 0 -*/ - -#define MASTER_BS_BUS0 0 -#define MASTER_BS_BUS1 MASTER_BS - -/* - * GRIOMMU GROUP register fields - */ -#define GRP_BASE (0xfffffff << GRP_BASE_BIT) -#define GRP_P (0x1 << GRP_P_BIT) -#define GRP_AG (0x1 << GRP_AG_BIT) - -#define GRP_BASE_BIT 4 -#define GRP_P_BIT 1 -#define GRP_AG_BIT 0 - - -#define REG_WRITE(addr, val) (*(volatile unsigned int *)(addr) = (unsigned int)(val)) -#define REG_READ(addr) (*(volatile unsigned int *)(addr)) - -/* - * GRIOMMU APB Register MAP - */ -struct griommu_regs { - volatile unsigned int cap0; /* 0x00 - Capability 0 */ - volatile unsigned int cap1; /* 0x04 - Capability 1 */ - volatile unsigned int cap2; /* 0x08 - Capability 2 */ - volatile unsigned int resv1; /* 0x0c - Reserved */ - volatile unsigned int ctrl; /* 0x10 - Control */ - volatile unsigned int flush; /* 0x14 - TLB/cache flush */ - volatile unsigned int status; /* 0x18 - Status */ - volatile unsigned int imask; /* 0x1c - Interrupt mask */ - volatile unsigned int ahbstat; /* 0x20 - AHB Failing Access */ - volatile unsigned int resv2[7]; /* 0x24-0x3c - Reserved. No access */ - volatile unsigned int master[16]; /* 0x40-0x7c - Master configuration */ - volatile unsigned int grp_ctrl[16]; /* 0x80-0xbc - Group control */ - volatile unsigned int diag_ca; /* 0xc0 - Diagnostic cache access */ - volatile unsigned int diag_cad[8]; /* 0xc4-0xe0 - Diagnostic cache data */ - volatile unsigned int diag_cat; /* 0xe4 - Diagnostic cache tag */ - volatile unsigned int ei_data; /* 0xe8 - Data RAM error injection */ - volatile unsigned int ei_tag; /* 0xec - Tag RAM error injection */ - volatile unsigned int resv3[4]; /* 0xf0-0xfc - Reserved. No access */ - volatile unsigned int asmpctrl[16]; /* 0x100-0x13c - ASMP access control */ -}; - -#define DEVNAME_LEN 9 -/* - * GRIOMMU Driver private data struture - */ -struct griommu_priv { - struct drvmgr_dev *dev; - char devname[DEVNAME_LEN]; - /* GRIOMMU control registers */ - struct griommu_regs *regs; - - /* GRIOMMU capabilities */ - int apv; - int apv_cache; - int apv_cache_addr; - int conf_pagesize; - - int groups; - int masters; - - /* GRIOMMU page size */ - int pagesize; - - /* GRIOMMU APV cache */ - int cache_enabled; - int group_addressing; - - /* User defined ISR */ - griommu_isr_t isr; - void *isr_arg; -}; - -/* - * GRIOMMU internal prototypes - */ -/* -Register access functions */ -STATIC INLINE unsigned int griommu_reg_cap0(void); -STATIC INLINE unsigned int griommu_reg_cap1(void); -STATIC INLINE unsigned int griommu_reg_ctrl(void); -STATIC INLINE int griommu_reg_ctrl_set(unsigned int val); -STATIC INLINE int griommu_reg_flush_set(unsigned int val); -STATIC INLINE unsigned int griommu_reg_status(void); -STATIC INLINE int griommu_reg_status_clear(unsigned int val); -STATIC INLINE unsigned int griommu_reg_imask(void); -STATIC INLINE int griommu_reg_imask_set(int mask); -STATIC INLINE unsigned int griommu_reg_ahbfas(void); -STATIC INLINE unsigned int griommu_reg_master(int master); -STATIC INLINE int griommu_reg_master_set(int master, unsigned int val); -STATIC INLINE unsigned int griommu_reg_group(int group); -STATIC INLINE int griommu_reg_group_set(int group, unsigned int val); - -/* APV helper functions */ -STATIC void griommu_apv_set_word(unsigned int * wordptr, int startbitidx, - int nbits, unsigned int val); -STATIC int griommu_apv_set(void * apv, int index, int size, unsigned int val); - -/* -Init function called by drvmgr */ -int griommu_init1(struct drvmgr_dev *dev); -STATIC int griommu_init(struct griommu_priv *priv); - - -/* -IRQ handler */ -void griommu_isr(void *arg); - -/* - * GRIOMMU static members - */ -static struct griommu_priv *griommupriv = NULL; - -/* GRIOMMU DRIVER */ - -struct drvmgr_drv_ops griommu_ops = -{ - .init = {griommu_init1, NULL, NULL, NULL}, - .remove = NULL, - .info = NULL -}; - -struct amba_dev_id griommu_ids[] = -{ - {VENDOR_GAISLER, GAISLER_GRIOMMU}, - {0, 0} /* Mark end of table */ -}; - -struct amba_drv_info griommu_info = -{ - { - DRVMGR_OBJ_DRV, /* Driver */ - NULL, /* Next driver */ - NULL, /* Device list */ - DRIVER_AMBAPP_GAISLER_GRIOMMU_ID,/* Driver ID */ - "GRIOMMU_DRV", /* Driver Name */ - DRVMGR_BUS_TYPE_AMBAPP, /* Bus Type */ - &griommu_ops, - NULL, /* Funcs */ - 0, /* No devices yet */ - sizeof(struct griommu_priv), /* Make drvmgr alloc private */ - }, - &griommu_ids[0] -}; - -void griommu_register_drv(void) -{ - DBG("Registering GRIOMMU driver\n"); - drvmgr_drv_register(&griommu_info.general); -} - -/* Initializes the GRIOMMU core and driver - * - * Return values - * 0 Successful initalization - */ -STATIC int griommu_init(struct griommu_priv *priv) -{ - struct ambapp_ahb_info *ahb; - struct amba_dev_info *ainfo = priv->dev->businfo; - - /* Find GRIOMMU core from Plug&Play information */ - ahb = ainfo->info.ahb_slv; - - /* Found GRIOMMU core, init private structure */ - priv->regs = (struct griommu_regs *)ahb->start[0]; - - /* Mask all interrupts */ - griommu_reg_imask_set(0); - - /* Initialize GRIOMMU capabilities */ - uint32_t cap0 = griommu_reg_cap0(); - priv->apv = (cap0 & CAP0_A) >> CAP0_A_BIT; - priv->apv_cache = (cap0 & CAP0_AC) >> CAP0_AC_BIT; - priv->apv_cache_addr = (cap0 & CAP0_CA) >> CAP0_CA_BIT; - priv->conf_pagesize = (cap0 & CAP0_CS) >> CAP0_CS_BIT; - priv->groups = ((cap0 & CAP0_GRPS) >> CAP0_GRPS_BIT) + 1; - priv->masters = ((cap0 & CAP0_MSTS) >> CAP0_MSTS_BIT) + 1; - - /* Get GRIOMMU pagesize */ - uint32_t ctrl = griommu_reg_ctrl(); - if (priv->conf_pagesize){ - priv->pagesize = (4*1024 << ((ctrl & CTRL_PGSZ) >> CTRL_PGSZ_BIT)); - }else{ - priv->pagesize = 4*1024; - } - priv->cache_enabled = (ctrl & CTRL_CE); - priv->group_addressing = (ctrl & CTRL_GS); - - DBG("GRIOMMU Capabilities: APV=%d, APVC=%d, APVCA=%d, CS=%d, " - "GRPS=%d, MSTS=%d\n", - priv->apv, priv->apv_cache, priv->apv_cache_addr, - priv->conf_pagesize, priv->groups, priv->masters); - DBG("GRIOMMU driver initialized\n"); - - return 0; -} - -/* Called when a core is found with the AMBA device and vendor ID - * given in griommu_ids[]. IRQ, Console does not work here - */ -int griommu_init1(struct drvmgr_dev *dev) -{ - int status; - struct griommu_priv *priv; - - DBG("GRIOMMU[%d] on bus %s\n", dev->minor_drv, dev->parent->dev->name); - - if (griommupriv) { - DBG("Driver only supports one GRIOMMU core\n"); - return DRVMGR_FAIL; - } - - priv = dev->priv; - if (!priv) - return DRVMGR_NOMEM; - - priv->dev = dev; - strncpy(&priv->devname[0], "griommu0", DEVNAME_LEN); - griommupriv = priv; - - /* Initialize GRIOMMU Hardware */ - status = griommu_init(priv); - if (status) { - printf("Failed to initialize griommu driver %d\n", status); - return -1; - } - - return DRVMGR_OK; -} - -STATIC INLINE unsigned int griommu_reg_cap0(void) -{ - struct griommu_priv *priv = griommupriv; - - return REG_READ(&priv->regs->cap0); -} - -STATIC INLINE unsigned int griommu_reg_cap1(void) -{ - struct griommu_priv *priv = griommupriv; - - return REG_READ(&priv->regs->cap1); -} - -STATIC INLINE unsigned int griommu_reg_ctrl(void) -{ - struct griommu_priv *priv = griommupriv; - - return REG_READ(&priv->regs->ctrl); -} - -STATIC INLINE int griommu_reg_ctrl_set(unsigned int val) -{ - struct griommu_priv *priv = griommupriv; - - REG_WRITE(&priv->regs->ctrl, val); - return 0; -} - -STATIC INLINE int griommu_reg_flush_set(unsigned int val) -{ - struct griommu_priv *priv = griommupriv; - - REG_WRITE(&priv->regs->flush, val); - return 0; -} - -STATIC INLINE unsigned int griommu_reg_status(void) -{ - struct griommu_priv *priv = griommupriv; - - return REG_READ(&priv->regs->status); -} - -STATIC INLINE int griommu_reg_status_clear(unsigned int val) -{ - struct griommu_priv *priv = griommupriv; - - /* Clear errors */ - REG_WRITE(&priv->regs->status, (val & STS_ALL)); - return 0; -} - -STATIC INLINE unsigned int griommu_reg_imask(void) -{ - struct griommu_priv *priv = griommupriv; - - return REG_READ(&priv->regs->imask); -} - -STATIC INLINE int griommu_reg_imask_set(int mask) -{ - struct griommu_priv *priv = griommupriv; - - /* Clear errors */ - REG_WRITE(&priv->regs->imask, (mask & IMASK_ALL)); - return 0; -} - -STATIC INLINE unsigned int griommu_reg_ahbfas(void) -{ - struct griommu_priv *priv = griommupriv; - - return REG_READ(&priv->regs->ahbstat); -} - -STATIC INLINE int griommu_reg_master_set(int master, unsigned int val) -{ - struct griommu_priv *priv = griommupriv; - - /* Change master conf */ - REG_WRITE(&priv->regs->master[master], val); - return 0; -} - -STATIC INLINE unsigned int griommu_reg_master(int master) -{ - struct griommu_priv *priv = griommupriv; - - return REG_READ(&priv->regs->master[master]); -} - -STATIC INLINE unsigned int griommu_reg_group(int group) -{ - struct griommu_priv *priv = griommupriv; - - return REG_READ(&priv->regs->grp_ctrl[group]); -} - -STATIC INLINE int griommu_reg_group_set(int group, unsigned int val) -{ - struct griommu_priv *priv = griommupriv; - - REG_WRITE(&priv->regs->grp_ctrl[group], val); - return 0; -} - -STATIC void griommu_apv_set_word(unsigned int * wordptr, int startbitidx, - int nbits, unsigned int val) -{ - unsigned int mask; - unsigned int word = *wordptr; - int endbitidx = startbitidx + nbits - 1; - - /* Set initial mask */ - mask = 0xffffffff; - - /* Adjust mask for the starting bit */ - mask >>= startbitidx; - - /* Adjust mask for the end bit */ - mask >>= (31 - endbitidx); - mask <<= (31 - endbitidx); - - DBG("Setting word: startbitdx=%d, endbitidx=%d, mask=0x%02x", - startbitidx, endbitidx, (unsigned int) mask); - - /* Clear written bits with mask */ - word &= ~(mask); - - /* Set bits in val with mask */ - mask &= val; - word |= mask; - - DBG(", old word=0x%08x, new word=0x%08x\n",*wordptr, word); - - /* Write word */ - *wordptr=word; -} - -/* Set certains bits of the APV to val */ -STATIC int griommu_apv_set(void * apv, int index, int size, unsigned int val) -{ - unsigned int * words = (unsigned int *) apv; - int len = size; - int wordidx = (index/32); - int startbit = (index % 32); - int nbits; - int nwords; - - /* First incomplete word is a special case */ - if (startbit != 0){ - /* Get how many bits are we changing in this word */ - if (startbit + len < 32){ - nbits = len; - }else{ - nbits = 32 - startbit; - } - griommu_apv_set_word(&words[wordidx], startbit, nbits, val); - DBG("First word: wordidx=%d, startbit=%d, bits=%d, val=0x%08x\n", - wordidx, startbit, nbits, words[wordidx]); - - /* Update wordidx and len */ - len = len - nbits; - wordidx++; - } - - /* Write all complete full words */ - if (len != 0){ - nwords = (len/32); - memset((void *) &words[wordidx], val, nwords*4); - DBG("Middle words: wordidx=%d, nwords=%d\n", wordidx, nwords); - /* Update wordidx and len*/ - wordidx = wordidx + nwords; - len = len - nwords*32; - } - - /* Last word is a special case */ - if (len != 0){ - nbits = len; - griommu_apv_set_word(&words[wordidx], 0, nbits, val); - DBG("First word: wordidx=%d, startbit=%d, bits=%d, val=0x%08x\n", - wordidx, 0, nbits, words[wordidx]); - /* Update len */ - len = len - (nbits); - } - - return GRIOMMU_ERR_OK; -} - -/* GRIOMMU Interrupt handler, called when there may be a GRIOMMU interrupt. - */ -void griommu_isr(void *arg) -{ - struct griommu_priv *priv = arg; - unsigned int sts = griommu_reg_status(); - unsigned int mask = griommu_reg_imask(); - unsigned int access = griommu_reg_ahbfas(); - - /* Make sure that the interrupt is pending and unmasked, - * otherwise it migth have been other core - * sharing the same interrupt line */ - if ((sts & STS_ALL) & (mask & IMASK_ALL)){ - /* Reset error status */ - griommu_reg_status_clear(sts); - /* Execute user IRQ (ther will always be one ISR */ - (priv->isr)(priv->isr_arg, access, sts); - } -} - -/* Setup IOMMU master: - */ -int griommu_master_setup(int master, int group, int options) -{ - struct griommu_priv * priv = griommupriv; - - if (priv == NULL){ - DBG("GRIOMMU not initialized.\n"); - return GRIOMMU_ERR_NOINIT; - } - - if ((master < 0) || (master >= priv->masters)){ - DBG("Wrong master id.\n"); - return GRIOMMU_ERR_EINVAL; - } - - if ((group < 0) || (group >= priv->groups)){ - DBG("Wrong group id.\n"); - return GRIOMMU_ERR_EINVAL; - } - - griommu_reg_master_set(master, - ((options & GRIOMMU_OPTIONS_BUS1)? MASTER_BS_BUS1: MASTER_BS_BUS0)| - ((group << MASTER_GROUP_BIT) & MASTER_GROUP) - ); - - DBG("IOMMU master setup: master %d, traffic routed %s, group %d\n", - master, - (options & GRIOMMU_OPTIONS_BUS1) ? - "to Secondary bus":"to Primary bus", - group); - - return GRIOMMU_ERR_OK; -} - - -/* Get IOMMU master info: - */ -int griommu_master_info(int master, uint32_t * info) -{ - struct griommu_priv * priv = griommupriv; - - if (priv == NULL){ - DBG("GRIOMMU not initialized.\n"); - return GRIOMMU_ERR_NOINIT; - } - - if ((master < 0) || (master >= priv->masters)){ - DBG("Wrong master id.\n"); - return GRIOMMU_ERR_EINVAL; - } - - if (info == NULL){ - DBG("Wrong pointer.\n"); - return GRIOMMU_ERR_EINVAL; - } - - /* Get master */ - *info = griommu_reg_master(master); - - return GRIOMMU_ERR_OK; -} - -/* Find IOMMU master: - */ -int griommu_master_find(int vendor, int device, int instance) -{ - struct griommu_priv * priv = griommupriv; - int i, gotvendor, gotdevice; - unsigned int master; - int found; - - if (priv == NULL){ - DBG("GRIOMMU not initialized.\n"); - return GRIOMMU_ERR_NOINIT; - } - - /* Find which master */ - found=0; - for (i=0; i< priv->masters; i++){ - master = griommu_reg_master(i); - gotvendor = (master & MASTER_VENDOR) >> MASTER_VENDOR_BIT; - gotdevice = (master & MASTER_DEVICE) >> MASTER_DEVICE_BIT; - if ((gotvendor == vendor) && (gotdevice == device)){ - if(found == instance){ - DBG("Found master %d: VENDOR=%s(0x%02x), DEVICE=%s(0x%03x), " - "Instance=%d\n", - i, - ambapp_vendor_id2str(vendor), vendor, - ambapp_device_id2str(vendor,device), device, instance - ); - return i; - } - found++; - } - } - - DBG("Master not found: VENDOR=%s(0x%02x), DEVICE=%s(0x%03x), " - "Instance=%d\n", - ambapp_vendor_id2str(vendor), vendor, - ambapp_device_id2str(vendor,device), device, instance - ); - return GRIOMMU_ERR_NOTFOUND; -} - -/* Setup IOMMU: - */ -int griommu_setup(int options) -{ - struct griommu_priv * priv = griommupriv; - unsigned int ctrl; - - if (priv == NULL){ - DBG("GRIOMMU not initialized.\n"); - return GRIOMMU_ERR_NOINIT; - } - - /* Check Cache */ - if (options & GRIOMMU_OPTIONS_CACHE_ENABLE) { - if (priv->apv_cache){ - /* Flush cache */ - griommu_reg_flush_set(FLUSH_F); - priv->cache_enabled = 1; - }else{ - DBG("GRIOMMU APV cache not supported.\n"); - return GRIOMMU_ERR_IMPLEMENTED; - } - }else{ - priv->cache_enabled = 0; - } - - /* Check group addressing */ - if (options & GRIOMMU_OPTIONS_GROUPADDRESSING_ENABLE){ - if (priv->apv_cache_addr){ - priv->group_addressing = 1; - }else{ - DBG("GRIOMMU APV cache group addressing not supported.\n"); - return GRIOMMU_ERR_IMPLEMENTED; - } - }else{ - priv->group_addressing = 0; - } - - /* Check pagesize */ - if ((options & CTRL_PGSZ) != GRIOMMU_OPTIONS_PAGESIZE_4KIB){ - if (priv->conf_pagesize == 0){ - DBG("GRIOMMU Configurable pagesize not supported.\n"); - return GRIOMMU_ERR_IMPLEMENTED; - } - } - - /* Get CTRL IOMMU */ - ctrl = griommu_reg_ctrl(); - - /* Clear used fields */ - ctrl &= ~(CTRL_CE | CTRL_GS | CTRL_PGSZ | CTRL_LB | - CTRL_DP | CTRL_AU | CTRL_WP); - - /* Clear not used fields */ - options &= (CTRL_CE | CTRL_GS | CTRL_PGSZ | CTRL_LB | - CTRL_DP | CTRL_AU | CTRL_WP); - - /* Set new values */ - ctrl |= options; - - /* Set CTRL IOMMU */ - griommu_reg_ctrl_set(ctrl); - - DBG("IOMMU setup: prefetching %s, cache %s, groupaddr %s, " - "lookup bus %s, ahb update %s,\nwprot only %s, pagesize %d KiB\n", - ((options & GRIOMMU_OPTIONS_PREFETCH_DISABLE)? - "disabled":"enabled"), - ((options & GRIOMMU_OPTIONS_CACHE_ENABLE)? "enabled":"disabled"), - ((options & GRIOMMU_OPTIONS_GROUPADDRESSING_ENABLE)? - "enabled":"disabled"), - ((options & GRIOMMU_OPTIONS_LOOKUPBUS_BUS1)? "bus1":"bus0"), - ((options & GRIOMMU_OPTIONS_AHBUPDATE_ENABLE)? - "enabled":"disabled"), - ((options & GRIOMMU_OPTIONS_WPROTONLY_ENABLE)? - "enabled":"disabled"), - (4 << ((options & GRIOMMU_OPTIONS_PAGESIZE_512KIB) >> 18)) - ); - - return GRIOMMU_ERR_OK; -} - -/* Status IOMMU: - */ -int griommu_status(void) -{ - struct griommu_priv * priv = griommupriv; - unsigned int ctrl; - - if (priv == NULL){ - DBG("GRIOMMU not initialized.\n"); - return GRIOMMU_ERR_NOINIT; - } - - /* Get CTRL IOMMU */ - ctrl = griommu_reg_ctrl(); - - DBG("IOMMU status: prefetching %s, cache %s, groupaddr %s, " - "lookup bus %s, ahb update %s,\nwprot only %s, pagesize %d KiB\n", - ((ctrl & CTRL_DP)? "disabled":"enabled"), - ((ctrl & CTRL_CE)? "enabled":"disabled"), - ((ctrl & CTRL_GS)? "enabled":"disabled"), - ((ctrl & CTRL_LB)? "bus1":"bus0"), - ((ctrl & CTRL_AU)? "enabled":"disabled"), - ((ctrl & CTRL_WP)? "enabled":"disabled"), - (4 << ((ctrl & CTRL_PGSZ) >> CTRL_PGSZ_BIT)) - ); - - return ctrl; -} - -int griommu_isr_register(griommu_isr_t isr, void * arg, int options) -{ - struct griommu_priv *priv = griommupriv; - unsigned int mask; - - if (priv == NULL){ - DBG("GRIOMMU not initialized.\n"); - return GRIOMMU_ERR_NOINIT; - } - - if (isr == NULL){ - DBG("GRIOMMU wrong isr.\n"); - return GRIOMMU_ERR_EINVAL; - } - - /* Get mask */ - mask = 0 | - ((options & GRIOMMU_INTERRUPT_PARITY_ERROR)? IMASK_PEI:0) | - ((options & GRIOMMU_INTERRUPT_FLUSH_COMPLETED)? IMASK_FCI:0) | - ((options & GRIOMMU_INTERRUPT_FLUSH_START)? IMASK_FLI:0) | - ((options & GRIOMMU_INTERRUPT_ACCESS_DENIED)? IMASK_ADI:0) | - ((options & GRIOMMU_INTERRUPT_TRANSLATION_ERROR)? IMASK_TEI:0); - - /* Clear previous interrupts and mask them*/ - griommu_reg_status_clear(STS_ALL); - griommu_reg_imask_set(0); - - /* First time registering an ISR */ - if (priv->isr == NULL){ - /* Install and Enable GRIOMMU interrupt handler */ - drvmgr_interrupt_register(priv->dev, 0, priv->devname, griommu_isr, - priv); - } - - /* Install user ISR */ - priv->isr=isr; - priv->isr_arg=arg; - - /* Now it is safe to unmask interrupts */ - griommu_reg_imask_set(mask); - - return GRIOMMU_ERR_OK; -} - -int griommu_isr_unregister(void) -{ - struct griommu_priv *priv = griommupriv; - - if (priv == NULL){ - DBG("GRIOMMU not initialized.\n"); - return GRIOMMU_ERR_NOINIT; - } - - if (priv->isr == NULL){ - DBG("GRIOMMU wrong isr.\n"); - return GRIOMMU_ERR_EINVAL; - } - - /* Clear previous interrupts and mask them*/ - griommu_reg_status_clear(STS_ALL); - griommu_reg_imask_set(0); - - /* Uninstall and disable GRIOMMU interrupt handler */ - drvmgr_interrupt_unregister(priv->dev, 0, griommu_isr, priv); - - /* Uninstall user ISR */ - priv->isr=NULL; - priv->isr_arg=NULL; - - return GRIOMMU_ERR_OK; -} - -int griommu_interrupt_unmask(int options) -{ - struct griommu_priv *priv = griommupriv; - unsigned int mask, irq; - - if (priv == NULL){ - DBG("GRIOMMU not initialized.\n"); - return GRIOMMU_ERR_NOINIT; - } - - if (priv->isr == NULL){ - DBG("GRIOMMU wrong isr.\n"); - return GRIOMMU_ERR_EINVAL; - } - - /* Unmask interrupts in GRIOMMU */ - mask = 0 | - ((options & GRIOMMU_INTERRUPT_PARITY_ERROR)? IMASK_PEI:0) | - ((options & GRIOMMU_INTERRUPT_FLUSH_COMPLETED)? IMASK_FCI:0) | - ((options & GRIOMMU_INTERRUPT_FLUSH_START)? IMASK_FLI:0) | - ((options & GRIOMMU_INTERRUPT_ACCESS_DENIED)? IMASK_ADI:0) | - ((options & GRIOMMU_INTERRUPT_TRANSLATION_ERROR)? IMASK_TEI:0); - - /* Clear previous interrupts*/ - griommu_reg_status_clear(STS_ALL); - - /* Get previous mask */ - irq = griommu_reg_imask() & IMASK_ALL; - - /* Set new mask */ - griommu_reg_imask_set(irq | mask); - - return GRIOMMU_ERR_OK; -} - -int griommu_interrupt_mask(int options) -{ - struct griommu_priv *priv = griommupriv; - unsigned int mask, irq; - - if (priv == NULL){ - DBG("GRIOMMU not initialized.\n"); - return GRIOMMU_ERR_NOINIT; - } - - if (priv->isr == NULL){ - DBG("GRIOMMU wrong isr.\n"); - return GRIOMMU_ERR_EINVAL; - } - - /* Mask interrupts in GRIOMMU */ - mask = 0 | - ((options & GRIOMMU_INTERRUPT_PARITY_ERROR)? IMASK_PEI:0) | - ((options & GRIOMMU_INTERRUPT_FLUSH_COMPLETED)? IMASK_FCI:0) | - ((options & GRIOMMU_INTERRUPT_FLUSH_START)? IMASK_FLI:0) | - ((options & GRIOMMU_INTERRUPT_ACCESS_DENIED)? IMASK_ADI:0) | - ((options & GRIOMMU_INTERRUPT_TRANSLATION_ERROR)? IMASK_TEI:0); - - /* Clear previous interrupts*/ - griommu_reg_status_clear(STS_ALL); - - /* Get previous mask */ - irq = griommu_reg_imask() & IMASK_ALL; - - /* Set new mask */ - griommu_reg_imask_set(irq & ~(mask)); - - return GRIOMMU_ERR_OK; -} - -int griommu_error_status(uint32_t * access) -{ - struct griommu_priv *priv = griommupriv; - int status; - - if (priv == NULL){ - DBG("GRIOMMU not initialized.\n"); - return GRIOMMU_ERR_NOINIT; - } - - /* Get status mask */ - status = griommu_reg_status(); - - if (status != 0){ - /* Update pointed value */ - if (access != NULL){ - *access = griommu_reg_ahbfas(); - } - /* Clear errors */ - griommu_reg_status_clear(status); - } - - return status; -} - -/* Print IOMMU masters - * DEBUG function - */ -int griommu_print(void) -{ - #ifdef DEBUG - struct griommu_priv * priv = griommupriv; - unsigned int ctrl; - - if (priv == NULL){ - DBG("GRIOMMU not initialized.\n"); - return GRIOMMU_ERR_NOINIT; - } - - /* Print IOMMU status */ - ctrl = griommu_reg_ctrl(); - - printf("IOMMU status: prefetching %s, lookup bus %s, ahb update %s,\n" - "wprot only %s, pagesize %d KiB\n", - ((ctrl & CTRL_DP)? "disabled":"enabled"), - ((ctrl & CTRL_LB)? "bus1":"bus0"), - ((ctrl & CTRL_AU)? "enabled":"disabled"), - ((ctrl & CTRL_WP)? "enabled":"disabled"), - (4 << ((ctrl & CTRL_PGSZ) >> CTRL_PGSZ_BIT)) - ); - - /* Print each master configuration */ - int i, vendor, device, routing; - unsigned int master; - for (i=0; i < priv->masters; i++){ - master = griommu_reg_master(i); - vendor = (master & MASTER_VENDOR) >> MASTER_VENDOR_BIT; - device = (master & MASTER_DEVICE) >> MASTER_DEVICE_BIT; - routing = (master & MASTER_BS); - printf("IOMMU master %d: VENDOR=%s(0x%02x), DEVICE=%s(0x%03x), " - "BS=%s\n", - i, - ambapp_vendor_id2str(vendor), vendor, - ambapp_device_id2str(vendor,device), device, - (routing == MASTER_BS_BUS0? "Primary bus" : "Secondary bus") - ); - } - #endif - return GRIOMMU_ERR_OK; -} - -void * griommu_apv_new(void) -{ - struct griommu_priv * priv = griommupriv; - - if (priv == NULL){ - DBG("GRIOMMU not initialized.\n"); - return NULL; - } - - /* Allocate APV */ - unsigned int * orig_ptr = (unsigned int *) malloc( - (GRIOMMU_APV_SIZE/priv->pagesize) + GRIOMMU_APV_ALIGN); - if (orig_ptr == NULL) return NULL; - - /* Get the aligned pointer */ - unsigned int aligned_ptr = ( - ((unsigned int) orig_ptr + GRIOMMU_APV_ALIGN) & - ~(GRIOMMU_APV_ALIGN - 1)); - - /* Save the original pointer before the aligned pointer */ - unsigned int ** tmp_ptr = - (unsigned int **) (aligned_ptr - sizeof(orig_ptr)); - *tmp_ptr= orig_ptr; - - /* Return aligned pointer */ - return (void *) aligned_ptr; -} - -void griommu_apv_delete(void * apv) -{ - /* Recover orignal pointer placed just before the aligned pointer */ - unsigned int * orig_ptr; - unsigned int ** tmp_ptr = (unsigned int **) (apv - sizeof(orig_ptr)); - orig_ptr = *tmp_ptr; - - /* Deallocate memory */ - free(orig_ptr); -} - -int griommu_enable(int mode) -{ - struct griommu_priv * priv = griommupriv; - unsigned int ctrl; - - if (priv == NULL){ - DBG("GRIOMMU not initialized.\n"); - return GRIOMMU_ERR_NOINIT; - } - - switch (mode){ - case GRIOMMU_MODE_IOMMU: - default: - DBG("IOMMU mode not implemented in driver.\n"); - return GRIOMMU_ERR_EINVAL; - break; - case GRIOMMU_MODE_GROUPAPV: - if (priv->apv == 0){ - DBG("IOMMU APV not supported.\n"); - return GRIOMMU_ERR_IMPLEMENTED; - } - /* Enable IOMMU */ - ctrl = (griommu_reg_ctrl() & ~(CTRL_PM)); - griommu_reg_ctrl_set(ctrl | CTRL_PM_APV | CTRL_EN); - - /* Wait until change has effect */ - while((griommu_reg_ctrl() & CTRL_EN)==0){}; - - DBG("IOMMU enabled.\n"); - return GRIOMMU_ERR_OK; - break; - } - return GRIOMMU_ERR_OK; -} - -int griommu_disable(void) -{ - struct griommu_priv * priv = griommupriv; - unsigned int ctrl; - - if (priv == NULL){ - DBG("GRIOMMU not initialized.\n"); - return GRIOMMU_ERR_NOINIT; - } - - /* Disable IOMMU */ - ctrl = (griommu_reg_ctrl() & ~(CTRL_EN)); - griommu_reg_ctrl_set(ctrl); - - /* Wait until change has effect */ - while(griommu_reg_ctrl() & CTRL_EN){}; - - return GRIOMMU_ERR_OK; -} - -int griommu_group_setup(int group, void * apv, int options) -{ - struct griommu_priv * priv = griommupriv; - - if (priv == NULL){ - DBG("GRIOMMU not initialized.\n"); - return GRIOMMU_ERR_NOINIT; - } - - if ((group < 0) || (group >= priv->groups)){ - DBG("Wrong group id.\n"); - return GRIOMMU_ERR_EINVAL; - } - - if ((options < 0) || (options > GRIOMMU_OPTIONS_GROUP_PASSTHROUGH)){ - DBG("Wrong options.\n"); - return GRIOMMU_ERR_EINVAL; - } - - if (options == GRIOMMU_OPTIONS_GROUP_DISABLE){ - if ((unsigned int) apv & (GRIOMMU_APV_ALIGN -1)){ - DBG("Wrong pointer.\n"); - return GRIOMMU_ERR_EINVAL; - } - - /* Disable GROUP */ - griommu_reg_group_set(group, (((unsigned int) apv) & GRP_BASE) | 0); - DBG("GROUP[%d] DISABLED.\n", group); - return GRIOMMU_ERR_OK; - }else if (options == GRIOMMU_OPTIONS_GROUP_PASSTHROUGH){ - if ((unsigned int) apv & (GRIOMMU_APV_ALIGN -1)){ - DBG("Wrong pointer.\n"); - return GRIOMMU_ERR_EINVAL; - } - - /* Group in passthrough */ - griommu_reg_group_set(group, - (((unsigned int) apv) & GRP_BASE) | GRP_P | GRP_AG); - DBG("GROUP[%d] set to PASSTHROUGH.\n", group); - return GRIOMMU_ERR_OK; - }else{ - if (priv->apv == 0){ - DBG("IOMMU APV not supported.\n"); - return GRIOMMU_ERR_IMPLEMENTED; - } - - if ((apv == NULL) || ((unsigned int) apv & (GRIOMMU_APV_ALIGN -1))){ - DBG("Wrong pointer.\n"); - return GRIOMMU_ERR_EINVAL; - } - - /* Set up base and enable */ - griommu_reg_group_set(group, - (((unsigned int) apv) & GRP_BASE) | GRP_AG); - DBG("GROUP[%d] set to APV (0x%08x).\n", group, (unsigned int) apv); - return GRIOMMU_ERR_OK; - } -} - -int griommu_group_apv_init(int group, int options) -{ - struct griommu_priv * priv = griommupriv; - void * apv; - int val; - int ret; - size_t len; - - /* Flush APV cache if needed. - * This function checks for priv and group being valid.*/ - ret = griommu_group_apv_flush(group); - if (ret < 0){ - return ret; - } - - /* Get APV group */ - apv = (void *) (griommu_reg_group(group) & GRP_BASE); - - if (apv == NULL){ - DBG("Wrong pointer.\n"); - return GRIOMMU_ERR_NOTFOUND; - } - - /* Get init value (is a char) */ - if (options == GRIOMMU_OPTIONS_APV_ALLOW){ - val = 0x00; - }else{ - val = 0xff; - } - - /* Get APV length */ - len = GRIOMMU_APV_SIZE/priv->pagesize; - - /* Initialize structure */ - memset(apv, val, len); - - return GRIOMMU_ERR_OK; -} - -int griommu_group_apv_page_set(int group, int index, int size, int options) -{ - void * apv; - unsigned int val; - int ret; - - /* Flush APV cache if needed. - * This function checks for priv and group being valid.*/ - ret = griommu_group_apv_flush(group); - if (ret < 0){ - return ret; - } - - /* Get APV group */ - apv = (void *) (griommu_reg_group(group) & GRP_BASE); - - if (apv == NULL){ - DBG("Wrong pointer.\n"); - return GRIOMMU_ERR_NOTFOUND; - } - - /* Get init value */ - if (options == GRIOMMU_OPTIONS_APV_ALLOW){ - val = 0x0; - }else{ - val = 0xffffffff; - } - - return griommu_apv_set(apv, index, size, val); -} - -int griommu_group_apv_address_set(int group, uint32_t addr, int size, - int options) -{ - struct griommu_priv * priv = griommupriv; - void * apv; - unsigned int val; - int ret; - int startpage; - int endpage; - int npages; - - /* Flush APV cache if needed. - * This function checks for priv and group being valid.*/ - ret = griommu_group_apv_flush(group); - if (ret < 0){ - return ret; - } - - /* Get APV group */ - apv = (void *) (griommu_reg_group(group) & GRP_BASE); - - if (apv == NULL){ - DBG("Wrong pointer.\n"); - return GRIOMMU_ERR_NOTFOUND; - } - - /* Get init value */ - if (options == GRIOMMU_OPTIONS_APV_ALLOW){ - val = 0x0; - }else{ - val = 0xffffffff; - } - - /* Get start page */ - startpage = (addr / priv->pagesize); - - /* Get end page */ - endpage = ((addr + size)/ priv->pagesize); - - /* Get number of pages */ - npages = endpage - startpage + 1; - - return griommu_apv_set(apv, startpage, npages, val); -} - -int griommu_apv_init(void * apv, int options) -{ - struct griommu_priv * priv = griommupriv; - int val; - size_t len; - - if (priv == NULL){ - DBG("GRIOMMU not initialized.\n"); - return GRIOMMU_ERR_NOINIT; - } - - if ((apv == NULL) || ((unsigned int) apv & (GRIOMMU_APV_ALIGN -1))){ - DBG("Wrong pointer.\n"); - return GRIOMMU_ERR_EINVAL; - } - - /* Get init value (is a char) */ - if (options == GRIOMMU_OPTIONS_APV_ALLOW){ - val = 0x00; - }else{ - val = 0xff; - } - - /* Get APV length */ - len = GRIOMMU_APV_SIZE/priv->pagesize; - - /* Initialize structure */ - memset(apv, val, len); - - return GRIOMMU_ERR_OK; -} - -int griommu_apv_page_set(void * apv, int index, int size, int options) -{ - struct griommu_priv * priv = griommupriv; - unsigned int val; - - if (priv == NULL){ - DBG("GRIOMMU not initialized.\n"); - return GRIOMMU_ERR_NOINIT; - } - - if ((apv == NULL) || ((unsigned int) apv & (GRIOMMU_APV_ALIGN -1))){ - DBG("Wrong pointer.\n"); - return GRIOMMU_ERR_EINVAL; - } - - /* Get init value */ - if (options == GRIOMMU_OPTIONS_APV_ALLOW){ - val = 0x0; - }else{ - val = 0xffffffff; - } - - return griommu_apv_set(apv, index, size, val); -} - -int griommu_apv_address_set(void * apv, uint32_t addr, int size, int options) -{ - struct griommu_priv * priv = griommupriv; - unsigned int val; - int startpage; - int endpage; - int npages; - - if (priv == NULL){ - DBG("GRIOMMU not initialized.\n"); - return GRIOMMU_ERR_NOINIT; - } - - if ((apv == NULL) || ((unsigned int) apv & (GRIOMMU_APV_ALIGN -1))){ - DBG("Wrong pointer.\n"); - return GRIOMMU_ERR_EINVAL; - } - - /* Get init value */ - if (options == GRIOMMU_OPTIONS_APV_ALLOW){ - val = 0x0; - }else{ - val = 0xffffffff; - } - - /* Get start page */ - startpage = (addr / priv->pagesize); - - /* Get end page */ - endpage = ((addr + size)/ priv->pagesize); - - /* Get number of pages */ - npages = endpage - startpage + 1; - - return griommu_apv_set(apv, startpage, npages, val); -} - -int griommu_group_info(int group, uint32_t * info) -{ - struct griommu_priv * priv = griommupriv; - - if (priv == NULL){ - DBG("GRIOMMU not initialized.\n"); - return GRIOMMU_ERR_NOINIT; - } - - if ((group < 0) || (group >= priv->groups)){ - DBG("Wrong group id.\n"); - return GRIOMMU_ERR_EINVAL; - } - - if (info == NULL){ - DBG("Wrong pointer.\n"); - return GRIOMMU_ERR_EINVAL; - } - - /* Get group */ - *info = griommu_reg_group(group); - - return GRIOMMU_ERR_OK; -} - -/* Flush APV cache group: - */ -int griommu_group_apv_flush(int group) -{ - struct griommu_priv * priv = griommupriv; - - if (priv == NULL){ - DBG("GRIOMMU not initialized.\n"); - return GRIOMMU_ERR_NOINIT; - } - - if ((group < 0) || (group >= priv->groups)){ - DBG("Wrong group id.\n"); - return GRIOMMU_ERR_EINVAL; - } - - /* Flush cache */ - if (priv->cache_enabled){ - if (priv->group_addressing){ - griommu_reg_flush_set(((group << FLUSH_FGRP_BIT) & FLUSH_FGRP) | - FLUSH_GF | FLUSH_F); - }else{ - griommu_reg_flush_set(FLUSH_F); - } - DBG("GRIOMMU APV cache flushed.\n"); - } - - return GRIOMMU_ERR_OK; -} - -/* Flush APV cache: - */ -int griommu_apv_flush(void) -{ - struct griommu_priv * priv = griommupriv; - - if (priv == NULL){ - DBG("GRIOMMU not initialized.\n"); - return GRIOMMU_ERR_NOINIT; - } - - /* Flush cache */ - if (priv->cache_enabled){ - griommu_reg_flush_set(FLUSH_F); - DBG("GRIOMMU APV cache flushed.\n"); - } - - return GRIOMMU_ERR_OK; -} - diff --git a/c/src/lib/libbsp/sparc/shared/irq/bsp_isr_handler.c b/c/src/lib/libbsp/sparc/shared/irq/bsp_isr_handler.c deleted file mode 100644 index a4d33b0932..0000000000 --- a/c/src/lib/libbsp/sparc/shared/irq/bsp_isr_handler.c +++ /dev/null @@ -1,35 +0,0 @@ -/* -* COPYRIGHT (c) 2015 -* Cobham Gaisler -* -* 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 - -static inline void bsp_dispatch_irq(int irq) -{ - bsp_interrupt_handler_entry *e = - &bsp_interrupt_handler_table[bsp_interrupt_handler_index(irq)]; - - while (e != NULL) { - (*e->handler)(e->arg); - e = e->next; - } -} - -/* Called directly from IRQ trap handler TRAP[0x10..0x1F] = IRQ[0..15] */ -void bsp_isr_handler(rtems_vector_number vector) -{ - int irq = vector - 0x10; - - /* Let BSP fixup and/or handle incomming IRQ */ - irq = bsp_irq_fixup(irq); - - bsp_dispatch_irq(irq); -} diff --git a/c/src/lib/libbsp/sparc/shared/irq/genirq.c b/c/src/lib/libbsp/sparc/shared/irq/genirq.c deleted file mode 100644 index bba642e701..0000000000 --- a/c/src/lib/libbsp/sparc/shared/irq/genirq.c +++ /dev/null @@ -1,243 +0,0 @@ -/* - * Generic interrupt helpers mainly for GRLIB PCI peripherals - * - * COPYRIGHT (c) 2008. - * Cobham Gaisler AB. - * - * 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 - -struct genirq_handler_entry { - struct genirq_handler_entry *next; /* Next ISR entry for this IRQ number */ - genirq_handler isr; /* ISR function called upon IRQ */ - void *arg; /* custom argument to ISR */ - int enabled; /* Inidicates if IRQ is enabled */ -}; - -struct genirq_irq_entry { - struct genirq_handler_entry *head; - struct genirq_stats stats; -}; - -struct genirq_priv { - /* Maximum number of interrupt */ - int genirq_max; - /* IRQ Table index N reflect IRQ number N */ - struct genirq_irq_entry genirq_table[1]; /* Length depends on */ -}; - -genirq_t genirq_init(int number_of_irqs) -{ - int size; - struct genirq_priv *priv; - - size = sizeof(int) + - number_of_irqs * sizeof(struct genirq_irq_entry); - - priv = (struct genirq_priv *)malloc(size); - if ( !priv ) - return NULL; - memset(priv, 0, size); - priv->genirq_max = number_of_irqs - 1; - - return priv; -} - -void genirq_destroy(genirq_t d) -{ - struct genirq_priv *priv = d; - struct genirq_irq_entry *irqentry; - struct genirq_handler_entry *isrentry, *tmp; - int i; - - /* Free all registered interrupts */ - for ( i=0; igenirq_max; i++) { - irqentry = &priv->genirq_table[i]; - isrentry = irqentry->head; - while ( isrentry ) { - tmp = isrentry; - isrentry = isrentry->next; - genirq_free_handler(tmp); - } - } - - free(priv); -} - -int genirq_check(genirq_t d, int irq) -{ - struct genirq_priv *priv = d; - - if ( (irq <= 0) || (irq > priv->genirq_max) ) - return -1; - else - return 0; -} - -void *genirq_alloc_handler(genirq_handler isr, void *arg) -{ - struct genirq_handler_entry *newentry; - - newentry = malloc(sizeof(struct genirq_handler_entry)); - if ( newentry ) { - /* Initialize ISR entry */ - newentry->isr = isr; - newentry->arg = arg; - newentry->enabled = 0; - } - return newentry; -} - -int genirq_register(genirq_t d, int irq, void *handler) -{ - struct genirq_priv *priv = d; - struct genirq_irq_entry *irqentry; - struct genirq_handler_entry *isrentry, *newentry = handler; - - if ( genirq_check(d, irq) ) - return -1; - - /* Insert new ISR entry first into table */ - irqentry = &priv->genirq_table[irq]; - isrentry = irqentry->head; - irqentry->head = newentry; - newentry->next = isrentry; - - if ( isrentry ) - return 1; /* This is the first handler on this IRQ */ - return 0; -} - -void *genirq_unregister(genirq_t d, int irq, genirq_handler isr, void *arg) -{ - struct genirq_priv *priv = d; - struct genirq_irq_entry *irqentry; - struct genirq_handler_entry *isrentry, **prev; - void *ret; - - if ( genirq_check(d, irq) ) - return NULL; - - /* Remove isr[arg] from ISR list */ - irqentry = &priv->genirq_table[irq]; - ret = NULL; - - prev = &irqentry->head; - isrentry = irqentry->head; - while ( isrentry ) { - if ( (isrentry->arg == arg) && (isrentry->isr == isr) ) { - /* Found ISR, remove it from list */ - if ( isrentry->enabled ) { - /* Can not remove enabled ISRs, disable first */ - ret = NULL; - break; - } - *prev = isrentry->next; - ret = isrentry; - break; - } - prev = &isrentry->next; - isrentry = isrentry->next; - } - - return ret; -} - -/* Enables or Disables ISR handler. Internal function to reduce footprint - * of enable/disable functions. - * - * \param action 1=enable, 0=disable ISR - */ -static int genirq_set_active( - struct genirq_priv *priv, - int irq, - genirq_handler isr, - void *arg, - int action) -{ - struct genirq_irq_entry *irqentry; - struct genirq_handler_entry *isrentry, *e = NULL; - int enabled; - - if ( genirq_check(priv, irq) ) - return -1; - - /* Find isr[arg] in ISR list */ - irqentry = &priv->genirq_table[irq]; - enabled = 0; - - isrentry = irqentry->head; - while ( isrentry ) { - if ( (isrentry->arg == arg) && (isrentry->isr == isr) ) { - /* Found ISR */ - if ( isrentry->enabled == action ) { - /* The ISR is already enabled or disabled - * depending on request, neccessary actions - * were taken last time the same action was - * requested. - */ - return 1; - } - e = isrentry; - } else { - enabled += isrentry->enabled; - } - isrentry = isrentry->next; - } - - if ( !e ) - return -1; - - e->enabled = action; - - return enabled; -} - -int genirq_enable(genirq_t d, int irq, genirq_handler isr, void *arg) -{ - struct genirq_priv *priv = d; - return genirq_set_active(priv, irq, isr, arg, 1); -} - -int genirq_disable(genirq_t d, int irq, genirq_handler isr, void *arg) -{ - struct genirq_priv *priv = d; - return genirq_set_active(priv, irq, isr, arg, 0); -} - -void genirq_doirq(genirq_t d, int irq) -{ - struct genirq_priv *priv = d; - struct genirq_irq_entry *irqentry; - struct genirq_handler_entry *isrentry; - int enabled; - - irqentry = &priv->genirq_table[irq]; - irqentry->stats.irq_cnt++; - - enabled = 0; - - isrentry = irqentry->head; - while ( isrentry ) { - if ( isrentry->enabled ) { - enabled = 1; - /* Call the ISR */ - isrentry->isr(isrentry->arg); - } - isrentry = isrentry->next; - } - - /* Was the IRQ an IRQ without source? */ - if ( enabled == 0 ) { - /* This should not happen */ - printk("Spurious IRQ happened on IRQ %d\n", irq); - } -} diff --git a/c/src/lib/libbsp/sparc/shared/irq/irq-shared.c b/c/src/lib/libbsp/sparc/shared/irq/irq-shared.c deleted file mode 100644 index 344ed71a34..0000000000 --- a/c/src/lib/libbsp/sparc/shared/irq/irq-shared.c +++ /dev/null @@ -1,103 +0,0 @@ -/* -* COPYRIGHT (c) 2012-2015 -* Cobham Gaisler -* -* 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 - -#if defined(RTEMS_SMP) && defined(LEON3) -/* Interrupt to CPU map. Default to CPU0 since in BSS. */ -const unsigned char LEON3_irq_to_cpu[32] __attribute__((weak)); - -/* On SMP use map table above relative to SMP Boot CPU (normally CPU0) */ -static inline int bsp_irq_cpu(int irq) -{ - /* protect from bad user configuration, default to boot cpu */ - if (rtems_configuration_get_maximum_processors() <= LEON3_irq_to_cpu[irq]) - return LEON3_Cpu_Index; - else - return LEON3_Cpu_Index + LEON3_irq_to_cpu[irq]; -} -#else -/* when not SMP the local CPU is returned */ -static inline int bsp_irq_cpu(int irq) -{ -#ifdef LEON3 - return _LEON3_Get_current_processor(); -#else - return 0; -#endif -} -#endif - -/* Initialize interrupts */ -void BSP_shared_interrupt_init(void) -{ - rtems_vector_number vector; - rtems_isr_entry previous_isr; - int i; - - for (i=0; i <= BSP_INTERRUPT_VECTOR_MAX_STD; i++) { -#if defined(LEON3) && \ - (defined(RTEMS_SMP) || defined(RTEMS_MULTIPROCESSING)) - /* Don't install IRQ handler on IPI interrupt. An SMP kernel with max one - * CPU does not use IPIs - */ -#ifdef RTEMS_SMP - if (rtems_configuration_get_maximum_processors() > 1) -#endif - if (i == LEON3_mp_irq) - continue; -#endif - vector = SPARC_ASYNCHRONOUS_TRAP(i) + 0x10; - rtems_interrupt_catch(bsp_isr_handler, vector, &previous_isr); - } - - /* Initalize interrupt support */ - bsp_interrupt_initialize(); -} - -/* Callback from bsp_interrupt_initialize() */ -rtems_status_code bsp_interrupt_facility_initialize(void) -{ - return RTEMS_SUCCESSFUL; -} - -void bsp_interrupt_vector_enable(rtems_vector_number vector) -{ - int irq = (int)vector; - bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector)); - BSP_Cpu_Unmask_interrupt(irq, bsp_irq_cpu(irq)); -} - -void bsp_interrupt_vector_disable(rtems_vector_number vector) -{ - int irq = (int)vector; - bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector)); - BSP_Cpu_Mask_interrupt(irq, bsp_irq_cpu(irq)); -} - -void BSP_shared_interrupt_mask(int irq) -{ - BSP_Cpu_Mask_interrupt(irq, bsp_irq_cpu(irq)); -} - -void BSP_shared_interrupt_unmask(int irq) -{ - BSP_Cpu_Unmask_interrupt(irq, bsp_irq_cpu(irq)); -} - -void BSP_shared_interrupt_clear(int irq) -{ - /* We don't have to interrupt lock here, because the register is only - * written and self clearing - */ - BSP_Clear_interrupt(irq); -} diff --git a/c/src/lib/libbsp/sparc/shared/l2c/l2c.c b/c/src/lib/libbsp/sparc/shared/l2c/l2c.c deleted file mode 100644 index 0c577f360d..0000000000 --- a/c/src/lib/libbsp/sparc/shared/l2c/l2c.c +++ /dev/null @@ -1,2110 +0,0 @@ -/* - * GRLIB L2CACHE Driver - * - * COPYRIGHT (c) 2017 - * Cobham Gaisler AB - * - * 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 - -/*#define STATIC*/ -#define STATIC static - -/*#define INLINE*/ -#define INLINE inline - -#define UNUSED __attribute__((unused)) - -/*#define DEBUG 1*/ - -#ifdef DEBUG -#define DBG(x...) printf(x) -#else -#define DBG(x...) -#endif - -/* - * L2CACHE CTRL register fields - */ -#define L2C_CTRL_EN (0x1 << L2C_CTRL_EN_BIT) -#define L2C_CTRL_EDAC (0x1 << L2C_CTRL_EDAC_BIT) -#define L2C_CTRL_REPL (0x3 << L2C_CTRL_REPL_BIT) -#define L2C_CTRL_IWAY (0xf << L2C_CTRL_IWAY_BIT) -#define L2C_CTRL_LOCK (0xf << L2C_CTRL_LOCK_BIT) -#define L2C_CTRL_HPRHB (0x1 << L2C_CTRL_HPRHB_BIT) -#define L2C_CTRL_HPB (0x1 << L2C_CTRL_HPB_BIT) -#define L2C_CTRL_UC (0x1 << L2C_CTRL_UC_BIT) -#define L2C_CTRL_HC (0x1 << L2C_CTRL_HC_BIT) -#define L2C_CTRL_WP (0x1 << L2C_CTRL_WP_BIT) -#define L2C_CTRL_HP (0x1 << L2C_CTRL_HP_BIT) - -#define L2C_CTRL_EN_BIT 31 -#define L2C_CTRL_EDAC_BIT 30 -#define L2C_CTRL_REPL_BIT 28 -#define L2C_CTRL_IWAY_BIT 12 -#define L2C_CTRL_LOCK_BIT 8 -#define L2C_CTRL_HPRHB_BIT 5 -#define L2C_CTRL_HPB_BIT 4 -#define L2C_CTRL_UC_BIT 3 -#define L2C_CTRL_HC_BIT 2 -#define L2C_CTRL_WP_BIT 1 -#define L2C_CTRL_HP_BIT 0 - -/* - * L2CACHE STATUS register fields - */ -#define L2C_STAT_LS (0x1 << L2C_STAT_LS_BIT) -#define L2C_STAT_AT (0x1 << L2C_STAT_AT_BIT) -#define L2C_STAT_MP (0x1 << L2C_STAT_MP_BIT) -#define L2C_STAT_MTRR (0x3f << L2C_STAT_MTRR_BIT) -#define L2C_STAT_BBUSW (0x7 << L2C_STAT_BBUSW_BIT) -#define L2C_STAT_WAYSIZE (0x7ff << L2C_STAT_WAYSIZE_BIT) -#define L2C_STAT_WAY (0x3 << L2C_STAT_WAY_BIT) - -#define L2C_STAT_LS_BIT 24 -#define L2C_STAT_AT_BIT 23 -#define L2C_STAT_MP_BIT 22 -#define L2C_STAT_MTRR_BIT 16 -#define L2C_STAT_BBUSW_BIT 13 -#define L2C_STAT_WAYSIZE_BIT 2 -#define L2C_STAT_WAY_BIT 0 - -/* - * L2CACHE MTRR register fields - */ -#define L2C_MTRR_ADDR (0x3fff << L2C_MTRR_ADDR_BIT) -#define L2C_MTRR_ACC (0x3 << L2C_MTRR_ACC_BIT) -#define L2C_MTRR_MASK (0x3fff << L2C_MTRR_MASK_BIT) -#define L2C_MTRR_WP (0x1 << L2C_MTRR_WP_BIT) -#define L2C_MTRR_AC (0x1 << L2C_MTRR_AC_BIT) - -#define L2C_MTRR_ADDR_BIT 18 -#define L2C_MTRR_ACC_BIT 16 -#define L2C_MTRR_MASK_BIT 2 -#define L2C_MTRR_WP_BIT 1 -#define L2C_MTRR_AC_BIT 0 - -#define L2C_MTRR_UNCACHED 0 -#define L2C_MTRR_WRITETHROUGH (0x1 << L2C_MTRR_ACC_BIT) -#define L2C_MTRR_WRITEPROT_ENABLE L2C_MTRR_WP -#define L2C_MTRR_WRITEPROT_DISABLE 0 -#define L2C_MTRR_ACCESSCONTROL_ENABLE L2C_MTRR_AC -#define L2C_MTRR_ACCESSCONTROL_DISABLE 0 - -#define REG_WRITE(addr, val) (*(volatile unsigned int *)(addr) = (unsigned int)(val)) -#define REG_READ(addr) (*(volatile unsigned int *)(addr)) - -/* - * L2CACHE FLUSHMEM register fields - */ -#define L2C_FLUSH_ADDR (0x7ffffff << L2C_FLUSH_ADDR_BIT) -#define L2C_FLUSH_DI (0x1 << L2C_FLUSH_DI_BIT) -#define L2C_FLUSH_FMODE (0x7 << L2C_FLUSH_FMODE_BIT) - -#define L2C_FLUSH_ADDR_BIT 5 -#define L2C_FLUSH_DI_BIT 3 -#define L2C_FLUSH_FMODE_BIT 0 - -#define L2C_FLUSH_FMODE_INV_ONE (0x1 << L2C_FLUSH_FMODE_BIT) -#define L2C_FLUSH_FMODE_WB_ONE (0x2 << L2C_FLUSH_FMODE_BIT) -#define L2C_FLUSH_FMODE_INV_WB_ONE (0x3 << L2C_FLUSH_FMODE_BIT) -#define L2C_FLUSH_FMODE_INV_ALL (0x5 << L2C_FLUSH_FMODE_BIT) -#define L2C_FLUSH_FMODE_WB_ALL (0x6 << L2C_FLUSH_FMODE_BIT) -#define L2C_FLUSH_FMODE_INV_WB_ALL (0x7 << L2C_FLUSH_FMODE_BIT) - -/* - * L2CACHE FLUSSETINDEX register fields - */ -#define L2C_FLUSHSI_INDEX (0xffff << L2C_FLUSHSI_INDEX_BIT) -#define L2C_FLUSHSI_TAG (0x3fffff << L2C_FLUSHSI_TAG_BIT) -#define L2C_FLUSHSI_FL (0x1 << L2C_FLUSHSI_FL_BIT) -#define L2C_FLUSHSI_VB (0x1 << L2C_FLUSHSI_VB_BIT) -#define L2C_FLUSHSI_DB (0x1 << L2C_FLUSHSI_DB_BIT) -#define L2C_FLUSHSI_WAY (0x3 << L2C_FLUSHSI_WAY_BIT) -#define L2C_FLUSHSI_DI (0x1 << L2C_FLUSHSI_DI_BIT) -#define L2C_FLUSHSI_WF (0x1 << L2C_FLUSHSI_WF_BIT) -#define L2C_FLUSHSI_FMODE (0x3 << L2C_FLUSHSI_FMODE_BIT) - -#define L2C_FLUSHSI_INDEX_BIT 16 -#define L2C_FLUSHSI_TAG_BIT 10 -#define L2C_FLUSHSI_FL_BIT 9 -#define L2C_FLUSHSI_VB_BIT 8 -#define L2C_FLUSHSI_DB_BIT 7 -#define L2C_FLUSHSI_WAY_BIT 4 -#define L2C_FLUSHSI_DI_BIT 3 -#define L2C_FLUSHSI_WF_BIT 2 -#define L2C_FLUSHSI_FMODE_BIT 0 - -#define L2C_FLUSHSI_FMODE_SET_INV_ONE (0x1 << L2C_FLUSHSI_FMODE_BIT) -#define L2C_FLUSHSI_FMODE_SET_WB_ONE (0x2 << L2C_FLUSHSI_FMODE_BIT) -#define L2C_FLUSHSI_FMODE_SET_INV_WB_ONE (0x3 << L2C_FLUSHSI_FMODE_BIT) -#define L2C_FLUSHSI_FMODE_WAY_UPDATE (0x1 << L2C_FLUSHSI_FMODE_BIT) -#define L2C_FLUSHSI_FMODE_WAY_WB (0x2 << L2C_FLUSHSI_FMODE_BIT) -#define L2C_FLUSHSI_FMODE_WAY_UPDATE_WB_ALL (0x3 << L2C_FLUSHSI_FMODE_BIT) - -/* - * L2CACHE ERROR register fields - */ -#define L2C_ERROR_AHBM (0xf << L2C_ERROR_AHBM_BIT) -#define L2C_ERROR_SCRUB (0x1 << L2C_ERROR_SCRUB_BIT) -#define L2C_ERROR_TYPE (0x7 << L2C_ERROR_TYPE_BIT) -#define L2C_ERROR_TAG (0x1 << L2C_ERROR_TAG_BIT) -#define L2C_ERROR_COR (0x1 << L2C_ERROR_COR_BIT) -#define L2C_ERROR_MULTI (0x1 << L2C_ERROR_MULTI_BIT) -#define L2C_ERROR_VALID (0x1 << L2C_ERROR_VALID_BIT) -#define L2C_ERROR_DISERESP (0x1 << L2C_ERROR_DISERESP_BIT) -#define L2C_ERROR_CEC (0x7 << L2C_ERROR_CEC_BIT) -#define L2C_ERROR_IRQP (0xf << L2C_ERROR_IRQP_BIT) -#define L2C_ERROR_IRQM (0xf << L2C_ERROR_IRQM_BIT) -#define L2C_ERROR_IRQM_BCKEND (0x1 << L2C_ERROR_IRQM_BCKEND_BIT) -#define L2C_ERROR_IRQM_WPROT (0x1 << L2C_ERROR_IRQM_WPROT_BIT) -#define L2C_ERROR_IRQM_UNCORR (0x1 << L2C_ERROR_IRQM_UNCORR_BIT) -#define L2C_ERROR_IRQM_CORR (0x1 << L2C_ERROR_IRQM_CORR_BIT) -#define L2C_ERROR_SCB (0x3 << L2C_ERROR_SCB_BIT) -#define L2C_ERROR_STCB (0x3 << L2C_ERROR_STCB_BIT) -#define L2C_ERROR_XCB (0x1 << L2C_ERROR_XCB_BIT) -#define L2C_ERROR_RCB (0x1 << L2C_ERROR_RCB_BIT) -#define L2C_ERROR_COMP (0x1 << L2C_ERROR_COMP_BIT) -#define L2C_ERROR_RST (0x1 << L2C_ERROR_RST_BIT) - -#define L2C_ERROR_AHBM_BIT 28 -#define L2C_ERROR_SCRUB_BIT 27 -#define L2C_ERROR_TYPE_BIT 24 -#define L2C_ERROR_TAG_BIT 23 -#define L2C_ERROR_COR_BIT 22 -#define L2C_ERROR_MULTI_BIT 21 -#define L2C_ERROR_VALID_BIT 20 -#define L2C_ERROR_DISERESP_BIT 19 -#define L2C_ERROR_CEC_BIT 16 -#define L2C_ERROR_IRQP_BIT 12 -#define L2C_ERROR_IRQM_BCKEND_BIT 11 -#define L2C_ERROR_IRQM_WPROT_BIT 10 -#define L2C_ERROR_IRQM_UNCORR_BIT 9 -#define L2C_ERROR_IRQM_CORR_BIT 8 -#define L2C_ERROR_IRQM_BIT 8 -#define L2C_ERROR_SCB_BIT 6 -#define L2C_ERROR_STCB_BIT 4 -#define L2C_ERROR_XCB_BIT 3 -#define L2C_ERROR_RCB_BIT 2 -#define L2C_ERROR_COMP_BIT 1 -#define L2C_ERROR_RST_BIT 0 - -/* - * L2CACHE DATA CHECK BITS register fields - */ -#define L2C_DCB_CB (0xfffffff << L2C_DCB_CB_BIT) - -#define L2C_DCB_CB_BIT 0 - -/* - * L2CACHE SCRUB register fields - */ -#define L2C_SCRUB_INDEX (0xffff << L2C_SCRUB_INDEX_BIT) -#define L2C_SCRUB_WAY (0x3 << L2C_SCRUB_WAY_BIT) -#define L2C_SCRUB_PEN (0x1 << L2C_SCRUB_PEN_BIT) -#define L2C_SCRUB_EN (0x1 << L2C_SCRUB_EN_BIT) - -#define L2C_SCRUB_INDEX_BIT 16 -#define L2C_SCRUB_WAY_BIT 2 -#define L2C_SCRUB_PEN_BIT 1 -#define L2C_SCRUB_EN_BIT 0 - -/* - * L2CACHE SCRUBDELAY register fields - */ -#define L2C_SCRUB_DEL (0xffff << L2C_SCRUB_DEL_BIT) - -#define L2C_SCRUB_DEL_BIT 0 - -/* - * L2CACHE ERROR INJECT register fields - */ -#define L2C_ERRINJ_ADDR (0x3fffffff << L2C_ERRINJ_ADDR_BIT) -#define L2C_ERRINJ_EN (0x1 << L2C_ERRINJ_EN_BIT) - -#define L2C_ERRINJ_ADDR_BIT 2 -#define L2C_ERRINJ_EN_BIT 0 - -/* - * L2CACHE ACCESS CONTROL register fields - */ -#define L2C_ACCCTRL_SPLITQ (0x1 << L2C_ACCCTRL_SPLITQ_BIT) -#define L2C_ACCCTRL_NHM (0x1 << L2C_ACCCTRL_NHM_BIT) -#define L2C_ACCCTRL_BERR (0x1 << L2C_ACCCTRL_BERR_BIT) -#define L2C_ACCCTRL_OAPM (0x1 << L2C_ACCCTRL_OAPM_BIT) -#define L2C_ACCCTRL_FLINE (0x1 << L2C_ACCCTRL_FLINE_BIT) -#define L2C_ACCCTRL_DBPF (0x1 << L2C_ACCCTRL_DBPF_BIT) -#define L2C_ACCCTRL_128WF (0x1 << L2C_ACCCTRL_128WF_BIT) -#define L2C_ACCCTRL_DBPWS (0x1 << L2C_ACCCTRL_DBPWS_BIT) -#define L2C_ACCCTRL_SPLIT (0x1 << L2C_ACCCTRL_SPLIT_BIT) - -#define L2C_ACCCTRL_SPLITQ_BIT 10 -#define L2C_ACCCTRL_NHM_BIT 9 -#define L2C_ACCCTRL_BERR_BIT 8 -#define L2C_ACCCTRL_OAPM_BIT 7 -#define L2C_ACCCTRL_FLINE_BIT 6 -#define L2C_ACCCTRL_DBPF_BIT 5 -#define L2C_ACCCTRL_128WF_BIT 4 -#define L2C_ACCCTRL_DBPWS_BIT 2 -#define L2C_ACCCTRL_SPLIT_BIT 1 - -#ifdef TEST_L2CACHE -/* - * L2CACHE TAG fields - */ -#define L2C_TAG_TAG (0xfffffc << L2C_TAG_TAG_BIT) -#define L2C_TAG_VALID (0x3 << L2C_TAG_VALID_BIT) -#define L2C_TAG_DIRTY (0x3 << L2C_TAG_DIRTY_BIT) -#define L2C_TAG_LRU (0x3 << L2C_TAG_LRU_BIT) - -#define L2C_TAG_TAG_BIT 10 -#define L2C_TAG_VALID_BIT 8 -#define L2C_TAG_DIRTY_BIT 6 -#define L2C_TAG_LRU_BIT 0 - -#endif /* TEST_L2CACHE */ - -#define DEVNAME_LEN 9 -/* - * L2CACHE Driver private data struture - */ -struct l2cache_priv { - struct drvmgr_dev *dev; - char devname[DEVNAME_LEN]; - - /* L2CACHE control registers */ - struct l2c_regs *regs; - - /* L2CACHE status */ - int ways; - int waysize; - int linesize; - int index; - int mtrr; - int ft_support; - int split_support; - - /* User defined ISR */ - l2cache_isr_t isr; - void *isr_arg; -}; - -/* - * L2CACHE internal prototypes - */ -/* -Register access functions */ -STATIC INLINE int l2cache_reg_ctrl_enable(void); -STATIC INLINE int l2cache_reg_ctrl_disable(void); -STATIC INLINE int l2cache_reg_ctrl_locked_set(int locked); -STATIC INLINE int l2cache_reg_ctrl_edac_set(int edac); -STATIC INLINE int l2cache_reg_ctrl_repl(int policy); -STATIC INLINE int l2cache_reg_ctrl_iway(int way); -STATIC INLINE int l2cache_reg_ctrl_writep(int policy); -STATIC INLINE unsigned int l2cache_reg_ctrl(void); -STATIC INLINE unsigned int l2cache_reg_status(void); -STATIC INLINE int l2cache_reg_mtrr_set(int index, unsigned int addr, - unsigned int mask, int options); -UNUSED STATIC INLINE unsigned int l2cache_reg_mtrr_get(int index); -STATIC INLINE int l2cache_reg_flushmem(unsigned int addr, int options); -STATIC INLINE int l2cache_reg_flushline(int way, int index, int options); -STATIC INLINE int l2cache_reg_flushway(unsigned int tag, int way, int options); -STATIC INLINE unsigned int l2cache_reg_error(void); -STATIC INLINE int l2cache_reg_error_reset(void); -STATIC INLINE int l2cache_reg_error_irqmask(int mask); -STATIC INLINE unsigned int l2cache_reg_error_addr(void); -STATIC INLINE unsigned int l2cache_reg_scrub(void); -STATIC INLINE int l2cache_reg_scrub_enable(int delay); -STATIC INLINE int l2cache_reg_scrub_disable(void); -STATIC INLINE unsigned int l2cache_reg_scrub_delay(void); -STATIC INLINE int l2cache_reg_scrub_line(int way, int index); -STATIC INLINE unsigned int l2cache_reg_accctrl(void); -STATIC INLINE int l2cache_reg_accctrl_split_disable(void); -STATIC INLINE int l2cache_reg_accctrl_split_enable(void); -#ifdef TEST_L2CACHE -STATIC INLINE int l2cache_reg_error_dcb(unsigned int cb); -STATIC INLINE int l2cache_reg_error_inject(unsigned int addr); -STATIC INLINE unsigned int l2cache_reg_diagtag(int way, int index); -STATIC INLINE unsigned int l2cache_reg_diagdata(int way, int index, int word); -STATIC unsigned int log2int(unsigned int v); -#endif /* TEST_L2CACHE */ - -/* -Control functions */ -STATIC int l2cache_ctrl_status(void); -STATIC void l2cache_flushwait(void); - -/* -Init function */ -STATIC int l2cache_init(struct l2cache_priv *priv); - -/* -Init function called by drvmgr */ -int l2cache_init1(struct drvmgr_dev *dev); - -/* -IRQ handler */ -void l2cache_isr(void *arg); - -/* - * L2CACHE static members - */ -static struct l2cache_priv *l2cachepriv = NULL; -#ifdef DEBUG -static char * repl_names[4] = {"LRU","Random","Master-Idx-1","Master-IDx-2"}; -#endif - -/* L2CACHE DRIVER */ - -struct drvmgr_drv_ops l2cache_ops = -{ - .init = {l2cache_init1, NULL, NULL, NULL}, - .remove = NULL, - .info = NULL -}; - -struct amba_dev_id l2cache_ids[] = -{ - {VENDOR_GAISLER, GAISLER_L2CACHE}, - {0, 0} /* Mark end of table */ -}; - -struct amba_drv_info l2cache_info = -{ - { - DRVMGR_OBJ_DRV, /* Driver */ - NULL, /* Next driver */ - NULL, /* Device list */ - DRIVER_AMBAPP_GAISLER_L2CACHE_ID,/* Driver ID */ - "L2CACHE_DRV", /* Driver Name */ - DRVMGR_BUS_TYPE_AMBAPP, /* Bus Type */ - &l2cache_ops, - NULL, /* Funcs */ - 0, /* No devices yet */ - sizeof(struct l2cache_priv), /* Make drvmgr alloc private */ - }, - &l2cache_ids[0] -}; - -void l2cache_register_drv(void) -{ - DBG("Registering L2CACHE driver\n"); - drvmgr_drv_register(&l2cache_info.general); -} - -/* Initializes the L2CACHE core and driver - * - * Return values - * 0 Successful initalization - */ -STATIC int l2cache_init(struct l2cache_priv *priv) -{ - struct ambapp_ahb_info *ahb; - struct amba_dev_info *ainfo = priv->dev->businfo; - - /* Find L2CACHE core from Plug&Play information */ - ahb = ainfo->info.ahb_slv; - - /* Found L2CACHE core, init private structure */ - priv->regs = (struct l2c_regs *)ahb->start[1]; - - /* Initialize L2CACHE status */ - unsigned int status = l2cache_reg_status(); - priv->ways = (status & L2C_STAT_WAY) + 1; - priv->waysize = - ((status & L2C_STAT_WAYSIZE) >> L2C_STAT_WAYSIZE_BIT) * 1024; - priv->linesize = ((status & L2C_STAT_LS)? 64 : 32); - priv->index = ((priv->waysize)/(priv->linesize)); - priv->mtrr = (status & L2C_STAT_MTRR) >> L2C_STAT_MTRR_BIT; - priv->ft_support = (status & L2C_STAT_MP) >> L2C_STAT_MP_BIT; - - /* Probe split support. */ - int split_old = 0; - int split_new = 0; - split_old = (l2cache_reg_accctrl() & L2C_ACCCTRL_SPLIT); - if (split_old){ - l2cache_reg_accctrl_split_disable(); - }else{ - l2cache_reg_accctrl_split_enable(); - } - split_new = (l2cache_reg_accctrl() & L2C_ACCCTRL_SPLIT); - if (split_old){ - l2cache_reg_accctrl_split_enable(); - }else{ - l2cache_reg_accctrl_split_disable(); - } - priv->split_support = - ((split_new ^ split_old) >> L2C_ACCCTRL_SPLIT_BIT) & 1; - - DBG("L2CACHE driver initialized\n"); - - return 0; -} - -/* Called when a core is found with the AMBA device and vendor ID - * given in l2cache_ids[]. IRQ, Console does not work here - */ -int l2cache_init1(struct drvmgr_dev *dev) -{ - int status; - struct l2cache_priv *priv; - - DBG("L2CACHE[%d] on bus %s\n", dev->minor_drv, dev->parent->dev->name); - - if (l2cachepriv) { - DBG("Driver only supports one L2CACHE core\n"); - return DRVMGR_FAIL; - } - - priv = dev->priv; - if (!priv) - return DRVMGR_NOMEM; - - priv->dev = dev; - strncpy(&priv->devname[0], "l2cache0", DEVNAME_LEN); - l2cachepriv = priv; - - /* Initialize L2CACHE Hardware */ - status = l2cache_init(priv); - if (status) { - printf("Failed to initialize l2cache driver %d\n", status); - return -1; - } - - return DRVMGR_OK; -} - -STATIC INLINE int l2cache_reg_ctrl_enable(void) -{ - struct l2cache_priv *priv = l2cachepriv; - - unsigned int ctrl = REG_READ(&priv->regs->control); - REG_WRITE(&priv->regs->control, (ctrl | L2C_CTRL_EN)); - return 0; -} - -STATIC INLINE int l2cache_reg_ctrl_disable(void) -{ - struct l2cache_priv *priv = l2cachepriv; - - unsigned int ctrl = REG_READ(&priv->regs->control); - REG_WRITE(&priv->regs->control, (ctrl & ~(L2C_CTRL_EN))); - return 0; -} - -STATIC INLINE int l2cache_reg_ctrl_repl(int policy) -{ - struct l2cache_priv *priv = l2cachepriv; - - unsigned int ctrl = REG_READ(&priv->regs->control); - REG_WRITE(&priv->regs->control, - ((ctrl & ~(L2C_CTRL_REPL)) | - ((policy << L2C_CTRL_REPL_BIT) & L2C_CTRL_REPL)) - ); - return 0; -} - -STATIC INLINE int l2cache_reg_ctrl_iway(int way) -{ - struct l2cache_priv *priv = l2cachepriv; - - unsigned int ctrl = REG_READ(&priv->regs->control); - REG_WRITE(&priv->regs->control, - ((ctrl & ~(L2C_CTRL_IWAY)) | - ((way << L2C_CTRL_IWAY_BIT) & L2C_CTRL_IWAY)) - ); - return 0; -} - -STATIC INLINE int l2cache_reg_ctrl_writep(int policy) -{ - struct l2cache_priv *priv = l2cachepriv; - - unsigned int ctrl = REG_READ(&priv->regs->control); - REG_WRITE(&priv->regs->control, - ((ctrl & ~(L2C_CTRL_WP)) | ((policy << L2C_CTRL_WP_BIT) & L2C_CTRL_WP)) - ); - return 0; -} - -STATIC INLINE int l2cache_reg_ctrl_locked_set(int locked) -{ - struct l2cache_priv *priv = l2cachepriv; - - unsigned int ctrl = REG_READ(&priv->regs->control); - ctrl = (ctrl & ~(L2C_CTRL_LOCK)); - REG_WRITE(&priv->regs->control, - ctrl | - ((locked << L2C_CTRL_LOCK_BIT) & L2C_CTRL_LOCK)); - return 0; -} - -STATIC INLINE int l2cache_reg_ctrl_edac_set(int edac) -{ - struct l2cache_priv *priv = l2cachepriv; - - unsigned int ctrl = REG_READ(&priv->regs->control); - REG_WRITE(&priv->regs->control, - (ctrl & ~(L2C_CTRL_EDAC)) | - (edac? L2C_CTRL_EDAC:0)); - return 0; -} - -STATIC INLINE unsigned int l2cache_reg_ctrl(void) -{ - struct l2cache_priv *priv = l2cachepriv; - - return REG_READ(&priv->regs->control); -} - -STATIC INLINE unsigned int l2cache_reg_status(void) -{ - struct l2cache_priv *priv = l2cachepriv; - - return REG_READ(&priv->regs->status); -} - -STATIC INLINE int l2cache_reg_mtrr_set(int index, unsigned int addr, - unsigned int mask, int options) -{ - struct l2cache_priv *priv = l2cachepriv; - - /* Set mtrr */ - addr = addr & L2C_MTRR_ADDR; - mask = (mask >> 16) & L2C_MTRR_MASK; - options = ((options & ~(L2C_MTRR_ADDR)) & ~(L2C_MTRR_MASK)); - unsigned int mtrr = 0 | addr | mask | options; - REG_WRITE(&priv->regs->mtrr[index], mtrr); - return 0; -} - -UNUSED STATIC INLINE unsigned int l2cache_reg_mtrr_get(int index) -{ - struct l2cache_priv *priv = l2cachepriv; - - return REG_READ(&priv->regs->mtrr[index]); -} - -STATIC INLINE int l2cache_reg_flushmem(unsigned int addr, int options) -{ - struct l2cache_priv *priv = l2cachepriv; - - options = (options & ~(L2C_FLUSH_ADDR)); - REG_WRITE(&priv->regs->flush_mem_addr, (addr & L2C_FLUSH_ADDR) | options); - return 0; -} - -STATIC INLINE int l2cache_reg_flushline(int way, int index, int options) -{ - struct l2cache_priv *priv = l2cachepriv; - - options = 0 | (options & (L2C_FLUSHSI_FMODE)); - REG_WRITE(&priv->regs->flush_set_index, - ((index << L2C_FLUSHSI_INDEX_BIT) & L2C_FLUSHSI_INDEX) | - ((way << L2C_FLUSHSI_WAY_BIT) & L2C_FLUSHSI_WAY) | - options - ); - return 0; -} - -STATIC INLINE int l2cache_reg_flushway(unsigned int tag, int way, int options) -{ - struct l2cache_priv *priv = l2cachepriv; - - options = (options & ~(L2C_FLUSHSI_TAG | L2C_FLUSHSI_WAY)) - | L2C_FLUSHSI_WF; - REG_WRITE(&priv->regs->flush_set_index, - (tag & L2C_FLUSHSI_TAG) | - ( (way << L2C_FLUSHSI_WAY_BIT) & L2C_FLUSHSI_WAY) | - options); - return 0; -} - -STATIC INLINE unsigned int l2cache_reg_error(void) -{ - struct l2cache_priv *priv = l2cachepriv; - - return REG_READ(&priv->regs->error_status_control); -} - -STATIC INLINE int l2cache_reg_error_reset(void) -{ - struct l2cache_priv *priv = l2cachepriv; - - unsigned int ctrl = REG_READ(&priv->regs->error_status_control); - REG_WRITE(&priv->regs->error_status_control, ctrl | L2C_ERROR_RST); - return 0; -} - -STATIC INLINE int l2cache_reg_error_irqmask(int mask) -{ - struct l2cache_priv *priv = l2cachepriv; - - unsigned int ctrl = REG_READ(&priv->regs->error_status_control); - REG_WRITE(&priv->regs->error_status_control, - (ctrl & ~(L2C_ERROR_IRQM)) | (mask & L2C_ERROR_IRQM)); - return 0; -} - -STATIC INLINE unsigned int l2cache_reg_error_addr(void) -{ - struct l2cache_priv *priv = l2cachepriv; - - return REG_READ(&priv->regs->error_addr); -} - -STATIC INLINE unsigned int l2cache_reg_scrub(void) -{ - struct l2cache_priv *priv = l2cachepriv; - - return REG_READ(&priv->regs->scrub_control_status); -} - -STATIC INLINE int l2cache_reg_scrub_enable(int delay) -{ - struct l2cache_priv *priv = l2cachepriv; - - unsigned int ctrl = REG_READ(&priv->regs->scrub_control_status); - REG_WRITE(&priv->regs->scrub_delay, - (delay << L2C_SCRUB_DEL_BIT) & L2C_SCRUB_DEL); - REG_WRITE(&priv->regs->scrub_control_status, ctrl | L2C_SCRUB_EN); - return 0; -} - -STATIC INLINE int l2cache_reg_scrub_disable(void) -{ - struct l2cache_priv *priv = l2cachepriv; - - unsigned int ctrl = REG_READ(&priv->regs->scrub_control_status); - REG_WRITE(&priv->regs->scrub_control_status, ctrl & ~(L2C_SCRUB_EN)); - return 0; -} - -STATIC INLINE int l2cache_reg_scrub_line(int way, int index) -{ - struct l2cache_priv *priv = l2cachepriv; - - REG_WRITE(&priv->regs->scrub_control_status, - ((index << L2C_SCRUB_INDEX_BIT) & L2C_SCRUB_INDEX) | - ((way << L2C_SCRUB_WAY_BIT) & L2C_SCRUB_WAY) | - L2C_SCRUB_PEN); - return 0; -} - -STATIC INLINE unsigned int l2cache_reg_scrub_delay(void) -{ - struct l2cache_priv *priv = l2cachepriv; - - return REG_READ(&priv->regs->scrub_delay); -} - -STATIC INLINE unsigned int l2cache_reg_accctrl(void){ - struct l2cache_priv *priv = l2cachepriv; - - return REG_READ(&priv->regs->access_control); -} - -STATIC INLINE int l2cache_reg_accctrl_split_disable(void) -{ - struct l2cache_priv *priv = l2cachepriv; - - /* Disable split */ - unsigned int ctrl = REG_READ(&priv->regs->access_control); - REG_WRITE(&priv->regs->access_control, (ctrl & ~(L2C_ACCCTRL_SPLIT))); - return 0; -} - -STATIC INLINE int l2cache_reg_accctrl_split_enable(void) -{ - struct l2cache_priv *priv = l2cachepriv; - - /* Enable split */ - unsigned int ctrl = REG_READ(&priv->regs->access_control); - REG_WRITE(&priv->regs->access_control, (ctrl | (L2C_ACCCTRL_SPLIT))); - return 0; -} - -STATIC INLINE int l2cache_ctrl_status(void) -{ - return ((l2cache_reg_ctrl() >> L2C_CTRL_EN_BIT) & 0x1); -} - -STATIC void l2cache_flushwait(void) -{ - /* Read any L2cache register to wait until flush is done */ - /* The L2 will block any access until the flush is done */ - /* Force read operation */ - //asm volatile ("" : : "r" (l2cache_reg_status())); - (void) l2cache_reg_status(); - return; -} - -#ifdef TEST_L2CACHE -STATIC INLINE int l2cache_reg_error_dcb(unsigned int cb) -{ - struct l2cache_priv *priv = l2cachepriv; - - REG_WRITE(&priv->regs->data_check_bit, (cb & L2C_DCB_CB)); - return 0; -} - -STATIC INLINE int l2cache_reg_error_inject(unsigned int addr) -{ - struct l2cache_priv *priv = l2cachepriv; - - REG_WRITE(&priv->regs->error_injection, - (addr & L2C_ERRINJ_ADDR) | L2C_ERRINJ_EN); - return 0; -} - -STATIC INLINE unsigned int l2cache_reg_diagtag(int way, int index) -{ - struct l2cache_priv *priv = l2cachepriv; - - int offset = (index*8 + way); - return REG_READ(&priv->regs->diag_iface_tag[offset]); -} - -STATIC INLINE unsigned int l2cache_reg_diagdata(int way, int index, int word) -{ - struct l2cache_priv *priv = l2cachepriv; - - int offset = (index*(priv->linesize/4) + way*0x20000 + word); - return REG_READ(&priv->regs->diag_iface_data[offset]); -} - -STATIC unsigned int log2int(unsigned int v) -{ - unsigned r = 0; - while (v >>= 1) { - r++; - } - return r; -} - -/* Return the index for a given addr */ -int l2cache_get_index( uint32_t addr) -{ - struct l2cache_priv * priv = l2cachepriv; - - if (priv == NULL){ - DBG("L2CACHE not initialized.\n"); - return L2CACHE_ERR_NOINIT; - } - - return (addr % priv->waysize)/(priv->linesize); -} - -/* Return the tag for a given addr */ -uint32_t l2cache_get_tag( uint32_t addr) -{ - struct l2cache_priv * priv = l2cachepriv; - - if (priv == NULL){ - DBG("L2CACHE not initialized.\n"); - return L2CACHE_ERR_NOINIT; - } - - uint32_t tmp; - int i = log2int(priv->waysize); - tmp = (addr >> i); - tmp = (tmp << i); - return tmp; -} - -int l2cache_lookup(uint32_t addr, int * way) -{ - struct l2cache_priv * priv = l2cachepriv; - int i; - struct l2cache_tag gottag; - int ret; - - if (priv == NULL){ - DBG("L2CACHE not initialized.\n"); - return L2CACHE_ERR_NOINIT; - } - - uint32_t exptag = l2cache_get_tag(addr); - int index = l2cache_get_index(addr); - - /* Check all tags in the set */ - for(i=0; i< priv->ways; i++){ - ret = l2cache_diag_tag(i, index, &gottag); - if (ret != L2CACHE_ERR_OK){ - return ret; - } - /*DBG("L2CACHE gottag: way=%d, valid=%d, tag=0x%08x.\n", - * i, gottag.valid, gottag.tag);*/ - /* Check if valid */ - if (gottag.valid){ - /* Check if they are the same */ - if (gottag.tag == exptag){ - /* HIT! */ - if (way){ - *way = i; - } - DBG("L2CACHE lookup: index=%d, tag=0x%08x HIT way=%d.\n", - index, (unsigned int) exptag, i); - return L2CACHE_HIT; - } - } - } - DBG("L2CACHE lookup: index=%d, tag=0x%08x MISS.\n", - index, (unsigned int) exptag); - /* MISS! */ - return L2CACHE_MISS; -} - -/* Diagnostic Accesses */ -#define l2cache_tag_valid(val) ((val & L2C_TAG_VALID) >> L2C_TAG_VALID_BIT) -#define l2cache_tag_dirty(val) ((val & L2C_TAG_DIRTY) >> L2C_TAG_DIRTY_BIT) -#define l2cache_tag_lru(val) ((val & L2C_TAG_LRU) >> L2C_TAG_LRU_BIT) -int l2cache_diag_tag( int way, int index, struct l2cache_tag * tag) -{ - struct l2cache_priv * priv = l2cachepriv; - - if (priv == NULL){ - DBG("L2CACHE not initialized.\n"); - return L2CACHE_ERR_NOINIT; - } - - if (way >= priv->ways){ - DBG("L2CACHE has only %d ways.\n", priv->ways); - return L2CACHE_ERR_EINVAL; - } - - if (index >= priv->index){ - DBG("L2CACHE has only %d lines.\n", priv->index); - return L2CACHE_ERR_EINVAL; - } - - unsigned int val = l2cache_reg_diagtag(way,index); - - if (tag){ - tag->tag = l2cache_get_tag(val); - tag->valid = l2cache_tag_valid(val); - tag->dirty = l2cache_tag_dirty(val); - tag->lru = l2cache_tag_lru(val); - }else{ - return L2CACHE_ERR_EINVAL; - } - return L2CACHE_ERR_OK; -} - -int l2cache_diag_line( int way, int index, struct l2cache_dataline * dataline) -{ - struct l2cache_priv * priv = l2cachepriv; - int i; - - if (priv == NULL){ - DBG("L2CACHE not initialized.\n"); - return L2CACHE_ERR_NOINIT; - } - - if (way >= priv->ways){ - DBG("L2CACHE has only %d ways.\n", priv->ways); - return L2CACHE_ERR_EINVAL; - } - - if (index >= priv->index){ - DBG("L2CACHE has only %d lines.\n", priv->index); - return L2CACHE_ERR_EINVAL; - } - - if (dataline){ - dataline->words = (priv->linesize/4); - for (i=0; i< (priv->linesize/4); i++){ - dataline->data[i] = l2cache_reg_diagdata(way,index,i); - } - }else{ - return L2CACHE_ERR_EINVAL; - } - return L2CACHE_ERR_OK; -} - -/* Inject an error on a given addr */ -int l2cache_error_inject_address( uint32_t addr, uint32_t mask) -{ - struct l2cache_priv * priv = l2cachepriv; - int word; - - if (priv == NULL){ - DBG("L2CACHE not initialized.\n"); - return L2CACHE_ERR_NOINIT; - } - - if (!priv->ft_support){ - DBG("L2CACHE does not have EDAC support.\n"); - return L2CACHE_ERR_ERROR; - } - - if (addr & 0x3){ - DBG("Address not aligned to 32-bit.\n"); - return L2CACHE_ERR_EINVAL; - } - - /* Get word index */ - word = (addr % priv->linesize)/4; - - /* Shift mask to proper word */ - mask = (mask << (7*(priv->ways - word - 1))); - - /* Write DCB mask to XOR */ - l2cache_reg_error_dcb(mask); - - /* Inject error */ - l2cache_reg_error_inject(addr); - - DBG("L2CACHE error injected in 0x%08x (0x%08x).\n", - (unsigned int) addr, (unsigned int) mask); - - return L2CACHE_ERR_OK; -} - -#endif /* TEST_L2CACHE */ - -/* L2CACHE Interrupt handler, called when there may be a L2CACHE interrupt. - */ -void l2cache_isr(void *arg) -{ - struct l2cache_priv *priv = arg; - unsigned int sts = l2cache_reg_error(); - unsigned int addr = l2cache_reg_error_addr(); - - /* Make sure that the interrupt is pending and unmasked, - * otherwise it migth have been other core - * sharing the same interrupt line */ - if ( ((sts & L2C_ERROR_IRQP) >> L2C_ERROR_IRQP_BIT) & - ((sts & L2C_ERROR_IRQM) >> L2C_ERROR_IRQM_BIT)){ - /* Reset error status */ - l2cache_reg_error_reset(); - /* Execute user IRQ (ther will always be one ISR */ - /* Give cacheline address */ - (priv->isr)(priv->isr_arg, (addr & ~(0x1f)), sts); - } -} - -/* Enable L2CACHE: - */ -int l2cache_enable(int flush) -{ - int ret; - - /* Flush checks flus parameter and INIT state */ - ret = l2cache_flush(flush); - if (ret < 0){ - return ret; - } - - l2cache_reg_ctrl_enable(); - - DBG("L2CACHE enabled\n"); - return L2CACHE_ERR_OK; -} - -/* Disable L2CACHE: - */ -int l2cache_disable(int flush) -{ - struct l2cache_priv * priv = l2cachepriv; - - if (priv == NULL){ - DBG("L2CACHE not initialized.\n"); - return L2CACHE_ERR_NOINIT; - } - - if ((flush < 0) || - (flush > - (L2CACHE_OPTIONS_FLUSH_INVALIDATE | L2CACHE_OPTIONS_FLUSH_WAIT)) - ){ - DBG("L2CACHE wrong flush option.\n"); - return L2CACHE_ERR_EINVAL; - } - - /* Flush & invalidate all cache. Also disable L2C */ - switch(flush & 0x3){ - case L2CACHE_OPTIONS_FLUSH_NONE: - l2cache_reg_ctrl_disable(); - break; - case L2CACHE_OPTIONS_FLUSH_INV_WBACK: - l2cache_reg_flushmem(0, L2C_FLUSH_FMODE_INV_WB_ALL | L2C_FLUSH_DI); - break; - case L2CACHE_OPTIONS_FLUSH_WRITEBACK: - l2cache_reg_flushmem(0, L2C_FLUSH_FMODE_WB_ALL | L2C_FLUSH_DI); - break; - case L2CACHE_OPTIONS_FLUSH_INVALIDATE: - default: - l2cache_reg_flushmem(0, L2C_FLUSH_FMODE_INV_ALL | L2C_FLUSH_DI); - break; - } - - if (flush & L2CACHE_OPTIONS_FLUSH_WAIT){ - l2cache_flushwait(); - } - - DBG("L2CACHE disabled\n"); - return L2CACHE_ERR_OK; -} - -/* Status L2CACHE: - */ -int l2cache_status(void) -{ - struct l2cache_priv * priv = l2cachepriv; - int status; - - if (priv == NULL){ - DBG("L2CACHE not initialized.\n"); - return L2CACHE_ERR_NOINIT; - } - - unsigned int ctrl = l2cache_reg_ctrl(); - int locked = (ctrl & L2C_CTRL_LOCK) >> L2C_CTRL_LOCK_BIT; - int enabled = ((ctrl & L2C_CTRL_EN) >> L2C_CTRL_EN_BIT) & 0x1; - int edac = (ctrl & L2C_CTRL_EDAC) >> L2C_CTRL_EDAC_BIT; - int repl = (ctrl & L2C_CTRL_REPL) >> L2C_CTRL_REPL_BIT; - int writep = (ctrl & L2C_CTRL_WP) >> L2C_CTRL_WP_BIT; - - unsigned int acc = l2cache_reg_accctrl(); - int split = (acc & L2C_ACCCTRL_SPLIT) >> L2C_ACCCTRL_SPLIT_BIT; - - unsigned int err = l2cache_reg_error(); - int interrupts = (err & L2C_ERROR_IRQM) >> L2C_ERROR_IRQM_BIT; - - unsigned int scr = l2cache_reg_scrub(); - int scrub = (scr & L2C_SCRUB_EN) >> L2C_SCRUB_EN_BIT; - - unsigned int dly = l2cache_reg_scrub_delay(); - int delay = (dly & L2C_SCRUB_DEL) >> L2C_SCRUB_DEL_BIT; - - status = 0| - (enabled? L2CACHE_STATUS_ENABLED: 0) | - (split? L2CACHE_STATUS_SPLIT_ENABLED: 0) | - (edac? L2CACHE_STATUS_EDAC_ENABLED: 0) | - ((repl & 0x3) << L2CACHE_STATUS_REPL_BIT) | - (writep? L2CACHE_STATUS_WRITETHROUGH: 0) | - ((locked & 0xf) << L2CACHE_STATUS_LOCK_BIT) | - ((interrupts & 0xf) << L2CACHE_STATUS_INT_BIT) | - (scrub? L2CACHE_STATUS_SCRUB_ENABLED: 0) | - ((delay & 0xffff) << L2CACHE_STATUS_SCRUB_DELAY_BIT); - - return status; -} - -/* Flush L2CACHE: - */ -int l2cache_flush(int flush) -{ - struct l2cache_priv * priv = l2cachepriv; - - if (priv == NULL){ - DBG("L2CACHE not initialized.\n"); - return L2CACHE_ERR_NOINIT; - } - - if ((flush < 0) || - (flush > - (L2CACHE_OPTIONS_FLUSH_INVALIDATE | L2CACHE_OPTIONS_FLUSH_WAIT)) - ){ - DBG("L2CACHE wrong flush option.\n"); - return L2CACHE_ERR_EINVAL; - } - - switch(flush & 0x3){ - case L2CACHE_OPTIONS_FLUSH_NONE: - break; - case L2CACHE_OPTIONS_FLUSH_INV_WBACK: - l2cache_reg_flushmem(0, L2C_FLUSH_FMODE_INV_WB_ALL); - break; - case L2CACHE_OPTIONS_FLUSH_WRITEBACK: - l2cache_reg_flushmem(0, L2C_FLUSH_FMODE_WB_ALL); - break; - case L2CACHE_OPTIONS_FLUSH_INVALIDATE: - default: - l2cache_reg_flushmem(0, L2C_FLUSH_FMODE_INV_ALL); - break; - } - - if (flush & L2CACHE_OPTIONS_FLUSH_WAIT){ - l2cache_flushwait(); - } - - DBG("L2CACHE flushed\n"); - return L2CACHE_ERR_OK; -} - -/* Flush L2CACHE address: - */ -int l2cache_flush_address(uint32_t addr, int size, int flush) -{ - struct l2cache_priv * priv = l2cachepriv; - uint32_t endaddr; - int options; - - if (priv == NULL){ - DBG("L2CACHE not initialized.\n"); - return L2CACHE_ERR_NOINIT; - } - - if ((flush < 0) || - (flush > - (L2CACHE_OPTIONS_FLUSH_INVALIDATE | L2CACHE_OPTIONS_FLUSH_WAIT)) - ){ - DBG("L2CACHE wrong flush option.\n"); - return L2CACHE_ERR_EINVAL; - } - - if (size <= 0){ - DBG("L2CACHE wrong size.\n"); - return L2CACHE_ERR_EINVAL; - } - - switch(flush & 0x3){ - case L2CACHE_OPTIONS_FLUSH_NONE: - break; - case L2CACHE_OPTIONS_FLUSH_INV_WBACK: - options=L2C_FLUSH_FMODE_INV_WB_ONE; - break; - case L2CACHE_OPTIONS_FLUSH_WRITEBACK: - options=L2C_FLUSH_FMODE_WB_ONE; - break; - case L2CACHE_OPTIONS_FLUSH_INVALIDATE: - default: - options=L2C_FLUSH_FMODE_INV_ONE; - break; - } - - if ( (flush & 0x3) == L2CACHE_OPTIONS_FLUSH_NONE){ - return L2CACHE_ERR_OK; - } - - /* Get the end address */ - endaddr = (addr + size); - - /* Start on first cacheline address */ - addr = addr - (addr % priv->linesize); - while( addr < endaddr){ - /* Flush address */ - l2cache_reg_flushmem(addr, options); - /* Update next line */ - addr += priv->linesize; - } - - if (flush & L2CACHE_OPTIONS_FLUSH_WAIT){ - l2cache_flushwait(); - } - - DBG("L2CACHE address range flushed\n"); - return L2CACHE_ERR_OK; -} - -/* Flush L2CACHE line: - */ -int l2cache_flush_line(int way, int index, int flush) -{ - struct l2cache_priv * priv = l2cachepriv; - - if (priv == NULL){ - DBG("L2CACHE not initialized.\n"); - return L2CACHE_ERR_NOINIT; - } - - if ((flush < 0) || - (flush > - (L2CACHE_OPTIONS_FLUSH_INVALIDATE | L2CACHE_OPTIONS_FLUSH_WAIT)) - ){ - DBG("L2CACHE wrong flush option.\n"); - return L2CACHE_ERR_EINVAL; - } - - if ((index < 0) || (index >= priv->index)){ - DBG("L2CACHE only has %d lines.\n", priv->index); - return L2CACHE_ERR_EINVAL; - } - - if ((way < 0 ) || (way >= priv->ways)){ - DBG("L2CACHE only has %d ways.\n", priv->ways); - return L2CACHE_ERR_EINVAL; - } - - switch(flush & 0x3){ - case L2CACHE_OPTIONS_FLUSH_NONE: - break; - case L2CACHE_OPTIONS_FLUSH_INV_WBACK: - l2cache_reg_flushline(way, index, - L2C_FLUSHSI_FMODE_SET_INV_WB_ONE); - break; - case L2CACHE_OPTIONS_FLUSH_WRITEBACK: - l2cache_reg_flushline(way, index, L2C_FLUSHSI_FMODE_SET_WB_ONE); - break; - case L2CACHE_OPTIONS_FLUSH_INVALIDATE: - default: - l2cache_reg_flushline(way, index, L2C_FLUSHSI_FMODE_SET_INV_ONE); - break; - } - - if (flush & L2CACHE_OPTIONS_FLUSH_WAIT){ - l2cache_flushwait(); - } - - DBG("L2CACHE line [%d,%d] flushed\n", way, index); - return L2CACHE_ERR_OK; -} - -/* Flush L2CACHE way: - */ -int l2cache_flush_way(int way, int flush) -{ - struct l2cache_priv * priv = l2cachepriv; - - if (priv == NULL){ - DBG("L2CACHE not initialized.\n"); - return L2CACHE_ERR_NOINIT; - } - - if ((flush < 0) || - (flush > - (L2CACHE_OPTIONS_FLUSH_INVALIDATE | L2CACHE_OPTIONS_FLUSH_WAIT)) - ){ - DBG("L2CACHE wrong flush option.\n"); - return L2CACHE_ERR_EINVAL; - } - - if ((way < 0 ) || (way >= priv->ways)){ - DBG("L2CACHE only has %d ways.\n", priv->ways); - return L2CACHE_ERR_EINVAL; - } - - switch(flush & 0x3){ - case L2CACHE_OPTIONS_FLUSH_NONE: - break; - case L2CACHE_OPTIONS_FLUSH_INVALIDATE: - l2cache_reg_flushway(0, way, L2C_FLUSHSI_FMODE_WAY_UPDATE); - break; - case L2CACHE_OPTIONS_FLUSH_WRITEBACK: - l2cache_reg_flushway(0, way, L2C_FLUSHSI_FMODE_WAY_WB); - break; - case L2CACHE_OPTIONS_FLUSH_INV_WBACK: - default: - l2cache_reg_flushway(0, way, L2C_FLUSHSI_FMODE_WAY_UPDATE_WB_ALL); - break; - } - - if (flush & L2CACHE_OPTIONS_FLUSH_WAIT){ - l2cache_flushwait(); - } - - DBG("L2CACHE way [%d] flushed\n",way); - return L2CACHE_ERR_OK; -} - -/* Fill L2CACHE way: - */ -int l2cache_fill_way(int way, uint32_t tag, int options, int flush) -{ - struct l2cache_priv * priv = l2cachepriv; - int flags; - - if (priv == NULL){ - DBG("L2CACHE not initialized.\n"); - return L2CACHE_ERR_NOINIT; - } - - if ((way < 0 ) || (way >= priv->ways)){ - DBG("L2CACHE only has %d ways.\n", priv->ways); - return L2CACHE_ERR_EINVAL; - } - - /* Check input parameters */ - if (tag & 0x000003ff){ - DBG("Only using bits 31:10 of Addr/Mask\n"); - return L2CACHE_ERR_EINVAL; - } - - /* Perform the Way-flush */ - flags = ((options & L2CACHE_OPTIONS_FETCH)? L2C_FLUSHSI_FL:0) | - ((options & L2CACHE_OPTIONS_VALID)? L2C_FLUSHSI_VB:0) | - ((options & L2CACHE_OPTIONS_DIRTY)? L2C_FLUSHSI_DB:0); - - /*DBG("L2CACHE lock way: Locked=%d, way=%d, option=0x%04x\n", - * locked, way, flags);*/ - - switch(flush & 0x3){ - case L2CACHE_OPTIONS_FLUSH_NONE: - break; - case L2CACHE_OPTIONS_FLUSH_INVALIDATE: - l2cache_reg_flushway(tag, way, - flags | L2C_FLUSHSI_FMODE_WAY_UPDATE); - break; - case L2CACHE_OPTIONS_FLUSH_WRITEBACK: - l2cache_reg_flushway(tag, way, flags | L2C_FLUSHSI_FMODE_WAY_WB); - break; - case L2CACHE_OPTIONS_FLUSH_INV_WBACK: - default: - l2cache_reg_flushway(tag, way, - flags | L2C_FLUSHSI_FMODE_WAY_UPDATE_WB_ALL); - break; - } - - if (flush & L2CACHE_OPTIONS_FLUSH_WAIT){ - l2cache_flushwait(); - } - - DBG("Way[%d] filled with Tag 0x%08x\n", way, (unsigned int) tag); - - return L2CACHE_ERR_OK; -} - -/* Lock L2CACHE way: - */ -int l2cache_lock_way(uint32_t tag, int options, int flush, int enable) -{ - struct l2cache_priv * priv = l2cachepriv; - int enabled; - int way; - int locked; - int flags; - int ret; - - if (priv == NULL){ - DBG("L2CACHE not initialized.\n"); - return L2CACHE_ERR_NOINIT; - } - - locked = L2CACHE_LOCKED_WAYS(l2cache_status()); - if (locked >= priv->ways){ - DBG("L2CACHE only has %d ways.\n", priv->ways); - return L2CACHE_ERR_TOOMANY; - } - - /* Check input parameters */ - if (tag & 0x000003ff){ - DBG("Only using bits 31:10 of Addr/Mask\n"); - return L2CACHE_ERR_EINVAL; - } - - /* Check L2C status */ - enabled = l2cache_ctrl_status(); - - /* Disable L2C */ - ret = l2cache_disable(flush); - if (ret < 0){ - return ret; - } - - /* Increase number of locked ways */ - locked++; - way = priv->ways - locked; - l2cache_reg_ctrl_locked_set(locked); - - /* Perform the Way-flush */ - flags = ((options & L2CACHE_OPTIONS_FETCH)? L2C_FLUSHSI_FL:0) | - ((options & L2CACHE_OPTIONS_VALID)? L2C_FLUSHSI_VB:0) | - ((options & L2CACHE_OPTIONS_DIRTY)? L2C_FLUSHSI_DB:0); - - /*DBG("L2CACHE lock way: Locked=%d, way=%d, option=0x%04x\n", - * locked, way, flags);*/ - - switch(flush & 0x3){ - case L2CACHE_OPTIONS_FLUSH_NONE: - break; - case L2CACHE_OPTIONS_FLUSH_INVALIDATE: - l2cache_reg_flushway(tag, way, - flags | L2C_FLUSHSI_FMODE_WAY_UPDATE); - break; - case L2CACHE_OPTIONS_FLUSH_WRITEBACK: - l2cache_reg_flushway(tag, way, flags | L2C_FLUSHSI_FMODE_WAY_WB); - break; - case L2CACHE_OPTIONS_FLUSH_INV_WBACK: - default: - l2cache_reg_flushway(tag, way, - flags | L2C_FLUSHSI_FMODE_WAY_UPDATE_WB_ALL); - break; - } - - /* Reenable L2C if required */ - switch(enable){ - case L2CACHE_OPTIONS_ENABLE: - l2cache_reg_ctrl_enable(); - break; - case L2CACHE_OPTIONS_DISABLE: - break; - case L2CACHE_OPTIONS_NONE: - default: - if (enabled) { - l2cache_reg_ctrl_enable(); - } - break; - } - - if (flush & L2CACHE_OPTIONS_FLUSH_WAIT){ - l2cache_flushwait(); - } - - DBG("Way[%d] locked with Tag 0x%08x\n", way, (unsigned int) tag); - - return L2CACHE_ERR_OK; -} - -/* Unlock L2CACHE waw: - */ -int l2cache_unlock() -{ - struct l2cache_priv * priv = l2cachepriv; - - if (priv == NULL){ - DBG("L2CACHE not initialized.\n"); - return L2CACHE_ERR_NOINIT; - } - - /* Set number of locked ways to 0*/ - l2cache_reg_ctrl_locked_set(0); - - DBG("L2CACHE ways unlocked\n"); - - return L2CACHE_ERR_OK; -} - -/* Setup L2CACHE: - * Parameters: - * -options: Can be: - */ -int l2cache_mtrr_enable(int index, uint32_t addr, uint32_t mask, int options, - int flush) -{ - struct l2cache_priv * priv = l2cachepriv; - int enabled; - int flags; - int ret; - - if (priv == NULL){ - DBG("L2CACHE not initialized.\n"); - return L2CACHE_ERR_NOINIT; - } - - if (index < 0){ - DBG("Wrong index\n"); - return L2CACHE_ERR_EINVAL; - } - - if (index >= priv->mtrr){ - DBG("Not enough MTRR registers\n"); - return L2CACHE_ERR_TOOMANY; - } - - /* Check input parameters */ - if ((addr & 0x0003ffff) || (mask & 0x0003ffff)){ - DBG("Only using bits 31:18 of Addr/Mask\n"); - return L2CACHE_ERR_EINVAL; - } - - /* Check L2C status */ - enabled = l2cache_ctrl_status(); - - /* Disable L2C */ - ret = l2cache_disable(flush); - if (ret < 0){ - return ret; - } - - /* Decode options */ - flags = 0 | - (options & L2CACHE_OPTIONS_MTRR_ACCESS_WRITETHROUGH? - L2C_MTRR_WRITETHROUGH : - L2C_MTRR_UNCACHED) | - (options & L2CACHE_OPTIONS_MTRR_WRITEPROT_ENABLE? - L2C_MTRR_WRITEPROT_ENABLE : - L2C_MTRR_WRITEPROT_DISABLE) | - L2C_MTRR_ACCESSCONTROL_ENABLE; - - /* Configure mtrr */ - l2cache_reg_mtrr_set(index, addr, mask, flags); - - /* Enable cache again (if needed) */ - if (enabled){ - l2cache_reg_ctrl_enable(); - } - - DBG("MTRR[%d] succesfully configured for 0x%08x (mask 0x%08x), " - "access=%s, wprot=%s\n", - index, (unsigned int) addr, (unsigned int) mask, - (options & L2CACHE_OPTIONS_MTRR_ACCESS_WRITETHROUGH? - "WRITETHROUGH":"UNCACHED"), - (options & L2CACHE_OPTIONS_MTRR_WRITEPROT_ENABLE? "ENABLE":"DISABLE") - ); - - return L2CACHE_ERR_OK; -} - -/* Setup L2CACHE: - * Parameters: - * -options: Can be: - */ -int l2cache_mtrr_disable(int index) -{ - struct l2cache_priv * priv = l2cachepriv; - - if (priv == NULL){ - DBG("L2CACHE not initialized.\n"); - return L2CACHE_ERR_NOINIT; - } - - if (index < 0){ - DBG("Wrong index\n"); - return L2CACHE_ERR_EINVAL; - } - - if (index >= priv->mtrr){ - DBG("Not enough MTRR registers\n"); - return L2CACHE_ERR_TOOMANY; - } - - /* Configure mtrr */ - l2cache_reg_mtrr_set(index, 0, 0, L2C_MTRR_ACCESSCONTROL_DISABLE); - - DBG("MTRR[%d] disabled\n", index); - - return L2CACHE_ERR_OK; -} - -/* Print L2CACHE status - * DEBUG function - */ -int l2cache_print(void) -{ - struct l2cache_priv * priv = l2cachepriv; - - if (priv == NULL){ - DBG("L2CACHE not initialized.\n"); - return L2CACHE_ERR_NOINIT; - } - - #ifdef DEBUG - int status = l2cache_status(); - if (status < 0){ - return status; - } - printf("L2cache: Ways:%d. Waysize:%d, Linesize:%d, Lines:%d\n" - " MTRR:%d, FT:%s, Locked:%d, Split:%s\n" - " REPL:%s, WP:%s, EDAC:%s, Enabled:%s\n" - " Scrub:%s, S-Delay:%d\n", - priv->ways, - priv->waysize, - priv->linesize, - (priv->index * priv->ways), - priv->mtrr, - (priv->ft_support? "Available":"N/A"), - L2CACHE_LOCKED_WAYS(status), - (priv->split_support? (L2CACHE_SPLIT_ENABLED(status)? - "Enabled":"Disabled"):"N/A"), - repl_names[L2CACHE_REPL(status)], - (L2CACHE_WRITETHROUGH(status)? "Write-through":"Write-back"), - (L2CACHE_EDAC_ENABLED(status)? "Enabled":"Disabled"), - (L2CACHE_ENABLED(status)? "Yes":"No"), - (L2CACHE_SCRUB_ENABLED(status)? "Enabled":"Disabled"), - L2CACHE_SCRUB_DELAY(status) - ); - if (l2cache_ctrl_status()){ - printf("L2cache enabled.\n"); - }else{ - printf("L2cache disabled.\n"); - } - #endif - return L2CACHE_ERR_OK; -} - -int l2cache_split_enable(void) -{ - struct l2cache_priv * priv = l2cachepriv; - - if (priv == NULL){ - DBG("L2CACHE not initialized.\n"); - return L2CACHE_ERR_NOINIT; - } - - if (!priv->split_support){ - DBG("L2CACHE does not have split support.\n"); - return L2CACHE_ERR_ERROR; - } - - l2cache_reg_accctrl_split_enable(); - DBG("L2CACHE split is now enabled\n"); - - return L2CACHE_ERR_OK; -} - -int l2cache_split_disable(void) -{ - struct l2cache_priv * priv = l2cachepriv; - - if (priv == NULL){ - DBG("L2CACHE not initialized.\n"); - return L2CACHE_ERR_NOINIT; - } - - if (!priv->split_support){ - DBG("L2CACHE does not have split support.\n"); - return L2CACHE_ERR_ERROR; - } - - l2cache_reg_accctrl_split_disable(); - DBG("L2CACHE split is now disabled\n"); - - return L2CACHE_ERR_OK; -} - -int l2cache_edac_enable(int flush) -{ - struct l2cache_priv * priv = l2cachepriv; - int enabled; - int ret; - - if (priv == NULL){ - DBG("L2CACHE not initialized.\n"); - return L2CACHE_ERR_NOINIT; - } - - if (!priv->ft_support){ - DBG("L2CACHE does not have EDAC support.\n"); - return L2CACHE_ERR_ERROR; - } - - /* Check that L2C is enabled */ - enabled = l2cache_ctrl_status(); - - /* Disable&Flush L2C */ - ret = l2cache_disable(flush); - if (ret < 0){ - return ret; - } - - /* Clear error register */ - l2cache_reg_error_reset(); - - /* Enable EDAC */ - l2cache_reg_ctrl_edac_set(1); - - /* Enable cache again */ - if (enabled){ - l2cache_reg_ctrl_enable(); - } - - DBG("L2CACHE EDAC is now enabled\n"); - - return L2CACHE_ERR_OK; -} - -int l2cache_edac_disable(int flush) -{ - struct l2cache_priv * priv = l2cachepriv; - int enabled; - int ret; - - if (priv == NULL){ - DBG("L2CACHE not initialized.\n"); - return L2CACHE_ERR_NOINIT; - } - - if (!priv->ft_support){ - DBG("L2CACHE does not have EDAC support.\n"); - return L2CACHE_ERR_ERROR; - } - - /* Check that L2C is enabled */ - enabled = l2cache_ctrl_status(); - - /* Disable&Flush L2C */ - ret = l2cache_disable(flush); - if (ret < 0){ - return ret; - } - - /* Disable EDAC */ - l2cache_reg_ctrl_edac_set(0); - - /* Clear error register */ - l2cache_reg_error_reset(); - - /* Enable cache again */ - if (enabled){ - l2cache_reg_ctrl_enable(); - } - - DBG("L2CACHE EDAC is now disabled\n"); - - return L2CACHE_ERR_OK; -} - -int l2cache_scrub_enable(int delay) -{ - struct l2cache_priv * priv = l2cachepriv; - - if (priv == NULL){ - DBG("L2CACHE not initialized.\n"); - return L2CACHE_ERR_NOINIT; - } - - if (!priv->ft_support){ - DBG("L2CACHE does not have EDAC support.\n"); - return L2CACHE_ERR_ERROR; - } - - /* Enable Scrub */ - l2cache_reg_scrub_enable(delay); - - DBG("L2CACHE Scrub is now enabled\n"); - - return L2CACHE_ERR_OK; -} - -int l2cache_scrub_disable(void) -{ - struct l2cache_priv * priv = l2cachepriv; - - if (priv == NULL){ - DBG("L2CACHE not initialized.\n"); - return L2CACHE_ERR_NOINIT; - } - - if (!priv->ft_support){ - DBG("L2CACHE does not have EDAC support.\n"); - return L2CACHE_ERR_ERROR; - } - - /* Disable Scrub */ - l2cache_reg_scrub_disable(); - - DBG("L2CACHE Scrub is now disabled\n"); - - return L2CACHE_ERR_OK; -} - -int l2cache_scrub_line(int way, int index) -{ - struct l2cache_priv * priv = l2cachepriv; - unsigned int scrub; - - if (priv == NULL){ - DBG("L2CACHE not initialized.\n"); - return L2CACHE_ERR_NOINIT; - } - - if (!priv->ft_support){ - DBG("L2CACHE does not have EDAC support.\n"); - return L2CACHE_ERR_ERROR; - } - - if ((index < 0) || (index >= priv->index)){ - DBG("L2CACHE only has %d lines.\n", priv->index); - return L2CACHE_ERR_EINVAL; - } - - if ((way < 0) || (way >= priv->ways)){ - DBG("L2CACHE only has %d ways.\n", priv->ways); - return L2CACHE_ERR_EINVAL; - } - - /* Check pending bit */ - scrub = l2cache_reg_scrub(); - if ( (scrub & L2C_SCRUB_PEN) || (scrub & L2C_SCRUB_EN) ){ - DBG("L2CACHE already scrubbing.\n"); - return L2CACHE_ERR_ERROR; - } - - /* Scrub line */ - l2cache_reg_scrub_line(way, index); - - DBG("L2CACHE Scrub line [%d,%d]\n",way,index); - - return L2CACHE_ERR_OK; -} - -int l2cache_writethrough(int flush) -{ - struct l2cache_priv * priv = l2cachepriv; - int enabled; - int ret; - - if (priv == NULL){ - DBG("L2CACHE not initialized.\n"); - return L2CACHE_ERR_NOINIT; - } - - /* Check that L2C is enabled */ - enabled = l2cache_ctrl_status(); - - /* Disable&Flush L2C */ - ret = l2cache_disable(flush); - if (ret < 0){ - return ret; - } - - /* Configure writethrough */ - l2cache_reg_ctrl_writep(1); - - /* Enable cache again */ - if (enabled){ - l2cache_reg_ctrl_enable(); - } - - DBG("L2CACHE now is writethrough\n"); - - return L2CACHE_ERR_OK; -} - -int l2cache_writeback(int flush) -{ - struct l2cache_priv * priv = l2cachepriv; - int enabled; - int ret; - - if (priv == NULL){ - DBG("L2CACHE not initialized.\n"); - return L2CACHE_ERR_NOINIT; - } - - /* Check that L2C is enabled */ - enabled = l2cache_ctrl_status(); - - /* Disable&Flush L2C */ - ret = l2cache_disable(flush); - if (ret < 0){ - return ret; - } - - /* Configure writeback */ - l2cache_reg_ctrl_writep(0); - - /* Enable cache again */ - if (enabled){ - l2cache_reg_ctrl_enable(); - } - - DBG("L2CACHE now is writeback\n"); - - return L2CACHE_ERR_OK; -} - -int l2cache_replacement(int options, int flush) -{ - struct l2cache_priv * priv = l2cachepriv; - int enabled; - int ret; - int way; - - if (priv == NULL){ - DBG("L2CACHE not initialized.\n"); - return L2CACHE_ERR_NOINIT; - } - - /* Check that L2C is enabled */ - enabled = l2cache_ctrl_status(); - - /* Disable&Flush L2C */ - ret = l2cache_disable(flush); - if (ret < 0){ - return ret; - } - - if ( (options & 0x3) == L2CACHE_OPTIONS_REPL_MASTERIDX_IDX){ - /* Set iway */ - way = (options >> 2) & 0x3; - l2cache_reg_ctrl_iway(way); - } - - /* Configure writeback */ - l2cache_reg_ctrl_repl(options & 0x3); - - /* Enable cache again */ - if (enabled){ - l2cache_reg_ctrl_enable(); - } - - DBG("L2CACHE replacement set to %d\n", (options & 0x3)); - - return L2CACHE_ERR_OK; - -} - -int l2cache_isr_register(l2cache_isr_t isr, void * arg, int options) -{ - struct l2cache_priv *priv = l2cachepriv; - unsigned int mask; - - if (priv == NULL){ - DBG("L2CACHE not initialized.\n"); - return L2CACHE_ERR_NOINIT; - } - - if (isr == NULL){ - DBG("L2CACHE wrong isr.\n"); - return L2CACHE_ERR_EINVAL; - } - - /* Get mask */ - mask = 0 | - ((options & L2CACHE_INTERRUPT_BACKENDERROR)? L2C_ERROR_IRQM_BCKEND:0) | - ((options & L2CACHE_INTERRUPT_WPROTHIT)? L2C_ERROR_IRQM_WPROT:0) | - ((options & L2CACHE_INTERRUPT_CORRERROR)? L2C_ERROR_IRQM_CORR:0) | - ((options & L2CACHE_INTERRUPT_UNCORRERROR)? L2C_ERROR_IRQM_UNCORR:0); - - /* Clear previous interrupts and mask them*/ - l2cache_reg_error_reset(); - l2cache_reg_error_irqmask(0); - - /* First time registering an ISR */ - if (priv->isr == NULL){ - /* Install and Enable L2CACHE interrupt handler */ - drvmgr_interrupt_register(priv->dev, 0, priv->devname, l2cache_isr, - priv); - } - - /* Install user ISR */ - priv->isr=isr; - priv->isr_arg=arg; - - /* Now it is safe to unmask interrupts */ - l2cache_reg_error_irqmask(mask); - - return L2CACHE_ERR_OK; -} - -int l2cache_isr_unregister(void) -{ - struct l2cache_priv *priv = l2cachepriv; - - if (priv == NULL){ - DBG("L2CACHE not initialized.\n"); - return L2CACHE_ERR_NOINIT; - } - - if (priv->isr == NULL){ - DBG("L2CACHE wrong isr.\n"); - return L2CACHE_ERR_EINVAL; - } - - /* Clear previous interrupts and mask them*/ - l2cache_reg_error_reset(); - l2cache_reg_error_irqmask(0); - - /* Uninstall and disable L2CACHE interrupt handler */ - drvmgr_interrupt_unregister(priv->dev, 0, l2cache_isr, priv); - - /* Uninstall user ISR */ - priv->isr=NULL; - priv->isr_arg=NULL; - - return L2CACHE_ERR_OK; -} - -int l2cache_interrupt_unmask(int options) -{ - struct l2cache_priv *priv = l2cachepriv; - unsigned int mask, irq; - - if (priv == NULL){ - DBG("L2CACHE not initialized.\n"); - return L2CACHE_ERR_NOINIT; - } - - if (priv->isr == NULL){ - DBG("L2CACHE wrong isr.\n"); - return L2CACHE_ERR_EINVAL; - } - - /* Unmask interrupts in L2CACHE */ - mask = 0 | - ((options & L2CACHE_INTERRUPT_BACKENDERROR)? L2C_ERROR_IRQM_BCKEND:0) | - ((options & L2CACHE_INTERRUPT_WPROTHIT)? L2C_ERROR_IRQM_WPROT:0) | - ((options & L2CACHE_INTERRUPT_CORRERROR)? L2C_ERROR_IRQM_CORR:0) | - ((options & L2CACHE_INTERRUPT_UNCORRERROR)? L2C_ERROR_IRQM_UNCORR:0); - - /* Clear previous interrupts*/ - l2cache_reg_error_reset(); - - /* Get previous mask */ - irq = ((l2cache_reg_error() & L2C_ERROR_IRQM) >> L2C_ERROR_IRQM_BIT); - - /* Set new mask */ - l2cache_reg_error_irqmask(irq | mask); - - return L2CACHE_ERR_OK; -} - -int l2cache_interrupt_mask(int options) -{ - struct l2cache_priv *priv = l2cachepriv; - unsigned int mask, irq; - - if (priv == NULL){ - DBG("L2CACHE not initialized.\n"); - return L2CACHE_ERR_NOINIT; - } - - /* Mask interrupts in L2CACHE */ - mask = 0 | - ((options & L2CACHE_INTERRUPT_BACKENDERROR)? L2C_ERROR_IRQM_BCKEND:0) | - ((options & L2CACHE_INTERRUPT_WPROTHIT)? L2C_ERROR_IRQM_WPROT:0) | - ((options & L2CACHE_INTERRUPT_CORRERROR)? L2C_ERROR_IRQM_CORR:0) | - ((options & L2CACHE_INTERRUPT_UNCORRERROR)? L2C_ERROR_IRQM_UNCORR:0); - - /* Clear previous interrupts */ - l2cache_reg_error_reset(); - - /* Get previous mask */ - irq = ((l2cache_reg_error() & L2C_ERROR_IRQM) >> L2C_ERROR_IRQM_BIT); - - /* Set new mask */ - l2cache_reg_error_irqmask(irq & ~(mask)); - - return L2CACHE_ERR_OK; -} - -int l2cache_error_status(uint32_t * addr, uint32_t * status) -{ - struct l2cache_priv *priv = l2cachepriv; - unsigned int sts; - unsigned int erraddr; - - if (priv == NULL){ - DBG("L2CACHE not initialized.\n"); - return L2CACHE_ERR_NOINIT; - } - - /* Get error register */ - sts = priv->regs->error_status_control; - erraddr = priv->regs->error_addr; - - /* Check if an error occurred */ - if (sts & L2C_ERROR_VALID){ - /* Reset error register */ - l2cache_reg_error_reset(); - - /* Update user variables if needed */ - if (addr != NULL){ - *addr = (erraddr & ~(0x1f)); - } - - if(status != NULL){ - *status = sts; - } - - /* Return status */ - if (sts & L2C_ERROR_MULTI){ - return L2CACHE_STATUS_MULTIPLEERRORS; - }else{ - return L2CACHE_STATUS_NEWERROR; - } - }else{ - /* Return status */ - return L2CACHE_STATUS_NOERROR; - } -} diff --git a/c/src/lib/libbsp/sparc/shared/mem/mctrl.c b/c/src/lib/libbsp/sparc/shared/mem/mctrl.c deleted file mode 100644 index 42c81c45cc..0000000000 --- a/c/src/lib/libbsp/sparc/shared/mem/mctrl.c +++ /dev/null @@ -1,212 +0,0 @@ -/* Memory Controller driver (FTMTRL, MCTRL) - * - * COPYRIGHT (c) 2008. - * Cobham Gaisler AB. - * - * This file contains the driver for the MCTRL memory controller. - * The driver sets the memory configuration registers (MCFG1, MCFG2, MCFG3) - * during driver initialization - * - * 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. - */ - -/******************* Driver manager interface ***********************/ -#include -#include -#include - -#include -#include - -#include - -#define MEMSET(priv, start, c, length) memset((void *)start, c, length) - -#define DBG(args...) -/*#define DBG(args...) printk(args)*/ - -struct mctrl_regs { - unsigned int mcfg[8]; -}; - -struct mctrl_priv; - -struct mctrl_ops { - void (*mcfg_set)(struct mctrl_priv *priv, int index, void *regs, unsigned int regval); -}; - -struct mctrl_priv { - struct drvmgr_dev *dev; - void *regs; - unsigned int mcfg[8]; /* The wanted memory configuration */ - unsigned int configured; /* Determines what mcfgs was configured by user */ - struct mctrl_ops *ops; /* Operation may depend on hardware */ -}; - -static int mctrl_init1(struct drvmgr_dev *dev); -static int mctrl_remove(struct drvmgr_dev *dev); - -/* Standard MCFG registers */ -static void mctrl_set_std(struct mctrl_priv *priv, int index, void *regs, unsigned int regval); - -struct mctrl_ops std_mctrl_ops = -{ - mctrl_set_std -}; - -struct drvmgr_drv_ops mctrl_ops = -{ - .init = {mctrl_init1, NULL, NULL, NULL}, - .remove = mctrl_remove, - .info = NULL -}; - -struct amba_dev_id mctrl_ids[] = -{ - {VENDOR_ESA, ESA_MCTRL}, - {VENDOR_GAISLER, GAISLER_FTMCTRL}, - {VENDOR_GAISLER, GAISLER_FTSRCTRL}, - {0, 0} /* Mark end of table */ -}; - -struct amba_drv_info mctrl_drv_info = -{ - { - DRVMGR_OBJ_DRV, /* Driver */ - NULL, /* Next driver */ - NULL, /* Device list */ - DRIVER_AMBAPP_MCTRL_ID, /* Driver ID */ - "MCTRL_DRV", /* Driver Name */ - DRVMGR_BUS_TYPE_AMBAPP, /* Bus Type */ - &mctrl_ops, - NULL, /* Funcs */ - 0, /* No devices yet */ - 0, - }, - &mctrl_ids[0] -}; - -void mctrl_register_drv (void) -{ - DBG("Registering MCTRL driver\n"); - drvmgr_drv_register(&mctrl_drv_info.general); -} - -static int mctrl_init1(struct drvmgr_dev *dev) -{ - struct mctrl_priv *priv; - struct amba_dev_info *ambadev; - struct ambapp_core *pnpinfo; - int i; - char res_name[16]; - union drvmgr_key_value *value; - unsigned int start, length; - - DBG("MCTRL[%d] on bus %s\n", dev->minor_drv, dev->parent->dev->name); - priv = dev->priv = malloc(sizeof(struct mctrl_priv)); - if ( !priv ) - return DRVMGR_NOMEM; - memset(priv, 0, sizeof(*priv)); - priv->dev = dev; - - /* Get device information from AMBA PnP information */ - ambadev = (struct amba_dev_info *)priv->dev->businfo; - if ( ambadev == NULL ) { - return DRVMGR_FAIL; - } - pnpinfo = &ambadev->info; - if ( pnpinfo->apb_slv == NULL ) { - /* LEON2 PnP systems are missing the APB interface */ - priv->regs = (void *)0x80000000; - } else { - priv->regs = (void *)pnpinfo->apb_slv->start; - } - - /* Depending on Hardware selection write/read routines */ - switch ( pnpinfo->vendor ) { - case VENDOR_ESA: - switch ( pnpinfo->device ) { - case ESA_MCTRL: - default: - priv->ops = &std_mctrl_ops; - } - break; - - case VENDOR_GAISLER: - switch ( pnpinfo->device ) { - case GAISLER_FTMCTRL: - case GAISLER_FTSRCTRL: - default: - priv->ops = &std_mctrl_ops; - } - break; - - default: - priv->ops = &std_mctrl_ops; - break; - } - - /* Find user configuration from bus resources */ - priv->configured = 0; - strcpy(res_name, "mcfgX"); - for(i=0; i<8; i++) { - res_name[4] = '1' + i; - value = drvmgr_dev_key_get(priv->dev, res_name, DRVMGR_KT_INT); - if ( value ) { - priv->mcfg[i] = value->i; - priv->configured |= (1<configured & (1<mcfg[i]); - priv->ops->mcfg_set(priv, i, priv->regs, priv->mcfg[i]); - } - } - - /* Wash memory partitions if user wants */ - for (i=0; i<9; i++) { - strcpy(res_name, "washXStart"); - res_name[4] = '0' + i; - value = drvmgr_dev_key_get(priv->dev, res_name, DRVMGR_KT_INT); - if ( value ) { - start = value->i; - strcpy(res_name, "washXLength"); - res_name[4] = '0' + i; - value = drvmgr_dev_key_get(priv->dev, res_name, DRVMGR_KT_INT); - if ( value ) { - length = value->i; - - if ( length > 0 ) { - DBG("MCTRL: Washing 0x%08x-0x%08x\n", start, start+length-1); - - MEMSET(priv, (void *)start, 0, length); - } - } - } - } - - return DRVMGR_OK; -} - -static int mctrl_remove(struct drvmgr_dev *dev) -{ - /* Nothing to be done */ - DBG("Removing %s\n", dev->name); - return DRVMGR_OK; -} - -/* Standard Operations */ -static void mctrl_set_std(struct mctrl_priv *priv, int index, void *regs, unsigned int regval) -{ - struct mctrl_regs *pregs = regs; - - /* Store new value */ - pregs->mcfg[index] = regval; -} diff --git a/c/src/lib/libbsp/sparc/shared/net/README b/c/src/lib/libbsp/sparc/shared/net/README deleted file mode 100644 index 3ef086f223..0000000000 --- a/c/src/lib/libbsp/sparc/shared/net/README +++ /dev/null @@ -1,7 +0,0 @@ -A non Driver Manager GRETH driver is located in libchip/network/greth.c. This -version requires the driver manager. - -network_interface_add is used to assign IP/NETMASK and MAC address to -GRETH interfaces dynamically according to in which order devices are -registered. The function takes the settings from the user defined -interface_configs[] array, defined in the project configuration. diff --git a/c/src/lib/libbsp/sparc/shared/net/greth.c b/c/src/lib/libbsp/sparc/shared/net/greth.c deleted file mode 100644 index eafcb9947a..0000000000 --- a/c/src/lib/libbsp/sparc/shared/net/greth.c +++ /dev/null @@ -1,1568 +0,0 @@ -/* - * Gaisler Research ethernet MAC driver - * adapted from Opencores driver by Marko Isomaki - * - * 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. - * - * - * 2008-12-10, Converted to driver manager and added support for - * multiple GRETH cores. - * 2007-09-07, Ported GBIT support from 4.6.5 - */ - -#define __INSIDE_RTEMS_BSD_TCPIP_STACK__ - -#include -#define _KERNEL -#define CPU_U32_FIX -#include - -#ifdef GRETH_SUPPORTED - -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -#include -#include - -#include -#include -#include -#include -#include - -/* map via rtems_interrupt_lock_* API: */ -#define SPIN_DECLARE(lock) RTEMS_INTERRUPT_LOCK_MEMBER(lock) -#define SPIN_INIT(lock, name) rtems_interrupt_lock_initialize(lock, name) -#define SPIN_LOCK(lock, level) rtems_interrupt_lock_acquire_isr(lock, &level) -#define SPIN_LOCK_IRQ(lock, level) rtems_interrupt_lock_acquire(lock, &level) -#define SPIN_UNLOCK(lock, level) rtems_interrupt_lock_release_isr(lock, &level) -#define SPIN_UNLOCK_IRQ(lock, level) rtems_interrupt_lock_release(lock, &level) -#define SPIN_IRQFLAGS(k) rtems_interrupt_lock_context k -#define SPIN_ISR_IRQFLAGS(k) SPIN_IRQFLAGS(k) - -#ifdef malloc -#undef malloc -#endif -#ifdef free -#undef free -#endif - -#if defined(__m68k__) -extern m68k_isr_entry set_vector( rtems_isr_entry, rtems_vector_number, int ); -#else -extern rtems_isr_entry set_vector( rtems_isr_entry, rtems_vector_number, int ); -#endif - - -/* #define GRETH_DEBUG */ - -#ifdef GRETH_DEBUG -#define DBG(args...) printk(args) -#else -#define DBG(args...) -#endif - -/* #define GRETH_DEBUG_MII */ - -#ifdef GRETH_DEBUG_MII -#define MIIDBG(args...) printk(args) -#else -#define MIIDBG(args...) -#endif - -#ifdef CPU_U32_FIX -extern void ipalign(struct mbuf *m); -#endif - -/* Used when reading from memory written by GRETH DMA unit */ -#ifndef GRETH_MEM_LOAD -#define GRETH_MEM_LOAD(addr) (*(volatile unsigned int *)(addr)) -#endif - -/* - * Number of OCs supported by this driver - */ -#define NOCDRIVER 1 - -/* - * Receive buffer size -- Allow for a full ethernet packet including CRC - */ -#define RBUF_SIZE 1518 - -#define ET_MINLEN 64 /* minimum message length */ - -/* - * RTEMS event used by interrupt handler to signal driver tasks. - * This must not be any of the events used by the network task synchronization. - */ -#define INTERRUPT_EVENT RTEMS_EVENT_1 - -/* - * RTEMS event used to start transmit daemon. - * This must not be the same as INTERRUPT_EVENT. - */ -#define START_TRANSMIT_EVENT RTEMS_EVENT_2 - - /* event to send when tx buffers become available */ -#define GRETH_TX_WAIT_EVENT RTEMS_EVENT_3 - -#if (MCLBYTES < RBUF_SIZE) -# error "Driver must have MCLBYTES > RBUF_SIZE" -#endif - -/* 4s Autonegotiation Timeout */ -#ifndef GRETH_AUTONEGO_TIMEOUT_MS -#define GRETH_AUTONEGO_TIMEOUT_MS 4000 -#endif -const struct timespec greth_tan = { - GRETH_AUTONEGO_TIMEOUT_MS/1000, - (GRETH_AUTONEGO_TIMEOUT_MS % 1000) * 1000000 -}; - -/* For optimizing the autonegotiation time */ -#define GRETH_AUTONEGO_PRINT_TIME - -/* Ethernet buffer descriptor */ - -typedef struct _greth_rxtxdesc { - volatile uint32_t ctrl; /* Length and status */ - uint32_t *addr; /* Buffer pointer */ -} greth_rxtxdesc; - - -/* - * Per-device data - */ -struct greth_softc -{ - - struct arpcom arpcom; - struct drvmgr_dev *dev; /* Driver manager device */ - char devName[32]; - - greth_regs *regs; - int minor; - int phyaddr; /* PHY Address configured by user (or -1 to autodetect) */ - unsigned int edcl_dis; - int greth_rst; - - int acceptBroadcast; - rtems_id daemonTid; - - unsigned int tx_ptr; - unsigned int tx_dptr; - unsigned int tx_cnt; - unsigned int rx_ptr; - unsigned int txbufs; - unsigned int rxbufs; - greth_rxtxdesc *txdesc; - greth_rxtxdesc *rxdesc; - unsigned int txdesc_remote; - unsigned int rxdesc_remote; - struct mbuf **rxmbuf; - struct mbuf **txmbuf; - rtems_vector_number vector; - - /* TX descriptor interrupt generation */ - int tx_int_gen; - int tx_int_gen_cur; - struct mbuf *next_tx_mbuf; - int max_fragsize; - - /*Status*/ - struct phy_device_info phydev; - int phy_read_access; - int phy_write_access; - int fd; - int sp; - int gb; - int gbit_mac; - int auto_neg; - unsigned int advmodes; /* advertise ethernet speed modes. 0 = all modes. */ - struct timespec auto_neg_time; - - /* - * Statistics - */ - unsigned long rxInterrupts; - - unsigned long rxPackets; - unsigned long rxLengthError; - unsigned long rxNonOctet; - unsigned long rxBadCRC; - unsigned long rxOverrun; - - unsigned long txInterrupts; - - unsigned long txDeferred; - unsigned long txHeartbeat; - unsigned long txLateCollision; - unsigned long txRetryLimit; - unsigned long txUnderrun; - - /* Spin-lock ISR protection */ - SPIN_DECLARE(devlock); -}; - -int greth_process_tx_gbit(struct greth_softc *sc); -int greth_process_tx(struct greth_softc *sc); - -static char *almalloc(int sz, int alignment) -{ - char *tmp; - tmp = calloc(1, sz + (alignment-1)); - tmp = (char *) (((int)tmp+alignment) & ~(alignment -1)); - return(tmp); -} - -/* GRETH interrupt handler */ - -static void greth_interrupt (void *arg) -{ - uint32_t status; - uint32_t ctrl; - rtems_event_set events = 0; - struct greth_softc *greth = arg; - SPIN_ISR_IRQFLAGS(flags); - - /* read and clear interrupt cause */ - status = greth->regs->status; - greth->regs->status = status; - - SPIN_LOCK(&greth->devlock, flags); - ctrl = greth->regs->ctrl; - - /* Frame received? */ - if ((ctrl & GRETH_CTRL_RXIRQ) && (status & (GRETH_STATUS_RXERR | GRETH_STATUS_RXIRQ))) - { - greth->rxInterrupts++; - /* Stop RX-Error and RX-Packet interrupts */ - ctrl &= ~GRETH_CTRL_RXIRQ; - events |= INTERRUPT_EVENT; - } - - if ( (ctrl & GRETH_CTRL_TXIRQ) && (status & (GRETH_STATUS_TXERR | GRETH_STATUS_TXIRQ)) ) - { - greth->txInterrupts++; - ctrl &= ~GRETH_CTRL_TXIRQ; - events |= GRETH_TX_WAIT_EVENT; - } - - /* Clear interrupt sources */ - greth->regs->ctrl = ctrl; - SPIN_UNLOCK(&greth->devlock, flags); - - /* Send the event(s) */ - if ( events ) - rtems_bsdnet_event_send(greth->daemonTid, events); -} - -static uint32_t read_mii(struct greth_softc *sc, uint32_t phy_addr, uint32_t reg_addr) -{ - sc->phy_read_access++; - while (sc->regs->mdio_ctrl & GRETH_MDIO_BUSY) {} - sc->regs->mdio_ctrl = (phy_addr << 11) | (reg_addr << 6) | GRETH_MDIO_READ; - while (sc->regs->mdio_ctrl & GRETH_MDIO_BUSY) {} - if (!(sc->regs->mdio_ctrl & GRETH_MDIO_LINKFAIL)) { - MIIDBG("greth%d: mii read[%d] OK to %" PRIx32 ".%" PRIx32 - " (0x%08" PRIx32 ",0x%08" PRIx32 ")\n", - sc->minor, sc->phy_read_access, phy_addr, reg_addr, - sc->regs->ctrl, sc->regs->mdio_ctrl); - return((sc->regs->mdio_ctrl >> 16) & 0xFFFF); - } else { - printf("greth%d: mii read[%d] failed to %" PRIx32 ".%" PRIx32 - " (0x%08" PRIx32 ",0x%08" PRIx32 ")\n", - sc->minor, sc->phy_read_access, phy_addr, reg_addr, - sc->regs->ctrl, sc->regs->mdio_ctrl); - return (0xffff); - } -} - -static void write_mii(struct greth_softc *sc, uint32_t phy_addr, uint32_t reg_addr, uint32_t data) -{ - sc->phy_write_access++; - while (sc->regs->mdio_ctrl & GRETH_MDIO_BUSY) {} - sc->regs->mdio_ctrl = - ((data & 0xFFFF) << 16) | (phy_addr << 11) | (reg_addr << 6) | GRETH_MDIO_WRITE; - while (sc->regs->mdio_ctrl & GRETH_MDIO_BUSY) {} - if (!(sc->regs->mdio_ctrl & GRETH_MDIO_LINKFAIL)) { - MIIDBG("greth%d: mii write[%d] OK to to %" PRIx32 ".%" PRIx32 - "(0x%08" PRIx32 ",0x%08" PRIx32 ")\n", - sc->minor, sc->phy_write_access, phy_addr, reg_addr, - sc->regs->ctrl, sc->regs->mdio_ctrl); - } else { - printf("greth%d: mii write[%d] failed to to %" PRIx32 ".%" PRIx32 - " (0x%08" PRIx32 ",0x%08" PRIx32 ")\n", - sc->minor, sc->phy_write_access, phy_addr, reg_addr, - sc->regs->ctrl, sc->regs->mdio_ctrl); - } -} - -static void print_init_info(struct greth_softc *sc) -{ - printf("greth: driver attached\n"); - if ( sc->auto_neg == -1 ){ - printf("Auto negotiation timed out. Selecting default config\n"); - } - printf("**** PHY ****\n"); - printf("Vendor: %x Device: %x Revision: %d\n",sc->phydev.vendor, sc->phydev.device, sc->phydev.rev); - printf("Current Operating Mode: "); - if (sc->gb) { - printf("1000 Mbit "); - } else if (sc->sp) { - printf("100 Mbit "); - } else { - printf("10 Mbit "); - } - if (sc->fd) { - printf("Full Duplex\n"); - } else { - printf("Half Duplex\n"); - } -#ifdef GRETH_AUTONEGO_PRINT_TIME - if ( sc->auto_neg ) { - printf("Autonegotiation Time: %ldms\n", sc->auto_neg_time.tv_sec * 1000 + - sc->auto_neg_time.tv_nsec / 1000000); - } -#endif -} - - -/* - * Initialize the ethernet hardware - */ -static void -greth_initialize_hardware (struct greth_softc *sc) -{ - struct mbuf *m; - int i; - int phyaddr; - int phyctrl; - int phystatus; - int tmp1; - int tmp2; - struct timespec tstart, tnow; - greth_regs *regs; - unsigned int advmodes, speed; - - regs = sc->regs; - - /* Reset the controller. */ - sc->rxInterrupts = 0; - sc->rxPackets = 0; - - if (sc->greth_rst) { - /* Reset ON */ - regs->ctrl = GRETH_CTRL_RST | GRETH_CTRL_DD | GRETH_CTRL_ED; - for (i = 0; i<100 && (regs->ctrl & GRETH_CTRL_RST); i++) - ; - speed = 0; /* probe mode below */ - } else { - /* inherit EDCL mode for now */ - speed = sc->regs->ctrl & (GRETH_CTRL_GB|GRETH_CTRL_SP|GRETH_CTRL_FULLD); - } - /* Reset OFF and RX/TX DMA OFF. SW do PHY Init */ - regs->ctrl = GRETH_CTRL_DD | GRETH_CTRL_ED | speed; - - /* Check if mac is gbit capable*/ - sc->gbit_mac = (regs->ctrl >> 27) & 1; - - /* Get the phy address which assumed to have been set - correctly with the reset value in hardware*/ - if ( sc->phyaddr == -1 ) { - phyaddr = (regs->mdio_ctrl >> 11) & 0x1F; - } else { - phyaddr = sc->phyaddr; - } - sc->phy_read_access = 0; - sc->phy_write_access = 0; - - /* As I understand the PHY comes back to a good default state after - * Power-down or Reset, so we do both just in case. Power-down bit should - * be cleared. - * Wait for old reset (if asserted by boot loader) to complete, otherwise - * power-down instruction might not have any effect. - */ - while (read_mii(sc, phyaddr, 0) & 0x8000) {} - write_mii(sc, phyaddr, 0, 0x0800); /* Power-down */ - write_mii(sc, phyaddr, 0, 0x0000); /* Power-Up */ - write_mii(sc, phyaddr, 0, 0x8000); /* Reset */ - - /* We wait about 30ms */ - rtems_task_wake_after(rtems_clock_get_ticks_per_second()/32); - - /* Wait for reset to complete and get default values */ - while ((phyctrl = read_mii(sc, phyaddr, 0)) & 0x8000) {} - - /* Set up PHY advertising modes for auto-negotiation */ - advmodes = sc->advmodes; - if (advmodes == 0) - advmodes = GRETH_ADV_ALL; - if (!sc->gbit_mac) - advmodes &= ~(GRETH_ADV_1000_FD | GRETH_ADV_1000_HD); - - /* Enable/Disable GBit auto-neg advetisement so that the link partner - * know that we have/haven't GBit capability. The MAC may not support - * Gbit even though PHY does... - */ - phystatus = read_mii(sc, phyaddr, 1); - if (phystatus & 0x0100) { - tmp1 = read_mii(sc, phyaddr, 9); - tmp1 &= ~0x300; - if (advmodes & GRETH_ADV_1000_FD) - tmp1 |= 0x200; - if (advmodes & GRETH_ADV_1000_HD) - tmp1 |= 0x100; - write_mii(sc, phyaddr, 9, tmp1); - } - - /* Optionally limit the 10/100 modes as configured by user */ - tmp1 = read_mii(sc, phyaddr, 4); - tmp1 &= ~0x1e0; - if (advmodes & GRETH_ADV_100_FD) - tmp1 |= 0x100; - if (advmodes & GRETH_ADV_100_HD) - tmp1 |= 0x080; - if (advmodes & GRETH_ADV_10_FD) - tmp1 |= 0x040; - if (advmodes & GRETH_ADV_10_HD) - tmp1 |= 0x020; - write_mii(sc, phyaddr, 4, tmp1); - - /* If autonegotiation implemented we start it */ - if (phystatus & 0x0008) { - write_mii(sc, phyaddr, 0, phyctrl | 0x1200); - phyctrl = read_mii(sc, phyaddr, 0); - } - - /* Check if PHY is autoneg capable and then determine operating mode, - otherwise force it to 10 Mbit halfduplex */ - sc->gb = 0; - sc->fd = 0; - sc->sp = 0; - sc->auto_neg = 0; - _Timespec_Set_to_zero(&sc->auto_neg_time); - if ((phyctrl >> 12) & 1) { - /*wait for auto negotiation to complete*/ - sc->auto_neg = 1; - if (rtems_clock_get_uptime(&tstart) != RTEMS_SUCCESSFUL) - printk("rtems_clock_get_uptime failed\n"); - while (!(((phystatus = read_mii(sc, phyaddr, 1)) >> 5) & 1)) { - if (rtems_clock_get_uptime(&tnow) != RTEMS_SUCCESSFUL) - printk("rtems_clock_get_uptime failed\n"); - _Timespec_Subtract(&tstart, &tnow, &sc->auto_neg_time); - if (_Timespec_Greater_than(&sc->auto_neg_time, &greth_tan)) { - sc->auto_neg = -1; /* Failed */ - tmp1 = read_mii(sc, phyaddr, 0); - sc->gb = ((phyctrl >> 6) & 1) && !((phyctrl >> 13) & 1); - sc->sp = !((phyctrl >> 6) & 1) && ((phyctrl >> 13) & 1); - sc->fd = (phyctrl >> 8) & 1; - goto auto_neg_done; - } - /* Wait about 30ms, time is PHY dependent */ - rtems_task_wake_after(rtems_clock_get_ticks_per_second()/32); - } - sc->phydev.adv = read_mii(sc, phyaddr, 4); - sc->phydev.part = read_mii(sc, phyaddr, 5); - if ((phystatus >> 8) & 1) { - sc->phydev.extadv = read_mii(sc, phyaddr, 9); - sc->phydev.extpart = read_mii(sc, phyaddr, 10); - if ( (sc->phydev.extadv & GRETH_MII_EXTADV_1000HD) && - (sc->phydev.extpart & GRETH_MII_EXTPRT_1000HD)) { - sc->gb = 1; - sc->fd = 0; - } - if ( (sc->phydev.extadv & GRETH_MII_EXTADV_1000FD) && - (sc->phydev.extpart & GRETH_MII_EXTPRT_1000FD)) { - sc->gb = 1; - sc->fd = 1; - } - } - if ((sc->gb == 0) || ((sc->gb == 1) && (sc->gbit_mac == 0))) { - if ( (sc->phydev.adv & GRETH_MII_100TXFD) && - (sc->phydev.part & GRETH_MII_100TXFD)) { - sc->sp = 1; - sc->fd = 1; - } else if ( (sc->phydev.adv & GRETH_MII_100TXHD) && - (sc->phydev.part & GRETH_MII_100TXHD)) { - sc->sp = 1; - sc->fd = 0; - } else if ( (sc->phydev.adv & GRETH_MII_10FD) && - (sc->phydev.part & GRETH_MII_10FD)) { - sc->fd = 1; - } - } - } -auto_neg_done: - sc->phydev.vendor = 0; - sc->phydev.device = 0; - sc->phydev.rev = 0; - phystatus = read_mii(sc, phyaddr, 1); - - /* Read out PHY info if extended registers are available */ - if (phystatus & 1) { - tmp1 = read_mii(sc, phyaddr, 2); - tmp2 = read_mii(sc, phyaddr, 3); - - sc->phydev.vendor = (tmp1 << 6) | ((tmp2 >> 10) & 0x3F); - sc->phydev.rev = tmp2 & 0xF; - sc->phydev.device = (tmp2 >> 4) & 0x3F; - } - - /* Force to 10 mbit half duplex if the 10/100 MAC is used with a 1000 PHY */ - if (((sc->gb) && !(sc->gbit_mac)) || !((phyctrl >> 12) & 1)) { - write_mii(sc, phyaddr, 0, sc->sp << 13); - - /* check if marvell 88EE1111 PHY. Needs special reset handling */ - if ((phystatus & 1) && (sc->phydev.vendor == 0x005043) && - (sc->phydev.device == 0x0C)) - write_mii(sc, phyaddr, 0, 0x8000); - - sc->gb = 0; - sc->sp = 0; - sc->fd = 0; - } - while ((read_mii(sc, phyaddr, 0)) & 0x8000) {} - - if (sc->greth_rst) { - /* Reset ON */ - regs->ctrl = GRETH_CTRL_RST | GRETH_CTRL_DD | GRETH_CTRL_ED; - for (i = 0; i < 100 && (regs->ctrl & GRETH_CTRL_RST); i++) - ; - } - /* Reset OFF. Set mode matching PHY settings. */ - speed = (sc->gb << 8) | (sc->sp << 7) | (sc->fd << 4); - regs->ctrl = GRETH_CTRL_DD | sc->edcl_dis | speed; - - /* Initialize rx/tx descriptor table pointers. Due to alignment we - * always allocate maximum table size. - */ - sc->txdesc = (greth_rxtxdesc *) almalloc(0x800, 0x400); - sc->rxdesc = (greth_rxtxdesc *) &sc->txdesc[128]; - sc->tx_ptr = 0; - sc->tx_dptr = 0; - sc->tx_cnt = 0; - sc->rx_ptr = 0; - - /* Translate the Descriptor DMA table base address into an address that - * the GRETH core can understand - */ - drvmgr_translate_check( - sc->dev, - CPUMEM_TO_DMA, - (void *)sc->txdesc, - (void **)&sc->txdesc_remote, - 0x800); - sc->rxdesc_remote = sc->txdesc_remote + 0x400; - regs->txdesc = (int) sc->txdesc_remote; - regs->rxdesc = (int) sc->rxdesc_remote; - - sc->rxmbuf = calloc(sc->rxbufs, sizeof(*sc->rxmbuf)); - sc->txmbuf = calloc(sc->txbufs, sizeof(*sc->txmbuf)); - - for (i = 0; i < sc->txbufs; i++) - { - sc->txdesc[i].ctrl = 0; - if (!(sc->gbit_mac)) { - drvmgr_translate_check( - sc->dev, - CPUMEM_TO_DMA, - (void *)malloc(GRETH_MAXBUF_LEN), - (void **)&sc->txdesc[i].addr, - GRETH_MAXBUF_LEN); - } -#ifdef GRETH_DEBUG - /* printf("TXBUF: %08x\n", (int) sc->txdesc[i].addr); */ -#endif - } - for (i = 0; i < sc->rxbufs; i++) - { - MGETHDR (m, M_WAIT, MT_DATA); - MCLGET (m, M_WAIT); - if (sc->gbit_mac) - m->m_data += 2; - m->m_pkthdr.rcvif = &sc->arpcom.ac_if; - sc->rxmbuf[i] = m; - drvmgr_translate_check( - sc->dev, - CPUMEM_TO_DMA, - (void *)mtod(m, uint32_t *), - (void **)&sc->rxdesc[i].addr, - GRETH_MAXBUF_LEN); - sc->rxdesc[i].ctrl = GRETH_RXD_ENABLE | GRETH_RXD_IRQ; -#ifdef GRETH_DEBUG -/* printf("RXBUF: %08x\n", (int) sc->rxdesc[i].addr); */ -#endif - } - sc->rxdesc[sc->rxbufs - 1].ctrl |= GRETH_RXD_WRAP; - - /* set ethernet address. */ - regs->mac_addr_msb = - sc->arpcom.ac_enaddr[0] << 8 | sc->arpcom.ac_enaddr[1]; - regs->mac_addr_lsb = - sc->arpcom.ac_enaddr[2] << 24 | sc->arpcom.ac_enaddr[3] << 16 | - sc->arpcom.ac_enaddr[4] << 8 | sc->arpcom.ac_enaddr[5]; - - if ( sc->rxbufs < 10 ) { - sc->tx_int_gen = sc->tx_int_gen_cur = 1; - }else{ - sc->tx_int_gen = sc->tx_int_gen_cur = sc->txbufs/2; - } - sc->next_tx_mbuf = NULL; - - if ( !sc->gbit_mac ) - sc->max_fragsize = 1; - - /* clear all pending interrupts */ - regs->status = 0xffffffff; - - /* install interrupt handler */ - drvmgr_interrupt_register(sc->dev, 0, "greth", greth_interrupt, sc); - - regs->ctrl |= GRETH_CTRL_RXEN | GRETH_CTRL_RXIRQ; - - print_init_info(sc); -} - -#ifdef CPU_U32_FIX - -/* - * Routine to align the received packet so that the ip header - * is on a 32-bit boundary. Necessary for cpu's that do not - * allow unaligned loads and stores and when the 32-bit DMA - * mode is used. - * - * Transfers are done on word basis to avoid possibly slow byte - * and half-word writes. - */ - -void ipalign(struct mbuf *m) -{ - unsigned int *first, *last, data; - unsigned int tmp = 0; - - if ((((int) m->m_data) & 2) && (m->m_len)) { - last = (unsigned int *) ((((int) m->m_data) + m->m_len + 8) & ~3); - first = (unsigned int *) (((int) m->m_data) & ~3); - /* tmp = *first << 16; */ - asm volatile (" lda [%1] 1, %0\n" : "=r"(tmp) : "r"(first) ); - tmp = tmp << 16; - first++; - do { - /* When snooping is not available the LDA instruction must be used - * to avoid the cache to return an illegal value. - ** Load with forced cache miss - * data = *first; - */ - asm volatile (" lda [%1] 1, %0\n" : "=r"(data) : "r"(first) ); - *first = tmp | (data >> 16); - tmp = data << 16; - first++; - } while (first <= last); - - m->m_data = (caddr_t)(((int) m->m_data) + 2); - } -} -#endif - -static void -greth_Daemon (void *arg) -{ - struct ether_header *eh; - struct greth_softc *dp = (struct greth_softc *) arg; - struct ifnet *ifp = &dp->arpcom.ac_if; - struct mbuf *m; - unsigned int len, len_status, bad; - rtems_event_set events; - SPIN_IRQFLAGS(flags); - int first; - int tmp; - unsigned int addr; - - for (;;) - { - rtems_bsdnet_event_receive (INTERRUPT_EVENT | GRETH_TX_WAIT_EVENT, - RTEMS_WAIT | RTEMS_EVENT_ANY, - RTEMS_NO_TIMEOUT, &events); - - if ( events & GRETH_TX_WAIT_EVENT ){ - /* TX interrupt. - * We only end up here when all TX descriptors has been used, - * and - */ - if ( dp->gbit_mac ) - greth_process_tx_gbit(dp); - else - greth_process_tx(dp); - - /* If we didn't get a RX interrupt we don't process it */ - if ( (events & INTERRUPT_EVENT) == 0 ) - continue; - } - - -#ifdef GRETH_ETH_DEBUG - printf ("r\n"); -#endif - first=1; - /* Scan for Received packets */ -again: - while (!((len_status = - GRETH_MEM_LOAD(&dp->rxdesc[dp->rx_ptr].ctrl)) & GRETH_RXD_ENABLE)) - { - bad = 0; - if (len_status & GRETH_RXD_TOOLONG) - { - dp->rxLengthError++; - bad = 1; - } - if (len_status & GRETH_RXD_DRIBBLE) - { - dp->rxNonOctet++; - bad = 1; - } - if (len_status & GRETH_RXD_CRCERR) - { - dp->rxBadCRC++; - bad = 1; - } - if (len_status & GRETH_RXD_OVERRUN) - { - dp->rxOverrun++; - bad = 1; - } - if (len_status & GRETH_RXD_LENERR) - { - dp->rxLengthError++; - bad = 1; - } - if (!bad) - { - /* pass on the packet in the receive buffer */ - len = len_status & 0x7FF; - m = dp->rxmbuf[dp->rx_ptr]; -#ifdef GRETH_DEBUG - int i; - printf("RX: 0x%08x, Len: %d : ", (int) m->m_data, len); - for (i=0; im_data[i] >> 4) & 0x0ff, m->m_data[i] & 0x0ff); - printf("\n"); -#endif - m->m_len = m->m_pkthdr.len = - len - sizeof (struct ether_header); - - eh = mtod (m, struct ether_header *); - - m->m_data += sizeof (struct ether_header); -#ifdef CPU_U32_FIX - if(!dp->gbit_mac) { - /* OVERRIDE CACHED ETHERNET HEADER FOR NON-SNOOPING SYSTEMS */ - addr = (unsigned int)eh; - asm volatile (" lda [%1] 1, %0\n" : "=r"(tmp) : "r"(addr) ); - addr+=4; - asm volatile (" lda [%1] 1, %0\n" : "=r"(tmp) : "r"(addr) ); - addr+=4; - asm volatile (" lda [%1] 1, %0\n" : "=r"(tmp) : "r"(addr) ); - addr+=4; - asm volatile (" lda [%1] 1, %0\n" : "=r"(tmp) : "r"(addr) ); - - ipalign(m); /* Align packet on 32-bit boundary */ - } -#endif -/* - if(!(dp->gbit_mac) && !CPU_SPARC_HAS_SNOOPING) { - rtems_cache_invalidate_entire_data(); - } -*/ - ether_input (ifp, eh, m); - MGETHDR (m, M_WAIT, MT_DATA); - MCLGET (m, M_WAIT); - if (dp->gbit_mac) - m->m_data += 2; - dp->rxmbuf[dp->rx_ptr] = m; - m->m_pkthdr.rcvif = ifp; - drvmgr_translate_check( - dp->dev, - CPUMEM_TO_DMA, - (void *)mtod (m, uint32_t *), - (void **)&dp->rxdesc[dp->rx_ptr].addr, - GRETH_MAXBUF_LEN); - dp->rxPackets++; - } - if (dp->rx_ptr == dp->rxbufs - 1) { - dp->rxdesc[dp->rx_ptr].ctrl = GRETH_RXD_ENABLE | GRETH_RXD_IRQ | GRETH_RXD_WRAP; - } else { - dp->rxdesc[dp->rx_ptr].ctrl = GRETH_RXD_ENABLE | GRETH_RXD_IRQ; - } - SPIN_LOCK_IRQ(&dp->devlock, flags); - dp->regs->ctrl |= GRETH_CTRL_RXEN; - SPIN_UNLOCK_IRQ(&dp->devlock, flags); - dp->rx_ptr = (dp->rx_ptr + 1) % dp->rxbufs; - } - - /* Always scan twice to avoid deadlock */ - if ( first ){ - first=0; - SPIN_LOCK_IRQ(&dp->devlock, flags); - dp->regs->ctrl |= GRETH_CTRL_RXIRQ; - SPIN_UNLOCK_IRQ(&dp->devlock, flags); - goto again; - } - - } -} - -static int -sendpacket (struct ifnet *ifp, struct mbuf *m) -{ - struct greth_softc *dp = ifp->if_softc; - unsigned char *temp; - struct mbuf *n; - unsigned int len; - SPIN_IRQFLAGS(flags); - - /* - * Is there a free descriptor available? - */ - if (GRETH_MEM_LOAD(&dp->txdesc[dp->tx_ptr].ctrl) & GRETH_TXD_ENABLE){ - /* No. */ - return 1; - } - - /* Remember head of chain */ - n = m; - - len = 0; - temp = (unsigned char *) GRETH_MEM_LOAD(&dp->txdesc[dp->tx_ptr].addr); - drvmgr_translate(dp->dev, CPUMEM_FROM_DMA, (void *)temp, (void **)&temp); -#ifdef GRETH_DEBUG - printf("TXD: 0x%08x : BUF: 0x%08x\n", (int) m->m_data, (int) temp); -#endif - for (;;) - { -#ifdef GRETH_DEBUG - int i; - printf("MBUF: 0x%08x : ", (int) m->m_data); - for (i=0;im_len;i++) - printf("%x%x", (m->m_data[i] >> 4) & 0x0ff, m->m_data[i] & 0x0ff); - printf("\n"); -#endif - len += m->m_len; - if (len <= RBUF_SIZE) - memcpy ((void *) temp, (char *) m->m_data, m->m_len); - temp += m->m_len; - if ((m = m->m_next) == NULL) - break; - } - - m_freem (n); - - /* don't send long packets */ - - if (len <= GRETH_MAXBUF_LEN) { - if (dp->tx_ptr < dp->txbufs-1) { - dp->txdesc[dp->tx_ptr].ctrl = GRETH_TXD_ENABLE | len; - } else { - dp->txdesc[dp->tx_ptr].ctrl = - GRETH_TXD_WRAP | GRETH_TXD_ENABLE | len; - } - dp->tx_ptr = (dp->tx_ptr + 1) % dp->txbufs; - SPIN_LOCK_IRQ(&dp->devlock, flags); - dp->regs->ctrl = dp->regs->ctrl | GRETH_CTRL_TXEN; - SPIN_UNLOCK_IRQ(&dp->devlock, flags); - - } - - return 0; -} - - -static int -sendpacket_gbit (struct ifnet *ifp, struct mbuf *m) -{ - struct greth_softc *dp = ifp->if_softc; - unsigned int len; - - unsigned int ctrl; - int frags; - struct mbuf *mtmp; - int int_en; - SPIN_IRQFLAGS(flags); - - len = 0; -#ifdef GRETH_DEBUG - printf("TXD: 0x%08x\n", (int) m->m_data); -#endif - /* Get number of fragments too see if we have enough - * resources. - */ - frags=1; - mtmp=m; - while(mtmp->m_next){ - frags++; - mtmp = mtmp->m_next; - } - - if ( frags > dp->max_fragsize ) - dp->max_fragsize = frags; - - if ( frags > dp->txbufs ){ - printf("GRETH: MBUF-chain cannot be sent. Increase descriptor count.\n"); - return -1; - } - - if ( frags > (dp->txbufs-dp->tx_cnt) ){ - /* Return number of fragments */ - return frags; - } - - - /* Enable interrupt from descriptor every tx_int_gen - * descriptor. Typically every 16 descriptor. This - * is only to reduce the number of interrupts during - * heavy load. - */ - dp->tx_int_gen_cur-=frags; - if ( dp->tx_int_gen_cur <= 0 ){ - dp->tx_int_gen_cur = dp->tx_int_gen; - int_en = GRETH_TXD_IRQ; - }else{ - int_en = 0; - } - - /* At this stage we know that enough descriptors are available */ - for (;;) - { - -#ifdef GRETH_DEBUG - int i; - printf("MBUF: 0x%08x, Len: %d : ", (int) m->m_data, m->m_len); - for (i=0; im_len; i++) - printf("%x%x", (m->m_data[i] >> 4) & 0x0ff, m->m_data[i] & 0x0ff); - printf("\n"); -#endif - len += m->m_len; - drvmgr_translate_check( - dp->dev, - CPUMEM_TO_DMA, - (void *)(uint32_t *)m->m_data, - (void **)&dp->txdesc[dp->tx_ptr].addr, - m->m_len); - - /* Wrap around? */ - if (dp->tx_ptr < dp->txbufs-1) { - ctrl = GRETH_TXD_ENABLE; - }else{ - ctrl = GRETH_TXD_ENABLE | GRETH_TXD_WRAP; - } - - /* Enable Descriptor */ - if ((m->m_next) == NULL) { - dp->txdesc[dp->tx_ptr].ctrl = ctrl | int_en | m->m_len; - break; - }else{ - dp->txdesc[dp->tx_ptr].ctrl = GRETH_TXD_MORE | ctrl | int_en | m->m_len; - } - - /* Next */ - dp->txmbuf[dp->tx_ptr] = m; - dp->tx_ptr = (dp->tx_ptr + 1) % dp->txbufs; - dp->tx_cnt++; - m = m->m_next; - } - dp->txmbuf[dp->tx_ptr] = m; - dp->tx_ptr = (dp->tx_ptr + 1) % dp->txbufs; - dp->tx_cnt++; - - /* Tell Hardware about newly enabled descriptor */ - SPIN_LOCK_IRQ(&dp->devlock, flags); - dp->regs->ctrl = dp->regs->ctrl | GRETH_CTRL_TXEN; - SPIN_UNLOCK_IRQ(&dp->devlock, flags); - - return 0; -} - -int greth_process_tx_gbit(struct greth_softc *sc) -{ - struct ifnet *ifp = &sc->arpcom.ac_if; - struct mbuf *m; - SPIN_IRQFLAGS(flags); - int first=1; - - /* - * Send packets till queue is empty - */ - for (;;){ - /* Reap Sent packets */ - while((sc->tx_cnt > 0) && !(GRETH_MEM_LOAD(&sc->txdesc[sc->tx_dptr].ctrl) & GRETH_TXD_ENABLE)) { - m_free(sc->txmbuf[sc->tx_dptr]); - sc->tx_dptr = (sc->tx_dptr + 1) % sc->txbufs; - sc->tx_cnt--; - } - - if ( sc->next_tx_mbuf ){ - /* Get packet we tried but faild to transmit last time */ - m = sc->next_tx_mbuf; - sc->next_tx_mbuf = NULL; /* Mark packet taken */ - }else{ - /* - * Get the next mbuf chain to transmit from Stack. - */ - IF_DEQUEUE (&ifp->if_snd, m); - if (!m){ - /* Hardware has sent all schedule packets, this - * makes the stack enter at greth_start next time - * a packet is to be sent. - */ - ifp->if_flags &= ~IFF_OACTIVE; - break; - } - } - - /* Are there free descriptors available? */ - /* Try to send packet, if it a negative number is returned. */ - if ( (sc->tx_cnt >= sc->txbufs) || sendpacket_gbit(ifp, m) ){ - /* Not enough resources */ - - /* Since we have taken the mbuf out of the "send chain" - * we must remember to use that next time we come back. - * or else we have dropped a packet. - */ - sc->next_tx_mbuf = m; - - /* Not enough resources, enable interrupt for transmissions - * this way we will be informed when more TX-descriptors are - * available. - */ - if ( first ){ - first = 0; - SPIN_LOCK_IRQ(&sc->devlock, flags); - ifp->if_flags |= IFF_OACTIVE; - sc->regs->ctrl |= GRETH_CTRL_TXIRQ; - SPIN_UNLOCK_IRQ(&sc->devlock, flags); - - /* We must check again to be sure that we didn't - * miss an interrupt (if a packet was sent just before - * enabling interrupts) - */ - continue; - } - - return -1; - }else{ - /* Sent Ok, proceed to process more packets if available */ - } - } - return 0; -} - -int greth_process_tx(struct greth_softc *sc) -{ - struct ifnet *ifp = &sc->arpcom.ac_if; - struct mbuf *m; - SPIN_IRQFLAGS(flags); - int first=1; - - /* - * Send packets till queue is empty - */ - for (;;){ - if ( sc->next_tx_mbuf ){ - /* Get packet we tried but failed to transmit last time */ - m = sc->next_tx_mbuf; - sc->next_tx_mbuf = NULL; /* Mark packet taken */ - }else{ - /* - * Get the next mbuf chain to transmit from Stack. - */ - IF_DEQUEUE (&ifp->if_snd, m); - if (!m){ - /* Hardware has sent all schedule packets, this - * makes the stack enter at greth_start next time - * a packet is to be sent. - */ - ifp->if_flags &= ~IFF_OACTIVE; - break; - } - } - - /* Try to send packet, failed if it a non-zero number is returned. */ - if ( sendpacket(ifp, m) ){ - /* Not enough resources */ - - /* Since we have taken the mbuf out of the "send chain" - * we must remember to use that next time we come back. - * or else we have dropped a packet. - */ - sc->next_tx_mbuf = m; - - /* Not enough resources, enable interrupt for transmissions - * this way we will be informed when more TX-descriptors are - * available. - */ - if ( first ){ - first = 0; - SPIN_LOCK_IRQ(&sc->devlock, flags); - ifp->if_flags |= IFF_OACTIVE; - sc->regs->ctrl |= GRETH_CTRL_TXIRQ; - SPIN_UNLOCK_IRQ(&sc->devlock, flags); - - /* We must check again to be sure that we didn't - * miss an interrupt (if a packet was sent just before - * enabling interrupts) - */ - continue; - } - - return -1; - }else{ - /* Sent Ok, proceed to process more packets if available */ - } - } - return 0; -} - -static void -greth_start (struct ifnet *ifp) -{ - struct greth_softc *sc = ifp->if_softc; - - if ( ifp->if_flags & IFF_OACTIVE ) - return; - - if ( sc->gbit_mac ){ - /* No use trying to handle this if we are waiting on GRETH - * to send the previously scheduled packets. - */ - - greth_process_tx_gbit(sc); - }else{ - greth_process_tx(sc); - } - -} - -/* - * Initialize and start the device - */ -static void -greth_init (void *arg) -{ - struct greth_softc *sc = arg; - struct ifnet *ifp = &sc->arpcom.ac_if; - char name[4] = {'E', 'T', 'H', '0'}; - - if (sc->daemonTid == 0) - { - /* - * Start driver tasks - */ - name[3] += sc->minor; - sc->daemonTid = rtems_bsdnet_newproc (name, 4096, - greth_Daemon, sc); - - /* - * Set up GRETH hardware - */ - greth_initialize_hardware (sc); - } - - /* - * Tell the world that we're running. - */ - ifp->if_flags |= IFF_RUNNING; -} - -/* - * Stop the device - */ -static void -greth_stop (struct greth_softc *sc) -{ - struct ifnet *ifp = &sc->arpcom.ac_if; - SPIN_IRQFLAGS(flags); - unsigned int speed; - - SPIN_LOCK_IRQ(&sc->devlock, flags); - ifp->if_flags &= ~IFF_RUNNING; - - speed = sc->regs->ctrl & (GRETH_CTRL_GB | GRETH_CTRL_SP | GRETH_CTRL_FULLD); - - /* RX/TX OFF */ - sc->regs->ctrl = GRETH_CTRL_DD | GRETH_CTRL_ED | speed; - /* Reset ON */ - if (sc->greth_rst) - sc->regs->ctrl = GRETH_CTRL_RST | GRETH_CTRL_DD | GRETH_CTRL_ED | speed; - /* Reset OFF and restore link settings previously detected if any */ - sc->regs->ctrl = GRETH_CTRL_DD | sc->edcl_dis | speed; - SPIN_UNLOCK_IRQ(&sc->devlock, flags); - - sc->next_tx_mbuf = NULL; -} - - -/* - * Show interface statistics - */ -static void -greth_stats (struct greth_softc *sc) -{ - printf (" Rx Interrupts:%-8lu", sc->rxInterrupts); - printf (" Rx Packets:%-8lu", sc->rxPackets); - printf (" Length:%-8lu", sc->rxLengthError); - printf (" Non-octet:%-8lu\n", sc->rxNonOctet); - printf (" Bad CRC:%-8lu", sc->rxBadCRC); - printf (" Overrun:%-8lu", sc->rxOverrun); - printf (" Tx Interrupts:%-8lu", sc->txInterrupts); - printf (" Maximal Frags:%-8d", sc->max_fragsize); - printf (" GBIT MAC:%-8d", sc->gbit_mac); -} - -/* - * Driver ioctl handler - */ -static int -greth_ioctl (struct ifnet *ifp, ioctl_command_t command, caddr_t data) -{ - struct greth_softc *sc = ifp->if_softc; - int error = 0; - - switch (command) - { - case SIOCGIFADDR: - case SIOCSIFADDR: - ether_ioctl (ifp, command, data); - break; - - case SIOCSIFFLAGS: - switch (ifp->if_flags & (IFF_UP | IFF_RUNNING)) - { - case IFF_RUNNING: - greth_stop (sc); - break; - - case IFF_UP: - greth_init (sc); - break; - - case IFF_UP | IFF_RUNNING: - greth_stop (sc); - greth_init (sc); - break; - default: - break; - } - break; - - case SIO_RTEMS_SHOW_STATS: - greth_stats (sc); - break; - - /* - * FIXME: All sorts of multicast commands need to be added here! - */ - default: - error = EINVAL; - break; - } - - return error; -} - -/* - * Attach an GRETH driver to the system - */ -static int -greth_interface_driver_attach ( - struct rtems_bsdnet_ifconfig *config, - int attach - ) -{ - struct greth_softc *sc; - struct ifnet *ifp; - int mtu; - int unitNumber; - char *unitName; - - /* parse driver name */ - if ((unitNumber = rtems_bsdnet_parse_driver_name (config, &unitName)) < 0) - return 0; - - sc = config->drv_ctrl; - ifp = &sc->arpcom.ac_if; -#ifdef GRETH_DEBUG - printf("GRETH[%d]: %s, sc %p, dev %p on %s\n", unitNumber, config->ip_address, sc, sc->dev, sc->dev->parent->dev->name); -#endif - if (config->hardware_address) - { - memcpy (sc->arpcom.ac_enaddr, config->hardware_address, - ETHER_ADDR_LEN); - } - else - { - memset (sc->arpcom.ac_enaddr, 0x08, ETHER_ADDR_LEN); - } - - if (config->mtu) - mtu = config->mtu; - else - mtu = ETHERMTU; - - sc->acceptBroadcast = !config->ignore_broadcast; - - /* - * Set up network interface values - */ - ifp->if_softc = sc; - ifp->if_unit = unitNumber; - ifp->if_name = unitName; - ifp->if_mtu = mtu; - ifp->if_init = greth_init; - ifp->if_ioctl = greth_ioctl; - ifp->if_start = greth_start; - ifp->if_output = ether_output; - ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX; - if (ifp->if_snd.ifq_maxlen == 0) - ifp->if_snd.ifq_maxlen = ifqmaxlen; - - /* - * Attach the interface - */ - if_attach (ifp); - ether_ifattach (ifp); - -#ifdef GRETH_DEBUG - printf ("GRETH : driver has been attached\n"); -#endif - return 1; -} - -/******************* Driver manager interface ***********************/ - -/* Driver prototypes */ -int greth_register_io(rtems_device_major_number *m); -int greth_device_init(struct greth_softc *sc); -int network_interface_add(struct rtems_bsdnet_ifconfig *interface); - -#ifdef GRETH_INFO_AVAIL -static int greth_info( - struct drvmgr_dev *dev, - void (*print_line)(void *p, char *str), - void *p, int argc, char *argv[]); -#define GRETH_INFO_FUNC greth_info -#else -#define GRETH_INFO_FUNC NULL -#endif - -int greth_init2(struct drvmgr_dev *dev); -int greth_init3(struct drvmgr_dev *dev); - -struct drvmgr_drv_ops greth_ops = -{ - .init = - { - NULL, - greth_init2, - greth_init3, - NULL - }, - .remove = NULL, - .info = GRETH_INFO_FUNC, -}; - -struct amba_dev_id greth_ids[] = -{ - {VENDOR_GAISLER, GAISLER_ETHMAC}, - {0, 0} /* Mark end of table */ -}; - -struct amba_drv_info greth_drv_info = -{ - { - DRVMGR_OBJ_DRV, /* Driver */ - NULL, /* Next driver */ - NULL, /* Device list */ - DRIVER_AMBAPP_GAISLER_GRETH_ID, /* Driver ID */ - "GRETH_DRV", /* Driver Name */ - DRVMGR_BUS_TYPE_AMBAPP, /* Bus Type */ - &greth_ops, - NULL, /* Funcs */ - 0, /* No devices yet */ - 0, - }, - &greth_ids[0] -}; - -void greth_register_drv (void) -{ - DBG("Registering GRETH driver\n"); - drvmgr_drv_register(&greth_drv_info.general); -} - -int greth_init2(struct drvmgr_dev *dev) -{ - struct greth_softc *priv; - - DBG("GRETH[%d] on bus %s\n", dev->minor_drv, dev->parent->dev->name); - priv = dev->priv = malloc(sizeof(struct greth_softc)); - if ( !priv ) - return DRVMGR_NOMEM; - memset(priv, 0, sizeof(*priv)); - priv->dev = dev; - - /* This core will not find other cores, so we wait for init3() */ - - return DRVMGR_OK; -} - -int greth_init3(struct drvmgr_dev *dev) -{ - struct greth_softc *sc; - struct rtems_bsdnet_ifconfig *ifp; - rtems_status_code status; - - sc = dev->priv; - sprintf(sc->devName, "gr_eth%d", (dev->minor_drv+1)); - - /* Init GRETH device */ - if ( greth_device_init(sc) ) { - printk("GRETH: Failed to init device\n"); - return DRVMGR_FAIL; - } - - /* Initialize Spin-lock for GRSPW Device. This is to protect - * CTRL and DMACTRL registers from ISR. - */ - SPIN_INIT(&sc->devlock, sc->devName); - - /* Register GRETH device as an Network interface */ - ifp = malloc(sizeof(struct rtems_bsdnet_ifconfig)); - memset(ifp, 0, sizeof(*ifp)); - - ifp->name = sc->devName; - ifp->drv_ctrl = sc; - ifp->attach = greth_interface_driver_attach; - - status = network_interface_add(ifp); - if (status != 0) { - return DRVMGR_FAIL; - } - - return DRVMGR_OK; -} - -int greth_device_init(struct greth_softc *sc) -{ - struct amba_dev_info *ambadev; - struct ambapp_core *pnpinfo; - union drvmgr_key_value *value; - unsigned int speed; - - /* Get device information from AMBA PnP information */ - ambadev = (struct amba_dev_info *)sc->dev->businfo; - if ( ambadev == NULL ) { - return -1; - } - pnpinfo = &ambadev->info; - sc->regs = (greth_regs *)pnpinfo->apb_slv->start; - sc->minor = sc->dev->minor_drv; - sc->greth_rst = 1; - - /* Remember EDCL enabled/disable state before reset */ - sc->edcl_dis = sc->regs->ctrl & GRETH_CTRL_ED; - - /* Default is to inherit EDCL Disable bit from HW. User can force En/Dis */ - value = drvmgr_dev_key_get(sc->dev, "edclDis", DRVMGR_KT_INT); - if ( value ) { - /* Force EDCL mode. Has an effect later when GRETH+PHY is initialized */ - if (value->i > 0) { - sc->edcl_dis = GRETH_CTRL_ED; - } else { - /* Default to avoid soft-reset the GRETH when EDCL is forced */ - sc->edcl_dis = 0; - sc->greth_rst = 0; - } - } - - /* let user control soft-reset of GRETH (for debug) */ - value = drvmgr_dev_key_get(sc->dev, "soft-reset", DRVMGR_KT_INT); - if ( value) { - sc->greth_rst = value->i ? 1 : 0; - } - - /* clear control register and reset NIC and keep current speed modes. - * This should be done as quick as possible during startup, this is to - * stop DMA transfers after a reboot. - * - * When EDCL is forced enabled reset is skipped, disabling RX/TX DMA is - * is enough during debug. - */ - speed = sc->regs->ctrl & (GRETH_CTRL_GB | GRETH_CTRL_SP | GRETH_CTRL_FULLD); - sc->regs->ctrl = GRETH_CTRL_DD | GRETH_CTRL_ED | speed; - if (sc->greth_rst) - sc->regs->ctrl = GRETH_CTRL_RST | GRETH_CTRL_DD | GRETH_CTRL_ED | speed; - sc->regs->ctrl = GRETH_CTRL_DD | sc->edcl_dis | speed; - - /* Configure driver by overriding default config with the bus resources - * configured by the user - */ - sc->txbufs = 32; - sc->rxbufs = 32; - sc->phyaddr = -1; - - value = drvmgr_dev_key_get(sc->dev, "txDescs", DRVMGR_KT_INT); - if ( value && (value->i <= 128) ) - sc->txbufs = value->i; - - value = drvmgr_dev_key_get(sc->dev, "rxDescs", DRVMGR_KT_INT); - if ( value && (value->i <= 128) ) - sc->rxbufs = value->i; - - value = drvmgr_dev_key_get(sc->dev, "phyAdr", DRVMGR_KT_INT); - if ( value && (value->i < 32) ) - sc->phyaddr = value->i; - - value = drvmgr_dev_key_get(sc->dev, "advModes", DRVMGR_KT_INT); - if ( value ) - sc->advmodes = value->i; - - return 0; -} - -#ifdef GRETH_INFO_AVAIL -static int greth_info( - struct drvmgr_dev *dev, - void (*print_line)(void *p, char *str), - void *p, int argc, char *argv[]) -{ - struct greth_softc *sc; - char buf[64]; - - if (dev->priv == NULL) - return -DRVMGR_EINVAL; - sc = dev->priv; - - sprintf(buf, "IFACE NAME: %s", sc->devName); - print_line(p, buf); - sprintf(buf, "GBIT MAC: %s", sc->gbit_mac ? "YES" : "NO"); - print_line(p, buf); - - return DRVMGR_OK; -} -#endif - -#endif diff --git a/c/src/lib/libbsp/sparc/shared/net/network_interface_add.c b/c/src/lib/libbsp/sparc/shared/net/network_interface_add.c deleted file mode 100644 index e434e27b8f..0000000000 --- a/c/src/lib/libbsp/sparc/shared/net/network_interface_add.c +++ /dev/null @@ -1,62 +0,0 @@ -/* Network interface register help function - * - * COPYRIGHT (c) 2008. - * Cobham Gaisler AB. - * - * This function adds a network interface to the - * rtems_bsdnet_config.ifconfig linked list of interfaces. - * The interface configuration is taken from the user defined - * array interface_configs. This function is useful for PnP - * systems when an unknown number of interfaces are available. - * - * 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 - -extern struct rtems_bsdnet_config rtems_bsdnet_config; - -/* Number of interfaces taken */ -int network_interface_cnt = 0; - -int network_interface_add(struct rtems_bsdnet_ifconfig *interface) -{ - struct ethernet_config *cfg = NULL; - int i, last_entry = 1; - - /* Init interface description */ - interface->next = NULL; - - cfg = &interface_configs[network_interface_cnt]; - for(i=0; i<6; i++) { - if ( cfg->eth_adr[i] != 0 ) { - last_entry = 0; - break; - } - } - /* Do we have a valid configuration? */ - if ( last_entry == 0 ) { - cfg = &interface_configs[network_interface_cnt]; - - interface->ip_address = cfg->ip_addr; - interface->ip_netmask = cfg->ip_netmask; - interface->hardware_address = cfg->eth_adr; - - network_interface_cnt++; - } else { - interface->ip_address = NULL; - interface->ip_netmask = NULL; - interface->hardware_address = NULL; - } - - /* Insert interface first into list */ - interface->next = rtems_bsdnet_config.ifconfig; - rtems_bsdnet_config.ifconfig = interface; - - return 0; -} diff --git a/c/src/lib/libbsp/sparc/shared/pci/gr_701.c b/c/src/lib/libbsp/sparc/shared/pci/gr_701.c deleted file mode 100644 index a6c9ebcd5c..0000000000 --- a/c/src/lib/libbsp/sparc/shared/pci/gr_701.c +++ /dev/null @@ -1,623 +0,0 @@ -/* GR-701 PCI Target driver. - * - * COPYRIGHT (c) 2008. - * Cobham Gaisler AB. - * - * Configures the GR-701 interface PCI board. - * This driver provides a AMBA PnP bus by using the general part - * of the AMBA PnP bus driver (ambapp_bus.c). - * - * Driver resources for the AMBA PnP bus provided can be set using - * gr701_set_resources(). - * - * 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 -#include -#include /* spin-lock */ -#include -#include - -#include - -#include -#include -#include -#include -#include -#include - -#include - -/* map via rtems_interrupt_lock_* API: */ -#define SPIN_DECLARE(lock) RTEMS_INTERRUPT_LOCK_MEMBER(lock) -#define SPIN_INIT(lock, name) rtems_interrupt_lock_initialize(lock, name) -#define SPIN_LOCK(lock, level) rtems_interrupt_lock_acquire_isr(lock, &level) -#define SPIN_LOCK_IRQ(lock, level) rtems_interrupt_lock_acquire(lock, &level) -#define SPIN_UNLOCK(lock, level) rtems_interrupt_lock_release_isr(lock, &level) -#define SPIN_UNLOCK_IRQ(lock, level) rtems_interrupt_lock_release(lock, &level) -#define SPIN_IRQFLAGS(k) rtems_interrupt_lock_context k -#define SPIN_ISR_IRQFLAGS(k) SPIN_IRQFLAGS(k) - -/* Offset from 0x80000000 (dual bus version) */ -#define AHB1_BASE_ADDR 0x80000000 -#define AHB1_IOAREA_BASE_ADDR 0x80100000 - -/* #define DEBUG 1 */ - -#ifdef DEBUG -#define DBG(x...) printk(x) -#else -#define DBG(x...) -#endif - -int gr701_init1(struct drvmgr_dev *dev); -int gr701_init2(struct drvmgr_dev *dev); -void gr701_interrupt(void *arg); - -#define READ_REG(address) (*(volatile unsigned int *)address) - -/* PCI bride reg layout on AMBA side */ -struct amba_bridge_regs { - volatile unsigned int bar0; - volatile unsigned int bar1; - volatile unsigned int bar2; - volatile unsigned int bar3; - volatile unsigned int bar4;/* 0x10 */ - - volatile unsigned int unused[4*3-1]; - - volatile unsigned int ambabars[1]; /* 0x40 */ -}; - -/* PCI bride reg layout on PCI side */ -struct pci_bridge_regs { - volatile unsigned int bar0; - volatile unsigned int bar1; - volatile unsigned int bar2; - volatile unsigned int bar3; - volatile unsigned int bar4; /* 0x10 */ - - volatile unsigned int ilevel; - volatile unsigned int ipend; - volatile unsigned int iforce; - volatile unsigned int istatus; - volatile unsigned int iclear; - volatile unsigned int imask; -}; - -/* Private data structure for driver */ -struct gr701_priv { - /* Driver management */ - struct drvmgr_dev *dev; - char prefix[16]; - SPIN_DECLARE(devlock); - - struct pci_bridge_regs *pcib; - struct amba_bridge_regs *ambab; - - /* PCI */ - pci_dev_t pcidev; - struct pci_dev_info *devinfo; - - /* IRQ */ - genirq_t genirq; - int interrupt_cnt; - - /* GR-701 Address translation */ - struct drvmgr_map_entry bus_maps_up[2]; - struct drvmgr_map_entry bus_maps_down[2]; - - /* AMBA Plug&Play information on GR-701 */ - struct ambapp_bus abus; - struct ambapp_mmap amba_maps[3]; - struct ambapp_config config; -}; - -int ambapp_gr701_int_register( - struct drvmgr_dev *dev, - int irq, - const char *info, - drvmgr_isr handler, - void *arg); -int ambapp_gr701_int_unregister( - struct drvmgr_dev *dev, - int irq, - drvmgr_isr isr, - void *arg); -int ambapp_gr701_int_unmask( - struct drvmgr_dev *dev, - int irq); -int ambapp_gr701_int_mask( - struct drvmgr_dev *dev, - int irq); -int ambapp_gr701_int_clear( - struct drvmgr_dev *dev, - int irq); -int ambapp_gr701_get_params( - struct drvmgr_dev *dev, - struct drvmgr_bus_params *params); - -struct ambapp_ops ambapp_gr701_ops = { - .int_register = ambapp_gr701_int_register, - .int_unregister = ambapp_gr701_int_unregister, - .int_unmask = ambapp_gr701_int_unmask, - .int_mask = ambapp_gr701_int_mask, - .int_clear = ambapp_gr701_int_clear, - .get_params = ambapp_gr701_get_params -}; - -struct drvmgr_drv_ops gr701_ops = -{ - .init = {gr701_init1, gr701_init2, NULL, NULL}, - .remove = NULL, - .info = NULL -}; - -struct pci_dev_id_match gr701_ids[] = -{ - PCIID_DEVVEND(PCIID_VENDOR_GAISLER, PCIID_DEVICE_GR_701), - PCIID_END_TABLE /* Mark end of table */ -}; - -struct pci_drv_info gr701_info = -{ - { - DRVMGR_OBJ_DRV, /* Driver */ - NULL, /* Next driver */ - NULL, /* Device list */ - DRIVER_PCI_GAISLER_GR701_ID, /* Driver ID */ - "GR-701_DRV", /* Driver Name */ - DRVMGR_BUS_TYPE_PCI, /* Bus Type */ - &gr701_ops, - NULL, /* Funcs */ - 0, /* No devices yet */ - 0, - }, - &gr701_ids[0] -}; - -/* Driver resources configuration for the AMBA bus on the GR-701 board. - * It is declared weak so that the user may override it from the project file, - * if the default settings are not enough. - * - * The configuration consists of an array of configuration pointers, each - * pointer determine the configuration of one GR-701 board. Pointer - * zero is for board0, pointer 1 for board1 and so on. - * - * The array must end with a NULL pointer. - */ -struct drvmgr_bus_res *gr701_resources[] __attribute__((weak)) = -{ - NULL -}; - -void gr701_register_drv(void) -{ - DBG("Registering GR-701 PCI driver\n"); - drvmgr_drv_register(&gr701_info.general); -} - -void gr701_interrupt(void *arg) -{ - struct gr701_priv *priv = arg; - unsigned int status; - int irq = 0; - SPIN_ISR_IRQFLAGS(irqflags); - - SPIN_LOCK(&priv->devlock, irqflags); - while ( (status=priv->pcib->istatus) != 0 ) { - priv->interrupt_cnt++; /* An interrupt was generated */ - irq = status; - genirq_doirq(priv->genirq, irq); - /* ACK interrupt */ - priv->pcib->istatus = 0; - } - SPIN_UNLOCK(&priv->devlock, irqflags); - - /* ACK interrupt, this is because PCI is Level, so the IRQ Controller still drives the IRQ. */ - if ( irq ) - drvmgr_interrupt_clear(priv->dev, 0); -} - -static int gr701_hw_init(struct gr701_priv *priv) -{ - uint32_t com1; - struct pci_bridge_regs *pcib; - struct amba_bridge_regs *ambab; - int mst; - unsigned int pci_freq_hz; - pci_dev_t pcidev = priv->pcidev; - struct pci_dev_info *devinfo = priv->devinfo; - - /* Set up PCI ==> AMBA */ - priv->pcib = pcib = (void *)devinfo->resources[0].address; - pcib->bar0 = 0xfc000000; - - /* Set up GR701 AMBA Masters connection to PCI */ - priv->ambab = ambab = (struct amba_bridge_regs *)( - devinfo->resources[1].address + 0x400); - - /* Init all msters, max 16 */ - for (mst=0; mst<16; mst++) { - ambab->ambabars[mst] = 0x40000000; - if (READ_REG(&ambab->ambabars[mst]) != 0x40000000) - break; - } - - /* Setup Address translation for AMBA bus, assume that PCI BAR - * are mapped 1:1 to CPU. - */ - - priv->amba_maps[0].size = 0x04000000; - priv->amba_maps[0].local_adr = devinfo->resources[1].address; - priv->amba_maps[0].remote_adr = 0xfc000000; - - /* Mark end of table */ - priv->amba_maps[1].size=0; - priv->amba_maps[1].local_adr = 0; - priv->amba_maps[1].remote_adr = 0; - - /* Setup DOWN-streams address translation */ - priv->bus_maps_down[0].name = "PCI BAR1 -> AMBA"; - priv->bus_maps_down[0].size = priv->amba_maps[0].size; - priv->bus_maps_down[0].from_adr = (void *)devinfo->resources[1].address; - priv->bus_maps_down[0].to_adr = (void *)0xfc000000; - - /* Setup UP-streams address translation */ - priv->bus_maps_up[0].name = "AMBA PCIF Window"; - priv->bus_maps_up[0].size = 0x10000000; - priv->bus_maps_up[0].from_adr = (void *)0xe0000000; - priv->bus_maps_up[0].to_adr = (void *)0x40000000; - - /* Mark end of translation tables */ - priv->bus_maps_down[1].size = 0; - priv->bus_maps_up[1].size = 0; - - /* Enable I/O and Mem accesses */ - pci_cfg_r32(pcidev, PCIR_COMMAND, &com1); - com1 |= PCIM_CMD_PORTEN | PCIM_CMD_MEMEN; - pci_cfg_w32(pcidev, PCIR_COMMAND, com1); - - /* Start AMBA PnP scan at first AHB bus */ - ambapp_scan(&priv->abus, devinfo->resources[1].address + 0x3f00000, - NULL, &priv->amba_maps[0]); - - /* Frequency is the same as the PCI bus frequency */ - drvmgr_freq_get(priv->dev, 0, &pci_freq_hz); - - /* Initialize Frequency of AMBA bus */ - ambapp_freq_init(&priv->abus, NULL, pci_freq_hz); - - /* Init IRQ controller (avoid IRQ generation) */ - pcib->imask = 0x0000; - pcib->ipend = 0; - pcib->iclear = 0xffff; - pcib->iforce = 0; - pcib->ilevel = 0x0; - - /* Successfully registered the GR-701 board */ - return 0; -} - -static void gr701_hw_init2(struct gr701_priv *priv) -{ - /* Enable PCI Master (for DMA) */ - pci_master_enable(priv->pcidev); -} - -/* Called when a PCI target is found with the PCI device and vendor ID - * given in gr701_ids[]. - */ -int gr701_init1(struct drvmgr_dev *dev) -{ - struct gr701_priv *priv; - struct pci_dev_info *devinfo; - uint32_t bar0, bar1, bar0_size, bar1_size; - int resources_cnt; - - priv = malloc(sizeof(struct gr701_priv)); - if ( !priv ) - return DRVMGR_NOMEM; - - memset(priv, 0, sizeof(*priv)); - dev->priv = priv; - priv->dev = dev; - - /* Determine number of configurations */ - resources_cnt = get_resarray_count(gr701_resources); - - /* Generate Device prefix */ - strcpy(priv->prefix, "/dev/gr701_0"); - priv->prefix[11] += dev->minor_drv; - mkdir(priv->prefix, S_IRWXU | S_IRWXG | S_IRWXO); - priv->prefix[12] = '/'; - priv->prefix[13] = '\0'; - - priv->devinfo = devinfo = (struct pci_dev_info *)dev->businfo; - priv->pcidev = devinfo->pcidev; - bar0 = devinfo->resources[0].address; - bar0_size = devinfo->resources[0].size; - bar1 = devinfo->resources[1].address; - bar1_size = devinfo->resources[1].size; - printf("\n\n--- GR-701[%d] ---\n", dev->minor_drv); - printf(" PCI BUS: 0x%x, SLOT: 0x%x, FUNCTION: 0x%x\n", - PCI_DEV_EXPAND(priv->pcidev)); - printf(" PCI VENDOR: 0x%04x, DEVICE: 0x%04x\n\n\n", - devinfo->id.vendor, devinfo->id.device); - printf(" PCI BAR[0]: 0x%lx - 0x%lx\n", bar0, bar0 + bar0_size - 1); - printf(" PCI BAR[1]: 0x%lx - 0x%lx\n", bar1, bar1 + bar1_size - 1); - printf(" IRQ: %d\n\n\n", devinfo->irq); - - /* all neccessary space assigned to GR-701 target? */ - if ((bar0_size == 0) || (bar1_size == 0)) - return DRVMGR_ENORES; - - /* Initialize spin-lock for this PCI perihperal device. This is to - * protect the Interrupt Controller Registers. The genirq layer is - * protecting its own internals and ISR dispatching. - */ - SPIN_INIT(&priv->devlock, priv->prefix); - - priv->genirq = genirq_init(16); - if ( priv->genirq == NULL ) { - free(priv); - dev->priv = NULL; - return DRVMGR_FAIL; - } - - if ( gr701_hw_init(priv) ) { - genirq_destroy(priv->genirq); - free(priv); - dev->priv = NULL; - printf(" Failed to initialize GR-701 HW\n"); - return DRVMGR_FAIL; - } - - /* Init amba bus */ - priv->config.abus = &priv->abus; - priv->config.ops = &ambapp_gr701_ops; - priv->config.maps_up = &priv->bus_maps_up[0]; - priv->config.maps_down = &priv->bus_maps_down[0]; - if ( priv->dev->minor_drv < resources_cnt ) { - priv->config.resources = gr701_resources[priv->dev->minor_drv]; - } else { - priv->config.resources = NULL; - } - - /* Create and register AMBA PnP bus. */ - return ambapp_bus_register(dev, &priv->config); -} - -/* Called when a PCI target is found with the PCI device and vendor ID - * given in gr701_ids[]. - */ -int gr701_init2(struct drvmgr_dev *dev) -{ - struct gr701_priv *priv = dev->priv; - - /* Clear any old interrupt requests */ - drvmgr_interrupt_clear(dev, 0); - - /* Enable System IRQ so that GR-701 PCI target interrupt goes through. - * - * It is important to enable it in stage init2. If interrupts were - * enabled in init1 this might hang the system when more than one PCI - * board is connected, this is because PCI interrupts might be shared - * and PCI target 2 have not initialized and might therefore drive - * interrupt already when entering init1(). - */ - drvmgr_interrupt_register(dev, 0, "gr701", gr701_interrupt, priv); - - gr701_hw_init2(priv); - - return DRVMGR_OK; -} - -int ambapp_gr701_int_register( - struct drvmgr_dev *dev, - int irq, - const char *info, - drvmgr_isr handler, - void *arg) -{ - struct gr701_priv *priv = dev->parent->dev->priv; - SPIN_IRQFLAGS(irqflags); - int status; - void *h; - - h = genirq_alloc_handler(handler, arg); - if ( h == NULL ) - return DRVMGR_FAIL; - - SPIN_LOCK_IRQ(&priv->devlock, irqflags); - - status = genirq_register(priv->genirq, irq, h); - if ( status == 0 ) { - /* Clear IRQ for first registered handler */ - priv->pcib->iclear = (1<devlock, irqflags); - genirq_free_handler(h); - return DRVMGR_FAIL; - } - - status = genirq_enable(priv->genirq, irq, handler, arg); - if ( status == 0 ) { - /* Enable IRQ for first enabled handler only */ - priv->pcib->imask |= (1<devlock, irqflags); - - return status; -} - -int ambapp_gr701_int_unregister( - struct drvmgr_dev *dev, - int irq, - drvmgr_isr isr, - void *arg) -{ - struct gr701_priv *priv = dev->parent->dev->priv; - SPIN_IRQFLAGS(irqflags); - int status; - void *handler; - - SPIN_LOCK_IRQ(&priv->devlock, irqflags); - - status = genirq_disable(priv->genirq, irq, isr, arg); - if ( status == 0 ) { - /* Disable IRQ only when no enabled handler exists */ - priv->pcib->imask &= ~(1<genirq, irq, isr, arg); - if ( handler == NULL ) - status = DRVMGR_FAIL; - else - status = DRVMGR_OK; - - SPIN_UNLOCK_IRQ(&priv->devlock, irqflags); - - if (handler) - genirq_free_handler(handler); - - return status; -} - -int ambapp_gr701_int_unmask( - struct drvmgr_dev *dev, - int irq) -{ - struct gr701_priv *priv = dev->parent->dev->priv; - SPIN_IRQFLAGS(irqflags); - - DBG("GR-701 IRQ %d: enable\n", irq); - - if ( genirq_check(priv->genirq, irq) ) - return DRVMGR_FAIL; - - SPIN_LOCK_IRQ(&priv->devlock, irqflags); - - /* Enable IRQ */ - priv->pcib->imask |= (1<devlock, irqflags); - - return DRVMGR_OK; -} - -int ambapp_gr701_int_mask( - struct drvmgr_dev *dev, - int irq) -{ - struct gr701_priv *priv = dev->parent->dev->priv; - SPIN_IRQFLAGS(irqflags); - - DBG("GR-701 IRQ %d: disable\n", irq); - - if ( genirq_check(priv->genirq, irq) ) - return DRVMGR_FAIL; - - SPIN_LOCK_IRQ(&priv->devlock, irqflags); - - /* Disable IRQ */ - priv->pcib->imask &= ~(1<devlock, irqflags); - - return DRVMGR_OK; -} - -int ambapp_gr701_int_clear( - struct drvmgr_dev *dev, - int irq) -{ - struct gr701_priv *priv = dev->parent->dev->priv; - - if ( genirq_check(priv->genirq, irq) ) - return DRVMGR_FAIL; - - priv->pcib->iclear = (1<parent->dev->priv; - - /* Device name prefix pointer, skip /dev */ - params->dev_prefix = &priv->prefix[5]; - - return 0; -} - -void gr701_print_dev(struct drvmgr_dev *dev, int options) -{ - struct gr701_priv *priv = dev->priv; - struct pci_dev_info *devinfo = priv->devinfo; - unsigned int freq_hz; - uint32_t bar0, bar1, bar0_size, bar1_size; - - /* Print */ - printf("--- GR-701 [bus 0x%x, dev 0x%x, fun 0x%x] ---\n", - PCI_DEV_EXPAND(priv->pcidev)); - bar0 = devinfo->resources[0].address; - bar0_size = devinfo->resources[0].size; - bar1 = devinfo->resources[1].address; - bar1_size = devinfo->resources[1].size; - - printf(" PCI BAR[0]: 0x%lx - 0x%lx\n", bar0, bar0 + bar0_size - 1); - printf(" PCI BAR[1]: 0x%lx - 0x%lx\n", bar1, bar1 + bar1_size - 1); - printf(" IRQ: %d\n", devinfo->irq); - - /* Frequency is the same as the PCI bus frequency */ - drvmgr_freq_get(dev, 0, &freq_hz); - - printf(" FREQ: %u Hz\n", freq_hz); - printf(" IMASK: 0x%08x\n", priv->pcib->imask); - printf(" IPEND: 0x%08x\n", priv->pcib->ipend); - - /* Print amba config */ - if ( options & GR701_OPTIONS_AMBA ) { - ambapp_print(&priv->abus, 10); - } - -#if 0 - /* Print IRQ handlers and their arguments */ - if ( options & GR701_OPTIONS_IRQ ) { - int i; - for(i=0; i<16; i++) { - printf(" IRQ[%02d]: 0x%x, arg: 0x%x\n", - i, (unsigned int)priv->isrs[i].handler, (unsigned int)priv->isrs[i].arg); - } - } -#endif -} - -void gr701_print(int options) -{ - struct pci_drv_info *drv = &gr701_info; - struct drvmgr_dev *dev; - - dev = drv->general.dev; - while(dev) { - gr701_print_dev(dev, options); - dev = dev->next_in_drv; - } -} diff --git a/c/src/lib/libbsp/sparc/shared/pci/gr_cpci_gr740.c b/c/src/lib/libbsp/sparc/shared/pci/gr_cpci_gr740.c deleted file mode 100644 index 7ff7206199..0000000000 --- a/c/src/lib/libbsp/sparc/shared/pci/gr_cpci_gr740.c +++ /dev/null @@ -1,772 +0,0 @@ -/* GR-CPCI-GR740 PCI Target driver. - * - * COPYRIGHT (c) 2017. - * Cobham Gaisler AB. - * - * 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.com/license/LICENSE. - * - * Configures the GR-CPCI-GR740 interface PCI board in peripheral - * mode. This driver provides a AMBA PnP bus by using the general part - * of the AMBA PnP bus driver (ambapp_bus.c). Based on the - * GR-RASTA-IO driver. - * - * - * Driver resource options: - * NAME DEFAULT VALUE - * ahbmst2pci _RAM_START AMBA->PCI translation PCI base address - * ambaFreq 250000000 (250MHz) AMBA system frequency of GR740 - * cgEnMask 0x1f (all) Clock gating enable mask - * bar0 0x00000000 L2-Cache SDRAM memory - * bar1 0xf0000000 L2-Cache registers - * - * TODO/UNTESTED - * Interrupt testing - */ - -#include -#include -#include -#include -#include - -#include -#include -#include /* spin-lock */ -#include - -#include -#include -#include -#include -#include -#include -#include - -#include - -/* map via rtems_interrupt_lock_* API: */ -#define SPIN_DECLARE(lock) RTEMS_INTERRUPT_LOCK_MEMBER(lock) -#define SPIN_INIT(lock, name) rtems_interrupt_lock_initialize(lock, name) -#define SPIN_LOCK(lock, level) rtems_interrupt_lock_acquire_isr(lock, &level) -#define SPIN_LOCK_IRQ(lock, level) rtems_interrupt_lock_acquire(lock, &level) -#define SPIN_UNLOCK(lock, level) rtems_interrupt_lock_release_isr(lock, &level) -#define SPIN_UNLOCK_IRQ(lock, level) rtems_interrupt_lock_release(lock, &level) -#define SPIN_IRQFLAGS(k) rtems_interrupt_lock_context k -#define SPIN_ISR_IRQFLAGS(k) SPIN_IRQFLAGS(k) - -/* Determines which PCI address the AHB masters on the GR740 board will - * access when accessing the AHB to PCI window, it should be set so that the - * masters can access the HOST RAM. - * Default is base of HOST RAM, HOST RAM is mapped 1:1 to PCI memory space. - */ -extern unsigned int _RAM_START; -#define AHBMST2PCIADR (((unsigned int)&_RAM_START) & 0xc0000000) - -#define GRPCI2_BAR0_TO_AHB_MAP 0x04 -#define GRPCI2_BAR1_TO_AHB_MAP 0x08 -#define GRPCI2_BAR2_TO_AHB_MAP 0x0c -#define GRPCI2_PCI_CONFIG 0x20 -#define CAP9_AHBPREF_OFS 0x3c - -/* #define DEBUG 1 */ - -#ifdef DEBUG -#define DBG(x...) printk(x) -#else -#define DBG(x...) -#endif - -int gr_cpci_gr740_init1(struct drvmgr_dev *dev); -int gr_cpci_gr740_init2(struct drvmgr_dev *dev); -void gr_cpci_gr740_isr(void *arg); - -struct grpci2_regs { - volatile unsigned int ctrl; /* 0x00 */ - volatile unsigned int sts_cap; /* 0x04 */ - volatile unsigned int ppref; /* 0x08 */ - volatile unsigned int io_map; /* 0x0C */ - volatile unsigned int dma_ctrl; /* 0x10 */ - volatile unsigned int dma_bdbase; /* 0x14 */ - volatile unsigned int dma_chact; /* 0x18 */ - int res1; /* 0x1C */ - volatile unsigned int bars[6]; /* 0x20 */ - int res2[2]; /* 0x38 */ - volatile unsigned int ahbmst_map[16]; /* 0x40 */ -}; - -/* Clock gating unit register layout */ -struct gr740_grcg_regs { - volatile unsigned int unlock; - volatile unsigned int enable; - volatile unsigned int reset; - volatile unsigned int cpu_fpu; -}; -#define CG_MASK 0x3ff - -/* Private data structure for driver */ -struct gr_cpci_gr740_priv { - /* Driver management */ - struct drvmgr_dev *dev; - char prefix[16]; - SPIN_DECLARE(devlock); - - /* PCI */ - pci_dev_t pcidev; - struct pci_dev_info *devinfo; - uint32_t ahbmst2pci_map; - - /* IRQ */ - int eirq; - genirq_t genirq; - - /* GR-CPCI-GR740 */ - unsigned int amba_freq_hz; - unsigned int cg_en_mask; /* Enabled cores */ - struct irqmp_regs *irq; - struct gr740_grcg_regs *cg; /* Clock-gating unit */ - struct grpci2_regs *grpci2; - struct drvmgr_map_entry bus_maps_up[2]; - struct drvmgr_map_entry bus_maps_down[4]; - - /* AMBA Plug&Play information on GR-CPCI-GR740 */ - struct ambapp_bus abus; - struct ambapp_mmap amba_maps[5]; - struct ambapp_config config; -}; - -int ambapp_gr740_int_register( - struct drvmgr_dev *dev, - int irq, - const char *info, - drvmgr_isr handler, - void *arg); -int ambapp_gr740_int_unregister( - struct drvmgr_dev *dev, - int irq, - drvmgr_isr handler, - void *arg); -int ambapp_gr740_int_unmask( - struct drvmgr_dev *dev, - int irq); -int ambapp_gr740_int_mask( - struct drvmgr_dev *dev, - int irq); -int ambapp_gr740_int_clear( - struct drvmgr_dev *dev, - int irq); -int ambapp_gr740_get_params( - struct drvmgr_dev *dev, - struct drvmgr_bus_params *params); - -static struct ambapp_ops ambapp_gr740_ops = { - .int_register = ambapp_gr740_int_register, - .int_unregister = ambapp_gr740_int_unregister, - .int_unmask = ambapp_gr740_int_unmask, - .int_mask = ambapp_gr740_int_mask, - .int_clear = ambapp_gr740_int_clear, - .get_params = ambapp_gr740_get_params -}; - -struct drvmgr_drv_ops gr_cpci_gr740_ops = -{ - .init = {gr_cpci_gr740_init1, gr_cpci_gr740_init2, NULL, NULL}, - .remove = NULL, - .info = NULL -}; - -struct pci_dev_id_match gr_cpci_gr740_ids[] = -{ - PCIID_DEVVEND(PCIID_VENDOR_GAISLER, PCIID_DEVICE_GR_CPCI_GR740), - PCIID_END_TABLE /* Mark end of table */ -}; - -struct pci_drv_info gr_cpci_gr740_info = -{ - { - DRVMGR_OBJ_DRV, /* Driver */ - NULL, /* Next driver */ - NULL, /* Device list */ - DRIVER_PCI_GAISLER_CPCI_GR740_ID, /* Driver ID */ - "GR-CPCI-GR740", /* Driver Name */ - DRVMGR_BUS_TYPE_PCI, /* Bus Type */ - &gr_cpci_gr740_ops, - NULL, /* Funcs */ - 0, /* No devices yet */ - sizeof(struct gr_cpci_gr740_priv), - }, - &gr_cpci_gr740_ids[0] -}; - -/* Driver resources configuration for the AMBA bus on the GR-CPCI-GR740 board. - * It is declared weak so that the user may override it from the project file, - * if the default settings are not enough. - * - * The configuration consists of an array of configuration pointers, each - * pointer determine the configuration of one GR-CPCI-GR740 board. Pointer - * zero is for board0, pointer 1 for board1 and so on. - * - * The array must end with a NULL pointer. - */ -struct drvmgr_bus_res *gr_cpci_gr740_resources[] __attribute__((weak)) = -{ - NULL -}; - -void gr_cpci_gr740_register_drv(void) -{ - DBG("Registering GR-CPCI-GR740 PCI driver\n"); - drvmgr_drv_register(&gr_cpci_gr740_info.general); -} - -void gr_cpci_gr740_isr(void *arg) -{ - struct gr_cpci_gr740_priv *priv = arg; - unsigned int status, tmp; - int irq, eirq; - SPIN_ISR_IRQFLAGS(irqflags); - - tmp = status = priv->irq->ipend; - - /* DBG("GR-CPCI-GR740: IRQ 0x%x\n",status); */ - - SPIN_LOCK(&priv->devlock, irqflags); - for(irq = 0; irq < 32; irq++) { - if (status & (1 << irq)) { - if (irq == priv->eirq) { - while ((eirq = priv->irq->intid[0] & 0x1f)) { - if ((eirq & 0x10) == 0) - continue; - genirq_doirq(priv->genirq, eirq); - priv->irq->iclear = (1 << eirq); - } - } else { - genirq_doirq(priv->genirq, irq); - } - priv->irq->iclear = (1 << irq); - status &= ~(1 << irq); - if ( status == 0 ) - break; - } - } - SPIN_UNLOCK(&priv->devlock, irqflags); - - /* ACK interrupt, this is because PCI is Level, so the IRQ Controller - * still drives the IRQ - */ - if ( tmp ) - drvmgr_interrupt_clear(priv->dev, 0); - - DBG("GR-CPCI-GR740-IRQ: 0x%x\n", tmp); -} - -static int gr_cpci_gr740_hw_init1(struct gr_cpci_gr740_priv *priv) -{ - int i; - uint32_t data; - unsigned int ctrl; - uint8_t tmp2; - struct ambapp_dev *tmp; - struct ambapp_ahb_info *ahb; - uint8_t cap_ptr; - pci_dev_t pcidev = priv->pcidev; - struct pci_dev_info *devinfo = priv->devinfo; - unsigned int cgmask, enabled; - - /* Check capabilities list bit and read its pointer */ - pci_cfg_r8(pcidev, PCIR_STATUS, &tmp2); - if (!((tmp2 >> 4) & 1)) { - /* Capabilities list not available which it should be in the GRPCI2 */ - return -2; - } - pci_cfg_r8(pcidev, PCIR_CAP_PTR, &cap_ptr); - - /* Set AHB address mappings for target PCI bars - * BAR0 maps to 0x00000000-0x07ffffff 128MB (SDRAM/DDR2 memory) - * BAR1 maps to 0xf0000000-0xf7ffffff 128MB (L2-Cache regs/diagnostics) - * BAR2 maps to 0xff800000-0xffffffff 8MB (PnP, I/O regs) - */ - pci_cfg_w32(pcidev, cap_ptr+GRPCI2_BAR0_TO_AHB_MAP, 0x00000000); - pci_cfg_w32(pcidev, cap_ptr+GRPCI2_BAR1_TO_AHB_MAP, 0xf0000000); - pci_cfg_w32(pcidev, cap_ptr+GRPCI2_BAR2_TO_AHB_MAP, 0xff800000); - - /* Set PCI bus to be big endian */ - pci_cfg_r32(pcidev, cap_ptr+GRPCI2_PCI_CONFIG, &data); - data = data & 0xFFFFFFFE; - pci_cfg_w32(pcidev, cap_ptr+GRPCI2_PCI_CONFIG, data); - -#if 0 - /* set parity error response */ - pci_cfg_r32(pcidev, PCIR_COMMAND, &data); - pci_cfg_w32(pcidev, PCIR_COMMAND, (data|PCIM_CMD_PERRESPEN)); -#endif - - /* Scan AMBA Plug&Play */ - - /* AMBA MAP bar0 (in gr740) ==> 0x00000000 (remote amba address) */ - priv->amba_maps[0].size = devinfo->resources[0].size; - priv->amba_maps[0].local_adr = devinfo->resources[0].address; - priv->amba_maps[0].remote_adr = 0x00000000; - - priv->amba_maps[1].size = devinfo->resources[1].size; - priv->amba_maps[1].local_adr = devinfo->resources[1].address; - priv->amba_maps[1].remote_adr = 0xf0000000; - - priv->amba_maps[2].size = devinfo->resources[2].size; - priv->amba_maps[2].local_adr = devinfo->resources[2].address; - priv->amba_maps[2].remote_adr = 0xff800000; - - /* Addresses not matching with map be untouched */ - priv->amba_maps[3].size = 0xfffffff0; - priv->amba_maps[3].local_adr = 0; - priv->amba_maps[3].remote_adr = 0; - - /* Mark end of table */ - priv->amba_maps[4].size=0; - - /* Start AMBA PnP scan at first AHB bus */ - ambapp_scan( - &priv->abus, - devinfo->resources[2].address + 0x00700000, - NULL, - &priv->amba_maps[0]); - - /* Initialize Frequency of AMBA bus */ - ambapp_freq_init(&priv->abus, NULL, priv->amba_freq_hz); - - /* Find IRQ controller, Clear all current IRQs */ - tmp = (struct ambapp_dev *)ambapp_for_each(&priv->abus, - (OPTIONS_ALL|OPTIONS_APB_SLVS), - VENDOR_GAISLER, GAISLER_IRQMP, - ambapp_find_by_idx, NULL); - if ( !tmp ) { - return -4; - } - priv->irq = (struct irqmp_regs *)DEV_TO_APB(tmp)->start; - /* Set up GR-CPCI-GR740 irq controller - * Interrupts are routed from IRQCtrl0, we leave the configuration - * for the other CPUs, as the board's CPUs may be running something. - * We assume IRQCtrl has been set up properly, or at least the reset - * values shuold work with this code.. - */ - priv->irq->mask[0] = 0; - priv->irq->iforce = 0; - priv->irq->force[0] = 0; - priv->irq->ilevel = 0; - priv->irq->ipend = 0; - priv->irq->iclear = 0xffffffff; - priv->irq->ilevel = 0; - /* Get extended Interrupt controller IRQ number */ - priv->eirq = (priv->irq->mpstat >> 16) & 0xf; - - /* Find first Clock-Gating unit, enable/disable the requested cores */ - tmp = (struct ambapp_dev *)ambapp_for_each(&priv->abus, - (OPTIONS_ALL|OPTIONS_APB_SLVS), - VENDOR_GAISLER, GAISLER_CLKGATE, - ambapp_find_by_idx, NULL); - if ( !tmp ) { - return -5; - } - priv->cg = (struct gr740_grcg_regs *)DEV_TO_APB(tmp)->start; - /* Do reset and enable sequence only if not already enabled */ - if (priv->cg && ((enabled = priv->cg->enable) != priv->cg_en_mask)) { - /* First disable already enabled cores */ - cgmask = ~priv->cg_en_mask & enabled; - if (cgmask) { - priv->cg->unlock = cgmask; - priv->cg->enable = enabled = ~cgmask & enabled; - priv->cg->unlock = 0; - } - /* Enable disabled cores */ - cgmask = priv->cg_en_mask & ~enabled; - if (cgmask) { - priv->cg->unlock = cgmask; - priv->cg->reset |= cgmask; - priv->cg->enable = cgmask | enabled; - priv->cg->reset &= ~cgmask; - priv->cg->unlock = 0; - } - } - - priv->bus_maps_down[0].name = "PCI BAR0 -> AMBA"; - priv->bus_maps_down[0].size = priv->amba_maps[0].size; - priv->bus_maps_down[0].from_adr = (void *)priv->amba_maps[0].local_adr; - priv->bus_maps_down[0].to_adr = (void *)priv->amba_maps[0].remote_adr; - priv->bus_maps_down[1].name = "PCI BAR1 -> AMBA"; - priv->bus_maps_down[1].size = priv->amba_maps[1].size; - priv->bus_maps_down[1].from_adr = (void *)priv->amba_maps[1].local_adr; - priv->bus_maps_down[1].to_adr = (void *)priv->amba_maps[1].remote_adr; - priv->bus_maps_down[2].name = "PCI BAR2 -> AMBA"; - priv->bus_maps_down[2].size = priv->amba_maps[2].size; - priv->bus_maps_down[2].from_adr = (void *)priv->amba_maps[2].local_adr; - priv->bus_maps_down[2].to_adr = (void *)priv->amba_maps[2].remote_adr; - priv->bus_maps_down[3].size = 0; - - /* Find GRPCI2 controller AHB Slave interface */ - tmp = (struct ambapp_dev *)ambapp_for_each(&priv->abus, - (OPTIONS_ALL|OPTIONS_AHB_SLVS), - VENDOR_GAISLER, GAISLER_GRPCI2, - ambapp_find_by_idx, NULL); - if ( !tmp ) { - return -6; - } - ahb = (struct ambapp_ahb_info *)tmp->devinfo; - priv->bus_maps_up[0].name = "AMBA GRPCI2 Window"; - priv->bus_maps_up[0].size = ahb->mask[0]; /* AMBA->PCI Window on GR-CPCI-GR740 board */ - priv->bus_maps_up[0].from_adr = (void *)ahb->start[0]; - priv->bus_maps_up[0].to_adr = (void *) - (priv->ahbmst2pci_map & ~(ahb->mask[0]-1)); - priv->bus_maps_up[1].size = 0; - - /* Find GRPCI2 controller APB Slave interface */ - tmp = (struct ambapp_dev *)ambapp_for_each(&priv->abus, - (OPTIONS_ALL|OPTIONS_APB_SLVS), - VENDOR_GAISLER, GAISLER_GRPCI2, - ambapp_find_by_idx, NULL); - if ( !tmp ) { - return -7; - } - priv->grpci2 = (struct grpci2_regs *) - ((struct ambapp_apb_info *)tmp->devinfo)->start; - - /* Set AHB to PCI mapping for all AMBA AHB masters */ - for(i = 0; i < 16; i++) { - priv->grpci2->ahbmst_map[i] = priv->ahbmst2pci_map & - ~(ahb->mask[0]-1); - } - - /* Make sure dirq(0) sampling is enabled */ - ctrl = priv->grpci2->ctrl; - ctrl = (ctrl & 0xFFFFFF0F) | (1 << 4); - priv->grpci2->ctrl = ctrl; - - /* Successfully registered the GR740 board */ - return 0; -} - -static int gr_cpci_gr740_hw_init2(struct gr_cpci_gr740_priv *priv) -{ - /* Enable DMA by enabling PCI target as master */ - pci_master_enable(priv->pcidev); - - return DRVMGR_OK; -} - -/* Called when a PCI target is found with the PCI device and vendor ID - * given in gr_cpci_gr740_ids[]. - */ -int gr_cpci_gr740_init1(struct drvmgr_dev *dev) -{ - struct gr_cpci_gr740_priv *priv; - struct pci_dev_info *devinfo; - int status, i; - union drvmgr_key_value *value; - int resources_cnt; - - priv = dev->priv; - if (!priv) - return DRVMGR_NOMEM; - - memset(priv, 0, sizeof(*priv)); - dev->priv = priv; - priv->dev = dev; - - /* Determine number of configurations */ - resources_cnt = get_resarray_count(gr_cpci_gr740_resources); - - /* Generate Device prefix */ - - strcpy(priv->prefix, "/dev/gr740_0"); - priv->prefix[11] += dev->minor_drv; - mkdir(priv->prefix, S_IRWXU | S_IRWXG | S_IRWXO); - priv->prefix[12] = '/'; - priv->prefix[13] = '\0'; - - priv->devinfo = devinfo = (struct pci_dev_info *)dev->businfo; - priv->pcidev = devinfo->pcidev; - printf("\n\n--- GR-CPCI-GR740[%d] ---\n", dev->minor_drv); - printf(" PCI BUS: 0x%x, SLOT: 0x%x, FUNCTION: 0x%x\n", - PCI_DEV_EXPAND(priv->pcidev)); - printf(" PCI VENDOR: 0x%04x, DEVICE: 0x%04x\n", - devinfo->id.vendor, devinfo->id.device); - for (i = 0; i < 3; i++) { - printf(" PCI BAR[%d]: 0x%08lx - 0x%08lx\n", - i, devinfo->resources[i].address, - devinfo->resources[i].address + - (devinfo->resources[i].size - 1)); - /* all neccessary space assigned to GR-CPCI-GR740 target? */ - if (devinfo->resources[i].size == 0) - return DRVMGR_ENORES; - } - printf(" IRQ: %d\n\n\n", devinfo->irq); - - /* Initialize spin-lock for this PCI perihperal device. This is to - * protect the Interrupt Controller Registers. The genirq layer is - * protecting its own internals and ISR dispatching. - */ - SPIN_INIT(&priv->devlock, priv->prefix); - - /* Let user override which PCI address the AHB masters of the - * GR740 board access when doing DMA to HOST RAM. The AHB masters - * access the PCI Window of the AMBA bus, the MSB 2-bits of that address - * is translated according this config option before the address goes - * out on the PCI bus. - * - * Only the 2 MSB bits have an effect. - */ - value = drvmgr_dev_key_get(priv->dev, "ahbmst2pci", DRVMGR_KT_INT); - if (value) - priv->ahbmst2pci_map = value->i; - else - priv->ahbmst2pci_map = AHBMST2PCIADR; /* default */ - - /* Let user override the default AMBA system frequency of the - * CPU-bus of the remote GR-CPCI-GR740. Default is 250MHz. - */ - value = drvmgr_dev_key_get(priv->dev, "ambaFreq", DRVMGR_KT_INT); - if (value) - priv->amba_freq_hz = value->i; - else - priv->amba_freq_hz = 250000000; /* default */ - - /* Let user determine clock-gating unit configuration. The default - * is to turn all cores on (disable gating). PCI is always turned ON. - */ - value = drvmgr_dev_key_get(priv->dev, "cgEnMask", DRVMGR_KT_INT); - if (value) - priv->cg_en_mask = (value->i & CG_MASK) | 0x08; - else - priv->cg_en_mask = CG_MASK; /* default all ON */ - - priv->genirq = genirq_init(32); - if (priv->genirq == NULL) - return DRVMGR_FAIL; - - if ((status = gr_cpci_gr740_hw_init1(priv)) != 0) { - genirq_destroy(priv->genirq); - printf(" Failed to initialize GR-CPCI-GR740 HW: %d\n", status); - return DRVMGR_FAIL; - } - - /* Init amba bus */ - priv->config.abus = &priv->abus; - priv->config.ops = &ambapp_gr740_ops; - priv->config.maps_up = &priv->bus_maps_up[0]; - priv->config.maps_down = &priv->bus_maps_down[0]; - if ( priv->dev->minor_drv < resources_cnt ) { - priv->config.resources = gr_cpci_gr740_resources[priv->dev->minor_drv]; - } else { - priv->config.resources = NULL; - } - - /* Create and register AMBA PnP bus. */ - return ambapp_bus_register(dev, &priv->config); -} - -int gr_cpci_gr740_init2(struct drvmgr_dev *dev) -{ - struct gr_cpci_gr740_priv *priv = dev->priv; - - /* Clear any old interrupt requests */ - drvmgr_interrupt_clear(dev, 0); - - /* Enable System IRQ so that GR-CPCI-GR740 PCI target interrupt - * goes through. - * - * It is important to enable it in stage init2. If interrupts were - * enabled in init1 this might hang the system when more than one - * PCI board is connected, this is because PCI interrupts might - * be shared and PCI board 2 have not initialized and - * might therefore drive interrupt already when entering init1(). - */ - drvmgr_interrupt_register( - dev, - 0, - "gr_cpci_gr740", - gr_cpci_gr740_isr, - (void *)priv); - - return gr_cpci_gr740_hw_init2(priv); -} - -int ambapp_gr740_int_register( - struct drvmgr_dev *dev, - int irq, - const char *info, - drvmgr_isr handler, - void *arg) -{ - struct gr_cpci_gr740_priv *priv = dev->parent->dev->priv; - SPIN_IRQFLAGS(irqflags); - int status; - void *h; - - h = genirq_alloc_handler(handler, arg); - if ( h == NULL ) - return DRVMGR_FAIL; - - SPIN_LOCK_IRQ(&priv->devlock, irqflags); - - status = genirq_register(priv->genirq, irq, h); - if (status == 0) { - /* Clear IRQ for first registered handler */ - priv->irq->iclear = (1<devlock, irqflags); - genirq_free_handler(h); - return DRVMGR_FAIL; - } - - status = genirq_enable(priv->genirq, irq, handler, arg); - if ( status == 0 ) { - /* Enable IRQ for first enabled handler only */ - priv->irq->mask[0] |= (1<devlock, irqflags); - - return status; -} - -int ambapp_gr740_int_unregister( - struct drvmgr_dev *dev, - int irq, - drvmgr_isr isr, - void *arg) -{ - struct gr_cpci_gr740_priv *priv = dev->parent->dev->priv; - SPIN_IRQFLAGS(irqflags); - int status; - void *handler; - - SPIN_LOCK_IRQ(&priv->devlock, irqflags); - - status = genirq_disable(priv->genirq, irq, isr, arg); - if ( status == 0 ) { - /* Disable IRQ only when no enabled handler exists */ - priv->irq->mask[0] &= ~(1<genirq, irq, isr, arg); - if ( handler == NULL ) - status = DRVMGR_FAIL; - else - status = DRVMGR_OK; - - SPIN_UNLOCK_IRQ(&priv->devlock, irqflags); - - if (handler) - genirq_free_handler(handler); - - return status; -} - -int ambapp_gr740_int_unmask( - struct drvmgr_dev *dev, - int irq) -{ - struct gr_cpci_gr740_priv *priv = dev->parent->dev->priv; - SPIN_IRQFLAGS(irqflags); - - DBG("GR740 IRQ %d: unmask\n", irq); - - if ( genirq_check(priv->genirq, irq) ) - return DRVMGR_EINVAL; - - SPIN_LOCK_IRQ(&priv->devlock, irqflags); - - /* Enable IRQ for first enabled handler only */ - priv->irq->mask[0] |= (1<devlock, irqflags); - - return DRVMGR_OK; -} - -int ambapp_gr740_int_mask( - struct drvmgr_dev *dev, - int irq) -{ - struct gr_cpci_gr740_priv *priv = dev->parent->dev->priv; - SPIN_IRQFLAGS(irqflags); - - DBG("GR740 IRQ %d: mask\n", irq); - - if ( genirq_check(priv->genirq, irq) ) - return DRVMGR_EINVAL; - - SPIN_LOCK_IRQ(&priv->devlock, irqflags); - - /* Disable/mask IRQ */ - priv->irq->mask[0] &= ~(1<devlock, irqflags); - - return DRVMGR_OK; -} - -int ambapp_gr740_int_clear( - struct drvmgr_dev *dev, - int irq) -{ - struct gr_cpci_gr740_priv *priv = dev->parent->dev->priv; - - if ( genirq_check(priv->genirq, irq) ) - return DRVMGR_EINVAL; - - priv->irq->iclear = (1<parent->dev->priv; - - /* Device name prefix pointer, skip /dev */ - params->dev_prefix = &priv->prefix[5]; - - return 0; -} - -void gr_cpci_gr740_print_dev(struct drvmgr_dev *dev, int options) -{ - struct gr_cpci_gr740_priv *priv = dev->priv; - struct pci_dev_info *devinfo = priv->devinfo; - uint32_t bar0, bar0_size; - - /* Print */ - printf("--- GR-CPCI-GR740 [bus 0x%x, dev 0x%x, fun 0x%x] ---\n", - PCI_DEV_EXPAND(priv->pcidev)); - - bar0 = devinfo->resources[0].address; - bar0_size = devinfo->resources[0].size; - printf(" PCI BAR[0]: 0x%lx - 0x%lx\n", bar0, bar0 + bar0_size - 1); - printf(" IRQ REGS: 0x%x\n", (unsigned int)priv->irq); - printf(" IRQ: %d\n", devinfo->irq); - printf(" PCI REVISION: %d\n", devinfo->rev); - printf(" FREQ: %d Hz\n", priv->amba_freq_hz); - printf(" IMASK: 0x%08x\n", priv->irq->mask[0]); - printf(" IPEND: 0x%08x\n", priv->irq->ipend); - - /* Print amba config */ - if (options & GR_CPCI_GR740_OPTIONS_AMBA) - ambapp_print(&priv->abus, 10); -} - -void gr_cpci_gr740_print(int options) -{ - struct pci_drv_info *drv = &gr_cpci_gr740_info; - struct drvmgr_dev *dev; - - dev = drv->general.dev; - while(dev) { - gr_cpci_gr740_print_dev(dev, options); - dev = dev->next_in_drv; - } -} diff --git a/c/src/lib/libbsp/sparc/shared/pci/gr_leon4_n2x.c b/c/src/lib/libbsp/sparc/shared/pci/gr_leon4_n2x.c deleted file mode 100644 index cb78de4032..0000000000 --- a/c/src/lib/libbsp/sparc/shared/pci/gr_leon4_n2x.c +++ /dev/null @@ -1,795 +0,0 @@ -/* GR-CPCI-LEON4-N2X (NGFP) PCI Peripheral driver - * - * COPYRIGHT (c) 2013. - * Cobham Gaisler AB. - * - * 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. - * - * Configures the GR-CPIC-LEON4-N2X interface PCI board in peripheral - * mode. This driver provides a AMBA PnP bus by using the general part - * of the AMBA PnP bus driver (ambapp_bus.c). - * - * - * Driver resource options: - * NAME DEFAULT VALUE - * ahbmst2pci _RAM_START AMBA->PCI translation PCI base address - * ambaFreq 200000000 (200MHz) AMBA system frequency of LEON4-N2X - * cgEnMask 0x1f (all) Clock gating enable mask - * - * TODO/UNTESTED - * Interrupt testing - * bar0 RESOURCE 0x00000000 L2-Cache SDRAM memory - * bar1 RESOURCE 0xf0000000 L2-Cache registers - */ - -#include -#include -#include -#include -#include - -#include -#include -#include /* spin-lock */ -#include - -#include -#include -#include -#include -#include -#include -#include - -#include - -/* map via rtems_interrupt_lock_* API: */ -#define SPIN_DECLARE(lock) RTEMS_INTERRUPT_LOCK_MEMBER(lock) -#define SPIN_INIT(lock, name) rtems_interrupt_lock_initialize(lock, name) -#define SPIN_LOCK(lock, level) rtems_interrupt_lock_acquire_isr(lock, &level) -#define SPIN_LOCK_IRQ(lock, level) rtems_interrupt_lock_acquire(lock, &level) -#define SPIN_UNLOCK(lock, level) rtems_interrupt_lock_release_isr(lock, &level) -#define SPIN_UNLOCK_IRQ(lock, level) rtems_interrupt_lock_release(lock, &level) -#define SPIN_IRQFLAGS(k) rtems_interrupt_lock_context k -#define SPIN_ISR_IRQFLAGS(k) SPIN_IRQFLAGS(k) - -/* Determines which PCI address the AHB masters on the LEON-N2X board will - * access when accessing the AHB to PCI window, it should be set so that the - * masters can access the HOST RAM. - * Default is base of HOST RAM, HOST RAM is mapped 1:1 to PCI memory space. - */ -extern unsigned int _RAM_START; -#define AHBMST2PCIADR (((unsigned int)&_RAM_START) & 0xc0000000) - -#define GRPCI2_BAR0_TO_AHB_MAP 0x04 -#define GRPCI2_BAR1_TO_AHB_MAP 0x08 -#define GRPCI2_BAR2_TO_AHB_MAP 0x0c -#define GRPCI2_PCI_CONFIG 0x20 -#define CAP9_AHBPREF_OFS 0x3c - -/* #define DEBUG 1 */ - -#ifdef DEBUG -#define DBG(x...) printk(x) -#else -#define DBG(x...) -#endif - -int gr_cpci_leon4_n2x_init1(struct drvmgr_dev *dev); -int gr_cpci_leon4_n2x_init2(struct drvmgr_dev *dev); -void gr_cpci_leon4_n2x_isr(void *arg); - -struct grpci2_regs { - volatile unsigned int ctrl; /* 0x00 */ - volatile unsigned int sts_cap; /* 0x04 */ - volatile unsigned int ppref; /* 0x08 */ - volatile unsigned int io_map; /* 0x0C */ - volatile unsigned int dma_ctrl; /* 0x10 */ - volatile unsigned int dma_bdbase; /* 0x14 */ - volatile unsigned int dma_chact; /* 0x18 */ - int res1; /* 0x1C */ - volatile unsigned int bars[6]; /* 0x20 */ - int res2[2]; /* 0x38 */ - volatile unsigned int ahbmst_map[16]; /* 0x40 */ -}; - -/* Clock gating unit register layout */ -struct l4n2x_grcg_regs { - volatile unsigned int unlock; - volatile unsigned int enable; - volatile unsigned int reset; - volatile unsigned int cpu_fpu; -}; -#define CG_MASK 0x1f - -/* Private data structure for driver */ -struct gr_cpci_leon4_n2x_priv { - /* Driver management */ - struct drvmgr_dev *dev; - char prefix[20]; - SPIN_DECLARE(devlock); - - /* PCI */ - pci_dev_t pcidev; - struct pci_dev_info *devinfo; - uint32_t ahbmst2pci_map; - - /* IRQ */ - int eirq; - genirq_t genirq; - - /* GR-CPCI-LEON4-N2X */ - unsigned int amba_freq_hz; - unsigned int cg_en_mask; /* Enabled cores */ - struct irqmp_regs *irq; - struct l4n2x_grcg_regs *cg; /* Clock-gating unit */ - struct grpci2_regs *grpci2; - struct drvmgr_map_entry bus_maps_up[2]; - struct drvmgr_map_entry bus_maps_down[4]; - - /* AMBA Plug&Play information on GR-CPCI-LEON4-N2X */ - struct ambapp_bus abus; - struct ambapp_mmap amba_maps[5]; - struct ambapp_config config; -}; - -int ambapp_leon4_n2x_int_register( - struct drvmgr_dev *dev, - int irq, - const char *info, - drvmgr_isr handler, - void *arg); -int ambapp_leon4_n2x_int_unregister( - struct drvmgr_dev *dev, - int irq, - drvmgr_isr handler, - void *arg); -int ambapp_leon4_n2x_int_unmask( - struct drvmgr_dev *dev, - int irq); -int ambapp_leon4_n2x_int_mask( - struct drvmgr_dev *dev, - int irq); -int ambapp_leon4_n2x_int_clear( - struct drvmgr_dev *dev, - int irq); -int ambapp_leon4_n2x_get_params( - struct drvmgr_dev *dev, - struct drvmgr_bus_params *params); - -static struct ambapp_ops ambapp_leon4_n2x_ops = { - .int_register = ambapp_leon4_n2x_int_register, - .int_unregister = ambapp_leon4_n2x_int_unregister, - .int_unmask = ambapp_leon4_n2x_int_unmask, - .int_mask = ambapp_leon4_n2x_int_mask, - .int_clear = ambapp_leon4_n2x_int_clear, - .get_params = ambapp_leon4_n2x_get_params -}; - -struct drvmgr_drv_ops gr_cpci_leon4_n2x_ops = -{ - .init = {gr_cpci_leon4_n2x_init1, gr_cpci_leon4_n2x_init2, NULL, NULL}, - .remove = NULL, - .info = NULL -}; - -struct pci_dev_id_match gr_cpci_leon4_n2x_ids[] = -{ - PCIID_DEVVEND(PCIID_VENDOR_GAISLER, PCIID_DEVICE_GR_LEON4_N2X), - PCIID_DEVVEND(PCIID_VENDOR_GAISLER, PCIID_DEVICE_GR_NGMP_PROTO), - PCIID_END_TABLE /* Mark end of table */ -}; - -struct pci_drv_info gr_cpci_leon4_n2x_info = -{ - { - DRVMGR_OBJ_DRV, /* Driver */ - NULL, /* Next driver */ - NULL, /* Device list */ - DRIVER_PCI_GAISLER_LEON4_N2X_ID,/* Driver ID */ - "GR-CPCI-LEON4-N2X", /* Driver Name */ - DRVMGR_BUS_TYPE_PCI, /* Bus Type */ - &gr_cpci_leon4_n2x_ops, - NULL, /* Funcs */ - 0, /* No devices yet */ - sizeof(struct gr_cpci_leon4_n2x_priv), - }, - &gr_cpci_leon4_n2x_ids[0] -}; - -/* Driver resources configuration for the AMBA bus on the GR-CPCI-LEON4-N2X board. - * It is declared weak so that the user may override it from the project file, - * if the default settings are not enough. - * - * The configuration consists of an array of configuration pointers, each - * pointer determine the configuration of one GR-CPCI-LEON4-N2X board. Pointer - * zero is for board0, pointer 1 for board1 and so on. - * - * The array must end with a NULL pointer. - */ -struct drvmgr_bus_res *gr_leon4_n2x_resources[] __attribute__((weak)) = -{ - NULL -}; - -void gr_cpci_leon4_n2x_register_drv(void) -{ - DBG("Registering GR-CPCI-LEON4-N2X PCI driver\n"); - drvmgr_drv_register(&gr_cpci_leon4_n2x_info.general); -} - -void gr_cpci_leon4_n2x_isr(void *arg) -{ - struct gr_cpci_leon4_n2x_priv *priv = arg; - unsigned int status, tmp; - int irq, eirq; - SPIN_ISR_IRQFLAGS(irqflags); - - tmp = status = priv->irq->ipend; - - /* DBG("GR-CPCI-LEON4-N2X: IRQ 0x%x\n",status); */ - - SPIN_LOCK(&priv->devlock, irqflags); - for(irq = 0; irq < 32; irq++) { - if (status & (1 << irq)) { - if (irq == priv->eirq) { - while ((eirq = priv->irq->intid[0] & 0x1f)) { - if ((eirq & 0x10) == 0) - continue; - genirq_doirq(priv->genirq, eirq); - priv->irq->iclear = (1 << eirq); - } - } else { - genirq_doirq(priv->genirq, irq); - } - priv->irq->iclear = (1 << irq); - status &= ~(1 << irq); - if ( status == 0 ) - break; - } - } - SPIN_UNLOCK(&priv->devlock, irqflags); - - /* ACK interrupt, this is because PCI is Level, so the IRQ Controller - * still drives the IRQ - */ - if ( tmp ) - drvmgr_interrupt_clear(priv->dev, 0); - - DBG("GR-CPCI-LEON4-N2X-IRQ: 0x%x\n", tmp); -} - -static int gr_cpci_leon4_n2x_hw_init1(struct gr_cpci_leon4_n2x_priv *priv) -{ - int i; - uint32_t data; - unsigned int ctrl; - uint8_t tmp2; - struct ambapp_dev *tmp; - struct ambapp_ahb_info *ahb; - uint8_t cap_ptr; - pci_dev_t pcidev = priv->pcidev; - struct pci_dev_info *devinfo = priv->devinfo; - unsigned int cgmask, enabled; - - /* Check capabilities list bit and read its pointer */ - pci_cfg_r8(pcidev, PCIR_STATUS, &tmp2); - if (!((tmp2 >> 4) & 1)) { - /* Capabilities list not available which it should be in the GRPCI2 */ - return -2; - } - pci_cfg_r8(pcidev, PCIR_CAP_PTR, &cap_ptr); - - /* Workarounds depends on PCI revision of GR-CPCI-LEON4-N2X board */ - switch (devinfo->rev) { - case 0: - /* Limit the AMBA prefetch for GRPCI2 version 0. */ - pci_cfg_w32(pcidev, cap_ptr+CAP9_AHBPREF_OFS, 0); - default: - break; - } - - /* Set AHB address mappings for target PCI bars - * BAR0 maps to 0x00000000-0x07ffffff 128MB (SDRAM/DDR2 memory) - * BAR1 maps to 0xf0000000-0xf7ffffff 128MB (L2-Cache regs/diagnostics) - * BAR2 maps to 0xff800000-0xffffffff 8MB (PnP, I/O regs) - */ - pci_cfg_w32(pcidev, cap_ptr+GRPCI2_BAR0_TO_AHB_MAP, 0x00000000); - pci_cfg_w32(pcidev, cap_ptr+GRPCI2_BAR1_TO_AHB_MAP, 0xf0000000); - pci_cfg_w32(pcidev, cap_ptr+GRPCI2_BAR2_TO_AHB_MAP, 0xff800000); - - /* Set PCI bus to be big endian */ - pci_cfg_r32(pcidev, cap_ptr+GRPCI2_PCI_CONFIG, &data); - data = data & 0xFFFFFFFE; - pci_cfg_w32(pcidev, cap_ptr+GRPCI2_PCI_CONFIG, data); - -#if 0 - /* set parity error response */ - pci_cfg_r32(pcidev, PCIR_COMMAND, &data); - pci_cfg_w32(pcidev, PCIR_COMMAND, (data|PCIM_CMD_PERRESPEN)); -#endif - - /* Scan AMBA Plug&Play */ - - /* AMBA MAP bar0 (in leon4-n2x) ==> 0x00000000 (remote amba address) */ - priv->amba_maps[0].size = devinfo->resources[0].size; - priv->amba_maps[0].local_adr = devinfo->resources[0].address; - priv->amba_maps[0].remote_adr = 0x00000000; - - priv->amba_maps[1].size = devinfo->resources[1].size; - priv->amba_maps[1].local_adr = devinfo->resources[1].address; - priv->amba_maps[1].remote_adr = 0xf0000000; - - priv->amba_maps[2].size = devinfo->resources[2].size; - priv->amba_maps[2].local_adr = devinfo->resources[2].address; - priv->amba_maps[2].remote_adr = 0xff800000; - - /* Addresses not matching with map be untouched */ - priv->amba_maps[3].size = 0xfffffff0; - priv->amba_maps[3].local_adr = 0; - priv->amba_maps[3].remote_adr = 0; - - /* Mark end of table */ - priv->amba_maps[4].size=0; - - /* Start AMBA PnP scan at first AHB bus */ - ambapp_scan( - &priv->abus, - devinfo->resources[2].address + 0x00700000, - NULL, - &priv->amba_maps[0]); - - /* Initialize Frequency of AMBA bus */ - ambapp_freq_init(&priv->abus, NULL, priv->amba_freq_hz); - - /* Find IRQ controller, Clear all current IRQs */ - tmp = (struct ambapp_dev *)ambapp_for_each(&priv->abus, - (OPTIONS_ALL|OPTIONS_APB_SLVS), - VENDOR_GAISLER, GAISLER_IRQMP, - ambapp_find_by_idx, NULL); - if ( !tmp ) { - return -4; - } - priv->irq = (struct irqmp_regs *)DEV_TO_APB(tmp)->start; - /* Set up GR-CPCI-LEON4-N2X irq controller - * Interrupts are routed from IRQCtrl0, we leave the configuration - * for the other CPUs, as the board's CPUs may be running something. - * We assume IRQCtrl has been set up properly, or at least the reset - * values shuold work with this code.. - */ - priv->irq->mask[0] = 0; - priv->irq->iforce = 0; - priv->irq->force[0] = 0; - priv->irq->ilevel = 0; - priv->irq->ipend = 0; - priv->irq->iclear = 0xffffffff; - priv->irq->ilevel = 0; - /* Get extended Interrupt controller IRQ number */ - priv->eirq = (priv->irq->mpstat >> 16) & 0xf; - - /* Find first Clock-Gating unit, enable/disable the requested cores. - * It is optional in order to support FPGA prototypes. - */ - priv->cg = NULL; - tmp = (struct ambapp_dev *)ambapp_for_each(&priv->abus, - (OPTIONS_ALL|OPTIONS_APB_SLVS), - VENDOR_GAISLER, GAISLER_CLKGATE, - ambapp_find_by_idx, NULL); - if (tmp) - priv->cg = (struct l4n2x_grcg_regs *)DEV_TO_APB(tmp)->start; - - /* Do reset and enable sequence only if not already enabled */ - if (priv->cg && ((enabled = priv->cg->enable) != priv->cg_en_mask)) { - /* First disable already enabled cores */ - cgmask = ~priv->cg_en_mask & enabled; - if (cgmask) { - priv->cg->unlock = cgmask; - priv->cg->enable = enabled = ~cgmask & enabled; - priv->cg->unlock = 0; - } - /* Enable disabled cores */ - cgmask = priv->cg_en_mask & ~enabled; - if (cgmask) { - priv->cg->unlock = cgmask; - priv->cg->reset |= cgmask; - priv->cg->enable = cgmask | enabled; - priv->cg->reset &= ~cgmask; - priv->cg->unlock = 0; - } - } - - priv->bus_maps_down[0].name = "PCI BAR0 -> AMBA"; - priv->bus_maps_down[0].size = priv->amba_maps[0].size; - priv->bus_maps_down[0].from_adr = (void *)priv->amba_maps[0].local_adr; - priv->bus_maps_down[0].to_adr = (void *)priv->amba_maps[0].remote_adr; - priv->bus_maps_down[1].name = "PCI BAR1 -> AMBA"; - priv->bus_maps_down[1].size = priv->amba_maps[1].size; - priv->bus_maps_down[1].from_adr = (void *)priv->amba_maps[1].local_adr; - priv->bus_maps_down[1].to_adr = (void *)priv->amba_maps[1].remote_adr; - priv->bus_maps_down[2].name = "PCI BAR2 -> AMBA"; - priv->bus_maps_down[2].size = priv->amba_maps[2].size; - priv->bus_maps_down[2].from_adr = (void *)priv->amba_maps[2].local_adr; - priv->bus_maps_down[2].to_adr = (void *)priv->amba_maps[2].remote_adr; - priv->bus_maps_down[3].size = 0; - - /* Find GRPCI2 controller AHB Slave interface */ - tmp = (struct ambapp_dev *)ambapp_for_each(&priv->abus, - (OPTIONS_ALL|OPTIONS_AHB_SLVS), - VENDOR_GAISLER, GAISLER_GRPCI2, - ambapp_find_by_idx, NULL); - if ( !tmp ) { - return -6; - } - ahb = (struct ambapp_ahb_info *)tmp->devinfo; - priv->bus_maps_up[0].name = "AMBA GRPCI2 Window"; - priv->bus_maps_up[0].size = ahb->mask[0]; /* AMBA->PCI Window on GR-CPCI-LEON4-N2X board */ - priv->bus_maps_up[0].from_adr = (void *)ahb->start[0]; - priv->bus_maps_up[0].to_adr = (void *) - (priv->ahbmst2pci_map & ~(ahb->mask[0]-1)); - priv->bus_maps_up[1].size = 0; - - /* Find GRPCI2 controller APB Slave interface */ - tmp = (struct ambapp_dev *)ambapp_for_each(&priv->abus, - (OPTIONS_ALL|OPTIONS_APB_SLVS), - VENDOR_GAISLER, GAISLER_GRPCI2, - ambapp_find_by_idx, NULL); - if ( !tmp ) { - return -7; - } - priv->grpci2 = (struct grpci2_regs *) - ((struct ambapp_apb_info *)tmp->devinfo)->start; - - /* Workarounds depends on PCI revision of GR-CPCI-LEON4-N2X board */ - switch (devinfo->rev) { - case 0: - /* Limit the PCI master prefetch for GRPCI2 version 0. - * This fix is required only when PCI Host bridge is - * GRPCI2 rev 0. - */ - priv->grpci2->ppref = 0xffff0000; - default: - break; - } - - /* Set AHB to PCI mapping for all AMBA AHB masters */ - for(i = 0; i < 16; i++) { - priv->grpci2->ahbmst_map[i] = priv->ahbmst2pci_map & - ~(ahb->mask[0]-1); - } - - /* Make sure dirq(0) sampling is enabled */ - ctrl = priv->grpci2->ctrl; - ctrl = (ctrl & 0xFFFFFF0F) | (1 << 4); - priv->grpci2->ctrl = ctrl; - - /* Successfully registered the LEON4-N2X board */ - return 0; -} - -static int gr_cpci_leon4_n2x_hw_init2(struct gr_cpci_leon4_n2x_priv *priv) -{ - /* Enable DMA by enabling PCI target as master */ - pci_master_enable(priv->pcidev); - - return DRVMGR_OK; -} - -/* Called when a PCI target is found with the PCI device and vendor ID - * given in gr_cpci_leon4_n2x_ids[]. - */ -int gr_cpci_leon4_n2x_init1(struct drvmgr_dev *dev) -{ - struct gr_cpci_leon4_n2x_priv *priv; - struct pci_dev_info *devinfo; - int status, i; - union drvmgr_key_value *value; - int resources_cnt; - - priv = dev->priv; - if (!priv) - return DRVMGR_NOMEM; - - memset(priv, 0, sizeof(*priv)); - dev->priv = priv; - priv->dev = dev; - - /* Determine number of configurations */ - resources_cnt = get_resarray_count(gr_leon4_n2x_resources); - - /* Generate Device prefix */ - - strcpy(priv->prefix, "/dev/leon4n2x0"); - priv->prefix[13] += dev->minor_drv; - mkdir(priv->prefix, S_IRWXU | S_IRWXG | S_IRWXO); - priv->prefix[14] = '/'; - priv->prefix[15] = '\0'; - - priv->devinfo = devinfo = (struct pci_dev_info *)dev->businfo; - priv->pcidev = devinfo->pcidev; - printf("\n\n--- GR-CPCI-LEON4-N2X[%d] ---\n", dev->minor_drv); - printf(" PCI BUS: 0x%x, SLOT: 0x%x, FUNCTION: 0x%x\n", - PCI_DEV_EXPAND(priv->pcidev)); - printf(" PCI VENDOR: 0x%04x, DEVICE: 0x%04x\n", - devinfo->id.vendor, devinfo->id.device); - for (i = 0; i < 3; i++) { - printf(" PCI BAR[%d]: 0x%08lx - 0x%08lx\n", - i, devinfo->resources[i].address, - devinfo->resources[i].address + - (devinfo->resources[i].size - 1)); - /* all neccessary space assigned to GR-CPCI-LEON4-N2X target? */ - if (devinfo->resources[i].size == 0) - return DRVMGR_ENORES; - } - printf(" IRQ: %d\n\n\n", devinfo->irq); - - /* Initialize spin-lock for this PCI perihperal device. This is to - * protect the Interrupt Controller Registers. The genirq layer is - * protecting its own internals and ISR dispatching. - */ - SPIN_INIT(&priv->devlock, priv->prefix); - - /* Let user override which PCI address the AHB masters of the - * LEON4-N2X board access when doing DMA to HOST RAM. The AHB masters - * access the PCI Window of the AMBA bus, the MSB 2-bits of that address - * is translated according this config option before the address goes - * out on the PCI bus. - * - * Only the 2 MSB bits have an effect. - */ - value = drvmgr_dev_key_get(priv->dev, "ahbmst2pci", DRVMGR_KT_INT); - if (value) - priv->ahbmst2pci_map = value->i; - else - priv->ahbmst2pci_map = AHBMST2PCIADR; /* default */ - - /* Let user override the default AMBA system frequency of the - * CPU-bus of the remote GR-CPCI-LEON4-N2X. Default is 200MHz. - */ - value = drvmgr_dev_key_get(priv->dev, "ambaFreq", DRVMGR_KT_INT); - if (value) - priv->amba_freq_hz = value->i; - else - priv->amba_freq_hz = 200000000; /* default */ - - /* Let user determine clock-gating unit configuration. The default - * is to turn all cores on (disable gating). PCI is always turned ON. - */ - value = drvmgr_dev_key_get(priv->dev, "cgEnMask", DRVMGR_KT_INT); - if (value) - priv->cg_en_mask = (value->i & CG_MASK) | 0x08; - else - priv->cg_en_mask = CG_MASK; /* default all ON */ - - priv->genirq = genirq_init(32); - if (priv->genirq == NULL) - return DRVMGR_FAIL; - - if ((status = gr_cpci_leon4_n2x_hw_init1(priv)) != 0) { - genirq_destroy(priv->genirq); - printf(" Failed to initialize GR-CPCI-LEON4-N2X HW: %d\n", status); - return DRVMGR_FAIL; - } - - /* Init amba bus */ - priv->config.abus = &priv->abus; - priv->config.ops = &ambapp_leon4_n2x_ops; - priv->config.maps_up = &priv->bus_maps_up[0]; - priv->config.maps_down = &priv->bus_maps_down[0]; - if ( priv->dev->minor_drv < resources_cnt ) { - priv->config.resources = gr_leon4_n2x_resources[priv->dev->minor_drv]; - } else { - priv->config.resources = NULL; - } - - /* Create and register AMBA PnP bus. */ - return ambapp_bus_register(dev, &priv->config); -} - -int gr_cpci_leon4_n2x_init2(struct drvmgr_dev *dev) -{ - struct gr_cpci_leon4_n2x_priv *priv = dev->priv; - - /* Clear any old interrupt requests */ - drvmgr_interrupt_clear(dev, 0); - - /* Enable System IRQ so that GR-CPCI-LEON4-N2X PCI target interrupt - * goes through. - * - * It is important to enable it in stage init2. If interrupts were - * enabled in init1 this might hang the system when more than one - * PCI board is connected, this is because PCI interrupts might - * be shared and PCI board 2 have not initialized and - * might therefore drive interrupt already when entering init1(). - */ - drvmgr_interrupt_register( - dev, - 0, - "gr_cpci_leon4_n2x", - gr_cpci_leon4_n2x_isr, - (void *)priv); - - return gr_cpci_leon4_n2x_hw_init2(priv); -} - -int ambapp_leon4_n2x_int_register( - struct drvmgr_dev *dev, - int irq, - const char *info, - drvmgr_isr handler, - void *arg) -{ - struct gr_cpci_leon4_n2x_priv *priv = dev->parent->dev->priv; - SPIN_IRQFLAGS(irqflags); - int status; - void *h; - - h = genirq_alloc_handler(handler, arg); - if ( h == NULL ) - return DRVMGR_FAIL; - - SPIN_LOCK_IRQ(&priv->devlock, irqflags); - - status = genirq_register(priv->genirq, irq, h); - if (status == 0) { - /* Clear IRQ for first registered handler */ - priv->irq->iclear = (1<devlock, irqflags); - genirq_free_handler(h); - return DRVMGR_FAIL; - } - - status = genirq_enable(priv->genirq, irq, handler, arg); - if ( status == 0 ) { - /* Enable IRQ for first enabled handler only */ - priv->irq->mask[0] |= (1<devlock, irqflags); - - return status; -} - -int ambapp_leon4_n2x_int_unregister( - struct drvmgr_dev *dev, - int irq, - drvmgr_isr isr, - void *arg) -{ - struct gr_cpci_leon4_n2x_priv *priv = dev->parent->dev->priv; - SPIN_IRQFLAGS(irqflags); - int status; - void *handler; - - SPIN_LOCK_IRQ(&priv->devlock, irqflags); - - status = genirq_disable(priv->genirq, irq, isr, arg); - if ( status == 0 ) { - /* Disable IRQ only when no enabled handler exists */ - priv->irq->mask[0] &= ~(1<genirq, irq, isr, arg); - if ( handler == NULL ) - status = DRVMGR_FAIL; - else - status = DRVMGR_OK; - - SPIN_UNLOCK_IRQ(&priv->devlock, irqflags); - - if (handler) - genirq_free_handler(handler); - - return status; -} - -int ambapp_leon4_n2x_int_unmask( - struct drvmgr_dev *dev, - int irq) -{ - struct gr_cpci_leon4_n2x_priv *priv = dev->parent->dev->priv; - SPIN_IRQFLAGS(irqflags); - - DBG("LEON4-N2X IRQ %d: unmask\n", irq); - - if ( genirq_check(priv->genirq, irq) ) - return DRVMGR_EINVAL; - - SPIN_LOCK_IRQ(&priv->devlock, irqflags); - - /* Enable IRQ for first enabled handler only */ - priv->irq->mask[0] |= (1<devlock, irqflags); - - return DRVMGR_OK; -} - -int ambapp_leon4_n2x_int_mask( - struct drvmgr_dev *dev, - int irq) -{ - struct gr_cpci_leon4_n2x_priv *priv = dev->parent->dev->priv; - SPIN_IRQFLAGS(irqflags); - - DBG("LEON4-N2X IRQ %d: mask\n", irq); - - if ( genirq_check(priv->genirq, irq) ) - return DRVMGR_EINVAL; - - SPIN_LOCK_IRQ(&priv->devlock, irqflags); - - /* Disable/mask IRQ */ - priv->irq->mask[0] &= ~(1<devlock, irqflags); - - return DRVMGR_OK; -} - -int ambapp_leon4_n2x_int_clear( - struct drvmgr_dev *dev, - int irq) -{ - struct gr_cpci_leon4_n2x_priv *priv = dev->parent->dev->priv; - - if ( genirq_check(priv->genirq, irq) ) - return DRVMGR_EINVAL; - - priv->irq->iclear = (1<parent->dev->priv; - - /* Device name prefix pointer, skip /dev */ - params->dev_prefix = &priv->prefix[5]; - - return 0; -} - -void gr_cpci_leon4_n2x_print_dev(struct drvmgr_dev *dev, int options) -{ - struct gr_cpci_leon4_n2x_priv *priv = dev->priv; - struct pci_dev_info *devinfo = priv->devinfo; - uint32_t bar0, bar0_size; - - /* Print */ - printf("--- GR-CPCI-LEON4-N2X [bus 0x%x, dev 0x%x, fun 0x%x] ---\n", - PCI_DEV_EXPAND(priv->pcidev)); - - bar0 = devinfo->resources[0].address; - bar0_size = devinfo->resources[0].size; - printf(" PCI BAR[0]: 0x%lx - 0x%lx\n", bar0, bar0 + bar0_size - 1); - printf(" IRQ REGS: 0x%x\n", (unsigned int)priv->irq); - printf(" IRQ: %d\n", devinfo->irq); - printf(" PCI REVISION: %d\n", devinfo->rev); - printf(" FREQ: %d Hz\n", priv->amba_freq_hz); - printf(" IMASK: 0x%08x\n", priv->irq->mask[0]); - printf(" IPEND: 0x%08x\n", priv->irq->ipend); - - /* Print amba config */ - if (options & GR_LEON4_N2X_OPTIONS_AMBA) - ambapp_print(&priv->abus, 10); -} - -void gr_leon4_n2x_print(int options) -{ - struct pci_drv_info *drv = &gr_cpci_leon4_n2x_info; - struct drvmgr_dev *dev; - - dev = drv->general.dev; - while(dev) { - gr_cpci_leon4_n2x_print_dev(dev, options); - dev = dev->next_in_drv; - } -} diff --git a/c/src/lib/libbsp/sparc/shared/pci/gr_rasta_adcdac.c b/c/src/lib/libbsp/sparc/shared/pci/gr_rasta_adcdac.c deleted file mode 100644 index 6d1f8f130f..0000000000 --- a/c/src/lib/libbsp/sparc/shared/pci/gr_rasta_adcdac.c +++ /dev/null @@ -1,699 +0,0 @@ -/* GR-RASTA-ADCDAC PCI Target driver. - * - * COPYRIGHT (c) 2008. - * Cobham Gaisler AB. - * - * Configures the GR-RASTA-ADCDAC interface PCI board. - * This driver provides a AMBA PnP bus by using the general part - * of the AMBA PnP bus driver (ambapp_bus.c). - * - * Driver resources for the AMBA PnP bus provided can be set using - * gr_rasta_adcdac_set_resources(). - * - * 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 -#include -#include /* spin-lock */ -#include - -#include -#include -#include -#include -#include -#include -#include - -#include - -/* map via rtems_interrupt_lock_* API: */ -#define SPIN_DECLARE(lock) RTEMS_INTERRUPT_LOCK_MEMBER(lock) -#define SPIN_INIT(lock, name) rtems_interrupt_lock_initialize(lock, name) -#define SPIN_LOCK(lock, level) rtems_interrupt_lock_acquire_isr(lock, &level) -#define SPIN_LOCK_IRQ(lock, level) rtems_interrupt_lock_acquire(lock, &level) -#define SPIN_UNLOCK(lock, level) rtems_interrupt_lock_release_isr(lock, &level) -#define SPIN_UNLOCK_IRQ(lock, level) rtems_interrupt_lock_release(lock, &level) -#define SPIN_IRQFLAGS(k) rtems_interrupt_lock_context k -#define SPIN_ISR_IRQFLAGS(k) SPIN_IRQFLAGS(k) - -/*#define DEBUG 1*/ - -#ifdef DEBUG -#define DBG(x...) printk(x) -#else -#define DBG(x...) -#endif - -/* Determines which PCI address the AHB masters will access, it should be - * set so that the masters can access the CPU RAM. Default is base of CPU RAM, - * CPU RAM is mapped 1:1 to PCI space. - */ -extern unsigned int _RAM_START; -#define AHBMST2PCIADR (((unsigned int)&_RAM_START) & 0xf0000000) - -/* PCI ID */ -#define PCIID_VENDOR_GAISLER 0x1AC8 -#define PCIID_DEVICE_GR_RASTA_ADCDAC 0x0014 - -int gr_rasta_adcdac_init1(struct drvmgr_dev *dev); -int gr_rasta_adcdac_init2(struct drvmgr_dev *dev); -void gr_rasta_adcdac_isr (void *arg); - -struct grpci_regs { - volatile unsigned int cfg_stat; - volatile unsigned int bar0; - volatile unsigned int page0; - volatile unsigned int bar1; - volatile unsigned int page1; - volatile unsigned int iomap; - volatile unsigned int stat_cmd; -}; - -struct gr_rasta_adcdac_ver { - const unsigned int amba_freq_hz; /* The frequency */ - const unsigned int amba_ioarea; /* The address where the PnP IOAREA starts at */ -}; - -/* Private data structure for driver */ -struct gr_rasta_adcdac_priv { - /* Driver management */ - struct drvmgr_dev *dev; - char prefix[20]; - SPIN_DECLARE(devlock); - - /* PCI */ - pci_dev_t pcidev; - struct pci_dev_info *devinfo; - uint32_t ahbmst2pci_map; - - /* IRQ */ - genirq_t genirq; - - /* GR-RASTA-ADCDAC */ - struct gr_rasta_adcdac_ver *version; - struct irqmp_regs *irq; - struct grpci_regs *grpci; - struct drvmgr_map_entry bus_maps_down[3]; - struct drvmgr_map_entry bus_maps_up[2]; - - /* AMBA Plug&Play information on GR-RASTA-ADCDAC */ - struct ambapp_bus abus; - struct ambapp_mmap amba_maps[4]; - struct ambapp_config config; -}; - -struct gr_rasta_adcdac_ver gr_rasta_adcdac_ver0 = { - .amba_freq_hz = 50000000, - .amba_ioarea = 0x80100000, -}; - -int ambapp_rasta_adcdac_int_register( - struct drvmgr_dev *dev, - int irq, - const char *info, - drvmgr_isr handler, - void *arg); -int ambapp_rasta_adcdac_int_unregister( - struct drvmgr_dev *dev, - int irq, - drvmgr_isr isr, - void *arg); -int ambapp_rasta_adcdac_int_unmask( - struct drvmgr_dev *dev, - int irq); -int ambapp_rasta_adcdac_int_mask( - struct drvmgr_dev *dev, - int irq); -int ambapp_rasta_adcdac_int_clear( - struct drvmgr_dev *dev, - int irq); -int ambapp_rasta_adcdac_get_params( - struct drvmgr_dev *dev, - struct drvmgr_bus_params *params); - -struct ambapp_ops ambapp_rasta_adcdac_ops = { - .int_register = ambapp_rasta_adcdac_int_register, - .int_unregister = ambapp_rasta_adcdac_int_unregister, - .int_unmask = ambapp_rasta_adcdac_int_unmask, - .int_mask = ambapp_rasta_adcdac_int_mask, - .int_clear = ambapp_rasta_adcdac_int_clear, - .get_params = ambapp_rasta_adcdac_get_params -}; - -struct drvmgr_drv_ops gr_rasta_adcdac_ops = -{ .init = {gr_rasta_adcdac_init1, gr_rasta_adcdac_init2, NULL, NULL}, - .remove = NULL, - .info = NULL -}; - -struct pci_dev_id_match gr_rasta_adcdac_ids[] = -{ - PCIID_DEVVEND(PCIID_VENDOR_GAISLER, PCIID_DEVICE_GR_RASTA_ADCDAC), - PCIID_END_TABLE /* Mark end of table */ -}; - -struct pci_drv_info gr_rasta_adcdac_info = -{ - { - DRVMGR_OBJ_DRV, /* Driver */ - NULL, /* Next driver */ - NULL, /* Device list */ - DRIVER_PCI_GAISLER_RASTAADCDAC_ID,/* Driver ID */ - "GR-RASTA-ADCDAC_DRV", /* Driver Name */ - DRVMGR_BUS_TYPE_PCI, /* Bus Type */ - &gr_rasta_adcdac_ops, - NULL, /* Funcs */ - 0, /* No devices yet */ - 0, - }, - &gr_rasta_adcdac_ids[0] -}; - -/* Driver resources configuration for the AMBA bus on the GR-RASTA-ADCDAC board. - * It is declared weak so that the user may override it from the project file, - * if the default settings are not enough. - * - * The configuration consists of an array of configuration pointers, each - * pointer determine the configuration of one GR-RASTA-ADCDAC board. Pointer - * zero is for board0, pointer 1 for board1 and so on. - * - * The array must end with a NULL pointer. - */ -struct drvmgr_bus_res *gr_rasta_adcdac_resources[] __attribute__((weak)) = -{ - NULL -}; - -void gr_rasta_adcdac_register_drv(void) -{ - DBG("Registering GR-RASTA-ADCDAC PCI driver\n"); - drvmgr_drv_register(&gr_rasta_adcdac_info.general); -} - -void gr_rasta_adcdac_isr (void *arg) -{ - struct gr_rasta_adcdac_priv *priv = arg; - unsigned int status, tmp; - int irq; - SPIN_ISR_IRQFLAGS(irqflags); - - tmp = status = priv->irq->ipend; - - /* DBG("GR-RASTA-ADCDAC: IRQ 0x%x\n",status); */ - - SPIN_LOCK(&priv->devlock, irqflags); - for(irq=0; irq<16; irq++) { - if ( status & (1<genirq, irq); - priv->irq->iclear = (1<devlock, irqflags); - - /* ACK interrupt, this is because PCI is Level, so the IRQ Controller still drives the IRQ. */ - if ( tmp ) - drvmgr_interrupt_clear(priv->dev, 0); - - DBG("RASTA-ADCDAC-IRQ: 0x%x\n", tmp); -} - -static int gr_rasta_adcdac_hw_init1(struct gr_rasta_adcdac_priv *priv) -{ - uint32_t data; - unsigned int *page0 = NULL; - struct ambapp_dev *tmp; - struct ambapp_ahb_info *ahb; - struct pci_dev_info *devinfo = priv->devinfo; - uint32_t bar0, bar0_size; - - /* Select version of GR-RASTA-ADCDAC board */ - switch (devinfo->rev) { - case 0: - priv->version = &gr_rasta_adcdac_ver0; - break; - default: - return -2; - } - - bar0 = devinfo->resources[0].address; - bar0_size = devinfo->resources[0].size; - page0 = (unsigned int *)(bar0 + bar0_size/2); - - /* Point PAGE0 to start of Plug and Play information */ - *page0 = priv->version->amba_ioarea & 0xf0000000; - - /* set parity error response */ - pci_cfg_r32(priv->pcidev, PCIR_COMMAND, &data); - pci_cfg_w32(priv->pcidev, PCIR_COMMAND, (data|PCIM_CMD_PERRESPEN)); - - /* Setup cache line size. Default cache line size will result in - * poor performance (256 word fetches), 0xff will set it according - * to the max size of the PCI FIFO. - */ - pci_cfg_w8(priv->pcidev, PCIR_CACHELNSZ, 0xff); - - /* Scan AMBA Plug&Play */ - - /* AMBA MAP bar0 (in CPU) ==> 0x80000000(remote amba address) */ - priv->amba_maps[0].size = bar0_size/2; - priv->amba_maps[0].local_adr = bar0; - priv->amba_maps[0].remote_adr = 0x80000000; - - /* AMBA MAP bar1 (in CPU) ==> 0x40000000(remote amba address) */ - priv->amba_maps[1].size = devinfo->resources[1].size; - priv->amba_maps[1].local_adr = devinfo->resources[1].address; - priv->amba_maps[1].remote_adr = 0x40000000; - - /* Addresses not matching with map be untouched */ - priv->amba_maps[2].size = 0xfffffff0; - priv->amba_maps[2].local_adr = 0; - priv->amba_maps[2].remote_adr = 0; - - /* Mark end of table */ - priv->amba_maps[3].size=0; - priv->amba_maps[3].local_adr = 0; - priv->amba_maps[3].remote_adr = 0; - - /* Start AMBA PnP scan at first AHB bus */ - /*ambapp_scan(priv->bar0 + (priv->version->amba_ioarea & ~0xf0000000), - NULL, &priv->amba_maps[0], NULL, &priv->abus.root, NULL);*/ - ambapp_scan(&priv->abus, - bar0 + (priv->version->amba_ioarea & ~0xf0000000), - NULL, &priv->amba_maps[0]); - - /* Initialize Frequency of AMBA bus */ - ambapp_freq_init(&priv->abus, NULL, priv->version->amba_freq_hz); - - /* Point PAGE0 to start of APB area */ - *page0 = 0x80000000; - - /* Find GRPCI controller */ - tmp = (struct ambapp_dev *)ambapp_for_each(&priv->abus, - (OPTIONS_ALL|OPTIONS_APB_SLVS), - VENDOR_GAISLER, GAISLER_PCIFBRG, - ambapp_find_by_idx, NULL); - if ( !tmp ) { - return -3; - } - priv->grpci = (struct grpci_regs *)((struct ambapp_apb_info *)tmp->devinfo)->start; - - /* Set GRPCI mmap so that AMBA masters can access CPU-RAM over - * the PCI window. - */ - priv->grpci->cfg_stat = (priv->grpci->cfg_stat & 0x0fffffff) | - (priv->ahbmst2pci_map & 0xf0000000); - priv->grpci->page1 = 0x40000000; - - /* Find IRQ controller */ - tmp = (struct ambapp_dev *)ambapp_for_each(&priv->abus, - (OPTIONS_ALL|OPTIONS_APB_SLVS), - VENDOR_GAISLER, GAISLER_IRQMP, - ambapp_find_by_idx, NULL); - if ( !tmp ) { - return -4; - } - priv->irq = (struct irqmp_regs *)DEV_TO_APB(tmp)->start; - /* Set up GR-RASTA-ADCDAC irq controller */ - priv->irq->iclear = 0xffff; - priv->irq->ilevel = 0; - priv->irq->mask[0] = 0; - - /* DOWN streams translation table */ - priv->bus_maps_down[0].name = "PCI BAR0 -> AMBA"; - priv->bus_maps_down[0].size = priv->amba_maps[0].size; - priv->bus_maps_down[0].from_adr = (void *)priv->amba_maps[0].local_adr; - priv->bus_maps_down[0].to_adr = (void *)priv->amba_maps[0].remote_adr; - - priv->bus_maps_down[1].name = "PCI BAR1 -> AMBA"; - priv->bus_maps_down[1].size = priv->amba_maps[1].size; - priv->bus_maps_down[1].from_adr = (void *)priv->amba_maps[1].local_adr; - priv->bus_maps_down[1].to_adr = (void *)priv->amba_maps[1].remote_adr; - - /* Mark end of translation table */ - priv->bus_maps_down[2].size = 0; - - /* Find GRPCI controller AHB Slave interface */ - tmp = (struct ambapp_dev *)ambapp_for_each(&priv->abus, - (OPTIONS_ALL|OPTIONS_AHB_SLVS), - VENDOR_GAISLER, GAISLER_PCIFBRG, - ambapp_find_by_idx, NULL); - if ( !tmp ) { - return -5; - } - ahb = (struct ambapp_ahb_info *)tmp->devinfo; - - /* UP streams translation table */ - priv->bus_maps_up[0].name = "AMBA GRPCI Window"; - priv->bus_maps_up[0].size = ahb->mask[0]; /* AMBA->PCI Window on GR-RASTA-ADCDAC board */ - priv->bus_maps_up[0].from_adr = (void *)ahb->start[0]; - priv->bus_maps_up[0].to_adr = (void *) - (priv->ahbmst2pci_map & 0xf0000000); - - /* Mark end of translation table */ - priv->bus_maps_up[1].size = 0; - - /* Successfully registered the RASTA board */ - return 0; -} - -static int gr_rasta_adcdac_hw_init2(struct gr_rasta_adcdac_priv *priv) -{ - /* Enable DMA by enabling PCI target as master */ - pci_master_enable(priv->pcidev); - - return DRVMGR_OK; -} - -/* Called when a PCI target is found with the PCI device and vendor ID - * given in gr_rasta_adcdac_ids[]. - */ -int gr_rasta_adcdac_init1(struct drvmgr_dev *dev) -{ - struct gr_rasta_adcdac_priv *priv; - struct pci_dev_info *devinfo; - int status; - uint32_t bar0, bar1, bar0_size, bar1_size; - union drvmgr_key_value *value; - int resources_cnt; - - priv = malloc(sizeof(struct gr_rasta_adcdac_priv)); - if ( !priv ) - return DRVMGR_NOMEM; - - memset(priv, 0, sizeof(*priv)); - dev->priv = priv; - priv->dev = dev; - - /* Determine number of configurations */ - resources_cnt = get_resarray_count(gr_rasta_adcdac_resources); - - /* Generate Device prefix */ - - strcpy(priv->prefix, "/dev/rastaadcdac0"); - priv->prefix[16] += dev->minor_drv; - mkdir(priv->prefix, S_IRWXU | S_IRWXG | S_IRWXO); - priv->prefix[17] = '/'; - priv->prefix[18] = '\0'; - - priv->devinfo = devinfo = (struct pci_dev_info *)dev->businfo; - priv->pcidev = devinfo->pcidev; - bar0 = devinfo->resources[0].address; - bar0_size = devinfo->resources[0].size; - bar1 = devinfo->resources[1].address; - bar1_size = devinfo->resources[1].size; - printf("\n\n--- GR-RASTA-ADCDAC[%d] ---\n", dev->minor_drv); - printf(" PCI BUS: 0x%x, SLOT: 0x%x, FUNCTION: 0x%x\n", - PCI_DEV_EXPAND(priv->pcidev)); - printf(" PCI VENDOR: 0x%04x, DEVICE: 0x%04x\n", - devinfo->id.vendor, devinfo->id.device); - printf(" PCI BAR[0]: 0x%lx - 0x%lx\n", bar0, bar0 + bar0_size - 1); - printf(" PCI BAR[1]: 0x%lx - 0x%lx\n", bar1, bar1 + bar1_size - 1); - printf(" IRQ: %d\n\n\n", devinfo->irq); - - /* all neccessary space assigned to GR-RASTA-ADCDAC target? */ - if ((bar0_size == 0) || (bar1_size == 0)) - return DRVMGR_ENORES; - - /* Initialize spin-lock for this PCI perihperal device. This is to - * protect the Interrupt Controller Registers. The genirq layer is - * protecting its own internals and ISR dispatching. - */ - SPIN_INIT(&priv->devlock, priv->prefix); - - /* Let user override which PCI address the AHB masters of the - * RASTA-ADCDAC board access when doing DMA to CPU RAM. The AHB masters - * access the PCI Window of the AMBA bus, the MSB 4-bits of that address - * is translated according this config option before the address - * goes out on the PCI bus. - * Only the 4 MSB bits have an effect; - */ - value = drvmgr_dev_key_get(priv->dev, "ahbmst2pci", DRVMGR_KT_INT); - if (value) - priv->ahbmst2pci_map = value->i; - else - priv->ahbmst2pci_map = AHBMST2PCIADR; /* default */ - - priv->genirq = genirq_init(16); - if ( priv->genirq == NULL ) { - free(priv); - dev->priv = NULL; - return DRVMGR_FAIL; - } - - if ( (status = gr_rasta_adcdac_hw_init1(priv)) != 0 ) { - genirq_destroy(priv->genirq); - free(priv); - dev->priv = NULL; - printf(" Failed to initialize GR-RASTA-ADCDAC HW: %d\n", status); - return DRVMGR_FAIL; - } - - /* Init amba bus */ - priv->config.abus = &priv->abus; - priv->config.ops = &ambapp_rasta_adcdac_ops; - priv->config.maps_up = &priv->bus_maps_up[0]; - priv->config.maps_down = &priv->bus_maps_down[0]; - if ( priv->dev->minor_drv < resources_cnt ) { - priv->config.resources = gr_rasta_adcdac_resources[priv->dev->minor_drv]; - } else { - priv->config.resources = NULL; - } - - /* Create and register AMBA PnP bus. */ - return ambapp_bus_register(dev, &priv->config); -} - -int gr_rasta_adcdac_init2(struct drvmgr_dev *dev) -{ - struct gr_rasta_adcdac_priv *priv = dev->priv; - - /* Clear any old interrupt requests */ - drvmgr_interrupt_clear(dev, 0); - - /* Enable System IRQ so that GR-RASTA-ADCDAC PCI target interrupt - * goes through. - * - * It is important to enable it in stage init2. If interrupts were - * enabled in init1 this might hang the system when more than one - * PCI board is connected, this is because PCI interrupts might - * be shared and PCI board 2 have not initialized and might - * therefore drive interrupt already when entering init1(). - */ - drvmgr_interrupt_register( - dev, - 0, - "gr_rasta_adcdac", - gr_rasta_adcdac_isr, - (void *)priv); - - return gr_rasta_adcdac_hw_init2(priv); -} - -int ambapp_rasta_adcdac_int_register( - struct drvmgr_dev *dev, - int irq, - const char *info, - drvmgr_isr handler, - void *arg) -{ - struct gr_rasta_adcdac_priv *priv = dev->parent->dev->priv; - SPIN_IRQFLAGS(irqflags); - int status; - void *h; - - h = genirq_alloc_handler(handler, arg); - if ( h == NULL ) - return DRVMGR_FAIL; - - SPIN_LOCK_IRQ(&priv->devlock, irqflags); - - status = genirq_register(priv->genirq, irq, h); - if ( status == 0 ) { - /* Clear IRQ for first registered handler */ - priv->irq->iclear = (1<devlock, irqflags); - genirq_free_handler(h); - return DRVMGR_FAIL; - } - - status = genirq_enable(priv->genirq, irq, handler, arg); - if ( status == 0 ) { - /* Enable IRQ for first enabled handler only */ - priv->irq->mask[0] |= (1<devlock, irqflags); - - return status; -} - -int ambapp_rasta_adcdac_int_unregister( - struct drvmgr_dev *dev, - int irq, - drvmgr_isr isr, - void *arg) -{ - struct gr_rasta_adcdac_priv *priv = dev->parent->dev->priv; - SPIN_IRQFLAGS(irqflags); - int status; - void *handler; - - SPIN_LOCK_IRQ(&priv->devlock, irqflags); - - status = genirq_disable(priv->genirq, irq, isr, arg); - if ( status == 0 ) { - /* Disable IRQ only when no enabled handler exists */ - priv->irq->mask[0] &= ~(1<genirq, irq, isr, arg); - if ( handler == NULL ) - status = DRVMGR_FAIL; - else - status = DRVMGR_OK; - - SPIN_UNLOCK_IRQ(&priv->devlock, irqflags); - - if (handler) - genirq_free_handler(handler); - - return status; -} - -int ambapp_rasta_adcdac_int_unmask( - struct drvmgr_dev *dev, - int irq) -{ - struct gr_rasta_adcdac_priv *priv = dev->parent->dev->priv; - SPIN_IRQFLAGS(irqflags); - - DBG("RASTA-ADCDAC IRQ %d: unmask\n", irq); - - if ( genirq_check(priv->genirq, irq) ) - return DRVMGR_EINVAL; - - SPIN_LOCK_IRQ(&priv->devlock, irqflags); - - /* Enable IRQ for first enabled handler only */ - priv->irq->mask[0] |= (1<devlock, irqflags); - - return DRVMGR_OK; -} - -int ambapp_rasta_adcdac_int_mask( - struct drvmgr_dev *dev, - int irq) -{ - struct gr_rasta_adcdac_priv *priv = dev->parent->dev->priv; - SPIN_IRQFLAGS(irqflags); - - DBG("RASTA-ADCDAC IRQ %d: mask\n", irq); - - if ( genirq_check(priv->genirq, irq) ) - return DRVMGR_EINVAL; - - SPIN_LOCK_IRQ(&priv->devlock, irqflags); - - /* Disable/mask IRQ */ - priv->irq->mask[0] &= ~(1<devlock, irqflags); - - return DRVMGR_OK; -} - -int ambapp_rasta_adcdac_int_clear( - struct drvmgr_dev *dev, - int irq) -{ - struct gr_rasta_adcdac_priv *priv = dev->parent->dev->priv; - - if ( genirq_check(priv->genirq, irq) ) - return DRVMGR_FAIL; - - priv->irq->iclear = (1<parent->dev->priv; - - /* Device name prefix pointer, skip /dev */ - params->dev_prefix = &priv->prefix[5]; - - return 0; -} - -void gr_rasta_adcdac_print_dev(struct drvmgr_dev *dev, int options) -{ - struct gr_rasta_adcdac_priv *priv = dev->priv; - struct pci_dev_info *devinfo = priv->devinfo; - uint32_t bar0, bar1, bar0_size, bar1_size; - - /* Print */ - printf("--- GR-RASTA-ADCDAC [bus 0x%x, dev 0x%x, fun 0x%x] ---\n", - PCI_DEV_EXPAND(priv->pcidev)); - - bar0 = devinfo->resources[0].address; - bar0_size = devinfo->resources[0].size; - bar1 = devinfo->resources[1].address; - bar1_size = devinfo->resources[1].size; - - printf(" PCI BAR[0]: 0x%lx - 0x%lx\n", bar0, bar0 + bar0_size - 1); - printf(" PCI BAR[1]: 0x%lx - 0x%lx\n", bar1, bar1 + bar1_size - 1); - printf(" IRQ REGS: 0x%x\n", (unsigned int)priv->irq); - printf(" IRQ: %d\n", devinfo->irq); - printf(" PCI REVISION: %d\n", devinfo->rev); - printf(" FREQ: %d Hz\n", priv->version->amba_freq_hz); - printf(" IMASK: 0x%08x\n", priv->irq->mask[0]); - printf(" IPEND: 0x%08x\n", priv->irq->ipend); - - /* Print amba config */ - if ( options & RASTA_ADCDAC_OPTIONS_AMBA ) { - ambapp_print(&priv->abus, 10); - } -#if 0 - /* Print IRQ handlers and their arguments */ - if ( options & RASTA_ADCDAC_OPTIONS_IRQ ) { - int i; - for(i=0; i<16; i++) { - printf(" IRQ[%02d]: 0x%x, arg: 0x%x\n", - i, (unsigned int)priv->isrs[i].handler, (unsigned int)priv->isrs[i].arg); - } - } -#endif -} - -void gr_rasta_adcdac_print(int options) -{ - struct pci_drv_info *drv = &gr_rasta_adcdac_info; - struct drvmgr_dev *dev; - - dev = drv->general.dev; - while(dev) { - gr_rasta_adcdac_print_dev(dev, options); - dev = dev->next_in_drv; - } -} diff --git a/c/src/lib/libbsp/sparc/shared/pci/gr_rasta_io.c b/c/src/lib/libbsp/sparc/shared/pci/gr_rasta_io.c deleted file mode 100644 index 1e424f67f0..0000000000 --- a/c/src/lib/libbsp/sparc/shared/pci/gr_rasta_io.c +++ /dev/null @@ -1,897 +0,0 @@ -/* GR-RASTA-IO PCI Target driver. - * - * COPYRIGHT (c) 2008. - * Cobham Gaisler AB. - * - * Configures the GR-RASTA-IO interface PCI board. - * This driver provides a AMBA PnP bus by using the general part - * of the AMBA PnP bus driver (ambapp_bus.c). - * - * Driver resources for the AMBA PnP bus provided can be set using - * gr_rasta_io_set_resources(). - * - * 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 -#include -#include /* spin-lock */ -#include - -#include -#include -#include -#include -#include -#include -#include - -#include - -/* map via rtems_interrupt_lock_* API: */ -#define SPIN_DECLARE(lock) RTEMS_INTERRUPT_LOCK_MEMBER(lock) -#define SPIN_INIT(lock, name) rtems_interrupt_lock_initialize(lock, name) -#define SPIN_LOCK(lock, level) rtems_interrupt_lock_acquire_isr(lock, &level) -#define SPIN_LOCK_IRQ(lock, level) rtems_interrupt_lock_acquire(lock, &level) -#define SPIN_UNLOCK(lock, level) rtems_interrupt_lock_release_isr(lock, &level) -#define SPIN_UNLOCK_IRQ(lock, level) rtems_interrupt_lock_release(lock, &level) -#define SPIN_IRQFLAGS(k) rtems_interrupt_lock_context k -#define SPIN_ISR_IRQFLAGS(k) SPIN_IRQFLAGS(k) - -/* Determines which PCI address the AHB masters will access, it should be - * set so that the masters can access the CPU RAM. Default is base of CPU RAM, - * CPU RAM is mapped 1:1 to PCI space. - */ -extern unsigned int _RAM_START; -#define AHBMST2PCIADR (((unsigned int)&_RAM_START) & 0xf0000000) - -/* Offset from 0x80000000 (dual bus version) */ -#define AHB1_BASE_ADDR 0x80000000 -#define AHB1_IOAREA_BASE_ADDR 0x80100000 -#define AHB1_IOAREA_OFS (AHB1_IOAREA_BASE_ADDR - AHB1_BASE_ADDR) - -/* Second revision constants (GRPCI2) */ -#define GRPCI2_BAR0_TO_AHB_MAP 0x04 /* Fixme */ -#define GRPCI2_BAR1_TO_AHB_MAP 0x08 /* Fixme */ -#define GRPCI2_PCI_CONFIG 0x20 /* Fixme */ - - -/* #define DEBUG 1 */ - -#ifdef DEBUG -#define DBG(x...) printk(x) -#else -#define DBG(x...) -#endif - -/* PCI ID */ -#define PCIID_VENDOR_GAISLER 0x1AC8 - -int gr_rasta_io_init1(struct drvmgr_dev *dev); -int gr_rasta_io_init2(struct drvmgr_dev *dev); -void gr_rasta_io_isr (void *arg); - -struct grpci_regs { - volatile unsigned int cfg_stat; - volatile unsigned int bar0; - volatile unsigned int page0; - volatile unsigned int bar1; - volatile unsigned int page1; - volatile unsigned int iomap; - volatile unsigned int stat_cmd; -}; - -struct grpci2_regs { - volatile unsigned int ctrl; - volatile unsigned int statcap; - volatile unsigned int pcimstprefetch; - volatile unsigned int ahbtopciiomap; - volatile unsigned int dmactrl; - volatile unsigned int dmadesc; - volatile unsigned int dmachanact; - volatile unsigned int reserved; - volatile unsigned int pcibartoahb[6]; - volatile unsigned int reserved2[2]; - volatile unsigned int ahbtopcimemmap[16]; - volatile unsigned int trcctrl; - volatile unsigned int trccntmode; - volatile unsigned int trcadpat; - volatile unsigned int trcadmask; - volatile unsigned int trcctrlsigpat; - volatile unsigned int trcctrlsigmask; - volatile unsigned int trcadstate; - volatile unsigned int trcctrlsigstate; -}; - -struct gr_rasta_io_ver { - const unsigned int amba_freq_hz; /* The frequency */ - const unsigned int amba_ioarea; /* The address where the PnP IOAREA starts at */ -}; - -/* Private data structure for driver */ -struct gr_rasta_io_priv { - /* Driver management */ - struct drvmgr_dev *dev; - char prefix[16]; - SPIN_DECLARE(devlock); - - /* PCI */ - pci_dev_t pcidev; - struct pci_dev_info *devinfo; - uint32_t ahbmst2pci_map; - - /* IRQ */ - genirq_t genirq; - - /* GR-RASTA-IO */ - struct gr_rasta_io_ver *version; - struct irqmp_regs *irq; - struct grpci_regs *grpci; - struct grpci2_regs *grpci2; - struct drvmgr_map_entry bus_maps_down[3]; - struct drvmgr_map_entry bus_maps_up[2]; - - /* AMBA Plug&Play information on GR-RASTA-IO */ - struct ambapp_bus abus; - struct ambapp_mmap amba_maps[4]; - struct ambapp_config config; -}; - -struct gr_rasta_io_ver gr_rasta_io_ver0 = { - .amba_freq_hz = 30000000, - .amba_ioarea = 0x80100000, -}; - -struct gr_rasta_io_ver gr_rasta_io_ver1 = { - .amba_freq_hz = 50000000, - .amba_ioarea = 0x80100000, -}; - -int ambapp_rasta_io_int_register( - struct drvmgr_dev *dev, - int irq, - const char *info, - drvmgr_isr handler, - void *arg); -int ambapp_rasta_io_int_unregister( - struct drvmgr_dev *dev, - int irq, - drvmgr_isr handler, - void *arg); -int ambapp_rasta_io_int_unmask( - struct drvmgr_dev *dev, - int irq); -int ambapp_rasta_io_int_mask( - struct drvmgr_dev *dev, - int irq); -int ambapp_rasta_io_int_clear( - struct drvmgr_dev *dev, - int irq); -int ambapp_rasta_io_get_params( - struct drvmgr_dev *dev, - struct drvmgr_bus_params *params); - -struct ambapp_ops ambapp_rasta_io_ops = { - .int_register = ambapp_rasta_io_int_register, - .int_unregister = ambapp_rasta_io_int_unregister, - .int_unmask = ambapp_rasta_io_int_unmask, - .int_mask = ambapp_rasta_io_int_mask, - .int_clear = ambapp_rasta_io_int_clear, - .get_params = ambapp_rasta_io_get_params -}; - -struct drvmgr_drv_ops gr_rasta_io_ops = -{ - .init = {gr_rasta_io_init1, gr_rasta_io_init2, NULL, NULL}, - .remove = NULL, - .info = NULL -}; - -struct pci_dev_id_match gr_rasta_io_ids[] = -{ - PCIID_DEVVEND(PCIID_VENDOR_GAISLER, PCIID_DEVICE_GR_RASTA_IO), - PCIID_DEVVEND(PCIID_VENDOR_GAISLER_OLD, PCIID_DEVICE_GR_RASTA_IO_OLD), - PCIID_END_TABLE /* Mark end of table */ -}; - -struct pci_drv_info gr_rasta_io_info = -{ - { - DRVMGR_OBJ_DRV, /* Driver */ - NULL, /* Next driver */ - NULL, /* Device list */ - DRIVER_PCI_GAISLER_RASTAIO_ID, /* Driver ID */ - "GR-RASTA-IO_DRV", /* Driver Name */ - DRVMGR_BUS_TYPE_PCI, /* Bus Type */ - &gr_rasta_io_ops, - NULL, /* Funcs */ - 0, /* No devices yet */ - 0, - }, - &gr_rasta_io_ids[0] -}; - -/* Driver resources configuration for the AMBA bus on the GR-RASTA-IO board. - * It is declared weak so that the user may override it from the project file, - * if the default settings are not enough. - * - * The configuration consists of an array of configuration pointers, each - * pointer determine the configuration of one GR-RASTA-IO board. Pointer - * zero is for board0, pointer 1 for board1 and so on. - * - * The array must end with a NULL pointer. - */ -struct drvmgr_bus_res *gr_rasta_io_resources[] __attribute__((weak)) = -{ - NULL -}; - -void gr_rasta_io_register_drv(void) -{ - DBG("Registering GR-RASTA-IO PCI driver\n"); - drvmgr_drv_register(&gr_rasta_io_info.general); -} - -void gr_rasta_io_isr (void *arg) -{ - struct gr_rasta_io_priv *priv = arg; - unsigned int status, tmp; - int irq; - SPIN_ISR_IRQFLAGS(irqflags); - - tmp = status = priv->irq->ipend; - - /* DBG("GR-RASTA-IO: IRQ 0x%x\n",status); */ - - SPIN_LOCK(&priv->devlock, irqflags); - for(irq=0; irq<16; irq++) { - if ( status & (1<genirq, irq); - priv->irq->iclear = (1<devlock, irqflags); - - /* ACK interrupt, this is because PCI is Level, so the IRQ Controller still drives the IRQ. */ - if ( tmp ) - drvmgr_interrupt_clear(priv->dev, 0); - - DBG("RASTA-IO-IRQ: 0x%x\n", tmp); -} - -/* PCI Hardware (Revision 0 and 1) initialization */ -static int gr_rasta_io_hw_init(struct gr_rasta_io_priv *priv) -{ - unsigned int *page0 = NULL; - struct ambapp_dev *tmp; - struct ambapp_ahb_info *ahb; - struct pci_dev_info *devinfo = priv->devinfo; - uint32_t bar0, bar0_size; - - bar0 = devinfo->resources[0].address; - bar0_size = devinfo->resources[0].size; - page0 = (unsigned int *)(bar0 + bar0_size/2); - - /* Point PAGE0 to start of Plug and Play information */ - *page0 = priv->version->amba_ioarea & 0xff000000; - -#if 0 - { - uint32_t data; - /* set parity error response */ - pci_cfg_r32(priv->pcidev, PCIR_COMMAND, &data); - pci_cfg_w32(priv->pcidev, PCIR_COMMAND, (data|PCIM_CMD_PERRESPEN)); - } -#endif - - /* Setup cache line size. Default cache line size will result in - * poor performance (256 word fetches), 0xff will set it according - * to the max size of the PCI FIFO. - */ - pci_cfg_w8(priv->pcidev, PCIR_CACHELNSZ, 0xff); - - /* Scan AMBA Plug&Play */ - - /* AMBA MAP bar0 (in CPU) ==> 0x80000000(remote amba address) */ - priv->amba_maps[0].size = bar0_size/2; - priv->amba_maps[0].local_adr = bar0; - priv->amba_maps[0].remote_adr = AHB1_BASE_ADDR; - - /* AMBA MAP bar1 (in CPU) ==> 0x40000000(remote amba address) */ - priv->amba_maps[1].size = devinfo->resources[1].size; - priv->amba_maps[1].local_adr = devinfo->resources[1].address; - priv->amba_maps[1].remote_adr = 0x40000000; - - /* Addresses not matching with map be untouched */ - priv->amba_maps[2].size = 0xfffffff0; - priv->amba_maps[2].local_adr = 0; - priv->amba_maps[2].remote_adr = 0; - - /* Mark end of table */ - priv->amba_maps[3].size=0; - priv->amba_maps[3].local_adr = 0; - priv->amba_maps[3].remote_adr = 0; - - /* Start AMBA PnP scan at first AHB bus */ - ambapp_scan(&priv->abus, - bar0 + (priv->version->amba_ioarea & ~0xff000000), - NULL, &priv->amba_maps[0]); - - /* Initialize Frequency of AMBA bus */ - ambapp_freq_init(&priv->abus, NULL, priv->version->amba_freq_hz); - - /* Point PAGE0 to start of APB area */ - *page0 = AHB1_BASE_ADDR; - - /* Find GRPCI controller */ - tmp = (struct ambapp_dev *)ambapp_for_each(&priv->abus, - (OPTIONS_ALL|OPTIONS_APB_SLVS), - VENDOR_GAISLER, GAISLER_PCIFBRG, - ambapp_find_by_idx, NULL); - if ( !tmp ) { - return -3; - } - priv->grpci = (struct grpci_regs *)((struct ambapp_apb_info *)tmp->devinfo)->start; - - /* Set GRPCI mmap so that AMBA masters can access CPU-RAM over - * the PCI window. - */ - priv->grpci->cfg_stat = (priv->grpci->cfg_stat & 0x0fffffff) | - (priv->ahbmst2pci_map & 0xf0000000); - priv->grpci->page1 = 0x40000000; - - /* Find IRQ controller, Clear all current IRQs */ - tmp = (struct ambapp_dev *)ambapp_for_each(&priv->abus, - (OPTIONS_ALL|OPTIONS_APB_SLVS), - VENDOR_GAISLER, GAISLER_IRQMP, - ambapp_find_by_idx, NULL); - if ( !tmp ) { - return -4; - } - priv->irq = (struct irqmp_regs *)DEV_TO_APB(tmp)->start; - /* Set up GR-RASTA-IO irq controller */ - priv->irq->mask[0] = 0; - priv->irq->iclear = 0xffff; - priv->irq->ilevel = 0; - - /* DOWN streams translation table */ - priv->bus_maps_down[0].name = "PCI BAR0 -> AMBA"; - priv->bus_maps_down[0].size = priv->amba_maps[0].size; - priv->bus_maps_down[0].from_adr = (void *)priv->amba_maps[0].local_adr; - priv->bus_maps_down[0].to_adr = (void *)priv->amba_maps[0].remote_adr; - - priv->bus_maps_down[1].name = "PCI BAR1 -> AMBA"; - priv->bus_maps_down[1].size = priv->amba_maps[1].size; - priv->bus_maps_down[1].from_adr = (void *)priv->amba_maps[1].local_adr; - priv->bus_maps_down[1].to_adr = (void *)priv->amba_maps[1].remote_adr; - - /* Mark end of translation table */ - priv->bus_maps_down[2].size = 0; - - /* Find GRPCI controller AHB Slave interface */ - tmp = (struct ambapp_dev *)ambapp_for_each(&priv->abus, - (OPTIONS_ALL|OPTIONS_AHB_SLVS), - VENDOR_GAISLER, GAISLER_PCIFBRG, - ambapp_find_by_idx, NULL); - if ( !tmp ) { - return -5; - } - ahb = (struct ambapp_ahb_info *)tmp->devinfo; - - /* UP streams translation table */ - priv->bus_maps_up[0].name = "AMBA GRPCI Window"; - priv->bus_maps_up[0].size = ahb->mask[0]; /* AMBA->PCI Window on GR-RASTA-IO board */ - priv->bus_maps_up[0].from_adr = (void *)ahb->start[0]; - priv->bus_maps_up[0].to_adr = (void *) - (priv->ahbmst2pci_map & 0xf0000000); - - /* Mark end of translation table */ - priv->bus_maps_up[1].size = 0; - - /* Successfully registered the RASTA board */ - return 0; -} - -/* PCI Hardware (Revision 1) initialization */ -static int gr_rasta_io2_hw_init(struct gr_rasta_io_priv *priv) -{ - int i; - uint32_t data; - unsigned int ctrl; - uint8_t tmp2; - struct ambapp_dev *tmp; - struct ambapp_ahb_info *ahb; - uint8_t cap_ptr; - pci_dev_t pcidev = priv->pcidev; - struct pci_dev_info *devinfo = priv->devinfo; - - /* Check capabilities list bit */ - pci_cfg_r8(pcidev, PCIR_STATUS, &tmp2); - - if (!((tmp2 >> 4) & 1)) { - /* Capabilities list not available which it should be in the - * GRPCI2 - */ - return -3; - } - - /* Read capabilities pointer */ - pci_cfg_r8(pcidev, PCIR_CAP_PTR, &cap_ptr); - - /* Set AHB address mappings for target PCI bars - * BAR0: 16MB : Mapped to I/O at 0x80000000 - * BAR1: 256MB : Mapped to MEM at 0x40000000 - */ - pci_cfg_w32(pcidev, cap_ptr+GRPCI2_BAR0_TO_AHB_MAP, AHB1_BASE_ADDR); - pci_cfg_w32(pcidev, cap_ptr+GRPCI2_BAR1_TO_AHB_MAP, 0x40000000); - - /* Set PCI bus to be same endianess as PCI system */ - pci_cfg_r32(pcidev, cap_ptr+GRPCI2_PCI_CONFIG, &data); - if (pci_endian == PCI_BIG_ENDIAN) - data = data & 0xFFFFFFFE; - else - data = data | 0x00000001; - pci_cfg_w32(pcidev, cap_ptr+GRPCI2_PCI_CONFIG, data); - -#if 0 - /* set parity error response */ - pci_cfg_r32(pcidev, PCIR_COMMAND, &data); - pci_cfg_w32(pcidev, PCIR_COMMAND, (data|PCIM_CMD_PERRESPEN)); -#endif - - /* Scan AMBA Plug&Play */ - - /* AMBA MAP bar0 (in PCI) ==> 0x40000000 (remote amba address) */ - priv->amba_maps[0].size = devinfo->resources[0].size; - priv->amba_maps[0].local_adr = devinfo->resources[0].address; - priv->amba_maps[0].remote_adr = AHB1_BASE_ADDR; - - /* AMBA MAP bar0 (in PCI) ==> 0x80000000 (remote amba address) */ - priv->amba_maps[1].size = devinfo->resources[1].size; - priv->amba_maps[1].local_adr = devinfo->resources[1].address; - priv->amba_maps[1].remote_adr = 0x40000000; - - /* Addresses not matching with map be untouched */ - priv->amba_maps[2].size = 0xfffffff0; - priv->amba_maps[2].local_adr = 0; - priv->amba_maps[2].remote_adr = 0; - - /* Mark end of table */ - priv->amba_maps[3].size=0; - - /* Start AMBA PnP scan at first AHB bus */ - ambapp_scan( - &priv->abus, - devinfo->resources[0].address + AHB1_IOAREA_OFS, - NULL, - &priv->amba_maps[0]); - - /* Initialize Frequency of AMBA bus. The AMBA bus runs at same - * frequency as PCI bus - */ - ambapp_freq_init(&priv->abus, NULL, priv->version->amba_freq_hz); - - /* Find IRQ controller, Clear all current IRQs */ - tmp = (struct ambapp_dev *)ambapp_for_each(&priv->abus, - (OPTIONS_ALL|OPTIONS_APB_SLVS), - VENDOR_GAISLER, GAISLER_IRQMP, - ambapp_find_by_idx, NULL); - if ( !tmp ) { - return -4; - } - priv->irq = (struct irqmp_regs *)DEV_TO_APB(tmp)->start; - /* Set up GR-RASTA-SPW-ROUTER irq controller */ - priv->irq->mask[0] = 0; - priv->irq->iclear = 0xffff; - priv->irq->ilevel = 0; - - priv->bus_maps_down[0].name = "PCI BAR0 -> AMBA"; - priv->bus_maps_down[0].size = priv->amba_maps[0].size; - priv->bus_maps_down[0].from_adr = (void *)priv->amba_maps[0].local_adr; - priv->bus_maps_down[0].to_adr = (void *)priv->amba_maps[0].remote_adr; - priv->bus_maps_down[1].name = "PCI BAR1 -> AMBA"; - priv->bus_maps_down[1].size = priv->amba_maps[1].size; - priv->bus_maps_down[1].from_adr = (void *)priv->amba_maps[1].local_adr; - priv->bus_maps_down[1].to_adr = (void *)priv->amba_maps[1].remote_adr; - priv->bus_maps_down[2].size = 0; - - /* Find GRPCI2 controller AHB Slave interface */ - tmp = (void *)ambapp_for_each(&priv->abus, - (OPTIONS_ALL|OPTIONS_AHB_SLVS), - VENDOR_GAISLER, GAISLER_GRPCI2, - ambapp_find_by_idx, NULL); - if ( !tmp ) { - return -5; - } - ahb = (struct ambapp_ahb_info *)tmp->devinfo; - priv->bus_maps_up[0].name = "AMBA GRPCI2 Window"; - priv->bus_maps_up[0].size = ahb->mask[0]; /* AMBA->PCI Window on GR-RASTA-SPW-ROUTER board */ - priv->bus_maps_up[0].from_adr = (void *)ahb->start[0]; - priv->bus_maps_up[0].to_adr = (void *) - (priv->ahbmst2pci_map & ~(ahb->mask[0]-1)); - priv->bus_maps_up[1].size = 0; - - /* Find GRPCI2 controller APB Slave interface */ - tmp = (void *)ambapp_for_each(&priv->abus, - (OPTIONS_ALL|OPTIONS_APB_SLVS), - VENDOR_GAISLER, GAISLER_GRPCI2, - ambapp_find_by_idx, NULL); - if ( !tmp ) { - return -6; - } - priv->grpci2 = (struct grpci2_regs *) - ((struct ambapp_apb_info *)tmp->devinfo)->start; - - /* Set AHB to PCI mapping for all AMBA AHB masters */ - for(i = 0; i < 16; i++) { - priv->grpci2->ahbtopcimemmap[i] = priv->ahbmst2pci_map & - ~(ahb->mask[0]-1); - } - - /* Make sure dirq(0) sampling is enabled */ - ctrl = priv->grpci2->ctrl; - ctrl = (ctrl & 0xFFFFFF0F) | (1 << 4); - priv->grpci2->ctrl = ctrl; - - /* Successfully registered the RASTA-SPW-ROUTER board */ - return 0; -} - -static int gr_rasta_io_hw_init2(struct gr_rasta_io_priv *priv) -{ - /* Enable DMA by enabling PCI target as master */ - pci_master_enable(priv->pcidev); - - return DRVMGR_OK; -} - -/* Called when a PCI target is found with the PCI device and vendor ID - * given in gr_rasta_io_ids[]. - */ -int gr_rasta_io_init1(struct drvmgr_dev *dev) -{ - struct gr_rasta_io_priv *priv; - struct pci_dev_info *devinfo; - int status; - uint32_t bar0, bar1, bar0_size, bar1_size; - union drvmgr_key_value *value; - int resources_cnt; - - priv = malloc(sizeof(struct gr_rasta_io_priv)); - if ( !priv ) - return DRVMGR_NOMEM; - - memset(priv, 0, sizeof(*priv)); - dev->priv = priv; - priv->dev = dev; - - /* Determine number of configurations */ - resources_cnt = get_resarray_count(gr_rasta_io_resources); - - /* Generate Device prefix */ - - strcpy(priv->prefix, "/dev/rastaio0"); - priv->prefix[12] += dev->minor_drv; - mkdir(priv->prefix, S_IRWXU | S_IRWXG | S_IRWXO); - priv->prefix[13] = '/'; - priv->prefix[14] = '\0'; - - priv->devinfo = devinfo = (struct pci_dev_info *)dev->businfo; - priv->pcidev = devinfo->pcidev; - bar0 = devinfo->resources[0].address; - bar0_size = devinfo->resources[0].size; - bar1 = devinfo->resources[1].address; - bar1_size = devinfo->resources[1].size; - printf("\n\n--- GR-RASTA-IO[%d] ---\n", dev->minor_drv); - printf(" PCI BUS: 0x%x, SLOT: 0x%x, FUNCTION: 0x%x\n", - PCI_DEV_EXPAND(priv->pcidev)); - printf(" PCI VENDOR: 0x%04x, DEVICE: 0x%04x\n", - devinfo->id.vendor, devinfo->id.device); - printf(" PCI BAR[0]: 0x%lx - 0x%lx\n", bar0, bar0 + bar0_size - 1); - printf(" PCI BAR[1]: 0x%lx - 0x%lx\n", bar1, bar1 + bar1_size - 1); - printf(" IRQ: %d\n\n\n", devinfo->irq); - - /* all neccessary space assigned to GR-RASTA-IO target? */ - if ((bar0_size == 0) || (bar1_size == 0)) - return DRVMGR_ENORES; - - /* Initialize spin-lock for this PCI peripheral device. This is to - * protect the Interrupt Controller Registers. The genirq layer is - * protecting its own internals and ISR dispatching. - */ - SPIN_INIT(&priv->devlock, priv->prefix); - - /* Let user override which PCI address the AHB masters of the - * GR-RASTA-IO board access when doing DMA to CPU RAM. The AHB masters - * access the PCI Window of the AMBA bus, the MSB 4-bits of that address - * is translated according this config option before the address - * goes out on the PCI bus. - * Only the 4 MSB bits have an effect; - */ - value = drvmgr_dev_key_get(priv->dev, "ahbmst2pci", DRVMGR_KT_INT); - if (value) - priv->ahbmst2pci_map = value->i; - else - priv->ahbmst2pci_map = AHBMST2PCIADR; /* default */ - - priv->genirq = genirq_init(16); - if ( priv->genirq == NULL ) { - free(priv); - dev->priv = NULL; - return DRVMGR_FAIL; - } - - /* Select version of GR-RASTA-IO board */ - switch (devinfo->rev) { - case 0: - priv->version = &gr_rasta_io_ver0; - status = gr_rasta_io_hw_init(priv); - break; - case 1: - priv->version = &gr_rasta_io_ver1; - status = gr_rasta_io_hw_init(priv); - break; - case 2: - priv->version = &gr_rasta_io_ver1; /* same cfg as 1 */ - status = gr_rasta_io2_hw_init(priv); - break; - default: - return -2; - } - - if ( status != 0 ) { - genirq_destroy(priv->genirq); - free(priv); - dev->priv = NULL; - printf(" Failed to initialize GR-RASTA-IO HW: %d\n", status); - return DRVMGR_FAIL; - } - - /* Init amba bus */ - priv->config.abus = &priv->abus; - priv->config.ops = &ambapp_rasta_io_ops; - priv->config.maps_up = &priv->bus_maps_up[0]; - priv->config.maps_down = &priv->bus_maps_down[0]; - if ( priv->dev->minor_drv < resources_cnt ) { - priv->config.resources = gr_rasta_io_resources[priv->dev->minor_drv]; - } else { - priv->config.resources = NULL; - } - - /* Create and register AMBA PnP bus. */ - return ambapp_bus_register(dev, &priv->config); -} - -int gr_rasta_io_init2(struct drvmgr_dev *dev) -{ - struct gr_rasta_io_priv *priv = dev->priv; - - /* Clear any old interrupt requests */ - drvmgr_interrupt_clear(dev, 0); - - /* Enable System IRQ so that GR-RASTA-IO PCI target interrupt goes - * through. - * - * It is important to enable it in stage init2. If interrupts were - * enabled in init1 this might hang the system when more than one - * PCI board is connected, this is because PCI interrupts might - * be shared and PCI board 2 have not initialized and - * might therefore drive interrupt already when entering init1(). - */ - drvmgr_interrupt_register( - dev, - 0, - "gr_rasta_io", - gr_rasta_io_isr, - (void *)priv); - - return gr_rasta_io_hw_init2(priv); -} - -int ambapp_rasta_io_int_register( - struct drvmgr_dev *dev, - int irq, - const char *info, - drvmgr_isr handler, - void *arg) -{ - struct gr_rasta_io_priv *priv = dev->parent->dev->priv; - SPIN_IRQFLAGS(irqflags); - int status; - void *h; - - h = genirq_alloc_handler(handler, arg); - if ( h == NULL ) - return DRVMGR_FAIL; - - SPIN_LOCK_IRQ(&priv->devlock, irqflags); - - status = genirq_register(priv->genirq, irq, h); - if ( status == 0 ) { - /* Clear IRQ for first registered handler */ - priv->irq->iclear = (1<devlock, irqflags); - genirq_free_handler(h); - return DRVMGR_FAIL; - } - - status = genirq_enable(priv->genirq, irq, handler, arg); - if ( status == 0 ) { - /* Enable IRQ for first enabled handler only */ - priv->irq->mask[0] |= (1<devlock, irqflags); - - return status; -} - -int ambapp_rasta_io_int_unregister( - struct drvmgr_dev *dev, - int irq, - drvmgr_isr isr, - void *arg) -{ - struct gr_rasta_io_priv *priv = dev->parent->dev->priv; - SPIN_IRQFLAGS(irqflags); - int status; - void *handler; - - SPIN_LOCK_IRQ(&priv->devlock, irqflags); - - status = genirq_disable(priv->genirq, irq, isr, arg); - if ( status == 0 ) { - /* Disable IRQ only when no enabled handler exists */ - priv->irq->mask[0] &= ~(1<genirq, irq, isr, arg); - if ( handler == NULL ) - status = DRVMGR_FAIL; - else - status = DRVMGR_OK; - - SPIN_UNLOCK_IRQ(&priv->devlock, irqflags); - - if (handler) - genirq_free_handler(handler); - - return status; -} - -int ambapp_rasta_io_int_unmask( - struct drvmgr_dev *dev, - int irq) -{ - struct gr_rasta_io_priv *priv = dev->parent->dev->priv; - SPIN_IRQFLAGS(irqflags); - - DBG("RASTA-IO IRQ %d: unmask\n", irq); - - if ( genirq_check(priv->genirq, irq) ) - return DRVMGR_EINVAL; - - SPIN_LOCK_IRQ(&priv->devlock, irqflags); - - /* Enable IRQ for first enabled handler only */ - priv->irq->mask[0] |= (1<devlock, irqflags); - - return DRVMGR_OK; -} - -int ambapp_rasta_io_int_mask( - struct drvmgr_dev *dev, - int irq) -{ - struct gr_rasta_io_priv *priv = dev->parent->dev->priv; - SPIN_IRQFLAGS(irqflags); - - DBG("RASTA-IO IRQ %d: mask\n", irq); - - if ( genirq_check(priv->genirq, irq) ) - return DRVMGR_EINVAL; - - SPIN_LOCK_IRQ(&priv->devlock, irqflags); - - /* Disable/mask IRQ */ - priv->irq->mask[0] &= ~(1<devlock, irqflags); - - return DRVMGR_OK; -} - -int ambapp_rasta_io_int_clear( - struct drvmgr_dev *dev, - int irq) -{ - struct gr_rasta_io_priv *priv = dev->parent->dev->priv; - - if ( genirq_check(priv->genirq, irq) ) - return DRVMGR_EINVAL; - - priv->irq->iclear = (1<parent->dev->priv; - - /* Device name prefix pointer, skip /dev */ - params->dev_prefix = &priv->prefix[5]; - - return 0; -} - -void gr_rasta_io_print_dev(struct drvmgr_dev *dev, int options) -{ - struct gr_rasta_io_priv *priv = dev->priv; - struct pci_dev_info *devinfo = priv->devinfo; - uint32_t bar0, bar1, bar0_size, bar1_size; - - /* Print */ - printf("--- GR-RASTA-IO [bus 0x%x, dev 0x%x, fun 0x%x] ---\n", - PCI_DEV_EXPAND(priv->pcidev)); - - bar0 = devinfo->resources[0].address; - bar0_size = devinfo->resources[0].size; - bar1 = devinfo->resources[1].address; - bar1_size = devinfo->resources[1].size; - - printf(" PCI BAR[0]: 0x%lx - 0x%lx\n", bar0, bar0 + bar0_size - 1); - printf(" PCI BAR[1]: 0x%lx - 0x%lx\n", bar1, bar1 + bar1_size - 1); - printf(" IRQ REGS: 0x%x\n", (unsigned int)priv->irq); - printf(" IRQ: %d\n", devinfo->irq); - printf(" PCI REVISION: %d\n", devinfo->rev); - printf(" FREQ: %d Hz\n", priv->version->amba_freq_hz); - printf(" IMASK: 0x%08x\n", priv->irq->mask[0]); - printf(" IPEND: 0x%08x\n", priv->irq->ipend); - - /* Print amba config */ - if ( options & RASTA_IO_OPTIONS_AMBA ) { - ambapp_print(&priv->abus, 10); - } - -#if 0 - /* Print IRQ handlers and their arguments */ - if ( options & RASTA_IO_OPTIONS_IRQ ) { - int i; - for(i=0; i<16; i++) { - printf(" IRQ[%02d]: 0x%x, arg: 0x%x\n", - i, (unsigned int)priv->isrs[i].handler, (unsigned int)priv->isrs[i].arg); - } - } -#endif -} - -void gr_rasta_io_print(int options) -{ - struct pci_drv_info *drv = &gr_rasta_io_info; - struct drvmgr_dev *dev; - - dev = drv->general.dev; - while(dev) { - gr_rasta_io_print_dev(dev, options); - dev = dev->next_in_drv; - } -} diff --git a/c/src/lib/libbsp/sparc/shared/pci/gr_rasta_spw_router.c b/c/src/lib/libbsp/sparc/shared/pci/gr_rasta_spw_router.c deleted file mode 100644 index 7f7e35085a..0000000000 --- a/c/src/lib/libbsp/sparc/shared/pci/gr_rasta_spw_router.c +++ /dev/null @@ -1,703 +0,0 @@ -/* GR-RASTA-SPW-ROUTER PCI Target driver. - * - * COPYRIGHT (c) 2011. - * Cobham Gaisler AB. - * - * 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. - * - * Configures the GR-RASTA-SPW-ROUTER interface PCI board. - * This driver provides a AMBA PnP bus by using the general part - * of the AMBA PnP bus driver (ambapp_bus.c). Based on the - * GR-RASTA-IO driver. - */ - -#include -#include -#include -#include -#include - -#include -#include -#include /* spin-lock */ -#include - -#include -#include -#include -#include -#include -#include -#include -#include - -/* map via rtems_interrupt_lock_* API: */ -#define SPIN_DECLARE(lock) RTEMS_INTERRUPT_LOCK_MEMBER(lock) -#define SPIN_INIT(lock, name) rtems_interrupt_lock_initialize(lock, name) -#define SPIN_LOCK(lock, level) rtems_interrupt_lock_acquire_isr(lock, &level) -#define SPIN_LOCK_IRQ(lock, level) rtems_interrupt_lock_acquire(lock, &level) -#define SPIN_UNLOCK(lock, level) rtems_interrupt_lock_release_isr(lock, &level) -#define SPIN_UNLOCK_IRQ(lock, level) rtems_interrupt_lock_release(lock, &level) -#define SPIN_IRQFLAGS(k) rtems_interrupt_lock_context k -#define SPIN_ISR_IRQFLAGS(k) SPIN_IRQFLAGS(k) - -/* Determines which PCI address the AHB masters will access, it should be - * set so that the masters can access the CPU RAM. Default is base of CPU RAM, - * CPU RAM is mapped 1:1 to PCI space. - */ -extern unsigned int _RAM_START; -#define AHBMST2PCIADR (((unsigned int)&_RAM_START) & 0xf0000000) - -/* Offset from 0x80000000 (dual bus version) */ -#define AHB1_BASE_ADDR 0x80000000 -#define AHB1_IOAREA_BASE_ADDR 0x80100000 - -#define GRPCI2_BAR0_TO_AHB_MAP 0x04 /* Fixme */ -#define GRPCI2_PCI_CONFIG 0x20 /* Fixme */ - -/* #define DEBUG 1 */ - -#ifdef DEBUG -#define DBG(x...) printk(x) -#else -#define DBG(x...) -#endif - -/* PCI ID */ -#define PCIID_VENDOR_GAISLER 0x1AC8 - -int gr_rasta_spw_router_init1(struct drvmgr_dev *dev); -int gr_rasta_spw_router_init2(struct drvmgr_dev *dev); -void gr_rasta_spw_router_isr(void *arg); - -struct grpci2_regs { - volatile unsigned int ctrl; - volatile unsigned int statcap; - volatile unsigned int pcimstprefetch; - volatile unsigned int ahbtopciiomap; - volatile unsigned int dmactrl; - volatile unsigned int dmadesc; - volatile unsigned int dmachanact; - volatile unsigned int reserved; - volatile unsigned int pcibartoahb[6]; - volatile unsigned int reserved2[2]; - volatile unsigned int ahbtopcimemmap[16]; - volatile unsigned int trcctrl; - volatile unsigned int trccntmode; - volatile unsigned int trcadpat; - volatile unsigned int trcadmask; - volatile unsigned int trcctrlsigpat; - volatile unsigned int trcctrlsigmask; - volatile unsigned int trcadstate; - volatile unsigned int trcctrlsigstate; -}; - -struct gr_rasta_spw_router_ver { - const unsigned int amba_freq_hz; /* The frequency */ - const unsigned int amba_ioarea; /* The address where the PnP IOAREA starts at */ -}; - -/* Private data structure for driver */ -struct gr_rasta_spw_router_priv { - /* Driver management */ - struct drvmgr_dev *dev; - char prefix[20]; - SPIN_DECLARE(devlock); - - /* PCI */ - pci_dev_t pcidev; - struct pci_dev_info *devinfo; - uint32_t ahbmst2pci_map; - - /* IRQ */ - genirq_t genirq; - - /* GR-RASTA-SPW-ROUTER */ - struct gr_rasta_spw_router_ver *version; - struct irqmp_regs *irq; - struct grpci2_regs *grpci2; - struct drvmgr_map_entry bus_maps_up[2]; - struct drvmgr_map_entry bus_maps_down[2]; - - /* AMBA Plug&Play information on GR-RASTA-SPW-ROUTER */ - struct ambapp_bus abus; - struct ambapp_mmap amba_maps[3]; - struct ambapp_config config; -}; - -struct gr_rasta_spw_router_ver gr_rasta_spw_router_ver0 = { - .amba_freq_hz = 50000000, - .amba_ioarea = 0xfff00000, -}; - -int ambapp_rasta_spw_router_int_register( - struct drvmgr_dev *dev, - int irq, - const char *info, - drvmgr_isr handler, - void *arg); -int ambapp_rasta_spw_router_int_unregister( - struct drvmgr_dev *dev, - int irq, - drvmgr_isr handler, - void *arg); -int ambapp_rasta_spw_router_int_unmask( - struct drvmgr_dev *dev, - int irq); -int ambapp_rasta_spw_router_int_mask( - struct drvmgr_dev *dev, - int irq); -int ambapp_rasta_spw_router_int_clear( - struct drvmgr_dev *dev, - int irq); -int ambapp_rasta_spw_router_get_params( - struct drvmgr_dev *dev, - struct drvmgr_bus_params *params); - -struct ambapp_ops ambapp_rasta_spw_router_ops = { - .int_register = ambapp_rasta_spw_router_int_register, - .int_unregister = ambapp_rasta_spw_router_int_unregister, - .int_unmask = ambapp_rasta_spw_router_int_unmask, - .int_mask = ambapp_rasta_spw_router_int_mask, - .int_clear = ambapp_rasta_spw_router_int_clear, - .get_params = ambapp_rasta_spw_router_get_params -}; - -struct drvmgr_drv_ops gr_rasta_spw_router_ops = -{ - .init = {gr_rasta_spw_router_init1, gr_rasta_spw_router_init2, NULL, NULL}, - .remove = NULL, - .info = NULL -}; - -struct pci_dev_id_match gr_rasta_spw_router_ids[] = -{ - PCIID_DEVVEND(PCIID_VENDOR_GAISLER, PCIID_DEVICE_GR_RASTA_SPW_RTR), - PCIID_END_TABLE /* Mark end of table */ -}; - -struct pci_drv_info gr_rasta_spw_router_info = -{ - { - DRVMGR_OBJ_DRV, /* Driver */ - NULL, /* Next driver */ - NULL, /* Device list */ - DRIVER_PCI_GAISLER_RASTA_SPW_ROUTER_ID, /* Driver ID */ - "GR-RASTA-SPW_ROUTER_DRV", /* Driver Name */ - DRVMGR_BUS_TYPE_PCI, /* Bus Type */ - &gr_rasta_spw_router_ops, - NULL, /* Funcs */ - 0, /* No devices yet */ - sizeof(struct gr_rasta_spw_router_priv), - }, - &gr_rasta_spw_router_ids[0] -}; - -/* Driver resources configuration for the AMBA bus on the GR-RASTA-SPW-ROUTER board. - * It is declared weak so that the user may override it from the project file, - * if the default settings are not enough. - * - * The configuration consists of an array of configuration pointers, each - * pointer determine the configuration of one GR-RASTA-SPW-ROUTER board. Pointer - * zero is for board0, pointer 1 for board1 and so on. - * - * The array must end with a NULL pointer. - */ -struct drvmgr_bus_res *gr_rasta_spw_router_resources[] __attribute__((weak)) = -{ - NULL -}; - -void gr_rasta_spw_router_register_drv(void) -{ - DBG("Registering GR-RASTA-SPW-ROUTER PCI driver\n"); - drvmgr_drv_register(&gr_rasta_spw_router_info.general); -} - -void gr_rasta_spw_router_isr(void *arg) -{ - struct gr_rasta_spw_router_priv *priv = arg; - unsigned int status, tmp; - int irq; - SPIN_ISR_IRQFLAGS(irqflags); - - tmp = status = priv->irq->ipend; - - /* DBG("GR-RASTA-SPW-ROUTER: IRQ 0x%x\n",status); */ - - SPIN_LOCK(&priv->devlock, irqflags); - for(irq=0; irq<16; irq++) { - if ( status & (1<genirq, irq); - priv->irq->iclear = (1<devlock, irqflags); - - /* ACK interrupt, this is because PCI is Level, so the IRQ Controller - * still drives the IRQ - */ - if ( tmp ) - drvmgr_interrupt_clear(priv->dev, 0); - - DBG("RASTA-SPW_ROUTER-IRQ: 0x%x\n", tmp); -} - -static int gr_rasta_spw_router_hw_init(struct gr_rasta_spw_router_priv *priv) -{ - int i; - uint32_t data; - unsigned int ctrl; - uint8_t tmp2; - struct ambapp_dev *tmp; - struct ambapp_ahb_info *ahb; - uint8_t cap_ptr; - pci_dev_t pcidev = priv->pcidev; - struct pci_dev_info *devinfo = priv->devinfo; - - /* Select version of GR-RASTA-SPW-ROUTER board. Currently only one - * version - */ - switch (devinfo->rev) { - case 0: - priv->version = &gr_rasta_spw_router_ver0; - break; - default: - return -2; - } - - /* Check capabilities list bit */ - pci_cfg_r8(pcidev, PCIR_STATUS, &tmp2); - - if (!((tmp2 >> 4) & 1)) { - /* Capabilities list not available which it should be in the GRPCI2 */ - return -3; - } - - /* Read capabilities pointer */ - pci_cfg_r8(pcidev, PCIR_CAP_PTR, &cap_ptr); - - /* Set AHB address mappings for target PCI bars */ - pci_cfg_w32(pcidev, cap_ptr+GRPCI2_BAR0_TO_AHB_MAP, 0xffe00000); /* APB bus, AHB I/O bus 2 MB */ - - /* Set PCI bus to be big endian */ - pci_cfg_r32(pcidev, cap_ptr+GRPCI2_PCI_CONFIG, &data); - data = data & 0xFFFFFFFE; - pci_cfg_w32(pcidev, cap_ptr+GRPCI2_PCI_CONFIG, data); - -#if 0 - /* set parity error response */ - pci_cfg_r32(pcidev, PCIR_COMMAND, &data); - pci_cfg_w32(pcidev, PCIR_COMMAND, (data|PCIM_CMD_PERRESPEN)); -#endif - - /* Scan AMBA Plug&Play */ - - /* AMBA MAP bar0 (in router) ==> 0xffe00000(remote amba address) */ - priv->amba_maps[0].size = devinfo->resources[0].size; - priv->amba_maps[0].local_adr = devinfo->resources[0].address; - priv->amba_maps[0].remote_adr = 0xffe00000; - - /* Addresses not matching with map be untouched */ - priv->amba_maps[1].size = 0xfffffff0; - priv->amba_maps[1].local_adr = 0; - priv->amba_maps[1].remote_adr = 0; - - /* Mark end of table */ - priv->amba_maps[2].size=0; - - /* Start AMBA PnP scan at first AHB bus */ - ambapp_scan( - &priv->abus, - devinfo->resources[0].address + 0x100000, - NULL, - &priv->amba_maps[0]); - - /* Initialize Frequency of AMBA bus */ - ambapp_freq_init(&priv->abus, NULL, priv->version->amba_freq_hz); - - /* Find IRQ controller, Clear all current IRQs */ - tmp = (struct ambapp_dev *)ambapp_for_each(&priv->abus, - (OPTIONS_ALL|OPTIONS_APB_SLVS), - VENDOR_GAISLER, GAISLER_IRQMP, - ambapp_find_by_idx, NULL); - if ( !tmp ) { - return -4; - } - priv->irq = (struct irqmp_regs *)DEV_TO_APB(tmp)->start; - /* Set up GR-RASTA-SPW-ROUTER irq controller */ - priv->irq->mask[0] = 0; - priv->irq->iclear = 0xffff; - priv->irq->ilevel = 0; - - priv->bus_maps_down[0].name = "PCI BAR0 -> AMBA"; - priv->bus_maps_down[0].size = priv->amba_maps[0].size; - priv->bus_maps_down[0].from_adr = (void *)priv->amba_maps[0].local_adr; - priv->bus_maps_down[0].to_adr = (void *)priv->amba_maps[0].remote_adr; - priv->bus_maps_down[1].size = 0; - - /* Find GRPCI2 controller AHB Slave interface */ - tmp = (struct ambapp_dev *)ambapp_for_each(&priv->abus, - (OPTIONS_ALL|OPTIONS_AHB_SLVS), - VENDOR_GAISLER, GAISLER_GRPCI2, - ambapp_find_by_idx, NULL); - if ( !tmp ) { - return -5; - } - ahb = (struct ambapp_ahb_info *)tmp->devinfo; - priv->bus_maps_up[0].name = "AMBA GRPCI2 Window"; - priv->bus_maps_up[0].size = ahb->mask[0]; /* AMBA->PCI Window on GR-RASTA-SPW-ROUTER board */ - priv->bus_maps_up[0].from_adr = (void *)ahb->start[0]; - priv->bus_maps_up[0].to_adr = (void *) - (priv->ahbmst2pci_map & ~(ahb->mask[0]-1)); - priv->bus_maps_up[1].size = 0; - - /* Find GRPCI2 controller APB Slave interface */ - tmp = (struct ambapp_dev *)ambapp_for_each(&priv->abus, - (OPTIONS_ALL|OPTIONS_APB_SLVS), - VENDOR_GAISLER, GAISLER_GRPCI2, - ambapp_find_by_idx, NULL); - if ( !tmp ) { - return -6; - } - priv->grpci2 = (struct grpci2_regs *) - ((struct ambapp_apb_info *)tmp->devinfo)->start; - - /* Set AHB to PCI mapping for all AMBA AHB masters */ - for(i = 0; i < 16; i++) { - priv->grpci2->ahbtopcimemmap[i] = priv->ahbmst2pci_map & - ~(ahb->mask[0]-1); - } - - /* Make sure dirq(0) sampling is enabled */ - ctrl = priv->grpci2->ctrl; - ctrl = (ctrl & 0xFFFFFF0F) | (1 << 4); - printf("data: 0x%x\n", ctrl); - priv->grpci2->ctrl = ctrl; - - /* Successfully registered the RASTA-SPW-ROUTER board */ - return 0; -} - -static int gr_rasta_spw_router_hw_init2(struct gr_rasta_spw_router_priv *priv) -{ - /* Enable DMA by enabling PCI target as master */ - pci_master_enable(priv->pcidev); - - return DRVMGR_OK; -} - -/* Called when a PCI target is found with the PCI device and vendor ID - * given in gr_rasta_spw_router_ids[]. - */ -int gr_rasta_spw_router_init1(struct drvmgr_dev *dev) -{ - struct gr_rasta_spw_router_priv *priv; - struct pci_dev_info *devinfo; - int status; - uint32_t bar0, bar0_size; - union drvmgr_key_value *value; - int resources_cnt; - - priv = dev->priv; - if (!priv) - return DRVMGR_NOMEM; - - memset(priv, 0, sizeof(*priv)); - dev->priv = priv; - priv->dev = dev; - - /* Determine number of configurations */ - resources_cnt = get_resarray_count(gr_rasta_spw_router_resources); - - /* Generate Device prefix */ - - strcpy(priv->prefix, "/dev/spwrouter0"); - priv->prefix[14] += dev->minor_drv; - mkdir(priv->prefix, S_IRWXU | S_IRWXG | S_IRWXO); - priv->prefix[15] = '/'; - priv->prefix[16] = '\0'; - - priv->devinfo = devinfo = (struct pci_dev_info *)dev->businfo; - priv->pcidev = devinfo->pcidev; - bar0 = devinfo->resources[0].address; - bar0_size = devinfo->resources[0].size; - printf("\n\n--- GR-RASTA-SPW-ROUTER[%d] ---\n", dev->minor_drv); - printf(" PCI BUS: 0x%x, SLOT: 0x%x, FUNCTION: 0x%x\n", - PCI_DEV_EXPAND(priv->pcidev)); - printf(" PCI VENDOR: 0x%04x, DEVICE: 0x%04x\n", - devinfo->id.vendor, devinfo->id.device); - printf(" PCI BAR[0]: 0x%08lx - 0x%08lx\n", bar0, bar0 + bar0_size - 1); - printf(" IRQ: %d\n\n\n", devinfo->irq); - - /* all neccessary space assigned to GR-RASTA-SPW-ROUTER target? */ - if (bar0_size == 0) - return DRVMGR_ENORES; - - /* Initialize spin-lock for this PCI peripheral device. This is to - * protect the Interrupt Controller Registers. The genirq layer is - * protecting its own internals and ISR dispatching. - */ - SPIN_INIT(&priv->devlock, priv->prefix); - - /* Let user override which PCI address the AHB masters of the - * GR-RASTA-SPW board access when doing DMA to CPU RAM. The AHB masters - * access the PCI Window of the AMBA bus, the MSB 4-bits of that address - * is translated according this config option before the address - * goes out on the PCI bus. - * Only the 4 MSB bits have an effect; - */ - value = drvmgr_dev_key_get(priv->dev, "ahbmst2pci", DRVMGR_KT_INT); - if (value) - priv->ahbmst2pci_map = value->i; - else - priv->ahbmst2pci_map = AHBMST2PCIADR; /* default */ - - priv->genirq = genirq_init(16); - if ( priv->genirq == NULL ) - return DRVMGR_FAIL; - - if ((status = gr_rasta_spw_router_hw_init(priv)) != 0) { - genirq_destroy(priv->genirq); - printf(" Failed to initialize GR-RASTA-SPW-ROUTER HW: %d\n", status); - return DRVMGR_FAIL; - } - - /* Init amba bus */ - priv->config.abus = &priv->abus; - priv->config.ops = &ambapp_rasta_spw_router_ops; - priv->config.maps_up = &priv->bus_maps_up[0]; - priv->config.maps_down = &priv->bus_maps_down[0]; - if ( priv->dev->minor_drv < resources_cnt ) { - priv->config.resources = gr_rasta_spw_router_resources[priv->dev->minor_drv]; - } else { - priv->config.resources = NULL; - } - - /* Create and register AMBA PnP bus. */ - return ambapp_bus_register(dev, &priv->config); -} - -int gr_rasta_spw_router_init2(struct drvmgr_dev *dev) -{ - struct gr_rasta_spw_router_priv *priv = dev->priv; - - /* Clear any old interrupt requests */ - drvmgr_interrupt_clear(dev, 0); - - /* Enable System IRQ so that GR-RASTA-SPW-ROUTER PCI target interrupt - * goes through. - * - * It is important to enable it in stage init2. If interrupts were - * enabled in init1 this might hang the system when more than one - * PCI board is connected, this is because PCI interrupts might - * be shared and PCI board 2 have not initialized and - * might therefore drive interrupt already when entering init1(). - */ - drvmgr_interrupt_register( - dev, - 0, - "gr_rasta_spw_router", - gr_rasta_spw_router_isr, - (void *)priv); - - return gr_rasta_spw_router_hw_init2(priv); -} - -int ambapp_rasta_spw_router_int_register( - struct drvmgr_dev *dev, - int irq, - const char *info, - drvmgr_isr handler, - void *arg) -{ - struct gr_rasta_spw_router_priv *priv = dev->parent->dev->priv; - SPIN_IRQFLAGS(irqflags); - int status; - void *h; - - h = genirq_alloc_handler(handler, arg); - if ( h == NULL ) - return DRVMGR_FAIL; - - SPIN_LOCK_IRQ(&priv->devlock, irqflags); - - status = genirq_register(priv->genirq, irq, h); - if (status == 0) { - /* Clear IRQ for first registered handler */ - priv->irq->iclear = (1<devlock, irqflags); - genirq_free_handler(h); - return DRVMGR_FAIL; - } - - status = genirq_enable(priv->genirq, irq, handler, arg); - if ( status == 0 ) { - /* Enable IRQ for first enabled handler only */ - priv->irq->mask[0] |= (1<devlock, irqflags); - - return status; -} - -int ambapp_rasta_spw_router_int_unregister( - struct drvmgr_dev *dev, - int irq, - drvmgr_isr isr, - void *arg) -{ - struct gr_rasta_spw_router_priv *priv = dev->parent->dev->priv; - SPIN_IRQFLAGS(irqflags); - int status; - void *handler; - - SPIN_LOCK_IRQ(&priv->devlock, irqflags); - - status = genirq_disable(priv->genirq, irq, isr, arg); - if ( status == 0 ) { - /* Disable IRQ only when no enabled handler exists */ - priv->irq->mask[0] &= ~(1<genirq, irq, isr, arg); - if ( handler == NULL ) - status = DRVMGR_FAIL; - else - status = DRVMGR_OK; - - SPIN_UNLOCK_IRQ(&priv->devlock, irqflags); - - if (handler) - genirq_free_handler(handler); - - return status; -} - -int ambapp_rasta_spw_router_int_unmask( - struct drvmgr_dev *dev, - int irq) -{ - struct gr_rasta_spw_router_priv *priv = dev->parent->dev->priv; - SPIN_IRQFLAGS(irqflags); - - DBG("RASTA-SPW-ROUTER IRQ %d: unmask\n", irq); - - if ( genirq_check(priv->genirq, irq) ) - return DRVMGR_EINVAL; - - SPIN_LOCK_IRQ(&priv->devlock, irqflags); - - /* Enable IRQ for first enabled handler only */ - priv->irq->mask[0] |= (1<devlock, irqflags); - - return DRVMGR_OK; -} - -int ambapp_rasta_spw_router_int_mask( - struct drvmgr_dev *dev, - int irq) -{ - struct gr_rasta_spw_router_priv *priv = dev->parent->dev->priv; - SPIN_IRQFLAGS(irqflags); - - DBG("RASTA-SPW-ROUTER IRQ %d: mask\n", irq); - - if ( genirq_check(priv->genirq, irq) ) - return DRVMGR_EINVAL; - - SPIN_LOCK_IRQ(&priv->devlock, irqflags); - - /* Disable/mask IRQ */ - priv->irq->mask[0] &= ~(1<devlock, irqflags); - - return DRVMGR_OK; -} - -int ambapp_rasta_spw_router_int_clear( - struct drvmgr_dev *dev, - int irq) -{ - struct gr_rasta_spw_router_priv *priv = dev->parent->dev->priv; - - if ( genirq_check(priv->genirq, irq) ) - return DRVMGR_EINVAL; - - priv->irq->iclear = (1<parent->dev->priv; - - /* Device name prefix pointer, skip /dev */ - params->dev_prefix = &priv->prefix[5]; - - return 0; -} - -void gr_rasta_spw_router_print_dev(struct drvmgr_dev *dev, int options) -{ - struct gr_rasta_spw_router_priv *priv = dev->priv; - struct pci_dev_info *devinfo = priv->devinfo; - uint32_t bar0, bar0_size; - - /* Print */ - printf("--- GR-RASTA-SPW-ROUTER [bus 0x%x, dev 0x%x, fun 0x%x] ---\n", - PCI_DEV_EXPAND(priv->pcidev)); - - bar0 = devinfo->resources[0].address; - bar0_size = devinfo->resources[0].size; - printf(" PCI BAR[0]: 0x%lx - 0x%lx\n", bar0, bar0 + bar0_size - 1); - printf(" IRQ REGS: 0x%x\n", (unsigned int)priv->irq); - printf(" IRQ: %d\n", devinfo->irq); - printf(" PCI REVISION: %d\n", devinfo->rev); - printf(" FREQ: %d Hz\n", priv->version->amba_freq_hz); - printf(" IMASK: 0x%08x\n", priv->irq->mask[0]); - printf(" IPEND: 0x%08x\n", priv->irq->ipend); - - /* Print amba config */ - if (options & RASTA_SPW_ROUTER_OPTIONS_AMBA) - ambapp_print(&priv->abus, 10); - -#if 0 - /* Print IRQ handlers and their arguments */ - if (options & RASTA_SPW_ROUTER_OPTIONS_IRQ) { - int i; - for(i = 0; i < 16; i++) { - printf(" IRQ[%02d]: 0x%x, arg: 0x%x\n", - i, (unsigned int)priv->isrs[i].handler, - (unsigned int)priv->isrs[i].arg); - } - } -#endif -} - -void gr_rasta_spw_router_print(int options) -{ - struct pci_drv_info *drv = &gr_rasta_spw_router_info; - struct drvmgr_dev *dev; - - dev = drv->general.dev; - while(dev) { - gr_rasta_spw_router_print_dev(dev, options); - dev = dev->next_in_drv; - } -} diff --git a/c/src/lib/libbsp/sparc/shared/pci/gr_rasta_tmtc.c b/c/src/lib/libbsp/sparc/shared/pci/gr_rasta_tmtc.c deleted file mode 100644 index 6ca3c6be1a..0000000000 --- a/c/src/lib/libbsp/sparc/shared/pci/gr_rasta_tmtc.c +++ /dev/null @@ -1,901 +0,0 @@ -/* GR-RASTA-TMTC PCI Target driver. - * - * COPYRIGHT (c) 2008. - * Cobham Gaisler AB. - * - * Configures the GR-RASTA-TMTC interface PCI board. - * This driver provides a AMBA PnP bus by using the general part - * of the AMBA PnP bus driver (ambapp_bus.c). - * - * Driver resources for the AMBA PnP bus provided can be set by overriding - * the defaults by declaring gr_rasta_tmtc_resources[]. - * - * 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 -#include -#include /* spin-lock */ -#include - -#include -#include -#include -#include -#include -#include -#include - -#include - -/* map via rtems_interrupt_lock_* API: */ -#define SPIN_DECLARE(lock) RTEMS_INTERRUPT_LOCK_MEMBER(lock) -#define SPIN_INIT(lock, name) rtems_interrupt_lock_initialize(lock, name) -#define SPIN_LOCK(lock, level) rtems_interrupt_lock_acquire_isr(lock, &level) -#define SPIN_LOCK_IRQ(lock, level) rtems_interrupt_lock_acquire(lock, &level) -#define SPIN_UNLOCK(lock, level) rtems_interrupt_lock_release_isr(lock, &level) -#define SPIN_UNLOCK_IRQ(lock, level) rtems_interrupt_lock_release(lock, &level) -#define SPIN_IRQFLAGS(k) rtems_interrupt_lock_context k -#define SPIN_ISR_IRQFLAGS(k) SPIN_IRQFLAGS(k) - -/* Determines which PCI address the AHB masters will access, it should be - * set so that the masters can access the CPU RAM. Default is base of CPU RAM, - * CPU RAM is mapped 1:1 to PCI space. - */ -extern unsigned int _RAM_START; -#define AHBMST2PCIADR (((unsigned int)&_RAM_START) & 0xf0000000) - -#define GAISLER_GPIO 0x01a -#define AHB1_BASE_ADDR 0x80000000 -#define AHB1_IOAREA_BASE_ADDR 0x80200000 -#define AHB1_IOAREA_OFS (AHB1_IOAREA_BASE_ADDR - AHB1_BASE_ADDR) - -/* Second revision constants (GRPCI2) */ -#define GRPCI2_BAR0_TO_AHB_MAP 0x04 /* Fixme */ -#define GRPCI2_BAR1_TO_AHB_MAP 0x08 /* Fixme */ -#define GRPCI2_PCI_CONFIG 0x20 /* Fixme */ - -/* #define DEBUG 1 */ - -#ifdef DEBUG -#define DBG(x...) printk(x) -#else -#define DBG(x...) -#endif - -int gr_rasta_tmtc_init1(struct drvmgr_dev *dev); -int gr_rasta_tmtc_init2(struct drvmgr_dev *dev); -void gr_rasta_tmtc_isr (void *arg); - -struct grpci_regs { - volatile unsigned int cfg_stat; - volatile unsigned int bar0; - volatile unsigned int page0; - volatile unsigned int bar1; - volatile unsigned int page1; - volatile unsigned int iomap; - volatile unsigned int stat_cmd; -}; - -struct grpci2_regs { - volatile unsigned int ctrl; - volatile unsigned int statcap; - volatile unsigned int pcimstprefetch; - volatile unsigned int ahbtopciiomap; - volatile unsigned int dmactrl; - volatile unsigned int dmadesc; - volatile unsigned int dmachanact; - volatile unsigned int reserved; - volatile unsigned int pcibartoahb[6]; - volatile unsigned int reserved2[2]; - volatile unsigned int ahbtopcimemmap[16]; - volatile unsigned int trcctrl; - volatile unsigned int trccntmode; - volatile unsigned int trcadpat; - volatile unsigned int trcadmask; - volatile unsigned int trcctrlsigpat; - volatile unsigned int trcctrlsigmask; - volatile unsigned int trcadstate; - volatile unsigned int trcctrlsigstate; -}; - -struct gr_rasta_tmtc_ver { - const unsigned int amba_freq_hz; /* The frequency */ - const unsigned int amba_ioarea; /* The address where the PnP IOAREA starts at */ -}; - -/* Private data structure for driver */ -struct gr_rasta_tmtc_priv { - /* Driver management */ - struct drvmgr_dev *dev; - char prefix[20]; - SPIN_DECLARE(devlock); - - /* PCI */ - pci_dev_t pcidev; - struct pci_dev_info *devinfo; - uint32_t ahbmst2pci_map; - - /* IRQ */ - genirq_t genirq; - - /* GR-RASTA-TMTC */ - struct gr_rasta_tmtc_ver *version; - struct irqmp_regs *irq; - struct grpci_regs *grpci; - struct grpci2_regs *grpci2; - struct grgpio_regs *gpio; - struct drvmgr_map_entry bus_maps_down[3]; - struct drvmgr_map_entry bus_maps_up[2]; - - /* AMBA Plug&Play information on GR-RASTA-TMTC */ - struct ambapp_bus abus; - struct ambapp_mmap amba_maps[4]; - struct ambapp_config config; -}; - -struct gr_rasta_tmtc_ver gr_rasta_tmtc_ver0 = { - .amba_freq_hz = 30000000, - .amba_ioarea = AHB1_IOAREA_BASE_ADDR, -}; - -int ambapp_rasta_tmtc_int_register( - struct drvmgr_dev *dev, - int irq, - const char *info, - drvmgr_isr handler, - void *arg); -int ambapp_rasta_tmtc_int_unregister( - struct drvmgr_dev *dev, - int irq, - drvmgr_isr handler, - void *arg); -int ambapp_rasta_tmtc_int_unmask( - struct drvmgr_dev *dev, - int irq); -int ambapp_rasta_tmtc_int_mask( - struct drvmgr_dev *dev, - int irq); -int ambapp_rasta_tmtc_int_clear( - struct drvmgr_dev *dev, - int irq); -int ambapp_rasta_tmtc_get_params( - struct drvmgr_dev *dev, - struct drvmgr_bus_params *params); - -struct ambapp_ops ambapp_rasta_tmtc_ops = { - .int_register = ambapp_rasta_tmtc_int_register, - .int_unregister = ambapp_rasta_tmtc_int_unregister, - .int_unmask = ambapp_rasta_tmtc_int_unmask, - .int_mask = ambapp_rasta_tmtc_int_mask, - .int_clear = ambapp_rasta_tmtc_int_clear, - .get_params = ambapp_rasta_tmtc_get_params -}; - -struct drvmgr_drv_ops gr_rasta_tmtc_ops = -{ - .init = {gr_rasta_tmtc_init1, gr_rasta_tmtc_init2, NULL, NULL}, - .remove = NULL, - .info = NULL, -}; - -struct pci_dev_id_match gr_rasta_tmtc_ids[] = -{ - PCIID_DEVVEND(PCIID_VENDOR_GAISLER, PCIID_DEVICE_GR_RASTA_TMTC), - PCIID_END_TABLE /* Mark end of table */ -}; - -struct pci_drv_info gr_rasta_tmtc_info = -{ - { - DRVMGR_OBJ_DRV, /* Driver */ - NULL, /* Next driver */ - NULL, /* Device list */ - DRIVER_PCI_GAISLER_RASTATMTC_ID,/* Driver ID */ - "GR-RASTA-TMTC_DRV", /* Driver Name */ - DRVMGR_BUS_TYPE_PCI, /* Bus Type */ - &gr_rasta_tmtc_ops, - NULL, /* Funcs */ - 0, /* No devices yet */ - sizeof(struct gr_rasta_tmtc_priv) /* Let drvmgr alloc private */ - }, - &gr_rasta_tmtc_ids[0] -}; - -/* Driver resources configuration for the AMBA bus on the GR-RASTA-TMTC board. - * It is declared weak so that the user may override it from the project file, - * if the default settings are not enough. - * - * The configuration consists of an array of configuration pointers, each - * pointer determine the configuration of one GR-RASTA-TMTC board. Pointer - * zero is for board0, pointer 1 for board1 and so on. - * - * The array must end with a NULL pointer. - */ -struct drvmgr_bus_res *gr_rasta_tmtc_resources[] __attribute__((weak)) = -{ - NULL, -}; - -void gr_rasta_tmtc_register_drv(void) -{ - DBG("Registering GR-RASTA-TMTC PCI driver\n"); - drvmgr_drv_register(&gr_rasta_tmtc_info.general); -} - -void gr_rasta_tmtc_isr (void *arg) -{ - struct gr_rasta_tmtc_priv *priv = arg; - unsigned int status, tmp; - int irq; - SPIN_ISR_IRQFLAGS(irqflags); - - tmp = status = priv->irq->ipend; - - /* printk("GR-RASTA-TMTC: IRQ 0x%x\n",status); */ - - SPIN_LOCK(&priv->devlock, irqflags); - for(irq=0; irq<32; irq++) { - if ( status & (1<genirq, irq); - priv->irq->iclear = (1<devlock, irqflags); - - /* ACK interrupt, this is because PCI is Level, so the IRQ Controller still drives the IRQ. */ - if ( tmp ) - drvmgr_interrupt_clear(priv->dev, 0); - - DBG("RASTA-TMTC-IRQ: 0x%x\n", tmp); -} - -/* Init AMBA bus frequency, IRQ controller, GPIO register, bus maps and other - * common stuff between rev0 and rev1. - */ -static int gr_rasta_tmtc_hw_init_common(struct gr_rasta_tmtc_priv *priv) -{ - struct ambapp_dev *tmp; - unsigned int pci_freq_hz; - - /* Initialize Frequency of AMBA bus. The AMBA bus runs at same - * frequency as PCI bus - */ - drvmgr_freq_get(priv->dev, 0, &pci_freq_hz); - ambapp_freq_init(&priv->abus, NULL, pci_freq_hz); - - /* Find IRQ controller, Clear all current IRQs */ - tmp = (struct ambapp_dev *)ambapp_for_each(&priv->abus, - (OPTIONS_ALL|OPTIONS_APB_SLVS), - VENDOR_GAISLER, GAISLER_IRQMP, - ambapp_find_by_idx, NULL); - if ( !tmp ) { - return -4; - } - priv->irq = (struct irqmp_regs *)DEV_TO_APB(tmp)->start; - /* Set up GR-RASTA-TMTC irq controller */ - priv->irq->mask[0] = 0; - priv->irq->iclear = 0xffffffff; - priv->irq->ilevel = 0; - - /* Find First GPIO controller */ - tmp = (struct ambapp_dev *)ambapp_for_each(&priv->abus, - (OPTIONS_ALL|OPTIONS_APB_SLVS), - VENDOR_GAISLER, GAISLER_GPIO, - ambapp_find_by_idx, NULL); - if ( !tmp ) { - return -5; - } - priv->gpio = (struct grgpio_regs *) (((struct ambapp_apb_info *)tmp->devinfo)->start); - /* Clear GR-RASTA-TMTC GPIO controller */ - priv->gpio->imask = 0; - priv->gpio->ipol = 0; - priv->gpio->iedge = 0; - priv->gpio->bypass = 0; - /* Set up GR-RASTA-TMTC GPIO controller to select GRTM and GRTC */ - priv->gpio->output = (GR_TMTC_GPIO_GRTM_SEL|GR_TMTC_GPIO_TRANSP_CLK) | (GR_TMTC_GPIO_TC_BIT_LOCK|GR_TMTC_GPIO_TC_RF_AVAIL|GR_TMTC_GPIO_TC_ACTIVE_HIGH|GR_TMTC_GPIO_TC_RISING_CLK); - priv->gpio->dir = 0xffffffff; - DBG("GR-TMTC GPIO: 0x%x\n", (unsigned int)priv->gpio); - - /* DOWN streams translation table */ - priv->bus_maps_down[0].name = "PCI BAR0 -> AMBA"; - priv->bus_maps_down[0].size = priv->amba_maps[0].size; - priv->bus_maps_down[0].from_adr = (void *)priv->amba_maps[0].local_adr; - priv->bus_maps_down[0].to_adr = (void *)priv->amba_maps[0].remote_adr; - - priv->bus_maps_down[1].name = "PCI BAR1 -> AMBA"; - priv->bus_maps_down[1].size = priv->amba_maps[1].size; - priv->bus_maps_down[1].from_adr = (void *)priv->amba_maps[1].local_adr; - priv->bus_maps_down[1].to_adr = (void *)priv->amba_maps[1].remote_adr; - - /* Mark end of translation table */ - priv->bus_maps_down[2].size = 0; - - return 0; -} - -/* PCI Hardware (Revision 0) initialization */ -static int gr_rasta_tmtc0_hw_init(struct gr_rasta_tmtc_priv *priv) -{ - unsigned int *page0 = NULL; - struct ambapp_dev *tmp; - struct ambapp_ahb_info *ahb; - int status; - pci_dev_t pcidev = priv->pcidev; - struct pci_dev_info *devinfo = priv->devinfo; - uint32_t bar0, bar0_size; - - /* Select version of GR-RASTA-TMTC board */ - switch (devinfo->rev) { - case 0: - priv->version = &gr_rasta_tmtc_ver0; - break; - default: - return -2; - } - - bar0 = devinfo->resources[0].address; - bar0_size = devinfo->resources[0].size; - page0 = (unsigned int *)(bar0 + bar0_size/2); - - /* Point PAGE0 to start of Plug and Play information */ - *page0 = priv->version->amba_ioarea & 0xf0000000; - -#if 0 - { - uint32_t data; - /* set parity error response */ - pci_cfg_r32(pcidev, PCIR_COMMAND, &data); - pci_cfg_w32(pcidev, PCIR_COMMAND, (data|PCIM_CMD_PERRESPEN)); - } -#endif - - /* Setup cache line size. Default cache line size will result in - * poor performance (256 word fetches), 0xff will set it according - * to the max size of the PCI FIFO. - */ - pci_cfg_w8(pcidev, PCIR_CACHELNSZ, 0xff); - - /* Scan AMBA Plug&Play */ - - /* AMBA MAP bar0 (in CPU) ==> 0x80000000(remote amba address) */ - priv->amba_maps[0].size = 0x10000000; - priv->amba_maps[0].local_adr = bar0; - priv->amba_maps[0].remote_adr = AHB1_BASE_ADDR; - - /* AMBA MAP bar1 (in CPU) ==> 0x40000000(remote amba address) */ - priv->amba_maps[1].size = devinfo->resources[1].size; - priv->amba_maps[1].local_adr = devinfo->resources[1].address; - priv->amba_maps[1].remote_adr = 0x40000000; - - /* Addresses not matching with map be untouched */ - priv->amba_maps[2].size = 0xfffffff0; - priv->amba_maps[2].local_adr = 0; - priv->amba_maps[2].remote_adr = 0; - - /* Mark end of table */ - priv->amba_maps[3].size=0; - priv->amba_maps[3].local_adr = 0; - priv->amba_maps[3].remote_adr = 0; - - /* Start AMBA PnP scan at first AHB bus */ - ambapp_scan(&priv->abus, - bar0 + (priv->version->amba_ioarea & ~0xf0000000), - NULL, &priv->amba_maps[0]); - - /* Point PAGE0 to start of APB area */ - *page0 = AHB1_BASE_ADDR; - - /* Find GRPCI controller */ - tmp = (struct ambapp_dev *)ambapp_for_each(&priv->abus, - (OPTIONS_ALL|OPTIONS_APB_SLVS), - VENDOR_GAISLER, GAISLER_PCIFBRG, - ambapp_find_by_idx, NULL); - if ( !tmp ) { - return -3; - } - priv->grpci = (struct grpci_regs *)((struct ambapp_apb_info *)tmp->devinfo)->start; - - /* Set GRPCI mmap so that AMBA masters can access CPU-RAM over - * the PCI window. - */ - priv->grpci->cfg_stat = (priv->grpci->cfg_stat & 0x0fffffff) | - (priv->ahbmst2pci_map & 0xf0000000); - priv->grpci->page1 = 0x40000000; - - /* init AMBA bus, IRQCtrl, GPIO, bus down-maps */ - status = gr_rasta_tmtc_hw_init_common(priv); - if (status) - return status; - - /* Find GRPCI controller AHB Slave interface */ - tmp = (struct ambapp_dev *)ambapp_for_each(&priv->abus, - (OPTIONS_ALL|OPTIONS_AHB_SLVS), - VENDOR_GAISLER, GAISLER_PCIFBRG, - ambapp_find_by_idx, NULL); - if ( !tmp ) { - return -6; - } - ahb = (struct ambapp_ahb_info *)tmp->devinfo; - - /* UP streams translation table */ - priv->bus_maps_up[0].name = "AMBA GRPCI Window"; - priv->bus_maps_up[0].size = ahb->mask[0]; /* AMBA->PCI Window on GR-RASTA-TMTC board */ - priv->bus_maps_up[0].from_adr = (void *)ahb->start[0]; - priv->bus_maps_up[0].to_adr = (void *) - (priv->ahbmst2pci_map & 0xf0000000); - - /* Mark end of translation table */ - priv->bus_maps_up[1].size = 0; - - /* Successfully registered the RASTA board */ - return 0; -} - -/* PCI Hardware (Revision 1) initialization */ -static int gr_rasta_tmtc1_hw_init(struct gr_rasta_tmtc_priv *priv) -{ - int i; - uint32_t data; - unsigned int ctrl; - uint8_t tmp2; - struct ambapp_dev *tmp; - int status; - struct ambapp_ahb_info *ahb; - uint8_t cap_ptr; - pci_dev_t pcidev = priv->pcidev; - struct pci_dev_info *devinfo = priv->devinfo; - - /* Check capabilities list bit */ - pci_cfg_r8(pcidev, PCIR_STATUS, &tmp2); - - if (!((tmp2 >> 4) & 1)) { - /* Capabilities list not available which it should be in the - * GRPCI2 - */ - return -3; - } - - /* Read capabilities pointer */ - pci_cfg_r8(pcidev, PCIR_CAP_PTR, &cap_ptr); - - /* Set AHB address mappings for target PCI bars - * BAR0: 16MB : Mapped to I/O at 0x80000000 - * BAR1: 256MB : Mapped to MEM at 0x40000000 - */ - pci_cfg_w32(pcidev, cap_ptr+GRPCI2_BAR0_TO_AHB_MAP, AHB1_BASE_ADDR); - pci_cfg_w32(pcidev, cap_ptr+GRPCI2_BAR1_TO_AHB_MAP, 0x40000000); - - /* Set PCI bus to be same endianess as PCI system */ - pci_cfg_r32(pcidev, cap_ptr+GRPCI2_PCI_CONFIG, &data); - if (pci_endian == PCI_BIG_ENDIAN) - data = data & 0xFFFFFFFE; - else - data = data | 0x00000001; - pci_cfg_w32(pcidev, cap_ptr+GRPCI2_PCI_CONFIG, data); - -#if 0 - /* set parity error response */ - pci_cfg_r32(pcidev, PCIR_COMMAND, &data); - pci_cfg_w32(pcidev, PCIR_COMMAND, (data|PCIM_CMD_PERRESPEN)); -#endif - - /* Scan AMBA Plug&Play */ - - /* AMBA MAP bar0 (in PCI) ==> 0x40000000 (remote amba address) */ - priv->amba_maps[0].size = devinfo->resources[0].size; - priv->amba_maps[0].local_adr = devinfo->resources[0].address; - priv->amba_maps[0].remote_adr = AHB1_BASE_ADDR; - - /* AMBA MAP bar0 (in PCI) ==> 0x80000000 (remote amba address) */ - priv->amba_maps[1].size = devinfo->resources[1].size; - priv->amba_maps[1].local_adr = devinfo->resources[1].address; - priv->amba_maps[1].remote_adr = 0x40000000; - - /* Addresses not matching with map be untouched */ - priv->amba_maps[2].size = 0xfffffff0; - priv->amba_maps[2].local_adr = 0; - priv->amba_maps[2].remote_adr = 0; - - /* Mark end of table */ - priv->amba_maps[3].size=0; - - /* Start AMBA PnP scan at first AHB bus */ - ambapp_scan( - &priv->abus, - devinfo->resources[0].address + AHB1_IOAREA_OFS, - NULL, - &priv->amba_maps[0]); - - /* init AMBA bus, IRQCtrl, GPIO, bus down-maps */ - status = gr_rasta_tmtc_hw_init_common(priv); - if (status) - return status; - - /* Find GRPCI2 controller AHB Slave interface */ - tmp = (struct ambapp_dev *)ambapp_for_each(&priv->abus, - (OPTIONS_ALL|OPTIONS_AHB_SLVS), - VENDOR_GAISLER, GAISLER_GRPCI2, - ambapp_find_by_idx, NULL); - if ( !tmp ) { - return -6; - } - ahb = (struct ambapp_ahb_info *)tmp->devinfo; - priv->bus_maps_up[0].name = "AMBA GRPCI2 Window"; - priv->bus_maps_up[0].size = ahb->mask[0]; /* AMBA->PCI Window on GR-RASTA-SPW-ROUTER board */ - priv->bus_maps_up[0].from_adr = (void *)ahb->start[0]; - priv->bus_maps_up[0].to_adr = (void *) - (priv->ahbmst2pci_map & ~(ahb->mask[0]-1)); - priv->bus_maps_up[1].size = 0; - - /* Find GRPCI2 controller APB Slave interface */ - tmp = (struct ambapp_dev *)ambapp_for_each(&priv->abus, - (OPTIONS_ALL|OPTIONS_APB_SLVS), - VENDOR_GAISLER, GAISLER_GRPCI2, - ambapp_find_by_idx, NULL); - if ( !tmp ) { - return -7; - } - priv->grpci2 = (struct grpci2_regs *) - ((struct ambapp_apb_info *)tmp->devinfo)->start; - - /* Set AHB to PCI mapping for all AMBA AHB masters */ - for(i = 0; i < 16; i++) { - priv->grpci2->ahbtopcimemmap[i] = priv->ahbmst2pci_map & - ~(ahb->mask[0]-1); - } - - /* Make sure dirq(0) sampling is enabled */ - ctrl = priv->grpci2->ctrl; - ctrl = (ctrl & 0xFFFFFF0F) | (1 << 4); - priv->grpci2->ctrl = ctrl; - - /* Successfully registered the RASTA-SPW-ROUTER board */ - return 0; -} - -static void gr_rasta_tmtc_hw_init2(struct gr_rasta_tmtc_priv *priv) -{ - /* Enable DMA by enabling PCI target as master */ - pci_master_enable(priv->pcidev); -} - -/* Called when a PCI target is found with the PCI device and vendor ID - * given in gr_rasta_tmtc_ids[]. - */ -int gr_rasta_tmtc_init1(struct drvmgr_dev *dev) -{ - struct gr_rasta_tmtc_priv *priv; - struct pci_dev_info *devinfo; - int status; - uint32_t bar0, bar1, bar0_size, bar1_size; - union drvmgr_key_value *value; - int resources_cnt; - - priv = dev->priv; - if (!priv) - return DRVMGR_NOMEM; - priv->dev = dev; - - /* Determine number of configurations */ - resources_cnt = get_resarray_count(gr_rasta_tmtc_resources); - - /* Generate Device prefix */ - - strcpy(priv->prefix, "/dev/rastatmtc0"); - priv->prefix[14] += dev->minor_drv; - mkdir(priv->prefix, S_IRWXU | S_IRWXG | S_IRWXO); - priv->prefix[15] = '/'; - priv->prefix[16] = '\0'; - - priv->devinfo = devinfo = (struct pci_dev_info *)dev->businfo; - priv->pcidev = devinfo->pcidev; - bar0 = devinfo->resources[0].address; - bar0_size = devinfo->resources[0].size; - bar1 = devinfo->resources[1].address; - bar1_size = devinfo->resources[1].size; - printf("\n\n--- GR-RASTA-TMTC[%d] ---\n", dev->minor_drv); - printf(" PCI BUS: 0x%x, SLOT: 0x%x, FUNCTION: 0x%x\n", - PCI_DEV_EXPAND(priv->pcidev)); - printf(" PCI VENDOR: 0x%04x, DEVICE: 0x%04x\n", - devinfo->id.vendor, devinfo->id.device); - printf(" PCI BAR[0]: 0x%lx - 0x%lx\n", bar0, bar0 + bar0_size - 1); - printf(" PCI BAR[1]: 0x%lx - 0x%lx\n", bar1, bar1 + bar1_size - 1); - printf(" IRQ: %d\n\n\n", devinfo->irq); - - /* all neccessary space assigned to GR-RASTA-IO target? */ - if ((bar0_size == 0) || (bar1_size == 0)) - return DRVMGR_ENORES; - - /* Initialize spin-lock for this PCI peripheral device. This is to - * protect the Interrupt Controller Registers. The genirq layer is - * protecting its own internals and ISR dispatching. - */ - SPIN_INIT(&priv->devlock, priv->prefix); - - /* Let user override which PCI address the AHB masters of the - * GR-RASTA-TMTC board access when doing DMA to CPU RAM. The AHB masters - * access the PCI Window of the AMBA bus, the MSB 4-bits of that address - * is translated according this config option before the address - * goes out on the PCI bus. - * Only the 4 MSB bits have an effect; - */ - value = drvmgr_dev_key_get(priv->dev, "ahbmst2pci", DRVMGR_KT_INT); - if (value) - priv->ahbmst2pci_map = value->i; - else - priv->ahbmst2pci_map = AHBMST2PCIADR; /* default */ - - priv->genirq = genirq_init(32); - if ( priv->genirq == NULL ) - return DRVMGR_FAIL; - - /* Select version of GR-RASTA-IO board */ - switch (devinfo->rev) { - case 0: - puts("GR-RASTA-TMTC: REVISION 0"); - status = gr_rasta_tmtc0_hw_init(priv); - break; - case 1: - puts("GR-RASTA-TMTC: REVISION 1"); - status = gr_rasta_tmtc1_hw_init(priv); - break; - default: - return DRVMGR_ENOSYS; /* HW not supported */ - } - - if ( status != 0 ) { - genirq_destroy(priv->genirq); - printf(" Failed to initialize GR-RASTA-TMTC HW: %d\n", status); - return DRVMGR_FAIL; - } - - /* Init amba bus */ - priv->config.abus = &priv->abus; - priv->config.ops = &ambapp_rasta_tmtc_ops; - priv->config.maps_up = &priv->bus_maps_up[0]; - priv->config.maps_down = &priv->bus_maps_down[0]; - if ( priv->dev->minor_drv < resources_cnt ) { - priv->config.resources = gr_rasta_tmtc_resources[priv->dev->minor_drv]; - } else { - priv->config.resources = NULL; - } - - return ambapp_bus_register(dev, &priv->config); -} - -int gr_rasta_tmtc_init2(struct drvmgr_dev *dev) -{ - struct gr_rasta_tmtc_priv *priv = dev->priv; - - /* Clear any old interrupt requests */ - drvmgr_interrupt_clear(priv->dev, 0); - - /* Enable System IRQ so that GR-RASTA-TMTC PCI target interrupt goes - * through. - * - * It is important to enable it in stage init2. If interrupts were - * enabled in init1 this might hang the system when more than one - * PCI target is connected, this is because PCI interrupts might - * be shared and PCI board 2 have not initialized and - * might therefore drive interrupt already when entering init1(). - */ - drvmgr_interrupt_register( - priv->dev, - 0, - "gr_rasta_tmtc", - gr_rasta_tmtc_isr, - (void *)priv); - - gr_rasta_tmtc_hw_init2(priv); - - return DRVMGR_OK; -} - -int ambapp_rasta_tmtc_int_register( - struct drvmgr_dev *dev, - int irq, - const char *info, - drvmgr_isr handler, - void *arg) -{ - struct gr_rasta_tmtc_priv *priv = dev->parent->dev->priv; - SPIN_IRQFLAGS(irqflags); - int status; - void *h; - - h = genirq_alloc_handler(handler, arg); - if ( h == NULL ) - return DRVMGR_FAIL; - - SPIN_LOCK_IRQ(&priv->devlock, irqflags); - - status = genirq_register(priv->genirq, irq, h); - if ( status == 0 ) { - /* Disable and clear IRQ for first registered handler */ - priv->irq->iclear = (1<devlock, irqflags); - genirq_free_handler(h); - return DRVMGR_FAIL; - } - - status = genirq_enable(priv->genirq, irq, handler, arg); - if ( status == 0 ) { - /* Enable IRQ for first enabled handler only */ - priv->irq->mask[0] |= (1<devlock, irqflags); - - return status; -} - -int ambapp_rasta_tmtc_int_unregister( - struct drvmgr_dev *dev, - int irq, - drvmgr_isr isr, - void *arg) -{ - struct gr_rasta_tmtc_priv *priv = dev->parent->dev->priv; - SPIN_IRQFLAGS(irqflags); - int status; - void *handler; - - SPIN_LOCK_IRQ(&priv->devlock, irqflags); - - status = genirq_disable(priv->genirq, irq, isr, arg); - if ( status == 0 ) { - /* Disable IRQ only when no enabled handler exists */ - priv->irq->mask[0] &= ~(1<genirq, irq, isr, arg); - if ( handler == NULL ) - status = DRVMGR_FAIL; - else - status = DRVMGR_OK; - - SPIN_UNLOCK_IRQ(&priv->devlock, irqflags); - - if (handler) - genirq_free_handler(handler); - - return status; -} - -int ambapp_rasta_tmtc_int_unmask( - struct drvmgr_dev *dev, - int irq) -{ - struct gr_rasta_tmtc_priv *priv = dev->parent->dev->priv; - SPIN_IRQFLAGS(irqflags); - - DBG("RASTA-TMTC IRQ %d: unmask\n", irq); - - if ( genirq_check(priv->genirq, irq) ) - return DRVMGR_EINVAL; - - SPIN_LOCK_IRQ(&priv->devlock, irqflags); - - /* Enable IRQ */ - priv->irq->mask[0] |= (1<devlock, irqflags); - - return DRVMGR_OK; -} - -int ambapp_rasta_tmtc_int_mask( - struct drvmgr_dev *dev, - int irq) -{ - struct gr_rasta_tmtc_priv *priv = dev->parent->dev->priv; - SPIN_IRQFLAGS(irqflags); - - DBG("RASTA-TMTC IRQ %d: mask\n", irq); - - if ( genirq_check(priv->genirq, irq) ) - return DRVMGR_EINVAL; - - SPIN_LOCK_IRQ(&priv->devlock, irqflags); - - /* Disable IRQ */ - priv->irq->mask[0] &= ~(1<devlock, irqflags); - - return DRVMGR_OK; -} - -int ambapp_rasta_tmtc_int_clear( - struct drvmgr_dev *dev, - int irq) -{ - struct gr_rasta_tmtc_priv *priv = dev->parent->dev->priv; - - if ( genirq_check(priv->genirq, irq) ) - return DRVMGR_FAIL; - - priv->irq->iclear = (1<parent->dev->priv; - - /* Device name prefix pointer, skip /dev */ - params->dev_prefix = &priv->prefix[5]; - - return 0; -} - -void gr_rasta_tmtc_print_dev(struct drvmgr_dev *dev, int options) -{ - struct gr_rasta_tmtc_priv *priv = dev->priv; - struct pci_dev_info *devinfo = priv->devinfo; - uint32_t bar0, bar1, bar0_size, bar1_size; - - /* Print */ - printf("--- GR-RASTA-TMTC [bus 0x%x, dev 0x%x, fun 0x%x] ---\n", - PCI_DEV_EXPAND(priv->pcidev)); - - bar0 = devinfo->resources[0].address; - bar0_size = devinfo->resources[0].size; - bar1 = devinfo->resources[1].address; - bar1_size = devinfo->resources[1].size; - - printf(" PCI BAR[0]: 0x%lx - 0x%lx\n", bar0, bar0 + bar0_size - 1); - printf(" PCI BAR[1]: 0x%lx - 0x%lx\n", bar1, bar1 + bar1_size - 1); - printf(" IRQ: %d\n", devinfo->irq); - printf(" PCI REVISION: %d\n", devinfo->rev); - printf(" FREQ: %d Hz\n", priv->version->amba_freq_hz); - printf(" IMASK: 0x%08x\n", priv->irq->mask[0]); - printf(" IPEND: 0x%08x\n", priv->irq->ipend); - - /* Print amba config */ - if ( options & RASTA_TMTC_OPTIONS_AMBA ) { - ambapp_print(&priv->abus, 10); - } - -#if 0 - /* Print IRQ handlers and their arguments */ - if ( options & RASTA_TMTC_OPTIONS_IRQ ) { - int i; - for(i=0; i<16; i++) { - printf(" IRQ[%02d]: 0x%x, arg: 0x%x\n", - i, (unsigned int)priv->isrs[i].handler, (unsigned int)priv->isrs[i].arg); - } - } -#endif -} - -void gr_rasta_tmtc_print(int options) -{ - struct pci_drv_info *drv = &gr_rasta_tmtc_info; - struct drvmgr_dev *dev; - - dev = drv->general.dev; - while(dev) { - gr_rasta_tmtc_print_dev(dev, options); - dev = dev->next_in_drv; - } -} diff --git a/c/src/lib/libbsp/sparc/shared/pci/gr_tmtc_1553.c b/c/src/lib/libbsp/sparc/shared/pci/gr_tmtc_1553.c deleted file mode 100644 index ec51ec312d..0000000000 --- a/c/src/lib/libbsp/sparc/shared/pci/gr_tmtc_1553.c +++ /dev/null @@ -1,602 +0,0 @@ -/* GR-TMTC-1553 PCI Target driver. - * - * COPYRIGHT (c) 2008. - * Cobham Gaisler AB. - * - * Configures the GR-TMTC-1553 interface PCI board. - * This driver provides a AMBA PnP bus by using the general part - * of the AMBA PnP bus driver (ambapp_bus.c). - * - * Driver resources for the AMBA PnP bus provided can be set using - * gr_tmtc_1553_set_resources(). - * - * 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 -#include -#include /* spin-lock */ -#include -#include - -#include -#include -#include -#include -#include -#include -#include - -#include - -/* map via rtems_interrupt_lock_* API: */ -#define SPIN_DECLARE(lock) RTEMS_INTERRUPT_LOCK_MEMBER(lock) -#define SPIN_INIT(lock, name) rtems_interrupt_lock_initialize(lock, name) -#define SPIN_LOCK(lock, level) rtems_interrupt_lock_acquire_isr(lock, &level) -#define SPIN_LOCK_IRQ(lock, level) rtems_interrupt_lock_acquire(lock, &level) -#define SPIN_UNLOCK(lock, level) rtems_interrupt_lock_release_isr(lock, &level) -#define SPIN_UNLOCK_IRQ(lock, level) rtems_interrupt_lock_release(lock, &level) -#define SPIN_IRQFLAGS(k) rtems_interrupt_lock_context k -#define SPIN_ISR_IRQFLAGS(k) SPIN_IRQFLAGS(k) - -/*#define DEBUG 1 */ - -#ifdef DEBUG -#define DBG(x...) printk(x) -#else -#define DBG(x...) -#endif - -/* PCI ID */ -#define PCIID_VENDOR_GAISLER 0x1AC8 - -int gr_tmtc_1553_init1(struct drvmgr_dev *dev); -int gr_tmtc_1553_init2(struct drvmgr_dev *dev); -void gr_tmtc_1553_isr (void *arg); - -struct gr_tmtc_1553_ver { - const unsigned int amba_freq_hz; /* The frequency */ - const unsigned int amba_ioarea; /* The address where the PnP IOAREA starts at */ -}; - -/* Private data structure for driver */ -struct gr_tmtc_1553_priv { - /* Driver management */ - struct drvmgr_dev *dev; - char prefix[32]; - SPIN_DECLARE(devlock); - - /* PCI */ - pci_dev_t pcidev; - struct pci_dev_info *devinfo; - - /* IRQ */ - genirq_t genirq; - - struct gr_tmtc_1553_ver *version; - struct irqmp_regs *irq; - struct drvmgr_map_entry bus_maps_down[2]; - - struct ambapp_bus abus; - struct ambapp_mmap amba_maps[4]; - struct ambapp_config config; -}; - -struct gr_tmtc_1553_ver gr_tmtc_1553_ver0 = { - .amba_freq_hz = 33333333, - .amba_ioarea = 0xfff00000, -}; - - -int ambapp_tmtc_1553_int_register( - struct drvmgr_dev *dev, - int irq, - const char *info, - drvmgr_isr handler, - void *arg); -int ambapp_tmtc_1553_int_unregister( - struct drvmgr_dev *dev, - int irq, - drvmgr_isr handler, - void *arg); -int ambapp_tmtc_1553_int_unmask( - struct drvmgr_dev *dev, - int irq); -int ambapp_tmtc_1553_int_mask( - struct drvmgr_dev *dev, - int irq); -int ambapp_tmtc_1553_int_clear( - struct drvmgr_dev *dev, - int irq); -int ambapp_tmtc_1553_get_params( - struct drvmgr_dev *dev, - struct drvmgr_bus_params *params); - -struct ambapp_ops ambapp_tmtc_1553_ops = { - .int_register = ambapp_tmtc_1553_int_register, - .int_unregister = ambapp_tmtc_1553_int_unregister, - .int_unmask = ambapp_tmtc_1553_int_unmask, - .int_mask = ambapp_tmtc_1553_int_mask, - .int_clear = ambapp_tmtc_1553_int_clear, - .get_params = ambapp_tmtc_1553_get_params -}; - -struct drvmgr_drv_ops gr_tmtc_1553_ops = -{ - {gr_tmtc_1553_init1, gr_tmtc_1553_init2, NULL, NULL}, - NULL, - NULL -}; - -struct pci_dev_id_match gr_tmtc_1553_ids[] = -{ - PCIID_DEVVEND(PCIID_VENDOR_GAISLER, PCIID_DEVICE_GR_TMTC_1553), - PCIID_END_TABLE /* Mark end of table */ -}; - -struct pci_drv_info gr_tmtc_1553_info = -{ - { - DRVMGR_OBJ_DRV, /* Driver */ - NULL, /* Next driver */ - NULL, /* Device list */ - DRIVER_PCI_GAISLER_TMTC_1553_ID, /* Driver ID */ - "GR-TMTC-1553_DRV", /* Driver Name */ - DRVMGR_BUS_TYPE_PCI, /* Bus Type */ - &gr_tmtc_1553_ops, - NULL, /* Funcs */ - 0, /* No devices yet */ - 0, - }, - &gr_tmtc_1553_ids[0] -}; - -/* Driver resources configuration for the AMBA bus on the GR-RASTA-IO board. - * It is declared weak so that the user may override it from the project file, - * if the default settings are not enough. - * - * The configuration consists of an array of configuration pointers, each - * pointer determine the configuration of one GR-RASTA-IO board. Pointer - * zero is for board0, pointer 1 for board1 and so on. - * - * The array must end with a NULL pointer. - */ -struct drvmgr_bus_res *gr_tmtc_1553_resources[] __attribute__((weak)) = -{ - NULL -}; - -void gr_tmtc_1553_register_drv(void) -{ - DBG("Registering GR-TMTC-1553 PCI driver\n"); - drvmgr_drv_register(&gr_tmtc_1553_info.general); -} - -void gr_tmtc_1553_isr (void *arg) -{ - struct gr_tmtc_1553_priv *priv = arg; - unsigned int status, tmp; - int irq; - SPIN_ISR_IRQFLAGS(irqflags); - - tmp = status = priv->irq->ipend; - - /* DBG("GR-RASTA-IO: IRQ 0x%x\n",status); */ - - SPIN_LOCK(&priv->devlock, irqflags); - for(irq=0; irq<16; irq++) { - if ( status & (1<genirq, irq); - priv->irq->iclear = (1<devlock, irqflags); - - /* ACK interrupt, this is because PCI is Level, so the IRQ Controller still drives the IRQ. */ - if ( tmp ) - drvmgr_interrupt_clear(priv->dev, 0); - - DBG("GR-TMTC-1553-IRQ: 0x%x\n", tmp); -} - -static int gr_tmtc_1553_hw_init(struct gr_tmtc_1553_priv *priv) -{ - unsigned int *page0 = NULL; - struct ambapp_dev *tmp; - unsigned int pci_freq_hz; - struct pci_dev_info *devinfo = priv->devinfo; - uint32_t bar0, bar0_size; - - /* Select version of GR-TMTC-1553 board */ - switch (devinfo->rev) { - case 0: - priv->version = &gr_tmtc_1553_ver0; - break; - default: - return -2; - } - - bar0 = devinfo->resources[0].address; - bar0_size = devinfo->resources[0].size; - page0 = (unsigned int *)(bar0 + bar0_size/2); - - /* Point PAGE0 to start of board address map. RAM at 0xff000000, APB at 0xffc00000, IOAREA at 0xfff000000 */ - /* XXX We assume little endian host with byte twisting enabled here */ - *page0 = 0x010000ff; /* Set little endian mode on peripheral. */ - - /* Scan AMBA Plug&Play */ - - /* AMBA MAP bar0 (in CPU) ==> 0x80000000(remote amba address) */ - priv->amba_maps[0].size = 0x1000000; - priv->amba_maps[0].local_adr = bar0; - priv->amba_maps[0].remote_adr = 0xff000000; - - /* Addresses not matching with map be untouched */ - priv->amba_maps[2].size = 0xfffffff0; - priv->amba_maps[2].local_adr = 0; - priv->amba_maps[2].remote_adr = 0; - - /* Mark end of table */ - priv->amba_maps[3].size=0; - priv->amba_maps[3].local_adr = 0; - priv->amba_maps[3].remote_adr = 0; - - /* Start AMBA PnP scan at first AHB bus */ - ambapp_scan(&priv->abus, - bar0 + (priv->version->amba_ioarea & ~0xff000000), - NULL, &priv->amba_maps[0]); - - /* Frequency is the hsame as the PCI bus frequency */ - drvmgr_freq_get(priv->dev, 0, &pci_freq_hz); - - ambapp_freq_init(&priv->abus, NULL, pci_freq_hz); - - /* Find IRQ controller */ - tmp = (struct ambapp_dev *)ambapp_for_each(&priv->abus, - (OPTIONS_ALL|OPTIONS_APB_SLVS), - VENDOR_GAISLER, GAISLER_IRQMP, - ambapp_find_by_idx, NULL); - if ( !tmp ) { - return -4; - } - priv->irq = (struct irqmp_regs *)DEV_TO_APB(tmp)->start; - /* Set up irq controller */ - priv->irq->mask[0] = 0; - priv->irq->iclear = 0xffff; - priv->irq->ilevel = 0; - - /* DOWN streams translation table */ - priv->bus_maps_down[0].name = "PCI BAR0 -> AMBA"; - priv->bus_maps_down[0].size = priv->amba_maps[0].size; - priv->bus_maps_down[0].from_adr = (void *)priv->amba_maps[0].local_adr; - priv->bus_maps_down[0].to_adr = (void *)priv->amba_maps[0].remote_adr; - /* Mark end of translation table */ - priv->bus_maps_down[1].size = 0; - - /* Successfully registered the board */ - return 0; -} - - -/* Called when a PCI target is found with the PCI device and vendor ID - * given in gr_tmtc_1553_ids[]. - */ -int gr_tmtc_1553_init1(struct drvmgr_dev *dev) -{ - struct gr_tmtc_1553_priv *priv; - struct pci_dev_info *devinfo; - int status; - uint32_t bar0, bar0_size; - int resources_cnt; - - /* PCI device does not have the IRQ line register, when PCI autoconf configures it the configuration - * is forgotten. We take the IRQ number from the PCI Host device (AMBA device), this works as long - * as PCI-IRQs are ored together on the bus. - * - * Note that this only works on LEON. - */ - ((struct pci_dev_info *)dev->businfo)->irq = ((struct amba_dev_info *)dev->parent->dev->businfo)->info.irq; - - priv = malloc(sizeof(struct gr_tmtc_1553_priv)); - if ( !priv ) - return DRVMGR_NOMEM; - - memset(priv, 0, sizeof(*priv)); - dev->priv = priv; - priv->dev = dev; - - /* Determine number of configurations */ - resources_cnt = get_resarray_count(gr_tmtc_1553_resources); - - /* Generate Device prefix */ - - strcpy(priv->prefix, "/dev/tmtc1553_0"); - priv->prefix[14] += dev->minor_drv; - mkdir(priv->prefix, S_IRWXU | S_IRWXG | S_IRWXO); - priv->prefix[15] = '/'; - priv->prefix[16] = '\0'; - - priv->devinfo = devinfo = (struct pci_dev_info *)dev->businfo; - priv->pcidev = devinfo->pcidev; - bar0 = devinfo->resources[0].address; - bar0_size = devinfo->resources[0].size; - printf("\n\n--- GR-TMTC-1553[%d] ---\n", dev->minor_drv); - printf(" PCI BUS: 0x%x, SLOT: 0x%x, FUNCTION: 0x%x\n", - PCI_DEV_EXPAND(priv->pcidev)); - printf(" PCI VENDOR: 0x%04x, DEVICE: 0x%04x\n", - devinfo->id.vendor, devinfo->id.device); - printf(" PCI BAR[0]: 0x%lx - 0x%lx\n", bar0, bar0 + bar0_size - 1); - printf(" IRQ: %d\n\n\n", devinfo->irq); - - /* all neccessary space assigned to GR-TMTC-1553 target? */ - if (bar0_size == 0) - return DRVMGR_ENORES; - - /* Initialize spin-lock for this PCI peripheral device. This is to - * protect the Interrupt Controller Registers. The genirq layer is - * protecting its own internals and ISR dispatching. - */ - SPIN_INIT(&priv->devlock, priv->prefix); - - priv->genirq = genirq_init(16); - if ( priv->genirq == NULL ) { - free(priv); - dev->priv = NULL; - return DRVMGR_FAIL; - } - - status = gr_tmtc_1553_hw_init(priv); - if ( status != 0 ) { - genirq_destroy(priv->genirq); - free(priv); - dev->priv = NULL; - printf(" Failed to initialize GR-TMTC-1553 HW: %d\n", status); - return DRVMGR_FAIL; - } - - /* Init amba bus */ - priv->config.abus = &priv->abus; - priv->config.ops = &ambapp_tmtc_1553_ops; - priv->config.maps_down = &priv->bus_maps_down[0]; - /* This PCI device has only target interface so DMA is not supported, - * which means that translation from AMBA->PCI should fail if attempted. - */ - priv->config.maps_up = DRVMGR_TRANSLATE_NO_BRIDGE; - if ( priv->dev->minor_drv < resources_cnt ) { - priv->config.resources = gr_tmtc_1553_resources[priv->dev->minor_drv]; - } else { - priv->config.resources = NULL; - } - - /* Create And Register AMBA PnP Bus */ - return ambapp_bus_register(dev, &priv->config); -} - -int gr_tmtc_1553_init2(struct drvmgr_dev *dev) -{ - struct gr_tmtc_1553_priv *priv = dev->priv; - - /* Clear any old interrupt requests */ - drvmgr_interrupt_clear(dev, 0); - - /* Enable System IRQ so that GR-TMTC-1553 PCI target interrupt goes through. - * - * It is important to enable it in stage init2. If interrupts were enabled in init1 - * this might hang the system when more than one PCI target is connected, this is - * because PCI interrupts might be shared and PCI target 2 have not initialized and - * might therefore drive interrupt already when entering init1(). - */ - drvmgr_interrupt_register( - dev, - 0, - "gr_tmtc_1553", - gr_tmtc_1553_isr, - (void *)priv); - - return DRVMGR_OK; -} - -int ambapp_tmtc_1553_int_register( - struct drvmgr_dev *dev, - int irq, - const char *info, - drvmgr_isr handler, - void *arg) -{ - struct gr_tmtc_1553_priv *priv = dev->parent->dev->priv; - SPIN_IRQFLAGS(irqflags); - int status; - void *h; - - h = genirq_alloc_handler(handler, arg); - if ( h == NULL ) - return DRVMGR_FAIL; - - SPIN_LOCK_IRQ(&priv->devlock, irqflags); - - status = genirq_register(priv->genirq, irq, h); - if ( status == 0 ) { - /* Disable and clear IRQ for first registered handler */ - priv->irq->iclear = (1<irq->mask[0] &= ~(1<devlock, irqflags); - genirq_free_handler(h); - return DRVMGR_FAIL; - } - - status = genirq_enable(priv->genirq, irq, handler, arg); - if ( status == 0 ) { - /* Enable IRQ for first enabled handler only */ - priv->irq->mask[0] |= (1<devlock, irqflags); - - return status; -} - -int ambapp_tmtc_1553_int_unregister( - struct drvmgr_dev *dev, - int irq, - drvmgr_isr isr, - void *arg) -{ - struct gr_tmtc_1553_priv *priv = dev->parent->dev->priv; - SPIN_IRQFLAGS(irqflags); - int status; - void *handler; - - SPIN_LOCK_IRQ(&priv->devlock, irqflags); - - status = genirq_disable(priv->genirq, irq, isr, arg); - if ( status == 0 ) { - /* Disable IRQ only when no enabled handler exists */ - priv->irq->mask[0] &= ~(1<genirq, irq, isr, arg); - if ( handler == NULL ) - status = DRVMGR_FAIL; - else - status = DRVMGR_OK; - - SPIN_UNLOCK_IRQ(&priv->devlock, irqflags); - - if (handler) - genirq_free_handler(handler); - - return status; -} - -int ambapp_tmtc_1553_int_unmask( - struct drvmgr_dev *dev, - int irq) -{ - struct gr_tmtc_1553_priv *priv = dev->parent->dev->priv; - SPIN_IRQFLAGS(irqflags); - - DBG("TMTC-1553 IRQ %d: enable\n", irq); - - if ( genirq_check(priv->genirq, irq) ) - return DRVMGR_FAIL; - - SPIN_LOCK_IRQ(&priv->devlock, irqflags); - - /* Enable IRQ */ - priv->irq->mask[0] |= (1<devlock, irqflags); - - return DRVMGR_OK; -} - -int ambapp_tmtc_1553_int_mask( - struct drvmgr_dev *dev, - int irq) -{ - struct gr_tmtc_1553_priv *priv = dev->parent->dev->priv; - SPIN_IRQFLAGS(irqflags); - - DBG("TMTC-1553 IRQ %d: disable\n", irq); - - if ( genirq_check(priv->genirq, irq) ) - return DRVMGR_FAIL; - - SPIN_LOCK_IRQ(&priv->devlock, irqflags); - - /* Disable IRQ */ - priv->irq->mask[0] &= ~(1<devlock, irqflags); - - return DRVMGR_OK; -} - -int ambapp_tmtc_1553_int_clear( - struct drvmgr_dev *dev, - int irq) -{ - struct gr_tmtc_1553_priv *priv = dev->parent->dev->priv; - - if ( genirq_check(priv->genirq, irq) ) - return DRVMGR_FAIL; - - priv->irq->iclear = (1<parent->dev->priv; - - /* Device name prefix pointer, skip /dev */ - params->dev_prefix = &priv->prefix[5]; - - return 0; -} - -void gr_tmtc_1553_print_dev(struct drvmgr_dev *dev, int options) -{ - struct gr_tmtc_1553_priv *priv = dev->priv; - struct pci_dev_info *devinfo = priv->devinfo; - uint32_t bar0, bar0_size; - - /* Print */ - printf("--- GR-TMTC-1553 [bus 0x%x, dev 0x%x, fun 0x%x] ---\n", - PCI_DEV_EXPAND(priv->pcidev)); - - bar0 = devinfo->resources[0].address; - bar0_size = devinfo->resources[0].size; - - printf(" PCI BAR[0]: 0x%lx - 0x%lx\n", bar0, bar0 + bar0_size - 1); - printf(" IRQ REGS: 0x%x\n", (unsigned int)priv->irq); - printf(" IRQ: %d\n", devinfo->irq); - printf(" FREQ: %d Hz\n", priv->version->amba_freq_hz); - printf(" IMASK: 0x%08x\n", priv->irq->mask[0]); - printf(" IPEND: 0x%08x\n", priv->irq->ipend); - - /* Print amba config */ - if ( options & TMTC_1553_OPTIONS_AMBA ) { - ambapp_print(&priv->abus, 10); - } -#if 0 - /* Print IRQ handlers and their arguments */ - if ( options & TMTC_1553_OPTIONS_IRQ ) { - int i; - for(i=0; i<16; i++) { - printf(" IRQ[%02d]: 0x%x, arg: 0x%x\n", - i, (unsigned int)priv->isrs[i].handler, (unsigned int)priv->isrs[i].arg); - } - } -#endif -} - -void gr_tmtc_1553_print(int options) -{ - struct pci_drv_info *drv = &gr_tmtc_1553_info; - struct drvmgr_dev *dev; - - dev = drv->general.dev; - while(dev) { - gr_tmtc_1553_print_dev(dev, options); - dev = dev->next_in_drv; - } -} diff --git a/c/src/lib/libbsp/sparc/shared/pci/grpci.c b/c/src/lib/libbsp/sparc/shared/pci/grpci.c deleted file mode 100644 index 047f1c199d..0000000000 --- a/c/src/lib/libbsp/sparc/shared/pci/grpci.c +++ /dev/null @@ -1,722 +0,0 @@ -/* GRLIB GRPCI PCI HOST driver. - * - * COPYRIGHT (c) 2008. - * Cobham Gaisler AB. - * - * Configures the GRPCI core and initialize, - * - the PCI Library (pci.c) - * - the general part of the PCI Bus driver (pci_bus.c) - * - * System interrupt assigned to PCI interrupt (INTA#..INTD#) is by - * default taken from Plug and Play, but may be overridden by the - * driver resources INTA#..INTD#. - * - * 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 -#include -#include - -#include -#include -#include -#include -#include - -#define DMAPCI_ADDR 0x80000500 - -/* Configuration options */ -#define SYSTEM_MAINMEM_START 0x40000000 - -/* If defined to 1 - byte twisting is enabled by default */ -#define DEFAULT_BT_ENABLED 0 - -/* Interrupt assignment. Set to other value than 0xff in order to - * override defaults and plug&play information - */ -#ifndef GRPCI_INTA_SYSIRQ - #define GRPCI_INTA_SYSIRQ 0xff -#endif -#ifndef GRPCI_INTB_SYSIRQ - #define GRPCI_INTB_SYSIRQ 0xff -#endif -#ifndef GRPCI_INTC_SYSIRQ - #define GRPCI_INTC_SYSIRQ 0xff -#endif -#ifndef GRPCI_INTD_SYSIRQ - #define GRPCI_INTD_SYSIRQ 0xff -#endif - -#define PAGE0_BTEN_BIT 0 -#define PAGE0_BTEN (1< 15) { - *val = 0xffffffff; - return PCISTS_OK; - } - - /* GRPCI can access "non-standard" devices on bus0 (on AD11.AD16), - * but we skip them. - */ - if (dev == HOST_TGT) - bus = devfn = 0; - else if (bus == 0) - devfn = PCI_DEV_DEVFUNC(dev) + PCI_DEV(0, 6, 0); - else - devfn = PCI_DEV_DEVFUNC(dev); - - /* Select bus */ - priv->regs->cfg_stat = (priv->regs->cfg_stat & ~(0xf<<23)) | (bus<<23); - - pci_conf = (volatile uint32_t *)(priv->pci_conf | (devfn << 8) | ofs); - - if (priv->bt_enabled) { - *val = CPU_swap_u32(*pci_conf); - } else { - *val = *pci_conf; - } - - if (priv->regs->cfg_stat & 0x100) { - *val = 0xffffffff; - retval = PCISTS_MSTABRT; - } else - retval = PCISTS_OK; - - DBG("pci_read: [%x:%x:%x] reg: 0x%x => addr: 0x%x, val: 0x%x\n", - PCI_DEV_EXPAND(dev), ofs, pci_conf, *val); - - return retval; -} - - -static int grpci_cfg_r16(pci_dev_t dev, int ofs, uint16_t *val) -{ - uint32_t v; - int retval; - - if (ofs & 1) - return PCISTS_EINVAL; - - retval = grpci_cfg_r32(dev, ofs & ~0x3, &v); - *val = 0xffff & (v >> (8*(ofs & 0x3))); - - return retval; -} - -static int grpci_cfg_r8(pci_dev_t dev, int ofs, uint8_t *val) -{ - uint32_t v; - int retval; - - retval = grpci_cfg_r32(dev, ofs & ~0x3, &v); - - *val = 0xff & (v >> (8*(ofs & 3))); - - return retval; -} - -static int grpci_cfg_w32(pci_dev_t dev, int ofs, uint32_t val) -{ - struct grpci_priv *priv = grpcipriv; - volatile uint32_t *pci_conf; - uint32_t value, devfn = PCI_DEV_DEVFUNC(dev); - int bus = PCI_DEV_BUS(dev); - - if (ofs & 0x3) - return PCISTS_EINVAL; - - if (PCI_DEV_SLOT(dev) > 15) - return PCISTS_MSTABRT; - - /* GRPCI can access "non-standard" devices on bus0 (on AD11.AD16), - * but we skip them. - */ - if (dev == HOST_TGT) - bus = devfn = 0; - else if (bus == 0) - devfn = PCI_DEV_DEVFUNC(dev) + PCI_DEV(0, 6, 0); - else - devfn = PCI_DEV_DEVFUNC(dev); - - /* Select bus */ - priv->regs->cfg_stat = (priv->regs->cfg_stat & ~(0xf<<23)) | (bus<<23); - - pci_conf = (volatile uint32_t *)(priv->pci_conf | (devfn << 8) | ofs); - - if ( priv->bt_enabled ) { - value = CPU_swap_u32(val); - } else { - value = val; - } - - *pci_conf = value; - - DBG("pci_write - [%x:%x:%x] reg: 0x%x => addr: 0x%x, val: 0x%x\n", - PCI_DEV_EXPAND(dev), ofs, pci_conf, value); - - return PCISTS_OK; -} - -static int grpci_cfg_w16(pci_dev_t dev, int ofs, uint16_t val) -{ - uint32_t v; - int retval; - - if (ofs & 1) - return PCISTS_EINVAL; - - retval = grpci_cfg_r32(dev, ofs & ~0x3, &v); - if (retval != PCISTS_OK) - return retval; - - v = (v & ~(0xffff << (8*(ofs&3)))) | ((0xffff&val) << (8*(ofs&3))); - - return grpci_cfg_w32(dev, ofs & ~0x3, v); -} - -static int grpci_cfg_w8(pci_dev_t dev, int ofs, uint8_t val) -{ - uint32_t v; - int retval; - - retval = grpci_cfg_r32(dev, ofs & ~0x3, &v); - if (retval != PCISTS_OK) - return retval; - - v = (v & ~(0xff << (8*(ofs&3)))) | ((0xff&val) << (8*(ofs&3))); - - return grpci_cfg_w32(dev, ofs & ~0x3, v); -} - -/* Return the assigned system IRQ number that corresponds to the PCI - * "Interrupt Pin" information from configuration space. - * - * The IRQ information is stored in the grpci_pci_irq_table configurable - * by the user. - * - * Returns the "system IRQ" for the PCI INTA#..INTD# pin in irq_pin. Returns - * 0xff if not assigned. - */ -static uint8_t grpci_bus0_irq_map(pci_dev_t dev, int irq_pin) -{ - uint8_t sysIrqNr = 0; /* not assigned */ - int irq_group; - - if ( (irq_pin >= 1) && (irq_pin <= 4) ) { - /* Use default IRQ decoding on PCI BUS0 according slot numbering */ - irq_group = PCI_DEV_SLOT(dev) & 0x3; - irq_pin = ((irq_pin - 1) + irq_group) & 0x3; - /* Valid PCI "Interrupt Pin" number */ - sysIrqNr = grpci_pci_irq_table[irq_pin]; - } - return sysIrqNr; -} - -static int grpci_translate(uint32_t *address, int type, int dir) -{ - uint32_t adr; - struct grpci_priv *priv = grpcipriv; - - if (type == 1) { - /* I/O */ - if (dir != 0) { - /* The PCI bus can not access the CPU bus from I/O - * because GRPCI core does not support I/O BARs - */ - return -1; - } - - /* We have got a PCI BAR address that the CPU want to access... - * Check that it is within the PCI I/O window, I/O adresses - * are mapped 1:1 with GRPCI driver... no translation needed. - */ - adr = *(uint32_t *)address; - if (adr < priv->pci_io || adr >= priv->pci_conf) - return -1; - } else { - /* MEMIO and MEM. - * Memory space is mapped 1:1 so no translation is needed. - * Check that address is within accessible windows. - */ - adr = *(uint32_t *)address; - if (dir == 0) { - /* PCI BAR to AMBA-CPU address.. check that it is - * located within GRPCI PCI Memory Window - * adr = PCI address. - */ - if (adr < priv->pci_area || adr >= priv->pci_area_end) - return -1; - } else { - /* We have a CPU address and want to get access to it - * from PCI space, typically when doing DMA into CPU - * RAM. The GRPCI core has two target BARs that PCI - * masters can access, we check here that the address - * is accessible from PCI. - * adr = AMBA address. - */ - if (adr < priv->bar1_pci_adr || - adr >= (priv->bar1_pci_adr + priv->bar1_size)) - return -1; - } - } - - return 0; -} - -extern struct pci_memreg_ops pci_memreg_sparc_le_ops; -extern struct pci_memreg_ops pci_memreg_sparc_be_ops; - -/* GRPCI PCI access routines, default to Little-endian PCI Bus */ -struct pci_access_drv grpci_access_drv = { - .cfg = - { - grpci_cfg_r8, - grpci_cfg_r16, - grpci_cfg_r32, - grpci_cfg_w8, - grpci_cfg_w16, - grpci_cfg_w32, - }, - .io = - { - _ld8, - _ld_le16, - _ld_le32, - _st8, - _st_le16, - _st_le32, - }, - .memreg = &pci_memreg_sparc_le_ops, - .translate = grpci_translate, -}; - -struct pci_io_ops grpci_io_ops_be = -{ - _ld8, - _ld_be16, - _ld_be32, - _st8, - _st_be16, - _st_be32, -}; - -static int grpci_hw_init(struct grpci_priv *priv) -{ - volatile unsigned int *mbar0, *page0; - uint32_t data, addr, mbar0size; - pci_dev_t host = HOST_TGT; - - mbar0 = (volatile unsigned int *)priv->pci_area; - - if ( !priv->bt_enabled && ((priv->regs->page0 & PAGE0_BTEN) == PAGE0_BTEN) ) { - /* Byte twisting is on, turn it off */ - grpci_cfg_w32(host, PCIR_BAR(0), 0xffffffff); - grpci_cfg_r32(host, PCIR_BAR(0), &addr); - /* Setup bar0 to nonzero value */ - grpci_cfg_w32(host, PCIR_BAR(0), - CPU_swap_u32(0x80000000)); - /* page0 is accessed through upper half of bar0 */ - addr = (~CPU_swap_u32(addr)+1)>>1; - mbar0size = addr*2; - DBG("GRPCI: Size of MBAR0: 0x%x, MBAR0: 0x%x(lower) 0x%x(upper)\n",mbar0size,((unsigned int)mbar0),((unsigned int)mbar0)+mbar0size/2); - page0 = &mbar0[mbar0size/8]; - DBG("GRPCI: PAGE0 reg address: 0x%x (0x%x)\n",((unsigned int)mbar0)+mbar0size/2,page0); - priv->regs->cfg_stat = (priv->regs->cfg_stat & (~0xf0000000)) | 0x80000000; /* Setup mmap reg so we can reach bar0 */ - *page0 = 0<devVend); - - /* set 1:1 mapping between AHB -> PCI memory */ - priv->regs->cfg_stat = (priv->regs->cfg_stat & 0x0fffffff) | priv->pci_area; - - /* determine size of target BAR1 */ - grpci_cfg_w32(host, PCIR_BAR(1), 0xffffffff); - grpci_cfg_r32(host, PCIR_BAR(1), &addr); - priv->bar1_size = (~(addr & ~0xf)) + 1; - - /* and map system RAM at pci address 0x40000000 */ - priv->bar1_pci_adr &= ~(priv->bar1_size - 1); /* Fix alignment of BAR1 */ - grpci_cfg_w32(host, PCIR_BAR(1), priv->bar1_pci_adr); - priv->regs->page1 = priv->bar1_pci_adr; - - /* Translate I/O accesses 1:1 */ - priv->regs->iomap = priv->pci_io & 0xffff0000; - - /* Setup Latency Timer and cache line size. Default cache line - * size will result in poor performance (256 word fetches), 0xff - * will set it according to the max size of the PCI FIFO. - */ - grpci_cfg_w8(host, PCIR_CACHELNSZ, 0xff); - grpci_cfg_w8(host, PCIR_LATTIMER, 0x40); - - /* set as bus master and enable pci memory responses */ - grpci_cfg_r32(host, PCIR_COMMAND, &data); - data |= (PCIM_CMD_MEMEN | PCIM_CMD_BUSMASTEREN); - grpci_cfg_w32(host, PCIR_COMMAND, data); - - /* unmask all PCI interrupts at PCI Core, not all GRPCI cores support - * this - */ - priv->regs->irq = 0xf0000; - - /* Successful */ - return 0; -} - -/* Initializes the GRPCI core and driver, must be called before calling init_pci() - * - * Return values - * 0 Successful initalization - * -1 Error during initialization, for example "PCI core not found". - * -2 Error PCI controller not HOST (targets not supported) - * -3 Error due to GRPCI hardware initialization - * -4 Error registering driver to PCI layer - */ -static int grpci_init(struct grpci_priv *priv) -{ - struct ambapp_apb_info *apb; - struct ambapp_ahb_info *ahb; - int pin; - union drvmgr_key_value *value; - char keyname[6]; - struct amba_dev_info *ainfo = priv->dev->businfo; - - /* Find PCI core from Plug&Play information */ - apb = ainfo->info.apb_slv; - ahb = ainfo->info.ahb_slv; - - /* Found PCI core, init private structure */ - priv->irq = apb->irq; - priv->regs = (struct grpci_regs *)apb->start; - priv->bt_enabled = DEFAULT_BT_ENABLED; - - /* Calculate the PCI windows - * AMBA->PCI Window: AHB SLAVE AREA0 - * AMBA->PCI I/O cycles Window: AHB SLAVE AREA1 Lower half - * AMBA->PCI Configuration cycles Window: AHB SLAVE AREA1 Upper half - */ - priv->pci_area = ahb->start[0]; - priv->pci_area_end = ahb->start[0] + ahb->mask[0]; - priv->pci_io = ahb->start[1]; - priv->pci_conf = ahb->start[1] + (ahb->mask[1] >> 1); - priv->pci_conf_end = ahb->start[1] + ahb->mask[1]; - - /* On systems where PCI I/O area and configuration area is apart of the "PCI Window" - * the PCI Window stops at the start of the PCI I/O area - */ - if ( (priv->pci_io > priv->pci_area) && (priv->pci_io < (priv->pci_area_end-1)) ) { - priv->pci_area_end = priv->pci_io; - } - - /* Init PCI interrupt assignment table to all use the interrupt routed through - * the GRPCI core. - */ - strcpy(keyname, "INTX#"); - for (pin=1; pin<5; pin++) { - if ( grpci_pci_irq_table[pin-1] == 0xff ) { - grpci_pci_irq_table[pin-1] = priv->irq; - - /* User may override Both hardcoded IRQ setup and Plug & Play IRQ */ - keyname[3] = 'A' + (pin-1); - value = drvmgr_dev_key_get(priv->dev, keyname, DRVMGR_KT_INT); - if ( value ) - grpci_pci_irq_table[pin-1] = value->i; - } - } - - /* User may override DEFAULT_BT_ENABLED to enable/disable byte twisting */ - value = drvmgr_dev_key_get(priv->dev, "byteTwisting", DRVMGR_KT_INT); - if ( value ) - priv->bt_enabled = value->i; - - /* Use GRPCI target BAR1 to map CPU RAM to PCI, this is to make it - * possible for PCI peripherals to do DMA directly to CPU memory. - */ - value = drvmgr_dev_key_get(priv->dev, "tgtbar1", DRVMGR_KT_INT); - if (value) - priv->bar1_pci_adr = value->i; - else - priv->bar1_pci_adr = SYSTEM_MAINMEM_START; /* default */ - - /* This driver only support HOST systems, we check for HOST */ - if ( !(priv->regs->cfg_stat & CFGSTAT_HOST) ) { - /* Target not supported */ - return -2; - } - - /* Init the PCI Core */ - if ( grpci_hw_init(priv) ) { - return -3; - } - - /* Down streams translation table */ - priv->maps_down[0].name = "AMBA -> PCI MEM Window"; - priv->maps_down[0].size = priv->pci_area_end - priv->pci_area; - priv->maps_down[0].from_adr = (void *)priv->pci_area; - priv->maps_down[0].to_adr = (void *)priv->pci_area; - /* End table */ - priv->maps_down[1].size = 0; - - /* Up streams translation table */ - priv->maps_up[0].name = "Target BAR1 -> AMBA"; - priv->maps_up[0].size = priv->bar1_size; - priv->maps_up[0].from_adr = (void *)priv->bar1_pci_adr; - priv->maps_up[0].to_adr = (void *)priv->bar1_pci_adr; - /* End table */ - priv->maps_up[1].size = 0; - - return 0; -} - -/* Called when a core is found with the AMBA device and vendor ID - * given in grpci_ids[]. IRQ, Console does not work here - */ -int grpci_init1(struct drvmgr_dev *dev) -{ - int status; - struct grpci_priv *priv; - struct pci_auto_setup grpci_auto_cfg; - - DBG("GRPCI[%d] on bus %s\n", dev->minor_drv, dev->parent->dev->name); - - if ( grpci_minor != 0 ) { - DBG("Driver only supports one PCI core\n"); - return DRVMGR_FAIL; - } - - if ( (strcmp(dev->parent->dev->drv->name, "AMBAPP_GRLIB_DRV") != 0) && - (strcmp(dev->parent->dev->drv->name, "AMBAPP_LEON2_DRV") != 0) ) { - /* We only support GRPCI driver on local bus */ - return DRVMGR_FAIL; - } - - priv = dev->priv; - if ( !priv ) - return DRVMGR_NOMEM; - - priv->dev = dev; - priv->minor = grpci_minor++; - - grpcipriv = priv; - status = grpci_init(priv); - if (status) { - printf("Failed to initialize grpci driver %d\n", status); - return DRVMGR_FAIL; - } - - - /* Register the PCI core at the PCI layers */ - - if (priv->bt_enabled == 0) { - /* Host is Big-Endian */ - pci_endian = PCI_BIG_ENDIAN; - - memcpy(&grpci_access_drv.io, &grpci_io_ops_be, - sizeof(grpci_io_ops_be)); - grpci_access_drv.memreg = &pci_memreg_sparc_be_ops; - } - - if (pci_access_drv_register(&grpci_access_drv)) { - /* Access routines registration failed */ - return DRVMGR_FAIL; - } - - /* Prepare memory MAP */ - grpci_auto_cfg.options = 0; - grpci_auto_cfg.mem_start = 0; - grpci_auto_cfg.mem_size = 0; - grpci_auto_cfg.memio_start = priv->pci_area; - grpci_auto_cfg.memio_size = priv->pci_area_end - priv->pci_area; - grpci_auto_cfg.io_start = priv->pci_io; - grpci_auto_cfg.io_size = priv->pci_conf - priv->pci_io; - grpci_auto_cfg.irq_map = grpci_bus0_irq_map; - grpci_auto_cfg.irq_route = NULL; /* use standard routing */ - pci_config_register(&grpci_auto_cfg); - - if (pci_config_init()) { - /* PCI configuration failed */ - return DRVMGR_FAIL; - } - - priv->config.maps_down = &priv->maps_down[0]; - priv->config.maps_up = &priv->maps_up[0]; - return pcibus_register(dev, &priv->config); -} - -/* DMA functions which uses GRPCIs optional DMA controller (len in words) */ -int grpci_dma_to_pci( - unsigned int ahb_addr, - unsigned int pci_addr, - unsigned int len) -{ - int ret = 0; - - pcidma[0] = 0x82; - pcidma[1] = ahb_addr; - pcidma[2] = pci_addr; - pcidma[3] = len; - pcidma[0] = 0x83; - - while ( (pcidma[0] & 0x4) == 0) - ; - - if (pcidma[0] & 0x8) { /* error */ - ret = -1; - } - - pcidma[0] |= 0xC; - return ret; - -} - -int grpci_dma_from_pci( - unsigned int ahb_addr, - unsigned int pci_addr, - unsigned int len) -{ - int ret = 0; - - pcidma[0] = 0x80; - pcidma[1] = ahb_addr; - pcidma[2] = pci_addr; - pcidma[3] = len; - pcidma[0] = 0x81; - - while ( (pcidma[0] & 0x4) == 0) - ; - - if (pcidma[0] & 0x8) { /* error */ - ret = -1; - } - - pcidma[0] |= 0xC; - return ret; - -} diff --git a/c/src/lib/libbsp/sparc/shared/pci/grpci2.c b/c/src/lib/libbsp/sparc/shared/pci/grpci2.c deleted file mode 100644 index 2d8e1521f7..0000000000 --- a/c/src/lib/libbsp/sparc/shared/pci/grpci2.c +++ /dev/null @@ -1,1000 +0,0 @@ -/* GRLIB GRPCI2 PCI HOST driver. - * - * COPYRIGHT (c) 2011 - * Cobham Gaisler AB. - * - * 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. - */ - -/* Configures the GRPCI2 core and initialize, - * - the PCI Library (pci.c) - * - the general part of the PCI Bus driver (pci_bus.c) - * - * System interrupt assigned to PCI interrupt (INTA#..INTD#) is by - * default taken from Plug and Play, but may be overridden by the - * driver resources INTA#..INTD#. GRPCI2 handles differently depending - * on the design (4 different ways). - * - * GRPCI2 IRQ implementation notes - * ------------------------------- - * Since the Driver Manager pci_bus layer implements IRQ by calling - * pci_interrupt_* which translates into BSP_shared_interrupt_*, and the - * root-bus also relies on BSP_shared_interrupt_*, it is safe for the GRPCI2 - * driver to use the drvmgr_interrupt_* routines since they will be - * accessing the same routines in the end. Otherwise the GRPCI2 driver must - * have used the pci_interrupt_* routines. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -/* Use interrupt lock privmitives compatible with SMP defined in - * RTEMS 4.11.99 and higher. - */ -#if (((__RTEMS_MAJOR__ << 16) | (__RTEMS_MINOR__ << 8) | __RTEMS_REVISION__) >= 0x040b63) - -/* map via rtems_interrupt_lock_* API: */ -#define SPIN_DECLARE(lock) RTEMS_INTERRUPT_LOCK_MEMBER(lock) -#define SPIN_INIT(lock, name) rtems_interrupt_lock_initialize(lock, name) -#define SPIN_LOCK(lock, level) rtems_interrupt_lock_acquire_isr(lock, &level) -#define SPIN_LOCK_IRQ(lock, level) rtems_interrupt_lock_acquire(lock, &level) -#define SPIN_UNLOCK(lock, level) rtems_interrupt_lock_release_isr(lock, &level) -#define SPIN_UNLOCK_IRQ(lock, level) rtems_interrupt_lock_release(lock, &level) -#define SPIN_IRQFLAGS(k) rtems_interrupt_lock_context k -#define SPIN_ISR_IRQFLAGS(k) SPIN_IRQFLAGS(k) - -#else - -/* maintain single-core compatibility with older versions of RTEMS: */ -#define SPIN_DECLARE(name) -#define SPIN_INIT(lock, name) -#define SPIN_LOCK(lock, level) -#define SPIN_LOCK_IRQ(lock, level) rtems_interrupt_disable(level) -#define SPIN_UNLOCK(lock, level) -#define SPIN_UNLOCK_IRQ(lock, level) rtems_interrupt_enable(level) -#define SPIN_IRQFLAGS(k) rtems_interrupt_level k -#define SPIN_ISR_IRQFLAGS(k) - -#ifdef RTEMS_SMP -#error SMP mode not compatible with these interrupt lock primitives -#endif -#endif - -/* If defined to 1 - byte twisting is enabled by default */ -#define DEFAULT_BT_ENABLED 0 - -/* If defined to 64 - Latency timer is 64 by default */ -#define DEFAULT_LATENCY_TIMER 64 - -/* Interrupt assignment. Set to other value than 0xff in order to - * override defaults and plug&play information - */ -#ifndef GRPCI2_INTA_SYSIRQ - #define GRPCI2_INTA_SYSIRQ 0xff -#endif -#ifndef GRPCI2_INTB_SYSIRQ - #define GRPCI2_INTB_SYSIRQ 0xff -#endif -#ifndef GRPCI2_INTC_SYSIRQ - #define GRPCI2_INTC_SYSIRQ 0xff -#endif -#ifndef GRPCI2_INTD_SYSIRQ - #define GRPCI2_INTD_SYSIRQ 0xff -#endif - -/*#define DEBUG 1*/ - -#ifdef DEBUG -#define DBG(x...) printk(x) -#else -#define DBG(x...) -#endif - -/* - * GRPCI2 APB Register MAP - */ -struct grpci2_regs { - volatile unsigned int ctrl; /* 0x00 */ - volatile unsigned int sts_cap; /* 0x04 */ - volatile unsigned int ppref; /* 0x08 */ - volatile unsigned int io_map; /* 0x0C */ - volatile unsigned int dma_ctrl; /* 0x10 */ - volatile unsigned int dma_bdbase; /* 0x14 */ - volatile unsigned int dma_chact; /* 0x18 */ - int res1; /* 0x1C */ - volatile unsigned int bars[6]; /* 0x20 */ - int res2[2]; /* 0x38 */ - volatile unsigned int ahbmst_map[16]; /* 0x40 */ -}; - -#define CTRL_BUS_BIT 16 - -#define CTRL_SI (1<<27) -#define CTRL_PE (1<<26) -#define CTRL_ER (1<<25) -#define CTRL_EI (1<<24) -#define CTRL_BUS (0xff< 15) { - retval = PCISTS_MSTABRT; - goto out; - } - - /* GRPCI2 can access "non-standard" devices on bus0 (on AD11.AD16), - * we skip them. - */ - if (dev == HOST_TGT) - bus = devfn = 0; - else if (bus == 0) - devfn = PCI_DEV_DEVFUNC(dev) + PCI_DEV(0, 6, 0); - else - devfn = PCI_DEV_DEVFUNC(dev); - - pci_conf = (volatile uint32_t *) (priv->pci_conf | (devfn << 8) | ofs); - - SPIN_LOCK_IRQ(&priv->devlock, irqflags); - - /* Select bus */ - priv->regs->ctrl = (priv->regs->ctrl & ~(0xff<<16)) | (bus<<16); - /* clear old status */ - priv->regs->sts_cap = (STS_CFGERR | STS_CFGERRVALID); - - tmp = *pci_conf; - - /* Wait until GRPCI2 signals that CFG access is done, it should be - * done instantaneously unless a DMA operation is ongoing... - */ - while ((priv->regs->sts_cap & STS_CFGERRVALID) == 0) - ; - - if (priv->regs->sts_cap & STS_CFGERR) { - retval = PCISTS_MSTABRT; - } else { - /* Bus always little endian (unaffected by byte-swapping) */ - *val = CPU_swap_u32(tmp); - retval = PCISTS_OK; - } - - SPIN_UNLOCK_IRQ(&priv->devlock, irqflags); - -out: - if (retval != PCISTS_OK) - *val = 0xffffffff; - - DBG("pci_read: [%x:%x:%x] reg: 0x%x => addr: 0x%x, val: 0x%x (%d)\n", - PCI_DEV_EXPAND(dev), ofs, pci_conf, *val, retval); - -out2: - return retval; -} - -static int grpci2_cfg_r16(pci_dev_t dev, int ofs, uint16_t *val) -{ - uint32_t v; - int retval; - - if (ofs & 1) - return PCISTS_EINVAL; - - retval = grpci2_cfg_r32(dev, ofs & ~0x3, &v); - *val = 0xffff & (v >> (8*(ofs & 0x3))); - - return retval; -} - -static int grpci2_cfg_r8(pci_dev_t dev, int ofs, uint8_t *val) -{ - uint32_t v; - int retval; - - retval = grpci2_cfg_r32(dev, ofs & ~0x3, &v); - - *val = 0xff & (v >> (8*(ofs & 3))); - - return retval; -} - -static int grpci2_cfg_w32(pci_dev_t dev, int ofs, uint32_t val) -{ - struct grpci2_priv *priv = grpci2priv; - volatile uint32_t *pci_conf; - uint32_t value, devfn; - int retval, bus = PCI_DEV_BUS(dev); - SPIN_IRQFLAGS(irqflags); - - if ((unsigned int)ofs & 0xffffff03) - return PCISTS_EINVAL; - - if (PCI_DEV_SLOT(dev) > 15) - return PCISTS_MSTABRT; - - value = CPU_swap_u32(val); - - /* GRPCI2 can access "non-standard" devices on bus0 (on AD11.AD16), - * we skip them. - */ - if (dev == HOST_TGT) - bus = devfn = 0; - else if (bus == 0) - devfn = PCI_DEV_DEVFUNC(dev) + PCI_DEV(0, 6, 0); - else - devfn = PCI_DEV_DEVFUNC(dev); - - pci_conf = (volatile uint32_t *) (priv->pci_conf | (devfn << 8) | ofs); - - SPIN_LOCK_IRQ(&priv->devlock, irqflags); - - /* Select bus */ - priv->regs->ctrl = (priv->regs->ctrl & ~(0xff<<16)) | (bus<<16); - /* clear old status */ - priv->regs->sts_cap = (STS_CFGERR | STS_CFGERRVALID); - - *pci_conf = value; - - /* Wait until GRPCI2 signals that CFG access is done, it should be - * done instantaneously unless a DMA operation is ongoing... - */ - while ((priv->regs->sts_cap & STS_CFGERRVALID) == 0) - ; - - if (priv->regs->sts_cap & STS_CFGERR) - retval = PCISTS_MSTABRT; - else - retval = PCISTS_OK; - - SPIN_UNLOCK_IRQ(&priv->devlock, irqflags); - - DBG("pci_write - [%x:%x:%x] reg: 0x%x => addr: 0x%x, val: 0x%x (%d)\n", - PCI_DEV_EXPAND(dev), ofs, pci_conf, value, retval); - - return retval; -} - -static int grpci2_cfg_w16(pci_dev_t dev, int ofs, uint16_t val) -{ - uint32_t v; - int retval; - - if (ofs & 1) - return PCISTS_EINVAL; - - retval = grpci2_cfg_r32(dev, ofs & ~0x3, &v); - if (retval != PCISTS_OK) - return retval; - - v = (v & ~(0xffff << (8*(ofs&3)))) | ((0xffff&val) << (8*(ofs&3))); - - return grpci2_cfg_w32(dev, ofs & ~0x3, v); -} - -static int grpci2_cfg_w8(pci_dev_t dev, int ofs, uint8_t val) -{ - uint32_t v; - int retval; - - retval = grpci2_cfg_r32(dev, ofs & ~0x3, &v); - if (retval != PCISTS_OK) - return retval; - - v = (v & ~(0xff << (8*(ofs&3)))) | ((0xff&val) << (8*(ofs&3))); - - return grpci2_cfg_w32(dev, ofs & ~0x3, v); -} - -/* Return the assigned system IRQ number that corresponds to the PCI - * "Interrupt Pin" information from configuration space. - * - * The IRQ information is stored in the grpci2_pci_irq_table configurable - * by the user. - * - * Returns the "system IRQ" for the PCI INTA#..INTD# pin in irq_pin. Returns - * 0xff if not assigned. - */ -static uint8_t grpci2_bus0_irq_map(pci_dev_t dev, int irq_pin) -{ - uint8_t sysIrqNr = 0; /* not assigned */ - int irq_group; - - if ( (irq_pin >= 1) && (irq_pin <= 4) ) { - /* Use default IRQ decoding on PCI BUS0 according slot numbering */ - irq_group = PCI_DEV_SLOT(dev) & 0x3; - irq_pin = ((irq_pin - 1) + irq_group) & 0x3; - /* Valid PCI "Interrupt Pin" number */ - sysIrqNr = grpci2_pci_irq_table[irq_pin]; - } - return sysIrqNr; -} - -static int grpci2_translate(uint32_t *address, int type, int dir) -{ - uint32_t adr, start, end; - struct grpci2_priv *priv = grpci2priv; - int i; - - if (type == 1) { - /* I/O */ - if (dir != 0) { - /* The PCI bus can not access the CPU bus from I/O - * because GRPCI2 core does not support I/O BARs - */ - return -1; - } - - /* We have got a PCI IO BAR address that the CPU want to access. - * Check that it is within the PCI I/O window, I/O adresses - * are NOT mapped 1:1 with GRPCI2 driver... translation needed. - */ - adr = *(uint32_t *)address; - if (adr < 0x100 || adr > 0x10000) - return -1; - *address = adr + priv->pci_io; - } else { - /* MEMIO and MEM. - * Memory space is mapped 1:1 so no translation is needed. - * Check that address is within accessible windows. - */ - adr = *(uint32_t *)address; - if (dir == 0) { - /* PCI BAR to AMBA-CPU address.. check that it is - * located within GRPCI2 PCI Memory Window - * adr = PCI address. - */ - if (adr < priv->pci_area || adr >= priv->pci_area_end) - return -1; - } else { - /* We have a CPU address and want to get access to it - * from PCI space, typically when doing DMA into CPU - * RAM. The GRPCI2 core may have multiple target BARs - * that PCI masters can access, the BARs are user - * configurable in the following ways: - * BAR_SIZE, PCI_BAR Address and MAPPING (AMBA ADR) - * - * The below code tries to find a BAR for which the - * AMBA bar may have been mapped onto, and translate - * the AMBA-CPU address into a PCI address using the - * given mapping. - * - * adr = AMBA address. - */ - for(i=0; i<6; i++) { - start = priv->barcfg[i].ahbadr; - end = priv->barcfg[i].ahbadr + - priv->barcfg[i].barsize; - if (adr >= start && adr < end) { - /* BAR match: Translate address */ - *address = (adr - start) + - priv->barcfg[i].pciadr; - return 0; - } - } - return -1; - } - } - - return 0; -} - -extern struct pci_memreg_ops pci_memreg_sparc_le_ops; -extern struct pci_memreg_ops pci_memreg_sparc_be_ops; - -/* GRPCI2 PCI access routines, default to Little-endian PCI Bus */ -struct pci_access_drv grpci2_access_drv = { - .cfg = - { - grpci2_cfg_r8, - grpci2_cfg_r16, - grpci2_cfg_r32, - grpci2_cfg_w8, - grpci2_cfg_w16, - grpci2_cfg_w32, - }, - .io = - { - _ld8, - _ld_le16, - _ld_le32, - _st8, - _st_le16, - _st_le32, - }, - .memreg = &pci_memreg_sparc_le_ops, - .translate = grpci2_translate, -}; - -struct pci_io_ops grpci2_io_ops_be = -{ - _ld8, - _ld_be16, - _ld_be32, - _st8, - _st_be16, - _st_be32, -}; - -/* PCI Error Interrupt handler, called when there may be a PCI Target/Master - * Abort. - */ -void grpci2_err_isr(void *arg) -{ - struct grpci2_priv *priv = arg; - unsigned int sts = priv->regs->sts_cap; - - if (sts & (STS_IMSTABRT | STS_ITGTABRT | STS_IPARERR | STS_ISYSERR | STS_ITIMEOUT)) { - /* A PCI error IRQ ... Error handler unimplemented - * add your code here... - */ - if (sts & STS_IMSTABRT) { - printk("GRPCI2: unhandled Master Abort IRQ\n"); - } - if (sts & STS_ITGTABRT) { - printk("GRPCI2: unhandled Target Abort IRQ\n"); - } - if (sts & STS_IPARERR) { - printk("GRPCI2: unhandled Parity Error IRQ\n"); - } - if (sts & STS_ISYSERR) { - printk("GRPCI2: unhandled System Error IRQ\n"); - } - if (sts & STS_ITIMEOUT) { - printk("GRPCI2: unhandled PCI target access timeout IRQ\n"); - } - } -} - -/* PCI DMA Interrupt handler, called when there may be a PCI DMA interrupt. - */ -void grpci2_dma_isr(void *arg) -{ - struct grpci2_priv *priv = arg; - unsigned int sts = (priv->regs->sts_cap & (STS_IDMAERR | STS_IDMA)); - - /* Clear Interrupt if taken*/ - if (sts != 0){ - /* Clear IDMAERR and IDMA bits */ - priv->regs->sts_cap = (STS_IDMAERR | STS_IDMA); - /* Clear DRVMGR interrupt */ - drvmgr_interrupt_clear(priv->dev, priv->irq_dma); - /* Call DMA driver ISR */ - (priv->dma_isr)(priv->dma_isr_arg); - } -} - -static int grpci2_hw_init(struct grpci2_priv *priv) -{ - struct grpci2_regs *regs = priv->regs; - int i; - uint8_t capptr; - uint32_t data, io_map, ahbadr, pciadr, size; - pci_dev_t host = HOST_TGT; - struct grpci2_pcibar_cfg *barcfg = priv->barcfg; - - /* Reset any earlier setup */ - regs->ctrl = 0; - regs->sts_cap = ~0; /* Clear Status */ - regs->dma_ctrl = 0; - regs->dma_bdbase = 0; - - /* Translate I/O accesses 1:1, (will not work for PCI 2.3) */ - regs->io_map = priv->pci_io & 0xffff0000; - - /* set 1:1 mapping between AHB -> PCI memory space, for all Masters - * Each AHB master has it's own mapping registers. Max 16 AHB masters. - */ - for (i=0; i<16; i++) - regs->ahbmst_map[i] = priv->pci_area; - - /* Get the GRPCI2 Host PCI ID */ - grpci2_cfg_r32(host, PCIR_VENDOR, &priv->devVend); - - /* Get address to first (always defined) capability structure */ - grpci2_cfg_r8(host, PCIR_CAP_PTR, &capptr); - if (capptr == 0) - return -1; - - /* Limit the prefetch for GRPCI2 version 0. */ - if (priv->ver == 0) - grpci2_cfg_w32(host, capptr+CAP9_AHBPREF_OFS, 0); - - /* Enable/Disable Byte twisting */ - grpci2_cfg_r32(host, capptr+CAP9_IOMAP_OFS, &io_map); - io_map = (io_map & ~0x1) | (priv->bt_enabled ? 1 : 0); - grpci2_cfg_w32(host, capptr+CAP9_IOMAP_OFS, io_map); - - /* Setup the Host's PCI Target BARs for others to access (DMA) */ - for (i=0; i<6; i++) { - /* Make sure address is properly aligned */ - size = ~(barcfg[i].barsize-1); - barcfg[i].pciadr &= size; - barcfg[i].ahbadr &= size; - - pciadr = barcfg[i].pciadr; - ahbadr = barcfg[i].ahbadr; - size |= PCIM_BAR_MEM_PREFETCH; - - grpci2_cfg_w32(host, capptr+CAP9_BARSIZE_OFS+i*4, size); - grpci2_cfg_w32(host, capptr+CAP9_BAR_OFS+i*4, ahbadr); - grpci2_cfg_w32(host, PCIR_BAR(0)+i*4, pciadr); - } - - /* set as bus master and enable pci memory responses */ - grpci2_cfg_r32(host, PCIR_COMMAND, &data); - data |= (PCIM_CMD_MEMEN | PCIM_CMD_BUSMASTEREN); - grpci2_cfg_w32(host, PCIR_COMMAND, data); - - /* set latency timer */ - grpci2_cfg_r32(host, PCIR_CACHELNSZ, &data); - data &= ~0xff00; - data |= ((priv->latency_timer & 0xff) << 8); - grpci2_cfg_w32(host, PCIR_CACHELNSZ, data); - - /* Enable Error respone (CPU-TRAP) on illegal memory access */ - regs->ctrl = CTRL_ER | CTRL_PE; - - /* Successful */ - return 0; -} - -/* Initializes the GRPCI2 core and driver, must be called before calling - * init_pci() - * - * Return values - * 0 Successful initalization - * -1 Error during initialization, for example "PCI core not found". - * -2 Error PCI controller not HOST (targets not supported) - * -3 Error due to GRPCI2 hardware initialization - */ -static int grpci2_init(struct grpci2_priv *priv) -{ - struct ambapp_apb_info *apb; - struct ambapp_ahb_info *ahb; - int pin, i, j; - union drvmgr_key_value *value; - char keyname[6]; - struct amba_dev_info *ainfo = priv->dev->businfo; - struct grpci2_pcibar_cfg *barcfg; - unsigned int size; - - /* Find PCI core from Plug&Play information */ - apb = ainfo->info.apb_slv; - ahb = ainfo->info.ahb_slv; - - /* Found PCI core, init private structure */ - priv->irq = apb->irq; - priv->ver = apb->ver; - priv->regs = (struct grpci2_regs *)apb->start; - priv->bt_enabled = DEFAULT_BT_ENABLED; - priv->irq_mode = (priv->regs->sts_cap & STS_IRQMODE) >> STS_IRQMODE_BIT; - priv->latency_timer = DEFAULT_LATENCY_TIMER; - - /* Initialize Spin-lock for GRPCI2 Device. */ - SPIN_INIT(&priv->devlock, "grpci2"); - - /* Calculate the PCI windows - * AMBA->PCI Window: AHB SLAVE AREA0 - * AMBA->PCI I/O cycles Window: AHB SLAVE AREA1 Lower half - * AMBA->PCI Configuration cycles Window: AHB SLAVE AREA1 Upper half - */ - priv->pci_area = ahb->start[0]; - priv->pci_area_end = ahb->start[0] + ahb->mask[0]; - priv->pci_io = ahb->start[1]; - priv->pci_conf = ahb->start[1] + 0x10000; - priv->pci_conf_end = priv->pci_conf + 0x10000; - - /* On systems where PCI I/O area and configuration area is apart of the - * "PCI Window" the PCI Window stops at the start of the PCI I/O area - */ - if ((priv->pci_io > priv->pci_area) && - (priv->pci_io < (priv->pci_area_end-1))) { - priv->pci_area_end = priv->pci_io; - } - - /* Init PCI interrupt assignment table to all use the interrupt routed - * through the GRPCI2 core. - */ - strcpy(keyname, "INTX#"); - for (pin=1; pin<5; pin++) { - if (grpci2_pci_irq_table[pin-1] == 0xff) { - if (priv->irq_mode < 2) { - /* PCI Interrupts are shared */ - grpci2_pci_irq_table[pin-1] = priv->irq; - } else { - /* Unique IRQ per PCI INT Pin */ - grpci2_pci_irq_table[pin-1] = priv->irq + pin-1; - } - - /* User may override Both hardcoded IRQ setup and Plug & Play IRQ */ - keyname[3] = 'A' + (pin-1); - value = drvmgr_dev_key_get(priv->dev, keyname, DRVMGR_KT_INT); - if (value) - grpci2_pci_irq_table[pin-1] = value->i; - } - - /* Remember which IRQs are enabled */ - if (grpci2_pci_irq_table[pin-1] != 0) - priv->irq_mask |= 1 << (pin-1); - } - - /* User may override DEFAULT_BT_ENABLED to enable/disable byte twisting */ - value = drvmgr_dev_key_get(priv->dev, "byteTwisting", DRVMGR_KT_INT); - if (value) - priv->bt_enabled = value->i; - - /* Let user Configure the 6 target BARs */ - value = drvmgr_dev_key_get(priv->dev, "tgtBarCfg", DRVMGR_KT_POINTER); - if (value) - priv->barcfg = value->ptr; - else - priv->barcfg = grpci2_default_bar_mapping; - - /* User may override DEFAULT_LATENCY_TIMER */ - value = drvmgr_dev_key_get(priv->dev, "latencyTimer", DRVMGR_KT_INT); - if (value) - priv->latency_timer = value->i; - - /* This driver only support HOST systems, we check that it can act as a - * PCI Master and that it is in the Host slot. */ - if ((priv->regs->sts_cap&STS_HOST) || !(priv->regs->sts_cap&STS_MST)) - return -2; /* Target not supported */ - - /* Init the PCI Core */ - if (grpci2_hw_init(priv)) - return -3; - - /* Down streams translation table */ - priv->maps_down[0].name = "AMBA -> PCI MEM Window"; - priv->maps_down[0].size = priv->pci_area_end - priv->pci_area; - priv->maps_down[0].from_adr = (void *)priv->pci_area; - priv->maps_down[0].to_adr = (void *)priv->pci_area; - /* End table */ - priv->maps_down[1].size = 0; - - /* Up streams translation table */ - /* Setup the Host's PCI Target BARs for others to access (DMA) */ - barcfg = priv->barcfg; - for (i=0,j=0; i<6; i++) { - size = barcfg[i].barsize; - if (size == 0) - continue; - - /* Make sure address is properly aligned */ - priv->maps_up[j].name = "Target BAR[I] -> AMBA"; - priv->maps_up[j].size = size; - priv->maps_up[j].from_adr = (void *) - (barcfg[i].pciadr & ~(size - 1)); - priv->maps_up[j].to_adr = (void *) - (barcfg[i].ahbadr & ~(size - 1)); - j++; - } - - /* End table */ - priv->maps_up[j].size = 0; - - return 0; -} - -/* Called when a core is found with the AMBA device and vendor ID - * given in grpci2_ids[]. IRQ, Console does not work here - */ -int grpci2_init1(struct drvmgr_dev *dev) -{ - int status; - struct grpci2_priv *priv; - struct pci_auto_setup grpci2_auto_cfg; - - DBG("GRPCI2[%d] on bus %s\n", dev->minor_drv, dev->parent->dev->name); - - if (grpci2priv) { - DBG("Driver only supports one PCI core\n"); - return DRVMGR_FAIL; - } - - if ((strcmp(dev->parent->dev->drv->name, "AMBAPP_GRLIB_DRV") != 0) && - (strcmp(dev->parent->dev->drv->name, "AMBAPP_LEON2_DRV") != 0)) { - /* We only support GRPCI2 driver on local bus */ - return DRVMGR_FAIL; - } - - priv = dev->priv; - if (!priv) - return DRVMGR_NOMEM; - - priv->dev = dev; - grpci2priv = priv; - - /* Initialize GRPCI2 Hardware */ - status = grpci2_init(priv); - if (status) { - printf("Failed to initialize grpci2 driver %d\n", status); - return -1; - } - - /* Register the PCI core at the PCI layers */ - - if (priv->bt_enabled == 0) { - /* Host is Big-Endian */ - pci_endian = PCI_BIG_ENDIAN; - - memcpy(&grpci2_access_drv.io, &grpci2_io_ops_be, - sizeof(grpci2_io_ops_be)); - grpci2_access_drv.memreg = &pci_memreg_sparc_be_ops; - } - - if (pci_access_drv_register(&grpci2_access_drv)) { - /* Access routines registration failed */ - return DRVMGR_FAIL; - } - - /* Prepare memory MAP */ - grpci2_auto_cfg.options = 0; - grpci2_auto_cfg.mem_start = 0; - grpci2_auto_cfg.mem_size = 0; - grpci2_auto_cfg.memio_start = priv->pci_area; - grpci2_auto_cfg.memio_size = priv->pci_area_end - priv->pci_area; - grpci2_auto_cfg.io_start = 0x100; /* avoid PCI address 0 */ - grpci2_auto_cfg.io_size = 0x10000 - 0x100; /* lower 64kB I/O 16 */ - grpci2_auto_cfg.irq_map = grpci2_bus0_irq_map; - grpci2_auto_cfg.irq_route = NULL; /* use standard routing */ - pci_config_register(&grpci2_auto_cfg); - - if (pci_config_init()) { - /* PCI configuration failed */ - return DRVMGR_FAIL; - } - - /* Initialize/Register Driver Manager PCI Bus */ - priv->config.maps_down = &priv->maps_down[0]; - priv->config.maps_up = &priv->maps_up[0]; - return pcibus_register(dev, &priv->config); -} - -int grpci2_init3(struct drvmgr_dev *dev) -{ - struct grpci2_priv *priv = dev->priv; - - /* Install and Enable PCI Error interrupt handler */ - drvmgr_interrupt_register(dev, 0, "grpci2", grpci2_err_isr, priv); - - /* Initialize DMA driver (if supported) */ - if (priv->regs->sts_cap & STS_DMA){ - grpci2dma_init((void *) &(priv->regs->dma_ctrl), grpci2_dma_isr_register); - } - - /* Unmask Error IRQ and all PCI interrupts at PCI Core. For this to be - * safe every PCI board have to be resetted (no IRQ generation) before - * Global IRQs are enabled (Init is reached or similar) - */ - priv->regs->ctrl |= (CTRL_EI | priv->irq_mask); - - return DRVMGR_OK; -} - -static void grpci2_dma_isr_register( void (*isr)(void *), void * arg) -{ - struct grpci2_priv *priv = grpci2priv; - - /* Handle unregistration */ - if (priv->dma_isr != NULL) { - drvmgr_interrupt_unregister(priv->dev, priv->irq_dma, grpci2_dma_isr, priv); - /* Uninstall user ISR */ - priv->dma_isr = NULL; - priv->dma_isr_arg = NULL; - } - - if (isr == NULL) - return; - - /* Install user ISR */ - priv->dma_isr_arg = arg; - priv->dma_isr = isr; - - /* Install and Enable PCI DMA interrupt handler */ - if (priv->irq_mode == 1) { - priv->irq_dma = 1; - } else if (priv->irq_mode == 3) { - priv->irq_dma = 4; - } else { - priv->irq_dma = 0; - } - drvmgr_interrupt_register(priv->dev, priv->irq_dma, "grpci2dma", grpci2_dma_isr, priv); -} diff --git a/c/src/lib/libbsp/sparc/shared/pci/grpci2dma.c b/c/src/lib/libbsp/sparc/shared/pci/grpci2dma.c deleted file mode 100644 index d5f1f9942f..0000000000 --- a/c/src/lib/libbsp/sparc/shared/pci/grpci2dma.c +++ /dev/null @@ -1,2059 +0,0 @@ -/* - * GRPCI2 DMA Driver - * - * COPYRIGHT (c) 2017 - * Cobham Gaisler AB - * - * 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 /* for printk */ -#include -#include - -/* This driver has been prepared for SMP operation - */ -/* Use interrupt lock privmitives compatible with SMP defined in - * RTEMS 4.11.99 and higher. - */ -#if (((__RTEMS_MAJOR__ << 16) | (__RTEMS_MINOR__ << 8) | __RTEMS_REVISION__) >= 0x040b63) - -/* map via rtems_interrupt_lock_* API: */ -#define SPIN_DECLARE(lock) RTEMS_INTERRUPT_LOCK_MEMBER(lock) -#define SPIN_INIT(lock, name) rtems_interrupt_lock_initialize(lock, name) -#define SPIN_LOCK(lock, level) rtems_interrupt_lock_acquire_isr(lock, &level) -#define SPIN_LOCK_IRQ(lock, level) rtems_interrupt_lock_acquire(lock, &level) -#define SPIN_UNLOCK(lock, level) rtems_interrupt_lock_release_isr(lock, &level) -#define SPIN_UNLOCK_IRQ(lock, level) rtems_interrupt_lock_release(lock, &level) -#define SPIN_IRQFLAGS(k) rtems_interrupt_lock_context k -#define SPIN_ISR_IRQFLAGS(k) SPIN_IRQFLAGS(k) - -#else - -/* maintain single-core compatibility with older versions of RTEMS: */ -#define SPIN_DECLARE(name) -#define SPIN_INIT(lock, name) -#define SPIN_LOCK(lock, level) -#define SPIN_LOCK_IRQ(lock, level) rtems_interrupt_disable(level) -#define SPIN_UNLOCK(lock, level) -#define SPIN_UNLOCK_IRQ(lock, level) rtems_interrupt_enable(level) -#define SPIN_IRQFLAGS(k) rtems_interrupt_level k -#define SPIN_ISR_IRQFLAGS(k) - -#ifdef RTEMS_SMP -#error SMP mode not compatible with these interrupt lock primitives -#endif - -#endif - -/*#define STATIC*/ -#define STATIC static - -/*#define INLINE*/ -#define INLINE inline - -/*#define UNUSED*/ -#define UNUSED __attribute__((unused)) - -/*#define DEBUG 1*/ - -#ifdef DEBUG -#define DBG(x...) printf(x) -#else -#define DBG(x...) -#endif - -#define BD_CHAN_EN (1<regs->dma_ctrl, 0|DMACTRL_SAFE|DMACTRL_CHIRQ|DMACTRL_ERR); - - /* Clear DMA BASE */ - REG_WRITE(&priv->regs->dma_bdbase, 0); - - /* Clear DMA Chan */ - REG_WRITE(&priv->regs->dma_chact, 0); - - return 0; -} - - -/* Stop the DMA */ -STATIC INLINE int grpci2dma_ctrl_stop( void ) -{ - struct grpci2dma_priv *priv = grpci2dmapriv; - - /* Stop DMA */ - unsigned int ctrl = REG_READ(&priv->regs->dma_ctrl); - REG_WRITE(&priv->regs->dma_ctrl, (ctrl & ~(DMACTRL_WCLEAR | DMACTRL_EN)) | - DMACTRL_DIS); - - return 0; -} - -/* Start the DMA */ -STATIC INLINE int grpci2dma_ctrl_start( struct grpci2_bd_chan * chan) -{ - struct grpci2dma_priv *priv = grpci2dmapriv; - - /* Set BDBASE to linked list of chans */ - REG_WRITE(&priv->regs->dma_bdbase, (unsigned int) chan); - - /* Start DMA */ - unsigned int ctrl = REG_READ(&priv->regs->dma_ctrl); - REG_WRITE(&priv->regs->dma_ctrl, (ctrl & ~(DMACTRL_WCLEAR | DMACTRL_DIS)) | - DMACTRL_EN); - - return 0; -} - -/* Resume the DMA */ -STATIC INLINE int grpci2dma_ctrl_resume( void ) -{ - struct grpci2dma_priv *priv = grpci2dmapriv; - - /* Resume DMA */ - unsigned int ctrl = REG_READ(&priv->regs->dma_ctrl); - REG_WRITE(&priv->regs->dma_ctrl, (ctrl & ~(DMACTRL_WCLEAR | DMACTRL_DIS)) | - DMACTRL_EN); - - return 0; -} - -/* Interrupt status*/ -STATIC INLINE int grpci2dma_ctrl_interrupt_status(void) -{ - struct grpci2dma_priv *priv = grpci2dmapriv; - - unsigned int ctrl = REG_READ(&priv->regs->dma_ctrl); - return (ctrl & DMACTRL_IE); -} - -/* Enable interrupts */ -STATIC INLINE int grpci2dma_ctrl_interrupt_enable(void) -{ - struct grpci2dma_priv *priv = grpci2dmapriv; - - unsigned int ctrl = REG_READ(&priv->regs->dma_ctrl); - if (ctrl & DMACTRL_IE){ - /* Nothing to do. Already enabled */ - return 0; - } - - /* Clear pending CHIRQ and errors */ - ctrl = ctrl | (DMACTRL_CHIRQ | DMACTRL_ERR); - - /* Enable interrupts */ - ctrl = ctrl | DMACTRL_IE; - - REG_WRITE(&priv->regs->dma_ctrl, ctrl ); - return 0; -} - -/* Disable interrupts */ -STATIC INLINE int grpci2dma_ctrl_interrupt_disable(void) -{ - struct grpci2dma_priv *priv = grpci2dmapriv; - - unsigned int ctrl = REG_READ(&priv->regs->dma_ctrl); - if ((ctrl & DMACTRL_IE) == 0){ - /* Nothing to do. Already disabled */ - return 0; - } - - /* Clear pending CHIRQ and errors */ - ctrl = ctrl | (DMACTRL_CHIRQ | DMACTRL_ERR); - - /* Disable interrupts */ - ctrl = ctrl & ~(DMACTRL_IE); - - REG_WRITE(&priv->regs->dma_ctrl, ctrl ); - return 0; -} - -/* Clear interrupts */ -STATIC INLINE int grpci2dma_ctrl_interrupt_clear(void) -{ - struct grpci2dma_priv *priv = grpci2dmapriv; - - unsigned int ctrl = REG_READ(&priv->regs->dma_ctrl); - REG_WRITE(&priv->regs->dma_ctrl, (ctrl | DMACTRL_ERR | DMACTRL_CHIRQ)); - return 0; -} - -STATIC INLINE unsigned int grpci2dma_ctrl_status() -{ - struct grpci2dma_priv *priv = grpci2dmapriv; - - /* Read DMA */ - return (REG_READ(&priv->regs->dma_ctrl)); -} - -STATIC INLINE unsigned int grpci2dma_ctrl_base() -{ - struct grpci2dma_priv *priv = grpci2dmapriv; - - /* Read DMA */ - return (REG_READ(&priv->regs->dma_bdbase)); -} - -UNUSED STATIC INLINE unsigned int grpci2dma_ctrl_active() -{ - struct grpci2dma_priv *priv = grpci2dmapriv; - - /* Read DMA */ - return (REG_READ(&priv->regs->dma_chact)); -} - -/* Set the DMA CTRL register NUMCH field */ -STATIC INLINE int grpci2dma_ctrl_numch_set(int numch) -{ - struct grpci2dma_priv *priv = grpci2dmapriv; - - unsigned int ctrl = REG_READ(&priv->regs->dma_ctrl); - - /* Clear old value */ - ctrl = (ctrl & ~(DMACTRL_NUMCH)); - - /* Put new value */ - ctrl = (ctrl | ( (numch << DMACTRL_NUMCH_BIT) & DMACTRL_NUMCH)); - - REG_WRITE(&priv->regs->dma_ctrl, ctrl & ~(DMACTRL_WCLEAR)); - return 0; -} - -/*** END OF DMACTRL ACCESS FUNCTIONS ***/ - -/*** START OF DESCRIPTOR ACCESS FUNCTIONS ***/ - -STATIC int grpci2dma_data_bd_init(struct grpci2_bd_data * data, - uint32_t pci_adr, uint32_t ahb_adr, int dir, int endianness, int size, - struct grpci2_bd_data * next) -{ - BD_WRITE(&data->ctrl, 0 | - (BD_DATA_EN) | - (BD_DATA_TYPE_DATA) | - (dir == GRPCI2DMA_AHBTOPCI? BD_DATA_DR:0) | - (endianness == GRPCI2DMA_LITTLEENDIAN? BD_DATA_BE:0) | - ( (size << BD_DATA_LEN_BIT) & BD_DATA_LEN ) - ); - BD_WRITE(&data->pci_adr, pci_adr); - BD_WRITE(&data->ahb_adr, ahb_adr); - BD_WRITE(&data->next, (unsigned int) next); - return 0; -} - -STATIC int grpci2dma_channel_bd_init(struct grpci2_bd_chan * chan) -{ - BD_WRITE(&chan->ctrl, 0 | BD_CHAN_TYPE_DMA | BD_CHAN_EN); - BD_WRITE(&chan->nchan, (unsigned int) chan); - BD_WRITE(&chan->nbd, (unsigned int) DISABLED_DESCRIPTOR); - return 0; -} - -/* Enable a channel with options. - * options include: - * - options & 0xFFFF: Maximum data descriptor count before - * moving to next DMA channel. - */ -STATIC int grpci2dma_channel_bd_enable(struct grpci2_bd_chan * chan, - unsigned int options) -{ - unsigned int ctrl = BD_READ(&chan->ctrl); - ctrl = (ctrl & ~(BD_CHAN_BDCNT)); - BD_WRITE(&chan->ctrl, (ctrl | BD_CHAN_EN | - ( (options << BD_CHAN_BDCNT_BIT) & BD_CHAN_BDCNT))); - return 0; -} - -/* Disable channel. - */ -STATIC int grpci2dma_channel_bd_disable(struct grpci2_bd_chan * chan) -{ - unsigned int ctrl = BD_READ(&chan->ctrl); - BD_WRITE(&chan->ctrl, (ctrl & ~(BD_CHAN_EN))); - return 0; -} - -/* Get the CID of a channel. - */ -UNUSED STATIC int grpci2dma_channel_bd_get_cid(struct grpci2_bd_chan * chan) -{ - /* Get cid from chan */ - unsigned ctrl = BD_READ(&chan->ctrl); - unsigned cid = (ctrl & (BD_CHAN_ID)) >> BD_CHAN_ID_BIT; - return cid; -} - -/* Set the CID of a channel. */ -STATIC void grpci2dma_channel_bd_set_cid(struct grpci2_bd_chan * chan, int cid) -{ - /* Set cid from chan */ - unsigned ctrl = BD_READ(&chan->ctrl); - ctrl = (ctrl & ~(BD_CHAN_ID)) | ((cid << BD_CHAN_ID_BIT) & BD_CHAN_ID); - BD_WRITE(&chan->ctrl,ctrl); - return; -} - -/* Disable data descriptor*/ -UNUSED STATIC int grpci2dma_data_bd_disable(struct grpci2_bd_data *desc) -{ - BD_WRITE(&desc->ctrl,0); - return 0; -} - -/* Return status of data descriptor*/ -STATIC int grpci2dma_data_bd_status(struct grpci2_bd_data *desc) -{ - int status = BD_READ(&desc->ctrl); - if (status & BD_DATA_ER) { - return GRPCI2DMA_BD_STATUS_ERR; - }else if (status & BD_DATA_EN) { - return GRPCI2DMA_BD_STATUS_ENABLED; - }else { - return GRPCI2DMA_BD_STATUS_DISABLED; - } - return GRPCI2DMA_BD_STATUS_ERR; -} - -/* Enable interrupts in data descriptor*/ -STATIC int grpci2dma_data_bd_interrupt_enable(struct grpci2_bd_data * data) -{ - unsigned int ctrl = BD_READ(&data->ctrl); - BD_WRITE(&data->ctrl, ctrl | BD_DATA_IE); - return 0; -} - -/* Get data descriptor */ -STATIC struct grpci2_bd_data * grpci2dma_channel_bd_get_data( - struct grpci2_bd_chan * chan) -{ - return (struct grpci2_bd_data *) BD_READ(&chan->nbd); -} - -/* Set data descriptorl */ -STATIC void grpci2dma_channel_bd_set_data(struct grpci2_bd_chan * chan, - struct grpci2_bd_data * data) -{ - BD_WRITE(&chan->nbd, (unsigned int) data); -} - -/* Get next channel */ -STATIC struct grpci2_bd_chan * grpci2dma_channel_bd_get_next( - struct grpci2_bd_chan * chan) -{ - return (struct grpci2_bd_chan *) BD_READ(&chan->nchan); -} - -/* Get next data */ -STATIC struct grpci2_bd_data * grpci2dma_data_bd_get_next( - struct grpci2_bd_data * data) -{ - return (struct grpci2_bd_data *) BD_READ(&data->next); -} - -/* Set next channel */ -STATIC void grpci2dma_channel_bd_set_next(struct grpci2_bd_chan * chan, - struct grpci2_bd_chan * next) -{ - BD_WRITE(&chan->nchan,(unsigned int) next); -} - -/* Set next data */ -STATIC void grpci2dma_data_bd_set_next(struct grpci2_bd_data * data, - struct grpci2_bd_data * next) -{ - BD_WRITE(&data->next,(unsigned int) next); -} - -/*** END OF DESCRIPTOR ACCESS FUNCTIONS ***/ - -/*** START OF CHANNEL FUNCTIONS ***/ - -STATIC int grpci2dma_channel_open(struct grpci2_bd_chan * chan, int cid) -{ - struct grpci2dma_priv *priv = grpci2dmapriv; - int allocated = 0; - - /* Get pointer */ - if (chan == NULL) { - /* User does not provide channel, let's create it */ - chan = grpci2dma_channel_new(1); - allocated = 1; - }else{ - /* Make sure the pointer is not already on the linked list */ - int i; - for (i=0; ichannel[i].ptr == chan){ - return GRPCI2DMA_ERR_WRONGPTR; - } - } - } - - DBG("Opening channel %d (0x%08x)\n", cid, (unsigned int) chan); - - /* Init channel descriptor */ - grpci2dma_channel_bd_init(chan); - - /* Assign cid to chan */ - priv->channel[cid].ptr = chan; - grpci2dma_channel_bd_set_cid(chan, cid); - - /* Increase number of channels */ - priv->nchans++; - - DBG("number of channels: %d\n", priv->nchans); - - /* Initialize channel data */ - priv->channel[cid].allocated = allocated; - priv->channel[cid].active = 0; - - /* Initialize record of last added data */ - priv->channel[cid].lastdata = DISABLED_DESCRIPTOR; - - return cid; -} - -/* Get first free CID. - */ -STATIC int grpci2dma_channel_free_id() -{ - struct grpci2dma_priv *priv = grpci2dmapriv; - - /* Find the first free CID */ - int i; - for (i=0; ichannel[i].ptr == NULL){ - return i; - } - } - return GRPCI2DMA_ERR_TOOMANY; -} - -/* Get the active channel circular linked list */ -STATIC struct grpci2_bd_chan * grpci2dma_channel_get_active_list() -{ - struct grpci2dma_priv *priv = grpci2dmapriv; - int i; - /* Just get the first non NULL associated cid */ - for (i=0; i< MAX_DMA_CHANS; i++){ - if ((priv->channel[i].ptr != NULL) && (priv->channel[i].active)){ - return priv->channel[i].ptr; - } - } - return NULL; -} - -/* Start a channel */ -STATIC int grpci2dma_channel_start(int chan_no, int options) -{ - struct grpci2dma_priv *priv = grpci2dmapriv; - struct grpci2_bd_chan *chan; - SPIN_IRQFLAGS(irqflags); - - /* Get chan pointer */ - chan = priv->channel[chan_no].ptr; - - /* Check if channel is active */ - if (priv->channel[chan_no].active){ - /* nothing to do */ - return GRPCI2DMA_ERR_OK; - } - - /* Get the max descriptor count */ - unsigned int desccnt; - if (options == 0){ - /* Default */ - desccnt = 0xffff; - }else{ - desccnt = options & 0xffff; - } - - /* Start the channel by enabling it. - * HWNOTE: In GRPCI2 this bit does not work as it is supposed. - * So we better add/remove the channel from the active linked - * list. */ - grpci2dma_channel_bd_enable(chan, desccnt); - priv->channel[chan_no].active = 1; - priv->nactive++; - /* Get active linked list */ - struct grpci2_bd_chan * list = grpci2dma_channel_get_active_list(); - if (list == NULL){ - /* No previous channels. New list */ - list = chan; - } - /* Add channel from the linked list */ - if (grpci2dma_channel_list_add(list, chan) < 0){ - return GRPCI2DMA_ERR_ERROR; - } - - /* Increase NUMCH in DMA ctrl */ - SPIN_LOCK_IRQ(&priv->devlock, irqflags); - grpci2dma_ctrl_numch_set( (priv->nactive? priv->nactive -1:0)); - - /* Check if DMA is active */ - if (!grpci2dma_active()){ - /* Start DMA */ - grpci2dma_ctrl_start(chan); - } - SPIN_UNLOCK_IRQ(&priv->devlock, irqflags); - - DBG("Channel %d started (0x%08x)\n", chan_no, (unsigned int) chan); - - return GRPCI2DMA_ERR_OK; -} - -/* Stop a channel */ -STATIC int grpci2dma_channel_stop(int chan_no) -{ - struct grpci2dma_priv *priv = grpci2dmapriv; - struct grpci2_bd_chan *chan; - SPIN_IRQFLAGS(irqflags); - int resume; - - /* Get chan pointer */ - chan = priv->channel[chan_no].ptr; - - /* Check if channel is active */ - if (!priv->channel[chan_no].active){ - /* nothing to do */ - return GRPCI2DMA_ERR_OK; - } - - /* First remove channel from the linked list */ - if (grpci2dma_channel_list_remove(chan) < 0){ - return GRPCI2DMA_ERR_ERROR; - } - - /* Update driver struct */ - priv->channel[chan_no].active = 0; - priv->nactive--; - - /* Check if DMA is active and it the removed - * channel is the active */ - resume = 0; - SPIN_LOCK_IRQ(&priv->devlock, irqflags); - if (grpci2dma_active() && (grpci2dma_ctrl_active() == (unsigned int)chan)){ - /* We need to stop the DMA */ - grpci2dma_ctrl_stop(); - SPIN_UNLOCK_IRQ(&priv->devlock, irqflags); - /* Wait until DMA stops */ - while (grpci2dma_active()){} - /* We need to check later to resume the DMA */ - resume = 1; - }else{ - SPIN_UNLOCK_IRQ(&priv->devlock, irqflags); - } - - - /* Now either the DMA is stopped, or it is processing - * a different channel and the removed channel is no - * longer in the linked list */ - - /* Now is safe to update the removed channel */ - grpci2dma_channel_bd_set_next(chan, chan); - - /* Stop the channel by disabling it. - * HWNOTE: In GRPCI2 this bit does not work as it is supposed. - * So we better remove the channel from the active linked - * list. */ - grpci2dma_channel_bd_disable(chan); - - /* Point channel to disabled descriptor */ - grpci2dma_channel_bd_set_data(chan, DISABLED_DESCRIPTOR); - - DBG("Channel %d stoped (0x%08x)\n", chan_no, (unsigned int) chan); - - /* Decrease NUMCH in DMA ctrl */ - SPIN_LOCK_IRQ(&priv->devlock, irqflags); - grpci2dma_ctrl_numch_set( (priv->nactive? priv->nactive -1:0)); - - /* Reactivate DMA only if we stopped */ - if (resume){ - /* We have two options, either we stopped when the active - * channel was still the active one, or we stopped when - * the active channel was a different one */ - if (grpci2dma_ctrl_active() == (unsigned int) chan){ - /* In this case, we need to start the DMA with - * any active channel on the list */ - int i; - for (i=0; ichannel[i].active){ - grpci2dma_ctrl_start(priv->channel[i].ptr); - break; - } - } - }else{ - /* In this case, we need to resume the DMA operation */ - /* HWNOTE: The GRPCI2 core does not update the channel next - * data descriptor if we stopped a channel. This means that - * we need to resume the DMA from the descriptor is was, - * by only setting the enable bit, and not changing the - * base register */ - grpci2dma_ctrl_resume(); - } - } - SPIN_UNLOCK_IRQ(&priv->devlock, irqflags); - - return GRPCI2DMA_ERR_OK; -} - -STATIC int grpci2dma_channel_push(int chan_no, void *dataptr, int index, - int ndata) -{ - struct grpci2dma_priv *priv = grpci2dmapriv; - struct grpci2_bd_chan * chan; - struct grpci2_bd_data * data = dataptr; - - /* Get channel */ - chan = priv->channel[chan_no].ptr; - - DBG("Pushing %d data (starting at 0x%08x) to channel %d (0x%08x)\n", - ndata, (unsigned int) &data[index], chan_no, (unsigned int) chan); - - /* Get last added data */ - struct grpci2_bd_data * last_added = priv->channel[chan_no].lastdata; - - /* Add data to channel */ - grpci2dma_data_list_add(chan, &data[index], last_added); - - /* Update last added */ - priv->channel[chan_no].lastdata = &data[index + ndata-1]; - - return GRPCI2DMA_ERR_OK; -} - -STATIC int grpci2dma_channel_close(int chan_no) -{ - struct grpci2dma_priv *priv = grpci2dmapriv; - struct grpci2_bd_chan * chan; - - /* Get channel */ - chan = priv->channel[chan_no].ptr; - - DBG("Closing channel %d (0x%08x)\n", chan_no, (unsigned int) chan); - - /* Stop channel */ - if (grpci2dma_channel_stop(chan_no) != GRPCI2DMA_ERR_OK ){ - DBG("Cannot stop channel!.\n"); - return GRPCI2DMA_ERR_STOPDMA; - } - - /* Unregister channel ISR */ - grpci2dma_channel_isr_unregister(chan_no); - - /* Free the cid */ - priv->channel[chan_no].ptr = NULL; - - /* Remove the ISR */ - priv->channel[chan_no].isr = NULL; - priv->channel[chan_no].isr_arg = NULL; - - /* Deallocate channel if needed */ - if (priv->channel[chan_no].allocated){ - grpci2dma_channel_delete((void *)chan); - } - - /* Decrease number of channels */ - priv->nchans--; - - DBG("number of channels: %d\n", priv->nchans); - - /* Everything OK */ - return GRPCI2DMA_ERR_OK; -} - -/* Register channel ISR */ -STATIC int grpci2dma_channel_isr_unregister(int chan_no) -{ - struct grpci2dma_priv *priv = grpci2dmapriv; - SPIN_IRQFLAGS(irqflags); - - /* Unregister channel ISR */ - priv->channel[chan_no].isr = NULL; - priv->channel[chan_no].isr_arg = NULL; - - /* Unregister DMA ISR in GRPCI2 if needed */ - priv->isr_registered--; - if(priv->isr_registered == 0){ - /* Disable DMA Interrupts */ - SPIN_LOCK_IRQ(&priv->devlock, irqflags); - grpci2dma_ctrl_interrupt_disable(); - SPIN_UNLOCK_IRQ(&priv->devlock, irqflags); - (priv->isr_register)( NULL, NULL); - } - - /* Everything OK */ - return GRPCI2DMA_ERR_OK; -} - -/*** END OF CHANNEL FUNCTIONS ***/ - -/*** START OF ISR FUNCTIONS ***/ - -/* PCI DMA Interrupt handler, called when there is a PCI DMA interrupt */ -STATIC void grpci2dma_isr(void *arg) -{ - struct grpci2dma_priv *priv = arg; - SPIN_ISR_IRQFLAGS(irqflags); - unsigned int ctrl = grpci2dma_ctrl_status(); - /* Clear Interrupts */ - SPIN_LOCK(&priv->devlock, irqflags); - grpci2dma_ctrl_interrupt_clear(); - SPIN_UNLOCK(&priv->devlock, irqflags); - unsigned int sts = (ctrl & DMACTRL_CHIRQ) >> DMACTRL_CHIRQ_BIT; - unsigned int errsts = (ctrl & DMACTRL_ERR); - - /* Error interrupt */ - if(errsts){ - /* Find which channels had the error. - * The GRPCI2DMA core does not indicate which channel - * had the error, so we need to get 1st the base descriptor register - * and see if it a channel. If is not a channel, then the active - * channel register tells us which channel is. - * After having the channel we need to find out which channel was. */ - struct grpci2_bd_chan * chan = - (struct grpci2_bd_chan *) grpci2dma_ctrl_base(); - /* Check if the base is a channel descriptor */ - if ((BD_READ(&chan->ctrl) & BD_CHAN_TYPE) != BD_CHAN_TYPE_DMA){ - /* Is not a channel, so the channel is in the channel active - * register */ - chan = (struct grpci2_bd_chan *) grpci2dma_ctrl_active(); - } - int i; - for (i=0; ichannel[i].ptr){ - /* Found */ - if (priv->channel[i].isr != NULL){ - (priv->channel[i].isr)(priv->channel[i].isr_arg,i,errsts); - }else{ - printk("Unhandled GRPCI2 DMA error interrupt, sts:0x%02x\n", errsts); - } - break; - } - } - if (i == MAX_DMA_CHANS){ - printk("Unhandled GRPCI2 DMA error interrupt , sts:0x%02x\n", errsts); - } - } - - /* Normal packet interrupt */ - int cid=0; - /* Find which channels have interrupts */ - while(sts){ - /* Find if current channel has an interrupt*/ - if(sts & 0x1){ - /* Find if current channel has an ISR */ - if (priv->channel[cid].isr != NULL){ - (priv->channel[cid].isr)( - priv->channel[cid].isr_arg, cid, errsts); - }else{ - printk("Unhandled GRPCI2 DMA interrupt in channel %d, sts:0x%02x\n", cid, 0); - } - } - /* Next channel */ - sts = sts >> 1; - cid++; - } -} - -/*** END OF ISR FUNCTIONS ***/ - -/*** START OF DEBUG HELPERS ***/ -#ifdef DEBUG -STATIC int grpci2dma_channel_print(struct grpci2_bd_chan * chan) -{ - printf(" GRPCI2 DMA channel descriptor\n"); - printf(" 0x%08x DMA channel control 0x%08x\n", (unsigned int) chan, chan->ctrl); - printf(" 31 en 0x%01x Channel descriptor enable.\n", (chan->ctrl >> 31) & (0x1)); - printf(" 24:22 cid 0x%01x Channel ID.\n", (chan->ctrl >> 22) & (0x7)); - printf(" 21:20 type 0x%01x Descriptor type. 01=DMA channel descriptor.\n", (chan->ctrl >> 20) & (0x3)); - printf(" 15:0 dlen 0x%04x Data descriptor count.\n", (chan->ctrl >> 0) & (0xffff)); - printf("\n"); - printf(" 0x%08x Next DMA channel 0x%08x\n", (unsigned int) &(chan->nchan), chan->nchan); - printf(" 31:0 nc 0x%08x Next DMA channel.\n", chan->nchan); - printf("\n"); - printf(" 0x%08x Next data descriptor 0x%08x\n" , (unsigned int) &(chan->nbd), chan->nbd); - printf(" 31:0 nd 0x%08x Next data descriptor.\n", chan->nbd); - printf("\n"); - return 0; -} - -STATIC int grpci2dma_data_print(struct grpci2_bd_data * data) -{ - printf(" GRPCI2 DMA data descriptor\n"); - printf(" 0x%08x DMA data control 0x%08x\n", (unsigned int) data, data->ctrl); - printf(" 31 en 0x%01x Data descriptor enable.\n" , (data->ctrl >> 31) & (0x1)); - printf(" 30 ie 0x%01x Interrupt generation enable.\n" , (data->ctrl >> 30) & (0x1)); - printf(" 29 dr 0x%01x Tranfer direction.\n" , (data->ctrl >> 29) & (0x1)); - printf(" 28 be 0x%01x Bus endianess.\n" , (data->ctrl >> 28) & (0x1)); - printf(" 21:20 type 0x%01x Descriptor type. 00=DMA data descriptor.\n" , (data->ctrl >> 20) & (0x3)); - printf(" 19 er 0x%01x Error status.\n" , (data->ctrl >> 19) & (0x1)); - printf(" 15:0 len 0x%04x Transfer lenght (in words) - 1.\n" , (data->ctrl >> 0) & (0xffff)); - printf("\n"); - printf(" 0x%08x 32-bit PCI start address 0x%08x\n" , (unsigned int) &(data->pci_adr), data->pci_adr); - printf(" 31:0 pa 0x%08x PCI address.\n" , data->pci_adr); - printf("\n"); - printf(" 0x%08x 32-bit AHB start address 0x%08x\n" , (unsigned int) &(data->ahb_adr), data->ahb_adr); - printf(" 31:0 aa 0x%08x AHB address.\n" , data->ahb_adr); - printf("\n"); - printf(" 0x%08x Next data descriptor 0x%08x\n" , (unsigned int) &(data->next), data->next); - printf(" 31:0 nd 0x%08x Next data descriptor.\n" , data->next); - printf("\n"); - return 0; -} -#endif -/*** END OF DEBUG HELPERS ***/ - -/*** START OF MEMORY ALLOCATION FUNCTIONS ***/ - -void * grpci2dma_channel_new(int number) -{ - /* Allocate memory */ - unsigned int * orig_ptr = (unsigned int *) malloc( - (GRPCI2DMA_BD_CHAN_SIZE)*number + GRPCI2DMA_BD_CHAN_ALIGN); - if (orig_ptr == NULL) return NULL; - - /* Get the aligned pointer */ - unsigned int aligned_ptr = ( - ((unsigned int) orig_ptr + GRPCI2DMA_BD_CHAN_ALIGN) & - ~(GRPCI2DMA_BD_CHAN_ALIGN - 1)); - - /* Save the original pointer just before the aligned pointer */ - unsigned int ** tmp_ptr = - (unsigned int **) (aligned_ptr - sizeof(orig_ptr)); - *tmp_ptr= orig_ptr; - - /* Return aligned pointer */ - return (void *) aligned_ptr; -} - -void grpci2dma_channel_delete(void * chan) -{ - /* Recover orignal pointer placed just before the aligned pointer */ - unsigned int * orig_ptr; - unsigned int ** tmp_ptr = (unsigned int **) (chan - sizeof(orig_ptr)); - orig_ptr = *tmp_ptr; - - /* Deallocate memory */ - free(orig_ptr); -} - -void * grpci2dma_data_new(int number) -{ - /* Allocate memory */ - unsigned int * orig_ptr = (unsigned int *) malloc( - (GRPCI2DMA_BD_DATA_SIZE)*number + GRPCI2DMA_BD_DATA_ALIGN); - if (orig_ptr == NULL) return NULL; - - /* Get the aligned pointer */ - unsigned int aligned_ptr = ( - ((unsigned int) orig_ptr + GRPCI2DMA_BD_DATA_ALIGN) & - ~(GRPCI2DMA_BD_DATA_ALIGN - 1)); - - /* Save the original pointer before the aligned pointer */ - unsigned int ** tmp_ptr = - (unsigned int **) (aligned_ptr - sizeof(orig_ptr)); - *tmp_ptr= orig_ptr; - - /* Return aligned pointer */ - return (void *) aligned_ptr; -} - -void grpci2dma_data_delete(void * data) -{ - /* Recover orignal pointer placed just before the aligned pointer */ - unsigned int * orig_ptr; - unsigned int ** tmp_ptr = (unsigned int **) (data - sizeof(orig_ptr)); - orig_ptr = *tmp_ptr; - - /* Deallocate memory */ - free(orig_ptr); -} - -/*** END OF MEMORY ALLOCATION FUNCTIONS ***/ - -/*** START OF USER API ***/ - -/* Initialize GRPCI2 DMA: GRPCI2 DRIVER calls this - * using a weak function definition */ -int grpci2dma_init( - void * regs, void isr_register( void (*isr)(void*), void * arg)) -{ - struct grpci2dma_priv *priv; - int i; - - DBG("Registering GRPCI2 DMA driver with arg: 0x%08x\n", - (unsigned int) regs); - - /* We only allow one GRPCI2 DMA */ - if (grpci2dmapriv) { - DBG("Driver only supports one PCI DMA core\n"); - return DRVMGR_FAIL; - } - - /* Device Semaphore created with count = 1 */ - if (rtems_semaphore_create(rtems_build_name('G', 'P', '2', 'D'), 1, - RTEMS_FIFO | RTEMS_SIMPLE_BINARY_SEMAPHORE | \ - RTEMS_NO_INHERIT_PRIORITY | RTEMS_LOCAL | \ - RTEMS_NO_PRIORITY_CEILING, 0, &grpci2dma_sem) != RTEMS_SUCCESSFUL) - return -1; - - /* Allocate and init Memory for DMA */ - int size = sizeof(struct grpci2dma_priv); - priv = (struct grpci2dma_priv *) malloc(size); - if (priv == NULL) - return DRVMGR_NOMEM; - - /* Initialize all fields */ - memset(priv, 0, size); - priv->regs = regs; - strncpy(&priv->devname[0], "grpci2dma0", DEVNAME_LEN); - - /* Initialize Spin-lock for GRPCI2dma Device. */ - SPIN_INIT(&priv->devlock, priv->devname); - - /* Channel Sempahores */ - for (i=0; ichannel[i].sem = RTEMS_ID_NONE; - } - - /* Register device */ - grpci2dmapriv = priv; - - /* Initialize Ctrl regs */ - grpci2dma_ctrl_init(); - - /* Install DMA ISR */ - priv->isr_register = isr_register; - - /* Startup actions: - * - stop DMA - */ - grpci2dma_ctrl_stop(); - - return DRVMGR_OK; -} - -/* Assign ISR Function to DMA IRQ */ -int grpci2dma_isr_register(int chan_no, grpci2dma_isr_t dmaisr, void *data) -{ - struct grpci2dma_priv *priv = grpci2dmapriv; - SPIN_IRQFLAGS(irqflags); - - if (!priv){ - /* DMA not initialized */ - return GRPCI2DMA_ERR_NOINIT; - } - - /* Check isr */ - if (dmaisr == NULL){ - /* No ISR */ - return GRPCI2DMA_ERR_WRONGPTR; - } - - /* Get chan pointer */ - if ((chan_no < 0 ) || (chan_no >= MAX_DMA_CHANS)) { - /* Wrong channel id */ - return GRPCI2DMA_ERR_WRONGPTR; - } - - /* Check chan is open */ - if (priv->channel[chan_no].ptr == NULL){ - /* No channel */ - return GRPCI2DMA_ERR_NOTFOUND; - } - - /* Take driver lock - Wait until we get semaphore */ - if (rtems_semaphore_obtain(grpci2dma_sem, RTEMS_WAIT, RTEMS_NO_TIMEOUT) - != RTEMS_SUCCESSFUL){ - return GRPCI2DMA_ERR_ERROR; - } - - /* Take channel lock - Wait until we get semaphore */ - if (rtems_semaphore_obtain(priv->channel[chan_no].sem, RTEMS_WAIT, RTEMS_NO_TIMEOUT) - != RTEMS_SUCCESSFUL){ - rtems_semaphore_release(grpci2dma_sem); - return GRPCI2DMA_ERR_ERROR; - } - - /* Register channel ISR */ - priv->channel[chan_no].isr_arg = data; - priv->channel[chan_no].isr = dmaisr; - - /* Register DMA ISR in GRPCI2 if not done yet */ - if(priv->isr_registered == 0){ - (priv->isr_register)( grpci2dma_isr, (void *) priv); - /* Enable DMA Interrupts */ - SPIN_LOCK_IRQ(&priv->devlock, irqflags); - grpci2dma_ctrl_interrupt_enable(); - SPIN_UNLOCK_IRQ(&priv->devlock, irqflags); - } - priv->isr_registered++; - - /* Release channel sempahore */ - rtems_semaphore_release(priv->channel[chan_no].sem); - - /* Release driver sempahore */ - rtems_semaphore_release(grpci2dma_sem); - - return GRPCI2DMA_ERR_OK; -} - -/* Assign ISR Function to DMA IRQ */ -int grpci2dma_isr_unregister(int chan_no) -{ - struct grpci2dma_priv *priv = grpci2dmapriv; - int ret; - - if (!priv){ - /* DMA not initialized */ - return GRPCI2DMA_ERR_NOINIT; - } - - /* Get chan pointer */ - if ((chan_no < 0 ) || (chan_no >= MAX_DMA_CHANS)) { - /* Wrong channel id */ - return GRPCI2DMA_ERR_WRONGPTR; - } - - /* Check chan is open */ - if (priv->channel[chan_no].ptr == NULL){ - /* No channel */ - return GRPCI2DMA_ERR_NOTFOUND; - } - - /* Get chan ISR */ - if (priv->channel[chan_no].isr == NULL){ - /* Nothing to do */ - return GRPCI2DMA_ERR_OK; - } - - /* Take driver lock - Wait until we get semaphore */ - if (rtems_semaphore_obtain(grpci2dma_sem, RTEMS_WAIT, RTEMS_NO_TIMEOUT) - != RTEMS_SUCCESSFUL){ - return GRPCI2DMA_ERR_ERROR; - } - - /* Take channel lock - Wait until we get semaphore */ - if (rtems_semaphore_obtain(priv->channel[chan_no].sem, RTEMS_WAIT, RTEMS_NO_TIMEOUT) - != RTEMS_SUCCESSFUL){ - rtems_semaphore_release(grpci2dma_sem); - return GRPCI2DMA_ERR_ERROR; - } - - /* Unregister channel ISR */ - ret = grpci2dma_channel_isr_unregister(chan_no); - - /* Release channel sempahore */ - rtems_semaphore_release(priv->channel[chan_no].sem); - - /* Release driver sempahore */ - rtems_semaphore_release(grpci2dma_sem); - - return ret; -} - -int grpci2dma_open(void * chanptr) -{ - struct grpci2dma_priv *priv = grpci2dmapriv; - int cid; - int ret; - - if (!priv){ - /* DMA not initialized */ - return GRPCI2DMA_ERR_NOINIT; - } - - /* Check alignment */ - if (((unsigned int ) chanptr) & (GRPCI2DMA_BD_CHAN_ALIGN-1)) { - /* Channel is not properly aligned */ - return GRPCI2DMA_ERR_WRONGPTR; - } - - /* Take driver lock - Wait until we get semaphore */ - if (rtems_semaphore_obtain(grpci2dma_sem, RTEMS_WAIT, RTEMS_NO_TIMEOUT) - != RTEMS_SUCCESSFUL){ - return GRPCI2DMA_ERR_ERROR; - } - - /* Get free channel id */ - cid = grpci2dma_channel_free_id(); - if (cid < 0 ){ - rtems_semaphore_release(grpci2dma_sem); - return GRPCI2DMA_ERR_TOOMANY; - } - - /* Open channel */ - ret = grpci2dma_channel_open((struct grpci2_bd_chan *) chanptr, cid); - - /* Create channel semaphore with count = 1 */ - if (ret >= 0){ - if (rtems_semaphore_create( - rtems_build_name('P', 'D', '0', '0' + cid), 1, - RTEMS_FIFO | RTEMS_SIMPLE_BINARY_SEMAPHORE | \ - RTEMS_NO_INHERIT_PRIORITY | RTEMS_LOCAL | \ - RTEMS_NO_PRIORITY_CEILING, 0, &priv->channel[cid].sem - ) != RTEMS_SUCCESSFUL) { - priv->channel[cid].sem = RTEMS_ID_NONE; - rtems_semaphore_release(grpci2dma_sem); - return GRPCI2DMA_ERR_ERROR; - } - } - - /* Release driver semaphore */ - rtems_semaphore_release(grpci2dma_sem); - - /* Return channel id */ - return ret; -} - -int grpci2dma_close(int chan_no) -{ - struct grpci2dma_priv *priv = grpci2dmapriv; - int ret; - - if (!priv){ - /* DMA not initialized */ - return GRPCI2DMA_ERR_NOINIT; - } - - /* Get chan pointer */ - if ((chan_no < 0) || (chan_no >= MAX_DMA_CHANS)){ - /* Wrong channel id */ - return GRPCI2DMA_ERR_WRONGPTR; - } - - /* Check chan is open */ - if (priv->channel[chan_no].ptr == NULL){ - /* No channel */ - return GRPCI2DMA_ERR_NOTFOUND; - } - - /* Take driver lock - Wait until we get semaphore */ - if (rtems_semaphore_obtain(grpci2dma_sem, RTEMS_WAIT, RTEMS_NO_TIMEOUT) - != RTEMS_SUCCESSFUL){ - return GRPCI2DMA_ERR_ERROR; - } - - /* Take channel lock - Wait until we get semaphore */ - if (rtems_semaphore_obtain(priv->channel[chan_no].sem, RTEMS_WAIT, RTEMS_NO_TIMEOUT) - != RTEMS_SUCCESSFUL){ - rtems_semaphore_release(grpci2dma_sem); - return GRPCI2DMA_ERR_ERROR; - } - - /* Close channel */ - ret = grpci2dma_channel_close(chan_no); - - /* Release channel sempahore */ - rtems_semaphore_release(priv->channel[chan_no].sem); - - /* Delete channel semaphore */ - if (ret == GRPCI2DMA_ERR_OK){ - if (rtems_semaphore_delete(priv->channel[chan_no].sem) - != RTEMS_SUCCESSFUL){ - /* Release driver semaphore */ - rtems_semaphore_release(grpci2dma_sem); - return GRPCI2DMA_ERR_ERROR; - } - } - - /* Release driver semaphore */ - rtems_semaphore_release(grpci2dma_sem); - - return ret; -} - -/* Transfer_size =0 means maximum */ -int grpci2dma_prepare( - uint32_t pci_start, uint32_t ahb_start, int dir, int endianness, - int size, void * dataptr, int index, int ndata, int transfer_size) -{ - struct grpci2_bd_data * data = dataptr; - - /* Check data pointer */ - if ((data == NULL) || - (((unsigned int ) data) & (GRPCI2DMA_BD_DATA_ALIGN-1))){ - return GRPCI2DMA_ERR_WRONGPTR; - } - - /* Check indexes */ - int maxdata = ndata - index; - if ((maxdata < 1) || (index < 0)){ - /* No data descriptors to use */ - return GRPCI2DMA_ERR_WRONGPTR; - } - - /* Check PCI transfer size */ - if ( (transfer_size < 0) || - (transfer_size > MAX_DMA_TRANSFER_SIZE) || - (transfer_size%4 != 0) ) { - return GRPCI2DMA_ERR_WRONGPTR; - } - if (transfer_size == 0){ - transfer_size = MAX_DMA_TRANSFER_SIZE; - } - - /* Check total size */ - if ( (size <=0) || (size % 4 != 0)){ - return GRPCI2DMA_ERR_WRONGPTR; - } - - /* Calculate number of data descriptors needed */ - int words = size/4; - int blocksize = transfer_size/4; - int datacnt = words/blocksize + (words%blocksize != 0? 1: 0); - /* Check that we can transfer the data */ - if (datacnt > maxdata) { - return GRPCI2DMA_ERR_TOOMANY; - } - - /* Prepare data descriptors */ - int i; - uint32_t pci_adr; - uint32_t ahb_adr; - int remaining=words; - int datasize; - struct grpci2_bd_data * next; - for (i=0; i= blocksize){ - datasize = blocksize - 1; - remaining -= blocksize; - } else { - datasize = remaining -1; - remaining = 0; - } - /* Get linked list pointers */ - if (i == datacnt - 1){ - /* Last transfer */ - next = DISABLED_DESCRIPTOR; - }else{ - next = &data[i+index+1]; - } - /* Set Data descriptor */ - grpci2dma_data_bd_init(&data[i+index], pci_adr, ahb_adr, dir, endianness, datasize, next); - } - /* Return number of transfers used */ - return datacnt; -} - -int grpci2dma_status(void *dataptr, int index, int ndata) -{ - struct grpci2_bd_data * data = dataptr; - int i; - - /* Check data pointer */ - if ((data == NULL) || - (((unsigned int ) data) & (GRPCI2DMA_BD_DATA_ALIGN-1))){ - return GRPCI2DMA_ERR_WRONGPTR; - } - - /* Check maxdata */ - int maxdata = ndata - index; - if ((maxdata < 1) || (index < 0)){ - /* No data descriptors to use */ - return GRPCI2DMA_ERR_WRONGPTR; - } - - /* Check status of all packets in transfer */ - int status; - for (i=0; i< maxdata; i++){ - status = grpci2dma_data_bd_status(&data[i+index]); - if (status == GRPCI2DMA_BD_STATUS_ERR){ - /* Error in one packet, means error in transfer */ - return status; - } else if (status == GRPCI2DMA_BD_STATUS_ENABLED){ - /* If one packet is enabled, means transfer is not done */ - return status; - } - } - - /* If we reach here it means they are all disabled */ - return status; -} - -int grpci2dma_print(int chan_no) -{ - struct grpci2dma_priv *priv = grpci2dmapriv; - struct grpci2_bd_chan * chan; - - if (!priv){ - /* DMA not initialized */ - DBG("DMA not initialized.\n"); - return GRPCI2DMA_ERR_NOINIT; - } - - if ( (chan_no < 0) || (chan_no >= MAX_DMA_CHANS )){ - /* Wrong chan no*/ - return GRPCI2DMA_ERR_WRONGPTR; - } - - chan = priv->channel[chan_no].ptr; - if (chan == NULL) { - return GRPCI2DMA_ERR_WRONGPTR; - } - - #ifdef DEBUG - /* Print channel state */ - grpci2dma_channel_print(chan); - - /* Get current DATA desc */ - struct grpci2_bd_data * first_data = (struct grpci2_bd_data *) BD_READ(&chan->nbd); - - /* Print data state */ - grpci2dma_data_list_foreach(first_data, grpci2dma_data_print, MAX_DMA_DATA); - #endif - return GRPCI2DMA_ERR_OK; -} - -int grpci2dma_print_bd(void * dataptr) -{ - struct grpci2dma_priv *priv = grpci2dmapriv; - struct grpci2_bd_data * data = (struct grpci2_bd_data *) dataptr; - - if (!priv){ - /* DMA not initialized */ - DBG("DMA not initialized.\n"); - return GRPCI2DMA_ERR_NOINIT; - } - - if ( data == NULL ){ - /* Wrong chan no*/ - return GRPCI2DMA_ERR_WRONGPTR; - } - - #ifdef DEBUG - /* Print data state */ - grpci2dma_data_list_foreach(data, grpci2dma_data_print, MAX_DMA_DATA); - #endif - return GRPCI2DMA_ERR_OK; -} - -int grpci2dma_interrupt_enable( - void *dataptr, int index, int maxindex, int options) -{ - struct grpci2_bd_data * data = dataptr; - struct grpci2dma_priv *priv = grpci2dmapriv; - SPIN_IRQFLAGS(irqflags); - - if (!priv){ - /* DMA not initialized */ - return GRPCI2DMA_ERR_NOINIT; - } - - /* Check data pointer */ - if ((data == NULL) || - (((unsigned int ) data) & (GRPCI2DMA_BD_DATA_ALIGN-1))){ - return GRPCI2DMA_ERR_WRONGPTR; - } - - /* Check index */ - if ((index < 0) || (maxindex < 1) || (index >= maxindex)){ - /* No data descriptors to use */ - return GRPCI2DMA_ERR_WRONGPTR; - } - - if (options & GRPCI2DMA_OPTIONS_ALL){ - /* Enable all interrupts */ - if (grpci2dma_data_list_foreach( - &data[index], - grpci2dma_data_bd_interrupt_enable, maxindex -index)){ - return GRPCI2DMA_ERR_ERROR; - } - }else{ - /* Enable one packet interrupts */ - grpci2dma_data_bd_interrupt_enable(&data[index]); - } - - /* Finally enable DMA interrupts if they are not already enabled */ - if (grpci2dma_ctrl_interrupt_status()==0){ - SPIN_LOCK_IRQ(&priv->devlock, irqflags); - grpci2dma_ctrl_interrupt_enable(); - SPIN_UNLOCK_IRQ(&priv->devlock, irqflags); - } - - DBG("Interrupts enabled for data (0x%08x), index:%d, maxindex:%d, %s.\n", - (unsigned int) data, index, maxindex, - (options & GRPCI2DMA_OPTIONS_ALL)? "ALL":"ONE" ); - - return GRPCI2DMA_ERR_OK; -} - -int grpci2dma_push(int chan_no, void *dataptr, int index, int ndata) -{ - struct grpci2dma_priv *priv = grpci2dmapriv; - SPIN_IRQFLAGS(irqflags); - int ret; - - if (!priv){ - /* DMA not initialized */ - return GRPCI2DMA_ERR_NOINIT; - } - - /* Check data pointer */ - if ((dataptr == NULL) || - (((unsigned int ) dataptr) & (GRPCI2DMA_BD_DATA_ALIGN-1))){ - return GRPCI2DMA_ERR_WRONGPTR; - } - - /* Check index */ - if ((ndata < 1) || (index < 0)){ - /* No data descriptors to use */ - return GRPCI2DMA_ERR_WRONGPTR; - } - - /* Check chan_no */ - if ( (chan_no < 0) || (chan_no >= MAX_DMA_CHANS )){ - /* Wrong chan no*/ - return GRPCI2DMA_ERR_WRONGPTR; - } - - /* Check chan is open */ - if (priv->channel[chan_no].ptr == NULL){ - /* No channel */ - return GRPCI2DMA_ERR_NOTFOUND; - } - - /* Take channel lock - Wait until we get semaphore */ - if (rtems_semaphore_obtain(priv->channel[chan_no].sem, RTEMS_WAIT, RTEMS_NO_TIMEOUT) - != RTEMS_SUCCESSFUL){ - return GRPCI2DMA_ERR_ERROR; - } - - /* push data to channel */ - ret = grpci2dma_channel_push(chan_no, dataptr, index, ndata); - - if (ret != GRPCI2DMA_ERR_OK){ - /* Release channel lock */ - rtems_semaphore_release(priv->channel[chan_no].sem); - return ret; - } - - /* Start DMA if it is not active and channel is active*/ - SPIN_LOCK_IRQ(&priv->devlock, irqflags); - if ((!grpci2dma_active()) && (priv->channel[chan_no].active)){ - grpci2dma_ctrl_start(priv->channel[chan_no].ptr); - } - SPIN_UNLOCK_IRQ(&priv->devlock, irqflags); - - /* Release channel lock */ - rtems_semaphore_release(priv->channel[chan_no].sem); - - return ret; -} - -/* Start the channel */ -int grpci2dma_start(int chan_no, int options) -{ - struct grpci2dma_priv *priv = grpci2dmapriv; - int ret; - - if (!priv){ - /* DMA not initialized */ - return GRPCI2DMA_ERR_NOINIT; - } - - if ((chan_no < 0 ) || (chan_no >= MAX_DMA_CHANS )) { - /* Wrong channel id */ - return GRPCI2DMA_ERR_WRONGPTR; - } - - if ( options < 0 ) { - /* Wrong options */ - return GRPCI2DMA_ERR_WRONGPTR; - } - - /* Check chan is open */ - if (priv->channel[chan_no].ptr == NULL){ - /* No channel */ - return GRPCI2DMA_ERR_NOTFOUND; - } - - /* Take driver lock - Wait until we get semaphore */ - if (rtems_semaphore_obtain(grpci2dma_sem, RTEMS_WAIT, RTEMS_NO_TIMEOUT) - != RTEMS_SUCCESSFUL){ - return GRPCI2DMA_ERR_ERROR; - } - - /* Take channel lock - Wait until we get semaphore */ - if (rtems_semaphore_obtain(priv->channel[chan_no].sem, RTEMS_WAIT, RTEMS_NO_TIMEOUT) - != RTEMS_SUCCESSFUL){ - rtems_semaphore_release(grpci2dma_sem); - return GRPCI2DMA_ERR_ERROR; - } - - /* Start the channel */ - ret = grpci2dma_channel_start(chan_no, options); - - /* Release channel lock */ - rtems_semaphore_release(priv->channel[chan_no].sem); - - /* Release driver lock */ - rtems_semaphore_release(grpci2dma_sem); - - return ret; -} - -/* Stop the channel, but don't stop ongoing transfers! */ -int grpci2dma_stop(int chan_no) -{ - struct grpci2dma_priv *priv = grpci2dmapriv; - int ret; - - if (!priv){ - /* DMA not initialized */ - return GRPCI2DMA_ERR_NOINIT; - } - - if ((chan_no < 0 ) || (chan_no >= MAX_DMA_CHANS)) { - /* Wrong channel id */ - return GRPCI2DMA_ERR_WRONGPTR; - } - - /* Check chan is open */ - if (priv->channel[chan_no].ptr == NULL){ - /* No channel */ - return GRPCI2DMA_ERR_NOTFOUND; - } - - /* Take driver lock - Wait until we get semaphore */ - if (rtems_semaphore_obtain(grpci2dma_sem, RTEMS_WAIT, RTEMS_NO_TIMEOUT) - != RTEMS_SUCCESSFUL){ - return GRPCI2DMA_ERR_ERROR; - } - - /* Take channel lock - Wait until we get semaphore */ - if (rtems_semaphore_obtain(priv->channel[chan_no].sem, RTEMS_WAIT, RTEMS_NO_TIMEOUT) - != RTEMS_SUCCESSFUL){ - rtems_semaphore_release(grpci2dma_sem); - return GRPCI2DMA_ERR_ERROR; - } - - /* Stop the channel */ - ret = grpci2dma_channel_stop(chan_no); - - /* Release channel lock */ - rtems_semaphore_release(priv->channel[chan_no].sem); - - /* Release driver lock */ - rtems_semaphore_release(grpci2dma_sem); - - return ret; -} - -int grpci2dma_active() -{ - return ((grpci2dma_ctrl_status()) & DMACTRL_ACT) >> DMACTRL_ACT_BIT; -} - diff --git a/c/src/lib/libbsp/sparc/shared/pci/pci_memreg_sparc_be.c b/c/src/lib/libbsp/sparc/shared/pci/pci_memreg_sparc_be.c deleted file mode 100644 index 6dae9c89fe..0000000000 --- a/c/src/lib/libbsp/sparc/shared/pci/pci_memreg_sparc_be.c +++ /dev/null @@ -1,27 +0,0 @@ -/* Registers-over-Memory Space - SPARC Big endian PCI bus definitions - * - * COPYRIGHT (c) 2011. - * Cobham Gaisler AB. - * - * 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 - -struct pci_memreg_ops pci_memreg_sparc_be_ops = { - .ld8 = _ld8, - .st8 = _st8, - - .ld_le16 = _ld_be16, - .st_le16 = _st_be16, - .ld_be16 = _ld_le16, - .st_be16 = _st_le16, - - .ld_le32 = _ld_be32, - .st_le32 = _st_be32, - .ld_be32 = _ld_le32, - .st_be32 = _st_le32, -}; diff --git a/c/src/lib/libbsp/sparc/shared/pci/pci_memreg_sparc_le.c b/c/src/lib/libbsp/sparc/shared/pci/pci_memreg_sparc_le.c deleted file mode 100644 index bc95811f24..0000000000 --- a/c/src/lib/libbsp/sparc/shared/pci/pci_memreg_sparc_le.c +++ /dev/null @@ -1,28 +0,0 @@ -/* Registers-over-Memory Space - SPARC Little endian PCI bus definitions - * - * COPYRIGHT (c) 2011. - * Cobham Gaisler AB. - * - * 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 - -struct pci_memreg_ops pci_memreg_sparc_le_ops = { - .ld8 = _ld8, - .st8 = _st8, - - .ld_le16 = _ld_le16, - .st_le16 = _st_le16, - .ld_be16 = _ld_be16, - .st_be16 = _st_be16, - - .ld_le32 = _ld_le32, - .st_le32 = _st_le32, - .ld_be32 = _ld_be32, - .st_be32 = _st_be32, -}; diff --git a/c/src/lib/libbsp/sparc/shared/pci/pcif.c b/c/src/lib/libbsp/sparc/shared/pci/pcif.c deleted file mode 100644 index c0b8fc9629..0000000000 --- a/c/src/lib/libbsp/sparc/shared/pci/pcif.c +++ /dev/null @@ -1,586 +0,0 @@ -/* GRLIB PCIF PCI HOST driver. - * - * COPYRIGHT (c) 2008. - * Cobham Gaisler AB. - * - * Configures the PCIF core and initialize, - * - the PCI Library (pci.c) - * - the general part of the PCI Bus driver (pci_bus.c) - * - * System interrupt assigned to PCI interrupt (INTA#..INTD#) is by - * default taken from Plug and Play, but may be overridden by the - * driver resources INTA#..INTD#. - * - * 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 -#include -#include - -#include -#include -#include -#include -#include - - -/* Configuration options */ -#define SYSTEM_MAINMEM_START 0x40000000 - -/* Interrupt assignment. Set to other value than 0xff in order to - * override defaults and plug&play information - */ -#ifndef PCIF_INTA_SYSIRQ - #define PCIF_INTA_SYSIRQ 0xff -#endif -#ifndef PCIF_INTB_SYSIRQ - #define PCIF_INTB_SYSIRQ 0xff -#endif -#ifndef PCIF_INTC_SYSIRQ - #define PCIF_INTC_SYSIRQ 0xff -#endif -#ifndef PCIF_INTD_SYSIRQ - #define PCIF_INTD_SYSIRQ 0xff -#endif - -/*#define DEBUG 1 */ - -#ifdef DEBUG -#define DBG(x...) printk(x) -#else -#define DBG(x...) -#endif - -/* - * Bit encode for PCI_CONFIG_HEADER_TYPE register - */ -struct pcif_regs { - volatile unsigned int bars[4]; /* 0x00-0x10 */ - volatile unsigned int bus; /* 0x10 */ - volatile unsigned int map_io; /* 0x14 */ - volatile unsigned int status; /* 0x18 */ - volatile unsigned int intr; /* 0x1c */ - int unused[(0x40-0x20)/4]; /* 0x20-0x40 */ - volatile unsigned int maps[(0x80-0x40)/4]; /* 0x40-0x80*/ -}; - -/* Used internally for accessing the PCI bridge's configuration space itself */ -#define HOST_TGT PCI_DEV(0xff, 0, 0) - -struct pcif_priv *pcifpriv = NULL; -static int pcif_minor = 0; - -/* PCI Interrupt assignment. Connects an PCI interrupt pin (INTA#..INTD#) - * to a system interrupt number. - */ -unsigned char pcif_pci_irq_table[4] = -{ - /* INTA# */ PCIF_INTA_SYSIRQ, - /* INTB# */ PCIF_INTB_SYSIRQ, - /* INTC# */ PCIF_INTC_SYSIRQ, - /* INTD# */ PCIF_INTD_SYSIRQ -}; - -/* Driver private data struture */ -struct pcif_priv { - struct drvmgr_dev *dev; - struct pcif_regs *regs; - int irq; - int minor; - int irq_mask; - - unsigned int pci_area; - unsigned int pci_area_end; - unsigned int pci_io; - unsigned int pci_conf; - unsigned int pci_conf_end; - - uint32_t devVend; /* Host PCI Vendor/Device ID */ - uint32_t bar1_size; - - struct drvmgr_map_entry maps_up[2]; - struct drvmgr_map_entry maps_down[2]; - struct pcibus_config config; -}; - -int pcif_init1(struct drvmgr_dev *dev); -int pcif_init3(struct drvmgr_dev *dev); - -/* PCIF DRIVER */ - -struct drvmgr_drv_ops pcif_ops = -{ - .init = {pcif_init1, NULL, pcif_init3, NULL}, - .remove = NULL, - .info = NULL -}; - -struct amba_dev_id pcif_ids[] = -{ - {VENDOR_GAISLER, GAISLER_PCIF}, - {0, 0} /* Mark end of table */ -}; - -struct amba_drv_info pcif_info = -{ - { - DRVMGR_OBJ_DRV, /* Driver */ - NULL, /* Next driver */ - NULL, /* Device list */ - DRIVER_AMBAPP_GAISLER_PCIF_ID, /* Driver ID */ - "PCIF_DRV", /* Driver Name */ - DRVMGR_BUS_TYPE_AMBAPP, /* Bus Type */ - &pcif_ops, - NULL, /* Funcs */ - 0, /* No devices yet */ - sizeof(struct pcif_priv), /* Let drvmgr alloc private */ - }, - &pcif_ids[0] -}; - -void pcif_register_drv(void) -{ - DBG("Registering PCIF driver\n"); - drvmgr_drv_register(&pcif_info.general); -} - -static int pcif_cfg_r32(pci_dev_t dev, int ofs, uint32_t *val) -{ - struct pcif_priv *priv = pcifpriv; - volatile uint32_t *pci_conf; - uint32_t devfn; - int retval; - int bus = PCI_DEV_BUS(dev); - - if (ofs & 3) - return PCISTS_EINVAL; - - if (PCI_DEV_SLOT(dev) > 15) { - *val = 0xffffffff; - return PCISTS_OK; - } - - /* PCIF can access "non-standard" devices on bus0 (on AD11.AD16), - * but we skip them. - */ - if (dev == HOST_TGT) - bus = devfn = 0; - else if (bus == 0) - devfn = PCI_DEV_DEVFUNC(dev) + PCI_DEV(0, 6, 0); - else - devfn = PCI_DEV_DEVFUNC(dev); - - /* Select bus */ - priv->regs->bus = bus << 16; - - pci_conf = (volatile uint32_t *)(priv->pci_conf | (devfn << 8) | ofs); - - *val = *pci_conf; - - if (priv->regs->status & 0x30000000) { - *val = 0xffffffff; - retval = PCISTS_MSTABRT; - } else - retval = PCISTS_OK; - - DBG("pci_read: [%x:%x:%x] reg: 0x%x => addr: 0x%x, val: 0x%x\n", - PCI_DEV_EXPAND(dev), ofs, pci_conf, *val); - - return retval; -} - -static int pcif_cfg_r16(pci_dev_t dev, int ofs, uint16_t *val) -{ - uint32_t v; - int retval; - - if (ofs & 1) - return PCISTS_EINVAL; - - retval = pcif_cfg_r32(dev, ofs & ~0x3, &v); - *val = 0xffff & (v >> (8*(ofs & 0x3))); - - return retval; -} - -static int pcif_cfg_r8(pci_dev_t dev, int ofs, uint8_t *val) -{ - uint32_t v; - int retval; - - retval = pcif_cfg_r32(dev, ofs & ~0x3, &v); - - *val = 0xff & (v >> (8*(ofs & 3))); - - return retval; -} - -static int pcif_cfg_w32(pci_dev_t dev, int ofs, uint32_t val) -{ - struct pcif_priv *priv = pcifpriv; - volatile uint32_t *pci_conf; - uint32_t devfn; - int bus = PCI_DEV_BUS(dev); - - if (ofs & ~0xfc) - return PCISTS_EINVAL; - - if (PCI_DEV_SLOT(dev) > 15) - return PCISTS_MSTABRT; - - /* PCIF can access "non-standard" devices on bus0 (on AD11.AD16), - * but we skip them. - */ - if (dev == HOST_TGT) - bus = devfn = 0; - else if (bus == 0) - devfn = PCI_DEV_DEVFUNC(dev) + PCI_DEV(0, 6, 0); - else - devfn = PCI_DEV_DEVFUNC(dev); - - /* Select bus */ - priv->regs->bus = bus << 16; - - pci_conf = (volatile uint32_t *)(priv->pci_conf | (devfn << 8) | ofs); - - *pci_conf = val; - - DBG("pci_write - [%x:%x:%x] reg: 0x%x => addr: 0x%x, val: 0x%x\n", - PCI_DEV_EXPAND(dev), ofs, pci_conf, value); - - return PCISTS_OK; -} - -static int pcif_cfg_w16(pci_dev_t dev, int ofs, uint16_t val) -{ - uint32_t v; - int retval; - - if (ofs & 1) - return PCISTS_EINVAL; - - retval = pcif_cfg_r32(dev, ofs & ~0x3, &v); - if (retval != PCISTS_OK) - return retval; - - v = (v & ~(0xffff << (8*(ofs&3)))) | ((0xffff&val) << (8*(ofs&3))); - - return pcif_cfg_w32(dev, ofs & ~0x3, v); -} - -static int pcif_cfg_w8(pci_dev_t dev, int ofs, uint8_t val) -{ - uint32_t v; - int retval; - - retval = pcif_cfg_r32(dev, ofs & ~0x3, &v); - if (retval != PCISTS_OK) - return retval; - - v = (v & ~(0xff << (8*(ofs&3)))) | ((0xff&val) << (8*(ofs&3))); - - return pcif_cfg_w32(dev, ofs & ~0x3, v); -} - - -/* Return the assigned system IRQ number that corresponds to the PCI - * "Interrupt Pin" information from configuration space. - * - * The IRQ information is stored in the pcif_pci_irq_table configurable - * by the user. - * - * Returns the "system IRQ" for the PCI INTA#..INTD# pin in irq_pin. Returns - * 0xff if not assigned. - */ -static uint8_t pcif_bus0_irq_map(pci_dev_t dev, int irq_pin) -{ - uint8_t sysIrqNr = 0; /* not assigned */ - int irq_group; - - if ( (irq_pin >= 1) && (irq_pin <= 4) ) { - /* Use default IRQ decoding on PCI BUS0 according slot numbering */ - irq_group = PCI_DEV_SLOT(dev) & 0x3; - irq_pin = ((irq_pin - 1) + irq_group) & 0x3; - /* Valid PCI "Interrupt Pin" number */ - sysIrqNr = pcif_pci_irq_table[irq_pin]; - } - return sysIrqNr; -} - -static int pcif_translate(uint32_t *address, int type, int dir) -{ - /* No address translation implmented at this point */ - return 0; -} - -extern struct pci_memreg_ops pci_memreg_sparc_be_ops; - -/* PCIF Big-Endian PCI access routines */ -struct pci_access_drv pcif_access_drv = { - .cfg = - { - pcif_cfg_r8, - pcif_cfg_r16, - pcif_cfg_r32, - pcif_cfg_w8, - pcif_cfg_w16, - pcif_cfg_w32, - }, - .io = /* PCIF only supports Big-endian */ - { - _ld8, - _ld_be16, - _ld_be32, - _st8, - _st_be16, - _st_be32, - }, - .memreg = &pci_memreg_sparc_be_ops, - .translate = pcif_translate, -}; - -/* Initializes the PCIF core hardware - * - */ -static int pcif_hw_init(struct pcif_priv *priv) -{ - struct pcif_regs *regs; - uint32_t data, size; - int mst; - pci_dev_t host = HOST_TGT; - - regs = priv->regs; - - /* Mask PCI interrupts */ - regs->intr = 0; - - /* Get the PCIF Host PCI ID */ - pcif_cfg_r32(host, PCIR_VENDOR, &priv->devVend); - - /* set 1:1 mapping between AHB -> PCI memory space, for all Master cores */ - for ( mst=0; mst<16; mst++) { - regs->maps[mst] = priv->pci_area; - - /* Check if this register is implemented */ - if ( regs->maps[mst] != priv->pci_area ) - break; - } - - /* and map system RAM at pci address SYSTEM_MAINMEM_START. This way - * PCI targets can do DMA directly into CPU main memory. - */ - regs->bars[0] = SYSTEM_MAINMEM_START; - regs->bars[1] = 0; - regs->bars[2] = 0; - regs->bars[3] = 0; - - /* determine size of target BAR1 */ - pcif_cfg_w32(host, PCIR_BAR(1), 0xffffffff); - pcif_cfg_r32(host, PCIR_BAR(1), &size); - priv->bar1_size = (~(size & ~0xf)) + 1; - - pcif_cfg_w32(host, PCIR_BAR(0), 0); - pcif_cfg_w32(host, PCIR_BAR(1), SYSTEM_MAINMEM_START); - pcif_cfg_w32(host, PCIR_BAR(2), 0); - pcif_cfg_w32(host, PCIR_BAR(3), 0); - pcif_cfg_w32(host, PCIR_BAR(4), 0); - pcif_cfg_w32(host, PCIR_BAR(5), 0); - - /* set as bus master and enable pci memory responses */ - pcif_cfg_r32(host, PCIR_COMMAND, &data); - data |= (PCIM_CMD_MEMEN | PCIM_CMD_BUSMASTEREN); - pcif_cfg_w32(host, PCIR_COMMAND, data); - - /* Successful */ - return 0; -} - -/* Initializes the PCIF core and driver, must be called before calling init_pci() - * - * Return values - * 0 Successful initalization - * -1 Error during initialization, for example "PCI core not found". - * -2 Error PCI controller not HOST (targets not supported) - * -3 Error due to PCIF hardware initialization - * -4 Error registering driver to PCI layer - */ -static int pcif_init(struct pcif_priv *priv) -{ - struct ambapp_apb_info *apb; - struct ambapp_ahb_info *ahb; - int pin; - union drvmgr_key_value *value; - char keyname[6]; - struct amba_dev_info *ainfo = priv->dev->businfo; - - /* Find PCI core from Plug&Play information */ - apb = ainfo->info.apb_slv; - ahb = ainfo->info.ahb_slv; - - /* Found PCI core, init private structure */ - priv->irq = apb->irq; - priv->regs = (struct pcif_regs *)apb->start; - - /* Calculate the PCI windows - * AMBA->PCI Window: AHB SLAVE AREA0 - * AMBA->PCI I/O cycles Window: AHB SLAVE AREA1 Lower half - * AMBA->PCI Configuration cycles Window: AHB SLAVE AREA1 Upper half - */ - priv->pci_area = ahb->start[0]; - priv->pci_area_end = ahb->start[0] + ahb->mask[0]; - priv->pci_io = ahb->start[1]; - priv->pci_conf = ahb->start[1] + (ahb->mask[1] >> 1); - priv->pci_conf_end = ahb->start[1] + ahb->mask[1]; - - /* On systems where PCI I/O area and configuration area is apart of the "PCI Window" - * the PCI Window stops at the start of the PCI I/O area - */ - if ( (priv->pci_io > priv->pci_area) && (priv->pci_io < (priv->pci_area_end-1)) ) { - priv->pci_area_end = priv->pci_io; - } - - /* Init PCI interrupt assignment table to all use the interrupt routed through - * the PCIF core. - */ - strcpy(keyname, "INTX#"); - for (pin=1; pin<5; pin++) { - if ( pcif_pci_irq_table[pin-1] == 0xff ) { - pcif_pci_irq_table[pin-1] = priv->irq; - - /* User may override Plug & Play IRQ */ - keyname[3] = 'A' + (pin-1); - value = drvmgr_dev_key_get(priv->dev, keyname, DRVMGR_KT_INT); - if ( value ) - pcif_pci_irq_table[pin-1] = value->i; - } - } - - priv->irq_mask = 0xf; - value = drvmgr_dev_key_get(priv->dev, "", DRVMGR_KT_INT); - if ( value ) - priv->irq_mask = value->i & 0xf; - - /* This driver only support HOST systems, we check for HOST */ - if ( priv->regs->status & 0x00000001 ) { - /* Target not supported */ - return -2; - } - - /* Init the PCI Core */ - if ( pcif_hw_init(priv) ) { - return -3; - } - - /* Down streams translation table */ - priv->maps_down[0].name = "AMBA -> PCI MEM Window"; - priv->maps_down[0].size = priv->pci_area_end - priv->pci_area; - priv->maps_down[0].from_adr = (void *)priv->pci_area; - priv->maps_down[0].to_adr = (void *)priv->pci_area; - /* End table */ - priv->maps_down[1].size = 0; - - /* Up streams translation table */ - priv->maps_up[0].name = "Target BAR1 -> AMBA"; - priv->maps_up[0].size = priv->bar1_size; - priv->maps_up[0].from_adr = (void *)SYSTEM_MAINMEM_START; - priv->maps_up[0].to_adr = (void *)SYSTEM_MAINMEM_START; - /* End table */ - priv->maps_up[1].size = 0; - - return 0; -} - -/* Called when a core is found with the AMBA device and vendor ID - * given in pcif_ids[]. - */ -int pcif_init1(struct drvmgr_dev *dev) -{ - struct pcif_priv *priv; - struct pci_auto_setup pcif_auto_cfg; - - DBG("PCIF[%d] on bus %s\n", dev->minor_drv, dev->parent->dev->name); - - if ( pcif_minor != 0 ) { - printf("Driver only supports one PCI core\n"); - return DRVMGR_FAIL; - } - - priv = dev->priv; - if ( !priv ) - return DRVMGR_NOMEM; - - dev->priv = priv; - priv->dev = dev; - priv->minor = pcif_minor++; - - pcifpriv = priv; - if ( pcif_init(priv) ) { - printf("Failed to initialize PCIF driver\n"); - free(priv); - dev->priv = NULL; - return DRVMGR_FAIL; - } - - /* Host is always Big-Endian */ - pci_endian = PCI_BIG_ENDIAN; - - /* Register the PCI core at the PCI layer */ - - if (pci_access_drv_register(&pcif_access_drv)) { - /* Access routines registration failed */ - return DRVMGR_FAIL; - } - - /* Prepare memory MAP */ - pcif_auto_cfg.options = 0; - pcif_auto_cfg.mem_start = 0; - pcif_auto_cfg.mem_size = 0; - pcif_auto_cfg.memio_start = priv->pci_area; - pcif_auto_cfg.memio_size = priv->pci_area_end - priv->pci_area; - pcif_auto_cfg.io_start = priv->pci_io; - pcif_auto_cfg.io_size = priv->pci_conf - priv->pci_io; - pcif_auto_cfg.irq_map = pcif_bus0_irq_map; - pcif_auto_cfg.irq_route = NULL; /* use standard routing */ - pci_config_register(&pcif_auto_cfg); - - if (pci_config_init()) { - /* PCI configuration failed */ - return DRVMGR_FAIL; - } - - priv->config.maps_down = &priv->maps_down[0]; - priv->config.maps_up = &priv->maps_up[0]; - return pcibus_register(dev, &priv->config); -} - -int pcif_init3(struct drvmgr_dev *dev) -{ - struct pcif_priv *priv = dev->priv; - - /* Unmask all interrupts, on some sytems this - * might be problematic because all PCI IRQs are - * not connected on the PCB or used for something - * else. The irqMask driver resource can be used to - * control which PCI IRQs are used to generate the - * PCI system IRQ, example: - * - * 0xf - enable all (DEFAULT) - * 0x8 - enable one PCI irq - * - * Before unmasking PCI IRQ, all PCI boards must - * have been initialized and IRQ turned off to avoid - * system hang. - */ - - priv->regs->intr = priv->irq_mask; - - return DRVMGR_OK; -} diff --git a/c/src/lib/libbsp/sparc/shared/pwm/grpwm.c b/c/src/lib/libbsp/sparc/shared/pwm/grpwm.c deleted file mode 100644 index 302df73e83..0000000000 --- a/c/src/lib/libbsp/sparc/shared/pwm/grpwm.c +++ /dev/null @@ -1,853 +0,0 @@ -/* - * GRPWM PWM Driver interface. - * - * COPYRIGHT (c) 2009. - * Cobham Gaisler AB, - * - * 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 -#include - -/* #define DEBUG 1 */ - -#ifdef DEBUG -#define DBG(x...) printk(x) -#define STATIC -#else -#define DBG(x...) -#define STATIC static -#endif - -/*** REGISTER LAYOUT ***/ - -/* PWM Channel specific registers */ -struct grpwm_pwm_regs { - volatile unsigned int period; /* 0x00 */ - volatile unsigned int comp; /* 0x04 */ - volatile unsigned int dbcomp; /* 0x08 */ - volatile unsigned int ctrl; /* 0x0C */ -}; - -/* Core common registers */ -struct grpwm_regs { - volatile unsigned int ctrl; /* 0x00 */ - volatile unsigned int scaler; /* 0x04 */ - volatile unsigned int ipend; /* 0x08 */ - volatile unsigned int cap1; /* 0x0C */ - volatile unsigned int cap2; /* 0x10 */ - volatile unsigned int wctrl; /* 0x14 */ - int reserved0[2]; - struct grpwm_pwm_regs pwms[8]; /* 0x20 */ - int reserved1[(0x8000-0xA0)/4]; /* 0xA0-0x7FFC */ - volatile unsigned int wram[0x8000/4]; /* 0x8000-0xFFFC */ -}; - -/*** REGISTER BIT LAYOUT ***/ - -/* CTRL REGISTER - 0x0 */ -#define GRPWM_CTRL_EN_BIT 0 -#define GRPWM_CTRL_SCSEL_BIT 8 -#define GRPWM_CTRL_NOUP_BIT 12 -#define GRPWM_CTRL_EN (1<minor_drv, dev->parent->dev->name); - - priv = dev->priv = malloc(sizeof(struct grpwm_priv)); - if ( !priv ) - return DRVMGR_NOMEM; - memset(priv, 0, sizeof(*priv)); - priv->dev = dev; - - /* This core will not find other cores, so we wait for init2() */ - - return DRVMGR_OK; -} - -int grpwm_init3(struct drvmgr_dev *dev) -{ - struct grpwm_priv *priv = dev->priv; - char prefix[32]; - rtems_status_code status; - - if ( !priv ) - return DRVMGR_FAIL; - - if ( grpwm_driver_io_registered == 0) { - /* Register the I/O driver only once for all cores */ - if ( grpwm_register_io(&grpwm_driver_io_major) ) { - /* Failed to register I/O driver */ - dev->priv = NULL; - return DRVMGR_FAIL; - } - - grpwm_driver_io_registered = 1; - } - - /* I/O system registered and initialized - * Now we take care of device initialization. - */ - if ( grpwm_device_init(priv) ) { - free(dev->priv); - dev->priv = NULL; - return DRVMGR_FAIL; - } - - /* Get Filesystem name prefix */ - prefix[0] = '\0'; - if ( drvmgr_get_dev_prefix(dev, prefix) ) { - /* Failed to get prefix, make sure of a unique FS name - * by using the driver minor. - */ - sprintf(priv->devName, "/dev/grpwm%d", dev->minor_drv); - } else { - /* Got special prefix, this means we have a bus prefix - * And we should use our "bus minor" - */ - sprintf(priv->devName, "/dev/%sgrpwm%d", prefix, dev->minor_bus); - } - - /* Register Device */ - status = rtems_io_register_name(priv->devName, grpwm_driver_io_major, - dev->minor_drv); - if (status != RTEMS_SUCCESSFUL) { - return DRVMGR_FAIL; - } - - return DRVMGR_OK; -} - -/******************* Driver Implementation ***********************/ - -static rtems_device_driver grpwm_initialize(rtems_device_major_number major, rtems_device_minor_number minor, void *arg); -static rtems_device_driver grpwm_open(rtems_device_major_number major, rtems_device_minor_number minor, void *arg); -static rtems_device_driver grpwm_close(rtems_device_major_number major, rtems_device_minor_number minor, void *arg); -static rtems_device_driver grpwm_read(rtems_device_major_number major, rtems_device_minor_number minor, void *arg); -static rtems_device_driver grpwm_write(rtems_device_major_number major, rtems_device_minor_number minor, void *arg); -static rtems_device_driver grpwm_ioctl(rtems_device_major_number major, rtems_device_minor_number minor, void *arg); - -#define GRPWM_DRIVER_TABLE_ENTRY { grpwm_initialize, grpwm_open, grpwm_close, grpwm_read, grpwm_write, grpwm_ioctl } - -static rtems_driver_address_table grpwm_driver = GRPWM_DRIVER_TABLE_ENTRY; - -int grpwm_register_io(rtems_device_major_number *m) -{ - rtems_status_code r; - - if ((r = rtems_io_register_driver(0, &grpwm_driver, m)) == RTEMS_SUCCESSFUL) { - DBG("GRPWM driver successfully registered, major: %d\n", *m); - } else { - switch(r) { - case RTEMS_TOO_MANY: - DBG("GRPWM rtems_io_register_driver failed: RTEMS_TOO_MANY\n"); - return -1; - case RTEMS_INVALID_NUMBER: - DBG("GRPWM rtems_io_register_driver failed: RTEMS_INVALID_NUMBER\n"); - return -1; - case RTEMS_RESOURCE_IN_USE: - DBG("GRPWM rtems_io_register_driver failed: RTEMS_RESOURCE_IN_USE\n"); - return -1; - default: - DBG("GRPWM rtems_io_register_driver failed\n"); - return -1; - } - } - return 0; -} - -static void grpwm_scaler_set( - struct grpwm_regs *regs, - int scaler, - unsigned int value) -{ - /* Select scaler */ - regs->ctrl = (regs->ctrl & ~GRPWM_CTRL_SCSEL) | (scaler << GRPWM_CTRL_SCSEL_BIT); - /* Write scaler */ - regs->scaler = value; -} - -/* Write Wave form RAM */ -static void grpwm_write_wram( - struct grpwm_regs *regs, - unsigned int *data, - int length) -{ - unsigned int *end; - volatile unsigned int *pos; - - pos = ®s->wram[0]; - - /* Write RAM */ - if ( data ) { - end = data + length; - while ( data < end ) { - *pos++ = *data++; - } - } else { - while( length > 0 ) { - *pos++ = 0; - length -= 4; - } - } -} - -static void grpwm_hw_reset(struct grpwm_priv *priv) -{ - int i; - struct grpwm_chan_priv *pwm; - struct grpwm_regs *regs = priv->regs; - - /* Disable Core */ - regs->ctrl = 0; - - /* Clear all registers */ - regs->ipend = 0xffffffff; - regs->wctrl = 0; - - /* Init all PWM channels */ - for (i=0; ichannel_cnt; i++) { - pwm = priv->channels[i]; - pwm->pwmregs->ctrl = 0; - pwm->pwmregs->period = 0; - pwm->pwmregs->comp = 0; - pwm->pwmregs->dbcomp = 0; - pwm->pwmregs->ctrl = 0; /* Twice because METH and POL requires EN=0 */ - } - - /* Clear RAM */ - if ( priv->wave ) { - grpwm_write_wram(regs, NULL, priv->wlength); - } - - /* Set max scaler */ - for (i=0; inscalers; i++) { - grpwm_scaler_set(regs, i, 0xffffffff); - } -} - -/* Update one Channel but leaves the "Hold update" bit set - * - * A bit mask of updated bits are returned. - */ -static unsigned int grpwm_update_prepare_channel( - struct grpwm_priv *priv, - int channel, - struct grpwm_ioctl_update_chan *up - ) -{ - struct grpwm_chan_priv *pwm; - struct grpwm_pwm_regs *pwmregs; - unsigned int ctrl; - unsigned int ret; - - pwm = priv->channels[channel]; - pwmregs = pwm->pwmregs; - - /* Read channel control register */ - ctrl = pwmregs->ctrl; - ret = 0; - - if ( up->options & GRPWM_UPDATE_OPTION_DISABLE ) { - ctrl &= ~GRPWM_PCTRL_EN; - pwmregs->ctrl = ctrl; - ret |= GRPWM_PCTRL_EN; - } - - /* Hold the updates */ - if ( up->options & (GRPWM_UPDATE_OPTION_PERIOD| - GRPWM_UPDATE_OPTION_COMP|GRPWM_UPDATE_OPTION_DBCOMP) ) { - - if ( up->options & (GRPWM_UPDATE_OPTION_PERIOD) ) { - DBG("GRPWM: UPDATING 0x%x: 0x%x\n", &pwmregs->period, up->period); - pwmregs->period = up->period; - } - if ( up->options & (GRPWM_UPDATE_OPTION_COMP) ) { - DBG("GRPWM: UPDATING 0x%x: 0x%x\n", &pwmregs->comp, up->compare); - pwmregs->comp = up->compare; - } - if ( up->options & (GRPWM_UPDATE_OPTION_DBCOMP) ) { - DBG("GRPWM: UPDATING 0x%x: 0x%x\n", &pwmregs->dbcomp, up->dbcomp); - pwmregs->dbcomp = up->dbcomp; - } - } - - if ( up->options & GRPWM_UPDATE_OPTION_ENABLE ) { - ret |= GRPWM_PCTRL_EN; - pwmregs->ctrl = ctrl | GRPWM_PCTRL_EN; - } - return ret; -} - -static void grpwm_update_active(struct grpwm_priv *priv, int enable) -{ - unsigned int ctrl; - int i; - - ctrl = priv->regs->ctrl; - - /* Make all "Update Hold" bits be cleared */ - ctrl &= ~GRPWM_CTRL_NOUP; - - /* A change in any of the Channel enable/disable bits? */ - if ( enable ) { - ctrl &= ~GRPWM_CTRL_EN; - for(i=0; ichannel_cnt; i++) { - ctrl |= priv->regs->pwms[i].ctrl & GRPWM_CTRL_EN; - } - } - priv->regs->ctrl = ctrl; -} - -/* Configure the hardware of a channel according to this */ -static rtems_status_code grpwm_config_channel( - struct grpwm_priv *priv, - int channel, - struct grpwm_ioctl_config *cfg - ) -{ - struct grpwm_chan_priv *pwm; - unsigned int pctrl, wctrl=0; - - pwm = priv->channels[channel]; - if ( pwm->pwmregs->ctrl & GRPWM_PCTRL_EN_BIT ) { - return RTEMS_RESOURCE_IN_USE; - } - if ( cfg->options & ~GRPWM_CONFIG_OPTION_MASK ) { - return RTEMS_INVALID_NAME; - } - if ( (cfg->options & GRPWM_CONFIG_OPTION_DUAL) && - ((priv->regs->cap1 & GRPWM_CAP_DCM) == 0) ) { - return RTEMS_INVALID_NAME; - } - /* IRQ set up */ - pwm->isr_arg = cfg->isr_arg; - pwm->isr = cfg->isr; - - pctrl = cfg->options | - (cfg->dbscaler << GRPWM_PCTRL_DBSC_BIT) | - (cfg->irqscaler << GRPWM_PCTRL_ISC_BIT) | - (cfg->scaler_index << GRPWM_PCTRL_SCSEL_BIT); - - /* Set Wave form gerneration if available */ - if ( !priv->wave || (priv->channel_cnt != (channel+1)) ) { - /* Wave Form not available for this channel (or core) */ - if ( cfg->wave_activate || cfg->wave_data || cfg->wave_data_length ) { - return RTEMS_INVALID_NAME; - } - } else if ( cfg->wave_activate ) { - /* Enable Wave form generation */ - DBG("GRPWM: ENABLING WAVE FORM GENERATION 0x%x\n", cfg->wave_data_length); - - if ( cfg->wave_data ) { - grpwm_write_wram(priv->regs, cfg->wave_data, cfg->wave_data_length); - } - - /* Write length register, and let user control Wave-Sync functionality */ - wctrl = (((cfg->wave_data_length-1) << GRPWM_WCTRL_STOP_BIT) & GRPWM_WCTRL_STOP); - wctrl |= cfg->wave_synccfg & (GRPWM_WCTRL_WSYNCCFG|GRPWM_WCTRL_WSEN); - wctrl |= (cfg->wave_sync << 16) & 0x1fff0000; - priv->regs->wctrl = wctrl; - - /* Enable Wave form */ - pctrl |= GRPWM_PCTRL_WEN; - } - - DBG("GRPWM: CONFIG: 0x%x, WAVE CONFIG: 0x%x\n", pctrl, wctrl); - - pwm->pwmregs->ctrl = pctrl; - - return RTEMS_SUCCESSFUL; -} - -static void grpwm_isr(void *arg) -{ - unsigned int ipend; - struct grpwm_chan_priv *pwm = arg; - struct grpwm_priv *priv = pwm->common; - int i; - - /* Get current pending interrupts */ - ipend = priv->regs->ipend; - - for (i=0; ichannel_cnt; i++) { - if ( ipend & (1<channels[i]; - if ( pwm->isr ) { - pwm->isr(i, pwm->isr_arg); - } - } - } - priv->regs->ipend = ipend; -} - -static rtems_device_driver grpwm_initialize(rtems_device_major_number major, rtems_device_minor_number minor, void *arg) -{ - return RTEMS_SUCCESSFUL; -} - -static rtems_device_driver grpwm_open(rtems_device_major_number major, rtems_device_minor_number minor, void *arg) -{ - struct grpwm_priv *priv; - rtems_device_driver ret; - struct drvmgr_dev *dev; - - if ( drvmgr_get_dev(&grpwm_drv_info.general, minor, &dev) ) { - DBG("Wrong minor %d\n", minor); - return RTEMS_INVALID_NAME; - } - priv = (struct grpwm_priv *)dev->priv; - - /* Wait until we get semaphore */ - if ( rtems_semaphore_obtain(priv->dev_sem, RTEMS_WAIT, RTEMS_NO_TIMEOUT) != - RTEMS_SUCCESSFUL ){ - return RTEMS_INTERNAL_ERROR; - } - - /* is device busy/taken? */ - if ( priv->open ) { - ret=RTEMS_RESOURCE_IN_USE; - goto out; - } - - /* Mark device taken */ - priv->open = 1; - - ret = RTEMS_SUCCESSFUL; -out: - rtems_semaphore_release(priv->dev_sem); - return ret; -} - -static rtems_device_driver grpwm_close(rtems_device_major_number major, rtems_device_minor_number minor, void *arg) -{ - struct grpwm_priv *priv; - struct drvmgr_dev *dev; - - if ( drvmgr_get_dev(&grpwm_drv_info.general, minor, &dev) ) { - return RTEMS_INVALID_NAME; - } - priv = (struct grpwm_priv *)dev->priv; - - /* Reset Hardware */ - grpwm_hw_reset(priv); - - /* Mark Device closed */ - priv->open = 0; - - return RTEMS_SUCCESSFUL; -} - -static rtems_device_driver grpwm_read(rtems_device_major_number major, rtems_device_minor_number minor, void *arg) -{ - return RTEMS_UNSATISFIED; -} - -static rtems_device_driver grpwm_write(rtems_device_major_number major, rtems_device_minor_number minor, void *arg) -{ - return RTEMS_UNSATISFIED; -} - -static rtems_device_driver grpwm_ioctl(rtems_device_major_number major, rtems_device_minor_number minor, void *arg) -{ - - struct grpwm_priv *priv; - struct drvmgr_dev *dev; - rtems_libio_ioctl_args_t *ioarg = (rtems_libio_ioctl_args_t *)arg; - - if ( drvmgr_get_dev(&grpwm_drv_info.general, minor, &dev) ) { - return RTEMS_INVALID_NAME; - } - priv = (struct grpwm_priv *)dev->priv; - - if (!ioarg) - return RTEMS_INVALID_NAME; - - ioarg->ioctl_return = 0; - switch(ioarg->command) { - default: /* Not a valid command */ - return RTEMS_NOT_DEFINED; - - case GRPWM_IOCTL_GET_CAP: - { - struct grpwm_ioctl_cap *cap = (void *)ioarg->buffer; - if ( cap == NULL ) - return RTEMS_INVALID_NAME; - - /* Copy Capability registers to user */ - cap->channel_cnt = priv->channel_cnt; - cap->pwm = priv->regs->cap1; - cap->wave = priv->regs->cap2; - break; - } - case GRPWM_IOCTL_SET_CONFIG: - { - struct grpwm_ioctl_config *cfg = (void *)ioarg->buffer; - if ( cfg == NULL ) - return RTEMS_INVALID_NAME; - if ( cfg->channel >= priv->channel_cnt ) - return RTEMS_INVALID_NAME; - - return grpwm_config_channel(priv, cfg->channel, cfg); - } - case GRPWM_IOCTL_SET_SCALER: - { - unsigned int invalid_mask; - int i; - struct grpwm_ioctl_scaler *sc = ioarg->buffer; - - if ( sc == NULL ) - return RTEMS_INVALID_NAME; - - /* Test if caller reqest to set a scaler not existing */ - invalid_mask = ~((1 << priv->nscalers) - 1); - if ( invalid_mask & sc->index_mask ) { - return RTEMS_INVALID_NAME; - } - - /* Set scalers requested */ - for (i=0; inscalers; i++) { - if ( sc->index_mask & (1<regs, i, sc->values[i]); - } - } - break; - } - case GRPWM_IOCTL_UPDATE: - { - struct grpwm_ioctl_update *up = ioarg->buffer; - unsigned int invalid_mask, pctrl = 0; - int i; - - if ( up == NULL ) - return RTEMS_INVALID_NAME; - - /* Test if caller reqest to set a scaler not existing */ - invalid_mask = ~((1 << priv->channel_cnt) - 1); - if ( invalid_mask & up->chanmask ) { - return RTEMS_INVALID_NAME; - } - - /* In order for the changes to take effect at the same time, the "Hold update" - * bits is set for all PWM channels that will be updated. The hold update bits - * will be cleared at the same time for all channels. - */ - priv->regs->ctrl = (priv->regs->ctrl & ~GRPWM_CTRL_NOUP) | - (up->chanmask << GRPWM_CTRL_NOUP_BIT); - - for (i=0; ichannel_cnt; i++) { - if ( up->chanmask & (1<channels[i]); - } - } - - /* 1. Update all channels requested, - * 2. Enable the core if at least one channel is enabled - * 3. Disable the core if all channels are disabled - */ - grpwm_update_active(priv, (pctrl & GRPWM_PCTRL_EN)); - - break; - } - case GRPWM_IOCTL_IRQ: - { - unsigned int data = (unsigned int)ioarg->buffer; - int channel = (data >> 8) & 0x7; - struct grpwm_chan_priv *pwm; - unsigned int pctrl; - - pwm = priv->channels[channel]; - - if ( data & GRPWM_IRQ_CLEAR ) { - priv->regs->ipend |= (1<dev, pwm->irqindex); - } - if ( (data & 0x3) && !pwm->isr ) { - /* Enable IRQ but no ISR */ - return RTEMS_INVALID_NAME; - } - pctrl = pwm->pwmregs->ctrl & ~(GRPWM_PCTRL_IEN|GRPWM_PCTRL_IT); - pctrl |= ((data & 0x3) << GRPWM_PCTRL_IEN_BIT); - pwm->pwmregs->ctrl = pctrl; - break; - } - } - - return RTEMS_SUCCESSFUL; -} - -#define MAX_CHANNEL 8 -char grpwm_irqindex_lookup[8][MAX_CHANNEL] = -{ -/* Channel 1 2 3 4 5 6 7 8 */ -/* npwm 1 */ {0, 0, 0, 0, 0, 0, 0, 0}, -/* npwm 2 */ {0, 1, 0, 0, 0, 0, 0, 0}, -/* npwm 3 */ {0, 0, 0, 0, 0, 0, 0, 0}, -/* npwm 4 */ {0, 0, 0, 1, 0, 0, 0, 0}, -/* npwm 5 */ {0, 0, 0, 1, 2, 0, 0, 0}, -/* npwm 6 */ {0, 0, 0, 1, 1, 1, 0, 0}, -/* npwm 7 */ {0, 0, 0, 1, 1, 1, 2, 0}, -/* npwm 8 */ {0, 0, 0, 1, 1, 1, 2, 3} -}; - -int grpwm_device_init(struct grpwm_priv *priv) -{ - struct amba_dev_info *ambadev; - struct ambapp_core *pnpinfo; - int mask, i, sepirq; - unsigned int wabits; - struct grpwm_chan_priv *pwm; - struct grpwm_regs *regs; - - /* Get device information from AMBA PnP information */ - ambadev = (struct amba_dev_info *)priv->dev->businfo; - if ( ambadev == NULL ) { - return -1; - } - pnpinfo = &ambadev->info; - priv->irq = pnpinfo->irq; - regs = priv->regs = (struct grpwm_regs *)pnpinfo->apb_slv->start; - - DBG("GRPWM: 0x%08x irq %d\n", (unsigned int)regs, priv->irq); - - /* Disable Core */ - regs->ctrl = 0; - - /* Clear all registers */ - regs->ipend = 0xffffffff; - regs->wctrl = 0; - - /* Find the number of PWM channels */ - priv->channel_cnt = 1 + ((regs->cap1 & GRPWM_CAP_NPWM) >> GRPWM_CAP_NPWM_BIT); - pwm = malloc(sizeof(*pwm)*priv->channel_cnt); - if ( !pwm ) - return -1; - memset(pwm, 0, sizeof(*pwm)*priv->channel_cnt); - - /* Init all PWM channels */ - sepirq = ((regs->cap1 & GRPWM_CAP_SEP) >> GRPWM_CAP_SEP_BIT); - for (i=0; ichannel_cnt; i++, pwm++) { - priv->channels[i] = pwm; - pwm->common = priv; - pwm->pwmregs = ®s->pwms[i]; - if ( sepirq == 0 ) { - pwm->irqindex = 0; - } else if ( sepirq == 1 ) { - pwm->irqindex = i; - } else { - pwm->irqindex = grpwm_irqindex_lookup[priv->channel_cnt][i]; - } - } - - /* Detect if Wave Form capability is availble for last PWM channel */ - if ( regs->cap2 & GRPWM_CAP2_WPWM ) { - priv->wave = 1; - - /* Clear RAM */ - wabits = (regs->cap2 & GRPWM_CAP2_WABITS) >> GRPWM_CAP2_WABITS_BIT; - priv->wlength = 1 << wabits; - } - priv->nscalers = 1 + ((regs->cap1 & GRPWM_CAP_NSC) >> GRPWM_CAP_NSC_BIT); - - grpwm_hw_reset(priv); - - /* Device Semaphore created with count = 1 */ - if ( rtems_semaphore_create(rtems_build_name('G', 'P', 'W', 'M'), - 1, - RTEMS_FIFO|RTEMS_SIMPLE_BINARY_SEMAPHORE|RTEMS_NO_INHERIT_PRIORITY|\ - RTEMS_LOCAL|RTEMS_NO_PRIORITY_CEILING, - 0, - &priv->dev_sem) != RTEMS_SUCCESSFUL ) { - return -1; - } - - /* Register interrupt handler for all PWM channels */ - mask = 0; - for (i=0; ichannel_cnt; i++) { - pwm = priv->channels[i]; - if ( (mask & (1 << pwm->irqindex)) == 0 ) { - /* Not registered interrupt handler for this IRQ index before, - * we do it now. - */ - mask |= (1 << pwm->irqindex); - drvmgr_interrupt_register( - priv->dev, - pwm->irqindex, - "grpwm", - grpwm_isr, - pwm); - } - } - - return 0; -} diff --git a/c/src/lib/libbsp/sparc/shared/scrub/memscrub.c b/c/src/lib/libbsp/sparc/shared/scrub/memscrub.c deleted file mode 100644 index 2e4dfeeb0c..0000000000 --- a/c/src/lib/libbsp/sparc/shared/scrub/memscrub.c +++ /dev/null @@ -1,692 +0,0 @@ -/* Memory Scrubber register driver - * - * COPYRIGHT (c) 2017. - * Cobham Gaisler AB. - * - * 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 - -/*#define STATIC*/ -#define STATIC static - -#define UNUSED __attribute__((unused)) - -/*#define DEBUG 1*/ - -#ifdef DEBUG -#define DBG(x...) printf(x) -#else -#define DBG(x...) -#endif - -#define REG_WRITE(addr, val) (*(volatile uint32_t *)(addr) = (uint32_t)(val)) -#define REG_READ(addr) (*(volatile uint32_t *)(addr)) - -/* - * MEMORYSCRUBBER AHBS register fields - * DEFINED IN HEADER FILE - */ - -/* - * MEMORYSCRUBBER AHBERC register fields - * DEFINED IN HEADER FILE - */ - -/* - * MEMORYSCRUBBER STAT register fields - * DEFINED IN HEADER FILE - */ - -/* - * MEMORYSCRUBBER CONFIG register fields - * DEFINED IN HEADER FILE - */ - -/* - * MEMORYSCRUBBER ETHRES register fields - * DEFINED IN HEADER FILE - */ - -/* MEMORYSCRUBBER Registers layout */ -struct memscrub_regs { - volatile uint32_t ahbstatus; /* 0x00 */ - volatile uint32_t ahbfailing; /* 0x04 */ - volatile uint32_t ahberc; /* 0x08 */ - volatile uint32_t resv1; /* 0x0c */ - volatile uint32_t status; /* 0x10 */ - volatile uint32_t config; /* 0x14 */ - volatile uint32_t rangel; /* 0x18 */ - volatile uint32_t rangeh; /* 0x1c */ - volatile uint32_t pos; /* 0x20 */ - volatile uint32_t ethres; /* 0x24 */ - volatile uint32_t init; /* 0x28 */ - volatile uint32_t rangel2; /* 0x2c */ - volatile uint32_t rangeh2; /* 0x30 */ -}; - -#define DEVNAME_LEN 10 -struct memscrub_priv { - struct drvmgr_dev *dev; - char devname[DEVNAME_LEN]; - struct memscrub_regs *regs; - int minor; - int burstlen; - int blockmask; - /* Cached error */ - uint32_t last_status; - uint32_t last_address; - /* User defined ISR */ - memscrub_isr_t isr; - void *isr_arg; -}; -static struct memscrub_priv * memscrubpriv = NULL; - -STATIC int memscrub_init2(struct drvmgr_dev *dev); -STATIC int memscrub_init(struct memscrub_priv *priv); - -void memscrub_isr(void *arg); - -struct drvmgr_drv_ops memscrub_ops = -{ - .init = {NULL, memscrub_init2, NULL, NULL}, - .remove = NULL, - .info = NULL -}; - -struct amba_dev_id memscrub_ids[] = -{ - {VENDOR_GAISLER, GAISLER_MEMSCRUB}, - {0, 0} /* Mark end of table */ -}; - -struct amba_drv_info memscrub_drv_info = -{ - { - DRVMGR_OBJ_DRV, /* Driver */ - NULL, /* Next driver */ - NULL, /* Device list */ - DRIVER_AMBAPP_GAISLER_MEMSCRUB_ID,/* Driver ID */ - "MEMSCRUB_DRV", /* Driver Name */ - DRVMGR_BUS_TYPE_AMBAPP, /* Bus Type */ - &memscrub_ops, - NULL, /* Funcs */ - 0, /* No devices yet */ - sizeof(struct memscrub_priv), - }, - &memscrub_ids[0] -}; - -void memscrub_register_drv (void) -{ - drvmgr_drv_register(&memscrub_drv_info.general); -} - -STATIC int memscrub_init(struct memscrub_priv *priv) -{ - struct ambapp_ahb_info *ahb; - struct amba_dev_info *ainfo = priv->dev->businfo; - unsigned int tmp; - int i,j; - - /* Get device information from AMBA PnP information */ - if (ainfo == NULL){ - return MEMSCRUB_ERR_ERROR; - } - - /* Find MEMSCRUB core from Plug&Play information */ - ahb = ainfo->info.ahb_slv; - priv->regs = (struct memscrub_regs *)ahb->start[0]; - - DBG("MEMSCRUB regs 0x%08x\n", (unsigned int) priv->regs); - - /* Find MEMSCRUB capabilities */ - tmp = REG_READ(&priv->regs->status); - i = (tmp & STAT_BURSTLEN) >> STAT_BURSTLEN_BIT; - for (j=1; i>0; i--) j <<= 1; - priv->burstlen = j; - - - /* If scrubber is active, we cannot stop it to read blockmask value */ - if (tmp & STAT_ACTIVE){ - priv->blockmask = 0; - }else{ - /* Detect block size in bytes and burst length */ - tmp = REG_READ(&priv->regs->rangeh); - REG_WRITE(&priv->regs->rangeh, 0); - priv->blockmask = REG_READ(&priv->regs->rangeh); - REG_WRITE(&priv->regs->rangeh, tmp); - } - - /* DEBUG print */ - DBG("MEMSCRUB with following capabilities:\n"); - DBG(" -Burstlength: %d\n", priv->burstlen); - - return MEMSCRUB_ERR_OK; -} - -STATIC int memscrub_init2(struct drvmgr_dev *dev) -{ - struct memscrub_priv *priv = dev->priv; - - DBG("MEMSCRUB[%d] on bus %s\n", dev->minor_drv, dev->parent->dev->name); - - if (memscrubpriv) { - DBG("Driver only supports one MEMSCRUB core\n"); - return DRVMGR_FAIL; - } - - if (priv==NULL){ - return DRVMGR_NOMEM; - } - - /* Assign priv */ - priv->dev = dev; - strncpy(&priv->devname[0], "memscrub0", DEVNAME_LEN); - memscrubpriv=priv; - - /* Initilize driver struct */ - if (memscrub_init(priv) != MEMSCRUB_ERR_OK){ - return DRVMGR_FAIL; - } - - /* Startup Action: - * - Clear status - * - Register ISR - */ - - /* Initialize hardware by clearing its status */ - REG_WRITE(&priv->regs->ahbstatus, 0); - REG_WRITE(&priv->regs->status, 0); - - return DRVMGR_OK; -} - - -int memscrub_init_start(uint32_t value, uint8_t delay, int options) -{ - struct memscrub_priv *priv = memscrubpriv; - uint32_t sts, tmp; - int i; - - if (priv==NULL){ - DBG("MEMSCRUB not init.\n"); - return MEMSCRUB_ERR_ERROR; - } - - /* Check if scrubber is active */ - sts = REG_READ(&priv->regs->status); - if (sts & STAT_ACTIVE){ - DBG("MEMSCRUB running.\n"); - return MEMSCRUB_ERR_ERROR; - } - - /* Check if we need to probe blockmask */ - if (priv->blockmask == 0){ - /* Detect block size in bytes and burst length */ - tmp = REG_READ(&priv->regs->rangeh); - REG_WRITE(&priv->regs->rangeh, 0); - priv->blockmask = REG_READ(&priv->regs->rangeh); - REG_WRITE(&priv->regs->rangeh, tmp); - } - - /* Set data value */ - for (i=0; iblockmask; i+=4){ - REG_WRITE(&priv->regs->init,value); - } - - /* Clear unused bits */ - options = options & ~(CONFIG_MODE | CONFIG_DELAY); - - /* Enable scrubber */ - REG_WRITE(&priv->regs->config, options | - ((delay << CONFIG_DELAY_BIT) & CONFIG_DELAY) | - CONFIG_MODE_INIT | CONFIG_SCEN); - - DBG("MEMSCRUB INIT STARTED\n"); - - return MEMSCRUB_ERR_OK; -} - -int memscrub_scrub_start(uint8_t delay, int options) -{ - struct memscrub_priv *priv = memscrubpriv; - uint32_t ctrl,sts; - - if (priv==NULL){ - DBG("MEMSCRUB not init.\n"); - return MEMSCRUB_ERR_ERROR; - } - - /* Check if scrubber is active */ - sts = REG_READ(&priv->regs->status); - if (sts & STAT_ACTIVE){ - /* Check if mode is not init */ - ctrl = REG_READ(&priv->regs->config); - if ((ctrl & CONFIG_MODE)==CONFIG_MODE_INIT){ - DBG("MEMSCRUB init running.\n"); - return MEMSCRUB_ERR_ERROR; - } - } - - /* Clear unused bits */ - options = options & ~(CONFIG_MODE | CONFIG_DELAY); - - /* Enable scrubber */ - REG_WRITE(&priv->regs->config, options | - ((delay << CONFIG_DELAY_BIT) & CONFIG_DELAY) | - CONFIG_MODE_SCRUB | CONFIG_SCEN); - - DBG("MEMSCRUB SCRUB STARTED\n"); - - return MEMSCRUB_ERR_OK; -} - -int memscrub_regen_start(uint8_t delay, int options) -{ - struct memscrub_priv *priv = memscrubpriv; - uint32_t ctrl,sts; - - if (priv==NULL){ - DBG("MEMSCRUB not init.\n"); - return MEMSCRUB_ERR_ERROR; - } - - /* Check if scrubber is active */ - sts = REG_READ(&priv->regs->status); - if (sts & STAT_ACTIVE){ - /* Check if mode is not init */ - ctrl = REG_READ(&priv->regs->config); - if ((ctrl & CONFIG_MODE)==CONFIG_MODE_INIT){ - DBG("MEMSCRUB init running.\n"); - return MEMSCRUB_ERR_ERROR; - } - } - - /* Clear unused bits */ - options = options & ~(CONFIG_MODE | CONFIG_DELAY); - - /* Enable scrubber */ - REG_WRITE(&priv->regs->config, options | - ((delay << CONFIG_DELAY_BIT) & CONFIG_DELAY) | - CONFIG_MODE_REGEN | CONFIG_SCEN); - - DBG("MEMSCRUB REGEN STARTED\n"); - - return MEMSCRUB_ERR_OK; -} - -int memscrub_stop(void) -{ - struct memscrub_priv *priv = memscrubpriv; - - if (priv==NULL){ - DBG("MEMSCRUB not init.\n"); - return MEMSCRUB_ERR_ERROR; - } - - /* Disable scrubber */ - REG_WRITE(&priv->regs->config, 0); - - /* Wait until finished */ - while(REG_READ(&priv->regs->status) & STAT_ACTIVE){}; - - DBG("MEMSCRUB STOPPED\n"); - - return MEMSCRUB_ERR_OK; -} - -int memscrub_range_set(uint32_t start, uint32_t end) -{ - struct memscrub_priv *priv = memscrubpriv; - - if (priv==NULL){ - DBG("MEMSCRUB not init.\n"); - return MEMSCRUB_ERR_ERROR; - } - - if (end <= start){ - DBG("MEMSCRUB wrong address.\n"); - return MEMSCRUB_ERR_EINVAL; - } - - /* Check if scrubber is active */ - if (REG_READ(&priv->regs->status) & STAT_ACTIVE){ - DBG("MEMSCRUB running.\n"); - return MEMSCRUB_ERR_ERROR; - } - - /* Set range */ - REG_WRITE(&priv->regs->rangel, start); - REG_WRITE(&priv->regs->rangeh, end); - - DBG("MEMSCRUB range: 0x%08x-0x%08x\n", - (unsigned int) start, - (unsigned int) end); - - return MEMSCRUB_ERR_OK; -} - -int memscrub_secondary_range_set(uint32_t start, uint32_t end) -{ - struct memscrub_priv *priv = memscrubpriv; - - if (priv==NULL){ - DBG("MEMSCRUB not init.\n"); - return MEMSCRUB_ERR_ERROR; - } - - if (end <= start){ - DBG("MEMSCRUB wrong address.\n"); - return MEMSCRUB_ERR_EINVAL; - } - - /* Check if scrubber is active */ - if (REG_READ(&priv->regs->status) & STAT_ACTIVE){ - DBG("MEMSCRUB running.\n"); - return MEMSCRUB_ERR_ERROR; - } - - /* Set range */ - REG_WRITE(&priv->regs->rangel2, start); - REG_WRITE(&priv->regs->rangeh2, end); - - DBG("MEMSCRUB 2nd range: 0x%08x-0x%08x\n", - (unsigned int) start, - (unsigned int) end); - - return MEMSCRUB_ERR_OK; -} - -int memscrub_range_get(uint32_t * start, uint32_t * end) -{ - struct memscrub_priv *priv = memscrubpriv; - - if (priv==NULL){ - DBG("MEMSCRUB not init.\n"); - return MEMSCRUB_ERR_ERROR; - } - - if ((start==NULL) || (end == NULL)){ - DBG("MEMSCRUB wrong pointer.\n"); - return MEMSCRUB_ERR_EINVAL; - } - - /* Get range */ - *start = REG_READ(&priv->regs->rangel); - *end = REG_READ(&priv->regs->rangeh); - - return MEMSCRUB_ERR_OK; -} - -int memscrub_secondary_range_get(uint32_t * start, uint32_t * end) -{ - struct memscrub_priv *priv = memscrubpriv; - - if (priv==NULL){ - DBG("MEMSCRUB not init.\n"); - return MEMSCRUB_ERR_ERROR; - } - - if ((start==NULL) || (end == NULL)){ - DBG("MEMSCRUB wrong pointer.\n"); - return MEMSCRUB_ERR_EINVAL; - } - - /* Get range */ - *start = REG_READ(&priv->regs->rangel2); - *end = REG_READ(&priv->regs->rangeh2); - - return MEMSCRUB_ERR_OK; -} - -int memscrub_ahberror_setup(int uethres, int cethres, int options) -{ - struct memscrub_priv *priv = memscrubpriv; - - if (priv==NULL){ - DBG("MEMSCRUB not init.\n"); - return MEMSCRUB_ERR_ERROR; - } - - /* Set AHBERR */ - REG_WRITE(&priv->regs->ahberc, - ((cethres << AHBERC_CECNTT_BIT) & AHBERC_CECNTT) | - ((uethres << AHBERC_UECNTT_BIT) & AHBERC_UECNTT) | - (options & (AHBERC_CECTE | AHBERC_UECTE))); - - DBG("MEMSCRUB ahb err: UE[%d]:%s, CE[%d]:%s\n", - (unsigned int) uethres, - (options & AHBERC_UECTE)? "enabled":"disabled", - (unsigned int) cethres, - (options & AHBERC_CECTE)? "enabled":"disabled" - ); - - return MEMSCRUB_ERR_OK; -} - -int memscrub_scruberror_setup(int blkthres, int runthres, int options) -{ - struct memscrub_priv *priv = memscrubpriv; - - if (priv==NULL){ - DBG("MEMSCRUB not init.\n"); - return MEMSCRUB_ERR_ERROR; - } - - /* Set ETHRES */ - REG_WRITE(&priv->regs->ethres, - ((blkthres << ETHRES_BECT_BIT) & ETHRES_BECT) | - ((runthres << ETHRES_RECT_BIT) & ETHRES_RECT) | - (options & (ETHRES_RECTE | ETHRES_BECTE))); - - DBG("MEMSCRUB scrub err: BLK[%d]:%s, RUN[%d]:%s\n", - (unsigned int) blkthres, - (options & ETHRES_BECTE)? "enabled":"disabled", - (unsigned int) runthres, - (options & ETHRES_RECTE)? "enabled":"disabled" - ); - - return MEMSCRUB_ERR_OK; -} - -int memscrub_scrub_position(uint32_t * position) -{ - struct memscrub_priv *priv = memscrubpriv; - - if (priv==NULL){ - DBG("MEMSCRUB not init.\n"); - return MEMSCRUB_ERR_ERROR; - } - - if (position==NULL){ - DBG("MEMSCRUB wrong pointer.\n"); - return MEMSCRUB_ERR_EINVAL; - } - - *position = REG_READ(&priv->regs->pos); - - return MEMSCRUB_ERR_OK; -} - -int memscrub_isr_register(memscrub_isr_t isr, void * data) -{ - struct memscrub_priv *priv = memscrubpriv; - unsigned int ethres, ahberc, config; - - if (priv==NULL){ - DBG("MEMSCRUB not init.\n"); - return MEMSCRUB_ERR_ERROR; - } - - if (isr==NULL){ - DBG("MEMSCRUB wrong pointer.\n"); - return MEMSCRUB_ERR_EINVAL; - } - - /* Mask interrupts */ - ethres = REG_READ(&priv->regs->ethres); - REG_WRITE(&priv->regs->ethres, ethres & ~(ETHRES_RECTE | ETHRES_BECTE)); - - ahberc = REG_READ(&priv->regs->ahberc); - REG_WRITE(&priv->regs->ahberc, ahberc & ~(AHBERC_CECTE | AHBERC_UECTE)); - - config = REG_READ(&priv->regs->config); - REG_WRITE(&priv->regs->config, config & ~(CONFIG_IRQD)); - - /* Install IRQ handler if needed */ - if (priv->isr == NULL){ - drvmgr_interrupt_register(priv->dev, 0, priv->devname, memscrub_isr, - priv); - } - - /* Install user ISR */ - priv->isr=isr; - priv->isr_arg=data; - - /* Unmask interrupts */ - REG_WRITE(&priv->regs->ethres, ethres); - - REG_WRITE(&priv->regs->ahberc, ahberc); - - REG_WRITE(&priv->regs->config, config); - - return MEMSCRUB_ERR_OK; -} - -int memscrub_isr_unregister(void) -{ - struct memscrub_priv *priv = memscrubpriv; - unsigned int ethres, ahberc, config; - - if (priv==NULL){ - DBG("MEMSCRUB not init.\n"); - return MEMSCRUB_ERR_ERROR; - } - - if (priv->isr==NULL){ - DBG("MEMSCRUB wrong pointer.\n"); - return MEMSCRUB_ERR_EINVAL; - } - - /* Mask interrupts */ - ethres = REG_READ(&priv->regs->ethres); - REG_WRITE(&priv->regs->ethres, ethres & ~(ETHRES_RECTE | ETHRES_BECTE)); - - ahberc = REG_READ(&priv->regs->ahberc); - REG_WRITE(&priv->regs->ahberc, ahberc & ~(AHBERC_CECTE | AHBERC_UECTE)); - - config = REG_READ(&priv->regs->config); - REG_WRITE(&priv->regs->config, config & ~(CONFIG_IRQD)); - - /* Uninstall IRQ handler if needed */ - drvmgr_interrupt_unregister(priv->dev, 0, memscrub_isr, priv); - - /* Uninstall user ISR */ - priv->isr=NULL; - priv->isr_arg=NULL; - - return MEMSCRUB_ERR_OK; -} - -int memscrub_error_status(uint32_t *ahbaccess, uint32_t *ahbstatus, - uint32_t *scrubstatus) -{ - struct memscrub_priv *priv = memscrubpriv; - uint32_t mask, ahbstatus_val; - - if (priv==NULL){ - DBG("MEMSCRUB not init.\n"); - return MEMSCRUB_ERR_ERROR; - } - - if ((ahbaccess==NULL) || (ahbstatus==NULL) || (scrubstatus == NULL)){ - DBG("MEMSCRUB wrong pointer.\n"); - return MEMSCRUB_ERR_EINVAL; - } - - /* Get hardware status */ - *ahbaccess = REG_READ(&priv->regs->ahbfailing); - *ahbstatus = ahbstatus_val = REG_READ(&priv->regs->ahbstatus); - *scrubstatus = REG_READ(&priv->regs->status); - - /* Clear error status */ - mask = 0; - /* Clear CECNT only if we crossed the CE threshold*/ - if ((ahbstatus_val & AHBS_CE) == 0){ - /* Don't clear the CECNT */ - mask |= AHBS_CECNT; - } - /* Clear UECNT only if we crossed the UE threshold*/ - if ((ahbstatus_val & (AHBS_NE|AHBS_CE|AHBS_SBC|AHBS_SEC)) != AHBS_NE){ - /* Don't clear the UECNT */ - mask |= AHBS_UECNT; - } - REG_WRITE(&priv->regs->ahbstatus, ahbstatus_val & mask); - REG_WRITE(&priv->regs->status,0); - - return MEMSCRUB_ERR_OK; -} - -int memscrub_active(void) -{ - struct memscrub_priv *priv = memscrubpriv; - - if (priv==NULL){ - DBG("MEMSCRUB not init.\n"); - return MEMSCRUB_ERR_ERROR; - } - - return REG_READ(&priv->regs->status) & STAT_ACTIVE; -} - -void memscrub_isr(void *arg) -{ - struct memscrub_priv *priv = arg; - uint32_t fadr, ahbstatus, status, mask; - - /* Get hardware status */ - ahbstatus = REG_READ(&priv->regs->ahbstatus); - if ((ahbstatus & (AHBS_NE|AHBS_DONE)) == 0){ - return; - } - - /* IRQ generated by MEMSCRUB core... handle it here */ - - /* Get Failing address */ - fadr = REG_READ(&priv->regs->ahbfailing); - - /* Get Status */ - status = REG_READ(&priv->regs->status); - - /* Clear error status */ - mask = 0; - /* Clear CECNT only if we crossed the CE threshold*/ - if ((ahbstatus & AHBS_CE) == 0){ - /* Don't clear the CECNT */ - mask |= AHBS_CECNT; - } - /* Clear UECNT only if we crossed the UE threshold*/ - if ((ahbstatus & (AHBS_NE|AHBS_CE|AHBS_SBC|AHBS_SEC)) != AHBS_NE){ - /* Don't clear the UECNT */ - mask |= AHBS_UECNT; - } - REG_WRITE(&priv->regs->ahbstatus, ahbstatus & mask); - REG_WRITE(&priv->regs->status,0); - - /* Let user handle error */ - (priv->isr)(priv->isr_arg, fadr, ahbstatus, status); - - return; -} diff --git a/c/src/lib/libbsp/sparc/shared/slink/grslink.c b/c/src/lib/libbsp/sparc/shared/slink/grslink.c deleted file mode 100644 index 22a29546d0..0000000000 --- a/c/src/lib/libbsp/sparc/shared/slink/grslink.c +++ /dev/null @@ -1,661 +0,0 @@ -/* - * This file contains the RTEMS GRSLINK SLINK master driver - * - * COPYRIGHT (c) 2009. - * Cobham Gaisler AB. - * - * 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. - * - * Comments concerning current driver implementation: - * - * The SLINK specification says that there are three IO cards that are capable - * of transmitting data. But these IO cards can have the address range 0 to 3, - * and an 'For information only' comment explains that the current - * implementation has receive buffers for ".. x 4 (IO cards)". - * Because of this the driver has four queues, one for each IO card 0 - 3. - * When the addressing convention used for the IO cards is known, the number of - * queues may be lowered to three. - * - */ - -#include - -#include -#include -#include - -#ifndef GAISLER_SLINK -#define GAISLER_SLINK 0x02F -#endif - -/* Enable debug output? */ -/* #define DEBUG */ - -#ifdef DEBUG -#define DBG(x...) printk(x) -#else -#define DBG(x...) -#endif - -/* Bits and fields in SLINK transmit word */ -#define SLINK_RW (1 << 23) -#define SLINK_CHAN_POS 16 - -/* Local types */ -typedef struct { - volatile unsigned int clockscale; - volatile unsigned int ctrl; - volatile unsigned int nullwrd; - volatile unsigned int sts; - volatile unsigned int msk; - volatile unsigned int abase; - volatile unsigned int bbase; - volatile unsigned int td; - volatile unsigned int rd; -} SLINK_regs; - -typedef struct { - char readstat; /* Status of READ operation */ - char seqstat; /* Status of SEQUENCE operation */ - unsigned char scnt; /* Number of SEQUENCE words transferred */ -} SLINK_status; - -typedef struct { - int size; - unsigned int *buf; - unsigned int *first; - unsigned int *last; - unsigned int *max; - int full; -} SLINK_queue; - -typedef struct { - SLINK_regs *reg; /* Pointer to core registers */ - SLINK_status *status; /* Driver status information */ - void (*slink_irq_handler)(int); /* Handler for INTERRUPT */ - void (*slink_seq_change)(int); /* Callback on SEQUENCE change */ - int rword; /* Placeholder for READ response */ - rtems_id read_sem; /* Semaphore for blocking SLINK_read */ - SLINK_queue *queues; /* Receive queues */ -#ifdef SLINK_COLLECT_STATISTICS - SLINK_stats *stats; /* Core statistics, optional */ -#endif -} SLINK_cfg; - - -static SLINK_cfg *cfg = NULL; - -/**** SLINK driver queues for unsolicited and INTERRUPT requests ****/ - -/* Function: SLINK_createqueues - * Arguments: size: Number of elements in each queue - * Returns: 0 on success, -1 on failure - * Description: Creates SLINK_NUMQUEUES queues, one for each IO card - * that can send data. The pointers to the queues is saved in the driver - * config structure. - */ -static int SLINK_createqueues(int size) -{ - SLINK_queue *q; - int i, j; - - if ((q = malloc(SLINK_NUMQUEUES*sizeof(SLINK_queue))) == NULL) - goto slink_qiniterr1; - - for (i = 0; i < SLINK_NUMQUEUES; i++) { - q[i].size = size; - if ((q[i].buf = malloc(size*sizeof(int))) == NULL) - goto slink_qiniterr2; - q[i].first = q[i].last = q[i].buf; - q[i].max = q[i].buf + (size-1); - q[i].full = 0; - } - - cfg->queues = q; - - return 0; - - slink_qiniterr2: - for (j = 0; j < i; j++) - free(q[i].buf); - free(q); - slink_qiniterr1: - return -1; -} - -/* - * Function: SLINK_destroyqueues - * Arguments: None - * Returns: Nothing - * Description: Frees the memory occupied by the queues in cfg->queues - */ -/* - static void SLINK_destroyqueues(void) - { - int i; - - for(i = 0; i < SLINK_NUMQUEUES; i++) - free(cfg->queues[i].buf); - - free(cfg->queues); -} -*/ - -/* - * Function: SLINK_enqueue - * Arguments: Received SLINK word - * Returns: Nothing - * Description: - */ -static void SLINK_enqueue(unsigned int slink_wrd) -{ - SLINK_queue *ioq = cfg->queues + SLINK_WRD_CARDNUM(slink_wrd); - - if (!ioq->full && SLINK_WRD_CARDNUM(slink_wrd) < SLINK_NUMQUEUES) { - *ioq->last = slink_wrd; - ioq->last = (ioq->last >= ioq->max) ? ioq->buf : ioq->last+1; - ioq->full = ioq->last == ioq->first; - return; - } -#ifdef SLINK_COLLECT_STATISTICS - cfg->stats->lostwords++; -#endif -} - -/**** SLINK driver helper functions ****/ - -/* - * Function: SLINK_getaddr - * Arguments: amba_conf - * base: assigned to base of core registers - * irq: assigned to core irq lines - * Returns: Base address and IRQ via arguments, 0 if core is found, else -1 - * Description: See above. - */ -static int SLINK_getaddr(int *base, int *irq) -{ - struct ambapp_apb_info c; - - if (ambapp_find_apbslv(&ambapp_plb,VENDOR_GAISLER,GAISLER_SLINK,&c) == 1) { - *base = c.start; - *irq = c.irq; - return 0; - } - return -1; -} - -/* Function: SLINK_calcscaler - * Arguments: sysfreq: System frequency in Hz - * Returns: Clock scaler register value - * Description: Calculates value for SLINK clock scaler register to attain - * a SLINK bus frequency as close to 6 MHz as possible. Please see the IP core - * documentation for a description of how clock scaling is implemented. - */ -static int SLINK_calcscaler(int sysfreq) -{ - int fact = sysfreq / SLINK_FREQ_HZ; - return ((fact/2-1) << 16) | (fact % 2 ? fact/2 : fact/2-1); -} - - -/* - * Function: SLINK_getsysfreq - * Arguments: None - * Returns: System frequency in Hz, or 0 if system timer is not found. - * Description: Looks at the timer to determine system frequency. Makes use - * of AMBA Plug'n'Play. - */ -static int SLINK_getsysfreq(void) -{ - struct ambapp_apb_info t; - struct gptimer_regs *tregs; - - if (ambapp_find_apbslv(&ambapp_plb,VENDOR_GAISLER,GAISLER_GPTIMER,&t)==1) { - tregs = (struct gptimer_regs *)t.start; - DBG("SLINK_getsysfreq returning %d\n", - (tregs->scaler_reload+1)*1000*1000); - return (tregs->scaler_reload+1)*1000*1000; - } - return 0; -} - -/* - * Function: SLINK_interrupt_handler - * Arguments: v: not used - * Returns: Nothing - * Description: Interrupt handles checks RNE, SEQUENCE and error status - * bits. Reads word from receive queue and distinguishes between INTERRUPT, - * READ responses and SLAVE-WORD-SEND. When an INTERRUPT transfer is detected - * the handler calls the user specified slink_irq_handler with the received - * word. READ responses are saved and given to SLINK_read via a private - * variable. SLAVE-WORD-SEND transfers are placed in the IO card's receive - * queue. - */ -static rtems_isr SLINK_interrupt_handler(rtems_vector_number v) -{ - unsigned int sts; - unsigned int wrd; - - /* Read all words from Receive queue */ - while ((sts = cfg->reg->sts) & SLINK_S_RNE) { - - /* Read first word in receive queue */ - wrd = cfg->reg->rd; - - /* Check channel value to determine action */ - switch (SLINK_WRD_CHAN(wrd)) { - case 0: /* Interrupt */ - cfg->slink_irq_handler(wrd); -#ifdef SLINK_COLLECT_STATISTICS - cfg->stats->interrupts++; -#endif - break; - case 3: /* Read response, if no active READ, fall-through */ - if (cfg->status->readstat == SLINK_ACTIVE) { - rtems_semaphore_release(cfg->read_sem); - cfg->status->readstat = SLINK_COMPLETED; - cfg->rword = wrd; - break; - } - default: /* Unsolicited request */ - SLINK_enqueue(wrd); - break; - } - } - - /* Check sequence operation */ - if (sts & SLINK_S_SC) { - /* SEQUENCE completed */ - cfg->status->seqstat = SLINK_COMPLETED; - if (cfg->slink_seq_change) - cfg->slink_seq_change(SLINK_COMPLETED); -#ifdef SLINK_COLLECT_STATISTICS - cfg->stats->seqcomp++; -#endif - } else if (sts & SLINK_S_SA) { - /* SEQUENCE aborted */ - cfg->status->seqstat = SLINK_ABORTED; - cfg->status->scnt = (sts >> SLINK_S_SI_POS); - if (cfg->slink_seq_change) - cfg->slink_seq_change(SLINK_ABORTED); - } - - /* Check error conditions */ - if (sts & SLINK_S_PERR) { - /* - Parity error detected, set seqstat if there is an ongoing - sequence so that the calling application can decide if the - sequence should be aborted - */ - if (cfg->status->seqstat == SLINK_ACTIVE) { - cfg->status->seqstat = SLINK_PARERR; - if (cfg->slink_seq_change) - cfg->slink_seq_change(SLINK_PARERR); - } - /* Abort READ operation */ - if (cfg->status->readstat == SLINK_ACTIVE) { - cfg->status->readstat = SLINK_PARERR; - rtems_semaphore_release(cfg->read_sem); - } -#ifdef SLINK_COLLECT_STATISTICS - cfg->stats->parerr++; -#endif - } - if (sts & SLINK_S_AERR) { - /* AMBA error response, sequence aborted */ - cfg->status->seqstat = SLINK_AMBAERR; - cfg->status->scnt = sts >> SLINK_S_SI_POS; - if (cfg->slink_seq_change) - cfg->slink_seq_change(SLINK_AMBAERR); - } - if (sts & SLINK_S_ROV) { - /* Receive overflow, abort any ongoing READ */ - if (cfg->status->readstat == SLINK_ACTIVE) { - cfg->status->readstat = SLINK_ROV; - rtems_semaphore_release(cfg->read_sem); - } -#ifdef SLINK_COLLECT_STATISICS - cfg->status->recov++; -#endif - } - - /* Clear processed bits */ - cfg->reg->sts = sts; -} - -/**** SLINK driver interface starts here ****/ - -/* Function: SLINK_init - * Arguments: nullwrd: NULL word - * parity: Even (0) or Odd (1) parity - * interrupt_trans_handler: Function that handles interrupt requests - * sequence_callback: Callback on SEQUENCE status changes - * qsize: Size of each receive queue - * Returns: 0 on success, -1 on failure - * Description: Initializes the SLINK core - */ -int SLINK_init(unsigned int nullwrd, int parity, int qsize, - void (*interrupt_trans_handler)(int), - void (*sequence_callback)(int)) -{ - int base; - int irq; - rtems_status_code st; - - /* Allocate private config structure */ - if (cfg == NULL && (cfg = malloc(sizeof(SLINK_cfg))) == NULL) { - DBG("SLINK_init: Could not allocate cfg structure\n"); - goto slink_initerr1; - } - - /* Create simple binary semaphore for blocking SLINK_read */ - st = rtems_semaphore_create(rtems_build_name('S', 'L', 'R', '0'), 0, - (RTEMS_FIFO|RTEMS_SIMPLE_BINARY_SEMAPHORE| - RTEMS_NO_INHERIT_PRIORITY|RTEMS_LOCAL| - RTEMS_NO_PRIORITY_CEILING), 0, - &cfg->read_sem); - if (st != RTEMS_SUCCESSFUL) { - DBG("SLINK_init: Could not create semaphore\n"); - goto slink_initerr1; - } - - /* Initialize pointer to SLINK core registers and get IRQ line */ - if (SLINK_getaddr(&base, &irq) == -1) { - DBG("SLINK_init: Could not find core\n"); - goto slink_initerr2; - } - cfg->reg = (SLINK_regs*)base; - - /* Allocate status structure and initialize members */ - if ((cfg->status = calloc(1, sizeof(SLINK_status))) == NULL) { - DBG("SLINK_init: Could not allocate status structure\n"); - goto slink_initerr2; - } - cfg->status->seqstat = SLINK_COMPLETED; - cfg->status->readstat = SLINK_COMPLETED; - -#ifdef SLINK_COLLECT_STATISTICS - /* Allocate statistics structure and initialize members */ - if ((cfg->stats = calloc(1, sizeof(SLINK_stats))) == NULL) { - DBG("SLINK_init: Could not allocate statistics structure\n"); - goto slink_initerr3; - } -#endif - - /* Allocate and initialize queues */ - if (SLINK_createqueues(qsize) == -1) { - DBG("SLINK_init: Could not create queues\n"); - goto slink_initerr3; - } - - /* Configure core registers */ - cfg->reg->clockscale = SLINK_calcscaler(SLINK_getsysfreq()); - cfg->reg->ctrl = parity ? SLINK_C_PAR : 0; - cfg->reg->nullwrd = nullwrd; - cfg->reg->msk = (SLINK_M_PERRE | SLINK_M_AERRE | SLINK_M_ROVE | - SLINK_M_RNEE | SLINK_M_SAE | SLINK_M_SCE); - - /* Set-up INTERRUPT transfer handling */ - cfg->slink_irq_handler = interrupt_trans_handler; - - /* Save SEQUENCE callback */ - cfg->slink_seq_change = sequence_callback; - - /* Set-up IRQ handling */ - set_vector(SLINK_interrupt_handler,irq+0x10,2); - - return 0; - - slink_initerr3: - free(cfg->status); - slink_initerr2: - free(cfg); - slink_initerr1: - return -1; -} - -/* Function: SLINK_start - * Description: Enables the core - */ -void SLINK_start(void) -{ - if (cfg != NULL) - cfg->reg->ctrl |= SLINK_C_SLE; -} - -/* Function: SLINK_stop - * Description: Disables the core - */ -void SLINK_stop(void) -{ - if (cfg != NULL) - cfg->reg->ctrl &= ~SLINK_C_SLE; -} - -/* - * Function: SLINK_read - * Arguments: data: Payload of data word - * channel: - - * reply: Reply from IO card - * Returns: 0 on success - * -(SLINK_PARERR, SLINK_ROV) on error or -SLINK_QFULL if transmit queue - * is full and software should try again. - * Description: Reads one word and returns the response in *reply unless there - * is an error. This function blocks until the READ operation is - * completed or aborted. - */ -int SLINK_read(int data, int channel, int *reply) -{ - DBG("SLINK_read: called.."); - - if (cfg->reg->sts & SLINK_S_TNF) { - cfg->status->readstat = SLINK_ACTIVE; - cfg->reg->td = SLINK_RW | channel << SLINK_CHAN_POS | data; - } else { - DBG("queue FULL\n"); - return -SLINK_QFULL; /* Transmit queue full */ - } - - /* Block until the operation has completed or has been aborted */ - rtems_semaphore_obtain(cfg->read_sem, RTEMS_WAIT, RTEMS_NO_TIMEOUT); - - if (cfg->status->readstat == SLINK_COMPLETED) { - *reply = cfg->rword; -#ifdef SLINK_COLLECT_STATISTICS - cfg->stats->reads++; -#endif - DBG("returning 0\n"); - return 0; - } else { - DBG("returning error code\n"); - return -cfg->status->readstat; - } -} - -/* - * Function: SLINK_write - * Arguments: data: Payload of SLINK data word - * channel: Channel value (bits 22 downto 16) of receive - * register word - * Returns: 0 if command was placed in transmit queue - * -SLINK_QFULL if transmit queue was full (software should retry) - * Description: See above. - */ -int SLINK_write(int data, int channel) -{ - if (cfg->reg->sts & SLINK_S_TNF) { - cfg->reg->td = channel << SLINK_CHAN_POS | data; -#ifdef SLINK_COLLECT_STATISTICS - cfg->stats->writes++; -#endif - return 0; - } - - return -SLINK_QFULL; -} - -/* - * Function: SLINK_sequence - * Arguments: a: Array containing sequence commands - * b: Array where SEQUENCE responses will be stored - * n: Number of commands in a array - * channel: Sequence Channel Number - * reconly: Set to 1 if the SEQUENCE operation is receive only - * Returns: 0 if SEQUENCE could be started (SUCCESS) - * -1 if SEQUNCE was not started due to ongoing SEQUENCE - */ -int SLINK_seqstart(int *a, int *b, int n, int channel, int reconly) -{ - /* Only start a new SEQUENCE of the former SEQUENCE has completed */ - if (cfg->status->seqstat == SLINK_ACTIVE || - cfg->status->seqstat == SLINK_PARERR) - return -1; - - /* Tell core about arrays */ - cfg->reg->abase = (int)a; - cfg->reg->bbase = (int)b; - - /* As far as software is concerned the sequence is now active */ - cfg->status->seqstat = SLINK_ACTIVE; - - /* Enable SEQUENCE operation with SCN = channel and SLEN = n-1 */ - if (reconly == 1) { - cfg->reg->ctrl = (((n-1) << SLINK_C_SLEN_POS) | SLINK_C_SRO | - (channel << SLINK_C_SCN_POS) | - SLINK_C_SE | (cfg->reg->ctrl & 0xC000000F)); - } else { - cfg->reg->ctrl = (((n-1) << SLINK_C_SLEN_POS) | - (channel << SLINK_C_SCN_POS) | - SLINK_C_SE | (cfg->reg->ctrl & 0xC000000F)); - } - -#ifdef SLINK_COLLECT_STATISTICS - cfg->stats->sequences++; -#endif - - return 0; -} - - -/* Function: SLINK_seqabort - * Description: This function aborts an ongoing SEQUENCE. Software can tell - * when the SEQUENCE is aborted by polling SLINK_seqstat(). - */ -void SLINK_seqabort(void) -{ - cfg->reg->ctrl = cfg->reg->ctrl | SLINK_C_AS; -} - - -/* - * Function: SLINK_seqstatus - * Returns: The current or status of the SEQUENCE operation: - * SLINK_COMPLETED, SLINK_ACTIVE, SLINK_PARERR, SLINK_AMBAERR, - * SLINK_ABORTED (these are defined in bsp/grslink.h) - * Description: Meaning of returned values: - * SLINK_ABORTED: Aborted before all operations completed. - * SLINK_ACTIVE: The core is busy processing the SEQUENCE - * SLINK_AMBAERR: The last SEQUENCE was aborted by an AMBA ERROR - * SLINK_COMPLETED: All words were transferred in the last SEQUENCE - * SLINK_PARERR: Parity error detected. Software may want to abort - * - * If the SEQUENCE was aborted SLINK_seqwrds() can be used to - * determine the number of completed operations. - */ -int SLINK_seqstatus(void) -{ - return cfg->status->seqstat; -} - -/* - * Function: SLINK_seqwrds - * Returns: -1 for ongoing sequence - * 0 if all words were transferred in the last sequence - * number of words if the last SEQUENCE did not complete - * (SLINK_AMBAERR or SLINK_ABORTED is reported ny SLINK_seqstatus()) - */ -int SLINK_seqwrds(void) -{ - switch (cfg->status->seqstat) { - case SLINK_COMPLETED: return 0; - case SLINK_ACTIVE | SLINK_PARERR: return -1; - default: return cfg->status->scnt; - } -} - -/* - * Function: SLINK_hwstatus - * Returns: The SLINK core's status register. The register values can be - * interpreted with the help of macros defined in bsp/grslink.h. - */ -int SLINK_hwstatus(void) -{ - return cfg->reg->sts; -} - -/* - * Function: SLINK_queuestatus - * Arguments: iocard: Queue which to check status for - * Returns: Number of elements in queue or -1 on non-existent queue - * Description: SLINK_queuestatus(queue) returns the number of elements in - * queue 'iocard' - */ -int SLINK_queuestatus(int iocard) -{ - unsigned int first, last; - SLINK_queue *ioq; - - if (iocard >= SLINK_NUMQUEUES) - return -1; - - ioq = cfg->queues + iocard; - - if (ioq->full) - return ioq->size; - if (ioq->first == ioq->last) - return 0; - - first = ((unsigned int)ioq->first)/sizeof(unsigned int); - last = ((unsigned int)ioq->last)/sizeof(unsigned int); - - return first < last ? last - first : ioq->size - first + last; -} - -/* - * Function: SLINK_dequeue - * Arguments: iocard: IO card number - * elem: First element in IO card queue - * Returns: 0 on success or -1 on empty or non-existent queue - * Description: - */ -int SLINK_dequeue(int iocard, int *elem) -{ - if (iocard >= SLINK_NUMQUEUES) - return -1; - - SLINK_queue *ioq = cfg->queues + iocard; - - if (ioq->last != ioq->first || ioq->full) { - *elem = *ioq->first; - ioq->first = (ioq->first >= ioq->max) ? ioq->buf : ioq->first+1; - ioq->full = 0; - return 0; - } - return -1; -} - -/* - * Function: SLINK_statistics - * Returns: If the core has statistics colletion enabled this function returns - * a pointer to a struct containing statistics information, otherwise NULL. - */ -SLINK_stats *SLINK_statistics(void) -{ -#ifdef SLINK_COLLECT_STATISTICS - return cfg->stats; -#else - return NULL; -#endif -} diff --git a/c/src/lib/libbsp/sparc/shared/spi/spictrl.c b/c/src/lib/libbsp/sparc/shared/spi/spictrl.c deleted file mode 100644 index 2d639882b2..0000000000 --- a/c/src/lib/libbsp/sparc/shared/spi/spictrl.c +++ /dev/null @@ -1,1017 +0,0 @@ -/* - * SPICTRL SPI driver implmenetation - * - * COPYRIGHT (c) 2009. - * Cobham Gaisler AB. - * - * 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 -#include - -#include - -/*#define DEBUG 1*/ - -#ifdef DEBUG -#define DBG(x...) printk(x) -#define STATIC -#else -#define DBG(x...) -#define STATIC static -#endif - -/*** CAPABILITY REGISTER 0x00 ***/ -#define SPICTRL_CAP_SSSZ_BIT 24 -#define SPICTRL_CAP_AMODE_BIT 18 -#define SPICTRL_CAP_ASELA_BIT 17 -#define SPICTRL_CAP_SSEN_BIT 16 -#define SPICTRL_CAP_FDEPTH_BIT 8 -#define SPICTRL_CAP_REV_BIT 0 - -#define SPICTRL_CAP_SSSZ (0xff << SPICTRL_CAP_SSSZ_BIT) -#define SPICTRL_CAP_AMODE (1<minor_drv, dev->parent->dev->name); - - priv = dev->priv = malloc(sizeof(struct spictrl_priv)); - if ( !priv ) - return DRVMGR_NOMEM; - memset(priv, 0, sizeof(*priv)); - priv->dev = dev; - - /* This core will not find other cores, so we wait for init2() */ - - return DRVMGR_OK; -} - -int spictrl_init3(struct drvmgr_dev *dev) -{ - struct spictrl_priv *priv; - char prefix[32]; - char devName[32]; - int rc; - - priv = (struct spictrl_priv *)dev->priv; - - /* Do initialization */ - - /* Initialize i2c library */ - rc = rtems_libi2c_initialize(); - if (rc != 0) { - DBG("SPICTRL: rtems_libi2c_initialize failed, exiting...\n"); - free(dev->priv); - dev->priv = NULL; - return DRVMGR_FAIL; - } - - /* I/O system registered and initialized - * Now we take care of device initialization. - */ - - /* Get frequency */ - if ( drvmgr_freq_get(dev, DEV_APB_SLV, &priv->core_freq_hz) ) { - return DRVMGR_FAIL; - } - - if ( spictrl_device_init(priv) ) { - free(dev->priv); - dev->priv = NULL; - return DRVMGR_FAIL; - } - - /* Get Filesystem name prefix */ - prefix[0] = '\0'; - if ( drvmgr_get_dev_prefix(dev, prefix) ) { - /* Failed to get prefix, make sure of a unique FS name - * by using the driver minor. - */ - sprintf(devName, "/dev/spi%d", dev->minor_drv+1); - } else { - /* Got special prefix, this means we have a bus prefix - * And we should use our "bus minor" - */ - sprintf(devName, "/dev/%sspi%d", prefix, dev->minor_bus+1); - } - - /* Register Bus for this Device */ - rc = rtems_libi2c_register_bus(devName, &priv->i2clib_desc); - if (rc < 0) { - DBG("SPICTRL: rtems_libi2c_register_bus(%s) failed\n", devName); - free(dev->priv); - dev->priv = NULL; - return DRVMGR_FAIL; - } - priv->minor = rc; - - return DRVMGR_OK; -} - -/******************* Driver Implementation ***********************/ - -STATIC rtems_status_code spictrl_libi2c_send_addr(rtems_libi2c_bus_t *bushdl, - uint32_t addr, int rw); - -/* Set as high frequency of SCK as possible but not higher than - * requested frequency (freq). - */ -static int spictrl_set_freq(struct spictrl_priv *priv, unsigned int freq) -{ - unsigned int core_freq_hz = priv->core_freq_hz; - unsigned int lowest_freq_possible; - unsigned int div, div16, pm, fact; - - /* Lowest possible when DIV16 is set and PM is 0xf */ - lowest_freq_possible = core_freq_hz / (16 * 4 * (0xf + 1)); - - if ( freq < lowest_freq_possible ) { - DBG("SPICTRL: TOO LOW FREQ %u, CORE FREQ %u, LOWEST FREQ %u\n", - freq, core_freq_hz, lowest_freq_possible); - return -1; - } - - div = ((core_freq_hz / 2) + (freq-1)) / freq; - DBG("SPICTRL: DIV=%d, FREQ=%d\n", div, freq); - - /* Is DIV16 neccessary? */ - if ( div > 16 ) { - div = (div + (16 - 1)) / 16; - div16 = 1; - } else { - div16 = 0; - } - - if ( div > 0xf ) { - fact = 0; /* FACT adds an factor /2 */ - div = (div + (2 - 1)) / 2; - } else { - fact = 1; - } - - pm = div-1; - - /* Update hardware */ - priv->regs->mode = - (priv->regs->mode & ~(SPICTRL_MODE_PM|SPICTRL_MODE_DIV16|SPICTRL_MODE_FACT)) | - (pm << SPICTRL_MODE_PM_BIT) | (div16 << SPICTRL_MODE_DIV16_BIT) | - (fact << SPICTRL_MODE_FACT_BIT); - - DBG("SPICTRL: Effective bit rate %u (requested %u), PM: %x, FACT: %d, div16: %x, core_freq: %u\n", - core_freq_hz / (2 * (fact ? 1 : 2) * (div) * (div16 ? 16 : 1)), - freq, pm, fact, div16, core_freq_hz); - - return 0; -} - -/* Start Automated Periodic transfers, after this call read can be done */ -static int spictrl_start_periodic(struct spictrl_priv *priv) -{ - struct spictrl_ioctl_config *cfg = &priv->periodic_cfg; - unsigned int am_cfg; - - /* Clear the events */ - priv->regs->event = 0xffffffff; - - /* Enable core */ - priv->regs->mode |= SPICTRL_MODE_EN | SPICTRL_MODE_MS; - - /* Update hardware config from flags and period */ - priv->regs->am_period = cfg->period; - - /* Remove SPICTRL_PERIOD_FLAGS_ASEL and ACT bit and shift into posistion */ - am_cfg = (cfg->period_flags & 0x1f8) >> 1; - priv->regs->am_cfg = am_cfg; - - /* Start automated periodic transfers */ - if ( cfg->period_flags & SPICTRL_PERIOD_FLAGS_EACT ) { - /* Enable external triggering */ - priv->regs->am_cfg = am_cfg | SPICTRL_AMCFG_EACT; - } else { - /* Activate periodic transfers */ - priv->regs->am_cfg = am_cfg | SPICTRL_AMCFG_ACT; - } - - return 0; -} - -/* Stop Automated Periodic transfers */ -static void spictrl_stop_periodic(struct spictrl_priv *priv) -{ - priv->regs->am_cfg = 0; -} - -/* Return the status of the SPI controller (the event register), - * it may be needed in periodic mode to look at the Not Full bit (NF) - * in order not to hang in an infinte loop when read is called. - */ -static inline unsigned int spictrl_status(struct spictrl_priv *priv) -{ - return priv->regs->event; -} - -static int spictrl_read_periodic( - struct spictrl_priv *priv, - struct spictrl_period_io *rarg) -{ - int i, rxi, rxshift, bits_per_char, reg; - unsigned int rx_word, mask; - void *rxbuf; - - if ( rarg->options & 0x1 ) { - /* Read mask registers */ - for (i=0; i<4; i++) { - rarg->masks[i] = priv->regs->am_mask[i]; - } - } - - if ( rarg->options & 0x2 ) { - /* Read receive registers (after updating masks so that the caller can - * read current buffer without knowning of actual register mask). - */ - - /* If not started we could be hanging here forever. */ - if ( !priv->periodic_started ) - return -1; - - rxshift = priv->rxshift; - bits_per_char = priv->bits_per_char; - rx_word = 0; - - rxbuf = rarg->data; - if ( !rxbuf ) { - /* If no data pointer specified we cannot copy data... */ - return -1; - } - - /* Wait until all data is available (if started) */ - while ( (priv->regs->event & SPICTRL_EVENT_NE) == 0 ) { - ; - } - - rxi = 0; - for (i=0; i<4; i++) { - mask = rarg->masks[i]; - reg = 0; - while ( mask ) { - if ( mask & 1 ) { - /* Update Register */ - rx_word = priv->regs->am_rx[i*32 + reg] >> rxshift; - - if ( bits_per_char <= 8 ) { - *((unsigned char *)rxbuf + rxi) = rx_word; - } else if ( bits_per_char <= 16 ) { - *((unsigned short *)rxbuf + rxi) = rx_word; - } else { - *((unsigned int *)rxbuf + rxi) = rx_word; - } - rxi++; - } - - mask = mask>>1; - reg++; - } - } - } - - return 0; -} - -static int spictrl_write_periodic( - struct spictrl_priv *priv, - struct spictrl_period_io *warg) -{ - int i, txi, txshift, bits_per_char, reg; - unsigned int tx_word, mask; - void *txbuf; - - if ( warg->options & 0x2 ) { - - /* Make sure core is enabled, otherwise TX registers writes are lost */ - priv->regs->mode |= SPICTRL_MODE_EN; - - /* Update Transmit registers (before updating masks so that we do not - * transmit invalid data) - */ - - txshift = priv->txshift; - bits_per_char = priv->bits_per_char; - tx_word = 0; - - txbuf = warg->data; - if ( !txbuf ) { - /* If no data pointer specified we fill up with - * idle chars. - */ - tx_word = priv->idle_char << txshift; - } - - txi = 0; - for (i=0; i<4; i++) { - mask = warg->masks[i]; - reg = 0; - while ( mask ) { - if ( mask & 1 ) { - if ( txbuf ) { - if ( bits_per_char <= 8 ) { - tx_word = *((unsigned char *)txbuf + txi); - } else if ( bits_per_char <= 16 ) { - tx_word = *((unsigned short *)txbuf + txi); - } else { - tx_word = *((unsigned int *)txbuf + txi); - } - tx_word = tx_word << txshift; - txi++; - } - - /* Update Register */ - DBG("WRITE 0x%08x to 0x%08x\n", tx_word, &priv->regs->am_tx[i*32 + reg]); - priv->regs->am_tx[i*32 + reg] = tx_word; - } - - mask = mask>>1; - reg++; - } - } - } - - if ( warg->options & 0x1 ) { - /* Update mask registers */ - for (i=0; i<4; i++) { - DBG("WRITE 0x%08x to 0x%08x (MSK%d)\n", warg->masks[i], &priv->regs->am_mask[i], i); - priv->regs->am_mask[i] = warg->masks[i]; - } - } - - return 0; -} - -static int spictrl_read_write( - struct spictrl_priv *priv, - void *rxbuf, - void *txbuf, - int len) -{ - unsigned int tx_word, rx_word, tmp; - int txshift = priv->txshift; - int rxshift = priv->rxshift; - int txi, rxi, bits_per_char; - int length; - - /* Use IOCTL for periodic reads. The FIFO is not supported in automated - * periodic mode - */ - if ( priv->periodic_cfg.periodic_mode ) { - return -1; - } - - bits_per_char = priv->bits_per_char; - tx_word = 0; - if ( !txbuf ) { - tx_word = priv->idle_char << txshift; - } - - /* Clear the events */ - priv->regs->event = 0xffffffff; - - /* Enable core */ - priv->regs->mode |= SPICTRL_MODE_EN | SPICTRL_MODE_MS; - - length = len; - if ( bits_per_char > 8 ) { - length = length / 2; - if ( bits_per_char > 16 ) - length = length / 2; - } - DBG("SPICTRL: LENGTH = %d, Bits/Char: %d, Shift: %d, %d\n", length, bits_per_char, txshift, rxshift); - - txi=0; - rxi=0; - while ( (rxi < length) || (txi < length) ) { - /* Get transmit word */ - if ( length > txi ) { - if ( txbuf ) { - if ( bits_per_char <= 8 ) { - tx_word = *((unsigned char *)txbuf + txi); - } else if ( bits_per_char <= 16 ) { - tx_word = *((unsigned short *)txbuf + txi); - } else { - tx_word = *((unsigned int *)txbuf + txi); - } - tx_word = tx_word << txshift; - } - - /* Wait for SPICTRL to get ready for another TX char */ - while ( (priv->regs->event & SPICTRL_EVENT_NF) == 0 ) { - /* Wait for all chars to transmit */ -/* Could implement waiting for SPICTRL IRQ here */ - } - - DBG("SPICTRL: Writing 0x%x\n", tx_word); - - /* Transmit word */ - priv->regs->tx = tx_word; - txi++; - } - - /* Read */ - while ( priv->regs->event & SPICTRL_EVENT_NE ) { - /* Read to avoid overrun */ - tmp = priv->regs->rx; - DBG("SPICTRL: Read 0x%x\n", tmp); - - if ( rxbuf && (length > rxi) ) { - /* Copy word to user buffer */ - rx_word = (tmp >> rxshift); - - DBG("SPICTRL: Receiving 0x%x (0x%x, %d)\n", rx_word, tmp, rxshift); - - if ( bits_per_char <= 8 ) { - *((unsigned char *)rxbuf + rxi) = rx_word; - } else if ( bits_per_char <= 16 ) { - *((unsigned short *)rxbuf + rxi) = rx_word; - } else { - *((unsigned int *)rxbuf + rxi) = rx_word; - } - - } - rxi++; - } - } - - return len; -} - - -STATIC rtems_status_code spictrl_libi2c_init(rtems_libi2c_bus_t *bushdl) -{ - struct spictrl_priv *priv = (struct spictrl_priv *)bushdl; - - DBG("SPICTRL: spictrl_libi2c_init\n"); - - /* Disable SPICTTRL, Select Master mode */ - priv->regs->mode = SPICTRL_MODE_MS; - - /* Mask all Interrupts */ - priv->regs->mask = 0; - - /* Select no slave */ - priv->regs->slvsel = 0xffffffff; - - /* Clear all events */ - priv->regs->event = 0xffffffff; - - return 0; -} - -/* Nothing to be done in start */ -STATIC rtems_status_code spictrl_libi2c_send_start(rtems_libi2c_bus_t *bushdl) -{ - DBG("SPICTRL: spictrl_libi2c_send_start\n"); - - return 0; -} - -/* Inactivate all chip selects, indicates "End of command" */ -STATIC rtems_status_code spictrl_libi2c_send_stop(rtems_libi2c_bus_t *bushdl) -{ - struct spictrl_priv *priv = (struct spictrl_priv *)bushdl; - - priv->regs->slvsel = 0xffffffff; - - if ( priv->slvSelFunc ) { - /* unslect all */ - return priv->slvSelFunc(priv->regs, -1, 0); - } - - DBG("SPICTRL: spictrl_libi2c_send_stop\n"); - return 0; -} - -/* Select Slave address by selecting apropriate chip select */ -STATIC rtems_status_code spictrl_libi2c_send_addr(rtems_libi2c_bus_t *bushdl, - uint32_t addr, int rw) -{ - struct spictrl_priv *priv = (struct spictrl_priv *)bushdl; - - DBG("SPICTRL: spictrl_libi2c_send_addr, %d\n", addr); - - if ( priv->slvSelFunc ) { - /* Let user set spi select using for example GPIO */ - return priv->slvSelFunc(priv->regs, addr, 1); - } else if ( priv->regs->capability & SPICTRL_CAP_SSEN ) { - int slaves; - - /* Maximum number of slaves the core support */ - slaves = (priv->regs->capability & SPICTRL_CAP_SSSZ) >> SPICTRL_CAP_SSSZ_BIT; - - if ( addr > slaves ) - return -1; - - if ( (priv->regs->capability & SPICTRL_CAP_ASELA) && - (priv->periodic_cfg.period_flags & SPICTRL_PERIOD_FLAGS_ASEL) ) { - /* When automatic slave select is supported by hardware and - * enabled by configuration the SPI address is determined by - * the automatic slave select register and the "idle" slave - * select register is set by configuration. - */ - priv->regs->am_slvsel = ~(1<<(addr-1)); - priv->regs->slvsel = priv->periodic_cfg.period_slvsel; - /* Enable automatic slave select */ - priv->regs->mode |= SPICTRL_MODE_ASEL; - } else { - /* Normal mode */ - priv->regs->slvsel = ~(1<<(addr-1)); - } - } - - return 0; -} - -/* Read a number of bytes */ -STATIC int spictrl_libi2c_read_bytes(rtems_libi2c_bus_t *bushdl, - unsigned char *bytes, int nbytes) -{ - struct spictrl_priv *priv = (struct spictrl_priv *)bushdl; - int ret; - - DBG("SPICTRL: spictrl_libi2c_read_bytes %d\n", nbytes); - ret = spictrl_read_write(priv, bytes, NULL, nbytes); - if ( ret < 0 ) { - printf("SPICTRL: Error Reading\n"); - } -#ifdef DEBUG - else { - int i; - for(i=0; iregs->mode &= ~SPICTRL_MODE_EN; - - /* Change bit frequency */ - if ( spictrl_set_freq(priv, trf_mode->baudrate) ) { - /* Unable to set such a low frequency. */ - return -1; - } - - /* Set Clock Polarity, Clock Phase, Reverse mode and Word Length */ - mode = (priv->regs->mode & - ~(SPICTRL_MODE_CPOL|SPICTRL_MODE_CPHA|SPICTRL_MODE_REV|SPICTRL_MODE_LEN)); - if ( trf_mode->clock_inv ) - mode |= SPICTRL_MODE_CPOL; - if ( trf_mode->clock_phs ) - mode |= SPICTRL_MODE_CPHA; - if ( trf_mode->lsb_first == 0 ) - mode |= SPICTRL_MODE_REV; /* Set Reverse mode (MSB first) */ - - if ( (trf_mode->bits_per_char < 4) || - ((trf_mode->bits_per_char > 16) && (trf_mode->bits_per_char != 32)) ) - return -1; - if ( trf_mode->bits_per_char == 32 ) { - priv->txshift = 0; - priv->rxshift = 0; - } else { - mode |= (trf_mode->bits_per_char-1) << SPICTRL_MODE_LEN_BIT; - if ( trf_mode->lsb_first == 0 ) { - /* REV bit 1 */ - priv->txshift = 32 - trf_mode->bits_per_char; - priv->rxshift = 16; - } else { - /* REV bit 0 */ - priv->txshift = 0; - priv->rxshift = 16 - trf_mode->bits_per_char; - } - } - - priv->bits_per_char = trf_mode->bits_per_char; - priv->lsb_first = trf_mode->lsb_first; - priv->idle_char = trf_mode->idle_char; - - /* Update hardware */ - priv->regs->mode = mode; - - return 0; - } - - case RTEMS_LIBI2C_IOCTL_READ_WRITE: - { - rtems_libi2c_read_write_t *arg = buffer; - - DBG("SPICTRL: IOCTL READ/WRITE, RX: 0x%x, TX: 0x%x, len: %d\n", arg->rd_buf, arg->wr_buf, arg->byte_cnt); -#ifdef DEBUG - /* Printf out what is going to be transmitted */ - if ( arg->wr_buf ) { - unsigned char *bytes = (unsigned char *)arg->wr_buf; - int i; - for(i=0; ibyte_cnt; i+=16) { - DBG("0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x ", - bytes[0+i], bytes[1+i], bytes[2+i], bytes[3+i], bytes[4+i], bytes[5+i], bytes[6+i], bytes[7+i]); - DBG("0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x\n", - bytes[8+i], bytes[9+i], bytes[10+i], bytes[11+i], bytes[12+i], bytes[13+i], bytes[14+i], bytes[15+i]); - } - } -#endif - - ret = spictrl_read_write(priv, arg->rd_buf, (unsigned char *)arg->wr_buf, - arg->byte_cnt); -#ifdef DEBUG - /* Printf out what was read */ - if ( arg->rd_buf ) { - unsigned char *bytes = (unsigned char *)arg->rd_buf; - int i; - for(i=0; ibyte_cnt; i+=16) { - DBG("0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x ", - bytes[0+i], bytes[1+i], bytes[2+i], bytes[3+i], bytes[4+i], bytes[5+i], bytes[6+i], bytes[7+i]); - DBG("0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x\n", - bytes[8+i], bytes[9+i], bytes[10+i], bytes[11+i], bytes[12+i], bytes[13+i], bytes[14+i], bytes[15+i]); - } - } -#endif - return ret; - } - - /* Enable Periodic mode */ - case SPICTRL_IOCTL_CONFIG: - { - struct spictrl_ioctl_config *cfg; - - DBG("SPICTRL: Configuring Periodic mode\n"); - - if ( priv->periodic_started ) { - DBG("SPICTRL: Periodic mode already started, too late to configure\n"); - return -1; - } - - cfg = buffer; - if ( cfg == NULL ) { - memset(&priv->periodic_cfg, 0, sizeof(priv->periodic_cfg)); - } else { - priv->periodic_cfg = *cfg; - } - cfg = &priv->periodic_cfg; - if ( cfg->periodic_mode ) { - /* Enable Automated Periodic mode */ - priv->regs->mode |= SPICTRL_MODE_AMEN; - - /* Check that hardware has support for periodic mode */ - if ( (priv->regs->mode & SPICTRL_MODE_AMEN) == 0 ) { - priv->periodic_cfg.periodic_mode = 0; - DBG("SPICTRL: Periodic mode not supported by hardware\n"); - return -1; - } - } else { - /* Disable Periodic mode */ - priv->regs->mode &= ~SPICTRL_MODE_AMEN; - } - priv->periodic_started = 0; - - /* Set clockgap and TAC */ - priv->regs->mode = (priv->regs->mode & ~(SPICTRL_MODE_CG|SPICTRL_MODE_TAC)) | - (cfg->clock_gap << SPICTRL_MODE_CG_BIT) | - (cfg->flags & SPICTRL_MODE_TAC); - return 0; - } - case SPICTRL_IOCTL_PERIOD_START: - { - if ( !priv->periodic_cfg.periodic_mode || priv->periodic_started ) { - return -1; - } - if ( spictrl_start_periodic(priv) == 0 ) { - priv->periodic_started = 1; - return 0; - } else - return -1; - } - case SPICTRL_IOCTL_PERIOD_STOP: - { - if ( !priv->periodic_cfg.periodic_mode || !priv->periodic_started ) { - return -1; - } - spictrl_stop_periodic(priv); - priv->periodic_started = 0; - return 0; - } - case SPICTRL_IOCTL_STATUS: - { - if ( !buffer ) - return 0; - *(unsigned int *)buffer = spictrl_status(priv); - return 0; - } - - case SPICTRL_IOCTL_PERIOD_WRITE: - { - if ( !priv->periodic_cfg.periodic_mode || !buffer ) { - return -1; - } - if ( spictrl_write_periodic(priv, (struct spictrl_period_io *) - buffer) == 0 ) { - return 0; - } else - return -1; - } - - case SPICTRL_IOCTL_PERIOD_READ: - { - if ( !priv->periodic_cfg.periodic_mode || !buffer ) { - return -1; - } - if ( spictrl_read_periodic(priv, (struct spictrl_period_io *) - buffer) == 0 ) { - return 0; - } else - return -1; - } - - case SPICTRL_IOCTL_REGS: - { - /* Copy Register Base Address to user space */ - if ( !buffer ) { - return -1; - } - *(struct spictrl_regs **)buffer = priv->regs; - return 0; - } - - default: - /* Unknown IOCTL */ - return -1; - } - - return 0; -} - -STATIC rtems_libi2c_bus_ops_t spictrl_libi2c_ops = -{ - .init = spictrl_libi2c_init, - .send_start = spictrl_libi2c_send_start, - .send_stop = spictrl_libi2c_send_stop, - .send_addr = spictrl_libi2c_send_addr, - .read_bytes = spictrl_libi2c_read_bytes, - .write_bytes = spictrl_libi2c_write_bytes, - .ioctl = spictrl_libi2c_ioctl -}; - -int spictrl_device_init(struct spictrl_priv *priv) -{ - struct amba_dev_info *ambadev; - struct ambapp_core *pnpinfo; - union drvmgr_key_value *value; - - /* Get device information from AMBA PnP information */ - ambadev = (struct amba_dev_info *)priv->dev->businfo; - if ( ambadev == NULL ) { - return -1; - } - pnpinfo = &ambadev->info; - priv->irq = pnpinfo->irq; - priv->regs = (struct spictrl_regs *)pnpinfo->apb_slv->start; - priv->fdepth = (priv->regs->capability & SPICTRL_CAP_FDEPTH) >> SPICTRL_CAP_FDEPTH_BIT; - - DBG("SPCTRL: 0x%x irq %d, FIFO: %d\n", (unsigned int)priv->regs, priv->irq, priv->fdepth); - - /* Mask all Interrupts */ - priv->regs->mask = 0; - - /* Disable SPICTTRL */ - priv->regs->mode = 0; - - /* Get custom */ - value = drvmgr_dev_key_get(priv->dev, "slvSelFunc", DRVMGR_KT_POINTER); - if ( value ) { - priv->slvSelFunc = value->ptr; - } - - /* Prepare I2C layer */ - priv->i2clib_desc.ops = &spictrl_libi2c_ops; - priv->i2clib_desc.size = sizeof(spictrl_libi2c_ops); - return 0; -} diff --git a/c/src/lib/libbsp/sparc/shared/spw/grspw.c b/c/src/lib/libbsp/sparc/shared/spw/grspw.c deleted file mode 100644 index 661ec6c01d..0000000000 --- a/c/src/lib/libbsp/sparc/shared/spw/grspw.c +++ /dev/null @@ -1,2035 +0,0 @@ -/* - * This file contains the GRSPW SpaceWire Driver for LEON2 and LEON3. - * - * COPYRIGHT (c) 2006 - * Cobham Gaisler AB. - * - * 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 - -#include -#include -#include - -#define DBGSPW_IOCALLS 1 -#define DBGSPW_TX 2 -#define DBGSPW_RX 4 -#define DBGSPW_IOCTRL 1 -#define DBGSPW_DUMP 16 -#define DEBUG_SPACEWIRE_FLAGS (DBGSPW_IOCALLS | DBGSPW_TX | DBGSPW_RX ) - -/* #define DEBUG_SPACEWIRE_ONOFF */ - -#ifdef DEBUG_SPACEWIRE_ONOFF -#define SPACEWIRE_DBG(fmt, args...) do { { printk(" : %03d @ %18s()]:" fmt , __LINE__,__FUNCTION__,## args); }} while(0) -#define SPACEWIRE_DBG2(fmt) do { { printk(" : %03d @ %18s()]:" fmt , __LINE__,__FUNCTION__); }} while(0) -#define SPACEWIRE_DBGC(c,fmt, args...) do { if (DEBUG_SPACEWIRE_FLAGS & c) { printk(" : %03d @ %18s()]:" fmt , __LINE__,__FUNCTION__,## args); }} while(0) -#else -#define SPACEWIRE_DBG(fmt, args...) -#define SPACEWIRE_DBG2(fmt, args...) -#define SPACEWIRE_DBGC(c, fmt, args...) -#endif - -typedef struct { - volatile unsigned int ctrl; - volatile unsigned int status; - volatile unsigned int nodeaddr; - volatile unsigned int clkdiv; - volatile unsigned int destkey; - volatile unsigned int time; - volatile unsigned int timer; - volatile unsigned int pad; - - volatile unsigned int dma0ctrl; - volatile unsigned int dma0rxmax; - volatile unsigned int dma0txdesc; - volatile unsigned int dma0rxdesc; - - /* For GRSPW core 2 and onwards */ - volatile unsigned int dma0addr; - -} LEON3_SPACEWIRE_Regs_Map; - -typedef struct { - volatile unsigned int ctrl; - volatile unsigned int addr; -} SPACEWIRE_RXBD; - -typedef struct { - volatile unsigned int ctrl; - volatile unsigned int addr_header; - volatile unsigned int len; - volatile unsigned int addr_data; -} SPACEWIRE_TXBD; - -#define SPACEWIRE_INIT_TIMEOUT 10 -#define SPACEWIRE_BDTABLE_SIZE 0x400 -#define SPACEWIRE_TXD_SIZE 1024 -#define SPACEWIRE_TXH_SIZE 64 -#define SPACEWIRE_RXPCK_SIZE 1024 -#define SPACEWIRE_TXBUFS_NR 64 -#define SPACEWIRE_RXBUFS_NR 128 - -#define BUFMEM_PER_LINK (SPACEWIRE_TXBUFS_NR*(SPACEWIRE_TXD_SIZE+SPACEWIRE_TXH_SIZE) + SPACEWIRE_RXBUFS_NR*SPACEWIRE_RXPCK_SIZE) - -typedef struct { - /* configuration parameters */ - struct drvmgr_dev *dev; /* Driver manager device */ - char devName[32]; /* Device Name */ - LEON3_SPACEWIRE_Regs_Map *regs; - spw_config config; - - unsigned int tx_all_in_use; - unsigned int tx_sent; - unsigned int tx_cur; - unsigned int rxcur; - unsigned int rxbufcur; - unsigned int txdbufsize; - unsigned int txhbufsize; - unsigned int rxbufsize; - unsigned int txbufcnt; - unsigned int rxbufcnt; - - /* DMA Area set by user */ - unsigned int rx_dma_area; - unsigned int tx_data_dma_area; - unsigned int tx_hdr_dma_area; - unsigned int bd_dma_area; - - /* statistics */ - spw_stats stat; - - unsigned int _ptr_rxbuf0; - char *ptr_rxbuf0; - char *ptr_txdbuf0; - char *ptr_txhbuf0; - char *_ptr_bd0, *ptr_bd0; - - char *ptr_rxbuf0_remote; - char *ptr_txdbuf0_remote; - char *ptr_txhbuf0_remote; - char *ptr_bd0_remote; - - unsigned int irq; - int minor; - int core_ver; - int open; - int running; - unsigned int core_freq_khz; - unsigned int rtimeout; - - /* semaphores*/ - rtems_id txsp; - rtems_id rxsp; - - SPACEWIRE_RXBD *rx; - SPACEWIRE_TXBD *tx; - - unsigned int rx_remote; - unsigned int tx_remote; -} GRSPW_DEV; - -/* Function pointer called upon timecode receive */ -void (*grspw_timecode_callback) - (void *pDev, void *regs, int minor, unsigned int tc) = NULL; - -#ifdef GRSPW_DONT_BYPASS_CACHE -#define _SPW_READ(address) (*(volatile unsigned int *)(address)) -#define _MEM_READ8(address) (*(volatile unsigned char *)(address)) -#define _MEM_READ32(address) (*(volatile unsigned int *)(address)) -#else -static inline unsigned int _SPW_READ(volatile void *addr) { - unsigned int tmp; - __asm__ (" lda [%1]1, %0 " - : "=r"(tmp) - : "r"(addr) - ); - return tmp; -} - -static inline unsigned int _MEM_READ8(volatile void *addr) { - unsigned int tmp; - __asm__ (" lduba [%1]1, %0 " - : "=r"(tmp) - : "r"(addr) - ); - return tmp; -} - -static inline unsigned int _MEM_READ32(volatile void *addr) { - unsigned int tmp; - __asm__ (" lda [%1]1, %0 " - : "=r"(tmp) - : "r"(addr) - ); - return tmp; -} -#endif - -#define MEM_READ8(addr) _MEM_READ8((volatile void *)(addr)) -#define MEM_READ32(addr) _MEM_READ32((volatile void *)(addr)) -#define SPW_READ(addr) _SPW_READ((volatile void *)(addr)) -#define SPW_WRITE(addr,v) (*(volatile unsigned int *)addr)=v - -#define SPW_REG(c,r) (c->regs->r) -#define SPW_REG_CTRL(c) SPW_REG(c,ctrl) -#define SPW_REG_STATUS(c) SPW_REG(c,status) -#define SPW_REG_NODEADDR(c) SPW_REG(c,nodeaddr) - -#define SPW_CTRL_READ(c) SPW_READ(&SPW_REG_CTRL(c)) -#define SPW_CTRL_WRITE(c,v) SPW_WRITE(&SPW_REG_CTRL(c),v) -#define SPW_STATUS_READ(c) SPW_READ(&SPW_REG_STATUS(c)) -#define SPW_STATUS_WRITE(c,v) SPW_WRITE(&SPW_REG_STATUS(c),v) - -#define SPW_LINKSTATE(c) (((c) >> 21) & 0x7) - -#define SPACEWIRE_RXNR(c) ((c&~(SPACEWIRE_BDTABLE_SIZE-1))>>3) -#define SPACEWIRE_TXNR(c) ((c&~(SPACEWIRE_BDTABLE_SIZE-1))>>4) - -#define SPW_RXBD_LENGTH 0x1ffffff -#define SPW_RXBD_EN (1 << 25) -#define SPW_RXBD_WR (1 << 26) -#define SPW_RXBD_IE (1 << 27) - -#define SPW_RXBD_EEP (1 << 28) -#define SPW_RXBD_EHC (1 << 29) -#define SPW_RXBD_EDC (1 << 30) -#define SPW_RXBD_ETR (1 << 31) - -#define SPW_RXBD_ERROR (SPW_RXBD_EEP | \ - SPW_RXBD_ETR) - -#define SPW_RXBD_RMAPERROR (SPW_RXBD_EHC | SPW_RXBD_EDC) - -#define SPW_TXBD_LENGTH 0xffffff - -#define SPW_TXBD_EN (1 << 12) -#define SPW_TXBD_WR (1 << 13) -#define SPW_TXBD_IE (1 << 14) -#define SPW_TXBD_LE (1 << 15) -#define SPW_TXBD_HC (1 << 16) -#define SPW_TXBD_DC (1 << 17) - -#define SPW_TXBD_ERROR (SPW_TXBD_LE) - -#define SPW_CTRL_LINKDISABLED (1 << 0) -#define SPW_CTRL_LINKSTART (1 << 1) -#define SPW_CTRL_AUTOSTART (1 << 2) -#define SPW_CTRL_IE (1 << 3) -#define SPW_CTRL_TI (1 << 4) -#define SPW_CTRL_PM (1 << 5) -#define SPW_CTRL_RESET (1 << 6) -#define SPW_CTRL_TQ (1 << 8) -#define SPW_CTRL_LI (1 << 9) -#define SPW_CTRL_TT (1 << 10) -#define SPW_CTRL_TR (1 << 11) -#define SPW_CTRL_RE (1 << 16) -#define SPW_CTRL_RD (1 << 17) - -#define SPW_CTRL_RC (1 << 29) -#define SPW_CTRL_RX (1 << 30) -#define SPW_CTRL_RA (1 << 31) - -#define SPW_STATUS_TO (1 << 0) -#define SPW_STATUS_CE (1 << 1) -#define SPW_STATUS_ER (1 << 2) -#define SPW_STATUS_DE (1 << 3) -#define SPW_STATUS_PE (1 << 4) -#define SPW_STATUS_WE (1 << 6) -#define SPW_STATUS_IA (1 << 7) -#define SPW_STATUS_EE (1 << 8) - -#define SPW_DMACTRL_TXEN (1 << 0) -#define SPW_DMACTRL_RXEN (1 << 1) -#define SPW_DMACTRL_TXIE (1 << 2) -#define SPW_DMACTRL_RXIE (1 << 3) -#define SPW_DMACTRL_AI (1 << 4) -#define SPW_DMACTRL_PS (1 << 5) -#define SPW_DMACTRL_PR (1 << 6) -#define SPW_DMACTRL_TA (1 << 7) -#define SPW_DMACTRL_RA (1 << 8) -#define SPW_DMACTRL_AT (1 << 9) -#define SPW_DMACTRL_RX (1 << 10) -#define SPW_DMACTRL_RD (1 << 11) -#define SPW_DMACTRL_NS (1 << 12) - -#define SPW_PREPAREMASK_TX (SPW_DMACTRL_RXEN | SPW_DMACTRL_RXIE | SPW_DMACTRL_PS | SPW_DMACTRL_TA | SPW_DMACTRL_RD | SPW_DMACTRL_NS) -#define SPW_PREPAREMASK_RX (SPW_DMACTRL_TXEN | SPW_DMACTRL_TXIE | SPW_DMACTRL_AI | SPW_DMACTRL_PR | SPW_DMACTRL_RA) - -static int grspw_hw_init(GRSPW_DEV *pDev); -static int grspw_hw_send(GRSPW_DEV *pDev, unsigned int hlen, char *hdr, unsigned int dlen, char *data, unsigned int options); -static int grspw_hw_receive(GRSPW_DEV *pDev,char *b,int c); -static int grspw_hw_startup (GRSPW_DEV *pDev, int timeout); -static int grspw_hw_stop (GRSPW_DEV *pDev, int rx, int tx); -static void grspw_hw_wait_rx_inactive(GRSPW_DEV *pDev); -static int grspw_hw_waitlink (GRSPW_DEV *pDev, int timeout); -static void grspw_hw_reset(GRSPW_DEV *pDev); -static void grspw_hw_read_config(GRSPW_DEV *pDev); - -static void check_rx_errors(GRSPW_DEV *pDev, int ctrl); -static void grspw_rxnext(GRSPW_DEV *pDev); -static void grspw_interrupt(void *arg); -static int grspw_buffer_alloc(GRSPW_DEV *pDev); - -static rtems_device_driver grspw_initialize( - rtems_device_major_number major, - rtems_device_minor_number minor, - void * arg - ); - -static rtems_device_driver grspw_open( - rtems_device_major_number major, - rtems_device_minor_number minor, - void * arg - ); - -static rtems_device_driver grspw_close( - rtems_device_major_number major, - rtems_device_minor_number minor, - void * arg - ); - -static rtems_device_driver grspw_read( - rtems_device_major_number major, - rtems_device_minor_number minor, - void * arg - ); - -static rtems_device_driver grspw_write( - rtems_device_major_number major, - rtems_device_minor_number minor, - void * arg - ); - -static rtems_device_driver grspw_control( - rtems_device_major_number major, - rtems_device_minor_number minor, - void * arg - ); - -#define GRSPW_DRIVER_TABLE_ENTRY \ - { grspw_initialize, \ - grspw_open, \ - grspw_close, \ - grspw_read, \ - grspw_write, \ - grspw_control } - -static rtems_driver_address_table grspw_driver = GRSPW_DRIVER_TABLE_ENTRY; -static int grspw_driver_io_registered = 0; -static rtems_device_major_number grspw_driver_io_major = 0; - -/******************* Driver manager interface ***********************/ - -/* Driver prototypes */ -int grspw_register_io(rtems_device_major_number *m); -int grspw_device_init(GRSPW_DEV *pDev); - -int grspw_init2(struct drvmgr_dev *dev); -int grspw_init3(struct drvmgr_dev *dev); - -struct drvmgr_drv_ops grspw_ops = -{ - .init = {NULL, grspw_init2, grspw_init3, NULL}, - .remove = NULL, - .info = NULL -}; - -struct amba_dev_id grspw_ids[] = -{ - {VENDOR_GAISLER, GAISLER_SPW}, - {VENDOR_GAISLER, GAISLER_SPW2}, - {VENDOR_GAISLER, GAISLER_SPW2_DMA}, - {0, 0} /* Mark end of table */ -}; - -struct amba_drv_info grspw_drv_info = -{ - { - DRVMGR_OBJ_DRV, /* Driver */ - NULL, /* Next driver */ - NULL, /* Device list */ - DRIVER_AMBAPP_GAISLER_GRSPW_ID, /* Driver ID */ - "GRSPW_DRV", /* Driver Name */ - DRVMGR_BUS_TYPE_AMBAPP, /* Bus Type */ - &grspw_ops, - NULL, /* Funcs */ - 0, /* No devices yet */ - 0, - }, - &grspw_ids[0] -}; - -void grspw_register_drv (void) -{ - SPACEWIRE_DBG("Registering GRSPW driver\n"); - drvmgr_drv_register(&grspw_drv_info.general); -} - -int grspw_init2(struct drvmgr_dev *dev) -{ - GRSPW_DEV *priv; - - SPACEWIRE_DBG("GRSPW[%d] on bus %s\n", dev->minor_drv, - dev->parent->dev->name); - priv = dev->priv = malloc(sizeof(GRSPW_DEV)); - if ( !priv ) - return DRVMGR_NOMEM; - memset(priv, 0, sizeof(*priv)); - priv->dev = dev; - - /* This core will not find other cores, so we wait for init2() */ - - return DRVMGR_OK; -} - -int grspw_init3(struct drvmgr_dev *dev) -{ - GRSPW_DEV *priv; - char prefix[32]; - rtems_status_code status; - - priv = dev->priv; - - /* Do initialization */ - - if ( grspw_driver_io_registered == 0) { - /* Register the I/O driver only once for all cores */ - if ( grspw_register_io(&grspw_driver_io_major) ) { - /* Failed to register I/O driver */ - free(dev->priv); - dev->priv = NULL; - return DRVMGR_FAIL; - } - - grspw_driver_io_registered = 1; - } - - /* I/O system registered and initialized - * Now we take care of device initialization. - */ - - /* Get frequency in Hz */ - if ( drvmgr_freq_get(dev, DEV_APB_SLV, &priv->core_freq_khz) ) { - return DRVMGR_FAIL; - } - /* Convert from Hz -> kHz */ - priv->core_freq_khz = priv->core_freq_khz / 1000; - - if ( grspw_device_init(priv) ) { - return DRVMGR_FAIL; - } - - /* Get Filesystem name prefix */ - prefix[0] = '\0'; - if ( drvmgr_get_dev_prefix(dev, prefix) ) { - /* Failed to get prefix, make sure of a unique FS name - * by using the driver minor. - */ - sprintf(priv->devName, "/dev/grspw%d", dev->minor_drv); - } else { - /* Got special prefix, this means we have a bus prefix - * And we should use our "bus minor" - */ - sprintf(priv->devName, "/dev/%sgrspw%d", prefix, dev->minor_bus); - } - - /* Register Device */ - status = rtems_io_register_name(priv->devName, grspw_driver_io_major, dev->minor_drv); - if (status != RTEMS_SUCCESSFUL) { - return DRVMGR_FAIL; - } - - return DRVMGR_OK; -} - -/******************* Driver Implementation ***********************/ - -int grspw_register_io(rtems_device_major_number *m) -{ - rtems_status_code r; - - if ((r = rtems_io_register_driver(0, &grspw_driver, m)) == RTEMS_SUCCESSFUL) { - SPACEWIRE_DBG("GRSPW driver successfully registered, major: %d\n", *m); - } else { - switch(r) { - case RTEMS_TOO_MANY: - printk("GRSPW rtems_io_register_driver failed: RTEMS_TOO_MANY\n"); - return -1; - case RTEMS_INVALID_NUMBER: - printk("GRSPW rtems_io_register_driver failed: RTEMS_INVALID_NUMBER\n"); - return -1; - case RTEMS_RESOURCE_IN_USE: - printk("GRSPW rtems_io_register_driver failed: RTEMS_RESOURCE_IN_USE\n"); - return -1; - default: - printk("GRSPW rtems_io_register_driver failed\n"); - return -1; - } - } - return 0; -} - -int grspw_device_init(GRSPW_DEV *pDev) -{ - struct amba_dev_info *ambadev; - struct ambapp_core *pnpinfo; - union drvmgr_key_value *value; - - /* Get device information from AMBA PnP information */ - ambadev = (struct amba_dev_info *)pDev->dev->businfo; - if ( ambadev == NULL ) { - return -1; - } - pnpinfo = &ambadev->info; - pDev->irq = pnpinfo->irq; - pDev->regs = (LEON3_SPACEWIRE_Regs_Map *)pnpinfo->apb_slv->start; - pDev->minor = pDev->dev->minor_drv; - - /* Get SpaceWire core version */ - switch( pnpinfo->device ) { - case GAISLER_SPW: - pDev->core_ver = 1; - break; - case GAISLER_SPW2: - pDev->core_ver = 2; - break; - case GAISLER_SPW2_DMA: - pDev->core_ver = 3; - break; - default: - return -1; - } - - /* initialize the code with some resonable values, - * actual initialization is done later using ioctl(fd) - * on the opened device */ - pDev->config.rxmaxlen = SPACEWIRE_RXPCK_SIZE; - pDev->txdbufsize = SPACEWIRE_TXD_SIZE; - pDev->txhbufsize = SPACEWIRE_TXH_SIZE; - pDev->rxbufsize = SPACEWIRE_RXPCK_SIZE; - pDev->txbufcnt = SPACEWIRE_TXBUFS_NR; - pDev->rxbufcnt = SPACEWIRE_RXBUFS_NR; - - pDev->_ptr_rxbuf0 = 0; - pDev->ptr_rxbuf0 = 0; - pDev->ptr_txdbuf0 = 0; - pDev->ptr_txhbuf0 = 0; - pDev->ptr_bd0 = 0; - pDev->rx_dma_area = 0; - pDev->tx_data_dma_area = 0; - pDev->tx_hdr_dma_area = 0; - pDev->bd_dma_area = 0; - - /* Get Configuration from Bus resources (Let user override defaults) */ - - value = drvmgr_dev_key_get(pDev->dev, "txBdCnt", DRVMGR_KT_INT); - if ( value ) - pDev->txbufcnt = value->i; - - value = drvmgr_dev_key_get(pDev->dev, "rxBdCnt", DRVMGR_KT_INT); - if ( value ) - pDev->rxbufcnt = value->i; - - value = drvmgr_dev_key_get(pDev->dev, "txDataSize", DRVMGR_KT_INT); - if ( value ) - pDev->txdbufsize = value->i; - - value = drvmgr_dev_key_get(pDev->dev, "txHdrSize", DRVMGR_KT_INT); - if ( value ) - pDev->txhbufsize = value->i; - - value = drvmgr_dev_key_get(pDev->dev, "rxPktSize", DRVMGR_KT_INT); - if ( value ) { - pDev->rxbufsize = value->i; - pDev->config.rxmaxlen = pDev->rxbufsize; - } - - value = drvmgr_dev_key_get(pDev->dev, "rxDmaArea", DRVMGR_KT_INT); - if ( value ) - pDev->rx_dma_area = value->i; - - value = drvmgr_dev_key_get(pDev->dev, "txDataDmaArea", DRVMGR_KT_INT); - if ( value ) - pDev->tx_data_dma_area = value->i; - - value = drvmgr_dev_key_get(pDev->dev, "txHdrDmaArea", DRVMGR_KT_INT); - if ( value ) - pDev->tx_hdr_dma_area = value->i; - - value = drvmgr_dev_key_get(pDev->dev, "bdDmaArea", DRVMGR_KT_INT); - if ( value ) - pDev->bd_dma_area = value->i; - - if (grspw_buffer_alloc(pDev)) - return RTEMS_NO_MEMORY; - - /* Create semaphores */ - rtems_semaphore_create( - rtems_build_name('T', 'x', 'S', '0' + pDev->minor), - 0, - RTEMS_FIFO | RTEMS_SIMPLE_BINARY_SEMAPHORE | RTEMS_NO_INHERIT_PRIORITY | \ - RTEMS_NO_PRIORITY_CEILING, - 0, - &(pDev->txsp)); - - rtems_semaphore_create( - rtems_build_name('R', 'x', 'S', '0' + pDev->minor), - 0, - RTEMS_FIFO | RTEMS_SIMPLE_BINARY_SEMAPHORE | RTEMS_NO_INHERIT_PRIORITY | \ - RTEMS_NO_PRIORITY_CEILING, - 0, - &(pDev->rxsp)); - - grspw_hw_init(pDev); - - return 0; -} - -/* Get a value at least 6.4us in number of clock cycles */ -static unsigned int grspw_calc_timer64(int freq_khz){ - unsigned int timer64 = (freq_khz*64+9999)/10000; - return timer64 & 0xfff; -} - -/* Get a value at least 850ns in number of clock cycles - 3 */ -static unsigned int grspw_calc_disconnect(int freq_khz){ - unsigned int disconnect = ((freq_khz*85+99999)/100000) - 3; - return disconnect & 0x3ff; -} - -static int grspw_buffer_alloc(GRSPW_DEV *pDev) -{ - /* RX DMA AREA */ - if (pDev->rx_dma_area & 1) { - /* Address given in remote address */ - pDev->ptr_rxbuf0_remote = (char *)(pDev->rx_dma_area & ~1); - drvmgr_translate_check( - pDev->dev, - DMAMEM_TO_CPU, - (void *)pDev->ptr_rxbuf0_remote, - (void **)&pDev->ptr_rxbuf0, - pDev->rxbufsize * pDev->rxbufcnt); - - } else { - if (pDev->rx_dma_area == 0) { - if (pDev->_ptr_rxbuf0) - free((void *)pDev->_ptr_rxbuf0); - pDev->_ptr_rxbuf0 = (unsigned int) malloc(pDev->rxbufsize * pDev->rxbufcnt+4); - pDev->ptr_rxbuf0 = (char *)((pDev->_ptr_rxbuf0+7)&~7); - if ( !pDev->ptr_rxbuf0 ) - return 1; - } else { - pDev->ptr_rxbuf0 = (char *)pDev->rx_dma_area; - } - drvmgr_translate_check( - pDev->dev, - CPUMEM_TO_DMA, - (void *)pDev->ptr_rxbuf0, - (void **)&pDev->ptr_rxbuf0_remote, - pDev->rxbufsize * pDev->rxbufcnt); - } - - /* TX-DATA DMA AREA */ - if (pDev->tx_data_dma_area & 1) { - /* Address given in remote address */ - pDev->ptr_txdbuf0_remote = (char*)(pDev->tx_data_dma_area & ~1); - drvmgr_translate_check( - pDev->dev, - DMAMEM_TO_CPU, - (void *)pDev->ptr_txdbuf0_remote, - (void **)&pDev->ptr_txdbuf0, - pDev->txdbufsize * pDev->txbufcnt); - } else { - if (pDev->tx_data_dma_area == 0) { - if (pDev->ptr_txdbuf0) - free(pDev->ptr_txdbuf0); - pDev->ptr_txdbuf0 = (char *) malloc(pDev->txdbufsize * pDev->txbufcnt); - if (!pDev->ptr_txdbuf0) - return 1; - } else { - pDev->ptr_txdbuf0 = (char *)pDev->tx_data_dma_area; - } - drvmgr_translate_check( - pDev->dev, - CPUMEM_TO_DMA, - (void *)pDev->ptr_txdbuf0, - (void **)&pDev->ptr_txdbuf0_remote, - pDev->txdbufsize * pDev->txbufcnt); - } - - /* TX-HEADER DMA AREA */ - if (pDev->tx_hdr_dma_area & 1) { - /* Address given in remote address */ - pDev->ptr_txhbuf0_remote = (char *)(pDev->tx_hdr_dma_area & ~1); - drvmgr_translate_check( - pDev->dev, - DMAMEM_TO_CPU, - (void *)pDev->ptr_txhbuf0_remote, - (void **)&pDev->ptr_txhbuf0, - pDev->txhbufsize * pDev->txbufcnt); - } else { - if (pDev->tx_hdr_dma_area == 0) { - if (pDev->ptr_txhbuf0) - free(pDev->ptr_txhbuf0); - pDev->ptr_txhbuf0 = (char *) malloc(pDev->txhbufsize * pDev->txbufcnt); - if (!pDev->ptr_txhbuf0) - return 1; - } else { - pDev->ptr_txhbuf0 = (char *)pDev->tx_hdr_dma_area; - } - drvmgr_translate_check( - pDev->dev, - CPUMEM_TO_DMA, - (void *)pDev->ptr_txhbuf0, - (void **)&pDev->ptr_txhbuf0_remote, - pDev->txhbufsize * pDev->txbufcnt); - } - - /* DMA DESCRIPTOR TABLES */ - if (pDev->bd_dma_area & 1) { - /* Address given in remote address */ - pDev->ptr_bd0_remote = (char *)(pDev->bd_dma_area & ~1); - drvmgr_translate_check( - pDev->dev, - DMAMEM_TO_CPU, - (void *)pDev->ptr_bd0_remote, - (void **)&pDev->ptr_bd0, - 2 * SPACEWIRE_BDTABLE_SIZE); - } else { - if (pDev->bd_dma_area == 0) { - if (pDev->_ptr_bd0) - free(pDev->_ptr_bd0); - pDev->_ptr_bd0 = - rtems_heap_allocate_aligned_with_boundary( - SPACEWIRE_BDTABLE_SIZE*2, 1024, 0); - if (!pDev->_ptr_bd0) - return 1; - pDev->ptr_bd0 = (char *)pDev->_ptr_bd0; - } else { - pDev->ptr_bd0 = (char *)pDev->bd_dma_area; - } - drvmgr_translate_check( - pDev->dev, - CPUMEM_TO_DMA, - (void *)pDev->ptr_bd0, - (void **)&pDev->ptr_bd0_remote, - 2 * SPACEWIRE_BDTABLE_SIZE); - } - - return 0; -} - -static void grspw_interrupt(void *arg) -{ - GRSPW_DEV *pDev = (GRSPW_DEV *)arg; - int dmactrl; - int status; - int ctrl; - unsigned int timecode; - - status = SPW_STATUS_READ(pDev); - /*SPW_STATUS_WRITE(pDev, SPW_STATUS_CE | SPW_STATUS_ER | SPW_STATUS_DE | SPW_STATUS_PE | SPW_STATUS_WE | SPW_STATUS_IA | SPW_STATUS_EE | SPW_STATUS_TO);*/ - SPW_STATUS_WRITE(pDev, status & (SPW_STATUS_CE | SPW_STATUS_ER | SPW_STATUS_DE | SPW_STATUS_PE | SPW_STATUS_WE | SPW_STATUS_IA | SPW_STATUS_EE)); - - /* Make sure to put the timecode handling first in order to get the smallest - * possible interrupt latency - */ - if ( (status & SPW_STATUS_TO) && (grspw_timecode_callback != NULL) ) { - /* Timecode received. Let custom function handle this */ - SPW_STATUS_WRITE(pDev, SPW_STATUS_TO); - timecode = SPW_READ(&pDev->regs->time); - (grspw_timecode_callback)(pDev,pDev->regs,pDev->minor,timecode); - } - - /* Clear SPW_DMACTRL_PR if set */ - dmactrl = SPW_READ(&pDev->regs->dma0ctrl); - /*SPW_WRITE(&pDev->regs->dma0ctrl, dmactrl | SPW_DMACTRL_PR);*/ - SPW_WRITE(&pDev->regs->dma0ctrl, dmactrl); - - /* If linkinterrupts are enabled check if it was a linkerror irq and then send an event to the - process set in the config */ - if (pDev->config.link_err_irq) { - if (status & (SPW_STATUS_CE | SPW_STATUS_ER | SPW_STATUS_DE | SPW_STATUS_PE | SPW_STATUS_WE)) { - rtems_event_send(pDev->config.event_id, SPW_LINKERR_EVENT); - if (pDev->config.disable_err) { - /* disable link*/ - SPW_CTRL_WRITE(pDev, (SPW_CTRL_READ(pDev) & 0xFFFFFFFC) | SPW_CTRL_LINKDISABLED); - pDev->config.linkdisabled = 1; - pDev->config.linkstart = 0; - pDev->running = 0; - } - } - } - if (status & SPW_STATUS_CE) { - pDev->stat.credit_err++; - } - if (status & SPW_STATUS_ER) { - pDev->stat.escape_err++; - } - if (status & SPW_STATUS_DE) { - pDev->stat.disconnect_err++; - } - if (status & SPW_STATUS_PE) { - pDev->stat.parity_err++; - } - if (status & SPW_STATUS_WE) { - pDev->stat.write_sync_err++; - } - if (status & SPW_STATUS_IA) { - pDev->stat.invalid_address++; - } - if (status & SPW_STATUS_EE) { - pDev->stat.early_ep++; - } - - /* Check for tx interrupts */ - while( (pDev->tx_sent != pDev->tx_cur) || pDev->tx_all_in_use) { - /* Has this descriptor been sent? */ - ctrl = SPW_READ((volatile void *)&pDev->tx[pDev->tx_sent].ctrl); - if ( ctrl & SPW_TXBD_EN ) { - break; - } - /* Yes, increment status counters & tx_sent so we can use this descriptor to send more packets with */ - pDev->stat.packets_sent++; - - rtems_semaphore_release(pDev->txsp); - - if ( ctrl & SPW_TXBD_LE ) { - pDev->stat.tx_link_err++; - } - - /* step to next descriptor */ - pDev->tx_sent = (pDev->tx_sent + 1) % pDev->txbufcnt; - pDev->tx_all_in_use = 0; /* not all of the descriptors can be in use since we just freed one. */ - } - - /* Check for rx interrupts */ - if (dmactrl & SPW_DMACTRL_PR) { - rtems_semaphore_release(pDev->rxsp); - } -} - -static rtems_device_driver grspw_initialize( - rtems_device_major_number major, - rtems_device_minor_number minor, - void *arg -) -{ - /* Initialize device-common data structures here */ - return RTEMS_SUCCESSFUL; -} - -static rtems_device_driver grspw_open( - rtems_device_major_number major, - rtems_device_minor_number minor, - void * arg - ) -{ - GRSPW_DEV *pDev; - struct drvmgr_dev *dev; - SPACEWIRE_DBGC(DBGSPW_IOCALLS, "open [%i,%i]\n", major, minor); - - if ( drvmgr_get_dev(&grspw_drv_info.general, minor, &dev) ) { - SPACEWIRE_DBG("Wrong minor %d\n", minor); - return RTEMS_INVALID_NAME; - } - pDev = (GRSPW_DEV *)dev->priv; - - if ( pDev->open ) - return RTEMS_RESOURCE_IN_USE; - - /* Mark device open */ - pDev->open = 1; - - pDev->stat.tx_link_err = 0; - pDev->stat.rx_rmap_header_crc_err = 0; - pDev->stat.rx_rmap_data_crc_err = 0; - pDev->stat.rx_eep_err = 0; - pDev->stat.rx_truncated = 0; - pDev->stat.parity_err = 0; - pDev->stat.escape_err = 0; - pDev->stat.credit_err = 0; - pDev->stat.write_sync_err = 0; - pDev->stat.disconnect_err = 0; - pDev->stat.early_ep = 0; - pDev->stat.invalid_address = 0; - pDev->stat.packets_sent = 0; - pDev->stat.packets_received = 0; - - pDev->config.rm_prot_id = 0; - pDev->config.keep_source = 0; - pDev->config.check_rmap_err = 0; - pDev->config.tx_blocking = 0; - pDev->config.tx_block_on_full = 0; - pDev->config.rx_blocking = 0; - pDev->config.disable_err = 0; - pDev->config.link_err_irq = 0; - pDev->config.event_id = 0; - pDev->config.rtimeout = 0; - - pDev->running = 0; - pDev->core_freq_khz = 0; - - /* Reset Core */ - grspw_hw_reset(pDev); - - /* Read default configuration */ - grspw_hw_read_config(pDev); - - return RTEMS_SUCCESSFUL; -} - -static rtems_device_driver grspw_close( - rtems_device_major_number major, - rtems_device_minor_number minor, - void * arg - ) -{ - GRSPW_DEV *pDev; - struct drvmgr_dev *dev; - - if ( drvmgr_get_dev(&grspw_drv_info.general, minor, &dev) ) { - return RTEMS_INVALID_NAME; - } - pDev = (GRSPW_DEV *)dev->priv; - - SPACEWIRE_DBGC(DBGSPW_IOCALLS, "close [%i,%i]\n", major, minor); - rtems_semaphore_delete(pDev->txsp); - rtems_semaphore_delete(pDev->rxsp); - - grspw_hw_stop(pDev,1,1); - - grspw_hw_reset(pDev); - - /* Mark device closed - not open */ - pDev->open = 0; - - return RTEMS_SUCCESSFUL; -} - -static rtems_device_driver grspw_read( - rtems_device_major_number major, - rtems_device_minor_number minor, - void * arg - ) -{ - rtems_libio_rw_args_t *rw_args; - unsigned int count = 0; - GRSPW_DEV *pDev; - struct drvmgr_dev *dev; - int status; - - if ( drvmgr_get_dev(&grspw_drv_info.general, minor, &dev) ) { - return RTEMS_INVALID_NAME; - } - pDev = (GRSPW_DEV *)dev->priv; - - rw_args = (rtems_libio_rw_args_t *) arg; - - /* is link up? */ - if ( !pDev->running ) { - return RTEMS_INVALID_NAME; - } - - if ((rw_args->count < 1) || (rw_args->buffer == NULL)) { - return RTEMS_INVALID_NAME; - } - - SPACEWIRE_DBGC(DBGSPW_IOCALLS, "read [%i,%i]: buf:0x%x len:%i \n", major, minor, (unsigned int)rw_args->buffer, rw_args->count); - - while ( (count = grspw_hw_receive(pDev, rw_args->buffer, rw_args->count)) == 0) { - /* wait a moment for any descriptors to get available - * - * Semaphore is signaled by interrupt handler - */ - if (pDev->config.rx_blocking) { - SPACEWIRE_DBG2("Rx blocking\n"); - if ( pDev->config.rtimeout ) { - status = rtems_semaphore_obtain(pDev->rxsp, RTEMS_WAIT, pDev->config.rtimeout); - if ( status == RTEMS_TIMEOUT ) - return RTEMS_TIMEOUT; - } else { - rtems_semaphore_obtain(pDev->rxsp, RTEMS_WAIT, RTEMS_NO_TIMEOUT); - } - } else { - SPACEWIRE_DBG2("Rx non blocking\n"); - return RTEMS_RESOURCE_IN_USE; - } - } - -#ifdef DEBUG_SPACEWIRE_ONOFF - if (DEBUG_SPACEWIRE_FLAGS & DBGSPW_DUMP) { - int k; - for (k = 0; k < count; k++){ - if (k % 16 == 0) { - printf ("\n"); - } - printf ("%.2x(%c) ", rw_args->buffer[k] & 0xff, isprint(rw_args->buffer[k] & 0xff) ? rw_args->buffer[k] & 0xff : ' '); - } - printf ("\n"); - } -#endif - - rw_args->bytes_moved = count; - return RTEMS_SUCCESSFUL; -} - -static rtems_device_driver grspw_write( - rtems_device_major_number major, - rtems_device_minor_number minor, - void * arg -) -{ - rtems_libio_rw_args_t *rw_args; - GRSPW_DEV *pDev; - struct drvmgr_dev *dev; - - if ( drvmgr_get_dev(&grspw_drv_info.general, minor, &dev) ) { - return RTEMS_INVALID_NAME; - } - pDev = (GRSPW_DEV *)dev->priv; - - rw_args = (rtems_libio_rw_args_t *) arg; - SPACEWIRE_DBGC(DBGSPW_IOCALLS, "write [%i,%i]: buf:0x%x len:%i\n", major, minor, (unsigned int)rw_args->buffer, rw_args->count); - - /* is link up? */ - if ( !pDev->running ) { - return RTEMS_INVALID_NAME; - } - - if ((rw_args->count > pDev->txdbufsize) || (rw_args->count < 1) || (rw_args->buffer == NULL)) { - return RTEMS_INVALID_NAME; - } - - while ((rw_args->bytes_moved = grspw_hw_send(pDev, 0, NULL, rw_args->count, rw_args->buffer, 0)) == 0) { - if (pDev->config.tx_block_on_full == 1) { - SPACEWIRE_DBG2("Tx Block on full \n"); - rtems_semaphore_obtain(pDev->txsp, RTEMS_WAIT, RTEMS_NO_TIMEOUT); - } else { - SPACEWIRE_DBG2("Tx non blocking return when full \n"); - return RTEMS_RESOURCE_IN_USE; - } - } - return RTEMS_SUCCESSFUL; -} - -static rtems_device_driver grspw_control( - rtems_device_major_number major, - rtems_device_minor_number minor, - void * arg - ) -{ - spw_ioctl_pkt_send *args; - spw_ioctl_packetsize *ps; - int status; - unsigned int tmp,mask,nodeaddr,nodemask; - int timeout; - rtems_device_driver ret; - rtems_libio_ioctl_args_t *ioarg = (rtems_libio_ioctl_args_t *) arg; - GRSPW_DEV *pDev; - struct drvmgr_dev *dev; - - SPACEWIRE_DBGC(DBGSPW_IOCALLS, "ctrl [%i,%i]\n", major, minor); - - if ( drvmgr_get_dev(&grspw_drv_info.general, minor, &dev) ) { - return RTEMS_INVALID_NAME; - } - pDev = (GRSPW_DEV *)dev->priv; - - if (!ioarg) - return RTEMS_INVALID_NAME; - - ioarg->ioctl_return = 0; - switch(ioarg->command) { - case SPACEWIRE_IOCTRL_SET_NODEADDR: - /*set node address*/ - SPACEWIRE_DBGC(DBGSPW_IOCTRL, "SPACEWIRE_IOCTRL_SET_NODEADDR %i\n",(unsigned int)ioarg->buffer); - if ((unsigned int)ioarg->buffer > 255) { - return RTEMS_INVALID_NAME; - } - nodeaddr = ((unsigned int)ioarg->buffer) & 0xff; - tmp = SPW_READ(&pDev->regs->nodeaddr); - tmp &= 0xffffff00; /* Remove old address */ - tmp |= nodeaddr; - SPW_WRITE(&pDev->regs->nodeaddr, tmp); - if ((SPW_READ(&pDev->regs->nodeaddr)&0xff) != nodeaddr) { - return RTEMS_IO_ERROR; - } - pDev->config.nodeaddr = nodeaddr; - break; - case SPACEWIRE_IOCTRL_SET_NODEMASK: - /*set node address*/ - SPACEWIRE_DBGC(DBGSPW_IOCTRL, "SPACEWIRE_IOCTRL_SET_NODEMASK %i\n",(unsigned int)ioarg->buffer); - if ( pDev->core_ver > 1 ){ - if ((unsigned int)ioarg->buffer > 255) { - return RTEMS_INVALID_NAME; - } - nodemask = ((unsigned int)ioarg->buffer) & 0xff; - tmp = SPW_READ(&pDev->regs->nodeaddr); - tmp &= 0xffff00ff; /* Remove old mask */ - tmp |= nodemask<<8; - SPW_WRITE(&pDev->regs->nodeaddr, tmp); - if (((SPW_READ(&pDev->regs->nodeaddr)>>8)&0xff) != nodemask) { - return RTEMS_IO_ERROR; - } - pDev->config.nodemask = nodemask; - }else{ - SPACEWIRE_DBG("SPACEWIRE_IOCTRL_SET_NODEMASK: not implemented in GRSPW1 HW\n"); - } - break; - case SPACEWIRE_IOCTRL_SET_RXBLOCK: - SPACEWIRE_DBGC(DBGSPW_IOCTRL, "SPACEWIRE_IOCTRL_SET_RXBLOCK %i \n", (unsigned int)ioarg->buffer); - if ((unsigned int)ioarg->buffer > 1) { - return RTEMS_INVALID_NAME; - } - pDev->config.rx_blocking = (unsigned int)ioarg->buffer; - break; - case SPACEWIRE_IOCTRL_SET_DESTKEY: - SPACEWIRE_DBGC(DBGSPW_IOCTRL,"SPACEWIRE_IOCTRL_SET_DESTKEY %i\n", (unsigned int)ioarg->buffer); - if (!pDev->config.is_rmap) { - return RTEMS_NOT_IMPLEMENTED; - } - if ((unsigned int)ioarg->buffer > 255) { - return RTEMS_INVALID_NAME; - } - SPW_WRITE(&pDev->regs->destkey, (unsigned int)ioarg->buffer); - if (SPW_READ(&pDev->regs->destkey) != (unsigned int)ioarg->buffer) { - return RTEMS_IO_ERROR; - } - pDev->config.destkey = (unsigned int)ioarg->buffer; - break; - case SPACEWIRE_IOCTRL_SET_CLKDIV: - SPACEWIRE_DBGC(DBGSPW_IOCTRL,"SPACEWIRE_IOCTRL_SET_CLKDIV %i\n", (unsigned int)ioarg->buffer); - if ((unsigned int)ioarg->buffer > 255) { - return RTEMS_INVALID_NAME; - } - if ( pDev->core_ver == 3 ) - break; - tmp = SPW_READ(&pDev->regs->clkdiv); - tmp &= ~0xff; /* Remove old Clockdiv Setting */ - tmp |= ((unsigned int)ioarg->buffer) & 0xff; /* add new clockdiv setting */ - SPW_WRITE(&pDev->regs->clkdiv, tmp); - if (SPW_READ(&pDev->regs->clkdiv) != tmp) { - return RTEMS_IO_ERROR; - } - pDev->config.clkdiv = tmp; - break; - case SPACEWIRE_IOCTRL_SET_CLKDIVSTART: - SPACEWIRE_DBGC(DBGSPW_IOCTRL,"SPACEWIRE_IOCTRL_SET_CLKDIVSTART %i\n", (unsigned int)ioarg->buffer); - if ((unsigned int)ioarg->buffer > 255) { - return RTEMS_INVALID_NAME; - } - if ( pDev->core_ver == 3 ) - break; - tmp = SPW_READ(&pDev->regs->clkdiv); - tmp &= ~0xff00; /* Remove old Clockdiv Start Setting */ - tmp |= (((unsigned int)ioarg->buffer) & 0xff)<<8; /* add new clockdiv start setting */ - SPW_WRITE(&pDev->regs->clkdiv, tmp); - if (SPW_READ(&pDev->regs->clkdiv) != tmp) { - return RTEMS_IO_ERROR; - } - pDev->config.clkdiv = tmp; - break; - case SPACEWIRE_IOCTRL_SET_TIMER: - SPACEWIRE_DBGC(DBGSPW_IOCTRL,"SPACEWIRE_IOCTRL_SET_TIMER %i\n", (unsigned int)ioarg->buffer); - if ( pDev->core_ver <= 1 ) { - if ((unsigned int)ioarg->buffer > 4095) { - return RTEMS_INVALID_NAME; - } - SPW_WRITE(&pDev->regs->timer, (SPW_READ(&pDev->regs->timer) & 0xFFFFF000) | ((unsigned int)ioarg->buffer & 0xFFF)); - if ((SPW_READ(&pDev->regs->timer) & 0xFFF) != (unsigned int)ioarg->buffer) { - return RTEMS_IO_ERROR; - } - pDev->config.timer = (unsigned int)ioarg->buffer; - }else{ - SPACEWIRE_DBG("SPACEWIRE_IOCTRL_SET_TIMER: removed in GRSPW2 HW\n"); - } - break; - case SPACEWIRE_IOCTRL_SET_DISCONNECT: - SPACEWIRE_DBGC(DBGSPW_IOCTRL,"SPACEWIRE_IOCTRL_SET_DISCONNECT %i\n", (unsigned int)ioarg->buffer); - if ( pDev->core_ver <= 1 ) { - if ((unsigned int)ioarg->buffer > 1023) { - return RTEMS_INVALID_NAME; - } - SPW_WRITE(&pDev->regs->timer, (SPW_READ(&pDev->regs->timer) & 0xFFC00FFF) | (((unsigned int)ioarg->buffer & 0x3FF) << 12)); - if (((SPW_READ(&pDev->regs->timer) >> 12) & 0x3FF) != (unsigned int)ioarg->buffer) { - return RTEMS_IO_ERROR; - } - pDev->config.disconnect = (unsigned int)ioarg->buffer; - }else{ - SPACEWIRE_DBG("SPACEWIRE_IOCTRL_SET_DISCONNECT: not implemented for GRSPW2\n"); - } - break; - case SPACEWIRE_IOCTRL_SET_PROMISCUOUS: - SPACEWIRE_DBGC(DBGSPW_IOCTRL,"SPACEWIRE_IOCTRL_SET_PROMISCUOUS %i \n", (unsigned int)ioarg->buffer); - if ((unsigned int)ioarg->buffer > 1) { - return RTEMS_INVALID_NAME; - } - SPW_CTRL_WRITE(pDev, SPW_CTRL_READ(pDev) | ((unsigned int)ioarg->buffer << 5)); - if (((SPW_CTRL_READ(pDev) >> 5) & 1) != (unsigned int)ioarg->buffer) { - return RTEMS_IO_ERROR; - } - pDev->config.promiscuous = (unsigned int)ioarg->buffer; - break; - case SPACEWIRE_IOCTRL_SET_RMAPEN: - SPACEWIRE_DBGC(DBGSPW_IOCTRL,"SPACEWIRE_IOCTRL_SET_RMAPEN %i \n", (unsigned int)ioarg->buffer); - if ((unsigned int)ioarg->buffer > 1) { - return RTEMS_INVALID_NAME; - } - SPW_CTRL_WRITE(pDev, (SPW_CTRL_READ(pDev) & 0xFFFEFFFF) | ((unsigned int)ioarg->buffer << 16)); - if (((SPW_CTRL_READ(pDev) >> 16) & 1) != (unsigned int)ioarg->buffer) { - return RTEMS_IO_ERROR; - } - pDev->config.rmapen = (unsigned int)ioarg->buffer; - break; - case SPACEWIRE_IOCTRL_SET_RMAPBUFDIS: - SPACEWIRE_DBGC(DBGSPW_IOCTRL,"SPACEWIRE_IOCTRL_SET_RMAPBUFDIS %i \n", (unsigned int)ioarg->buffer); - if ((unsigned int)ioarg->buffer > 1) { - return RTEMS_INVALID_NAME; - } - SPW_CTRL_WRITE(pDev, (SPW_CTRL_READ(pDev) & 0xFFFDFFFF) | ((unsigned int)ioarg->buffer << 17)); - if (((SPW_CTRL_READ(pDev) >> 17) & 1) != (unsigned int)ioarg->buffer) { - return RTEMS_IO_ERROR; - } - pDev->config.rmapbufdis = (unsigned int)ioarg->buffer; - break; - case SPACEWIRE_IOCTRL_SET_CHECK_RMAP: - SPACEWIRE_DBGC(DBGSPW_IOCTRL,"SPACEWIRE_IOCTRL_SET_CHECK_RMAP %i \n", (unsigned int)ioarg->buffer); - if ((unsigned int)ioarg->buffer > 1) { - return RTEMS_INVALID_NAME; - } - pDev->config.check_rmap_err = (unsigned int)ioarg->buffer; - break; - case SPACEWIRE_IOCTRL_SET_RM_PROT_ID: - SPACEWIRE_DBGC(DBGSPW_IOCTRL, "SPACEWIRE_IOCTRL_SET_RM_PROT_ID %i \n", (unsigned int)ioarg->buffer); - if ((unsigned int)ioarg->buffer > 1) { - return RTEMS_INVALID_NAME; - } - pDev->config.rm_prot_id = (unsigned int)ioarg->buffer; - break; - case SPACEWIRE_IOCTRL_SET_KEEP_SOURCE: - SPACEWIRE_DBGC(DBGSPW_IOCTRL, "SPACEWIRE_IOCTRL_SET_KEEP_SOURCE %i \n", (unsigned int)ioarg->buffer); - if ((unsigned int)ioarg->buffer > 1) { - return RTEMS_INVALID_NAME; - } - pDev->config.keep_source = (unsigned int)ioarg->buffer; - break; - case SPACEWIRE_IOCTRL_SET_TXBLOCK: - SPACEWIRE_DBGC(DBGSPW_IOCTRL, "SPACEWIRE_IOCTRL_SET_TXBLOCK %i \n", (unsigned int)ioarg->buffer); - if ((unsigned int)ioarg->buffer > 1) { - return RTEMS_INVALID_NAME; - } - pDev->config.tx_blocking = (unsigned int)ioarg->buffer; - break; - case SPACEWIRE_IOCTRL_SET_TXBLOCK_ON_FULL: - SPACEWIRE_DBGC(DBGSPW_IOCTRL, "SPACEWIRE_IOCTRL_SET_TXBLOCK_ON_FULL %i \n", (unsigned int)ioarg->buffer); - if ((unsigned int)ioarg->buffer > 1) { - return RTEMS_INVALID_NAME; - } - pDev->config.tx_block_on_full = (unsigned int)ioarg->buffer; - break; - case SPACEWIRE_IOCTRL_SET_DISABLE_ERR: - SPACEWIRE_DBGC(DBGSPW_IOCTRL, "SPACEWIRE_IOCTRL_SET_DISABLE_ERR %i \n", (unsigned int)ioarg->buffer); - if ((unsigned int)ioarg->buffer > 1) { - return RTEMS_INVALID_NAME; - } - pDev->config.disable_err = (unsigned int)ioarg->buffer; - break; - case SPACEWIRE_IOCTRL_SET_LINK_ERR_IRQ: - SPACEWIRE_DBGC(DBGSPW_IOCTRL, "SPACEWIRE_IOCTRL_SET_LINK_ERR_IRQ %i \n", (unsigned int)ioarg->buffer); - SPACEWIRE_DBGC(DBGSPW_IOCTRL, "CTRL REG: %x\n", SPW_CTRL_READ(pDev)); - if ((unsigned int)ioarg->buffer > 1) { - return RTEMS_INVALID_NAME; - } - tmp = (SPW_CTRL_READ(pDev) & 0xFFFFFDF7) | ((unsigned int)ioarg->buffer << 9); - if (tmp & (SPW_CTRL_LI|SPW_CTRL_TQ)) - tmp |= SPW_CTRL_IE; - SPW_CTRL_WRITE(pDev, tmp); - SPACEWIRE_DBGC(DBGSPW_IOCTRL, "CTRL REG: %x\n", SPW_CTRL_READ(pDev)); - if (((SPW_CTRL_READ(pDev) >> 9) & 1) != (unsigned int)ioarg->buffer) { - return RTEMS_IO_ERROR; - } - pDev->config.link_err_irq = (unsigned int)ioarg->buffer; - break; - case SPACEWIRE_IOCTRL_SET_EVENT_ID: - SPACEWIRE_DBGC(DBGSPW_IOCTRL, "SPACEWIRE_IOCTRL_SET_EVENT_ID %i \n", (unsigned int)ioarg->buffer); - pDev->config.event_id = (rtems_id)ioarg->buffer; - SPACEWIRE_DBGC(DBGSPW_IOCTRL, "Event id: %i\n", pDev->config.event_id); - break; - - /* Change MAX Packet size by: - * - stop RX/TX (if on) - * - wait for hw to complete RX DMA (if on) - * - reallocate buffers with new size - * - tell hw about new size & start RX/TX again (if previously on) - */ - case SPACEWIRE_IOCTRL_SET_PACKETSIZE: - if (ioarg->buffer == NULL) - return RTEMS_INVALID_NAME; - ps = (spw_ioctl_packetsize*) ioarg->buffer; - SPACEWIRE_DBGC(DBGSPW_IOCTRL,"SPACEWIRE_IOCTRL_SET_RXPACKETSIZE %i \n", (unsigned int)ioarg->buffer); - - tmp = pDev->running; - - if ( pDev->running ){ - /* Stop RX */ - grspw_hw_stop(pDev,1,1); - - /* If packetsize fails it is good to know if in running mode */ - pDev->running = 0; - - /* Wait for Receiver to finnish pending DMA transfers if any */ - grspw_hw_wait_rx_inactive(pDev); - } - - /* Save new buffer sizes */ - pDev->rxbufsize = ((ps->rxsize+7)&~7); - pDev->txdbufsize = ps->txdsize; - pDev->txhbufsize = ps->txhsize; - pDev->config.rxmaxlen = pDev->rxbufsize; - - /* Free previous buffers & allocate buffers with new size */ - if (grspw_buffer_alloc(pDev)) - return RTEMS_NO_MEMORY; - - /* if RX was actived before, we reactive it again */ - if ( tmp ) { - if ( (status = grspw_hw_startup(pDev,-1)) != RTEMS_SUCCESSFUL ) { - return status; - } - pDev->running = 1; - } -#if 0 - /* Rewrite previous config which was wasted due to reset in hw_startup */ - SPW_WRITE(&pDev->regs->nodeaddr, pDev->config.nodeaddr); - SPW_WRITE(&pDev->regs->destkey, pDev->config.destkey); - SPW_WRITE(&pDev->regs->clkdiv, pDev->config.clkdiv); - SPW_WRITE(&pDev->regs->timer, pDev->config.timer | ( (pDev->config.disconnect & 0x3FF) << 12) ); - SPW_CTRL_WRITE(pDev, (SPW_CTRL_READ(pDev) & !(SPW_CTRL_LINKSTART | SPW_CTRL_PM | SPW_CTRL_RE | SPW_CTRL_RD | SPW_CTRL_TT | SPW_CTRL_TR)) | \ - (pDev->config.promiscuous << 5) | (pDev->config.rmapen << 16) | (pDev->config.rmapbufdis << 17) | \ - (pDev->config.linkdisabled) | (pDev->config.linkstart << 1)); -#endif - break; - case SPACEWIRE_IOCTRL_GET_CONFIG: - if (ioarg->buffer == NULL) - return RTEMS_INVALID_NAME; - SPACEWIRE_DBG2("SPACEWIRE_IOCTRL_GET_CONFIG \n"); - (*(spw_config *)ioarg->buffer).nodeaddr = pDev->config.nodeaddr; - (*(spw_config *)ioarg->buffer).nodemask = pDev->config.nodemask; - (*(spw_config *)ioarg->buffer).destkey = pDev->config.destkey; - (*(spw_config *)ioarg->buffer).clkdiv = pDev->config.clkdiv; - (*(spw_config *)ioarg->buffer).rxmaxlen = pDev->config.rxmaxlen; - (*(spw_config *)ioarg->buffer).timer = pDev->config.timer; - (*(spw_config *)ioarg->buffer).disconnect = pDev->config.disconnect; - (*(spw_config *)ioarg->buffer).promiscuous = pDev->config.promiscuous; - (*(spw_config *)ioarg->buffer).rmapen = pDev->config.rmapen; - (*(spw_config *)ioarg->buffer).rmapbufdis = pDev->config.rmapbufdis; - (*(spw_config *)ioarg->buffer).check_rmap_err = pDev->config.check_rmap_err; - (*(spw_config *)ioarg->buffer).rm_prot_id = pDev->config.rm_prot_id; - (*(spw_config *)ioarg->buffer).tx_blocking = pDev->config.tx_blocking; - (*(spw_config *)ioarg->buffer).disable_err = pDev->config.disable_err; - (*(spw_config *)ioarg->buffer).link_err_irq = pDev->config.link_err_irq; - (*(spw_config *)ioarg->buffer).event_id = pDev->config.event_id; - (*(spw_config *)ioarg->buffer).is_rmap = pDev->config.is_rmap; - (*(spw_config *)ioarg->buffer).is_rmapcrc = pDev->config.is_rmapcrc; - (*(spw_config *)ioarg->buffer).is_rxunaligned = pDev->config.is_rxunaligned; - (*(spw_config *)ioarg->buffer).linkdisabled = pDev->config.linkdisabled; - (*(spw_config *)ioarg->buffer).linkstart = pDev->config.linkstart; - (*(spw_config *)ioarg->buffer).rx_blocking = pDev->config.rx_blocking; - (*(spw_config *)ioarg->buffer).tx_block_on_full = pDev->config.tx_block_on_full; - (*(spw_config *)ioarg->buffer).keep_source = pDev->config.keep_source; - (*(spw_config *)ioarg->buffer).rtimeout = pDev->config.rtimeout; - break; - case SPACEWIRE_IOCTRL_GET_LINK_STATUS: - SPACEWIRE_DBGC(DBGSPW_IOCTRL,"SPACEWIRE_IOCTRL_GET_STATUS=%i \n", (unsigned int)((SPW_STATUS_READ(pDev) >> 21) & 0x7)); - *(unsigned int *)ioarg->buffer = (unsigned int )((SPW_STATUS_READ(pDev) >> 21) & 0x7); - break; - case SPACEWIRE_IOCTRL_GET_STATISTICS: - if (ioarg->buffer == NULL) - return RTEMS_INVALID_NAME; - SPACEWIRE_DBG2("SPACEWIRE_IOCTRL_GET_STATISTICS \n"); - (*(spw_stats *)ioarg->buffer).tx_link_err = pDev->stat.tx_link_err; - (*(spw_stats *)ioarg->buffer).rx_rmap_header_crc_err = pDev->stat.rx_rmap_header_crc_err; - (*(spw_stats *)ioarg->buffer).rx_rmap_data_crc_err = pDev->stat.rx_rmap_data_crc_err; - (*(spw_stats *)ioarg->buffer).rx_eep_err = pDev->stat.rx_eep_err; - (*(spw_stats *)ioarg->buffer).rx_truncated = pDev->stat.rx_truncated; - (*(spw_stats *)ioarg->buffer).parity_err = pDev->stat.parity_err; - (*(spw_stats *)ioarg->buffer).escape_err = pDev->stat.escape_err; - (*(spw_stats *)ioarg->buffer).credit_err = pDev->stat.credit_err; - (*(spw_stats *)ioarg->buffer).write_sync_err = pDev->stat.write_sync_err; - (*(spw_stats *)ioarg->buffer).disconnect_err = pDev->stat.disconnect_err; - (*(spw_stats *)ioarg->buffer).early_ep = pDev->stat.early_ep; - (*(spw_stats *)ioarg->buffer).invalid_address = pDev->stat.invalid_address; - (*(spw_stats *)ioarg->buffer).packets_sent = pDev->stat.packets_sent; - (*(spw_stats *)ioarg->buffer).packets_received = pDev->stat.packets_received; - break; - case SPACEWIRE_IOCTRL_CLR_STATISTICS: - SPACEWIRE_DBG2("SPACEWIRE_IOCTRL_CLR_STATISTICS \n"); - pDev->stat.tx_link_err = 0; - pDev->stat.rx_rmap_header_crc_err = 0; - pDev->stat.rx_rmap_data_crc_err = 0; - pDev->stat.rx_eep_err = 0; - pDev->stat.rx_truncated = 0; - pDev->stat.parity_err = 0; - pDev->stat.escape_err = 0; - pDev->stat.credit_err = 0; - pDev->stat.write_sync_err = 0; - pDev->stat.disconnect_err = 0; - pDev->stat.early_ep = 0; - pDev->stat.invalid_address = 0; - pDev->stat.packets_sent = 0; - pDev->stat.packets_received = 0; - break; - case SPACEWIRE_IOCTRL_SEND: - if (ioarg->buffer == NULL) - return RTEMS_INVALID_NAME; - args = (spw_ioctl_pkt_send *)ioarg->buffer; - args->sent = 0; - - /* is link up? */ - if ( !pDev->running ) { - return RTEMS_INVALID_NAME; - } - - SPACEWIRE_DBGC(DBGSPW_IOCALLS, "write [%i,%i]: hlen: %i hbuf:0x%x dlen:%i dbuf:0x%x\n", major, minor, - (unsigned int)args->hlen, (int)args->hdr,(unsigned int)args->dlen, (int)args->data); - - if ((args->hlen > pDev->txhbufsize) || (args->dlen > pDev->txdbufsize) || - ((args->hlen+args->dlen) < 1) || - ((args->hdr == NULL) && (args->hlen != 0)) || ((args->data == NULL) && (args->dlen != 0))) { - return RTEMS_INVALID_NAME; - } - while ((args->sent = grspw_hw_send(pDev, args->hlen, args->hdr, args->dlen, args->data, args->options)) == 0) { - if (pDev->config.tx_block_on_full == 1) { - SPACEWIRE_DBG2("Tx Block on full \n"); - rtems_semaphore_obtain(pDev->txsp, RTEMS_WAIT, RTEMS_NO_TIMEOUT); - } else { - SPACEWIRE_DBG2("Tx non blocking return when full \n"); - return RTEMS_RESOURCE_IN_USE; - } - } - SPACEWIRE_DBGC(DBGSPW_IOCALLS, "Tx ioctl return: %i \n", args->sent); - break; - - case SPACEWIRE_IOCTRL_LINKDISABLE: - pDev->config.linkdisabled = 1; - pDev->config.linkstart = 0; - if ( pDev->core_ver != 3 ) { - SPW_CTRL_WRITE(pDev, (SPW_CTRL_READ(pDev) & 0xFFFFFFFC) | 1); - if ((SPW_CTRL_READ(pDev) & 3) != 1) { - return RTEMS_IO_ERROR; - } - } - break; - - case SPACEWIRE_IOCTRL_LINKSTART: - pDev->config.linkdisabled = 0; - pDev->config.linkstart = 1; - if ( pDev->core_ver != 3 ) { - SPW_CTRL_WRITE(pDev, (SPW_CTRL_READ(pDev) & 0xFFFFFFFC) | 2); - if ((SPW_CTRL_READ(pDev) & 3) != 2) { - return RTEMS_IO_ERROR; - } - } - break; - - /* Calculate timer register from GRSPW Core frequency - * Also possible to set disconnect and timer64 from - * - SPACEWIRE_IOCTRL_SET_DISCONNECT - * - SPACEWIRE_IOCTRL_SET_TIMER - */ - case SPACEWIRE_IOCTRL_SET_COREFREQ: - pDev->core_freq_khz = (unsigned int)ioarg->buffer; - if ( pDev->core_freq_khz == 0 ){ - /* Get GRSPW clock frequency from system clock. - * System clock has been read from timer inited - * by RTEMS loader (mkprom) - */ - drvmgr_freq_get(pDev->dev, DEV_APB_SLV, - &pDev->core_freq_khz); - /* Convert from Hz -> kHz */ - pDev->core_freq_khz = pDev->core_freq_khz / 1000; - } - - /* Only GRSPW1 needs the Timer64 and Disconnect values - * GRSPW2 and onwards doesn't have this register. - */ - if ( pDev->core_ver <= 1 ){ - /* Calculate Timer64 & Disconnect */ - pDev->config.timer = grspw_calc_timer64(pDev->core_freq_khz); - pDev->config.disconnect = grspw_calc_disconnect(pDev->core_freq_khz); - - /* Set Timer64 & Disconnect Register */ - SPW_WRITE(&pDev->regs->timer, - (SPW_READ(&pDev->regs->timer) & 0xFFC00000) | - ((pDev->config.disconnect & 0x3FF)<<12) | - (pDev->config.timer & 0xFFF)); - - /* Check that the registers were written successfully */ - tmp = SPW_READ(&pDev->regs->timer) & 0x003fffff; - if ( ((tmp & 0xFFF) != pDev->config.timer) || - (((tmp >> 12) & 0x3FF) != pDev->config.disconnect) ) { - return RTEMS_IO_ERROR; - } - } - break; - - case SPACEWIRE_IOCTRL_START: - if ( pDev->running ){ - return RTEMS_INVALID_NAME; - } - - /* Get timeout from userspace - * timeout: - * ¤ -1 = Default timeout - * ¤ less than -1 = forever - * ¤ 0 = no wait, proceed if link is up - * ¤ positive = specifies number of system clock ticks that - * startup will wait for link to enter ready mode. - */ - timeout = (int)ioarg->buffer; - - if ( (ret=grspw_hw_startup(pDev,timeout)) != RTEMS_SUCCESSFUL ) { - return ret; - } - pDev->running = 1; - /* Register interrupt routine and unmask IRQ */ - drvmgr_interrupt_register(pDev->dev, 0, "grspw", grspw_interrupt, pDev); - - break; - - case SPACEWIRE_IOCTRL_STOP: - if ( !pDev->running ){ - return RTEMS_INVALID_NAME; - } - /* Disable interrupts */ - drvmgr_interrupt_unregister(dev, 0, grspw_interrupt, pDev); - - pDev->running = 0; - - /* Stop Receiver and transmitter */ - grspw_hw_stop(pDev,1,1); - break; - - /* Set time-code control register bits, and Enables/Disables - * Time code interrupt, make sure to connect the callback - * grspw_timecode_callback if using interrupts. - */ - case SPACEWIRE_IOCTRL_SET_TCODE_CTRL: - tmp = (unsigned int)ioarg->buffer; - mask = tmp & (SPACEWIRE_TCODE_CTRL_IE_MSK|SPACEWIRE_TCODE_CTRL_TT_MSK|SPACEWIRE_TCODE_CTRL_TR_MSK); - mask <<= 8; - tmp &= mask; - tmp = (SPW_CTRL_READ(pDev) & ~(mask | SPW_CTRL_IE)) | tmp; - if (tmp & (SPW_CTRL_LI|SPW_CTRL_TQ)) - tmp |= SPW_CTRL_IE; - SPW_CTRL_WRITE(pDev, tmp); - break; - - /* Set time register and optionaly send a time code */ - case SPACEWIRE_IOCTRL_SET_TCODE: - tmp = (unsigned int)ioarg->buffer; - /* Set timecode register */ - if (tmp & SPACEWIRE_TCODE_SET) { - SPW_WRITE(&pDev->regs->time, - ((SPW_READ(&pDev->regs->time) & ~(0xff)) | - (tmp & SPACEWIRE_TCODE_TCODE))); - } - /* Send timecode directly (tick-in) ? */ - if (tmp & SPACEWIRE_TCODE_TX) { - SPW_CTRL_WRITE(pDev, - ((SPW_CTRL_READ(pDev) & ~(SPW_CTRL_TI)) | SPW_CTRL_TI)); - } - break; - - /* Read time code register and tick-out status bit */ - case SPACEWIRE_IOCTRL_GET_TCODE: - tmp = (unsigned int)ioarg->buffer; - if ( !tmp ){ - return RTEMS_INVALID_NAME; - } - - /* Copy timecode register */ - if (SPW_READ(&pDev->regs->status) & SPW_STATUS_TO) { - *(unsigned int *)tmp = (1 << 8) | SPW_READ(&pDev->regs->time); - } else { - *(unsigned int *)tmp = SPW_READ(&pDev->regs->time); - } - break; - - case SPACEWIRE_IOCTRL_SET_READ_TIMEOUT: - pDev->config.rtimeout = (unsigned int)ioarg->buffer; - break; - - default: - return RTEMS_NOT_IMPLEMENTED; - } - - SPACEWIRE_DBGC(DBGSPW_IOCALLS, "SPW_IOCTRL Return\n"); - return RTEMS_SUCCESSFUL; -} - -/* ============================================================================== */ - -static int grspw_set_rxmaxlen(GRSPW_DEV *pDev) { - unsigned int rxmax; - SPW_WRITE(&pDev->regs->dma0rxmax,pDev->config.rxmaxlen); /*set rx maxlength*/ - rxmax = SPW_READ(&pDev->regs->dma0rxmax); - if (rxmax != pDev->config.rxmaxlen) { - return 0; - } - return 1; -} - -static int grspw_hw_init(GRSPW_DEV *pDev) { - unsigned int ctrl; - - ctrl = SPW_CTRL_READ(pDev); - - pDev->rx = (SPACEWIRE_RXBD *) pDev->ptr_bd0; - pDev->tx = (SPACEWIRE_TXBD *) (pDev->ptr_bd0 + SPACEWIRE_BDTABLE_SIZE); - - /* Set up remote addresses */ - pDev->rx_remote = (unsigned int)pDev->ptr_bd0_remote; - pDev->tx_remote = pDev->rx_remote + SPACEWIRE_BDTABLE_SIZE; - - SPACEWIRE_DBG("hw_init [minor %i]\n", pDev->minor); - - pDev->config.is_rmap = ctrl & SPW_CTRL_RA; - pDev->config.is_rxunaligned = ctrl & SPW_CTRL_RX; - pDev->config.is_rmapcrc = ctrl & SPW_CTRL_RC; - return 0; -} - -static int grspw_hw_waitlink (GRSPW_DEV *pDev, int timeout) -{ - int j; - - /* No actual link interface on a DMA-only GRSPW2 connected to the - * SPW router - */ - if (pDev->core_ver == 3) - return 0; - - if ( timeout == -1 ){ - /* Wait default timeout */ - timeout = SPACEWIRE_INIT_TIMEOUT; - } - - j=0; - while (SPW_LINKSTATE(SPW_STATUS_READ(pDev)) != 5) { - if ( timeout < -1 ) { - /* wait forever */ - }else if ( j >= timeout ){ - /* timeout reached, return fail */ - return 1; - } - - /* Sleep for 10 ticks */ - rtems_task_wake_after(10); - j+=10; - } - return 0; -} - -static void grspw_hw_reset(GRSPW_DEV *pDev) -{ - SPW_CTRL_WRITE(pDev, SPW_CTRL_RESET); /*reset core*/ - SPW_STATUS_WRITE(pDev, SPW_STATUS_TO | SPW_STATUS_CE | SPW_STATUS_ER | SPW_STATUS_DE | SPW_STATUS_PE | - SPW_STATUS_WE | SPW_STATUS_IA | SPW_STATUS_EE); /*clear status*/ - - /* Add extra writes to make sure we wait the number of clocks required - * after reset - */ - SPW_STATUS_WRITE(pDev, SPW_STATUS_TO | SPW_STATUS_CE | SPW_STATUS_ER | SPW_STATUS_DE | SPW_STATUS_PE | - SPW_STATUS_WE | SPW_STATUS_IA | SPW_STATUS_EE); /*clear status*/ - SPW_STATUS_WRITE(pDev, SPW_STATUS_TO | SPW_STATUS_CE | SPW_STATUS_ER | SPW_STATUS_DE | SPW_STATUS_PE | - SPW_STATUS_WE | SPW_STATUS_IA | SPW_STATUS_EE); /*clear status*/ - SPW_STATUS_WRITE(pDev, SPW_STATUS_TO | SPW_STATUS_CE | SPW_STATUS_ER | SPW_STATUS_DE | SPW_STATUS_PE | - SPW_STATUS_WE | SPW_STATUS_IA | SPW_STATUS_EE); /*clear status*/ - SPW_STATUS_WRITE(pDev, SPW_STATUS_TO | SPW_STATUS_CE | SPW_STATUS_ER | SPW_STATUS_DE | SPW_STATUS_PE | - SPW_STATUS_WE | SPW_STATUS_IA | SPW_STATUS_EE); /*clear status*/ - - SPW_CTRL_WRITE(pDev, SPW_CTRL_LINKSTART); /*start link core*/ -} - -static void grspw_hw_read_config(GRSPW_DEV *pDev) -{ - unsigned int tmp; - - tmp = SPW_READ(&pDev->regs->nodeaddr); - pDev->config.nodeaddr = 0xFF & tmp; - pDev->config.nodemask = 0xFF & (tmp>>8); - pDev->config.destkey = 0xFF & SPW_READ(&pDev->regs->destkey); - pDev->config.clkdiv = 0xFFFF & SPW_READ(&pDev->regs->clkdiv); - - tmp = SPW_CTRL_READ(pDev); - pDev->config.promiscuous = 1 & (tmp >> 5); - pDev->config.rmapen = 1 & (tmp >> 16); - pDev->config.rmapbufdis = 1 & (tmp >> 17); - pDev->config.is_rmap = 1 & (tmp >> 31); - pDev->config.is_rxunaligned = 1 & (tmp >> 30); - pDev->config.is_rmapcrc = 1 & (tmp >> 29); - pDev->config.linkdisabled = 1 & tmp; - pDev->config.linkstart = 1 & (tmp >> 1); - - if ( pDev->core_ver <= 1 ){ - tmp = SPW_READ(&pDev->regs->timer); - pDev->config.timer = 0xFFF & tmp; - pDev->config.disconnect = 0x3FF & (tmp >> 12); - }else{ - pDev->config.timer = 0; - pDev->config.disconnect = 0; - } - - return; -} - -/* timeout is given in ticks */ -static int grspw_hw_startup (GRSPW_DEV *pDev, int timeout) -{ - int i; - unsigned int dmactrl; - - SPW_WRITE(&pDev->regs->status, (SPW_STATUS_TO|SPW_STATUS_CE|SPW_STATUS_ER|SPW_STATUS_DE|SPW_STATUS_PE|SPW_STATUS_WE|SPW_STATUS_IA|SPW_STATUS_EE)); /*clear status*/ - - if (grspw_hw_waitlink(pDev,timeout)) { - SPACEWIRE_DBG2("Device open. Link is not up\n"); - return RTEMS_TIMEOUT; - } - - SPW_WRITE(&pDev->regs->dma0ctrl, SPW_DMACTRL_PS | SPW_DMACTRL_PR | SPW_DMACTRL_TA | SPW_DMACTRL_RA); /*clear status, set ctrl*/ - - if ((dmactrl = SPW_READ(&pDev->regs->dma0ctrl)) != 0) { - SPACEWIRE_DBG2("DMACtrl is not cleared\n"); - return RTEMS_IO_ERROR; - } - - /* prepare transmit buffers */ - for (i = 0; i < pDev->txbufcnt; i++) { - pDev->tx[i].ctrl = 0; - pDev->tx[i].addr_header = ((unsigned int)&pDev->ptr_txhbuf0_remote[0]) + (i * pDev->txhbufsize); - pDev->tx[i].addr_data = ((unsigned int)&pDev->ptr_txdbuf0_remote[0]) + (i * pDev->txdbufsize); - } - pDev->tx_cur = 0; - pDev->tx_sent = 0; - pDev->tx_all_in_use = 0; - - /* prepare receive buffers */ - for (i = 0; i < pDev->rxbufcnt; i++) { - if (i+1 == pDev->rxbufcnt) { - pDev->rx[i].ctrl = SPW_RXBD_IE | SPW_RXBD_EN | SPW_RXBD_WR; - } else { - pDev->rx[i].ctrl = SPW_RXBD_IE | SPW_RXBD_EN; - } - pDev->rx[i].addr = ((unsigned int)&pDev->ptr_rxbuf0_remote[0]) + (i * pDev->rxbufsize); - } - pDev->rxcur = 0; - pDev->rxbufcur = -1; - grspw_set_rxmaxlen(pDev); - - SPW_WRITE(&pDev->regs->dma0txdesc, pDev->tx_remote); - SPW_WRITE(&pDev->regs->dma0rxdesc, pDev->rx_remote); - - /* start RX */ - dmactrl = SPW_READ(&pDev->regs->dma0ctrl); - SPW_WRITE(&pDev->regs->dma0ctrl, (dmactrl & SPW_PREPAREMASK_RX) | SPW_DMACTRL_RD | SPW_DMACTRL_RXEN | SPW_DMACTRL_NS | SPW_DMACTRL_TXIE | SPW_DMACTRL_RXIE); - - SPACEWIRE_DBGC(DBGSPW_TX,"0x%x: setup complete\n", (unsigned int)pDev->regs); - return RTEMS_SUCCESSFUL; -} - -/* Wait until the receiver is inactive */ -static void grspw_hw_wait_rx_inactive(GRSPW_DEV *pDev) -{ - while( SPW_READ(&pDev->regs->dma0ctrl) & SPW_DMACTRL_RX ){ - /* switching may be needed: - * - low frequency GRSPW - * - mega packet incoming - */ - rtems_task_wake_after(1); - } -} - -/* Stop the rx or/and tx by disabling the receiver/transmitter */ -static int grspw_hw_stop (GRSPW_DEV *pDev, int rx, int tx) -{ - unsigned int dmactrl; - - /* stop rx and/or tx */ - dmactrl = SPW_READ(&pDev->regs->dma0ctrl); - if ( rx ) { - dmactrl &= ~(SPW_DMACTRL_RXEN|SPW_DMACTRL_RXIE|SPW_DMACTRL_RD); - } - if ( tx ) { - dmactrl &= ~(SPW_DMACTRL_TXEN|SPW_DMACTRL_TXIE); - } - /*SPW_WRITE(&pDev->regs->dma0ctrl, (dmactrl & SPW_PREPAREMASK_RX) & ~(SPW_DMACTRL_RD | SPW_DMACTRL_RXEN) & ~(SPW_DMACTRL_TXEN));*/ - - /* don't clear status flags */ - dmactrl &= ~(SPW_DMACTRL_RA|SPW_DMACTRL_PR|SPW_DMACTRL_AI); - SPW_WRITE(&pDev->regs->dma0ctrl, dmactrl); - return RTEMS_SUCCESSFUL; -} - - - -int grspw_hw_send(GRSPW_DEV *pDev, unsigned int hlen, char *hdr, unsigned int dlen, char *data, unsigned int options) -{ - unsigned int dmactrl, ctrl; -#ifdef DEBUG_SPACEWIRE_ONOFF - unsigned int k; -#endif - rtems_interrupt_level level; - unsigned int cur = pDev->tx_cur, bdctrl; - char *txh = pDev->ptr_txhbuf0 + (cur * pDev->txhbufsize); - char *txd = pDev->ptr_txdbuf0 + (cur * pDev->txdbufsize); - char *txh_remote = pDev->ptr_txhbuf0_remote + (cur * pDev->txhbufsize); - char *txd_remote = pDev->ptr_txdbuf0_remote + (cur * pDev->txdbufsize); - - ctrl = SPW_READ((volatile void *)&pDev->tx[cur].ctrl); - - if (ctrl & SPW_TXBD_EN) { - return 0; - } - - memcpy(&txd[0], data, dlen); - memcpy(&txh[0], hdr, hlen); - -#ifdef DEBUG_SPACEWIRE_ONOFF - if (DEBUG_SPACEWIRE_FLAGS & DBGSPW_DUMP) { - for (k = 0; k < hlen; k++){ - if (k % 16 == 0) { - printf ("\n"); - } - printf ("%.2x(%c) ",txh[k] & 0xff,isprint(txh[k] & 0xff) ? txh[k] & 0xff : ' '); - } - printf ("\n"); - } - if (DEBUG_SPACEWIRE_FLAGS & DBGSPW_DUMP) { - for (k = 0; k < dlen; k++){ - if (k % 16 == 0) { - printf ("\n"); - } - printf ("%.2x(%c) ",txd[k] & 0xff,isprint(txd[k] & 0xff) ? txd[k] & 0xff : ' '); - } - printf ("\n"); - } -#endif - - pDev->tx[cur].addr_header = (unsigned int)txh_remote; - pDev->tx[cur].len = dlen; - pDev->tx[cur].addr_data = (unsigned int)txd_remote; - - bdctrl = SPW_TXBD_IE | SPW_TXBD_EN | hlen; - if ( options & GRSPW_PKTSEND_OPTION_HDR_CRC ) - bdctrl |= SPW_TXBD_HC; - if ( options & GRSPW_PKTSEND_OPTION_DATA_CRC ) - bdctrl |= SPW_TXBD_DC; - bdctrl |= options & GRSPW_PKTSEND_OPTION_NOCRCLEN_MASK; - - /* Update counters */ - rtems_interrupt_disable(level); - if (pDev->tx_cur == (pDev->txbufcnt - 1) ) { - bdctrl |= SPW_TXBD_WR; - } - pDev->tx[cur].ctrl = bdctrl; - - dmactrl = SPW_READ(&pDev->regs->dma0ctrl); - SPW_WRITE(&pDev->regs->dma0ctrl, (dmactrl & SPW_PREPAREMASK_TX) | SPW_DMACTRL_TXEN | SPW_DMACTRL_TXIE); - - pDev->tx_cur = (pDev->tx_cur + 1) % pDev->txbufcnt; - if (pDev->tx_cur == pDev->tx_sent) { - pDev->tx_all_in_use = 1; - } - rtems_interrupt_enable(level); - - /* In blocking mode wait until message is sent */ - if (pDev->config.tx_blocking) { - while ( SPW_READ(&pDev->regs->dma0ctrl) & SPW_DMACTRL_TXEN) { - /* if changed to blocking mode */ - SPACEWIRE_DBGC(DBGSPW_TX, "Tx blocking\n"); - rtems_semaphore_obtain(pDev->txsp, RTEMS_WAIT, RTEMS_NO_TIMEOUT); - } - } - SPACEWIRE_DBGC(DBGSPW_TX, "0x%x: transmitted <%i> bytes\n", (unsigned int) pDev->regs, dlen+hlen); - return hlen + dlen; -} - -static int grspw_hw_receive(GRSPW_DEV *pDev, char *b, int c) { - unsigned int len, rxlen, ctrl; - unsigned int cur; - unsigned int tmp; - unsigned int dump_start_len; - int i; - char *rxb; - - if ( pDev->config.promiscuous || pDev->config.keep_source ) { - dump_start_len = 0; /* make sure address and prot can be read in promiscuous mode */ - } else if (pDev->config.rm_prot_id) { - dump_start_len = 2; /* skip source address and protocol id */ - } else { - dump_start_len = 1; /* default: skip only source address */ - } - - rxlen = 0; - cur = pDev->rxcur; - rxb = pDev->ptr_rxbuf0 + (cur * pDev->rxbufsize); - - SPACEWIRE_DBGC(DBGSPW_RX, "0x%x: waitin packet at pos %i\n", (unsigned int) pDev->regs, cur); - - ctrl = SPW_READ((volatile void *)&pDev->rx[cur].ctrl); - if (ctrl & SPW_RXBD_EN) { - return rxlen; - } - SPACEWIRE_DBGC(DBGSPW_RX, "checking packet\n"); - - len = SPW_RXBD_LENGTH & ctrl; - if (!((ctrl & SPW_RXBD_ERROR) || (pDev->config.check_rmap_err && (ctrl & SPW_RXBD_RMAPERROR)))) { - if (pDev->rxbufcur == -1) { - SPACEWIRE_DBGC(DBGSPW_RX, "incoming packet len %i\n", len); - pDev->stat.packets_received++; - pDev->rxbufcur = dump_start_len; - } - rxlen = tmp = len - pDev->rxbufcur; - SPACEWIRE_DBGC(DBGSPW_RX, "C %i\n", c); - SPACEWIRE_DBGC(DBGSPW_RX, "Dump %i\n", dump_start_len); - SPACEWIRE_DBGC(DBGSPW_RX, "Bufcur %i\n", pDev->rxbufcur); - SPACEWIRE_DBGC(DBGSPW_RX, "Rxlen %i\n", rxlen ); - if (rxlen > c) { - rxlen = c; - } - if (CPU_SPARC_HAS_SNOOPING) { -/* if ( 1 ) {*/ - /*printf("RX_MEMCPY(0x%x, 0x%x, 0x%x)\n", (unsigned int)b, (unsigned int)(rxb+pDev->rxbufcur), (unsigned int)rxlen);*/ - memcpy(b, rxb+pDev->rxbufcur, rxlen); - } else { - int left = rxlen; - /* Copy word wise if Aligned */ - if ( (((int)b & 3) == 0) && (((int)(rxb+pDev->rxbufcur) & 3) == 0) ){ - while(left>=32){ - *(int *)(b+0) = MEM_READ32(rxb+pDev->rxbufcur+0); - *(int *)(b+4) = MEM_READ32(rxb+pDev->rxbufcur+4); - *(int *)(b+8) = MEM_READ32(rxb+pDev->rxbufcur+8); - *(int *)(b+12) = MEM_READ32(rxb+pDev->rxbufcur+12); - *(int *)(b+16) = MEM_READ32(rxb+pDev->rxbufcur+16); - *(int *)(b+20) = MEM_READ32(rxb+pDev->rxbufcur+20); - *(int *)(b+24) = MEM_READ32(rxb+pDev->rxbufcur+24); - *(int *)(b+28) = MEM_READ32(rxb+pDev->rxbufcur+28); - rxb+=32; - b+=32; - left-=32; - } - while(left>=4){ - *(int *)b = MEM_READ32(rxb+pDev->rxbufcur); - rxb+=4; - b+=4; - left-=4; - } - } - for(i = 0; i < left; i++) { - b[i] = MEM_READ8(rxb+pDev->rxbufcur+i); - } - } - - pDev->rxbufcur += rxlen; - if (c >= tmp) { - SPACEWIRE_DBGC(DBGSPW_RX, "Next descriptor\n"); - grspw_rxnext(pDev); - } - } else { - check_rx_errors(pDev, ctrl); - grspw_rxnext(pDev); - } - return rxlen; -} - -static void grspw_rxnext(GRSPW_DEV *pDev) -{ - unsigned int dmactrl; - unsigned int cur = pDev->rxcur; - unsigned int ctrl = 0; - rtems_interrupt_level level; - - rtems_interrupt_disable(level); - - if (cur == (pDev->rxbufcnt - 1)) { - pDev->rx[cur].ctrl = ctrl | SPW_RXBD_EN | SPW_RXBD_IE | SPW_RXBD_WR; - cur = 0; - } else { - pDev->rx[cur].ctrl = ctrl | SPW_RXBD_EN | SPW_RXBD_IE; - cur++; - } - - pDev->rxcur = cur; - pDev->rxbufcur = -1; - - /* start RX */ - dmactrl = SPW_READ(&pDev->regs->dma0ctrl); - SPW_WRITE(&pDev->regs->dma0ctrl, (dmactrl & SPW_PREPAREMASK_RX) | SPW_DMACTRL_RD | SPW_DMACTRL_RXEN | SPW_DMACTRL_RXIE | SPW_DMACTRL_NS); - - rtems_interrupt_enable(level); -} - -static void check_rx_errors(GRSPW_DEV *pDev, int ctrl) -{ - if (ctrl & SPW_RXBD_EEP) { - pDev->stat.rx_eep_err++; - } - if (ctrl & SPW_RXBD_EHC) { - if (pDev->config.check_rmap_err) { - pDev->stat.rx_rmap_header_crc_err++; - } - } - if (ctrl & SPW_RXBD_EDC) { - if (pDev->config.check_rmap_err) { - pDev->stat.rx_rmap_data_crc_err++; - } - } - if (ctrl & SPW_RXBD_ETR) { - pDev->stat.rx_truncated++; - } -} - - -static void grspw_print_dev(struct drvmgr_dev *dev, int options) -{ - GRSPW_DEV *pDev = dev->priv; - - /* Print */ - printf("--- GRSPW %s ---\n", pDev->devName); - printf(" REGS: 0x%x\n", (unsigned int)pDev->regs); - printf(" IRQ: %d\n", pDev->irq); - printf(" CORE VERSION: %d\n", pDev->core_ver); - printf(" CTRL: 0x%x\n", pDev->regs->ctrl); - printf(" STATUS: 0x%x\n", pDev->regs->status); - printf(" DMA0CTRL: 0x%x\n", pDev->regs->dma0ctrl); - printf(" TXBD: 0x%x\n", (unsigned int)pDev->tx); - printf(" RXBD: 0x%x\n", (unsigned int)pDev->rx); -} - -void grspw_print(int options) -{ - struct amba_drv_info *drv = &grspw_drv_info; - struct drvmgr_dev *dev; - - dev = drv->general.dev; - while(dev) { - grspw_print_dev(dev, options); - dev = dev->next_in_drv; - } -} diff --git a/c/src/lib/libbsp/sparc/shared/spw/grspw_pkt.c b/c/src/lib/libbsp/sparc/shared/spw/grspw_pkt.c deleted file mode 100644 index b7b3624588..0000000000 --- a/c/src/lib/libbsp/sparc/shared/spw/grspw_pkt.c +++ /dev/null @@ -1,3327 +0,0 @@ -/* - * Cobham Gaisler GRSPW/GRSPW2 SpaceWire Kernel Library Interface for RTEMS. - * - * This driver can be used to implement a standard I/O system "char"-driver - * or used directly. NOTE SMP support has not been tested. - * - * COPYRIGHT (c) 2011 - * Cobham Gaisler AB - * - * 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 - -#include -#include -#include -#include - -/* Use interrupt lock privmitives compatible with SMP defined in - * RTEMS 4.11.99 and higher. - */ -#if (((__RTEMS_MAJOR__ << 16) | (__RTEMS_MINOR__ << 8) | __RTEMS_REVISION__) >= 0x040b63) - -#include /* spin-lock */ - -/* map via ISR lock: */ -#define SPIN_DECLARE(lock) ISR_LOCK_MEMBER(lock) -#define SPIN_INIT(lock, name) _ISR_lock_Initialize(lock, name) -#define SPIN_LOCK(lock, level) _ISR_lock_Acquire_inline(lock, &level) -#define SPIN_LOCK_IRQ(lock, level) _ISR_lock_ISR_disable_and_acquire(lock, &level) -#define SPIN_UNLOCK(lock, level) _ISR_lock_Release_inline(lock, &level) -#define SPIN_UNLOCK_IRQ(lock, level) _ISR_lock_Release_and_ISR_enable(lock, &level) -#define SPIN_IRQFLAGS(k) ISR_lock_Context k -#define SPIN_ISR_IRQFLAGS(k) SPIN_IRQFLAGS(k) - -#else - -/* maintain single-core compatibility with older versions of RTEMS: */ -#define SPIN_DECLARE(name) -#define SPIN_INIT(lock, name) -#define SPIN_LOCK(lock, level) -#define SPIN_LOCK_IRQ(lock, level) rtems_interrupt_disable(level) -#define SPIN_UNLOCK(lock, level) -#define SPIN_UNLOCK_IRQ(lock, level) rtems_interrupt_enable(level) -#define SPIN_IRQFLAGS(k) rtems_interrupt_level k -#define SPIN_ISR_IRQFLAGS(k) - -#ifdef RTEMS_SMP -#error SMP mode not compatible with these interrupt lock primitives -#endif - -#endif - -/*#define STATIC*/ -#define STATIC static - -/*#define GRSPW_DBG(args...) printk(args)*/ -#define GRSPW_DBG(args...) - -struct grspw_dma_regs { - volatile unsigned int ctrl; /* DMA Channel Control */ - volatile unsigned int rxmax; /* RX Max Packet Length */ - volatile unsigned int txdesc; /* TX Descriptor Base/Current */ - volatile unsigned int rxdesc; /* RX Descriptor Base/Current */ - volatile unsigned int addr; /* Address Register */ - volatile unsigned int resv[3]; -}; - -struct grspw_regs { - volatile unsigned int ctrl; - volatile unsigned int status; - volatile unsigned int nodeaddr; - volatile unsigned int clkdiv; - volatile unsigned int destkey; - volatile unsigned int time; - volatile unsigned int timer; /* Used only in GRSPW1 */ - volatile unsigned int resv1; - - /* DMA Registers, ctrl.NCH determines number of ports, - * up to 4 channels are supported - */ - struct grspw_dma_regs dma[4]; - - volatile unsigned int icctrl; - volatile unsigned int icrx; - volatile unsigned int icack; - volatile unsigned int ictimeout; - volatile unsigned int ictickomask; - volatile unsigned int icaamask; - volatile unsigned int icrlpresc; - volatile unsigned int icrlisr; - volatile unsigned int icrlintack; - volatile unsigned int resv2; - volatile unsigned int icisr; - volatile unsigned int resv3; -}; - -/* GRSPW - Control Register - 0x00 */ -#define GRSPW_CTRL_RA_BIT 31 -#define GRSPW_CTRL_RX_BIT 30 -#define GRSPW_CTRL_RC_BIT 29 -#define GRSPW_CTRL_NCH_BIT 27 -#define GRSPW_CTRL_PO_BIT 26 -#define GRSPW_CTRL_ID_BIT 24 -#define GRSPW_CTRL_LE_BIT 22 -#define GRSPW_CTRL_PS_BIT 21 -#define GRSPW_CTRL_NP_BIT 20 -#define GRSPW_CTRL_RD_BIT 17 -#define GRSPW_CTRL_RE_BIT 16 -#define GRSPW_CTRL_TF_BIT 12 -#define GRSPW_CTRL_TR_BIT 11 -#define GRSPW_CTRL_TT_BIT 10 -#define GRSPW_CTRL_LI_BIT 9 -#define GRSPW_CTRL_TQ_BIT 8 -#define GRSPW_CTRL_RS_BIT 6 -#define GRSPW_CTRL_PM_BIT 5 -#define GRSPW_CTRL_TI_BIT 4 -#define GRSPW_CTRL_IE_BIT 3 -#define GRSPW_CTRL_AS_BIT 2 -#define GRSPW_CTRL_LS_BIT 1 -#define GRSPW_CTRL_LD_BIT 0 - -#define GRSPW_CTRL_RA (1<> GRSPW_CTRL_LS_BIT) - -/* Software Defaults */ -#define DEFAULT_RXMAX 1024 /* 1 KBytes Max RX Packet Size */ - -/* GRSPW Constants */ -#define GRSPW_TXBD_NR 64 /* Maximum number of TX Descriptors */ -#define GRSPW_RXBD_NR 128 /* Maximum number of RX Descriptors */ -#define GRSPW_TXBD_SIZE 16 /* Size in bytes of one TX descriptor */ -#define GRSPW_RXBD_SIZE 8 /* Size in bytes of one RX descriptor */ -#define BDTAB_SIZE 0x400 /* BD Table Size (RX or TX) */ -#define BDTAB_ALIGN 0x400 /* BD Table Alignment Requirement */ - -/* Memory and HW Registers Access routines. All 32-bit access routines */ -#define BD_WRITE(addr, val) (*(volatile unsigned int *)(addr) = (unsigned int)(val)) -/*#define BD_READ(addr) (*(volatile unsigned int *)(addr))*/ -#define BD_READ(addr) leon_r32_no_cache((unsigned long)(addr)) -#define REG_WRITE(addr, val) (*(volatile unsigned int *)(addr) = (unsigned int)(val)) -#define REG_READ(addr) (*(volatile unsigned int *)(addr)) - -struct grspw_ring { - struct grspw_ring *next; /* Next Descriptor */ - union { - struct grspw_txbd *tx; /* Descriptor Address */ - struct grspw_rxbd *rx; /* Descriptor Address */ - } bd; - struct grspw_pkt *pkt; /* Packet description associated.NULL if none*/ -}; - -/* An entry in the TX descriptor Ring */ -struct grspw_txring { - struct grspw_txring *next; /* Next Descriptor */ - struct grspw_txbd *bd; /* Descriptor Address */ - struct grspw_pkt *pkt; /* Packet description associated.NULL if none*/ -}; - -/* An entry in the RX descriptor Ring */ -struct grspw_rxring { - struct grspw_rxring *next; /* Next Descriptor */ - struct grspw_rxbd *bd; /* Descriptor Address */ - struct grspw_pkt *pkt; /* Packet description associated.NULL if none*/ -}; - - -struct grspw_dma_priv { - struct grspw_priv *core; /* GRSPW Core */ - struct grspw_dma_regs *regs; /* DMA Channel Registers */ - int index; /* DMA Channel Index @ GRSPW core */ - int open; /* DMA Channel opened by user */ - int started; /* DMA Channel activity (start|stop) */ - rtems_id sem_rxdma; /* DMA Channel RX Semaphore */ - rtems_id sem_txdma; /* DMA Channel TX Semaphore */ - struct grspw_dma_stats stats; /* DMA Channel Statistics */ - struct grspw_dma_config cfg; /* DMA Channel Configuration */ - - /*** RX ***/ - - /* RX Descriptor Ring */ - struct grspw_rxbd *rx_bds; /* Descriptor Address */ - struct grspw_rxbd *rx_bds_hwa; /* Descriptor HW Address */ - struct grspw_rxring *rx_ring_base; - struct grspw_rxring *rx_ring_head; /* Next descriptor to enable */ - struct grspw_rxring *rx_ring_tail; /* Oldest enabled Descriptor */ - int rx_irq_en_cnt_curr; - struct { - int waiting; - int ready_cnt; - int op; - int recv_cnt; - rtems_id sem_wait; /* RX Semaphore used to implement RX blocking */ - } rx_wait; - - /* Queue of Packets READY to be scheduled */ - struct grspw_list ready; - int ready_cnt; - - /* Scheduled RX Packets Queue */ - struct grspw_list rx_sched; - int rx_sched_cnt; - - /* Queue of Packets that has been RECIEVED */ - struct grspw_list recv; - int recv_cnt; - - - /*** TX ***/ - - /* TX Descriptor Ring */ - struct grspw_txbd *tx_bds; /* Descriptor Address */ - struct grspw_txbd *tx_bds_hwa; /* Descriptor HW Address */ - struct grspw_txring *tx_ring_base; - struct grspw_txring *tx_ring_head; - struct grspw_txring *tx_ring_tail; - int tx_irq_en_cnt_curr; - struct { - int waiting; - int send_cnt; - int op; - int sent_cnt; - rtems_id sem_wait; /* TX Semaphore used to implement TX blocking */ - } tx_wait; - - /* Queue of Packets ready to be scheduled for transmission */ - struct grspw_list send; - int send_cnt; - - /* Scheduled TX Packets Queue */ - struct grspw_list tx_sched; - int tx_sched_cnt; - - /* Queue of Packets that has been SENT */ - struct grspw_list sent; - int sent_cnt; -}; - -struct grspw_priv { - char devname[8]; /* Device name "grspw%d" */ - struct drvmgr_dev *dev; /* Device */ - struct grspw_regs *regs; /* Virtual Address of APB Registers */ - int irq; /* AMBA IRQ number of core */ - int index; /* Index in order it was probed */ - int core_index; /* Core Bus Index */ - int open; /* If Device is alrady opened (=1) or not (=0) */ - void *data; /* User private Data for this device instance, set by grspw_initialize_user */ - - /* Features supported by Hardware */ - struct grspw_hw_sup hwsup; - - /* Pointer to an array of Maximally 4 DMA Channels */ - struct grspw_dma_priv *dma; - - /* Spin-lock ISR protection */ - SPIN_DECLARE(devlock); - - /* Descriptor Memory Area for TX & RX and all DMA channels */ - unsigned int bd_mem; - unsigned int bd_mem_alloced; - - /*** Time Code Handling ***/ - void (*tcisr)(void *data, int timecode); - void *tcisr_arg; - - /*** Interrupt-code Handling ***/ - spwpkt_ic_isr_t icisr; - void *icisr_arg; - - /* Bit mask representing events which shall cause link disable. */ - unsigned int dis_link_on_err; - - /* Bit mask for link status bits to clear by ISR */ - unsigned int stscfg; - - /*** Message Queue Handling ***/ - struct grspw_work_config wc; - - /* "Core Global" Statistics gathered, not dependent on DMA channel */ - struct grspw_core_stats stats; -}; - -int grspw_initialized = 0; -int grspw_count = 0; -rtems_id grspw_sem; -static struct grspw_priv *priv_tab[GRSPW_MAX]; - -/* callback to upper layer when devices are discovered/removed */ -void *(*grspw_dev_add)(int) = NULL; -void (*grspw_dev_del)(int,void*) = NULL; - -/* Defaults to do nothing - user can override this function. - * Called from work-task. - */ -void __attribute__((weak)) grspw_work_event( - enum grspw_worktask_ev ev, - unsigned int msg) -{ - -} - -/* USER OVERRIDABLE - The work task priority. Set to -1 to disable creating - * the work-task and work-queue to save space. - */ -int grspw_work_task_priority __attribute__((weak)) = 100; -rtems_id grspw_work_task; -static struct grspw_work_config grspw_wc_def; - -STATIC void grspw_hw_stop(struct grspw_priv *priv); -STATIC void grspw_hw_dma_stop(struct grspw_dma_priv *dma); -STATIC void grspw_dma_reset(struct grspw_dma_priv *dma); -STATIC void grspw_dma_stop_locked(struct grspw_dma_priv *dma); -STATIC void grspw_isr(void *data); - -void *grspw_open(int dev_no) -{ - struct grspw_priv *priv; - unsigned int bdtabsize, hwa; - int i; - union drvmgr_key_value *value; - - if (grspw_initialized != 1 || (dev_no >= grspw_count)) - return NULL; - - priv = priv_tab[dev_no]; - - /* Take GRSPW lock - Wait until we get semaphore */ - if (rtems_semaphore_obtain(grspw_sem, RTEMS_WAIT, RTEMS_NO_TIMEOUT) - != RTEMS_SUCCESSFUL) - return NULL; - - if (priv->open) { - priv = NULL; - goto out; - } - - /* Initialize Spin-lock for GRSPW Device. This is to protect - * CTRL and DMACTRL registers from ISR. - */ - SPIN_INIT(&priv->devlock, priv->devname); - - priv->tcisr = NULL; - priv->tcisr_arg = NULL; - priv->icisr = NULL; - priv->icisr_arg = NULL; - priv->stscfg = LINKSTS_MASK; - - /* Default to common work queue and message queue, if not created - * during initialization then its disabled. - */ - grspw_work_cfg(priv, &grspw_wc_def); - - grspw_stats_clr(priv); - - /* Allocate TX & RX Descriptor memory area for all DMA - * channels. Max-size descriptor area is allocated (or user assigned): - * - 128 RX descriptors per DMA Channel - * - 64 TX descriptors per DMA Channel - * Specified address must be in CPU RAM. - */ - bdtabsize = 2 * BDTAB_SIZE * priv->hwsup.ndma_chans; - value = drvmgr_dev_key_get(priv->dev, "bdDmaArea", DRVMGR_KT_INT); - if (value) { - priv->bd_mem = value->i; - priv->bd_mem_alloced = 0; - if (priv->bd_mem & (BDTAB_ALIGN-1)) { - GRSPW_DBG("GRSPW[%d]: user-def DMA-area not aligned", - priv->index); - priv = NULL; - goto out; - } - } else { - priv->bd_mem_alloced = (unsigned int)malloc(bdtabsize + BDTAB_ALIGN - 1); - if (priv->bd_mem_alloced == 0) { - priv = NULL; - goto out; - } - /* Align memory */ - priv->bd_mem = (priv->bd_mem_alloced + (BDTAB_ALIGN - 1)) & - ~(BDTAB_ALIGN-1); - } - - /* Translate into DMA address that HW can use to access DMA - * descriptors - */ - drvmgr_translate_check( - priv->dev, - CPUMEM_TO_DMA, - (void *)priv->bd_mem, - (void **)&hwa, - bdtabsize); - - GRSPW_DBG("GRSPW%d DMA descriptor table setup: (alloced:%p, bd_mem:%p, size: %d)\n", - priv->index, priv->bd_mem_alloced, priv->bd_mem, bdtabsize + BDTAB_ALIGN - 1); - for (i=0; ihwsup.ndma_chans; i++) { - /* Do DMA Channel Init, other variables etc. are inited - * when respective DMA channel is opened. - * - * index & core are initialized by probe function. - */ - priv->dma[i].open = 0; - priv->dma[i].rx_bds = (struct grspw_rxbd *) - (priv->bd_mem + i*BDTAB_SIZE*2); - priv->dma[i].rx_bds_hwa = (struct grspw_rxbd *) - (hwa + BDTAB_SIZE*(2*i)); - priv->dma[i].tx_bds = (struct grspw_txbd *) - (priv->bd_mem + BDTAB_SIZE*(2*i+1)); - priv->dma[i].tx_bds_hwa = (struct grspw_txbd *) - (hwa + BDTAB_SIZE*(2*i+1)); - GRSPW_DBG(" DMA[%i]: RX %p - %p (%p - %p) TX %p - %p (%p - %p)\n", - i, - priv->dma[i].rx_bds, (void *)priv->dma[i].rx_bds + BDTAB_SIZE - 1, - priv->dma[i].rx_bds_hwa, (void *)priv->dma[i].rx_bds_hwa + BDTAB_SIZE - 1, - priv->dma[i].tx_bds, (void *)priv->dma[i].tx_bds + BDTAB_SIZE - 1, - priv->dma[i].tx_bds_hwa, (void *)priv->dma[i].tx_bds_hwa + BDTAB_SIZE - 1); - } - - /* Basic initialization of hardware, clear some registers but - * keep Link/RMAP/Node-Address registers intact. - */ - grspw_hw_stop(priv); - - /* Register Interrupt handler and enable IRQ at IRQ ctrl */ - drvmgr_interrupt_register(priv->dev, 0, priv->devname, grspw_isr, priv); - - /* Take the device */ - priv->open = 1; -out: - rtems_semaphore_release(grspw_sem); - return priv; -} - -int grspw_close(void *d) -{ - struct grspw_priv *priv = d; - int i; - - /* Take GRSPW lock - Wait until we get semaphore */ - if (rtems_semaphore_obtain(grspw_sem, RTEMS_WAIT, RTEMS_NO_TIMEOUT) - != RTEMS_SUCCESSFUL) - return -1; - - /* Check that user has stopped and closed all DMA channels - * appropriately. At this point the Hardware shall not be doing DMA - * or generating Interrupts. We want HW in a "startup-state". - */ - for (i=0; ihwsup.ndma_chans; i++) { - if (priv->dma[i].open) { - rtems_semaphore_release(grspw_sem); - return 1; - } - } - grspw_hw_stop(priv); - - /* Uninstall Interrupt handler */ - drvmgr_interrupt_unregister(priv->dev, 0, grspw_isr, priv); - - /* Free descriptor table memory if allocated using malloc() */ - if (priv->bd_mem_alloced) { - free((void *)priv->bd_mem_alloced); - priv->bd_mem_alloced = 0; - } - - /* Mark not open */ - priv->open = 0; - rtems_semaphore_release(grspw_sem); - return 0; -} - -void grspw_hw_support(void *d, struct grspw_hw_sup *hw) -{ - struct grspw_priv *priv = d; - - *hw = priv->hwsup; -} - -void grspw_addr_ctrl(void *d, struct grspw_addr_config *cfg) -{ - struct grspw_priv *priv = d; - struct grspw_regs *regs = priv->regs; - unsigned int ctrl, nodeaddr; - SPIN_IRQFLAGS(irqflags); - int i; - - if (!priv || !cfg) - return; - - SPIN_LOCK_IRQ(&priv->devlock, irqflags); - - if (cfg->promiscuous != -1) { - /* Set Configuration */ - ctrl = REG_READ(®s->ctrl); - if (cfg->promiscuous) - ctrl |= GRSPW_CTRL_PM; - else - ctrl &= ~GRSPW_CTRL_PM; - REG_WRITE(®s->ctrl, ctrl); - REG_WRITE(®s->nodeaddr, (cfg->def_mask<<8) | cfg->def_addr); - - for (i=0; ihwsup.ndma_chans; i++) { - ctrl = REG_READ(®s->dma[i].ctrl); - ctrl &= ~(GRSPW_DMACTRL_PS|GRSPW_DMACTRL_PR|GRSPW_DMA_STATUS_ERROR); - if (cfg->dma_nacfg[i].node_en) { - ctrl |= GRSPW_DMACTRL_EN; - REG_WRITE(®s->dma[i].addr, - (cfg->dma_nacfg[i].node_addr & 0xff) | - ((cfg->dma_nacfg[i].node_mask & 0xff)<<8)); - } else { - ctrl &= ~GRSPW_DMACTRL_EN; - } - REG_WRITE(®s->dma[i].ctrl, ctrl); - } - } - - /* Read Current Configuration */ - cfg->promiscuous = REG_READ(®s->ctrl) & GRSPW_CTRL_PM; - nodeaddr = REG_READ(®s->nodeaddr); - cfg->def_addr = (nodeaddr & GRSPW_DEF_ADDR) >> GRSPW_DEF_ADDR_BIT; - cfg->def_mask = (nodeaddr & GRSPW_DEF_MASK) >> GRSPW_DEF_MASK_BIT; - for (i=0; ihwsup.ndma_chans; i++) { - cfg->dma_nacfg[i].node_en = REG_READ(®s->dma[i].ctrl) & - GRSPW_DMACTRL_EN; - ctrl = REG_READ(®s->dma[i].addr); - cfg->dma_nacfg[i].node_addr = (ctrl & GRSPW_DMAADR_ADDR) >> - GRSPW_DMAADR_ADDR_BIT; - cfg->dma_nacfg[i].node_mask = (ctrl & GRSPW_DMAADR_MASK) >> - GRSPW_DMAADR_MASK_BIT; - } - SPIN_UNLOCK_IRQ(&priv->devlock, irqflags); - for (; i<4; i++) { - cfg->dma_nacfg[i].node_en = 0; - cfg->dma_nacfg[i].node_addr = 0; - cfg->dma_nacfg[i].node_mask = 0; - } -} - -/* Return Current DMA CTRL/Status Register */ -unsigned int grspw_dma_ctrlsts(void *c) -{ - struct grspw_dma_priv *dma = c; - - return REG_READ(&dma->regs->ctrl); -} - -/* Return Current Status Register */ -unsigned int grspw_link_status(void *d) -{ - struct grspw_priv *priv = d; - - return REG_READ(&priv->regs->status); -} - -/* Clear Status Register bits */ -void grspw_link_status_clr(void *d, unsigned int mask) -{ - struct grspw_priv *priv = d; - - REG_WRITE(&priv->regs->status, mask); -} - -/* Return Current Link State */ -spw_link_state_t grspw_link_state(void *d) -{ - struct grspw_priv *priv = d; - unsigned int status = REG_READ(&priv->regs->status); - - return (status & GRSPW_STS_LS) >> GRSPW_STS_LS_BIT; -} - -/* Enable Global IRQ only if some irq source is set */ -static inline int grspw_is_irqsource_set(unsigned int ctrl, unsigned int icctrl) -{ - return (ctrl & GRSPW_CTRL_IRQSRC_MASK) || - (icctrl & GRSPW_ICCTRL_IRQSRC_MASK); -} - - -/* options and clkdiv [in/out]: set to -1 to only read current config */ -void grspw_link_ctrl(void *d, int *options, int *stscfg, int *clkdiv) -{ - struct grspw_priv *priv = d; - struct grspw_regs *regs = priv->regs; - unsigned int ctrl; - SPIN_IRQFLAGS(irqflags); - - /* Write? */ - if (clkdiv) { - if (*clkdiv != -1) - REG_WRITE(®s->clkdiv, *clkdiv & GRSPW_CLKDIV_MASK); - *clkdiv = REG_READ(®s->clkdiv) & GRSPW_CLKDIV_MASK; - } - if (options) { - SPIN_LOCK_IRQ(&priv->devlock, irqflags); - ctrl = REG_READ(®s->ctrl); - if (*options != -1) { - ctrl = (ctrl & ~GRSPW_LINK_CFG) | - (*options & GRSPW_LINK_CFG); - - /* Enable Global IRQ only if some irq source is set */ - if (grspw_is_irqsource_set(ctrl, REG_READ(®s->icctrl))) - ctrl |= GRSPW_CTRL_IE; - else - ctrl &= ~GRSPW_CTRL_IE; - - REG_WRITE(®s->ctrl, ctrl); - /* Store the link disable events for use in - ISR. The LINKOPTS_DIS_ON_* options are actually the - corresponding bits in the status register, shifted - by 16. */ - priv->dis_link_on_err = *options & - (LINKOPTS_MASK_DIS_ON | LINKOPTS_DIS_ONERR); - } - SPIN_UNLOCK_IRQ(&priv->devlock, irqflags); - *options = (ctrl & GRSPW_LINK_CFG) | priv->dis_link_on_err; - } - if (stscfg) { - if (*stscfg != -1) { - priv->stscfg = *stscfg & LINKSTS_MASK; - } - *stscfg = priv->stscfg; - } -} - -/* Generate Tick-In (increment Time Counter, Send Time Code) */ -void grspw_tc_tx(void *d) -{ - struct grspw_priv *priv = d; - struct grspw_regs *regs = priv->regs; - SPIN_IRQFLAGS(irqflags); - - SPIN_LOCK_IRQ(&priv->devlock, irqflags); - REG_WRITE(®s->ctrl, REG_READ(®s->ctrl) | GRSPW_CTRL_TI); - SPIN_UNLOCK_IRQ(&priv->devlock, irqflags); -} - -void grspw_tc_ctrl(void *d, int *options) -{ - struct grspw_priv *priv = d; - struct grspw_regs *regs = priv->regs; - unsigned int ctrl; - SPIN_IRQFLAGS(irqflags); - - if (options == NULL) - return; - - /* Write? */ - if (*options != -1) { - SPIN_LOCK_IRQ(&priv->devlock, irqflags); - ctrl = REG_READ(®s->ctrl); - ctrl &= ~(GRSPW_CTRL_TR|GRSPW_CTRL_TT|GRSPW_CTRL_TQ); - ctrl |= (*options & 0xd) << GRSPW_CTRL_TQ_BIT; - - /* Enable Global IRQ only if some irq source is set */ - if (grspw_is_irqsource_set(ctrl, REG_READ(®s->icctrl))) - ctrl |= GRSPW_CTRL_IE; - else - ctrl &= ~GRSPW_CTRL_IE; - - REG_WRITE(®s->ctrl, ctrl); - SPIN_UNLOCK_IRQ(&priv->devlock, irqflags); - } else - ctrl = REG_READ(®s->ctrl); - *options = (ctrl >> GRSPW_CTRL_TQ_BIT) & 0xd; -} - -/* Assign ISR Function to TimeCode RX IRQ */ -void grspw_tc_isr(void *d, void (*tcisr)(void *data, int tc), void *data) -{ - struct grspw_priv *priv = d; - - priv->tcisr_arg = data; - priv->tcisr = tcisr; -} - -/* Read/Write TCTRL and TIMECNT. Write if not -1, always read current value - * TCTRL = bits 7 and 6 - * TIMECNT = bits 5 to 0 - */ -void grspw_tc_time(void *d, int *time) -{ - struct grspw_priv *priv = d; - struct grspw_regs *regs = priv->regs; - - if (time == NULL) - return; - if (*time != -1) - REG_WRITE(®s->time, *time & (GRSPW_TIME_TCNT | GRSPW_TIME_CTRL)); - *time = REG_READ(®s->time) & (GRSPW_TIME_TCNT | GRSPW_TIME_CTRL); -} - -/* Generate Tick-In for the given Interrupt-code and check for generation - * error. - * - * Returns zero on success and non-zero on failure - */ -int grspw_ic_tickin(void *d, int ic) -{ - struct grspw_priv *priv = d; - struct grspw_regs *regs = priv->regs; - SPIN_IRQFLAGS(irqflags); - unsigned int icctrl, mask; - - /* Prepare before turning off IRQ */ - mask = 0x3f << GRSPW_ICCTRL_TXIRQ_BIT; - ic = ((ic << GRSPW_ICCTRL_TXIRQ_BIT) & mask) | - GRSPW_ICCTRL_II | GRSPW_ICCTRL_ID; - - SPIN_LOCK_IRQ(&priv->devlock, irqflags); - icctrl = REG_READ(®s->icctrl); - icctrl &= ~mask; - icctrl |= ic; - REG_WRITE(®s->icctrl, icctrl); /* Generate SpW Interrupt Tick-In */ - /* the ID bit is valid after two clocks, so we not to wait here */ - icctrl = REG_READ(®s->icctrl); /* Check SpW-Int generation error */ - SPIN_UNLOCK_IRQ(&priv->devlock, irqflags); - - return icctrl & GRSPW_ICCTRL_ID; -} - -#define ICOPTS_CTRL_MASK ICOPTS_EN_FLAGFILTER -#define ICOPTS_ICCTRL_MASK \ - (ICOPTS_INTNUM | ICOPTS_EN_SPWIRQ_ON_EE | ICOPTS_EN_SPWIRQ_ON_IA | \ - ICOPTS_EN_PRIO | ICOPTS_EN_TIMEOUTIRQ | ICOPTS_EN_ACKIRQ | \ - ICOPTS_EN_TICKOUTIRQ | ICOPTS_EN_RX | ICOPTS_EN_TX | \ - ICOPTS_BASEIRQ) - -/* Control Interrupt-code settings of core - * Write if not pointing to -1, always read current value - * - * TODO: A lot of code duplication with grspw_tc_ctrl - */ -void grspw_ic_ctrl(void *d, unsigned int *options) -{ - struct grspw_priv *priv = d; - struct grspw_regs *regs = priv->regs; - unsigned int ctrl; - unsigned int icctrl; - SPIN_IRQFLAGS(irqflags); - - if (options == NULL) - return; - - if (*options != -1) { - SPIN_LOCK_IRQ(&priv->devlock, irqflags); - - ctrl = REG_READ(®s->ctrl); - ctrl &= ~GRSPW_CTRL_TF; /* Depends on one to one relation between - * irqopts bits and ctrl bits */ - ctrl |= (*options & ICOPTS_CTRL_MASK) << - (GRSPW_CTRL_TF_BIT - 0); - - icctrl = REG_READ(®s->icctrl); - icctrl &= ~ICOPTS_ICCTRL_MASK; /* Depends on one to one relation between - * irqopts bits and icctrl bits */ - icctrl |= *options & ICOPTS_ICCTRL_MASK; - - /* Enable Global IRQ only if some irq source is set */ - if (grspw_is_irqsource_set(ctrl, icctrl)) - ctrl |= GRSPW_CTRL_IE; - else - ctrl &= ~GRSPW_CTRL_IE; - - REG_WRITE(®s->ctrl, ctrl); - REG_WRITE(®s->icctrl, icctrl); - SPIN_UNLOCK_IRQ(&priv->devlock, irqflags); - } - *options = ((REG_READ(®s->ctrl) & ICOPTS_CTRL_MASK) | - (REG_READ(®s->icctrl) & ICOPTS_ICCTRL_MASK)); -} - -void grspw_ic_config(void *d, int rw, struct spwpkt_ic_config *cfg) -{ - struct grspw_priv *priv = d; - struct grspw_regs *regs = priv->regs; - - if (!cfg) - return; - - if (rw & 1) { - REG_WRITE(®s->ictickomask, cfg->tomask); - REG_WRITE(®s->icaamask, cfg->aamask); - REG_WRITE(®s->icrlpresc, cfg->scaler); - REG_WRITE(®s->icrlisr, cfg->isr_reload); - REG_WRITE(®s->icrlintack, cfg->ack_reload); - } - if (rw & 2) { - cfg->tomask = REG_READ(®s->ictickomask); - cfg->aamask = REG_READ(®s->icaamask); - cfg->scaler = REG_READ(®s->icrlpresc); - cfg->isr_reload = REG_READ(®s->icrlisr); - cfg->ack_reload = REG_READ(®s->icrlintack); - } -} - -/* Read or Write Interrupt-code status registers */ -void grspw_ic_sts(void *d, unsigned int *rxirq, unsigned int *rxack, unsigned int *intto) -{ - struct grspw_priv *priv = d; - struct grspw_regs *regs = priv->regs; - - /* No locking needed since the status bits are clear-on-write */ - - if (rxirq) { - if (*rxirq != 0) - REG_WRITE(®s->icrx, *rxirq); - else - *rxirq = REG_READ(®s->icrx); - } - - if (rxack) { - if (*rxack != 0) - REG_WRITE(®s->icack, *rxack); - else - *rxack = REG_READ(®s->icack); - } - - if (intto) { - if (*intto != 0) - REG_WRITE(®s->ictimeout, *intto); - else - *intto = REG_READ(®s->ictimeout); - } -} - -/* Assign handler function to Interrupt-code tick out IRQ */ -void grspw_ic_isr(void *d, spwpkt_ic_isr_t handler, void *data) -{ - struct grspw_priv *priv = d; - - priv->icisr_arg = data; - priv->icisr = handler; -} - -/* Set (not -1) and/or read RMAP options. */ -int grspw_rmap_ctrl(void *d, int *options, int *dstkey) -{ - struct grspw_priv *priv = d; - struct grspw_regs *regs = priv->regs; - unsigned int ctrl; - SPIN_IRQFLAGS(irqflags); - - if (dstkey) { - if (*dstkey != -1) - REG_WRITE(®s->destkey, *dstkey & GRSPW_DK_DESTKEY); - *dstkey = REG_READ(®s->destkey) & GRSPW_DK_DESTKEY; - } - if (options) { - if (*options != -1) { - if ((*options & RMAPOPTS_EN_RMAP) && !priv->hwsup.rmap) - return -1; - - - SPIN_LOCK_IRQ(&priv->devlock, irqflags); - ctrl = REG_READ(®s->ctrl); - ctrl &= ~(GRSPW_CTRL_RE|GRSPW_CTRL_RD); - ctrl |= (*options & 0x3) << GRSPW_CTRL_RE_BIT; - REG_WRITE(®s->ctrl, ctrl); - SPIN_UNLOCK_IRQ(&priv->devlock, irqflags); - } - *options = (REG_READ(®s->ctrl) >> GRSPW_CTRL_RE_BIT) & 0x3; - } - - return 0; -} - -void grspw_rmap_support(void *d, char *rmap, char *rmap_crc) -{ - struct grspw_priv *priv = d; - - if (rmap) - *rmap = priv->hwsup.rmap; - if (rmap_crc) - *rmap_crc = priv->hwsup.rmap_crc; -} - -/* Select port, if - * -1=The current selected port is returned - * 0=Port 0 - * 1=Port 1 - * Others=Both Port0 and Port1 - */ -int grspw_port_ctrl(void *d, int *port) -{ - struct grspw_priv *priv = d; - struct grspw_regs *regs = priv->regs; - unsigned int ctrl; - SPIN_IRQFLAGS(irqflags); - - if (port == NULL) - return -1; - - if ((*port == 1) || (*port == 0)) { - /* Select port user selected */ - if ((*port == 1) && (priv->hwsup.nports < 2)) - return -1; /* Changing to Port 1, but only one port available */ - SPIN_LOCK_IRQ(&priv->devlock, irqflags); - ctrl = REG_READ(®s->ctrl); - ctrl &= ~(GRSPW_CTRL_NP | GRSPW_CTRL_PS); - ctrl |= (*port & 1) << GRSPW_CTRL_PS_BIT; - REG_WRITE(®s->ctrl, ctrl); - SPIN_UNLOCK_IRQ(&priv->devlock, irqflags); - } else if (*port > 1) { - /* Select both ports */ - SPIN_LOCK_IRQ(&priv->devlock, irqflags); - REG_WRITE(®s->ctrl, REG_READ(®s->ctrl) | GRSPW_CTRL_NP); - SPIN_UNLOCK_IRQ(&priv->devlock, irqflags); - } - - /* Get current settings */ - ctrl = REG_READ(®s->ctrl); - if (ctrl & GRSPW_CTRL_NP) { - /* Any port, selected by hardware */ - if (priv->hwsup.nports > 1) - *port = 3; - else - *port = 0; /* Port0 the only port available */ - } else { - *port = (ctrl & GRSPW_CTRL_PS) >> GRSPW_CTRL_PS_BIT; - } - - return 0; -} - -/* Returns Number ports available in hardware */ -int grspw_port_count(void *d) -{ - struct grspw_priv *priv = d; - - return priv->hwsup.nports; -} - -/* Current active port: 0 or 1 */ -int grspw_port_active(void *d) -{ - struct grspw_priv *priv = d; - unsigned int status; - - status = REG_READ(&priv->regs->status); - - return (status & GRSPW_STS_AP) >> GRSPW_STS_AP_BIT; -} - -void grspw_stats_read(void *d, struct grspw_core_stats *sts) -{ - struct grspw_priv *priv = d; - - if (sts == NULL) - return; - memcpy(sts, &priv->stats, sizeof(priv->stats)); -} - -void grspw_stats_clr(void *d) -{ - struct grspw_priv *priv = d; - - /* Clear most of the statistics */ - memset(&priv->stats, 0, sizeof(priv->stats)); -} - -/*** DMA Interface ***/ - -/* Initialize the RX and TX Descriptor Ring, empty of packets */ -STATIC void grspw_bdrings_init(struct grspw_dma_priv *dma) -{ - struct grspw_ring *r; - int i; - - /* Empty BD rings */ - dma->rx_ring_head = dma->rx_ring_base; - dma->rx_ring_tail = dma->rx_ring_base; - dma->tx_ring_head = dma->tx_ring_base; - dma->tx_ring_tail = dma->tx_ring_base; - - /* Init RX Descriptors */ - r = (struct grspw_ring *)dma->rx_ring_base; - for (i=0; irx_bds[i]; - r[i].pkt = NULL; - - /* Init HW Descriptor */ - BD_WRITE(&r[i].bd.rx->ctrl, 0); - BD_WRITE(&r[i].bd.rx->addr, 0); - } - r[GRSPW_RXBD_NR-1].next = &r[0]; - - /* Init TX Descriptors */ - r = (struct grspw_ring *)dma->tx_ring_base; - for (i=0; itx_bds[i]; - r[i].pkt = NULL; - - /* Init HW Descriptor */ - BD_WRITE(&r[i].bd.tx->ctrl, 0); - BD_WRITE(&r[i].bd.tx->haddr, 0); - BD_WRITE(&r[i].bd.tx->dlen, 0); - BD_WRITE(&r[i].bd.tx->daddr, 0); - } - r[GRSPW_TXBD_NR-1].next = &r[0]; -} - -/* Try to populate descriptor ring with as many as possible READY unused packet - * buffers. The packets assigned with to a descriptor are put in the end of - * the scheduled list. - * - * The number of Packets scheduled is returned. - * - * - READY List -> RX-SCHED List - * - Descriptors are initialized and enabled for reception - */ -STATIC int grspw_rx_schedule_ready(struct grspw_dma_priv *dma) -{ - int cnt; - unsigned int ctrl, dmactrl; - void *hwaddr; - struct grspw_rxring *curr_bd; - struct grspw_pkt *curr_pkt, *last_pkt; - struct grspw_list lst; - SPIN_IRQFLAGS(irqflags); - - /* Is Ready Q empty? */ - if (grspw_list_is_empty(&dma->ready)) - return 0; - - cnt = 0; - lst.head = curr_pkt = dma->ready.head; - curr_bd = dma->rx_ring_head; - while (!curr_bd->pkt) { - - /* Assign Packet to descriptor */ - curr_bd->pkt = curr_pkt; - - /* Prepare descriptor address. */ - hwaddr = curr_pkt->data; - if (curr_pkt->flags & PKT_FLAG_TR_DATA) { - drvmgr_translate(dma->core->dev, CPUMEM_TO_DMA, - hwaddr, &hwaddr); - if (curr_pkt->data == hwaddr) /* translation needed? */ - curr_pkt->flags &= ~PKT_FLAG_TR_DATA; - } - BD_WRITE(&curr_bd->bd->addr, hwaddr); - - ctrl = GRSPW_RXBD_EN; - if (curr_bd->next == dma->rx_ring_base) { - /* Wrap around (only needed when smaller descriptor - * table) - */ - ctrl |= GRSPW_RXBD_WR; - } - - /* Is this Packet going to be an interrupt Packet? */ - if ((--dma->rx_irq_en_cnt_curr) <= 0) { - if (dma->cfg.rx_irq_en_cnt == 0) { - /* IRQ is disabled. A big number to avoid - * equal to zero too often - */ - dma->rx_irq_en_cnt_curr = 0x3fffffff; - } else { - dma->rx_irq_en_cnt_curr = dma->cfg.rx_irq_en_cnt; - ctrl |= GRSPW_RXBD_IE; - } - } - - if (curr_pkt->flags & RXPKT_FLAG_IE) - ctrl |= GRSPW_RXBD_IE; - - /* Enable descriptor */ - BD_WRITE(&curr_bd->bd->ctrl, ctrl); - - last_pkt = curr_pkt; - curr_bd = curr_bd->next; - cnt++; - - /* Get Next Packet from Ready Queue */ - if (curr_pkt == dma->ready.tail) { - /* Handled all in ready queue. */ - curr_pkt = NULL; - break; - } - curr_pkt = curr_pkt->next; - } - - /* Has Packets been scheduled? */ - if (cnt > 0) { - /* Prepare list for insertion/deleation */ - lst.tail = last_pkt; - - /* Remove scheduled packets from ready queue */ - grspw_list_remove_head_list(&dma->ready, &lst); - dma->ready_cnt -= cnt; - if (dma->stats.ready_cnt_min > dma->ready_cnt) - dma->stats.ready_cnt_min = dma->ready_cnt; - - /* Insert scheduled packets into scheduled queue */ - grspw_list_append_list(&dma->rx_sched, &lst); - dma->rx_sched_cnt += cnt; - if (dma->stats.rx_sched_cnt_max < dma->rx_sched_cnt) - dma->stats.rx_sched_cnt_max = dma->rx_sched_cnt; - - /* Update TX ring posistion */ - dma->rx_ring_head = curr_bd; - - /* Make hardware aware of the newly enabled descriptors - * We must protect from ISR which writes RI|TI - */ - SPIN_LOCK_IRQ(&dma->core->devlock, irqflags); - dmactrl = REG_READ(&dma->regs->ctrl); - dmactrl &= ~(GRSPW_DMACTRL_PS|GRSPW_DMACTRL_PR|GRSPW_DMA_STATUS_ERROR); - dmactrl |= GRSPW_DMACTRL_RE | GRSPW_DMACTRL_RD; - REG_WRITE(&dma->regs->ctrl, dmactrl); - SPIN_UNLOCK_IRQ(&dma->core->devlock, irqflags); - } - - return cnt; -} - -/* Scans the RX desciptor table for scheduled Packet that has been received, - * and moves these Packet from the head of the scheduled queue to the - * tail of the recv queue. - * - * Also, for all packets the status is updated. - * - * - SCHED List -> SENT List - * - * Return Value - * Number of packets moved - */ -STATIC int grspw_rx_process_scheduled(struct grspw_dma_priv *dma) -{ - struct grspw_rxring *curr; - struct grspw_pkt *last_pkt; - int recv_pkt_cnt = 0; - unsigned int ctrl; - struct grspw_list lst; - - curr = dma->rx_ring_tail; - - /* Step into RX ring to find if packets have been scheduled for - * reception. - */ - if (!curr->pkt) - return 0; /* No scheduled packets, thus no received, abort */ - - /* There has been Packets scheduled ==> scheduled Packets may have been - * received and needs to be collected into RECV List. - * - * A temporary list "lst" with all received packets is created. - */ - lst.head = curr->pkt; - - /* Loop until first enabled "unrecveived" SpW Packet is found. - * An unused descriptor is indicated by an unassigned pkt field. - */ - while (curr->pkt && !((ctrl=BD_READ(&curr->bd->ctrl)) & GRSPW_RXBD_EN)) { - /* Handle one received Packet */ - - /* Remember last handled Packet so that insertion/removal from - * Packet lists go fast. - */ - last_pkt = curr->pkt; - - /* Get Length of Packet in bytes, and reception options */ - last_pkt->dlen = (ctrl & GRSPW_RXBD_LEN) >> GRSPW_RXBD_LEN_BIT; - - /* Set flags to indicate error(s) and CRC information, - * and Mark Received. - */ - last_pkt->flags = (last_pkt->flags & ~RXPKT_FLAG_OUTPUT_MASK) | - ((ctrl >> 20) & RXPKT_FLAG_OUTPUT_MASK) | - RXPKT_FLAG_RX; - - /* Packet was Truncated? */ - if (ctrl & GRSPW_RXBD_TR) - dma->stats.rx_err_trunk++; - - /* Error End-Of-Packet? */ - if (ctrl & GRSPW_RXBD_EP) - dma->stats.rx_err_endpkt++; - curr->pkt = NULL; /* Mark descriptor unused */ - - /* Increment */ - curr = curr->next; - recv_pkt_cnt++; - } - - /* 1. Remove all handled packets from scheduled queue - * 2. Put all handled packets into recv queue - */ - if (recv_pkt_cnt > 0) { - - /* Update Stats, Number of Received Packets */ - dma->stats.rx_pkts += recv_pkt_cnt; - - /* Save RX ring posistion */ - dma->rx_ring_tail = curr; - - /* Prepare list for insertion/deleation */ - lst.tail = last_pkt; - - /* Remove received Packets from RX-SCHED queue */ - grspw_list_remove_head_list(&dma->rx_sched, &lst); - dma->rx_sched_cnt -= recv_pkt_cnt; - if (dma->stats.rx_sched_cnt_min > dma->rx_sched_cnt) - dma->stats.rx_sched_cnt_min = dma->rx_sched_cnt; - - /* Insert received Packets into RECV queue */ - grspw_list_append_list(&dma->recv, &lst); - dma->recv_cnt += recv_pkt_cnt; - if (dma->stats.recv_cnt_max < dma->recv_cnt) - dma->stats.recv_cnt_max = dma->recv_cnt; - } - - return recv_pkt_cnt; -} - -/* Try to populate descriptor ring with as many SEND packets as possible. The - * packets assigned with to a descriptor are put in the end of - * the scheduled list. - * - * The number of Packets scheduled is returned. - * - * - SEND List -> TX-SCHED List - * - Descriptors are initialized and enabled for transmission - */ -STATIC int grspw_tx_schedule_send(struct grspw_dma_priv *dma) -{ - int cnt; - unsigned int ctrl, dmactrl; - void *hwaddr; - struct grspw_txring *curr_bd; - struct grspw_pkt *curr_pkt, *last_pkt; - struct grspw_list lst; - SPIN_IRQFLAGS(irqflags); - - /* Is Ready Q empty? */ - if (grspw_list_is_empty(&dma->send)) - return 0; - - cnt = 0; - lst.head = curr_pkt = dma->send.head; - curr_bd = dma->tx_ring_head; - while (!curr_bd->pkt) { - - /* Assign Packet to descriptor */ - curr_bd->pkt = curr_pkt; - - /* Set up header transmission */ - if (curr_pkt->hdr && curr_pkt->hlen) { - hwaddr = curr_pkt->hdr; - if (curr_pkt->flags & PKT_FLAG_TR_HDR) { - drvmgr_translate(dma->core->dev, CPUMEM_TO_DMA, - hwaddr, &hwaddr); - /* translation needed? */ - if (curr_pkt->hdr == hwaddr) - curr_pkt->flags &= ~PKT_FLAG_TR_HDR; - } - BD_WRITE(&curr_bd->bd->haddr, hwaddr); - ctrl = GRSPW_TXBD_EN | curr_pkt->hlen; - } else { - ctrl = GRSPW_TXBD_EN; - } - /* Enable IRQ generation and CRC options as specified - * by user. - */ - ctrl |= (curr_pkt->flags & TXPKT_FLAG_INPUT_MASK) << 8; - - if (curr_bd->next == dma->tx_ring_base) { - /* Wrap around (only needed when smaller descriptor table) */ - ctrl |= GRSPW_TXBD_WR; - } - - /* Is this Packet going to be an interrupt Packet? */ - if ((--dma->tx_irq_en_cnt_curr) <= 0) { - if (dma->cfg.tx_irq_en_cnt == 0) { - /* IRQ is disabled. - * A big number to avoid equal to zero too often - */ - dma->tx_irq_en_cnt_curr = 0x3fffffff; - } else { - dma->tx_irq_en_cnt_curr = dma->cfg.tx_irq_en_cnt; - ctrl |= GRSPW_TXBD_IE; - } - } - - /* Prepare descriptor address. Parts of CTRL is written to - * DLEN for debug-only (CTRL is cleared by HW). - */ - if (curr_pkt->data && curr_pkt->dlen) { - hwaddr = curr_pkt->data; - if (curr_pkt->flags & PKT_FLAG_TR_DATA) { - drvmgr_translate(dma->core->dev, CPUMEM_TO_DMA, - hwaddr, &hwaddr); - /* translation needed? */ - if (curr_pkt->data == hwaddr) - curr_pkt->flags &= ~PKT_FLAG_TR_DATA; - } - BD_WRITE(&curr_bd->bd->daddr, hwaddr); - BD_WRITE(&curr_bd->bd->dlen, curr_pkt->dlen | - ((ctrl & 0x3f000) << 12)); - } else { - BD_WRITE(&curr_bd->bd->daddr, 0); - BD_WRITE(&curr_bd->bd->dlen, ((ctrl & 0x3f000) << 12)); - } - - /* Enable descriptor */ - BD_WRITE(&curr_bd->bd->ctrl, ctrl); - - last_pkt = curr_pkt; - curr_bd = curr_bd->next; - cnt++; - - /* Get Next Packet from Ready Queue */ - if (curr_pkt == dma->send.tail) { - /* Handled all in ready queue. */ - curr_pkt = NULL; - break; - } - curr_pkt = curr_pkt->next; - } - - /* Have Packets been scheduled? */ - if (cnt > 0) { - /* Prepare list for insertion/deleation */ - lst.tail = last_pkt; - - /* Remove scheduled packets from ready queue */ - grspw_list_remove_head_list(&dma->send, &lst); - dma->send_cnt -= cnt; - if (dma->stats.send_cnt_min > dma->send_cnt) - dma->stats.send_cnt_min = dma->send_cnt; - - /* Insert scheduled packets into scheduled queue */ - grspw_list_append_list(&dma->tx_sched, &lst); - dma->tx_sched_cnt += cnt; - if (dma->stats.tx_sched_cnt_max < dma->tx_sched_cnt) - dma->stats.tx_sched_cnt_max = dma->tx_sched_cnt; - - /* Update TX ring posistion */ - dma->tx_ring_head = curr_bd; - - /* Make hardware aware of the newly enabled descriptors */ - SPIN_LOCK_IRQ(&dma->core->devlock, irqflags); - dmactrl = REG_READ(&dma->regs->ctrl); - dmactrl &= ~(GRSPW_DMACTRL_PS|GRSPW_DMACTRL_PR|GRSPW_DMA_STATUS_ERROR); - dmactrl |= GRSPW_DMACTRL_TE; - REG_WRITE(&dma->regs->ctrl, dmactrl); - SPIN_UNLOCK_IRQ(&dma->core->devlock, irqflags); - } - return cnt; -} - -/* Scans the TX desciptor table for transmitted packets, and moves these - * packets from the head of the scheduled queue to the tail of the sent queue. - * - * Also, for all packets the status is updated. - * - * - SCHED List -> SENT List - * - * Return Value - * Number of packet moved - */ -STATIC int grspw_tx_process_scheduled(struct grspw_dma_priv *dma) -{ - struct grspw_txring *curr; - struct grspw_pkt *last_pkt; - int sent_pkt_cnt = 0; - unsigned int ctrl; - struct grspw_list lst; - - curr = dma->tx_ring_tail; - - /* Step into TX ring to find if packets have been scheduled for - * transmission. - */ - if (!curr->pkt) - return 0; /* No scheduled packets, thus no sent, abort */ - - /* There has been Packets scheduled ==> scheduled Packets may have been - * transmitted and needs to be collected into SENT List. - * - * A temporary list "lst" with all sent packets is created. - */ - lst.head = curr->pkt; - - /* Loop until first enabled "un-transmitted" SpW Packet is found. - * An unused descriptor is indicated by an unassigned pkt field. - */ - while (curr->pkt && !((ctrl=BD_READ(&curr->bd->ctrl)) & GRSPW_TXBD_EN)) { - /* Handle one sent Packet */ - - /* Remember last handled Packet so that insertion/removal from - * packet lists go fast. - */ - last_pkt = curr->pkt; - - /* Set flags to indicate error(s) and Mark Sent. - */ - last_pkt->flags = (last_pkt->flags & ~TXPKT_FLAG_OUTPUT_MASK) | - (ctrl & TXPKT_FLAG_LINKERR) | - TXPKT_FLAG_TX; - - /* Sent packet experienced link error? */ - if (ctrl & GRSPW_TXBD_LE) - dma->stats.tx_err_link++; - - curr->pkt = NULL; /* Mark descriptor unused */ - - /* Increment */ - curr = curr->next; - sent_pkt_cnt++; - } - - /* 1. Remove all handled packets from TX-SCHED queue - * 2. Put all handled packets into SENT queue - */ - if (sent_pkt_cnt > 0) { - /* Update Stats, Number of Transmitted Packets */ - dma->stats.tx_pkts += sent_pkt_cnt; - - /* Save TX ring posistion */ - dma->tx_ring_tail = curr; - - /* Prepare list for insertion/deleation */ - lst.tail = last_pkt; - - /* Remove sent packets from TX-SCHED queue */ - grspw_list_remove_head_list(&dma->tx_sched, &lst); - dma->tx_sched_cnt -= sent_pkt_cnt; - if (dma->stats.tx_sched_cnt_min > dma->tx_sched_cnt) - dma->stats.tx_sched_cnt_min = dma->tx_sched_cnt; - - /* Insert received packets into SENT queue */ - grspw_list_append_list(&dma->sent, &lst); - dma->sent_cnt += sent_pkt_cnt; - if (dma->stats.sent_cnt_max < dma->sent_cnt) - dma->stats.sent_cnt_max = dma->sent_cnt; - } - - return sent_pkt_cnt; -} - -void *grspw_dma_open(void *d, int chan_no) -{ - struct grspw_priv *priv = d; - struct grspw_dma_priv *dma; - int size; - - if ((chan_no < 0) || (priv->hwsup.ndma_chans <= chan_no)) - return NULL; - - dma = &priv->dma[chan_no]; - - /* Take GRSPW lock */ - if (rtems_semaphore_obtain(grspw_sem, RTEMS_WAIT, RTEMS_NO_TIMEOUT) - != RTEMS_SUCCESSFUL) - return NULL; - - if (dma->open) { - dma = NULL; - goto out; - } - - dma->started = 0; - - /* Set Default Configuration: - * - * - MAX RX Packet Length = - * - Disable IRQ generation - * - - */ - dma->cfg.rxmaxlen = DEFAULT_RXMAX; - dma->cfg.rx_irq_en_cnt = 0; - dma->cfg.tx_irq_en_cnt = 0; - dma->cfg.flags = DMAFLAG_NO_SPILL; - - /* set to NULL so that error exit works correctly */ - dma->sem_rxdma = RTEMS_ID_NONE; - dma->sem_txdma = RTEMS_ID_NONE; - dma->rx_wait.sem_wait = RTEMS_ID_NONE; - dma->tx_wait.sem_wait = RTEMS_ID_NONE; - dma->rx_ring_base = NULL; - - /* DMA Channel Semaphore created with count = 1 */ - if (rtems_semaphore_create( - rtems_build_name('S', 'D', '0' + priv->index, '0' + chan_no*2), 1, - RTEMS_FIFO | RTEMS_SIMPLE_BINARY_SEMAPHORE | \ - RTEMS_NO_INHERIT_PRIORITY | RTEMS_LOCAL | \ - RTEMS_NO_PRIORITY_CEILING, 0, &dma->sem_rxdma) != RTEMS_SUCCESSFUL) { - dma->sem_rxdma = RTEMS_ID_NONE; - goto err; - } - if (rtems_semaphore_create( - rtems_build_name('S', 'D', '0' + priv->index, '0' + chan_no*2+1), 1, - RTEMS_FIFO | RTEMS_SIMPLE_BINARY_SEMAPHORE | \ - RTEMS_NO_INHERIT_PRIORITY | RTEMS_LOCAL | \ - RTEMS_NO_PRIORITY_CEILING, 0, &dma->sem_txdma) != RTEMS_SUCCESSFUL) { - dma->sem_txdma = RTEMS_ID_NONE; - goto err; - } - - /* Allocate memory for the two descriptor rings */ - size = sizeof(struct grspw_ring) * (GRSPW_RXBD_NR + GRSPW_TXBD_NR); - dma->rx_ring_base = (struct grspw_rxring *)malloc(size); - dma->tx_ring_base = (struct grspw_txring *)&dma->rx_ring_base[GRSPW_RXBD_NR]; - if (dma->rx_ring_base == NULL) - goto err; - - /* Create DMA RX and TX Channel sempahore with count = 0 */ - if (rtems_semaphore_create( - rtems_build_name('S', 'R', '0' + priv->index, '0' + chan_no), 0, - RTEMS_FIFO | RTEMS_SIMPLE_BINARY_SEMAPHORE | \ - RTEMS_NO_INHERIT_PRIORITY | RTEMS_LOCAL | \ - RTEMS_NO_PRIORITY_CEILING, 0, &dma->rx_wait.sem_wait) != RTEMS_SUCCESSFUL) { - dma->rx_wait.sem_wait = RTEMS_ID_NONE; - goto err; - } - if (rtems_semaphore_create( - rtems_build_name('S', 'T', '0' + priv->index, '0' + chan_no), 0, - RTEMS_FIFO | RTEMS_SIMPLE_BINARY_SEMAPHORE | \ - RTEMS_NO_INHERIT_PRIORITY | RTEMS_LOCAL | \ - RTEMS_NO_PRIORITY_CEILING, 0, &dma->tx_wait.sem_wait) != RTEMS_SUCCESSFUL) { - dma->tx_wait.sem_wait = RTEMS_ID_NONE; - goto err; - } - - /* Reset software structures */ - grspw_dma_reset(dma); - - /* Take the device */ - dma->open = 1; -out: - /* Return GRSPW Lock */ - rtems_semaphore_release(grspw_sem); - - return dma; - - /* initialization error happended */ -err: - if (dma->sem_rxdma != RTEMS_ID_NONE) - rtems_semaphore_delete(dma->sem_rxdma); - if (dma->sem_txdma != RTEMS_ID_NONE) - rtems_semaphore_delete(dma->sem_txdma); - if (dma->rx_wait.sem_wait != RTEMS_ID_NONE) - rtems_semaphore_delete(dma->rx_wait.sem_wait); - if (dma->tx_wait.sem_wait != RTEMS_ID_NONE) - rtems_semaphore_delete(dma->tx_wait.sem_wait); - if (dma->rx_ring_base) - free(dma->rx_ring_base); - dma = NULL; - goto out; -} - -/* Initialize Software Structures: - * - Clear all Queues - * - init BD ring - * - init IRQ counter - * - clear statistics counters - * - init wait structures and semaphores - */ -STATIC void grspw_dma_reset(struct grspw_dma_priv *dma) -{ - /* Empty RX and TX queues */ - grspw_list_clr(&dma->ready); - grspw_list_clr(&dma->rx_sched); - grspw_list_clr(&dma->recv); - grspw_list_clr(&dma->send); - grspw_list_clr(&dma->tx_sched); - grspw_list_clr(&dma->sent); - dma->ready_cnt = 0; - dma->rx_sched_cnt = 0; - dma->recv_cnt = 0; - dma->send_cnt = 0; - dma->tx_sched_cnt = 0; - dma->sent_cnt = 0; - - dma->rx_irq_en_cnt_curr = 0; - dma->tx_irq_en_cnt_curr = 0; - - grspw_bdrings_init(dma); - - dma->rx_wait.waiting = 0; - dma->tx_wait.waiting = 0; - - grspw_dma_stats_clr(dma); -} - -int grspw_dma_close(void *c) -{ - struct grspw_dma_priv *dma = c; - - if (!dma->open) - return 0; - - /* Take device lock - Wait until we get semaphore */ - if (rtems_semaphore_obtain(dma->sem_rxdma, RTEMS_WAIT, RTEMS_NO_TIMEOUT) - != RTEMS_SUCCESSFUL) - return -1; - if (rtems_semaphore_obtain(dma->sem_txdma, RTEMS_WAIT, RTEMS_NO_TIMEOUT) - != RTEMS_SUCCESSFUL) { - rtems_semaphore_release(dma->sem_rxdma); - return -1; - } - - /* Can not close active DMA channel. User must stop DMA and make sure - * no threads are active/blocked within driver. - */ - if (dma->started || dma->rx_wait.waiting || dma->tx_wait.waiting) { - rtems_semaphore_release(dma->sem_txdma); - rtems_semaphore_release(dma->sem_rxdma); - return 1; - } - - /* Free resources */ - rtems_semaphore_delete(dma->rx_wait.sem_wait); - rtems_semaphore_delete(dma->tx_wait.sem_wait); - /* Release and delete lock. Operations requiring lock will fail */ - rtems_semaphore_delete(dma->sem_txdma); - rtems_semaphore_delete(dma->sem_rxdma); - dma->sem_txdma = RTEMS_ID_NONE; - dma->sem_rxdma = RTEMS_ID_NONE; - - /* Free memory */ - if (dma->rx_ring_base) - free(dma->rx_ring_base); - dma->rx_ring_base = NULL; - dma->tx_ring_base = NULL; - - dma->open = 0; - return 0; -} - -unsigned int grspw_dma_enable_int(void *c, int rxtx, int force) -{ - struct grspw_dma_priv *dma = c; - int rc = 0; - unsigned int ctrl, ctrl_old; - SPIN_IRQFLAGS(irqflags); - - SPIN_LOCK_IRQ(&dma->core->devlock, irqflags); - if (dma->started == 0) { - rc = 1; /* DMA stopped */ - goto out; - } - ctrl = REG_READ(&dma->regs->ctrl); - ctrl_old = ctrl; - - /* Read/Write DMA error ? */ - if (ctrl & GRSPW_DMA_STATUS_ERROR) { - rc = 2; /* DMA error */ - goto out; - } - - /* DMA has finished a TX/RX packet and user wants work-task to - * take care of DMA table processing. - */ - ctrl &= ~GRSPW_DMACTRL_AT; - - if ((rxtx & 1) == 0) - ctrl &= ~GRSPW_DMACTRL_PR; - else if (force || ((dma->cfg.rx_irq_en_cnt != 0) || - (dma->cfg.flags & DMAFLAG2_RXIE))) - ctrl |= GRSPW_DMACTRL_RI; - - if ((rxtx & 2) == 0) - ctrl &= ~GRSPW_DMACTRL_PS; - else if (force || ((dma->cfg.tx_irq_en_cnt != 0) || - (dma->cfg.flags & DMAFLAG2_TXIE))) - ctrl |= GRSPW_DMACTRL_TI; - - REG_WRITE(&dma->regs->ctrl, ctrl); - /* Re-enabled interrupts previously enabled */ - rc = ctrl_old & (GRSPW_DMACTRL_PR | GRSPW_DMACTRL_PS); -out: - SPIN_UNLOCK_IRQ(&dma->core->devlock, irqflags); - return rc; -} - -/* Schedule List of packets for transmission at some point in - * future. - * - * 1. Move transmitted packets to SENT List (SCHED->SENT) - * 2. Add the requested packets to the SEND List (USER->SEND) - * 3. Schedule as many packets as possible (SEND->SCHED) - */ -int grspw_dma_tx_send(void *c, int opts, struct grspw_list *pkts, int count) -{ - struct grspw_dma_priv *dma = c; - int ret; - - /* Take DMA channel lock */ - if (rtems_semaphore_obtain(dma->sem_txdma, RTEMS_WAIT, RTEMS_NO_TIMEOUT) - != RTEMS_SUCCESSFUL) - return -1; - - if (dma->started == 0) { - ret = 1; /* signal DMA has been stopped */ - goto out; - } - ret = 0; - - /* 1. Move transmitted packets to SENT List (SCHED->SENT) */ - if ((opts & 1) == 0) - grspw_tx_process_scheduled(dma); - - /* 2. Add the requested packets to the SEND List (USER->SEND) */ - if (pkts && (count > 0)) { - grspw_list_append_list(&dma->send, pkts); - dma->send_cnt += count; - if (dma->stats.send_cnt_max < dma->send_cnt) - dma->stats.send_cnt_max = dma->send_cnt; - } - - /* 3. Schedule as many packets as possible (SEND->SCHED) */ - if ((opts & 2) == 0) - grspw_tx_schedule_send(dma); - -out: - /* Unlock DMA channel */ - rtems_semaphore_release(dma->sem_txdma); - - return ret; -} - -int grspw_dma_tx_reclaim(void *c, int opts, struct grspw_list *pkts, int *count) -{ - struct grspw_dma_priv *dma = c; - struct grspw_pkt *pkt, *lastpkt; - int cnt, started; - - /* Take DMA channel lock */ - if (rtems_semaphore_obtain(dma->sem_txdma, RTEMS_WAIT, RTEMS_NO_TIMEOUT) - != RTEMS_SUCCESSFUL) - return -1; - - /* 1. Move transmitted packets to SENT List (SCHED->SENT) */ - started = dma->started; - if ((started > 0) && ((opts & 1) == 0)) - grspw_tx_process_scheduled(dma); - - /* Move all/count SENT packet to the callers list (SENT->USER) */ - if (pkts) { - if ((count == NULL) || (*count == -1) || - (*count >= dma->sent_cnt)) { - /* Move all SENT Packets */ - *pkts = dma->sent; - grspw_list_clr(&dma->sent); - if (count) - *count = dma->sent_cnt; - dma->sent_cnt = 0; - } else { - /* Move a number of SENT Packets */ - pkts->head = pkt = lastpkt = dma->sent.head; - cnt = 0; - while (cnt < *count) { - lastpkt = pkt; - pkt = pkt->next; - cnt++; - } - if (cnt > 0) { - pkts->tail = lastpkt; - grspw_list_remove_head_list(&dma->sent, pkts); - dma->sent_cnt -= cnt; - } else { - grspw_list_clr(pkts); - } - } - } else if (count) { - *count = 0; - } - - /* 3. Schedule as many packets as possible (SEND->SCHED) */ - if ((started > 0) && ((opts & 2) == 0)) - grspw_tx_schedule_send(dma); - - /* Unlock DMA channel */ - rtems_semaphore_release(dma->sem_txdma); - - return (~started) & 1; /* signal DMA has been stopped */ -} - -void grspw_dma_tx_count(void *c, int *send, int *sched, int *sent, int *hw) -{ - struct grspw_dma_priv *dma = c; - int sched_cnt, diff; - unsigned int hwbd; - struct grspw_txbd *tailbd; - - /* Take device lock - Wait until we get semaphore. - * The lock is taken so that the counters are in sync with each other - * and that DMA descriptor table and tx_ring_tail is not being updated - * during HW counter processing in this function. - */ - if (rtems_semaphore_obtain(dma->sem_txdma, RTEMS_WAIT, RTEMS_NO_TIMEOUT) - != RTEMS_SUCCESSFUL) - return; - - if (send) - *send = dma->send_cnt; - sched_cnt = dma->tx_sched_cnt; - if (sched) - *sched = sched_cnt; - if (sent) - *sent = dma->sent_cnt; - if (hw) { - /* Calculate number of descriptors (processed by HW) between - * HW pointer and oldest SW pointer. - */ - hwbd = REG_READ(&dma->regs->txdesc); - tailbd = dma->tx_ring_tail->bd; - diff = ((hwbd - (unsigned int)tailbd) / GRSPW_TXBD_SIZE) & - (GRSPW_TXBD_NR - 1); - /* Handle special case when HW and SW pointers are equal - * because all TX descriptors have been processed by HW. - */ - if ((diff == 0) && (sched_cnt == GRSPW_TXBD_NR) && - ((BD_READ(&tailbd->ctrl) & GRSPW_TXBD_EN) == 0)) { - diff = GRSPW_TXBD_NR; - } - *hw = diff; - } - - /* Unlock DMA channel */ - rtems_semaphore_release(dma->sem_txdma); -} - -static inline int grspw_tx_wait_eval(struct grspw_dma_priv *dma) -{ - int send_val, sent_val; - - if (dma->tx_wait.send_cnt >= (dma->send_cnt + dma->tx_sched_cnt)) - send_val = 1; - else - send_val = 0; - - if (dma->tx_wait.sent_cnt <= dma->sent_cnt) - sent_val = 1; - else - sent_val = 0; - - /* AND or OR ? */ - if (dma->tx_wait.op == 0) - return send_val & sent_val; /* AND */ - else - return send_val | sent_val; /* OR */ -} - -/* Block until send_cnt or fewer packets are Queued in "Send and Scheduled" Q, - * op (AND or OR), sent_cnt or more packet "have been sent" (Sent Q) condition - * is met. - * If a link error occurs and the Stop on Link error is defined, this function - * will also return to caller. - */ -int grspw_dma_tx_wait(void *c, int send_cnt, int op, int sent_cnt, int timeout) -{ - struct grspw_dma_priv *dma = c; - int ret, rc, initialized = 0; - - if (timeout == 0) - timeout = RTEMS_NO_TIMEOUT; - -check_condition: - - /* Take DMA channel lock */ - if (rtems_semaphore_obtain(dma->sem_txdma, RTEMS_WAIT, RTEMS_NO_TIMEOUT) - != RTEMS_SUCCESSFUL) - return -1; - - /* Check so that no other thread is waiting, this driver only supports - * one waiter at a time. - */ - if (initialized == 0 && dma->tx_wait.waiting) { - ret = 3; - goto out_release; - } - - /* Stop if link error or similar (DMA stopped), abort */ - if (dma->started == 0) { - ret = 1; - goto out_release; - } - - /* Set up Condition */ - dma->tx_wait.send_cnt = send_cnt; - dma->tx_wait.op = op; - dma->tx_wait.sent_cnt = sent_cnt; - - if (grspw_tx_wait_eval(dma) == 0) { - /* Prepare Wait */ - initialized = 1; - dma->tx_wait.waiting = 1; - - /* Release DMA channel lock */ - rtems_semaphore_release(dma->sem_txdma); - - /* Try to take Wait lock, if this fail link may have gone down - * or user stopped this DMA channel - */ - rc = rtems_semaphore_obtain(dma->tx_wait.sem_wait, RTEMS_WAIT, - timeout); - if (rc == RTEMS_TIMEOUT) { - ret = 2; - goto out; - } else if (rc == RTEMS_UNSATISFIED || - rc == RTEMS_OBJECT_WAS_DELETED) { - ret = 1; /* sem was flushed/deleted, means DMA stop */ - goto out; - } else if (rc != RTEMS_SUCCESSFUL) { - /* Unknown Error */ - ret = -1; - goto out; - } else if (dma->started == 0) { - ret = 1; - goto out; - } - - /* Check condition once more */ - goto check_condition; - } - - ret = 0; - -out_release: - /* Unlock DMA channel */ - rtems_semaphore_release(dma->sem_txdma); - -out: - if (initialized) - dma->tx_wait.waiting = 0; - return ret; -} - -int grspw_dma_rx_recv(void *c, int opts, struct grspw_list *pkts, int *count) -{ - struct grspw_dma_priv *dma = c; - struct grspw_pkt *pkt, *lastpkt; - int cnt, started; - - /* Take DMA channel lock */ - if (rtems_semaphore_obtain(dma->sem_rxdma, RTEMS_WAIT, RTEMS_NO_TIMEOUT) - != RTEMS_SUCCESSFUL) - return -1; - - /* 1. Move Scheduled packets to RECV List (SCHED->RECV) */ - started = dma->started; - if (((opts & 1) == 0) && (started > 0)) - grspw_rx_process_scheduled(dma); - - /* Move all RECV packet to the callers list */ - if (pkts) { - if ((count == NULL) || (*count == -1) || - (*count >= dma->recv_cnt)) { - /* Move all Received packets */ - *pkts = dma->recv; - grspw_list_clr(&dma->recv); - if ( count ) - *count = dma->recv_cnt; - dma->recv_cnt = 0; - } else { - /* Move a number of RECV Packets */ - pkts->head = pkt = lastpkt = dma->recv.head; - cnt = 0; - while (cnt < *count) { - lastpkt = pkt; - pkt = pkt->next; - cnt++; - } - if (cnt > 0) { - pkts->tail = lastpkt; - grspw_list_remove_head_list(&dma->recv, pkts); - dma->recv_cnt -= cnt; - } else { - grspw_list_clr(pkts); - } - } - } else if (count) { - *count = 0; - } - - /* 3. Schedule as many free packet buffers as possible (READY->SCHED) */ - if (((opts & 2) == 0) && (started > 0)) - grspw_rx_schedule_ready(dma); - - /* Unlock DMA channel */ - rtems_semaphore_release(dma->sem_rxdma); - - return (~started) & 1; -} - -int grspw_dma_rx_prepare(void *c, int opts, struct grspw_list *pkts, int count) -{ - struct grspw_dma_priv *dma = c; - int ret; - - /* Take DMA channel lock */ - if (rtems_semaphore_obtain(dma->sem_rxdma, RTEMS_WAIT, RTEMS_NO_TIMEOUT) - != RTEMS_SUCCESSFUL) - return -1; - - if (dma->started == 0) { - ret = 1; - goto out; - } - - /* 1. Move Received packets to RECV List (SCHED->RECV) */ - if ((opts & 1) == 0) - grspw_rx_process_scheduled(dma); - - /* 2. Add the "free/ready" packet buffers to the READY List (USER->READY) */ - if (pkts && (count > 0)) { - grspw_list_append_list(&dma->ready, pkts); - dma->ready_cnt += count; - if (dma->stats.ready_cnt_max < dma->ready_cnt) - dma->stats.ready_cnt_max = dma->ready_cnt; - } - - /* 3. Schedule as many packets as possible (READY->SCHED) */ - if ((opts & 2) == 0) - grspw_rx_schedule_ready(dma); - - ret = 0; -out: - /* Unlock DMA channel */ - rtems_semaphore_release(dma->sem_rxdma); - - return ret; -} - -void grspw_dma_rx_count(void *c, int *ready, int *sched, int *recv, int *hw) -{ - struct grspw_dma_priv *dma = c; - int sched_cnt, diff; - unsigned int hwbd; - struct grspw_rxbd *tailbd; - - /* Take device lock - Wait until we get semaphore. - * The lock is taken so that the counters are in sync with each other - * and that DMA descriptor table and rx_ring_tail is not being updated - * during HW counter processing in this function. - */ - if (rtems_semaphore_obtain(dma->sem_rxdma, RTEMS_WAIT, RTEMS_NO_TIMEOUT) - != RTEMS_SUCCESSFUL) - return; - - if (ready) - *ready = dma->ready_cnt; - sched_cnt = dma->rx_sched_cnt; - if (sched) - *sched = sched_cnt; - if (recv) - *recv = dma->recv_cnt; - if (hw) { - /* Calculate number of descriptors (processed by HW) between - * HW pointer and oldest SW pointer. - */ - hwbd = REG_READ(&dma->regs->rxdesc); - tailbd = dma->rx_ring_tail->bd; - diff = ((hwbd - (unsigned int)tailbd) / GRSPW_RXBD_SIZE) & - (GRSPW_RXBD_NR - 1); - /* Handle special case when HW and SW pointers are equal - * because all RX descriptors have been processed by HW. - */ - if ((diff == 0) && (sched_cnt == GRSPW_RXBD_NR) && - ((BD_READ(&tailbd->ctrl) & GRSPW_RXBD_EN) == 0)) { - diff = GRSPW_RXBD_NR; - } - *hw = diff; - } - - /* Unlock DMA channel */ - rtems_semaphore_release(dma->sem_rxdma); -} - -static inline int grspw_rx_wait_eval(struct grspw_dma_priv *dma) -{ - int ready_val, recv_val; - - if (dma->rx_wait.ready_cnt >= (dma->ready_cnt + dma->rx_sched_cnt)) - ready_val = 1; - else - ready_val = 0; - - if (dma->rx_wait.recv_cnt <= dma->recv_cnt) - recv_val = 1; - else - recv_val = 0; - - /* AND or OR ? */ - if (dma->rx_wait.op == 0) - return ready_val & recv_val; /* AND */ - else - return ready_val | recv_val; /* OR */ -} - -/* Block until recv_cnt or more packets are Queued in RECV Q, op (AND or OR), - * ready_cnt or fewer packet buffers are available in the "READY and Scheduled" Q, - * condition is met. - * If a link error occurs and the Stop on Link error is defined, this function - * will also return to caller, however with an error. - */ -int grspw_dma_rx_wait(void *c, int recv_cnt, int op, int ready_cnt, int timeout) -{ - struct grspw_dma_priv *dma = c; - int ret, rc, initialized = 0; - - if (timeout == 0) - timeout = RTEMS_NO_TIMEOUT; - -check_condition: - - /* Take DMA channel lock */ - if (rtems_semaphore_obtain(dma->sem_rxdma, RTEMS_WAIT, RTEMS_NO_TIMEOUT) - != RTEMS_SUCCESSFUL) - return -1; - - /* Check so that no other thread is waiting, this driver only supports - * one waiter at a time. - */ - if (initialized == 0 && dma->rx_wait.waiting) { - ret = 3; - goto out_release; - } - - /* Stop if link error or similar (DMA stopped), abort */ - if (dma->started == 0) { - ret = 1; - goto out_release; - } - - /* Set up Condition */ - dma->rx_wait.recv_cnt = recv_cnt; - dma->rx_wait.op = op; - dma->rx_wait.ready_cnt = ready_cnt; - - if (grspw_rx_wait_eval(dma) == 0) { - /* Prepare Wait */ - initialized = 1; - dma->rx_wait.waiting = 1; - - /* Release channel lock */ - rtems_semaphore_release(dma->sem_rxdma); - - /* Try to take Wait lock, if this fail link may have gone down - * or user stopped this DMA channel - */ - rc = rtems_semaphore_obtain(dma->rx_wait.sem_wait, RTEMS_WAIT, - timeout); - if (rc == RTEMS_TIMEOUT) { - ret = 2; - goto out; - } else if (rc == RTEMS_UNSATISFIED || - rc == RTEMS_OBJECT_WAS_DELETED) { - ret = 1; /* sem was flushed/deleted, means DMA stop */ - goto out; - } else if (rc != RTEMS_SUCCESSFUL) { - /* Unknown Error */ - ret = -1; - goto out; - } else if (dma->started == 0) { - ret = 1; - goto out; - } - - /* Check condition once more */ - goto check_condition; - } - - ret = 0; - -out_release: - /* Unlock DMA channel */ - rtems_semaphore_release(dma->sem_rxdma); - -out: - if (initialized) - dma->rx_wait.waiting = 0; - return ret; -} - -int grspw_dma_config(void *c, struct grspw_dma_config *cfg) -{ - struct grspw_dma_priv *dma = c; - - if (dma->started || !cfg) - return -1; - - if (cfg->flags & ~(DMAFLAG_MASK | DMAFLAG2_MASK)) - return -1; - - /* Update Configuration */ - memcpy(&dma->cfg, cfg, sizeof(*cfg)); - - return 0; -} - -void grspw_dma_config_read(void *c, struct grspw_dma_config *cfg) -{ - struct grspw_dma_priv *dma = c; - - /* Copy Current Configuration */ - memcpy(cfg, &dma->cfg, sizeof(*cfg)); -} - -void grspw_dma_stats_read(void *c, struct grspw_dma_stats *sts) -{ - struct grspw_dma_priv *dma = c; - - memcpy(sts, &dma->stats, sizeof(dma->stats)); -} - -void grspw_dma_stats_clr(void *c) -{ - struct grspw_dma_priv *dma = c; - - /* Clear most of the statistics */ - memset(&dma->stats, 0, sizeof(dma->stats)); - - /* Init proper default values so that comparisons will work the - * first time. - */ - dma->stats.send_cnt_min = 0x3fffffff; - dma->stats.tx_sched_cnt_min = 0x3fffffff; - dma->stats.ready_cnt_min = 0x3fffffff; - dma->stats.rx_sched_cnt_min = 0x3fffffff; -} - -int grspw_dma_start(void *c) -{ - struct grspw_dma_priv *dma = c; - struct grspw_dma_regs *dregs = dma->regs; - unsigned int ctrl; - SPIN_IRQFLAGS(irqflags); - - if (dma->started) - return 0; - - /* Initialize Software Structures: - * - Clear all Queues - * - init BD ring - * - init IRQ counter - * - clear statistics counters - * - init wait structures and semaphores - */ - grspw_dma_reset(dma); - - /* RX&RD and TX is not enabled until user fills SEND and READY Queue - * with SpaceWire Packet buffers. So we do not have to worry about - * IRQs for this channel just yet. However other DMA channels - * may be active. - * - * Some functionality that is not changed during started mode is set up - * once and for all here: - * - * - RX MAX Packet length - * - TX Descriptor base address to first BD in TX ring (not enabled) - * - RX Descriptor base address to first BD in RX ring (not enabled) - * - IRQs (TX DMA, RX DMA, DMA ERROR) - * - Strip PID - * - Strip Address - * - No Spill - * - Receiver Enable - * - disable on link error (LE) - * - * Note that the address register and the address enable bit in DMACTRL - * register must be left untouched, they are configured on a GRSPW - * core level. - * - * Note that the receiver is enabled here, but since descriptors are - * not enabled the GRSPW core may stop/pause RX (if NS bit set) until - * descriptors are enabled or it may ignore RX packets (NS=0) until - * descriptors are enabled (writing RD bit). - */ - REG_WRITE(&dregs->txdesc, dma->tx_bds_hwa); - REG_WRITE(&dregs->rxdesc, dma->rx_bds_hwa); - - /* MAX Packet length */ - REG_WRITE(&dma->regs->rxmax, dma->cfg.rxmaxlen); - - ctrl = GRSPW_DMACTRL_AI | GRSPW_DMACTRL_PS | GRSPW_DMACTRL_PR | - GRSPW_DMACTRL_TA | GRSPW_DMACTRL_RA | GRSPW_DMACTRL_RE | - (dma->cfg.flags & DMAFLAG_MASK) << GRSPW_DMACTRL_NS_BIT; - if (dma->core->dis_link_on_err & LINKOPTS_DIS_ONERR) - ctrl |= GRSPW_DMACTRL_LE; - if (dma->cfg.rx_irq_en_cnt != 0 || dma->cfg.flags & DMAFLAG2_RXIE) - ctrl |= GRSPW_DMACTRL_RI; - if (dma->cfg.tx_irq_en_cnt != 0 || dma->cfg.flags & DMAFLAG2_TXIE) - ctrl |= GRSPW_DMACTRL_TI; - SPIN_LOCK_IRQ(&dma->core->devlock, irqflags); - ctrl |= REG_READ(&dma->regs->ctrl) & GRSPW_DMACTRL_EN; - REG_WRITE(&dregs->ctrl, ctrl); - SPIN_UNLOCK_IRQ(&dma->core->devlock, irqflags); - - dma->started = 1; /* open up other DMA interfaces */ - - return 0; -} - -STATIC void grspw_dma_stop_locked(struct grspw_dma_priv *dma) -{ - SPIN_IRQFLAGS(irqflags); - - if (dma->started == 0) - return; - dma->started = 0; - - SPIN_LOCK_IRQ(&dma->core->devlock, irqflags); - grspw_hw_dma_stop(dma); - SPIN_UNLOCK_IRQ(&dma->core->devlock, irqflags); - - /* From here no more packets will be sent, however - * there may still exist scheduled packets that has been - * sent, and packets in the SEND Queue waiting for free - * descriptors. All packets are moved to the SENT Queue - * so that the user may get its buffers back, the user - * must look at the TXPKT_FLAG_TX in order to determine - * if the packet was sent or not. - */ - - /* Retreive scheduled all sent packets */ - grspw_tx_process_scheduled(dma); - - /* Move un-sent packets in SEND and SCHED queue to the - * SENT Queue. (never marked sent) - */ - if (!grspw_list_is_empty(&dma->tx_sched)) { - grspw_list_append_list(&dma->sent, &dma->tx_sched); - grspw_list_clr(&dma->tx_sched); - dma->sent_cnt += dma->tx_sched_cnt; - dma->tx_sched_cnt = 0; - } - if (!grspw_list_is_empty(&dma->send)) { - grspw_list_append_list(&dma->sent, &dma->send); - grspw_list_clr(&dma->send); - dma->sent_cnt += dma->send_cnt; - dma->send_cnt = 0; - } - - /* Similar for RX */ - grspw_rx_process_scheduled(dma); - if (!grspw_list_is_empty(&dma->rx_sched)) { - grspw_list_append_list(&dma->recv, &dma->rx_sched); - grspw_list_clr(&dma->rx_sched); - dma->recv_cnt += dma->rx_sched_cnt; - dma->rx_sched_cnt = 0; - } - if (!grspw_list_is_empty(&dma->ready)) { - grspw_list_append_list(&dma->recv, &dma->ready); - grspw_list_clr(&dma->ready); - dma->recv_cnt += dma->ready_cnt; - dma->ready_cnt = 0; - } - - /* Throw out blocked threads */ - rtems_semaphore_flush(dma->rx_wait.sem_wait); - rtems_semaphore_flush(dma->tx_wait.sem_wait); -} - -void grspw_dma_stop(void *c) -{ - struct grspw_dma_priv *dma = c; - - /* If DMA channel is closed we should not access the semaphore */ - if (!dma->open) - return; - - /* Take DMA Channel lock */ - if (rtems_semaphore_obtain(dma->sem_rxdma, RTEMS_WAIT, RTEMS_NO_TIMEOUT) - != RTEMS_SUCCESSFUL) - return; - if (rtems_semaphore_obtain(dma->sem_txdma, RTEMS_WAIT, RTEMS_NO_TIMEOUT) - != RTEMS_SUCCESSFUL) { - rtems_semaphore_release(dma->sem_rxdma); - return; - } - - grspw_dma_stop_locked(dma); - - rtems_semaphore_release(dma->sem_txdma); - rtems_semaphore_release(dma->sem_rxdma); -} - -/* Do general work, invoked indirectly from ISR */ -static void grspw_work_shutdown_func(struct grspw_priv *priv) -{ - int i; - - /* Link is down for some reason, and the user has configured - * that we stop all (open) DMA channels and throw out all their - * blocked threads. - */ - for (i=0; ihwsup.ndma_chans; i++) - grspw_dma_stop(&priv->dma[i]); - grspw_hw_stop(priv); -} - -/* Do DMA work on one channel, invoked indirectly from ISR */ -static void grspw_work_dma_func(struct grspw_dma_priv *dma, unsigned int msg) -{ - int tx_cond_true, rx_cond_true, rxtx; - - /* If DMA channel is closed we should not access the semaphore */ - if (dma->open == 0) - return; - - dma->stats.irq_cnt++; - - /* Look at cause we were woken up and clear source */ - rxtx = 0; - if (msg & WORK_DMA_RX_MASK) - rxtx |= 1; - if (msg & WORK_DMA_TX_MASK) - rxtx |= 2; - switch (grspw_dma_enable_int(dma, rxtx, 0)) { - case 1: - /* DMA stopped */ - return; - case 2: - /* DMA error -> Stop DMA channel (both RX and TX) */ - if (msg & WORK_DMA_ER_MASK) { - /* DMA error and user wants work-task to handle error */ - grspw_dma_stop(dma); - grspw_work_event(WORKTASK_EV_DMA_STOP, msg); - } - return; - default: - break; - } - if (msg == 0) - return; - - rx_cond_true = 0; - tx_cond_true = 0; - - if ((dma->cfg.flags & DMAFLAG2_IRQD_MASK) == DMAFLAG2_IRQD_BOTH) { - /* In case both interrupt sources are disabled simultaneously - * by the ISR the re-enabling of the interrupt source must also - * do so to avoid missing interrupts. Both RX and TX process - * will be forced. - */ - msg |= WORK_DMA_RX_MASK | WORK_DMA_TX_MASK; - } - - if (msg & WORK_DMA_RX_MASK) { - /* Do RX Work */ - - /* Take DMA channel RX lock */ - if (rtems_semaphore_obtain(dma->sem_rxdma, RTEMS_WAIT, RTEMS_NO_TIMEOUT) - != RTEMS_SUCCESSFUL) - return; - - dma->stats.rx_work_cnt++; - grspw_rx_process_scheduled(dma); - if (dma->started) { - dma->stats.rx_work_enabled += - grspw_rx_schedule_ready(dma); - /* Check to see if condition for waking blocked - * USER task is fullfilled. - */ - if (dma->rx_wait.waiting) - rx_cond_true = grspw_rx_wait_eval(dma); - } - rtems_semaphore_release(dma->sem_rxdma); - } - - if (msg & WORK_DMA_TX_MASK) { - /* Do TX Work */ - - /* Take DMA channel TX lock */ - if (rtems_semaphore_obtain(dma->sem_txdma, RTEMS_WAIT, RTEMS_NO_TIMEOUT) - != RTEMS_SUCCESSFUL) - return; - - dma->stats.tx_work_cnt++; - grspw_tx_process_scheduled(dma); - if (dma->started) { - dma->stats.tx_work_enabled += - grspw_tx_schedule_send(dma); - /* Check to see if condition for waking blocked - * USER task is fullfilled. - */ - if (dma->tx_wait.waiting) - tx_cond_true = grspw_tx_wait_eval(dma); - } - rtems_semaphore_release(dma->sem_txdma); - } - - if (rx_cond_true) - rtems_semaphore_release(dma->rx_wait.sem_wait); - - if (tx_cond_true) - rtems_semaphore_release(dma->tx_wait.sem_wait); -} - -/* Work task is receiving work for the work message queue posted from - * the ISR. - */ -void grspw_work_func(rtems_id msgQ) -{ - unsigned int message = 0, msg; - size_t size; - struct grspw_priv *priv; - int i; - - /* Wait for ISR to schedule work */ - while (rtems_message_queue_receive(msgQ, &message, &size, - RTEMS_WAIT, RTEMS_NO_TIMEOUT) == RTEMS_SUCCESSFUL) { - if (message & WORK_QUIT_TASK) - break; - - /* Handle work */ - priv = priv_tab[message >> WORK_CORE_BIT]; - if (message & WORK_SHUTDOWN) { - grspw_work_shutdown_func(priv); - - grspw_work_event(WORKTASK_EV_SHUTDOWN, message); - } else if (message & WORK_DMA_MASK) { - for (i = 0; i < priv->hwsup.ndma_chans; i++) { - msg = message & - (WORK_CORE_MASK | WORK_DMA_CHAN_MASK(i)); - if (msg) - grspw_work_dma_func(&priv->dma[i], msg); - } - } - message = 0; - } - - if (message & WORK_FREE_MSGQ) - rtems_message_queue_delete(msgQ); - - grspw_work_event(WORKTASK_EV_QUIT, message); - rtems_task_delete(RTEMS_SELF); -} - -STATIC void grspw_isr(void *data) -{ - struct grspw_priv *priv = data; - unsigned int dma_stat, stat, stat_clrmsk, ctrl, icctrl, timecode, irqs; - unsigned int rxirq, rxack, intto; - int i, handled = 0, call_user_int_isr; - unsigned int message = WORK_NONE, dma_en; - SPIN_ISR_IRQFLAGS(irqflags); - - /* Get Status from Hardware */ - stat = REG_READ(&priv->regs->status); - stat_clrmsk = stat & (GRSPW_STS_TO | GRSPW_STAT_ERROR) & - (GRSPW_STS_TO | priv->stscfg); - - /* Make sure to put the timecode handling first in order to get the - * smallest possible interrupt latency - */ - if ((stat & GRSPW_STS_TO) && (priv->tcisr != NULL)) { - ctrl = REG_READ(&priv->regs->ctrl); - if (ctrl & GRSPW_CTRL_TQ) { - /* Timecode received. Let custom function handle this */ - timecode = REG_READ(&priv->regs->time) & - (GRSPW_TIME_CTRL | GRSPW_TIME_TCNT); - (priv->tcisr)(priv->tcisr_arg, timecode); - } - } - - /* Get Interrupt status from hardware */ - icctrl = REG_READ(&priv->regs->icctrl); - if ((icctrl & GRSPW_ICCTRL_IRQSRC_MASK) && (priv->icisr != NULL)) { - call_user_int_isr = 0; - rxirq = rxack = intto = 0; - - if ((icctrl & GRSPW_ICCTRL_IQ) && - (rxirq = REG_READ(&priv->regs->icrx)) != 0) - call_user_int_isr = 1; - - if ((icctrl & GRSPW_ICCTRL_AQ) && - (rxack = REG_READ(&priv->regs->icack)) != 0) - call_user_int_isr = 1; - - if ((icctrl & GRSPW_ICCTRL_TQ) && - (intto = REG_READ(&priv->regs->ictimeout)) != 0) - call_user_int_isr = 1; - - /* Let custom functions handle this POTENTIAL SPW interrupt. The - * user function is called even if no such IRQ has happened! - * User must make sure to clear all interrupts that have been - * handled from the three registers by writing a one. - */ - if (call_user_int_isr) - priv->icisr(priv->icisr_arg, rxirq, rxack, intto); - } - - /* An Error occured? */ - if (stat & GRSPW_STAT_ERROR) { - /* Wake Global WorkQ */ - handled = 1; - - if (stat & GRSPW_STS_EE) - priv->stats.err_eeop++; - - if (stat & GRSPW_STS_IA) - priv->stats.err_addr++; - - if (stat & GRSPW_STS_PE) - priv->stats.err_parity++; - - if (stat & GRSPW_STS_DE) - priv->stats.err_disconnect++; - - if (stat & GRSPW_STS_ER) - priv->stats.err_escape++; - - if (stat & GRSPW_STS_CE) - priv->stats.err_credit++; - - if (stat & GRSPW_STS_WE) - priv->stats.err_wsync++; - - if (((priv->dis_link_on_err >> 16) & stat) && - (REG_READ(&priv->regs->ctrl) & GRSPW_CTRL_IE)) { - /* Disable the link, no more transfers are expected - * on any DMA channel. - */ - SPIN_LOCK(&priv->devlock, irqflags); - ctrl = REG_READ(&priv->regs->ctrl); - REG_WRITE(&priv->regs->ctrl, GRSPW_CTRL_LD | - (ctrl & ~(GRSPW_CTRL_IE|GRSPW_CTRL_LS))); - SPIN_UNLOCK(&priv->devlock, irqflags); - /* Signal to work-thread to stop DMA and clean up */ - message = WORK_SHUTDOWN; - } - } - - /* Clear Status Flags */ - if (stat_clrmsk) { - handled = 1; - REG_WRITE(&priv->regs->status, stat_clrmsk); - } - - /* A DMA transfer or Error occured? In that case disable more IRQs - * from the DMA channel, then invoke the workQ. - * - * Also the GI interrupt flag may not be available for older - * designs where (was added together with mutiple DMA channels). - */ - SPIN_LOCK(&priv->devlock, irqflags); - for (i=0; ihwsup.ndma_chans; i++) { - dma_stat = REG_READ(&priv->regs->dma[i].ctrl); - /* Check for Errors and if Packets been sent or received if - * respective IRQ are enabled - */ - irqs = (((dma_stat << 3) & (GRSPW_DMACTRL_PR | GRSPW_DMACTRL_PS)) - | GRSPW_DMA_STATUS_ERROR) & dma_stat; - if (!irqs) - continue; - - handled = 1; - - /* DMA error has priority, if error happens it is assumed that - * the common work-queue stops the DMA operation for that - * channel and makes the DMA tasks exit from their waiting - * functions (both RX and TX tasks). - * - * Disable Further IRQs (until enabled again) - * from this DMA channel. Let the status - * bit remain so that they can be handled by - * work function. - */ - if (irqs & GRSPW_DMA_STATUS_ERROR) { - REG_WRITE(&priv->regs->dma[i].ctrl, dma_stat & - ~(GRSPW_DMACTRL_RI | GRSPW_DMACTRL_TI | - GRSPW_DMACTRL_PR | GRSPW_DMACTRL_PS | - GRSPW_DMACTRL_RA | GRSPW_DMACTRL_TA | - GRSPW_DMACTRL_AT)); - message |= WORK_DMA_ER(i); - } else { - /* determine if RX/TX interrupt source(s) shall remain - * enabled. - */ - if (priv->dma[i].cfg.flags & DMAFLAG2_IRQD_SRC) { - dma_en = ~irqs >> 3; - } else { - dma_en = priv->dma[i].cfg.flags >> - (DMAFLAG2_IRQD_BIT - GRSPW_DMACTRL_TI_BIT); - } - dma_en &= (GRSPW_DMACTRL_RI | GRSPW_DMACTRL_TI); - REG_WRITE(&priv->regs->dma[i].ctrl, dma_stat & - (~(GRSPW_DMACTRL_RI | GRSPW_DMACTRL_TI | - GRSPW_DMACTRL_PR | GRSPW_DMACTRL_PS | - GRSPW_DMACTRL_RA | GRSPW_DMACTRL_TA | - GRSPW_DMACTRL_AT) | dma_en)); - message |= WORK_DMA(i, irqs >> GRSPW_DMACTRL_PS_BIT); - } - } - SPIN_UNLOCK(&priv->devlock, irqflags); - - if (handled != 0) - priv->stats.irq_cnt++; - - /* Schedule work by sending message to work thread */ - if (message != WORK_NONE && priv->wc.msgisr) { - int status; - message |= WORK_CORE(priv->index); - /* func interface compatible with msgQSend() on purpose, but - * at the same time the user can assign a custom function to - * handle DMA RX/TX operations as indicated by the "message" - * and clear the handled bits before given to msgQSend(). - */ - status = priv->wc.msgisr(priv->wc.msgisr_arg, &message, 4); - if (status != RTEMS_SUCCESSFUL) { - printk("grspw_isr(%d): message fail %d (0x%x)\n", - priv->index, status, message); - } - } -} - -STATIC void grspw_hw_dma_stop(struct grspw_dma_priv *dma) -{ - unsigned int ctrl; - struct grspw_dma_regs *dregs = dma->regs; - - ctrl = REG_READ(&dregs->ctrl) & (GRSPW_DMACTRL_LE | GRSPW_DMACTRL_EN | - GRSPW_DMACTRL_SP | GRSPW_DMACTRL_SA | GRSPW_DMACTRL_NS); - ctrl |= GRSPW_DMACTRL_AT; - REG_WRITE(&dregs->ctrl, ctrl); -} - -STATIC void grspw_hw_dma_softreset(struct grspw_dma_priv *dma) -{ - unsigned int ctrl; - struct grspw_dma_regs *dregs = dma->regs; - - ctrl = REG_READ(&dregs->ctrl) & (GRSPW_DMACTRL_LE | GRSPW_DMACTRL_EN); - REG_WRITE(&dregs->ctrl, ctrl); - - REG_WRITE(&dregs->rxmax, DEFAULT_RXMAX); - REG_WRITE(&dregs->txdesc, 0); - REG_WRITE(&dregs->rxdesc, 0); -} - -/* Hardware Action: - * - stop DMA - * - do not bring down the link (RMAP may be active) - * - RMAP settings untouched (RMAP may be active) - * - port select untouched (RMAP may be active) - * - timecodes are disabled - * - IRQ generation disabled - * - status not cleared (let user analyze it if requested later on) - * - Node address / First DMA channels Node address - * is untouched (RMAP may be active) - */ -STATIC void grspw_hw_stop(struct grspw_priv *priv) -{ - int i; - unsigned int ctrl; - SPIN_IRQFLAGS(irqflags); - - SPIN_LOCK_IRQ(&priv->devlock, irqflags); - - for (i=0; ihwsup.ndma_chans; i++) - grspw_hw_dma_stop(&priv->dma[i]); - - ctrl = REG_READ(&priv->regs->ctrl); - REG_WRITE(&priv->regs->ctrl, ctrl & ( - GRSPW_CTRL_LD | GRSPW_CTRL_LS | GRSPW_CTRL_AS | - GRSPW_CTRL_RE | GRSPW_CTRL_RD | - GRSPW_CTRL_NP | GRSPW_CTRL_PS)); - - SPIN_UNLOCK_IRQ(&priv->devlock, irqflags); -} - -/* Soft reset of GRSPW core registers */ -STATIC void grspw_hw_softreset(struct grspw_priv *priv) -{ - int i; - unsigned int tmp; - - for (i=0; ihwsup.ndma_chans; i++) - grspw_hw_dma_softreset(&priv->dma[i]); - - REG_WRITE(&priv->regs->status, 0xffffffff); - REG_WRITE(&priv->regs->time, 0); - /* Clear all but valuable reset values of ICCTRL */ - tmp = REG_READ(&priv->regs->icctrl); - tmp &= GRSPW_ICCTRL_INUM | GRSPW_ICCTRL_BIRQ | GRSPW_ICCTRL_TXIRQ; - tmp |= GRSPW_ICCTRL_ID; - REG_WRITE(&priv->regs->icctrl, tmp); - REG_WRITE(&priv->regs->icrx, 0xffffffff); - REG_WRITE(&priv->regs->icack, 0xffffffff); - REG_WRITE(&priv->regs->ictimeout, 0xffffffff); -} - -int grspw_dev_count(void) -{ - return grspw_count; -} - -void grspw_initialize_user(void *(*devfound)(int), void (*devremove)(int,void*)) -{ - int i; - struct grspw_priv *priv; - - /* Set new Device Found Handler */ - grspw_dev_add = devfound; - grspw_dev_del = devremove; - - if (grspw_initialized == 1 && grspw_dev_add) { - /* Call callback for every previously found device */ - for (i=0; idata = grspw_dev_add(i); - } - } -} - -/* Get a value at least 6.4us in number of clock cycles */ -static unsigned int grspw1_calc_timer64(int freq_khz) -{ - unsigned int timer64 = (freq_khz * 64 + 9999) / 10000; - return timer64 & 0xfff; -} - -/* Get a value at least 850ns in number of clock cycles - 3 */ -static unsigned int grspw1_calc_discon(int freq_khz) -{ - unsigned int discon = ((freq_khz * 85 + 99999) / 100000) - 3; - return discon & 0x3ff; -} - -/******************* Driver manager interface ***********************/ - -/* Driver prototypes */ -static int grspw_common_init(void); -static int grspw2_init3(struct drvmgr_dev *dev); - -static struct drvmgr_drv_ops grspw2_ops = -{ - .init = {NULL, NULL, grspw2_init3, NULL}, - .remove = NULL, - .info = NULL -}; - -static struct amba_dev_id grspw2_ids[] = -{ - {VENDOR_GAISLER, GAISLER_SPW}, /* not yet supported */ - {VENDOR_GAISLER, GAISLER_SPW2}, - {VENDOR_GAISLER, GAISLER_SPW2_DMA}, - {0, 0} /* Mark end of table */ -}; - -static struct amba_drv_info grspw2_drv_info = -{ - { - DRVMGR_OBJ_DRV, /* Driver */ - NULL, /* Next driver */ - NULL, /* Device list */ - DRIVER_AMBAPP_GAISLER_GRSPW2_ID,/* Driver ID */ - "GRSPW_PKT_DRV", /* Driver Name */ - DRVMGR_BUS_TYPE_AMBAPP, /* Bus Type */ - &grspw2_ops, - NULL, /* Funcs */ - 0, /* No devices yet */ - sizeof(struct grspw_priv), /* Let DrvMgr alloc priv */ - }, - &grspw2_ids[0] -}; - -void grspw2_register_drv (void) -{ - GRSPW_DBG("Registering GRSPW2 packet driver\n"); - drvmgr_drv_register(&grspw2_drv_info.general); -} - -static int grspw2_init3(struct drvmgr_dev *dev) -{ - struct grspw_priv *priv; - struct amba_dev_info *ambadev; - struct ambapp_core *pnpinfo; - int i, size; - unsigned int ctrl, icctrl, numi; - union drvmgr_key_value *value; - - GRSPW_DBG("GRSPW[%d] on bus %s\n", dev->minor_drv, - dev->parent->dev->name); - - if (grspw_count >= GRSPW_MAX) - return DRVMGR_ENORES; - - priv = dev->priv; - if (priv == NULL) - return DRVMGR_NOMEM; - priv->dev = dev; - - /* If first device init common part of driver */ - if (grspw_common_init()) - return DRVMGR_FAIL; - - /*** Now we take care of device initialization ***/ - - /* Get device information from AMBA PnP information */ - ambadev = (struct amba_dev_info *)dev->businfo; - if (ambadev == NULL) - return -1; - pnpinfo = &ambadev->info; - priv->irq = pnpinfo->irq; - priv->regs = (struct grspw_regs *)pnpinfo->apb_slv->start; - - /* Read Hardware Support from Control Register */ - ctrl = REG_READ(&priv->regs->ctrl); - priv->hwsup.rmap = (ctrl & GRSPW_CTRL_RA) >> GRSPW_CTRL_RA_BIT; - priv->hwsup.rmap_crc = (ctrl & GRSPW_CTRL_RC) >> GRSPW_CTRL_RC_BIT; - priv->hwsup.rx_unalign = (ctrl & GRSPW_CTRL_RX) >> GRSPW_CTRL_RX_BIT; - priv->hwsup.nports = 1 + ((ctrl & GRSPW_CTRL_PO) >> GRSPW_CTRL_PO_BIT); - priv->hwsup.ndma_chans = 1 + ((ctrl & GRSPW_CTRL_NCH) >> GRSPW_CTRL_NCH_BIT); - priv->hwsup.irq = ((ctrl & GRSPW_CTRL_ID) >> GRSPW_CTRL_ID_BIT); - icctrl = REG_READ(&priv->regs->icctrl); - numi = (icctrl & GRSPW_ICCTRL_NUMI) >> GRSPW_ICCTRL_NUMI_BIT; - if (numi > 0) - priv->hwsup.irq_num = 1 << (numi - 1); - else - priv->hwsup.irq_num = 0; - - /* Construct hardware version identification */ - priv->hwsup.hw_version = pnpinfo->device << 16 | pnpinfo->apb_slv->ver; - - if ((pnpinfo->device == GAISLER_SPW2) || - (pnpinfo->device == GAISLER_SPW2_DMA)) { - priv->hwsup.strip_adr = 1; /* All GRSPW2 can strip Address */ - priv->hwsup.strip_pid = 1; /* All GRSPW2 can strip PID */ - } else { - unsigned int apb_hz, apb_khz; - - /* Autodetect GRSPW1 features? */ - priv->hwsup.strip_adr = 0; - priv->hwsup.strip_pid = 0; - - drvmgr_freq_get(dev, DEV_APB_SLV, &apb_hz); - apb_khz = apb_hz / 1000; - - REG_WRITE(&priv->regs->timer, - ((grspw1_calc_discon(apb_khz) & 0x3FF) << 12) | - (grspw1_calc_timer64(apb_khz) & 0xFFF)); - } - - /* Probe width of SpaceWire Interrupt ISR timers. All have the same - * width... so only the first is probed, if no timer result will be - * zero. - */ - REG_WRITE(&priv->regs->icrlpresc, 0x7fffffff); - ctrl = REG_READ(&priv->regs->icrlpresc); - REG_WRITE(&priv->regs->icrlpresc, 0); - priv->hwsup.itmr_width = 0; - while (ctrl & 1) { - priv->hwsup.itmr_width++; - ctrl = ctrl >> 1; - } - - /* Let user limit the number of DMA channels on this core to save - * space. Only the first nDMA channels will be available. - */ - value = drvmgr_dev_key_get(priv->dev, "nDMA", DRVMGR_KT_INT); - if (value && (value->i < priv->hwsup.ndma_chans)) - priv->hwsup.ndma_chans = value->i; - - /* Allocate and init Memory for all DMA channels */ - size = sizeof(struct grspw_dma_priv) * priv->hwsup.ndma_chans; - priv->dma = (struct grspw_dma_priv *) malloc(size); - if (priv->dma == NULL) - return DRVMGR_NOMEM; - memset(priv->dma, 0, size); - for (i=0; ihwsup.ndma_chans; i++) { - priv->dma[i].core = priv; - priv->dma[i].index = i; - priv->dma[i].regs = &priv->regs->dma[i]; - } - - /* Startup Action: - * - stop DMA - * - do not bring down the link (RMAP may be active) - * - RMAP settings untouched (RMAP may be active) - * - port select untouched (RMAP may be active) - * - timecodes are diabled - * - IRQ generation disabled - * - status cleared - * - Node address / First DMA channels Node address - * is untouched (RMAP may be active) - */ - grspw_hw_stop(priv); - grspw_hw_softreset(priv); - - /* Register character device in registered region */ - priv->index = grspw_count; - priv_tab[priv->index] = priv; - grspw_count++; - - /* Device name */ - sprintf(priv->devname, "grspw%d", priv->index); - - /* Tell above layer about new device */ - if (grspw_dev_add) - priv->data = grspw_dev_add(priv->index); - - return DRVMGR_OK; -} - -/******************* Driver Implementation ***********************/ -/* Creates a MsgQ (optional) and spawns a worker task associated with the - * message Q. The task can also be associated with a custom msgQ if *msgQ. - * is non-zero. - */ -rtems_id grspw_work_spawn(int prio, int stack, rtems_id *pMsgQ, int msgMax) -{ - rtems_id tid; - int created_msgq = 0; - static char work_name = 'A'; - - if (pMsgQ == NULL) - return OBJECTS_ID_NONE; - - if (*pMsgQ == OBJECTS_ID_NONE) { - if (msgMax <= 0) - msgMax = 32; - - if (rtems_message_queue_create( - rtems_build_name('S', 'G', 'Q', work_name), - msgMax, 4, RTEMS_FIFO, pMsgQ) != - RTEMS_SUCCESSFUL) - return OBJECTS_ID_NONE; - created_msgq = 1; - } - - if (prio < 0) - prio = grspw_work_task_priority; /* default prio */ - if (stack < 0x800) - stack = RTEMS_MINIMUM_STACK_SIZE; /* default stack size */ - - if (rtems_task_create(rtems_build_name('S', 'G', 'T', work_name), - prio, stack, RTEMS_PREEMPT | RTEMS_NO_ASR, - RTEMS_NO_FLOATING_POINT, &tid) != RTEMS_SUCCESSFUL) - tid = OBJECTS_ID_NONE; - else if (rtems_task_start(tid, (rtems_task_entry)grspw_work_func, *pMsgQ) != - RTEMS_SUCCESSFUL) { - rtems_task_delete(tid); - tid = OBJECTS_ID_NONE; - } - - if (tid == OBJECTS_ID_NONE && created_msgq) { - rtems_message_queue_delete(*pMsgQ); - *pMsgQ = OBJECTS_ID_NONE; - } else { - if (++work_name > 'Z') - work_name = 'A'; - } - return tid; -} - -/* Free task associated with message queue and optionally also the message - * queue itself. The message queue is deleted by the work task and is therefore - * delayed until it the work task resumes its execution. - */ -rtems_status_code grspw_work_free(rtems_id msgQ, int freeMsgQ) -{ - int msg = WORK_QUIT_TASK; - if (freeMsgQ) - msg |= WORK_FREE_MSGQ; - return rtems_message_queue_send(msgQ, &msg, 4); -} - -void grspw_work_cfg(void *d, struct grspw_work_config *wc) -{ - struct grspw_priv *priv = (struct grspw_priv *)d; - - if (wc == NULL) - wc = &grspw_wc_def; /* use default config */ - priv->wc = *wc; -} - -#ifdef RTEMS_SMP -int grspw_isr_affinity(void *d, const cpu_set_t *cpus) -{ - return -1; /* BSP support only static configured IRQ affinity */ -} -#endif - -static int grspw_common_init(void) -{ - if (grspw_initialized == 1) - return 0; - if (grspw_initialized == -1) - return -1; - grspw_initialized = -1; - - /* Device Semaphore created with count = 1 */ - if (rtems_semaphore_create(rtems_build_name('S', 'G', 'L', 'S'), 1, - RTEMS_FIFO | RTEMS_SIMPLE_BINARY_SEMAPHORE | \ - RTEMS_NO_INHERIT_PRIORITY | RTEMS_LOCAL | \ - RTEMS_NO_PRIORITY_CEILING, 0, &grspw_sem) != RTEMS_SUCCESSFUL) - return -1; - - /* Work queue, Work thread. Not created if user disables it. - * user can disable it when interrupt is not used to save resources - */ - if (grspw_work_task_priority != -1) { - grspw_work_task = grspw_work_spawn(-1, 0, - (rtems_id *)&grspw_wc_def.msgisr_arg, 0); - if (grspw_work_task == OBJECTS_ID_NONE) - return -2; - grspw_wc_def.msgisr = - (grspw_msgqisr_t) rtems_message_queue_send; - } else { - grspw_wc_def.msgisr = NULL; - grspw_wc_def.msgisr_arg = NULL; - } - - grspw_initialized = 1; - return 0; -} diff --git a/c/src/lib/libbsp/sparc/shared/spw/grspw_router.c b/c/src/lib/libbsp/sparc/shared/spw/grspw_router.c deleted file mode 100644 index d95c351443..0000000000 --- a/c/src/lib/libbsp/sparc/shared/spw/grspw_router.c +++ /dev/null @@ -1,1988 +0,0 @@ -/* GRSPW ROUTER APB-Register Driver. - * - * COPYRIGHT (c) 2010-2017. - * Cobham Gaisler AB. - * - * 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 /* printk */ - -#include -#include -#include - -//#define STATIC -#define STATIC static - -#define UNUSED __attribute__((unused)) - -//#define DEBUG 1 - -#ifdef DEBUG -#define DBG(x...) printf(x) -#else -#define DBG(x...) -#endif - -#define THREAD_SAFE 1 - -/* Use interrupt lock privmitives compatible with SMP defined in - * RTEMS 4.11.99 and higher. - */ -#if (((__RTEMS_MAJOR__ << 16) | (__RTEMS_MINOR__ << 8) | __RTEMS_REVISION__) >= 0x040b63) - -#ifdef THREAD_SAFE -/* map via rtems_interrupt_lock_* API: */ -#define SPIN_DECLARE(lock) RTEMS_INTERRUPT_LOCK_MEMBER(lock) -#define SPIN_INIT(lock, name) rtems_interrupt_lock_initialize(lock, name) -#define SPIN_LOCK(lock, level) rtems_interrupt_lock_acquire_isr(lock, &level) -#define SPIN_LOCK_IRQ(lock, level) rtems_interrupt_lock_acquire(lock, &level) -#define SPIN_UNLOCK(lock, level) rtems_interrupt_lock_release_isr(lock, &level) -#define SPIN_UNLOCK_IRQ(lock, level) rtems_interrupt_lock_release(lock, &level) -#define SPIN_IRQFLAGS(k) rtems_interrupt_lock_context k -#define SPIN_ISR_IRQFLAGS(k) SPIN_IRQFLAGS(k) -#define SPIN_FREE(lock) rtems_interrupt_lock_destroy(lock) -#else -#define SPIN_DECLARE(lock) -#define SPIN_INIT(lock, name) -#define SPIN_LOCK(lock, level) -#define SPIN_LOCK_IRQ(lock, level) -#define SPIN_UNLOCK(lock, level) -#define SPIN_UNLOCK_IRQ(lock, level) -#define SPIN_IRQFLAGS(k) -#define SPIN_ISR_IRQFLAGS(k) -#define SPIN_FREE(lock) -#endif - -#else - -#ifdef THREAD_SAFE -#error THREAD SAFE operation not supported on this RTEMS version -#else -#define SPIN_DECLARE(lock) -#define SPIN_INIT(lock, name) -#define SPIN_LOCK(lock, level) -#define SPIN_LOCK_IRQ(lock, level) -#define SPIN_UNLOCK(lock, level) -#define SPIN_UNLOCK_IRQ(lock, level) -#define SPIN_IRQFLAGS(k) -#define SPIN_ISR_IRQFLAGS(k) -#define SPIN_FREE(lock) -#endif - -#ifdef RTEMS_SMP -#error SMP mode not compatible with these interrupt lock primitives -#endif - -#endif - -#define REG_WRITE(addr, val) (*(volatile unsigned int *)(addr) = (unsigned int)(val)) -#define REG_READ(addr) (*(volatile unsigned int *)(addr)) - - -/* - * ROUTER RTPMAP register fields - */ -#define RTPMAP_PE (0x7fffffff << RTPMAP_PE_BIT) -#define RTPMAP_PD (0x1 << RTPMAP_PD_BIT) - -#define RTPMAP_PE_BIT 1 -#define RTPMAP_PD_BIT 0 - -/* - * ROUTER RTACTRL register fields - * DEFINED IN HEADER - */ - -/* - * ROUTER PCTRL register fields - * DEFINED IN HEADER - */ - -/* - * ROUTER PSTSCFG register fields - * DEFINED IN HEADER - */ - -/* - * ROUTER PSTS register fields - * DEFINED IN HEADER - */ - -/* - * ROUTER PTIMER register fields - */ -#define PTIMER_RL (0xffff << PTIMER_RL_BIT) - -#define PTIMER_RL_BIT 0 - -/* - * ROUTER PCTRL2 register fields - * DEFINED IN HEADER - */ - -/* - * ROUTER RTRCFG register fields - */ -#define RTRCFG_SP (0x1f << RTRCFG_SP_BIT) -#define RTRCFG_AP (0x1f << RTRCFG_AP_BIT) -#define RTRCFG_FP (0x1f << RTRCFG_FP_BIT) -#define RTRCFG_SR (0x1 << RTRCFG_SR_BIT) -#define RTRCFG_PE (0x1 << RTRCFG_PE_BIT) -#define RTRCFG_IC (0x1 << RTRCFG_IC_BIT) -#define RTRCFG_IS (0x1 << RTRCFG_IS_BIT) -#define RTRCFG_IP (0x1 << RTRCFG_IP_BIT) -#define RTRCFG_AI (0x1 << RTRCFG_AI_BIT) -#define RTRCFG_AT (0x1 << RTRCFG_AT_BIT) -#define RTRCFG_IE (0x1 << RTRCFG_IE_BIT) -#define RTRCFG_RE (0x1 << RTRCFG_RE_BIT) -#define RTRCFG_EE (0x1 << RTRCFG_EE_BIT) -#define RTRCFG_LS (0x1 << RTRCFG_LS_BIT) -#define RTRCFG_SA (0x1 << RTRCFG_SA_BIT) -#define RTRCFG_TF (0x1 << RTRCFG_TF_BIT) -#define RTRCFG_ME (0x1 << RTRCFG_ME_BIT) -#define RTRCFG_TA (0x1 << RTRCFG_TA_BIT) -#define RTRCFG_PP (0x1 << RTRCFG_PP_BIT) -#define RTRCFG_WCLEAR (RTRCFG_ME) - -#define RTRCFG_SP_BIT 27 -#define RTRCFG_AP_BIT 22 -#define RTRCFG_FP_BIT 17 -#define RTRCFG_SR_BIT 15 -#define RTRCFG_PE_BIT 14 -#define RTRCFG_IC_BIT 13 -#define RTRCFG_IS_BIT 12 -#define RTRCFG_IP_BIT 11 -#define RTRCFG_AI_BIT 10 -#define RTRCFG_AT_BIT 9 -#define RTRCFG_IE_BIT 8 -#define RTRCFG_RE_BIT 7 -#define RTRCFG_EE_BIT 6 -#define RTRCFG_LS_BIT 5 -#define RTRCFG_SA_BIT 4 -#define RTRCFG_TF_BIT 3 -#define RTRCFG_ME_BIT 2 -#define RTRCFG_TA_BIT 1 -#define RTRCFG_PP_BIT 0 - -/* - * ROUTER TC register fields - */ -#define TC_RE (0x3f << TC_RE_BIT) -#define TC_EN (0x3f << TC_EN_BIT) -#define TC_CF (0x3f << TC_CF_BIT) -#define TC_TC (0x3f << TC_TC_BIT) - -#define TC_RE_BIT 9 -#define TC_EN_BIT 8 -#define TC_CF_BIT 6 -#define TC_TC_BIT 0 - -/* - * ROUTER VER register fields - */ -#define VER_MA (0xff << VER_MA_BIT) -#define VER_MI (0xff << VER_MI_BIT) -#define VER_PA (0xff << VER_PA_BIT) -#define VER_ID (0xff << VER_ID_BIT) - -#define VER_MA_BIT 24 -#define VER_MI_BIT 16 -#define VER_PA_BIT 8 -#define VER_ID_BIT 0 - -/* - * ROUTER IDIV register fields - */ -#define IDIV_ID (0xff << IDIV_ID_BIT) - -#define IDIV_ID_BIT 0 - -/* - * ROUTER CFGWE register fields - */ -#define CFGWE_WE (0x1 << CFGWE_WE_BIT) - -#define CFGWE_WE_BIT 0 - -/* - * ROUTER PRESCALER register fields - */ -#define PRESCALER_RL (0xffff << PRESCALER_RL_BIT) - -#define PRESCALER_RL_BIT 0 - -/* - * ROUTER IMASK register fields - * DEFINED IN HEADER - */ - -/* - * ROUTER ICODEGEN register fields - * DEFINED IN HEADER - */ - -/* - * ROUTER ISRTIMER register fields - */ -#define ISRTIMER_RL (0xffff << ISRTIMER_RL_BIT) - -#define ISRTIMER_RL_BIT 0 - -/* - * ROUTER AITIMER register fields - */ -#define AITIMER_RL (0xffff << AITIMER_RL_BIT) - -#define AITIMER_RL_BIT 0 - -/* - * ROUTER ISRCTIMER register fields - */ -#define ISRCTIMER_RL (0x1f << ISRCTIMER_RL_BIT) - -#define ISRCTIMER_RL_BIT 0 - -/* - * ROUTER CAP register fields - */ -#define CAP_AF (0x3 << CAP_AF_BIT) -#define CAP_PF (0x7 << CAP_PF_BIT) -#define CAP_RM (0x7 << CAP_RM_BIT) -#define CAP_AS (0x1 << CAP_AS_BIT) -#define CAP_AX (0x1 << CAP_AX_BIT) -#define CAP_DP (0x1 << CAP_DP_BIT) -#define CAP_ID (0x1 << CAP_ID_BIT) -#define CAP_SD (0x1 << CAP_SD_BIT) -#define CAP_PC (0x1f << CAP_PC_BIT) -#define CAP_CC (0x1f << CAP_CC_BIT) - -#define CAP_AF_BIT 24 -#define CAP_PF_BIT 29 -#define CAP_RM_BIT 16 -#define CAP_AS_BIT 14 -#define CAP_AX_BIT 13 -#define CAP_DP_BIT 12 -#define CAP_ID_BIT 11 -#define CAP_SD_BIT 10 -#define CAP_PC_BIT 4 -#define CAP_CC_BIT 0 - -/* - * ROUTER PNPVEND register fields - */ -#define PNPVEND_VI (0xffff << PNPVEND_VI_BIT) -#define PNPVEND_PI (0xffff << PNPVEND_PI_BIT) - -#define PNPVEND_VI_BIT 16 -#define PNPVEND_PI_BIT 0 - -/* - * ROUTER PNPUVEND register fields - */ -#define PNPUVEND_VI (0xffff << PNPUVEND_VI_BIT) -#define PNPUVEND_PI (0xffff << PNPUVEND_PI_BIT) - -#define PNPUVEND_VI_BIT 16 -#define PNPUVEND_PI_BIT 0 - -/* - * ROUTER MAXPLEN register fields - */ -#define MAXPLEN_ML (0xffffff << MAXPLEN_ML_BIT) - -#define MAXPLEN_ML_BIT 0 - -/* - * ROUTER CHARO register fields - */ -#define CHARO_OR (0x1 << CHARO_OR_BIT) -#define CHARO_CC (0x7fffffff << CHARO_CC_BIT) - -#define CHARO_OR_BIT 31 -#define CHARO_CC_BIT 0 - -/* - * ROUTER CHARI register fields - */ -#define CHARI_OR (0x1 << CHARI_OR_BIT) -#define CHARI_CC (0x7fffffff << CHARI_CC_BIT) - -#define CHARI_OR_BIT 31 -#define CHARI_CC_BIT 0 - -/* - * ROUTER PKTO register fields - */ -#define PKTO_OR (0x1 << PKTO_OR_BIT) -#define PKTO_CC (0x7fffffff << PKTO_CC_BIT) - -#define PKTO_OR_BIT 31 -#define PKTO_CC_BIT 0 - -/* - * ROUTER PKTI register fields - */ -#define PKTI_OR (0x1 << PKTI_OR_BIT) -#define PKTI_CC (0x7fffffff << PKTI_CC_BIT) - -#define PKTI_OR_BIT 31 -#define PKTI_CC_BIT 0 - -/* - * ROUTER CRED register fields - */ -#define CRED_OC (0x3f << CRED_OC_BIT) -#define CRED_IC (0x3f << CRED_IC_BIT) - -#define CRED_OC_BIT 6 -#define CRED_IC_BIT 0 - -/* - * ROUTER RTRCOMB register fields - */ -#define RTRCOMB_SR (0x1 << RTRCOMB_SR_BIT) -#define RTRCOMB_EN (0x1 << RTRCOMB_EN_BIT) -#define RTRCOMB_PR (0x1 << RTRCOMB_PR_BIT) -#define RTRCOMB_HD (0x1 << RTRCOMB_HD_BIT) -#define RTRCOMB_PE (0x7ffff << RTRCOMB_PE_BIT) -#define RTRCOMB_PD (0x1 << RTRCOMB_PD_BIT) - -#define RTRCOMB_SR_BIT 31 -#define RTRCOMB_EN_BIT 30 -#define RTRCOMB_PR_BIT 29 -#define RTRCOMB_HD_BIT 28 -#define RTRCOMB_PE_BIT 1 -#define RTRCOMB_PD_BIT 0 - -struct router_regs { - unsigned int resv1; /* 0x000 */ - unsigned int psetup[255]; /* 0x004 */ - unsigned int resv2; /* 0x400 */ - unsigned int routes[255]; /* 0x404 */ - unsigned int pctrl[32]; /* 0x800 */ - unsigned int psts[32]; /* 0x880 */ - unsigned int treload[32]; /* 0x900 */ - unsigned int pctrl2[32]; /* 0x980 */ - unsigned int cfgsts; /* 0xA00 */ - unsigned int timecode; /* 0xA04 */ - unsigned int ver; /* 0xA08 */ - unsigned int idiv; /* 0xA0C */ - unsigned int cfgwe; /* 0xA10 */ - unsigned int tprescaler; /* 0xA14 */ - unsigned int imask; /* 0xA18 */ - unsigned int ipmask; /* 0xA1C */ - unsigned int pip; /* 0xA20 */ - unsigned int icodegen; /* 0xA24 */ - unsigned int isr0; /* 0xA28 */ - unsigned int isr1; /* 0xA2C */ - unsigned int isrtimer; /* 0xA30 */ - unsigned int aitimer; /* 0xA34 */ - unsigned int isrctimer; /* 0xA38 */ - unsigned int resv4; /* 0xA3C */ - unsigned int lrunsts; /* 0xA40 */ - unsigned int cap; /* 0xA44 */ - unsigned int resv5[111]; /* 0xA48 */ - unsigned int charo[31]; /* 0xC04 */ /* TODO check GR718 */ - unsigned int resv6; /* 0xC80 */ - unsigned int chari[31]; /* 0xC84 */ - unsigned int resv7; /* 0xD00 */ - unsigned int pkto[31]; /* 0xD04 */ - unsigned int resv8; /* 0xD80 */ - unsigned int pkti[31]; /* 0xD84 */ - unsigned int maxplen[32]; /* 0xE00 */ - unsigned int resv9; /* 0xE80 */ - unsigned int credcnt[31]; /* 0xE84 */ - unsigned int resv10[64]; /* 0xF00 */ - unsigned int resv11; /* 0x1000 */ - unsigned int rtcomb[255]; /* 0x1004 */ -}; - -struct router_priv { - struct drvmgr_dev *dev; - - /* ROUTER control registers */ - struct router_regs *regs; - - #ifdef THREAD_SAFE - /* ROUTER semaphore */ - rtems_id sem; - #endif - - /* ROUTER driver register */ - char devname[9]; - int index; /* Index in order it was probed */ - - int minor; - int open; - struct router_hw_info hwinfo; - int nports; - int irq_init; - - SPIN_DECLARE(plock[32]) - -}; - -int router_count = 0; -static struct router_priv *priv_tab[ROUTER_MAX]; - -/* Driver prototypes */ - -STATIC int router_init(struct router_priv *priv); -STATIC void router_hwinfo(struct router_priv *priv, - struct router_hw_info *hwinfo); -STATIC int router_acontrol_set(struct router_priv *priv, - struct router_route_acontrol *control); -STATIC int router_acontrol_get(struct router_priv *priv, - struct router_route_acontrol *control); -STATIC int router_portmap_set(struct router_priv *priv, - struct router_route_portmap *pmap); -STATIC int router_portmap_get(struct router_priv *priv, - struct router_route_portmap *pmap); - -/* -IRQ handler */ -void router_isr(void *arg); - -int router_init2(struct drvmgr_dev *dev); - -struct drvmgr_drv_ops router_ops = -{ - .init = {NULL, router_init2, NULL, NULL}, - .remove = NULL, - .info = NULL -}; - -struct amba_dev_id router_ids[] = -{ - {VENDOR_GAISLER, GAISLER_SPW_ROUTER}, - {0, 0} /* Mark end of table */ -}; - -struct amba_drv_info router_drv_info = -{ - { - DRVMGR_OBJ_DRV, /* Driver */ - NULL, /* Next driver */ - NULL, /* Device list */ - DRIVER_AMBAPP_GAISLER_SPW_ROUTER_ID,/* Driver ID */ - "ROUTER_DRV", /* Driver Name */ - DRVMGR_BUS_TYPE_AMBAPP, /* Bus Type */ - &router_ops, - NULL, /* Funcs */ - 0, /* No devices yet */ - sizeof(struct router_priv), /* Let DRVMGR allocate for us */ - }, - &router_ids[0], -}; - -void router_register_drv (void) -{ - DBG("Registering SPW ROUTER driver\n"); - drvmgr_drv_register(&router_drv_info.general); -} - -STATIC void router_hwinfo(struct router_priv *priv, - struct router_hw_info *hwinfo) -{ - unsigned int tmp; - - /* Find router info */ - tmp = REG_READ(&priv->regs->cfgsts); - hwinfo->nports_spw = (tmp & RTRCFG_SP) >> RTRCFG_SP_BIT; - hwinfo->nports_amba = (tmp & RTRCFG_AP) >> RTRCFG_AP_BIT; - hwinfo->nports_fifo = (tmp & RTRCFG_FP) >> RTRCFG_FP_BIT; - hwinfo->srouting = (tmp & RTRCFG_SR) >> RTRCFG_SR_BIT; - hwinfo->pnp_enable = (tmp & RTRCFG_PE) >> RTRCFG_PE_BIT; - hwinfo->timers_avail = (tmp & RTRCFG_TA) >> RTRCFG_TA_BIT; - hwinfo->pnp_avail = (tmp & RTRCFG_PP) >> RTRCFG_PP_BIT; - - tmp = REG_READ(&priv->regs->ver); - hwinfo->ver_major = (tmp & VER_MA) >> VER_MA_BIT; - hwinfo->ver_minor = (tmp & VER_MI) >> VER_MI_BIT; - hwinfo->ver_patch = (tmp & VER_PA) >> VER_PA_BIT; - hwinfo->iid = (tmp & VER_ID) >> VER_ID_BIT; - - /* Find router capabilities */ - tmp = REG_READ(&priv->regs->cap); - hwinfo->amba_port_fifo_size = 4 << ((tmp & CAP_AF) >> CAP_AF_BIT); - hwinfo->spw_port_fifo_size = 16 << ((tmp & CAP_PF) >> CAP_PF_BIT); - hwinfo->rmap_maxdlen = 4 << ((tmp & CAP_RM) >> CAP_RM_BIT); - hwinfo->aux_async = (tmp & CAP_AS) >> CAP_AS_BIT; - hwinfo->aux_dist_int_support = (tmp & CAP_AX) >> CAP_AX_BIT; - hwinfo->dual_port_support = (tmp & CAP_ID) >> CAP_ID_BIT; - hwinfo->dist_int_support = (tmp & CAP_DP) >> CAP_DP_BIT; - hwinfo->spwd_support = (tmp & CAP_SD) >> CAP_SD_BIT; - hwinfo->pktcnt_support = (tmp & CAP_PC) >> CAP_PC_BIT; - hwinfo->charcnt_support = (tmp & CAP_CC) >> CAP_CC_BIT; -} - -STATIC void router_hwinfo_print(struct router_hw_info *hwinfo) -{ - DBG(" -PORTS= SPW: %d, AMBA: %d, FIFO: %d\n", hwinfo->nports_spw, - hwinfo->nports_amba, hwinfo->nports_fifo); - DBG(" -Static routing: %s, Timers: %s\n", - (hwinfo->srouting?"Enabled":"Disabled"), - (hwinfo->timers_avail?"Available":"N/A")); - DBG(" -PnP: %s, %s\n", - (hwinfo->pnp_avail?"Available":"N/A"), - (hwinfo->pnp_enable?"Enabled":"Disabled")); - DBG(" -Version= Major: 0x%02x, Minor: 0x%02x, Patch: 0x%02x, ID: 0x%02x\n", - hwinfo->ver_major, hwinfo->ver_minor, - hwinfo->ver_patch, hwinfo->iid); - DBG(" -Aux: %s, AuxDistInt: %s, DistInt: %s, SPWD: %s, PKTCNT: %s, " - "CHARCNT: %s\n", - (hwinfo->aux_async?"Async":"Sync"), - (hwinfo->aux_dist_int_support?"Supported":"N/A"), - (hwinfo->dist_int_support?"Supported":"N/A"), - (hwinfo->spwd_support?"Supported":"N/A"), - (hwinfo->pktcnt_support?"Supported":"N/A"), - (hwinfo->charcnt_support?"Supported":"N/A")); -} - -STATIC int router_acontrol_set(struct router_priv *priv, - struct router_route_acontrol *control) -{ - int i; - for (i=0; i<31; i++) { - REG_WRITE(&priv->regs->routes[i], control->control[i]); - } - for (i=0; i<224; i++) { - REG_WRITE(&priv->regs->routes[i+31], control->control_logical[i]); - } - return ROUTER_ERR_OK; -} - -STATIC int router_acontrol_get(struct router_priv *priv, - struct router_route_acontrol *control) -{ - int i; - for (i=0; i<31; i++) { - control->control[i] = REG_READ(&priv->regs->routes[i]); - } - for (i=0; i<224; i++) { - control->control_logical[i] = REG_READ(&priv->regs->routes[i+31]); - } - return ROUTER_ERR_OK; -} - -STATIC int router_portmap_set(struct router_priv *priv, - struct router_route_portmap *pmap) -{ - int i; - for (i=0; i<31; i++) { - REG_WRITE(&priv->regs->psetup[i], pmap->pmap[i]); - } - for (i=0; i<224; i++) { - REG_WRITE(&priv->regs->psetup[i+31], pmap->pmap_logical[i]); - } - return ROUTER_ERR_OK; -} - -STATIC int router_portmap_get(struct router_priv *priv, - struct router_route_portmap *pmap) -{ - int i; - for (i=0; i<31; i++) { - pmap->pmap[i] = REG_READ(&priv->regs->psetup[i]); - } - for (i=0; i<224; i++) { - pmap->pmap_logical[i] = REG_READ(&priv->regs->psetup[i+31]); - } - return ROUTER_ERR_OK; -} - -STATIC int router_init(struct router_priv *priv) -{ - #ifdef THREAD_SAFE - int i; - - /* Device Semaphore created with count = 1 */ - if (rtems_semaphore_create( - rtems_build_name('S', 'R', 'O', '0' + priv->index), 1, - RTEMS_FIFO | RTEMS_SIMPLE_BINARY_SEMAPHORE | \ - RTEMS_NO_INHERIT_PRIORITY | RTEMS_LOCAL | \ - RTEMS_NO_PRIORITY_CEILING, 0, &priv->sem) != RTEMS_SUCCESSFUL) { - return DRVMGR_FAIL; - } - #endif - - /* Find router info */ - router_hwinfo(priv, &priv->hwinfo); - - priv->open = 0; - /* Number of ports has to consider the configuration port (1 + SPW + AMBA + FIFO) */ - priv->nports = 1 + priv->hwinfo.nports_spw + priv->hwinfo.nports_amba + - priv->hwinfo.nports_fifo; - if ((priv->nports < 2) || (priv->nports > 32)) { - return DRVMGR_EIO; - } - - #ifdef THREAD_SAFE - /* Init port spin-lock memory structures */ - for (i=0; inports; i++) { - SPIN_INIT(&priv->plock[i],"portlock"); - } - #endif - - /* DEBUG print */ - DBG("SPW ROUTER[%d] with following capabilities:\n", priv->index); - router_hwinfo_print(&priv->hwinfo); - - return DRVMGR_OK; -} - -int router_init2(struct drvmgr_dev *dev) -{ - struct router_priv *priv = dev->priv; - struct amba_dev_info *ambadev; - struct ambapp_core *pnpinfo; - unsigned int tmp; - int i; - int status; - - DBG("SPW ROUTER[%d] on bus %s\n", dev->minor_drv, dev->parent->dev->name); - - if (router_count >= ROUTER_MAX) { - return DRVMGR_ENORES; - } - - if (priv == NULL) { - return DRVMGR_NOMEM; - } - priv->dev = dev; - - /* Get device information from AMBA PnP information */ - ambadev = (struct amba_dev_info *)priv->dev->businfo; - if (ambadev == NULL) { - return DRVMGR_FAIL; - } - pnpinfo = &ambadev->info; - priv->regs = (struct router_regs *)pnpinfo->ahb_slv->start[0]; - priv->minor = dev->minor_drv; - - /* Initilize driver struct */ - status = router_init(priv); - if (status != DRVMGR_OK) { - return status; - } - - /* Startup Action: - * - Clear interrupts - * - Mask interrupts - */ - - /* Mask interrupts in ROTUER */ - REG_WRITE(&priv->regs->imask,0); - REG_WRITE(&priv->regs->ipmask,0); - - /* Clear interrupts in ROTUER */ - REG_WRITE(&priv->regs->pip,0xffffffff); - - /* Clear errors in router and ports */ - tmp = REG_READ(&priv->regs->cfgsts); - REG_WRITE(&priv->regs->cfgsts, tmp | RTRCFG_WCLEAR); - tmp = REG_READ(&priv->regs->psts[0]); - REG_WRITE(&priv->regs->psts[0], (tmp & PSTSCFG_WCLEAR) | PSTSCFG_WCLEAR2); - for (i=1; inports; i++) { - tmp = REG_READ(&priv->regs->psts[i]); - REG_WRITE(&priv->regs->psts[i], tmp & PSTS_WCLEAR); - } - - /* Register driver internally */ - priv->index = router_count; - priv_tab[priv->index] = priv; - router_count++; - - /* Device name */ - sprintf(priv->devname, "router%d", priv->index); - - return DRVMGR_OK; -} - -void *router_open(unsigned int dev_no) -{ - struct router_priv *priv, *ret; - - if (dev_no >= router_count) { - DBG("ROUTER Wrong index %u\n", dev_no); - return NULL; - } - - priv = priv_tab[dev_no]; - - if (priv == NULL) { - DBG("ROUTER Device not initialized\n"); - return NULL; - } - - #ifdef THREAD_SAFE - /* Take device lock - Wait until we get semaphore */ - if (rtems_semaphore_obtain(priv->sem, RTEMS_WAIT, RTEMS_NO_TIMEOUT) - != RTEMS_SUCCESSFUL) { - DBG("ROUTER Sempahore failed\n"); - return NULL; - } - #endif - - if (priv->open) { - DBG("ROUTER Device already opened\n"); - ret = NULL; - } else { - /* Take the device */ - priv->open = 1; - ret = priv; - } - #ifdef THREAD_SAFE - /* Unlock dev */ - rtems_semaphore_release(priv->sem); - #endif - - return ret; -} - -int router_close(void *d) -{ - struct router_priv *priv = d; - int ret; - - if (priv == NULL) { - DBG("ROUTER Device not initialized\n"); - return ROUTER_ERR_EINVAL; - } - - #ifdef THREAD_SAFE - /* Take device lock - Wait until we get semaphore */ - if (rtems_semaphore_obtain(priv->sem, RTEMS_WAIT, RTEMS_NO_TIMEOUT) - != RTEMS_SUCCESSFUL) { - DBG("ROUTER Sempahore failed\n"); - return ROUTER_ERR_ERROR; - } - #endif - - if (priv->open == 0) { - DBG("ROUTER Device already closed\n"); - ret = ROUTER_ERR_ERROR; - } else { - /* Mark not open */ - priv->open = 0; - ret = ROUTER_ERR_OK; - } - - #ifdef THREAD_SAFE - /* Unlock dev */ - rtems_semaphore_release(priv->sem); - #endif - - return ret; -} - -STATIC int router_check_open(void *d) -{ - struct router_priv *priv = d; - - if (priv == NULL) { - DBG("ROUTER Device not initialized\n"); - return ROUTER_ERR_EINVAL; - } - - if (priv->open == 0) { - DBG("ROUTER Device closed\n"); - return ROUTER_ERR_ERROR; - } - - return 0; -} - -STATIC int router_check_port(void *d, int port) -{ - int ret = router_check_open(d); - - if (ret == 0) { - struct router_priv *priv = d; - if((port < 0) || (port >= priv->nports)) { - DBG("ROUTER wrong port\n"); - ret = ROUTER_ERR_EINVAL; - } - } - - return ret; -} - -STATIC int router_check_distint_support(void *d) -{ - int ret = router_check_open(d); - - if (ret == 0) { - struct router_priv *priv = d; - if (priv->hwinfo.dist_int_support == 0) { - DBG("ROUTER Dist interrupts not supported\n"); - ret = ROUTER_ERR_IMPLEMENTED; - } - } - - return ret; -} - -int router_hwinfo_get(void *d, struct router_hw_info *hwinfo) -{ - struct router_priv *priv = d; - int error = router_check_open(d); - - if (error) - return error; - - if (hwinfo == NULL) { - DBG("ROUTER Wrong pointer\n"); - return ROUTER_ERR_EINVAL; - } - - /* Get hwinfo */ - router_hwinfo(priv, hwinfo); - - return ROUTER_ERR_OK; -} - -int router_print(void *d) -{ - struct router_priv *priv = d; - int error = router_check_open(d); - - if (error) - return error; - - /* DEBUG print */ - DBG("Number of routers: %d\n", router_count); - DBG("SPW ROUTER[%d] with following capabilities:\n", priv->index); - router_hwinfo_print(&priv->hwinfo); - - return ROUTER_ERR_OK; -} - -/* Configure Router. Leave field NULL in order to skip configuration - */ -int router_config_set(void *d, struct router_config *cfg) -{ - struct router_priv *priv = d; - int error = router_check_open(d); - - if (error) - return error; - - if (cfg == NULL) { - DBG("ROUTER CFG wrong\n"); - return ROUTER_ERR_EINVAL; - } - - if ((cfg->flags & (ROUTER_FLG_TPRES|ROUTER_FLG_TRLD)) && - !priv->hwinfo.timers_avail) { - return ROUTER_ERR_IMPLEMENTED; - } - - #ifdef THREAD_SAFE - /* Take device lock - Wait until we get semaphore */ - if (rtems_semaphore_obtain(priv->sem, RTEMS_WAIT, RTEMS_NO_TIMEOUT) - != RTEMS_SUCCESSFUL) { - DBG("ROUTER Sempahore failed\n"); - return ROUTER_ERR_ERROR; - } - #endif - - /* Write only configuration bits in Config register */ - if (cfg->flags & ROUTER_FLG_CFG) { - REG_WRITE(&priv->regs->cfgsts, cfg->config & ~(RTRCFG_WCLEAR)); - } - - /* Write Instance ID to Version Register */ - if (cfg->flags & ROUTER_FLG_IID) { - REG_WRITE(&priv->regs->ver, (cfg->iid << VER_ID_BIT) & VER_ID); - } - - /* Write startup-clock-divisor Register */ - if (cfg->flags & ROUTER_FLG_IDIV) { - REG_WRITE(&priv->regs->idiv, (cfg->idiv << IDIV_ID_BIT) & IDIV_ID); - } - - /* Write Timer Prescaler Register */ - if (cfg->flags & ROUTER_FLG_TPRES) { - REG_WRITE(&priv->regs->tprescaler, - (cfg->timer_prescaler << PRESCALER_RL_BIT) & PRESCALER_RL); - } - - #ifdef THREAD_SAFE - /* Unlock dev */ - rtems_semaphore_release(priv->sem); - #endif - - return ROUTER_ERR_OK; -} - -int router_config_get(void *d, struct router_config *cfg) -{ - struct router_priv *priv = d; - int error = router_check_open(d); - - if (error) - return error; - - if (cfg == NULL) { - DBG("ROUTER CFG wrong\n"); - return ROUTER_ERR_EINVAL; - } - - #ifdef THREAD_SAFE - /* Take device lock - Wait until we get semaphore */ - if (rtems_semaphore_obtain(priv->sem, RTEMS_WAIT, RTEMS_NO_TIMEOUT) - != RTEMS_SUCCESSFUL) { - DBG("ROUTER Sempahore failed\n"); - return ROUTER_ERR_ERROR; - } - #endif - - cfg->config = REG_READ(&priv->regs->cfgsts) & - ~(RTRCFG_SP|RTRCFG_AP|RTRCFG_FP|RTRCFG_SR|RTRCFG_PE|RTRCFG_ME| - RTRCFG_TA|RTRCFG_PP); - cfg->iid = (REG_READ(&priv->regs->ver) & VER_ID) >> VER_ID_BIT; - cfg->idiv = (REG_READ(&priv->regs->idiv) & IDIV_ID) >> IDIV_ID_BIT; - cfg->timer_prescaler = - (REG_READ(&priv->regs->tprescaler) & PRESCALER_RL) >> PRESCALER_RL_BIT; - - #ifdef THREAD_SAFE - /* Unlock dev */ - rtems_semaphore_release(priv->sem); - #endif - - return ROUTER_ERR_OK; -} - -/* Configure Router routing table. - * Leave field NULL in order to skip configuration - */ -int router_routing_table_set(void *d, struct router_routing_table *cfg) -{ - struct router_priv *priv = d; - int error = router_check_open(d); - - if (error) - return error; - - if (cfg == NULL) { - DBG("ROUTER CFG wrong\n"); - return ROUTER_ERR_EINVAL; - } - - #ifdef THREAD_SAFE - /* Take device lock - Wait until we get semaphore */ - if (rtems_semaphore_obtain(priv->sem, RTEMS_WAIT, RTEMS_NO_TIMEOUT) - != RTEMS_SUCCESSFUL) { - DBG("ROUTER Sempahore failed\n"); - return ROUTER_ERR_ERROR; - } - #endif - - /* Write Address control */ - if (cfg->flags & ROUTER_ROUTE_FLG_CTRL) { - router_acontrol_set(priv,&cfg->acontrol); - } - - /* Write Port map */ - if (cfg->flags & ROUTER_ROUTE_FLG_MAP) { - router_portmap_set(priv,&cfg->portmap); - } - - #ifdef THREAD_SAFE - /* Unlock dev */ - rtems_semaphore_release(priv->sem); - #endif - - return ROUTER_ERR_OK; -} - -int router_routing_table_get(void *d, struct router_routing_table *cfg) -{ - struct router_priv *priv = d; - int error = router_check_open(d); - - if (error) - return error; - - if (cfg == NULL) { - DBG("ROUTER CFG wrong\n"); - return ROUTER_ERR_EINVAL; - } - - #ifdef THREAD_SAFE - /* Take device lock - Wait until we get semaphore */ - if (rtems_semaphore_obtain(priv->sem, RTEMS_WAIT, RTEMS_NO_TIMEOUT) - != RTEMS_SUCCESSFUL) { - DBG("ROUTER Sempahore failed\n"); - return ROUTER_ERR_ERROR; - } - #endif - - /* Read Address control */ - router_acontrol_get(priv,&cfg->acontrol); - - /* Read Port map */ - router_portmap_get(priv,&cfg->portmap); - - #ifdef THREAD_SAFE - /* Unlock dev */ - rtems_semaphore_release(priv->sem); - #endif - - return ROUTER_ERR_OK; -} - -int router_route_set(void *d, struct router_route *route) -{ - struct router_priv *priv = d; - int i; - unsigned int mask; - int error = router_check_open(d); - - if (error) - return error; - - if (route == NULL) { - DBG("ROUTER route wrong\n"); - return ROUTER_ERR_EINVAL; - } - - if (route->from_address < 32) { - /* Physical address */ - if ((route->from_address == 0) || - (route->from_address >= priv->nports)) { - DBG("ROUTER wrong physical address\n"); - return ROUTER_ERR_TOOMANY; - } - } - - /* Compute port map */ - mask=0; - for (i=0; i < route->count; i++) { - if ((route->to_port[i] == 0) || (route->to_port[i] >= priv->nports)) { - DBG("ROUTER route wrong destiny port\n"); - return ROUTER_ERR_EINVAL; - } - mask |= (0x1 << route->to_port[i]); - } - if (route->options & ROUTER_ROUTE_PACKETDISTRIBUTION_ENABLE) { - mask |= RTPMAP_PD; - } - - #ifdef THREAD_SAFE - /* Take device lock - Wait until we get semaphore */ - if (rtems_semaphore_obtain(priv->sem, RTEMS_WAIT, RTEMS_NO_TIMEOUT) - != RTEMS_SUCCESSFUL) { - DBG("ROUTER Sempahore failed\n"); - return ROUTER_ERR_ERROR; - } - #endif - - /* Write port map */ - REG_WRITE(&priv->regs->psetup[route->from_address-1], mask); - - /* Write Address control */ - REG_WRITE(&priv->regs->routes[route->from_address-1], - route->options & (0xf)); - - #ifdef THREAD_SAFE - /* Unlock dev */ - rtems_semaphore_release(priv->sem); - #endif - - return ROUTER_ERR_OK; -} - -int router_route_get(void *d, struct router_route *route) -{ - struct router_priv *priv = d; - int i,count; - unsigned int mask; - int error = router_check_open(d); - - if (error) - return error; - - if (route == NULL) { - DBG("ROUTER route wrong\n"); - return ROUTER_ERR_EINVAL; - } - - if (route->from_address < 32) { - /* Physical address */ - if ((route->from_address == 0) || - (route->from_address >= priv->nports)) { - DBG("ROUTER wrong physical address\n"); - return ROUTER_ERR_TOOMANY; - } - } - - #ifdef THREAD_SAFE - /* Take device lock - Wait until we get semaphore */ - if (rtems_semaphore_obtain(priv->sem, RTEMS_WAIT, RTEMS_NO_TIMEOUT) - != RTEMS_SUCCESSFUL) { - DBG("ROUTER Sempahore failed\n"); - return ROUTER_ERR_ERROR; - } - #endif - - /* Get Address control */ - route->options = - REG_READ(&priv->regs->routes[route->from_address-1]) & (0xf); - - /* Read port map */ - mask=REG_READ(&priv->regs->psetup[route->from_address-1]); - - #ifdef THREAD_SAFE - /* Unlock dev */ - rtems_semaphore_release(priv->sem); - #endif - - if (mask & RTPMAP_PD) { - route->options |= ROUTER_ROUTE_PACKETDISTRIBUTION_ENABLE; - } - - /*DBG("ROUTE from address 0x%02x read, PMAP: 0x%08x, CTRL: 0x%08x\n", - * (unsigned int) route->from_address, mask, - * (unsigned int) route->options);*/ - - i=0; - count=0; - mask &= (RTPMAP_PE); - while (mask != 0) { - if (mask & 0x1) { - route->to_port[count] = i; - count++; - } - mask >>= 1; - i++; - } - route->count=count; - - return ROUTER_ERR_OK; -} - -int router_write_enable(void *d) -{ - struct router_priv *priv = d; - int error = router_check_open(d); - - if (error) - return error; - - REG_WRITE(&priv->regs->cfgwe, 0x1); - - return ROUTER_ERR_OK; -} - -int router_write_disable(void *d) -{ - struct router_priv *priv = d; - int error = router_check_open(d); - - if (error) - return error; - - REG_WRITE(&priv->regs->cfgwe, 0x0); - - return ROUTER_ERR_OK; -} - -int router_port_ioc(void *d, int port, struct router_port *cfg) -{ - struct router_priv *priv = d; - unsigned int ctrl, ctrl2, sts, timer, pktl; - SPIN_IRQFLAGS(irqflags); - int error = router_check_port(d, port); - - if (error) - return error; - - if (cfg == NULL) { - DBG("ROUTER Wrong cfg\n"); - return ROUTER_ERR_EINVAL; - } - - SPIN_LOCK_IRQ(&priv->plock[port], irqflags); - - ctrl = cfg->ctrl; - if (cfg->flag & ROUTER_PORT_FLG_GET_CTRL) { - ctrl = REG_READ(&priv->regs->pctrl[port]); - } - ctrl2 = cfg->ctrl; - if (cfg->flag & ROUTER_PORT_FLG_GET_CTRL2) { - ctrl2 = REG_READ(&priv->regs->pctrl2[port]); - } - sts = cfg->sts; - if (cfg->flag & ROUTER_PORT_FLG_GET_STS) { - sts = REG_READ(&priv->regs->psts[port]); - } - timer = cfg->timer_reload; - if (cfg->flag & ROUTER_PORT_FLG_GET_TIMER) { - REG_READ(&priv->regs->treload[port]); - } - pktl = cfg->packet_length; - if (cfg->flag & ROUTER_PORT_FLG_GET_PKTLEN) { - REG_READ(&priv->regs->maxplen[port]); - } - - if (cfg->flag & ROUTER_PORT_FLG_SET_CTRL) { - REG_WRITE(&priv->regs->pctrl[port], cfg->ctrl); - } - if (cfg->flag & ROUTER_PORT_FLG_SET_CTRL2) { - REG_WRITE(&priv->regs->pctrl2[port], cfg->ctrl2); - } - if (cfg->flag & ROUTER_PORT_FLG_SET_STS) { - REG_WRITE(&priv->regs->psts[port], cfg->sts); - } - if (cfg->flag & ROUTER_PORT_FLG_SET_TIMER) { - REG_WRITE(&priv->regs->treload[port], cfg->timer_reload & PTIMER_RL); - } - if (cfg->flag & ROUTER_PORT_FLG_SET_PKTLEN) { - REG_WRITE(&priv->regs->maxplen[port], cfg->packet_length & MAXPLEN_ML); - } - - SPIN_UNLOCK_IRQ(&priv->plock[port], irqflags); - - cfg->ctrl = ctrl; - cfg->ctrl2 = ctrl2; - cfg->sts = sts; - cfg->timer_reload = timer; - cfg->packet_length = pktl; - - return ROUTER_ERR_OK; -} - -int router_port_ctrl_rmw(void *d, int port, uint32_t *oldvalue, uint32_t bitmask, uint32_t value) -{ - struct router_priv *priv = d; - int error = router_check_port(d, port); - unsigned int oldctrl, ctrl; - SPIN_IRQFLAGS(irqflags); - - if (error) - return error; - - SPIN_LOCK_IRQ(&priv->plock[port], irqflags); - - oldctrl = REG_READ(&priv->regs->pctrl[port]); - ctrl = ((oldctrl & ~(bitmask)) | (value & bitmask)); - REG_WRITE(&priv->regs->pctrl[port], ctrl); - - SPIN_UNLOCK_IRQ(&priv->plock[port], irqflags); - - if (oldvalue != NULL) { - *oldvalue = oldctrl; - } - - return ROUTER_ERR_OK; -} - -int router_port_ctrl2_rmw(void *d, int port, uint32_t *oldvalue, uint32_t bitmask, uint32_t value) -{ - struct router_priv *priv = d; - int error = router_check_port(d, port); - unsigned int oldctrl, ctrl; - SPIN_IRQFLAGS(irqflags); - - if (error) - return error; - - SPIN_LOCK_IRQ(&priv->plock[port], irqflags); - - oldctrl = REG_READ(&priv->regs->pctrl2[port]); - ctrl = ((oldctrl & ~(bitmask)) | (value & bitmask)); - REG_WRITE(&priv->regs->pctrl2[port], ctrl); - - SPIN_UNLOCK_IRQ(&priv->plock[port], irqflags); - - if (oldvalue != NULL) { - *oldvalue = oldctrl; - } - - return ROUTER_ERR_OK; -} - -/* Read Port Control register */ -int router_port_ctrl_get(void *d, int port, uint32_t *ctrl) -{ - struct router_priv *priv = d; - int error = router_check_port(d, port); - - if (error) - return error; - - if (ctrl == NULL) { - DBG("ROUTER Wrong ctrl\n"); - return ROUTER_ERR_EINVAL; - } - - *ctrl = REG_READ(&priv->regs->pctrl[port]); - return ROUTER_ERR_OK; -} - -/* Read Port Status register and clear errors if there are */ -int router_port_status(void *d, int port, uint32_t *sts, uint32_t clrmsk) -{ - struct router_priv *priv = d; - int error = router_check_port(d, port); - SPIN_IRQFLAGS(irqflags); - - if (error) - return error; - - if (sts == NULL) { - DBG("ROUTER Wrong sts\n"); - return ROUTER_ERR_EINVAL; - } - - SPIN_LOCK_IRQ(&priv->plock[port], irqflags); - *sts = REG_READ(&priv->regs->psts[port]); - if (port == 0) { - REG_WRITE(&priv->regs->psts[port], ((*sts) & (PSTSCFG_WCLEAR & clrmsk)) | (PSTSCFG_WCLEAR2 & clrmsk)); - }else{ - REG_WRITE(&priv->regs->psts[port], (*sts) & (PSTS_WCLEAR & clrmsk)); - } - SPIN_UNLOCK_IRQ(&priv->plock[port], irqflags); - return ROUTER_ERR_OK; -} - -/* Read Port Control2 register */ -int router_port_ctrl2_get(void *d, int port, uint32_t *ctrl2) -{ - struct router_priv *priv = d; - int error = router_check_port(d, port); - - if (error) - return error; - - if (ctrl2 == NULL) { - DBG("ROUTER Wrong ctrl2\n"); - return ROUTER_ERR_EINVAL; - } - - *ctrl2 = REG_READ(&priv->regs->pctrl2[port]); - return ROUTER_ERR_OK; -} - -/* Write Port Control Register */ -int router_port_ctrl_set(void *d, int port, uint32_t mask, uint32_t ctrl) -{ - return router_port_ctrl_rmw(d, port, NULL, mask, ctrl); -} - -/* Write Port Control2 Register */ -int router_port_ctrl2_set(void *d, int port, uint32_t mask, uint32_t ctrl2) -{ - return router_port_ctrl_rmw(d, port, NULL, mask, ctrl2); -} - -int router_port_treload_set(void *d, int port, uint32_t reload) -{ - struct router_priv *priv = d; - int error = router_check_port(d, port); - - if (error) - return error; - - REG_WRITE(&priv->regs->treload[port], reload & PTIMER_RL); - - return ROUTER_ERR_OK; -} - -int router_port_treload_get(void *d, int port, uint32_t *reload) -{ - struct router_priv *priv = d; - int error = router_check_port(d, port); - - if (error) - return error; - - if (reload == NULL) { - DBG("ROUTER Wrong reload pointer\n"); - return ROUTER_ERR_EINVAL; - } - - *reload = REG_READ(&priv->regs->treload[port]) & PTIMER_RL; - - return ROUTER_ERR_OK; -} - -int router_port_maxplen_set(void *d, int port, uint32_t length) -{ - struct router_priv *priv = d; - int error = router_check_port(d, port); - - if (error) - return error; - - REG_WRITE(&priv->regs->maxplen[port], length & MAXPLEN_ML); - - return ROUTER_ERR_OK; -} - -int router_port_maxplen_get(void *d, int port, uint32_t *length) -{ - struct router_priv *priv = d; - int error = router_check_port(d, port); - - if (error) - return error; - - if (length == NULL) { - DBG("ROUTER Wrong length pointer\n"); - return ROUTER_ERR_EINVAL; - } - - *length = REG_READ(&priv->regs->maxplen[port]); - - return ROUTER_ERR_OK; -} - -/* Get Port Link Status */ -int router_port_link_status(void *d, int port) -{ - struct router_priv *priv = d; - int error = router_check_port(d, port); - - if (error) - return error; - - return ((REG_READ(&priv->regs->psts[port]) & PSTS_LS) >> PSTS_LS_BIT); -} - -int router_port_disable(void *d, int port) -{ - return router_port_ctrl_rmw(d, port, NULL, PCTRL_DI, PCTRL_DI); -} - -int router_port_enable(void *d, int port) -{ - return router_port_ctrl_rmw(d, port, NULL, PCTRL_DI, 0); -} - -int router_port_link_stop(void *d, int port) -{ - return router_port_ctrl_rmw(d, port, NULL, PCTRL_LD | PCTRL_LS, PCTRL_LD); -} - -int router_port_link_start(void *d, int port) -{ - return router_port_ctrl_rmw(d, port, NULL, PCTRL_LD | PCTRL_LS, PCTRL_LS); -} - -int router_port_link_receive_spill(void *d, int port) -{ - struct router_priv *priv = d; - unsigned int ctrl; - SPIN_IRQFLAGS(irqflags); - int error = router_check_port(d, port); - - if (error) - return error; - - SPIN_LOCK_IRQ(&priv->plock[port], irqflags); - - ctrl = REG_READ(&priv->regs->pctrl[port]); - REG_WRITE(&priv->regs->pctrl[port], (ctrl| (PCTRL_RS))); - - /* Wait until the spill is done */ - while(REG_READ(&priv->regs->pctrl[port]) & PCTRL_RS) {}; - - SPIN_UNLOCK_IRQ(&priv->plock[port], irqflags); - - return ROUTER_ERR_OK; -} - -int router_port_link_transmit_reset(void *d, int port) -{ - struct router_priv *priv = d; - unsigned int ctrl; - SPIN_IRQFLAGS(irqflags); - int error = router_check_port(d, port); - - if (error) - return error; - - SPIN_LOCK_IRQ(&priv->plock[port], irqflags); - - ctrl = REG_READ(&priv->regs->pctrl[port]); - REG_WRITE(&priv->regs->pctrl[port], (ctrl| (PCTRL_TF))); - - /* Wait until the spill is done */ - while(REG_READ(&priv->regs->pctrl[port]) & PCTRL_TF) {}; - - SPIN_UNLOCK_IRQ(&priv->plock[port], irqflags); - - return ROUTER_ERR_OK; -} - -int router_port_cred_get(void *d, int port, uint32_t *cred) -{ - struct router_priv *priv = d; - int error = router_check_port(d, port); - - if (error) - return error; - - if (cred == NULL) { - DBG("ROUTER Wrong cred pointer\n"); - return ROUTER_ERR_EINVAL; - } - - *cred = REG_READ(&priv->regs->credcnt[port]); - return ROUTER_ERR_OK; -} - -int router_instance_set(void *d, uint8_t instance) -{ - struct router_priv *priv = d; - int error = router_check_open(d); - - if (error) - return error; - - REG_WRITE(&priv->regs->ver, (instance << VER_ID_BIT) & VER_ID); - return ROUTER_ERR_OK; -} - -int router_idiv_set(void *d, uint8_t idiv) -{ - struct router_priv *priv = d; - int error = router_check_open(d); - - if (error) - return error; - - REG_WRITE(&priv->regs->idiv, (idiv << IDIV_ID_BIT) & IDIV_ID); - return ROUTER_ERR_OK; -} - -int router_tpresc_set(void *d, uint32_t prescaler) -{ - struct router_priv *priv = d; - int error = router_check_open(d); - - if (error) - return error; - - REG_WRITE(&priv->regs->tprescaler, - (prescaler << PRESCALER_RL_BIT) & PRESCALER_RL); - return ROUTER_ERR_OK; -} - -int router_instance_get(void *d, uint8_t *instance) -{ - struct router_priv *priv = d; - int error = router_check_open(d); - - if (error) - return error; - - if (instance == NULL) { - DBG("ROUTER Wrong instance pointer\n"); - return ROUTER_ERR_EINVAL; - } - - *instance = REG_READ(&priv->regs->ver); - - return ROUTER_ERR_OK; -} - -int router_idiv_get(void *d, uint8_t *idiv) -{ - struct router_priv *priv = d; - int error = router_check_open(d); - - if (error) - return error; - - if (idiv == NULL) { - DBG("ROUTER Wrong idiv pointer\n"); - return ROUTER_ERR_EINVAL; - } - - *idiv = REG_READ(&priv->regs->idiv); - - return ROUTER_ERR_OK; -} - -int router_tpresc_get(void *d, uint32_t *prescaler) -{ - struct router_priv *priv = d; - int error = router_check_open(d); - - if (error) - return error; - - if (prescaler == NULL) { - DBG("ROUTER Wrong prescaler pointer\n"); - return ROUTER_ERR_EINVAL; - } - - *prescaler = REG_READ(&priv->regs->tprescaler); - - return ROUTER_ERR_OK; -} - -int router_cfgsts_set(void *d, uint32_t cfgsts) -{ - struct router_priv *priv = d; - int error = router_check_open(d); - - if (error) - return error; - - REG_WRITE(&priv->regs->cfgsts, cfgsts); - - return ROUTER_ERR_OK; -} - -int router_cfgsts_get(void *d, uint32_t *cfgsts) -{ - struct router_priv *priv = d; - int error = router_check_open(d); - - if (error) - return error; - - if (cfgsts == NULL) { - DBG("ROUTER Wrong cfgsts pointer\n"); - return ROUTER_ERR_EINVAL; - } - - *cfgsts = REG_READ(&priv->regs->cfgsts); - - return ROUTER_ERR_OK; -} - -int router_tc_enable(void *d) -{ - struct router_priv *priv = d; - int error = router_check_open(d); - - if (error) - return error; - - REG_WRITE(&priv->regs->timecode, TC_EN); - - return ROUTER_ERR_OK; -} - -int router_tc_disable(void *d) -{ - struct router_priv *priv = d; - int error = router_check_open(d); - - if (error) - return error; - - REG_WRITE(&priv->regs->timecode, 0); - - return ROUTER_ERR_OK; -} - -int router_tc_reset(void *d) -{ - struct router_priv *priv = d; - unsigned int tc; - int error = router_check_open(d); - - if (error) - return error; - - tc = REG_READ(&priv->regs->timecode); - REG_WRITE(&priv->regs->timecode, tc | TC_RE); - - return ROUTER_ERR_OK; -} - -int router_tc_get(void *d) -{ - struct router_priv *priv = d; - int error = router_check_open(d); - - if (error) - return error; - - return (REG_READ(&priv->regs->timecode) & (TC_CF | TC_TC)) >> TC_TC_BIT; -} - -int router_interrupt_unmask(void *d, int options) -{ - struct router_priv *priv = d; - unsigned int mask; - int error = router_check_open(d); - - if (error) - return error; - - #ifdef THREAD_SAFE - /* Take device lock - Wait until we get semaphore */ - if (rtems_semaphore_obtain(priv->sem, RTEMS_WAIT, RTEMS_NO_TIMEOUT) - != RTEMS_SUCCESSFUL) { - DBG("ROUTER Sempahore failed\n"); - return ROUTER_ERR_ERROR; - } - #endif - - /* Unmask interrupts in ROTUER */ - /* Get previous mask */ - mask = REG_READ(&priv->regs->imask); - - /* Clear previous interrupts*/ - REG_WRITE(&priv->regs->pip, 0xffffffff); - - /* Set new mask */ - REG_WRITE(&priv->regs->imask, mask | options); - - #ifdef THREAD_SAFE - /* Unlock dev */ - rtems_semaphore_release(priv->sem); - #endif - - return ROUTER_ERR_OK; -} - -int router_interrupt_mask(void *d, int options) -{ - struct router_priv *priv = d; - unsigned int mask; - int error = router_check_open(d); - - if (error) - return error; - - #ifdef THREAD_SAFE - /* Take device lock - Wait until we get semaphore */ - if (rtems_semaphore_obtain(priv->sem, RTEMS_WAIT, RTEMS_NO_TIMEOUT) - != RTEMS_SUCCESSFUL) { - DBG("ROUTER Sempahore failed\n"); - return ROUTER_ERR_ERROR; - } - #endif - - /* Mask interrupts in ROTUER */ - /* Get previous mask */ - mask = REG_READ(&priv->regs->imask); - - /* Clear previous interrupts*/ - REG_WRITE(&priv->regs->pip, 0xffffffff); - - /* Set new mask */ - REG_WRITE(&priv->regs->imask, mask & ~(options)); - - #ifdef THREAD_SAFE - /* Unlock dev */ - rtems_semaphore_release(priv->sem); - #endif - - return ROUTER_ERR_OK; -} - -int router_port_interrupt_unmask(void *d, int port) -{ - struct router_priv *priv = d; - unsigned int mask; - int error = router_check_port(d, port); - - if (error) - return error; - - #ifdef THREAD_SAFE - /* Take device lock - Wait until we get semaphore */ - if (rtems_semaphore_obtain(priv->sem, RTEMS_WAIT, RTEMS_NO_TIMEOUT) - != RTEMS_SUCCESSFUL) { - DBG("ROUTER Sempahore failed\n"); - return ROUTER_ERR_ERROR; - } - #endif - - /* Unmask interrupts in ROTUER */ - /* Get previous mask */ - mask = REG_READ(&priv->regs->ipmask); - - /* Clear previous interrupts*/ - REG_WRITE(&priv->regs->pip, (0x1 << port)); - - /* Set new mask */ - REG_WRITE(&priv->regs->ipmask, mask | (0x1 << port)); - - #ifdef THREAD_SAFE - /* Unlock dev */ - rtems_semaphore_release(priv->sem); - #endif - - return ROUTER_ERR_OK; -} - -int router_port_interrupt_mask(void *d, int port) -{ - struct router_priv *priv = d; - unsigned int mask; - int error = router_check_port(d, port); - - if (error) - return error; - - #ifdef THREAD_SAFE - /* Take device lock - Wait until we get semaphore */ - if (rtems_semaphore_obtain(priv->sem, RTEMS_WAIT, RTEMS_NO_TIMEOUT) - != RTEMS_SUCCESSFUL) { - DBG("ROUTER Sempahore failed\n"); - return ROUTER_ERR_ERROR; - } - #endif - - /* Mask interrupts in ROTUER */ - /* Get previous mask */ - mask = REG_READ(&priv->regs->ipmask); - - /* Clear previous interrupts*/ - REG_WRITE(&priv->regs->pip, (0x1 << port)); - - /* Set new mask */ - REG_WRITE(&priv->regs->ipmask, mask & ~(0x1 << port)); - - #ifdef THREAD_SAFE - /* Unlock dev */ - rtems_semaphore_release(priv->sem); - #endif - - return ROUTER_ERR_OK; -} - -int router_reset(void *d) -{ - struct router_priv *priv = d; - int error = router_check_open(d); - - if (error) - return error; - - /* Reset router */ - REG_WRITE(&priv->regs->cfgsts, RTRCFG_RE); - - return ROUTER_ERR_OK; -} - -int router_icodegen_enable(void *d, uint8_t intn, uint32_t aitimer, - int options) -{ - struct router_priv *priv = d; - int error = router_check_distint_support(d); - - if (error) - return error; - - #ifdef THREAD_SAFE - /* Take device lock - Wait until we get semaphore */ - if (rtems_semaphore_obtain(priv->sem, RTEMS_WAIT, RTEMS_NO_TIMEOUT) - != RTEMS_SUCCESSFUL) { - DBG("ROUTER Sempahore failed\n"); - return ROUTER_ERR_ERROR; - } - #endif - - REG_WRITE(&priv->regs->icodegen, (options & ~(ICODEGEN_IN)) | - ICODEGEN_EN | (intn & ICODEGEN_IN)); - - if (options & ICODEGEN_TE) { - REG_WRITE(&priv->regs->aitimer, (aitimer & AITIMER_RL)); - } - - #ifdef THREAD_SAFE - /* Unlock dev */ - rtems_semaphore_release(priv->sem); - #endif - - return ROUTER_ERR_OK; -} - -int router_icodegen_disable(void *d) -{ - struct router_priv *priv = d; - int error = router_check_distint_support(d); - - if (error) - return error; - - REG_WRITE(&priv->regs->icodegen, ICODEGEN_TE); - - return ROUTER_ERR_OK; -} - -int router_isrctimer_set(void *d, uint32_t reloadvalue) -{ - struct router_priv *priv = d; - int error = router_check_distint_support(d); - - if (error) - return error; - - /* Set ISRC TIMER */ - REG_WRITE(&priv->regs->isrctimer, (reloadvalue & (ISRCTIMER_RL))); - - return ROUTER_ERR_OK; -} - -int router_isrtimer_set(void *d, uint32_t reloadvalue) -{ - struct router_priv *priv = d; - int error = router_check_distint_support(d); - - if (error) - return error; - - /* Set ISR TIMER */ - REG_WRITE(&priv->regs->isrtimer, (reloadvalue & (ISRTIMER_RL))); - - return ROUTER_ERR_OK; -} - -int router_isrctimer_get(void *d, uint32_t *reloadvalue) -{ - struct router_priv *priv = d; - int error = router_check_distint_support(d); - - if (error) - return error; - - if (reloadvalue == NULL) { - DBG("ROUTER Wrong reloadvalue pointer\n"); - return ROUTER_ERR_EINVAL; - } - - /* Set ISRC TIMER */ - *reloadvalue = REG_READ(&priv->regs->isrctimer) & (ISRCTIMER_RL); - - return ROUTER_ERR_OK; -} - -int router_isrtimer_get(void *d, uint32_t *reloadvalue) -{ - struct router_priv *priv = d; - int error = router_check_distint_support(d); - - if (error) - return error; - - if (reloadvalue == NULL) { - DBG("ROUTER Wrong reloadvalue pointer\n"); - return ROUTER_ERR_EINVAL; - } - - /* Set ISR TIMER */ - *reloadvalue = REG_READ(&priv->regs->isrtimer) & (ISRTIMER_RL); - - return ROUTER_ERR_OK; -} diff --git a/c/src/lib/libbsp/sparc/shared/stat/l4stat.c b/c/src/lib/libbsp/sparc/shared/stat/l4stat.c deleted file mode 100644 index a7621feb00..0000000000 --- a/c/src/lib/libbsp/sparc/shared/stat/l4stat.c +++ /dev/null @@ -1,626 +0,0 @@ -/* L4STAT APB-Register Driver. - * - * COPYRIGHT (c) 2017. - * Cobham Gaisler AB. - * - * 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 /* printk */ - -#include -#include -#include - -/*#define STATIC*/ -#define STATIC static - -/*#define DEBUG 1*/ - -#ifdef DEBUG -#define DBG(x...) printf(x) -#else -#define DBG(x...) -#endif - -#define REG_WRITE(addr, val) (*(volatile unsigned int *)(addr) = (unsigned int)(val)) -#define REG_READ(addr) (*(volatile unsigned int *)(addr)) - - -/* - * L4STAT CCTRL register fields - * DEFINED IN HEADER file - */ - -struct l4stat_regs { - unsigned int cval[32]; /* 0x000 */ - unsigned int cctrl[32]; /* 0x080 */ - unsigned int cmax[32]; /* 0x100 */ - unsigned int timestamp; /* 0x180 */ -}; - -struct l4stat_priv { - struct drvmgr_dev *dev; - - /* L4STAT control registers */ - struct l4stat_regs *regs; - - /* L4STAT driver register */ - char devname[9]; - - int ncpu; - int ncnt; - - /* L4stat capabilities */ - int max_count_support; - int internalahb_event_support; - int dsu_event_support; - int external_event_support; - int ahbtrace_event_support; -}; - -STATIC struct l4stat_priv *l4statpriv = NULL; - -/* Event names */ -#ifdef DEBUG -#define L4STAT_BAD_CMD "N/A. Wrong event" -STATIC const char *l4stat_event_names[] = { - "Instruction cache miss", /* 0x00 */ - "Instruction MMU TLB miss", /* 0x01 */ - "Instruction cache hold", /* 0x02 */ - "Instruction MMU hold", /* 0x03 */ - L4STAT_BAD_CMD, /* 0x04 */ - L4STAT_BAD_CMD, /* 0x05 */ - L4STAT_BAD_CMD, /* 0x06 */ - L4STAT_BAD_CMD, /* 0x07 */ - "Data cache (read) miss", /* 0x08 */ - "Data MMU TLB miss", /* 0x09 */ - "Data cache hold", /* 0x0a */ - "Data MMU hold", /* 0x0b */ - L4STAT_BAD_CMD, /* 0x0c */ - L4STAT_BAD_CMD, /* 0x0d */ - L4STAT_BAD_CMD, /* 0x0e */ - L4STAT_BAD_CMD, /* 0x0f */ - "Data write buffer hold", /* 0x10 */ - "Total instruction count", /* 0x11 */ - "Integer instruction count", /* 0x12 */ - "Floating-point unit instruction count", /* 0x13 */ - "Branch prediction miss", /* 0x14 */ - "Execution time, exluding debug mode", /* 0x15 */ - L4STAT_BAD_CMD, /* 0x16 */ - "AHB utilization (per AHB master)", /* 0x17 */ - "AHB utilization (total)", /* 0x18 */ - L4STAT_BAD_CMD, /* 0x19 */ - L4STAT_BAD_CMD, /* 0x1a */ - L4STAT_BAD_CMD, /* 0x1b */ - L4STAT_BAD_CMD, /* 0x1c */ - L4STAT_BAD_CMD, /* 0x1d */ - L4STAT_BAD_CMD, /* 0x1e */ - L4STAT_BAD_CMD, /* 0x1f */ - L4STAT_BAD_CMD, /* 0x20 */ - L4STAT_BAD_CMD, /* 0x21 */ - "Integer branches", /* 0x22 */ - L4STAT_BAD_CMD, /* 0x23 */ - L4STAT_BAD_CMD, /* 0x24 */ - L4STAT_BAD_CMD, /* 0x25 */ - L4STAT_BAD_CMD, /* 0x26 */ - L4STAT_BAD_CMD, /* 0x27 */ - "CALL instructions", /* 0x28 */ - L4STAT_BAD_CMD, /* 0x29 */ - L4STAT_BAD_CMD, /* 0x2a */ - L4STAT_BAD_CMD, /* 0x2b */ - L4STAT_BAD_CMD, /* 0x2c */ - L4STAT_BAD_CMD, /* 0x2d */ - L4STAT_BAD_CMD, /* 0x2e */ - L4STAT_BAD_CMD, /* 0x2f */ - "Regular type 2 instructions", /* 0x30 */ - L4STAT_BAD_CMD, /* 0x31 */ - L4STAT_BAD_CMD, /* 0x32 */ - L4STAT_BAD_CMD, /* 0x33 */ - L4STAT_BAD_CMD, /* 0x34 */ - L4STAT_BAD_CMD, /* 0x35 */ - L4STAT_BAD_CMD, /* 0x36 */ - L4STAT_BAD_CMD, /* 0x37 */ - "LOAD and STORE instructions", /* 0x38 */ - "LOAD instructions", /* 0x39 */ - "STORE instructions", /* 0x3a */ - L4STAT_BAD_CMD, /* 0x3b */ - L4STAT_BAD_CMD, /* 0x3c */ - L4STAT_BAD_CMD, /* 0x3d */ - L4STAT_BAD_CMD, /* 0x3e */ - L4STAT_BAD_CMD, /* 0x3f */ - "AHB IDLE cycles", /* 0x40 */ - "AHB BUSY cycles", /* 0x41 */ - "AHB Non-Seq. transfers", /* 0x42 */ - "AHB Seq. transfers", /* 0x43 */ - "AHB read accesses", /* 0x44 */ - "AHB write accesses", /* 0x45 */ - "AHB byte accesses", /* 0x46 */ - "AHB half-word accesses", /* 0x47 */ - "AHB word accesses", /* 0x48 */ - "AHB double word accesses", /* 0x49 */ - "AHB quad word accesses", /* 0x4A */ - "AHB eight word accesses", /* 0x4B */ - "AHB waitstates", /* 0x4C */ - "AHB RETRY responses", /* 0x4D */ - "AHB SPLIT responses", /* 0x4E */ - "AHB SPLIT delay", /* 0x4F */ - "AHB bus locked", /* 0x50 */ - L4STAT_BAD_CMD, /* 0x51 */ - L4STAT_BAD_CMD, /* 0x52 */ - L4STAT_BAD_CMD, /* 0x53 */ - L4STAT_BAD_CMD, /* 0x54 */ - L4STAT_BAD_CMD, /* 0x55 */ - L4STAT_BAD_CMD, /* 0x56 */ - L4STAT_BAD_CMD, /* 0x57 */ - L4STAT_BAD_CMD, /* 0x58 */ - L4STAT_BAD_CMD, /* 0x59 */ - L4STAT_BAD_CMD, /* 0x5a */ - L4STAT_BAD_CMD, /* 0x5b */ - L4STAT_BAD_CMD, /* 0x5c */ - L4STAT_BAD_CMD, /* 0x5d */ - L4STAT_BAD_CMD, /* 0x5e */ - L4STAT_BAD_CMD, /* 0x5f */ - "external event 0", /* 0x60 */ - "external event 1", /* 0x61 */ - "external event 2", /* 0x62 */ - "external event 3", /* 0x63 */ - "external event 4", /* 0x64 */ - "external event 5", /* 0x65 */ - "external event 6", /* 0x66 */ - "external event 7", /* 0x67 */ - "external event 8", /* 0x68 */ - "external event 9", /* 0x69 */ - "external event 10", /* 0x6A */ - "external event 11", /* 0x6B */ - "external event 12", /* 0x6C */ - "external event 13", /* 0x6D */ - "external event 14", /* 0x6E */ - "external event 15", /* 0x6F */ - "AHB IDLE cycles (2)", /* 0x70 */ - "AHB BUSY cycles (2)", /* 0x71 */ - "AHB Non-Seq. transfers (2)", /* 0x72 */ - "AHB Seq. transfers (2)", /* 0x73 */ - "AHB read accesses (2)", /* 0x74 */ - "AHB write accesses (2)", /* 0x75 */ - "AHB byte accesses (2)", /* 0x76 */ - "AHB half-word accesses (2)", /* 0x77 */ - "AHB word accesses (2)", /* 0x78 */ - "AHB double word accesses (2)", /* 0x79 */ - "AHB quad word accesses (2)", /* 0x7A */ - "AHB eight word accesses (2)", /* 0x7B */ - "AHB waitstates (2)", /* 0x7C */ - "AHB RETRY responses (2)", /* 0x7D */ - "AHB SPLIT responses (2)", /* 0x7E */ - "AHB SPLIT delay (2)", /* 0x7F */ - "PMC: master 0 has grant", /* 0x80 */ - "PMC: master 1 has grant", /* 0x81 */ - "PMC: master 2 has grant", /* 0x82 */ - "PMC: master 3 has grant", /* 0x83 */ - "PMC: master 4 has grant", /* 0x84 */ - "PMC: master 5 has grant", /* 0x85 */ - "PMC: master 6 has grant", /* 0x86 */ - "PMC: master 7 has grant", /* 0x87 */ - "PMC: master 8 has grant", /* 0x88 */ - "PMC: master 9 has grant", /* 0x89 */ - "PMC: master 10 has grant", /* 0x8A */ - "PMC: master 11 has grant", /* 0x8B */ - "PMC: master 12 has grant", /* 0x8C */ - "PMC: master 13 has grant", /* 0x8D */ - "PMC: master 14 has grant", /* 0x8E */ - "PMC: master 15 has grant", /* 0x8F */ - "PMC: master 0 lacks grant", /* 0x90 */ - "PMC: master 1 lacks grant", /* 0x91 */ - "PMC: master 2 lacks grant", /* 0x92 */ - "PMC: master 3 lacks grant", /* 0x93 */ - "PMC: master 4 lacks grant", /* 0x94 */ - "PMC: master 5 lacks grant", /* 0x95 */ - "PMC: master 6 lacks grant", /* 0x96 */ - "PMC: master 7 lacks grant", /* 0x97 */ - "PMC: master 8 lacks grant", /* 0x98 */ - "PMC: master 9 lacks grant", /* 0x99 */ - "PMC: master 10 lacks grant", /* 0x9A */ - "PMC: master 11 lacks grant", /* 0x9B */ - "PMC: master 12 lacks grant", /* 0x9C */ - "PMC: master 13 lacks grant", /* 0x9D */ - "PMC: master 14 lacks grant", /* 0x9E */ - "PMC: master 15 lacks grant", /* 0x9F */ - "" -}; -#endif /* DEBUG */ - -/* Driver prototypes */ - -STATIC int l4stat_init(struct l4stat_priv *priv); - -int l4stat_init1(struct drvmgr_dev *dev); - -struct drvmgr_drv_ops l4stat_ops = -{ - .init = {l4stat_init1, NULL, NULL, NULL}, - .remove = NULL, - .info = NULL -}; - -struct amba_dev_id l4stat_ids[] = -{ - {VENDOR_GAISLER, GAISLER_L4STAT}, - {VENDOR_GAISLER, GAISLER_L3STAT}, - {0, 0} /* Mark end of table */ -}; - -struct amba_drv_info l4stat_drv_info = -{ - { - DRVMGR_OBJ_DRV, /* Driver */ - NULL, /* Next driver */ - NULL, /* Device list */ - DRIVER_AMBAPP_GAISLER_L4STAT_ID,/* Driver ID */ - "L4STAT_DRV", /* Driver Name */ - DRVMGR_BUS_TYPE_AMBAPP, /* Bus Type */ - &l4stat_ops, - NULL, /* Funcs */ - 0, /* No devices yet */ - sizeof(struct l4stat_priv), /* Let DRVMGR allocate for us */ - }, - &l4stat_ids[0], -}; - -void l4stat_register_drv (void) -{ - DBG("Registering L4STAT driver\n"); - drvmgr_drv_register(&l4stat_drv_info.general); -} - -STATIC int l4stat_init(struct l4stat_priv *priv) -{ - struct ambapp_apb_info *apb; - struct amba_dev_info *ainfo = priv->dev->businfo; - unsigned int tmp; - unsigned short dev_id; - - /* Find L4STAT core from Plug&Play information */ - apb = ainfo->info.apb_slv; - - /* Check if L4STAT or L3STAT core from Plug&Play information */ - dev_id = ainfo->id.device; - - /* Check if rev 1 of core (only rev 0 supported) */ - if (apb->ver != 0) { - DBG("L4STAT rev 0 only supported.\n"); - return L4STAT_ERR_ERROR; - } - - /* Found L4STAT core, init private structure */ - priv->regs = (struct l4stat_regs *)apb->start; - - DBG("L4STAT regs 0x%08x\n", (unsigned int) priv->regs); - - /* Find L4STAT capabilities */ - tmp = REG_READ(&priv->regs->cctrl[0]); - /* The CPU field in the register is just information of the - * cpus that are connected to the stat unit, but it is not - * really used for anything else. I can still have more masters - * on the bus (e.g. IOMMU) that I can collect stats from, - * so it makes no sense to limit the cpus to the actual cpus. - * Therefore, I will take the maximum number as 16. */ - /*priv->ncpu = ((tmp & CCTRL_NCPU) >> CCTRL_NCPU_BIT) + 1;*/ - priv->ncpu = 16; - if (dev_id == GAISLER_L3STAT) { - priv->ncnt = ((tmp & CCTRL_NCNT_L3STAT) >> CCTRL_NCNT_BIT) + 1; - }else{ - priv->ncnt = ((tmp & CCTRL_NCNT) >> CCTRL_NCNT_BIT) + 1; - } - priv->max_count_support = (tmp & CCTRL_MC) >> CCTRL_MC_BIT; - priv->internalahb_event_support = (tmp & CCTRL_IA) >> CCTRL_IA_BIT; - priv->dsu_event_support = (tmp & CCTRL_DS) >> CCTRL_DS_BIT; - priv->external_event_support = (tmp & CCTRL_EE) >> CCTRL_EE_BIT; - priv->ahbtrace_event_support = (tmp & CCTRL_AE) >> CCTRL_AE_BIT; - - /* DEBUG print */ - DBG("L4STAT with following capabilities:\n"); - DBG(" -NCPU: %d, NCNT: %d, MaxCNT: %s\n", priv->ncpu, priv->ncnt, - (priv->max_count_support?"Available":"N/A")); - DBG(" -Events= InternalAHB: %s, DSU: %s, External: %s, AHBTRACE: %s\n", - (priv->internalahb_event_support?"Available":"N/A"), - (priv->dsu_event_support?"Available":"N/A"), - (priv->external_event_support?"Available":"N/A"), - (priv->ahbtrace_event_support?"Available":"N/A")); - - return L4STAT_ERR_OK; -} - -int l4stat_init1(struct drvmgr_dev *dev) -{ - struct l4stat_priv *priv = dev->priv; - - DBG("L4STAT[%d] on bus %s\n", dev->minor_drv, dev->parent->dev->name); - - if (l4statpriv) { - DBG("Driver only supports one L4STAT core\n"); - return DRVMGR_FAIL; - } - - if (priv == NULL) { - return DRVMGR_NOMEM; - } - priv->dev = dev; - l4statpriv = priv; - - /* Initilize driver struct */ - if (l4stat_init(priv) != L4STAT_ERR_OK) { - return DRVMGR_FAIL; - } - - /* Startup Action: - * - None - */ - - /* Device name */ - sprintf(priv->devname, "l4stat0"); - - return DRVMGR_OK; -} - -int l4stat_counter_enable(unsigned int counter, int event, int cpu, int options) -{ - struct l4stat_priv *priv = l4statpriv; - unsigned int ctrl; - - if (priv == NULL) { - DBG("L4STAT Device not initialized\n"); - return L4STAT_ERR_EINVAL; - } - - if (counter >= priv->ncnt) { - DBG("L4STAT Wrong counter\n"); - return L4STAT_ERR_EINVAL; - } - - if ((cpu < 0) || (cpu >= priv->ncpu)) { - DBG("L4STAT Wrong cpu\n"); - return L4STAT_ERR_EINVAL; - } - - if ((options & L4STAT_OPTIONS_MAXIMUM_DURATION) || - (options & L4STAT_OPTIONS_EVENT_LEVEL_ENABLE)) { - if (priv->max_count_support == 0) { - DBG("L4STAT maximum duration count not supported\n"); - return L4STAT_ERR_IMPLEMENTED; - } - } - - /* Check event is supported */ - if ((event < 0) || (event >= 0x80)) { - DBG("L4STAT Wrong event\n"); - return L4STAT_ERR_EINVAL; - } - if ((event == 0x18) || (event == 0x17)) { - if (priv->internalahb_event_support == 0) { - DBG("L4STAT internal ahb event not supported\n"); - return L4STAT_ERR_IMPLEMENTED; - } - } - if ((event >= 0x40) && (event < 0x60)) { - if (priv->dsu_event_support == 0) { - DBG("L4STAT dsu event not supported\n"); - return L4STAT_ERR_IMPLEMENTED; - } - } - if ((event >= 0x60) && (event < 0x70)) { - if (priv->external_event_support == 0) { - DBG("L4STAT external event not supported\n"); - return L4STAT_ERR_IMPLEMENTED; - } - } - if ((event >= 0x70) && (event < 0x80)) { - if (priv->ahbtrace_event_support == 0) { - DBG("L4STAT ahbtrace event not supported\n"); - return L4STAT_ERR_IMPLEMENTED; - } - } - - /* Prepare counter control */ - ctrl = (options & ~(CCTRL_EVENTID | CCTRL_CPUAHBM)); - /* Put event id */ - ctrl = (ctrl | ((event << CCTRL_EVENTID_BIT) & CCTRL_EVENTID)); - /* Put cpu id */ - ctrl = (ctrl | ((cpu << CCTRL_CPUAHBM_BIT) & CCTRL_CPUAHBM)); - /* Enable counter */ - ctrl = (ctrl | CCTRL_EN); - - REG_WRITE(&priv->regs->cctrl[counter], ctrl); - - /* DEBUG print */ - DBG("L4STAT COUNTER[%d] enabled with event: %s, cpu: %d\n", counter, - l4stat_event_names[event],cpu); - - return L4STAT_ERR_OK; -} - -int l4stat_counter_disable(unsigned int counter) -{ - struct l4stat_priv *priv = l4statpriv; - - if (priv == NULL) { - DBG("L4STAT Device not initialized\n"); - return L4STAT_ERR_EINVAL; - } - - if (counter >= priv->ncnt) { - DBG("L4STAT Wrong counter\n"); - return L4STAT_ERR_EINVAL; - } - - /* Disable counter */ - REG_WRITE(&priv->regs->cctrl[counter], 0); - - /* DEBUG print */ - DBG("L4STAT COUNTER[%d] disabled\n", counter); - - return L4STAT_ERR_OK; -} - -int l4stat_counter_get(unsigned int counter, uint32_t * val) -{ - struct l4stat_priv *priv = l4statpriv; - - if (priv == NULL) { - DBG("L4STAT Device not initialized\n"); - return L4STAT_ERR_EINVAL; - } - - if (counter >= priv->ncnt) { - DBG("L4STAT Wrong counter\n"); - return L4STAT_ERR_EINVAL; - } - - if (val == NULL) { - DBG("L4STAT Wrong pointer\n"); - return L4STAT_ERR_EINVAL; - } - - *val = REG_READ(&priv->regs->cval[counter]); - - return L4STAT_ERR_OK; -} - -int l4stat_counter_set(unsigned int counter, uint32_t val) -{ - struct l4stat_priv *priv = l4statpriv; - - if (priv == NULL) { - DBG("L4STAT Device not initialized\n"); - return L4STAT_ERR_EINVAL; - } - - if (counter >= priv->ncnt) { - DBG("L4STAT Wrong counter\n"); - return L4STAT_ERR_EINVAL; - } - - REG_WRITE(&priv->regs->cval[counter],val); - - return L4STAT_ERR_OK; -} - -int l4stat_counter_max_get(unsigned int counter, uint32_t * val) -{ - struct l4stat_priv *priv = l4statpriv; - - if (priv == NULL) { - DBG("L4STAT Device not initialized\n"); - return L4STAT_ERR_EINVAL; - } - - if (counter >= priv->ncnt) { - DBG("L4STAT Wrong counter\n"); - return L4STAT_ERR_EINVAL; - } - - if (val == NULL) { - DBG("L4STAT Wrong pointer\n"); - return L4STAT_ERR_EINVAL; - } - - *val = REG_READ(&priv->regs->cmax[counter]); - - return L4STAT_ERR_OK; -} - -int l4stat_counter_max_set(unsigned int counter, uint32_t val) -{ - struct l4stat_priv *priv = l4statpriv; - - if (priv == NULL) { - DBG("L4STAT Device not initialized\n"); - return L4STAT_ERR_EINVAL; - } - - if (counter >= priv->ncnt) { - DBG("L4STAT Wrong counter\n"); - return L4STAT_ERR_EINVAL; - } - - REG_WRITE(&priv->regs->cmax[counter],val); - - return L4STAT_ERR_OK; -} - -int l4stat_tstamp_get(uint32_t * val) -{ - struct l4stat_priv *priv = l4statpriv; - - if (priv == NULL) { - DBG("L4STAT Device not initialized\n"); - return L4STAT_ERR_EINVAL; - } - - if (val == NULL) { - DBG("L4STAT Wrong pointer\n"); - return L4STAT_ERR_EINVAL; - } - - *val = REG_READ(&priv->regs->timestamp); - - return L4STAT_ERR_OK; -} - -int l4stat_tstamp_set(uint32_t val) -{ - struct l4stat_priv *priv = l4statpriv; - - if (priv == NULL) { - DBG("L4STAT Device not initialized\n"); - return L4STAT_ERR_EINVAL; - } - - REG_WRITE(&priv->regs->timestamp,val); - - return L4STAT_ERR_OK; -} - -int l4stat_counter_print(unsigned int counter) -{ -#ifdef DEBUG - struct l4stat_priv *priv = l4statpriv; - unsigned int val; - unsigned int ctrl; - unsigned int event; - - if (priv == NULL) { - DBG("L4STAT Device not initialized\n"); - return L4STAT_ERR_EINVAL; - } - - if (counter >= priv->ncnt) { - DBG("L4STAT Wrong counter\n"); - return L4STAT_ERR_EINVAL; - } - - /* Get counter val*/ - val = REG_READ(&priv->regs->cval[counter]); - - /* Get counter info*/ - ctrl = REG_READ(&priv->regs->cctrl[counter]); - if ((ctrl & CCTRL_EN) == 0) { - DBG("L4STAT COUNTER[%d] disabled\n", counter); - return L4STAT_ERR_OK; - } - - event = (ctrl & CCTRL_EVENTID) >> CCTRL_EVENTID_BIT; - - /* DEBUG print */ - DBG("L4STAT COUNTER[%d], Event: %s, Count: %d [0x%08x]\n", - counter, l4stat_event_names[event],val,val); -#endif /* DEBUG */ - - return L4STAT_ERR_OK; -} - diff --git a/c/src/lib/libbsp/sparc/shared/time/grctm.c b/c/src/lib/libbsp/sparc/shared/time/grctm.c deleted file mode 100644 index 39fc972bb9..0000000000 --- a/c/src/lib/libbsp/sparc/shared/time/grctm.c +++ /dev/null @@ -1,410 +0,0 @@ -/* GRCTM - CCSDS Time Manager - register driver interface. - * - * COPYRIGHT (c) 2009. - * Cobham Gaisler AB. - * - * 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 - -/* Private structure of GRCTM driver */ -struct grctm_priv { - struct drvmgr_dev *dev; - struct grctm_regs *regs; - int open; - - grctm_isr_t user_isr; - void *user_isr_arg; - - struct grctm_stats stats; -}; - -void grctm_isr(void *data); - -struct amba_drv_info grctm_drv_info; - -void *grctm_open(int minor) -{ - struct grctm_priv *priv; - struct drvmgr_dev *dev; - - /* Get Device from Minor */ - if ( drvmgr_get_dev(&grctm_drv_info.general, minor, &dev) ) { - return NULL; - } - - priv = dev->priv; - if ( (priv == NULL) || priv->open ) - return NULL; - - /* Set initial state of software */ - priv->open = 1; - - /* Clear Statistics */ - grctm_clr_stats(priv); - priv->user_isr = NULL; - priv->user_isr_arg = NULL; - - return priv; -} - -void grctm_close(void *grctm) -{ - struct grctm_priv *priv = (struct grctm_priv *)grctm; - - if ( priv->open == 0 ) - return; - - /* Reset Hardware */ - grctm_reset(priv); - - priv->open = 0; -} - -/* Hardware Reset of GRCTM */ -int grctm_reset(void *grctm) -{ - struct grctm_priv *priv = grctm; - struct grctm_regs *r = priv->regs; - - r->grr = 0x55000001; - - int i = 1000; - while ((r->grr & 1) && i > 0) { - i--; - } - - return i ? 0 : -1; -} - -void grctm_int_enable(void *grctm) -{ - struct grctm_priv *priv = (struct grctm_priv *)grctm; - - /* Register and Enable Interrupt at Interrupt controller */ - drvmgr_interrupt_register(priv->dev, 0, "grctm", grctm_isr, priv); -} - -void grctm_int_disable(void *grctm) -{ - struct grctm_priv *priv = (struct grctm_priv *)grctm; - - /* Enable Interrupt at Interrupt controller */ - drvmgr_interrupt_unregister(priv->dev, 0, grctm_isr, priv); -} - -void grctm_clr_stats(void *grctm) -{ - struct grctm_priv *priv = (struct grctm_priv *)grctm; - - memset(&priv->stats, 0, sizeof(priv->stats)); -} - -void grctm_get_stats(void *grctm, struct grctm_stats *stats) -{ - struct grctm_priv *priv = (struct grctm_priv *)grctm; - - memcpy(stats, &priv->stats, sizeof(priv->stats)); -} - -/* Enable external synchronisation (from grctm) */ -void grctm_enable_ext_sync(void *grctm) -{ - struct grctm_priv *priv = grctm; - - priv->regs->gcr |= 0x55<<24 | 1<<9; -} - -/* Disable external synchronisation (from grctm) */ -void grctm_disable_ext_sync(void *grctm) -{ - struct grctm_priv *priv = grctm; - - priv->regs->gcr &= ~((0xAA<<24) | 1<<9); -} - -/* Enable TimeWire synchronisation */ -void grctm_enable_tw_sync(void *grctm) -{ - struct grctm_priv *priv = grctm; - - priv->regs->gcr |= 0x55<<24 | 1<<8; -} - -/* Disable TimeWire synchronisation */ -void grctm_disable_tw_sync(void *grctm) -{ - struct grctm_priv *priv = grctm; - - priv->regs->gcr &= ~((0xAA<<24) | 1<<8); -} - -/* Disable frequency synthesizer from driving ET */ -void grctm_disable_fs(void *grctm) -{ - struct grctm_priv *priv = grctm; - - priv->regs->gcr |= 0x55<<24 | 1<<7; -} - -/* Enable frequency synthesizer to drive ET */ -void grctm_enable_fs(void *grctm) -{ - struct grctm_priv *priv = grctm; - - priv->regs->gcr &= ~((0xAA<<24) | 1<<7); -} - -/* Return elapsed coarse time */ -unsigned int grctm_get_et_coarse(void *grctm) -{ - struct grctm_priv *priv = grctm; - - return priv->regs->etcr; -} - -/* Return elapsed fine time */ -unsigned int grctm_get_et_fine(void *grctm) -{ - struct grctm_priv *priv = grctm; - - return (priv->regs->etfr & 0xffffff00) >> 8; -} - -/* Return elapsed time (coarse and fine) */ -unsigned long long grctm_get_et(void *grctm) -{ - return (((unsigned long)grctm_get_et_coarse(grctm)) << 24) | grctm_get_et_fine(grctm); -} - - -/* Return 1 if specified datation has been latched */ -int grctm_is_dat_latched(void *grctm, int dat) -{ - struct grctm_priv *priv = grctm; - - return (priv->regs->gsr >> dat) & 1; -} - -/* Set triggering edge of datation input */ -void grctm_set_dat_edge(void *grctm, int dat, int edge) -{ - struct grctm_priv *priv = grctm; - - priv->regs->gcr &= ~((0xAA<<24) | 1 << (10+dat)); - priv->regs->gcr |= 0x55<<24 | (edge&1) << (10+dat); -} - -/* Return latched datation coarse time */ -unsigned int grctm_get_dat_coarse(void *grctm, int dat) -{ - struct grctm_priv *priv = grctm; - - switch (dat) { - case 0 : return priv->regs->dcr0; - case 1 : return priv->regs->dcr1; - case 2 : return priv->regs->dcr2; - default: return -1; - } -} - -/* Return latched datation fine time */ -unsigned int grctm_get_dat_fine(void *grctm, int dat) -{ - struct grctm_priv *priv = grctm; - - switch (dat) { - case 0 : return (priv->regs->dfr0 & 0xffffff00) >> 8; - case 1 : return (priv->regs->dfr1 & 0xffffff00) >> 8; - case 2 : return (priv->regs->dfr2 & 0xffffff00) >> 8; - default: return -1; - } -} - - -/* Return latched datation ET */ -unsigned long long grctm_get_dat_et(void *grctm, int dat) -{ - return (((unsigned long)grctm_get_dat_coarse(grctm, dat)) << 24) | - grctm_get_dat_fine(grctm, dat); -} - - -/* Return current pulse configuration */ -unsigned int grctm_get_pulse_reg(void *grctm, int pulse) -{ - struct grctm_priv *priv = grctm; - - return priv->regs->pdr[pulse]; -} - -/* Set pulse register */ -void grctm_set_pulse_reg(void *grctm, int pulse, unsigned int val) -{ - struct grctm_priv *priv = grctm; - - priv->regs->pdr[pulse] = val; -} - -/* Configure pulse: pp = period, pw = width, pl = level, en = enable */ -void grctm_cfg_pulse(void *grctm, int pulse, int pp, int pw, int pl, int en) -{ - grctm_set_pulse_reg(grctm, pulse, (pp&0xf)<<20 | (pw&0xf)<<16 | (pl&1)<<10 | (en&1)<<1); -} - -/* Enable pulse output */ -void grctm_enable_pulse(void *grctm, int pulse) -{ - struct grctm_priv *priv = grctm; - - priv->regs->pdr[pulse] |= 0x2; -} - -/* Disable pulse output */ -void grctm_disable_pulse(void *grctm, int pulse) -{ - struct grctm_priv *priv = grctm; - - priv->regs->pdr[pulse] &= ~0x2; -} - -/* Clear interrupts */ -void grctm_clear_irqs(void *grctm, int irqs) -{ - struct grctm_priv *priv = grctm; - - priv->regs->picr = irqs; -} - -/* Enable interrupts */ -void grctm_enable_irqs(void *grctm, int irqs) -{ - struct grctm_priv *priv = grctm; - - priv->regs->imr = irqs; -} - -/* Set Frequency synthesizer increment */ -void grctm_set_fs_incr(void *grctm, int incr) -{ - struct grctm_priv *priv = grctm; - - priv->regs->fsir = incr; -} - -/* Set ET increment */ -void grctm_set_et_incr(void *grctm, int incr) -{ - struct grctm_priv *priv = grctm; - - priv->regs->etir = incr; -} - - -void grctm_isr(void *data) -{ - struct grctm_priv *priv = data; - struct grctm_stats *stats = &priv->stats; - unsigned int pimr = priv->regs->pimr; - - if ( pimr == 0 ) - return; - - stats->nirqs++; - if (pimr & PULSE0_IRQ ) - stats->pulse++; - - /* Let user Handle Interrupt */ - if ( priv->user_isr ) - priv->user_isr(pimr, priv->user_isr_arg); -} - -struct grctm_regs *grctm_get_regs(void *grctm) -{ - struct grctm_priv *priv = (struct grctm_priv *)grctm; - - return priv->regs; -} - -void grctm_int_register(void *grctm, grctm_isr_t func, void *data) -{ - struct grctm_priv *priv = (struct grctm_priv *)grctm; - - priv->user_isr = func; - priv->user_isr_arg = data; -} - -/*** INTERFACE TO DRIVER MANAGER ***/ - -static int grctm_init2(struct drvmgr_dev *dev) -{ - struct amba_dev_info *ambadev; - struct ambapp_core *pnpinfo; - struct grctm_priv *priv; - struct grctm_regs *regs; - - priv = (struct grctm_priv *)malloc(sizeof(*priv)); - if ( priv == NULL ) - return -1; - memset(priv, 0, sizeof(*priv)); - priv->dev = dev; - dev->priv = priv; - - /* Get device information from AMBA PnP information */ - ambadev = (struct amba_dev_info *)dev->businfo; - if ( ambadev == NULL ) { - return -1; - } - pnpinfo = &ambadev->info; - regs = (struct grctm_regs *)pnpinfo->ahb_slv->start[0]; - - priv->regs = regs; - - grctm_reset(priv); - - return 0; -} - -struct drvmgr_drv_ops grctm_ops = -{ - {NULL, grctm_init2, NULL, NULL}, - NULL, - NULL -}; - -struct amba_dev_id grctm_ids[] = -{ - {VENDOR_GAISLER, GAISLER_GRCTM}, - {0, 0} /* Mark end of table */ -}; - -struct amba_drv_info grctm_drv_info = -{ - { - DRVMGR_OBJ_DRV, /* Driver */ - NULL, /* Next driver */ - NULL, /* Device list */ - DRIVER_AMBAPP_GAISLER_GRCTM_ID, /* Driver ID */ - "GRCTM_DRV", /* Driver Name */ - DRVMGR_BUS_TYPE_AMBAPP, /* Bus Type */ - &grctm_ops, - NULL, /* Funcs */ - 0, /* No devices yet */ - 0, - }, - &grctm_ids[0] -}; - -/* Register the grctm Driver */ -void grctm_register(void) -{ - drvmgr_drv_register(&grctm_drv_info.general); -} diff --git a/c/src/lib/libbsp/sparc/shared/time/spwcuc.c b/c/src/lib/libbsp/sparc/shared/time/spwcuc.c deleted file mode 100644 index 082ced0772..0000000000 --- a/c/src/lib/libbsp/sparc/shared/time/spwcuc.c +++ /dev/null @@ -1,370 +0,0 @@ -/* SPWCUC - SpaceWire - CCSDS unsegmented Code Transfer Protocol GRLIB core - * register driver interface. - * - * COPYRIGHT (c) 2009. - * Cobham Gaisler AB. - * - * 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 - -/* Private structure of SPWCUC driver. */ -struct spwcuc_priv { - struct drvmgr_dev *dev; - struct spwcuc_regs *regs; - int open; - - spwcuc_isr_t user_isr; - void *user_isr_arg; - - struct spwcuc_stats stats; -}; - -void spwcuc_isr(void *data); - -struct amba_drv_info spwcuc_drv_info; - -/* Hardware Reset of SPWCUC */ -static int spwcuc_hw_reset(struct spwcuc_priv *priv) -{ - struct spwcuc_regs *r = priv->regs; - int i = 1000; - - r->control = 1; - - while ((r->control & 1) && i > 0) { - i--; - } - - spwcuc_clear_irqs(priv, -1); - - return i ? 0 : -1; -} - -int spwcuc_reset(void *spwcuc) -{ - struct spwcuc_priv *priv = (struct spwcuc_priv *)spwcuc; - - return spwcuc_hw_reset(priv); -} - -void *spwcuc_open(int minor) -{ - struct spwcuc_priv *priv; - struct drvmgr_dev *dev; - - /* Get Device from Minor */ - if ( drvmgr_get_dev(&spwcuc_drv_info.general, minor, &dev) ) { - return NULL; - } - - priv = dev->priv; - if ( (priv == NULL) || priv->open ) - return NULL; - - /* Set initial state of software */ - priv->open = 1; - - /* Clear Statistics */ - spwcuc_clr_stats(priv); - priv->user_isr = NULL; - priv->user_isr_arg = NULL; - - return priv; -} - -void spwcuc_close(void *spwcuc) -{ - struct spwcuc_priv *priv = (struct spwcuc_priv *)spwcuc; - - if ( priv->open == 0 ) - return; - - /* Reset Hardware */ - spwcuc_hw_reset(priv); - - priv->open = 0; -} - -void spwcuc_int_enable(void *spwcuc) -{ - struct spwcuc_priv *priv = (struct spwcuc_priv *)spwcuc; - - /* Register and Enable Interrupt at Interrupt controller */ - drvmgr_interrupt_register(priv->dev, 0, "spwcuc", spwcuc_isr, priv); -} - -void spwcuc_int_disable(void *spwcuc) -{ - struct spwcuc_priv *priv = (struct spwcuc_priv *)spwcuc; - - /* Enable Interrupt at Interrupt controller */ - drvmgr_interrupt_unregister(priv->dev, 0, spwcuc_isr, priv); -} - -void spwcuc_clr_stats(void *spwcuc) -{ - struct spwcuc_priv *priv = (struct spwcuc_priv *)spwcuc; - - memset(&priv->stats, 0, sizeof(priv->stats)); -} - -void spwcuc_get_stats(void *spwcuc, struct spwcuc_stats *stats) -{ - struct spwcuc_priv *priv = (struct spwcuc_priv *)spwcuc; - - memcpy(stats, &priv->stats, sizeof(priv->stats)); -} - -/* Configure the spwcuc core */ -void spwcuc_config(void *spwcuc, struct spwcuc_cfg *cfg) -{ - struct spwcuc_priv *priv = (struct spwcuc_priv *)spwcuc; - struct spwcuc_regs *r = priv->regs; - - r->config = (cfg->sel_out & 0x1f) << 28 | - (cfg->sel_in & 0x1f) << 24 | - (cfg->mapping & 0x1f) << 16 | - (cfg->tolerance & 0x1f) << 8 | - (cfg->tid & 0x7) << 4 | - (cfg->ctf & 1) << 1 | - (cfg->cp & 1); - - r->control = (cfg->txen & 1) << 1 | - (cfg->rxen & 1) << 2 | - (cfg->pktsyncen & 1) << 3 | - (cfg->pktiniten & 1) << 4 | - (cfg->pktrxen & 1) << 5; - - r->dla = (cfg->dla_mask & 0xff)<<8 | (cfg->dla & 0xff); - - r->pid = cfg->pid; - - r->offset = cfg->offset; -} - -/* Return elapsed coarse time */ -unsigned int spwcuc_get_et_coarse(void *spwcuc) -{ - struct spwcuc_priv *priv = (struct spwcuc_priv *)spwcuc; - - return priv->regs->etct; -} - -/* Return elapsed fine time */ -unsigned int spwcuc_get_et_fine(void *spwcuc) -{ - struct spwcuc_priv *priv = (struct spwcuc_priv *)spwcuc; - - return (priv->regs->etft & 0xffffff) >> 8; -} - -/* Return elapsed time (coarse and fine) */ -unsigned long long spwcuc_get_et(void *spwcuc) -{ - return (((unsigned long long)spwcuc_get_et_coarse(spwcuc)) << 24) | spwcuc_get_et_fine(spwcuc); -} - -/* Return next elapsed coarse time (for use when sending SpW time packet) */ -unsigned int spwcuc_get_next_et_coarse(void *spwcuc) -{ - struct spwcuc_priv *priv = (struct spwcuc_priv *)spwcuc; - - return priv->regs->etct_next; -} - -/* Return next elapsed fine time (for use when sending SpW time packet) */ -unsigned int spwcuc_get_next_et_fine(void *spwcuc) -{ - struct spwcuc_priv *priv = (struct spwcuc_priv *)spwcuc; - - return (priv->regs->etft_next & 0xffffff) >> 8; -} - -/* Return next elapsed time (for use when sending SpW time packet) */ -unsigned long long spwcuc_get_next_et(void *spwcuc) -{ - return (((unsigned long long)spwcuc_get_next_et_coarse(spwcuc)) << 24) | spwcuc_get_next_et_fine(spwcuc); -} - -/* Force/Set the elapsed time (coarse 32-bit and fine 24-bit) by writing the - * T-Field Time Packet Registers then the FORCE, NEW and INIT bits. - * The latter three are needed for the ET to be set with the new value. - */ -void spwcuc_force_et(void *spwcuc, unsigned long long time) -{ - struct spwcuc_priv *priv = (struct spwcuc_priv *)spwcuc; - struct spwcuc_regs *regs = priv->regs; - - regs->etft_next = (time & 0xffffff) << 8; - regs->etct_next = (time >> 24) & 0xffffffff; - regs->pkt_pf_crc = (1 << 29) | (1 << 30) | (1 << 31); -} - -/* Return received (from time packet) elapsed coarse time */ -unsigned int spwcuc_get_tp_et_coarse(void *spwcuc) -{ - struct spwcuc_priv *priv = (struct spwcuc_priv *)spwcuc; - - return priv->regs->pkt_ct; -} - -/* Return received (from time packet) elapsed fine time */ -unsigned int spwcuc_get_tp_et_fine(void *spwcuc) -{ - struct spwcuc_priv *priv = (struct spwcuc_priv *)spwcuc; - - return (priv->regs->pkt_ft & 0xffffff) >> 8; -} - -/* Return received (from time packet) elapsed time (coarse and fine) */ -unsigned long long spwcuc_get_tp_et(void *spwcuc) -{ - return (((unsigned long long)spwcuc_get_tp_et_coarse(spwcuc)) << 24) | spwcuc_get_tp_et_fine(spwcuc); -} - -/* Clear interrupts */ -void spwcuc_clear_irqs(void *spwcuc, int irqs) -{ - struct spwcuc_priv *priv = (struct spwcuc_priv *)spwcuc; - - priv->regs->picr = irqs; -} - -/* Enable interrupts */ -void spwcuc_enable_irqs(void *spwcuc, int irqs) -{ - struct spwcuc_priv *priv = (struct spwcuc_priv *)spwcuc; - - priv->regs->imr = irqs; -} - -struct spwcuc_regs *spwcuc_get_regs(void *spwcuc) -{ - struct spwcuc_priv *priv = (struct spwcuc_priv *)spwcuc; - - return priv->regs; -} - -void spwcuc_int_register(void *spwcuc, spwcuc_isr_t func, void *data) -{ - struct spwcuc_priv *priv = (struct spwcuc_priv *)spwcuc; - - priv->user_isr = func; - priv->user_isr_arg = data; -} - -void spwcuc_isr(void *data) -{ - struct spwcuc_priv *priv = data; - struct spwcuc_stats *stats = &priv->stats; - unsigned int pimr = priv->regs->pimr; - - stats->nirqs++; - - if (pimr & PKT_INIT_IRQ) - stats->pkt_init++; - if (pimr & PKT_ERR_IRQ) - stats->pkt_err++; - if (pimr & PKT_RX_IRQ) - stats->pkt_rx++; - if (pimr & WRAP_ERR_IRQ) - stats->wraperr++; - if (pimr & WRAP_IRQ) - stats->wrap++; - if (pimr & SYNC_ERR_IRQ) - stats->syncerr++; - if (pimr & SYNC_IRQ) - stats->sync++; - if (pimr & TOL_ERR_IRQ) - stats->tolerr++; - if (pimr & TICK_RX_ERR_IRQ) - stats->tick_rx_error++; - if (pimr & TICK_RX_WRAP_IRQ) - stats->tick_rx_wrap++; - if (pimr & TICK_RX_IRQ) - stats->tick_rx++; - if (pimr & TICK_TX_WRAP_IRQ) - stats->tick_tx_wrap++; - if (pimr & TICK_TX_IRQ) - stats->tick_tx++; - - /* Let user Handle Interrupt */ - if ( priv->user_isr ) - priv->user_isr(pimr, priv->user_isr_arg); -} - -/*** INTERFACE TO DRIVER MANAGER ***/ - -static int spwcuc_init2(struct drvmgr_dev *dev) -{ - struct amba_dev_info *ambadev; - struct ambapp_core *pnpinfo; - struct spwcuc_priv *priv; - struct spwcuc_regs *regs; - - priv = (struct spwcuc_priv *)malloc(sizeof(*priv)); - if ( priv == NULL ) - return -1; - memset(priv, 0, sizeof(*priv)); - priv->dev = dev; - dev->priv = priv; - - /* Get device information from AMBA PnP information */ - ambadev = (struct amba_dev_info *)dev->businfo; - if ( ambadev == NULL ) { - return -1; - } - pnpinfo = &ambadev->info; - regs = (struct spwcuc_regs *)pnpinfo->apb_slv->start; - - priv->regs = regs; - - spwcuc_hw_reset(priv); - - return 0; -} - -struct drvmgr_drv_ops spwcuc_ops = -{ - {NULL, spwcuc_init2, NULL, NULL}, - NULL, - NULL -}; - -struct amba_dev_id spwcuc_ids[] = -{ - {VENDOR_GAISLER, GAISLER_SPWCUC}, - {0, 0} /* Mark end of table */ -}; - -struct amba_drv_info spwcuc_drv_info = -{ - { - DRVMGR_OBJ_DRV, /* Driver */ - NULL, /* Next driver */ - NULL, /* Device list */ - DRIVER_AMBAPP_GAISLER_SPWCUC_ID,/* Driver ID */ - "SPWCUC_DRV", /* Driver Name */ - DRVMGR_BUS_TYPE_AMBAPP, /* Bus Type */ - &spwcuc_ops, - NULL, /* Funcs */ - 0, /* No devices yet */ - 0, - }, - &spwcuc_ids[0] -}; - -/* Register the SPWCUC Driver */ -void spwcuc_register(void) -{ - drvmgr_drv_register(&spwcuc_drv_info.general); -} diff --git a/c/src/lib/libbsp/sparc/shared/tmtc/grtc.c b/c/src/lib/libbsp/sparc/shared/tmtc/grtc.c deleted file mode 100644 index c01d7d8391..0000000000 --- a/c/src/lib/libbsp/sparc/shared/tmtc/grtc.c +++ /dev/null @@ -1,1998 +0,0 @@ -/* GRTC Telecommand decoder driver - * - * COPYRIGHT (c) 2007. - * Cobham Gaisler AB. - * - * 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 -#include -#include -#include - -/* map via rtems_interrupt_lock_* API: */ -#define SPIN_DECLARE(lock) RTEMS_INTERRUPT_LOCK_MEMBER(lock) -#define SPIN_INIT(lock, name) rtems_interrupt_lock_initialize(lock, name) -#define SPIN_LOCK(lock, level) rtems_interrupt_lock_acquire_isr(lock, &level) -#define SPIN_LOCK_IRQ(lock, level) rtems_interrupt_lock_acquire(lock, &level) -#define SPIN_UNLOCK(lock, level) rtems_interrupt_lock_release_isr(lock, &level) -#define SPIN_UNLOCK_IRQ(lock, level) rtems_interrupt_lock_release(lock, &level) -#define SPIN_IRQFLAGS(k) rtems_interrupt_lock_context k -#define SPIN_ISR_IRQFLAGS(k) SPIN_IRQFLAGS(k) - -/* turn on/off local CPU's interrupt to ensure HW timing - not SMP safe. */ -#define IRQ_LOCAL_DECLARE(_level) rtems_interrupt_level _level -#define IRQ_LOCAL_DISABLE(_level) rtems_interrupt_local_disable(_level) -#define IRQ_LOCAL_ENABLE(_level) rtems_interrupt_local_enable(_level) - -/* -#define DEBUG -#define DEBUGFUNCS -*/ - -#include - -#ifdef DEBUG_ERROR -#define DEBUG_ERR_LOG(device,error) grtc_log_error(device,error) -#else -#define DEBUG_ERR_LOG(device,error) -#endif - -/* GRTC register map */ -struct grtc_regs { - volatile unsigned int grst; /* Global Reset Register (GRR 0x00) */ - volatile unsigned int gctrl; /* Global Control Register (GCR 0x04) */ - int unused0; - volatile unsigned int sir; /* Spacecraft Identifier Register (SIR 0x0c) */ - volatile unsigned int far; /* Frame Acceptance Report Register (FAR 0x10) */ - - volatile unsigned int clcw1; /* CLCW Register 1 (CLCWR1 0x14) */ - volatile unsigned int clcw2; /* CLCW Register 2 (CLCWR2 0x18) */ - volatile unsigned int phir; /* Physical Interface Register (PHIR 0x1c) */ - volatile unsigned int cor; /* Control Register (COR 0x20) */ - - volatile unsigned int str; /* Status Register (STR 0x24) */ - volatile unsigned int asr; /* Address Space Register (ASR 0x28) */ - volatile unsigned int rp; /* Receive Read Pointer Register (RRP 0x2c) */ - volatile unsigned int wp; /* Receive Write Pointer Register (RWP 0x30) */ - - int unused1[(0x60-0x34)/4]; - - volatile unsigned int pimsr; /* Pending Interrupt Masked Status Register (PIMSR 0x60) */ - volatile unsigned int pimr; /* Pending Interrupt Masked Register (PIMR 0x64) */ - volatile unsigned int pisr; /* Pending Interrupt Status Register (PISR 0x68) */ - volatile unsigned int pir; /* Pending Interrupt Register (PIR 0x6c) */ - volatile unsigned int imr; /* Interrupt Mask Register (IMR 0x70) */ - volatile unsigned int picr; /* Pending Interrupt Clear Register (PICR 0x74) */ -}; - -/* Security Byte */ -#define GRTC_SEB 0x55000000 - -/* Global Reset Register (GRR 0x00) */ -#define GRTC_GRR_SRST 0x1 -#define GRTC_GRR_SRST_BIT 0 - -/* Global Control Register (GCR 0x04) */ -#define GRTC_GCR_PSR_BIT 10 -#define GRTC_GCR_NRZM_BIT 11 -#define GRTC_GCR_PSS_BIT 12 - -#define GRTC_GCR_PSR (1<minor_drv, dev->parent->dev->name); - priv = dev->priv; - if ( !priv ) - return DRVMGR_NOMEM; - priv->dev = dev; - - /* This core will not find other cores, so we wait for init2() */ - - return DRVMGR_OK; -} - -static int grtc_init3(struct drvmgr_dev *dev) -{ - struct grtc_priv *priv; - char prefix[32]; - rtems_status_code status; - - priv = dev->priv; - - /* Do initialization */ - - if ( grtc_driver_io_registered == 0) { - /* Register the I/O driver only once for all cores */ - if ( grtc_register_io(&grtc_driver_io_major) ) { - /* Failed to register I/O driver */ - dev->priv = NULL; - return DRVMGR_FAIL; - } - - grtc_driver_io_registered = 1; - } - - /* I/O system registered and initialized - * Now we take care of device initialization. - */ - if ( grtc_device_init(priv) ) { - return DRVMGR_FAIL; - } - - /* Get Filesystem name prefix */ - prefix[0] = '\0'; - if ( drvmgr_get_dev_prefix(dev, prefix) ) { - /* Failed to get prefix, make sure of a unique FS name - * by using the driver minor. - */ - sprintf(priv->devName, "/dev/grtc%d", dev->minor_drv); - } else { - /* Got special prefix, this means we have a bus prefix - * And we should use our "bus minor" - */ - sprintf(priv->devName, "/dev/%sgrtc%d", prefix, dev->minor_bus); - } - - SPIN_INIT(&priv->devlock, priv->devName); - - /* Register Device */ - status = rtems_io_register_name(priv->devName, grtc_driver_io_major, dev->minor_drv); - if (status != RTEMS_SUCCESSFUL) { - return DRVMGR_FAIL; - } - - return DRVMGR_OK; -} - -/******************* Driver Implementation ***********************/ - -static int grtc_register_io(rtems_device_major_number *m) -{ - rtems_status_code r; - - if ((r = rtems_io_register_driver(0, &grtc_driver, m)) == RTEMS_SUCCESSFUL) { - DBG("GRTC driver successfully registered, major: %d\n", *m); - } else { - switch(r) { - case RTEMS_TOO_MANY: - printk("GRTC rtems_io_register_driver failed: RTEMS_TOO_MANY\n"); - return -1; - case RTEMS_INVALID_NUMBER: - printk("GRTC rtems_io_register_driver failed: RTEMS_INVALID_NUMBER\n"); - return -1; - case RTEMS_RESOURCE_IN_USE: - printk("GRTC rtems_io_register_driver failed: RTEMS_RESOURCE_IN_USE\n"); - return -1; - default: - printk("GRTC rtems_io_register_driver failed\n"); - return -1; - } - } - return 0; -} - -static int grtc_device_init(struct grtc_priv *pDev) -{ - struct amba_dev_info *ambadev; - struct ambapp_core *pnpinfo; - - /* Get device information from AMBA PnP information */ - ambadev = (struct amba_dev_info *)pDev->dev->businfo; - if ( ambadev == NULL ) { - return -1; - } - pnpinfo = &ambadev->info; - pDev->irq = pnpinfo->irq; - pDev->regs = (struct grtc_regs *)pnpinfo->ahb_slv->start[0]; - pDev->minor = pDev->dev->minor_drv; - pDev->open = 0; - pDev->running = 0; - - /* Create Binary RX Semaphore with count = 0 */ - if ( rtems_semaphore_create(rtems_build_name('G', 'R', 'C', '0' + pDev->minor), - 0, - RTEMS_FIFO|RTEMS_SIMPLE_BINARY_SEMAPHORE|RTEMS_NO_INHERIT_PRIORITY|\ - RTEMS_LOCAL|RTEMS_NO_PRIORITY_CEILING, - 0, - &pDev->sem_rx) != RTEMS_SUCCESSFUL ) { - return -1; - } - - /* Reset Hardware before attaching IRQ handler */ - grtc_hw_reset(pDev); - - return 0; -} - -static void grtc_hw_reset(struct grtc_priv *priv) -{ - /* Reset Core */ - priv->regs->grst = GRTC_SEB | GRTC_GRR_SRST; -} - -static void grtc_hw_get_defaults(struct grtc_priv *pDev, struct grtc_ioc_config *config) -{ - unsigned int gcr = READ_REG(&pDev->regs->gctrl); - - config->psr_enable = (gcr & GRTC_GCR_PSR) ? 1:0; - config->nrzm_enable = (gcr & GRTC_GCR_NRZM) ? 1:0; - config->pss_enable = (gcr & GRTC_GCR_PSS) ? 1:0; - - config->crc_calc = 0; -} - -/* bufsize is given in bytes */ -static int __inline__ grtc_hw_data_avail_upper(unsigned int rrp, unsigned rwp, unsigned int bufsize) -{ - if ( rrp == rwp ) - return 0; - - if ( rwp > rrp ) { - return rwp-rrp; - } - - return (bufsize-rrp); -} - -/* bufsize is given in bytes */ -static int __inline__ grtc_hw_data_avail_lower(unsigned int rrp, unsigned rwp, unsigned int bufsize) -{ - if ( rrp == rwp ) - return 0; - - if ( rwp > rrp ) { - return 0; - } - - return rwp; -} - -/* bufsize is given in bytes */ -static int __inline__ grtc_hw_data_avail(unsigned int rrp, unsigned rwp, unsigned int bufsize) -{ - if ( rrp == rwp ) - return 0; - - if ( rwp > rrp ) { - return rwp-rrp; - } - - return rwp+(bufsize-rrp); -} - -/* Reads as much as possible but not more than 'max' bytes from the TC receive buffer. - * Number of bytes put into 'buf' is returned. - */ -static int grtc_hw_read_try(struct grtc_priv *pDev, char *buf, int max) -{ - struct grtc_regs *regs = pDev->regs; - unsigned int rp, wp, asr, bufmax, rrp, rwp; - unsigned int upper, lower; - unsigned int count, cnt, left; - - FUNCDBG(); - - if ( max < 1 ) - return 0; - - rp = READ_REG(®s->rp); - asr = READ_REG(®s->asr); - bufmax = (asr & GRTC_ASR_RXLEN) >> GRTC_ASR_RXLEN_BIT; - bufmax = (bufmax+1) << 10; /* Convert from 1kbyte blocks into bytes */ - wp = READ_REG(®s->wp); - - /* Relative rp and wp */ - rrp = rp - (asr & GRTC_ASR_BUFST); - rwp = wp - (asr & GRTC_ASR_BUFST); - - lower = grtc_hw_data_avail_lower(rrp,rwp,bufmax); - upper = grtc_hw_data_avail_upper(rrp,rwp,bufmax); - - DBG("grtc_hw_read_try: AVAIL: Lower: %d, Upper: %d\n",lower,upper); - DBG("grtc_hw_read_try: rp: 0x%x, rrp: 0x%x, wp: 0x%x, rwp: 0x%x, bufmax: %d\n, start: 0x%x\n", - rp,rrp,wp,rwp,bufmax,pDev->buffer); - - if ( (upper+lower) == 0 ) - return 0; - - /* Count bytes will be read */ - count = (upper+lower) > max ? max : (upper+lower); - left = count; - - /* Read from upper part of data buffer */ - if ( upper > 0 ){ - if ( left < upper ){ - cnt = left; - }else{ - cnt = upper; /* Read all upper data available */ - } - DBG("grtc_hw_read_try: COPYING %d from upper\n",cnt); - /* Convert from Remote address (RP) into CPU Local address */ - memcpy(buf, (void *)((rp - (unsigned int)pDev->buf_remote) + (unsigned int)pDev->buf), cnt); - buf += cnt; - left -= cnt; - } - - /* Read from lower part of data buffer */ - if ( left > 0 ){ - if ( left < lower ){ - cnt = left; - }else{ - cnt = lower; /* Read all lower data available */ - } - DBG("grtc_hw_read_try: COPYING %d from lower\n",cnt); - memcpy(buf, (void *)pDev->buf, cnt); - buf += cnt; - left -= cnt; - } - - /* Update hardware RP pointer to tell hardware about new space available */ - if ( (rp+count) >= ((asr&GRTC_ASR_BUFST)+bufmax) ){ - regs->rp = (rp+count-bufmax); - } else { - regs->rp = rp+count; - } - - return count; -} - -/* Reads as much as possible but not more than 'max' bytes from the TC receive buffer. - * Number of bytes put into 'buf' is returned. - */ -static int grtc_data_avail(struct grtc_priv *pDev) -{ - unsigned int rp, wp, asr, bufmax, rrp, rwp; - struct grtc_regs *regs = pDev->regs; - - FUNCDBG(); - - rp = READ_REG(®s->rp); - asr = READ_REG(®s->asr); - bufmax = (asr & GRTC_ASR_RXLEN) >> GRTC_ASR_RXLEN_BIT; - bufmax = (bufmax+1) << 10; /* Convert from 1kbyte blocks into bytes */ - wp = READ_REG(®s->wp); - - /* Relative rp and wp */ - rrp = rp - (asr & GRTC_ASR_BUFST); - rwp = wp - (asr & GRTC_ASR_BUFST); - - return grtc_hw_data_avail(rrp,rwp,bufmax); -} - -static void *grtc_memalign(unsigned int boundary, unsigned int length, void *realbuf) -{ - *(int *)realbuf = (int)malloc(length+(~GRTC_ASR_BUFST)+1); - DBG("GRTC: Alloced %d (0x%x) bytes, requested: %d\n",length+(~GRTC_ASR_BUFST)+1,length+(~GRTC_ASR_BUFST)+1,length); - return (void *)(((*(unsigned int *)realbuf)+(~GRTC_ASR_BUFST)+1) & ~(boundary-1)); -} - -static int grtc_start(struct grtc_priv *pDev) -{ - struct grtc_regs *regs = pDev->regs; - unsigned int tmp; - - if ( !pDev->buf || (((unsigned int)pDev->buf & ~GRTC_ASR_BUFST) != 0) || - (pDev->len>(1024*0x100)) || (pDev->len<1024) || ((pDev->len & (1024-1)) != 0) - ) { - DBG("GRTC: start: buffer not properly allocated(0x%x,0x%x,0x%x,0x%x)\n",pDev->buf,pDev->len,((unsigned int)pDev->buf & ~GRTC_ASR_BUFST),(pDev->len & ~(1024-1))); - return RTEMS_NO_MEMORY; - } - - memset(pDev->buf,0,pDev->len); - - /* Software init */ - pDev->overrun_condition = 0; -#ifdef DEBUG_ERROR - pDev->last_error_cnt = 0; - memset(&pDev->last_error[0],0,128*sizeof(int)); -#endif - memset(&pDev->stats,0,sizeof(struct grtc_ioc_stats)); - - /* Reset the receiver */ - regs->cor = GRTC_SEB | GRTC_COR_CRST; - if ( READ_REG(®s->cor) & GRTC_COR_CRST ){ - /* Reset Failed */ - DBG("GRTC: start: Reseting receiver failed\n"); - return RTEMS_IO_ERROR; - } - - /* make sure the RX semaphore is in the correct state when starting. - * In case of a previous overrun condition it could be in incorrect - * state (where rtems_semaphore_flush was used). - */ - rtems_semaphore_obtain(pDev->sem_rx, RTEMS_NO_WAIT, 0); - - /* Set operating modes */ - tmp = 0; - if ( pDev->config.psr_enable ) - tmp |= GRTC_GCR_PSR; - if ( pDev->config.nrzm_enable ) - tmp |= GRTC_GCR_NRZM; - if ( pDev->config.pss_enable ) - tmp |= GRTC_GCR_PSS; - regs->gctrl = GRTC_SEB | tmp; - - /* Clear any pending interrupt */ - tmp = READ_REG(®s->pir); - regs->picr = GRTC_INT_ALL; - - /* Unmask only the Overrun interrupt */ - regs->imr = GRTC_INT_OV; - - /* Set up DMA registers - * 1. Let hardware know about our DMA area (size and location) - * 2. Set DMA read/write posistions to zero. - */ - regs->asr = (unsigned int)pDev->buf_remote | ((pDev->len>>10)-1); - regs->rp = (unsigned int)pDev->buf_remote; - - /* Mark running before enabling the receiver, we could receive - * an interrupt directly after enabling the receiver and it would - * then interpret the interrupt as spurious (see interrupt handler) - */ - pDev->running = 1; - - /* Enable receiver */ - regs->cor = GRTC_SEB | GRTC_COR_RE; - - DBG("GRTC: STARTED\n"); - - return 0; -} - -static void grtc_stop(struct grtc_priv *pDev, int overrun) -{ - struct grtc_regs *regs = pDev->regs; - SPIN_IRQFLAGS(irqflags); - - SPIN_LOCK_IRQ(&pDev->devlock, irqflags); - - /* Disable the receiver */ - regs->cor = GRTC_SEB; - - /* disable all interrupts and clear them */ - regs->imr = 0; - READ_REG(®s->pir); - regs->picr = GRTC_INT_ALL; - - DBG("GRTC: STOPPED\n"); - - if (overrun) { - pDev->overrun_condition = 1; - } else { - pDev->running = 0; - } - - SPIN_UNLOCK_IRQ(&pDev->devlock, irqflags); - - /* Flush semaphores in case a thread is stuck waiting for CLTUs (RX data) */ - rtems_semaphore_flush(pDev->sem_rx); -} - -/* Wait until 'count' bytes are available in receive buffer, or until - * the timeout expires. - */ -static int grtc_wait_data(struct grtc_priv *pDev, int count, rtems_interval timeout) -{ - int avail; - int ret; - SPIN_IRQFLAGS(irqflags); - - FUNCDBG(); - - if ( count < 1 ) - return 0; - - SPIN_LOCK_IRQ(&pDev->devlock, irqflags); - - /* Enable interrupts when receiving CLTUs, Also clear old pending CLTUs store - * interrupts. - */ - pDev->regs->picr = GRTC_INT_CS; - pDev->regs->imr = READ_REG(&pDev->regs->imr) | GRTC_INT_CS; - - avail = grtc_data_avail(pDev); - if ( avail < count ) { - /* Wait for interrupt. */ - - SPIN_UNLOCK_IRQ(&pDev->devlock, irqflags); - - if ( timeout == 0 ){ - timeout = RTEMS_NO_TIMEOUT; - } - ret = rtems_semaphore_obtain(pDev->sem_rx,RTEMS_WAIT,timeout); - /* RTEMS_SUCCESSFUL = interrupt signaled data is available - * RTEMS_TIMEOUT = timeout expired, probably not enough data available - * RTEMS_UNSATISFIED = driver has been closed or an error (overrun) occured - * which should cancel this operation. - * RTEMS_OBJECT_WAS_DELETED, RTEMS_INVALID_ID = driver error. - */ - SPIN_LOCK_IRQ(&pDev->devlock, irqflags); - }else{ - ret = RTEMS_SUCCESSFUL; - } - - /* Disable interrupts when receiving CLTUs */ - pDev->regs->imr = READ_REG(&pDev->regs->imr) & ~GRTC_INT_CS; - - SPIN_UNLOCK_IRQ(&pDev->devlock, irqflags); - - return ret; -} - -static rtems_device_driver grtc_open( - rtems_device_major_number major, - rtems_device_minor_number minor, - void *arg) -{ - struct grtc_priv *pDev; - struct drvmgr_dev *dev; - - FUNCDBG(); - - if ( drvmgr_get_dev(&grtc_drv_info.general, minor, &dev) ) { - DBG("Wrong minor %d\n", minor); - return RTEMS_INVALID_NUMBER; - } - pDev = (struct grtc_priv *)dev->priv; - - /* Wait until we get semaphore */ - if ( rtems_semaphore_obtain(grtc_dev_sem, RTEMS_WAIT, RTEMS_NO_TIMEOUT) != RTEMS_SUCCESSFUL ){ - return RTEMS_INTERNAL_ERROR; - } - - /* Is device in use? */ - if ( pDev->open ){ - rtems_semaphore_release(grtc_dev_sem); - return RTEMS_RESOURCE_IN_USE; - } - - /* Mark device taken */ - pDev->open = 1; - - rtems_semaphore_release(grtc_dev_sem); - - DBG("grtc_open: OPENED minor %d (pDev: 0x%x)\n",pDev->minor,(unsigned int)pDev); - - /* Set defaults */ - pDev->buf = NULL; - pDev->_buf = NULL; - pDev->buf_custom = 0; - pDev->buf_remote = 0; - pDev->len = 0; - pDev->timeout = 0; /* no timeout */ - pDev->blocking = 0; /* polling mode */ - pDev->mode = GRTC_MODE_RAW; /* Always default to Raw mode */ - pDev->ready.head = NULL; - pDev->ready.tail = NULL; - pDev->ready.cnt = 0; - - pDev->running = 0; - pDev->overrun_condition = 0; - - memset(&pDev->config,0,sizeof(pDev->config)); - - /* The core has been reset when we execute here, so it is possible - * to read out defualts from core. - */ - grtc_hw_get_defaults(pDev,&pDev->config); - - return RTEMS_SUCCESSFUL; -} - -static rtems_device_driver grtc_close(rtems_device_major_number major, rtems_device_minor_number minor, void *arg) -{ - struct grtc_priv *pDev; - struct drvmgr_dev *dev; - - FUNCDBG(); - - if ( drvmgr_get_dev(&grtc_drv_info.general, minor, &dev) ) { - return RTEMS_INVALID_NUMBER; - } - pDev = (struct grtc_priv *)dev->priv; - - if ( pDev->running ){ - grtc_stop(pDev, 0); - } - - /* Reset core */ - grtc_hw_reset(pDev); - - /* Mark not open */ - pDev->open = 0; - - return RTEMS_SUCCESSFUL; -} - -static rtems_device_driver grtc_read(rtems_device_major_number major, rtems_device_minor_number minor, void *arg) -{ - struct grtc_priv *pDev; - struct drvmgr_dev *dev; - int count; - int left; - int timedout; - int err; - rtems_interval timeout; - rtems_libio_rw_args_t *rw_args; - - FUNCDBG(); - - if ( drvmgr_get_dev(&grtc_drv_info.general, minor, &dev) ) { - return RTEMS_INVALID_NUMBER; - } - pDev = (struct grtc_priv *)dev->priv; - - if ( !pDev->running && !pDev->overrun_condition ) { - return RTEMS_RESOURCE_IN_USE; - } - - if ( pDev->mode != GRTC_MODE_RAW ) { - return RTEMS_NOT_DEFINED; - } - - rw_args = (rtems_libio_rw_args_t *) arg; - left = rw_args->count; - timedout = 0; - timeout = pDev->timeout; - -read_from_buffer: - /* Read maximally rw_args->count bytes from receive buffer */ - count = grtc_hw_read_try(pDev,rw_args->buffer,left); - - left -= count; - - DBG("READ %d bytes from DMA, left: %d\n",count,left); - - if ( !timedout && !pDev->overrun_condition && ((count < 1) || ((count < rw_args->count) && (pDev->blocking == GRTC_BLKMODE_COMPLETE))) ){ - /* didn't read anything (no data available) or we want to wait for all bytes requested. - * - * Wait for data to arrive only in blocking mode - */ - if ( pDev->blocking ) { - if ( (err=grtc_wait_data(pDev,left,timeout)) != RTEMS_SUCCESSFUL ){ - /* Some kind of error, closed, overrun etc. */ - if ( err == RTEMS_TIMEOUT ){ - /* Got a timeout, we try to read as much as possible */ - timedout = 1; - goto read_from_buffer; - } - return err; - } - goto read_from_buffer; - } - /* Non-blocking mode and no data read. */ - return RTEMS_TIMEOUT; - } - - /* Tell caller how much was read. */ - - DBG("READ returning %d bytes, left: %d\n",rw_args->count-left,left); - - rw_args->bytes_moved = rw_args->count - left; - if ( rw_args->bytes_moved == 0 ) { - if ( pDev->overrun_condition ) { - /* signal to the user that overrun has happend when - * no more data can be read out. - */ - return RTEMS_IO_ERROR; - } - return RTEMS_TIMEOUT; - } - - return RTEMS_SUCCESSFUL; -} - -static rtems_device_driver grtc_write(rtems_device_major_number major, rtems_device_minor_number minor, void *arg) -{ - FUNCDBG(); - return RTEMS_NOT_IMPLEMENTED; -} - -static int grtc_pool_add_frms(struct grtc_frame *frms) -{ - struct grtc_frame *frm, *next; - - /* Add frames to pools */ - frm = frms; - while(frm){ - - if ( !frm->pool ) { - /* */ - DBG("GRTC: Frame not assigned to a pool\n"); - return -1; - } - next = frm->next; /* Remember next frame to process */ - - DBG("GRTC: adding frame 0x%x to pool %d (%d)\n",frm,frm->pool->frame_len,frm->pool->frame_cnt); - - /* Insert Frame into pool */ - frm->next = frm->pool->frms; - frm->pool->frms = frm; - frm->pool->frame_cnt++; - - frm = next; - } - - return 0; -} - -static struct grtc_frame *grtc_pool_get_frm(struct grtc_priv *pDev, int frame_len, int *error) -{ - struct grtc_frame *frm; - struct grtc_frame_pool *pool; - int i; - - /* Loop through all pools until a pool is found - * with a matching (or larger) frame length - */ - pool = pDev->pools; - for (i=0; ipool_cnt; i++,pool++) { - if ( pool->frame_len >= frame_len ) { - /* Found a good pool ==> get frame */ - frm = pool->frms; - if ( !frm ) { - /* not enough frames available for this - * frame length, we try next - * - * If this is a severe error add your handling - * code here. - */ -#if 0 - if ( error ) - *error = 0; - return 0; -#endif - continue; - } - - /* Got a frame, the frame is taken out of the - * pool for usage. - */ - pool->frms = frm->next; - pool->frame_cnt--; - return frm; - } - } - - if ( error ) - *error = 1; - - /* Didn't find any frames */ - return NULL; -} - -/* Return number of bytes processed, Stops at the first occurance - * of the pattern given in 'pattern' - */ -static int grtc_scan(unsigned short *src, int max, unsigned char pattern, int *found) -{ - unsigned short tmp = 0; - unsigned int left = max; - - while ( (left>1) && (((tmp=*src) & 0x00ff) != pattern) ) { - src++; - left-=2; - } - if ( (tmp & 0xff) == pattern ) { - *found = 1; - } else { - *found = 0; - } - return max-left; -} - -static int grtc_copy(unsigned short *src, unsigned char *buf, int cnt) -{ - unsigned short tmp; - int left = cnt; - - while ( (left>0) && ((((tmp=*src) & 0x00ff) == 0x00) || ((tmp & 0x00ff) == 0x01)) ) { - *buf++ = tmp>>8; - src++; - left--; - } - - return cnt-left; -} - - -static int grtc_hw_find_frm(struct grtc_priv *pDev) -{ - struct grtc_regs *regs = pDev->regs; - unsigned int rp, wp, asr, bufmax, rrp, rwp; - unsigned int upper, lower; - unsigned int count, cnt; - int found; - - FUNCDBG(); - - rp = READ_REG(®s->rp); - asr = READ_REG(®s->asr); - wp = READ_REG(®s->wp); - - /* Quick Check for most common case where Start of frame is at next - * data byte. - */ - if ( rp != wp ) { - /* At least 1 byte in buffer */ - if ( ((*(unsigned short *)((rp - (unsigned int)pDev->buf_remote) + (unsigned int)pDev->buf)) & 0x00ff) == 0x01 ) { - return 0; - } - } - - bufmax = (asr & GRTC_ASR_RXLEN) >> GRTC_ASR_RXLEN_BIT; - bufmax = (bufmax+1) << 10; /* Convert from 1kbyte blocks into bytes */ - - /* Relative rp and wp */ - rrp = rp - (asr & GRTC_ASR_BUFST); - rwp = wp - (asr & GRTC_ASR_BUFST); - - lower = grtc_hw_data_avail_lower(rrp,rwp,bufmax); - upper = grtc_hw_data_avail_upper(rrp,rwp,bufmax); - - DBG("grtc_hw_find_frm: AVAIL: Lower: %d, Upper: %d\n",lower,upper); - DBG("grtc_hw_find_frm: rp: 0x%x, rrp: 0x%x, wp: 0x%x, rwp: 0x%x, bufmax: %d\n, start: 0x%x\n", - rp,rrp,wp,rwp,bufmax,pDev->buf_remote); - - if ( (upper+lower) == 0 ) - return 1; - - /* Count bytes will be read */ - count = 0; - found = 0; - - /* Read from upper part of data buffer */ - if ( upper > 0 ){ - cnt = grtc_scan((unsigned short *)((rp - (unsigned int)pDev->buf_remote) + (unsigned int)pDev->buf), upper, 0x01, &found); - count = cnt; - if ( found ) { - DBG("grtc_hw_find_frm: SCANNED upper %d bytes until found\n",cnt); - goto out; - } - - DBG("grtc_hw_find_frm: SCANNED all upper %d bytes, not found\n",cnt); - } - - /* Read from lower part of data buffer */ - if ( lower > 0 ){ - cnt = grtc_scan((unsigned short *)pDev->buf, lower, 0x01, &found); - count += cnt; - - if ( found ) { - DBG("grtc_hw_find_frm: SCANNED lower %d bytes until found\n",cnt); - goto out; - } - - DBG("grtc_hw_find_frm: SCANNED all lower %d bytes, not found\n",cnt); - } - -out: - /* Update hardware RP pointer to tell hardware about new space available */ - if ( count > 0 ) { - if ( (rp+count) >= ((asr&GRTC_ASR_BUFST)+bufmax) ){ - regs->rp = (rp+count-bufmax); - } else { - regs->rp = rp+count; - } - } - if ( found ) - return 0; - return 1; - -} - -static int grtc_check_ending(unsigned short *src, int max, int end) -{ - while ( max > 0 ) { - /* Check Filler */ - if ( *src != 0x5500 ) { - /* Filler is wrong */ - return -1; - } - src++; - max-=2; - } - - /* Check ending (at least */ - if ( end ) { - if ( (*src & 0x00ff) != 0x02 ) { - return -1; - } - } - - return 0; -} - -static int grtc_hw_check_ending(struct grtc_priv *pDev, int max) -{ - struct grtc_regs *regs = pDev->regs; - unsigned int rp, wp, asr, bufmax, rrp, rwp; - unsigned int upper, lower; - unsigned int count, cnt, left; - - FUNCDBG(); - - if ( max < 1 ) - return 0; - max = max*2; - max += 2; /* Check ending also (2 byte extra) */ - - rp = READ_REG(®s->rp); - asr = READ_REG(®s->asr); - bufmax = (asr & GRTC_ASR_RXLEN) >> GRTC_ASR_RXLEN_BIT; - bufmax = (bufmax+1) << 10; /* Convert from 1kbyte blocks into bytes */ - wp = READ_REG(®s->wp); - - /* Relative rp and wp */ - rrp = rp - (asr & GRTC_ASR_BUFST); - rwp = wp - (asr & GRTC_ASR_BUFST); - - lower = grtc_hw_data_avail_lower(rrp,rwp,bufmax); - upper = grtc_hw_data_avail_upper(rrp,rwp,bufmax); - - DBG("grtc_hw_check_ending: AVAIL: Lower: %d, Upper: %d\n",lower,upper); - DBG("grtc_hw_check_ending: rp: 0x%x, rrp: 0x%x, wp: 0x%x, rwp: 0x%x, bufmax: %d\n, start: 0x%x\n", - rp,rrp,wp,rwp,bufmax,pDev->buf_remote); - - if ( (upper+lower) < max ) - return 0; - - /* Count bytes will be read */ - count = max; - left = count; - - /* Read from upper part of data buffer */ - if ( upper > 0 ){ - if ( left <= upper ){ - cnt = left; - if ( grtc_check_ending((unsigned short *)((rp-(unsigned int)pDev->buf_remote)+(unsigned int)pDev->buf), cnt-2, 1) ) { - return -1; - } - }else{ - cnt = upper; /* Read all upper data available */ - if ( grtc_check_ending((unsigned short *)((rp-(unsigned int)pDev->buf_remote)+(unsigned int)pDev->buf), cnt, 0) ) { - return -1; - } - } - left -= cnt; - } - - /* Read from lower part of data buffer */ - if ( left > 0 ){ - cnt = left; - if ( grtc_check_ending((unsigned short *)pDev->buf, cnt-2, 1) ) { - return -1; - } - left -= cnt; - } - - /* Update hardware RP pointer to tell hardware about new space available */ - if ( (rp+count) >= ((asr&GRTC_ASR_BUFST)+bufmax) ){ - regs->rp = (rp+count-bufmax); - } else { - regs->rp = rp+count; - } - - return 0; -} - -/* Copies Data from DMA area to buf, the control bytes are stripped. For - * every data byte, in the DMA area, one control byte is stripped. - */ -static int grtc_hw_copy(struct grtc_priv *pDev, unsigned char *buf, int max, int partial) -{ - struct grtc_regs *regs = pDev->regs; - unsigned int rp, wp, asr, bufmax, rrp, rwp; - unsigned int upper, lower; - unsigned int count, cnt, left; - int ret, tot, tmp; - - FUNCDBG(); - - if ( max < 1 ) - return 0; - - rp = READ_REG(®s->rp); - asr = READ_REG(®s->asr); - bufmax = (asr & GRTC_ASR_RXLEN) >> GRTC_ASR_RXLEN_BIT; - bufmax = (bufmax+1) << 10; /* Convert from 1kbyte blocks into bytes */ - wp = READ_REG(®s->wp); - - /* Relative rp and wp */ - rrp = rp - (asr & GRTC_ASR_BUFST); - rwp = wp - (asr & GRTC_ASR_BUFST); - - lower = grtc_hw_data_avail_lower(rrp,rwp,bufmax) >> 1; - upper = grtc_hw_data_avail_upper(rrp,rwp,bufmax) >> 1; - - DBG("grtc_hw_copy: AVAIL: Lower: %d, Upper: %d\n",lower,upper); - DBG("grtc_hw_copy: rp: 0x%x, rrp: 0x%x, wp: 0x%x, rwp: 0x%x, bufmax: %d\n, start: 0x%x\n", - rp,rrp,wp,rwp,bufmax,pDev->buf_remote); - - if ( (upper+lower) == 0 || (!partial && ((upper+lower) max ? max : (upper+lower); - left = count; - tot = 0; - - /* Read from upper part of data buffer */ - if ( upper > 0 ){ - if ( left < upper ){ - cnt = left; - }else{ - cnt = upper; /* Read all upper data available */ - } - DBG("grtc_hw_copy: COPYING %d from upper\n",cnt); - if ( (tot=grtc_copy((unsigned short *)((rp-(unsigned int)pDev->buf_remote)+(unsigned int)pDev->buf), buf, cnt)) != cnt ) { - /* Failed to copy due to an receive error */ - DBG("grtc_hw_copy(upper): not all in DMA buffer (%d)\n",tot); - count = tot; - ret = -1; - goto out; - } - buf += cnt; - left -= cnt; - } - - /* Read from lower part of data buffer */ - if ( left > 0 ){ - if ( left < lower ){ - cnt = left; - }else{ - cnt = lower; /* Read all lower data available */ - } - DBG("grtc_hw_copy: COPYING %d from lower\n",cnt); - if ( (tmp=grtc_copy((unsigned short *)pDev->buf, buf, cnt)) != cnt ) { - /* Failed to copy due to an receive error */ - DBG("grtc_hw_copy(lower): not all in DMA buffer (%d)\n",tot); - count = tot+tmp; - ret = -1; - goto out; - } - buf += cnt; - left -= cnt; - } - ret = count; - -out: - count = count*2; - /* Update hardware RP pointer to tell hardware about new space available */ - if ( (rp+count) >= ((asr&GRTC_ASR_BUFST)+bufmax) ){ - regs->rp = (rp+count-bufmax); - } else { - regs->rp = rp+count; - } - - return ret; -} - -#ifdef DEBUG_ERROR -void grtc_log_error(struct grtc_priv *pDev, int err) -{ - /* Stop Receiver */ - *(volatile unsigned int *)&pDev->regs->cor = 0x55000000; - *(volatile unsigned int *)&pDev->regs->cor = 0x55000000; - pDev->last_error[pDev->last_error_cnt] = err; - if ( ++pDev->last_error_cnt > 128 ) - pDev->last_error_cnt = 0; -} -#endif - -/* Read one frame from DMA buffer - * - * Return Values - * Zero - nothing more to process - * 1 - more to process, no free frames - * 2 - more to process, frame received - * negative - more to process, frame dropped - */ -static int process_dma(struct grtc_priv *pDev) -{ - int ret, err; - int left, total_len; - unsigned char *dst; - struct grtc_frame *frm; - - switch( pDev->frame_state ) { - case FRM_STATE_NONE: - DBG2("FRAME_STATE_NONE\n"); - - /* Find Start of next frame by searching for 0x01 */ - ret = grtc_hw_find_frm(pDev); - if ( ret != 0 ) { - /* Frame start not found */ - return 0; - } - - /* Start of frame found, Try to copy header */ - pDev->frm = NULL; - pDev->frame_state = FRM_STATE_HDR; - - case FRM_STATE_HDR: - DBG2("FRAME_STATE_HDR\n"); - - /* Wait for all of header to be in place by setting partial to 0 */ - ret = grtc_hw_copy(pDev, (unsigned char *)pDev->hdr, 5, 0); - if ( ret < 0 ) { - /* Error copying header, restart scanning for new frame */ - DEBUG_ERR_LOG(pDev,1); - pDev->stats.err++; - pDev->stats.err_hdr++; - DBG("FRAME_STATE_HDR: copying failed %d\n",ret); - pDev->frame_state = FRM_STATE_NONE; - return -1; - } else if ( ret != 5 ) { - DBG("FRAME_STATE_HDR: no header (%d)\n",ret); - /* Not all bytes available, come back later */ - return 0; - } - - /* The complete header has been copied, parse it */ - pDev->frmlen = (((unsigned short *)pDev->hdr)[1] & 0x3ff)+1; - if ( pDev->frmlen < 5 ) { - /* Error: frame length is not correct */ - pDev->stats.err++; - pDev->stats.err_hdr++; - DBG("FRAME_STATE_HDR: frame length error: %d\n", pDev->frmlen); - pDev->frame_state = FRM_STATE_NONE; - return -1; - } - pDev->frame_state = FRM_STATE_ALLOC; - - case FRM_STATE_ALLOC: - DBG2("FRAME_STATE_ALLOC\n"); - /* Header has been read, allocate a frame to put payload and header into */ - - /* Allocate Frame matching Frame length */ - err = 0; - frm = grtc_pool_get_frm(pDev,pDev->frmlen,&err); - if ( !frm ) { - /* Couldn't find frame */ - DEBUG_ERR_LOG(pDev,2); - pDev->stats.dropped++; - DBG2("No free frames\n"); - if ( err == 0 ){ - /* Frame length exist in pool configuration, but no - * frames are available for that frame length. - */ - DEBUG_ERR_LOG(pDev,3); - pDev->stats.dropped_no_buf++; - return 1; - } else { - /* Frame length of incoming frame is larger than the - * frame length in any of the configured frame pools. - * - * This may be because of an corrupt header. We simply - * scan for the end of frame marker in the DMA buffer - * so we can drop the frame. - */ - DEBUG_ERR_LOG(pDev,4); - pDev->stats.dropped_too_long++; - pDev->frame_state = FRM_STATE_NONE; - return -2; - } - } - frm->len = 5; /* Only header currenlty in frame */ - - /* Copy Frame Header into frame structure */ - ((unsigned char*)&frm->hdr)[0] = ((unsigned char*)pDev->hdr)[0]; - ((unsigned char*)&frm->hdr)[1] = ((unsigned char*)pDev->hdr)[1]; - ((unsigned char*)&frm->hdr)[2] = ((unsigned char*)pDev->hdr)[2]; - ((unsigned char*)&frm->hdr)[3] = ((unsigned char*)pDev->hdr)[3]; - ((unsigned char*)&frm->hdr)[4] = ((unsigned char*)pDev->hdr)[4]; - - /* Calc Total and Filler byte count in frame */ - total_len = pDev->frmlen / 7; - total_len = total_len * 7; - if ( pDev->frmlen != total_len ) - total_len += 7; - - pDev->filler = total_len - pDev->frmlen; - - pDev->frame_state = FRM_STATE_PAYLOAD; - pDev->frm = frm; - - case FRM_STATE_PAYLOAD: - DBG2("FRAME_STATE_PAYLOAD\n"); - /* Parts of payload and the complete header has been read */ - frm = pDev->frm; - - dst = (unsigned char *)&frm->data[frm->len-5]; - left = pDev->frmlen-frm->len; - - ret = grtc_hw_copy(pDev,dst,left,1); - if ( ret < 0 ) { - DEBUG_ERR_LOG(pDev,5); - /* Error copying header, restart scanning for new frame */ - pDev->frame_state = FRM_STATE_NONE; - frm->next = NULL; - grtc_pool_add_frms(frm); - pDev->frm = NULL; - pDev->stats.err++; - pDev->stats.err_payload++; - return -1; - } else if ( ret != left ) { - /* Not all bytes available, come back later */ - frm->len += ret; - return 0; - } - frm->len += ret; - pDev->frame_state = FRM_STATE_FILLER; - - case FRM_STATE_FILLER: - DBG2("FRAME_STATE_FILLER\n"); - /* check filler data */ - frm = pDev->frm; - - ret = grtc_hw_check_ending(pDev,pDev->filler); - if ( ret != 0 ) { - /* Error in frame, drop frame */ - DEBUG_ERR_LOG(pDev,6); - pDev->frame_state = FRM_STATE_NONE; - frm->next = NULL; - grtc_pool_add_frms(frm); - pDev->frm = NULL; - pDev->stats.err++; - pDev->stats.err_ending++; - return -1; - } - - /* A complete frame received, put it into received frame queue */ - if ( pDev->ready.head ) { - /* Queue not empty */ - pDev->ready.tail->next = frm; - } else { - /* Queue empty */ - pDev->ready.head = frm; - } - pDev->ready.tail = frm; - frm->next = NULL; - pDev->ready.cnt++; - pDev->stats.frames_recv++; - - pDev->frame_state = FRM_STATE_NONE; - frm->next = NULL; - return 2; - -#if 0 - case FRM_STATE_DROP: - DBG2("FRAME_STATE_DROP\n"); - break; -#endif - - default: - printk("GRTC: internal error\n"); - pDev->frame_state = FRM_STATE_NONE; - break; - } - - return 0; -} - -static rtems_device_driver grtc_ioctl(rtems_device_major_number major, rtems_device_minor_number minor, void *arg) -{ - struct grtc_priv *pDev; - struct drvmgr_dev *dev; - rtems_libio_ioctl_args_t *ioarg = (rtems_libio_ioctl_args_t *)arg; - unsigned int *data = ioarg->buffer; - int status,frm_len,i,ret; - struct grtc_ioc_buf_params *buf_arg; - struct grtc_ioc_config *cfg; - struct grtc_ioc_hw_status *hwregs; - struct grtc_ioc_pools_setup *pocfg; - struct grtc_ioc_assign_frm_pool *poassign; - struct grtc_frame *frm, *frms; - struct grtc_frame_pool *pool; - struct grtc_list *frmlist; - struct grtc_ioc_stats *stats; - unsigned int mem; - IRQ_LOCAL_DECLARE(oldLevel); - - FUNCDBG(); - - if ( drvmgr_get_dev(&grtc_drv_info.general, minor, &dev) ) { - return RTEMS_INVALID_NUMBER; - } - pDev = (struct grtc_priv *)dev->priv; - - if (!ioarg) - return RTEMS_INVALID_NAME; - - ioarg->ioctl_return = 0; - switch(ioarg->command) { - case GRTC_IOC_START: - if ( pDev->running ) { - return RTEMS_RESOURCE_IN_USE; /* EBUSY */ - } - if ( (status=grtc_start(pDev)) != RTEMS_SUCCESSFUL ){ - return status; - } - /* Register ISR and Unmask interrupt */ - drvmgr_interrupt_register(pDev->dev, 0, "grtc", grtc_interrupt, pDev); - - /* Read and write are now open... */ - break; - - case GRTC_IOC_STOP: - if ( !pDev->running ) { - return RTEMS_RESOURCE_IN_USE; - } - drvmgr_interrupt_unregister(pDev->dev, 0, grtc_interrupt, pDev); - grtc_stop(pDev, 0); - break; - - case GRTC_IOC_ISSTARTED: - if ( !pDev->running ) { - return RTEMS_RESOURCE_IN_USE; - } else if ( pDev->overrun_condition ) { - return RTEMS_IO_ERROR; - } - break; - - case GRTC_IOC_SET_BLOCKING_MODE: - if ( (unsigned int)data > GRTC_BLKMODE_COMPLETE ) { - return RTEMS_INVALID_NAME; - } - DBG("GRTC: Set blocking mode: %d\n",(unsigned int)data); - pDev->blocking = (unsigned int)data; - break; - - case GRTC_IOC_SET_TIMEOUT: - DBG("GRTC: Timeout: %d\n",(unsigned int)data); - pDev->timeout = (rtems_interval)data; - break; - - case GRTC_IOC_SET_BUF_PARAM: - if ( pDev->running ) { - return RTEMS_RESOURCE_IN_USE; /* EBUSY */ - } - - buf_arg = (struct grtc_ioc_buf_params *)data; - if ( !buf_arg ) { - return RTEMS_INVALID_NAME; - } - - DBG("GRTC: IOC_SET_BUF_PARAM: Len: 0x%x, Custom Buffer: 0x%x\n",buf_arg->length,buf_arg->custom_buffer); - - /* Check alignment need, skip bit 0 since that bit only indicates remote address or not */ - if ( (unsigned int)buf_arg->custom_buffer & (~GRTC_BUF_MASK) & (~0x1) ) { - return RTEMS_INVALID_NAME; - } - - if ( buf_arg->length > 0x100 ){ - DBG("GRTC: Too big buffer requested\n"); - return RTEMS_INVALID_NAME; - } - - /* If current buffer allocated by driver we must free it */ - if ( !pDev->buf_custom && pDev->buf ){ - free(pDev->_buf); - pDev->_buf = NULL; - } - pDev->buf = NULL; - pDev->len = buf_arg->length*1024; - - if (pDev->len <= 0) - break; - mem = (unsigned int)buf_arg->custom_buffer; - pDev->buf_custom = mem; - - if (mem & 1) { - /* Remote address given, the address is as the GRTC - * core looks at it. Translate the base address into - * an address that the CPU can understand. - */ - pDev->buf_remote = (void *)(mem & ~0x1); - drvmgr_translate_check(pDev->dev, DMAMEM_TO_CPU, - (void *)pDev->buf_remote, - (void **)&pDev->buf, - pDev->len); - } else { - if (mem == 0) { - pDev->buf = grtc_memalign((~GRTC_ASR_BUFST)+1,pDev->len,&pDev->_buf); - DBG("grtc_ioctl: SETBUF: new buf: 0x%x(0x%x), Len: %d\n",pDev->buf,pDev->_buf,pDev->len); - if (!pDev->buf){ - pDev->len = 0; - pDev->buf_custom = 0; - pDev->_buf = NULL; - pDev->buf_remote = 0; - DBG("GRTC: Failed to allocate memory\n"); - return RTEMS_NO_MEMORY; - } - } else{ - pDev->buf = buf_arg->custom_buffer; - } - - /* Translate into a remote address so that GRTC core - * on a remote AMBA bus (for example over the PCI bus) - * gets a valid address - */ - drvmgr_translate_check(pDev->dev, CPUMEM_TO_DMA, - (void *)pDev->buf, - (void **)&pDev->buf_remote, - pDev->len); - } - break; - - case GRTC_IOC_GET_BUF_PARAM: - if ( pDev->running ) { - return RTEMS_RESOURCE_IN_USE; /* EBUSY */ - } - - buf_arg = (struct grtc_ioc_buf_params *)data; - if ( !buf_arg ) { - return RTEMS_INVALID_NAME; - } - - buf_arg->length = pDev->len >> 10; /* Length in 1kByte blocks */ - if ( pDev->buf_custom ) - buf_arg->custom_buffer =(void *)pDev->buf; - else - buf_arg->custom_buffer = 0; /* Don't reveal internal driver buffer */ - break; - - case GRTC_IOC_SET_CONFIG: - cfg = (struct grtc_ioc_config *)data; - if ( !cfg ) { - return RTEMS_INVALID_NAME; - } - - if ( pDev->running ) { - return RTEMS_RESOURCE_IN_USE; - } - - pDev->config = *cfg; - break; - - case GRTC_IOC_GET_CONFIG: - cfg = (struct grtc_ioc_config *)data; - if ( !cfg ) { - return RTEMS_INVALID_NAME; - } - - *cfg = pDev->config; - break; - - case GRTC_IOC_GET_HW_STATUS: - hwregs = (struct grtc_ioc_hw_status *)data; - if ( !hwregs ) { - return RTEMS_INVALID_NAME; - } - /* We disable interrupt on the local CPU in order to get a - * snapshot of the registers. - */ - IRQ_LOCAL_DISABLE(oldLevel); - hwregs->sir = READ_REG(&pDev->regs->sir); - hwregs->far = READ_REG(&pDev->regs->far); - hwregs->clcw1 = READ_REG(&pDev->regs->clcw1); - hwregs->clcw2 = READ_REG(&pDev->regs->clcw2); - hwregs->phir = READ_REG(&pDev->regs->phir); - hwregs->str = READ_REG(&pDev->regs->str); - IRQ_LOCAL_ENABLE(oldLevel); - break; - - case GRTC_IOC_GET_STATS: - stats = (struct grtc_ioc_stats *)data; - if ( !stats ) { - return RTEMS_INVALID_NAME; - } - memcpy(stats,&pDev->stats,sizeof(struct grtc_ioc_stats)); - break; - - case GRTC_IOC_CLR_STATS: - memset(&pDev->stats,0,sizeof(struct grtc_ioc_stats)); - break; - - case GRTC_IOC_SET_MODE: - if ( pDev->running ) { - return RTEMS_RESOURCE_IN_USE; - } - if ( (int)data == GRTC_MODE_FRAME ) { - pDev->mode = GRTC_MODE_FRAME; - } else if ( (int)data == GRTC_MODE_RAW ) { - pDev->mode = GRTC_MODE_RAW; - } else { - return RTEMS_INVALID_NAME; - } - break; - - case GRTC_IOC_POOLS_SETUP: - if ( pDev->running ) { - return RTEMS_RESOURCE_IN_USE; - } - pocfg = (struct grtc_ioc_pools_setup *)data; - if ( (pDev->mode != GRTC_MODE_FRAME) || !pocfg ) { - return RTEMS_INVALID_NAME; - } - - /* Check that list is sorted */ - frm_len = 0; - for(i=0;ipool_cnt;i++){ - if ( pocfg->pool_frame_len[i] <= frm_len ) { - return RTEMS_INVALID_NAME; - } - frm_len = pocfg->pool_frame_len[i]; - } - - /* Ok, we trust user. The pool descriptions are allocated - * but not frames, that the user must do self. - */ - if ( pDev->pools ) { - free(pDev->pools); - } - pDev->pools = malloc(pocfg->pool_cnt * sizeof(struct grtc_frame_pool)); - if ( !pDev->pools ) { - pDev->pool_cnt = 0; - return RTEMS_NO_MEMORY; - } - pDev->pool_cnt = pocfg->pool_cnt; - for (i=0;ipool_cnt;i++) { - pDev->pools[i].frame_len = pocfg->pool_frame_len[i]; - pDev->pools[i].frame_cnt = 0; - pDev->pools[i].frms = NULL; - } - break; - - case GRTC_IOC_ASSIGN_FRM_POOL: - if ( pDev->running ) { - return RTEMS_RESOURCE_IN_USE; - } - - if ( (pDev->mode != GRTC_MODE_FRAME) ) { - return RTEMS_INVALID_NAME; - } - - poassign = (struct grtc_ioc_assign_frm_pool *)data; - if ( !poassign ) { - return RTEMS_INVALID_NAME; - } - - /* Find pool to assign the frames to */ - pool = NULL; - for(i=0; ipool_cnt; i++) { - if ( pDev->pools[i].frame_len == poassign->frame_len ) { - pool = &pDev->pools[i]; - break; - } - } - if ( !pool ) { - /* No Pool matching frame length */ - return RTEMS_INVALID_NAME; - } - - /* Assign frames to pool */ - frm = poassign->frames; - while(frm){ - frm->pool = pool; /* Assign Frame to pool */ - frm = frm->next; - } - break; - - case GRTC_IOC_ADD_BUFF: - frms = (struct grtc_frame *)data; - - if ( (pDev->mode != GRTC_MODE_FRAME) ) { - return RTEMS_NOT_DEFINED; - } - if ( !frms ) { - return RTEMS_INVALID_NAME; - } - - /* Add frames to respicative pools */ - if ( grtc_pool_add_frms(frms) ) { - return RTEMS_INVALID_NAME; - } - break; - - /* Try to read as much data as possible from DMA area and - * put it into free frames. - * - * If receiver is in stopped mode, let user only read previously - * received frames. - */ - case GRTC_IOC_RECV: - - if ( (pDev->mode != GRTC_MODE_FRAME) ) { - return RTEMS_NOT_DEFINED; - } - - while ( pDev->running && ((ret=process_dma(pDev) == 2) || (ret == -1)) ) { - /* Frame received or dropped, process next frame */ - } - - /* Take frames out from ready queue and put them to user */ - frmlist = (struct grtc_list *)data; - if ( !frmlist ) { - return RTEMS_INVALID_NAME; - } - - frmlist->head = pDev->ready.head; - frmlist->tail = pDev->ready.tail; - frmlist->cnt = pDev->ready.cnt; - - /* Empty list */ - pDev->ready.head = NULL; - pDev->ready.tail = NULL; - pDev->ready.cnt = 0; - - if ((frmlist->cnt == 0) && pDev->overrun_condition) { - /* signal to the user that overrun has happend when - * no more data can be read out. - */ - return RTEMS_IO_ERROR; - } - break; - - case GRTC_IOC_GET_CLCW_ADR: - if ( !data ) { - return RTEMS_INVALID_NAME; - } - *data = (unsigned int)&pDev->regs->clcw1; - break; - - default: - return RTEMS_NOT_DEFINED; - } - return RTEMS_SUCCESSFUL; -} - -static void grtc_interrupt(void *arg) -{ - struct grtc_priv *pDev = arg; - struct grtc_regs *regs = pDev->regs; - unsigned int status; - SPIN_ISR_IRQFLAGS(irqflags); - - /* Clear interrupt by reading it */ - status = READ_REG(®s->pisr); - - /* Spurious Interrupt? */ - if ( !pDev->running ) - return; - - if ( status & GRTC_INT_OV ){ - /* Stop core (Disable receiver, interrupts), set overrun condition, - * Flush semaphore if thread waiting for data in grtc_wait_data(). - */ - grtc_stop(pDev, 1); - - /* No need to handle the reset of interrupts, we are still */ - goto out; - } - - if ( status & GRTC_INT_CS ){ - SPIN_LOCK(&pDev->devlock, irqflags); - - if ( (pDev->blocking==GRTC_BLKMODE_COMPLETE) && pDev->timeout ){ - /* Signal to thread only if enough data is available */ - if ( pDev->wait_for_nbytes > grtc_data_avail(pDev) ){ - /* Not enough data available */ - goto procceed_processing_interrupts; - } - - /* Enough data is available which means that we should - * wake up the thread sleeping. - */ - } - - /* Disable further CLTUs Stored interrupts, no point until - * thread waiting for them says it want to wait for more. - */ - regs->imr = READ_REG(®s->imr) & ~GRTC_INT_CS; - SPIN_UNLOCK(&pDev->devlock, irqflags); - - /* Signal Semaphore to wake waiting thread in read() */ - rtems_semaphore_release(pDev->sem_rx); - } - -procceed_processing_interrupts: - - if ( status & GRTC_INT_CR ){ - - } - - if ( status & GRTC_INT_FAR ){ - - } - - if ( status & GRTC_INT_BLO ){ - - } - - if ( status & GRTC_INT_RFA ){ - - } -out: - if ( status ) - regs->picr = status; -} - -static rtems_device_driver grtc_initialize( - rtems_device_major_number major, - rtems_device_minor_number unused, - void *arg - ) -{ - /* Device Semaphore created with count = 1 */ - if ( rtems_semaphore_create(rtems_build_name('G', 'R', 'T', 'C'), - 1, - RTEMS_FIFO|RTEMS_NO_INHERIT_PRIORITY|RTEMS_LOCAL|RTEMS_NO_PRIORITY_CEILING, - 0, - &grtc_dev_sem) != RTEMS_SUCCESSFUL ) { - return RTEMS_INTERNAL_ERROR; - } - - return RTEMS_SUCCESSFUL; -} diff --git a/c/src/lib/libbsp/sparc/shared/tmtc/grtm.c b/c/src/lib/libbsp/sparc/shared/tmtc/grtm.c deleted file mode 100644 index bd7d98f972..0000000000 --- a/c/src/lib/libbsp/sparc/shared/tmtc/grtm.c +++ /dev/null @@ -1,1623 +0,0 @@ -/* GRTM CCSDS Telemetry Encoder driver - * - * COPYRIGHT (c) 2007. - * Cobham Gaisler AB. - * - * 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 -#include -#include -#include - -/* map via rtems_interrupt_lock_* API: */ -#define SPIN_DECLARE(lock) RTEMS_INTERRUPT_LOCK_MEMBER(lock) -#define SPIN_INIT(lock, name) rtems_interrupt_lock_initialize(lock, name) -#define SPIN_LOCK(lock, level) rtems_interrupt_lock_acquire_isr(lock, &level) -#define SPIN_LOCK_IRQ(lock, level) rtems_interrupt_lock_acquire(lock, &level) -#define SPIN_UNLOCK(lock, level) rtems_interrupt_lock_release_isr(lock, &level) -#define SPIN_UNLOCK_IRQ(lock, level) rtems_interrupt_lock_release(lock, &level) -#define SPIN_IRQFLAGS(k) rtems_interrupt_lock_context k -#define SPIN_ISR_IRQFLAGS(k) SPIN_IRQFLAGS(k) - -/* -#define DEBUG -#define DEBUGFUNCS -*/ - -#include - -/* GRTM register map */ -struct grtm_regs { - volatile unsigned int dma_ctrl; /* DMA Control Register (0x00) */ - volatile unsigned int dma_status; /* DMA Status Register (0x04) */ - volatile unsigned int dma_len; /* DMA Length Register (0x08) */ - volatile unsigned int dma_bd; /* DMA Descriptor Pointer Register (0x0c) */ - - volatile unsigned int dma_cfg; /* DMA Configuration Register (0x10) */ - volatile unsigned int revision; /* GRTM Revision Register (0x14) */ - - int unused0[(0x80-0x18)/4]; - - volatile unsigned int ctrl; /* TM Control Register (0x80) */ - volatile unsigned int status; /* TM Status Register (0x84) */ - volatile unsigned int cfg; /* TM Configuration Register (0x88) */ - volatile unsigned int size; /* TM Size Register (0x8c) */ - - volatile unsigned int phy; /* TM Physical Layer Register (0x90) */ - volatile unsigned int code; /* TM Coding Sub-Layer Register (0x94) */ - volatile unsigned int asmr; /* TM Attached Synchronization Marker Register (0x98) */ - - int unused1; - - volatile unsigned int all_frm; /* TM All Frames Generation Register (0xa0) */ - volatile unsigned int mst_frm; /* TM Master Channel Frame Generation Register (0xa4) */ - volatile unsigned int idle_frm; /* TM Idle Frame Generation Register (0xa8) */ - - int unused2[(0xc0-0xac)/4]; - - volatile unsigned int fsh[4]; /* TM FSH/Insert Zone Registers (0xc0..0xcc) */ - - volatile unsigned int ocf; /* TM Operational Control Field Register (0xd0) */ -}; - -/* DMA Control Register (0x00) */ -#define GRTM_DMA_CTRL_EN_BIT 0 -#define GRTM_DMA_CTRL_IE_BIT 1 -#define GRTM_DMA_CTRL_TXRST_BIT 2 -#define GRTM_DMA_CTRL_RST_BIT 3 -#define GRTM_DMA_CTRL_TFIE_BIT 4 - -#define GRTM_DMA_CTRL_EN (1<minor_drv, dev->parent->dev->name); - priv = dev->priv = malloc(sizeof(struct grtm_priv)); - if ( !priv ) - return DRVMGR_NOMEM; - memset(priv, 0, sizeof(*priv)); - priv->dev = dev; - - /* This core will not find other cores, so we wait for init2() */ - - return DRVMGR_OK; -} - -static int grtm_init3(struct drvmgr_dev *dev) -{ - struct grtm_priv *priv; - char prefix[32]; - rtems_status_code status; - - priv = dev->priv; - - /* Do initialization */ - - if ( grtm_driver_io_registered == 0) { - /* Register the I/O driver only once for all cores */ - if ( grtm_register_io(&grtm_driver_io_major) ) { - /* Failed to register I/O driver */ - dev->priv = NULL; - return DRVMGR_FAIL; - } - - grtm_driver_io_registered = 1; - } - - /* I/O system registered and initialized - * Now we take care of device initialization. - */ - if ( grtm_device_init(priv) ) { - return DRVMGR_FAIL; - } - - /* Get Filesystem name prefix */ - prefix[0] = '\0'; - if ( drvmgr_get_dev_prefix(dev, prefix) ) { - /* Failed to get prefix, make sure of a unique FS name - * by using the driver minor. - */ - sprintf(priv->devName, "/dev/grtm%d", dev->minor_drv); - } else { - /* Got special prefix, this means we have a bus prefix - * And we should use our "bus minor" - */ - sprintf(priv->devName, "/dev/%sgrtm%d", prefix, dev->minor_bus); - } - - SPIN_INIT(&priv->devlock, priv->devName); - - /* Register Device */ - status = rtems_io_register_name(priv->devName, grtm_driver_io_major, dev->minor_drv); - if (status != RTEMS_SUCCESSFUL) { - return DRVMGR_FAIL; - } - - return DRVMGR_OK; -} - -/******************* Driver Implementation ***********************/ - -static int grtm_register_io(rtems_device_major_number *m) -{ - rtems_status_code r; - - if ((r = rtems_io_register_driver(0, &grtm_driver, m)) == RTEMS_SUCCESSFUL) { - DBG("GRTM driver successfully registered, major: %d\n", *m); - } else { - switch(r) { - case RTEMS_TOO_MANY: - printk("GRTM rtems_io_register_driver failed: RTEMS_TOO_MANY\n"); - return -1; - case RTEMS_INVALID_NUMBER: - printk("GRTM rtems_io_register_driver failed: RTEMS_INVALID_NUMBER\n"); - return -1; - case RTEMS_RESOURCE_IN_USE: - printk("GRTM rtems_io_register_driver failed: RTEMS_RESOURCE_IN_USE\n"); - return -1; - default: - printk("GRTM rtems_io_register_driver failed\n"); - return -1; - } - } - return 0; -} - -static int grtm_device_init(struct grtm_priv *pDev) -{ - struct amba_dev_info *ambadev; - struct ambapp_core *pnpinfo; - union drvmgr_key_value *value; - - /* Get device information from AMBA PnP information */ - ambadev = (struct amba_dev_info *)pDev->dev->businfo; - if ( ambadev == NULL ) { - return -1; - } - pnpinfo = &ambadev->info; - pDev->irq = pnpinfo->irq; - pDev->regs = (struct grtm_regs *)pnpinfo->apb_slv->start; - pDev->minor = pDev->dev->minor_drv; - pDev->open = 0; - pDev->running = 0; - - /* Create Binary RX Semaphore with count = 0 */ - if ( rtems_semaphore_create(rtems_build_name('G', 'R', 'M', '0' + pDev->minor), - 0, - RTEMS_FIFO|RTEMS_SIMPLE_BINARY_SEMAPHORE|RTEMS_NO_INHERIT_PRIORITY|\ - RTEMS_LOCAL|RTEMS_NO_PRIORITY_CEILING, - 0, - &pDev->sem_tx) != RTEMS_SUCCESSFUL ) { - return -1; - } - - /* Allocate Memory for Buffer Descriptor Table, or let user provide a custom - * address. - */ - value = drvmgr_dev_key_get(pDev->dev, "bdTabAdr", DRVMGR_KT_POINTER); - if ( value ) { - pDev->bds = (struct grtm_bd *)value->ptr; - pDev->_bds = (void *)value->ptr; - } else { - pDev->bds = (struct grtm_bd *)grtm_memalign(0x400, 0x400, &pDev->_bds); - } - if ( !pDev->bds ) { - DBG("GRTM: Failed to allocate descriptor table\n"); - return -1; - } - memset(pDev->bds, 0, 0x400); - - pDev->_ring = malloc(sizeof(struct grtm_ring) * 128); - if ( !pDev->_ring ) { - return -1; - } - - /* Reset Hardware before attaching IRQ handler */ - grtm_hw_reset(pDev); - - /* Read SUB revision number, ignore */ - pDev->subrev = (READ_REG(&pDev->regs->revision) & GRTM_REV1_REV_SREV) - >> GRTM_REV1_REV_SREV_BIT; - - return 0; -} - - -static inline void grtm_list_clr(struct grtm_list *list) -{ - list->head = NULL; - list->tail = NULL; -} - -static void grtm_hw_reset(struct grtm_priv *pDev) -{ - /* Reset Core */ - pDev->regs->dma_ctrl = GRTM_DMA_CTRL_RST; -} - -static void grtm_hw_get_implementation(struct grtm_priv *pDev, struct grtm_ioc_hw *hwcfg) -{ - unsigned int cfg = READ_REG(&pDev->regs->cfg); - - hwcfg->cs = (cfg & GRTM_CFG_SC) ? 1:0; - hwcfg->sp = (cfg & GRTM_CFG_SP) ? 1:0; - hwcfg->ce = (cfg & GRTM_CFG_CE) ? 1:0; - hwcfg->nrz = (cfg & GRTM_CFG_NRZ) ? 1:0; - hwcfg->psr = (cfg & GRTM_CFG_PSR) ? 1:0; - hwcfg->te = (cfg & GRTM_CFG_TE) ? 1:0; - hwcfg->rsdep = (cfg & GRTM_CFG_RSDEP)>>GRTM_CFG_RSDEP_BIT; - hwcfg->rs = (cfg & GRTM_CFG_RS)>>GRTM_CFG_RS_BIT; - hwcfg->aasm = (cfg & GRTM_CFG_AASM) ? 1:0; - hwcfg->fecf = (cfg & GRTM_CFG_FECF) ? 1:0; - hwcfg->ocf = (cfg & GRTM_CFG_OCF) ? 1:0; - hwcfg->evc = (cfg & GRTM_CFG_EVC) ? 1:0; - hwcfg->idle = (cfg & GRTM_CFG_IDLE) ? 1:0; - hwcfg->fsh = (cfg & GRTM_CFG_FSH) ? 1:0; - hwcfg->mcg = (cfg & GRTM_CFG_MCG) ? 1:0; - hwcfg->iz = (cfg & GRTM_CFG_IZ) ? 1:0; - hwcfg->fhec = (cfg & GRTM_CFG_FHEC) ? 1:0; - hwcfg->aos = (cfg & GRTM_CFG_AOS) ? 1:0; - hwcfg->cif = (cfg & GRTM_CFG_CIF) ? 1:0; - hwcfg->ocfb = (cfg & GRTM_CFG_OCFB) ? 1:0; - - cfg = READ_REG(&pDev->regs->dma_cfg); - hwcfg->blk_size = (cfg & GRTM_DMA_CFG_BLKSZ) >> GRTM_DMA_CFG_BLKSZ_BIT; - hwcfg->fifo_size= (cfg & GRTM_DMA_CFG_FIFOSZ) >> GRTM_DMA_CFG_FIFOSZ_BIT; -} - - -/* TODO: Implement proper default calculation from hardware configuration */ -static void grtm_hw_get_default_modes(struct grtm_ioc_config *cfg, struct grtm_ioc_hw *hwcfg) -{ - cfg->mode = GRTM_MODE_TM; - cfg->frame_length = 223; - cfg->limit = 0; /* Make driver auto configure it on START, user may override with non-zero value */ - cfg->as_marker = 0x1ACFFC1D; - - /* Physical */ - cfg->phy_subrate = 1; - cfg->phy_symbolrate = 1; - cfg->phy_opts = 0; - - /* Coding Layer */ - cfg->code_rsdep = 1; - cfg->code_ce_rate = 0; - cfg->code_csel = 0; - cfg->code_opts = 0; - - /* All Frame Generation */ - cfg->all_izlen = 0; - cfg->all_opts = GRTM_IOC_ALL_FECF; - - /* Master Channel Frame Generation */ - if ( hwcfg->mcg ) { - cfg->mf_opts = GRTM_IOC_MF_MC; - } else { - cfg->mf_opts = 0; - } - - /* Idle Frame Generation */ - cfg->idle_scid = 0; - cfg->idle_vcid = 0; - if ( hwcfg->idle ) { - cfg->idle_opts = GRTM_IOC_IDLE_EN; - } else { - cfg->idle_opts = 0; - } - - /* Interrupt options */ - cfg->blocking = 0; /* non-blocking mode is default */ - cfg->enable_cnt = 16; /* generate interrupt every 16 descriptor */ - cfg->isr_desc_proc = 1; /* Let interrupt handler do descriptor processing */ - cfg->timeout = RTEMS_NO_TIMEOUT; - -} - -static void *grtm_memalign(unsigned int boundary, unsigned int length, void *realbuf) -{ - *(int *)realbuf = (int)malloc(length+boundary); - DBG("GRTM: Alloced %d (0x%x) bytes, requested: %d\n",length+boundary,length+boundary,length); - return (void *)(((*(unsigned int *)realbuf)+boundary) & ~(boundary-1)); -} - -static int grtm_hw_set_config(struct grtm_priv *pDev, struct grtm_ioc_config *cfg, struct grtm_ioc_hw *hwcfg) -{ - struct grtm_regs *regs = pDev->regs; - unsigned int tmp; - unsigned int limit; - - if ( cfg->limit == 0 ) { - /* Calculate Limit */ - if ( cfg->frame_length > hwcfg->blk_size ) { - limit = hwcfg->blk_size*2; - } else { - limit = cfg->frame_length; - } - } else { - /* Use user configured limit */ - limit = cfg->limit; - } - - /* Frame Length and Limit */ - regs->dma_len = (((limit-1) << GRTM_DMA_LEN_LIM_BIT) & GRTM_DMA_LEN_LIM)| - (((cfg->frame_length-1) << GRTM_DMA_LEN_LEN_BIT) & GRTM_DMA_LEN_LEN); - - /* Physical layer options */ - tmp = (cfg->phy_opts & (GRTM_IOC_PHY_SCF|GRTM_IOC_PHY_SF)) | - (((cfg->phy_symbolrate-1)<phy_subrate-1)<phy = tmp; - - /* Coding Sub-layer Options */ - tmp = (cfg->code_opts & GRTM_IOC_CODE_ALL) | ((cfg->code_csel<code_rsdep-1)<code_ce_rate<code = tmp; - - /* Attached synchronization marker register */ - regs->asmr = cfg->as_marker; - - /* All Frames Generation */ - tmp = ((cfg->all_opts & GRTM_IOC_ALL_ALL)<<14) | - ((cfg->all_izlen<mode<all_frm = tmp; - - /* Master Frame Generation */ - regs->mst_frm = cfg->mf_opts & GRTM_IOC_MF_ALL; - - /* Idle frame Generation */ - tmp = ((cfg->idle_opts & GRTM_IOC_IDLE_ALL) << 16) | - ((cfg->idle_vcid << GRTM_IDLE_VCID_BIT) & GRTM_IDLE_VCID) | - ((cfg->idle_scid << GRTM_IDLE_SCID_BIT) & GRTM_IDLE_SCID); - regs->idle_frm = tmp; - - return 0; -} - -static int grtm_start(struct grtm_priv *pDev) -{ - struct grtm_regs *regs = pDev->regs; - int i; - struct grtm_ioc_config *cfg = &pDev->config; - unsigned int txrdy; - - /* Clear Descriptors */ - memset(pDev->bds,0,0x400); - - /* Clear stats */ - memset(&pDev->stats,0,sizeof(struct grtm_ioc_stats)); - - /* Init Descriptor Ring */ - memset(pDev->_ring,0,sizeof(struct grtm_ring)*128); - for(i=0;i<127;i++){ - pDev->_ring[i].next = &pDev->_ring[i+1]; - pDev->_ring[i].bd = &pDev->bds[i]; - pDev->_ring[i].frm = NULL; - } - pDev->_ring[127].next = &pDev->_ring[0]; - pDev->_ring[127].bd = &pDev->bds[127]; - pDev->_ring[127].frm = NULL; - - pDev->ring = &pDev->_ring[0]; - pDev->ring_end = &pDev->_ring[0]; - - /* Clear Scheduled, Ready and Sent list */ - grtm_list_clr(&pDev->ready); - grtm_list_clr(&pDev->scheduled); - grtm_list_clr(&pDev->sent); - - /* Software init */ - pDev->handling_transmission = 0; - - /* Reset the transmitter */ - regs->dma_ctrl = GRTM_DMA_CTRL_TXRST; - regs->dma_ctrl = 0; /* Leave Reset */ - - /* Clear old interrupts */ - regs->dma_status = GRTM_DMA_STS_ALL; - - /* Set Descriptor Pointer Base register to point to first descriptor */ - drvmgr_translate_check(pDev->dev, CPUMEM_TO_DMA, (void *)pDev->bds, - (void **)®s->dma_bd, 0x400); - - /* Set hardware options as defined by config */ - if ( grtm_hw_set_config(pDev, cfg, &pDev->hw_avail) ) { - return RTEMS_IO_ERROR; - } - - /* Enable TM Transmitter */ - regs->ctrl = GRTM_CTRL_EN; - - /* Wait for TXRDY to be cleared */ - i=1000; - while( i > 0 ) { - asm volatile ("nop"::); - i--; - } - - /* Check transmitter startup OK */ - i = 1000000; - do { - /* Location of TXRDY Bit is different for different revisions */ - if ( pDev->subrev == 0 ) { - txrdy = READ_REG(®s->dma_ctrl) & - GRTM_REV0_DMA_CTRL_TXRDY; - } else { - txrdy = READ_REG(®s->dma_status) & - GRTM_REV1_DMA_STS_TXRDY; - } - if (txrdy != 0) - break; - - asm volatile ("nop"::); - } while ( --i > 0 ); - if ( i == 0 ) { - /* Reset Failed */ - DBG("GRTM: start: Reseting transmitter failed (%d)\n",i); - return RTEMS_IO_ERROR; - } - DBG("GRTM: reset time %d\n",i); - - /* Everything is configured, the TM transmitter is started - * and idle frames has been sent. - */ - - /* Mark running before enabling the DMA transmitter */ - pDev->running = 1; - - /* Enable interrupts (Error and DMA TX) */ - regs->dma_ctrl = GRTM_DMA_CTRL_IE; - - DBG("GRTM: STARTED\n"); - - return RTEMS_SUCCESSFUL; -} - -static void grtm_stop(struct grtm_priv *pDev) -{ - struct grtm_regs *regs = pDev->regs; - - /* Disable the transmitter & Interrupts */ - regs->dma_ctrl = 0; - - /* Clear any pending interrupt */ - regs->dma_status = GRTM_DMA_STS_ALL; - - DBG("GRTM: STOPPED\n"); - - /* Flush semaphore in case a thread is stuck waiting for TX Interrupts */ - rtems_semaphore_flush(pDev->sem_tx); -} - -static rtems_device_driver grtm_open( - rtems_device_major_number major, - rtems_device_minor_number minor, - void *arg) -{ - struct grtm_priv *pDev; - struct drvmgr_dev *dev; - - FUNCDBG(); - - if ( drvmgr_get_dev(&grtm_drv_info.general, minor, &dev) ) { - DBG("Wrong minor %d\n", minor); - return RTEMS_INVALID_NUMBER; - } - pDev = (struct grtm_priv *)dev->priv; - - /* Wait until we get semaphore */ - if ( rtems_semaphore_obtain(grtm_dev_sem, RTEMS_WAIT, RTEMS_NO_TIMEOUT) != RTEMS_SUCCESSFUL ){ - return RTEMS_INTERNAL_ERROR; - } - - /* Is device in use? */ - if ( pDev->open ){ - rtems_semaphore_release(grtm_dev_sem); - return RTEMS_RESOURCE_IN_USE; - } - - /* Mark device taken */ - pDev->open = 1; - - rtems_semaphore_release(grtm_dev_sem); - - DBG("grtm_open: OPENED minor %d (pDev: 0x%x)\n",pDev->minor,(unsigned int)pDev); - - /* Set defaults */ - pDev->config.timeout = RTEMS_NO_TIMEOUT; /* no timeout (wait forever) */ - pDev->config.blocking = 0; /* polling mode */ - - pDev->running = 0; /* not in running mode yet */ - - memset(&pDev->config,0,sizeof(pDev->config)); - - /* The core has been reset when we execute here, so it is possible - * to read out what HW is implemented from core. - */ - grtm_hw_get_implementation(pDev, &pDev->hw_avail); - - /* Get default modes */ - grtm_hw_get_default_modes(&pDev->config,&pDev->hw_avail); - - return RTEMS_SUCCESSFUL; -} - -static rtems_device_driver grtm_close(rtems_device_major_number major, rtems_device_minor_number minor, void *arg) -{ - struct grtm_priv *pDev; - struct drvmgr_dev *dev; - - FUNCDBG(); - - if ( drvmgr_get_dev(&grtm_drv_info.general, minor, &dev) ) { - return RTEMS_INVALID_NUMBER; - } - pDev = (struct grtm_priv *)dev->priv; - - if ( pDev->running ){ - drvmgr_interrupt_unregister(dev, 0, grtm_interrupt, pDev); - grtm_stop(pDev); - pDev->running = 0; - } - - /* Reset core */ - grtm_hw_reset(pDev); - - /* Clear descriptor area just for sure */ - memset(pDev->bds, 0, 0x400); - - /* Mark not open */ - pDev->open = 0; - - return RTEMS_SUCCESSFUL; -} - -static rtems_device_driver grtm_read(rtems_device_major_number major, rtems_device_minor_number minor, void *arg) -{ - FUNCDBG(); - return RTEMS_NOT_IMPLEMENTED; -} - -static rtems_device_driver grtm_write(rtems_device_major_number major, rtems_device_minor_number minor, void *arg) -{ - FUNCDBG(); - return RTEMS_NOT_IMPLEMENTED; -} - -/* Scans the desciptor table for scheduled frames that has been sent, - * and moves these frames from the head of the scheduled queue to the - * tail of the sent queue. - * - * Also, for all frames the status is updated. - * - * Return Value - * Number of frames freed. - */ -static int grtm_free_sent(struct grtm_priv *pDev) -{ - struct grtm_ring *curr; - struct grtm_frame *last_frm, *first_frm; - int freed_frame_cnt=0; - unsigned int ctrl; - - curr = pDev->ring_end; - - /* Step into TX ring to find sent frames */ - if ( !curr->frm ){ - /* No scheduled frames, abort */ - return 0; - } - - /* There has been messages scheduled ==> scheduled messages may have been - * transmitted and needs to be collected. - */ - - first_frm = curr->frm; - - /* Loop until first enabled unsent frame is found. - * A unused descriptor is indicated by an unassigned frm field - */ - while ( curr->frm && !((ctrl=READ_REG(&curr->bd->ctrl)) & GRTM_BD_EN) ){ - /* Handle one sent Frame */ - - /* Remember last handled frame so that insertion/removal from - * frames lists go fast. - */ - last_frm = curr->frm; - - /* 1. Set flags to indicate error(s) and other information */ - last_frm->flags |= GRTM_FLAGS_SENT; /* Mark sent */ - - /* Update Stats */ - pDev->stats.frames_sent++; - - /* Did packet encounter link error? */ - if ( ctrl & GRTM_BD_UE ) { - pDev->stats.err_underrun++; - last_frm->flags |= GRRM_FLAGS_ERR; - } - - curr->frm = NULL; /* Mark unused */ - - /* Increment */ - curr = curr->next; - freed_frame_cnt++; - } - - /* 1. Remove all handled frames from scheduled queue - * 2. Put all handled frames into sent queue - */ - if ( freed_frame_cnt > 0 ){ - - /* Save TX ring posistion */ - pDev->ring_end = curr; - - /* Remove all sent frames from scheduled list */ - if ( pDev->scheduled.tail == last_frm ){ - /* All scheduled frames sent... */ - pDev->scheduled.head = NULL; - pDev->scheduled.tail = NULL; - }else{ - pDev->scheduled.head = last_frm->next; - } - last_frm->next = NULL; - - /* Put all sent frames into "Sent queue" for user to - * collect, later on. - */ - if ( !pDev->sent.head ){ - /* Sent queue empty */ - pDev->sent.head = first_frm; - pDev->sent.tail = last_frm; - }else{ - pDev->sent.tail->next = first_frm; - pDev->sent.tail = last_frm; - } - } - return freed_frame_cnt; -} - - -/* Moves as many frames in the ready queue (as there are free descriptors for) - * to the scheduled queue. The free descriptors are then assigned one frame - * each and enabled for transmission. - * - * Return Value - * Returns number of frames moved from ready to scheduled queue - */ -static int grtm_schedule_ready(struct grtm_priv *pDev) -{ - int cnt; - unsigned int ctrl, dmactrl; - struct grtm_ring *curr_bd; - struct grtm_frame *curr_frm, *last_frm; - - if ( !pDev->ready.head ){ - return 0; - } - - cnt=0; - curr_frm = pDev->ready.head; - curr_bd = pDev->ring; - while( !curr_bd->frm ){ - /* Assign frame to descriptor */ - curr_bd->frm = curr_frm; - - /* Prepare descriptor address. Three cases: - * - GRTM core on same bus as CPU ==> no translation (Address used by CPU = address used by GRTM) - * - GRTM core on remote bus, and payload address given as used by CPU ==> Translation needed - * - GRTM core on remote bus, and payload address given as used by GRTM ==> no translation [ USER does custom translation] - */ - if ( curr_frm->flags & (GRTM_FLAGS_TRANSLATE|GRTM_FLAGS_TRANSLATE_AND_REMEMBER) ) { - /* Do translation */ - drvmgr_translate(pDev->dev, CPUMEM_TO_DMA, (void *)curr_frm->payload, (void **)&curr_bd->bd->address); - if ( curr_frm->flags & GRTM_FLAGS_TRANSLATE_AND_REMEMBER ) { - if ( curr_frm->payload != (unsigned int *)curr_bd->bd->address ) { - /* Translation needed */ - curr_frm->flags &= ~GRTM_FLAGS_TRANSLATE_AND_REMEMBER; - curr_frm->flags |= GRTM_FLAGS_TRANSLATE; - } else { - /* No Trnaslation needed */ - curr_frm->flags &= ~(GRTM_FLAGS_TRANSLATE|GRTM_FLAGS_TRANSLATE_AND_REMEMBER); - } - } - } else { - /* Custom translation or no translation needed */ - curr_bd->bd->address = (unsigned int)curr_frm->payload; - } - - ctrl = GRTM_BD_EN; - if ( curr_bd->next == pDev->_ring ){ - ctrl |= GRTM_BD_WR; /* Wrap around */ - } - /* Apply user options/flags */ - ctrl |= (curr_frm->flags & GRTM_FLAGS_MASK); - - /* Is this Frame going to be an interrupt Frame? */ - if ( (--pDev->enable_cnt_curr) <= 0 ){ - if ( pDev->config.enable_cnt == 0 ){ - pDev->enable_cnt_curr = 0x3fffffff; - }else{ - pDev->enable_cnt_curr = pDev->config.enable_cnt; - ctrl |= GRTM_BD_IE; - } - } - - /* Enable descriptor */ - curr_bd->bd->ctrl = ctrl; - - last_frm = curr_frm; - curr_bd = curr_bd->next; - cnt++; - - /* Get Next Frame from Ready Queue */ - if ( curr_frm == pDev->ready.tail ){ - /* Handled all in ready queue. */ - curr_frm = NULL; - break; - } - curr_frm = curr_frm->next; - } - - /* Has frames have been scheduled? */ - if ( cnt > 0 ){ - /* Make last frame mark end of chain, probably pointless... */ - last_frm->next = NULL; - - /* Insert scheduled packets into scheduled queue */ - if ( !pDev->scheduled.head ){ - /* empty scheduled queue */ - pDev->scheduled.head = pDev->ready.head; - pDev->scheduled.tail = last_frm; - }else{ - pDev->scheduled.tail->next = pDev->ready.head; - pDev->scheduled.tail = last_frm; - } - - /* Remove scheduled packets from ready queue */ - pDev->ready.head = curr_frm; - if ( !curr_frm ){ - pDev->ready.tail = NULL; - } - - /* Update TX ring posistion */ - pDev->ring = curr_bd; - - /* Make hardware aware of the newly enabled descriptors */ - dmactrl = READ_REG(&pDev->regs->dma_ctrl); - dmactrl &= ~(GRTM_DMA_CTRL_TXRST | GRTM_DMA_CTRL_RST); - dmactrl |= GRTM_DMA_CTRL_EN; - pDev->regs->dma_ctrl = dmactrl; - } - - return cnt; -} - -static void grtm_tx_process(struct grtm_priv *pDev) -{ - int num; - - /* Free used descriptors and put the sent frame into the "Sent queue" - * (SCHEDULED->SENT) - */ - num = grtm_free_sent(pDev); - pDev->scheduled_cnt -= num; - pDev->sent_cnt += num; - - /* Use all available free descriptors there are frames for - * in the ready queue. - * (READY->SCHEDULED) - */ - if (pDev->running) { - num = grtm_schedule_ready(pDev); - pDev->ready_cnt -= num; - pDev->scheduled_cnt += num; - } -} - -/* - * The TX lock protects user tasks from the ISR. If TX DMA interrupt occurs - * while the user task is processing the TX DMA descriptors the ISR will - * ignore interrupt the request by not processing the DMA table since that - * is done by the user task anyway. In SMP, when a user task enters the TX DMA - * processing while the ISR (on another CPU) is also processing the user task - * will loop waiting for the ISR to complete. - */ -static int grtm_request_txlock(struct grtm_priv *pDev, int block) -{ - SPIN_IRQFLAGS(irqflags); - int got_lock = 0; - - do { - SPIN_LOCK_IRQ(&pDev->devlock, irqflags); - if (pDev->handling_transmission == 0) { - pDev->handling_transmission = 1; - got_lock = 1; - } - SPIN_UNLOCK_IRQ(&pDev->devlock, irqflags); - } while (!got_lock && block); - - return got_lock; -} - -static inline int grtm_request_txlock_isr(struct grtm_priv *pDev) -{ - SPIN_ISR_IRQFLAGS(irqflags); - int got_lock = 0; - - SPIN_LOCK(&pDev->devlock, irqflags); - if (pDev->handling_transmission == 0) { - pDev->handling_transmission = 1; - got_lock = 1; - } - SPIN_UNLOCK(&pDev->devlock, irqflags); - - return got_lock; -} - -static inline void grtm_release_txlock(struct grtm_priv *pDev) -{ - pDev->handling_transmission = 0; -} - -static rtems_device_driver grtm_ioctl(rtems_device_major_number major, rtems_device_minor_number minor, void *arg) -{ - struct grtm_priv *pDev; - struct drvmgr_dev *dev; - rtems_libio_ioctl_args_t *ioarg = (rtems_libio_ioctl_args_t *)arg; - unsigned int *data; - int status; - struct grtm_ioc_config *cfg; - struct grtm_ioc_hw_status *hwregs; - struct grtm_list *chain; - struct grtm_frame *curr; - struct grtm_ioc_hw *hwimpl; - struct grtm_ioc_stats *stats; - int num,ret; - - FUNCDBG(); - - if ( drvmgr_get_dev(&grtm_drv_info.general, minor, &dev) ) { - return RTEMS_INVALID_NUMBER; - } - pDev = (struct grtm_priv *)dev->priv; - - if (!ioarg) - return RTEMS_INVALID_NAME; - - data = ioarg->buffer; - ioarg->ioctl_return = 0; - switch(ioarg->command) { - case GRTM_IOC_START: - if ( pDev->running ) { - return RTEMS_RESOURCE_IN_USE; /* EBUSY */ - } - if ( (status=grtm_start(pDev)) != RTEMS_SUCCESSFUL ){ - return status; - } - /* Register ISR & Enable interrupt */ - drvmgr_interrupt_register(dev, 0, "grtm", grtm_interrupt, pDev); - - /* Read and write are now open... */ - break; - - case GRTM_IOC_STOP: - if ( !pDev->running ) { - return RTEMS_RESOURCE_IN_USE; - } - - /* Disable interrupts */ - drvmgr_interrupt_unregister(dev, 0, grtm_interrupt, pDev); - grtm_stop(pDev); - pDev->running = 0; - break; - - case GRTM_IOC_ISSTARTED: - if ( !pDev->running ) { - return RTEMS_RESOURCE_IN_USE; - } - break; - - case GRTM_IOC_SET_BLOCKING_MODE: - if ( (unsigned int)data > GRTM_BLKMODE_BLK ) { - return RTEMS_INVALID_NAME; - } - DBG("GRTM: Set blocking mode: %d\n",(unsigned int)data); - pDev->config.blocking = (unsigned int)data; - break; - - case GRTM_IOC_SET_TIMEOUT: - DBG("GRTM: Timeout: %d\n",(unsigned int)data); - pDev->config.timeout = (rtems_interval)data; - break; - - case GRTM_IOC_SET_CONFIG: - cfg = (struct grtm_ioc_config *)data; - if ( !cfg ) { - return RTEMS_INVALID_NAME; - } - - if ( pDev->running ) { - return RTEMS_RESOURCE_IN_USE; - } - - pDev->config = *cfg; - break; - - case GRTM_IOC_GET_STATS: - stats = (struct grtm_ioc_stats *)data; - if ( !stats ) { - return RTEMS_INVALID_NAME; - } - memcpy(stats,&pDev->stats,sizeof(struct grtm_ioc_stats)); - break; - - case GRTM_IOC_CLR_STATS: - memset(&pDev->stats,0,sizeof(struct grtm_ioc_stats)); - break; - - case GRTM_IOC_GET_CONFIG: - cfg = (struct grtm_ioc_config *)data; - if ( !cfg ) { - return RTEMS_INVALID_NAME; - } - - *cfg = pDev->config; - break; - - case GRTM_IOC_GET_OCFREG: - if ( !pDev->hw_avail.ocf ) { - /* Hardware does not implement the OCF register */ - return RTEMS_NOT_DEFINED; - } - if ( !data ) { - return RTEMS_INVALID_NAME; - } - *(unsigned int **)data = (unsigned int *)&pDev->regs->ocf; - break; - - case GRTM_IOC_GET_HW_IMPL: - hwimpl = (struct grtm_ioc_hw *)data; - if ( !hwimpl ) { - return RTEMS_INVALID_NAME; - } - *hwimpl = pDev->hw_avail; - break; - - case GRTM_IOC_GET_HW_STATUS: - hwregs = (struct grtm_ioc_hw_status *)data; - if ( !hwregs ) { - return RTEMS_INVALID_NAME; - } - /* We disable interrupt in order to get a snapshot of the registers */ -/* TODO: implement hwregs */ - break; - - /* Put a chain of frames at the back of the "Ready frames" queue. This - * triggers the driver to put frames from the Ready queue into unused - * available descriptors. (Ready -> Scheduled) - */ - - case GRTM_IOC_SEND: - if ( !pDev->running ){ - return RTEMS_RESOURCE_IN_USE; - } - - /* Get pointer to frame chain wished be sent */ - chain = (struct grtm_list *)ioarg->buffer; - if ( !chain ){ - /* No new frames to send ==> just trigger hardware - * to send previously made ready frames to be sent. - * If someone else is processing the DMA we igore the - * request. - */ - if (grtm_request_txlock(pDev, 0)) { - grtm_tx_process(pDev); - grtm_release_txlock(pDev); - } - break; - } - if ( !chain->tail || !chain->head ){ - return RTEMS_INVALID_NAME; - } - - DBG("GRTM_SEND: head: 0x%x, tail: 0x%x\n",chain->head,chain->tail); - - /* Mark ready frames unsent by clearing GRTM_FLAGS_SENT of all frames */ - - num = 0; - curr = chain->head; - while(curr != chain->tail){ - curr->flags = curr->flags & ~(GRTM_FLAGS_SENT|GRRM_FLAGS_ERR); - curr = curr->next; - num++; - } - curr->flags = curr->flags & ~(GRTM_FLAGS_SENT|GRRM_FLAGS_ERR); - num++; - - /* wait until we get the device lock */ - grtm_request_txlock(pDev, 1); - - /* 1. Put frames into ready queue - * (New Frames->READY) - */ - if ( pDev->ready.head ){ - /* Frames already on ready queue (no free descriptors previously) ==> - * Put frames at end of ready queue - */ - pDev->ready.tail->next = chain->head; - pDev->ready.tail = chain->tail; - chain->tail->next = NULL; - }else{ - /* All frames is put into the ready queue for later processing */ - pDev->ready.head = chain->head; - pDev->ready.tail = chain->tail; - chain->tail->next = NULL; - } - pDev->ready_cnt += num; /* Added 'num' frames to ready queue */ - - /* 2. SCHEDULED->SENT - * 3. READY->SCHEDULED - */ - grtm_tx_process(pDev); - grtm_release_txlock(pDev); - break; - - /* Take all available sent frames from the "Sent frames" queue. - * If no frames has been sent, the thread may get blocked if in blocking - * mode. The blocking mode is not available if driver is not in running mode. - * - * Note this ioctl may return success even if the driver is not in STARTED mode. - * This is because in case of a error (link error of similar) and the driver switch - * from START to STOP mode we must still be able to get our frames back. - * - * Note in case the driver fails to send a frame for some reason (link error), - * the sent flag is set to 0 indicating a failure. - * - */ - case GRTM_IOC_RECLAIM: - /* Get pointer to were to place reaped chain */ - chain = (struct grtm_list *)ioarg->buffer; - if ( !chain ){ - return RTEMS_INVALID_NAME; - } - - /* Lock out interrupt handler */ - grtm_request_txlock(pDev, 1); - - do { - /* Process descriptor table and populate with new - * buffers: - * * SCHEDULED->SENT - * * READY->SCHEDULED - */ - grtm_tx_process(pDev); - - /* Are there any frames on the sent queue waiting to be - * reclaimed? - */ - - if ( !pDev->sent.head ){ - /* No frames to reclaim - no frame in sent queue. - * Instead we block thread until frames have been sent - * if in blocking mode. - */ - if ( pDev->running && pDev->config.blocking ){ - ret = rtems_semaphore_obtain(pDev->sem_tx,RTEMS_WAIT,pDev->config.timeout); - if ( ret == RTEMS_TIMEOUT ) { - grtm_release_txlock(pDev); - return RTEMS_TIMEOUT; - } else if ( ret == RTEMS_SUCCESSFUL ) { - /* There might be frames available, go check */ - continue; - } else { - /* any error (driver closed, internal error etc.) */ - grtm_release_txlock(pDev); - return RTEMS_UNSATISFIED; - } - - }else{ - /* non-blocking mode, we quit */ - chain->head = NULL; - chain->tail = NULL; - /* do not lock out interrupt handler any more */ - grtm_release_txlock(pDev); - return RTEMS_TIMEOUT; - } - }else{ - /* Take all sent framess from sent queue to userspace queue */ - chain->head = pDev->sent.head; - chain->tail = pDev->sent.tail; - chain->tail->next = NULL; /* Just for sure */ - - /* Mark no Sent */ - grtm_list_clr(&pDev->sent); - pDev->sent_cnt = 0; - - DBG("TX_RECLAIM: head: 0x%x, tail: 0x%x\n",chain->head,chain->tail); - break; - } - - }while(1); - - /* do not lock out interrupt handler any more */ - grtm_release_txlock(pDev); - break; - - default: - return RTEMS_NOT_DEFINED; - } - return RTEMS_SUCCESSFUL; -} - -static void grtm_interrupt(void *arg) -{ - struct grtm_priv *pDev = arg; - struct grtm_regs *regs = pDev->regs; - unsigned int status; - - /* Clear interrupt by reading it */ - status = READ_REG(®s->dma_status); - - /* Spurious Interrupt? */ - if ( !pDev->running || !status) - return; - - regs->dma_status = status; - - if ( status & GRTM_DMA_STS_TFF ){ - pDev->stats.err_transfer_frame++; - } - - if ( status & GRTM_DMA_STS_TA ){ - pDev->stats.err_ahb++; - } - - if ( status & GRTM_DMA_STS_TE ){ - pDev->stats.err_tx++; - } - - if ( status & GRTM_DMA_STS_TI ){ - - if ( pDev->config.isr_desc_proc) { - if (grtm_request_txlock_isr(pDev)) { - grtm_tx_process(pDev); - grtm_release_txlock(pDev); - } - -#if 0 - if ( (pDev->config.blocking==GRTM_BLKMODE_COMPLETE) && pDev->timeout ){ - /* Signal to thread only if enough data is available */ - if ( pDev->wait_for_frames > grtm_data_avail(pDev) ){ - /* Not enough data available */ - goto procceed_processing_interrupts; - } - - /* Enough number of frames has been transmitted which means that - * the waiting thread should be woken up. - */ - rtems_semaphore_release(pDev->sem_tx); - } -#endif - } - - if ( pDev->config.blocking == GRTM_BLKMODE_BLK ) { - /* Blocking mode */ - -#if 0 - /* Disable further Interrupts until handled by waiting task. */ - regs->dma_ctrl = READ_REG(®s->dma_ctrl) & ~GRTM_DMA_CTRL_IE; -#endif - - /* Signal Semaphore to wake waiting thread in ioctl(SEND|RECLAIM) */ - rtems_semaphore_release(pDev->sem_tx); - } - - } -#if 0 -procceed_processing_interrupts: - ; -#endif -} - -static rtems_device_driver grtm_initialize( - rtems_device_major_number major, - rtems_device_minor_number unused, - void *arg - ) -{ - /* Device Semaphore created with count = 1 */ - if ( rtems_semaphore_create(rtems_build_name('G', 'R', 'T', 'M'), - 1, - RTEMS_FIFO|RTEMS_NO_INHERIT_PRIORITY|RTEMS_LOCAL|RTEMS_NO_PRIORITY_CEILING, - 0, - &grtm_dev_sem) != RTEMS_SUCCESSFUL ) { - return RTEMS_INTERNAL_ERROR; - } - - return RTEMS_SUCCESSFUL; -} diff --git a/c/src/lib/libbsp/sparc/shared/uart/apbuart_cons.c b/c/src/lib/libbsp/sparc/shared/uart/apbuart_cons.c deleted file mode 100644 index e406bc01b7..0000000000 --- a/c/src/lib/libbsp/sparc/shared/uart/apbuart_cons.c +++ /dev/null @@ -1,867 +0,0 @@ -/* This file contains the driver for the GRLIB APBUART serial port. The driver - * is implemented by using the cons.c console layer. Interrupt/Polling/Task - * driven mode can be configured using driver resources: - * - * - mode (0=Polling, 1=Interrupt, 2=Task-Driven-Interrupt Mode) - * - syscon (0=Force not Ssystem Console, 1=Suggest System Console) - * - * The BSP define APBUART_INFO_AVAIL in order to add the info routine - * used for debugging. - * - * COPYRIGHT (c) 2010. - * Cobham Gaisler AB. - * - * 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. - */ - -/******************* Driver manager interface ***********************/ -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include - -/*#define DEBUG 1 */ - -#ifdef DEBUG -#define DBG(x...) printk(x) -#else -#define DBG(x...) -#endif - -/* LEON3 Low level transmit/receive functions provided by debug-uart code */ -extern void apbuart_outbyte_polled( - struct apbuart_regs *regs, - unsigned char ch, - int do_cr_on_newline, - int wait_sent); -extern int apbuart_inbyte_nonblocking(struct apbuart_regs *regs); -#ifdef LEON3 -extern struct apbuart_regs *leon3_debug_uart; /* The debug UART */ -#endif - -/* Probed hardware capabilities */ -enum { - CAP_FIFO = 0x01, /* FIFO available */ - CAP_DI = 0x02, /* RX delayed interrupt available */ -}; -struct apbuart_priv { - struct console_dev condev; - struct drvmgr_dev *dev; - struct apbuart_regs *regs; - struct rtems_termios_tty *tty; - char devName[32]; - volatile int sending; - int mode; - int cap; -}; - -/* Getters for different interfaces. It happens to be just casting which we do - * in one place to avoid getting cast away. */ -static struct console_dev *base_get_condev(rtems_termios_device_context *base) -{ - return (struct console_dev *) base; -} - -static struct apbuart_priv *condev_get_priv(struct console_dev *condev) -{ - return (struct apbuart_priv *) condev; -} - -static struct apbuart_priv *base_get_priv(rtems_termios_device_context *base) -{ - return condev_get_priv(base_get_condev(base)); -} - -/* TERMIOS Layer Callback functions */ -static bool first_open( - rtems_termios_tty *tty, - rtems_termios_device_context *base, - struct termios *term, - rtems_libio_open_close_args_t *args -); -static void last_close( - rtems_termios_tty *tty, - rtems_termios_device_context *base, - rtems_libio_open_close_args_t *args -); -static void write_interrupt( - rtems_termios_device_context *base, - const char *buf, - size_t len -); -static bool set_attributes( - rtems_termios_device_context *base, - const struct termios *t -); -static void get_attributes( - rtems_termios_device_context *base, - struct termios *t -); -static int read_polled(rtems_termios_device_context *base); -static int read_task(rtems_termios_device_context *base); -static void write_polled( - rtems_termios_device_context *base, - const char *buf, - size_t len -); - -static void apbuart_cons_isr(void *arg); -int apbuart_get_baud(struct apbuart_priv *uart); - -int apbuart_init1(struct drvmgr_dev *dev); -#ifdef APBUART_INFO_AVAIL -static int apbuart_info( - struct drvmgr_dev *dev, - void (*print_line)(void *p, char *str), - void *p, int, char *argv[]); -#define APBUART_INFO_FUNC apbuart_info -#else -#define APBUART_INFO_FUNC NULL -#endif - -struct drvmgr_drv_ops apbuart_ops = -{ - .init = {apbuart_init1, NULL, NULL, NULL}, - .remove = NULL, - .info = APBUART_INFO_FUNC -}; - -static struct amba_dev_id apbuart_ids[] = -{ - {VENDOR_GAISLER, GAISLER_APBUART}, - {0, 0} /* Mark end of table */ -}; - -static struct amba_drv_info apbuart_drv_info = -{ - { - DRVMGR_OBJ_DRV, /* Driver */ - NULL, /* Next driver */ - NULL, /* Device list */ - DRIVER_AMBAPP_GAISLER_APBUART_ID, /* Driver ID */ - "APBUART_DRV", /* Driver Name */ - DRVMGR_BUS_TYPE_AMBAPP, /* Bus Type */ - &apbuart_ops, - NULL, /* Funcs */ - 0, /* No devices yet */ - sizeof(struct apbuart_priv), /*DrvMgr alloc private*/ - }, - &apbuart_ids[0] -}; - -void apbuart_cons_register_drv (void) -{ - DBG("Registering APBUART Console driver\n"); - drvmgr_drv_register(&apbuart_drv_info.general); -} - -static const rtems_termios_device_handler handler_interrupt = { - .first_open = first_open, - .last_close = last_close, - .write = write_interrupt, - .set_attributes = set_attributes, - .mode = TERMIOS_IRQ_DRIVEN -}; - -static const rtems_termios_device_handler handler_task = { - .first_open = first_open, - .last_close = last_close, - .poll_read = read_task, - .write = write_interrupt, - .set_attributes = set_attributes, - .mode = TERMIOS_TASK_DRIVEN -}; - -static const rtems_termios_device_handler handler_polled = { - .first_open = first_open, - .last_close = last_close, - .poll_read = read_polled, - .write = write_polled, - .set_attributes = set_attributes, - .mode = TERMIOS_POLLED -}; - -/* - * APBUART hardware instantiation is flexible. Probe features here and driver - * can select appropriate routines for the hardware. probecap() return value - * is a CAP_ bitmask. - */ -static int probecap(struct apbuart_regs *regs) -{ - int cap = 0; - - /* Probe FIFO */ - if (regs->ctrl & APBUART_CTRL_FA) { - cap |= CAP_FIFO; - - /* Probe RX delayed interrupt */ - regs->ctrl |= APBUART_CTRL_DI; - if (regs->ctrl & APBUART_CTRL_DI) { - regs->ctrl &= ~APBUART_CTRL_DI; - cap |= CAP_DI; - } - } - - return cap; -} - -int apbuart_init1(struct drvmgr_dev *dev) -{ - struct apbuart_priv *priv; - struct amba_dev_info *ambadev; - struct ambapp_core *pnpinfo; - union drvmgr_key_value *value; - char prefix[32]; - unsigned int db; - static int first_uart = 1; - - /* The default operation in AMP is to use APBUART[0] for CPU[0], - * APBUART[1] for CPU[1] and so on. The remaining UARTs is not used - * since we don't know how many CPU-cores there are. Note this only - * affects the on-chip amba bus (the root bus). The user can override - * the default resource sharing by defining driver resources for the - * APBUART devices on each AMP OS instance. - */ -#if defined(RTEMS_MULTIPROCESSING) && defined(LEON3) - if (drvmgr_on_rootbus(dev) && dev->minor_drv != LEON3_Cpu_Index && - drvmgr_keys_get(dev, NULL) != 0) { - /* User hasn't configured on-chip APBUART, leave it untouched */ - return DRVMGR_EBUSY; - } -#endif - - DBG("APBUART[%d] on bus %s\n", dev->minor_drv, dev->parent->dev->name); - /* Private data was allocated and zeroed by driver manager */ - priv = dev->priv; - if (!priv) - return DRVMGR_NOMEM; - priv->dev = dev; - - /* Get device information from AMBA PnP information */ - ambadev = (struct amba_dev_info *)priv->dev->businfo; - if (ambadev == NULL) - return -1; - pnpinfo = &ambadev->info; - priv->regs = (struct apbuart_regs *)pnpinfo->apb_slv->start; - - /* Clear HW regs, leave baudrate register as it is */ - priv->regs->status = 0; - - /* leave Transmitter/receiver if this is the RTEMS debug UART (assume - * it has been setup by boot loader). - */ - db = 0; -#ifdef LEON3 - if (priv->regs == leon3_debug_uart) { - db = priv->regs->ctrl & (LEON_REG_UART_CTRL_RE | - LEON_REG_UART_CTRL_TE | - LEON_REG_UART_CTRL_PE | - LEON_REG_UART_CTRL_PS); - } -#endif - /* Let UART debug tunnelling be untouched if Flow-control is set. - * - * With old APBUARTs debug is enabled by setting LB and FL, since LB or - * DB are not reset we can not trust them. However since FL is reset we - * guess that we are debugging if FL is already set, the debugger set - * either LB or DB depending on UART capabilities. - */ - if (priv->regs->ctrl & LEON_REG_UART_CTRL_FL) { - db |= priv->regs->ctrl & (LEON_REG_UART_CTRL_DB | - LEON_REG_UART_CTRL_LB | LEON_REG_UART_CTRL_FL); - } - - priv->regs->ctrl = db; - - priv->cap = probecap(priv->regs); - - /* The system console and Debug console may depend on this device, so - * initialize it straight away. - * - * We default to have System Console on first APBUART, user may override - * this behaviour by setting the syscon option to 0. - */ - if (drvmgr_on_rootbus(dev) && first_uart) { - priv->condev.flags = CONSOLE_FLAG_SYSCON; - first_uart = 0; - } else { - priv->condev.flags = 0; - } - - value = drvmgr_dev_key_get(priv->dev, "syscon", DRVMGR_KT_INT); - if (value) { - if (value->i) - priv->condev.flags |= CONSOLE_FLAG_SYSCON; - else - priv->condev.flags &= ~CONSOLE_FLAG_SYSCON; - } - - /* Select 0=Polled, 1=IRQ, 2=Task-Driven UART Mode */ - value = drvmgr_dev_key_get(priv->dev, "mode", DRVMGR_KT_INT); - if (value) - priv->mode = value->i; - else - priv->mode = TERMIOS_POLLED; - /* TERMIOS device handlers */ - if (priv->mode == TERMIOS_IRQ_DRIVEN) { - priv->condev.handler = &handler_interrupt; - } else if (priv->mode == TERMIOS_TASK_DRIVEN) { - priv->condev.handler = &handler_task; - } else { - priv->condev.handler = &handler_polled; - } - - priv->condev.fsname = NULL; - /* Get Filesystem name prefix */ - prefix[0] = '\0'; - if (drvmgr_get_dev_prefix(dev, prefix)) { - /* Got special prefix, this means we have a bus prefix - * And we should use our "bus minor" - */ - sprintf(priv->devName, "/dev/%sapbuart%d", prefix, dev->minor_bus); - priv->condev.fsname = priv->devName; - } else { - sprintf(priv->devName, "/dev/apbuart%d", dev->minor_drv); - } - - /* Register it as a console device, the console driver will register - * a termios device as well - */ - console_dev_register(&priv->condev); - - return DRVMGR_OK; -} - -#ifdef APBUART_INFO_AVAIL -static int apbuart_info( - struct drvmgr_dev *dev, - void (*print_line)(void *p, char *str), - void *p, int argc, char *argv[]) -{ - struct apbuart_priv *priv = dev->priv; - char *str1; - char buf[64]; - - if (dev->priv == NULL) - return -DRVMGR_EINVAL; - - if (priv->mode == TERMIOS_POLLED) - str1 = "TERMIOS_POLLED"; - else if (priv->mode == TERMIOS_IRQ_DRIVEN) - str1 = "TERMIOS_IRQ_DRIVEN"; - else if (priv->mode == TERMIOS_TASK_DRIVEN) - str1 = "TERMIOS_TASK_DRIVEN"; - else - str1 = "BAD MODE"; - - sprintf(buf, "UART Mode: %s", str1); - print_line(p, buf); - if (priv->condev.fsname) { - sprintf(buf, "FS Name: %s", priv->condev.fsname); - print_line(p, buf); - } - sprintf(buf, "STATUS REG: 0x%x", priv->regs->status); - print_line(p, buf); - sprintf(buf, "CTRL REG: 0x%x", priv->regs->ctrl); - print_line(p, buf); - sprintf(buf, "SCALER REG: 0x%x baud rate %d", - priv->regs->scaler, apbuart_get_baud(priv)); - print_line(p, buf); - - return DRVMGR_OK; -} -#endif - -#ifndef LEON3 -/* This routine transmits a character, it will busy-wait until on character - * fits in the APBUART Transmit FIFO - */ -void apbuart_outbyte_polled( - struct apbuart_regs *regs, - unsigned char ch, - int do_cr_on_newline, - int wait_sent) -{ -send: - while ((regs->status & LEON_REG_UART_STATUS_THE) == 0) { - /* Lower bus utilization while waiting for UART */ - asm volatile ("nop"::); asm volatile ("nop"::); - asm volatile ("nop"::); asm volatile ("nop"::); - asm volatile ("nop"::); asm volatile ("nop"::); - asm volatile ("nop"::); asm volatile ("nop"::); - } - regs->data = (unsigned int) ch; - - if ((ch == '\n') && do_cr_on_newline) { - ch = '\r'; - goto send; - } - - /* Wait until the character has been sent? */ - if (wait_sent) { - while ((regs->status & LEON_REG_UART_STATUS_THE) == 0) - ; - } -} - -/* This routine polls for one character, return EOF if no character is available */ -int apbuart_inbyte_nonblocking(struct apbuart_regs *regs) -{ - if (regs->status & LEON_REG_UART_STATUS_ERR) { - regs->status = ~LEON_REG_UART_STATUS_ERR; - } - - if ((regs->status & LEON_REG_UART_STATUS_DR) == 0) - return EOF; - - return (int)regs->data; -} -#endif - -static bool first_open( - rtems_termios_tty *tty, - rtems_termios_device_context *base, - struct termios *term, - rtems_libio_open_close_args_t *args -) -{ - struct apbuart_priv *uart = base_get_priv(base); - - uart->tty = tty; - - /* Inherit UART hardware parameters from bootloader on system console */ - if (uart->condev.flags & CONSOLE_FLAG_SYSCON_GRANT) { - get_attributes(base, term); - term->c_oflag |= ONLCR; - set_attributes(base, term); - } - - /* Enable TX/RX */ - uart->regs->ctrl |= APBUART_CTRL_RE | APBUART_CTRL_TE; - - if (uart->mode != TERMIOS_POLLED) { - int ret; - uint32_t ctrl; - - /* Register interrupt and enable it */ - ret = drvmgr_interrupt_register( - uart->dev, 0, uart->devName, apbuart_cons_isr, tty - ); - if (ret) { - return false; - } - - uart->sending = 0; - - /* Turn on RX interrupts */ - ctrl = uart->regs->ctrl; - ctrl |= APBUART_CTRL_RI; - if (uart->cap & CAP_DI) { - /* Use RX FIFO interrupt only if delayed interrupt available. */ - ctrl |= (APBUART_CTRL_DI | APBUART_CTRL_RF); - } - uart->regs->ctrl = ctrl; - } - - return true; -} - -static void last_close( - rtems_termios_tty *tty, - rtems_termios_device_context *base, - rtems_libio_open_close_args_t *args -) -{ - struct apbuart_priv *uart = base_get_priv(base); - rtems_interrupt_lock_context lock_context; - - if (uart->mode != TERMIOS_POLLED) { - /* Turn off RX interrupts */ - rtems_termios_device_lock_acquire(base, &lock_context); - uart->regs->ctrl &= - ~(APBUART_CTRL_DI | APBUART_CTRL_RI | APBUART_CTRL_RF); - rtems_termios_device_lock_release(base, &lock_context); - - /**** Flush device ****/ - while (uart->sending) { - /* Wait until all data has been sent */ - } - while ( - (uart->regs->ctrl & APBUART_CTRL_TE) && - !(uart->regs->status & APBUART_STATUS_TS) - ) { - /* Wait until all data has left shift register */ - } - - /* Disable and unregister interrupt handler */ - drvmgr_interrupt_unregister(uart->dev, 0, apbuart_cons_isr, tty); - } - -#ifdef LEON3 - /* Disable TX/RX if not used for DEBUG */ - if (uart->regs != leon3_debug_uart) - uart->regs->ctrl &= ~(APBUART_CTRL_RE | APBUART_CTRL_TE); -#endif -} - -static int read_polled(rtems_termios_device_context *base) -{ - struct apbuart_priv *uart = base_get_priv(base); - - return apbuart_inbyte_nonblocking(uart->regs); -} - -/* This function is called from TERMIOS rxdaemon task without device lock. */ -static int read_task(rtems_termios_device_context *base) -{ - rtems_interrupt_lock_context lock_context; - struct apbuart_priv *uart = base_get_priv(base); - struct apbuart_regs *regs = uart->regs; - int cnt; - char buf[33]; - struct rtems_termios_tty *tty; - uint32_t ctrl_add; - - ctrl_add = APBUART_CTRL_RI; - if (uart->cap & CAP_DI) { - ctrl_add |= (APBUART_CTRL_DI | APBUART_CTRL_RF); - } - tty = uart->tty; - do { - cnt = 0; - while ( - (regs->status & APBUART_STATUS_DR) && - (cnt < sizeof(buf)) - ) { - buf[cnt] = regs->data; - cnt++; - } - if (0 < cnt) { - /* Tell termios layer about new characters */ - rtems_termios_enqueue_raw_characters(tty, &buf[0], cnt); - } - - /* - * Turn on RX interrupts. A new character in FIFO now may not - * cause interrupt so we must check data ready again - * afterwards. - */ - rtems_termios_device_lock_acquire(base, &lock_context); - regs->ctrl |= ctrl_add; - rtems_termios_device_lock_release(base, &lock_context); - } while (regs->status & APBUART_STATUS_DR); - - return EOF; -} - - -struct apbuart_baud { - unsigned int num; - unsigned int baud; -}; -static struct apbuart_baud apbuart_baud_table[] = { - {B50, 50}, - {B75, 75}, - {B110, 110}, - {B134, 134}, - {B150, 150}, - {B200, 200}, - {B300, 300}, - {B600, 600}, - {B1200, 1200}, - {B1800, 1800}, - {B2400, 2400}, - {B4800, 4800}, - {B9600, 9600}, - {B19200, 19200}, - {B38400, 38400}, - {B57600, 57600}, - {B115200, 115200}, - {B230400, 230400}, - {B460800, 460800}, -}; -#define BAUD_NUM (sizeof(apbuart_baud_table)/sizeof(struct apbuart_baud)) - -static int apbuart_baud_num2baud(unsigned int num) -{ - int i; - - for(i=0; iregs->scaler; - - /* Get APBUART core frequency */ - drvmgr_freq_get(uart->dev, DEV_APB_SLV, &core_clk_hz); - - /* Calculate baud rate from generator "scaler" number */ - return core_clk_hz / ((scaler + 1) * 8); -} - -static struct apbuart_baud *apbuart_get_baud_closest(struct apbuart_priv *uart) -{ - return apbuart_baud_find_closest(apbuart_get_baud(uart)); -} - -static bool set_attributes( - rtems_termios_device_context *base, - const struct termios *t -) -{ - unsigned int core_clk_hz; - unsigned int scaler; - unsigned int ctrl; - int baud; - struct apbuart_priv *uart = base_get_priv(base); - rtems_interrupt_lock_context lock_context; - - switch(t->c_cflag & CSIZE) { - default: - case CS5: - case CS6: - case CS7: - /* Hardware doesn't support other than CS8 */ - return false; - case CS8: - break; - } - - rtems_termios_device_lock_acquire(base, &lock_context); - - /* Read out current value */ - ctrl = uart->regs->ctrl; - - switch(t->c_cflag & (PARENB|PARODD)){ - case (PARENB|PARODD): - /* Odd parity */ - ctrl |= LEON_REG_UART_CTRL_PE|LEON_REG_UART_CTRL_PS; - break; - - case PARENB: - /* Even parity */ - ctrl &= ~LEON_REG_UART_CTRL_PS; - ctrl |= LEON_REG_UART_CTRL_PE; - break; - - default: - case 0: - case PARODD: - /* No Parity */ - ctrl &= ~(LEON_REG_UART_CTRL_PS|LEON_REG_UART_CTRL_PE); - } - - if (!(t->c_cflag & CLOCAL)) - ctrl |= LEON_REG_UART_CTRL_FL; - else - ctrl &= ~LEON_REG_UART_CTRL_FL; - - /* Update new settings */ - uart->regs->ctrl = ctrl; - - rtems_termios_device_lock_release(base, &lock_context); - - /* Baud rate */ - baud = apbuart_baud_num2baud(t->c_ospeed); - if (baud > 0){ - /* Get APBUART core frequency */ - drvmgr_freq_get(uart->dev, DEV_APB_SLV, &core_clk_hz); - - /* Calculate Baud rate generator "scaler" number */ - scaler = (((core_clk_hz*10)/(baud*8))-5)/10; - - /* Set new baud rate by setting scaler */ - uart->regs->scaler = scaler; - } - - return true; -} - -static void get_attributes( - rtems_termios_device_context *base, - struct termios *t -) -{ - struct apbuart_priv *uart = base_get_priv(base); - unsigned int ctrl; - struct apbuart_baud *baud; - - t->c_cflag = t->c_cflag & ~(CSIZE|PARENB|PARODD|CLOCAL); - - /* Hardware support only CS8 */ - t->c_cflag |= CS8; - - /* Read out current parity */ - ctrl = uart->regs->ctrl; - if (ctrl & LEON_REG_UART_CTRL_PE) { - if (ctrl & LEON_REG_UART_CTRL_PS) - t->c_cflag |= PARENB|PARODD; /* Odd parity */ - else - t->c_cflag |= PARENB; /* Even parity */ - } - - if ((ctrl & LEON_REG_UART_CTRL_FL) == 0) - t->c_cflag |= CLOCAL; - - baud = apbuart_get_baud_closest(uart); - t->c_cflag |= baud->num; -} - -static void write_polled( - rtems_termios_device_context *base, - const char *buf, - size_t len -) -{ - struct apbuart_priv *uart = base_get_priv(base); - int nwrite = 0; - - while (nwrite < len) { - apbuart_outbyte_polled(uart->regs, *buf++, 0, 0); - nwrite++; - } -} - -static void write_interrupt( - rtems_termios_device_context *base, - const char *buf, - size_t len -) -{ - struct apbuart_priv *uart = base_get_priv(base); - struct apbuart_regs *regs = uart->regs; - int sending; - unsigned int ctrl; - - ctrl = regs->ctrl; - - if (len > 0) { - /* - * sending is used to remember how much we have outstanding so - * we can tell termios later. - */ - /* Enable TX interrupt (interrupt is edge-triggered) */ - regs->ctrl = ctrl | APBUART_CTRL_TI; - - if (ctrl & APBUART_CTRL_FA) { - /* APBUART with FIFO.. Fill as many as FIFO allows */ - sending = 0; - while ( - ((regs->status & APBUART_STATUS_TF) == 0) && - (sending < len) - ) { - regs->data = *buf; - buf++; - sending++; - } - } else { - /* start UART TX, this will result in an interrupt when done */ - regs->data = *buf; - - sending = 1; - } - } else { - /* No more to send, disable TX interrupts */ - regs->ctrl = ctrl & ~APBUART_CTRL_TI; - - /* Tell close that we sent everything */ - sending = 0; - } - - uart->sending = sending; -} - -/* Handle UART interrupts */ -static void apbuart_cons_isr(void *arg) -{ - rtems_termios_tty *tty = arg; - rtems_termios_device_context *base; - struct console_dev *condev = rtems_termios_get_device_context(tty); - struct apbuart_priv *uart = condev_get_priv(condev); - struct apbuart_regs *regs = uart->regs; - unsigned int status; - char buf[33]; - int cnt; - - if (uart->mode == TERMIOS_TASK_DRIVEN) { - if ((status = regs->status) & APBUART_STATUS_DR) { - rtems_interrupt_lock_context lock_context; - - /* Turn off RX interrupts */ - base = rtems_termios_get_device_context(tty); - rtems_termios_device_lock_acquire(base, &lock_context); - regs->ctrl &= - ~(APBUART_CTRL_DI | APBUART_CTRL_RI | - APBUART_CTRL_RF); - rtems_termios_device_lock_release(base, &lock_context); - /* Activate termios RX daemon task */ - rtems_termios_rxirq_occured(tty); - } - } else { - /* - * Get all new characters from APBUART RX (FIFO) and store them - * on the stack. Then tell termios about the new characters. - * Maximum APBUART RX FIFO size is 32 characters. - */ - cnt = 0; - while ( - ((status=regs->status) & APBUART_STATUS_DR) && - (cnt < sizeof(buf)) - ) { - buf[cnt] = regs->data; - cnt++; - } - if (0 < cnt) { - /* Tell termios layer about new characters */ - rtems_termios_enqueue_raw_characters(tty, &buf[0], cnt); - } - } - - if (uart->sending && (status & APBUART_STATUS_TE)) { - /* Tell close that we sent everything */ - cnt = uart->sending; - - /* - * Tell termios how much we have sent. dequeue() may call - * write_interrupt() to refill the transmitter. - * write_interrupt() will eventually be called with 0 len to - * disable TX interrupts. - */ - rtems_termios_dequeue_characters(tty, cnt); - } -} - diff --git a/c/src/lib/libbsp/sparc/shared/uart/apbuart_termios.c b/c/src/lib/libbsp/sparc/shared/uart/apbuart_termios.c deleted file mode 100644 index 28ece27d9d..0000000000 --- a/c/src/lib/libbsp/sparc/shared/uart/apbuart_termios.c +++ /dev/null @@ -1,311 +0,0 @@ -/* - * COPYRIGHT (c) 1989-1998. - * On-Line Applications Research Corporation (OAR). - * - * Modified for LEON3 BSP. - * COPYRIGHT (c) 2004. - * Gaisler Research. - * - * 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 - -static void apbuart_isr(void *arg) -{ - rtems_termios_tty *tty = arg; - struct apbuart_context *uart = rtems_termios_get_device_context(tty); - unsigned int status; - char data; - - /* Get all received characters */ - while ((status=uart->regs->status) & APBUART_STATUS_DR) { - /* Data has arrived, get new data */ - data = uart->regs->data; - - /* Tell termios layer about new character */ - rtems_termios_enqueue_raw_characters(tty, &data, 1); - } - - if ( - (status & APBUART_STATUS_TE) - && (uart->regs->ctrl & APBUART_CTRL_TI) != 0 - ) { - /* write_interrupt will get called from this function */ - rtems_termios_dequeue_characters(tty, 1); - } -} - -static void apbuart_write_support( - rtems_termios_device_context *base, - const char *buf, - size_t len -) -{ - struct apbuart_context *uart = (struct apbuart_context *) base; - int sending; - - if (len > 0) { - /* Enable TX interrupt (interrupt is edge-triggered) */ - uart->regs->ctrl |= APBUART_CTRL_TI; - - /* start UART TX, this will result in an interrupt when done */ - uart->regs->data = *buf; - - sending = 1; - } else { - /* No more to send, disable TX interrupts */ - uart->regs->ctrl &= ~APBUART_CTRL_TI; - - /* Tell close that we sent everything */ - sending = 0; - } - - uart->sending = sending; -} - -static void apbuart_write_polled( - rtems_termios_device_context *base, - const char *buf, - size_t len -) -{ - struct apbuart_context *uart = (struct apbuart_context *) base; - size_t nwrite = 0; - - while (nwrite < len) { - apbuart_outbyte_polled(uart->regs, *buf++, 0, 0); - nwrite++; - } -} - -static int apbuart_poll_read(rtems_termios_device_context *base) -{ - struct apbuart_context *uart = (struct apbuart_context *) base; - - return apbuart_inbyte_nonblocking(uart->regs); -} - -static bool apbuart_set_attributes( - rtems_termios_device_context *base, - const struct termios *t -) -{ - struct apbuart_context *uart = (struct apbuart_context *) base; - rtems_interrupt_lock_context lock_context; - unsigned int scaler; - unsigned int ctrl; - int baud; - - switch (t->c_cflag & CSIZE) { - default: - case CS5: - case CS6: - case CS7: - /* Hardware doesn't support other than CS8 */ - return false; - case CS8: - break; - } - - rtems_termios_device_lock_acquire(base, &lock_context); - - /* Read out current value */ - ctrl = uart->regs->ctrl; - - switch (t->c_cflag & (PARENB|PARODD)) { - case (PARENB|PARODD): - /* Odd parity */ - ctrl |= APBUART_CTRL_PE|APBUART_CTRL_PS; - break; - - case PARENB: - /* Even parity */ - ctrl &= ~APBUART_CTRL_PS; - ctrl |= APBUART_CTRL_PE; - break; - - default: - case 0: - case PARODD: - /* No Parity */ - ctrl &= ~(APBUART_CTRL_PS|APBUART_CTRL_PE); - } - - if (!(t->c_cflag & CLOCAL)) { - ctrl |= APBUART_CTRL_FL; - } else { - ctrl &= ~APBUART_CTRL_FL; - } - - /* Update new settings */ - uart->regs->ctrl = ctrl; - - rtems_termios_device_lock_release(base, &lock_context); - - /* Baud rate */ - baud = rtems_termios_baud_to_number(t->c_ospeed); - if (baud > 0) { - /* Calculate Baud rate generator "scaler" number */ - scaler = (((uart->freq_hz * 10) / (baud * 8)) - 5) / 10; - - /* Set new baud rate by setting scaler */ - uart->regs->scaler = scaler; - } - - return true; -} - -static void apbuart_set_best_baud( - const struct apbuart_context *uart, - struct termios *term -) -{ - uint32_t baud = (uart->freq_hz * 10) / ((uart->regs->scaler * 10 + 5) * 8); - - rtems_termios_set_best_baud(term, baud); -} - -static bool apbuart_first_open_polled( - rtems_termios_tty *tty, - rtems_termios_device_context *base, - struct termios *term, - rtems_libio_open_close_args_t *args -) -{ - struct apbuart_context *uart = (struct apbuart_context *) base; - - apbuart_set_best_baud(uart, term); - - /* Initialize UART on opening */ - uart->regs->ctrl |= APBUART_CTRL_RE | APBUART_CTRL_TE; - uart->regs->status = 0; - - return true; -} - -static bool apbuart_first_open_interrupt( - rtems_termios_tty *tty, - rtems_termios_device_context *base, - struct termios *term, - rtems_libio_open_close_args_t *args -) -{ - struct apbuart_context *uart = (struct apbuart_context *) base; - rtems_status_code sc; - - apbuart_set_best_baud(uart, term); - - /* Register Interrupt handler */ - sc = rtems_interrupt_handler_install(uart->irq, "console", - RTEMS_INTERRUPT_SHARED, - apbuart_isr, - tty); - if (sc != RTEMS_SUCCESSFUL) - return false; - - uart->sending = 0; - /* Enable Receiver and transmitter and Turn on RX interrupts */ - uart->regs->ctrl |= APBUART_CTRL_RE | APBUART_CTRL_TE | - APBUART_CTRL_RI; - /* Initialize UART on opening */ - uart->regs->ctrl |= APBUART_CTRL_RE | APBUART_CTRL_TE; - uart->regs->status = 0; - - return true; -} - -static void apbuart_last_close_interrupt( - rtems_termios_tty *tty, - rtems_termios_device_context *base, - rtems_libio_open_close_args_t *args -) -{ - struct apbuart_context *uart = (struct apbuart_context *) base; - rtems_interrupt_lock_context lock_context; - - /* Turn off RX interrupts */ - rtems_termios_device_lock_acquire(base, &lock_context); - uart->regs->ctrl &= ~(APBUART_CTRL_RI); - rtems_termios_device_lock_release(base, &lock_context); - - /**** Flush device ****/ - while (uart->sending) { - /* Wait until all data has been sent */ - } - - /* uninstall ISR */ - rtems_interrupt_handler_remove(uart->irq, apbuart_isr, tty); -} - -/* - * apbuart_outbyte_polled - * - * This routine transmits a character using polling. - */ -void apbuart_outbyte_polled( - struct apbuart_regs *regs, - unsigned char ch, - int do_cr_on_newline, - int wait_sent -) -{ -send: - while ( (regs->status & APBUART_STATUS_TE) == 0 ) { - /* Lower bus utilization while waiting for UART */ - __asm__ volatile ("nop"::); __asm__ volatile ("nop"::); - __asm__ volatile ("nop"::); __asm__ volatile ("nop"::); - __asm__ volatile ("nop"::); __asm__ volatile ("nop"::); - __asm__ volatile ("nop"::); __asm__ volatile ("nop"::); - } - - if ((ch == '\n') && do_cr_on_newline) { - regs->data = (unsigned int) '\r'; - do_cr_on_newline = 0; - goto send; - } - regs->data = (unsigned int) ch; - - /* Wait until the character has been sent? */ - if (wait_sent) { - while ((regs->status & APBUART_STATUS_TE) == 0) - ; - } -} - -/* - * apbuart_inbyte_nonblocking - * - * This routine polls for a character. - */ -int apbuart_inbyte_nonblocking(struct apbuart_regs *regs) -{ - /* Clear errors */ - if (regs->status & APBUART_STATUS_ERR) - regs->status = ~APBUART_STATUS_ERR; - - if ((regs->status & APBUART_STATUS_DR) == 0) - return -1; - else - return (int) regs->data; -} - -const rtems_termios_device_handler apbuart_handler_interrupt = { - .first_open = apbuart_first_open_interrupt, - .last_close = apbuart_last_close_interrupt, - .write = apbuart_write_support, - .set_attributes = apbuart_set_attributes, - .mode = TERMIOS_IRQ_DRIVEN -}; - -const rtems_termios_device_handler apbuart_handler_polled = { - .first_open = apbuart_first_open_polled, - .poll_read = apbuart_poll_read, - .write = apbuart_write_polled, - .set_attributes = apbuart_set_attributes, - .mode = TERMIOS_POLLED -}; diff --git a/c/src/lib/libbsp/sparc/shared/uart/cons.c b/c/src/lib/libbsp/sparc/shared/uart/cons.c deleted file mode 100644 index 37f448cbf1..0000000000 --- a/c/src/lib/libbsp/sparc/shared/uart/cons.c +++ /dev/null @@ -1,136 +0,0 @@ -/* This file contains the TTY driver for the serial ports. The driver - * is layered so that different UART hardware can be used. It is implemented - * using the Driver Manager. - * - * This driver uses the termios pseudo driver. - * - * COPYRIGHT (c) 2010. - * Cobham Gaisler AB. - * - * 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 RTEMS_DRVMGR_STARTUP - -/* Note that it is not possible to use the interrupt mode of the driver - * together with the "old" APBUART and -u to GRMON. However the new - * APBUART core (from 1.0.17-b2710) has the GRMON debug bit and can - * handle interrupts. - */ - -static int console_initialized = 0; - -#define FLAG_SYSCON 0x01 -struct console_priv { - int flags; /* 0x1=SystemConsole */ - int minor; - struct console_dev *dev; -}; - -#define CONSOLE_MAX BSP_NUMBER_OF_TERMIOS_PORTS -struct console_priv cons[CONSOLE_MAX] = {{0,0},}; - -/* Install Console in TERMIOS layer */ -static void console_dev_init(struct console_priv *con) -{ - char name[16], *fsname; - rtems_status_code status; - int minor; - - minor = con->minor; - if (!con->dev->fsname) { - strcpy(name, "/dev/console_a"); - /* Special console name and MINOR for SYSTEM CONSOLE */ - if (minor == 0) - name[12] = '\0'; /* /dev/console */ - name[13] += minor; /* when minor=0, this has no effect... */ - fsname = name; - } else { - fsname = con->dev->fsname; - } - status = rtems_termios_device_install( - fsname, - con->dev->handler, - NULL, - &con->dev->base - ); - if (status != RTEMS_SUCCESSFUL) { - rtems_fatal_error_occurred(status); - } -} - -/* Called by device driver to register itself to the cons interface. */ -void console_dev_register(struct console_dev *dev) -{ - int i, minor = 0; - struct console_priv *con = NULL; - - if ((dev->flags & CONSOLE_FLAG_SYSCON) && !cons[0].dev) { - con = &cons[0]; - con->flags = FLAG_SYSCON; - } else { - for (i=1; iflags = 0; - minor = i; - break; - } - } - } - if (con == NULL) { - /* Not enough console structures */ - return; - } - dev->flags &= ~CONSOLE_FLAG_SYSCON_GRANT; - if (con->flags & FLAG_SYSCON) { - dev->flags |= CONSOLE_FLAG_SYSCON_GRANT; - } - - /* Assign Console */ - con->dev = dev; - con->minor = minor; - - if (console_initialized) { - /* Console layer is already initialized, that means that we can - * register termios interface directly. - */ - console_dev_init(con); - } -} - -#if 0 -void console_dev_unregister(struct console_dev *dev) -{ - -} -#endif - -rtems_device_driver console_initialize( - rtems_device_major_number major, - rtems_device_minor_number minor, - void *arg) -{ - int i; - - rtems_termios_initialize(); - - /* Register all Console a file system device node */ - for (i=0; i