forked from Imagelibrary/rtems
LEON: added new drivers to the LEON2/LEON3 BSPs
Most drivers use the Driver Manager for device probing, they work on AMBA-over-PCI systems if PCI is big-endian. New APIs: * GPIO Library, interfaced to GRGPIO * GENIRQ, Generic interrupt service implementation helper New GRLIB Drivers: * ACTEL 1553 RT, user interface is similar to 1553 BRM driver * GR1553 (1553 BC, RT and BM core) * AHBSTAT (AHB error status core) * GRADCDAC (Core interfacing to ADC/DAC hardware) * GRGPIO (GPIO port accessed from GPIO Library) * MCTRL (Memory controller settings configuration) * GRETH (10/100/1000 Ethernet driver using Driver manager) * GRPWM (Pulse Width Modulation core) * SPICTRL (SPI master interface) * GRSPW_ROUTER (SpaceWire Router AMBA configuration interface) * GRCTM (SpaceCraft on-board Time Management core) * SPWCUC (Time distribution over SpaceWire) * GRTC (SpaceCraft up-link Tele core) * GRTM (SpaceCraft down-link Tele Metry core) GR712RC ASIC specific interfaces: * GRASCS * CANMUX (select between OCCAN and SATCAN) * SATCAN * SLINK
This commit is contained in:
@@ -12,11 +12,15 @@ EXTRA_DIST += shared/start/start.S
|
||||
# Interrupt
|
||||
EXTRA_DIST += shared/irq/irq-shared.c
|
||||
EXTRA_DIST += shared/irq/bsp_isr_handler.c
|
||||
EXTRA_DIST += shared/irq/genirq.c
|
||||
EXTRA_DIST += shared/include/genirq.h
|
||||
|
||||
# AMBA Plug&Play bus
|
||||
EXTRA_DIST += shared/include/ahbstat.h
|
||||
EXTRA_DIST += shared/include/ambapp.h
|
||||
EXTRA_DIST += shared/include/ambapp_ids.h
|
||||
EXTRA_DIST += shared/include/grlib.h
|
||||
EXTRA_DIST += shared/amba/ahbstat.c
|
||||
EXTRA_DIST += shared/amba/ambapp.c
|
||||
EXTRA_DIST += shared/amba/ambapp_alloc.c
|
||||
EXTRA_DIST += shared/amba/ambapp_count.c
|
||||
@@ -58,9 +62,11 @@ EXTRA_DIST += shared/pci/gr_tmtc_1553.c
|
||||
# DEBUG
|
||||
EXTRA_DIST += shared/include/debug_defs.h
|
||||
|
||||
# SpaceWire (GRSPW)
|
||||
# SpaceWire
|
||||
EXTRA_DIST += shared/spw/grspw.c
|
||||
EXTRA_DIST += shared/spw/grspw_router.c
|
||||
EXTRA_DIST += shared/include/grspw.h
|
||||
EXTRA_DIST += shared/include/grspw_router.h
|
||||
|
||||
# UART
|
||||
EXTRA_DIST += shared/uart/cons.c
|
||||
@@ -75,14 +81,58 @@ EXTRA_DIST += shared/can/grcan.c
|
||||
EXTRA_DIST += shared/include/occan.h
|
||||
EXTRA_DIST += shared/include/grcan.h
|
||||
|
||||
# MEM
|
||||
EXTRA_DIST += shared/mem/mctrl.c
|
||||
|
||||
# MIL-STD-B1553 (Core1553BRM)
|
||||
EXTRA_DIST += shared/1553/b1553brm.c
|
||||
EXTRA_DIST += shared/1553/b1553rt.c
|
||||
EXTRA_DIST += shared/include/b1553brm.h
|
||||
EXTRA_DIST += shared/include/b1553rt.h
|
||||
|
||||
# MIL-STD-B1553 (GR1553B)
|
||||
EXTRA_DIST += shared/1553/gr1553b.c
|
||||
EXTRA_DIST += shared/1553/gr1553bc.c
|
||||
EXTRA_DIST += shared/1553/gr1553bm.c
|
||||
EXTRA_DIST += shared/1553/gr1553rt.c
|
||||
EXTRA_DIST += shared/include/gr1553b.h
|
||||
EXTRA_DIST += shared/include/gr1553bc.h
|
||||
EXTRA_DIST += shared/include/gr1553bc_list.h
|
||||
EXTRA_DIST += shared/include/gr1553bm.h
|
||||
EXTRA_DIST += shared/include/gr1553rt.h
|
||||
|
||||
# I2C-master (I2CMST)
|
||||
EXTRA_DIST += shared/i2c/i2cmst.c
|
||||
EXTRA_DIST += shared/include/i2cmst.h
|
||||
|
||||
# SPI
|
||||
EXTRA_DIST += shared/spi/spictrl.c
|
||||
EXTRA_DIST += shared/include/spictrl.h
|
||||
|
||||
# TIME
|
||||
EXTRA_DIST += shared/time/spwcuc.c
|
||||
EXTRA_DIST += shared/time/grctm.c
|
||||
EXTRA_DIST += shared/include/spwcuc.h
|
||||
EXTRA_DIST += shared/include/grctm.h
|
||||
|
||||
# GPIO
|
||||
EXTRA_DIST += shared/gpio/grgpio.c
|
||||
EXTRA_DIST += shared/gpio/gpiolib.c
|
||||
EXTRA_DIST += shared/include/grgpio.h
|
||||
EXTRA_DIST += shared/include/gpiolib.h
|
||||
|
||||
# PWM
|
||||
EXTRA_DIST += shared/pwm/grpwm.c
|
||||
EXTRA_DIST += shared/include/grpwm.h
|
||||
|
||||
# ADC and DAC
|
||||
EXTRA_DIST += shared/analog/gradcdac.c
|
||||
EXTRA_DIST += shared/include/gradcdac.h
|
||||
|
||||
# GRETH
|
||||
EXTRA_DIST += shared/net/greth.c
|
||||
EXTRA_DIST += shared/include/greth.h
|
||||
|
||||
# Network configuration
|
||||
EXTRA_DIST += shared/net/network_interface_add.c
|
||||
EXTRA_DIST += shared/include/network_interface_add.h
|
||||
@@ -96,6 +146,19 @@ EXTRA_DIST += shared/drvmgr/leon2_amba_bus.c
|
||||
EXTRA_DIST += shared/include/drvmgr/ambapp_bus_grlib.h
|
||||
EXTRA_DIST += shared/include/drvmgr/ambapp_bus.h
|
||||
EXTRA_DIST += shared/include/drvmgr/leon2_amba_bus.h
|
||||
# GR712
|
||||
EXTRA_DIST += shared/ascs/grascs.c
|
||||
EXTRA_DIST += shared/include/grascs.h
|
||||
EXTRA_DIST += shared/can/satcan.c
|
||||
EXTRA_DIST += shared/include/satcan.h
|
||||
EXTRA_DIST += shared/slink/grslink.c
|
||||
EXTRA_DIST += shared/include/grslink.h
|
||||
|
||||
# TMTC
|
||||
EXTRA_DIST += shared/tmtc/grtc.c
|
||||
EXTRA_DIST += shared/include/grtc.h
|
||||
EXTRA_DIST += shared/tmtc/grtm.c
|
||||
EXTRA_DIST += shared/include/grtm.h
|
||||
|
||||
include $(top_srcdir)/../../../automake/subdirs.am
|
||||
include $(top_srcdir)/../../../automake/local.am
|
||||
|
||||
@@ -58,6 +58,8 @@ libbsp_a_SOURCES += console/console.c console/debugputs.c
|
||||
libbsp_a_SOURCES += clock/ckinit.c
|
||||
libbsp_a_SOURCES += ../../shared/clockdrv_shell.h
|
||||
# IRQ
|
||||
include_HEADERS += ../../sparc/shared/include/genirq.h
|
||||
libbsp_a_SOURCES += ../../sparc/shared/irq/genirq.c
|
||||
include_bsp_HEADERS += \
|
||||
../../shared/include/irq-generic.h \
|
||||
../../shared/include/irq-info.h \
|
||||
@@ -76,6 +78,7 @@ libbsp_a_SOURCES += \
|
||||
include_HEADERS += ../../sparc/shared/include/ambapp.h
|
||||
include_HEADERS += ../../sparc/shared/include/ambapp_ids.h
|
||||
include_HEADERS += ../../sparc/shared/include/grlib.h
|
||||
include_HEADERS += ../../sparc/shared/include/ahbstat.h
|
||||
libbsp_a_SOURCES += ../../sparc/shared/amba/ambapp.c
|
||||
libbsp_a_SOURCES += ../../sparc/shared/amba/ambapp_alloc.c
|
||||
libbsp_a_SOURCES += ../../sparc/shared/amba/ambapp_count.c
|
||||
@@ -86,6 +89,7 @@ libbsp_a_SOURCES += ../../sparc/shared/amba/ambapp_parent.c
|
||||
libbsp_a_SOURCES += ../../sparc/shared/amba/ambapp_old.c
|
||||
libbsp_a_SOURCES += ../../sparc/shared/amba/ambapp_names.c
|
||||
libbsp_a_SOURCES += ../../sparc/shared/amba/ambapp_show.c
|
||||
libbsp_a_SOURCES += ../../sparc/shared/amba/ahbstat.c
|
||||
|
||||
# Clock Driver and Timer Library
|
||||
include_HEADERS += ../../sparc/shared/include/tlib.h
|
||||
@@ -114,7 +118,20 @@ libbsp_a_SOURCES += ../../sparc/shared/pci/gr_rasta_tmtc.c
|
||||
|
||||
# B1553BRM
|
||||
include_HEADERS += ../../sparc/shared/include/b1553brm.h
|
||||
include_HEADERS += ../../sparc/shared/include/b1553rt.h
|
||||
libbsp_a_SOURCES += ../../sparc/shared/1553/b1553brm.c
|
||||
libbsp_a_SOURCES += ../../sparc/shared/1553/b1553rt.c
|
||||
|
||||
# GR1553B
|
||||
include_HEADERS += ../../sparc/shared/include/gr1553b.h
|
||||
include_HEADERS += ../../sparc/shared/include/gr1553bc.h
|
||||
include_HEADERS += ../../sparc/shared/include/gr1553bc_list.h
|
||||
include_HEADERS += ../../sparc/shared/include/gr1553bm.h
|
||||
include_HEADERS += ../../sparc/shared/include/gr1553rt.h
|
||||
libbsp_a_SOURCES += ../../sparc/shared/1553/gr1553b.c
|
||||
libbsp_a_SOURCES += ../../sparc/shared/1553/gr1553bc.c
|
||||
libbsp_a_SOURCES += ../../sparc/shared/1553/gr1553bm.c
|
||||
libbsp_a_SOURCES += ../../sparc/shared/1553/gr1553rt.c
|
||||
|
||||
# CAN
|
||||
include_HEADERS += ../../sparc/shared/include/occan.h
|
||||
@@ -124,7 +141,9 @@ libbsp_a_SOURCES += ../../sparc/shared/can/occan.c \
|
||||
|
||||
# SpaceWire
|
||||
include_HEADERS += ../../sparc/shared/include/grspw.h
|
||||
include_HEADERS += ../../sparc/shared/include/grspw_router.h
|
||||
libbsp_a_SOURCES += ../../sparc/shared/spw/grspw.c
|
||||
libbsp_a_SOURCES += ../../sparc/shared/spw/grspw_router.c
|
||||
|
||||
# UART (RAW)
|
||||
include_HEADERS += ../../sparc/shared/include/apbuart.h
|
||||
@@ -134,9 +153,42 @@ libbsp_a_SOURCES += ../../sparc/shared/uart/apbuart.c
|
||||
include_HEADERS += ../../sparc/shared/include/i2cmst.h
|
||||
libbsp_a_SOURCES += ../../sparc/shared/i2c/i2cmst.c
|
||||
|
||||
# SPI
|
||||
include_HEADERS += ../../sparc/shared/include/spictrl.h
|
||||
libbsp_a_SOURCES += ../../sparc/shared/spi/spictrl.c
|
||||
|
||||
# TIME
|
||||
include_HEADERS += ../../sparc/shared/include/spwcuc.h
|
||||
include_HEADERS += ../../sparc/shared/include/grctm.h
|
||||
libbsp_a_SOURCES += ../../sparc/shared/time/spwcuc.c
|
||||
libbsp_a_SOURCES += ../../sparc/shared/time/grctm.c
|
||||
|
||||
# GPIO
|
||||
include_HEADERS += ../../sparc/shared/include/grgpio.h
|
||||
include_HEADERS += ../../sparc/shared/include/gpiolib.h
|
||||
libbsp_a_SOURCES += ../../sparc/shared/gpio/grgpio.c
|
||||
libbsp_a_SOURCES += ../../sparc/shared/gpio/gpiolib.c
|
||||
|
||||
# PWM
|
||||
include_HEADERS += ../../sparc/shared/include/grpwm.h
|
||||
libbsp_a_SOURCES += ../../sparc/shared/pwm/grpwm.c
|
||||
|
||||
# ADC and DAC
|
||||
include_HEADERS += ../../sparc/shared/include/gradcdac.h
|
||||
libbsp_a_SOURCES += ../../sparc/shared/analog/gradcdac.c
|
||||
|
||||
# Memory controllers
|
||||
libbsp_a_SOURCES += ../../sparc/shared/mem/mctrl.c
|
||||
|
||||
# timer
|
||||
libbsp_a_SOURCES += timer/timer.c
|
||||
|
||||
# TM/TC
|
||||
include_HEADERS += ../../sparc/shared/include/grtc.h
|
||||
include_HEADERS += ../../sparc/shared/include/grtm.h
|
||||
libbsp_a_SOURCES += ../../sparc/shared/tmtc/grtc.c
|
||||
libbsp_a_SOURCES += ../../sparc/shared/tmtc/grtm.c
|
||||
|
||||
# Driver Manager
|
||||
include_drvmgrdir = $(includedir)/drvmgr
|
||||
include_drvmgr_HEADERS = ../../sparc/shared/include/drvmgr/ambapp_bus.h
|
||||
@@ -166,6 +218,14 @@ leon_open_eth_rel_CPPFLAGS += -D__INSIDE_RTEMS_BSD_TCPIP_STACK__
|
||||
leon_open_eth_rel_LDFLAGS = $(RTEMS_RELLDFLAGS)
|
||||
endif
|
||||
|
||||
if HAS_NETWORKING
|
||||
noinst_PROGRAMS += leon_greth.rel
|
||||
leon_greth_rel_SOURCES = ../../sparc/shared/net/greth.c
|
||||
include_HEADERS += ../../sparc/shared/include/greth.h
|
||||
leon_greth_rel_CPPFLAGS = $(AM_CPPFLAGS)
|
||||
leon_greth_rel_CPPFLAGS += -D__INSIDE_RTEMS_BSD_TCPIP_STACK__
|
||||
leon_greth_rel_LDFLAGS = $(RTEMS_RELLDFLAGS)
|
||||
|
||||
# BSP Network configuration
|
||||
include_HEADERS += ../../sparc/shared/include/network_interface_add.h
|
||||
libbsp_a_SOURCES += ../../sparc/shared/net/network_interface_add.c
|
||||
@@ -178,6 +238,7 @@ libbsp_a_LIBADD = \
|
||||
../../../libcpu/@RTEMS_CPU@/syscall.rel
|
||||
|
||||
if HAS_NETWORKING
|
||||
libbsp_a_LIBADD += leon_greth.rel
|
||||
libbsp_a_LIBADD += leon_open_eth.rel
|
||||
libbsp_a_LIBADD += leon_smc91111.rel
|
||||
endif
|
||||
|
||||
@@ -227,6 +227,7 @@ int cchip1_register(void);
|
||||
*/
|
||||
#define AMBAPPBUS_INFO_AVAIL /* AMBAPP Bus driver */
|
||||
#define GPTIMER_INFO_AVAIL /* GPTIMER Timer driver */
|
||||
#define GRETH_INFO_AVAIL /* GRETH Ethernet driver */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
||||
@@ -81,6 +81,10 @@ $(PROJECT_INCLUDE)/bsp/gnatcommon.h: ../shared/include/gnatcommon.h $(PROJECT_IN
|
||||
$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/bsp/gnatcommon.h
|
||||
PREINSTALL_FILES += $(PROJECT_INCLUDE)/bsp/gnatcommon.h
|
||||
|
||||
$(PROJECT_INCLUDE)/genirq.h: ../../sparc/shared/include/genirq.h $(PROJECT_INCLUDE)/$(dirstamp)
|
||||
$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/genirq.h
|
||||
PREINSTALL_FILES += $(PROJECT_INCLUDE)/genirq.h
|
||||
|
||||
$(PROJECT_INCLUDE)/bsp/irq-generic.h: ../../shared/include/irq-generic.h $(PROJECT_INCLUDE)/bsp/$(dirstamp)
|
||||
$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/bsp/irq-generic.h
|
||||
PREINSTALL_FILES += $(PROJECT_INCLUDE)/bsp/irq-generic.h
|
||||
@@ -105,6 +109,10 @@ $(PROJECT_INCLUDE)/grlib.h: ../../sparc/shared/include/grlib.h $(PROJECT_INCLUDE
|
||||
$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/grlib.h
|
||||
PREINSTALL_FILES += $(PROJECT_INCLUDE)/grlib.h
|
||||
|
||||
$(PROJECT_INCLUDE)/ahbstat.h: ../../sparc/shared/include/ahbstat.h $(PROJECT_INCLUDE)/$(dirstamp)
|
||||
$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/ahbstat.h
|
||||
PREINSTALL_FILES += $(PROJECT_INCLUDE)/ahbstat.h
|
||||
|
||||
$(PROJECT_INCLUDE)/tlib.h: ../../sparc/shared/include/tlib.h $(PROJECT_INCLUDE)/$(dirstamp)
|
||||
$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/tlib.h
|
||||
PREINSTALL_FILES += $(PROJECT_INCLUDE)/tlib.h
|
||||
@@ -133,6 +141,30 @@ $(PROJECT_INCLUDE)/b1553brm.h: ../../sparc/shared/include/b1553brm.h $(PROJECT_I
|
||||
$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/b1553brm.h
|
||||
PREINSTALL_FILES += $(PROJECT_INCLUDE)/b1553brm.h
|
||||
|
||||
$(PROJECT_INCLUDE)/b1553rt.h: ../../sparc/shared/include/b1553rt.h $(PROJECT_INCLUDE)/$(dirstamp)
|
||||
$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/b1553rt.h
|
||||
PREINSTALL_FILES += $(PROJECT_INCLUDE)/b1553rt.h
|
||||
|
||||
$(PROJECT_INCLUDE)/gr1553b.h: ../../sparc/shared/include/gr1553b.h $(PROJECT_INCLUDE)/$(dirstamp)
|
||||
$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/gr1553b.h
|
||||
PREINSTALL_FILES += $(PROJECT_INCLUDE)/gr1553b.h
|
||||
|
||||
$(PROJECT_INCLUDE)/gr1553bc.h: ../../sparc/shared/include/gr1553bc.h $(PROJECT_INCLUDE)/$(dirstamp)
|
||||
$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/gr1553bc.h
|
||||
PREINSTALL_FILES += $(PROJECT_INCLUDE)/gr1553bc.h
|
||||
|
||||
$(PROJECT_INCLUDE)/gr1553bc_list.h: ../../sparc/shared/include/gr1553bc_list.h $(PROJECT_INCLUDE)/$(dirstamp)
|
||||
$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/gr1553bc_list.h
|
||||
PREINSTALL_FILES += $(PROJECT_INCLUDE)/gr1553bc_list.h
|
||||
|
||||
$(PROJECT_INCLUDE)/gr1553bm.h: ../../sparc/shared/include/gr1553bm.h $(PROJECT_INCLUDE)/$(dirstamp)
|
||||
$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/gr1553bm.h
|
||||
PREINSTALL_FILES += $(PROJECT_INCLUDE)/gr1553bm.h
|
||||
|
||||
$(PROJECT_INCLUDE)/gr1553rt.h: ../../sparc/shared/include/gr1553rt.h $(PROJECT_INCLUDE)/$(dirstamp)
|
||||
$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/gr1553rt.h
|
||||
PREINSTALL_FILES += $(PROJECT_INCLUDE)/gr1553rt.h
|
||||
|
||||
$(PROJECT_INCLUDE)/occan.h: ../../sparc/shared/include/occan.h $(PROJECT_INCLUDE)/$(dirstamp)
|
||||
$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/occan.h
|
||||
PREINSTALL_FILES += $(PROJECT_INCLUDE)/occan.h
|
||||
@@ -145,6 +177,10 @@ $(PROJECT_INCLUDE)/grspw.h: ../../sparc/shared/include/grspw.h $(PROJECT_INCLUDE
|
||||
$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/grspw.h
|
||||
PREINSTALL_FILES += $(PROJECT_INCLUDE)/grspw.h
|
||||
|
||||
$(PROJECT_INCLUDE)/grspw_router.h: ../../sparc/shared/include/grspw_router.h $(PROJECT_INCLUDE)/$(dirstamp)
|
||||
$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/grspw_router.h
|
||||
PREINSTALL_FILES += $(PROJECT_INCLUDE)/grspw_router.h
|
||||
|
||||
$(PROJECT_INCLUDE)/apbuart.h: ../../sparc/shared/include/apbuart.h $(PROJECT_INCLUDE)/$(dirstamp)
|
||||
$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/apbuart.h
|
||||
PREINSTALL_FILES += $(PROJECT_INCLUDE)/apbuart.h
|
||||
@@ -153,6 +189,42 @@ $(PROJECT_INCLUDE)/i2cmst.h: ../../sparc/shared/include/i2cmst.h $(PROJECT_INCLU
|
||||
$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/i2cmst.h
|
||||
PREINSTALL_FILES += $(PROJECT_INCLUDE)/i2cmst.h
|
||||
|
||||
$(PROJECT_INCLUDE)/spictrl.h: ../../sparc/shared/include/spictrl.h $(PROJECT_INCLUDE)/$(dirstamp)
|
||||
$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/spictrl.h
|
||||
PREINSTALL_FILES += $(PROJECT_INCLUDE)/spictrl.h
|
||||
|
||||
$(PROJECT_INCLUDE)/spwcuc.h: ../../sparc/shared/include/spwcuc.h $(PROJECT_INCLUDE)/$(dirstamp)
|
||||
$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/spwcuc.h
|
||||
PREINSTALL_FILES += $(PROJECT_INCLUDE)/spwcuc.h
|
||||
|
||||
$(PROJECT_INCLUDE)/grctm.h: ../../sparc/shared/include/grctm.h $(PROJECT_INCLUDE)/$(dirstamp)
|
||||
$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/grctm.h
|
||||
PREINSTALL_FILES += $(PROJECT_INCLUDE)/grctm.h
|
||||
|
||||
$(PROJECT_INCLUDE)/grgpio.h: ../../sparc/shared/include/grgpio.h $(PROJECT_INCLUDE)/$(dirstamp)
|
||||
$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/grgpio.h
|
||||
PREINSTALL_FILES += $(PROJECT_INCLUDE)/grgpio.h
|
||||
|
||||
$(PROJECT_INCLUDE)/gpiolib.h: ../../sparc/shared/include/gpiolib.h $(PROJECT_INCLUDE)/$(dirstamp)
|
||||
$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/gpiolib.h
|
||||
PREINSTALL_FILES += $(PROJECT_INCLUDE)/gpiolib.h
|
||||
|
||||
$(PROJECT_INCLUDE)/grpwm.h: ../../sparc/shared/include/grpwm.h $(PROJECT_INCLUDE)/$(dirstamp)
|
||||
$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/grpwm.h
|
||||
PREINSTALL_FILES += $(PROJECT_INCLUDE)/grpwm.h
|
||||
|
||||
$(PROJECT_INCLUDE)/gradcdac.h: ../../sparc/shared/include/gradcdac.h $(PROJECT_INCLUDE)/$(dirstamp)
|
||||
$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/gradcdac.h
|
||||
PREINSTALL_FILES += $(PROJECT_INCLUDE)/gradcdac.h
|
||||
|
||||
$(PROJECT_INCLUDE)/grtc.h: ../../sparc/shared/include/grtc.h $(PROJECT_INCLUDE)/$(dirstamp)
|
||||
$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/grtc.h
|
||||
PREINSTALL_FILES += $(PROJECT_INCLUDE)/grtc.h
|
||||
|
||||
$(PROJECT_INCLUDE)/grtm.h: ../../sparc/shared/include/grtm.h $(PROJECT_INCLUDE)/$(dirstamp)
|
||||
$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/grtm.h
|
||||
PREINSTALL_FILES += $(PROJECT_INCLUDE)/grtm.h
|
||||
|
||||
$(PROJECT_INCLUDE)/drvmgr/$(dirstamp):
|
||||
@$(MKDIR_P) $(PROJECT_INCLUDE)/drvmgr
|
||||
@: > $(PROJECT_INCLUDE)/drvmgr/$(dirstamp)
|
||||
@@ -166,6 +238,11 @@ $(PROJECT_INCLUDE)/drvmgr/leon2_amba_bus.h: ../../sparc/shared/include/drvmgr/le
|
||||
$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/drvmgr/leon2_amba_bus.h
|
||||
PREINSTALL_FILES += $(PROJECT_INCLUDE)/drvmgr/leon2_amba_bus.h
|
||||
|
||||
if HAS_NETWORKING
|
||||
$(PROJECT_INCLUDE)/greth.h: ../../sparc/shared/include/greth.h $(PROJECT_INCLUDE)/$(dirstamp)
|
||||
$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/greth.h
|
||||
PREINSTALL_FILES += $(PROJECT_INCLUDE)/greth.h
|
||||
|
||||
$(PROJECT_INCLUDE)/network_interface_add.h: ../../sparc/shared/include/network_interface_add.h $(PROJECT_INCLUDE)/$(dirstamp)
|
||||
$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/network_interface_add.h
|
||||
PREINSTALL_FILES += $(PROJECT_INCLUDE)/network_interface_add.h
|
||||
|
||||
@@ -55,6 +55,7 @@ include_HEADERS += include/amba.h
|
||||
include_HEADERS += ../../sparc/shared/include/ambapp.h
|
||||
include_HEADERS += ../../sparc/shared/include/ambapp_ids.h
|
||||
include_HEADERS += ../../sparc/shared/include/grlib.h
|
||||
include_HEADERS += ../../sparc/shared/include/ahbstat.h
|
||||
libbsp_a_SOURCES += amba/amba.c
|
||||
libbsp_a_SOURCES += ../../sparc/shared/amba/ambapp.c
|
||||
libbsp_a_SOURCES += ../../sparc/shared/amba/ambapp_alloc.c
|
||||
@@ -66,6 +67,7 @@ libbsp_a_SOURCES += ../../sparc/shared/amba/ambapp_parent.c
|
||||
libbsp_a_SOURCES += ../../sparc/shared/amba/ambapp_old.c
|
||||
libbsp_a_SOURCES += ../../sparc/shared/amba/ambapp_names.c
|
||||
libbsp_a_SOURCES += ../../sparc/shared/amba/ambapp_show.c
|
||||
libbsp_a_SOURCES += ../../sparc/shared/amba/ahbstat.c
|
||||
|
||||
# Clock Driver and Timer Library
|
||||
include_HEADERS += ../../sparc/shared/include/tlib.h
|
||||
@@ -86,12 +88,14 @@ include_HEADERS += ../../sparc/shared/include/cons.h
|
||||
libbsp_a_SOURCES += console/printk_support.c
|
||||
|
||||
# IRQ
|
||||
include_HEADERS += ../../sparc/shared/include/genirq.h
|
||||
include_bsp_HEADERS += \
|
||||
../../shared/include/irq-generic.h \
|
||||
../../shared/include/irq-info.h \
|
||||
include/bsp/irq.h
|
||||
libbsp_a_SOURCES += \
|
||||
startup/eirq.c \
|
||||
../../sparc/shared/irq/genirq.c \
|
||||
../../sparc/shared/irq/irq-shared.c \
|
||||
../../sparc/shared/irq/bsp_isr_handler.c \
|
||||
../../shared/src/irq-default-handler.c \
|
||||
@@ -124,7 +128,20 @@ libbsp_a_SOURCES += ../../sparc/shared/pci/gr_tmtc_1553.c
|
||||
|
||||
# B1553BRM
|
||||
include_HEADERS += ../../sparc/shared/include/b1553brm.h
|
||||
include_HEADERS += ../../sparc/shared/include/b1553rt.h
|
||||
libbsp_a_SOURCES += ../../sparc/shared/1553/b1553brm.c
|
||||
libbsp_a_SOURCES += ../../sparc/shared/1553/b1553rt.c
|
||||
|
||||
# GR1553B
|
||||
include_HEADERS += ../../sparc/shared/include/gr1553b.h
|
||||
include_HEADERS += ../../sparc/shared/include/gr1553bc.h
|
||||
include_HEADERS += ../../sparc/shared/include/gr1553bc_list.h
|
||||
include_HEADERS += ../../sparc/shared/include/gr1553bm.h
|
||||
include_HEADERS += ../../sparc/shared/include/gr1553rt.h
|
||||
libbsp_a_SOURCES += ../../sparc/shared/1553/gr1553b.c
|
||||
libbsp_a_SOURCES += ../../sparc/shared/1553/gr1553bc.c
|
||||
libbsp_a_SOURCES += ../../sparc/shared/1553/gr1553bm.c
|
||||
libbsp_a_SOURCES += ../../sparc/shared/1553/gr1553rt.c
|
||||
|
||||
# CAN
|
||||
include_HEADERS += ../../sparc/shared/include/occan.h \
|
||||
@@ -134,7 +151,9 @@ libbsp_a_SOURCES += ../../sparc/shared/can/occan.c \
|
||||
|
||||
# SpaceWire
|
||||
include_HEADERS += ../../sparc/shared/include/grspw.h
|
||||
include_HEADERS += ../../sparc/shared/include/grspw_router.h
|
||||
libbsp_a_SOURCES += ../../sparc/shared/spw/grspw.c
|
||||
libbsp_a_SOURCES += ../../sparc/shared/spw/grspw_router.c
|
||||
|
||||
# UART
|
||||
include_HEADERS += ../../sparc/shared/include/apbuart.h \
|
||||
@@ -146,6 +165,33 @@ libbsp_a_SOURCES += ../../sparc/shared/uart/apbuart.c \
|
||||
include_HEADERS += ../../sparc/shared/include/i2cmst.h
|
||||
libbsp_a_SOURCES += ../../sparc/shared/i2c/i2cmst.c
|
||||
|
||||
# SPI
|
||||
include_HEADERS += ../../sparc/shared/include/spictrl.h
|
||||
libbsp_a_SOURCES += ../../sparc/shared/spi/spictrl.c
|
||||
|
||||
# TIME
|
||||
include_HEADERS += ../../sparc/shared/include/spwcuc.h
|
||||
include_HEADERS += ../../sparc/shared/include/grctm.h
|
||||
libbsp_a_SOURCES += ../../sparc/shared/time/spwcuc.c
|
||||
libbsp_a_SOURCES += ../../sparc/shared/time/grctm.c
|
||||
|
||||
# GPIO
|
||||
include_HEADERS += ../../sparc/shared/include/grgpio.h
|
||||
include_HEADERS += ../../sparc/shared/include/gpiolib.h
|
||||
libbsp_a_SOURCES += ../../sparc/shared/gpio/grgpio.c
|
||||
libbsp_a_SOURCES += ../../sparc/shared/gpio/gpiolib.c
|
||||
|
||||
# PWM
|
||||
include_HEADERS += ../../sparc/shared/include/grpwm.h
|
||||
libbsp_a_SOURCES += ../../sparc/shared/pwm/grpwm.c
|
||||
|
||||
# ADC and DAC
|
||||
include_HEADERS += ../../sparc/shared/include/gradcdac.h
|
||||
libbsp_a_SOURCES += ../../sparc/shared/analog/gradcdac.c
|
||||
|
||||
# Memory controllers
|
||||
libbsp_a_SOURCES += ../../sparc/shared/mem/mctrl.c
|
||||
|
||||
# timer
|
||||
libbsp_a_SOURCES += timer/timer.c
|
||||
libbsp_a_SOURCES += timer/watchdog.c
|
||||
@@ -156,6 +202,22 @@ libbsp_a_SOURCES += ../../../libcpu/shared/src/cache_manager.c
|
||||
libbsp_a_SOURCES += include/cache_.h
|
||||
libbsp_a_CPPFLAGS = -I$(srcdir)/include
|
||||
|
||||
# GR712
|
||||
include_HEADERS += ../../sparc/shared/include/grascs.h
|
||||
include_HEADERS += ../../sparc/shared/include/satcan.h
|
||||
include_HEADERS += ../../sparc/shared/include/canmux.h
|
||||
include_HEADERS += ../../sparc/shared/include/grslink.h
|
||||
libbsp_a_SOURCES += ../../sparc/shared/ascs/grascs.c
|
||||
libbsp_a_SOURCES += ../../sparc/shared/can/satcan.c
|
||||
libbsp_a_SOURCES += ../../sparc/shared/can/canmux.c
|
||||
libbsp_a_SOURCES += ../../sparc/shared/slink/grslink.c
|
||||
|
||||
# TM/TC
|
||||
include_HEADERS += ../../sparc/shared/include/grtc.h
|
||||
include_HEADERS += ../../sparc/shared/include/grtm.h
|
||||
libbsp_a_SOURCES += ../../sparc/shared/tmtc/grtc.c
|
||||
libbsp_a_SOURCES += ../../sparc/shared/tmtc/grtm.c
|
||||
|
||||
# Driver Manager
|
||||
include_drvmgrdir = $(includedir)/drvmgr
|
||||
include_drvmgr_HEADERS = ../../sparc/shared/include/drvmgr/ambapp_bus_grlib.h
|
||||
@@ -185,7 +247,9 @@ endif
|
||||
|
||||
if HAS_NETWORKING
|
||||
noinst_PROGRAMS += leon_greth.rel
|
||||
leon_greth_rel_SOURCES = leon_greth/leon_greth.c
|
||||
libbsp_a_SOURCES += leon_greth/leon_greth.c
|
||||
leon_greth_rel_SOURCES = ../../sparc/shared/net/greth.c
|
||||
include_HEADERS += ../../sparc/shared/include/greth.h
|
||||
leon_greth_rel_CPPFLAGS = $(AM_CPPFLAGS)
|
||||
leon_greth_rel_CPPFLAGS += -D__INSIDE_RTEMS_BSD_TCPIP_STACK__
|
||||
leon_greth_rel_LDFLAGS = $(RTEMS_RELLDFLAGS)
|
||||
|
||||
@@ -257,6 +257,7 @@ extern const unsigned char LEON3_irq_to_cpu[32];
|
||||
#define AMBAPPBUS_INFO_AVAIL /* AMBAPP Bus driver */
|
||||
#define APBUART_INFO_AVAIL /* APBUART Console driver */
|
||||
#define GPTIMER_INFO_AVAIL /* GPTIMER Timer driver */
|
||||
#define GRETH_INFO_AVAIL /* GRETH Ethernet driver */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
||||
@@ -105,6 +105,10 @@ $(PROJECT_INCLUDE)/grlib.h: ../../sparc/shared/include/grlib.h $(PROJECT_INCLUDE
|
||||
$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/grlib.h
|
||||
PREINSTALL_FILES += $(PROJECT_INCLUDE)/grlib.h
|
||||
|
||||
$(PROJECT_INCLUDE)/ahbstat.h: ../../sparc/shared/include/ahbstat.h $(PROJECT_INCLUDE)/$(dirstamp)
|
||||
$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/ahbstat.h
|
||||
PREINSTALL_FILES += $(PROJECT_INCLUDE)/ahbstat.h
|
||||
|
||||
$(PROJECT_INCLUDE)/tlib.h: ../../sparc/shared/include/tlib.h $(PROJECT_INCLUDE)/$(dirstamp)
|
||||
$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/tlib.h
|
||||
PREINSTALL_FILES += $(PROJECT_INCLUDE)/tlib.h
|
||||
@@ -113,6 +117,10 @@ $(PROJECT_INCLUDE)/cons.h: ../../sparc/shared/include/cons.h $(PROJECT_INCLUDE)/
|
||||
$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/cons.h
|
||||
PREINSTALL_FILES += $(PROJECT_INCLUDE)/cons.h
|
||||
|
||||
$(PROJECT_INCLUDE)/genirq.h: ../../sparc/shared/include/genirq.h $(PROJECT_INCLUDE)/$(dirstamp)
|
||||
$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/genirq.h
|
||||
PREINSTALL_FILES += $(PROJECT_INCLUDE)/genirq.h
|
||||
|
||||
$(PROJECT_INCLUDE)/bsp/irq-generic.h: ../../shared/include/irq-generic.h $(PROJECT_INCLUDE)/bsp/$(dirstamp)
|
||||
$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/bsp/irq-generic.h
|
||||
PREINSTALL_FILES += $(PROJECT_INCLUDE)/bsp/irq-generic.h
|
||||
@@ -153,6 +161,30 @@ $(PROJECT_INCLUDE)/b1553brm.h: ../../sparc/shared/include/b1553brm.h $(PROJECT_I
|
||||
$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/b1553brm.h
|
||||
PREINSTALL_FILES += $(PROJECT_INCLUDE)/b1553brm.h
|
||||
|
||||
$(PROJECT_INCLUDE)/b1553rt.h: ../../sparc/shared/include/b1553rt.h $(PROJECT_INCLUDE)/$(dirstamp)
|
||||
$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/b1553rt.h
|
||||
PREINSTALL_FILES += $(PROJECT_INCLUDE)/b1553rt.h
|
||||
|
||||
$(PROJECT_INCLUDE)/gr1553b.h: ../../sparc/shared/include/gr1553b.h $(PROJECT_INCLUDE)/$(dirstamp)
|
||||
$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/gr1553b.h
|
||||
PREINSTALL_FILES += $(PROJECT_INCLUDE)/gr1553b.h
|
||||
|
||||
$(PROJECT_INCLUDE)/gr1553bc.h: ../../sparc/shared/include/gr1553bc.h $(PROJECT_INCLUDE)/$(dirstamp)
|
||||
$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/gr1553bc.h
|
||||
PREINSTALL_FILES += $(PROJECT_INCLUDE)/gr1553bc.h
|
||||
|
||||
$(PROJECT_INCLUDE)/gr1553bc_list.h: ../../sparc/shared/include/gr1553bc_list.h $(PROJECT_INCLUDE)/$(dirstamp)
|
||||
$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/gr1553bc_list.h
|
||||
PREINSTALL_FILES += $(PROJECT_INCLUDE)/gr1553bc_list.h
|
||||
|
||||
$(PROJECT_INCLUDE)/gr1553bm.h: ../../sparc/shared/include/gr1553bm.h $(PROJECT_INCLUDE)/$(dirstamp)
|
||||
$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/gr1553bm.h
|
||||
PREINSTALL_FILES += $(PROJECT_INCLUDE)/gr1553bm.h
|
||||
|
||||
$(PROJECT_INCLUDE)/gr1553rt.h: ../../sparc/shared/include/gr1553rt.h $(PROJECT_INCLUDE)/$(dirstamp)
|
||||
$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/gr1553rt.h
|
||||
PREINSTALL_FILES += $(PROJECT_INCLUDE)/gr1553rt.h
|
||||
|
||||
$(PROJECT_INCLUDE)/occan.h: ../../sparc/shared/include/occan.h $(PROJECT_INCLUDE)/$(dirstamp)
|
||||
$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/occan.h
|
||||
PREINSTALL_FILES += $(PROJECT_INCLUDE)/occan.h
|
||||
@@ -165,6 +197,10 @@ $(PROJECT_INCLUDE)/grspw.h: ../../sparc/shared/include/grspw.h $(PROJECT_INCLUDE
|
||||
$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/grspw.h
|
||||
PREINSTALL_FILES += $(PROJECT_INCLUDE)/grspw.h
|
||||
|
||||
$(PROJECT_INCLUDE)/grspw_router.h: ../../sparc/shared/include/grspw_router.h $(PROJECT_INCLUDE)/$(dirstamp)
|
||||
$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/grspw_router.h
|
||||
PREINSTALL_FILES += $(PROJECT_INCLUDE)/grspw_router.h
|
||||
|
||||
$(PROJECT_INCLUDE)/apbuart.h: ../../sparc/shared/include/apbuart.h $(PROJECT_INCLUDE)/$(dirstamp)
|
||||
$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/apbuart.h
|
||||
PREINSTALL_FILES += $(PROJECT_INCLUDE)/apbuart.h
|
||||
@@ -177,10 +213,62 @@ $(PROJECT_INCLUDE)/i2cmst.h: ../../sparc/shared/include/i2cmst.h $(PROJECT_INCLU
|
||||
$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/i2cmst.h
|
||||
PREINSTALL_FILES += $(PROJECT_INCLUDE)/i2cmst.h
|
||||
|
||||
$(PROJECT_INCLUDE)/spictrl.h: ../../sparc/shared/include/spictrl.h $(PROJECT_INCLUDE)/$(dirstamp)
|
||||
$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/spictrl.h
|
||||
PREINSTALL_FILES += $(PROJECT_INCLUDE)/spictrl.h
|
||||
|
||||
$(PROJECT_INCLUDE)/spwcuc.h: ../../sparc/shared/include/spwcuc.h $(PROJECT_INCLUDE)/$(dirstamp)
|
||||
$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/spwcuc.h
|
||||
PREINSTALL_FILES += $(PROJECT_INCLUDE)/spwcuc.h
|
||||
|
||||
$(PROJECT_INCLUDE)/grctm.h: ../../sparc/shared/include/grctm.h $(PROJECT_INCLUDE)/$(dirstamp)
|
||||
$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/grctm.h
|
||||
PREINSTALL_FILES += $(PROJECT_INCLUDE)/grctm.h
|
||||
|
||||
$(PROJECT_INCLUDE)/grgpio.h: ../../sparc/shared/include/grgpio.h $(PROJECT_INCLUDE)/$(dirstamp)
|
||||
$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/grgpio.h
|
||||
PREINSTALL_FILES += $(PROJECT_INCLUDE)/grgpio.h
|
||||
|
||||
$(PROJECT_INCLUDE)/gpiolib.h: ../../sparc/shared/include/gpiolib.h $(PROJECT_INCLUDE)/$(dirstamp)
|
||||
$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/gpiolib.h
|
||||
PREINSTALL_FILES += $(PROJECT_INCLUDE)/gpiolib.h
|
||||
|
||||
$(PROJECT_INCLUDE)/grpwm.h: ../../sparc/shared/include/grpwm.h $(PROJECT_INCLUDE)/$(dirstamp)
|
||||
$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/grpwm.h
|
||||
PREINSTALL_FILES += $(PROJECT_INCLUDE)/grpwm.h
|
||||
|
||||
$(PROJECT_INCLUDE)/gradcdac.h: ../../sparc/shared/include/gradcdac.h $(PROJECT_INCLUDE)/$(dirstamp)
|
||||
$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/gradcdac.h
|
||||
PREINSTALL_FILES += $(PROJECT_INCLUDE)/gradcdac.h
|
||||
|
||||
$(PROJECT_INCLUDE)/watchdog.h: include/watchdog.h $(PROJECT_INCLUDE)/$(dirstamp)
|
||||
$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/watchdog.h
|
||||
PREINSTALL_FILES += $(PROJECT_INCLUDE)/watchdog.h
|
||||
|
||||
$(PROJECT_INCLUDE)/grascs.h: ../../sparc/shared/include/grascs.h $(PROJECT_INCLUDE)/$(dirstamp)
|
||||
$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/grascs.h
|
||||
PREINSTALL_FILES += $(PROJECT_INCLUDE)/grascs.h
|
||||
|
||||
$(PROJECT_INCLUDE)/satcan.h: ../../sparc/shared/include/satcan.h $(PROJECT_INCLUDE)/$(dirstamp)
|
||||
$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/satcan.h
|
||||
PREINSTALL_FILES += $(PROJECT_INCLUDE)/satcan.h
|
||||
|
||||
$(PROJECT_INCLUDE)/canmux.h: ../../sparc/shared/include/canmux.h $(PROJECT_INCLUDE)/$(dirstamp)
|
||||
$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/canmux.h
|
||||
PREINSTALL_FILES += $(PROJECT_INCLUDE)/canmux.h
|
||||
|
||||
$(PROJECT_INCLUDE)/grslink.h: ../../sparc/shared/include/grslink.h $(PROJECT_INCLUDE)/$(dirstamp)
|
||||
$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/grslink.h
|
||||
PREINSTALL_FILES += $(PROJECT_INCLUDE)/grslink.h
|
||||
|
||||
$(PROJECT_INCLUDE)/grtc.h: ../../sparc/shared/include/grtc.h $(PROJECT_INCLUDE)/$(dirstamp)
|
||||
$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/grtc.h
|
||||
PREINSTALL_FILES += $(PROJECT_INCLUDE)/grtc.h
|
||||
|
||||
$(PROJECT_INCLUDE)/grtm.h: ../../sparc/shared/include/grtm.h $(PROJECT_INCLUDE)/$(dirstamp)
|
||||
$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/grtm.h
|
||||
PREINSTALL_FILES += $(PROJECT_INCLUDE)/grtm.h
|
||||
|
||||
$(PROJECT_INCLUDE)/drvmgr/$(dirstamp):
|
||||
@$(MKDIR_P) $(PROJECT_INCLUDE)/drvmgr
|
||||
@: > $(PROJECT_INCLUDE)/drvmgr/$(dirstamp)
|
||||
@@ -194,6 +282,11 @@ $(PROJECT_INCLUDE)/drvmgr/ambapp_bus.h: ../../sparc/shared/include/drvmgr/ambapp
|
||||
$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/drvmgr/ambapp_bus.h
|
||||
PREINSTALL_FILES += $(PROJECT_INCLUDE)/drvmgr/ambapp_bus.h
|
||||
|
||||
if HAS_NETWORKING
|
||||
$(PROJECT_INCLUDE)/greth.h: ../../sparc/shared/include/greth.h $(PROJECT_INCLUDE)/$(dirstamp)
|
||||
$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/greth.h
|
||||
PREINSTALL_FILES += $(PROJECT_INCLUDE)/greth.h
|
||||
endif
|
||||
if HAS_NETWORKING
|
||||
$(PROJECT_INCLUDE)/network_interface_add.h: ../../sparc/shared/include/network_interface_add.h $(PROJECT_INCLUDE)/$(dirstamp)
|
||||
$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/network_interface_add.h
|
||||
|
||||
859
c/src/lib/libbsp/sparc/shared/1553/b1553rt.c
Normal file
859
c/src/lib/libbsp/sparc/shared/1553/b1553rt.c
Normal file
@@ -0,0 +1,859 @@
|
||||
/*
|
||||
* 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.com/license/LICENSE.
|
||||
*/
|
||||
|
||||
#include <bsp.h>
|
||||
#include <rtems/libio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
#include <ctype.h>
|
||||
#include <rtems/bspIo.h>
|
||||
|
||||
#include <drvmgr/drvmgr.h>
|
||||
#include <b1553rt.h>
|
||||
#include <ambapp.h>
|
||||
#include <drvmgr/ambapp_bus.h>
|
||||
|
||||
/* 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", KEY_TYPE_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 = (char *)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", KEY_TYPE_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;
|
||||
struct amba_dev_info *devinfo;
|
||||
|
||||
devinfo = (struct amba_dev_info *)pDev->dev->businfo;
|
||||
|
||||
/* 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;
|
||||
}
|
||||
}
|
||||
305
c/src/lib/libbsp/sparc/shared/1553/gr1553b.c
Normal file
305
c/src/lib/libbsp/sparc/shared/1553/gr1553b.c
Normal file
@@ -0,0 +1,305 @@
|
||||
/* 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.com/license/LICENSE.
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <drvmgr/ambapp_bus.h>
|
||||
|
||||
#include <gr1553b.h>
|
||||
|
||||
/* 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 */
|
||||
struct gr1553_device_feature *gr1553_bm_root = NULL;
|
||||
struct gr1553_device_feature *gr1553_rt_root = NULL;
|
||||
struct gr1553_device_feature *gr1553_bc_root = NULL;
|
||||
|
||||
/* Driver registered */
|
||||
int gr1553_driver_registerd = 0;
|
||||
|
||||
/* Add 'feat' to linked list pointed to by 'root'. A minor is also assigned. */
|
||||
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;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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;
|
||||
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.
|
||||
*/
|
||||
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;
|
||||
if ( ambadev == NULL ) {
|
||||
return DRVMGR_FAIL;
|
||||
}
|
||||
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);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
1674
c/src/lib/libbsp/sparc/shared/1553/gr1553bc.c
Normal file
1674
c/src/lib/libbsp/sparc/shared/1553/gr1553bc.c
Normal file
File diff suppressed because it is too large
Load Diff
519
c/src/lib/libbsp/sparc/shared/1553/gr1553bm.c
Normal file
519
c/src/lib/libbsp/sparc/shared/1553/gr1553bm.c
Normal file
@@ -0,0 +1,519 @@
|
||||
/* 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.com/license/LICENSE.
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <drvmgr/drvmgr.h>
|
||||
#include <drvmgr/ambapp_bus.h>
|
||||
|
||||
#include <gr1553b.h>
|
||||
#include <gr1553bm.h>
|
||||
|
||||
|
||||
#define GR1553BM_WRITE_MEM(adr, val) *(volatile uint32_t *)(adr) = (val)
|
||||
#define GR1553BM_READ_MEM(adr) (*(volatile uint32_t *)(adr))
|
||||
|
||||
#define GR1553BM_WRITE_REG(adr, val) *(volatile uint32_t *)(adr) = (val)
|
||||
#define GR1553BM_READ_REG(adr) (*(volatile uint32_t *)(adr))
|
||||
|
||||
#ifndef IRQ_GLOBAL_PREPARE
|
||||
#define IRQ_GLOBAL_PREPARE(level) rtems_interrupt_level level
|
||||
#endif
|
||||
|
||||
#ifndef IRQ_GLOBAL_DISABLE
|
||||
#define IRQ_GLOBAL_DISABLE(level) rtems_interrupt_disable(level)
|
||||
#endif
|
||||
|
||||
#ifndef IRQ_GLOBAL_ENABLE
|
||||
#define IRQ_GLOBAL_ENABLE(level) rtems_interrupt_enable(level)
|
||||
#endif
|
||||
|
||||
struct gr1553bm_priv {
|
||||
struct drvmgr_dev **pdev;
|
||||
struct gr1553b_regs *regs;
|
||||
|
||||
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)
|
||||
{
|
||||
IRQ_GLOBAL_PREPARE(oldLevel);
|
||||
|
||||
/* Enable IRQ source and mark running state */
|
||||
IRQ_GLOBAL_DISABLE(oldLevel);
|
||||
|
||||
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;
|
||||
|
||||
IRQ_GLOBAL_ENABLE(oldLevel);
|
||||
}
|
||||
|
||||
static void gr1553bm_hw_stop(struct gr1553bm_priv *priv)
|
||||
{
|
||||
IRQ_GLOBAL_PREPARE(oldLevel);
|
||||
|
||||
IRQ_GLOBAL_DISABLE(oldLevel);
|
||||
|
||||
/* 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;
|
||||
|
||||
IRQ_GLOBAL_ENABLE(oldLevel);
|
||||
}
|
||||
|
||||
/* 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;
|
||||
|
||||
/* 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);
|
||||
}
|
||||
}
|
||||
1256
c/src/lib/libbsp/sparc/shared/1553/gr1553rt.c
Normal file
1256
c/src/lib/libbsp/sparc/shared/1553/gr1553rt.c
Normal file
File diff suppressed because it is too large
Load Diff
206
c/src/lib/libbsp/sparc/shared/amba/ahbstat.c
Normal file
206
c/src/lib/libbsp/sparc/shared/amba/ahbstat.c
Normal file
@@ -0,0 +1,206 @@
|
||||
/* AHB Status register 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.com/license/LICENSE.
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include <drvmgr/drvmgr.h>
|
||||
#include <drvmgr/ambapp_bus.h>
|
||||
|
||||
#include <ahbstat.h>
|
||||
|
||||
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)
|
||||
|
||||
struct ahbstat_priv {
|
||||
struct drvmgr_dev *dev;
|
||||
struct ahbstat_regs *regs;
|
||||
int minor;
|
||||
uint32_t last_status;
|
||||
uint32_t last_address;
|
||||
};
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
/* Initialize hardware */
|
||||
priv->regs->status = 0;
|
||||
|
||||
/* Install IRQ handler */
|
||||
drvmgr_interrupt_register(dev, 0, "ahbstat", ahbstat_isr, priv);
|
||||
|
||||
return DRVMGR_OK;
|
||||
}
|
||||
|
||||
void ahbstat_isr(void *arg)
|
||||
{
|
||||
struct ahbstat_priv *priv = arg;
|
||||
uint32_t fadr, status;
|
||||
int rc;
|
||||
|
||||
/* Get hardware status */
|
||||
status = priv->regs->status;
|
||||
if ((status & AHBSTAT_STS_NE) == 0)
|
||||
return;
|
||||
|
||||
/* IRQ generated by AHBSTAT core... handle it here */
|
||||
|
||||
/* Get Failing address */
|
||||
fadr = priv->regs->failing;
|
||||
|
||||
priv->last_status = status;
|
||||
priv->last_address = fadr;
|
||||
|
||||
/* 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 reenable
|
||||
* 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 %lu by master %d"
|
||||
" 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 */
|
||||
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;
|
||||
|
||||
if (drvmgr_get_dev(&ahbstat_drv_info.general, minor, &dev)) {
|
||||
return -1;
|
||||
}
|
||||
priv = (struct ahbstat_priv *)dev->priv;
|
||||
|
||||
*status = priv->last_status;
|
||||
*address = priv->last_address;
|
||||
|
||||
return (priv->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;
|
||||
}
|
||||
578
c/src/lib/libbsp/sparc/shared/analog/gradcdac.c
Normal file
578
c/src/lib/libbsp/sparc/shared/analog/gradcdac.c
Normal file
@@ -0,0 +1,578 @@
|
||||
/* 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.com/license/LICENSE.
|
||||
*/
|
||||
|
||||
#include <rtems.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <drvmgr/drvmgr.h>
|
||||
#include <drvmgr/ambapp_bus.h>
|
||||
#include <gradcdac.h>
|
||||
|
||||
/****************** 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 <debug_defs.h>
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
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<<GRADCDAC_CFG_DACWS_BIT)&GRADCDAC_CFG_DACWS;
|
||||
|
||||
if ( cfg->wr_pol )
|
||||
config |= GRADCDAC_CFG_WRPOL;
|
||||
|
||||
config |= (cfg->dac_dw<<GRADCDAC_CFG_DACDW_BIT)&GRADCDAC_CFG_DACDW;
|
||||
|
||||
config |= (cfg->adc_ws<<GRADCDAC_CFG_ADCWS_BIT)&GRADCDAC_CFG_ADCWS;
|
||||
|
||||
if ( cfg->rc_pol )
|
||||
config |= GRADCDAC_CFG_RCPOL;
|
||||
|
||||
config |= (cfg->cs_mode<<GRADCDAC_CFG_CSMODE_BIT)&GRADCDAC_CFG_CSMODE;
|
||||
|
||||
if ( cfg->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<<GRADCDAC_CFG_TRIGMODE_BIT)&GRADCDAC_CFG_TRIGMODE;
|
||||
|
||||
config |= (cfg->adc_dw<<GRADCDAC_CFG_ADCDW_BIT)&GRADCDAC_CFG_ADCDW;
|
||||
|
||||
/* Write config */
|
||||
pDev->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;
|
||||
}
|
||||
615
c/src/lib/libbsp/sparc/shared/ascs/grascs.c
Normal file
615
c/src/lib/libbsp/sparc/shared/ascs/grascs.c
Normal file
@@ -0,0 +1,615 @@
|
||||
/* 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.com/license/LICENSE.
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <bsp.h>
|
||||
#include <ambapp.h>
|
||||
#include <grascs.h>
|
||||
|
||||
#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_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;
|
||||
}
|
||||
if(rtems_semaphore_create(rtems_build_name('A','S','C','2'),0,
|
||||
(RTEMS_FIFO|RTEMS_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;
|
||||
}
|
||||
197
c/src/lib/libbsp/sparc/shared/can/canmux.c
Normal file
197
c/src/lib/libbsp/sparc/shared/can/canmux.c
Normal file
@@ -0,0 +1,197 @@
|
||||
/*
|
||||
* 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.com/license/LICENSE.
|
||||
*/
|
||||
|
||||
#include <rtems/libio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <bsp.h>
|
||||
#include <rtems/bspIo.h> /* printk */
|
||||
|
||||
#include <canmux.h>
|
||||
#include <ambapp.h>
|
||||
|
||||
#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;
|
||||
}
|
||||
714
c/src/lib/libbsp/sparc/shared/can/satcan.c
Normal file
714
c/src/lib/libbsp/sparc/shared/can/satcan.c
Normal file
@@ -0,0 +1,714 @@
|
||||
/*
|
||||
* 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.com/license/LICENSE.
|
||||
*/
|
||||
|
||||
#include <rtems/libio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <bsp.h>
|
||||
#include <rtems/bspIo.h> /* printk */
|
||||
|
||||
#include <satcan.h>
|
||||
#include <ambapp.h>
|
||||
|
||||
#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;
|
||||
}
|
||||
265
c/src/lib/libbsp/sparc/shared/gpio/gpiolib.c
Normal file
265
c/src/lib/libbsp/sparc/shared/gpio/gpiolib.c
Normal file
@@ -0,0 +1,265 @@
|
||||
/* 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.com/license/LICENSE.
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <gpiolib.h>
|
||||
|
||||
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 */
|
||||
void gpiolib_list_add(struct gpiolib_port *port)
|
||||
{
|
||||
port->next = gpiolib_ports;
|
||||
gpiolib_ports = port;
|
||||
}
|
||||
|
||||
struct gpiolib_port *gpiolib_find(int minor)
|
||||
{
|
||||
struct gpiolib_port *p;
|
||||
|
||||
p = gpiolib_ports;
|
||||
while ( p && (p->minor != minor) ) {
|
||||
p = p->next;
|
||||
}
|
||||
return p;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
void gpiolib_list_remove(struct gpiolib_port *port)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
/*** Initialization ***/
|
||||
int gpiolib_initialize(void)
|
||||
{
|
||||
if ( gpiolib_initied != 0 )
|
||||
return 0;
|
||||
|
||||
/* Initialize Libarary */
|
||||
port_nr = 0;
|
||||
gpiolib_ports = 0;
|
||||
gpiolib_initied = 1;
|
||||
return 0;
|
||||
}
|
||||
437
c/src/lib/libbsp/sparc/shared/gpio/grgpio.c
Normal file
437
c/src/lib/libbsp/sparc/shared/gpio/grgpio.c
Normal file
@@ -0,0 +1,437 @@
|
||||
/* 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.com/license/LICENSE.
|
||||
*/
|
||||
|
||||
#include <bsp.h>
|
||||
#include <rtems/libio.h>
|
||||
#include <stdlib.h>
|
||||
#include <assert.h>
|
||||
#include <rtems/bspIo.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include <drvmgr/drvmgr.h>
|
||||
#include <drvmgr/ambapp_bus.h>
|
||||
#include <grgpio.h>
|
||||
#include <gpiolib.h>
|
||||
#include <ambapp.h>
|
||||
#include <grlib.h>
|
||||
|
||||
/*#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; port<priv->port_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 */
|
||||
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;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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<<portnr);
|
||||
|
||||
/* Return error when IRQ not supported by this I/O Line and it
|
||||
* is beeing enabled by user.
|
||||
*/
|
||||
if ( ((mask & priv->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;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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<<portnr;
|
||||
priv->regs->dir = (priv->regs->dir & ~mask) | (dir ? mask : 0);
|
||||
priv->regs->output = (priv->regs->output & ~mask) | (outval ? mask : 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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", KEY_TYPE_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)) == 0 )
|
||||
break;
|
||||
priv->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", KEY_TYPE_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;
|
||||
}
|
||||
73
c/src/lib/libbsp/sparc/shared/include/ahbstat.h
Normal file
73
c/src/lib/libbsp/sparc/shared/include/ahbstat.h
Normal file
@@ -0,0 +1,73 @@
|
||||
/* AHBSTAT driver interface
|
||||
*
|
||||
* 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.com/license/LICENSE.
|
||||
*/
|
||||
|
||||
#ifndef __AHBSTAT_H__
|
||||
#define __AHBSTAT_H__
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* AHBSTAT Registers layout */
|
||||
struct ahbstat_regs {
|
||||
volatile uint32_t status;
|
||||
volatile uint32_t failing;
|
||||
};
|
||||
|
||||
/* 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
|
||||
*/
|
||||
extern int (*ahbstat_error)(
|
||||
int minor,
|
||||
struct ahbstat_regs *regs,
|
||||
uint32_t status,
|
||||
uint32_t failing_address);
|
||||
|
||||
/* Get Last received AHB Error
|
||||
*
|
||||
* \param minor Index used to indentify a specific AHBSTAT core
|
||||
* \param status Status register at time of error IRQ was recevied
|
||||
* \param address Failing address register at time of error IRQ
|
||||
*
|
||||
* Return
|
||||
* 0: No error received
|
||||
* 1: Error Received, last status and address stored into argument pointers
|
||||
* -1: No such AHBSTAT device
|
||||
*/
|
||||
extern int ahbstat_last_error(int minor, uint32_t *status, uint32_t *address);
|
||||
|
||||
/* Get AHBSTAT registers address from minor. Can also be used to check if
|
||||
* AHBSTAT hardware is present.
|
||||
*
|
||||
* Return
|
||||
* NULL returned if no such device
|
||||
* non-zero Address to AHBSTAT register
|
||||
*/
|
||||
extern struct ahbstat_regs *ahbstat_get_regs(int minor);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
74
c/src/lib/libbsp/sparc/shared/include/b1553rt.h
Normal file
74
c/src/lib/libbsp/sparc/shared/include/b1553rt.h
Normal file
@@ -0,0 +1,74 @@
|
||||
/* B1553RT driver interface
|
||||
*
|
||||
* COPYRIGHT (c) 2009.
|
||||
* Aeroflex 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.com/license/LICENSE.
|
||||
*/
|
||||
|
||||
#ifndef __B1553RT_H__
|
||||
#define __B1553RT_H__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
struct rt_reg {
|
||||
volatile unsigned int stat; /* 0x00 */
|
||||
volatile unsigned int ctrl; /* 0x04 */
|
||||
volatile unsigned int vword; /* 0x08 */
|
||||
volatile unsigned int irq; /* 0x0C */
|
||||
volatile unsigned int addr; /* 0x10 */
|
||||
volatile unsigned int ipm; /* 0x14 */
|
||||
};
|
||||
|
||||
|
||||
struct rt_msg {
|
||||
unsigned short miw;
|
||||
unsigned short time;
|
||||
unsigned short data[32];
|
||||
unsigned short desc;
|
||||
};
|
||||
|
||||
#define RT_FREQ_12MHZ 0
|
||||
#define RT_FREQ_16MHZ 1
|
||||
#define RT_FREQ_20MHZ 2
|
||||
#define RT_FREQ_24MHZ 3
|
||||
#define RT_FREQ_MASK 0x3
|
||||
|
||||
/* IOCTLs */
|
||||
#define RT_SET_ADDR 3
|
||||
#define RT_SET_BCE 5
|
||||
#define RT_RX_BLOCK 8
|
||||
#define RT_CLR_STATUS 12
|
||||
#define RT_GET_STATUS 13
|
||||
#define RT_SET_EVENTID 14
|
||||
|
||||
#define RT_SET_VECTORW 32
|
||||
#define RT_SET_EXTMDATA 33
|
||||
|
||||
#define RT_ILLCMD_IRQ 128
|
||||
#define RT_MERR_IRQ 2048
|
||||
#define RT_DMAF_IRQ 32768 /* DMA Fail irq */
|
||||
|
||||
#define RT_TSW_OK (1<<14)
|
||||
#define RT_TSW_BUS (1<<13)
|
||||
#define RT_TSW_BC (1<<12)
|
||||
#define RT_TSW_LPBKERRB (1<<11)
|
||||
#define RT_TSW_LPBKERRA (1<<10)
|
||||
#define RT_TSW_ILL (1<<9)
|
||||
#define RT_TSW_MEM (1<<8)
|
||||
#define RT_TSW_MAN (1<<7)
|
||||
#define RT_TSW_PAR (1<<6)
|
||||
#define RT_TSW_WC (1<<5)
|
||||
|
||||
void b1553rt_register_drv(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __RT_H__ */
|
||||
|
||||
32
c/src/lib/libbsp/sparc/shared/include/canmux.h
Normal file
32
c/src/lib/libbsp/sparc/shared/include/canmux.h
Normal file
@@ -0,0 +1,32 @@
|
||||
/*
|
||||
* Header file for RTEMS CAN_MUX 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.com/license/LICENSE.
|
||||
*/
|
||||
|
||||
#ifndef __CANMUX_H__
|
||||
#define __CANMUX_H__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Driver interface */
|
||||
int canmux_register(void);
|
||||
|
||||
/* ioctl calls */
|
||||
#define CANMUX_IOC_BUSA_SATCAN 1
|
||||
#define CANMUX_IOC_BUSA_OCCAN1 2
|
||||
#define CANMUX_IOC_BUSB_SATCAN 3
|
||||
#define CANMUX_IOC_BUSB_OCCAN2 4
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __CANMUX_H__ */
|
||||
@@ -1,7 +1,7 @@
|
||||
/* General part of a AMBA Plug & Play bus driver.
|
||||
*
|
||||
* COPYRIGHT (c) 2008.
|
||||
* Cobham Gaisler AB
|
||||
* Cobham Gaisler AB.
|
||||
*
|
||||
* This is the general part of the different AMBA Plug & Play
|
||||
* drivers. The drivers are wrappers around this driver, making
|
||||
@@ -28,8 +28,36 @@ extern "C" {
|
||||
DRIVER_ID(DRVMGR_BUS_TYPE_AMBAPP, ((((vendor) & 0xff) << 16) | ((device) & 0xfff)))
|
||||
|
||||
/*** Gaisler Hardware Device Driver IDs ***/
|
||||
#define DRIVER_AMBAPP_GAISLER_APBUART_ID DRIVER_AMBAPP_ID(VENDOR_GAISLER, GAISLER_APBUART)
|
||||
#define DRIVER_AMBAPP_GAISLER_GPTIMER_ID DRIVER_AMBAPP_ID(VENDOR_GAISLER, GAISLER_GPTIMER)
|
||||
#define DRIVER_AMBAPP_GAISLER_AHBSTAT_ID DRIVER_AMBAPP_ID(VENDOR_GAISLER, GAISLER_AHBSTAT)
|
||||
#define DRIVER_AMBAPP_GAISLER_APBUART_ID DRIVER_AMBAPP_ID(VENDOR_GAISLER, GAISLER_APBUART)
|
||||
#define DRIVER_AMBAPP_GAISLER_B1553BRM_ID DRIVER_AMBAPP_ID(VENDOR_GAISLER, GAISLER_B1553BRM)
|
||||
#define DRIVER_AMBAPP_GAISLER_B1553RT_ID DRIVER_AMBAPP_ID(VENDOR_GAISLER, GAISLER_B1553RT)
|
||||
#define DRIVER_AMBAPP_GAISLER_GPTIMER_ID DRIVER_AMBAPP_ID(VENDOR_GAISLER, GAISLER_GPTIMER)
|
||||
#define DRIVER_AMBAPP_GAISLER_GR1553B_ID DRIVER_AMBAPP_ID(VENDOR_GAISLER, GAISLER_GR1553B)
|
||||
#define DRIVER_AMBAPP_GAISLER_GRADCDAC_ID DRIVER_AMBAPP_ID(VENDOR_GAISLER, GAISLER_GRADCDAC)
|
||||
#define DRIVER_AMBAPP_GAISLER_GRAES_ID DRIVER_AMBAPP_ID(VENDOR_GAISLER, GAISLER_GRAESDMA)
|
||||
#define DRIVER_AMBAPP_GAISLER_GRCAN_ID DRIVER_AMBAPP_ID(VENDOR_GAISLER, GAISLER_GRCAN)
|
||||
#define DRIVER_AMBAPP_GAISLER_GRCTM_ID DRIVER_AMBAPP_ID(VENDOR_GAISLER, GAISLER_GRCTM)
|
||||
#define DRIVER_AMBAPP_GAISLER_GRETH_ID DRIVER_AMBAPP_ID(VENDOR_GAISLER, GAISLER_ETHMAC)
|
||||
#define DRIVER_AMBAPP_GAISLER_GRGPIO_ID DRIVER_AMBAPP_ID(VENDOR_GAISLER, GAISLER_GPIO)
|
||||
#define DRIVER_AMBAPP_GAISLER_GRPCI2_ID DRIVER_AMBAPP_ID(VENDOR_GAISLER, GAISLER_GRPCI2)
|
||||
#define DRIVER_AMBAPP_GAISLER_GRPCI_ID DRIVER_AMBAPP_ID(VENDOR_GAISLER, GAISLER_PCIFBRG)
|
||||
#define DRIVER_AMBAPP_GAISLER_GRPWM_ID DRIVER_AMBAPP_ID(VENDOR_GAISLER, GAISLER_GRPWM)
|
||||
#define DRIVER_AMBAPP_GAISLER_GRPWRX_ID DRIVER_AMBAPP_ID(VENDOR_GAISLER, GAISLER_PW2APB)
|
||||
#define DRIVER_AMBAPP_GAISLER_GRSPW_ID DRIVER_AMBAPP_ID(VENDOR_GAISLER, GAISLER_SPW)
|
||||
#define DRIVER_AMBAPP_GAISLER_GRTC_ID DRIVER_AMBAPP_ID(VENDOR_GAISLER, GAISLER_GRTC)
|
||||
#define DRIVER_AMBAPP_GAISLER_GRTM_ID DRIVER_AMBAPP_ID(VENDOR_GAISLER, GAISLER_GRTM)
|
||||
#define DRIVER_AMBAPP_GAISLER_I2CMST_ID DRIVER_AMBAPP_ID(VENDOR_GAISLER, GAISLER_I2CMST)
|
||||
#define DRIVER_AMBAPP_GAISLER_OCCAN_ID DRIVER_AMBAPP_ID(VENDOR_GAISLER, GAISLER_CANAHB)
|
||||
#define DRIVER_AMBAPP_GAISLER_PCIF_ID DRIVER_AMBAPP_ID(VENDOR_GAISLER, GAISLER_PCIF)
|
||||
#define DRIVER_AMBAPP_GAISLER_PCITRACE_ID DRIVER_AMBAPP_ID(VENDOR_GAISLER, GAISLER_PCITRACE)
|
||||
#define DRIVER_AMBAPP_GAISLER_SPICTRL_ID DRIVER_AMBAPP_ID(VENDOR_GAISLER, GAISLER_SPICTRL)
|
||||
#define DRIVER_AMBAPP_GAISLER_SPWCUC_ID DRIVER_AMBAPP_ID(VENDOR_GAISLER, GAISLER_SPWCUC)
|
||||
#define DRIVER_AMBAPP_GAISLER_SPW_ROUTER_ID DRIVER_AMBAPP_ID(VENDOR_GAISLER, GAISLER_SPW_ROUTER)
|
||||
|
||||
/*** ESA Hardware Device Driver IDs ***/
|
||||
#define DRIVER_AMBAPP_ESA_MCTRL_ID DRIVER_AMBAPP_ID(VENDOR_ESA, ESA_MCTRL)
|
||||
#define DRIVER_AMBAPP_MCTRL_ID DRIVER_AMBAPP_ESA_MCTRL_ID
|
||||
|
||||
struct amba_dev_id {
|
||||
unsigned short vendor;
|
||||
|
||||
107
c/src/lib/libbsp/sparc/shared/include/genirq.h
Normal file
107
c/src/lib/libbsp/sparc/shared/include/genirq.h
Normal file
@@ -0,0 +1,107 @@
|
||||
/* General Shared Interrupt handling function interface
|
||||
*
|
||||
* The functions does not manipulate the IRQ controller or the
|
||||
* interrupt level of the CPU. It simply helps the caller with
|
||||
* managing shared interrupts where multiple interrupt routines
|
||||
* share on interrupt vector/number.
|
||||
*
|
||||
* 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.com/license/LICENSE.
|
||||
*/
|
||||
|
||||
#ifndef __GENIRQ_H__
|
||||
#define __GENIRQ_H__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef void (*genirq_handler)(void *arg);
|
||||
typedef void* genirq_t;
|
||||
|
||||
struct genirq_stats {
|
||||
unsigned int irq_cnt;
|
||||
};
|
||||
|
||||
/* Initialize the genirq interface. Must be the first function
|
||||
* called.
|
||||
*
|
||||
* Returns zero on success, otherwise failure.
|
||||
*/
|
||||
extern genirq_t genirq_init(int number_of_irqs);
|
||||
|
||||
/* Free the dynamically allocated memory that the genirq interface has
|
||||
* allocated.
|
||||
*
|
||||
* Returns zero on success, otherwise failure.
|
||||
*/
|
||||
extern void genirq_destroy(genirq_t d);
|
||||
|
||||
/* Check IRQ number validity
|
||||
*
|
||||
* Returns zero for valid IRQ numbers, -1 of invalid IRQ numbers.
|
||||
*/
|
||||
extern int genirq_check(genirq_t d, int irq);
|
||||
|
||||
/* Register shared interrupt handler.
|
||||
*
|
||||
* \param irq The interrupt number to register ISR on
|
||||
* \param isr The interrupt service routine called upon IRQ
|
||||
* \param arg The argument given to isr() when called.
|
||||
*
|
||||
* Return Values
|
||||
* -1 = Failed
|
||||
* 0 = Handler registered Successfully, first handler on this IRQ
|
||||
* 1 = Handler registered Successfully, _not_ first handler on this IRQ
|
||||
*/
|
||||
extern int genirq_register(genirq_t d, int irq, genirq_handler isr, void *arg);
|
||||
|
||||
/* Unregister an previous registered interrupt handler
|
||||
*
|
||||
* Return Values
|
||||
* -1 = ISR not registered before
|
||||
* 0 = ISR unregistered
|
||||
* 1 = Unable to unregister enabled ISR
|
||||
*/
|
||||
extern int genirq_unregister(genirq_t d, int irq, genirq_handler isr, void *arg);
|
||||
|
||||
/* Enables IRQ only for this isr[arg] combination. Records if this
|
||||
* is the first interrupt enable, only then must interrupts be enabled
|
||||
* on the interrupt controller.
|
||||
*
|
||||
* IRQs must be disabled before entering this function.
|
||||
*
|
||||
* Return values
|
||||
* -1 = Failure, for example isr[arg] not registered on this irq
|
||||
* 0 = IRQ must be enabled, it is the first IRQ handler to be enabled
|
||||
* 1 = IRQ has already been enabled, either by isr[arg] or by another handler
|
||||
*/
|
||||
extern int genirq_enable(genirq_t d, int irq, genirq_handler isr, void *arg);
|
||||
|
||||
/* Disables IRQ only for this isr[arg] combination. Records if this
|
||||
* is the only interrupt handler that is enabled on this IRQ, only then
|
||||
* must interrupts be disabled on the interrupt controller.
|
||||
*
|
||||
* IRQs must be disabled before entering this function.
|
||||
*
|
||||
* Return values
|
||||
* -1 = Failure, for example isr[arg] not registered on this irq
|
||||
* 0 = IRQ must be disabled, no ISR are enabled for this IRQ
|
||||
* 1 = ISR has already been disabled, or other ISRs are still enabled
|
||||
*/
|
||||
extern int genirq_disable(genirq_t d, int irq, genirq_handler isr, void *arg);
|
||||
|
||||
/* Must be called by user when an IRQ has fired, the argument 'irq'
|
||||
* is the IRQ number of the IRQ which was fired.
|
||||
*/
|
||||
extern void genirq_doirq(genirq_t d, int irq);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
90
c/src/lib/libbsp/sparc/shared/include/gpiolib.h
Normal file
90
c/src/lib/libbsp/sparc/shared/include/gpiolib.h
Normal file
@@ -0,0 +1,90 @@
|
||||
/* GPIO Library 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.com/license/LICENSE.
|
||||
*/
|
||||
|
||||
#ifndef __GPIOLIB_H__
|
||||
#define __GPIOLIB_H__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* GPIO Config of one GPIO port */
|
||||
struct gpiolib_config {
|
||||
char mask; /* 0=Masked/1=Unmasked IRQ */
|
||||
char irq_level; /* Edge or Level triggered IRQ */
|
||||
char irq_polarity; /* Polarity of IRQ */
|
||||
};
|
||||
|
||||
#define GPIOLIB_IRQ_EDGE 0
|
||||
#define GPIOLIB_IRQ_LEVEL 1
|
||||
|
||||
#define GPIOLIB_IRQ_POL_LOW 0
|
||||
#define GPIOLIB_IRQ_POL_HIGH 1
|
||||
|
||||
/* Libarary initialize function must be called befor any other */
|
||||
extern int gpiolib_initialize(void);
|
||||
|
||||
/*** User Interface ***/
|
||||
|
||||
extern void *gpiolib_open(int port);
|
||||
extern void *gpiolib_open_by_name(char *devName);
|
||||
extern void gpiolib_close(void *handle);
|
||||
|
||||
/* Show the current status one or all GPIO ports in the system.
|
||||
* Int port is port nunber, if port = -1 selects all ports.
|
||||
*
|
||||
* If port != -1, handle is used to get port.
|
||||
* If port != -1, handle == NULL, then port is used as port number
|
||||
*/
|
||||
extern void gpiolib_show(int port, void *handle);
|
||||
|
||||
extern int gpiolib_set_config(void *handle, struct gpiolib_config *cfg);
|
||||
extern int gpiolib_set(void *handle, int dir, int val);
|
||||
extern int gpiolib_get(void *handle, int *inval);
|
||||
extern int gpiolib_irq_clear(void *handle);
|
||||
extern int gpiolib_irq_enable(void *handle);
|
||||
extern int gpiolib_irq_disable(void *handle);
|
||||
extern int gpiolib_irq_force(void *handle);
|
||||
extern int gpiolib_irq_register(void *handle, void *func, void *arg);
|
||||
|
||||
/*** Driver Interface ***/
|
||||
|
||||
struct gpiolib_info {
|
||||
char devName[64];
|
||||
};
|
||||
|
||||
struct gpiolib_drv_ops {
|
||||
int (*config)(void *handle, struct gpiolib_config *cfg);
|
||||
int (*get)(void *handle, int *val);
|
||||
int (*irq_opts)(void *handle, unsigned int options);
|
||||
int (*irq_register)(void *handle, void *func, void *arg);
|
||||
int (*open)(void *handle);
|
||||
int (*set)(void *handle, int dir, int outval);
|
||||
int (*show)(void *handle);
|
||||
int (*get_info)(void *handle, struct gpiolib_info *pinfo);
|
||||
};
|
||||
|
||||
#define GPIOLIB_IRQ_ENABLE 0x01
|
||||
#define GPIOLIB_IRQ_DISABLE 0x02
|
||||
#define GPIOLIB_IRQ_CLEAR 0x04
|
||||
#define GPIOLIB_IRQ_FORCE 0x08
|
||||
|
||||
struct gpiolib_drv {
|
||||
struct gpiolib_drv_ops *ops;
|
||||
};
|
||||
|
||||
/* Register a GPIO port */
|
||||
extern int gpiolib_drv_register(struct gpiolib_drv *drv, void *handle);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
365
c/src/lib/libbsp/sparc/shared/include/gr1553b.h
Normal file
365
c/src/lib/libbsp/sparc/shared/include/gr1553b.h
Normal file
@@ -0,0 +1,365 @@
|
||||
/* 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.com/license/LICENSE.
|
||||
*
|
||||
* OVERVIEW
|
||||
* ========
|
||||
* This driver controls the GR1553B device regardless of interfaces supported
|
||||
* (BC, RT and/or BM). The device can be located at an on-chip AMBA or an
|
||||
* AMBA-over-PCI bus. This driver provides an interface for the BC, RT and BM
|
||||
* drivers to use. Since the different interfaces are accessed over the same
|
||||
* register interface on the same core, the other drivers must share a GR1553B
|
||||
* device. Any combination of interface functionality is supported, but the RT
|
||||
* and BC functionality can nnot be used simultaneously due to hardware
|
||||
* limitation.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __GR1553B_H__
|
||||
#define __GR1553B_H__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* The GR1553B registers */
|
||||
struct gr1553b_regs {
|
||||
/* Common Registers */
|
||||
volatile unsigned int irq; /* 0x00 IRQ register */
|
||||
volatile unsigned int imask; /* 0x04 IRQ enable mask */
|
||||
int unused0[(0x10-0x08)/4];
|
||||
volatile unsigned int hwcfg; /* 0x10 HW config register */
|
||||
|
||||
int unused1[(0x40-0x14)/4]; /* Padding */
|
||||
|
||||
/* BC Registers */
|
||||
volatile unsigned int bc_stat; /* 0x40 BC status */
|
||||
volatile unsigned int bc_ctrl; /* 0x44 BC Action register */
|
||||
volatile unsigned int bc_bd; /* 0x48 BC transfer list pointer */
|
||||
volatile unsigned int bc_abd; /* 0x4c BC async list pointer */
|
||||
volatile unsigned int bc_timer; /* 0x50 BC timer register */
|
||||
volatile unsigned int bc_wake; /* 0x54 BC wakeup control register */
|
||||
volatile unsigned int bc_irqptr;/* 0x58 BC transfer IRQ pointer */
|
||||
volatile unsigned int bc_busmsk;/* 0x5C BC per-RT bus mask register */
|
||||
|
||||
int unused2[(0x68-0x60)/4]; /* Padding */
|
||||
|
||||
volatile unsigned int bc_slot; /* 0x48 BC Current BD pointer */
|
||||
volatile unsigned int bc_aslot; /* 0x4c BC Current async BD pointer */
|
||||
|
||||
int unused3[(0x80-0x70)/4]; /* Padding */
|
||||
|
||||
/* RT Registers */
|
||||
volatile unsigned int rt_stat; /* 0x80 RT status */
|
||||
volatile unsigned int rt_cfg; /* 0x84 RT config register */
|
||||
volatile unsigned int rt_stat2; /* 0x88 RT bus status bits */
|
||||
volatile unsigned int rt_statw; /* 0x8c RT status words */
|
||||
volatile unsigned int rt_sync; /* 0x90 RT bus synchronize */
|
||||
volatile unsigned int rt_tab; /* 0x94 RT subaddress table base */
|
||||
volatile unsigned int rt_mcctrl;/* 0x98 RT valid mode code mask */
|
||||
int unused4[(0xa4-0x9c)/4];
|
||||
volatile unsigned int rt_ttag; /* 0xa4 RT time tag register */
|
||||
int unused5; /* 0xa8 RESERVED */
|
||||
volatile unsigned int rt_evsz; /* 0xac RT event log end pointer */
|
||||
volatile unsigned int rt_evlog; /* 0xb0 RT event log position */
|
||||
volatile unsigned int rt_evirq; /* 0xb4 RT event log IRQ position */
|
||||
|
||||
int unused6[(0xc0-0xb8)/4]; /* Padding */
|
||||
|
||||
/* BM Registers */
|
||||
volatile unsigned int bm_stat; /* 0xc0 BM status */
|
||||
volatile unsigned int bm_ctrl; /* 0xc4 BM control register */
|
||||
volatile unsigned int bm_adr; /* 0xc8 BM address filter */
|
||||
volatile unsigned int bm_subadr;/* 0xcc BM subaddress filter */
|
||||
volatile unsigned int bm_mc; /* 0xd0 BM mode code filter */
|
||||
volatile unsigned int bm_start; /* 0xd4 BM log start address */
|
||||
volatile unsigned int bm_end; /* 0xd8 BM log size/alignment mask */
|
||||
volatile unsigned int bm_pos; /* 0xdc BM log position */
|
||||
volatile unsigned int bm_ttag; /* 0xe0 BM time tag register */
|
||||
};
|
||||
|
||||
#define GR1553BC_KEY 0x15520000
|
||||
#define GR1553RT_KEY 0x15530000
|
||||
|
||||
/* IRQ Definitions */
|
||||
#define GR1553BC_IRQLOG_SIZE 64
|
||||
#define GR1553BC_IRQLOG_CNT (GR1553BC_IRQLOG_SIZE/sizeof(uint32_t))
|
||||
|
||||
/*** IRQ Flag Register ***/
|
||||
#define GR1553B_IRQ_BCEV_BIT 0
|
||||
#define GR1553B_IRQ_BCD_BIT 1
|
||||
#define GR1553B_IRQ_BCWK_BIT 2
|
||||
#define GR1553B_IRQ_RTEV_BIT 8
|
||||
#define GR1553B_IRQ_RTD_BIT 9
|
||||
#define GR1553B_IRQ_RTTE_BIT 10
|
||||
#define GR1553B_IRQ_BMD_BIT 16
|
||||
#define GR1553B_IRQ_BMTOF_BIT 17
|
||||
|
||||
#define GR1553B_IRQ_BCEV (1<<GR1553B_IRQ_BCEV_BIT)
|
||||
#define GR1553B_IRQ_BCD (1<<GR1553B_IRQ_BCD_BIT)
|
||||
#define GR1553B_IRQ_BCWK (1<<GR1553B_IRQ_BCWK_BIT)
|
||||
#define GR1553B_IRQ_RTEV (1<<GR1553B_IRQ_RTEV_BIT)
|
||||
#define GR1553B_IRQ_RTD (1<<GR1553B_IRQ_RTD_BIT)
|
||||
#define GR1553B_IRQ_RTTE (1<<GR1553B_IRQ_RTTE_BIT)
|
||||
#define GR1553B_IRQ_BMD (1<<GR1553B_IRQ_BMD_BIT)
|
||||
#define GR1553B_IRQ_BMTOF (1<<GR1553B_IRQ_BMTOF_BIT)
|
||||
|
||||
/*** IRQ Enable Register ***/
|
||||
#define GR1553B_IRQEN_BCEVE_BIT 0
|
||||
#define GR1553B_IRQEN_BCDE_BIT 1
|
||||
#define GR1553B_IRQEN_BCWKE_BIT 2
|
||||
#define GR1553B_IRQEN_RTEVE_BIT 8
|
||||
#define GR1553B_IRQEN_RTDE_BIT 9
|
||||
#define GR1553B_IRQEN_RTTEE_BIT 10
|
||||
#define GR1553B_IRQEN_BMDE_BIT 16
|
||||
#define GR1553B_IRQEN_BMTOE_BIT 17
|
||||
|
||||
#define GR1553B_IRQEN_BCEVE (1<<GR1553B_IRQEN_BCEVE_BIT)
|
||||
#define GR1553B_IRQEN_BCDE (1<<GR1553B_IRQEN_BCDE_BIT)
|
||||
#define GR1553B_IRQEN_BCWKE (1<<GR1553B_IRQEN_BCWKE_BIT)
|
||||
#define GR1553B_IRQEN_RTEVE (1<<GR1553B_IRQEN_RTEVE_BIT)
|
||||
#define GR1553B_IRQEN_RTDE (1<<GR1553B_IRQEN_RTDE_BIT)
|
||||
#define GR1553B_IRQEN_RTTEE (1<<GR1553B_IRQEN_RTTEE_BIT)
|
||||
#define GR1553B_IRQEN_BMDE (1<<GR1553B_IRQEN_BMDE_BIT)
|
||||
#define GR1553B_IRQEN_BMTOE (1<<GR1553B_IRQEN_BMTOE_BIT)
|
||||
|
||||
/*** BC Status Register ***/
|
||||
#define GR1553B_BC_STAT_SCST_BIT 0
|
||||
#define GR1553B_BC_STAT_SCADL_BIT 3
|
||||
#define GR1553B_BC_STAT_ASST_BIT 8
|
||||
#define GR1553B_BC_STAT_ASADL_BIT 11
|
||||
#define GR1553B_BC_STAT_BCSUP_BIT 31
|
||||
|
||||
#define GR1553B_BC_STAT_SCST (0x3<<GR1553B_BC_STAT_SCST_BIT)
|
||||
#define GR1553B_BC_STAT_SCADL (0x1f<<GR1553B_BC_STAT_SCADL_BIT)
|
||||
#define GR1553B_BC_STAT_ASST (0x3<<GR1553B_BC_STAT_ASST_BIT)
|
||||
#define GR1553B_BC_STAT_ASADL (0x1f<<GR1553B_BC_STAT_ASADL_BIT)
|
||||
#define GR1553B_BC_STAT_BCSUP (1<<GR1553B_BC_STAT_BCSUP_BIT)
|
||||
|
||||
/*** BC Action Register ***/
|
||||
#define GR1553B_BC_ACT_SCSRT_BIT 0
|
||||
#define GR1553B_BC_ACT_SCSUS_BIT 1
|
||||
#define GR1553B_BC_ACT_SCSTP_BIT 2
|
||||
#define GR1553B_BC_ACT_SETT_BIT 3
|
||||
#define GR1553B_BC_ACT_CLRT_BIT 4
|
||||
#define GR1553B_BC_ACT_ASSRT_BIT 8
|
||||
#define GR1553B_BC_ACT_ASSTP_BIT 9
|
||||
#define GR1553B_BC_ACT_BCKEY_BIT 16
|
||||
|
||||
#define GR1553B_BC_ACT_SCSRT (1<<GR1553B_BC_ACT_SCSRT_BIT)
|
||||
#define GR1553B_BC_ACT_SCSUS (1<<GR1553B_BC_ACT_SCSUS_BIT)
|
||||
#define GR1553B_BC_ACT_SCSTP (1<<GR1553B_BC_ACT_SCSTP_BIT)
|
||||
#define GR1553B_BC_ACT_SETT (1<<GR1553B_BC_ACT_SETT_BIT)
|
||||
#define GR1553B_BC_ACT_CLRT (1<<GR1553B_BC_ACT_CLRT_BIT)
|
||||
#define GR1553B_BC_ACT_ASSRT (1<<GR1553B_BC_ACT_ASSRT_BIT)
|
||||
#define GR1553B_BC_ACT_ASSTP (1<<GR1553B_BC_ACT_ASSTP_BIT)
|
||||
#define GR1553B_BC_ACT_BCKEY (0xffff<<GR1553B_BC_ACT_BCKEY_BIT)
|
||||
|
||||
/*** BC Timer Register ***/
|
||||
#define GR1553B_BC_TIMER_SCTM_BIT 0
|
||||
|
||||
#define GR1553B_BC_TIMER_SCTM (0xffffff<<GR1553B_BC_TIMER_SCTM_BIT)
|
||||
|
||||
/*** BC Wake-up control Register ***/
|
||||
#define GR1553B_BC_WAKE_TIME_BIT 0
|
||||
#define GR1553B_BC_WAKE_WKEN_BIT 31
|
||||
|
||||
#define GR1553B_BC_WAKE_TIME (0xffffff<<GR1553B_BC_WAKE_TIME_BIT)
|
||||
#define GR1553B_BC_WAKE_WKEN (1<GR1553B_BC_WAKE_WKEN_BIT)
|
||||
|
||||
/*** RT status Register ***/
|
||||
#define GR1553B_RT_STAT_RUN_BIT 0
|
||||
#define GR1553B_RT_STAT_SHDB_BIT 1
|
||||
#define GR1553B_RT_STAT_SHDA_BIT 2
|
||||
#define GR1553B_RT_STAT_ACT_BIT 3
|
||||
#define GR1553B_RT_STAT_RTSUP_BIT 31
|
||||
|
||||
#define GR1553B_RT_STAT_RUN (1<<GR1553B_RT_STAT_RUN_BIT)
|
||||
#define GR1553B_RT_STAT_SHDB (1<<GR1553B_RT_STAT_SHDB_BIT)
|
||||
#define GR1553B_RT_STAT_SHDA (1<<GR1553B_RT_STAT_SHDA_BIT)
|
||||
#define GR1553B_RT_STAT_ACT (1<<GR1553B_RT_STAT_ACT_BIT)
|
||||
#define GR1553B_RT_STAT_RTSUP (1<<GR1553B_RT_STAT_RTSUP_BIT)
|
||||
|
||||
|
||||
/*** RT Config Register ***/
|
||||
#define GR1553B_RT_CFG_RTEN_BIT 0
|
||||
#define GR1553B_RT_CFG_RTADDR_BIT 1
|
||||
#define GR1553B_RT_CFG_RTKEY_BIT 16
|
||||
|
||||
#define GR1553B_RT_CFG_RTEN (1<<GR1553B_RT_CFG_RTEN_BIT)
|
||||
#define GR1553B_RT_CFG_RTADDR (1<<GR1553B_RT_CFG_RTADDR_BIT)
|
||||
#define GR1553B_RT_CFG_RTKEY (0xffff<<GR1553B_RT_CFG_RTKEY_BIT)
|
||||
|
||||
/*** RT Bus Status Register ***/
|
||||
#define GR1553B_RT_STAT2_RTEN_BIT 0
|
||||
#define GR1553B_RT_STAT2_DBCA_BIT 1
|
||||
#define GR1553B_RT_STAT2_SSF_BIT 2
|
||||
#define GR1553B_RT_STAT2_BUSY_BIT 3
|
||||
#define GR1553B_RT_STAT2_SREQ_BIT 4
|
||||
|
||||
#define GR1553B_RT_STAT2_RTEN (1<<GR1553B_RT_STAT2_RTEN_BIT)
|
||||
#define GR1553B_RT_STAT2_DBCA (1<<GR1553B_RT_STAT2_DBCA_BIT)
|
||||
#define GR1553B_RT_STAT2_SSF (1<<GR1553B_RT_STAT2_SSF_BIT)
|
||||
#define GR1553B_RT_STAT2_BUSY (1<<GR1553B_RT_STAT2_BUSY_BIT)
|
||||
#define GR1553B_RT_STAT2_SREQ (1<<GR1553B_RT_STAT2_RTEN_BIT)
|
||||
|
||||
/*** RT Status Words Register ***/
|
||||
#define GR1553B_RT_STATW_VECW_BIT 0
|
||||
#define GR1553B_RT_STATW_BITW_BIT 16
|
||||
|
||||
#define GR1553B_RT_STATW_VECW (0xffff<<GR1553B_RT_STATW_VECW_BIT)
|
||||
#define GR1553B_RT_STATW_BITW (0xffff<<GR1553B_RT_STATW_BITW_BIT)
|
||||
|
||||
/*** RT Sync Register ***/
|
||||
#define GR1553B_RT_SYNC_SYD_BIT 0
|
||||
#define GR1553B_RT_SYNC_SYTM_BIT 16
|
||||
|
||||
#define GR1553B_RT_SYNC_SYD (0xffff<<GR1553B_RT_SYNC_SYD_BIT)
|
||||
#define GR1553B_RT_SYNC_SYTM (0xffff<<GR1553B_RT_SYNC_SYTM_BIT)
|
||||
|
||||
/*** RT Sub adress table Register ***/
|
||||
#define GR1553B_RT_TAB_SATB_BIT 0
|
||||
|
||||
#define GR1553B_RT_TAB_SATB (0xffff<<GR1553B_RT_TAB_SATB_BIT)
|
||||
|
||||
/*** RT Mode code control Register ***/
|
||||
#define GR1553B_RT_MCCTRL_S_BIT 0
|
||||
#define GR1553B_RT_MCCTRL_SB_BIT 2
|
||||
#define GR1553B_RT_MCCTRL_SD_BIT 4
|
||||
#define GR1553B_RT_MCCTRL_SDB_BIT 6
|
||||
#define GR1553B_RT_MCCTRL_TS_BIT 8
|
||||
#define GR1553B_RT_MCCTRL_TSB_BIT 10
|
||||
#define GR1553B_RT_MCCTRL_TVW_BIT 12
|
||||
#define GR1553B_RT_MCCTRL_TBW_BIT 14
|
||||
#define GR1553B_RT_MCCTRL_DBC_BIT 16
|
||||
#define GR1553B_RT_MCCTRL_IST_BIT 18
|
||||
#define GR1553B_RT_MCCTRL_ISTB_BIT 20
|
||||
#define GR1553B_RT_MCCTRL_ITF_BIT 22
|
||||
#define GR1553B_RT_MCCTRL_ITFB_BIT 24
|
||||
#define GR1553B_RT_MCCTRL_RRT_BIT 26
|
||||
#define GR1553B_RT_MCCTRL_RRTB_BIT 28
|
||||
|
||||
#define GR1553B_RT_MCCTRL_S (1<<GR1553B_RT_MCCTRL_S_BIT)
|
||||
#define GR1553B_RT_MCCTRL_SB (1<<GR1553B_RT_MCCTRL_SB_BIT)
|
||||
#define GR1553B_RT_MCCTRL_SD (1<<GR1553B_RT_MCCTRL_SD_BIT)
|
||||
#define GR1553B_RT_MCCTRL_SDB (1<<GR1553B_RT_MCCTRL_SDB_BIT)
|
||||
#define GR1553B_RT_MCCTRL_TS (1<<GR1553B_RT_MCCTRL_TS_BIT)
|
||||
#define GR1553B_RT_MCCTRL_TSB (1<<GR1553B_RT_MCCTRL_TSB_BIT)
|
||||
#define GR1553B_RT_MCCTRL_TVW (1<<GR1553B_RT_MCCTRL_TVW_BIT)
|
||||
#define GR1553B_RT_MCCTRL_TBW (1<<GR1553B_RT_MCCTRL_TBW_BIT)
|
||||
#define GR1553B_RT_MCCTRL_DBC (1<<GR1553B_RT_MCCTRL_DBC_BIT)
|
||||
#define GR1553B_RT_MCCTRL_IST (1<<GR1553B_RT_MCCTRL_IST_BIT)
|
||||
#define GR1553B_RT_MCCTRL_ISTB (1<<GR1553B_RT_MCCTRL_ISTB_BIT)
|
||||
#define GR1553B_RT_MCCTRL_ITF (1<<GR1553B_RT_MCCTRL_ITF_BIT)
|
||||
#define GR1553B_RT_MCCTRL_ITFB (1<<GR1553B_RT_MCCTRL_ITFB_BIT)
|
||||
#define GR1553B_RT_MCCTRL_RRT (1<<GR1553B_RT_MCCTRL_RRT_BIT)
|
||||
#define GR1553B_RT_MCCTRL_RRTB (1<<GR1553B_RT_MCCTRL_RRTB_BIT)
|
||||
|
||||
/*** RT Time Tag control Register ***/
|
||||
#define GR1553B_RT_TTAG_TVAL_BIT 0
|
||||
#define GR1553B_RT_TTAG_TRES_BIT 16
|
||||
|
||||
#define GR1553B_RT_TTAG_TVAL (0xffff<<GR1553B_RT_TTAG_TVAL_BIT)
|
||||
#define GR1553B_RT_TTAG_TRES (0xffff<<GR1553B_RT_TTAG_TRES_BIT)
|
||||
|
||||
/*** BM Control Register ***/
|
||||
#define GR1553B_BM_STAT_BMSUP_BIT 31
|
||||
|
||||
#define GR1553B_BM_STAT_BMSUP (1<<GR1553B_BM_STAT_BMSUP_BIT)
|
||||
|
||||
/*** BM Control Register ***/
|
||||
#define GR1553B_BM_CTRL_BMEN_BIT 0
|
||||
#define GR1553B_BM_CTRL_MANL_BIT 1
|
||||
#define GR1553B_BM_CTRL_UDWL_BIT 2
|
||||
#define GR1553B_BM_CTRL_IMCL_BIT 3
|
||||
|
||||
#define GR1553B_BM_CTRL_BMEN (1<<GR1553B_BM_CTRL_BMEN_BIT)
|
||||
#define GR1553B_BM_CTRL_MANL (1<<GR1553B_BM_CTRL_MANL_BIT)
|
||||
#define GR1553B_BM_CTRL_UDWL (1<<GR1553B_BM_CTRL_UDWL_BIT)
|
||||
#define GR1553B_BM_CTRL_IMCL (1<<GR1553B_BM_CTRL_IMCL_BIT)
|
||||
|
||||
/*** BM RT Mode code filter Register ***/
|
||||
#define GR1553B_BM_MC_S_BIT 0
|
||||
#define GR1553B_BM_MC_SB_BIT 1
|
||||
#define GR1553B_BM_MC_SD_BIT 2
|
||||
#define GR1553B_BM_MC_SDB_BIT 3
|
||||
#define GR1553B_BM_MC_TS_BIT 4
|
||||
#define GR1553B_BM_MC_TSB_BIT 5
|
||||
#define GR1553B_BM_MC_TVW_BIT 6
|
||||
#define GR1553B_BM_MC_TBW_BIT 7
|
||||
#define GR1553B_BM_MC_DBC_BIT 8
|
||||
#define GR1553B_BM_MC_IST_BIT 9
|
||||
#define GR1553B_BM_MC_ISTB_BIT 10
|
||||
#define GR1553B_BM_MC_ITF_BIT 11
|
||||
#define GR1553B_BM_MC_ITFB_BIT 12
|
||||
#define GR1553B_BM_MC_RRT_BIT 13
|
||||
#define GR1553B_BM_MC_RRTB_BIT 14
|
||||
#define GR1553B_BM_MC_TSW_BIT 15
|
||||
#define GR1553B_BM_MC_TLC_BIT 16
|
||||
#define GR1553B_BM_MC_STS_BIT 17
|
||||
#define GR1553B_BM_MC_STSB_BIT 18
|
||||
|
||||
#define GR1553B_BM_MC_S (1<<GR1553B_BM_MC_S_BIT)
|
||||
#define GR1553B_BM_MC_SB (1<<GR1553B_BM_MC_SB_BIT)
|
||||
#define GR1553B_BM_MC_SD (1<<GR1553B_BM_MC_SD_BIT)
|
||||
#define GR1553B_BM_MC_SDB (1<<GR1553B_BM_MC_SDB_BIT)
|
||||
#define GR1553B_BM_MC_TS (1<<GR1553B_BM_MC_TS_BIT)
|
||||
#define GR1553B_BM_MC_TSB (1<<GR1553B_BM_MC_TSB_BIT)
|
||||
#define GR1553B_BM_MC_TVW (1<<GR1553B_BM_MC_TVW_BIT)
|
||||
#define GR1553B_BM_MC_TBW (1<<GR1553B_BM_MC_TBW_BIT)
|
||||
#define GR1553B_BM_MC_DBC (1<<GR1553B_BM_MC_DBC_BIT)
|
||||
#define GR1553B_BM_MC_IST (1<<GR1553B_BM_MC_IST_BIT)
|
||||
#define GR1553B_BM_MC_ISTB (1<<GR1553B_BM_MC_ISTB_BIT)
|
||||
#define GR1553B_BM_MC_ITF (1<<GR1553B_BM_MC_ITF_BIT)
|
||||
#define GR1553B_BM_MC_ITFB (1<<GR1553B_BM_MC_ITFB_BIT)
|
||||
#define GR1553B_BM_MC_RRT (1<<GR1553B_BM_MC_RRT_BIT)
|
||||
#define GR1553B_BM_MC_RRTB (1<<GR1553B_BM_MC_RRTB_BIT)
|
||||
#define GR1553B_BM_MC_TSW (1<<GR1553B_BM_MC_TSW_BIT)
|
||||
#define GR1553B_BM_MC_TLC (1<<GR1553B_BM_MC_TLC_BIT)
|
||||
#define GR1553B_BM_MC_STS (1<<GR1553B_BM_MC_STS_BIT)
|
||||
#define GR1553B_BM_MC_STSB (1<<GR1553B_BM_MC_STSB_BIT)
|
||||
|
||||
/*** BM RT Mode code filter Register ***/
|
||||
#define GR1553B_BM_TTAG_VAL_BIT 0
|
||||
#define GR1553B_BM_TTAG_RES_BIT 24
|
||||
|
||||
#define GR1553B_BM_TTAG_VAL (0xffffff<<GR1553B_BM_TTAG_VAL_BIT)
|
||||
#define GR1553B_BM_TTAG_RES (0xff<<GR1553B_BM_TTAG_RES_BIT)
|
||||
|
||||
/* Register GR1553B driver */
|
||||
extern void gr1553_register(void);
|
||||
|
||||
/*** BC Device allocation ***/
|
||||
/* Allocate a BC device. Minor is assigned to a device in the order
|
||||
* they are registered to the driver.
|
||||
*/
|
||||
extern struct drvmgr_dev **gr1553_bc_open(int minor);
|
||||
/* Free a BC device previously allocated */
|
||||
extern void gr1553_bc_close(struct drvmgr_dev **dev);
|
||||
|
||||
/*** RT Device allocation ***/
|
||||
/* Allocate a BC device. Minor is assigned to a device in the order
|
||||
* they are registered to the driver.
|
||||
*/
|
||||
extern struct drvmgr_dev **gr1553_rt_open(int minor);
|
||||
/* Free a BC device previously allocated */
|
||||
extern void gr1553_rt_close(struct drvmgr_dev **dev);
|
||||
|
||||
/*** BM Device allocation ***/
|
||||
/* Allocate a BC device. Minor is assigned to a device in the order
|
||||
* they are registered to the driver.
|
||||
*/
|
||||
extern struct drvmgr_dev **gr1553_bm_open(int minor);
|
||||
/* Free a BC device previously allocated */
|
||||
extern void gr1553_bm_close(struct drvmgr_dev **dev);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __GR1553B_H__ */
|
||||
250
c/src/lib/libbsp/sparc/shared/include/gr1553bc.h
Normal file
250
c/src/lib/libbsp/sparc/shared/include/gr1553bc.h
Normal file
@@ -0,0 +1,250 @@
|
||||
/* 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.com/license/LICENSE.
|
||||
*
|
||||
* OVERVIEW
|
||||
* ========
|
||||
* This driver controls the BC device, located at an on-chip AMBA or an
|
||||
* AMBA-over-PCI bus. The driver operates the BC device and provides you
|
||||
* with interrupt services and core control. The driver start execution of
|
||||
* a synchronuos and/or an asynchronous BC descriptor List. The list contains
|
||||
* a descriptor table and a software description to make some operations
|
||||
* possible, for example translate descriptor-address into descriptor-number.
|
||||
*
|
||||
* BC descriptors are generated by the list API, available in gr1553bc_list.h.
|
||||
*
|
||||
* See gr1553bc_list.h for more information.
|
||||
*/
|
||||
|
||||
#ifndef __GR1553BC_H__
|
||||
#define __GR1553BC_H__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Forward declaration */
|
||||
struct gr1553bc_list;
|
||||
struct gr1553bc_major;
|
||||
struct gr1553bc_minor;
|
||||
struct gr1553bc_minor_cfg;
|
||||
struct gr1553bc_major_cfg;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#include <stdint.h>
|
||||
#include <gr1553bc_list.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Register GR1553B driver needed by BC driver */
|
||||
extern void gr1553bc_register(void);
|
||||
|
||||
/* A BC descriptor accessed as is */
|
||||
struct gr1553bc_bd_raw {
|
||||
volatile uint32_t words[4];
|
||||
};
|
||||
|
||||
/* A BC descriptor accessed as a transfer descriptor */
|
||||
struct gr1553bc_bd_tr {
|
||||
volatile uint32_t settings[2];
|
||||
volatile uint32_t dptr;
|
||||
volatile uint32_t status;
|
||||
};
|
||||
|
||||
/* A BC descriptor accessed as a conditional descriptor */
|
||||
struct gr1553bc_bd_cond {
|
||||
volatile uint32_t cond;
|
||||
volatile uint32_t bdptr;
|
||||
volatile uint32_t padding[2];
|
||||
};
|
||||
|
||||
/* A BC descriptor accessed any way */
|
||||
union gr1553bc_bd {
|
||||
struct gr1553bc_bd_raw raw;
|
||||
struct gr1553bc_bd_tr tr;
|
||||
struct gr1553bc_bd_cond cond;
|
||||
};
|
||||
|
||||
/* Current state of the BC hardware */
|
||||
struct gr1553bc_status {
|
||||
unsigned int status;
|
||||
unsigned int time;
|
||||
};
|
||||
|
||||
#define KEEP_TIMESLOT 0x10
|
||||
/* Initialize a BC descriptor. The words written is controllable by
|
||||
* the flags argument.
|
||||
*
|
||||
* flags:
|
||||
* bit[N=0..3]: 1 = set BD wordN according to argument wordN,
|
||||
* 0 = do not modify BD wordN
|
||||
*
|
||||
* If bit KEEP_TIMESLOT is set the time slot of word0 is preserved,
|
||||
* this bit only have an affect when the descriptor is a transfer
|
||||
* descriptor.
|
||||
*/
|
||||
extern void gr1553bc_bd_init(
|
||||
union gr1553bc_bd *bd,
|
||||
unsigned int flags,
|
||||
uint32_t word0,
|
||||
uint32_t word1,
|
||||
uint32_t word2,
|
||||
uint32_t word3
|
||||
);
|
||||
|
||||
/* Initialize a Transfer descriptor
|
||||
*
|
||||
* Arguments:
|
||||
* struct gr1553bc_bd_tr *bd
|
||||
* uint32_t setting0
|
||||
* uint32_t setting1
|
||||
* uint32_t data
|
||||
* uint32_t status
|
||||
*/
|
||||
#define gr1553bc_bd_tr_init(bd, set0, set1, data, status) \
|
||||
gr1553bc_bd_init((union gr1553bc_bd *)bd,\
|
||||
0xf, set0, set1, data, status)
|
||||
/* Initializa a Condition descriptor
|
||||
*
|
||||
* Arguments:
|
||||
* struct gr1553bc_bd_cond *bd
|
||||
* uint32_t cond
|
||||
* uint32_t jump_adr
|
||||
*/
|
||||
#define gr1553bc_bd_cond_init(bd, cond, jump_adr) \
|
||||
gr1553bc_bd_init((union gr1553bc_bd *)bd, \
|
||||
0xf, cond, jump_adr, 0, 0)
|
||||
|
||||
/* Size of a descriptor */
|
||||
#define GR1553BC_BD_SIZE sizeof(struct gr1553bc_bd_raw)
|
||||
|
||||
/* Alignment of a descriptor */
|
||||
#define GR1553BC_BD_ALIGN 16
|
||||
|
||||
/* End of list marker */
|
||||
#define GR1553BC_TR_EOL 0x80ffffff
|
||||
|
||||
#define GR1553BC_BD_TYPE 0x80000000
|
||||
|
||||
/* Condition descriptor bits */
|
||||
#define GR1553BC_UNCOND_JMP 0x820000ff
|
||||
#define GR1553BC_UNCOND_IRQ 0x860000ff
|
||||
#define GR1553BC_UNCOND_NOJMP 0x82000000
|
||||
|
||||
/* Transfer descriptor bits */
|
||||
#define GR1553BC_TR_DUMMY_0 0x00000000
|
||||
#define GR1553BC_TR_DUMMY_1 0x80000000
|
||||
|
||||
#define GR1553BC_TR_TIME 0x0000ffff
|
||||
|
||||
#define GR1553BC_TR_EXTTRIG 0x40000000
|
||||
|
||||
/* Take a GR1553BC hardware device identified by instance index (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.
|
||||
*/
|
||||
extern void *gr1553bc_open(int minor);
|
||||
|
||||
extern void gr1553bc_close(void *bc);
|
||||
|
||||
/* Stores Current Major/Minor frame number and the Slot number executing
|
||||
* into the location indicated by 'mid'. There may be two lists executing
|
||||
* in "parallel", the 'async' argument select for which list the MID is
|
||||
* looked up, the Syncronous (async=0) list or the Asynchronous (async=1)
|
||||
* list.
|
||||
*
|
||||
*/
|
||||
extern int gr1553bc_indication(void *bc, int async, int *mid);
|
||||
|
||||
/* Trigger external time sync by writing to the BC action register.
|
||||
* This may be good for debugging or if the time management is
|
||||
* implemented in software.
|
||||
*
|
||||
* if trig=0 the external trigger memory is cleared.
|
||||
* if trig!=0 the external trigger memory is set.
|
||||
*/
|
||||
extern void gr1553bc_ext_trig(void *bc, int trig);
|
||||
|
||||
/* Configure the GR1553BC driver */
|
||||
/*extern int gr1553bc_config(struct gr1553bc_config *cfg);*/
|
||||
|
||||
/* Start major frame processing. At least one list pointer must be
|
||||
* non-zero to affect BC operation. The BC communication is enabled
|
||||
* depending on list and Interrupts are enabled. This function can
|
||||
* be called multiple times.
|
||||
*
|
||||
* If a list is already executing it will be replaced with the new
|
||||
* list.
|
||||
*
|
||||
* list - Schedule Transfer List
|
||||
* list_async - Asynchronous list
|
||||
*/
|
||||
extern int gr1553bc_start
|
||||
(
|
||||
void *bc,
|
||||
struct gr1553bc_list *list,
|
||||
struct gr1553bc_list *list_async
|
||||
);
|
||||
|
||||
/* Pause GR1553B BC scheduled transfers.
|
||||
*
|
||||
* Does not affect asynchronous operation.
|
||||
*/
|
||||
extern int gr1553bc_pause(void *bc);
|
||||
|
||||
/* Restart GR1553B BC scheduled transfers, after being paused
|
||||
*
|
||||
* Does not affect asynchronous operation.
|
||||
*/
|
||||
extern int gr1553bc_restart(void *bc);
|
||||
|
||||
/* Stop BC transmission.
|
||||
*
|
||||
* OPTIONS
|
||||
* bit0 - 1=STOP schedule list
|
||||
* bit1 - 1=STOP asynchronous list
|
||||
*/
|
||||
extern int gr1553bc_stop(void *bc, int options);
|
||||
|
||||
/* Standard IRQ function setup. IRQ can be generated by condition descriptors
|
||||
* or by transfer descriptors or by errors.
|
||||
*
|
||||
* Condition descriptors are inserted into the list by user, each condition
|
||||
* may have a custom function and data assigned to it, see
|
||||
* gr1553bc_slot_irq_prepare(). IRQs generated by condition descriptors are
|
||||
* not handled by this function.
|
||||
*
|
||||
* Transfer descriptors can generate IRQ if enabled by user.
|
||||
*
|
||||
* IRQs generated by transfer descriptors or by BC errors (DMA error etc.)
|
||||
* is handled by this standard ISR handler.
|
||||
*/
|
||||
extern int gr1553bc_irq_setup
|
||||
(
|
||||
void *bc,
|
||||
bcirq_func_t func,
|
||||
void *data
|
||||
);
|
||||
|
||||
/* Get Current BC hardware state/status. The Status is stored into the
|
||||
* area pointed to by status. See "struct gr1553bc_status" for more
|
||||
* info.
|
||||
*/
|
||||
extern void gr1553bc_status(void *bc, struct gr1553bc_status *status);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __GR1553BC_H__ */
|
||||
707
c/src/lib/libbsp/sparc/shared/include/gr1553bc_list.h
Normal file
707
c/src/lib/libbsp/sparc/shared/include/gr1553bc_list.h
Normal file
@@ -0,0 +1,707 @@
|
||||
/*
|
||||
* GR1553B BC driver, Descriptor LIST handling
|
||||
*
|
||||
* 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.com/license/LICENSE.
|
||||
*/
|
||||
|
||||
#ifndef __GR1553BC_LIST_H__
|
||||
#define __GR1553BC_LIST_H__
|
||||
|
||||
/*!\file doc/gr1553bc_list.h
|
||||
* \brief GR1553B BC driver
|
||||
*
|
||||
* \section OVERVIEW
|
||||
*
|
||||
* The BC device driver can schedule synchronous and asynchronous lists
|
||||
* of descriptors. The list contains a descriptor table and a software
|
||||
* description to make some operations possible, for example translate
|
||||
* descriptor-address into descriptor-number.
|
||||
*
|
||||
* This is the LIST API. It provides functionality to create and manage
|
||||
* a BC descriptor list.
|
||||
*
|
||||
* A list is built up by the following build blocks:
|
||||
* - Major Frame (Consists of N Minor Frames)
|
||||
* - Minor Frame (Consists of up to 32 1553 Message Slots)
|
||||
* - Message Slot (Transfer/Condition BC descriptor)
|
||||
*
|
||||
* The user can configure lists with different configuration of number of
|
||||
* Major Frames, Minor Frame and messages slots within a Minor Frame. The
|
||||
* List manages a strait descriptor table (may be changed) and a Frame/Slot
|
||||
* tree in order to easily find it's way through all descriptor created.
|
||||
*
|
||||
* Each Minor frame consist of up to 32 message slot and 2 message slots
|
||||
* for time management and descriptor find operations. The list can manage
|
||||
* time slots per minor frame, for example a minor frame may be programmed
|
||||
* to take 8ms and when the user allocate a message slot within that Minor
|
||||
* frame the time spcified will be subtracted from the 8ms, and when the
|
||||
* message slot is freed the time will be returned to the Minor frame again.
|
||||
*
|
||||
* A Major, Minor and Message Slots are identified using a MID (Message-ID).
|
||||
* The MID is a way for the user to avoid using pointers are talk with the
|
||||
* list API in an easier way. For example a condition Slot that should jump
|
||||
* to a transfer slot can be created by knowing "MID and Jump-To-MID". When
|
||||
* allocating a Slot (with or without time) the user may specify a certain
|
||||
* Slot or a Minor frame, when a Minor frame is given then the API will find
|
||||
* a free Slot as early in the Minor Frame as possible and return it to the
|
||||
* user.
|
||||
*
|
||||
* A MID can be created using the macros:
|
||||
* GR1553BC_ID(major,minor,slot) - ID of a SLOT
|
||||
* GR1553BC_MINOR_ID(major,minor) - ID of a MINOR (Slot=0xff)
|
||||
* GR1553BC_MAJOR_ID(major) - ID of a Major (Minor=0xff,Slot=0xff)
|
||||
*
|
||||
* The typical approach create lists is in the following order:
|
||||
* -# gr1553bc_list_alloc(&list, MAJOR_CNT)
|
||||
* -# gr1553bc_list_config(list, &listcfg)
|
||||
* -# Create all Major Frames and Minor frame, for each major frame:
|
||||
* a) gr1553bc_major_alloc_skel(&major, &major_minor_cfg)
|
||||
* b) gr1553bc_list_set_major(list, &major, MAJOR_NUM)
|
||||
* -# link end Major Frames together:
|
||||
* a) gr1553bc_list_set_major(&major7, &major0) // Connect Major frames
|
||||
* -# gr1553bc_list_table_alloc() (Allocate Descriptor Table)
|
||||
* -# gr1553bc_list_table_build() (Build Descriptor Table from Majors/Minors)
|
||||
* -# Allocate and initialize Descriptors pre defined before starting:
|
||||
* -## gr1553bc_slot_alloc(list, &MID, TIME_REQUIRED, ..)
|
||||
* -## gr1553bc_slot_transfer(MID, ...)
|
||||
* -# START BC HARDWARE BY SHCDULING ABOVE LIST
|
||||
* -# Operate on List
|
||||
*
|
||||
*
|
||||
* \section bc_list_update Changing a scheduled BC list (during BC-runtime)
|
||||
*
|
||||
* One can use the INDICATION service to avoid modifying
|
||||
* a descriptor currently in use by the BC core. One can also in most cases
|
||||
* do descriptor initialization in three steps: Init Descriptor as Dummy
|
||||
* with and allocated time (often done before starting/scheduling list),
|
||||
* then modify transfer options and data-pointers, then clear the Dummy
|
||||
* bit in one atomic data store. This approach will avoid potential races
|
||||
* between software has hardware.
|
||||
*
|
||||
*
|
||||
* \section bc_memory_setup Custom Memory Setup
|
||||
*
|
||||
* For designs where dynamically memory is not an option, or the driver
|
||||
* is used on a AMBA-over-PCI bus (where malloc() does not work), the
|
||||
* API allows the user to provide custom addresses for descriptor table
|
||||
* and object descriptions (lists, major frames, minor frames). Custom
|
||||
* descriptor table is probably the most interesting thing for most, it
|
||||
* is setup with gr1553bc_list_table_alloc(list, CUSTOM_ADDRESS).
|
||||
*
|
||||
* Object descriptions are normally allocated during initialization
|
||||
* procedure by providing the API with a object configuration, for
|
||||
* example a Major Frame configuration enables the API to allocate
|
||||
* the software description of a Major Frame with all it's Minor frames.
|
||||
*
|
||||
*
|
||||
* \section major Major Frame
|
||||
*
|
||||
* Consists of multiple Minor frames. A Major frame may be connected/linked
|
||||
* with another Major frame, this will result in a Jump Slot from last
|
||||
* Minor frame in the first Major to the first Minor in the second Major.
|
||||
*
|
||||
*
|
||||
* \section minor Minor Frame
|
||||
*
|
||||
* Consists of up to 32 Message Slots. The services are Time-Management and
|
||||
* Slot allocation.
|
||||
*
|
||||
* Time-Management is optional.
|
||||
*
|
||||
* Time-Slot-Management can be enabled per Minor frame. A Minor frame can be
|
||||
* assigned a time in microseconds. The BC will not continue to the next
|
||||
* Minor frame until the time has passed. It is managed by adding an extra
|
||||
* Dummy Message Slot with the total minor frame time. Each time a message
|
||||
* Slot is allocated (with a certain time: Slot-Time) the Slot-Time will
|
||||
* be decremented from the total time of the Minor frame. This way the
|
||||
* sum of the Message Slot will always sum up to the total time of the
|
||||
* Minor configuration. When a message slot is freed, the Dymmy Message
|
||||
* Slot's Slot-Time is incremented with the freed Slot-Time.
|
||||
*
|
||||
* A Message Slot can be allocated by identifying a specific free Slot
|
||||
* by the MID (Message-ID) or by letting the API allocate the first free
|
||||
* Slot in the Minor Frame (Set MID Slot-ID to 0xff to identify Minor
|
||||
* Frame).
|
||||
*
|
||||
*
|
||||
* \section slot Message Slot
|
||||
*
|
||||
* The GR1553B BC core supports two Slot (Descriptor) Types:
|
||||
* - Transfer descriptor
|
||||
* - Condition descriptor (Jump, unconditional-IRQ)
|
||||
*
|
||||
* See the hardware manual for a detail description of a descriptor (Slot).
|
||||
*
|
||||
* The BC Core is unaware of lists, it steps through executing each
|
||||
* descriptor as the encountered, Conditionals resulting in jumps may
|
||||
* let us to create more complex arrangements of buffer descriptos (BDs)
|
||||
* which we call list.
|
||||
*
|
||||
* Transfer BDs (TBDs) may have a time slot assigned, the BC core will wait
|
||||
* until the time has expired before executing the next descriptor. Time
|
||||
* slots are handled by a Minor frame in the list.
|
||||
*
|
||||
* A Message Slot is allocated using the gr1553bc_slot_alloc() function,
|
||||
* and configured by calling one of the below functions:
|
||||
* - gr1553bc_slot_irq_prepare [unconditional IRQ slot]
|
||||
* - gr1553bc_slot_jump [unconditional jump]
|
||||
* - gr1553bc_slot_exttrig [Dummy transfer, wait for EXTERNAL-TRIGGER]
|
||||
* - gr1553bc_slot_transfer [Transfer descriptor]
|
||||
* - gr1553bc_slot_empty [Create Dummy Transfer descriptor]
|
||||
* - gr1553bc_slot_raw [Custom Descriptor handling]
|
||||
*
|
||||
* - gr1553bc_slot_dummy [Set existing Transfer descriptor to Dummy]
|
||||
* - gr1553bc_slot_update [Update DataPointer|Status of a TBD]
|
||||
*
|
||||
*
|
||||
* \section bc_IRQ Interrupt Handling
|
||||
*
|
||||
* There are different types of interrupts, Error IRQs or transfer IRQs. The
|
||||
* Error IRQs are handled by the driver can a callback function is called.
|
||||
*
|
||||
* Transfer Descriptors can be programmed to generate interrupt, and
|
||||
* condition descriptors can be programmed to generate interrupt
|
||||
* unconditionaly (there exists more conditional types). When a Transfer
|
||||
* descriptor causes IRQ the general ISR callback of the BC driver is
|
||||
* called to let the user handle the interrupt. When a condition descriptor
|
||||
* causes an IRQ a custom IRQ handler is called (if assigned).
|
||||
*
|
||||
* Transfers descriptor IRQ is enabled by configuring the descriptor.
|
||||
*
|
||||
* The API provides functions for placing unconditional IRQ points anywhere
|
||||
* in the list. The order:
|
||||
* -# gr1553bc_slot_alloc(&MID, TIME=0, ..)
|
||||
* -# gr1553bc_slot_irq_prepare(MID, funcISR, data)
|
||||
* -# gr1553bc_slot_irq_enable(MID)
|
||||
*
|
||||
* \verbatim
|
||||
* void funcISR(*bd, *data)
|
||||
* {
|
||||
* // HANDLE ONE OR MULTIPLE DESCRIPTORS (MULTIPLE IN THIS EXAMPLE):
|
||||
* int MID;
|
||||
* gr1553bc_mid_from_bd(bd,&MID,NULL);
|
||||
* printf("IRQ ON %06x\n", MID);
|
||||
* }
|
||||
* \endverbatim
|
||||
*
|
||||
* \ingroup GR1553BC
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include <gr1553bc.h>
|
||||
|
||||
/**** CONFIGURATION OPTIONS ****/
|
||||
|
||||
/* Define GR1553BC_TIMESLOT to make driver take care of time
|
||||
* management of minor frames.
|
||||
*/
|
||||
#define GR1553BC_TIMESLOT
|
||||
|
||||
#define GR1553BC_MINOR_MAX 256
|
||||
#define GR1553BC_SLOT_MAX 32
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
struct gr1553bc_list;
|
||||
struct gr1553bc_major;
|
||||
struct gr1553bc_minor;
|
||||
struct gr1553bc_minor_cfg;
|
||||
struct gr1553bc_major_cfg;
|
||||
|
||||
struct gr1553bc_minor_cfg {
|
||||
int slot_cnt;
|
||||
int timeslot; /* Total time of minor frame in us */
|
||||
};
|
||||
|
||||
struct gr1553bc_major_cfg {
|
||||
int minor_cnt; /* Number of Minor Frames */
|
||||
struct gr1553bc_minor_cfg minor_cfgs[1];
|
||||
};
|
||||
|
||||
struct gr1553bc_list_cfg {
|
||||
unsigned char rt_timeout[31]; /* Number of us timeout tolerance per RT */
|
||||
unsigned char bc_timeout; /* Number of us timeout tolerance of
|
||||
* broadcast transfers */
|
||||
int tropt_irq_on_err; /* Generate IRQ on transfer error */
|
||||
int tropt_pause_on_err; /* Pause list on transfer error */
|
||||
int async_list; /* Set to non-zero if asyncronous list*/
|
||||
};
|
||||
|
||||
/* Default Configuration */
|
||||
extern struct gr1553bc_list_cfg gr1553bc_def_cfg;
|
||||
|
||||
/* Complete list of all major frames */
|
||||
struct gr1553bc_list {
|
||||
void *_table_custom; /* Config option given by user */
|
||||
void *_table; /* address of allocated bd-table */
|
||||
unsigned int table_hw; /* Descriptor table base HW-ADR */
|
||||
unsigned int table_cpu; /* Descriptor table base CPU-ADR */
|
||||
int table_size; /* Descriptor Table Size */
|
||||
void *bc; /* BC HW, needed for adr translation */
|
||||
unsigned char rt_timeout[32]; /* Tolerance per RT, default 20us
|
||||
* Note: 31 is for Broadcast */
|
||||
uint32_t tropts; /* Transfer descriptor options:
|
||||
* On transfer error the following bits
|
||||
* do affect:
|
||||
* - bit28 1=Generate IRQ
|
||||
* - bit26 1=Pause transfer list
|
||||
*
|
||||
*/
|
||||
int async_list; /* async list or not */
|
||||
int major_cnt; /* Number of Major frames */
|
||||
struct gr1553bc_major *majors[1]; /* Var-Array of Major Pointers*/
|
||||
};
|
||||
|
||||
/* Alloc a List with a maximum number of Major frames supported */
|
||||
extern int gr1553bc_list_alloc(struct gr1553bc_list **list, int max_major);
|
||||
|
||||
/* Free List if allocated with gr1553bc_list_alloc() */
|
||||
extern void gr1553bc_list_free(struct gr1553bc_list *list);
|
||||
|
||||
/* Configure Global List parameters
|
||||
*
|
||||
* \param list List to be configured and initialized.
|
||||
* \param cfg List Configuration
|
||||
* \param bc The BC hardware device description
|
||||
* (only needed for address translation)
|
||||
*/
|
||||
extern int gr1553bc_list_config
|
||||
(
|
||||
struct gr1553bc_list *list,
|
||||
struct gr1553bc_list_cfg *cfg,
|
||||
void *bc
|
||||
);
|
||||
|
||||
/* Link a 'major' Major frame with next major frame
|
||||
* The links affected:
|
||||
* - major->next
|
||||
* - major->minor[LAST]->next
|
||||
*/
|
||||
extern void gr1553bc_list_link_major(
|
||||
struct gr1553bc_major *major,
|
||||
struct gr1553bc_major *next
|
||||
);
|
||||
|
||||
/* Link in a Major frame into a BC list.
|
||||
* Calls gr1553bc_list_link_major() to link major frame with major-1 and
|
||||
* major+1. If ending or starting major frame the frame is wrapped around.
|
||||
*/
|
||||
extern int gr1553bc_list_set_major(
|
||||
struct gr1553bc_list *list,
|
||||
struct gr1553bc_major *major,
|
||||
int no);
|
||||
|
||||
/* Calculate the size required in the descriptor table by one minor frame. */
|
||||
extern int gr1553bc_minor_table_size(struct gr1553bc_minor *minor);
|
||||
|
||||
/* Calculate the size required for the descriptor table.
|
||||
*/
|
||||
extern int gr1553bc_list_table_size(struct gr1553bc_list *list);
|
||||
|
||||
/* Allocate an empty descriptor table from list description suitable for
|
||||
* the BC given by 'bc'.
|
||||
*
|
||||
* \param bdtab_custom Custom Descriptor Allocation options:
|
||||
* ZERO: Dynamically allocated by Driver (CPU near RAM)
|
||||
* Non-Zero: Use provided address as BASE of BD-TABLE
|
||||
* Non-Zero with LSB set: Same as Non-Zero but address
|
||||
* is given as HW address (used with AMBA-over-PCI to
|
||||
* to specify RAM location on PCI board).
|
||||
*/
|
||||
extern int gr1553bc_list_table_alloc
|
||||
(
|
||||
struct gr1553bc_list *list,
|
||||
void *bdtab_custom
|
||||
);
|
||||
|
||||
/* Free descriptor table allocated with gr1553bc_list_table_alloc() */
|
||||
extern void gr1553bc_list_table_free(struct gr1553bc_list *list);
|
||||
|
||||
/* Build an empty descriptor table from list description,
|
||||
* the minor frames will be linked together.
|
||||
*/
|
||||
extern int gr1553bc_list_table_build(struct gr1553bc_list *list);
|
||||
|
||||
/* Major Frame */
|
||||
struct gr1553bc_major {
|
||||
struct gr1553bc_major *next; /* Next Major Frame */
|
||||
struct gr1553bc_major_cfg *cfg; /* User Config of Major frame */
|
||||
struct gr1553bc_minor *minors[1]; /* Minor frames */
|
||||
};
|
||||
|
||||
/* Minor Frame */
|
||||
struct gr1553bc_minor {
|
||||
struct gr1553bc_minor *next; /* Next Minor Frame */
|
||||
struct gr1553bc_minor_cfg *cfg; /* User Config of Minor frame */
|
||||
uint32_t alloc; /* Descripts allocated */
|
||||
|
||||
/* Note: THIS POINTER MUST BE ALIGNED ON A 128-bit BOUNDARY */
|
||||
union gr1553bc_bd *bds; /* Descriptors for this minor frame (CPU ADRS)*/
|
||||
};
|
||||
|
||||
/* Alloc a Major/Minor frame skeleton according to the configuration structure.
|
||||
* The descriptor table is not allocated.
|
||||
*/
|
||||
extern int gr1553bc_major_alloc_skel
|
||||
(
|
||||
struct gr1553bc_major **major,
|
||||
struct gr1553bc_major_cfg *cfg
|
||||
);
|
||||
|
||||
/* Unique Message/Descriptor ID. Can be used to identify a Major or Minor
|
||||
* Frame, or a Slot.
|
||||
*
|
||||
* - If minor_num is 0xff, the ID identifies a Major Frame
|
||||
* - If slot_num is 0xff, the ID identifies a Minor Frame
|
||||
* - If non of the above is true, the ID identifies a specific Slot
|
||||
*/
|
||||
#define GR1553BC_ID(major_num, minor_num, slot_num) \
|
||||
((((major_num)<<16)&0xff0000) | (((minor_num)<<8)&0xff00) | \
|
||||
((slot_num) & 0xff))
|
||||
#define GR1553BC_MINOR_ID(major_num, minor_num) \
|
||||
GR1553BC_ID(major_num, minor_num, 0xff)
|
||||
#define GR1553BC_MAJOR_ID(major_num) \
|
||||
GR1553BC_ID(major_num, 0xff, 0xff)
|
||||
|
||||
#define GR1553BC_MAJID_FROM_ID(mid) (((mid) >> 16) & 0xff)
|
||||
#define GR1553BC_MINID_FROM_ID(mid) (((mid) >> 8) & 0xff)
|
||||
#define GR1553BC_SLOTID_FROM_ID(mid) ((mid) & 0xff)
|
||||
#define GR1553BC_ID_SET_SLOT(mid, slot_num) (((mid) & ~0xff) | ((slot_num) & 0xff))
|
||||
|
||||
extern struct gr1553bc_major *gr1553bc_major_from_id
|
||||
(
|
||||
struct gr1553bc_list *list,
|
||||
int mid
|
||||
);
|
||||
|
||||
extern struct gr1553bc_minor *gr1553bc_minor_from_id
|
||||
(
|
||||
struct gr1553bc_list *list,
|
||||
int mid
|
||||
);
|
||||
|
||||
/* Get free time left of minor frame identified by MID 'mid' */
|
||||
extern int gr1553bc_list_freetime(struct gr1553bc_list *list, int mid);
|
||||
|
||||
/* Get free time left of minor frame */
|
||||
extern int gr1553bc_minor_freetime(struct gr1553bc_minor *minor);
|
||||
|
||||
/* Allocate a time slot on a minor frame, major/minor frame is identified
|
||||
* by MID. The 'mid' is a input/ouput parameter, the resulting slot taken
|
||||
* will be placed in 'mid', a pointer to the allocated descriptor is stored
|
||||
* into bd.
|
||||
*
|
||||
* Major/Minor must be specified by MID, if slot is specified that slot will
|
||||
* be allocated, if slot is 0xff, then the first free slot is allocated.
|
||||
*
|
||||
* The function fails (return negative) if timeslot is longer than remaining
|
||||
* time in minor frame, if no more slots are available in minor frame, if
|
||||
* MID points to a bad major/minor or major/minor/slot.
|
||||
*/
|
||||
extern int gr1553bc_slot_alloc(
|
||||
struct gr1553bc_list *list,
|
||||
int *mid,
|
||||
int timeslot,
|
||||
union gr1553bc_bd **bd
|
||||
);
|
||||
/* Same as gr1553bc_slot_alloc but identifies a minor instead of list.
|
||||
* The major/minor part of MID is ignored.
|
||||
*/
|
||||
extern int gr1553bc_slot_alloc2(
|
||||
struct gr1553bc_minor *minor,
|
||||
int *mid,
|
||||
int timeslot,
|
||||
union gr1553bc_bd **bd
|
||||
);
|
||||
|
||||
/* Free message slot and the time associated with it. The time taken by the
|
||||
* message slot is added to the END TIME descriptor, if managed by the driver
|
||||
* for this minor frame. The descriptor will be
|
||||
*/
|
||||
extern int gr1553bc_slot_free(struct gr1553bc_list *list, int mid);
|
||||
extern int gr1553bc_slot_free2(struct gr1553bc_minor *minor, int mid);
|
||||
|
||||
/* Find MID from Descriptor pointer
|
||||
*
|
||||
* In the end of each minor frame is a unconditional jump
|
||||
* to next minor frame descriptor. The hardware does not
|
||||
* use the last 8 bytes of conditional descriptors, in the
|
||||
* padding area a MID is stored so that we can lookup the
|
||||
* MID of a descriptor. This function finds the jump
|
||||
* descriptor and subtracs the offset from it.
|
||||
*
|
||||
* A faster way of looking up can be implemented if the
|
||||
* list is symertical, however in the current setup we
|
||||
* allow different numbers of slots in minor frames, and
|
||||
* different number of minor frames in a major frame.
|
||||
*
|
||||
* \param bd IN: Descriptor to lookup MID of (CPU address of BD)
|
||||
* \param mid OUT: Pointer to where Message-ID (Slot-ID) will be stored
|
||||
* \param async OUT: Function will store non-zero value if BD belogs to
|
||||
* async list.
|
||||
*/
|
||||
extern int gr1553bc_mid_from_bd(
|
||||
union gr1553bc_bd *bd,
|
||||
int *mid,
|
||||
int *async
|
||||
);
|
||||
|
||||
/********** TRANSFER DESCRIPTOR MANIPULATION **********/
|
||||
|
||||
/* Get pointer to descriptor entry from MID. */
|
||||
extern union gr1553bc_bd *gr1553bc_slot_bd
|
||||
(
|
||||
struct gr1553bc_list *list,
|
||||
int mid
|
||||
);
|
||||
|
||||
/* IRQ function */
|
||||
typedef void (*bcirq_func_t)(union gr1553bc_bd *bd, void *data);
|
||||
|
||||
/* Create unconditional IRQ customly defined location.
|
||||
* The IRQ is disabled, enable it with gr1553bc_slot_irq_enable().
|
||||
*/
|
||||
extern int gr1553bc_slot_irq_prepare
|
||||
(
|
||||
struct gr1553bc_list *list,
|
||||
int mid,
|
||||
bcirq_func_t func,
|
||||
void *data
|
||||
);
|
||||
|
||||
/* Enable previously prepared unconditional IRQ */
|
||||
extern int gr1553bc_slot_irq_enable(struct gr1553bc_list *list, int mid);
|
||||
|
||||
/* Disable unconditional IRQ point, changed to unconditional JUMP
|
||||
* to descriptor following.
|
||||
* After disabling it it can be enabled again, or freed.
|
||||
*/
|
||||
extern int gr1553bc_slot_irq_disable(struct gr1553bc_list *list, int mid);
|
||||
|
||||
/* Create custom jump to descriptor, conditional or unconditional, see
|
||||
* hardware manual for conditions.
|
||||
*
|
||||
* set conditional to GR1553BC_UNCOND_JMP for unconditional jump.
|
||||
*/
|
||||
extern int gr1553bc_slot_jump
|
||||
(
|
||||
struct gr1553bc_list *list,
|
||||
int mid,
|
||||
uint32_t condition,
|
||||
int to_mid
|
||||
);
|
||||
|
||||
/* Create a dummy transfer, paused until external trigger is set. The
|
||||
* Slot is will have the dummy bit set, no transfer will take place.
|
||||
*/
|
||||
extern int gr1553bc_slot_exttrig(struct gr1553bc_list *list, int mid);
|
||||
|
||||
/* Create a transfer on a previous allocated descriptor. It is assumed
|
||||
* that the descriptor has been initialized empty before calling this
|
||||
* function, this is to avoid races.
|
||||
*
|
||||
* The settings that are controlled on a global level (and not
|
||||
* by this function):
|
||||
* - IRQ after transfer error
|
||||
* - IRQ after transfer (not supported, insert separate IRQ slot after this)
|
||||
* - Pause schedule after transfer error
|
||||
* - Pause schedule after transfer (not supported)
|
||||
* - slot time optional (set when MID allocated), otherwise 0
|
||||
* - (OPTIONAL) Dummy Bit, set using slot_empty() or ..._TT_DUMMY
|
||||
* - RT timeout tolerance (managed per RT)
|
||||
*
|
||||
* Input Parameters:
|
||||
* - Retry Mode (options)
|
||||
* - Number of retires (options)
|
||||
* - Bus selection (A or B) (options)
|
||||
* - dummy bit (options)
|
||||
* - transfer type (tt)
|
||||
* - rt src/dst address (tt)
|
||||
* - RT subaddress (tt)
|
||||
* - word count (tt)
|
||||
* - mode code (tt)
|
||||
* - data pointer (dptr)
|
||||
*
|
||||
*
|
||||
* See macros defined in this header file for creating transfer types (tt)
|
||||
* and word count etc.
|
||||
*
|
||||
* See macros defined in this header file for creating the mask of options.
|
||||
*
|
||||
* Note that if bit0 (LSB) of dptr is set, then the address is translated into
|
||||
* hardware address, otherwise the dptr is assumed to be accessible from the
|
||||
* 1553 core. This is an option only for AMBA-over-PCI.
|
||||
*/
|
||||
extern int gr1553bc_slot_transfer(
|
||||
struct gr1553bc_list *list,
|
||||
int mid,
|
||||
int options,
|
||||
int tt,
|
||||
uint16_t *dptr);
|
||||
|
||||
/* Remove or set dummy bit of a transfer descriptor
|
||||
* Bit31 of *dummy is written to the dummy bit, the
|
||||
* old descriptor value is stored into *dummy.
|
||||
*/
|
||||
extern int gr1553bc_slot_dummy(
|
||||
struct gr1553bc_list *list,
|
||||
int mid,
|
||||
unsigned int *dummy);
|
||||
|
||||
/* Make a slot empty (BC will not generate bus transfers), time slot
|
||||
* allocated is untouched (if assigned).
|
||||
*/
|
||||
extern int gr1553bc_slot_empty(struct gr1553bc_list *list, int mid);
|
||||
|
||||
/* Transfer descriptor status and/or update Transfer descriptor data pointer.
|
||||
*
|
||||
* Read and/or write Status of a slot. Writing the status word may be
|
||||
* used by software to indicate that result has been handled, or bit 31
|
||||
* may be written 1 telling software that when it reaches 0, then BC
|
||||
* has executed the request.
|
||||
*
|
||||
* Operation:
|
||||
* bd->status = *stat & (bd->status 0xffffff) | (*stat & 0x80000000);
|
||||
* *stat = Value of bd->status before rewrite.
|
||||
*
|
||||
* Note that the status word is not written when *stat is zero.
|
||||
*
|
||||
* Note that if bit0 (LSB) of dptr is set, then the address is translated into
|
||||
* hardware address, otherwise the dptr is assumed to be accessible from the
|
||||
* 1553 core. This is an option only for AMBA-over-PCI.
|
||||
*/
|
||||
extern int gr1553bc_slot_update(
|
||||
struct gr1553bc_list *list,
|
||||
int mid,
|
||||
uint16_t *dptr,
|
||||
unsigned int *stat);
|
||||
|
||||
/* Modify a transfer descriptor in any way,
|
||||
*
|
||||
* flags:
|
||||
* bit[N=0..3]: 1 = set BD wordN according to argument wordN,
|
||||
* 0 = do not modify BD wordN
|
||||
*/
|
||||
extern 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
|
||||
);
|
||||
|
||||
|
||||
/***** Macros to create BC Transfer Types (tt) for gr1553bc_slot_transfer() *****/
|
||||
|
||||
/* WRITE TO RT (BC-to-RT) */
|
||||
#define GR1553BC_BC2RT(rtadr, subadr, word_count) \
|
||||
((rtadr<<11) | (subadr<<5) | (0x1f<<21) | (0<<10) | \
|
||||
((word_count>=32) ? 0 : word_count))
|
||||
|
||||
/* READ FROM RT (RT-to-BC) */
|
||||
#define GR1553BC_RT2BC(rtadr, subadr, word_count) \
|
||||
((rtadr<<11) | (subadr<<5) | (0x1f<<21) | (1<<10) | \
|
||||
((word_count>=32) ? 0 : word_count))
|
||||
|
||||
/* RT(TX) WRITE TO RT(RX) (RT-to-RT) */
|
||||
#define GR1553BC_RT2RT(tx_rtadr, tx_subadr, rx_rtadr, rx_subadr, word_count) \
|
||||
((rx_rtadr<<11) | (rx_subadr<<5) | \
|
||||
(tx_rtadr<<21) | (tx_subadr<<16) | \
|
||||
(0<<10) | \
|
||||
((word_count>=32) ? 0 : word_count))
|
||||
|
||||
/* Mode command without data. (BC-to-RT)
|
||||
* Mode code: 0,1,2,3,4,5,6,7 or 8.
|
||||
*/
|
||||
#define GR1553BC_MC_NODATA(rtadr, modecode) \
|
||||
((rtadr<<11) | (0x1f<<5) | (0x1f<<21) | \
|
||||
(modecode<<0) | (1<<10))
|
||||
|
||||
/* Mode command with 4 byte data (RT-to-BC)
|
||||
* Mode code: 16, 18 or 19.
|
||||
*/
|
||||
#define GR1553BC_MC_RT2BC(rtadr, modecode) \
|
||||
((rtadr<<11) | (0x1f<<5) | (0x1f<<21) | \
|
||||
(modecode<<0) | (1<<10))
|
||||
|
||||
/* Mode command with 4 byte data (BC-to-RT)
|
||||
* Mode code: 17, 20 or 21.
|
||||
*/
|
||||
#define GR1553BC_MC_BC2RT(rtadr, modecode) \
|
||||
((rtadr<<11) | (0x1f<<5) | (0x1f<<21) | \
|
||||
(modecode<<0) | (0<<10))
|
||||
|
||||
/* Broadcast to all RTs, to a specific subaddress (BC-to-RTs) */
|
||||
#define GR1553BC_BC_BC2RT(subadr, word_count) \
|
||||
((0x1f<<11) | (subadr<<5) | (0x1f<<21) | \
|
||||
(0<<10) | \
|
||||
((word_count>=32) ? 0 : word_count))
|
||||
|
||||
/* Request RT to broadcast to all RTs, to a specific subaddress (RT-to-RTs) */
|
||||
#define GR1553BC_BC_RT2RT(tx_rtadr, tx_subadr, rx_subadr, word_count) \
|
||||
((0x1f<<11) | (rx_subadr<<5) | \
|
||||
(tx_rtadr<<21) | (tx_subadr<<16) | \
|
||||
(0<<10) | \
|
||||
((word_count>=32) ? 0 : word_count))
|
||||
|
||||
/* Broadcast mode command without data (BC-to-RTs)
|
||||
* Mode code: 1,3,4,5,6,7 or 8
|
||||
*/
|
||||
#define GR1553BC_BC_MC_NODATA(modecode) \
|
||||
((0x1f<<11) | (0x1f<<5) | (0x1f<<21) | \
|
||||
((modecode)<<0) | (1<<10))
|
||||
|
||||
/* Broadcast mode command with 4 byte data (BC-to-RTs)
|
||||
* Mode code: 17, 20 or 21
|
||||
*/
|
||||
#define GR1553BC_BC_MC_BC2RT(modecode) \
|
||||
((0x1f<<11) | (0x1f<<5) | (0x1f<<21) | \
|
||||
((modecode)<<0) | (0<<10))
|
||||
|
||||
|
||||
/***** Macros to create BC options (options) for gr1553bc_slot_transfer() *****/
|
||||
|
||||
/* Dummy (BC does no bus trasactions) */
|
||||
#define GR1553BC_OPT_DUMMY (1<<1)
|
||||
|
||||
/* Retry modes */
|
||||
#define GR1553BC_RETRY_SAME 0x0 /* Retry on the same bus only */
|
||||
#define GR1553BC_RETRY_ALTER 0x1 /* Retry alternating on both busses */
|
||||
#define GR1553BC_RETRY_ATTEMPT 0x2 /* Many attepts first on original
|
||||
* bus then on other bus */
|
||||
/* Number of retires supported */
|
||||
#define GR1553BC_RETRY_CNT_MAX 6
|
||||
|
||||
/* Dummy bit: No transfer
|
||||
* Bus bit: 0=A, 1=B
|
||||
* Exttrig bit: Wait for external trigger (used for timesync)
|
||||
* Exclusive bit: 1=Don't allow other messages in this time slot.
|
||||
*/
|
||||
#define GR1553BC_OPTIONS(dummy, exttrig, exclusive, retrymode, nretry, bus) \
|
||||
((((exttrig) & 0x1) << 30) | (((exclusive) & 0x1) << 29) | \
|
||||
((retrymode) << 23) | ((nretry) << 20) | \
|
||||
((bus) & 1) | (((dummy) & 0x1) << 1))
|
||||
|
||||
#define GR1553BC_OPTIONS_BUSA GR1553BC_OPTIONS(0,0,0,GR1553BC_RETRY_SAME,0,0)
|
||||
#define GR1553BC_OPTIONS_BUSB GR1553BC_OPTIONS(0,0,0,GR1553BC_RETRY_SAME,0,1)
|
||||
#define GR1553BC_OPTIONS_BUSA_DUM GR1553BC_OPTIONS(1,0,0,GR1553BC_RETRY_SAME,0,0)
|
||||
#define GR1553BC_OPTIONS_BUSB_DUM GR1553BC_OPTIONS(1,0,0,GR1553BC_RETRY_SAME,0,1)
|
||||
|
||||
/* Show parts of a list - this is for debugging only */
|
||||
extern void gr1553bc_show_list(struct gr1553bc_list *list, int options);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __GR1553BC_LIST_H__ */
|
||||
204
c/src/lib/libbsp/sparc/shared/include/gr1553bm.h
Normal file
204
c/src/lib/libbsp/sparc/shared/include/gr1553bm.h
Normal file
@@ -0,0 +1,204 @@
|
||||
/* 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.com/license/LICENSE.
|
||||
*/
|
||||
|
||||
#ifndef __GR1553BM_H__
|
||||
#define __GR1553BM_H__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Register GR1553B driver needed by BM driver */
|
||||
extern void gr1553bm_register(void);
|
||||
|
||||
struct gr1553bm_entry {
|
||||
uint32_t time; /* bit31=1, bit 30=0 */
|
||||
uint32_t data; /* bit31=0, bit 30=0 */
|
||||
};
|
||||
|
||||
#define GR1553BM_ERROPTS_MANL 0x02
|
||||
#define GR1553BM_ERROPTS_UDWL 0x04
|
||||
#define GR1553BM_ERROPTS_IMCL 0x08
|
||||
#define GR1553BM_ERROPTS_ALL 0x0e
|
||||
|
||||
/* Function used to implement a custom copy routine.
|
||||
* Returns number of bytes the desctionation address
|
||||
* should be incremented with.
|
||||
*
|
||||
* \param dst Optional Destination address
|
||||
* \param src Source DMA address
|
||||
* \param nentires Number of entries to be processed.
|
||||
* \param data Custom Data (set by config)
|
||||
*/
|
||||
typedef int (*bmcopy_func_t)(
|
||||
unsigned int dst,
|
||||
struct gr1553bm_entry *src,
|
||||
int nentries,
|
||||
void *data
|
||||
);
|
||||
|
||||
/* IRQ function callback, called on BM DMA error */
|
||||
typedef void (*bmisr_func_t)(void *bm, void *data);
|
||||
|
||||
/* BM driver configuration */
|
||||
struct gr1553bm_config {
|
||||
|
||||
/*** Time options ***/
|
||||
|
||||
/* 8-bit time resolution, the BM will update the time according
|
||||
* to this setting. 0 will make the time tag be of highest
|
||||
* resolution (no division), 1 will make the BM increment the
|
||||
* time tag once for two time ticks (div with 2), etc.
|
||||
*/
|
||||
uint8_t time_resolution;
|
||||
|
||||
/* Enable Time Overflow IRQ handling. Setting this to 1
|
||||
* makes the driver to update the 64-bit time by it self,
|
||||
* it will use time overflow IRQ to detect when the 64-bit
|
||||
* time counter must be incremented.
|
||||
*
|
||||
* If set to zero, the driver expect the user to call
|
||||
* gr1553bm_time() regularly, it must be called more often
|
||||
* than the time overflows to avoid an incorrect time.
|
||||
*/
|
||||
int time_ovf_irq;
|
||||
|
||||
|
||||
|
||||
/*** Filtering options ***/
|
||||
|
||||
/* Bus error log options
|
||||
*
|
||||
* bit0,4-31 = reserved, set to zero
|
||||
* Bit1 = Enables logging of Invalid mode code errors
|
||||
* Bit2 = Enables logging of Unexpected Data errors
|
||||
* Bit3 = Enables logging of Manchester/parity errors
|
||||
*/
|
||||
unsigned int filt_error_options;
|
||||
|
||||
/* RT Address filtering bit mask. Each bit enables (if set)
|
||||
* logging of a certain RT sub address. Bit 31 enables logging
|
||||
* of broadcast messages.
|
||||
*/
|
||||
unsigned int filt_rtadr;
|
||||
|
||||
/* RT Subaddress filtering bit mask, bit definition:
|
||||
* 31: Enables logging of mode commands on subadr 31
|
||||
* 1..30: BitN enables/disables logging of RT subadr N
|
||||
* 0: Enables logging of mode commands on subadr 0
|
||||
*/
|
||||
unsigned int filt_subadr;
|
||||
|
||||
/* Mode code Filter, is written into "BM RT Mode code filter"
|
||||
* register, please see hardware manual for bit declarations.
|
||||
*/
|
||||
unsigned int filt_mc;
|
||||
|
||||
|
||||
|
||||
/*** Buffer options ***/
|
||||
|
||||
/* Size of buffer in bytes, must be aligned to 8-byte
|
||||
* The size is limited to max 4Mb.
|
||||
*/
|
||||
unsigned int buffer_size;
|
||||
|
||||
/* Custom buffer, must be aligned to 8-byte and be of buffer_size
|
||||
* length. If NULL dynamic memory allocation is used.
|
||||
*/
|
||||
void *buffer_custom;
|
||||
|
||||
/* Custom Copy function, may be used to implement a more
|
||||
* effective way of copying the DMA buffer. For example
|
||||
* the DMA log may need to be compressed before copied
|
||||
* onto a storage, this function can be used to avoid an
|
||||
* extra copy.
|
||||
*/
|
||||
bmcopy_func_t copy_func;
|
||||
|
||||
/* Optional Custom Data passed on to copy_func() */
|
||||
void *copy_func_arg;
|
||||
|
||||
|
||||
|
||||
/*** Interrupt options ***/
|
||||
|
||||
/* Custom DMA error function, note that this function is called
|
||||
* from Interrupt Context. Set to NULL to disable this callback.
|
||||
*/
|
||||
bmisr_func_t dma_error_isr;
|
||||
|
||||
/* Optional Custom Data passed on to dma_error_isr() */
|
||||
void *dma_error_arg;
|
||||
};
|
||||
|
||||
/* Open BM device by instance number (minor)
|
||||
*
|
||||
* The return value is used as input parameter in all other function calls
|
||||
* in the A
|
||||
*/
|
||||
extern void *gr1553bm_open(int minor);
|
||||
|
||||
/* Close previously opened Bm device */
|
||||
extern void gr1553bm_close(void *bm);
|
||||
|
||||
/* Configure the BM driver before starting */
|
||||
extern int gr1553bm_config(void *bm, struct gr1553bm_config *cfg);
|
||||
|
||||
/* Start logging */
|
||||
extern int gr1553bm_start(void *bm);
|
||||
|
||||
/* Get 64-bit 1553 Time. Low 24-bit time is acquired from BM hardware,
|
||||
* the MSB is taken from a software counter internal to the driver. The
|
||||
* counter is incremented every time the Time overflows by:
|
||||
* - using "Time overflow" IRQ if enabled in user configuration
|
||||
* - by checking IRQ flag (IRQ disabled), it is required that user
|
||||
* calls this function before the next time overflow.
|
||||
*
|
||||
* The BM timer is limited to 24-bits, in order to handle overflows
|
||||
* correctly and maintain a valid time an Interrupt handler is used
|
||||
* or this function must be called when IRQ is not used.
|
||||
*
|
||||
* Update software time counters and return the current time.
|
||||
*/
|
||||
extern void gr1553bm_time(void *bm, uint64_t *time);
|
||||
|
||||
/* Return zero when logging has not been started, non-zero when logging
|
||||
* has been started
|
||||
*/
|
||||
extern int gr1553bm_started(void *bm);
|
||||
|
||||
/* Check how many entries are currently stored in the BM Log DMA-area */
|
||||
extern int gr1553bm_available(void *bm, int *nentries);
|
||||
|
||||
/* Stop logging */
|
||||
extern void gr1553bm_stop(void *bm);
|
||||
|
||||
/* Read a maximum number of entries from LOG buffer. This function
|
||||
* must be
|
||||
*
|
||||
* Arguments
|
||||
* bm - Private pointer returned by gr1553bm_open()
|
||||
* dst - Address where log data is written
|
||||
* max - (IN/OUT) Maximum number of entires, when successfull
|
||||
* the number of entries actually written is stored
|
||||
* into the address of max.
|
||||
*
|
||||
* Result
|
||||
* 0 = success
|
||||
* -1 = fail. (may be due to BM logging not started)
|
||||
*/
|
||||
extern int gr1553bm_read(void *bm, struct gr1553bm_entry *dst, int *max);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __GR1553BM_H__ */
|
||||
434
c/src/lib/libbsp/sparc/shared/include/gr1553rt.h
Normal file
434
c/src/lib/libbsp/sparc/shared/include/gr1553rt.h
Normal file
@@ -0,0 +1,434 @@
|
||||
/* 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.com/license/LICENSE.
|
||||
*/
|
||||
|
||||
#ifndef __GR1553RT_H__
|
||||
#define __GR1553RT_H__
|
||||
|
||||
/* CONFIG OPTION: Maximum number of LIST IDs supported.
|
||||
* There are two lists per RT subaddress, one for RX one
|
||||
* for TX.
|
||||
*/
|
||||
#define RTLISTID_MAX 64
|
||||
|
||||
/* CONFIG OPTION: Maximum number of Interrupt handlers per device supported
|
||||
* max is 256 supported, and minimum is 1.
|
||||
*/
|
||||
#define RTISR_MAX 64
|
||||
|
||||
/* CONFIG OPTION: Maximum number of transfer (RX/TX) descriptors supported.
|
||||
*
|
||||
* Set this option to zero to allow flexible number of descriptors,
|
||||
* requires dynamically allocation of driver structures.
|
||||
*/
|
||||
/*#define RTBD_MAX 4096*/
|
||||
#define RTBD_MAX 0
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Register GR1553B driver needed by RT driver */
|
||||
extern void gr1553rt_register(void);
|
||||
|
||||
struct gr1553rt_list;
|
||||
|
||||
/* Descriptor read/written by hardware.
|
||||
*
|
||||
* Must be aligned to 16 byte boundary
|
||||
*/
|
||||
struct gr1553rt_bd {
|
||||
volatile unsigned int ctrl; /* 0x00 Control/Status word */
|
||||
volatile unsigned int dptr; /* 0x04 Data Pointer */
|
||||
volatile unsigned int next; /* 0x08 Next Descriptor in list */
|
||||
volatile unsigned int unused; /* 0x0C UNUSED BY HARDWARE */
|
||||
};
|
||||
|
||||
/* Sub address table entry, the hardware access */
|
||||
struct gr1553rt_sa {
|
||||
volatile unsigned int ctrl; /* 0x00 SUBADDRESS CONTROL WORD */
|
||||
volatile unsigned int txptr; /* 0x04 TRANSMIT BD POINTER */
|
||||
volatile unsigned int rxptr; /* 0x08 RECEIVE BD POINTER */
|
||||
volatile unsigned int unused; /* 0x0C UNUSED BY HARDWARE */
|
||||
};
|
||||
|
||||
/* Configuration of a RT-SubAddress-List */
|
||||
struct gr1553rt_list_cfg {
|
||||
unsigned int bd_cnt; /* Number of hw-descriptors in list */
|
||||
};
|
||||
|
||||
/* A TX or RX subaddress descriptor list */
|
||||
struct gr1553rt_list {
|
||||
short listid; /* ID/NUMBER of List. -1 unassigned */
|
||||
short subadr; /* SubAddress. -1 when not scheduled */
|
||||
void *rt; /* Scheduled on Device */
|
||||
struct gr1553rt_list_cfg *cfg; /* List configuration */
|
||||
int bd_cnt; /* Number of Descriptors */
|
||||
|
||||
/* !!Must be last in data structure!!
|
||||
* !!Array must at least be of length bd_cnt!!
|
||||
*/
|
||||
unsigned short bds[1]; /* Array of BDIDs, -1 unused/end */
|
||||
};
|
||||
|
||||
/* GR1553B-RT Driver configuration options used when calling gr1553rt_config().
|
||||
*
|
||||
* Note that if not custom addresses are given the driver will dynamically
|
||||
* allocate memory for buffers.
|
||||
* Note that if custom addresses with the LSB set, the address will be
|
||||
* interpreted as a address accessible by hardware, and translated
|
||||
* into an address used by CPU.
|
||||
*/
|
||||
struct gr1553rt_cfg {
|
||||
unsigned char rtaddress; /* RT Address 0..30 */
|
||||
|
||||
/*** MODE CODE CONFIG ***/
|
||||
unsigned int modecode; /* Mode codes enable/disable/IRQ/EV-Log.
|
||||
* Each modecode has a 2-bit cfg field.
|
||||
* See Mode Code Control Register in
|
||||
* hardware manual.
|
||||
*/
|
||||
|
||||
/*** TIME CONFIG ***/
|
||||
unsigned short time_res; /* Time tag resolution in us */
|
||||
|
||||
/*** SUBADDRESS TABLE CONFIG ***/
|
||||
void *satab_buffer; /* Optional Custom buffer. Must be
|
||||
* At least 16*32 bytes, and be aligned
|
||||
* to 10-bit (1KB) boundary. Set to NULL
|
||||
* to make driver allocate buffer.
|
||||
*/
|
||||
|
||||
/*** EVENT LOG CONFIG ***/
|
||||
void *evlog_buffer; /* Optional Custom buffer */
|
||||
int evlog_size; /* Length, must be a multiple of 2.
|
||||
* If set to ZERO event log is disabled
|
||||
*/
|
||||
|
||||
/*** TRANSFER DESCRIPTOR CONFIG ***/
|
||||
int bd_count; /* Number of transfer descriptors shared
|
||||
* by all RX/TX sub-addresses */
|
||||
void *bd_buffer; /* Optional Custom descriptor area.
|
||||
* Must hold bd_count*32 bytes.
|
||||
* If NULL, descriptors will be
|
||||
* allocated dynamically. */
|
||||
};
|
||||
|
||||
/* GR1553B-RT status indication, copied from the RT registers and stored
|
||||
* here. Used when calling the gr1553rt_status() function.
|
||||
*/
|
||||
struct gr1553rt_status {
|
||||
unsigned int status; /* RT Status word */
|
||||
unsigned int bus_status; /* BUS Status */
|
||||
unsigned short synctime; /* Time Tag of last sync with data */
|
||||
unsigned short syncword; /* Data of last mode code synchronize
|
||||
* with data. */
|
||||
unsigned short time_res; /* Time resolution (set by config) */
|
||||
unsigned short time; /* Current Time Tag */
|
||||
};
|
||||
|
||||
/* ISR callback definition for ERRORs detected in the GR1553B-RT interrupt
|
||||
* handler.
|
||||
*
|
||||
* \param err Inidicate Error type. The IRQ flag register bit mask:
|
||||
* Bit 9 - RT DMA ERROR
|
||||
* Bit 10 - RT Table access error
|
||||
* \param data Custom data assigned by user
|
||||
*/
|
||||
typedef void (*gr1553rt_irqerr_t)(int err, void *data);
|
||||
|
||||
/* ISR callback definition for modecodes that are configured to generate
|
||||
* an IRQ. The callback is called from within the GR1553B-RT interrupt
|
||||
* handler.
|
||||
*
|
||||
* \param mcode Mode code that caused this IRQ
|
||||
* \param entry The raw Eventlog Entry
|
||||
* \param data Custom data assigned by user
|
||||
*/
|
||||
typedef void (*gr1553rt_irqmc_t)(int mcode, unsigned int entry, void *data);
|
||||
|
||||
/* Transfer ISR callback definition. Called from GR1553B-RT interrupt handler
|
||||
* when an interrupt has been generated and a event logged due to a 1553
|
||||
* transfer to this RT.
|
||||
*
|
||||
* \param list List (Subaddress/TransferType) that caused IRQ
|
||||
* \param entry The raw Eventlog Entry
|
||||
* \param bd_next Next Descriptor-entry index in the list (Subaddress/tr-type)
|
||||
* This can be used to process all descriptors upto entry_next.
|
||||
* \param data Custom data assigned by user
|
||||
*/
|
||||
typedef void (*gr1553rt_irq_t)(
|
||||
struct gr1553rt_list *list,
|
||||
unsigned int entry,
|
||||
int bd_next,
|
||||
void *data
|
||||
);
|
||||
|
||||
/* Configure a list according to configuration. Assign the list
|
||||
* to a device, however not to a RT sub address yet. The rt
|
||||
* is stored within list.
|
||||
*
|
||||
* \param rt RT Device driver identification, stored within list.
|
||||
* \param list The list to configure
|
||||
* \param cfg Configuration for list. Pointer to configuration is
|
||||
* stored within list for later use.
|
||||
*/
|
||||
extern int gr1553rt_list_init
|
||||
(
|
||||
void *rt,
|
||||
struct gr1553rt_list **plist,
|
||||
struct gr1553rt_list_cfg *cfg
|
||||
);
|
||||
|
||||
/* Assign an Error Interrupt handler. Before the handler is called the
|
||||
* RT hardware is stopped/disabled. The handler is optional, if not assigned
|
||||
* the ISR will still stop the RT upon error.
|
||||
*
|
||||
* Errors detected by the interrupt handler:
|
||||
* - DMA error
|
||||
* - Subaddress table access error
|
||||
*
|
||||
* \param func ISR called when an error causes an interrupt.
|
||||
* \param data Custom data given as an argument when calling ISR
|
||||
*/
|
||||
extern int gr1553rt_irq_err
|
||||
(
|
||||
void *rt,
|
||||
gr1553rt_irqerr_t func,
|
||||
void *data
|
||||
);
|
||||
|
||||
/* Assign a ModeCode Interrupt handler callback. Called when a 1553 modecode
|
||||
* transfer is logged and cause an IRQ. The modecode IRQ generation is
|
||||
* configured from "struct gr1553rt_cfg" when calling gr1553rt_config().
|
||||
*
|
||||
* \param func ISR called when a modecode causes an interrupt.
|
||||
* \param data Custom data given as an argument when calling ISR
|
||||
*/
|
||||
extern int gr1553rt_irq_mc
|
||||
(
|
||||
void *rt,
|
||||
gr1553rt_irqmc_t func,
|
||||
void *data
|
||||
);
|
||||
|
||||
/* Assign transfer interrupt handler callback. Called when a RX or TX
|
||||
* transfer is logged and cause an interrupt, the function is called
|
||||
* from the GR1553B-RT driver's ISR, in interrupt context.
|
||||
*
|
||||
* The callback can be installed per subaddress and transfer type.
|
||||
* Subaddress 0 and 31 are not valid (gr1553rt_irq_mc() for modecodes).
|
||||
*
|
||||
* \param subadr Select subaddress (1-30)
|
||||
* \param tx 1=TX subaddress, 0=RX subaddress
|
||||
* \param func ISR called when subaddress of spcified transfer type
|
||||
* causes an interrupt.
|
||||
* \param data Custom data given as an argument when calling ISR
|
||||
*/
|
||||
extern int gr1553rt_irq_sa
|
||||
(
|
||||
void *rt,
|
||||
int subadr,
|
||||
int tx,
|
||||
gr1553rt_irq_t func,
|
||||
void *data
|
||||
);
|
||||
|
||||
#define GR1553RT_BD_FLAGS_IRQEN (1<<30)
|
||||
/* Initialize a descriptor entry in a list. This is typically done
|
||||
* prior to scheduling the list.
|
||||
*
|
||||
* \param entry_no Entry number in list (descriptor index in list)
|
||||
* \param flags Enable IRQ when descriptor is accessed by setting
|
||||
* argument GR1553RT_BD_FLAGS_IRQEN. Enabling IRQ on a
|
||||
* descriptor basis will override SA-table IRQ config.
|
||||
* \param dptr Data Pointer to RX or TX operation. The LSB indicate
|
||||
* if the address must be translated into Hardware address
|
||||
* - this is useful when a buffer close to CPU is used
|
||||
* as a data pointer and the RT core is located over PCI.
|
||||
* \param next Next Entry in list. Set to 0xffff for end of list. Set
|
||||
* 0xfffe for next entry in list, wrap around to entry
|
||||
* zero if entry_no is last descriptor in list (circular).
|
||||
*/
|
||||
extern int gr1553rt_bd_init(
|
||||
struct gr1553rt_list *list,
|
||||
unsigned short entry_no,
|
||||
unsigned int flags,
|
||||
uint16_t *dptr,
|
||||
unsigned short next
|
||||
);
|
||||
|
||||
/* Manipulate/Read Control/Status and Data Pointer words of a buffer descriptor.
|
||||
* If status is zero, the control/status word is accessed. If dptr is non-zero
|
||||
* the data pointer word is accessed.
|
||||
*
|
||||
* \param list The list that the descriptor is located at
|
||||
*
|
||||
* \param entry_no The descriptor number accessed
|
||||
*
|
||||
* \param status IN/OUT. If zero no effect. If pointer is non-zero the
|
||||
* value pointed to:
|
||||
* IN: Written to Control/Status
|
||||
* OUT: the value of the Control/Status word before writing.
|
||||
*
|
||||
* \param dptr IN/OUT. If zero no effect. If pointer is non-zero, the
|
||||
* value pointed to:
|
||||
* IN: non-zero: Descriptor data pointer will be updated with
|
||||
* this value. Note that the LSB indicate if the address
|
||||
* must be translated into hardware-aware address.
|
||||
* OUT: The old data pointer is stored here.
|
||||
*/
|
||||
extern int gr1553rt_bd_update(
|
||||
struct gr1553rt_list *list,
|
||||
int entry_no,
|
||||
unsigned int *status,
|
||||
uint16_t **dptr
|
||||
);
|
||||
|
||||
/* Get the next/current descriptor processed of a RT sub-address.
|
||||
*
|
||||
* \param subadr RT Subaddress
|
||||
* \param txeno Pointer to where TX descriptor number is stored.
|
||||
* \param rxeno Pointer to where RX descriptor number is stored.
|
||||
*/
|
||||
extern int gr1553rt_indication(void *rt, int subadr, int *txeno, int *rxeno);
|
||||
|
||||
/* Take a GR1553RT hardware device identified by minor.
|
||||
* A pointer is returned that is used internally by the GR1553RT
|
||||
* driver, it is used as an input parameter 'rt' to all other
|
||||
* functions that manipulate the hardware.
|
||||
*
|
||||
* This function initializes the RT hardware to a stopped/disable level.
|
||||
*/
|
||||
extern void *gr1553rt_open(int minor);
|
||||
|
||||
/* Close and stop/disable the RT hardware. */
|
||||
extern void gr1553rt_close(void *rt);
|
||||
|
||||
/* Configure the RT. The RT device must be configured once before
|
||||
* started. A started RT device can not be configured.
|
||||
*
|
||||
* \param rt The RT to configure
|
||||
* \param cfg Configuration parameters
|
||||
*/
|
||||
extern int gr1553rt_config(void *rt, struct gr1553rt_cfg *cfg);
|
||||
|
||||
/* Schedule a RX or TX list on a sub address. If a list has already been
|
||||
* schduled on the subaddress and on the same transfer type (RX/TX), the
|
||||
* old list is replaced with the list given here.
|
||||
*
|
||||
* \param subadr Subaddress to schedule list on
|
||||
* \param tx Subaddress transfer type: 1=TX, 0=RX
|
||||
* \param list Preconfigued RT list scheduled
|
||||
*/
|
||||
extern void gr1553rt_sa_schedule(
|
||||
void *rt,
|
||||
int subadr,
|
||||
int tx,
|
||||
struct gr1553rt_list *list
|
||||
);
|
||||
|
||||
/* Set SubAdress options. One may for example Enable or Disable a sub
|
||||
* address RX and/or TX. See hardware manual for SA-Table configuration
|
||||
* options.
|
||||
*
|
||||
* \param subadr SubAddress to configure
|
||||
* \param mask Bit mask of option-bits written to subaddress config
|
||||
* \param options The new options written to subaddress config.
|
||||
*
|
||||
*/
|
||||
extern void gr1553rt_sa_setopts(
|
||||
void *rt,
|
||||
int subadr,
|
||||
unsigned int mask,
|
||||
unsigned int options
|
||||
);
|
||||
|
||||
/* Get The Subaddress and transfer type of a scheduled list. Normally the
|
||||
* application knows which subaddress the list is for.
|
||||
*
|
||||
* \param list List to lookup information for
|
||||
* \param subadr Pointer to where the subaddress is stored
|
||||
* \param tx Transfer type is stored here. 1=TX, 0=RX.
|
||||
*/
|
||||
extern void gr1553rt_list_sa(
|
||||
struct gr1553rt_list *list,
|
||||
int *subadr,
|
||||
int *tx
|
||||
);
|
||||
|
||||
/* Start RT Communication
|
||||
*
|
||||
* Interrupts will be enabled. The RT enabled and the "RT-run-time"
|
||||
* part of the API will be opened for the user and parts that need the
|
||||
* RT to be stopped are no longer available. After the RT has been
|
||||
* started the configuration function can not be called.
|
||||
*/
|
||||
extern int gr1553rt_start(void *rt);
|
||||
|
||||
/* Get Status of the RT core. See data structure gr1553rt_status for more
|
||||
* information about the result. It can be used to read out:
|
||||
* - time information
|
||||
* - sync information
|
||||
* - bus & RT status
|
||||
*
|
||||
* \param status Pointer to where the status words will be stored. They
|
||||
* are stored according to the gr1553rt_status data structure.
|
||||
*/
|
||||
extern void gr1553rt_status(void *rt, struct gr1553rt_status *status);
|
||||
|
||||
/* Stop RT communication. Only possible to stop an already started RT device.
|
||||
* Interrupts are disabled and the RT Enable bit cleared.
|
||||
*/
|
||||
extern void gr1553rt_stop(void *rt);
|
||||
|
||||
/* Set RT vector and/or bit word.
|
||||
*
|
||||
* - Vector Word is used in response to "Transmit vector word" BC commands
|
||||
* - Bit Word is used in response to "Transmit bit word" BC commands
|
||||
*
|
||||
*
|
||||
* \param mask Bit-Mask, bits that are 1 will result in that bit in the
|
||||
* words register being overwritten with the value of words
|
||||
* \param words Bits 31..16: Bit Word. Bits 15..0: Vector Word.
|
||||
*
|
||||
* Operation:
|
||||
* hw_words = (hw_words & ~mask) | (words & mask)
|
||||
*/
|
||||
extern void gr1553rt_set_vecword(
|
||||
void *rt,
|
||||
unsigned int mask,
|
||||
unsigned int words
|
||||
);
|
||||
|
||||
/* Set selectable bits of the "Bus Status Register". The bits written
|
||||
* is determined by the "mask" bit-mask. Operation:
|
||||
*
|
||||
* bus_status = (bus_status & ~mask) | (sts & mask)
|
||||
*
|
||||
*/
|
||||
extern void gr1553rt_set_bussts(void *rt, unsigned int mask, unsigned int sts);
|
||||
|
||||
/* Read up to MAX number of entries in eventlog log.
|
||||
*
|
||||
* \param dst Destination address for event log entries
|
||||
* \param max Maximal number of event log entries that an be stored into dst
|
||||
*
|
||||
* Return
|
||||
* negative Failure
|
||||
* zero No entries available at the moment
|
||||
* positive Number of entries copied into dst
|
||||
*/
|
||||
extern int gr1553rt_evlog_read(void *rt, unsigned int *dst, int max);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
227
c/src/lib/libbsp/sparc/shared/include/gradcdac.h
Normal file
227
c/src/lib/libbsp/sparc/shared/include/gradcdac.h
Normal file
@@ -0,0 +1,227 @@
|
||||
/* ADC / DAC (GRADCDAC) 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.com/license/LICENSE.
|
||||
*/
|
||||
|
||||
#ifndef __GRADCDAC_H__
|
||||
#define __GRADCDAC_H__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
struct gradcdac_regs {
|
||||
volatile unsigned int config; /* 0x00 Configuration Register */
|
||||
volatile unsigned int status; /* 0x04 Status Register */
|
||||
int unused0[2];
|
||||
volatile unsigned int adc_din; /* 0x10 ADC Data Input Register */
|
||||
volatile unsigned int dac_dout; /* 0x14 DAC Data Output Register */
|
||||
int unused1[2];
|
||||
volatile unsigned int adrin; /* 0x20 Address Input Register */
|
||||
volatile unsigned int adrout; /* 0x24 Address Output Register */
|
||||
volatile unsigned int adrdir; /* 0x28 Address Direction Register */
|
||||
int unused2[1];
|
||||
volatile unsigned int data_in; /* 0x30 Data Input Register */
|
||||
volatile unsigned int data_out; /* 0x34 Data Output Register */
|
||||
volatile unsigned int data_dir; /* 0x38 Data Direction Register */
|
||||
};
|
||||
|
||||
#define GRADCDAC_CFG_DACWS 0x00f80000
|
||||
#define GRADCDAC_CFG_WRPOL 0x00040000
|
||||
#define GRADCDAC_CFG_DACDW 0x00030000
|
||||
#define GRADCDAC_CFG_ADCWS 0x0000f800
|
||||
#define GRADCDAC_CFG_RCPOL 0x00000400
|
||||
#define GRADCDAC_CFG_CSMODE 0x00000300
|
||||
#define GRADCDAC_CFG_CSPOL 0x00000080
|
||||
#define GRADCDAC_CFG_RDYMODE 0x00000040
|
||||
#define GRADCDAC_CFG_RDYPOL 0x00000020
|
||||
#define GRADCDAC_CFG_TRIGPOL 0x00000010
|
||||
#define GRADCDAC_CFG_TRIGMODE 0x0000000c
|
||||
#define GRADCDAC_CFG_ADCDW 0x00000003
|
||||
|
||||
#define GRADCDAC_CFG_DACWS_BIT 19
|
||||
#define GRADCDAC_CFG_WRPOL_BIT 18
|
||||
#define GRADCDAC_CFG_DACDW_BIT 16
|
||||
#define GRADCDAC_CFG_ADCWS_BIT 11
|
||||
#define GRADCDAC_CFG_RCPOL_BIT 10
|
||||
#define GRADCDAC_CFG_CSMODE_BIT 8
|
||||
#define GRADCDAC_CFG_CSPOL_BIT 7
|
||||
#define GRADCDAC_CFG_RDYMODE_BIT 6
|
||||
#define GRADCDAC_CFG_RDYPOL_BIT 5
|
||||
#define GRADCDAC_CFG_TRIGPOL_BIT 4
|
||||
#define GRADCDAC_CFG_TRIGMODE_BIT 2
|
||||
#define GRADCDAC_CFG_ADCDW_BIT 0
|
||||
|
||||
#define GRADCDAC_STATUS_DACNO 0x40
|
||||
#define GRADCDAC_STATUS_DACRDY 0x20
|
||||
#define GRADCDAC_STATUS_DACON 0x10
|
||||
#define GRADCDAC_STATUS_ADCTO 0x08
|
||||
#define GRADCDAC_STATUS_ADCNO 0x04
|
||||
#define GRADCDAC_STATUS_ADCRDY 0x02
|
||||
#define GRADCDAC_STATUS_ADCON 0x01
|
||||
|
||||
#define GRADCDAC_STATUS_DACNO_BIT 6
|
||||
#define GRADCDAC_STATUS_DACRDY_BIT 5
|
||||
#define GRADCDAC_STATUS_DACON_BIT 4
|
||||
#define GRADCDAC_STATUS_ADCTO_BIT 3
|
||||
#define GRADCDAC_STATUS_ADCNO_BIT 2
|
||||
#define GRADCDAC_STATUS_ADCRDY_BIT 1
|
||||
#define GRADCDAC_STATUS_ADCON_BIT 0
|
||||
|
||||
#define GRADCDAC_IRQ_DAC 1
|
||||
#define GRADCDAC_IRQ_ADC 0
|
||||
|
||||
struct gradcdac_config {
|
||||
unsigned char dac_ws;
|
||||
char wr_pol;
|
||||
unsigned char dac_dw;
|
||||
unsigned char adc_ws;
|
||||
char rc_pol;
|
||||
unsigned char cs_mode;
|
||||
char cs_pol;
|
||||
char ready_mode;
|
||||
char ready_pol;
|
||||
char trigg_pol;
|
||||
unsigned char trigg_mode;
|
||||
unsigned char adc_dw;
|
||||
};
|
||||
|
||||
extern void *gradcdac_open(char *devname);
|
||||
|
||||
extern void gradcdac_set_config(void *cookie, struct gradcdac_config *cfg);
|
||||
|
||||
extern void gradcdac_get_config(void *cookie, struct gradcdac_config *cfg);
|
||||
|
||||
extern void gradcdac_set_cfg(void *cookie, unsigned int config);
|
||||
|
||||
extern unsigned int gradcdac_get_cfg(void *cookie);
|
||||
|
||||
extern unsigned int gradcdac_get_status(void *cookie);
|
||||
|
||||
static int __inline__ gradcdac_DAC_ReqRej(unsigned int status)
|
||||
{
|
||||
return (status & GRADCDAC_STATUS_DACNO);
|
||||
}
|
||||
|
||||
static int __inline__ gradcdac_DAC_isCompleted(unsigned int status)
|
||||
{
|
||||
return (status & GRADCDAC_STATUS_DACRDY);
|
||||
}
|
||||
|
||||
static int __inline__ gradcdac_DAC_isOngoing(unsigned int status)
|
||||
{
|
||||
return (status & GRADCDAC_STATUS_DACON);
|
||||
}
|
||||
|
||||
static int __inline__ gradcdac_ADC_isTimeouted(unsigned int status)
|
||||
{
|
||||
return (status & GRADCDAC_STATUS_ADCTO);
|
||||
}
|
||||
|
||||
static int __inline__ gradcdac_ADC_ReqRej(unsigned int status)
|
||||
{
|
||||
return (status & GRADCDAC_STATUS_ADCNO);
|
||||
}
|
||||
|
||||
static int __inline__ gradcdac_ADC_isCompleted(unsigned int status)
|
||||
{
|
||||
return (status & GRADCDAC_STATUS_ADCRDY);
|
||||
}
|
||||
|
||||
static int __inline__ gradcdac_ADC_isOngoing(unsigned int status)
|
||||
{
|
||||
return (status & GRADCDAC_STATUS_ADCON);
|
||||
}
|
||||
|
||||
#define GRADCDAC_ISR_BOTH 3
|
||||
#define GRADCDAC_ISR_DAC 2
|
||||
#define GRADCDAC_ISR_ADC 1
|
||||
|
||||
/* 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.
|
||||
*/
|
||||
extern int gradcdac_install_irq_handler
|
||||
(void *cookie, int adc, void (*isr)(void *cookie, void *arg), void *arg);
|
||||
|
||||
extern void gradcdac_uninstall_irq_handler(void *cookie, int adc);
|
||||
|
||||
/* 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.
|
||||
*/
|
||||
extern void gradcdac_adc_convert_start(void *cookie);
|
||||
|
||||
/* 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.
|
||||
*/
|
||||
extern int gradcdac_adc_convert_try(void *cookie, unsigned short *digital_value);
|
||||
|
||||
/* Waits until the ADC circuity has finished a digital to analogue
|
||||
* conversion. The Waiting is implemented as a busy loop utilizing
|
||||
* 100% CPU load.
|
||||
*
|
||||
* \return zero = Conversion ok
|
||||
* negative = Conversion request failed.
|
||||
*/
|
||||
extern int gradcdac_adc_convert(void *cookie, unsigned short *digital_value);
|
||||
|
||||
/* 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.
|
||||
*/
|
||||
extern int gradcdac_dac_convert_try(void *cookie, unsigned short digital_value);
|
||||
|
||||
/* Initializes a digital to analogue conversion by waiting until
|
||||
* previous conversions is finished before procceding with the
|
||||
* conversion. The Waiting is implemented as a busy loop utilizing
|
||||
* 100% CPU load.
|
||||
*/
|
||||
extern void gradcdac_dac_convert(void *cookie, unsigned short digital_value);
|
||||
|
||||
extern unsigned int gradcdac_get_adrinput(void *cookie);
|
||||
extern void gradcdac_set_adrinput(void *cookie, unsigned int input);
|
||||
|
||||
extern unsigned int gradcdac_get_adroutput(void *cookie);
|
||||
extern void gradcdac_set_adroutput(void *cookie, unsigned int output);
|
||||
|
||||
extern unsigned int gradcdac_get_adrdir(void *cookie);
|
||||
extern void gradcdac_set_adrdir(void *cookie, unsigned int dir);
|
||||
|
||||
extern unsigned int gradcdac_get_datainput(void *cookie);
|
||||
extern void gradcdac_set_datainput(void *cookie, unsigned int input);
|
||||
|
||||
extern unsigned int gradcdac_get_dataoutput(void *cookie);
|
||||
extern void gradcdac_set_dataoutput(void *cookie, unsigned int output);
|
||||
|
||||
extern unsigned int gradcdac_get_datadir(void *cookie);
|
||||
extern void gradcdac_set_datadir(void *cookie, unsigned int dir);
|
||||
|
||||
/* Show one or all GRADCDAC cores. If cookie is NULL all GRADCDAC's are shown */
|
||||
extern void grAdcDacShow(void *cookie);
|
||||
|
||||
/* Register Driver routine */
|
||||
extern void gradcdac_register_drv (void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
92
c/src/lib/libbsp/sparc/shared/include/grascs.h
Normal file
92
c/src/lib/libbsp/sparc/shared/include/grascs.h
Normal file
@@ -0,0 +1,92 @@
|
||||
/*
|
||||
* Header file for 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.com/license/LICENSE.
|
||||
*/
|
||||
|
||||
#ifndef __GRASCS_H__
|
||||
#define __GRASCS_H__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Minimum and maximum system frequency */
|
||||
#define GRASCS_MIN_SFREQ 10000
|
||||
#define GRASCS_MAX_SFREQ 255000
|
||||
|
||||
/* Default, minimum and maximum ETR pulse frequency */
|
||||
#define GRASCS_DEFAULT_ETRFREQ 10
|
||||
#define GRASCS_MIN_ETRFREQ 1
|
||||
#define GRASCS_MAX_ETRFREQ 100
|
||||
|
||||
/* Maximum number of external time markers */
|
||||
#define GRASCS_MAX_TMS 6
|
||||
|
||||
/* Error codes */
|
||||
#define GRASCS_ERROR_STARTSTOP 1 /* Serial/synch interface is running/stopped */
|
||||
#define GRASCS_ERROR_TRANSACTIVE 2 /* Busy with transaction */
|
||||
#define GRASCS_ERROR_CAPFAULT 3 /* Core capabilities prohibit request */
|
||||
|
||||
/* Command register */
|
||||
#define GRASCS_CMD_RESET (1 << 0)
|
||||
#define GRASCS_CMD_STARTSTOP (1 << 1)
|
||||
#define GRASCS_CMD_ESTARTSTOP (1 << 2)
|
||||
#define GRASCS_CMD_SENDTM (1 << 3)
|
||||
#define GRASCS_CMD_ETRCTRL (7 << 4)
|
||||
#define GRASCS_CMD_ETRCTRL_BITS 4
|
||||
#define GRASCS_CMD_SLAVESEL (15 << 8)
|
||||
#define GRASCS_CMD_SLAVESEL_BITS 8
|
||||
#define GRASCS_CMD_TCDONE (1 << 12)
|
||||
#define GRASCS_CMD_TMDONE (1 << 13)
|
||||
#define GRASCS_CMD_US1 (255 << 16)
|
||||
#define GRASCS_CMD_US1_BITS 16
|
||||
#define GRASCS_CMD_US1C (1 << 24)
|
||||
|
||||
/* Clock scale register */
|
||||
#define GRASCS_CLK_ETRFREQ_BITS 12
|
||||
|
||||
/* Status register */
|
||||
#define GRASCS_STS_RUNNING (1 << 0)
|
||||
#define GRASCS_STS_ERUNNING (1 << 1)
|
||||
#define GRASCS_STS_TCDONE (1 << 4)
|
||||
#define GRASCS_STS_TMDONE (1 << 5)
|
||||
#define GRASCS_STS_DBITS_BITS 8
|
||||
#define GRASCS_STS_NSLAVES_BITS 13
|
||||
#define GRASCS_STS_USCONF_BITS 18
|
||||
#define GRASCS_STS_TMCONF_BITS 19
|
||||
|
||||
extern int ASCS_init();
|
||||
|
||||
extern int ASCS_input_select(int slave);
|
||||
|
||||
extern int ASCS_etr_select(int etr, int freq);
|
||||
|
||||
extern void ASCS_start(void);
|
||||
|
||||
extern void ASCS_stop(void);
|
||||
|
||||
extern int ASCS_iface_status(void);
|
||||
|
||||
extern int ASCS_TC_send(int *word);
|
||||
|
||||
extern int ASCS_TC_send_block(int *block, int ntrans);
|
||||
|
||||
extern void ASCS_TC_sync_start(void);
|
||||
|
||||
extern void ASCS_TC_sync_stop(void);
|
||||
|
||||
extern int ASCS_TM_recv(int *word);
|
||||
|
||||
extern int ASCS_TM_recv_block(int *block, int ntrans);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
168
c/src/lib/libbsp/sparc/shared/include/grctm.h
Normal file
168
c/src/lib/libbsp/sparc/shared/include/grctm.h
Normal file
@@ -0,0 +1,168 @@
|
||||
/* 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.com/license/LICENSE.
|
||||
*/
|
||||
|
||||
#ifndef __GRCTM_H__
|
||||
#define __GRCTM_H__
|
||||
|
||||
#define DAT0_IRQ 0x1
|
||||
#define DAT1_IRQ 0x2
|
||||
#define DAT2_IRQ 0x4
|
||||
#define PULSE0_IRQ 0x10
|
||||
#define PULSE1_IRQ 0x20
|
||||
#define PULSE2_IRQ 0x40
|
||||
#define PULSE3_IRQ 0x80
|
||||
#define PULSE4_IRQ 0x100
|
||||
#define PULSE5_IRQ 0x200
|
||||
#define PULSE6_IRQ 0x400
|
||||
#define PULSE7_IRQ 0x800
|
||||
|
||||
struct grctm_regs {
|
||||
volatile unsigned int grr;
|
||||
volatile unsigned int gcr;
|
||||
volatile unsigned int gsr;
|
||||
volatile unsigned int unused[2];
|
||||
volatile unsigned int pfr;
|
||||
volatile unsigned int etcr;
|
||||
volatile unsigned int etfr;
|
||||
volatile unsigned int dcr0;
|
||||
volatile unsigned int dfr0;
|
||||
volatile unsigned int dcr1;
|
||||
volatile unsigned int dfr1;
|
||||
volatile unsigned int dcr2;
|
||||
volatile unsigned int dfr2;
|
||||
volatile unsigned int stcr;
|
||||
volatile unsigned int stfr;
|
||||
volatile unsigned int pdr[8];
|
||||
volatile unsigned int pimsr;
|
||||
volatile unsigned int pimr;
|
||||
volatile unsigned int pisr;
|
||||
volatile unsigned int pir;
|
||||
volatile unsigned int imr;
|
||||
volatile unsigned int picr;
|
||||
volatile unsigned int unused1[2];
|
||||
volatile unsigned int etir;
|
||||
volatile unsigned int fsir;
|
||||
volatile unsigned int serconf;
|
||||
volatile unsigned int unused2;
|
||||
volatile unsigned int twsc;
|
||||
volatile unsigned int twadj;
|
||||
volatile unsigned int twtx;
|
||||
volatile unsigned int twrx;
|
||||
};
|
||||
|
||||
struct grctm_stats {
|
||||
|
||||
/* IRQ Stats */
|
||||
unsigned int nirqs;
|
||||
unsigned int pulse;
|
||||
};
|
||||
|
||||
/* Function ISR callback prototype */
|
||||
typedef void (*grctm_isr_t)(unsigned int pimr, void *data);
|
||||
|
||||
/* Open a GRCTM device by minor number. */
|
||||
extern void *grctm_open(int minor);
|
||||
|
||||
/* Close a previously opened GRCTM device */
|
||||
extern void grctm_close(void *spwcuc);
|
||||
|
||||
/* Hardware Reset of GRCTM */
|
||||
extern int grctm_reset(void *grctm);
|
||||
|
||||
/* Enable Interrupts at Interrupt controller */
|
||||
extern void grctm_int_enable(void *grctm);
|
||||
|
||||
/* Disable Interrupts at Interrupt controller */
|
||||
extern void grctm_int_disable(void *grctm);
|
||||
|
||||
/* Clear Statistics gathered by the driver */
|
||||
extern void grctm_clr_stats(void *grctm);
|
||||
|
||||
/* Get Statistics gathered by the driver */
|
||||
extern void grctm_get_stats(void *grctm, struct grctm_stats *stats);
|
||||
|
||||
/* Register an Interrupt handler and custom data, the function call is
|
||||
* removed by setting func to NULL.
|
||||
*/
|
||||
extern void grctm_int_register(void *grctm, grctm_isr_t func, void *data);
|
||||
|
||||
/* Enable external synchronisation (from spwcuc) */
|
||||
extern void grctm_enable_ext_sync(void *grctm);
|
||||
|
||||
/* Disable external synchronisation (from spwcuc) */
|
||||
extern void grctm_disable_ext_sync(void *grctm);
|
||||
|
||||
/* Enable TimeWire synchronisation */
|
||||
extern void grctm_enable_tw_sync(void *grctm);
|
||||
|
||||
/* Disable TimeWire synchronisation */
|
||||
extern void grctm_disable_tw_sync(void *grctm);
|
||||
|
||||
/* Disable frequency synthesizer from driving ET */
|
||||
extern void grctm_disable_fs(void *grctm);
|
||||
|
||||
/* Enable frequency synthesizer to drive ET */
|
||||
extern void grctm_enable_fs(void *grctm);
|
||||
|
||||
/* Return elapsed coarse time */
|
||||
extern unsigned int grctm_get_et_coarse(void *grctm);
|
||||
|
||||
/* Return elapsed fine time */
|
||||
extern unsigned int grctm_get_et_fine(void *grctm);
|
||||
|
||||
/* Return elapsed time (coarse and fine) */
|
||||
extern unsigned long long grctm_get_et(void *grctm);
|
||||
|
||||
/* Return 1 if specified datation has been latched */
|
||||
extern int grctm_is_dat_latched(void *grctm, int dat);
|
||||
|
||||
/* Set triggering edge of datation input */
|
||||
extern void grctm_set_dat_edge(void *grctm, int dat, int edge);
|
||||
|
||||
/* Return latched datation coarse time */
|
||||
extern unsigned int grctm_get_dat_coarse(void *grctm, int dat);
|
||||
|
||||
/* Return latched datation fine time */
|
||||
extern unsigned int grctm_get_dat_fine(void *grctm, int dat);
|
||||
|
||||
/* Return latched datation ET */
|
||||
extern unsigned long long grctm_get_dat_et(void *grctm, int dat);
|
||||
|
||||
/* Return current pulse configuration */
|
||||
extern unsigned int grctm_get_pulse_reg(void *grctm, int pulse);
|
||||
|
||||
/* Set pulse register */
|
||||
extern void grctm_set_pulse_reg(void *grctm, int pulse, unsigned int val);
|
||||
|
||||
/* Configure pulse: pp = period, pw = width, pl = level, en = enable */
|
||||
extern void grctm_cfg_pulse(void *grctm, int pulse, int pp, int pw, int pl, int en);
|
||||
|
||||
/* Enable pulse output */
|
||||
extern void grctm_enable_pulse(void *grctm, int pulse);
|
||||
|
||||
/* Disable pulse output */
|
||||
extern void grctm_disable_pulse(void *grctm, int pulse);
|
||||
|
||||
/* Clear interrupts */
|
||||
extern void grctm_clear_irqs(void *grctm, int irqs);
|
||||
|
||||
/* Enable interrupts */
|
||||
extern void grctm_enable_irqs(void *grctm, int irqs);
|
||||
|
||||
/* Set Frequency synthesizer increment */
|
||||
void grctm_set_fs_incr(void *grctm, int incr);
|
||||
|
||||
/* Set ET increment */
|
||||
void grctm_set_et_incr(void *grctm, int incr);
|
||||
|
||||
/* Register the GRCTM driver to Driver Manager */
|
||||
extern void grctm_register(void);
|
||||
|
||||
#endif
|
||||
145
c/src/lib/libbsp/sparc/shared/include/greth.h
Normal file
145
c/src/lib/libbsp/sparc/shared/include/greth.h
Normal file
@@ -0,0 +1,145 @@
|
||||
/*
|
||||
* Cobham Gaisler 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.com/license/LICENSE.
|
||||
*/
|
||||
|
||||
#ifndef __GRETH_H__
|
||||
#define __GRETH_H__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Ethernet configuration registers */
|
||||
|
||||
typedef struct _greth_regs {
|
||||
volatile uint32_t ctrl; /* Ctrl Register */
|
||||
volatile uint32_t status; /* Status Register */
|
||||
volatile uint32_t mac_addr_msb; /* Bit 47-32 of MAC address */
|
||||
volatile uint32_t mac_addr_lsb; /* Bit 31-0 of MAC address */
|
||||
volatile uint32_t mdio_ctrl; /* MDIO control and status */
|
||||
volatile uint32_t txdesc; /* Transmit descriptor pointer */
|
||||
volatile uint32_t rxdesc; /* Receive descriptor pointer */
|
||||
} greth_regs;
|
||||
|
||||
#define GRETH_TOTAL_BD 128
|
||||
#define GRETH_MAXBUF_LEN 1520
|
||||
|
||||
/* Tx BD */
|
||||
#define GRETH_TXD_ENABLE 0x0800 /* Tx BD Enable */
|
||||
#define GRETH_TXD_WRAP 0x1000 /* Tx BD Wrap (last BD) */
|
||||
#define GRETH_TXD_IRQ 0x2000 /* Tx BD IRQ Enable */
|
||||
#define GRETH_TXD_MORE 0x20000 /* Tx BD More (more descs for packet) */
|
||||
#define GRETH_TXD_IPCS 0x40000 /* Tx BD insert ip chksum */
|
||||
#define GRETH_TXD_TCPCS 0x80000 /* Tx BD insert tcp chksum */
|
||||
#define GRETH_TXD_UDPCS 0x100000 /* Tx BD insert udp chksum */
|
||||
|
||||
#define GRETH_TXD_UNDERRUN 0x4000 /* Tx BD Underrun Status */
|
||||
#define GRETH_TXD_RETLIM 0x8000 /* Tx BD Retransmission Limit Status */
|
||||
#define GRETH_TXD_LATECOL 0x10000 /* Tx BD Late Collision */
|
||||
|
||||
#define GRETH_TXD_STATS (GRETH_TXD_UNDERRUN | \
|
||||
GRETH_TXD_RETLIM | \
|
||||
GRETH_TXD_LATECOL)
|
||||
|
||||
#define GRETH_TXD_CS (GRETH_TXD_IPCS | \
|
||||
GRETH_TXD_TCPCS | \
|
||||
GRETH_TXD_UDPCS)
|
||||
|
||||
/* Rx BD */
|
||||
#define GRETH_RXD_ENABLE 0x0800 /* Rx BD Enable */
|
||||
#define GRETH_RXD_WRAP 0x1000 /* Rx BD Wrap (last BD) */
|
||||
#define GRETH_RXD_IRQ 0x2000 /* Rx BD IRQ Enable */
|
||||
|
||||
#define GRETH_RXD_DRIBBLE 0x4000 /* Rx BD Dribble Nibble Status */
|
||||
#define GRETH_RXD_TOOLONG 0x8000 /* Rx BD Too Long Status */
|
||||
#define GRETH_RXD_CRCERR 0x10000 /* Rx BD CRC Error Status */
|
||||
#define GRETH_RXD_OVERRUN 0x20000 /* Rx BD Overrun Status */
|
||||
#define GRETH_RXD_LENERR 0x40000 /* Rx BD Length Error */
|
||||
#define GRETH_RXD_ID 0x40000 /* Rx BD IP Detected */
|
||||
#define GRETH_RXD_IR 0x40000 /* Rx BD IP Chksum Error */
|
||||
#define GRETH_RXD_UD 0x40000 /* Rx BD UDP Detected*/
|
||||
#define GRETH_RXD_UR 0x40000 /* Rx BD UDP Chksum Error */
|
||||
#define GRETH_RXD_TD 0x40000 /* Rx BD TCP Detected */
|
||||
#define GRETH_RXD_TR 0x40000 /* Rx BD TCP Chksum Error */
|
||||
|
||||
|
||||
#define GRETH_RXD_STATS (GRETH_RXD_OVERRUN | \
|
||||
GRETH_RXD_DRIBBLE | \
|
||||
GRETH_RXD_TOOLONG | \
|
||||
GRETH_RXD_CRCERR)
|
||||
|
||||
/* CTRL Register */
|
||||
#define GRETH_CTRL_TXEN 0x00000001 /* Transmit Enable */
|
||||
#define GRETH_CTRL_RXEN 0x00000002 /* Receive Enable */
|
||||
#define GRETH_CTRL_TXIRQ 0x00000004 /* Transmit Enable */
|
||||
#define GRETH_CTRL_RXIRQ 0x00000008 /* Receive Enable */
|
||||
#define GRETH_CTRL_FULLD 0x00000010 /* Full Duplex */
|
||||
#define GRETH_CTRL_PRO 0x00000020 /* Promiscuous (receive all) */
|
||||
#define GRETH_CTRL_RST 0x00000040 /* Reset MAC */
|
||||
|
||||
/* Status Register */
|
||||
#define GRETH_STATUS_RXERR 0x00000001 /* Receive Error */
|
||||
#define GRETH_STATUS_TXERR 0x00000002 /* Transmit Error IRQ */
|
||||
#define GRETH_STATUS_RXIRQ 0x00000004 /* Receive Frame IRQ */
|
||||
#define GRETH_STATUS_TXIRQ 0x00000008 /* Transmit Error IRQ */
|
||||
#define GRETH_STATUS_RXAHBERR 0x00000010 /* Receiver AHB Error */
|
||||
#define GRETH_STATUS_TXAHBERR 0x00000020 /* Transmitter AHB Error */
|
||||
|
||||
/* MDIO Control */
|
||||
#define GRETH_MDIO_WRITE 0x00000001 /* MDIO Write */
|
||||
#define GRETH_MDIO_READ 0x00000002 /* MDIO Read */
|
||||
#define GRETH_MDIO_LINKFAIL 0x00000004 /* MDIO Link failed */
|
||||
#define GRETH_MDIO_BUSY 0x00000008 /* MDIO Link Busy */
|
||||
#define GRETH_MDIO_REGADR 0x000007C0 /* Register Address */
|
||||
#define GRETH_MDIO_PHYADR 0x0000F800 /* PHY address */
|
||||
#define GRETH_MDIO_DATA 0xFFFF0000 /* MDIO DATA */
|
||||
|
||||
|
||||
/* MII registers */
|
||||
#define GRETH_MII_EXTADV_1000FD 0x00000200
|
||||
#define GRETH_MII_EXTADV_1000HD 0x00000100
|
||||
#define GRETH_MII_EXTPRT_1000FD 0x00000800
|
||||
#define GRETH_MII_EXTPRT_1000HD 0x00000400
|
||||
|
||||
#define GRETH_MII_100T4 0x00000200
|
||||
#define GRETH_MII_100TXFD 0x00000100
|
||||
#define GRETH_MII_100TXHD 0x00000080
|
||||
#define GRETH_MII_10FD 0x00000040
|
||||
#define GRETH_MII_10HD 0x00000020
|
||||
|
||||
|
||||
/* Attach routine */
|
||||
|
||||
void greth_register_drv(void);
|
||||
|
||||
/* PHY data */
|
||||
struct phy_device_info
|
||||
{
|
||||
int vendor;
|
||||
int device;
|
||||
int rev;
|
||||
|
||||
int adv;
|
||||
int part;
|
||||
|
||||
int extadv;
|
||||
int extpart;
|
||||
};
|
||||
|
||||
/*
|
||||
#ifdef CPU_U32_FIX
|
||||
void ipalign(struct mbuf *m);
|
||||
#endif
|
||||
|
||||
*/
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
25
c/src/lib/libbsp/sparc/shared/include/grgpio.h
Normal file
25
c/src/lib/libbsp/sparc/shared/include/grgpio.h
Normal file
@@ -0,0 +1,25 @@
|
||||
/*
|
||||
* 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.com/license/LICENSE.
|
||||
*/
|
||||
|
||||
#ifndef __GRGPIO_H__
|
||||
#define __GRGPIO_H__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
extern void grgpio_register_drv (void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
127
c/src/lib/libbsp/sparc/shared/include/grpwm.h
Normal file
127
c/src/lib/libbsp/sparc/shared/include/grpwm.h
Normal file
@@ -0,0 +1,127 @@
|
||||
/*
|
||||
* 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.com/license/LICENSE.
|
||||
*/
|
||||
|
||||
#ifndef __GRPWM_H__
|
||||
#define __GRPWM_H__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
extern void grpwm_register_drv (void);
|
||||
|
||||
#define GRPWM_IOCTL_GET_CAP 1 /* Get Capabilities */
|
||||
#define GRPWM_IOCTL_SET_CONFIG 2 /* Configure one PWM Channel */
|
||||
#define GRPWM_IOCTL_SET_SCALER 3 /* Set one scaler */
|
||||
#define GRPWM_IOCTL_UPDATE 4 /* Set current period and compare value */
|
||||
#define GRPWM_IOCTL_IRQ 5 /* Set up IRQ handling */
|
||||
|
||||
/*** Argument for GRPWM_IOCTL_GET_CAP ***/
|
||||
|
||||
/* The Capability of the PWM core */
|
||||
struct grpwm_ioctl_cap {
|
||||
int channel_cnt; /* Number of channels */
|
||||
unsigned int pwm; /* Capability1 register */
|
||||
unsigned int wave; /* Capability2 register, Wave form capabilities of last PWM channel, otherwise 0 */
|
||||
};
|
||||
|
||||
/*** Argument for GRPWM_IOCTL_GET_CONFIG and GRPWM_IOCTL_SET_CONFIG ***/
|
||||
|
||||
/* Config One PWM */
|
||||
struct grpwm_ioctl_config {
|
||||
unsigned int channel; /* Select channel to configure */
|
||||
|
||||
/* Specific for one PWM channel */
|
||||
unsigned int options; /* PWM options */
|
||||
unsigned char dbscaler; /* value greater than 15 disable Dead band */
|
||||
unsigned char scaler_index; /* Select scaler used by PWM channel */
|
||||
|
||||
/* IRQ Setup */
|
||||
unsigned char irqscaler; /* IRQ scaler */
|
||||
void *isr_arg; /* Argument of IRQ handler */
|
||||
void (*isr)(int channel, void *arg); /* Interrupt service routine for this PWM Channel */
|
||||
|
||||
/* Waveform set up */
|
||||
int wave_activate; /* Enables Waveform functionality */
|
||||
unsigned int wave_synccfg; /* Bits [29,30,31] is written into Wave-Config register */
|
||||
unsigned int wave_sync; /* Sets sync compare register */
|
||||
unsigned int *wave_data; /* If not NULL, the Wave RAM is filled with data */
|
||||
unsigned int wave_data_length; /* Length of Wave RAM Data, Also used for wstopaddr */
|
||||
};
|
||||
|
||||
#define GRPWM_CONFIG_OPTION_FLIP 0x04000000 /* Set this to Flip PWM output pair */
|
||||
#define GRPWM_CONFIG_OPTION_DEAD_BAND 0x00200000 /* Dead Band enable */
|
||||
#define GRPWM_CONFIG_OPTION_SYMMETRIC 0x00000040 /* If not defined, asymmetric */
|
||||
#define GRPWM_CONFIG_OPTION_ASYMMERTIC 0
|
||||
#define GRPWM_CONFIG_OPTION_DUAL 0x00000020 /* Dual Compare Enable */
|
||||
#define GRPWM_CONFIG_OPTION_PAIR 0x00000004 /* PWM Pair Enable */
|
||||
#define GRPWM_CONFIG_OPTION_SINGLE 0x00000000 /* PWM Pair Disable */
|
||||
#define GRPWM_CONFIG_OPTION_POLARITY_HIGH 0x00000002 /* PWM Polarity HIGH */
|
||||
#define GRPWM_CONFIG_OPTION_POLARITY_LOW 0x00000000 /* PWM Polarity LOW */
|
||||
|
||||
#define GRPWM_CONFIG_OPTION_MASK ( \
|
||||
GRPWM_CONFIG_OPTION_DEAD_BAND | GRPWM_CONFIG_OPTION_SYMMETRIC | \
|
||||
GRPWM_CONFIG_OPTION_DUAL | GRPWM_CONFIG_OPTION_PAIR | \
|
||||
GRPWM_CONFIG_OPTION_POLARITY_HIGH \
|
||||
)
|
||||
|
||||
/*** Argument for GPPWM_IOCTL_SET_SCALER ***/
|
||||
|
||||
struct grpwm_ioctl_scaler {
|
||||
unsigned int index_mask;/* Scaler update index mask, bit 0 = Scaler 0, bit 1 = Scaler 1 */
|
||||
unsigned int values[8]; /* Scaler update values, values[N] is stored into scaler N, if mask & 1<<N is set */
|
||||
};
|
||||
|
||||
/*** Argument for GRPWM_IOCTL_UPDATE ***/
|
||||
|
||||
#define GRPWM_UPDATE_OPTION_ENABLE 0x01 /* Enable the PWM core */
|
||||
#define GRPWM_UPDATE_OPTION_DISABLE 0x02 /* Disable the PWM core */
|
||||
#define GRPWM_UPDATE_OPTION_PERIOD 0x04 /* Update period register */
|
||||
#define GRPWM_UPDATE_OPTION_COMP 0x08 /* Update Compare register */
|
||||
#define GRPWM_UPDATE_OPTION_DBCOMP 0x10 /* Update Dead band register */
|
||||
#define GRPWM_UPDATE_OPTION_FIX 0x20 /* Update fix output pins (bypass PWM) */
|
||||
|
||||
/* FIX PIN bit-mask */
|
||||
#define GRPWM_UPDATE_FIX_ENABLE 1 /* Enable force ouput */
|
||||
#define GRPWM_UPDATE_FIX_DISABLE 0 /* Disable force ouput */
|
||||
#define GRPWM_UPDATE_FIX_0_LOW 0 /* PIN 0 OUPUT: LOW */
|
||||
#define GRPWM_UPDATE_FIX_0_HIGH 2 /* PIN 0 OUPUT: HIGH */
|
||||
#define GRPWM_UPDATE_FIX_1_LOW 0 /* PIN 1 OUPUT: LOW */
|
||||
#define GRPWM_UPDATE_FIX_1_HIGH 4 /* PIN 1 OUPUT: HIGH */
|
||||
|
||||
struct grpwm_ioctl_update_chan {
|
||||
unsigned int options; /* Select what is updated */
|
||||
unsigned int period; /* Period register content */
|
||||
unsigned int compare; /* Compare register content */
|
||||
unsigned int dbcomp; /* Dead band register content */
|
||||
unsigned char fix; /* Bit-mask that select output on one or two PWM
|
||||
* output pins. Depends on PAIR config value.
|
||||
*/
|
||||
};
|
||||
struct grpwm_ioctl_update {
|
||||
unsigned char chanmask; /* Bit Mask select channels */
|
||||
struct grpwm_ioctl_update_chan channels[8]; /* */
|
||||
};
|
||||
|
||||
/*** Argument for GPPWM_IOCTL_IRQ ***/
|
||||
|
||||
#define GRPWM_IRQ_DISABLE 0 /* Disable IRQ */
|
||||
#define GRPWM_IRQ_PERIOD 1 /* Enable IRQ on period match */
|
||||
#define GRPWM_IRQ_COMPARE 3 /* Enable IRQ on Compare Match */
|
||||
#define GRPWM_IRQ_CLEAR 0x10 /* Clear any pending IRQ on GRPWM and IRQ controller */
|
||||
|
||||
#define GRPWM_IRQ_CHAN 0x100 /* Channel N is selected, by adding 0x100*N */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
148
c/src/lib/libbsp/sparc/shared/include/grslink.h
Normal file
148
c/src/lib/libbsp/sparc/shared/include/grslink.h
Normal file
@@ -0,0 +1,148 @@
|
||||
/*
|
||||
* Header file for 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.com/license/LICENSE.
|
||||
*/
|
||||
|
||||
#ifndef __GRSLINK_H__
|
||||
#define __GRSLINK_H__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**** Configuration ****/
|
||||
/* Collect statistics ? */
|
||||
#define SLINK_COLLECT_STATISTICS
|
||||
|
||||
/* Frequency of SLINK SCLK */
|
||||
#define SLINK_FREQ_HZ 6000000
|
||||
/* Number of queues used in driver */
|
||||
#define SLINK_NUMQUEUES 4
|
||||
|
||||
/* The four values below are only used in the demo software */
|
||||
#define SLINK_CORE_REGBASE 0x80000600
|
||||
#define SLINK_CORE_IRQ 6
|
||||
#define IRQ_CNTRL_REG 0x80000200
|
||||
#define IRQ_CNTRL_MASK_OFFSET 0x40
|
||||
|
||||
/*
|
||||
* Structure returned by SLINK_statistics if SLINK_COLLECT_STATISTCS has
|
||||
* been defined
|
||||
*/
|
||||
typedef struct {
|
||||
unsigned int parerr; /* Number of parity errors */
|
||||
unsigned int recov; /* Number of receive overflows */
|
||||
unsigned int reads; /* Number of completed READs */
|
||||
unsigned int writes; /* Number of performed WRITES */
|
||||
unsigned int sequences; /* Number of started SEQUENCEs */
|
||||
unsigned int seqcomp; /* Number of completed SEQUENCEs */
|
||||
unsigned int interrupts; /* Number of INTERRUPT transfers */
|
||||
unsigned int lostwords; /* Number of lost words due to full queue */
|
||||
} SLINK_stats;
|
||||
|
||||
/**** SLINK status codes ****/
|
||||
#define SLINK_ABORTED 0
|
||||
#define SLINK_QFULL 1
|
||||
#define SLINK_ACTIVE 2
|
||||
#define SLINK_AMBAERR 3
|
||||
#define SLINK_COMPLETED 4
|
||||
#define SLINK_PARERR 5
|
||||
#define SLINK_ROV 6 /* Only used internally in driver */
|
||||
|
||||
/**** SLINK master register fields *****/
|
||||
/* Control register */
|
||||
#define SLINK_C_SLEN_POS 16
|
||||
#define SLINK_C_SRO (1 << 8)
|
||||
#define SLINK_C_SCN_POS 4
|
||||
#define SLINK_C_PAR (1 << 3)
|
||||
#define SLINK_C_AS (1 << 2)
|
||||
#define SLINK_C_SE (1 << 1)
|
||||
#define SLINK_C_SLE (1 << 0)
|
||||
|
||||
/* Status register fields */
|
||||
#define SLINK_S_SI_POS 16
|
||||
#define SLINK_S_PERR (1 << 7)
|
||||
#define SLINK_S_AERR (1 << 6)
|
||||
#define SLINK_S_ROV (1 << 5)
|
||||
#define SLINK_S_RNE (1 << 4)
|
||||
#define SLINK_S_TNF (1 << 3)
|
||||
#define SLINK_S_SC (1 << 2)
|
||||
#define SLINK_S_SA (1 << 1)
|
||||
#define SLINK_S_SRX (1 << 0)
|
||||
|
||||
/* Mask register fields */
|
||||
#define SLINK_M_PERRE (1 << 7)
|
||||
#define SLINK_M_AERRE (1 << 6)
|
||||
#define SLINK_M_ROVE (1 << 5)
|
||||
#define SLINK_M_RNEE (1 << 4)
|
||||
#define SLINK_M_TNFE (1 << 3)
|
||||
#define SLINK_M_SCE (1 << 2)
|
||||
#define SLINK_M_SAE (1 << 1)
|
||||
#define SLINK_M_SRXE (1 << 0)
|
||||
|
||||
/**** Macros ****/
|
||||
/* Get channel field from received SLINK word */
|
||||
#define SLINK_WRD_CHAN(x) ((x >> 16) & 0xF)
|
||||
/* Get IO card # from received SLINK word */
|
||||
#define SLINK_WRD_CARDNUM(x) ((x >> 21) & 0x3)
|
||||
/* Get data part from SLINK word */
|
||||
#define SLINK_WRD_PAYLOAD(x) (x & 0xFFFF)
|
||||
|
||||
/* Checks status value to see if transmit queue has free slot */
|
||||
#define SLINK_STS_TRANSFREE(x) (x & SLINK_S_TNF)
|
||||
/* Get Sequence Index value */
|
||||
#define SLINK_STS_SI(x) ((x >> 16) & 0xFF)
|
||||
|
||||
/**** Function declarations, driver interface ****/
|
||||
/* Initializes the SLINK core */
|
||||
int SLINK_init(unsigned int nullwrd, int parity, int qsize,
|
||||
void (*interrupt_trans_handler)(int),
|
||||
void (*sequence_callback)(int));
|
||||
|
||||
/* Enables the core */
|
||||
void SLINK_start(void);
|
||||
|
||||
/* Disables the core */
|
||||
void SLINK_stop(void);
|
||||
|
||||
/* Reads one word */
|
||||
int SLINK_read(int data, int channel, int *reply);
|
||||
|
||||
/* Writes one word */
|
||||
int SLINK_write(int data, int channel);
|
||||
|
||||
/* Peforms a SEQUENCE */
|
||||
int SLINK_seqstart(int *a, int *b, int n, int channel, int reconly);
|
||||
|
||||
/* Aborts a SEQUENCE */
|
||||
void SLINK_seqabort(void);
|
||||
|
||||
/* Status of current or last SEQUENCE */
|
||||
int SLINK_seqstatus(void);
|
||||
|
||||
/* Number of words transferred in last SEQUENCE */
|
||||
int SLINK_seqwrds(void);
|
||||
|
||||
/* Returns value of core's status register */
|
||||
int SLINK_hwstatus(void);
|
||||
|
||||
/* Returns number of elements in queue associated with IO card */
|
||||
int SLINK_queuestatus(int iocard);
|
||||
|
||||
/* Take first element from queue for IO card # 'iocard' */
|
||||
int SLINK_dequeue(int iocard, int *elem);
|
||||
|
||||
/* Returns structure containing core driver statistics */
|
||||
SLINK_stats *SLINK_statistics(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __GRSLINK_H__ */
|
||||
104
c/src/lib/libbsp/sparc/shared/include/grspw_router.h
Normal file
104
c/src/lib/libbsp/sparc/shared/include/grspw_router.h
Normal file
@@ -0,0 +1,104 @@
|
||||
/*
|
||||
* GRSPW ROUTER APB-Register 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.com/license/LICENSE.
|
||||
*/
|
||||
|
||||
#ifndef __GRSPW_ROUTER_H__
|
||||
#define __GRSPW_ROUTER_H__
|
||||
|
||||
/* Hardware Information */
|
||||
struct router_hw_info {
|
||||
unsigned char nports_spw;
|
||||
unsigned char nports_amba;
|
||||
unsigned char nports_fifo;
|
||||
char timers_avail;
|
||||
char pnp_avail;
|
||||
unsigned char ver_major;
|
||||
unsigned char ver_minor;
|
||||
unsigned char ver_patch;
|
||||
unsigned char iid;
|
||||
};
|
||||
|
||||
#define ROUTER_FLG_CFG 0x01
|
||||
#define ROUTER_FLG_IID 0x02
|
||||
#define ROUTER_FLG_IDIV 0x04
|
||||
#define ROUTER_FLG_TPRES 0x08
|
||||
#define ROUTER_FLG_TRLD 0x10
|
||||
#define ROUTER_FLG_ALL 0x1f /* All Above Flags */
|
||||
|
||||
struct router_config {
|
||||
unsigned int flags; /* Determine what configuration should be updated */
|
||||
|
||||
/* Router Configuration Register */
|
||||
unsigned int config;
|
||||
|
||||
/* Set Instance ID */
|
||||
unsigned char iid;
|
||||
|
||||
/* SpaceWire Link Initialization Clock Divisor */
|
||||
unsigned char idiv;
|
||||
|
||||
/* Timer Prescaler and Reload */
|
||||
unsigned int timer_prescaler;
|
||||
unsigned int timer_reload[32];
|
||||
};
|
||||
|
||||
/* Logical routing table */
|
||||
struct router_routes {
|
||||
unsigned int route[224];
|
||||
};
|
||||
|
||||
/* Port Setup, see register definitions for "Port setup register" */
|
||||
struct router_ps {
|
||||
unsigned int ps[31]; /* Port Setup for ports 1-31 */
|
||||
unsigned int ps_logical[224]; /* Port setup for locgical addresses 32-255 */
|
||||
};
|
||||
|
||||
/* Set/Get Port Control/Status */
|
||||
#define ROUTER_PORTFLG_SET_CTRL 0x01
|
||||
#define ROUTER_PORTFLG_GET_CTRL 0x02
|
||||
#define ROUTER_PORTFLG_SET_STS 0x04
|
||||
#define ROUTER_PORTFLG_GET_STS 0x08
|
||||
struct router_port {
|
||||
unsigned int flag;
|
||||
int port;
|
||||
unsigned int ctrl;
|
||||
unsigned int sts;
|
||||
};
|
||||
|
||||
/* Get Hardware support/information available */
|
||||
#define GRSPWR_IOCTL_HWINFO 0x01 /* OUT: struct router_hw_info */
|
||||
|
||||
/* Router Configuration */
|
||||
#define GRSPWR_IOCTL_CFG_SET 0x02 /* IN: struct router_config */
|
||||
#define GRSPWR_IOCTL_CFG_GET 0x03 /* OUT: struct router_config */
|
||||
|
||||
/* Routes */
|
||||
#define GRSPWR_IOCTL_ROUTES_SET 0x04 /* IN: struct router_routes */
|
||||
#define GRSPWR_IOCTL_ROUTES_GET 0x05 /* OUT: struct router_routes */
|
||||
|
||||
/* Port Setup */
|
||||
#define GRSPWR_IOCTL_PS_SET 0x06 /* IN: struct router_ps */
|
||||
#define GRSPWR_IOCTL_PS_GET 0x07 /* OUT: struct router_ps */
|
||||
|
||||
/* Set configuration write enable */
|
||||
#define GRSPWR_IOCTL_WE_SET 0x08 /* INT: int */
|
||||
|
||||
/* Set/Get Port Control/Status */
|
||||
#define GRSPWR_IOCTL_PORT 0x09 /* IN/OUT: struct router_port */
|
||||
|
||||
/* Set Router Configuration/Status Register */
|
||||
#define GRSPWR_IOCTL_CFGSTS_SET 0x0a /* IN: unsigned int */
|
||||
/* Get Router Configuration/Status Register */
|
||||
#define GRSPWR_IOCTL_CFGSTS_GET 0x0b /* OUT: unsigned int */
|
||||
|
||||
/* Get Current Time-Code Register */
|
||||
#define GRSPWR_IOCTL_TC_GET 0x0c /* OUT: unsigned int */
|
||||
|
||||
#endif
|
||||
152
c/src/lib/libbsp/sparc/shared/include/grtc.h
Normal file
152
c/src/lib/libbsp/sparc/shared/include/grtc.h
Normal file
@@ -0,0 +1,152 @@
|
||||
/* GRTC Telecommand (TC) decoder driver interface
|
||||
*
|
||||
* 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.com/license/LICENSE.
|
||||
*/
|
||||
|
||||
#ifndef __GRTC_H__
|
||||
#define __GRTC_H__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define GRTC_IOC_UNUSED 0
|
||||
|
||||
/* Driver operation controlling commands */
|
||||
#define GRTC_IOC_START 1
|
||||
#define GRTC_IOC_STOP 2
|
||||
#define GRTC_IOC_ISSTARTED 3
|
||||
#define GRTC_IOC_SET_BLOCKING_MODE 4 /* Raw mode only */
|
||||
#define GRTC_IOC_SET_TIMEOUT 5 /* Raw mode only */
|
||||
|
||||
#define GRTC_IOC_ADD_BUFF 16 /* Frame mode only */
|
||||
#define GRTC_IOC_RECV 17 /* Frame mode only */
|
||||
|
||||
/* Available only in STOPPED mode */
|
||||
#define GRTC_IOC_SET_MODE 32 /* Set frame mode (ioctl) or raw mode (read) */
|
||||
#define GRTC_IOC_SET_BUF_PARAM 33
|
||||
#define GRTC_IOC_SET_CONFIG 34
|
||||
#define GRTC_IOC_POOLS_SETUP 35 /* Frame mode only */
|
||||
|
||||
/* Available in both running and stopped mode */
|
||||
#define GRTC_IOC_GET_CONFIG 64
|
||||
#define GRTC_IOC_GET_BUF_PARAM 65
|
||||
#define GRTC_IOC_GET_HW_STATUS 66
|
||||
#define GRTC_IOC_ASSIGN_FRM_POOL 67
|
||||
#define GRTC_IOC_GET_CLCW_ADR 68 /* Get address of CLCWRx1 */
|
||||
#define GRTC_IOC_GET_STATS 69 /* Get statistics, note that most of the stats are only avilable in FRAME mode */
|
||||
#define GRTC_IOC_CLR_STATS 70 /* Clear statistics */
|
||||
|
||||
/* Available only in RUNNING mode */
|
||||
|
||||
/* Args to GRTC_IOC_GET_BUF_PARAMS */
|
||||
#define GRTC_BUF_MAXLEN (0x100*1024)
|
||||
#define GRTC_BUF_MASK 0xfffffc00
|
||||
struct grtc_ioc_buf_params {
|
||||
unsigned int length; /* Length of new buffer in multiples of 1kbyte blocks */
|
||||
void *custom_buffer; /* If set zero driver will allocate with malloc, set LSB to 1 to indicate remote address */
|
||||
};
|
||||
|
||||
/* Args to GRTC_IOC_SET_BLOCKING_MODE */
|
||||
enum {
|
||||
GRTC_BLKMODE_POLL = 0, /* Never block (polling mode) */
|
||||
GRTC_BLKMODE_BLK = 1, /* Block until at least 1 byte can be read */
|
||||
GRTC_BLKMODE_COMPLETE = 2 /* Block until all data requested has be read */
|
||||
};
|
||||
|
||||
/* Argument of GRTC_IOC_SET_CONFIG and GRTC_IOC_GET_CONFIG
|
||||
* Pointer to:
|
||||
*/
|
||||
struct grtc_ioc_config {
|
||||
int psr_enable;
|
||||
int nrzm_enable;
|
||||
int pss_enable;
|
||||
int crc_calc; /* Enable Software CRC calculation (only Frame mode) */
|
||||
};
|
||||
|
||||
/* Argument of GRTC_IOC_GET_HW_STATUS:
|
||||
* Pointer to a grtc_ioc_hw_status structure that will be filled
|
||||
* in by driver.
|
||||
*/
|
||||
struct grtc_ioc_hw_status {
|
||||
unsigned int sir;
|
||||
unsigned int far;
|
||||
unsigned int clcw1;
|
||||
unsigned int clcw2;
|
||||
unsigned int phir;
|
||||
unsigned int str;
|
||||
};
|
||||
|
||||
struct grtc_hdr {
|
||||
unsigned short flags_scid;
|
||||
unsigned short vc_len;
|
||||
unsigned char seqnum;
|
||||
} __attribute__((packed));
|
||||
|
||||
/* Frame pool, all frames in pool have the same buffer length (frame mode only) */
|
||||
struct grtc_frame {
|
||||
struct grtc_frame *next; /* Next frame in list */
|
||||
unsigned short len; /* Length of frame extracted */
|
||||
unsigned short reserved; /* Reserved */
|
||||
struct grtc_frame_pool *pool; /* The frame pool this frame belongs to */
|
||||
|
||||
/* The Frame content */
|
||||
struct grtc_hdr hdr; /* Primary Header */
|
||||
unsigned char data[3]; /* Frame payload */
|
||||
} __attribute__((packed));
|
||||
|
||||
/* GRTC_IOC_RECV argument, single linked list of received frames */
|
||||
struct grtc_list {
|
||||
struct grtc_frame *head; /* First frame in list */
|
||||
struct grtc_frame *tail; /* Last frame in list */
|
||||
int cnt; /* Number of frames in list */
|
||||
};
|
||||
|
||||
struct grtc_ioc_pools_setup {
|
||||
unsigned int pool_cnt; /* Number of pools */
|
||||
unsigned int pool_frame_len[1]; /* Array of 'pool_cnt' length: Frame length of frames in a pool
|
||||
* Lengths must be sorted, starting with the smallest frame pool.
|
||||
*/
|
||||
};
|
||||
|
||||
struct grtc_ioc_assign_frm_pool {
|
||||
unsigned int frame_len; /* The length of the pool to insert the frame into */
|
||||
struct grtc_frame *frames; /* Frames to assign to a pool */
|
||||
};
|
||||
|
||||
enum {
|
||||
GRTC_MODE_RAW = 0,
|
||||
GRTC_MODE_FRAME = 1
|
||||
};
|
||||
|
||||
/* TC driver stats collected during receiving. The statistics is only available
|
||||
* in FRAME mode. In RAW mode the user interprets the incoming frames and is
|
||||
* therefore responsible for generating the staticstics.
|
||||
*/
|
||||
struct grtc_ioc_stats {
|
||||
unsigned long long frames_recv; /* Total number of non-erroneous frames received */
|
||||
/* Errors related to incoming data */
|
||||
unsigned int err; /* total number of errors */
|
||||
unsigned int err_hdr; /* number of errors in Header */
|
||||
unsigned int err_payload; /* Number of errors in payload */
|
||||
unsigned int err_ending; /* Number of errors in end (Filler, end marker) */
|
||||
unsigned int err_abandoned; /* Number of abandoned frames, NOT IMPLEMENTED */
|
||||
/* Errors related to the handling of incoming frames */
|
||||
unsigned int dropped; /* Number of dropped frames TC driver */
|
||||
unsigned int dropped_no_buf; /* Number of dropped frame caused by no buffers were available */
|
||||
unsigned int dropped_too_long; /* Number of dropped frames that was larger than any buffer available for driver */
|
||||
};
|
||||
|
||||
/* Register GRTC driver at driver manager */
|
||||
void grtc_register_drv(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __GRTC_H__ */
|
||||
241
c/src/lib/libbsp/sparc/shared/include/grtm.h
Normal file
241
c/src/lib/libbsp/sparc/shared/include/grtm.h
Normal file
@@ -0,0 +1,241 @@
|
||||
/* GRTM Telemetry (TM) driver interface
|
||||
*
|
||||
* 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.com/license/LICENSE.
|
||||
*/
|
||||
|
||||
#ifndef __GRTM_H__
|
||||
#define __GRTM_H__
|
||||
|
||||
#include <rtems.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define GRTM_IOC_UNUSED 0
|
||||
|
||||
/* Driver operation controlling commands */
|
||||
#define GRTM_IOC_START 1
|
||||
#define GRTM_IOC_STOP 2
|
||||
#define GRTM_IOC_ISSTARTED 3
|
||||
#define GRTM_IOC_SET_BLOCKING_MODE 4
|
||||
#define GRTM_IOC_SET_TIMEOUT 5
|
||||
|
||||
/* Available only in STOPPED mode */
|
||||
#define GRTM_IOC_SET_CONFIG 32
|
||||
|
||||
/* Available in both running and stopped mode */
|
||||
#define GRTM_IOC_RECLAIM 64
|
||||
#define GRTM_IOC_GET_CONFIG 65
|
||||
#define GRTM_IOC_GET_HW_IMPL 66
|
||||
#define GRTM_IOC_GET_HW_STATUS 67 /* Not implemented */
|
||||
#define GRTM_IOC_GET_OCFREG 68
|
||||
#define GRTM_IOC_GET_STATS 69
|
||||
#define GRTM_IOC_CLR_STATS 70
|
||||
|
||||
/* Available only in RUNNING mode */
|
||||
#define GRTM_IOC_SEND 96
|
||||
|
||||
/* Args to GRTC_IOC_SET_BLOCKING_MODE */
|
||||
enum {
|
||||
GRTM_BLKMODE_POLL = 0, /* Never block (polling mode) */
|
||||
GRTM_BLKMODE_BLK = 1, /* Block until at least 1 byte can be read */
|
||||
};
|
||||
|
||||
/* Reed Solomon Encoder implemented */
|
||||
enum {
|
||||
GRTM_RS_IMPL_NONE = 0,
|
||||
GRTM_RS_IMPL_E16 = 1, /* E16 */
|
||||
GRTM_RS_IMPL_E8 = 2, /* E8 */
|
||||
GRTM_RS_IMPL_BOTH = 3 /* Both E8 and E16 */
|
||||
|
||||
};
|
||||
|
||||
struct grtm_ioc_hw {
|
||||
char cs; /* Sub Carrier */
|
||||
char sp; /* Split-Phase Level */
|
||||
char ce;
|
||||
char nrz;
|
||||
char psr;
|
||||
char te;
|
||||
unsigned char rsdep;
|
||||
unsigned char rs;
|
||||
char aasm;
|
||||
char fecf;
|
||||
char ocf;
|
||||
char evc;
|
||||
char idle;
|
||||
char fsh;
|
||||
char mcg;
|
||||
char iz;
|
||||
char fhec;
|
||||
char aos;
|
||||
char cif;
|
||||
char ocfb;
|
||||
|
||||
unsigned short blk_size; /* Block Size */
|
||||
unsigned short fifo_size; /* FIFO Size */
|
||||
|
||||
};
|
||||
|
||||
/* Driver Mode */
|
||||
enum {
|
||||
GRTM_MODE_TM = 0, /* TM */
|
||||
GRTM_MODE_AOS = 1 /* AOS */
|
||||
};
|
||||
|
||||
/* Physical layer Options */
|
||||
#define GRTM_IOC_PHY_SCF (1<<15) /* Sub Carrier Fall */
|
||||
#define GRTM_IOC_PHY_SF (1<<31) /* Symbol Fall */
|
||||
|
||||
/* Coding Sub-layer Options */
|
||||
#define GRTM_IOC_CODE_SC (1<<0) /* Enable Sub Carrier modulation */
|
||||
#define GRTM_IOC_CODE_SP (1<<1) /* Enable Split-Phase (SP) level modulation */
|
||||
#define GRTM_IOC_CODE_CE (1<<5) /* Enable Convolutional Encoding */
|
||||
#define GRTM_IOC_CODE_NRZ (1<<6) /* Enable Non-Return-to-Zero mark encoding */
|
||||
#define GRTM_IOC_CODE_PSR (1<<7) /* Enable Pseudo-Randomizer */
|
||||
#define GRTM_IOC_CODE_RS8 (1<<11) /* Reed-solomon Encoder to use: 0=E16, 1=E8 */
|
||||
#define GRTM_IOC_CODE_RS (1<<15) /* Enable Reed-Solomon Encoder */
|
||||
#define GRTM_IOC_CODE_AASM (1<<16) /* Enable Alternative attached synchronization marker */
|
||||
#define GRTM_IOC_CODE_ALL (GRTM_IOC_CODE_SC|GRTM_IOC_CODE_SP|GRTM_IOC_CODE_CE| \
|
||||
GRTM_IOC_CODE_NRZ|GRTM_IOC_CODE_PSR|GRTM_IOC_CODE_RS8|\
|
||||
GRTM_IOC_CODE_RS|GRTM_IOC_CODE_AASM)
|
||||
|
||||
enum {
|
||||
GRTM_CERATE_00 = 0, /* Rate 1/2, no puncturing */
|
||||
GRTM_CERATE_02 = 2, /* Rate 1/2, punctured */
|
||||
GRTM_CERATE_04 = 4, /* Rate 2/3, punctured */
|
||||
GRTM_CERATE_05 = 5, /* Rate 3/4, punctured */
|
||||
GRTM_CERATE_06 = 6, /* Rate 5/6, punctured */
|
||||
GRTM_CERATE_07 = 7, /* Rate 7/8, punctured */
|
||||
};
|
||||
|
||||
/* Options for Generating all frames */
|
||||
#define GRTM_IOC_ALL_FHEC 0x01 /* Enable Frame Header Error Control (Only AOS) */
|
||||
#define GRTM_IOC_ALL_FECF 0x02 /* Enable Transfer Frame CRC */
|
||||
#define GRTM_IOC_ALL_IZ 0x04 /* Enable Insert Zone */
|
||||
#define GRTM_IOC_ALL_ALL (GRTM_IOC_ALL_FHEC|GRTM_IOC_ALL_FECF|GRTM_IOC_ALL_IZ)
|
||||
|
||||
/* Master Frame Generation Options */
|
||||
#define GRTM_IOC_MF_OW 0x01 /* Over Write OCF bits 16 and 17 */
|
||||
#define GRTM_IOC_MF_OCF 0x02 /* Enable Operation Control Field (OCF) for master channel */
|
||||
#define GRTM_IOC_MF_FSH 0x04 /* Enable MC_FSH for master channel */
|
||||
#define GRTM_IOC_MF_MC 0x08 /* Enable Master channel counter generation */
|
||||
#define GRTM_IOC_MF_ALL (GRTM_IOC_MF_OW|GRTM_IOC_MF_OCF|GRTM_IOC_MF_FSH|GRTM_IOC_MF_MC)
|
||||
|
||||
/* Idle Frames Generation Options */
|
||||
#define GRTM_IOC_IDLE_MC 0x01 /* Enable Master Channel (MC) counter generation (TM Only) */
|
||||
#define GRTM_IOC_IDLE_VCC 0x02 /* Enable Virtual Channel counter cycle generation (AOS Only)*/
|
||||
#define GRTM_IOC_IDLE_FSH 0x04 /* Enable Frame Secondary Header (FSH) for idle frames (TM Only) */
|
||||
#define GRTM_IOC_IDLE_EVC 0x08 /* Enable Extended Virtual Channel Counter Generation */
|
||||
#define GRTM_IOC_IDLE_OCF 0x10 /* Enable OCF/CLCW in idle frame */
|
||||
#define GRTM_IOC_IDLE_EN 0x20 /* Enable Idle frame generation */
|
||||
#define GRTM_IOC_IDLE_ALL (GRTM_IOC_IDLE_MC|GRTM_IOC_IDLE_VCC|GRTM_IOC_IDLE_FSH| \
|
||||
GRTM_IOC_IDLE_EVC|GRTM_IOC_IDLE_OCF|GRTM_IOC_IDLE_EN)
|
||||
|
||||
/* Argument of GRTM_IOC_SET_CONFIG and GRTM_IOC_GET_CONFIG.
|
||||
* Driver and Hardware configuration.
|
||||
*
|
||||
* Pointer to:
|
||||
*/
|
||||
struct grtm_ioc_config {
|
||||
|
||||
/* Mode AOS or TM */
|
||||
unsigned char mode; /* 0=TM, 1=AOS */
|
||||
|
||||
unsigned short frame_length; /* Length of every frame transmitted */
|
||||
unsigned short limit; /* Number of data bytes fetched by DMA before transmission starts */
|
||||
unsigned int as_marker; /* Attached Synchronization Marker */
|
||||
|
||||
/* Physical layer options */
|
||||
unsigned short phy_subrate; /* Sub Carrier rate - sub carrier devision factor - 1 */
|
||||
unsigned short phy_symbolrate; /* Symbol Rate division factor - 1 */
|
||||
unsigned char phy_opts; /* Mask of GRTM_IOC_PHY_XXXX */
|
||||
|
||||
/* Coding sub-layer Options */
|
||||
unsigned char code_rsdep; /* Coding sub-layer Reed-Solomon interleave depth (3-bit) */
|
||||
unsigned char code_ce_rate; /* Convolutional encoding rate, select one of GRTM_CERATE_00 ... GRTM_CERATE_07 */
|
||||
unsigned char code_csel; /* */
|
||||
unsigned int code_opts; /* Mask of GRTM_IOC_CODE_XXXX */
|
||||
|
||||
/* All Frames Generation */
|
||||
unsigned char all_izlen; /* FSH/IZ Length (5-bit) */
|
||||
unsigned char all_opts; /* Mask of GRTM_IOC_ALL_XXXX */
|
||||
|
||||
/* Master Frame Generation */
|
||||
unsigned char mf_opts; /* Mask of GRTM_IOC_MF_XXXX */
|
||||
|
||||
/* Idle frame Generation */
|
||||
unsigned short idle_scid;
|
||||
unsigned char idle_vcid;
|
||||
unsigned char idle_opts; /* Mask of GRTM_IOC_IDLE_XXXX */
|
||||
|
||||
/* Interrupt options */
|
||||
unsigned int enable_cnt; /* Number of frames in between Interrupt is generated, Zero disables interrupt */
|
||||
int isr_desc_proc; /* Enable ISR to process descriptors */
|
||||
int blocking; /* Blocking mode select (POLL,BLK..) */
|
||||
rtems_interval timeout; /* Blocking mode timeout */
|
||||
};
|
||||
|
||||
struct grtm_frame;
|
||||
|
||||
struct grtm_list {
|
||||
struct grtm_frame *head; /* First Frame in list */
|
||||
struct grtm_frame *tail; /* Last Frame in list */
|
||||
};
|
||||
|
||||
#define GRTM_FLAGS_SENT 0x01
|
||||
#define GRRM_FLAGS_ERR 0x02
|
||||
|
||||
#define GRTM_FLAGS_TRANSLATE (1<<31) /* Translate frame payload address from CPU address to remote bus (the bus GRTM is resident on) */
|
||||
#define GRTM_FLAGS_TRANSLATE_AND_REMEMBER (1<<30) /* As GRTM_FLAGS_TRANSLATE, however if the translated payload address equals the payload address
|
||||
* the GRTM_FLAGS_TRANSLATE_AND_REMEMBER bit is cleared and the GRTM_FLAGS_TRANSLATE bit is set */
|
||||
#define GRTM_FLAGS_COPY_DATA (1<<29) /* Where available: Transfer Frame payload to target, may be used for SpaceWire, where the GRTM driver transfer
|
||||
* the payload to a buffer on the SpaceWire target.
|
||||
*/
|
||||
|
||||
#define GRTM_FLAGS_TS (1<<9)
|
||||
#define GRTM_FLAGS_MCB (1<<8)
|
||||
#define GRTM_FLAGS_FSHB (1<<7)
|
||||
#define GRTM_FLAGS_OCFB (1<<6)
|
||||
#define GRTM_FLAGS_FHECB (1<<5)
|
||||
#define GRTM_FLAGS_IZB (1<<4)
|
||||
#define GRTM_FLAGS_FECFB (1<<3)
|
||||
|
||||
#define GRTM_FLAGS_MASK (GRTM_FLAGS_TS|GRTM_FLAGS_MCB|GRTM_FLAGS_FSHB|\
|
||||
GRTM_FLAGS_OCFB|GRTM_FLAGS_FHECB|GRTM_FLAGS_IZB|\
|
||||
GRTM_FLAGS_FECFB)
|
||||
|
||||
/* The GRTM software representation of a Frame */
|
||||
struct grtm_frame {
|
||||
/* Options and status */
|
||||
unsigned int flags; /* bypass options, and sent/error status */
|
||||
|
||||
struct grtm_frame *next; /* Next packet in chain */
|
||||
|
||||
unsigned int *payload; /* The Headers and Payload, Frame data and header must be word aligned */
|
||||
};
|
||||
|
||||
#define FRAME_SIZE(payloadlen) (sizeof(struct grtm_frame)+payloadlen)
|
||||
|
||||
struct grtm_ioc_stats {
|
||||
unsigned long long frames_sent;
|
||||
unsigned int err_underrun;
|
||||
unsigned int err_tx;
|
||||
unsigned int err_ahb;
|
||||
unsigned int err_transfer_frame;
|
||||
};
|
||||
|
||||
/* Register GRTM driver at driver manager */
|
||||
void grtm_register_drv(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __GRTM_H__ */
|
||||
142
c/src/lib/libbsp/sparc/shared/include/satcan.h
Normal file
142
c/src/lib/libbsp/sparc/shared/include/satcan.h
Normal file
@@ -0,0 +1,142 @@
|
||||
/*
|
||||
* Header file for RTEMS SATCAN FPGA 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.com/license/LICENSE.
|
||||
*/
|
||||
|
||||
#ifndef __SATCAN_H__
|
||||
#define __SATCAN_H__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Config structure passed to SatCAN_init(..) */
|
||||
typedef struct {
|
||||
/* Configuration */
|
||||
int nodeno;
|
||||
int dps;
|
||||
/* Callback functions */
|
||||
void (*ahb_irq_callback)(void);
|
||||
void (*pps_irq_callback)(void);
|
||||
void (*m5_irq_callback)(void);
|
||||
void (*m4_irq_callback)(void);
|
||||
void (*m3_irq_callback)(void);
|
||||
void (*m2_irq_callback)(void);
|
||||
void (*m1_irq_callback)(void);
|
||||
void (*sync_irq_callback)(void);
|
||||
void (*can_irq_callback)(unsigned int fifo);
|
||||
} satcan_config;
|
||||
|
||||
#define SATCAN_HEADER_SIZE 4
|
||||
#define SATCAN_HEADER_NMM_POS 3
|
||||
#define SATCAN_PAYLOAD_SIZE 8
|
||||
|
||||
/* SatCAN message */
|
||||
typedef struct {
|
||||
unsigned char header[SATCAN_HEADER_SIZE]; /* Header of SatCAN message */
|
||||
unsigned char payload[SATCAN_PAYLOAD_SIZE]; /* Payload of SatCAN message */
|
||||
} satcan_msg;
|
||||
|
||||
/* SatCAN modify register structure */
|
||||
typedef struct {
|
||||
unsigned int reg;
|
||||
unsigned int val;
|
||||
} satcan_regmod;
|
||||
|
||||
/* Driver interface */
|
||||
int satcan_register(satcan_config *conf);
|
||||
|
||||
/* SatCAN interrupt IDs */
|
||||
#define SATCAN_IRQ_NONACT_TO_ACT 0
|
||||
#define SATCAN_IRQ_ACTIVE_TO_NONACT 1
|
||||
#define SATCAN_IRQ_STR1_TO_DPS 2
|
||||
#define SATCAN_IRQ_DPS_TO_STR1 3
|
||||
#define SATCAN_IRQ_STR2_TO_DPS 4
|
||||
#define SATCAN_IRQ_DPS_TO_STR2 5
|
||||
#define SATCAN_IRQ_STR3_TO_DPS 6
|
||||
#define SATCAN_IRQ_DPS_TO_STR3 7
|
||||
#define SATCAN_IRQ_PLD1_TO_DPS 8
|
||||
#define SATCAN_IRQ_DPS_TO_PLD1 9
|
||||
#define SATCAN_IRQ_PLD2_TO_DPS 10
|
||||
#define SATCAN_IRQ_DPS_TO_PLD2 11
|
||||
#define SATCAN_IRQ_SYNC 16
|
||||
#define SATCAN_IRQ_TIME_MARKER1 17
|
||||
#define SATCAN_IRQ_TIME_MARKER2 18
|
||||
#define SATCAN_IRQ_TIME_MARKER3 19
|
||||
#define SATCAN_IRQ_TIME_MARKER4 20
|
||||
#define SATCAN_IRQ_TIME_MARKER5 21
|
||||
#define SATCAN_IRQ_EOD1 22
|
||||
#define SATCAN_IRQ_EOD2 23
|
||||
#define SATCAN_IRQ_TOD 24
|
||||
#define SATCAN_IRQ_CRITICAL 25
|
||||
|
||||
/* IOC */
|
||||
#define SATCAN_IOC_DMA_2K 1 /* Use DMA area for 2K messages */
|
||||
#define SATCAN_IOC_DMA_8K 2 /* Use DMA area for 8K messages */
|
||||
#define SATCAN_IOC_GET_REG 3 /* Provides direct read access to all core registers */
|
||||
#define SATCAN_IOC_SET_REG 4 /* Provides direct write access to all core registers */
|
||||
#define SATCAN_IOC_OR_REG 5 /* Provides direct read access to all core registers */
|
||||
#define SATCAN_IOC_AND_REG 6 /* Provides direct write access to all core registers */
|
||||
#define SATCAN_IOC_EN_TX1_DIS_TX2 7 /* Enable DMA TX channel 1, Disable DMA TX channel 2 */
|
||||
#define SATCAN_IOC_EN_TX2_DIS_TX1 8 /* Enable DMA TX channel 2, Disable DMA TX channel 1 */
|
||||
#define SATCAN_IOC_GET_DMA_MODE 9 /* Returns the current DMA mode */
|
||||
#define SATCAN_IOC_SET_DMA_MODE 10 /* Sets the DMA mode */
|
||||
#define SATCAN_IOC_ACTIVATE_DMA 11 /* Directly activate DMA channel */
|
||||
#define SATCAN_IOC_DEACTIVATE_DMA 12 /* Directly deactivate DMA channel */
|
||||
#define SATCAN_IOC_DMA_STATUS 13 /* Returns status of directly activated DMA */
|
||||
#define SATCAN_IOC_GET_DOFFSET 14 /* Get TX DMA offset */
|
||||
#define SATCAN_IOC_SET_DOFFSET 15 /* Set TX DMA offset */
|
||||
#define SATCAN_IOC_GET_TIMEOUT 16 /* Set TX DMA timeout */
|
||||
#define SATCAN_IOC_SET_TIMEOUT 17 /* Get TX DMA timeout */
|
||||
|
||||
|
||||
/* Values used to select core register with IOC_SET_REG/IOC_GET_REG */
|
||||
#define SATCAN_SWRES 0 /* Software reset */
|
||||
#define SATCAN_INT_EN 1 /* Interrupt enable */
|
||||
#define SATCAN_FIFO 3 /* FIFO read */
|
||||
#define SATCAN_FIFO_RES 4 /* FIFO reset */
|
||||
#define SATCAN_TSTAMP 5 /* Current time stamp */
|
||||
#define SATCAN_CMD0 6 /* Command register 0 */
|
||||
#define SATCAN_CMD1 7 /* Command register 1 */
|
||||
#define SATCAN_START_CTC 8 /* Start cycle time counter */
|
||||
#define SATCAN_RAM_BASE 9 /* RAM offset address */
|
||||
#define SATCAN_STOP_CTC 10 /* Stop cycle time counter / DPS active status */
|
||||
#define SATCAN_DPS_ACT 10 /* Stop cycle time counter / DPS active status */
|
||||
#define SATCAN_PLL_RST 11 /* DPLL reset */
|
||||
#define SATCAN_PLL_CMD 12 /* DPLL command */
|
||||
#define SATCAN_PLL_STAT 13 /* DPLL status */
|
||||
#define SATCAN_PLL_OFF 14 /* DPLL offset */
|
||||
#define SATCAN_DMA 15 /* DMA channel enable */
|
||||
#define SATCAN_DMA_TX_1_CUR 16 /* DMA channel 1 TX current address */
|
||||
#define SATCAN_DMA_TX_1_END 17 /* DMA channel 1 TX end address */
|
||||
#define SATCAN_DMA_TX_2_CUR 18 /* DMA channel 2 TX current address */
|
||||
#define SATCAN_DMA_TX_2_END 19 /* DMA channel 2 TX end address */
|
||||
#define SATCAN_RX 20 /* CAN RX enable / Filter start ID */
|
||||
#define SATCAN_FILTER_START 20 /* CAN RX enable / Filter start ID */
|
||||
#define SATCAN_FILTER_SETUP 21 /* Filter setup / Filter stop ID */
|
||||
#define SATCAN_FILTER_STOP 21 /* Filter setup / Filter stop ID */
|
||||
#define SATCAN_WCTRL 32 /* Wrapper status/control register */
|
||||
#define SATCAN_WIPEND 33 /* Wrapper interrupt pending register */
|
||||
#define SATCAN_WIMASK 34 /* Wrapper interrupt mask register */
|
||||
#define SATCAN_WAHBADDR 35 /* Wrapper AHB address register */
|
||||
|
||||
|
||||
/* Values used to communicate DMA mode */
|
||||
#define SATCAN_DMA_MODE_USER 0
|
||||
#define SATCAN_DMA_MODE_SYSTEM 1
|
||||
|
||||
/* Values used to directly activate DMA channel */
|
||||
#define SATCAN_DMA_ENABLE_TX1 1
|
||||
#define SATCAN_DMA_ENABLE_TX2 2
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __SATCAN_H__ */
|
||||
126
c/src/lib/libbsp/sparc/shared/include/spictrl.h
Normal file
126
c/src/lib/libbsp/sparc/shared/include/spictrl.h
Normal file
@@ -0,0 +1,126 @@
|
||||
/*
|
||||
* SPICTRL SPI 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.com/license/LICENSE.
|
||||
*/
|
||||
|
||||
#ifndef __SPICTRL_H__
|
||||
#define __SPICTRL_H__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
extern void spictrl_register_drv (void);
|
||||
|
||||
/*** REGISTER LAYOUT ***/
|
||||
struct spictrl_regs {
|
||||
volatile unsigned int capability; /* 0x00 */
|
||||
volatile unsigned int resv[7]; /* 0x04 */
|
||||
volatile unsigned int mode; /* 0x20 */
|
||||
volatile unsigned int event; /* 0x24 */
|
||||
volatile unsigned int mask; /* 0x28 */
|
||||
volatile unsigned int command; /* 0x2c */
|
||||
volatile unsigned int tx; /* 0x30 */
|
||||
volatile unsigned int rx; /* 0x34 */
|
||||
volatile unsigned int slvsel; /* 0x38 */
|
||||
volatile unsigned int am_slvsel; /* 0x3c */
|
||||
volatile unsigned int am_cfg; /* 0x40 */
|
||||
volatile unsigned int am_period; /* 0x44 */
|
||||
int reserved0[2];
|
||||
volatile unsigned int am_mask[4]; /* 0x50-0x5C */
|
||||
int reserved1[(0x200-0x60)/4];
|
||||
volatile unsigned int am_tx[128]; /* 0x200-0x3FC */
|
||||
volatile unsigned int am_rx[128]; /* 0x400-0x5FC */
|
||||
};
|
||||
|
||||
/* -- About automated periodic transfer mode --
|
||||
*
|
||||
* Core must support this feature.
|
||||
*
|
||||
* The SPI core must be configured in periodic mode before
|
||||
* writing the data into the transfer FIFO which will be used
|
||||
* mutiple times in different transfers, it will also make
|
||||
* the receive FIFO to be updated.
|
||||
*
|
||||
* In periodic mode the following sequence is performed,
|
||||
* 1. start()
|
||||
* 2. ioctl(CONFIG, &config) - Enable periodic mode
|
||||
* 3. set_address()
|
||||
* 4. write() - Fills TX FIFO, this has some constraints
|
||||
* 5. ioctl(START) - Starts the periodic transmission of the TX FIFO
|
||||
* 6. read() - Read one response of the tranistted data. It will
|
||||
* hang until data is available. If hanging is not an
|
||||
* options use ioctl(STATUS)
|
||||
* 7. go back to 6.
|
||||
*
|
||||
* 8. ioctl(STOP) - Stop to set up a new periodic or normal transfer
|
||||
* 9. stop()
|
||||
*
|
||||
* Note that the the read length must equal the total write length.
|
||||
*/
|
||||
|
||||
/* Custom SPICTRL driver ioctl commands */
|
||||
#define SPICTRL_IOCTL_PERIOD_START 5000 /* Start automated periodic transfer mode */
|
||||
#define SPICTRL_IOCTL_PERIOD_STOP 5001 /* Stop to SPI core from doing periodic transfers */
|
||||
#define SPICTRL_IOCTL_CONFIG 5002 /* Configure Periodic transfer mode (before calling write() and START) */
|
||||
#define SPICTRL_IOCTL_STATUS 5003 /* Get status */
|
||||
|
||||
#define SPICTRL_IOCTL_PERIOD_READ 5005 /* Write transmit registers and mask register
|
||||
* (only in automatic periodic mode)
|
||||
* Note that it is probably prefferred to read
|
||||
* the received words using the read() using
|
||||
* operations instead.
|
||||
*/
|
||||
#define SPICTRL_IOCTL_PERIOD_WRITE 5006 /* Read receive registers and mask register
|
||||
* (only in automatic periodic mode) */
|
||||
#define SPICTRL_IOCTL_REGS 5007 /* Get SPICTRL Register */
|
||||
|
||||
/* SPICTRL_IOCTL_CONFIG argument */
|
||||
struct spictrl_ioctl_config {
|
||||
int clock_gap; /* Clock GAP between */
|
||||
unsigned int flags; /* Normal mode flags */
|
||||
int periodic_mode; /* 1=Enables Automated periodic transfers if supported by hardware */
|
||||
unsigned int period; /* Number of clocks between automated transfers are started */
|
||||
unsigned int period_flags; /* Options */
|
||||
unsigned int period_slvsel; /* Slave Select when transfer is not active, default is 0xffffffff */
|
||||
};
|
||||
#define SPICTRL_FLAGS_TAC 0x10
|
||||
|
||||
#define SPICTRL_PERIOD_FLAGS_ERPT 0x80 /* Trigger start-period from external signal */
|
||||
#define SPICTRL_PERIOD_FLAGS_SEQ 0x40
|
||||
#define SPICTRL_PERIOD_FLAGS_STRICT 0x20
|
||||
#define SPICTRL_PERIOD_FLAGS_OVTB 0x10
|
||||
#define SPICTRL_PERIOD_FLAGS_OVDB 0x08
|
||||
#define SPICTRL_PERIOD_FLAGS_ASEL 0x04
|
||||
#define SPICTRL_PERIOD_FLAGS_EACT 0x01
|
||||
|
||||
/* SPICTRL_IOCTL_PERIOD_READ and SPICTRL_IOCTL_PERIOD_WRITE Argument data structure
|
||||
*
|
||||
* Note that the order of reading the mask registers are different for read/write
|
||||
* operation. See options notes.
|
||||
*/
|
||||
struct spictrl_period_io {
|
||||
int options; /* READ: bit0=Read Mask Registers into masks[].
|
||||
* bit1=Read Receive registers according to masks[]
|
||||
* (after reading masks).
|
||||
*
|
||||
* WRITE: bit0=Update Mask accoring to masks[].
|
||||
* bit1=Update Transmit registers according to masks[].
|
||||
* (before reading masks)
|
||||
*/
|
||||
unsigned int masks[4];
|
||||
|
||||
void *data; /* Data read sequentially according to masks[] bit. */
|
||||
};
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
188
c/src/lib/libbsp/sparc/shared/include/spwcuc.h
Normal file
188
c/src/lib/libbsp/sparc/shared/include/spwcuc.h
Normal file
@@ -0,0 +1,188 @@
|
||||
/* 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.com/license/LICENSE.
|
||||
*/
|
||||
|
||||
#ifndef __SPWCUC_H__
|
||||
#define __SPWCUC_H__
|
||||
|
||||
#define PKT_INIT_IRQ 0x1
|
||||
#define PKT_ERR_IRQ 0x2
|
||||
#define PKT_RX_IRQ 0x4
|
||||
#define WRAP_ERR_IRQ 0x8
|
||||
#define WRAP_IRQ 0x10
|
||||
#define SYNC_ERR_IRQ 0x20
|
||||
#define SYNC_IRQ 0x40
|
||||
#define TOL_ERR_IRQ 0x80
|
||||
#define TICK_RX_ERR_IRQ 0x100
|
||||
#define TICK_RX_WRAP_IRQ 0x200
|
||||
#define TICK_RX_IRQ 0x400
|
||||
#define TICK_TX_WRAP_IRQ 0x800
|
||||
#define TICK_TX_IRQ 0x1000
|
||||
|
||||
/* SPWCUC Register layout */
|
||||
struct spwcuc_regs {
|
||||
volatile unsigned int config; /* 00 */
|
||||
volatile unsigned int status; /* 04 */
|
||||
volatile unsigned int control; /* 08 */
|
||||
volatile unsigned int unused0; /* 0c */
|
||||
volatile unsigned int dla; /* 10 */
|
||||
volatile unsigned int pid; /* 14 */
|
||||
volatile unsigned int offset; /* 18 */
|
||||
volatile unsigned int unused1; /* 1c */
|
||||
volatile unsigned int pkt_ct; /* 20 */
|
||||
volatile unsigned int pkt_ft; /* 24 */
|
||||
volatile unsigned int pkt_pf_crc; /* 28 */
|
||||
volatile unsigned int unused2; /* 2c */
|
||||
volatile unsigned int etct; /* 30 */
|
||||
volatile unsigned int etft; /* 34 */
|
||||
volatile unsigned int etct_next; /* 38 */
|
||||
volatile unsigned int etft_next; /* 3c */
|
||||
volatile unsigned int unused3[8]; /* 40-5c */
|
||||
volatile unsigned int pimsr; /* 60 */
|
||||
volatile unsigned int pimr; /* 64 */
|
||||
volatile unsigned int pisr; /* 68 */
|
||||
volatile unsigned int pir; /* 6c */
|
||||
volatile unsigned int imr; /* 70 */
|
||||
volatile unsigned int picr; /* 74 */
|
||||
};
|
||||
|
||||
struct spwcuc_cfg {
|
||||
unsigned char sel_out; /* Bits 3-0 enable time code transmission on respective output */
|
||||
unsigned char sel_in; /* Select SpW to receive time codes on, 0-3 */
|
||||
unsigned char mapping; /* Define mapping of time code time info into T-field, 0-31 */
|
||||
unsigned char tolerance; /* Define SpaceWire time code reception tolerance, 0-31 */
|
||||
unsigned char tid; /* Define CUC P-Field time code identification, 1 = Level 1, 2 = Level 2 */
|
||||
unsigned char ctf; /* If 1 check time code flags to be all zero */
|
||||
unsigned char cp; /* If 1 check P-Field time code id against tid */
|
||||
|
||||
unsigned char txen; /* Enable SpaceWire time code transmission */
|
||||
unsigned char rxen; /* Enable SpaceWire time code reception */
|
||||
unsigned char pktsyncen; /* Enable SpaceWire time CUC packet sync */
|
||||
unsigned char pktiniten; /* Enable SpaceWire time CUC packet init */
|
||||
unsigned char pktrxen; /* Enable SpaceWire time CUC packet reception */
|
||||
|
||||
unsigned char dla; /* SpaceWire destination logical address */
|
||||
unsigned char dla_mask; /* SpaceWire destination logical address mask */
|
||||
unsigned char pid; /* SpaceWire protocol ID */
|
||||
|
||||
unsigned int offset; /* Packet reception offset */
|
||||
};
|
||||
|
||||
/* SPWCUC Statistics gathered by driver */
|
||||
struct spwcuc_stats {
|
||||
|
||||
/* IRQ Stats */
|
||||
unsigned int nirqs;
|
||||
unsigned int tick_tx;
|
||||
unsigned int tick_tx_wrap;
|
||||
unsigned int tick_rx;
|
||||
unsigned int tick_rx_wrap;
|
||||
unsigned int tick_rx_error;
|
||||
unsigned int tolerr;
|
||||
unsigned int sync;
|
||||
unsigned int syncerr;
|
||||
unsigned int wrap;
|
||||
unsigned int wraperr;
|
||||
unsigned int pkt_rx;
|
||||
unsigned int pkt_err;
|
||||
unsigned int pkt_init;
|
||||
};
|
||||
|
||||
/* Function ISR callback prototype
|
||||
*
|
||||
* pimr - PIMR/PIR register of the SPWCUC core read by ISR
|
||||
* data - Custom data provided by user
|
||||
*/
|
||||
typedef void (*spwcuc_isr_t)(unsigned int pimr, void *data);
|
||||
|
||||
/* Open a SPWCUC device by minor number. A SPWCUC device can only by opened
|
||||
* once. The handle returned must be used as the input parameter 'spwcuc' in
|
||||
* the rest of the calls in the function interface.
|
||||
*/
|
||||
extern void *spwcuc_open(int minor);
|
||||
|
||||
/* Close a previously opened SPWCUC device */
|
||||
extern void spwcuc_close(void *spwcuc);
|
||||
|
||||
/* Reset SPWCUC Core */
|
||||
extern int spwcuc_reset(void *spwcuc);
|
||||
|
||||
/* Enable Interrupts at Interrupt controller */
|
||||
extern void spwcuc_int_enable(void *spwcuc);
|
||||
|
||||
/* Disable Interrupts at Interrupt controller */
|
||||
extern void spwcuc_int_disable(void *spwcuc);
|
||||
|
||||
/* Clear Statistics gathered by the driver */
|
||||
extern void spwcuc_clr_stats(void *spwcuc);
|
||||
|
||||
/* Get Statistics gathered by the driver. The statistics are stored into
|
||||
* the location pointed to by 'stats'.
|
||||
*/
|
||||
extern void spwcuc_get_stats(void *spwcuc, struct spwcuc_stats *stats);
|
||||
|
||||
/* Register an Interrupt handler and custom data, the function call is
|
||||
* removed by setting func to NULL.
|
||||
*
|
||||
* The driver's interrupt handler is installed on open(), however the user
|
||||
* callback called from the driver's ISR is installed using this function.
|
||||
*/
|
||||
extern void spwcuc_int_register(void *spwcuc, spwcuc_isr_t func, void *data);
|
||||
|
||||
/* Configure the spwcuc core. The configuration is taken from the data
|
||||
* structure pointed to by 'cfg'. See data structure spwcuc_cfg fields.
|
||||
*/
|
||||
extern void spwcuc_config(void *spwcuc, struct spwcuc_cfg *cfg);
|
||||
|
||||
/* Return elapsed coarse time */
|
||||
extern unsigned int spwcuc_get_et_coarse(void *spwcuc);
|
||||
|
||||
/* Return elapsed fine time */
|
||||
extern unsigned int spwcuc_get_et_fine(void *spwcuc);
|
||||
|
||||
/* Return elapsed time (coarse and fine) 64-bit value */
|
||||
extern unsigned long long spwcuc_get_et(void *spwcuc);
|
||||
|
||||
/* Return next elapsed coarse time (for use when sending SpW time packet) */
|
||||
extern unsigned int spwcuc_get_next_et_coarse(void *spwcuc);
|
||||
|
||||
/* Return next elapsed fine time (for use when sending SpW time packet) */
|
||||
extern unsigned int spwcuc_get_next_et_fine(void *spwcuc);
|
||||
|
||||
/* Return next elapsed time (for use when sending SpW time packet) */
|
||||
extern unsigned long long spwcuc_get_next_et(void *spwcuc);
|
||||
|
||||
/* Force/Set the elapsed time (coarse 32-bit and fine 24-bit) by writing the
|
||||
* T-Field Time Packet Registers then the FORCE bit.
|
||||
*/
|
||||
extern void spwcuc_force_et(void *spwcuc, unsigned long long time);
|
||||
|
||||
/* Return received (from time packet) elapsed coarse time */
|
||||
extern unsigned int spwcuc_get_tp_et_coarse(void *spwcuc);
|
||||
|
||||
/* Return received (from time packet) elapsed fine time */
|
||||
extern unsigned int spwcuc_get_tp_et_fine(void *spwcuc);
|
||||
|
||||
/* Return received (from time packet) elapsed time (coarse and fine) */
|
||||
extern unsigned long long spwcuc_get_tp_et(void *spwcuc);
|
||||
|
||||
/* Clear interrupts */
|
||||
extern void spwcuc_clear_irqs(void *spwcuc, int irqs);
|
||||
|
||||
/* Enable interrupts */
|
||||
extern void spwcuc_enable_irqs(void *spwcuc, int irqs);
|
||||
|
||||
/* Get Register */
|
||||
extern struct spwcuc_regs *spwcuc_get_regs(void *spwcuc);
|
||||
|
||||
/* Register the SPWCUC Driver to the Driver Manager */
|
||||
extern void spwcuc_register(void);
|
||||
|
||||
#endif
|
||||
241
c/src/lib/libbsp/sparc/shared/irq/genirq.c
Normal file
241
c/src/lib/libbsp/sparc/shared/irq/genirq.c
Normal file
@@ -0,0 +1,241 @@
|
||||
/*
|
||||
* 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.com/license/LICENSE.
|
||||
*/
|
||||
|
||||
#include <rtems.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <genirq.h>
|
||||
|
||||
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; i<priv->genirq_max; i++) {
|
||||
irqentry = &priv->genirq_table[i];
|
||||
isrentry = irqentry->head;
|
||||
while ( isrentry ) {
|
||||
tmp = isrentry;
|
||||
isrentry = isrentry->next;
|
||||
free(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;
|
||||
}
|
||||
|
||||
int genirq_register(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, *newentry;
|
||||
rtems_interrupt_level level;
|
||||
|
||||
if ( genirq_check(d, irq) )
|
||||
return -1;
|
||||
|
||||
newentry = malloc(sizeof(*newentry));
|
||||
if ( !newentry )
|
||||
return -1;
|
||||
|
||||
/* Initialize ISR entry */
|
||||
newentry->isr = isr;
|
||||
newentry->arg = arg;
|
||||
newentry->enabled = 0;
|
||||
|
||||
rtems_interrupt_disable(level);
|
||||
|
||||
/* Insert new ISR entry first into table */
|
||||
irqentry = &priv->genirq_table[irq];
|
||||
isrentry = irqentry->head;
|
||||
irqentry->head = newentry;
|
||||
newentry->next = isrentry;
|
||||
|
||||
rtems_interrupt_enable(level);
|
||||
|
||||
if ( isrentry )
|
||||
return 1; /* This is the first handler on this IRQ */
|
||||
return 0;
|
||||
}
|
||||
|
||||
int 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;
|
||||
rtems_interrupt_level level;
|
||||
int ret;
|
||||
|
||||
if ( genirq_check(d, irq) )
|
||||
return -1;
|
||||
|
||||
/* Remove isr[arg] from ISR list */
|
||||
irqentry = &priv->genirq_table[irq];
|
||||
ret = -1;
|
||||
|
||||
rtems_interrupt_disable(level);
|
||||
|
||||
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 = 1;
|
||||
break;
|
||||
}
|
||||
*prev = isrentry->next;
|
||||
ret = 0;
|
||||
break;
|
||||
}
|
||||
prev = &isrentry->next;
|
||||
isrentry = isrentry->next;
|
||||
}
|
||||
|
||||
rtems_interrupt_enable(level);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Enables or Disables ISR handler. Internal function to reduce footprint
|
||||
* of enable/disable functions.
|
||||
*
|
||||
* \param action 1=enable, 0=disable ISR
|
||||
*/
|
||||
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);
|
||||
}
|
||||
}
|
||||
210
c/src/lib/libbsp/sparc/shared/mem/mctrl.c
Normal file
210
c/src/lib/libbsp/sparc/shared/mem/mctrl.c
Normal file
@@ -0,0 +1,210 @@
|
||||
/* 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.com/license/LICENSE.
|
||||
*/
|
||||
|
||||
/******************* Driver manager interface ***********************/
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include <drvmgr/drvmgr.h>
|
||||
#include <drvmgr/ambapp_bus.h>
|
||||
|
||||
#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, KEY_TYPE_INT);
|
||||
if ( value ) {
|
||||
priv->mcfg[i] = value->i;
|
||||
priv->configured |= (1<<i);
|
||||
}
|
||||
}
|
||||
|
||||
/* Init hardware registers right away, other devices may depend on it in init2(), also
|
||||
* the washing depend on it.
|
||||
*/
|
||||
for ( i=0; i<8; i++) {
|
||||
if ( priv->configured & (1<<i) ) {
|
||||
DBG("Setting MCFG%d to 0x%08x\n", i+1, priv->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, KEY_TYPE_INT);
|
||||
if ( value ) {
|
||||
start = value->i;
|
||||
strcpy(res_name, "washXLength");
|
||||
res_name[4] = '0' + i;
|
||||
value = drvmgr_dev_key_get(priv->dev, res_name, KEY_TYPE_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;
|
||||
}
|
||||
7
c/src/lib/libbsp/sparc/shared/net/README
Normal file
7
c/src/lib/libbsp/sparc/shared/net/README
Normal file
@@ -0,0 +1,7 @@
|
||||
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.
|
||||
1424
c/src/lib/libbsp/sparc/shared/net/greth.c
Normal file
1424
c/src/lib/libbsp/sparc/shared/net/greth.c
Normal file
File diff suppressed because it is too large
Load Diff
847
c/src/lib/libbsp/sparc/shared/pwm/grpwm.c
Normal file
847
c/src/lib/libbsp/sparc/shared/pwm/grpwm.c
Normal file
@@ -0,0 +1,847 @@
|
||||
/*
|
||||
* 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.com/license/LICENSE.
|
||||
*/
|
||||
|
||||
#include <bsp.h>
|
||||
#include <rtems/libio.h>
|
||||
#include <stdlib.h>
|
||||
#include <assert.h>
|
||||
#include <rtems/bspIo.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include <drvmgr/drvmgr.h>
|
||||
#include <drvmgr/ambapp_bus.h>
|
||||
#include <grpwm.h>
|
||||
#include <ambapp.h>
|
||||
|
||||
/* #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<<GRPWM_CTRL_EN_BIT)
|
||||
#define GRPWM_CTRL_SCSEL (0x7<<GRPWM_CTRL_SCSEL_BIT)
|
||||
#define GRPWM_CTRL_NOUP (0xff<<GRPWM_CTRL_NOUP_BIT)
|
||||
|
||||
|
||||
/* CAPABILITY1 REGISTER - 0x0C */
|
||||
#define GRPWM_CAP_NPWM_BIT 0
|
||||
#define GRPWM_CAP_PBITS_BIT 3
|
||||
#define GRPWM_CAP_SBITS_BIT 8
|
||||
#define GRPWM_CAP_NSC_BIT 13
|
||||
#define GRPWM_CAP_DBB_BIT 16
|
||||
#define GRPWM_CAP_DBSC_BIT 21
|
||||
#define GRPWM_CAP_ASY_BIT 22
|
||||
#define GRPWM_CAP_SYM_BIT 23
|
||||
#define GRPWM_CAP_SEP_BIT 25
|
||||
#define GRPWM_CAP_DCM_BIT 27
|
||||
|
||||
#define GRPWM_CAP_NPWM (0x7<<GRPWM_CAP_NPWM_BIT)
|
||||
#define GRPWM_CAP_PBITS (0x1f<<GRPWM_CAP_PBITS_BIT)
|
||||
#define GRPWM_CAP_SBITS (0x1f<<GRPWM_CAP_SBITS_BIT)
|
||||
#define GRPWM_CAP_NSC (0x7<<GRPWM_CAP_NSC_BIT)
|
||||
#define GRPWM_CAP_DBB (0x1f<<GRPWM_CAP_DBB_BIT)
|
||||
#define GRPWM_CAP_DBSC (1<<GRPWM_CAP_DBSC_BIT)
|
||||
#define GRPWM_CAP_ASY (1<<GRPWM_CAP_ASY_BIT)
|
||||
#define GRPWM_CAP_SYM (1<<GRPWM_CAP_SYM_BIT)
|
||||
#define GRPWM_CAP_SEP (0x3<<GRPWM_CAP_SEP_BIT)
|
||||
#define GRPWM_CAP_DCM (1<<GRPWM_CAP_DCM_BIT)
|
||||
|
||||
/* CAPABILITY2 REGISTER - 0x10 */
|
||||
#define GRPWM_CAP2_WPWM_BIT 0
|
||||
#define GRPWM_CAP2_WDBITS_BIT 1
|
||||
#define GRPWM_CAP2_WABITS_BIT 6
|
||||
#define GRPWM_CAP2_WSYNC_BIT 10
|
||||
|
||||
#define GRPWM_CAP2_WPWM (0x1<<GRPWM_CAP2_WPWM_BIT)
|
||||
#define GRPWM_CAP2_WDBITS (0x1f<<GRPWM_CAP2_WDBITS_BIT)
|
||||
#define GRPWM_CAP2_WABITS (0xf<<GRPWM_CAP2_WABITS_BIT)
|
||||
#define GRPWM_CAP2_WSYNC (1<<GRPWM_CAP2_WSYNC_BIT)
|
||||
|
||||
/* WAVE FORM CONFIG REGISTER - 0x14 */
|
||||
#define GRPWM_WCTRL_STOP_BIT 0
|
||||
#define GRPWM_WCTRL_WSYNC_BIT 16
|
||||
#define GRPWM_WCTRL_WSEN_BIT 29
|
||||
#define GRPWM_WCTRL_WSYNCCFG_BIT 30
|
||||
|
||||
#define GRPWM_WCTRL_STOP (0x1fff<<GRPWM_WCTRL_STOP_BIT)
|
||||
#define GRPWM_WCTRL_WSYNC (0x1fff<<GRPWM_WCTRL_WSYNC_BIT)
|
||||
#define GRPWM_WCTRL_WSEN (0x1<<GRPWM_WCTRL_WSEN_BIT)
|
||||
#define GRPWM_WCTRL_WSYNCCFG (0x3<<GRPWM_WCTRL_WSYNCCFG_BIT)
|
||||
|
||||
|
||||
/* PWM CONTROL REGISTER - 0x2C, 0x3C... */
|
||||
#define GRPWM_PCTRL_EN_BIT 0
|
||||
#define GRPWM_PCTRL_POL_BIT 1
|
||||
#define GRPWM_PCTRL_PAIR_BIT 2
|
||||
#define GRPWM_PCTRL_FIX_BIT 3
|
||||
#define GRPWM_PCTRL_METH_BIT 6
|
||||
#define GRPWM_PCTRL_DCEN_BIT 8
|
||||
#define GRPWM_PCTRL_WEN_BIT 9
|
||||
#define GRPWM_PCTRL_SCSEL_BIT 10
|
||||
#define GRPWM_PCTRL_IEN_BIT 13
|
||||
#define GRPWM_PCTRL_IT_BIT 14
|
||||
#define GRPWM_PCTRL_ISC_BIT 15
|
||||
#define GRPWM_PCTRL_DBEN_BIT 21
|
||||
#define GRPWM_PCTRL_DBSC_BIT 22
|
||||
#define GRPWM_PCTRL_FLIP_BIT 26
|
||||
|
||||
#define GRPWM_PCTRL_EN (0x1<<GRPWM_PCTRL_EN_BIT)
|
||||
#define GRPWM_PCTRL_POL (0x1<<GRPWM_PCTRL_POL_BIT)
|
||||
#define GRPWM_PCTRL_PAIR (0x1<<GRPWM_PCTRL_PAIR_BIT)
|
||||
#define GRPWM_PCTRL_FIX (0x7<<GRPWM_PCTRL_FIX_BIT)
|
||||
#define GRPWM_PCTRL_METH (0x1<<GRPWM_PCTRL_METH_BIT)
|
||||
#define GRPWM_PCTRL_DCEN (0x1<<GRPWM_PCTRL_DCEN_BIT)
|
||||
#define GRPWM_PCTRL_WEN (0x1<<GRPWM_PCTRL_WEN_BIT)
|
||||
#define GRPWM_PCTRL_SCSEL (0x7<<GRPWM_PCTRL_SCSEL_BIT)
|
||||
#define GRPWM_PCTRL_IEN (0x1<<GRPWM_PCTRL_IEN_BIT)
|
||||
#define GRPWM_PCTRL_IT (0x1<<GRPWM_PCTRL_IT_BIT)
|
||||
#define GRPWM_PCTRL_ISC (0x3f<<GRPWM_PCTRL_ISC_BIT)
|
||||
#define GRPWM_PCTRL_DBEN (0x1<<GRPWM_PCTRL_DBEN_BIT)
|
||||
#define GRPWM_PCTRL_DBSC (0xf<<GRPWM_PCTRL_DBSC_BIT)
|
||||
#define GRPWM_PCTRL_FLIP (0xf<<GRPWM_PCTRL_FLIP_BIT)
|
||||
|
||||
/*** DRIVER PRIVATE STRUCTURE ***/
|
||||
struct grpwm_priv {
|
||||
struct drvmgr_dev *dev;
|
||||
struct grpwm_regs *regs;
|
||||
char devName[32];
|
||||
int irq;
|
||||
int open;
|
||||
|
||||
/* Driver implementation */
|
||||
char nscalers; /* Number of scalers */
|
||||
char wave; /* If Wave form is available */
|
||||
int wlength; /* Wave Form RAM Length */
|
||||
int channel_cnt;
|
||||
struct grpwm_chan_priv *channels[8];
|
||||
rtems_id dev_sem;
|
||||
};
|
||||
|
||||
struct grpwm_chan_priv {
|
||||
struct grpwm_priv *common;
|
||||
struct grpwm_pwm_regs *pwmregs;
|
||||
/* IRQ */
|
||||
int irqindex;
|
||||
void (*isr)(int channel, void *arg);
|
||||
void *isr_arg;
|
||||
};
|
||||
|
||||
/******************* Driver Manager Part ***********************/
|
||||
|
||||
int grpwm_device_init(struct grpwm_priv *priv);
|
||||
int grpwm_register_io(rtems_device_major_number *m);
|
||||
static int grpwm_driver_io_registered = 0;
|
||||
static rtems_device_major_number grpwm_driver_io_major = 0;
|
||||
|
||||
int grpwm_init2(struct drvmgr_dev *dev);
|
||||
int grpwm_init3(struct drvmgr_dev *dev);
|
||||
|
||||
struct drvmgr_drv_ops grpwm_ops =
|
||||
{
|
||||
.init = {NULL, grpwm_init2, grpwm_init3, NULL},
|
||||
.remove = NULL,
|
||||
.info = NULL
|
||||
};
|
||||
|
||||
struct amba_dev_id grpwm_ids[] =
|
||||
{
|
||||
{VENDOR_GAISLER, GAISLER_GRPWM},
|
||||
{0, 0} /* Mark end of table */
|
||||
};
|
||||
|
||||
struct amba_drv_info grpwm_drv_info =
|
||||
{
|
||||
{
|
||||
DRVMGR_OBJ_DRV, /* Driver */
|
||||
NULL, /* Next driver */
|
||||
NULL, /* Device list */
|
||||
DRIVER_AMBAPP_GAISLER_GRPWM_ID, /* Driver ID */
|
||||
"GRPWM_DRV", /* Driver Name */
|
||||
DRVMGR_BUS_TYPE_AMBAPP, /* Bus Type */
|
||||
&grpwm_ops,
|
||||
NULL, /* Funcs */
|
||||
0, /* No devices yet */
|
||||
0,
|
||||
},
|
||||
&grpwm_ids[0]
|
||||
};
|
||||
|
||||
void grpwm_register_drv (void)
|
||||
{
|
||||
DBG("Registering GRPWM driver\n");
|
||||
drvmgr_drv_register(&grpwm_drv_info.general);
|
||||
}
|
||||
|
||||
int grpwm_init2(struct drvmgr_dev *dev)
|
||||
{
|
||||
struct grpwm_priv *priv;
|
||||
|
||||
DBG("GRPWM[%d] on bus %s\n", dev->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;
|
||||
}
|
||||
|
||||
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 */
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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; i<priv->channel_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; i<priv->nscalers; 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.
|
||||
*/
|
||||
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;
|
||||
}
|
||||
|
||||
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; i<priv->channel_cnt; i++) {
|
||||
ctrl |= priv->regs->pwms[i].ctrl & GRPWM_CTRL_EN;
|
||||
}
|
||||
}
|
||||
priv->regs->ctrl = ctrl;
|
||||
}
|
||||
|
||||
/* Configure the hardware of a channel according to this */
|
||||
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; i<priv->channel_cnt; i++) {
|
||||
if ( ipend & (1<<i) ) {
|
||||
pwm = priv->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; i<priv->nscalers; i++) {
|
||||
if ( sc->index_mask & (1<<i) ) {
|
||||
/* Update Scaler 'i' */
|
||||
grpwm_scaler_set(priv->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; i<priv->channel_cnt; i++) {
|
||||
if ( up->chanmask & (1<<i) ) {
|
||||
/* Prepare update channel 'i' */
|
||||
pctrl |= grpwm_update_prepare_channel(priv, i, &up->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<<channel);
|
||||
drvmgr_interrupt_clear(priv->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; i<priv->channel_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; i<priv->channel_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;
|
||||
}
|
||||
661
c/src/lib/libbsp/sparc/shared/slink/grslink.c
Normal file
661
c/src/lib/libbsp/sparc/shared/slink/grslink.c
Normal file
@@ -0,0 +1,661 @@
|
||||
/*
|
||||
* 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.com/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 <stdlib.h>
|
||||
|
||||
#include <bsp.h>
|
||||
#include <grslink.h>
|
||||
#include <ambapp.h>
|
||||
|
||||
#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 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 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
|
||||
}
|
||||
1008
c/src/lib/libbsp/sparc/shared/spi/spictrl.c
Normal file
1008
c/src/lib/libbsp/sparc/shared/spi/spictrl.c
Normal file
File diff suppressed because it is too large
Load Diff
549
c/src/lib/libbsp/sparc/shared/spw/grspw_router.c
Normal file
549
c/src/lib/libbsp/sparc/shared/spw/grspw_router.c
Normal file
@@ -0,0 +1,549 @@
|
||||
/* GRSPW ROUTER APB-Register 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.com/license/LICENSE.
|
||||
*/
|
||||
|
||||
#include <rtems.h>
|
||||
#include <rtems/libio.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include <drvmgr/drvmgr.h>
|
||||
#include <drvmgr/ambapp_bus.h>
|
||||
#include <grspw_router.h>
|
||||
|
||||
#define ROUTER_DBG(args...)
|
||||
|
||||
#define REG_READ(adr) (*(volatile unsigned int *)(adr))
|
||||
#define REG_WRITE(adr, value) (*(volatile unsigned int *)(adr) = (value))
|
||||
|
||||
struct router_regs {
|
||||
unsigned int resv1; /* 0x000 */
|
||||
unsigned int psetup[255]; /* 0x004 */
|
||||
unsigned int resv2[32]; /* 0x400 */
|
||||
unsigned int routes[224]; /* 0x480 */
|
||||
unsigned int pctrl[32]; /* 0x800 */
|
||||
unsigned int psts[32]; /* 0x880 */
|
||||
unsigned int treload[32]; /* 0x900 */
|
||||
unsigned int resv3[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 resv4[123]; /* 0xA18 */
|
||||
unsigned int charo[31]; /* 0xC04 */
|
||||
unsigned int resv5; /* 0xC80 */
|
||||
unsigned int chari[31]; /* 0xC84 */
|
||||
unsigned int resv6; /* 0xD00 */
|
||||
unsigned int pkto[31]; /* 0xD04 */
|
||||
unsigned int resv7; /* 0xD80 */
|
||||
unsigned int pkti[31]; /* 0xD84 */
|
||||
};
|
||||
|
||||
struct router_priv {
|
||||
char devName[32];
|
||||
struct drvmgr_dev *dev;
|
||||
struct router_regs *regs;
|
||||
int minor;
|
||||
int open;
|
||||
struct router_hw_info hwinfo;
|
||||
int nports;
|
||||
};
|
||||
|
||||
static rtems_device_driver router_initialize(
|
||||
rtems_device_major_number major,
|
||||
rtems_device_minor_number minor,
|
||||
void * arg
|
||||
);
|
||||
|
||||
static rtems_device_driver router_open(
|
||||
rtems_device_major_number major,
|
||||
rtems_device_minor_number minor,
|
||||
void * arg
|
||||
);
|
||||
|
||||
static rtems_device_driver router_close(
|
||||
rtems_device_major_number major,
|
||||
rtems_device_minor_number minor,
|
||||
void * arg
|
||||
);
|
||||
|
||||
static rtems_device_driver router_control(
|
||||
rtems_device_major_number major,
|
||||
rtems_device_minor_number minor,
|
||||
void * arg
|
||||
);
|
||||
|
||||
#define ROUTER_DRIVER_TABLE_ENTRY \
|
||||
{ router_initialize, \
|
||||
router_open, \
|
||||
router_close, \
|
||||
NULL, \
|
||||
NULL, \
|
||||
router_control }
|
||||
|
||||
void router_hwinfo(struct router_priv *priv, struct router_hw_info *hwinfo);
|
||||
|
||||
static rtems_driver_address_table router_driver = ROUTER_DRIVER_TABLE_ENTRY;
|
||||
static int router_driver_io_registered = 0;
|
||||
static rtems_device_major_number router_driver_io_major = 0;
|
||||
|
||||
/******************* Driver manager interface ***********************/
|
||||
|
||||
/* Driver prototypes */
|
||||
int router_register_io(rtems_device_major_number *m);
|
||||
|
||||
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)
|
||||
{
|
||||
drvmgr_drv_register(&router_drv_info.general);
|
||||
}
|
||||
|
||||
int router_init2(struct drvmgr_dev *dev)
|
||||
{
|
||||
struct router_priv *priv = dev->priv;
|
||||
struct amba_dev_info *ambadev;
|
||||
struct ambapp_core *pnpinfo;
|
||||
char prefix[32];
|
||||
rtems_status_code status;
|
||||
|
||||
if ( priv == NULL )
|
||||
return DRVMGR_NOMEM;
|
||||
priv->dev = dev;
|
||||
|
||||
/* Do initialization */
|
||||
if ( router_driver_io_registered == 0) {
|
||||
/* Register the I/O driver only once for all cores */
|
||||
if ( router_register_io(&router_driver_io_major) ) {
|
||||
/* Failed to register I/O driver */
|
||||
return DRVMGR_FAIL;
|
||||
}
|
||||
|
||||
router_driver_io_registered = 1;
|
||||
}
|
||||
|
||||
/* 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;
|
||||
|
||||
/* Register character device in registered region */
|
||||
router_hwinfo(priv, &priv->hwinfo);
|
||||
priv->open = 0;
|
||||
priv->nports = priv->hwinfo.nports_spw + priv->hwinfo.nports_amba +
|
||||
priv->hwinfo.nports_fifo;
|
||||
if ( (priv->nports < 2) || (priv->nports > 32) )
|
||||
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/router%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/%srouter%d", prefix, dev->minor_bus);
|
||||
}
|
||||
|
||||
/* Register Device */
|
||||
status = rtems_io_register_name(priv->devName, router_driver_io_major, dev->minor_drv);
|
||||
if (status != RTEMS_SUCCESSFUL) {
|
||||
return DRVMGR_FAIL;
|
||||
}
|
||||
|
||||
return DRVMGR_OK;
|
||||
}
|
||||
|
||||
int router_register_io(rtems_device_major_number *m)
|
||||
{
|
||||
rtems_status_code r;
|
||||
|
||||
if ((r = rtems_io_register_driver(0, &router_driver, m)) == RTEMS_SUCCESSFUL) {
|
||||
ROUTER_DBG("ROUTER driver successfully registered, major: %d\n", *m);
|
||||
} else {
|
||||
switch(r) {
|
||||
case RTEMS_TOO_MANY:
|
||||
printk("ROUTER rtems_io_register_driver failed: RTEMS_TOO_MANY\n");
|
||||
return -1;
|
||||
case RTEMS_INVALID_NUMBER:
|
||||
printk("ROUTER rtems_io_register_driver failed: RTEMS_INVALID_NUMBER\n");
|
||||
return -1;
|
||||
case RTEMS_RESOURCE_IN_USE:
|
||||
printk("ROUTER rtems_io_register_driver failed: RTEMS_RESOURCE_IN_USE\n");
|
||||
return -1;
|
||||
default:
|
||||
printk("ROUTER rtems_io_register_driver failed\n");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static rtems_device_driver router_initialize(
|
||||
rtems_device_major_number major,
|
||||
rtems_device_minor_number minor,
|
||||
void *arg
|
||||
)
|
||||
{
|
||||
return RTEMS_SUCCESSFUL;
|
||||
}
|
||||
|
||||
static rtems_device_driver router_open(
|
||||
rtems_device_major_number major,
|
||||
rtems_device_minor_number minor,
|
||||
void * arg
|
||||
)
|
||||
{
|
||||
struct router_priv *priv;
|
||||
struct drvmgr_dev *dev;
|
||||
|
||||
if ( drvmgr_get_dev(&router_drv_info.general, minor, &dev) ) {
|
||||
ROUTER_DBG("Wrong minor %d\n", minor);
|
||||
return RTEMS_INVALID_NAME;
|
||||
}
|
||||
priv = (struct router_priv *)dev->priv;
|
||||
|
||||
if ( !priv || priv->open ) {
|
||||
return RTEMS_RESOURCE_IN_USE;
|
||||
}
|
||||
|
||||
priv->open = 1;
|
||||
|
||||
return RTEMS_SUCCESSFUL;
|
||||
}
|
||||
|
||||
static rtems_device_driver router_close(
|
||||
rtems_device_major_number major,
|
||||
rtems_device_minor_number minor,
|
||||
void * arg
|
||||
)
|
||||
{
|
||||
struct router_priv *priv;
|
||||
struct drvmgr_dev *dev;
|
||||
|
||||
if ( drvmgr_get_dev(&router_drv_info.general, minor, &dev) ) {
|
||||
ROUTER_DBG("Wrong minor %d\n", minor);
|
||||
return RTEMS_INVALID_NAME;
|
||||
}
|
||||
priv = (struct router_priv *)dev->priv;
|
||||
|
||||
priv->open = 0;
|
||||
|
||||
return RTEMS_SUCCESSFUL;
|
||||
}
|
||||
|
||||
void router_hwinfo(struct router_priv *priv, struct router_hw_info *hwinfo)
|
||||
{
|
||||
unsigned int tmp;
|
||||
|
||||
tmp = REG_READ(&priv->regs->cfgsts);
|
||||
hwinfo->nports_spw = (tmp >> 27) & 0x1f;
|
||||
hwinfo->nports_amba = (tmp >> 22) & 0x1f;
|
||||
hwinfo->nports_fifo = (tmp >> 17) & 0x1f;
|
||||
hwinfo->timers_avail = (tmp >> 1) & 0x1;
|
||||
hwinfo->pnp_avail = (tmp >> 0) & 0x1;
|
||||
|
||||
tmp = REG_READ(&priv->regs->ver);
|
||||
hwinfo->ver_major = (tmp >> 24) & 0xff;
|
||||
hwinfo->ver_minor = (tmp >> 16) & 0xff;
|
||||
hwinfo->ver_patch = (tmp >> 8) & 0xff;
|
||||
hwinfo->iid = (tmp >> 0) & 0xff;
|
||||
}
|
||||
|
||||
int router_config_set(struct router_priv *priv, struct router_config *cfg)
|
||||
{
|
||||
int i;
|
||||
|
||||
if ( (cfg->flags & (ROUTER_FLG_TPRES|ROUTER_FLG_TRLD)) &&
|
||||
!priv->hwinfo.timers_avail ) {
|
||||
return RTEMS_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
/* Write only configuration bits in Config register */
|
||||
if ( cfg->flags & ROUTER_FLG_CFG ) {
|
||||
REG_WRITE(&priv->regs->cfgsts, cfg->config & ~0x4);
|
||||
}
|
||||
|
||||
/* Write Instance ID to Version Register */
|
||||
if ( cfg->flags & ROUTER_FLG_IID ) {
|
||||
REG_WRITE(&priv->regs->ver, cfg->iid);
|
||||
}
|
||||
|
||||
/* Write startup-clock-divisor Register */
|
||||
if ( cfg->flags & ROUTER_FLG_IDIV ) {
|
||||
REG_WRITE(&priv->regs->idiv, cfg->idiv);
|
||||
}
|
||||
|
||||
/* Write Timer Prescaler Register */
|
||||
if ( cfg->flags & ROUTER_FLG_TPRES ) {
|
||||
REG_WRITE(&priv->regs->tprescaler, cfg->timer_prescaler);
|
||||
}
|
||||
|
||||
/* Write Timer Reload Register */
|
||||
if ( cfg->flags & ROUTER_FLG_TRLD ) {
|
||||
for (i=0; i<=priv->nports; i++)
|
||||
REG_WRITE(&priv->regs->treload[i], cfg->timer_reload[i]);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int router_config_read(struct router_priv *priv, struct router_config *cfg)
|
||||
{
|
||||
int i;
|
||||
|
||||
cfg->config = REG_READ(&priv->regs->cfgsts) & ~0xffff0007;
|
||||
cfg->iid = REG_READ(&priv->regs->ver) & 0xff;
|
||||
cfg->idiv = REG_READ(&priv->regs->idiv) & 0xff;
|
||||
cfg->timer_prescaler = REG_READ(&priv->regs->tprescaler);
|
||||
for (i=0; i<=priv->nports; i++)
|
||||
cfg->timer_reload[i] = REG_READ(&priv->regs->treload[i]);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int router_routes_set(struct router_priv *priv, struct router_routes *routes)
|
||||
{
|
||||
int i;
|
||||
for (i=0; i<224; i++)
|
||||
REG_WRITE(&priv->regs->routes[i], routes->route[i]);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int router_routes_read(struct router_priv *priv, struct router_routes *routes)
|
||||
{
|
||||
int i;
|
||||
for (i=0; i<224; i++)
|
||||
routes->route[i] = REG_READ(&priv->regs->routes[i]);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int router_ps_set(struct router_priv *priv, struct router_ps *ps)
|
||||
{
|
||||
int i;
|
||||
unsigned int *p = &ps->ps[0];
|
||||
for (i=0; i<255; i++,p++)
|
||||
REG_WRITE(&priv->regs->psetup[i], *p);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int router_ps_read(struct router_priv *priv, struct router_ps *ps)
|
||||
{
|
||||
int i;
|
||||
unsigned int *p = &ps->ps[0];
|
||||
for (i=0; i<255; i++,p++)
|
||||
REG_WRITE(&priv->regs->psetup[i], *p);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int router_we_set(struct router_priv *priv, int we)
|
||||
{
|
||||
REG_WRITE(&priv->regs->cfgwe, we & 0x1);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int router_port_ctrl(struct router_priv *priv, struct router_port *port)
|
||||
{
|
||||
unsigned int ctrl, sts;
|
||||
|
||||
if ( port->port > priv->nports )
|
||||
return RTEMS_INVALID_NAME;
|
||||
|
||||
ctrl = port->ctrl;
|
||||
if ( port->flag & ROUTER_PORTFLG_GET_CTRL ) {
|
||||
ctrl = REG_READ(&priv->regs->pctrl[port->port]);
|
||||
}
|
||||
sts = port->sts;
|
||||
if ( port->flag & ROUTER_PORTFLG_GET_STS ) {
|
||||
sts = REG_READ(&priv->regs->psts[port->port]);
|
||||
}
|
||||
|
||||
if ( port->flag & ROUTER_PORTFLG_SET_CTRL ) {
|
||||
REG_WRITE(&priv->regs->pctrl[port->port], port->ctrl);
|
||||
}
|
||||
if ( port->flag & ROUTER_PORTFLG_SET_STS ) {
|
||||
REG_WRITE(&priv->regs->psts[port->port], port->sts);
|
||||
}
|
||||
|
||||
port->ctrl = ctrl;
|
||||
port->sts = sts;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int router_cfgsts_set(struct router_priv *priv, unsigned int cfgsts)
|
||||
{
|
||||
REG_WRITE(&priv->regs->cfgsts, cfgsts);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int router_cfgsts_read(struct router_priv *priv, unsigned int *cfgsts)
|
||||
{
|
||||
*cfgsts = REG_READ(&priv->regs->cfgsts);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int router_tc_read(struct router_priv *priv, unsigned int *tc)
|
||||
{
|
||||
*tc = REG_READ(&priv->regs->timecode);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static rtems_device_driver router_control(
|
||||
rtems_device_major_number major,
|
||||
rtems_device_minor_number minor,
|
||||
void * arg
|
||||
)
|
||||
{
|
||||
struct router_priv *priv;
|
||||
struct drvmgr_dev *dev;
|
||||
rtems_libio_ioctl_args_t *ioarg = (rtems_libio_ioctl_args_t *) arg;
|
||||
void *argp = (void *)ioarg->buffer;
|
||||
|
||||
if ( drvmgr_get_dev(&router_drv_info.general, minor, &dev) ) {
|
||||
ROUTER_DBG("Wrong minor %d\n", minor);
|
||||
return RTEMS_INVALID_NAME;
|
||||
}
|
||||
priv = (struct router_priv *)dev->priv;
|
||||
|
||||
ioarg->ioctl_return = 0;
|
||||
switch (ioarg->command) {
|
||||
|
||||
/* Get Hardware support/information available */
|
||||
case GRSPWR_IOCTL_HWINFO:
|
||||
{
|
||||
struct router_hw_info *hwinfo = argp;
|
||||
router_hwinfo(priv, hwinfo);
|
||||
break;
|
||||
}
|
||||
|
||||
/* Set Router Configuration */
|
||||
case GRSPWR_IOCTL_CFG_SET:
|
||||
{
|
||||
struct router_config *cfg = argp;
|
||||
return router_config_set(priv, cfg);
|
||||
}
|
||||
|
||||
/* Read Router Configuration */
|
||||
case GRSPWR_IOCTL_CFG_GET:
|
||||
{
|
||||
struct router_config *cfg = argp;
|
||||
router_config_read(priv, cfg);
|
||||
break;
|
||||
}
|
||||
|
||||
/* Routes */
|
||||
case GRSPWR_IOCTL_ROUTES_SET:
|
||||
{
|
||||
struct router_routes *routes = argp;
|
||||
return router_routes_set(priv, routes);
|
||||
}
|
||||
|
||||
case GRSPWR_IOCTL_ROUTES_GET:
|
||||
{
|
||||
struct router_routes *routes = argp;
|
||||
router_routes_read(priv, routes);
|
||||
break;
|
||||
}
|
||||
|
||||
/* Port Setup */
|
||||
case GRSPWR_IOCTL_PS_SET:
|
||||
{
|
||||
struct router_ps *ps = argp;
|
||||
return router_ps_set(priv, ps);
|
||||
}
|
||||
|
||||
case GRSPWR_IOCTL_PS_GET:
|
||||
{
|
||||
struct router_ps *ps = argp;
|
||||
router_ps_read(priv, ps);
|
||||
break;
|
||||
}
|
||||
|
||||
/* Set configuration write enable */
|
||||
case GRSPWR_IOCTL_WE_SET:
|
||||
{
|
||||
return router_we_set(priv, (int)argp);
|
||||
}
|
||||
|
||||
/* Set/Get Port Control/Status */
|
||||
case GRSPWR_IOCTL_PORT:
|
||||
{
|
||||
struct router_port *port = argp;
|
||||
int result;
|
||||
if ( (result=router_port_ctrl(priv, port)) )
|
||||
return result;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Set Router Configuration/Status Register */
|
||||
case GRSPWR_IOCTL_CFGSTS_SET:
|
||||
{
|
||||
return router_cfgsts_set(priv, (int)argp);
|
||||
}
|
||||
|
||||
/* Get Router Configuration/Status Register */
|
||||
case GRSPWR_IOCTL_CFGSTS_GET:
|
||||
{
|
||||
unsigned int *cfgsts = argp;
|
||||
router_cfgsts_read(priv, cfgsts);
|
||||
break;
|
||||
}
|
||||
|
||||
/* Get Current Time-Code Register */
|
||||
case GRSPWR_IOCTL_TC_GET:
|
||||
{
|
||||
unsigned int *tc = argp;
|
||||
router_tc_read(priv, tc);
|
||||
break;
|
||||
}
|
||||
|
||||
default: return RTEMS_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
409
c/src/lib/libbsp/sparc/shared/time/grctm.c
Normal file
409
c/src/lib/libbsp/sparc/shared/time/grctm.c
Normal file
@@ -0,0 +1,409 @@
|
||||
/* 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.com/license/LICENSE.
|
||||
*/
|
||||
|
||||
#include <drvmgr/drvmgr.h>
|
||||
#include <drvmgr/ambapp_bus.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <grctm.h>
|
||||
|
||||
/* 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 ***/
|
||||
|
||||
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);
|
||||
}
|
||||
369
c/src/lib/libbsp/sparc/shared/time/spwcuc.c
Normal file
369
c/src/lib/libbsp/sparc/shared/time/spwcuc.c
Normal file
@@ -0,0 +1,369 @@
|
||||
/* 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.com/license/LICENSE.
|
||||
*/
|
||||
|
||||
#include <drvmgr/drvmgr.h>
|
||||
#include <drvmgr/ambapp_bus.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <spwcuc.h>
|
||||
|
||||
/* 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 */
|
||||
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 ***/
|
||||
|
||||
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);
|
||||
}
|
||||
1962
c/src/lib/libbsp/sparc/shared/tmtc/grtc.c
Normal file
1962
c/src/lib/libbsp/sparc/shared/tmtc/grtc.c
Normal file
File diff suppressed because it is too large
Load Diff
1587
c/src/lib/libbsp/sparc/shared/tmtc/grtm.c
Normal file
1587
c/src/lib/libbsp/sparc/shared/tmtc/grtm.c
Normal file
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user