[Cryptech-Commits] [test/novena_base] 03/04: reformat C code slightly

git at cryptech.is git at cryptech.is
Tue Feb 3 16:15:11 UTC 2015


This is an automated email from the git hooks/post-receive script.

paul at psgd.org pushed a commit to branch master
in repository test/novena_base.

commit c3c708d6526323e956699d756cce03df1310fcd2
Author: Paul Selkirk <paul at psgd.org>
Date:   Tue Feb 3 10:49:36 2015 -0500

    reformat C code slightly
---
 sw/test-adder/Makefile     |   8 +-
 sw/test-adder/novena-eim.c | 857 ++++++++++++++++++++++++---------------------
 sw/test-adder/novena-eim.h | 618 ++++++++++++++++----------------
 sw/test-adder/test-adder.c | 339 ++++++++++--------
 4 files changed, 964 insertions(+), 858 deletions(-)

diff --git a/sw/test-adder/Makefile b/sw/test-adder/Makefile
index 5271b70..bd6cfa0 100755
--- a/sw/test-adder/Makefile
+++ b/sw/test-adder/Makefile
@@ -2,10 +2,10 @@ all: test-adder
 
 test-adder : test-adder.o novena-eim.o
 	gcc -o test-adder test-adder.o novena-eim.o
-	
+
 test-adder.o: test-adder.c novena-eim.h novena-eim.c
-	gcc -c test-adder.c
-	gcc -c novena-eim.c
-	
+	gcc -c -Wall test-adder.c
+	gcc -c -Wall novena-eim.c
+
 clean:
 	rm -f *.o test-adder
diff --git a/sw/test-adder/novena-eim.c b/sw/test-adder/novena-eim.c
index 9ea76ef..3fe3566 100644
--- a/sw/test-adder/novena-eim.c
+++ b/sw/test-adder/novena-eim.c
@@ -1,406 +1,451 @@
-//------------------------------------------------------------------------------
-// novena-eim.c
-//------------------------------------------------------------------------------
-
-
-//------------------------------------------------------------------------------
-// Headers
-//------------------------------------------------------------------------------
-#include <fcntl.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-#include <sys/mman.h>
-#include "novena-eim.h"
-
-
-//------------------------------------------------------------------------------
-// Variables
-//------------------------------------------------------------------------------
-static long		mem_page_size	= 0;
-static int		mem_dev_fd		= -1;
-static void *	mem_map_ptr		= MAP_FAILED;
-static off_t	mem_base_addr	= 0;
-
-
-//------------------------------------------------------------------------------
-int eim_setup()
-//------------------------------------------------------------------------------
-{
-		// register cleanup function
-	int ok = atexit(_eim_cleanup);
-	if (ok != 0)
-	{	printf("ERROR: atexit() failed.\n");
-		return -1;
-	}
-	
-		// determine memory page size to use in mmap()
-	mem_page_size = sysconf(_SC_PAGESIZE);
-	if (mem_page_size < 1)
-	{	printf("ERROR: sysconf(_SC_PAGESIZE) == %l\n", mem_page_size);
-		return -1;
-	}
-	
-		// try to open memory device
-	mem_dev_fd = open(MEMORY_DEVICE, O_RDWR | O_SYNC);
-	if (mem_dev_fd == -1)
-	{	printf("ERROR: open(%s) failed.\n", MEMORY_DEVICE);
-		return -1;
-	}
-
-		/* Several blocks in the CPU have common pins, we can use I/O MUX Controller
-		 * to configure what block will actually use I/O pins. We wait EIM module to be able
-		 * to communicate with the on-board FPGA. Let's configure IOMUXC accordingly.
-		 */
-	_eim_setup_iomuxc();
-	
-		/* We need to enable clocking of EIM block in order to be able to use it.
-		 * Let's configure Clock Controller Module accordingly.
-		 */
-	_eim_setup_ccm();
-	
-		/* We need to properly configure EIM mode and all the corresponding parameters.
-		 * That's a lot of code, let's do it now.
-		 */
-	_eim_setup_eim();
-	
-	
-		// done
-	return 1;
-}
-
-
-//------------------------------------------------------------------------------
-void _eim_cleanup()
-//------------------------------------------------------------------------------
-{
-		// unmap memory if needed
-	if (mem_map_ptr != MAP_FAILED)
-	{	int ok = munmap(mem_map_ptr, mem_page_size);
-		if (ok != 0) printf("WARNING: munmap() failed.\n");
-	}
-
-		// close memory device if needed
-	if (mem_dev_fd != -1)
-	{	int ok = close(mem_dev_fd);
-		if (ok != 0) printf("WARNING: close() failed.\n");
-	}
-}
-
-
-//------------------------------------------------------------------------------
-void _eim_setup_iomuxc()
-//------------------------------------------------------------------------------
-{
-		// create structures
-	struct IOMUXC_SW_MUX_CTL_PAD_EIM	reg_mux;				// mux control register
-	struct IOMUXC_SW_PAD_CTL_PAD_EIM	reg_pad;				// pad control register
-	
-		// setup mux control register
-	reg_mux.mux_mode		= IOMUXC_MUX_MODE_ALT0;				// ALT0 mode must be used for EIM
-	reg_mux.sion			= 0;								// forced input not needed
-	reg_mux.reserved_3		= 0;								// must be 0
-	reg_mux.reserved_31_5	= 0;								// must be 0
-
-		// setup pad control register
-	reg_pad.sre				= IOMUXC_PAD_CTL_SRE_FAST;			// fast slew rate
-	reg_pad.dse				= IOMUXC_PAD_CTL_DSE_33_OHM;		// highest drive strength
-	reg_pad.speed			= IOMUXC_PAD_CTL_SPEED_MEDIUM_10;	// medium speed
-	reg_pad.ode				= IOMUXC_PAD_CTL_ODE_DISABLED;		// open drain not needed
-	reg_pad.pke				= IOMUXC_PAD_CTL_PKE_DISABLED;		// neither pull nor keeper are needed
-	reg_pad.pue				= IOMUXC_PAD_CTL_PUE_PULL;			// doesn't matter actually, because PKE is disabled
-	reg_pad.pus				= IOMUXC_PAD_CTL_PUS_100K_OHM_PU;	// doesn't matter actually, because PKE is disabled
-	reg_pad.hys				= IOMUXC_PAD_CTL_HYS_DISABLED;		// use CMOS, not Schmitt trigger input
-	reg_pad.reserved_2_1	= 0;								// must be 0
-	reg_pad.reserved_10_8	= 0;								// must be 0
-	reg_pad.reserved_31_17	= 0;								// must be 0
-
-		// all the pins must be configured to use the same ALT0 mode
-	eim_write_32(IOMUXC_SW_MUX_CTL_PAD_EIM_CS0_B,	(unsigned int *)&reg_mux);
-	eim_write_32(IOMUXC_SW_MUX_CTL_PAD_EIM_OE_B,	(unsigned int *)&reg_mux);
-	eim_write_32(IOMUXC_SW_MUX_CTL_PAD_EIM_RW,		(unsigned int *)&reg_mux);
-	eim_write_32(IOMUXC_SW_MUX_CTL_PAD_EIM_LBA_B,	(unsigned int *)&reg_mux);
-	eim_write_32(IOMUXC_SW_MUX_CTL_PAD_EIM_AD00,	(unsigned int *)&reg_mux);
-	eim_write_32(IOMUXC_SW_MUX_CTL_PAD_EIM_AD01,	(unsigned int *)&reg_mux);
-	eim_write_32(IOMUXC_SW_MUX_CTL_PAD_EIM_AD02,	(unsigned int *)&reg_mux);
-	eim_write_32(IOMUXC_SW_MUX_CTL_PAD_EIM_AD03,	(unsigned int *)&reg_mux);
-	eim_write_32(IOMUXC_SW_MUX_CTL_PAD_EIM_AD04,	(unsigned int *)&reg_mux);
-	eim_write_32(IOMUXC_SW_MUX_CTL_PAD_EIM_AD05,	(unsigned int *)&reg_mux);
-	eim_write_32(IOMUXC_SW_MUX_CTL_PAD_EIM_AD06,	(unsigned int *)&reg_mux);
-	eim_write_32(IOMUXC_SW_MUX_CTL_PAD_EIM_AD07,	(unsigned int *)&reg_mux);
-	eim_write_32(IOMUXC_SW_MUX_CTL_PAD_EIM_AD08,	(unsigned int *)&reg_mux);
-	eim_write_32(IOMUXC_SW_MUX_CTL_PAD_EIM_AD09,	(unsigned int *)&reg_mux);
-	eim_write_32(IOMUXC_SW_MUX_CTL_PAD_EIM_AD10,	(unsigned int *)&reg_mux);
-	eim_write_32(IOMUXC_SW_MUX_CTL_PAD_EIM_AD11,	(unsigned int *)&reg_mux);
-	eim_write_32(IOMUXC_SW_MUX_CTL_PAD_EIM_AD12,	(unsigned int *)&reg_mux);
-	eim_write_32(IOMUXC_SW_MUX_CTL_PAD_EIM_AD13,	(unsigned int *)&reg_mux);
-	eim_write_32(IOMUXC_SW_MUX_CTL_PAD_EIM_AD14,	(unsigned int *)&reg_mux);
-	eim_write_32(IOMUXC_SW_MUX_CTL_PAD_EIM_AD15,	(unsigned int *)&reg_mux);
-	eim_write_32(IOMUXC_SW_MUX_CTL_PAD_EIM_WAIT_B,	(unsigned int *)&reg_mux);
-	eim_write_32(IOMUXC_SW_MUX_CTL_PAD_EIM_BCLK,	(unsigned int *)&reg_mux);
-
-		// we need to configure all the I/O pads too
-	eim_write_32(IOMUXC_SW_PAD_CTL_PAD_EIM_CS0_B,	(unsigned int *)&reg_pad);
-	eim_write_32(IOMUXC_SW_PAD_CTL_PAD_EIM_OE_B,	(unsigned int *)&reg_pad);
-	eim_write_32(IOMUXC_SW_PAD_CTL_PAD_EIM_RW,		(unsigned int *)&reg_pad);
-	eim_write_32(IOMUXC_SW_PAD_CTL_PAD_EIM_LBA_B,	(unsigned int *)&reg_pad);
-	eim_write_32(IOMUXC_SW_PAD_CTL_PAD_EIM_AD00,	(unsigned int *)&reg_pad);
-	eim_write_32(IOMUXC_SW_PAD_CTL_PAD_EIM_AD01,	(unsigned int *)&reg_pad);
-	eim_write_32(IOMUXC_SW_PAD_CTL_PAD_EIM_AD02,	(unsigned int *)&reg_pad);
-	eim_write_32(IOMUXC_SW_PAD_CTL_PAD_EIM_AD03,	(unsigned int *)&reg_pad);
-	eim_write_32(IOMUXC_SW_PAD_CTL_PAD_EIM_AD04,	(unsigned int *)&reg_pad);
-	eim_write_32(IOMUXC_SW_PAD_CTL_PAD_EIM_AD05,	(unsigned int *)&reg_pad);
-	eim_write_32(IOMUXC_SW_PAD_CTL_PAD_EIM_AD06,	(unsigned int *)&reg_pad);
-	eim_write_32(IOMUXC_SW_PAD_CTL_PAD_EIM_AD07,	(unsigned int *)&reg_pad);
-	eim_write_32(IOMUXC_SW_PAD_CTL_PAD_EIM_AD08,	(unsigned int *)&reg_pad);
-	eim_write_32(IOMUXC_SW_PAD_CTL_PAD_EIM_AD09,	(unsigned int *)&reg_pad);
-	eim_write_32(IOMUXC_SW_PAD_CTL_PAD_EIM_AD10,	(unsigned int *)&reg_pad);
-	eim_write_32(IOMUXC_SW_PAD_CTL_PAD_EIM_AD11,	(unsigned int *)&reg_pad);
-	eim_write_32(IOMUXC_SW_PAD_CTL_PAD_EIM_AD12,	(unsigned int *)&reg_pad);
-	eim_write_32(IOMUXC_SW_PAD_CTL_PAD_EIM_AD13,	(unsigned int *)&reg_pad);
-	eim_write_32(IOMUXC_SW_PAD_CTL_PAD_EIM_AD14,	(unsigned int *)&reg_pad);
-	eim_write_32(IOMUXC_SW_PAD_CTL_PAD_EIM_AD15,	(unsigned int *)&reg_pad);
-	eim_write_32(IOMUXC_SW_PAD_CTL_PAD_EIM_WAIT_B,	(unsigned int *)&reg_pad);
-	eim_write_32(IOMUXC_SW_PAD_CTL_PAD_EIM_BCLK,	(unsigned int *)&reg_pad);
-}
-
-
-//------------------------------------------------------------------------------
-void _eim_setup_ccm()
-//------------------------------------------------------------------------------
-{
-		// create structure
-	struct CCM_CCGR6 ccm_ccgr6;
-	
-		// read register
-	eim_read_32(CCM_CCGR6, (unsigned int *)&ccm_ccgr6);
-	
-		// modify register
-	ccm_ccgr6.cg0_usboh3		= CCM_CGR_ON_EXCEPT_STOP;
-	ccm_ccgr6.cg1_usdhc1		= CCM_CGR_OFF;
-	ccm_ccgr6.cg2_usdhc2		= CCM_CGR_ON_EXCEPT_STOP;
-	ccm_ccgr6.cg3_usdhc3		= CCM_CGR_ON_EXCEPT_STOP;
-	
-	ccm_ccgr6.cg3_usdhc4		= CCM_CGR_OFF;
-	ccm_ccgr6.cg5_eim_slow		= CCM_CGR_ON_EXCEPT_STOP;
-	ccm_ccgr6.cg6_vdoaxiclk		= CCM_CGR_OFF;
-	ccm_ccgr6.cg7_vpu			= CCM_CGR_OFF;
-	
-	ccm_ccgr6.cg8_reserved		= 0;
-	ccm_ccgr6.cg9_reserved		= 0;
-	ccm_ccgr6.cg10_reserved		= 0;
-	ccm_ccgr6.cg11_reserved		= 0;
-	ccm_ccgr6.cg12_reserved		= 0;
-	ccm_ccgr6.cg13_reserved		= 0;
-	ccm_ccgr6.cg14_reserved		= 0;
-	ccm_ccgr6.cg15_reserved		= 0;
-	
-		// write register
-	eim_write_32(CCM_CCGR6, (unsigned int *)&ccm_ccgr6);
-}
-
-
-//------------------------------------------------------------------------------
-void _eim_setup_eim()
-//------------------------------------------------------------------------------
-{
-		// create structures
-	struct EIM_CS_GCR1	gcr1;
-	struct EIM_CS_GCR2	gcr2;
-	struct EIM_CS_RCR1	rcr1;
-	struct EIM_CS_RCR2	rcr2;
-	struct EIM_CS_WCR1	wcr1;
-	struct EIM_CS_WCR2	wcr2;
-	
-	struct EIM_WCR		wcr;
-	struct EIM_WIAR		wiar;
-	struct EIM_EAR		ear;
-	
-		// read all the registers
-	eim_read_32(EIM_CS0GCR1, (unsigned int *)&gcr1);
-	eim_read_32(EIM_CS0GCR2, (unsigned int *)&gcr2);
-	eim_read_32(EIM_CS0RCR1, (unsigned int *)&rcr1);
-	eim_read_32(EIM_CS0RCR2, (unsigned int *)&rcr2);
-	eim_read_32(EIM_CS0WCR1, (unsigned int *)&wcr1);
-	eim_read_32(EIM_CS0WCR2, (unsigned int *)&wcr2);
-	
-	eim_read_32(EIM_WCR,	(unsigned int *)&wcr);
-	eim_read_32(EIM_WIAR,	(unsigned int *)&wiar);
-	eim_read_32(EIM_EAR,	(unsigned int *)&ear);
-	
-		// manipulate registers as needed
-	gcr1.csen				= 1;	// chip select is enabled					|
-	gcr1.swr				= 1;	// write is sync							|
-	gcr1.srd				= 1;	// read is sync								|
-	gcr1.mum				= 1;	// address and data are multiplexed			|
-	gcr1.wfl				= 0;	// write latency is not fixed				|
-	gcr1.rfl				= 0;	// read latency is not fixed				|
-	gcr1.cre				= 0;	// CRE signal not needed					|
-	//gcr1.crep				= x;	// don't care, CRE not used					|
-	gcr1.bl					= 4;	// burst length 							| ?
-	gcr1.wc					= 0;	// write is not continuous 				 	| ?
-	gcr1.bcd				= 3;	// BCLK divisor is 3+1=4					|
-	gcr1.bcs				= 1;	// delay from ~CS to BCLK is 1 cycle		|
-	gcr1.dsz				= 1;	// 16 bits per databeat at DATA[15:0]		|
-	gcr1.sp					= 0;	// supervisor protection is disabled		|
-	gcr1.csrec				= 1;	// ~CS recovery is 1 cycle 					|
-	gcr1.aus				= 1;	// address is not shifted 					|
-	gcr1.gbc				= 1;	// ~CS gap is 1 cycle						|
-	gcr1.wp					= 0;	// write protection is not enabled			|
-	//gcr1.psz				= x;	// don't care, page mode is not used		|
-	
-	gcr2.adh				= 0;	// address hold duration is 1 cycle			|
-	//gcr2.daps				= x;	// don't care, DTACK is not used			|
-	gcr2.dae				= 0;	// DTACK is not used						|
-	//gcr2.dap				= x;	// don't care, DTACK is not used			|
-	gcr2.mux16_byp_grant	= 1;	// enable grant mechanism 					| ?
-	gcr2.reserved_3_2		= 0;	// must be 0								|
-	gcr2.reserved_11_10		= 0;	// must be 0								|
-	gcr2.reserved_31_13		= 0;	// must be 0								|
-	
-	//rcr1.rcsn				= x;	// don't care in sync mode					|
-	rcr1.rcsa				= 0;	// no delay for ~CS needed					|
-	//rcr1.oen				= x;	// don't care in sync mode					|
-	rcr1.oea				= 0;	// no delay for ~OE needed					|
-	rcr1.radvn				= 0;	// no delay for ~LBA needed					|
-	rcr1.ral				= 0;	// clear ~LBA when needed					|
-	rcr1.radva				= 0;	// no delay for ~LBA needed					|
-	rcr1.rwsc				= 1;	// one wait state							|
-	rcr1.reserved_3			= 0;	// must be 0								|
-	rcr1.reserved_7			= 0;	// must be 0								|
-	rcr1.reserved_11		= 0;	// must be 0								|
-	rcr1.reserved_15		= 0;	// must be 0								|
-	rcr1.reserved_23		= 0;	// must be 0								|
-	rcr1.reserved_31_30		= 0;	// must be 0								|
-	
-	//rcr2.rben				= x;	// don't care in sync mode					|
-	rcr2.rbe				= 0;	// BE is disabled							|
-	//rcr2.rbea				= x;	// don't care when BE is not used			|
-	rcr2.rl					= 0;	// read latency is 0 						| ?
-	//rcr2.pat				= x;	// don't care when page read is not used	|
-	rcr2.apr				= 0;	// page read mode is not used				|
-	rcr2.reserved_7			= 0;	// must be 0								|
-	rcr2.reserved_11_10		= 0;	// must be 0								|
-	rcr2.reserved_31_16		= 0;	// must be 0								|
-
-	//wcr1.wcsn				= x;	// don't care in sync mode					|
-	wcr1.wcsa				= 0;	// no delay for ~CS needed					|
-	//wcr1.wen				= x;	// don't care in sync mode					|
-	wcr1.wea				= 0;	// no delay for ~WR_N needed				|
-	//wcr1.wben				= x;	// don't care in sync mode					|
-	//wcr1.wbea				= x;	// don't care in sync mode					|
-	wcr1.wadvn				= 0;	// no delay for ~LBA needed					|
-	wcr1.wadva				= 0;	// no delay for ~LBA needed					|
-	wcr1.wwsc				= 1;	// no wait state in needed					|
-	wcr1.wbed				= 1;	// BE is disabled							|
-	wcr1.wal				= 0;	// clear ~LBA when needed					|
-
-	wcr2.wbcdd				= 0;	// write clock division is not needed		|
-	wcr2.reserved_31_1		= 0;	// must be 0								|
-	
-	wcr.bcm					= 0;	// clock is only active during access		|
-	//wcr.gbcd				= x;	// don't care when BCM=0					|
-	wcr.inten				= 0;	// interrupt is not used					|
-	//wcr.intpol			= x;	// don't care when interrupt is not used	|
-	wcr.wdog_en				= 1;	// watchdog is enabled						|
-	wcr.wdog_limit			= 00;	// timeout is 128 BCLK cycles				|
-	wcr.reserved_3			= 0;	// must be 0								|		
-	wcr.reserved_7_6		= 0;	// must be 0								|
-	wcr.reserved_31_11		= 0;	// must be 0								|
-	
-	wiar.ips_req			= 0;	// IPS not needed							|
-	wiar.ips_ack			= 0;	// IPS not needed							|
-	//wiar.irq				= x;	// don't touch								|
-	//wiar.errst			= x;	// don't touch								|
-	wiar.aclk_en			= 1;	// clock is enabled							|
-	wiar.reserved_31_5		= 0;	// must be 0								|
-	
-	//ear.error_addr		= x;	// read-only								|
-	
-		// write modified registers
-	eim_write_32(EIM_CS0GCR1,	(unsigned int *)&gcr1);
-	eim_write_32(EIM_CS0GCR2,	(unsigned int *)&gcr2);
-	eim_write_32(EIM_CS0RCR1,	(unsigned int *)&rcr1);
-	eim_write_32(EIM_CS0RCR2,	(unsigned int *)&rcr2);
-	eim_write_32(EIM_CS0WCR1,	(unsigned int *)&wcr1);
-	eim_write_32(EIM_CS0WCR2,	(unsigned int *)&wcr2);
-	eim_write_32(EIM_WCR,		(unsigned int *)&wcr);
-	eim_write_32(EIM_WIAR,	(unsigned int *)&wiar);/*
-	eim_write_32(EIM_EAR,		(unsigned int *)&ear);*/
-}
-
-
-//------------------------------------------------------------------------------
-void eim_write_32(off_t offset, unsigned int *pvalue)
-//------------------------------------------------------------------------------
-{
-		// calculate memory offset
-	unsigned int *ptr = (unsigned int *)_eim_calc_offset(offset);
-	
-		// write data to memory
-	memcpy(ptr, pvalue, sizeof(unsigned int));	
-}
-
-//------------------------------------------------------------------------------
-void eim_read_32(off_t offset, unsigned int *pvalue)
-//------------------------------------------------------------------------------
-{
-		// calculate memory offset
-	unsigned int *ptr = (unsigned int *)_eim_calc_offset(offset);
-	
-		// read data from memory
-	memcpy(pvalue, ptr, sizeof(unsigned int));	
-}
-
-
-//------------------------------------------------------------------------------
-off_t _eim_calc_offset(off_t offset)
-//------------------------------------------------------------------------------
-{
-		// make sure that memory is mapped
-	if (mem_map_ptr == MAP_FAILED) _eim_remap_mem(offset);
-
-		// calculate starting and ending addresses of currently mapped page
-	off_t offset_low	= mem_base_addr;
-	off_t offset_high	= mem_base_addr + (mem_page_size - 1);
-	
-		// check that offset is in currently mapped page, remap new page otherwise
-	if ((offset < offset_low) || (offset > offset_high)) _eim_remap_mem(offset);
-	
-		// calculate pointer
-	return (off_t)mem_map_ptr + (offset - mem_base_addr);
-}
-
-
-//------------------------------------------------------------------------------
-void _eim_remap_mem(off_t offset)
-//------------------------------------------------------------------------------
-{
-		// unmap old memory page if needed
-	if (mem_map_ptr != MAP_FAILED)
-	{	int ok = munmap(mem_map_ptr, mem_page_size);
-		if (ok != 0)
-		{	printf("ERROR: munmap() failed.\n");
-			exit(EXIT_FAILURE);
-		}
-	}
-	
-		// calculate starting address of new page
-	while (offset % mem_page_size) offset--;
-	
-		// try to map new memory page
-	mem_map_ptr = mmap(NULL, mem_page_size, PROT_READ | PROT_WRITE, MAP_SHARED, mem_dev_fd, offset);
-	if (mem_map_ptr == MAP_FAILED)
-	{	printf("ERROR: mmap() failed.\n");
-		exit(EXIT_FAILURE);
-	}
-	
-		// save last mapped page address
-	mem_base_addr = offset;
-}
-
-
-//------------------------------------------------------------------------------
-// End-of-File
-//------------------------------------------------------------------------------
+/*
+ * novena-eim.c
+ * ------------
+ * This module contains the user interface to the Novena EIM bus.
+ *
+ * Author: Pavel Shatov
+ * Copyright (c) 2015, NORDUnet A/S All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ *
+ * - Neither the name of the NORDUnet nor the names of its contributors may
+ *   be used to endorse or promote products derived from this software
+ *   without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+ * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+ * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+//------------------------------------------------------------------------------
+// Headers
+//------------------------------------------------------------------------------
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/mman.h>
+#include "novena-eim.h"
+
+
+//------------------------------------------------------------------------------
+// Variables
+//------------------------------------------------------------------------------
+static long     mem_page_size   = 0;
+static int      mem_dev_fd      = -1;
+static void *   mem_map_ptr     = MAP_FAILED;
+static off_t    mem_base_addr   = 0;
+
+
+//------------------------------------------------------------------------------
+// Prototypes
+//------------------------------------------------------------------------------
+static void  _eim_setup_iomuxc  (void);
+static void  _eim_setup_ccm     (void);
+static void  _eim_setup_eim     (void);
+static void  _eim_cleanup       (void);
+static off_t _eim_calc_offset   (off_t);
+static void  _eim_remap_mem     (off_t);
+
+
+//------------------------------------------------------------------------------
+int eim_setup(void)
+//------------------------------------------------------------------------------
+{
+    // register cleanup function
+    if (atexit(_eim_cleanup) != 0) {
+        printf("ERROR: atexit() failed.\n");
+        return -1;
+    }
+
+    // determine memory page size to use in mmap()
+    mem_page_size = sysconf(_SC_PAGESIZE);
+    if (mem_page_size < 1) {
+        printf("ERROR: sysconf(_SC_PAGESIZE) == %ld\n", mem_page_size);
+        return -1;
+    }
+
+    // try to open memory device
+    mem_dev_fd = open(MEMORY_DEVICE, O_RDWR | O_SYNC);
+    if (mem_dev_fd == -1) {
+        printf("ERROR: open(%s) failed.\n", MEMORY_DEVICE);
+        return -1;
+    }
+
+    /* Several blocks in the CPU have common pins, we can use I/O MUX
+     * Controller to configure what block will actually use I/O pins. We wait
+     * EIM module to be able to communicate with the on-board FPGA. Let's
+     * configure IOMUXC accordingly.
+     */
+    _eim_setup_iomuxc();
+
+    /* We need to enable clocking of EIM block in order to be able to use it.
+     * Let's configure Clock Controller Module accordingly.
+     */
+    _eim_setup_ccm();
+
+    /* We need to properly configure EIM mode and all the corresponding
+     * parameters. That's a lot of code, let's do it now.
+     */
+    _eim_setup_eim();
+
+    // done
+    return 1;
+}
+
+
+//------------------------------------------------------------------------------
+static void _eim_cleanup(void)
+//------------------------------------------------------------------------------
+{
+    // unmap memory if needed
+    if (mem_map_ptr != MAP_FAILED) {
+        if (munmap(mem_map_ptr, mem_page_size) != 0)
+            printf("WARNING: munmap() failed.\n");
+    }
+
+    // close memory device if needed
+    if (mem_dev_fd != -1) {
+        if (close(mem_dev_fd) != 0)
+            printf("WARNING: close() failed.\n");
+    }
+}
+
+
+//------------------------------------------------------------------------------
+static void _eim_setup_iomuxc(void)
+//------------------------------------------------------------------------------
+{
+    // create structures
+    struct IOMUXC_SW_MUX_CTL_PAD_EIM    reg_mux;                // mux control register
+    struct IOMUXC_SW_PAD_CTL_PAD_EIM    reg_pad;                // pad control register
+
+    // setup mux control register
+    reg_mux.mux_mode        = IOMUXC_MUX_MODE_ALT0;             // ALT0 mode must be used for EIM
+    reg_mux.sion            = 0;                                // forced input not needed
+    reg_mux.reserved_3      = 0;                                // must be 0
+    reg_mux.reserved_31_5   = 0;                                // must be 0
+
+    // setup pad control register
+    reg_pad.sre             = IOMUXC_PAD_CTL_SRE_FAST;          // fast slew rate
+    reg_pad.dse             = IOMUXC_PAD_CTL_DSE_33_OHM;        // highest drive strength
+    reg_pad.speed           = IOMUXC_PAD_CTL_SPEED_MEDIUM_10;   // medium speed
+    reg_pad.ode             = IOMUXC_PAD_CTL_ODE_DISABLED;      // open drain not needed
+    reg_pad.pke             = IOMUXC_PAD_CTL_PKE_DISABLED;      // neither pull nor keeper are needed
+    reg_pad.pue             = IOMUXC_PAD_CTL_PUE_PULL;          // doesn't matter actually, because PKE is disabled
+    reg_pad.pus             = IOMUXC_PAD_CTL_PUS_100K_OHM_PU;   // doesn't matter actually, because PKE is disabled
+    reg_pad.hys             = IOMUXC_PAD_CTL_HYS_DISABLED;      // use CMOS, not Schmitt trigger input
+    reg_pad.reserved_2_1    = 0;                                // must be 0
+    reg_pad.reserved_10_8   = 0;                                // must be 0
+    reg_pad.reserved_31_17  = 0;                                // must be 0
+
+    // all the pins must be configured to use the same ALT0 mode
+    eim_write_32(IOMUXC_SW_MUX_CTL_PAD_EIM_CS0_B,   (unsigned int *)&reg_mux);
+    eim_write_32(IOMUXC_SW_MUX_CTL_PAD_EIM_OE_B,    (unsigned int *)&reg_mux);
+    eim_write_32(IOMUXC_SW_MUX_CTL_PAD_EIM_RW,      (unsigned int *)&reg_mux);
+    eim_write_32(IOMUXC_SW_MUX_CTL_PAD_EIM_LBA_B,   (unsigned int *)&reg_mux);
+    eim_write_32(IOMUXC_SW_MUX_CTL_PAD_EIM_AD00,    (unsigned int *)&reg_mux);
+    eim_write_32(IOMUXC_SW_MUX_CTL_PAD_EIM_AD01,    (unsigned int *)&reg_mux);
+    eim_write_32(IOMUXC_SW_MUX_CTL_PAD_EIM_AD02,    (unsigned int *)&reg_mux);
+    eim_write_32(IOMUXC_SW_MUX_CTL_PAD_EIM_AD03,    (unsigned int *)&reg_mux);
+    eim_write_32(IOMUXC_SW_MUX_CTL_PAD_EIM_AD04,    (unsigned int *)&reg_mux);
+    eim_write_32(IOMUXC_SW_MUX_CTL_PAD_EIM_AD05,    (unsigned int *)&reg_mux);
+    eim_write_32(IOMUXC_SW_MUX_CTL_PAD_EIM_AD06,    (unsigned int *)&reg_mux);
+    eim_write_32(IOMUXC_SW_MUX_CTL_PAD_EIM_AD07,    (unsigned int *)&reg_mux);
+    eim_write_32(IOMUXC_SW_MUX_CTL_PAD_EIM_AD08,    (unsigned int *)&reg_mux);
+    eim_write_32(IOMUXC_SW_MUX_CTL_PAD_EIM_AD09,    (unsigned int *)&reg_mux);
+    eim_write_32(IOMUXC_SW_MUX_CTL_PAD_EIM_AD10,    (unsigned int *)&reg_mux);
+    eim_write_32(IOMUXC_SW_MUX_CTL_PAD_EIM_AD11,    (unsigned int *)&reg_mux);
+    eim_write_32(IOMUXC_SW_MUX_CTL_PAD_EIM_AD12,    (unsigned int *)&reg_mux);
+    eim_write_32(IOMUXC_SW_MUX_CTL_PAD_EIM_AD13,    (unsigned int *)&reg_mux);
+    eim_write_32(IOMUXC_SW_MUX_CTL_PAD_EIM_AD14,    (unsigned int *)&reg_mux);
+    eim_write_32(IOMUXC_SW_MUX_CTL_PAD_EIM_AD15,    (unsigned int *)&reg_mux);
+    eim_write_32(IOMUXC_SW_MUX_CTL_PAD_EIM_WAIT_B,  (unsigned int *)&reg_mux);
+    eim_write_32(IOMUXC_SW_MUX_CTL_PAD_EIM_BCLK,    (unsigned int *)&reg_mux);
+
+    // we need to configure all the I/O pads too
+    eim_write_32(IOMUXC_SW_PAD_CTL_PAD_EIM_CS0_B,   (unsigned int *)&reg_pad);
+    eim_write_32(IOMUXC_SW_PAD_CTL_PAD_EIM_OE_B,    (unsigned int *)&reg_pad);
+    eim_write_32(IOMUXC_SW_PAD_CTL_PAD_EIM_RW,      (unsigned int *)&reg_pad);
+    eim_write_32(IOMUXC_SW_PAD_CTL_PAD_EIM_LBA_B,   (unsigned int *)&reg_pad);
+    eim_write_32(IOMUXC_SW_PAD_CTL_PAD_EIM_AD00,    (unsigned int *)&reg_pad);
+    eim_write_32(IOMUXC_SW_PAD_CTL_PAD_EIM_AD01,    (unsigned int *)&reg_pad);
+    eim_write_32(IOMUXC_SW_PAD_CTL_PAD_EIM_AD02,    (unsigned int *)&reg_pad);
+    eim_write_32(IOMUXC_SW_PAD_CTL_PAD_EIM_AD03,    (unsigned int *)&reg_pad);
+    eim_write_32(IOMUXC_SW_PAD_CTL_PAD_EIM_AD04,    (unsigned int *)&reg_pad);
+    eim_write_32(IOMUXC_SW_PAD_CTL_PAD_EIM_AD05,    (unsigned int *)&reg_pad);
+    eim_write_32(IOMUXC_SW_PAD_CTL_PAD_EIM_AD06,    (unsigned int *)&reg_pad);
+    eim_write_32(IOMUXC_SW_PAD_CTL_PAD_EIM_AD07,    (unsigned int *)&reg_pad);
+    eim_write_32(IOMUXC_SW_PAD_CTL_PAD_EIM_AD08,    (unsigned int *)&reg_pad);
+    eim_write_32(IOMUXC_SW_PAD_CTL_PAD_EIM_AD09,    (unsigned int *)&reg_pad);
+    eim_write_32(IOMUXC_SW_PAD_CTL_PAD_EIM_AD10,    (unsigned int *)&reg_pad);
+    eim_write_32(IOMUXC_SW_PAD_CTL_PAD_EIM_AD11,    (unsigned int *)&reg_pad);
+    eim_write_32(IOMUXC_SW_PAD_CTL_PAD_EIM_AD12,    (unsigned int *)&reg_pad);
+    eim_write_32(IOMUXC_SW_PAD_CTL_PAD_EIM_AD13,    (unsigned int *)&reg_pad);
+    eim_write_32(IOMUXC_SW_PAD_CTL_PAD_EIM_AD14,    (unsigned int *)&reg_pad);
+    eim_write_32(IOMUXC_SW_PAD_CTL_PAD_EIM_AD15,    (unsigned int *)&reg_pad);
+    eim_write_32(IOMUXC_SW_PAD_CTL_PAD_EIM_WAIT_B,  (unsigned int *)&reg_pad);
+    eim_write_32(IOMUXC_SW_PAD_CTL_PAD_EIM_BCLK,    (unsigned int *)&reg_pad);
+}
+
+
+//------------------------------------------------------------------------------
+static void _eim_setup_ccm(void)
+//------------------------------------------------------------------------------
+{
+    // create structure
+    struct CCM_CCGR6 ccm_ccgr6;
+
+    // read register
+    eim_read_32(CCM_CCGR6, (unsigned int *)&ccm_ccgr6);
+
+    // modify register
+    ccm_ccgr6.cg0_usboh3        = CCM_CGR_ON_EXCEPT_STOP;
+    ccm_ccgr6.cg1_usdhc1        = CCM_CGR_OFF;
+    ccm_ccgr6.cg2_usdhc2        = CCM_CGR_ON_EXCEPT_STOP;
+    ccm_ccgr6.cg3_usdhc3        = CCM_CGR_ON_EXCEPT_STOP;
+
+    ccm_ccgr6.cg3_usdhc4        = CCM_CGR_OFF;
+    ccm_ccgr6.cg5_eim_slow      = CCM_CGR_ON_EXCEPT_STOP;
+    ccm_ccgr6.cg6_vdoaxiclk     = CCM_CGR_OFF;
+    ccm_ccgr6.cg7_vpu           = CCM_CGR_OFF;
+
+    ccm_ccgr6.cg8_reserved      = 0;
+    ccm_ccgr6.cg9_reserved      = 0;
+    ccm_ccgr6.cg10_reserved     = 0;
+    ccm_ccgr6.cg11_reserved     = 0;
+    ccm_ccgr6.cg12_reserved     = 0;
+    ccm_ccgr6.cg13_reserved     = 0;
+    ccm_ccgr6.cg14_reserved     = 0;
+    ccm_ccgr6.cg15_reserved     = 0;
+
+    // write register
+    eim_write_32(CCM_CCGR6, (unsigned int *)&ccm_ccgr6);
+}
+
+
+//------------------------------------------------------------------------------
+static void _eim_setup_eim(void)
+//------------------------------------------------------------------------------
+{
+    // create structures
+    struct EIM_CS_GCR1  gcr1;
+    struct EIM_CS_GCR2  gcr2;
+    struct EIM_CS_RCR1  rcr1;
+    struct EIM_CS_RCR2  rcr2;
+    struct EIM_CS_WCR1  wcr1;
+    struct EIM_CS_WCR2  wcr2;
+
+    struct EIM_WCR      wcr;
+    struct EIM_WIAR     wiar;
+    //struct EIM_EAR      ear;
+
+    // read all the registers
+    eim_read_32(EIM_CS0GCR1, (unsigned int *)&gcr1);
+    eim_read_32(EIM_CS0GCR2, (unsigned int *)&gcr2);
+    eim_read_32(EIM_CS0RCR1, (unsigned int *)&rcr1);
+    eim_read_32(EIM_CS0RCR2, (unsigned int *)&rcr2);
+    eim_read_32(EIM_CS0WCR1, (unsigned int *)&wcr1);
+    eim_read_32(EIM_CS0WCR2, (unsigned int *)&wcr2);
+
+    eim_read_32(EIM_WCR,    (unsigned int *)&wcr);
+    eim_read_32(EIM_WIAR,   (unsigned int *)&wiar);
+    //eim_read_32(EIM_EAR,    (unsigned int *)&ear);
+
+    // manipulate registers as needed
+    gcr1.csen               = 1;    // chip select is enabled                   |
+    gcr1.swr                = 1;    // write is sync                            |
+    gcr1.srd                = 1;    // read is sync                             |
+    gcr1.mum                = 1;    // address and data are multiplexed         |
+    gcr1.wfl                = 0;    // write latency is not fixed               |
+    gcr1.rfl                = 0;    // read latency is not fixed                |
+    gcr1.cre                = 0;    // CRE signal not needed                    |
+    //gcr1.crep             = x;    // don't care, CRE not used                 |
+    gcr1.bl                 = 4;    // burst length                             | ?
+    gcr1.wc                 = 0;    // write is not continuous                  | ?
+    gcr1.bcd                = 3;    // BCLK divisor is 3+1=4                    |
+    gcr1.bcs                = 1;    // delay from ~CS to BCLK is 1 cycle        |
+    gcr1.dsz                = 1;    // 16 bits per databeat at DATA[15:0]       |
+    gcr1.sp                 = 0;    // supervisor protection is disabled        |
+    gcr1.csrec              = 1;    // ~CS recovery is 1 cycle                  |
+    gcr1.aus                = 1;    // address is not shifted                   |
+    gcr1.gbc                = 1;    // ~CS gap is 1 cycle                       |
+    gcr1.wp                 = 0;    // write protection is not enabled          |
+    //gcr1.psz              = x;    // don't care, page mode is not used        |
+
+    gcr2.adh                = 0;    // address hold duration is 1 cycle         |
+    //gcr2.daps             = x;    // don't care, DTACK is not used            |
+    gcr2.dae                = 0;    // DTACK is not used                        |
+    //gcr2.dap              = x;    // don't care, DTACK is not used            |
+    gcr2.mux16_byp_grant    = 1;    // enable grant mechanism                   | ?
+    gcr2.reserved_3_2       = 0;    // must be 0                                |
+    gcr2.reserved_11_10     = 0;    // must be 0                                |
+    gcr2.reserved_31_13     = 0;    // must be 0                                |
+
+    //rcr1.rcsn             = x;    // don't care in sync mode                  |
+    rcr1.rcsa               = 0;    // no delay for ~CS needed                  |
+    //rcr1.oen              = x;    // don't care in sync mode                  |
+    rcr1.oea                = 0;    // no delay for ~OE needed                  |
+    rcr1.radvn              = 0;    // no delay for ~LBA needed                 |
+    rcr1.ral                = 0;    // clear ~LBA when needed                   |
+    rcr1.radva              = 0;    // no delay for ~LBA needed                 |
+    rcr1.rwsc               = 1;    // one wait state                           |
+    rcr1.reserved_3         = 0;    // must be 0                                |
+    rcr1.reserved_7         = 0;    // must be 0                                |
+    rcr1.reserved_11        = 0;    // must be 0                                |
+    rcr1.reserved_15        = 0;    // must be 0                                |
+    rcr1.reserved_23        = 0;    // must be 0                                |
+    rcr1.reserved_31_30     = 0;    // must be 0                                |
+
+    //rcr2.rben             = x;    // don't care in sync mode                  |
+    rcr2.rbe                = 0;    // BE is disabled                           |
+    //rcr2.rbea             = x;    // don't care when BE is not used           |
+    rcr2.rl                 = 0;    // read latency is 0                        | ?
+    //rcr2.pat              = x;    // don't care when page read is not used    |
+    rcr2.apr                = 0;    // page read mode is not used               |
+    rcr2.reserved_7         = 0;    // must be 0                                |
+    rcr2.reserved_11_10     = 0;    // must be 0                                |
+    rcr2.reserved_31_16     = 0;    // must be 0                                |
+
+    //wcr1.wcsn             = x;    // don't care in sync mode                  |
+    wcr1.wcsa               = 0;    // no delay for ~CS needed                  |
+    //wcr1.wen              = x;    // don't care in sync mode                  |
+    wcr1.wea                = 0;    // no delay for ~WR_N needed                |
+    //wcr1.wben             = x;    // don't care in sync mode                  |
+    //wcr1.wbea             = x;    // don't care in sync mode                  |
+    wcr1.wadvn              = 0;    // no delay for ~LBA needed                 |
+    wcr1.wadva              = 0;    // no delay for ~LBA needed                 |
+    wcr1.wwsc               = 1;    // no wait state in needed                  |
+    wcr1.wbed               = 1;    // BE is disabled                           |
+    wcr1.wal                = 0;    // clear ~LBA when needed                   |
+
+    wcr2.wbcdd              = 0;    // write clock division is not needed       |
+    wcr2.reserved_31_1      = 0;    // must be 0                                |
+
+    wcr.bcm                 = 0;    // clock is only active during access       |
+    //wcr.gbcd              = x;    // don't care when BCM=0                    |
+    wcr.inten               = 0;    // interrupt is not used                    |
+    //wcr.intpol            = x;    // don't care when interrupt is not used    |
+    wcr.wdog_en             = 1;    // watchdog is enabled                      |
+    wcr.wdog_limit          = 00;   // timeout is 128 BCLK cycles               |
+    wcr.reserved_3          = 0;    // must be 0                                |
+    wcr.reserved_7_6        = 0;    // must be 0                                |
+    wcr.reserved_31_11      = 0;    // must be 0                                |
+
+    wiar.ips_req            = 0;    // IPS not needed                           |
+    wiar.ips_ack            = 0;    // IPS not needed                           |
+    //wiar.irq              = x;    // don't touch                              |
+    //wiar.errst            = x;    // don't touch                              |
+    wiar.aclk_en            = 1;    // clock is enabled                         |
+    wiar.reserved_31_5      = 0;    // must be 0                                |
+
+    //ear.error_addr        = x;    // read-only                                |
+
+    // write modified registers
+    eim_write_32(EIM_CS0GCR1, (unsigned int *)&gcr1);
+    eim_write_32(EIM_CS0GCR2, (unsigned int *)&gcr2);
+    eim_write_32(EIM_CS0RCR1, (unsigned int *)&rcr1);
+    eim_write_32(EIM_CS0RCR2, (unsigned int *)&rcr2);
+    eim_write_32(EIM_CS0WCR1, (unsigned int *)&wcr1);
+    eim_write_32(EIM_CS0WCR2, (unsigned int *)&wcr2);
+    eim_write_32(EIM_WCR,     (unsigned int *)&wcr);
+    eim_write_32(EIM_WIAR,    (unsigned int *)&wiar);
+    //eim_write_32(EIM_EAR,     (unsigned int *)&ear);
+}
+
+
+//------------------------------------------------------------------------------
+void eim_write_32(off_t offset, unsigned int *pvalue)
+//------------------------------------------------------------------------------
+{
+    // calculate memory offset
+    unsigned int *ptr = (unsigned int *)_eim_calc_offset(offset);
+
+    // write data to memory
+    memcpy(ptr, pvalue, sizeof(unsigned int));
+}
+
+
+//------------------------------------------------------------------------------
+void eim_read_32(off_t offset, unsigned int *pvalue)
+//------------------------------------------------------------------------------
+{
+    // calculate memory offset
+    unsigned int *ptr = (unsigned int *)_eim_calc_offset(offset);
+
+    // read data from memory
+    memcpy(pvalue, ptr, sizeof(unsigned int));
+}
+
+
+//------------------------------------------------------------------------------
+static off_t _eim_calc_offset(off_t offset)
+//------------------------------------------------------------------------------
+{
+    // calculate starting and ending addresses of currently mapped page
+    off_t offset_low    = mem_base_addr;
+    off_t offset_high   = mem_base_addr + (mem_page_size - 1);
+
+    // make sure that memory is mapped
+    if (mem_map_ptr == MAP_FAILED)
+        _eim_remap_mem(offset);
+
+    // check that offset is in currently mapped page, remap new page otherwise
+    if ((offset < offset_low) || (offset > offset_high))
+        _eim_remap_mem(offset);
+
+    // calculate pointer
+    return (off_t)mem_map_ptr + (offset - mem_base_addr);
+}
+
+
+//------------------------------------------------------------------------------
+static void _eim_remap_mem(off_t offset)
+//------------------------------------------------------------------------------
+{
+    // unmap old memory page if needed
+    if (mem_map_ptr != MAP_FAILED) {
+        if (munmap(mem_map_ptr, mem_page_size) != 0) {
+            printf("ERROR: munmap() failed.\n");
+            exit(EXIT_FAILURE);
+        }
+    }
+
+    // calculate starting address of new page
+    while (offset % mem_page_size)
+        offset--;
+
+    // try to map new memory page
+    mem_map_ptr = mmap(NULL, mem_page_size, PROT_READ | PROT_WRITE,
+                       MAP_SHARED, mem_dev_fd, offset);
+    if (mem_map_ptr == MAP_FAILED) {
+        printf("ERROR: mmap() failed.\n");
+        exit(EXIT_FAILURE);
+    }
+
+    // save last mapped page address
+    mem_base_addr = offset;
+}
+
+
+//------------------------------------------------------------------------------
+// End-of-File
+//------------------------------------------------------------------------------
diff --git a/sw/test-adder/novena-eim.h b/sw/test-adder/novena-eim.h
index fdcf5a5..5a90618 100644
--- a/sw/test-adder/novena-eim.h
+++ b/sw/test-adder/novena-eim.h
@@ -1,297 +1,321 @@
-//------------------------------------------------------------------------------
-// novena-eim.h
-//------------------------------------------------------------------------------
-
-
-//------------------------------------------------------------------------------
-// Defined Values
-//------------------------------------------------------------------------------
-#define MEMORY_DEVICE	"/dev/mem"
-
-
-//------------------------------------------------------------------------------
-// IOMUXC Values
-//------------------------------------------------------------------------------
-#define IOMUXC_MUX_MODE_ALT0			0	// 000
-
-#define IOMUXC_PAD_CTL_SRE_FAST			1	// 1
-#define IOMUXC_PAD_CTL_DSE_33_OHM		7	// 111
-#define IOMUXC_PAD_CTL_SPEED_MEDIUM_10	2	// 10
-#define IOMUXC_PAD_CTL_ODE_DISABLED		0	// 0
-#define IOMUXC_PAD_CTL_PKE_DISABLED		0	// 0
-#define IOMUXC_PAD_CTL_PUE_PULL			1	// 1
-#define IOMUXC_PAD_CTL_PUS_100K_OHM_PU	2	// 10
-#define IOMUXC_PAD_CTL_HYS_DISABLED		0	// 0
-
-//------------------------------------------------------------------------------
-// CCM Values
-//------------------------------------------------------------------------------
-#define CCM_CGR_OFF						0	// 00
-#define CCM_CGR_ON_EXCEPT_STOP			3	// 11
-
-
-//------------------------------------------------------------------------------
-// CPU Registers
-//------------------------------------------------------------------------------
-enum IMX6DQ_REGISTER_OFFSET
-{
-	IOMUXC_SW_MUX_CTL_PAD_EIM_CS0_B		= 0x020E00F8,
-	IOMUXC_SW_MUX_CTL_PAD_EIM_OE_B		= 0x020E0100,
-	IOMUXC_SW_MUX_CTL_PAD_EIM_RW		= 0x020E0104,
-	IOMUXC_SW_MUX_CTL_PAD_EIM_LBA_B		= 0x020E0108,
-	IOMUXC_SW_MUX_CTL_PAD_EIM_AD00		= 0x020E0114,
-	IOMUXC_SW_MUX_CTL_PAD_EIM_AD01		= 0x020E0118,
-	IOMUXC_SW_MUX_CTL_PAD_EIM_AD02		= 0x020E011C,
-	IOMUXC_SW_MUX_CTL_PAD_EIM_AD03		= 0x020E0120,
-	IOMUXC_SW_MUX_CTL_PAD_EIM_AD04		= 0x020E0124,
-	IOMUXC_SW_MUX_CTL_PAD_EIM_AD05		= 0x020E0128,
-	IOMUXC_SW_MUX_CTL_PAD_EIM_AD06		= 0x020E012C,
-	IOMUXC_SW_MUX_CTL_PAD_EIM_AD07		= 0x020E0130,
-	IOMUXC_SW_MUX_CTL_PAD_EIM_AD08		= 0x020E0134,
-	IOMUXC_SW_MUX_CTL_PAD_EIM_AD09		= 0x020E0138,
-	IOMUXC_SW_MUX_CTL_PAD_EIM_AD10		= 0x020E013C,
-	IOMUXC_SW_MUX_CTL_PAD_EIM_AD11		= 0x020E0140,
-	IOMUXC_SW_MUX_CTL_PAD_EIM_AD12		= 0x020E0144,
-	IOMUXC_SW_MUX_CTL_PAD_EIM_AD13		= 0x020E0148,
-	IOMUXC_SW_MUX_CTL_PAD_EIM_AD14		= 0x020E014C,
-	IOMUXC_SW_MUX_CTL_PAD_EIM_AD15		= 0x020E0150,
-	IOMUXC_SW_MUX_CTL_PAD_EIM_WAIT_B	= 0x020E0154,
-	IOMUXC_SW_MUX_CTL_PAD_EIM_BCLK		= 0x020E0158,
-
-	IOMUXC_SW_PAD_CTL_PAD_EIM_CS0_B		= 0x020E040C,
-	IOMUXC_SW_PAD_CTL_PAD_EIM_OE_B		= 0x020E0414,
-	IOMUXC_SW_PAD_CTL_PAD_EIM_RW		= 0x020E0418,
-	IOMUXC_SW_PAD_CTL_PAD_EIM_LBA_B		= 0x020E041C,
-	IOMUXC_SW_PAD_CTL_PAD_EIM_AD00		= 0x020E0428,
-	IOMUXC_SW_PAD_CTL_PAD_EIM_AD01		= 0x020E042C,
-	IOMUXC_SW_PAD_CTL_PAD_EIM_AD02		= 0x020E0430,
-	IOMUXC_SW_PAD_CTL_PAD_EIM_AD03		= 0x020E0434,
-	IOMUXC_SW_PAD_CTL_PAD_EIM_AD04		= 0x020E0438,
-	IOMUXC_SW_PAD_CTL_PAD_EIM_AD05		= 0x020E043C,
-	IOMUXC_SW_PAD_CTL_PAD_EIM_AD06		= 0x020E0440,
-	IOMUXC_SW_PAD_CTL_PAD_EIM_AD07		= 0x020E0444,
-	IOMUXC_SW_PAD_CTL_PAD_EIM_AD08		= 0x020E0448,
-	IOMUXC_SW_PAD_CTL_PAD_EIM_AD09		= 0x020E044C,
-	IOMUXC_SW_PAD_CTL_PAD_EIM_AD10		= 0x020E0450,
-	IOMUXC_SW_PAD_CTL_PAD_EIM_AD11		= 0x020E0454,
-	IOMUXC_SW_PAD_CTL_PAD_EIM_AD12		= 0x020E0458,
-	IOMUXC_SW_PAD_CTL_PAD_EIM_AD13		= 0x020E045C,
-	IOMUXC_SW_PAD_CTL_PAD_EIM_AD14		= 0x020E0460,
-	IOMUXC_SW_PAD_CTL_PAD_EIM_AD15		= 0x020E0464,
-	IOMUXC_SW_PAD_CTL_PAD_EIM_WAIT_B	= 0x020E0468,
-	IOMUXC_SW_PAD_CTL_PAD_EIM_BCLK		= 0x020E046C,
-	
-	CCM_CCGR6							= 0x020C4080,
-	
-	EIM_CS0GCR1							= 0x021B8000,
-	EIM_CS0GCR2							= 0x021B8004,
-	EIM_CS0RCR1							= 0x021B8008,
-	EIM_CS0RCR2							= 0x021B800C,
-	EIM_CS0WCR1							= 0x021B8010,
-	EIM_CS0WCR2							= 0x021B8014,
-
-	EIM_WCR								= 0x021B8090,
-	EIM_WIAR							= 0x021B8094,
-	EIM_EAR								= 0x021B8098,
-	
-	EIM_BASE_ADDR						= 0x08000000
-};
-
-
-//------------------------------------------------------------------------------
-struct IOMUXC_SW_MUX_CTL_PAD_EIM
-//------------------------------------------------------------------------------
-{
-	unsigned int	mux_mode			:  3;
-	unsigned int	reserved_3			:  1;
-	unsigned int	sion				:  1;
-	unsigned int	reserved_31_5		: 27;
-};
-//------------------------------------------------------------------------------
-struct IOMUXC_SW_PAD_CTL_PAD_EIM
-//------------------------------------------------------------------------------
-{
-	unsigned int	sre					: 1;
-	unsigned int	reserved_2_1		: 2;
-	unsigned int	dse					: 3;
-	unsigned int	speed				: 2;
-	unsigned int	reserved_10_8		: 3;
-	unsigned int	ode					: 1;
-	unsigned int	pke					: 1;
-	unsigned int	pue					: 1;
-	unsigned int	pus					: 2;
-	unsigned int	hys					: 1;
-	unsigned int	reserved_31_17		: 15;
-};
-
-
-//------------------------------------------------------------------------------
-struct CCM_CCGR6
-//------------------------------------------------------------------------------
-{
-	unsigned int	cg0_usboh3			: 2;
-	unsigned int	cg1_usdhc1			: 2;
-	unsigned int	cg2_usdhc2			: 2;
-	unsigned int	cg3_usdhc3			: 2;
-	
-	unsigned int	cg3_usdhc4			: 2;
-	unsigned int	cg5_eim_slow		: 2;
-	unsigned int	cg6_vdoaxiclk		: 2;
-	unsigned int	cg7_vpu				: 2;
-	
-	unsigned int	cg8_reserved		: 2;
-	unsigned int	cg9_reserved		: 2;
-	unsigned int	cg10_reserved		: 2;
-	unsigned int	cg11_reserved		: 2;
-	
-	unsigned int	cg12_reserved		: 2;
-	unsigned int	cg13_reserved		: 2;
-	unsigned int	cg14_reserved		: 2;
-	unsigned int	cg15_reserved		: 2;
-};
-
-
-//------------------------------------------------------------------------------
-struct EIM_CS_GCR1
-//------------------------------------------------------------------------------
-{
-	unsigned int	csen				: 1;
-	unsigned int	swr					: 1;
-	unsigned int	srd					: 1;
-	unsigned int	mum					: 1;
-	unsigned int	wfl					: 1;
-	unsigned int	rfl					: 1;
-	unsigned int	cre					: 1;
-	unsigned int	crep				: 1;
-	unsigned int	bl					: 3;
-	unsigned int	wc					: 1;
-	unsigned int	bcd					: 2;
-	unsigned int	bcs					: 2;
-	unsigned int	dsz					: 3;
-	unsigned int	sp					: 1;
-	unsigned int	csrec				: 3;
-	unsigned int	aus					: 1;
-	unsigned int	gbc					: 3;
-	unsigned int	wp					: 1;
-	unsigned int	psz					: 4;
-};
-//------------------------------------------------------------------------------
-struct EIM_CS_GCR2
-//------------------------------------------------------------------------------
-{
-	unsigned int	adh					:  2;
-	unsigned int 	reserved_3_2		:  2;
-	unsigned int	daps				:  4;
-	unsigned int	dae					:  1;
-	unsigned int	dap					:  1;
-	unsigned int	reserved_11_10		:  2;
-	unsigned int	mux16_byp_grant		:  1;
-	unsigned int	reserved_31_13		: 19;
-};
-//------------------------------------------------------------------------------
-struct EIM_CS_RCR1
-//------------------------------------------------------------------------------
-{
-	unsigned int	rcsn				: 3;
-	unsigned int	reserved_3			: 1;
-	unsigned int	rcsa				: 3;
-	unsigned int	reserved_7			: 1;
-	unsigned int	oen					: 3;
-	unsigned int	reserved_11			: 1;
-	unsigned int	oea					: 3;
-	unsigned int	reserved_15			: 1;
-	unsigned int	radvn				: 3;
-	unsigned int	ral					: 1;
-	unsigned int	radva				: 3;
-	unsigned int	reserved_23			: 1;
-	unsigned int	rwsc				: 6;
-	unsigned int	reserved_31_30		: 2;
-};
-//------------------------------------------------------------------------------
-struct EIM_CS_RCR2
-//------------------------------------------------------------------------------
-{
-	unsigned int	rben				:  3;
-	unsigned int	rbe					:  1;
-	unsigned int	rbea				:  3;
-	unsigned int	reserved_7			:  1;
-	unsigned int	rl					:  2;
-	unsigned int	reserved_11_10		:  2;
-	unsigned int	pat					:  3;
-	unsigned int	apr					:  1;
-	unsigned int	reserved_31_16		: 16;
-};
-//------------------------------------------------------------------------------
-struct EIM_CS_WCR1
-//------------------------------------------------------------------------------
-{
-	unsigned int	wcsn				: 3;
-	unsigned int 	wcsa				: 3;
-	unsigned int	wen					: 3;
-	unsigned int	wea					: 3;
-	unsigned int 	wben				: 3;
-	unsigned int	wbea				: 3;
-	unsigned int	wadvn				: 3;
-	unsigned int	wadva				: 3;
-	unsigned int	wwsc				: 6;
-	unsigned int	wbed				: 1;
-	unsigned int	wal					: 1;
-};
-//------------------------------------------------------------------------------
-struct EIM_CS_WCR2
-//------------------------------------------------------------------------------
-{
-	unsigned int	wbcdd				:  1;
-	unsigned int	reserved_31_1		: 31;
-};
-//------------------------------------------------------------------------------
-struct EIM_WCR
-//------------------------------------------------------------------------------
-{
-	unsigned int	bcm					:  1;
-	unsigned int	gbcd				:  2;
-	unsigned int	reserved_3			:  1;
-	unsigned int	inten				:  1;
-	unsigned int	intpol				:  1;
-	unsigned int	reserved_7_6		:  2;
-	unsigned int	wdog_en				:  1;
-	unsigned int	wdog_limit			:  2;
-	unsigned int	reserved_31_11		: 21;
-};
-//------------------------------------------------------------------------------
-struct EIM_WIAR
-//------------------------------------------------------------------------------
-{
-	unsigned int	ips_req				:  1;
-	unsigned int	ips_ack				:  1;
-	unsigned int	irq					:  1;
-	unsigned int	errst				:  1;
-	unsigned int	aclk_en				:  1;
-	unsigned int	reserved_31_5		: 27;
-};
-//------------------------------------------------------------------------------
-struct EIM_EAR
-//------------------------------------------------------------------------------
-{
-	unsigned int	error_addr			: 32;
-};
-
-
-//------------------------------------------------------------------------------
-// Prototypes
-//------------------------------------------------------------------------------
-int		eim_setup			();
-void	eim_write_32		(off_t, unsigned int *);
-void	eim_read_32			(off_t, unsigned int *);
-
-void	_eim_setup_iomuxc	();
-void	_eim_setup_ccm		();
-void	_eim_setup_eim		();
-void	_eim_cleanup		();
-off_t	_eim_calc_offset	(off_t);
-void	_eim_remap_mem		(off_t);
-
-
-//------------------------------------------------------------------------------
-// End-of-File
-//------------------------------------------------------------------------------
+/*
+ * novena-eim.h
+ * ------------
+ * This module contains the user interface to the Novena EIM bus.
+ *
+ * Author: Pavel Shatov
+ * Copyright (c) 2015, NORDUnet A/S All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ *
+ * - Neither the name of the NORDUnet nor the names of its contributors may
+ *   be used to endorse or promote products derived from this software
+ *   without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+ * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+ * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+//------------------------------------------------------------------------------
+// Defined Values
+//------------------------------------------------------------------------------
+#define MEMORY_DEVICE   "/dev/mem"
+
+
+//------------------------------------------------------------------------------
+// IOMUXC Values
+//------------------------------------------------------------------------------
+#define IOMUXC_MUX_MODE_ALT0            0   // 000
+
+#define IOMUXC_PAD_CTL_SRE_FAST         1   // 1
+#define IOMUXC_PAD_CTL_DSE_33_OHM       7   // 111
+#define IOMUXC_PAD_CTL_SPEED_MEDIUM_10  2   // 10
+#define IOMUXC_PAD_CTL_ODE_DISABLED     0   // 0
+#define IOMUXC_PAD_CTL_PKE_DISABLED     0   // 0
+#define IOMUXC_PAD_CTL_PUE_PULL         1   // 1
+#define IOMUXC_PAD_CTL_PUS_100K_OHM_PU  2   // 10
+#define IOMUXC_PAD_CTL_HYS_DISABLED     0   // 0
+
+//------------------------------------------------------------------------------
+// CCM Values
+//------------------------------------------------------------------------------
+#define CCM_CGR_OFF                     0   // 00
+#define CCM_CGR_ON_EXCEPT_STOP          3   // 11
+
+
+//------------------------------------------------------------------------------
+// CPU Registers
+//------------------------------------------------------------------------------
+enum IMX6DQ_REGISTER_OFFSET
+{
+    IOMUXC_SW_MUX_CTL_PAD_EIM_CS0_B     = 0x020E00F8,
+    IOMUXC_SW_MUX_CTL_PAD_EIM_OE_B      = 0x020E0100,
+    IOMUXC_SW_MUX_CTL_PAD_EIM_RW        = 0x020E0104,
+    IOMUXC_SW_MUX_CTL_PAD_EIM_LBA_B     = 0x020E0108,
+    IOMUXC_SW_MUX_CTL_PAD_EIM_AD00      = 0x020E0114,
+    IOMUXC_SW_MUX_CTL_PAD_EIM_AD01      = 0x020E0118,
+    IOMUXC_SW_MUX_CTL_PAD_EIM_AD02      = 0x020E011C,
+    IOMUXC_SW_MUX_CTL_PAD_EIM_AD03      = 0x020E0120,
+    IOMUXC_SW_MUX_CTL_PAD_EIM_AD04      = 0x020E0124,
+    IOMUXC_SW_MUX_CTL_PAD_EIM_AD05      = 0x020E0128,
+    IOMUXC_SW_MUX_CTL_PAD_EIM_AD06      = 0x020E012C,
+    IOMUXC_SW_MUX_CTL_PAD_EIM_AD07      = 0x020E0130,
+    IOMUXC_SW_MUX_CTL_PAD_EIM_AD08      = 0x020E0134,
+    IOMUXC_SW_MUX_CTL_PAD_EIM_AD09      = 0x020E0138,
+    IOMUXC_SW_MUX_CTL_PAD_EIM_AD10      = 0x020E013C,
+    IOMUXC_SW_MUX_CTL_PAD_EIM_AD11      = 0x020E0140,
+    IOMUXC_SW_MUX_CTL_PAD_EIM_AD12      = 0x020E0144,
+    IOMUXC_SW_MUX_CTL_PAD_EIM_AD13      = 0x020E0148,
+    IOMUXC_SW_MUX_CTL_PAD_EIM_AD14      = 0x020E014C,
+    IOMUXC_SW_MUX_CTL_PAD_EIM_AD15      = 0x020E0150,
+    IOMUXC_SW_MUX_CTL_PAD_EIM_WAIT_B    = 0x020E0154,
+    IOMUXC_SW_MUX_CTL_PAD_EIM_BCLK      = 0x020E0158,
+
+    IOMUXC_SW_PAD_CTL_PAD_EIM_CS0_B     = 0x020E040C,
+    IOMUXC_SW_PAD_CTL_PAD_EIM_OE_B      = 0x020E0414,
+    IOMUXC_SW_PAD_CTL_PAD_EIM_RW        = 0x020E0418,
+    IOMUXC_SW_PAD_CTL_PAD_EIM_LBA_B     = 0x020E041C,
+    IOMUXC_SW_PAD_CTL_PAD_EIM_AD00      = 0x020E0428,
+    IOMUXC_SW_PAD_CTL_PAD_EIM_AD01      = 0x020E042C,
+    IOMUXC_SW_PAD_CTL_PAD_EIM_AD02      = 0x020E0430,
+    IOMUXC_SW_PAD_CTL_PAD_EIM_AD03      = 0x020E0434,
+    IOMUXC_SW_PAD_CTL_PAD_EIM_AD04      = 0x020E0438,
+    IOMUXC_SW_PAD_CTL_PAD_EIM_AD05      = 0x020E043C,
+    IOMUXC_SW_PAD_CTL_PAD_EIM_AD06      = 0x020E0440,
+    IOMUXC_SW_PAD_CTL_PAD_EIM_AD07      = 0x020E0444,
+    IOMUXC_SW_PAD_CTL_PAD_EIM_AD08      = 0x020E0448,
+    IOMUXC_SW_PAD_CTL_PAD_EIM_AD09      = 0x020E044C,
+    IOMUXC_SW_PAD_CTL_PAD_EIM_AD10      = 0x020E0450,
+    IOMUXC_SW_PAD_CTL_PAD_EIM_AD11      = 0x020E0454,
+    IOMUXC_SW_PAD_CTL_PAD_EIM_AD12      = 0x020E0458,
+    IOMUXC_SW_PAD_CTL_PAD_EIM_AD13      = 0x020E045C,
+    IOMUXC_SW_PAD_CTL_PAD_EIM_AD14      = 0x020E0460,
+    IOMUXC_SW_PAD_CTL_PAD_EIM_AD15      = 0x020E0464,
+    IOMUXC_SW_PAD_CTL_PAD_EIM_WAIT_B    = 0x020E0468,
+    IOMUXC_SW_PAD_CTL_PAD_EIM_BCLK      = 0x020E046C,
+
+    CCM_CCGR6                           = 0x020C4080,
+
+    EIM_CS0GCR1                         = 0x021B8000,
+    EIM_CS0GCR2                         = 0x021B8004,
+    EIM_CS0RCR1                         = 0x021B8008,
+    EIM_CS0RCR2                         = 0x021B800C,
+    EIM_CS0WCR1                         = 0x021B8010,
+    EIM_CS0WCR2                         = 0x021B8014,
+
+    EIM_WCR                             = 0x021B8090,
+    EIM_WIAR                            = 0x021B8094,
+    EIM_EAR                             = 0x021B8098,
+
+    EIM_BASE_ADDR                       = 0x08000000
+};
+
+
+//------------------------------------------------------------------------------
+struct IOMUXC_SW_MUX_CTL_PAD_EIM
+//------------------------------------------------------------------------------
+{
+    unsigned int    mux_mode            :  3;
+    unsigned int    reserved_3          :  1;
+    unsigned int    sion                :  1;
+    unsigned int    reserved_31_5       : 27;
+};
+//------------------------------------------------------------------------------
+struct IOMUXC_SW_PAD_CTL_PAD_EIM
+//------------------------------------------------------------------------------
+{
+    unsigned int    sre                 : 1;
+    unsigned int    reserved_2_1        : 2;
+    unsigned int    dse                 : 3;
+    unsigned int    speed               : 2;
+    unsigned int    reserved_10_8       : 3;
+    unsigned int    ode                 : 1;
+    unsigned int    pke                 : 1;
+    unsigned int    pue                 : 1;
+    unsigned int    pus                 : 2;
+    unsigned int    hys                 : 1;
+    unsigned int    reserved_31_17      : 15;
+};
+
+
+//------------------------------------------------------------------------------
+struct CCM_CCGR6
+//------------------------------------------------------------------------------
+{
+    unsigned int    cg0_usboh3          : 2;
+    unsigned int    cg1_usdhc1          : 2;
+    unsigned int    cg2_usdhc2          : 2;
+    unsigned int    cg3_usdhc3          : 2;
+
+    unsigned int    cg3_usdhc4          : 2;
+    unsigned int    cg5_eim_slow        : 2;
+    unsigned int    cg6_vdoaxiclk       : 2;
+    unsigned int    cg7_vpu             : 2;
+
+    unsigned int    cg8_reserved        : 2;
+    unsigned int    cg9_reserved        : 2;
+    unsigned int    cg10_reserved       : 2;
+    unsigned int    cg11_reserved       : 2;
+
+    unsigned int    cg12_reserved       : 2;
+    unsigned int    cg13_reserved       : 2;
+    unsigned int    cg14_reserved       : 2;
+    unsigned int    cg15_reserved       : 2;
+};
+
+
+//------------------------------------------------------------------------------
+struct EIM_CS_GCR1
+//------------------------------------------------------------------------------
+{
+    unsigned int    csen                : 1;
+    unsigned int    swr                 : 1;
+    unsigned int    srd                 : 1;
+    unsigned int    mum                 : 1;
+    unsigned int    wfl                 : 1;
+    unsigned int    rfl                 : 1;
+    unsigned int    cre                 : 1;
+    unsigned int    crep                : 1;
+    unsigned int    bl                  : 3;
+    unsigned int    wc                  : 1;
+    unsigned int    bcd                 : 2;
+    unsigned int    bcs                 : 2;
+    unsigned int    dsz                 : 3;
+    unsigned int    sp                  : 1;
+    unsigned int    csrec               : 3;
+    unsigned int    aus                 : 1;
+    unsigned int    gbc                 : 3;
+    unsigned int    wp                  : 1;
+    unsigned int    psz                 : 4;
+};
+//------------------------------------------------------------------------------
+struct EIM_CS_GCR2
+//------------------------------------------------------------------------------
+{
+    unsigned int    adh                 :  2;
+    unsigned int    reserved_3_2        :  2;
+    unsigned int    daps                :  4;
+    unsigned int    dae                 :  1;
+    unsigned int    dap                 :  1;
+    unsigned int    reserved_11_10      :  2;
+    unsigned int    mux16_byp_grant     :  1;
+    unsigned int    reserved_31_13      : 19;
+};
+//------------------------------------------------------------------------------
+struct EIM_CS_RCR1
+//------------------------------------------------------------------------------
+{
+    unsigned int    rcsn                : 3;
+    unsigned int    reserved_3          : 1;
+    unsigned int    rcsa                : 3;
+    unsigned int    reserved_7          : 1;
+    unsigned int    oen                 : 3;
+    unsigned int    reserved_11         : 1;
+    unsigned int    oea                 : 3;
+    unsigned int    reserved_15         : 1;
+    unsigned int    radvn               : 3;
+    unsigned int    ral                 : 1;
+    unsigned int    radva               : 3;
+    unsigned int    reserved_23         : 1;
+    unsigned int    rwsc                : 6;
+    unsigned int    reserved_31_30      : 2;
+};
+//------------------------------------------------------------------------------
+struct EIM_CS_RCR2
+//------------------------------------------------------------------------------
+{
+    unsigned int    rben                :  3;
+    unsigned int    rbe                 :  1;
+    unsigned int    rbea                :  3;
+    unsigned int    reserved_7          :  1;
+    unsigned int    rl                  :  2;
+    unsigned int    reserved_11_10      :  2;
+    unsigned int    pat                 :  3;
+    unsigned int    apr                 :  1;
+    unsigned int    reserved_31_16      : 16;
+};
+//------------------------------------------------------------------------------
+struct EIM_CS_WCR1
+//------------------------------------------------------------------------------
+{
+    unsigned int    wcsn                : 3;
+    unsigned int    wcsa                : 3;
+    unsigned int    wen                 : 3;
+    unsigned int    wea                 : 3;
+    unsigned int    wben                : 3;
+    unsigned int    wbea                : 3;
+    unsigned int    wadvn               : 3;
+    unsigned int    wadva               : 3;
+    unsigned int    wwsc                : 6;
+    unsigned int    wbed                : 1;
+    unsigned int    wal                 : 1;
+};
+//------------------------------------------------------------------------------
+struct EIM_CS_WCR2
+//------------------------------------------------------------------------------
+{
+    unsigned int    wbcdd               :  1;
+    unsigned int    reserved_31_1       : 31;
+};
+//------------------------------------------------------------------------------
+struct EIM_WCR
+//------------------------------------------------------------------------------
+{
+    unsigned int    bcm                 :  1;
+    unsigned int    gbcd                :  2;
+    unsigned int    reserved_3          :  1;
+    unsigned int    inten               :  1;
+    unsigned int    intpol              :  1;
+    unsigned int    reserved_7_6        :  2;
+    unsigned int    wdog_en             :  1;
+    unsigned int    wdog_limit          :  2;
+    unsigned int    reserved_31_11      : 21;
+};
+//------------------------------------------------------------------------------
+struct EIM_WIAR
+//------------------------------------------------------------------------------
+{
+    unsigned int    ips_req             :  1;
+    unsigned int    ips_ack             :  1;
+    unsigned int    irq                 :  1;
+    unsigned int    errst               :  1;
+    unsigned int    aclk_en             :  1;
+    unsigned int    reserved_31_5       : 27;
+};
+//------------------------------------------------------------------------------
+struct EIM_EAR
+//------------------------------------------------------------------------------
+{
+    unsigned int    error_addr          : 32;
+};
+
+
+//------------------------------------------------------------------------------
+// Prototypes
+//------------------------------------------------------------------------------
+int     eim_setup           (void);
+void    eim_write_32        (off_t, unsigned int *);
+void    eim_read_32         (off_t, unsigned int *);
+
+
+//------------------------------------------------------------------------------
+// End-of-File
+//------------------------------------------------------------------------------
diff --git a/sw/test-adder/test-adder.c b/sw/test-adder/test-adder.c
index 70415d8..88d4353 100644
--- a/sw/test-adder/test-adder.c
+++ b/sw/test-adder/test-adder.c
@@ -1,6 +1,38 @@
-//------------------------------------------------------------------------------
-// setup-eim.c
-//------------------------------------------------------------------------------
+/*
+ * test-adder.c
+ * ------------
+ * This program tests the Novena EIM interface by repeatedly writing
+ * two 32-bit values to the FPGA, and reading back the sum.
+ *
+ * Author: Pavel Shatov
+ * Copyright (c) 2015, NORDUnet A/S All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ *
+ * - Neither the name of the NORDUnet nor the names of its contributors may
+ *   be used to endorse or promote products derived from this software
+ *   without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+ * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+ * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
 
 
 //------------------------------------------------------------------------------
@@ -14,70 +46,74 @@
 //------------------------------------------------------------------------------
 // Demo Adder
 //------------------------------------------------------------------------------
-#define DEMO_ADDER_BASE_ADDR	(0x3210)
-#define DEMO_ADDER_REG_X		(EIM_BASE_ADDR + DEMO_ADDER_BASE_ADDR + (0<<2))
-#define DEMO_ADDER_REG_Y		(EIM_BASE_ADDR + DEMO_ADDER_BASE_ADDR + (1<<2))
-#define DEMO_ADDER_REG_Z		(EIM_BASE_ADDR + DEMO_ADDER_BASE_ADDR + (2<<2))
-#define DEMO_ADDER_REG_SC		(EIM_BASE_ADDR + DEMO_ADDER_BASE_ADDR + (3<<2))
+#define DEMO_ADDER_BASE_ADDR    (0x3210)
+#define DEMO_ADDER_REG_X        (EIM_BASE_ADDR + DEMO_ADDER_BASE_ADDR + (0<<2))
+#define DEMO_ADDER_REG_Y        (EIM_BASE_ADDR + DEMO_ADDER_BASE_ADDR + (1<<2))
+#define DEMO_ADDER_REG_Z        (EIM_BASE_ADDR + DEMO_ADDER_BASE_ADDR + (2<<2))
+#define DEMO_ADDER_REG_SC       (EIM_BASE_ADDR + DEMO_ADDER_BASE_ADDR + (3<<2))
 
 
 //------------------------------------------------------------------------------
 // Prototypes
 //------------------------------------------------------------------------------
-unsigned int	demo_adder_test_round	(unsigned int, unsigned int);
-unsigned int	lfsr_next_x				(unsigned int);
-unsigned int	lfsr_next_y				(unsigned int);
+unsigned int    demo_adder_test_round   (unsigned int, unsigned int);
+unsigned int    lfsr_next_x             (unsigned int);
+unsigned int    lfsr_next_y             (unsigned int);
 
 
 //------------------------------------------------------------------------------
 // Testing Parameters
 //------------------------------------------------------------------------------
-const int	NUM_TEST_ROUNDS		= 10000;
-const int	PRINT_XYZ_VALUES	= 1;
+const int   NUM_TEST_ROUNDS     = 10000;
+const int   PRINT_XYZ_VALUES    = 1;
 
 
 //------------------------------------------------------------------------------
-int main()
+int main(void)
 //------------------------------------------------------------------------------
 {
-		// try to setup eim (return value should be 1)
-	printf("Configuring EIM .. ");
-	int ok = eim_setup();
-	if (ok < 1)
-	{	printf("ERROR\n");
-		return EXIT_FAILURE;
-	}
-	else printf("OK\n");
-	
-		// run test
-	int i;
-	unsigned int x = 0x12341234, y = 0xABCDABCD, zyx;
-	printf("Testing started.\n");
-	for (i=0; i<NUM_TEST_ROUNDS; i++)
-	{	
-			// run another round
-		unsigned int z = demo_adder_test_round(x, y);
-		
-			// calculate correct answer
-		zyx = x + y;
-
-			// check result
-		if (z != zyx)
-		{	printf("ERROR: round %10d of %10d: x == 0x%08X, y == 0x%08X, z == 0x%08X [z should be 0x%08X]\n", i+1, NUM_TEST_ROUNDS, x, y, z, zyx);
-			exit(EXIT_FAILURE);
-		}
-		else if (PRINT_XYZ_VALUES) printf("OK: round %10d of %10d: x == 0x%08X, y == 0x%08X, z == 0x%08X\n", i+1, NUM_TEST_ROUNDS, x, y, z);
-		
-			// update input values
-		x = lfsr_next_x(x);
-		y = lfsr_next_x(y);
-	}
-	
-		// ok
-	printf("Testing completed successfully.\n");
-	
-		// done
-	return EXIT_SUCCESS;
+    int i;
+    unsigned int x = 0x12341234, y = 0xABCDABCD, zyx;
+
+    // try to setup eim (return value should be 1)
+    printf("Configuring EIM .. ");
+    if (eim_setup() < 1) {
+        printf("ERROR\n");
+        return EXIT_FAILURE;
+    }
+    else
+        printf("OK\n");
+
+    // run test
+    printf("Testing started.\n");
+    for (i=0; i<NUM_TEST_ROUNDS; i++) {
+        // run another round
+        unsigned int z = demo_adder_test_round(x, y);
+
+        // calculate correct answer
+        zyx = x + y;
+
+        // check result
+        if (z != zyx) {
+            printf("ERROR: round %10d of %10d: x == 0x%08X, y == 0x%08X, "
+                   "z == 0x%08X [z should be 0x%08X]\n",
+                   i+1, NUM_TEST_ROUNDS, x, y, z, zyx);
+            exit(EXIT_FAILURE);
+        }
+        else if (PRINT_XYZ_VALUES)
+            printf("OK: round %10d of %10d: x == 0x%08X, y == 0x%08X, "
+                   "z == 0x%08X\n", i+1, NUM_TEST_ROUNDS, x, y, z);
+
+        // update input values
+        x = lfsr_next_x(x);
+        y = lfsr_next_x(y);
+    }
+
+    // ok
+    printf("Testing completed successfully.\n");
+
+    // done
+    return EXIT_SUCCESS;
 }
 
 
@@ -85,44 +121,45 @@ int main()
 unsigned int demo_adder_test_round(unsigned int x, unsigned int y)
 //------------------------------------------------------------------------------
 {
-		// write x
-	eim_write_32(DEMO_ADDER_REG_X, &x);
-	
-		// write y
-	eim_write_32(DEMO_ADDER_REG_Y, &y);
-	
-		/* To make adder calculate something we need to change its control register,
-		 * so we read it, increment and write back. Control register is in the lower 16 bits.
-		 */
-	unsigned int ctl;
-	eim_read_32(DEMO_ADDER_REG_SC, &ctl);
-	ctl += 1;
-	ctl &= 0x0000FFFF;
-	eim_write_32(DEMO_ADDER_REG_SC, &ctl);
-	
-		/* When adder is done, it will write new control value into its status register. Adder has 1-cycle latency
-		 * which is very small, we don't even need to poll, just check that status was updated. Status register is
-		 * in the upper 16 bits.
-		 */
-	unsigned int sts;
-	eim_read_32(DEMO_ADDER_REG_SC, &sts);
-	sts >>= 16;
-	if (sts != ctl)
-	{	printf("ERROR: Adder timeout!\n");
-		exit(EXIT_FAILURE);
-	}
-
-		// read z
-	unsigned int z;
-	eim_read_32(DEMO_ADDER_REG_Z, &z);
-	
-		// uncomment to trigger an error
-	/**
-	z++;
-	**/
-	
-		// done
-	return z;
+    unsigned int ctl;
+    unsigned int sts;
+    unsigned int z;
+
+    // write x
+    eim_write_32(DEMO_ADDER_REG_X, &x);
+
+    // write y
+    eim_write_32(DEMO_ADDER_REG_Y, &y);
+
+    /* To make adder calculate something we need to change its control
+     * register, so we read it, increment and write back. Control register is
+     * in the lower 16 bits.
+     */
+    eim_read_32(DEMO_ADDER_REG_SC, &ctl);
+    ctl += 1;
+    ctl &= 0x0000FFFF;
+    eim_write_32(DEMO_ADDER_REG_SC, &ctl);
+
+    /* When adder is done, it will write new control value into its status
+     * register. Adder has 1-cycle latency which is very small, we don't even
+     * need to poll, just check that status was updated. Status register is in
+     * the upper 16 bits.
+     */
+    eim_read_32(DEMO_ADDER_REG_SC, &sts);
+    sts >>= 16;
+    if (sts != ctl)
+    {   printf("ERROR: Adder timeout!\n");
+        exit(EXIT_FAILURE);
+    }
+
+    // read z
+    eim_read_32(DEMO_ADDER_REG_Z, &z);
+
+    // uncomment to trigger an error
+    //z++;
+
+    // done
+    return z;
 }
 
 
@@ -130,36 +167,36 @@ unsigned int demo_adder_test_round(unsigned int x, unsigned int y)
 unsigned int lfsr_next_x(unsigned int value)
 //------------------------------------------------------------------------------
 {
-	//
-	// [32, 31, 29, 28, 27, 25, 24, 23, 21, 19, 17, 14, 10, 6, 4, 2]
-	//   0   1   3   4   5   7   8   9  11  13  15  18  22 24 28 30
-	//
-	
-	unsigned int carry = 0;
-
-	carry ^= (value >>  0);
-	carry ^= (value >>  1);
-	carry ^= (value >>  3);
-	carry ^= (value >>  4);
-
-	carry ^= (value >>  5);
-	carry ^= (value >>  7);
-	carry ^= (value >>  8);
-	carry ^= (value >>  9);
-
-	carry ^= (value >> 11);
-	carry ^= (value >> 13);
-	carry ^= (value >> 15);
-	carry ^= (value >> 18);
-
-	carry ^= (value >> 22);
-	carry ^= (value >> 24);
-	carry ^= (value >> 28);
-	carry ^= (value >> 30);
-
-	value >>= 1, value |= (carry << 31);
-
-	return value;
+    //
+    // [32, 31, 29, 28, 27, 25, 24, 23, 21, 19, 17, 14, 10, 6, 4, 2]
+    //   0   1   3   4   5   7   8   9  11  13  15  18  22 24 28 30
+    //
+
+    unsigned int carry = 0;
+
+    carry ^= (value >>  0);
+    carry ^= (value >>  1);
+    carry ^= (value >>  3);
+    carry ^= (value >>  4);
+
+    carry ^= (value >>  5);
+    carry ^= (value >>  7);
+    carry ^= (value >>  8);
+    carry ^= (value >>  9);
+
+    carry ^= (value >> 11);
+    carry ^= (value >> 13);
+    carry ^= (value >> 15);
+    carry ^= (value >> 18);
+
+    carry ^= (value >> 22);
+    carry ^= (value >> 24);
+    carry ^= (value >> 28);
+    carry ^= (value >> 30);
+
+    value >>= 1, value |= (carry << 31);
+
+    return value;
 }
 
 
@@ -167,37 +204,37 @@ unsigned int lfsr_next_x(unsigned int value)
 unsigned int lfsr_next_y(unsigned int value)
 //------------------------------------------------------------------------------
 {
-	//
-	// [32, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 1]
-	//   0  15  16  17  18  19  20  21  22 23 24 25 26 27 28 31
-	//
-	
-	unsigned int carry = 0;
-
-	carry ^= (value >>  0);
-	carry ^= (value >> 15);
-	carry ^= (value >> 16);
-	carry ^= (value >> 17);
-
-	carry ^= (value >> 18);
-	carry ^= (value >> 19);
-	carry ^= (value >> 20);
-	carry ^= (value >> 21);
-
-	carry ^= (value >> 22);
-	carry ^= (value >> 23);
-	carry ^= (value >> 24);
-	carry ^= (value >> 25);
-
-	carry ^= (value >> 26);
-	carry ^= (value >> 27);
-	carry ^= (value >> 28);
-	carry ^= (value >> 31);
-
-	value >>= 1, value |= (carry << 31);
-
-	return value;
-}	
+    //
+    // [32, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 1]
+    //   0  15  16  17  18  19  20  21  22 23 24 25 26 27 28 31
+    //
+
+    unsigned int carry = 0;
+
+    carry ^= (value >>  0);
+    carry ^= (value >> 15);
+    carry ^= (value >> 16);
+    carry ^= (value >> 17);
+
+    carry ^= (value >> 18);
+    carry ^= (value >> 19);
+    carry ^= (value >> 20);
+    carry ^= (value >> 21);
+
+    carry ^= (value >> 22);
+    carry ^= (value >> 23);
+    carry ^= (value >> 24);
+    carry ^= (value >> 25);
+
+    carry ^= (value >> 26);
+    carry ^= (value >> 27);
+    carry ^= (value >> 28);
+    carry ^= (value >> 31);
+
+    value >>= 1, value |= (carry << 31);
+
+    return value;
+}
 
 
 



More information about the Commits mailing list