From 56601df6184c282695c8c2654a4e5fb1df253e85 Mon Sep 17 00:00:00 2001 From: Patrick Robbe <robbe@lal.in2p3.fr> Date: Tue, 11 Jun 2019 18:46:10 +0900 Subject: [PATCH] New structure --- Pcie40DriverLibraries/pcie40_driverlib.c | 7 + Pcie40DriverLibraries/pcie40_driverlib.h | 8 + Pcie40DriverLibraries/rules.mk | 318 +++++++++++ Pcie40Libraries/Makefile | 127 +++++ Pcie40Libraries/Makefile.conf | 26 + Pcie40Libraries/i2cDriver.c | 656 +++++++++++++++++++++++ Pcie40Libraries/i2cDriver.h | 19 + Pcie40Libraries/pcie40_ecs.c | 351 ++++++++++++ Pcie40Libraries/pcie40_ecs.h | 55 ++ Pcie40Libraries/systemConfig.h | 61 +++ 10 files changed, 1628 insertions(+) create mode 100644 Pcie40DriverLibraries/pcie40_driverlib.c create mode 100644 Pcie40DriverLibraries/pcie40_driverlib.h create mode 100644 Pcie40DriverLibraries/rules.mk create mode 100644 Pcie40Libraries/Makefile create mode 100644 Pcie40Libraries/Makefile.conf create mode 100644 Pcie40Libraries/i2cDriver.c create mode 100644 Pcie40Libraries/i2cDriver.h create mode 100644 Pcie40Libraries/pcie40_ecs.c create mode 100644 Pcie40Libraries/pcie40_ecs.h create mode 100644 Pcie40Libraries/systemConfig.h diff --git a/Pcie40DriverLibraries/pcie40_driverlib.c b/Pcie40DriverLibraries/pcie40_driverlib.c new file mode 100644 index 0000000..f938c4f --- /dev/null +++ b/Pcie40DriverLibraries/pcie40_driverlib.c @@ -0,0 +1,7 @@ +#include "pcie40_driverlib.h" +#include <stdio.h> + +int p40_get_devname(int dev, const char* suffix, char *dst, size_t dstlen) +{ + return snprintf(dst, dstlen, "/dev/pcie40_%d_%s", dev, suffix); +} diff --git a/Pcie40DriverLibraries/pcie40_driverlib.h b/Pcie40DriverLibraries/pcie40_driverlib.h new file mode 100644 index 0000000..9f8430e --- /dev/null +++ b/Pcie40DriverLibraries/pcie40_driverlib.h @@ -0,0 +1,8 @@ +#ifndef __PCIE40_H +#define __PCIE40_H + +#include <stdlib.h> + +int p40_get_devname(int dev, const char *suffix, char *dst, size_t dstlen); + +#endif//__PCIE40_H diff --git a/Pcie40DriverLibraries/rules.mk b/Pcie40DriverLibraries/rules.mk new file mode 100644 index 0000000..3847904 --- /dev/null +++ b/Pcie40DriverLibraries/rules.mk @@ -0,0 +1,318 @@ +BUILD_PREFIX ?= +LIBDIR_SUFFIX ?=64 +FLEX ?=flex +LFLAGS ?= +CFLAGS +=-Wall -g -O3 +CXXFLAGS +=-Wall -g -O3 +DOCRA ?=docra +ASCIIDOCTOR ?=asciidoctor + +define INST_template #file, dst, mode +INSTALL +=$(BUILD_PREFIX)$(2)/$(notdir $(1)) +ifeq (,$(wildcard $(HERE)/$(1))) +# Installing using absolute path +$(BUILD_PREFIX)$(2)/$(notdir $(1)): $(1) + @install -m 755 -d $(BUILD_PREFIX)$(2) + install -m $(3) $$< $(BUILD_PREFIX)$(2) +else +# Installing using relative path +$(BUILD_PREFIX)$(2)/$(notdir $(1)): $(HERE)/$(1) + @install -m 755 -d $(BUILD_PREFIX)$(2) + install -m $(3) $$< $(BUILD_PREFIX)$(2) +endif +endef + +%.out/_dir: $(HERE)/Makefile $(TOP)/rules.mk $(TOP)/flags.mk + mkdir -p $*.out && touch $@ + +define ODIR_template #var, [nodefault] +ifneq ($(2),nodefault) + DEFAULT +=$$($(1)) +endif +$(1)_ODIR :=$$($(1)).out +$(1)_ODOT :=$$($(1)_ODIR)/_dir + +-include $$(addprefix $$($(1)_ODIR)/,$$($(1)_OBJS:.o=.d)) + +ODIRS +=$$($(1)_ODIR) + +ifeq (,$(wildcard $(shell pwd)/Makefile)) +# Out-of-tree build, external libraries are built locally +ifdef $(1)_LIBS_S +$$($(1)): $$(notdir $$($(1)_LIBS_S)) +endif +else +# In-tree build, external libraries are in their source dir +$$($(1)): $$($(1)_LIBS_S) +endif + +ifdef $(1)_DEPS +$$($(1)): $$($(1)_DEPS) +endif + +###################### +ifdef $(1)_CXXFLAGS +$(1)_CXXFLAGS +=-I$$($(1)_ODIR) + +$$($(1)_ODIR)/%.d $$($(1)_ODIR)/%.pic.d: $(HERE)/%.cpp $$($(1)_ODOT) + $$(CXX) $$($(1)_CXXFLAGS) -MM -MT $$(@:.d=.o) $$< > $$@ + +$$($(1)_ODIR)/%.d $$($(1)_ODIR)/%.pic.d: %.cpp $$($(1)_ODOT) + $$(CXX) $$($(1)_CXXFLAGS) -MM -MT $$(@:.d=.o) $$< > $$@ + +$$($(1)_ODIR)/%.d $$($(1)_ODIR)/%.pic.d: $$($(1)_ODIR)/%.cpp $$($(1)_ODOT) + $$(CXX) $$($(1)_CXXFLAGS) -MM -MT $$(@:.d=.o) $$< > $$@ + +$$($(1)_ODIR)/%.o: %.cpp $$($(1)_ODOT) + $$(CXX) $$($(1)_CXXFLAGS) -c -o $$@ $$< + +$$($(1)_ODIR)/%.pic.o: %.cpp $$($(1)_ODOT) + $$(CXX) $$($(1)_CXXFLAGS) -fPIC -c -o $$@ $$< + +$$($(1)_ODIR)/%.o: $(HERE)/%.cpp $$($(1)_ODOT) + $$(CXX) $$($(1)_CXXFLAGS) -c -o $$@ $$< + +$$($(1)_ODIR)/%.pic.o: $(HERE)/%.cpp $$($(1)_ODOT) + $$(CXX) $$($(1)_CXXFLAGS) -fPIC -c -o $$@ $$< + +$$($(1)_ODIR)/%.o: $$($(1)_ODIR)/%.cpp $$($(1)_ODOT) + $$(CXX) $$($(1)_CXXFLAGS) -c -o $$@ $$< + +$$($(1)_ODIR)/%.pic.o: $$($(1)_ODIR)/%.cpp $$($(1)_ODOT) + $$(CXX) $$($(1)_CXXFLAGS) -fPIC -c -o $$@ $$< + +$$($(1)_ODIR)/%.o: %.c $$($(1)_ODOT) + $$(CXX) $$($(1)_CXXFLAGS) -c -o $$@ $$< + +$$($(1)_ODIR)/%.pic.o: %.c $$($(1)_ODOT) + $$(CXX) $$($(1)_CXXFLAGS) -fPIC -c -o $$@ $$< + +$$($(1)_ODIR)/%.o: $(HERE)/%.c $$($(1)_ODOT) + $$(CXX) $$($(1)_CXXFLAGS) -c -o $$@ $$< + +$$($(1)_ODIR)/%.pic.o: $(HERE)/%.c $$($(1)_ODOT) + $$(CXX) $$($(1)_CXXFLAGS) -fPIC -c -o $$@ $$< + +$$($(1)_ODIR)/%.o: $$($(1)_ODIR)/%.c $$($(1)_ODOT) + $$(CXX) $$($(1)_CXXFLAGS) -c -o $$@ $$< + +$$($(1)_ODIR)/%.pic.o: $$($(1)_ODIR)/%.c $$($(1)_ODOT) + $$(CXX) $$($(1)_CXXFLAGS) -fPIC -c -o $$@ $$< + +$$($(1)_ODIR)/%.l.cpp $$($(1)_ODIR)/%.l.hpp: $(HERE)/%.lpp $$($(1)_ODOT) + $(FLEX) $(LFLAGS) --outfile=$$($(1)_ODIR)/$$*.l.cpp --header-file=$$($(1)_ODIR)/$$*.l.hpp $$< + +$$($(1)_ODIR)/%.l.o: $$($(1)_ODIR)/%.l.cpp $$($(1)_ODOT) + $$(CXX) $$($(1)_CXXFLAGS) -Wno-sign-compare -c -o $$@ $$< + +$$($(1)_ODIR)/%.l.pic.o: $$($(1)_ODIR)/%.l.cpp $$($(1)_ODOT) + $$(CXX) $$($(1)_CXXFLAGS) -fPIC -Wno-sign-compare -c -o $$@ $$< + +ifeq (,$(wildcard $(shell pwd)/Makefile)) +# Out-of-tree build, external libraries are built locally +ifdef $(1)_LIBS_S +$$($(1)): $$(notdir $$($(1)_LIBS_S)) +endif +else +# In-tree build, external libraries are in their source dir +$$($(1)): $$($(1)_LIBS_S) +endif + +ifdef $(1)_DEPS +$$($(1)): $$($(1)_DEPS) +endif + +ifdef $(1)_ARFLAGS +$$($(1)): $$(addprefix $$($(1)_ODIR)/,$$($(1)_OBJS)) + $(AR) $$($(1)_ARFLAGS) $$@ $$(filter %.o %.a,$$^) +else +$$($(1)): $$(addprefix $$($(1)_ODIR)/,$$($(1)_OBJS)) + $(CXX) $$($(1)_CXXFLAGS) $$(filter %.o %.a,$$^) -o $$@ $$($(1)_LDFLAGS) +endif + +###################### +else ifdef $(1)_CFLAGS +$(1)_CFLAGS +=-I$$($(1)_ODIR) + +$$($(1)_ODIR)/%.d $$($(1)_ODIR)/%.pic.d: $(HERE)/%.c $$($(1)_ODOT) + $$(CC) $$($(1)_CFLAGS) -MM -MT $$(@:.d=.o) $$< > $$@ + +$$($(1)_ODIR)/%.d $$($(1)_ODIR)/%.pic.d: %.c $$($(1)_ODOT) + $$(CC) $$($(1)_CFLAGS) -MM -MT $$(@:.d=.o) $$< > $$@ + +$$($(1)_ODIR)/%.d $$($(1)_ODIR)/%.pic.d: $$($(1)_ODIR)/%.c $$($(1)_ODOT) + $$(CC) $$($(1)_CFLAGS) -MM -MT $$(@:.d=.o) $$< > $$@ + +$$($(1)_ODIR)/%.o: %.c $$($(1)_ODOT) + $$(CC) $$($(1)_CFLAGS) -c -o $$@ $$< + +$$($(1)_ODIR)/%.pic.o: %.c $$($(1)_ODOT) + $$(CC) $$($(1)_CFLAGS) -fPIC -c -o $$@ $$< + +$$($(1)_ODIR)/%.o: $(HERE)/%.c $$($(1)_ODOT) + $$(CC) $$($(1)_CFLAGS) -c -o $$@ $$< + +$$($(1)_ODIR)/%.pic.o: $(HERE)/%.c $$($(1)_ODOT) + $$(CC) $$($(1)_CFLAGS) -fPIC -c -o $$@ $$< + +$$($(1)_ODIR)/%.o: $$($(1)_ODIR)/%.c $$($(1)_ODOT) + $$(CC) $$($(1)_CFLAGS) -c -o $$@ $$< + +$$($(1)_ODIR)/%.pic.o: $$($(1)_ODIR)/%.c $$($(1)_ODOT) + $$(CC) $$($(1)_CFLAGS) -fPIC -c -o $$@ $$< + +$$($(1)_ODIR)/%.l.c $$($(1)_ODIR)/%.l.h: $(HERE)/%.lpp $$($(1)_ODOT) + $(FLEX) $(LFLAGS) --outfile=$$($(1)_ODIR)/$$*.l.c --header-file=$$($(1)_ODIR)/$$*.l.h $$< + +$$($(1)_ODIR)/%.l.o: $$($(1)_ODIR)/%.l.c $$($(1)_ODOT) + $$(CC) $$($(1)_CFLAGS) -fPIC -Wno-sign-compare -c -o $$@ $$< + +$$($(1)_ODIR)/%.l.pic.o: $$($(1)_ODIR)/%.l.c $$($(1)_ODOT) + $$(CC) $$($(1)_CFLAGS) -Wno-sign-compare -c -o $$@ $$< + +ifdef $(1)_ARFLAGS +$$($(1)): $$(addprefix $$($(1)_ODIR)/,$$($(1)_OBJS)) + $(AR) $$($(1)_ARFLAGS) $$@ $$^ +else +$$($(1)): $$(addprefix $$($(1)_ODIR)/,$$($(1)_OBJS)) + $(CC) $$($(1)_CFLAGS) $$^ -o $$@ $$($(1)_LDFLAGS) +endif + +###################### +else +#$$(error no compilation flags defined for target $(1)) +endif + +ifdef $(1)_INSTALL +ifdef $(1)_ARFLAGS +$$(eval $$(call INST_template,$($(1)),$($(1)_INSTALL),644)) +else +$$(eval $$(call INST_template,$($(1)),$($(1)_INSTALL),755)) +endif +endif +endef + +define HDRS_template #var + $(foreach hdr,$($(1)_HDRS),$(eval $(call INST_template,$(hdr),$($(1)_HDRS_INSTALL),644))) +endef + +define COPY_template #var, chmod + $(foreach hdr,$($(1)),$(eval $(call INST_template,$(hdr),$($(1)_INSTALL),$(2)))) +endef + +define LINK_template #var +INSTALL +=$(BUILD_PREFIX)$($(1)_INSTALL)/$($(1)) +$(BUILD_PREFIX)$($(1)_INSTALL)/$($(1)): $(BUILD_PREFIX)$($(1)_LINK) + @install -m 755 -d $(BUILD_PREFIX)$($(1)_INSTALL) + ln -s $($(1)_LINK) $$@ +endef + +define DEP_template #file +DEP_DIRS +=$(dir $(1)) + +ifeq (,$(wildcard $(shell pwd)/Makefile)) +# Out-of-tree build, all targets go to the local folder +DEFAULT +=$(notdir $(1)) +$(notdir $(1)): + $(MAKE) $(notdir $(1)) -f $(dir $(1))Makefile +.PHONY: $(notdir $(1)) +else +# In-tree build, each target goes into its source folder +DEFAULT +=$(1) +$(1): + $(MAKE) $(notdir $(1)) -C $(dir $(1)) +.PHONY: $(1) +endif +endef + +define MAN_template #var, mansection +$(1)_ODIR :=$$($(1)).out +$(1)_ODOT :=$$($(1)_ODIR)/_dir +$(1)_MAN.ADOC :=$$($(1)_ODIR)/$$(patsubst %.dcrt,%.adoc,$$(notdir $$($(1)_MAN_DCRT))) +$(1)_MAN :=$$($(1)_ODIR)/$$($(1)).$(2) +$(1)_MAN.GZ :=$$($(1)_ODIR)/$$($(1)).$(2).gz + +MAN +=$$($(1)_MAN.GZ) + +ifeq ($(ENABLE_DOCRA), true) +$$($(1)_MAN.ADOC): $$($(1)_ODOT) + docra -l 0 -o $$($(1)_ODIR) $$($(1)_MAN_FLAGS) $$(dir $$($(1)_MAN_DCRT)) $$($(1)_MAN_DCRT) + +$$($(1)_MAN): $$($(1)_MAN.ADOC) + $(ASCIIDOCTOR) -b manpage $$< + +$$($(1)_MAN.GZ): $$($(1)_MAN) + gzip -f $$^ + +ifdef $(1)_MAN_INSTALL +MANINSTALL +=$(BUILD_PREFIX)$($(1)_MAN_INSTALL)/man$(2)/$$($(1)).$(2).gz +$(BUILD_PREFIX)$$($(1)_MAN_INSTALL)/man$(2)/$$($(1)).$(2).gz: $$($(1)_MAN.GZ) + @install -m 755 -d $(BUILD_PREFIX)$$($(1)_MAN_INSTALL)/man$(2) + @cp -v $$< $$@ +endif + +endif + +.PHONY: $$($(1)_MAN.ADOC) $$($(1)_MAN) $$($(1)_MAN.GZ) +endef + +define ALIAS_template #aliasvar, var, mansection + +ifdef $(2)_INSTALL +INSTALL +=$(BUILD_PREFIX)$($(2)_INSTALL)/$($(1)) +$(BUILD_PREFIX)$$($(2)_INSTALL)/$($(1)): + @install -m 755 -d $(BUILD_PREFIX)$$($(2)_INSTALL) + ln -s $$($(2)_INSTALL)/$$($(2)) $$@ +endif + +ifdef $(2)_MAN_INSTALL +MANINSTALL +=$(BUILD_PREFIX)$($(2)_MAN_INSTALL)/man$(3)/$($(1)).$(3).gz +$(BUILD_PREFIX)$$($(2)_MAN_INSTALL)/man$(3)/$$($(1)).$(3).gz: + @install -m 755 -d $(BUILD_PREFIX)$$($(2)_MAN_INSTALL)/man$(3) + ln -s $$($(2)_MAN_INSTALL)/man$(3)/$$($(2)).$(3).gz $$@ +endif + +endef + +#dg`make.sub` Each subfolder containing a ``Makefile`` can be build individually by simply issuing ``make`` from there. Dependencies on targets built in other subfolders will be built automatically. This can be used during development to quickly iterate on a single subproject. +# By default, a sub-project ``Makefile`` implements at least the following targets: _ +# *default*:: +# Builds all library and executable targets. +# *install*:: +# Copies installable files to their destination. +# *uninstall*:: +# Removes files copied by both *install* and *maninstall*. +# *man*:: +# Builds man pages. +# *maninstall*:: +# Installs man pages under ``$(PREFIX)/share/man``. +# *clean*:: +# Cleans build directory and deletes final targets. +# *depclean*:: +# Makes the *clean* target in every dependency of this subproject. + +define DEFAULT_template +default: $$(DEFAULT) + +install: $$(INSTALL) + +uninstall: + $$(RM) $$(INSTALL) $$(MANINSTALL) + +man: $$(MAN) + +maninstall: $$(MANINSTALL) + +clean: + $(RM) -r *.out/ $(ODIRS) + $(RM) $(DEFAULT) + +depclean: + for dep_dir in ${DEP_DIRS}; do $(MAKE) -C $$$${dep_dir} clean; done + +.PHONY: install uninstall man maninstall clean depclean +endef + +default: + +.PHONY: default diff --git a/Pcie40Libraries/Makefile b/Pcie40Libraries/Makefile new file mode 100644 index 0000000..333c2da --- /dev/null +++ b/Pcie40Libraries/Makefile @@ -0,0 +1,127 @@ +CC=gcc -fPIC -g +CFLAGS= -c -Wall +LDFLAGS= + +#defined global variables and programs to build +include Makefile.conf + +PCIE40_DYN_LIB=../Pcie40DriverLibraries +PCIE40_INC_DIR=../Pcie40DriverLibraries + +OBJ_DIR=obj/ +INC_DIR=inc/ +LIB_DIR=lib/ + + +#Files ------------------------------------------------------------------------ + +#ECS +ECS_SRC= pcie40_ecs.c +ECS_OBJ=$(ECS_SRC:%.c=$(OBJ_DIR)%.o) + +#Minipods +MINIPODS_SRC= i2cDriver.c +MINIPODS_OBJ=$(MINIPODS_SRC:%.c=$(OBJ_DIR)%.o) + +#User +USER_SRC= +USER_OBJ=$(USER_SRC:$(SRC_DIR)$(USER_DIR)%.c=$(OBJ_DIR)%.o) + +#LTC2990 +LTC2990_SRC= +LTC2990_OBJ=$(LTC2990_SRC:$(SRC_DIR)$(LTC2990_DIR)%.c=$(OBJ_DIR)%.o) + +# static libraries +ECS_LIB= libecs.a +MINIPODS_LIB= libminipods.a +USER_LIB= libuser.a +LTC2990_LIB= libltc2990.a +# dynamic libraries +USER_DYNLIB= libuser-dyn.so +LLI_DYNLIB= libpcie40.so + + +all: $(ECS_OBJ) $(ECS_LIB) $(MINIPODS_OBJ) $(MINIPODS_LIB) $(LTC2990_OBJ) $(LTC2990_LIB) $(LLI_DYNLIB) $(USER_LIB) $(USER_DYNLIB) + +$(ECS_OBJ): $(OBJ_DIR)%.o : %.c + @echo "Construction of ecs objects $@ from $<" + mkdir -p obj + $(CC) $(CFLAGS) -I . -I $(PCIE40_INC_DIR) $< -o $@ + +$(ECS_LIB) : $(ECS_OBJ) + @echo "Construction of ECS Library" + mkdir -p lib + ar -q $(LIB_DIR)$(ECS_LIB) $(ECS_OBJ) + @echo "" + +$(MINIPODS_OBJ): $(OBJ_DIR)%.o : $(SRC_DIR)%.c + @echo "Construction of $@ from $<" + $(CC) $(CFLAGS) -I . -I $(INC_DIR)$(SYSTEM_DIR) -I $(PCIE40_INC_DIR) $< -o $@ + @echo "" + +$(MINIPODS_LIB) : $(MINIPODS_OBJ) + @echo "Construction of MINIPODS Library" + ar -q $(LIB_DIR)$(MINIPODS_LIB) $(MINIPODS_OBJ) + @echo "" + +$(LTC2990_OBJ): $(OBJ_DIR)%.o : $(SRC_DIR)$(LTC2990_DIR)%.c + @echo "Construction of $@ from $<" + $(CC) $(CFLAGS) -I $(INC_DIR)$(PLL_DIR) -I $(INC_DIR)$(LTC2990_DIR) -I $(INC_DIR)$(SYSTEM_DIR) -I $(INC_DIR)$(MINIPODS_DIR) -I $(INC_DIR)$(LTC2990_DIR) -I $(PCIE40_INC_DIR) $< -o $@ + @echo "" + +$(LTC2990_LIB) : $(LTC2990_OBJ) + @echo "Construction of LTC2990 Library" + ar -q $(LIB_DIR)$(LTC2990_LIB) $(LTC2990_OBJ) + @echo "" + +$(USER_OBJ): $(OBJ_DIR)%.o : $(SRC_DIR)$(USER_DIR)%.c + @echo "Construction of $@ from $<" + $(CC) $(CFLAGS) -I $(INC_DIR)$(USER_DIR) -I $(INC_DIR)$(SYSTEM_DIR) -I $(INC_DIR)$(ECS_DIR) -I $(PCIE40_INC_DIR) $< -o $@ + @echo "" + +$(USER_LIB) : $(USER_OBJ) + @echo "Construction of USER Library" + ar -q $(LIB_DIR)$(USER_LIB) $(USER_OBJ) $(ECS_OBJ) + @echo "" + +$(USER_DYNLIB) : $(USER_OBJ) + @echo "Construction of dynamic USER Library" + $(CC) -o $(LIB_DIR)$(USER_DYNLIB) -shared $(USER_OBJ) $(ECS_OBJ) + @echo + +$(LLI_DYNLIB) : $(ECS_OBJ) $(MINIPODS_OBJ) + @echo "Construction of dynamic LLI technical Library for V2" + mkdir -p lib + $(CC) -o $(LIB_DIR)$(LLI_DYNLIB) -shared $(ECS_OBJ) $(PLL_OBJ) $(MINIPODS_OBJ) -L $(PCIE40_DYN_LIB) -lpcie40driver_ecs + @echo + +clean: mrproper + @echo "removing lli objects" + -rm $(OBJ_DIR)*.o + @echo "" + + @echo "removing $(ECS_LIB)" + -rm $(LIB_DIR)$(ECS_LIB) + @echo "" + + @echo "removing $(MINIPODS_LIB)" + -rm $(LIB_DIR)$(MINIPODS_LIB) + @echo "" + + @echo "removing $(LTC2990_LIB)" + -rm $(LIB_DIR)$(LTC2990_LIB) + @echo "" + + @echo "removing $(USER_LIB)" + -rm $(LIB_DIR)$(USER_LIB) + -rm $(LIB_DIR)$(USER_DYNLIB) + -rm $(LIB_DIR)$(LLI_DYNLIB) + -rm -r $(LIB_DIR) + + @echo "" + +mrproper: + @echo "Removing all *~ files" + -find . -name "*~" -exec rm {} \; + @echo "" + diff --git a/Pcie40Libraries/Makefile.conf b/Pcie40Libraries/Makefile.conf new file mode 100644 index 0000000..7584010 --- /dev/null +++ b/Pcie40Libraries/Makefile.conf @@ -0,0 +1,26 @@ + +# +----------------------------------------------------+" +# | Library Construction, flags |" +# +----------------------------------------------------+" + +path=$(PWD) +libdir=$(path)/lli/lib/$(ES) +includedir=$(path)/lli/inc +ecsdir=ecs +systemdir=system +minipodsdir=minipods +ltc2990dir=ltc2990 + +LLI_CFLAGS= -I/usr/include/lhcb -I$(includedir)/$(ecsdir) -I$(includedir)/$(systemdir) -I$(includedir)/$(minipodsdir) -I$(includedir)/$(ltc2990dir) +LLI_LIBS= -L${libdir} -lminipods -lecs -lpcie40_ecs + +userdir=user +LLI_USER_LIBS= -L$(libdir) -luser + +LLI_USER_CFLAGS= -I$(includedir)/$(userdir) + +export LLI_LIBS +export LLI_CFLAGS +export LLI_USER_LIBS +export LLI_USER_CFLAGS + diff --git a/Pcie40Libraries/i2cDriver.c b/Pcie40Libraries/i2cDriver.c new file mode 100644 index 0000000..7c1ba4a --- /dev/null +++ b/Pcie40Libraries/i2cDriver.c @@ -0,0 +1,656 @@ +/****************************************************************************************//** +* \file i2cDriver.c +* +* \brief This unit is a simple driver library for I2C bus based on the Open-Core I2C-master. +* +* \author PYD : 12/6/2013 +* \version 0.1 +* \date 12/6/2013 + +* PYD : 12/6/2013 initial version +* PYD : 01/10/2018 remove code for ES12 and ES3 versions +*//******************************************************************************************/ +#include <stdio.h> +#include <error.h> +#include <stdlib.h> +#include <unistd.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> + +#define offsetReg(r) (r*4) + +//========================= SYSTEM CONFIGURATION ================================= +#include <systemConfig.h> +#include <pcie40_ecs.h> +//================================================================================ +// USER ORIENTED PROCEDURES FOR EXTERNAL USE +#include <i2cDriver.h> +//=============================================================================== +//#define I2C_FREQ 0xc7 ;#(199dec) value for 100MHz clock to match 100kHz SCL +//#define I2C_FREQ 0x31 ;#(49dec) value for 100MHz clock to match 400kHz SCL +//#define I2C_FREQ 0x18 ;#(24dec) value for 100MHz clock to match 800kHz SCL + +// addresses of I2C registers (start at 0xa40 in qsys) +#define I2C_PRELOREG 0x0 +#define I2C_PREHIREG 0x1 +#define I2C_CTRLREG 0x2 +#define I2C_TSMTREG 0x3 +#define I2C_RCVREG 0x3 +#define I2C_CMDREG 0x4 +#define I2C_STATREG 0x4 + +// Control register +#define I2C_ENA 0x80 +#define I2C_DIS 0x00 +// Command register bits +#define I2C_STA 0x80 +#define I2C_STO 0x40 +#define I2C_RD 0x20 +#define I2C_WR 0x10 +#define I2C_NACK 0x08 +#define I2C_IACK 0x01 +// Status register bits +#define I2C_TIP 0x02 +#define I2C_BUSY 0x40 + +/***********************************************************************//** + * \fn int unsigned I2C_MakeAvagoAdd(compNb) + * \brief Function to build a device address + * + * For TX(pair) the address is 0101hjkx (hjk is hard add) (x is 1=R 0=W) + * + * For RX(odd) the address is 0110hjkx (hjk is hard add) (x is 1=R 0=W) + * + * NOTE the x is added in Read/Write function + * + * \return the I2c address + *//***********************************************************************/ +/* +static unsigned i2c_MakeAvagoAdd(int compNb) { + unsigned i2cAdd; +// partern 0 + 0101/TX or 0110/RX + fixAdd on 3digits + if (compNb%2) + i2cAdd = 5<<3; + else + i2cAdd = 6<<3; + i2cAdd = i2cAdd + compNb; + + return(i2cAdd); +} +*/ + +unsigned lastSetInCLK[MAX_DEV]; +unsigned LastSetSCLfreq[MAX_DEV]; + +static int getBusBase(int bus){ + switch(bus){ + case I2C_BUS_TEMPERATURES: + return(I2C_BUS_BASE_TEMPERATURES); + break; + case I2C_BUS_PLL_CLEANER1: + return(I2C_BUS_BASE_PLL_CLEANER1); + break; + case I2C_BUS_PLL_CLEANER2: + return(I2C_BUS_BASE_PLL_CLEANER2); + break; + case I2C_BUS_PLL_TFC: + return(I2C_BUS_BASE_PLL_TFC); + break; + case I2C_BUS_SFP1: + return(I2C_BUS_BASE_SFP1); + break; + case I2C_BUS_SFP2: + return(I2C_BUS_BASE_SFP2); + break; + case I2C_BUS_MINIPODS: + return(I2C_BUS_BASE_MINIPODS); + break; + case I2C_BUS_TEMP_MEZZANINE: + return(I2C_BUS_BASE_TEMP_MEZZANINE); + break; + case I2C_BUS_CURRENT1: + return(I2C_BUS_BASE_CURRENT1); + break; + case I2C_BUS_CURRENT2: + return(I2C_BUS_BASE_CURRENT2); + break; + case I2C_BUS_FANOUT: + return(I2C_BUS_BASE_FANOUT); + break; + case I2C_BUS_FPGA_EEPROM: + return(I2C_BUS_BASE_FPGA_EEPROM); + default: + printf("ERROR: unknown i2c bus number %d in file %s line %d\n",bus,__FILE__,__LINE__); + return(99); + } +} + /***********************************************************************//** + * \fn void i2c_enable(int dev, int bus) + * \brief Function to activate the i2c-opencore IP. + * \param dev: the board number + * \param bus: the target i2c bus number + *//***********************************************************************/ +static void i2c_enable(int dev, int bus) { + unsigned cval = I2C_ENA; + + ecs_iowrI2c_slow( dev, getBusBase(bus)+ (I2C_CTRLREG*4), &cval); +} +/***********************************************************************//** + * \fn void i2c_disable(int dev,int bus) + * \param dev: the board number + * \brief Function to deactivate the i2c-opencore IP. + * \param bus: the target i2c bus number + *//***********************************************************************/ +static void i2c_disable(int dev,int bus) { + unsigned cval = I2C_DIS; + + ecs_iowrI2c_slow( dev, getBusBase(bus)+ (I2C_CTRLREG*4), &cval); +} +/***********************************************************************//** + * \fn void i2c_stop(int dev,int bus) + * \param dev: the board number + * \brief Function to generate the stop condition on the i2c bus. + * \param bus: the target i2c bus number + *//***********************************************************************/ +static void i2c_stop(int dev, int bus) { + unsigned cval = I2C_STO; + + ecs_iowrI2c_slow( dev, getBusBase(bus)+ (I2C_CMDREG*4), &cval); +} + +/****************************************************************************//** + * \fn void i2c_setSpeed(int dev, int bus, int value) + * \brief Function to program the prescale the SCL clock line. Should be called + * before the I2C use. + * \param dev: the board number + * \param bus: the target i2c bus number + * \param value: the value to write in the prescale register + *//**************************************************************************/ +static void i2c_setSpeed(int dev, int bus, int value ) { + unsigned cval = value>>8; + int base = getBusBase(bus); + + ecs_iowrI2c_slow(dev, base + (I2C_PREHIREG*4), &cval); + cval =value & 0xFF; + ecs_iowrI2c_slow(dev, base + (I2C_PRELOREG*4), &cval); +} +/****************************************************************************//** + * \fn int i2c_init(int dev, int bus, unsigned inCLK, unsigned SCLfreq) + * \brief Function to open access to i2c opencore and set speed + * \ if it is specified + * \param dev: the board number + * \param bus: the target i2c bus number + * \param inCLK: the input system clock ferquency in Hz + * \param SCLfreq: the target SCL clock frequency in Hz + * \return 0 success,-1 error + *//**************************************************************************/ +int i2c_init(int dev, int bus, unsigned inCLK, unsigned SCLfreq) { + long int prescale; + +// printf("Simulation init with clock %d fequency %d \n",inCLK, SCLfreq); return(0); + + if (ecs_openLli(dev)<0){ + printf("ERROR: Can't init I2C\n"); + return(-1); + } + i2c_stop(dev, bus); + i2c_disable(dev, bus); + i2c_enable(dev, bus); + // set prescale register + if (inCLK!=0 && SCLfreq !=0){ + prescale = (inCLK/(5*SCLfreq))-1; +// printf("PYD i2c i2c_init() bus %d applied speed is %ld\n", bus, prescale); + i2c_setSpeed(dev, bus, prescale); + lastSetInCLK[dev] = inCLK; + LastSetSCLfreq[dev] = SCLfreq; + } + return(0); +} + +/****************************************************************************//** + * \fn int i2c_getInit(int dev, int bus, unsigned &inCLK, unsigned &SCLfreq) + * \brief Read the last values in the prescale of the SCL clock line. + * + * \param dev: the board number + * \param bus: the target i2c bus number + * \param inCLK: the system clock ferquency in Hz + * \param SCLfreq: the target SCL clock frequency in Hz + *//**************************************************************************/ +void i2c_getInit(int dev, int bus, unsigned *inCLK, unsigned *SCLfreq) { + *inCLK = lastSetInCLK[dev]; + *SCLfreq = LastSetSCLfreq[dev]; +} +/***********************************************************************************//** + * \fn int _waitTIP() + * \brief function to wait for the status register TIP bit value 0 "transfer complete" + * + * \param dev: the borad number + * \param bus: the target i2c bus number + * \return 0 success,-1 error + *//********************************************************************************/ +static int i2c_waitTIP(int dev, int bus) { + unsigned val, step = 0; + int base = getBusBase(bus); + while(1){ + usleep(10); //MJ POUR TEMPO_FERNAND LE 12 SEPT 2017 +// printf("step %d\n", step); + step = step + 1; + if(ecs_iordI2c_slow(dev, base + (I2C_STATREG*4), &val)==0){ +// printf("PYD status 0x%x\n", val); + if ((val & I2C_TIP) == 0){ //transfer complete + return(0); + } else { // transfer in progress + if (step > 500){ + printf("ERROR: timeout in i2c_waitTIP()\n"); + return(-1); + } else { + usleep(10); +// printf("PYD wait %d\n", step); +// for (i=0; i<loop; i++) dum++; + } + } + } else { // read error + printf("i2c_waitTIP firmware level read error KO\n"); + return(-1); + } + }//while +} + +/***********************************************************************//** + * \fn int i2c_readMem(int dev, int bus, unsigned slaveAdd, unsigned regIndex, unsigned *val) + * \brief Function to read one single register + * + * \param dev: the board number + * \param bus: the target i2c bus number + * \param slaveAdd: the address of the device to write in the I2C space + * \param regIndex: the number of the register in the component + * \param val : a pointer to receive the read value + * \return 0 success,-1 error + *//***********************************************************************/ +int i2c_readMem(int dev, int bus, unsigned slaveAdd, unsigned regIndex, unsigned *val) { + unsigned cval; + int base = getBusBase(bus); + + // generate start command + // write $slaveAdd (slaveAdd+WR bit) in transmitReg + // + // printf("PYD bus=%d i2c_readMem() at base 0x%x subadd 0x%x register %d\n", bus, base, slaveAdd, regIndex); +// printf("Simulation\n"); *val=0x55; return(0); + + cval = slaveAdd<<1; + ecs_iowrI2c_slow(dev, base + (I2C_TSMTREG*4), &cval); + // set STA bit and WR bit in commandReg + cval = I2C_STA | I2C_WR; + ecs_iowrI2c_slow(dev, base + (I2C_CMDREG*4), &cval); + // wait fir TIP flaf in statusReg + if ( i2c_waitTIP(dev, bus) != 0) + return(-1); + // read statusReg to verify RxACK=0 + ecs_iordI2c_slow(dev, base + (I2C_STATREG*4), &cval); + if ((cval & I2C_NACK) == I2C_NACK){ + printf("ERROR: bus=%d i2c_readMem() first transaction slave address not acknowledge in I2C_Write\n",bus); + return(-1); + } + // + // write $regIndex in transmitReg + // + cval = regIndex; + ecs_iowrI2c_slow(dev, base + (I2C_TSMTREG*4), &cval); + // set WR bit in commandReg + cval = I2C_WR; + ecs_iowrI2c_slow(dev, base + (I2C_CMDREG*4), &cval); + // wait fir TIP flaf in statusReg + if ( i2c_waitTIP(dev, bus) != 0) + return(-1); + // read statusReg to verify RxACK=0 + ecs_iordI2c_slow(dev, base + (I2C_STATREG*4), &cval); + if ((cval & I2C_NACK) == I2C_NACK){ + printf("ERROR:bus %d i2c_readMem() second transaction slave address not acknowledge in I2C_Write\n",bus); + return(-1); + } + // + // write $slaveAdd (slaveAdd+RD bit) in transmitReg + // + cval = slaveAdd<<1 | 1; + ecs_iowrI2c_slow(dev, base + (I2C_TSMTREG*4), &cval); + // set STA bit and WR bit in commandReg + cval = I2C_STA | I2C_WR; + ecs_iowrI2c_slow(dev, base + (I2C_CMDREG*4), &cval); + // wait fir TIP flaf in statusReg + if ( i2c_waitTIP(dev, bus) != 0) + return(-1); + // read statusReg to verify RxACK=0 + if ((cval & I2C_NACK) == I2C_NACK){ + printf("ERROR: bus %d i2c_readMem() third transaction slave address not acknowledge in I2C_Write\n",bus); + return(-1); + } + // + // set RD bit, set ACK bit =1(NACK) set STO bit in commandReg + // + cval = I2C_RD | I2C_NACK | I2C_STO; + ecs_iowrI2c_slow(dev, base + (I2C_CMDREG*4), &cval); + // wait for TIP flag in statusReg + if ( i2c_waitTIP(dev, bus) != 0) + return(-1); + return( ecs_iordI2c_slow(dev, base + (I2C_RCVREG*4), val) ); +} +/***********************************************************************//** + * \fn int i2c_writeMem(int dev, int bus, unsigned slaveAdd, unsigned regIndex, unsigned *val) + * \brief Function to write a value in a register + * + * \param dev: the board number + * \param bus: the target i2c bus number + * \param slaveAdd: the address of the device to write in the I2C space + * \param regIndex: the number of the register in the component + * \param val : a pointer to the value to write + * \return 0 success,-1 error + *//***********************************************************************/ +int i2c_writeMem(int dev, int bus, unsigned slaveAdd, unsigned regIndex, unsigned *val){ + unsigned cval; + int base = getBusBase(bus); + + // generate start command +// printf("bus %d i2c_writeMem() at add 0x%x register %d val %x\n", bus, slaveAdd, regIndex, *val); +// printf("Simulation\n"); return(0); + // write $slaveAdd (slaveAdd+WR bit) in transmitReg + cval = slaveAdd<<1; + ecs_iowrI2c_slow(dev, base + (I2C_TSMTREG*4), &cval); + // set STA bit and WR bit in commandReg + cval = I2C_STA | I2C_WR; + ecs_iowrI2c_slow(dev, base + (I2C_CMDREG*4), &cval); + // wait fir TIP flaf in statusReg + if ( i2c_waitTIP(dev, bus) != 0) + return(-1); + // read statusReg to verify RxACK=0 + ecs_iordI2c_slow(dev, base + (I2C_STATREG*4), &cval); + if ((cval & I2C_NACK) == I2C_NACK){ + printf("ERROR: bus %d slave address not acknowledge in I2C_Write\n",bus); + return(-1); + } + // + // write $regIndex in transmitReg + // + cval = regIndex; + ecs_iowrI2c_slow(dev, base + (I2C_TSMTREG*4), &cval); + // set WR bit in commandReg + cval = I2C_WR; + ecs_iowrI2c_slow(dev, base + (I2C_CMDREG*4), &cval); + // wait fir TIP flaf in statusReg + if ( i2c_waitTIP(dev, bus) != 0) + return(-1); + // read statusReg to verify RxACK=0 + ecs_iordI2c_slow(dev, base + (I2C_STATREG*4), &cval); + if ((cval & I2C_NACK) == I2C_NACK){ + printf("ERROR: bus %d slave address not acknowledge in I2C_Write\n",bus); + return(-1); + } + // + // write $slaveAdd (slaveAdd+RD bit) in transmitReg + // + ecs_iowrI2c_slow(dev, base + (I2C_TSMTREG*4), val); + // set STA bit and WR bit in commandReg + cval = I2C_STO | I2C_WR; + ecs_iowrI2c_slow(dev, base + (I2C_CMDREG*4), &cval); + // wait fir TIP flaf in statusReg + if ( i2c_waitTIP(dev, bus) != 0) + return(-1); +return(0); +} +/***********************************************************************//** + * \fn int i2c_multReadMemInit(int dev, int bus, unsigned slaveAdd, unsigned regIndex) + * \brief Function to initialize a multiread sequence from slave at + * i2c address slaveAdd starting at device internal register regIndex + * + * \param dev: the board number + * \param bus: the target i2c bus number + * \param slaveAdd: the address of the device to read from in the I2C space + * \param regIndex: the number of the first register in the sequence to read + * \return 0 success,-1 error + *//***********************************************************************/ +static int i2c_multReadMemInit(int dev, int bus, unsigned slaveAdd, unsigned regIndex) { + unsigned cval; + int base = getBusBase(bus); + + // generate start command + // write $slaveAdd (slaveAdd+WR bit) in transmitReg + // +// printf("PYD start i2c_multReadMemInit\n"); + cval = slaveAdd<<1; + ecs_iowrI2c_slow(dev, base + (I2C_TSMTREG*4), &cval); + // set STA bit and WR bit in commandReg + cval = I2C_STA | I2C_WR; + ecs_iowrI2c_slow(dev, base + (I2C_CMDREG*4), &cval); +// printf("PYD wait for TIP flag in statusReg\n"); + // wait for TIP flag in statusReg + if ( i2c_waitTIP(dev, bus) != 0) + return(-1); + // read statusReg to verify RxACK=0 +// printf("PYD read statusReg to verify RxACK=0\n"); + ecs_iordI2c_slow(dev, base + (I2C_STATREG*4), &cval); + if ((cval & I2C_NACK) == I2C_NACK){ + printf("ERROR: bus %d slave address not acknowledge in I2C_Write\n",bus); + return(-1); + } + // + // write $regIndex in transmitReg + // +// printf("PYD write $regIndex in transmitReg\n"); + cval = regIndex; + ecs_iowrI2c_slow(dev, base + (I2C_TSMTREG*4), &cval); + // set WR bit in commandReg + cval = I2C_WR; + ecs_iowrI2c_slow(dev, base + (I2C_CMDREG*4), &cval); + // wait fir TIP flaf in statusReg + if ( i2c_waitTIP(dev, bus) != 0) + return(-1); + // read statusReg to verify RxACK=0 + ecs_iordI2c_slow(dev, base + (I2C_STATREG*4), &cval); + if ((cval & I2C_NACK) == I2C_NACK){ + printf("ERROR: bus %d slave address not acknowledge in I2C_Write\n",bus); + return(-1); + } + // + // write $slaveAdd (slaveAdd+RD bit) in transmitReg + // +// printf("PYD write $slaveAdd (slaveAdd+RD bit) in transmitReg\n"); + cval = slaveAdd<<1 | 1; + ecs_iowrI2c_slow(dev, base + (I2C_TSMTREG*4), &cval); + // set STA bit and WR bit in commandReg + cval = I2C_STA | I2C_WR; + ecs_iowrI2c_slow(dev, base + (I2C_CMDREG*4), &cval); + // wait fir TIP flaf in statusReg + if ( i2c_waitTIP(dev, bus) != 0) + return(-1); +// printf("PYD end i2c_multReadMemInit\n"); +return(0); +} +/******************************************************************************//** + * \fn int i2c_multReadMem(int dev, int bus, unsigned slaveAdd, unsigned regIndex, int nb) + * \brief Function to read/print a sequence of nb conscecutive registers from slave at + * i2c address slaveAdd starting at device internal register regIndex + * Used with nb=1 is a function to read one register value + * + * This function allocate the array to store the read data in. The user + * should free it after use. + * + * \param dev: the board number + * \param bus: the target i2c bus number + * \param slaveAdd: the address of the device to read from in the I2C space + * \param regIndex: the number of the first register in the sequence to read + * \param nb : the number of conscecutives registers to read + * \param data : a pointer to receive the data array reference + * \return 0 success,-1 error + *//******************************************************************************/ +int i2c_multReadMem(int dev, int bus, unsigned slaveAdd, unsigned regIndex, int nb, unsigned **data) { + unsigned cval; + int i; + unsigned *bloc; + + int base = getBusBase(bus); + + if (i2c_multReadMemInit(dev, bus, slaveAdd, regIndex) != 0) + return(-1); + bloc = malloc(nb*sizeof(unsigned)); + if (bloc==0){ + perror("Can't malloc in i2c_multReadMem()\n"); + return(-1); + } +/* printf("Reading bytes at slave add 0x%x (%d) starting at internal address 0x%x (%d)\n", + slaveAdd, slaveAdd, regIndex, regIndex); +*/ + // Read and display values + cval = I2C_RD; +// printf("PYD read loop\n"); + for (i=0; i<(nb-1); i++){ + ecs_iowrI2c_slow(dev, base + (I2C_CMDREG*4), &cval); + // wait for TIP flag in statusReg + if ( i2c_waitTIP(dev, bus) != 0) + return(-1); + ecs_iordI2c_slow(dev, base + (I2C_RCVREG*4), &bloc[i]); +// printf("PYD 0x%x "); + } +// printf("PYD\n"); + + // last byte to transfer + cval = I2C_RD | I2C_NACK | I2C_STO; + ecs_iowrI2c_slow(dev, base + (I2C_CMDREG*4), &cval); + // wait for TIP flag in statusReg + if ( i2c_waitTIP(dev, bus) != 0) + return(-1); + ecs_iordI2c_slow(dev, base + (I2C_RCVREG*4), &bloc[nb-1]); + *data = bloc; + return(0); +} + +#ifdef MAIN_DRIVER +int main(){ + unsigned val, i2cAdd; + unsigned cval[3]; + int i, loop; + unsigned val1[] = { 0x4, 0x5, 0xc0 }; + unsigned val2[] = { 0xa, 0xb, 0x00 }; + unsigned i2cAddTab[] = {0x28, 0x31, 0x2A, 0x33, 0x2C, 0x35}; + unsigned *data; + int base; + int dev = 0; + + if (ecs_openLli(dev) != 0){ + perror("Can't access i2c ocore\n"); + exit(0); + } + printf("TEST on PCIe access to ocore regsiters\n"); + printf("======================================\n"); + base = I2C_BASE_0; + + // raw test for pcie access to opencore registers + ecs_iordI2c(dev, base + (I2C_PRELOREG*4), &cval[0]); + ecs_iordI2c(dev, base + (I2C_PREHIREG*4), &cval[1]); + ecs_iordI2c(dev, base + (I2C_CTRLREG*4), &cval[2]); + printf("Before ...\n"); + for (i=0; i<3; i++) + printf("Ox%x ", cval[i]); + printf("\n"); + + ecs_iowrI2c(dev, base + (I2C_PRELOREG*4), &val1[0]); + ecs_iowrI2c(dev, base + (I2C_PREHIREG*4), &val1[1]); + ecs_iowrI2c(dev, base + (I2C_CTRLREG*4), &val1[2]); + printf("After first loop ... should be equal\n"); + ecs_iordI2c(dev, base + (I2C_PRELOREG*4), &cval[0]); + ecs_iordI2c(dev, base + (I2C_PREHIREG*4), &cval[1]); + ecs_iordI2c(dev, base + (I2C_CTRLREG*4), &cval[2]); + for (i=0; i<3; i++) + printf(" Ox%x =?= 0x%x |", cval[i], val1[i]); + printf("\n"); + + exit(0); + + ecs_iowrI2c(dev, base + (I2C_PRELOREG*4), &val2[0]); + ecs_iowrI2c(dev, base + (I2C_PREHIREG*4), &val2[1]); + ecs_iowrI2c(dev, base + (I2C_CTRLREG*4), &val2[2]); + printf("After second loop ... should be equal\n"); + ecs_iordI2c(dev, base + (I2C_PRELOREG*4), &cval[0]); + ecs_iordI2c(dev, base + (I2C_PREHIREG*4), &cval[1]); + ecs_iordI2c(dev, base + (I2C_CTRLREG*4), &cval[2]); + for (i=0; i<3; i++) + printf("Ox%x =?= 0x%x |", cval[i], val2[i]); + printf("\n"); + + printf("\nTEST on I2C access to avago registers\n"); + printf("=====================================\n"); + // init and set address for TX 0 +// i2c_init(dev, 100000000, 100000); // for TCL/TK because jtag master set this clock + i2c_init(dev, 125000000, 100000); // fast clock with PCI +// i2c_init(dev, 62500000, 100000); // slow clock with PCI + // set i2c address of avago number 0 (a TX) + printf("Select avago number 0 (a TX) as target\n"); + i2cAdd = 5<<3; // comp 0 TX + + printf("Read register 0 should be 0x00 ---> read "); + val = 0xaa; + i2c_readMem(dev, i2cAdd, 0, &val); + printf("(0x%x)\n", val); + + + printf("Write NULL in page select register\n"); + val = 0; // select page 0 + i2c_writeMem(dev, i2cAdd, 127, &val); + printf("Read read page select register should be NULL ---> read "); + val = 0xaa; + i2c_readMem(dev, i2cAdd, 127, &val); + printf("(0x%x)\n", val); + + printf("Write 1 in page select register\n"); + val = 1; // select page 0 + i2c_writeMem(dev, i2cAdd, 127, &val); + printf("Read read page select register should be 1 ---> read "); + val = 0xaa; + i2c_readMem(dev, i2cAdd, 127, &val); + printf("(0x%x)\n", val); + + printf("Write NULL in page select register\n"); + val = 0; // select page 0 + i2c_writeMem(dev, i2cAdd, 127, &val); + printf("Read read page select register should be NULL ---> read "); + val = 0xaa; + i2c_readMem(dev, i2cAdd, 127, &val); + printf("(0x%x)\n", val); + + printf("Write 0xff in register 94 squelch\n"); + val = 0xff; // select page 0 + i2c_writeMem(dev, i2cAdd, 94, &val); + printf("Read squelch ---> read "); + val = 0xaa; + i2c_readMem(dev, i2cAdd, 94, &val); + printf("(0x%x)\n", val); + + printf("Write 0xff in register 95 squelch\n"); + val = 0xff; // select page 0 + i2c_writeMem(dev, i2cAdd, 95, &val); + printf("Read squelch ---> read "); + val = 0xaa; + i2c_readMem(dev, i2cAdd, 95, &val); + printf("(0x%x)\n", val); + + printf("Read Vendor Name\n"); + loop = 16; + // test to read vendor name at reg 152 to 167 (16bytes) + // in module at address 0 + for (i=0; i<loop; i++){ + val = 1; + i2c_readMem(dev, i2cAdd, 152+i, &val); +// printf("0x%x %c ", val, (char)val); + printf("%c", (char)val); + } + printf("\n"); + + i2c_multReadMem(dev, i2cAdd, 152, 16, &data); + for (i=0; i<loop; i++) + printf("%c", (char)data[i]); + printf("\n"); + +return(0); +} +#endif + + diff --git a/Pcie40Libraries/i2cDriver.h b/Pcie40Libraries/i2cDriver.h new file mode 100644 index 0000000..43994f9 --- /dev/null +++ b/Pcie40Libraries/i2cDriver.h @@ -0,0 +1,19 @@ +/****************************************************************************************//** +* \file i2cDriver.h +* +* \brief This unit is the includes for a simple driver library for I2C bus based + on the Open-Core I2C-master. +* +* \author PYD : 12/6/2013 +* \version 0.1 +* \date 12/6/2013 + +* PYD : 12/6/2013 initial version +* PYD : 12/6/2015 add a second bus for PCIe40 +*//******************************************************************************************/ +// USER ORIENTED PROCEDURES FOR EXTERNAL USE +int i2c_init(int dev, int bus, unsigned inCLK, unsigned SCLfreq); +void i2c_getInit(int dev, int bus, unsigned *inCLK, unsigned *SCLfreq); +int i2c_readMem(int dev, int bus, unsigned slaveAdd, unsigned regIndex, unsigned *val); +int i2c_writeMem(int dev, int bus, unsigned slaveAdd, unsigned regIndex, unsigned *val); +int i2c_multReadMem(int dev, int bus, unsigned slaveAdd, unsigned regIndex, int nb, unsigned **data); diff --git a/Pcie40Libraries/pcie40_ecs.c b/Pcie40Libraries/pcie40_ecs.c new file mode 100644 index 0000000..5bad326 --- /dev/null +++ b/Pcie40Libraries/pcie40_ecs.c @@ -0,0 +1,351 @@ +/****************************************************************************************//** +* \file ecs.c +* +* \brief This file contains the user library to access PCI driver. +* +* \author JM : 02/11/2013 +* \version 1.0 +* \date 08/11/2013 + +* \copyright (c) Copyright CERN for the benefit of the LHCb Collaboration. +* Distributed under the terms of the GNU General Public Licence V3. +* ana.py script is free and open source software. + + CHANGELOG + JM : 02/11/2013 Initial version + JM/PYD : 04/11/2013 PYD code integration + PYD : adapt for Paolo driver with its library and add multiple board choice +*/ +/************************************************************************************************** +The *Bar*() type of functions concentrate the conditional code which depends of the driver type. + +The ecs_*Lli() or ecs_*User() type of functions are driver blind and used to match user registers +or lli registers. + +ecs_openUser() ecs_openLli() +ecs_iordUser() ecs_iordLli() +ecs_iowrUser() ecs_iowrLli() +ecs_iordBlocUser() ecs_iordBlocLli() +ecs_iowrBlocUser() ecs_iowrBlocLli() +ecs_closeUser() ecs_closeLli() +************************************************************************************************/ +#include <stdio.h> +#include <unistd.h> +#include <string.h> +#include <stdlib.h> + +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> + +#include <linux/ioctl.h> +#include <sys/ioctl.h> + +#include <pcie40_ecs.h> +#include <systemConfig.h> + +// rpm includes +// PYD 20/03/2018 force the use of rpm for all borads types +#include <ecs_driverlib.h> + +/** + * \var ecs_userFile + * \brief ecs_open function return a file description which is stored on userFile for bar 0. +*/ +static int ecs_userFile[MAX_DEV]; + +/** + * \var ecs_lliFile + * \brief ecs_open function return a file description which is stored on lliFile for bar 2. +*/ +static int ecs_lliFile[MAX_DEV]; +/** + * \var ecs_bar2_mm + * \brief ecs_open function for bar 2 mmaps registers area from a start address. +*/ +static unsigned *ecs_bar1_mm[MAX_DEV]; // bar1 start add of mmap +static unsigned *ecs_bar2_mm[MAX_DEV]; // bar2 start add of mmap + +/******************************************************//** + * \fn int ecs_close(int dev, int bar) + * \brief Function to close bar file + * + * \param dev: the selected board number + * \param bar: the bar number + *//******************************************************/ +void ecs_close(int dev, int bar){ + if (bar==2){ + p40_ecs_close(ecs_lliFile[dev],ecs_bar2_mm[dev]); + } + else if (bar==0){ + p40_ecs_close(ecs_lliFile[dev],ecs_bar1_mm[dev]); + } +} + +/******************************************************//** + * \fn int ecs_open(int dev, int bar) + * \brief Function to open bar file + * + * \param dev: the selected board number + * \param bar: number of bar + * \return -1 error / file descriptor + *//******************************************************/ +int ecs_open(int dev,int bar){ + if (bar==2){ + ecs_lliFile[dev] = p40_ecs_open(dev,bar,&(ecs_bar2_mm[dev])); + return ecs_lliFile[dev]; + } + else if (bar==0){ + ecs_userFile[dev] = p40_ecs_open(dev,bar,&(ecs_bar1_mm[dev])); + return ecs_userFile[dev]; + } +return -1; +} + +int ecs_write(int dev, int bar, unsigned add, int val){ + if (add%4 != 0) + return(-1); + + if (bar==2){ + p40_ecs_w32(ecs_bar2_mm[dev],add,val); + } + else if (bar==0){ + p40_ecs_w32(ecs_bar1_mm[dev],add,val); + } + return(0); +} + +unsigned ecs_read(int dev, int bar, unsigned add){ + uint32_t val; + if (add%4 != 0) + return(-1); + if (bar==2){ + val = p40_ecs_r32(ecs_bar2_mm[dev],add); + } + else if (bar==0){ + val = p40_ecs_r32(ecs_bar1_mm[dev],add); + } + return val; +} + +int ecs_iowrBar(int dev, int bar, unsigned add, unsigned *val){ + if (add%4 != 0) + return(-1); + if (bar==2){ + if (ecs_lliFile[dev] == 0) ecs_open(dev,bar); + } + else if (bar==0){ + if (ecs_userFile[dev] == 0) ecs_open(dev,bar); + } + ecs_write(dev,bar,add,*val); + return(0); +} + +int ecs_iordBar(int dev, int bar, unsigned add, unsigned *val){ + if (add%4 != 0) + return(-1); + if (bar==2){ + if (ecs_lliFile[dev] == 0) ecs_open(dev,bar); + } + else if (bar==0){ + if (ecs_userFile[dev] == 0) ecs_open(dev,bar); + } + *val = ecs_read(dev,bar,add); + return(0); +} +int ecs_writeBloc(int dev, int bar, unsigned add, int size, unsigned *val){ + int i; + unsigned wd; + if (add%sizeof(unsigned) != 0) + return(-1); + for (i=0; i<size; i = i + 1){ + wd = val[i]; + ecs_write(dev,bar, add+i*sizeof(unsigned), wd); + } + return 0; +} + +int ecs_readBloc(int dev, int bar, unsigned add, int size, unsigned *val){ + int i; + if (add%4 != 0) + return(-1); + for (i=0; i<size; i = i + 1){ + val[i] = ecs_read(dev,bar,add+i*sizeof(unsigned)); + } + return 0; +} +int ecs_iowrBarBloc(int dev, int bar, unsigned add, int size, unsigned *val){ + ecs_writeBloc(dev,bar,add,size,val); +return 0; +} + +int ecs_iordBarBloc(int dev, int bar, unsigned add, int size, unsigned *val){ + ecs_readBloc(dev,bar,add,size,val); +return 0; +} + +/***********************************************************************//** + * \fn int ecs_printSetup() + * \brief Function to print BAR configurations for checking + * + *//***********************************************************************/ +void ecs_printSetup(){ + printf("-------------------------------------------------\n"); + printf("driver type = MMAP (PCIe40 daq) version\n"); + printf("-------------------------------------------------\n"); + printf("BAR user = BAR%d\n",BAR_USER); + printf("BAR i2c = BAR%d\n",BAR_I2C); + + printf("BASE i2c bus %d TEMPERATURES = 0x%08x\n", I2C_BUS_TEMPERATURES, I2C_BUS_BASE_TEMPERATURES); + printf("BASE i2c bus %d CLEANER1 = 0x%08x\n", I2C_BUS_PLL_CLEANER1, I2C_BUS_BASE_PLL_CLEANER1); + printf("BASE i2c bus %d CLEANER2 = 0x%08x\n", I2C_BUS_PLL_CLEANER2, I2C_BUS_BASE_PLL_CLEANER2); + printf("BASE i2c bus %d PLL_TFC = 0x%08x\n", I2C_BUS_PLL_TFC, I2C_BUS_BASE_PLL_TFC); + printf("BASE i2c bus %d SFP1 = 0x%08x\n", I2C_BUS_SFP1, I2C_BUS_BASE_SFP1); + printf("BASE i2c bus %d SFP2 = 0x%08x\n", I2C_BUS_SFP2, I2C_BUS_BASE_SFP2); + printf("BASE i2c bus %d MINIPODS = 0x%08x\n", I2C_BUS_MINIPODS, I2C_BUS_BASE_MINIPODS); + printf("BASE i2c bus %d TEMP_MEZZANINE = 0x%08x\n", I2C_BUS_TEMP_MEZZANINE, I2C_BUS_BASE_TEMP_MEZZANINE); + printf("BASE i2c bus %d CURRENT1 = 0x%08x\n", I2C_BUS_CURRENT1, I2C_BUS_BASE_CURRENT1); + printf("BASE i2c bus %d CURRENT2 = 0x%08x\n", I2C_BUS_CURRENT2, I2C_BUS_BASE_CURRENT2); +} + +// Usefull for python wrappers when memory is allocated by the lli C libs +// it should be freed after python module has used it. +void ecs_free( int *data) { + free(data); +} +/***********************************************************************//** + * \fn int ecs_openUser(int dev) + * \brief Function to init the ecs pcie bus accesses for user space + * Thus function has to be done before any access. + * + * Here we have a detailed description of the function + * + * \param : dev the board number + * \return 0 success, -1 error + *//***********************************************************************/ +int ecs_openUser(int dev){ + return ecs_open(dev,0); +} + +/***********************************************************************//** + * \fn int ecs_closeUser(int dev) + * \brief Function to disconnect from the ecs user space. + * A new ecs_open() should be done before any new read or write + * + * \param : dev the board number + *//***********************************************************************/ +void ecs_closeUser(int dev){ + ecs_close(dev,0); +} + +/***********************************************************************//** + * \fn int ecs_openLli(int dev) + * \brief Function to init the ecs pcie bus accesses for LLI devices + * Thus function has to be done before any access. + * + * \param : dev the board number + * \return 0 success, -1 error + *//***********************************************************************/ +int ecs_openLli(int dev){ + return ecs_open(dev,2); +} + +/***********************************************************************//** + * \fn int ecs_closeLli(int dev) + * \brief Function to disconnect from the LLI devices io. + * A new ecs_openLli() should be done before any new read or write + * + * \param : dev the board number + *//***********************************************************************/ +void ecs_closeLli(int dev){ + ecs_close(dev,2); +} + +/***********************************************************************//** + * \fn int ecs_iordLli(int dev, unsigned add, unsigned *val) + * \brief Function to read a word at offset add in the lli registers space. + * + * \param : dev the board number + * \param add the offset of the word to read in the lli register space + * \param val a pointer to receive the read value in case of success + * \return 0 success,-1 error + *//***********************************************************************/ +int ecs_iordLli(int dev, unsigned add, unsigned *val){ + return ecs_iordBar(dev, 2, add, val); +} + +/***********************************************************************//** + * \fn int ecs_iowrLli(int dev, unsigned add, unsigned *val) + * \brief Function to write a word at offset add in the Lli registers space. + * + * \param : dev the board number + * \param add the offset of the word to write in the Lli registers space + * \param val a pointer to the value to write + * \return 0 success,-1 error + *//***********************************************************************/ +int ecs_iowrLli(int dev, unsigned add, unsigned *val){ + return ecs_iowrBar(dev, 2, add, val); +} + +/***********************************************************************//** + * \fn int ecs_iordBlocLli(unsigned add, int size, unsigned *val) + * \brief Function to read size words at offset add in the lli registers space. + * + * \param : dev the board number + * \param add : the offset of the word to read in the lli register space + * \param size : number of bytes to read + * \param val : a pointer to receive the read value in case of success + * \return 0 success,-1 error + *//***********************************************************************/ +int ecs_iordBlocLli(int dev, unsigned add, int size, unsigned *val){ + return ecs_iordBarBloc(dev, 2, add, size, val); +} + +/***********************************************************************//** + * \fn int ecs_iowrBlocLli(unsigned add, int size, unsigned *val) + * \brief Function to write size words at offset add in the Lli registers space. + * + * \param : dev the board number + * \param add : the offset of the word to write in the Lli registers space + * \param size : number of bytes to write + * \param val : a pointer to the value to write + * \return 0 success,-1 error + *//***********************************************************************/ +int ecs_iowrBlocLli(int dev, unsigned add, int size, unsigned *val){ + return ecs_iowrBarBloc(dev, 2, add, size, val); +} + +/***********************************************************************//** + * \fn int ecs_iordI2c(int dev, unsigned add, unsigned *val) + * \brief Function to read a word at offset add in the I2C core registers space. + * + * \param : dev the board number + * \param add the offset of the word to read in the I2C core register space + * \param val a pointer to receive the read value in case of success + * \return 0 success,-1 error + *//***********************************************************************/ +int ecs_iordI2c(int dev, unsigned add, unsigned *val){ + return ecs_iordLli(dev, add, val); +} +int ecs_iordI2c_slow(int dev, unsigned add, unsigned *val){ + int dat = ecs_iordLli(dev, add, val); + usleep(0); + return dat; +} +/***********************************************************************//** + * \fn int ecs_iowrI2c(unsigned add, unsigned *val) + * \brief Function to write a word at offset add in the I2C core registers space. + * + * \param : dev the board number + * \param add the offset of the word to write in the I2C core registers space + * \param val a pointer to the value to write + * \return 0 success,-1 error + *//***********************************************************************/ +int ecs_iowrI2c(int dev, unsigned add, unsigned *val){ + return ecs_iowrLli(dev, add, val); +} +int ecs_iowrI2c_slow(int dev, unsigned add, unsigned *val){ + int dat = ecs_iowrLli(dev, add, val); + usleep(0); + return dat; +} diff --git a/Pcie40Libraries/pcie40_ecs.h b/Pcie40Libraries/pcie40_ecs.h new file mode 100644 index 0000000..d386b72 --- /dev/null +++ b/Pcie40Libraries/pcie40_ecs.h @@ -0,0 +1,55 @@ +#ifndef ECS_H +#define ECS_H + +#include <linux/ioctl.h> + +typedef struct { + int size; +} ecs_arg_t; + +#define ECS_IOCTL_SET_SIZE _IOW('e',0, ecs_arg_t *) +#define ECS_IOCTL_GET_SIZE _IOR('e',1, ecs_arg_t *) + +void ecs_printSetup(); + +int ecs_open(int dev, int bar); +void ecs_close(int dev, int bar); + +int ecs_write(int dev, int bar, unsigned add, int val); +unsigned ecs_read(int dev, int bar, unsigned add); +int ecs_writeBloc(int dev, int bar, unsigned add, int size, unsigned *val); +int ecs_readBloc(int dev, int bar, int unsigned, int size, unsigned *val); + + +//Adaptation with old library +int ecs_iowrBar(int dev, int bar, unsigned add, unsigned *val); +int ecs_iordBar(int dev, int bar, unsigned add, unsigned *val); +int ecs_iowrBarBloc(int dev, int bar, unsigned add, int size, unsigned *val); +int ecs_iordBarBloc(int dev, int bar, unsigned add, int size, unsigned *val); + +// functions to use for user space registers R/W +int ecs_openUser(int dev); +void ecs_closeUser(int dev); +int ecs_iordUser(int dev, unsigned add, unsigned *val); +int ecs_iowrUser(int dev, unsigned add, unsigned *val); +int ecs_iordBlocUser(int dev, unsigned add, int size, unsigned *val); +int ecs_iowrBlocUser(int dev, unsigned add, int size, unsigned *val); + +// functions to use to access the LLI ressources +int ecs_openLli(int dev); +void ecs_closeLli(int dev); +int ecs_iordLli(int dev, unsigned add, unsigned *val); +int ecs_iowrLli(int dev, unsigned add, unsigned *val); +int ecs_iordBlocLli(int dev, unsigned add, int size, unsigned *val); +int ecs_iowrBlocLli(int dev, unsigned add, int size, unsigned *val); + +// functions to use to access the I2C core registers +int ecs_iordI2c(int dev, unsigned add, unsigned *val); +int ecs_iowrI2c(int dev, unsigned add, unsigned *val); +int ecs_iordI2c_slow(int dev, unsigned add, unsigned *val); +int ecs_iowrI2c_slow(int dev, unsigned add, unsigned *val); + +// function to access the PHY registers space +int ecs_iordPhy(int dev, unsigned add, unsigned *val); +int ecs_iowrPhy(int dev, unsigned add, unsigned *val); +#endif diff --git a/Pcie40Libraries/systemConfig.h b/Pcie40Libraries/systemConfig.h new file mode 100644 index 0000000..06c351e --- /dev/null +++ b/Pcie40Libraries/systemConfig.h @@ -0,0 +1,61 @@ +#ifndef SYSTEM_CONFIG_H +#define SYSTEM_CONFIG_H + +// max number of used borad in a PC +#define MAX_DEV 16 + +//================= BAR DEFINE ================= +#define BAR_USER 0 +#define BAR_LLI 2 + +#define BAR_I2C 2 + +//================= I2C ======================== +// Makes the association between the BUS number and the BUS BASE + +#define I2C_BUS_BASE_TEMPERATURES 0x10000 +#define I2C_BUS_TEMPERATURES 0 + +#define I2C_BUS_BASE_PLL_CLEANER1 0x10020 +#define I2C_BUS_PLL_CLEANER1 1 + +#define I2C_BUS_BASE_PLL_CLEANER2 0x10040 +#define I2C_BUS_PLL_CLEANER2 2 + +#define I2C_BUS_BASE_PLL_TFC 0x10060 +#define I2C_BUS_PLL_TFC 3 + +#define I2C_BUS_BASE_FANOUT 0x10080 +#define I2C_BUS_FANOUT 4 + +#define I2C_BUS_BASE_SFP1 0x100A0 +#define I2C_BUS_SFP1 5 + +#define I2C_BUS_BASE_SFP2 0x100C0 +#define I2C_BUS_SFP2 6 + +#define I2C_BUS_BASE_MINIPODS 0x100E0 +#define I2C_BUS_MINIPODS 7 + +#define I2C_BUS_BASE_TEMP_MEZZANINE 0x10100 +#define I2C_BUS_TEMP_MEZZANINE 8 + +#define I2C_BUS_BASE_FPGA_EEPROM 0x10120 +#define I2C_BUS_FPGA_EEPROM 9 + +#define I2C_BUS_BASE_CURRENT1 0x20000 +#define I2C_BUS_CURRENT1 10 + +#define I2C_BUS_BASE_CURRENT2 0x20020 +#define I2C_BUS_CURRENT2 11 + +//============== FPGA Transceivers ===================== +#define NB_RECONFIG 1 //Number of reconfig blocs (transceivers) (Max 6 link by reconfig) +#define RECONFIG_BASE_ADDR_LIST {0x0200} //{addr_reconf0, addr_reconf1, addr_reconf2, addr_reconf3, ...} +#define RECONFIG_MGMT_BASE 0x0200 +#define PHY_MGMT_BASE 0x0800 + +//================= USER_SPACE Master (BRIDGE) ========== +#define USER_SPACE_MASTER 0x80000 + +#endif -- GitLab