[Cryptech-Commits] [test/novena_base] 03/04: Adding initial version of the sw parts of the baseline.

git at cryptech.is git at cryptech.is
Sat Jan 31 07:59:44 UTC 2015


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

joachim at secworks.se pushed a commit to branch master
in repository test/novena_base.

commit 7a9e34eadc7db72f43d2566d0595e7de5e4a18ab
Author: Joachim Strömbergson <joachim at secworks.se>
Date:   Sat Jan 31 08:58:23 2015 +0100

    Adding initial version of the sw parts of the baseline.
---
 sw/test-adder/Makefile     |  11 ++
 sw/test-adder/novena-eim.c | 406 +++++++++++++++++++++++++++++++++++++++++++++
 sw/test-adder/novena-eim.h | 297 +++++++++++++++++++++++++++++++++
 sw/test-adder/test-adder.c | 206 +++++++++++++++++++++++
 4 files changed, 920 insertions(+)

diff --git a/sw/test-adder/Makefile b/sw/test-adder/Makefile
new file mode 100755
index 0000000..5271b70
--- /dev/null
+++ b/sw/test-adder/Makefile
@@ -0,0 +1,11 @@
+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
+	
+clean:
+	rm -f *.o test-adder
diff --git a/sw/test-adder/novena-eim.c b/sw/test-adder/novena-eim.c
new file mode 100755
index 0000000..9ea76ef
--- /dev/null
+++ b/sw/test-adder/novena-eim.c
@@ -0,0 +1,406 @@
+//------------------------------------------------------------------------------
+// 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
+//------------------------------------------------------------------------------
diff --git a/sw/test-adder/novena-eim.h b/sw/test-adder/novena-eim.h
new file mode 100755
index 0000000..fdcf5a5
--- /dev/null
+++ b/sw/test-adder/novena-eim.h
@@ -0,0 +1,297 @@
+//------------------------------------------------------------------------------
+// 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
+//------------------------------------------------------------------------------
diff --git a/sw/test-adder/test-adder.c b/sw/test-adder/test-adder.c
new file mode 100755
index 0000000..70415d8
--- /dev/null
+++ b/sw/test-adder/test-adder.c
@@ -0,0 +1,206 @@
+//------------------------------------------------------------------------------
+// setup-eim.c
+//------------------------------------------------------------------------------
+
+
+//------------------------------------------------------------------------------
+// Headers
+//------------------------------------------------------------------------------
+#include <stdio.h>
+#include <stdlib.h>
+#include "novena-eim.h"
+
+
+//------------------------------------------------------------------------------
+// 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))
+
+
+//------------------------------------------------------------------------------
+// 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);
+
+
+//------------------------------------------------------------------------------
+// Testing Parameters
+//------------------------------------------------------------------------------
+const int	NUM_TEST_ROUNDS		= 10000;
+const int	PRINT_XYZ_VALUES	= 1;
+
+
+//------------------------------------------------------------------------------
+int main()
+//------------------------------------------------------------------------------
+{
+		// 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;
+}
+
+
+//------------------------------------------------------------------------------
+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 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;
+}
+
+
+//------------------------------------------------------------------------------
+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;
+}	
+
+
+
+//------------------------------------------------------------------------------
+// End-of-File
+//------------------------------------------------------------------------------



More information about the Commits mailing list