diff --git a/board/actel/sf2-dev-kit/Makefile b/board/actel/sf2-dev-kit/Makefile
index ae566a0511cd55198fa311f81295fbeedb152128..934808d663ccd7695225a6b3c20ccde1478f11c6 100644
--- a/board/actel/sf2-dev-kit/Makefile
+++ b/board/actel/sf2-dev-kit/Makefile
@@ -26,7 +26,7 @@ include $(TOPDIR)/config.mk
 
 LIB	= $(obj)lib$(BOARD).a
 
-COBJS	:= board.o
+COBJS	:= board.o mss_spi/mss_spi.o zl30362_config.o
 
 SRCS	:= $(COBJS:.o=.c)
 OBJS	:= $(addprefix $(obj),$(COBJS))
diff --git a/board/actel/sf2-dev-kit/board.c b/board/actel/sf2-dev-kit/board.c
index 0b4a69e02937278027d52ab4e65d9261dbfde761..73d1fb4e2a7c7cfc61b76c4958b639642d7339d6 100644
--- a/board/actel/sf2-dev-kit/board.c
+++ b/board/actel/sf2-dev-kit/board.c
@@ -36,8 +36,29 @@ void dummy_func(void)
 	return;
 }
 
+extern void configure_zl30362(void);
+
+#define SERDES0_LANE3_REGS	0x40029c00
+#define TX_PST_RATIO		0x28
+
 int board_init(void)
 {
+	/* some magic from the Libero design generated source code
+	   to get the PHY working in the SGMII mode */
+	*(volatile uint32_t*)(SERDES0_LANE3_REGS + TX_PST_RATIO) = 0x0;
+	/* configure the ZL30362 Clock Network Synchronizer
+	   (required for Ethernet to function in U-boot and Linux) */
+	configure_zl30362();
+	CORE_SF2_CFG->config_done = 1u; /* Signal to CoreSF2Reset that peripheral
+					   configuration registers have
+					   been written.*/
+#if 0 /* FIXME: init_done is never signalled after a soft reset
+	 if the DDR has been initialized before the reset. */
+	while(!CORE_SF2_CFG->init_done)
+	{
+		;   /* Wait for INIT_DONE from CoreSF2Reset. */
+	}
+#endif
 	return 0;
 }
 
diff --git a/board/actel/sf2-dev-kit/mss_spi/mss_spi.c b/board/actel/sf2-dev-kit/mss_spi/mss_spi.c
new file mode 100644
index 0000000000000000000000000000000000000000..4fb9a722cc15978e8abc3910cfbded4f937ac72c
--- /dev/null
+++ b/board/actel/sf2-dev-kit/mss_spi/mss_spi.c
@@ -0,0 +1,991 @@
+/*******************************************************************************
+ * (c) Copyright 2008 Actel Corporation.  All rights reserved.
+ * 
+ * SmartFusion microcontroller subsystem SPI bare metal software driver
+ * implementation.
+ *
+ * SVN $Revision: 4566 $
+ * SVN $Date: 2012-08-23 17:12:11 +0100 (Thu, 23 Aug 2012) $
+ */
+#include <common.h>
+#include "mss_spi.h"
+/* #include "../../CMSIS/mss_assert.h" */
+
+#ifdef __cplusplus
+extern "C" {
+#endif 
+    
+/***************************************************************************//**
+  MSS SPI can operate as master or slave.
+ */
+#define MSS_SPI_MODE_SLAVE      0u
+#define MSS_SPI_MODE_MASTER     1u
+
+/***************************************************************************//**
+ * Mask of transfer protocol and SPO, SPH bits within control register.
+ */
+#define PROTOCOL_MODE_MASK  (uint32_t)0x030000C0
+
+/***************************************************************************//**
+ * Mask of theframe count bits within the SPI control register.
+ */
+#define TXRXDFCOUNT_MASK    (uint32_t)0x00FFFF00
+#define TXRXDFCOUNT_SHIFT   (uint32_t)8
+
+/***************************************************************************//**
+ * SPI hardware FIFO depth.
+ */
+#define RX_FIFO_SIZE    4u
+#define BIG_FIFO_SIZE   32u
+
+/***************************************************************************//**
+ * 
+ */
+#define RX_IRQ_THRESHOLD    (BIG_FIFO_SIZE / 2u)
+
+/***************************************************************************//**
+  Marker used to detect that the configuration has not been selected for a
+  specific slave when operating as a master.
+ */
+#define NOT_CONFIGURED  0xFFFFFFFF
+
+/***************************************************************************//**
+ * CONTROL register bit masks
+ */
+#define CTRL_ENABLE_MASK    0x00000001u
+#define CTRL_MASTER_MASK    0x00000002u
+
+/***************************************************************************//**
+  Registers bit masks
+ */
+/* CONTROL register. */
+#define MASTER_MODE_MASK        0x00000002u
+#define CTRL_RX_IRQ_EN_MASK     0x00000010u
+#define CTRL_TX_IRQ_EN_MASK     0x00000020u
+#define CTRL_REG_RESET_MASK     0x80000000u
+#define BIGFIFO_MASK            0x20000000u
+
+/* CONTROL2 register */
+#define ENABLE_CMD_IRQ_MASK     0x00000010u
+#define ENABLE_SSEND_IRQ_MASK   0x00000020u
+
+/* STATUS register */
+#define TX_DONE_MASK            0x00000001u
+#define RX_DATA_READY_MASK      0x00000002u
+#define RX_OVERFLOW_MASK        0x00000004u
+#define RX_FIFO_EMPTY_MASK      0x00000040u
+#define TX_FIFO_FULL_MASK       0x00000100u
+#define TX_FIFO_EMPTY_MASK      0x00000400u
+
+/* MIS register. */
+#define TXDONE_IRQ_MASK         0x00000001u
+#define RXDONE_IRQ_MASK         0x00000002u
+#define RXOVER_IRQ_MASK         0x00000004u
+#define RXUNDER_IRQ_MASK        0x00000008u
+#define CMD_IRQ_MASK            0x00000010u
+#define SSEND_IRQ_MASK          0x00000020u
+
+/* COMMAND register */
+#define AUTOFILL_MASK           0x00000001u
+#define RX_FIFO_RESET_MASK      0x00000004u
+#define TX_FIFO_RESET_MASK      0x00000008u
+
+/***************************************************************************//**
+ * SPI instance data structures for SPI0 and SPI1. A pointer to these data
+ * structures must be used as first parameter to any of the SPI driver functions
+ * to identify the SPI hardware block that will perform the requested operation.
+ */
+mss_spi_instance_t g_mss_spi0;
+volatile mss_spi_instance_t g_mss_spi1;
+
+/***************************************************************************//**
+  SPI0 interrupt service routine
+ */
+#if defined(__GNUC__)
+__attribute__((__interrupt__)) void SPI0_IRQHandler(void);
+#else
+void SPI0_IRQHandler(void);
+#endif
+
+/***************************************************************************//**
+  SPI1 interrupt service routine
+ */
+#if defined(__GNUC__)
+__attribute__((__interrupt__)) void SPI1_IRQHandler(void);
+#else
+void SPI1_IRQHandler(void);
+#endif
+
+/***************************************************************************//**
+  local functions
+ */
+static void recover_from_rx_overflow(volatile mss_spi_instance_t * this_spi);
+/* static void fill_slave_tx_fifo(mss_spi_instance_t * this_spi); */
+/* static void read_slave_rx_fifo(mss_spi_instance_t * this_spi); */
+
+/***************************************************************************//**
+ * MSS_SPI_init()
+ * See "mss_spi.h" for details of how to use this function.
+ */
+void MSS_SPI_init
+(
+    volatile mss_spi_instance_t * this_spi
+)
+{
+    uint16_t i;
+    
+    ASSERT((this_spi == &g_mss_spi0) || (this_spi == &g_mss_spi1));
+    
+    if(this_spi == &g_mss_spi0)
+    {
+        this_spi->hw_reg = ((SPI_REVB_TypeDef *) SPI0_BASE);
+        this_spi->irqn = SPI0_IRQn;
+
+        /* reset SPI0 */
+        SYSREG->SOFT_RST_CR |= SYSREG_SPI0_SOFTRESET_MASK;
+        /* Clear any previously pended SPI0 interrupt */
+        /* NVIC_ClearPendingIRQ(SPI0_IRQn); */
+        /* Take SPI0 out of reset. */
+        SYSREG->SOFT_RST_CR &= ~SYSREG_SPI0_SOFTRESET_MASK;
+
+        this_spi->hw_reg->CONTROL &= ~CTRL_REG_RESET_MASK;
+    }
+    else
+    {
+        this_spi->hw_reg = ((SPI_REVB_TypeDef *) SPI1_BASE);
+        this_spi->irqn = SPI1_IRQn;
+        
+        /* reset SPI1 */
+        SYSREG->SOFT_RST_CR |= SYSREG_SPI1_SOFTRESET_MASK;
+        /* Clear any previously pended SPI1 interrupt */
+        /* NVIC_ClearPendingIRQ(SPI1_IRQn); */
+        /* Take SPI1 out of reset. */
+        SYSREG->SOFT_RST_CR &= ~SYSREG_SPI1_SOFTRESET_MASK;
+        
+        this_spi->hw_reg->CONTROL &= ~CTRL_REG_RESET_MASK;
+    }
+    
+    this_spi->frame_rx_handler = 0u;
+    this_spi->slave_tx_frame = 0u;
+    
+    this_spi->block_rx_handler = 0u;
+    
+    this_spi->slave_tx_buffer = 0u;
+    this_spi->slave_tx_size = 0u;
+    this_spi->slave_tx_idx = 0u;
+
+    this_spi->resp_tx_buffer = 0u;
+    this_spi->resp_buff_size = 0u;
+    this_spi->resp_buff_tx_idx = 0u;
+    
+    for(i = 0u; i < (uint16_t)MSS_SPI_MAX_NB_OF_SLAVES; ++i)
+    {
+        this_spi->slaves_cfg[i].ctrl_reg = NOT_CONFIGURED;
+    }
+}
+
+/***************************************************************************//**
+ *
+ *
+ */
+static void recover_from_rx_overflow
+(
+ volatile    mss_spi_instance_t * this_spi
+)
+{
+    uint32_t control_reg;
+    uint32_t clk_gen;
+    uint32_t frame_size;
+    
+    /*
+     * Read current SPI hardware block configuration.
+     */
+    control_reg = this_spi->hw_reg->CONTROL;
+    clk_gen = this_spi->hw_reg->CLK_GEN;
+    frame_size = this_spi->hw_reg->TXRXDF_SIZE;
+     
+    /*
+     * Reset the SPI hardware block.
+     */
+    if(this_spi == &g_mss_spi0)
+    {
+        this_spi->hw_reg = ((SPI_REVB_TypeDef *) SPI0_BASE);
+        this_spi->irqn = SPI0_IRQn;
+
+        /* reset SPI0 */
+        SYSREG->SOFT_RST_CR |= SYSREG_SPI0_SOFTRESET_MASK;
+        /* Clear any previously pended SPI0 interrupt */
+        /* NVIC_ClearPendingIRQ(SPI0_IRQn); */
+        /* Take SPI0 out of reset. */
+        SYSREG->SOFT_RST_CR &= ~SYSREG_SPI0_SOFTRESET_MASK;
+
+        this_spi->hw_reg->CONTROL &= ~CTRL_REG_RESET_MASK;
+    }
+    else
+    {
+        this_spi->hw_reg = ((SPI_REVB_TypeDef *) SPI1_BASE);
+        this_spi->irqn = SPI1_IRQn;
+        
+        /* reset SPI1 */
+        SYSREG->SOFT_RST_CR |= SYSREG_SPI1_SOFTRESET_MASK;
+        /* Clear any previously pended SPI1 interrupt */
+        /* NVIC_ClearPendingIRQ(SPI1_IRQn); */
+        /* Take SPI1 out of reset. */
+        SYSREG->SOFT_RST_CR &= ~SYSREG_SPI1_SOFTRESET_MASK;
+        
+        this_spi->hw_reg->CONTROL &= ~CTRL_REG_RESET_MASK;
+    }
+    
+    /*
+     * Restore SPI hardware block configuration.
+     */
+    this_spi->hw_reg->CONTROL &= ~CTRL_ENABLE_MASK;
+    this_spi->hw_reg->CONTROL = control_reg;
+    this_spi->hw_reg->CLK_GEN = clk_gen;
+    this_spi->hw_reg->TXRXDF_SIZE = frame_size;
+    this_spi->hw_reg->CONTROL |= CTRL_ENABLE_MASK;
+}
+
+/* /\***************************************************************************\//\** */
+/*  * MSS_SPI_configure_slave_mode() */
+/*  * See "mss_spi.h" for details of how to use this function. */
+/*  *\/ */
+/* void MSS_SPI_configure_slave_mode */
+/* ( */
+/*     mss_spi_instance_t * this_spi, */
+/*     mss_spi_protocol_mode_t protocol_mode, */
+/*     mss_spi_pclk_div_t clk_rate, */
+/*     uint8_t frame_bit_length */
+/* ) */
+/* { */
+/*     ASSERT((this_spi == &g_mss_spi0) || (this_spi == &g_mss_spi1)); */
+/*     ASSERT(frame_bit_length <= 32); */
+    
+/*     /\* Set the mode. *\/ */
+/*     this_spi->hw_reg->CONTROL &= ~CTRL_MASTER_MASK; */
+
+/*     /\* Set the clock rate. *\/ */
+/*     this_spi->hw_reg->CONTROL &= ~CTRL_ENABLE_MASK; */
+/*     this_spi->hw_reg->CONTROL = (this_spi->hw_reg->CONTROL & ~PROTOCOL_MODE_MASK) | */
+/*                                 (uint32_t)protocol_mode | BIGFIFO_MASK; */
+                                
+/*     this_spi->hw_reg->CLK_GEN = (uint32_t)clk_rate; */
+    
+/*     /\* Set default frame size to byte size and number of data frames to 1. *\/ */
+/*     this_spi->hw_reg->CONTROL = (this_spi->hw_reg->CONTROL & ~TXRXDFCOUNT_MASK) | ((uint32_t)1 << TXRXDFCOUNT_SHIFT); */
+/*     this_spi->hw_reg->TXRXDF_SIZE = frame_bit_length; */
+/*     this_spi->hw_reg->CONTROL |= CTRL_ENABLE_MASK; */
+/* } */
+
+/***************************************************************************//**
+ * MSS_SPI_configure_master_mode()
+ * See "mss_spi.h" for details of how to use this function.
+ */
+void MSS_SPI_configure_master_mode
+(
+    volatile mss_spi_instance_t *    this_spi,
+    mss_spi_slave_t         slave,
+    mss_spi_protocol_mode_t protocol_mode,
+    mss_spi_pclk_div_t      clk_rate,
+    uint8_t                 frame_bit_length
+)
+{
+    ASSERT((this_spi == &g_mss_spi0) || (this_spi == &g_mss_spi1));
+    ASSERT(slave < MSS_SPI_MAX_NB_OF_SLAVES);
+    ASSERT(frame_bit_length <= 32);
+    
+    /* Set the mode. */
+    this_spi->hw_reg->CONTROL &= ~CTRL_ENABLE_MASK;
+    this_spi->hw_reg->CONTROL |= CTRL_MASTER_MASK;
+    this_spi->hw_reg->CONTROL |= CTRL_ENABLE_MASK;
+
+    /*
+     * Keep track of the required register configuration for this slave. These
+     * values will be used by the MSS_SPI_set_slave_select() function to configure
+     * the master to match the slave being selected.
+     */
+    if(slave < MSS_SPI_MAX_NB_OF_SLAVES)     
+    {
+        this_spi->slaves_cfg[slave].ctrl_reg = MASTER_MODE_MASK |
+                                               BIGFIFO_MASK |
+                                               (uint32_t)protocol_mode | 
+                                               ((uint32_t)1 << TXRXDFCOUNT_SHIFT);
+        this_spi->slaves_cfg[slave].txrxdf_size_reg = frame_bit_length;
+        this_spi->slaves_cfg[slave].clk_gen = (uint8_t)clk_rate;
+    }
+}
+
+/***************************************************************************//**
+ * MSS_SPI_set_slave_select()
+ * See "mss_spi.h" for details of how to use this function.
+ */
+void MSS_SPI_set_slave_select
+(
+    volatile mss_spi_instance_t * this_spi,
+    mss_spi_slave_t slave
+)
+{
+    uint32_t rx_overflow;
+    
+    ASSERT((this_spi == &g_mss_spi0) || (this_spi == &g_mss_spi1));
+    
+    /* This function is only intended to be used with an SPI master. */
+    ASSERT((this_spi->hw_reg->CONTROL & CTRL_MASTER_MASK) == CTRL_MASTER_MASK);
+    
+    ASSERT(this_spi->slaves_cfg[slave].ctrl_reg != NOT_CONFIGURED);
+
+    /* Recover from receive overflow. */
+    rx_overflow = this_spi->hw_reg->STATUS & RX_OVERFLOW_MASK;
+    if(rx_overflow)
+    {
+         recover_from_rx_overflow(this_spi);
+    }
+    
+    /* Set the clock rate. */
+    this_spi->hw_reg->CONTROL &= ~CTRL_ENABLE_MASK;
+    this_spi->hw_reg->CONTROL = this_spi->slaves_cfg[slave].ctrl_reg;
+    this_spi->hw_reg->CLK_GEN = this_spi->slaves_cfg[slave].clk_gen;
+    this_spi->hw_reg->TXRXDF_SIZE = this_spi->slaves_cfg[slave].txrxdf_size_reg;
+    this_spi->hw_reg->CONTROL |= CTRL_ENABLE_MASK;
+    
+    /* Set slave select */
+    this_spi->hw_reg->SLAVE_SELECT |= ((uint32_t)1 << (uint32_t)slave);
+}
+
+/***************************************************************************//**
+ * MSS_SPI_clear_slave_select()
+ * See "mss_spi.h" for details of how to use this function.
+ */
+void MSS_SPI_clear_slave_select
+(
+    mss_spi_instance_t * this_spi,
+    mss_spi_slave_t slave
+)
+{
+    uint32_t rx_overflow;
+    
+    ASSERT((this_spi == &g_mss_spi0) || (this_spi == &g_mss_spi1));
+    
+    /* This function is only intended to be used with an SPI master. */
+    ASSERT((this_spi->hw_reg->CONTROL & CTRL_MASTER_MASK) == CTRL_MASTER_MASK);
+
+    /* Recover from receive overflow. */
+    rx_overflow = this_spi->hw_reg->STATUS & RX_OVERFLOW_MASK;
+    if(rx_overflow)
+    {
+         recover_from_rx_overflow(this_spi);
+    }
+    
+    this_spi->hw_reg->SLAVE_SELECT &= ~((uint32_t)1 << (uint32_t)slave);
+}
+
+/***************************************************************************//**
+ * MSS_SPI_transfer_frame()
+ * See "mss_spi.h" for details of how to use this function.
+ */
+uint32_t MSS_SPI_transfer_frame
+(
+	volatile mss_spi_instance_t * this_spi,
+    uint32_t tx_bits
+)
+{
+    volatile uint32_t dummy;
+    uint32_t rx_ready;
+    uint32_t tx_done;
+    
+    ASSERT((this_spi == &g_mss_spi0) || (this_spi == &g_mss_spi1));
+    
+    /* This function is only intended to be used with an SPI master. */
+    ASSERT((this_spi->hw_reg->CONTROL & CTRL_MASTER_MASK) == CTRL_MASTER_MASK);
+    
+    /* printf("%s %d %s  %08x\n", __FILE__, __LINE__, __FUNCTION__, this_spi->hw_reg->STATUS); */
+    /* Flush Rx FIFO. */
+    rx_ready = this_spi->hw_reg->STATUS & RX_DATA_READY_MASK;
+    while(rx_ready)
+    {
+        dummy = this_spi->hw_reg->RX_DATA;
+        dummy = dummy;  /* Prevent Lint warning. */
+        rx_ready = this_spi->hw_reg->STATUS & RX_DATA_READY_MASK;
+    }
+    
+    /* printf("%s %d %s  %08x\n", __FILE__, __LINE__, __FUNCTION__, this_spi->hw_reg->STATUS); */
+    /* Send frame. */
+    this_spi->hw_reg->TX_DATA = tx_bits;
+    
+    /* Wait for frame Tx to complete. */
+    tx_done = this_spi->hw_reg->STATUS & TX_DONE_MASK;
+    while(!tx_done)
+    {
+        tx_done = this_spi->hw_reg->STATUS & TX_DONE_MASK;
+	/* printf("%s %d %s  %08x\n", __FILE__, __LINE__, __FUNCTION__, this_spi->hw_reg->STATUS); */
+    }
+    /* printf("%s %d %s  %08x\n", __FILE__, __LINE__, __FUNCTION__, this_spi->hw_reg->STATUS); */
+    
+    /* Read received frame. */
+    /* Wait for Rx complete. */
+    rx_ready = this_spi->hw_reg->STATUS & RX_DATA_READY_MASK;
+    while(!rx_ready)
+    {
+        rx_ready = this_spi->hw_reg->STATUS & RX_DATA_READY_MASK;
+    }
+	/* printf("%s %d %s\n", __FILE__, __LINE__, __FUNCTION__); */
+    /* Return Rx data. */
+    return( this_spi->hw_reg->RX_DATA );
+}
+
+
+/* /\***************************************************************************\//\** */
+/*  * MSS_SPI_transfer_block() */
+/*  * See "mss_spi.h" for details of how to use this function. */
+/*  *\/ */
+/* void MSS_SPI_transfer_block */
+/* ( */
+/*     mss_spi_instance_t * this_spi, */
+/*     const uint8_t * cmd_buffer, */
+/*     uint16_t cmd_byte_size, */
+/*     uint8_t * rd_buffer, */
+/*     uint16_t rd_byte_size */
+/* ) */
+/* { */
+/*     uint16_t transfer_idx = 0u; */
+/*     uint16_t tx_idx; */
+/*     uint16_t rx_idx; */
+/*     uint32_t frame_count; */
+/*     volatile uint32_t rx_raw; */
+/*     uint16_t transit = 0u; */
+/*     uint32_t tx_fifo_full; */
+/*     uint32_t rx_overflow; */
+/*     uint32_t rx_fifo_empty; */
+    
+/*     uint16_t transfer_size;     /\* Total number of bytes transfered. *\/ */
+    
+/*     ASSERT((this_spi == &g_mss_spi0) || (this_spi == &g_mss_spi1)); */
+    
+/*     /\* This function is only intended to be used with an SPI master. *\/ */
+/*     ASSERT((this_spi->hw_reg->CONTROL & CTRL_MASTER_MASK) == CTRL_MASTER_MASK); */
+    
+/*     /\* Compute number of bytes to transfer. *\/ */
+/*     transfer_size = cmd_byte_size + rd_byte_size; */
+    
+/*     /\* Adjust to 1 byte transfer to cater for DMA transfers. *\/ */
+/*     if(transfer_size == 0u) */
+/*     { */
+/*         frame_count = 1u; */
+/*     } */
+/*     else */
+/*     { */
+/*         frame_count = transfer_size; */
+/*     } */
+
+/*     /\* Recover from receive overflow. *\/ */
+/*     rx_overflow = this_spi->hw_reg->STATUS & RX_OVERFLOW_MASK; */
+/*     if(rx_overflow) */
+/*     { */
+/*          recover_from_rx_overflow(this_spi); */
+/*     } */
+    
+/*     /\* Set frame size to 8 bits and the frame count to the transfer size. *\/ */
+/*     this_spi->hw_reg->CONTROL &= ~CTRL_ENABLE_MASK; */
+/*     this_spi->hw_reg->CONTROL = (this_spi->hw_reg->CONTROL & ~TXRXDFCOUNT_MASK) | ( (frame_count << TXRXDFCOUNT_SHIFT) & TXRXDFCOUNT_MASK); */
+/*     this_spi->hw_reg->TXRXDF_SIZE = 8u; */
+/*     this_spi->hw_reg->CONTROL |= CTRL_ENABLE_MASK; */
+
+/*     /\* Flush the receive FIFO. *\/ */
+/*     rx_fifo_empty = this_spi->hw_reg->STATUS & RX_FIFO_EMPTY_MASK; */
+/*     while(!rx_fifo_empty) */
+/*     { */
+/*         rx_raw = this_spi->hw_reg->RX_DATA; */
+/*         rx_fifo_empty = this_spi->hw_reg->STATUS & RX_FIFO_EMPTY_MASK; */
+/*     } */
+    
+/*     tx_idx = 0u; */
+/*     rx_idx = 0u; */
+/*     if(tx_idx < cmd_byte_size) */
+/*     { */
+/*         this_spi->hw_reg->TX_DATA = cmd_buffer[tx_idx]; */
+/*         ++tx_idx; */
+/*         ++transit; */
+/*     } */
+/*     else */
+/*     { */
+/*         if(tx_idx < transfer_size) */
+/*         { */
+/*             this_spi->hw_reg->TX_DATA = 0x00u; */
+/*             ++tx_idx; */
+/*             ++transit; */
+/*         } */
+/*     } */
+/*     /\* Perform the remainder of the transfer by sending a byte every time a byte */
+/*      * has been received. This should ensure that no Rx overflow can happen in */
+/*      * case of an interrupt occurs during this function. *\/ */
+/*     while(transfer_idx < transfer_size) */
+/*     { */
+/*         rx_fifo_empty = this_spi->hw_reg->STATUS & RX_FIFO_EMPTY_MASK; */
+/*         if(!rx_fifo_empty) */
+/*         { */
+/*             /\* Process received byte. *\/ */
+/*             rx_raw = this_spi->hw_reg->RX_DATA; */
+/*             if(transfer_idx >= cmd_byte_size) */
+/*             { */
+/*                 if(rx_idx < rd_byte_size) */
+/*                 { */
+/*                     rd_buffer[rx_idx] = (uint8_t)rx_raw;    */
+/*                 } */
+/*                 ++rx_idx; */
+/*             } */
+/*             ++transfer_idx; */
+/*             --transit; */
+/*         } */
+
+/*         tx_fifo_full = this_spi->hw_reg->STATUS & TX_FIFO_FULL_MASK; */
+/*         if(!tx_fifo_full) */
+/*         { */
+/*             if(transit < RX_FIFO_SIZE) */
+/*             { */
+/*                 /\* Send another byte. *\/ */
+/*                 if(tx_idx < cmd_byte_size) */
+/*                 { */
+/*                     this_spi->hw_reg->TX_DATA = cmd_buffer[tx_idx]; */
+/*                     ++tx_idx; */
+/*                     ++transit; */
+/*                 } */
+/*                 else */
+/*                 { */
+/*                     if(tx_idx < transfer_size) */
+/*                     { */
+/*                         this_spi->hw_reg->TX_DATA = 0x00u; */
+/*                         ++tx_idx; */
+/*                         ++transit; */
+/*                     } */
+/*                 } */
+/*             } */
+/*         } */
+/*     } */
+/* } */
+
+/* /\***************************************************************************\//\** */
+/*  * MSS_SPI_set_frame_rx_handler() */
+/*  * See "mss_spi.h" for details of how to use this function. */
+/*  *\/ */
+/* void MSS_SPI_set_frame_rx_handler */
+/* ( */
+/*     mss_spi_instance_t * this_spi, */
+/*     mss_spi_frame_rx_handler_t rx_handler */
+/* ) */
+/* { */
+/*     uint32_t tx_fifo_empty; */
+    
+/*     ASSERT((this_spi == &g_mss_spi0) || (this_spi == &g_mss_spi1)); */
+    
+/*     /\* This function is only intended to be used with an SPI slave. *\/ */
+/*     ASSERT((this_spi->hw_reg->CONTROL & CTRL_MASTER_MASK) != CTRL_MASTER_MASK); */
+    
+/*     /\* Disable block Rx handler as they are mutually exclusive. *\/ */
+/*     this_spi->block_rx_handler = 0u; */
+    
+/*     /\* Keep a copy of the pointer to the rx hnadler function. *\/ */
+/*     this_spi->frame_rx_handler = rx_handler; */
+    
+/*     /\* Automatically fill the TX FIFO with zeroes if no slave tx frame set.*\/ */
+/*     tx_fifo_empty = this_spi->hw_reg->STATUS & TX_FIFO_EMPTY_MASK; */
+/*     if(tx_fifo_empty) */
+/*     { */
+/*         this_spi->hw_reg->COMMAND |= AUTOFILL_MASK; */
+/*     } */
+    
+/*     /\* Enable Rx interrupt. *\/ */
+/*     this_spi->hw_reg->CONTROL |= CTRL_RX_IRQ_EN_MASK; */
+/*     /\* NVIC_EnableIRQ( this_spi->irqn ); *\/ */
+/* } */
+
+/* /\***************************************************************************\//\** */
+/*  * MSS_SPI_set_slave_tx_frame() */
+/*  * See "mss_spi.h" for details of how to use this function. */
+/*  *\/ */
+/* void MSS_SPI_set_slave_tx_frame */
+/* ( */
+/*     mss_spi_instance_t * this_spi, */
+/*     uint32_t frame_value */
+/* ) */
+/* { */
+/*     ASSERT((this_spi == &g_mss_spi0) || (this_spi == &g_mss_spi1)); */
+
+/*     /\* This function is only intended to be used with an SPI slave. *\/ */
+/*     ASSERT((this_spi->hw_reg->CONTROL & CTRL_MASTER_MASK) != CTRL_MASTER_MASK); */
+    
+/*     /\* Disable slave block tx buffer as it is mutually exclusive with frame */
+/*      * level handling. *\/     */
+/*     this_spi->slave_tx_buffer = 0u; */
+/*     this_spi->slave_tx_size = 0u; */
+/*     this_spi->slave_tx_idx = 0u; */
+    
+/*     /\* Keep a copy of the slave tx frame value. *\/ */
+/*     this_spi->slave_tx_frame = frame_value; */
+    
+/*     /\* Disable automatic fill of the TX FIFO with zeroes.*\/ */
+/*     this_spi->hw_reg->COMMAND &= ~AUTOFILL_MASK; */
+/*     this_spi->hw_reg->COMMAND |= TX_FIFO_RESET_MASK; */
+    
+/*     /\* Load frame into Tx data register. *\/ */
+/*     this_spi->hw_reg->TX_DATA = this_spi->slave_tx_frame; */
+    
+/*     /\* Enable Tx Done interrupt in order to reload the slave Tx frame after each */
+/*      * time it has been sent. *\/ */
+/*     this_spi->hw_reg->CONTROL |= CTRL_TX_IRQ_EN_MASK; */
+/*     /\* NVIC_EnableIRQ( this_spi->irqn ); *\/ */
+/* } */
+
+/* /\***************************************************************************\//\** */
+/*  * MSS_SPI_set_slave_block_buffers() */
+/*  * See "mss_spi.h" for details of how to use this function. */
+/*  *\/ */
+/* void MSS_SPI_set_slave_block_buffers */
+/* ( */
+/*     mss_spi_instance_t * this_spi, */
+/*     const uint8_t * tx_buffer, */
+/*     uint32_t tx_buff_size, */
+/*     uint8_t * rx_buffer, */
+/*     uint32_t rx_buff_size, */
+/*     mss_spi_block_rx_handler_t block_rx_handler */
+/* ) */
+/* { */
+/*     uint32_t frame_count; */
+/*     uint32_t tx_fifo_full; */
+    
+/*     ASSERT((this_spi == &g_mss_spi0) || (this_spi == &g_mss_spi1)); */
+    
+/*     /\* This function is only intended to be used with an SPI slave. *\/ */
+/*     ASSERT((this_spi->hw_reg->CONTROL & CTRL_MASTER_MASK) != CTRL_MASTER_MASK); */
+    
+/*     /\* Disable Rx frame handler as it is mutually exclusive with block rx handler. *\/ */
+/*     this_spi->frame_rx_handler = 0u; */
+    
+/*     /\* Keep a copy of the pointer to the block rx handler function. *\/ */
+/*     this_spi->block_rx_handler = block_rx_handler; */
+    
+/*     this_spi->slave_rx_buffer = rx_buffer; */
+/*     this_spi->slave_rx_size = rx_buff_size; */
+/*     this_spi->slave_rx_idx = 0u; */
+    
+/*     /\* Initialise the transmit state data. *\/ */
+/*     this_spi->slave_tx_buffer = tx_buffer; */
+/*     this_spi->slave_tx_size = tx_buff_size; */
+/*     this_spi->slave_tx_idx = 0u; */
+
+/*     /\* Use the frame counter to control how often receive interrupts are generated. *\/ */
+/*     frame_count = RX_IRQ_THRESHOLD; */
+    
+/*     /\**\/ */
+/*     this_spi->hw_reg->CONTROL &= ~CTRL_ENABLE_MASK; */
+/*     this_spi->hw_reg->CONTROL = (this_spi->hw_reg->CONTROL & ~TXRXDFCOUNT_MASK) | (frame_count << TXRXDFCOUNT_SHIFT); */
+/*     this_spi->hw_reg->TXRXDF_SIZE = 8u; */
+/*     this_spi->hw_reg->CONTROL |= CTRL_ENABLE_MASK; */
+    
+/*     /\* Load the transmit FIFO. *\/ */
+/*     tx_fifo_full = this_spi->hw_reg->STATUS & TX_FIFO_FULL_MASK; */
+/*     while(!tx_fifo_full && (this_spi->slave_tx_idx < this_spi->slave_tx_size)) */
+/*     { */
+/*         this_spi->hw_reg->TX_DATA = this_spi->slave_tx_buffer[this_spi->slave_tx_idx]; */
+/*         ++this_spi->slave_tx_idx; */
+/*         tx_fifo_full = this_spi->hw_reg->STATUS & TX_FIFO_FULL_MASK; */
+/*     } */
+    
+/*     /\* Enable Rx interrupt. *\/ */
+/*     this_spi->hw_reg->CONTROL |= CTRL_RX_IRQ_EN_MASK; */
+    
+    
+/*     if(tx_buff_size > 0) */
+/*     { */
+/*         this_spi->hw_reg->COMMAND &= ~AUTOFILL_MASK; */
+/*         this_spi->hw_reg->CONTROL |= CTRL_TX_IRQ_EN_MASK; */
+/*     } */
+/*     else */
+/*     { */
+/*         this_spi->hw_reg->COMMAND |= AUTOFILL_MASK; */
+/*     } */
+    
+/*     /\* */
+/*      * Enable slave select release interrupt. The SSEND interrupt is used to */
+/*      * complete reading of the recieve FIFO and prepare the transmit FIFO for */
+/*      * the next transaction. */
+/*      *\/ */
+/*     this_spi->hw_reg->CONTROL2 |= ENABLE_SSEND_IRQ_MASK; */
+    
+/*     /\* NVIC_EnableIRQ(this_spi->irqn); *\/ */
+/* } */
+
+/* /\***************************************************************************\//\** */
+/*  * MSS_SPI_set_cmd_handler() */
+/*  * See "mss_spi.h" for details of how to use this function. */
+/*  *\/ */
+/* void MSS_SPI_set_cmd_handler */
+/* ( */
+/*     mss_spi_instance_t * this_spi, */
+/*     mss_spi_block_rx_handler_t cmd_handler, */
+/*     uint32_t cmd_size */
+/* ) */
+/* { */
+/*     this_spi->cmd_handler = cmd_handler; */
+/*     this_spi->hw_reg->CMDSIZE = cmd_size; */
+/*     this_spi->hw_reg->CONTROL2 |= ENABLE_CMD_IRQ_MASK; */
+/* } */
+
+/* /\***************************************************************************\//\** */
+/*  * MSS_SPI_set_cmd_response() */
+/*  * See "mss_spi.h" for details of how to use this function. */
+/*  *\/ */
+/* void MSS_SPI_set_cmd_response */
+/* ( */
+/*     mss_spi_instance_t * this_spi, */
+/*     const uint8_t * resp_tx_buffer, */
+/*     uint32_t resp_buff_size */
+/* ) */
+/* { */
+/*     this_spi->resp_tx_buffer = resp_tx_buffer; */
+/*     this_spi->resp_buff_size = resp_buff_size; */
+/*     this_spi->resp_buff_tx_idx = 0u; */
+    
+/*     fill_slave_tx_fifo(this_spi); */
+/* } */
+
+/***************************************************************************//**
+ * MSS_SPI_enable()
+ * See "mss_spi.h" for details of how to use this function.
+ */
+void MSS_SPI_enable
+(
+    volatile mss_spi_instance_t * this_spi
+)
+{
+    this_spi->hw_reg->CONTROL |= CTRL_ENABLE_MASK;
+}
+
+/***************************************************************************//**
+ * MSS_SPI_disable()
+ * See "mss_spi.h" for details of how to use this function.
+ */
+void MSS_SPI_disable
+(
+    volatile mss_spi_instance_t * this_spi
+)
+{
+    this_spi->hw_reg->CONTROL &= ~CTRL_ENABLE_MASK;
+}
+
+/* /\***************************************************************************\//\** */
+/*  * MSS_SPI_set_transfer_byte_count() */
+/*  * See "mss_spi.h" for details of how to use this function. */
+/*  *\/ */
+/* void MSS_SPI_set_transfer_byte_count */
+/* ( */
+/*     volatile mss_spi_instance_t * this_spi, */
+/*     uint16_t byte_count */
+/* ) */
+/* { */
+/*     this_spi->hw_reg->CONTROL = (this_spi->hw_reg->CONTROL & ~TXRXDFCOUNT_MASK) */
+/*                                 | ((byte_count << TXRXDFCOUNT_SHIFT) & TXRXDFCOUNT_MASK); */
+                                
+/*     this_spi->hw_reg->TXRXDF_SIZE = 8u; */
+/* } */
+
+/* /\***************************************************************************\//\** */
+/*  * MSS_SPI_tx_done() */
+/*  * See "mss_spi.h" for details of how to use this function. */
+/*  *\/ */
+/* uint32_t MSS_SPI_tx_done */
+/* ( */
+/*     mss_spi_instance_t * this_spi */
+/* ) */
+/* { */
+/*     uint32_t tx_done; */
+    
+/*     tx_done = this_spi->hw_reg->STATUS & TX_DONE_MASK; */
+    
+/*     return tx_done; */
+/* } */
+
+/* /\***************************************************************************\//\** */
+/*  * Fill the transmit FIFO (used for slave block transfers). */
+/*  *\/ */
+/* static void fill_slave_tx_fifo */
+/* ( */
+/*     mss_spi_instance_t * this_spi */
+/* ) */
+/* { */
+/*     uint32_t more_data = 1u; */
+/*     uint32_t tx_fifo_full; */
+    
+/*     tx_fifo_full = this_spi->hw_reg->STATUS & TX_FIFO_FULL_MASK; */
+    
+/*     while(!tx_fifo_full && more_data) */
+/*     { */
+/*         if(this_spi->slave_tx_idx < this_spi->slave_tx_size) */
+/*         { */
+/*             this_spi->hw_reg->TX_DATA = this_spi->slave_tx_buffer[this_spi->slave_tx_idx]; */
+/*             ++this_spi->slave_tx_idx; */
+/*         } */
+/*         else if(this_spi->resp_buff_tx_idx < this_spi->resp_buff_size) */
+/*         { */
+/*             this_spi->hw_reg->TX_DATA = this_spi->resp_tx_buffer[this_spi->resp_buff_tx_idx]; */
+/*             ++this_spi->resp_buff_tx_idx; */
+/*         } */
+/*         else */
+/*         { */
+/*             more_data = 0u; */
+/*         } */
+/*         tx_fifo_full = this_spi->hw_reg->STATUS & TX_FIFO_FULL_MASK; */
+/*     } */
+/* } */
+
+/***************************************************************************//**
+ * 
+ */
+/* static void read_slave_rx_fifo */
+/* ( */
+/*     mss_spi_instance_t * this_spi */
+/* ) */
+/* { */
+/*     uint32_t rx_frame; */
+/*     uint32_t rx_fifo_empty; */
+    
+/*     if(this_spi->frame_rx_handler != 0u) */
+/*     { */
+/*         rx_fifo_empty = this_spi->hw_reg->STATUS & RX_FIFO_EMPTY_MASK; */
+        
+/*         while(!rx_fifo_empty) */
+/*         { */
+/*             /\* Single frame handling mode. *\/ */
+/*             rx_frame = this_spi->hw_reg->RX_DATA; */
+/*             this_spi->frame_rx_handler( rx_frame ); */
+/*             rx_fifo_empty = this_spi->hw_reg->STATUS & RX_FIFO_EMPTY_MASK; */
+/*         } */
+/*     } */
+/*     else  */
+/*     { */
+/*         /\* Block handling mode. *\/ */
+/*         rx_fifo_empty = this_spi->hw_reg->STATUS & RX_FIFO_EMPTY_MASK; */
+        
+/*         while((!rx_fifo_empty) && (this_spi->slave_rx_idx < this_spi->slave_rx_size)) */
+/*         { */
+/*             rx_frame = this_spi->hw_reg->RX_DATA; */
+/*             this_spi->slave_rx_buffer[this_spi->slave_rx_idx] = (uint8_t)rx_frame; */
+/*             ++this_spi->slave_rx_idx; */
+/*             rx_fifo_empty = this_spi->hw_reg->STATUS & RX_FIFO_EMPTY_MASK; */
+/*         } */
+/*     } */
+/* } */
+
+/***************************************************************************//**
+ * SPI interrupt service routine.
+ */
+/* static void mss_spi_isr */
+/* ( */
+/*     mss_spi_instance_t * this_spi */
+/* ) */
+/* { */
+/*     uint32_t tx_done; */
+    
+/*     ASSERT((this_spi == &g_mss_spi0) || (this_spi == &g_mss_spi1)); */
+  
+/*     /\* Handle receive. *\/ */
+/*     if(this_spi->hw_reg->MIS & RXDONE_IRQ_MASK) */
+/*     { */
+/*         read_slave_rx_fifo(this_spi); */
+/*         this_spi->hw_reg->IRQ_CLEAR = RXDONE_IRQ_MASK; */
+/*     } */
+    
+/*     /\* Handle transmit. *\/ */
+/*     tx_done = this_spi->hw_reg->MIS & TXDONE_IRQ_MASK; */
+/*     if(tx_done) */
+/*     { */
+/*         if(0u == this_spi->slave_tx_buffer) */
+/*         { */
+/*             /\* Reload slave tx frame into Tx data register. *\/ */
+/*             this_spi->hw_reg->TX_DATA = this_spi->slave_tx_frame; */
+/*         } */
+/*         this_spi->hw_reg->IRQ_CLEAR = TXDONE_IRQ_MASK; */
+/*     } */
+    
+/*     /\* Handle command interrupt. *\/ */
+/*     if(this_spi->hw_reg->MIS & CMD_IRQ_MASK) */
+/*     { */
+/*         read_slave_rx_fifo(this_spi); */
+        
+/*         /\* */
+/*          * Call the command handler if one exists. */
+/*          *\/ */
+/*         if(this_spi->cmd_handler != 0u) */
+/*         { */
+/*             (*this_spi->cmd_handler)(this_spi->slave_rx_buffer, this_spi->slave_rx_idx); */
+/*         } */
+        
+/*         this_spi->hw_reg->IRQ_CLEAR = CMD_IRQ_MASK; */
+/*     } */
+    
+/*     /\* Handle slave select becoming de-asserted. *\/ */
+/*     if(this_spi->hw_reg->MIS & SSEND_IRQ_MASK) */
+/*     { */
+/*         uint32_t rx_size; */
+        
+/*         read_slave_rx_fifo(this_spi); */
+/*         rx_size = this_spi->slave_rx_idx; */
+        
+/*         /\*  */
+/*          * Reset the transmit index to 0 to restart transmit at the start of the */
+/*          * transmit buffer in the next transaction. This also requires flushing */
+/*          * the Tx FIFO and refilling it with the start of Tx data buffer. */
+/*          *\/ */
+/*         this_spi->slave_tx_idx = 0u; */
+/*         this_spi->hw_reg->COMMAND |= TX_FIFO_RESET_MASK; */
+/*         fill_slave_tx_fifo(this_spi); */
+        
+/*         /\* Prepare to receive next packet. *\/ */
+/*         this_spi->slave_rx_idx = 0u; */
+        
+/*         /\* */
+/*          * Call the receive handler if one exists. */
+/*          *\/ */
+/*         if(this_spi->block_rx_handler != 0u) */
+/*         { */
+/*             (*this_spi->block_rx_handler)(this_spi->slave_rx_buffer, rx_size); */
+/*         } */
+        
+/*         this_spi->hw_reg->IRQ_CLEAR = SSEND_IRQ_MASK; */
+/*     } */
+/* } */
+
+
+/***************************************************************************//**
+ * SPIO interrupt service routine.
+ * Please note that the name of this ISR is defined as part of the SmartFusion
+ * CMSIS startup code.
+ */
+#if defined(__GNUC__)
+__attribute__((__interrupt__)) void SPI0_IRQHandler(void)
+#else
+void SPI0_IRQHandler( void )
+#endif
+{
+    /* mss_spi_isr(&g_mss_spi0); */
+    /* NVIC_ClearPendingIRQ(SPI0_IRQn); */
+}
+
+/***************************************************************************//**
+ * SPI1 interrupt service routine.
+ * Please note that the name of this ISR is defined as part of the SmartFusion
+ * CMSIS startup code.
+ */
+#if defined(__GNUC__)
+__attribute__((__interrupt__)) void SPI1_IRQHandler(void)
+#else
+void SPI1_IRQHandler(void)
+#endif
+{
+    /* mss_spi_isr(&g_mss_spi1); */
+    /* NVIC_ClearPendingIRQ(SPI1_IRQn); */
+}
+
+#ifdef __cplusplus
+}
+#endif
+
diff --git a/board/actel/sf2-dev-kit/mss_spi/mss_spi.h b/board/actel/sf2-dev-kit/mss_spi/mss_spi.h
new file mode 100644
index 0000000000000000000000000000000000000000..8ed4ee630e7d9a5b714f7e6c52e13ded9c09098e
--- /dev/null
+++ b/board/actel/sf2-dev-kit/mss_spi/mss_spi.h
@@ -0,0 +1,1663 @@
+/***************************************************************************//**
+ * (c) Copyright 2008 Actel Corporation.  All rights reserved.
+ * 
+ * SmartFusion microcontroller subsystem SPI bare metal software driver public API.
+ *
+ * The microcontroller subsystem SPI driver provides functions for implementing
+ * SPI master or SPI slave operations. These operations can be one of two
+ * classes: SPI frame operation or block transfer operations.
+ * Frame operations allow transferring SPI frames from 4 to 32 bits long. Block
+ * operations allow transferring blocks of data organized as 8 bit bytes. 
+ *
+ * SVN $Revision: 4566 $
+ * SVN $Date: 2012-08-23 17:12:11 +0100 (Thu, 23 Aug 2012) $
+ */
+#define SPI0_BASE               0x40001000u
+#define SPI1_BASE               0x40011000u
+#define SYSREG_BASE             0x40038000u
+
+#define SPI0_IRQn 0
+#define SPI1_IRQn 0
+
+
+#define SYSREG                  ((SYSREG_TypeDef *) SYSREG_BASE)
+
+/*=========================================================================*//**
+  @mainpage SmartFusion MSS SPI Bare Metal Driver.
+
+  @section intro_sec Introduction
+  The SmartFusion™ microcontroller subsystem (MSS) includes two serial
+  peripheral interface SPI peripherals for serial communication. This driver
+  provides a set of functions for controlling the MSS SPIs as part of a bare
+  metal system where no operating system is available. These drivers can be
+  adapted for use as part of an operating system, but the implementation of the
+  adaptation layer between this driver and the operating system's driver model
+  is outside the scope of this driver.
+    
+  @section hw_dependencies Hardware Flow Dependencies
+  The configuration of all features of the MSS SPIs is covered by this driver
+  with the exception of the SmartFusion IOMUX configuration. SmartFusion allows
+  multiple non-concurrent uses of some external pins through IOMUX configuration.
+  This feature allows optimization of external pin usage by assigning external
+  pins for use by either the microcontroller subsystem or the FPGA fabric. The
+  MSS SPIs serial signals are routed through IOMUXes to the SmartFusion device
+  external pins. These IOMUXes are automatically configured correctly by the MSS
+  configurator tool in the hardware flow when the MSS SPIs are enabled in that
+  tool. You must ensure that the MSS SPIs are enabled by the MSS configurator
+  tool in the hardware flow; otherwise the serial inputs and outputs will not be
+  connected to the chip's external pins. For more information on IOMUX, refer to
+  the IOMUX section of the SmartFusion Datasheet.
+  The base address, register addresses and interrupt number assignment for the
+  MSS SPI blocks are defined as constants in the SmartFusion CMSIS-PAL. You must
+  ensure that the SmartFusion CMSIS-PAL is either included in the software tool
+  chain used to build your project or is included in your project.
+  
+  @section theory_op Theory of Operation
+  The MSS SPI driver functions are grouped into the following categories:
+    • Initialization
+    • Configuration for either master or slave operations
+    • SPI master frame transfer control
+    • SPI master block transfer control
+    • SPI slave frame transfer control
+    • SPI slave block transfer control
+    • DMA block transfer
+  Frame transfers allow the MSS SPI to write or read up to 32 bits of data in a
+  SPI transaction. For example, a frame transfer of 12 bits might be used to
+  read the result of an ADC conversion from a SPI analog to digital converter.
+  Block transfers allow the MSS SPI to write or read a number of bytes in a SPI
+  transaction. Block transfer transactions allow data transfers in multiples of
+  8 bits (8, 16, 24, 32, 40…). Block transfers are typically used with byte
+  oriented devices like SPI FLASH devices.
+
+  Initialization 
+    The MSS SPI driver is initialized through a call to the MSS_SPI_init()
+    function. The MSS_SPI_init() function takes only one parameter, a pointer
+    to one of two global data structures used by the driver to store state
+    information for each MSS SPI. A pointer to these data structures is also
+    used as first parameter to any of the driver functions to identify which MSS
+    SPI will be used by the called function. The names of these two data
+    structures are g_mss_spi0 and g_mss_spi1. Therefore any call to an MSS SPI
+    driver function should be of the form MSS_SPI_function_name( &g_mss_spi0, ... )
+    or MSS_SPI_function_name( &g_mss_spi1, ... ).
+    The MSS_SPI_init() function resets the specified MSS SPI hardware block and
+    clears any pending interrupts from that MSS SPI in the Cortex-M3 NVIC.
+    The MSS_SPI_init() function must be called before any other MSS SPI driver
+    functions can be called.
+
+  Configuration
+    A MSS SPI block can operate either as a master or slave SPI device. There
+    are two distinct functions for configuring a MSS SPI block for master or
+    slave operations.
+
+    Master configuration
+    The MSS_SPI_configure_master_mode() function configures the specified MSS
+    SPI block for operations as a SPI master. It must be called once for each
+    remote SPI slave device the MSS SPI block will communicate with. It is used
+    to provide the following information about each SPI slave’s communication
+    characteristics:
+        • The SPI protocol mode
+        • The SPI clock speed
+        • The frame bit length
+    This information is held by the driver and will be used to alter the
+    configuration of the MSS SPI block each time a slave is selected through a
+    call to MSS_SPI_set_slave_select(). The SPI protocol mode defines the
+    initial state of the clock signal at the start of a transaction and which
+    clock edge will be used to sample the data signal, or it defines whether the
+    SPI block will operate in TI synchronous serial mode or in NSC MICROWIRE mode.
+
+    Slave configuration
+    The MSS_SPI_configure_slave_mode() function configures the specified MSS SPI
+    block for operations as a SPI slave. It configures the following SPI
+    communication characteristics:
+        • The SPI protocol mode 
+        • The SPI clock speed
+        • The frame bit length
+    The SPI protocol mode defines the initial state of the clock signal at the
+    start of a transaction and which clock edge will be used to sample the data
+    signal, or it defines whether the SPI block will operate in TI synchronous
+    serial mode or in NSC MICROWIRE mode.
+
+  SPI master frame transfer control
+    The following functions are used as part of SPI master frame transfers:
+        • MSS_SPI_set_slave_select()
+        • MSS_SPI_transfer_frame()
+        • MSS_SPI_clear_slave_select()
+    The master must first select the target slave through a call to
+    MSS_SPI_set_slave_select(). This causes the relevant slave select line to
+    become asserted while data is clocked out onto the SPI data line.
+    A call to is then made to function MSS_SPI_transfer_frame() specifying and
+    the value of the data frame to be sent.
+    The function MSS_SPI_clear_slave_select() can be used after the transfer is
+    complete to prevent this slave select line from being asserted during
+    subsequent SPI transactions. A call to this function is only required if the
+    master is communicating with multiple slave devices.
+
+  SPI master block transfer control
+    The following functions are used as part of SPI master block transfers:
+        • MSS_SPI_set_slave_select()
+        • MSS_SPI_clear_slave_select()
+        • MSS_SPI_transfer_block()
+    The master must first select the target slave through a call to
+    MSS_SPI_set_slave_select(). This causes the relevant slave select line to
+    become asserted while data is clocked out onto the SPI data line.
+    Alternatively a GPIO can be used to control the state of the target slave
+    device’s chip select signal.
+    A call to is then made to function MSS_SPI_transfer_block (). The
+    parameters of this function specify:
+        • the number of bytes to be transmitted
+        • a pointer to the buffer containing the data to be transmitted
+        • the number of bytes to be received
+        • a pointer to the buffer where received data will be stored
+    The number of bytes to be transmitted can be set to zero to indicate that
+    the transfer is purely a block read transfer. The number of bytes to be
+    received can be set to zero to specify that the transfer is purely a block
+    write transfer.
+    The function MSS_SPI_clear_slave_select() can be used after the transfer is
+    complete to prevent this slave select line from being asserted during
+    subsequent SPI transactions. A call to this function is only required if the
+    master is communicating with multiple slave devices.
+ 
+  SPI slave frame transfer control
+    The following functions are used as part of SPI slave frame transfers:
+        • MSS_SPI_set_slave_tx_frame()
+        • MSS_SPI_set_frame_rx_handler()
+    The MSS_SPI_set_slave_tx_frame() function specifies the frame data that will
+    be returned to the SPI master. The frame data specified through this
+    function is the value that will be read over the SPI bus by the remote SPI
+    master when it initiates a transaction. A call to MSS_SPI_set_slave_tx_frame()
+    is only required if the MSS SPI slave is the target of SPI  read transactions,
+    i.e. if data is meant to be read from the SmartFusion device over SPI.
+    The MSS_SPI_set_frame_rx_handler() function specifies the receive handler
+    function that will called when a frame of data has been received by the MSS
+    SPI when it is configured as a slave. The receive handler function specified
+    through this call will process the frame data written, over the SPI bus, to
+    the MSS SPI slave by the remote SPI master. The receive handler function must
+    be implemented as part of the application. It is only required if the MSS SPI
+    slave is the target of SPI frame write transactions.
+
+  SPI slave block transfer control
+    The following functions are used as part of SPI slave block transfers:
+        • MSS_SPI_set_slave_block_buffers()
+    The MSS_SPI_set_slave_block_buffers() function is used to configure a MSS SPI
+    slave for block transfer operations. It specifies:
+        • The buffer containing the data that will be returned to the remote SPI master
+        • The buffer where data received from the remote SPI master will be stored
+        • The handler function that will be called after the receive buffer is filled
+
+  DMA block transfer control
+    The following functions are used as part of MSS SPI DMA transfers:
+        • MSS_SPI_disable()
+        • MSS_SPI_set_transfer_byte_count()
+        • MSS_SPI_enable()
+        • MSS_SPI_tx_done()
+    The MSS SPI must first be disabled through a call to function MSS_SPI_disable().
+    The number of bytes to be transferred is then set through a call to function
+    MSS_SPI_set_transfer_byte_count(). The DMA transfer is then initiated by a call
+    to the MSS_PDMA_start() function provided by the MSS PDMA driver. The actual
+    DMA transfer will only start once the MSS SPI block has been re-enabled through
+    a call to  MSS_SPI_enable(). The completion of the DMA driven SPI transfer can
+    be detected through a call to MSS_SPI_tx_done(). The direction of the SPI
+    transfer, write or read, depends on the DMA channel configuration. A SPI write
+    transfer occurs when the DMA channel is configured to write data to the MSS SPI
+    block. A SPI read transfer occurs when the DMA channel is configured to read data
+    from the MSS SPI block.
+
+ *//*=========================================================================*/
+#ifndef MSS_SPI_H_
+#define MSS_SPI_H_
+
+/* #include "../../CMSIS/m2sxxx.h" */
+
+#ifdef __cplusplus
+extern "C" {
+#endif 
+
+/***************************************************************************//**
+  This defines the function prototype that must be followed by MSS SPI slave
+  frame receive handler functions. These functions are registered with the MSS
+  SPI driver through the MSS_SPI_set_frame_rx_handler () function.
+  
+  Declaring and Implementing Slave Frame Receive Handler Functions:
+    Slave frame receive handler functions should follow the following prototype:
+        void slave_frame_receive_handler ( uint32_t rx_frame );
+    The actual name of the receive handler is unimportant. You can use any name
+    of your choice for the receive frame handler. The rx_frame parameter will
+    contain the value of the received frame.
+ */
+typedef void (*mss_spi_frame_rx_handler_t)( uint32_t rx_frame );
+
+/***************************************************************************//**
+  This defines the function prototype that must be followed by MSS SPI slave
+  block receive handler functions. These functions are registered with the MSS
+  SPI driver through the MSS_SPI_set_slave_block_buffers() function.
+  
+  Declaring and Implementing Slave Block Receive Handler Functions
+    Slave block receive handler functions should follow the following prototype:
+        void mss_spi_block_rx_handler ( uint8_t * rx_buff, uint16_t rx_size );
+    The actual name of the receive handler is unimportant. You can use any name
+    of your choice for the receive frame handler. The rx_buff parameter will
+    contain a pointer to the start of the received block. The rx_size parameter
+    will contain the number of bytes of the received block.
+
+ */
+typedef void (*mss_spi_block_rx_handler_t)( uint8_t * rx_buff, uint32_t rx_size );
+
+/***************************************************************************//**
+  This enumeration is used to define the settings for the SPI protocol mode
+  bits, CPHA and CPOL. It is used as a parameter to the MSS_SPI_configure_master_mode()
+  and MSS_SPI_configure_slave_mode() functions.
+  
+  - MSS_SPI_MODE0:
+        Clock starts low, data read on clock's rising edge, data changes on
+        falling edge.
+        
+  - MSS_SPI_MODE1:
+        Clock starts low, data read on clock's falling edge, data changes on
+        rising edge.
+        
+  - MSS_SPI_MODE2:
+        Clock starts high, data read on clock's falling edge, data changes on
+        rising edge.
+        
+  - MSS_SPI_MODE3:
+        Clock starts high, data read on clock's rising edge, data changes on
+        falling edge.
+        
+  - MSS_TI_MODE:  
+        TI syncronous serial mode. Slave select is pulsed at start of transfer.
+        
+  - MSS_NSC_MODE:
+        NSC Microwire mode.
+ */
+typedef enum __mss_spi_protocol_mode_t
+{
+    MSS_SPI_MODE0    = 0x00000000,
+    MSS_SPI_TI_MODE  = 0x01000004,
+    MSS_SPI_NSC_MODE = 0x00000008,
+    MSS_SPI_MODE2    = 0x01000000,
+    MSS_SPI_MODE1    = 0x02000000,
+    MSS_SPI_MODE3    = 0x03000000
+} mss_spi_protocol_mode_t;
+
+/***************************************************************************//**
+ This enumeration specifies the divider to be applied to the the APB bus clock
+ in order to generate the SPI clock. It is used as parameter to the
+ MSS_SPI_configure_master_mode() and MSS_SPI_configure_slave_mode()functions.
+ */
+ typedef enum __mss_spi_pclk_div_t
+ {
+    MSS_SPI_PCLK_DIV_2      = 0,
+    MSS_SPI_PCLK_DIV_4      = 1,
+    MSS_SPI_PCLK_DIV_8      = 2,
+    MSS_SPI_PCLK_DIV_16     = 3,
+    MSS_SPI_PCLK_DIV_32     = 4,
+    MSS_SPI_PCLK_DIV_64     = 5,
+    MSS_SPI_PCLK_DIV_128    = 6,
+    MSS_SPI_PCLK_DIV_256    = 7
+} mss_spi_pclk_div_t;
+
+/***************************************************************************//**
+ This enumeration is used to select a specific SPI slave device (0 to 7). It is
+ used as a parameter to the MSS_SPI_configure_master_mode(),
+ MSS_SPI_set_slave_select() and MSS_SPI_clear_slave_select () functions.
+ */
+ typedef enum __mss_spi_slave_t
+ {
+    MSS_SPI_SLAVE_0             = 0,
+    MSS_SPI_SLAVE_1             = 1,
+    MSS_SPI_SLAVE_2             = 2,
+    MSS_SPI_SLAVE_3             = 3,
+    MSS_SPI_SLAVE_4             = 4,
+    MSS_SPI_SLAVE_5             = 5,
+    MSS_SPI_SLAVE_6             = 6,
+    MSS_SPI_SLAVE_7             = 7,
+    MSS_SPI_MAX_NB_OF_SLAVES    = 8
+} mss_spi_slave_t;
+
+/***************************************************************************//**
+  This constant defines a frame size of 8 bits when configuring an MSS SPI to
+  perform block transfer data transactions.
+  It must be used as the value for the frame_bit_length parameter of function
+  MSS_SPI_configure_master_mode() when performing block transfers between the
+  MSS SPI master and the target SPI slave.
+  It must also be used as the value for the frame_bit_length parameter of
+  function MSS_SPI_configure_slave_mode() when performing block transfers
+  between the MSS SPI slave and the remote SPI master.
+ */
+#define MSS_SPI_BLOCK_TRANSFER_FRAME_SIZE   8
+
+/***************************************************************************//**
+  The mss_spi_slave_cfg_t holds the MSS SPI configuration that must be used to
+  communicate with a specific SPI slave.
+ */
+typedef struct __mss_spi_slave_cfg_t
+{
+    uint32_t ctrl_reg;
+    uint8_t txrxdf_size_reg;
+    uint8_t clk_gen;
+} mss_spi_slave_cfg_t;
+
+#define __IO
+#define __I
+#define __O
+
+/***************************************************************************//**
+  
+ */
+typedef struct
+{
+    __IO uint32_t CONTROL;
+    __IO uint32_t TXRXDF_SIZE;
+    __I  uint32_t STATUS;
+    __O  uint32_t IRQ_CLEAR;
+    __I  uint32_t RX_DATA;
+    __O  uint32_t TX_DATA;
+    __IO uint32_t CLK_GEN;
+    __IO uint32_t SLAVE_SELECT;
+    __I  uint32_t MIS;
+    __I  uint32_t RIS;
+    __IO uint32_t CONTROL2;
+    __IO uint32_t COMMAND;
+    __IO uint32_t _PKTSIZE;
+    __IO uint32_t CMDSIZE;
+    __IO uint32_t HWSTATUS;
+    __IO uint32_t STAT8;
+    __IO uint32_t CTRL0;
+    __IO uint32_t CTRL1;
+    __IO uint32_t CTRL2;
+    __IO uint32_t CTRL3;
+} SPI_REVB_TypeDef;
+
+
+typedef struct
+{
+    __IO     uint32_t    ESRAM_CR;                                 /*0X0   */
+    __IO     uint32_t    ESRAM_MAX_LAT_CR;                         /*0X4   */
+    __IO     uint32_t    DDR_CR;                                   /*0X8   */
+    __IO     uint32_t    ENVM_CR;                                  /*0XC   */
+    __IO     uint32_t    ENVM_REMAP_BASE_CR;                       /*0X10  */
+    __IO     uint32_t    ENVM_REMAP_FAB_CR;                        /*0X14  */
+    __IO     uint32_t    CC_CR;                                    /*0X18  */
+    __IO     uint32_t    CC_REGION_CR;                             /*0X1C  */
+    __IO     uint32_t    CC_LOCK_BASE_ADDR_CR;                     /*0X20  */
+    __IO     uint32_t    CC_FLUSH_INDX_CR;                         /*0X24  */
+    __IO     uint32_t    DDRB_BUF_TIMER_CR;                        /*0X28  */
+    __IO     uint32_t    DDRB_NB_ADDR_CR;                          /*0X2C  */
+    __IO     uint32_t    DDRB_NB_SIZE_CR;                          /*0X30  */
+    __IO     uint32_t    DDRB_CR;                                  /*0X34  */
+    __IO     uint32_t    EDAC_CR;                                  /*0X38  */
+    __IO     uint32_t    MASTER_WEIGHT0_CR;                        /*0X3C  */
+    __IO     uint32_t    MASTER_WEIGHT1_CR;                        /*0X40  */
+    __IO     uint32_t    SOFT_IRQ_CR;                              /*0X44  */
+    __IO     uint32_t    SOFT_RST_CR;                              /*0X48  */
+    __IO     uint32_t    M3_CR;                                    /*0X4C  */
+    __IO     uint32_t    FAB_IF_CR;                                /*0X50  */
+    __IO     uint32_t    LOOPBACK_CR;                              /*0X54  */
+    __IO     uint32_t    GPIO_SYSRESET_SEL_CR;                     /*0X58  */
+    __IO     uint32_t    GPIN_SRC_SEL_CR;                          /*0X5C  */
+    __IO     uint32_t    MDDR_CR;                                  /*0X60  */
+    __IO     uint32_t    USB_IO_INPUT_SEL_CR;                      /*0X64  */
+    __IO     uint32_t    PERIPH_CLK_MUX_SEL_CR;                    /*0X68  */
+    __IO     uint32_t    WDOG_CR;                                  /*0X6C  */
+    __IO     uint32_t    MDDR_IO_CALIB_CR;                         /*0X70  */
+    __IO     uint32_t    SPARE_OUT_CR;                             /*0X74  */
+    __IO     uint32_t    EDAC_IRQ_ENABLE_CR;                       /*0X78  */
+    __IO     uint32_t    USB_CR;                                   /*0X7C  */
+    __IO     uint32_t    ESRAM_PIPELINE_CR;                        /*0X80  */
+    __IO     uint32_t    MSS_IRQ_ENABLE_CR;                        /*0X84  */
+    __IO     uint32_t    RTC_WAKEUP_CR;                            /*0X88  */
+    __IO     uint32_t    MAC_CR;                                   /*0X8C  */
+    __IO     uint32_t    MSSDDR_PLL_STATUS_LOW_CR;                 /*0X90  */
+    __IO     uint32_t    MSSDDR_PLL_STATUS_HIGH_CR;                /*0X94  */
+    __IO     uint32_t    MSSDDR_FACC1_CR;                          /*0X98  */
+    __IO     uint32_t    MSSDDR_FACC2_CR;                          /*0X9C  */
+    __IO     uint32_t    PLL_LOCK_EN_CR;                           /*0XA0  */
+    __IO     uint32_t    MSSDDR_CLK_CALIB_CR;                      /*0XA4  */
+    __IO     uint32_t    PLL_DELAY_LINE_SEL_CR;                    /*0XA8  */
+    __IO     uint32_t    MAC_STAT_CLRONRD_CR;                      /*0XAC  */
+    __IO     uint32_t    RESET_SOURCE_CR;                          /*0XB0  */
+    __I      uint32_t    CC_DC_ERR_ADDR_SR;                        /*0XB4  */
+    __I      uint32_t    CC_IC_ERR_ADDR_SR;                        /*0XB8  */
+    __I      uint32_t    CC_SB_ERR_ADDR_SR;                        /*0XBC  */
+    __I      uint32_t    CC_DECC_ERR_ADDR_SR;                      /*0XC0  */
+    __I      uint32_t    CC_IC_MISS_CNT_SR;                        /*0XC4  */
+    __I      uint32_t    CC_IC_HIT_CNT_SR;                         /*0XC8  */
+    __I      uint32_t    CC_DC_MISS_CNT_SR;                        /*0XCC  */
+    __I      uint32_t    CC_DC_HIT_CNT_SR;                         /*0XD0  */
+    __I      uint32_t    CC_IC_TRANS_CNT_SR;                       /*0XD4  */
+    __I      uint32_t    CC_DC_TRANS_CNT_SR;                       /*0XD8  */
+    __I      uint32_t    DDRB_DS_ERR_ADR_SR;                       /*0XDC  */
+    __I      uint32_t    DDRB_HPD_ERR_ADR_SR;                      /*0XE0  */
+    __I      uint32_t    DDRB_SW_ERR_ADR_SR;                       /*0XE4  */
+    __I      uint32_t    DDRB_BUF_EMPTY_SR;                        /*0XE8  */
+    __I      uint32_t    DDRB_DSBL_DN_SR;                          /*0XEC  */
+    __I      uint32_t    ESRAM0_EDAC_CNT;                          /*0XF0  */
+    __I      uint32_t    ESRAM1_EDAC_CNT;                          /*0XF4  */
+    __I      uint32_t    CC_EDAC_CNT;                              /*0XF8  */
+    __I      uint32_t    MAC_EDAC_TX_CNT;                          /*0XFC  */
+    __I      uint32_t    MAC_EDAC_RX_CNT;                          /*0X100 */
+    __I      uint32_t    USB_EDAC_CNT;                             /*0X104 */
+    __I      uint32_t    CAN_EDAC_CNT;                             /*0X108 */
+    __I      uint32_t    ESRAM0_EDAC_ADR;                          /*0X10C */
+    __I      uint32_t    ESRAM1_EDAC_ADR;                          /*0X110 */
+    __I      uint32_t    MAC_EDAC_RX_ADR;                          /*0X114 */
+    __I      uint32_t    MAC_EDAC_TX_ADR;                          /*0X118 */
+    __I      uint32_t    CAN_EDAC_ADR;                             /*0X11C */
+    __I      uint32_t    USB_EDAC_ADR;                             /*0X120 */
+    __I      uint32_t    MM0_1_2_SECURITY;                         /*0X124 */
+    __I      uint32_t    MM4_5_FIC64_SECURITY;                     /*0X128 */
+    __I      uint32_t    MM3_6_7_8_SECURITY;                       /*0X12C */
+    __I      uint32_t    MM9_SECURITY;                             /*0X130 */
+    __I      uint32_t    M3_SR;                                    /*0X134 */
+    __I      uint32_t    ETM_COUNT_LOW;                            /*0X138 */
+    __I      uint32_t    ETM_COUNT_HIGH;                           /*0X13C */
+    __I      uint32_t    DEVICE_SR;                                /*0X140 */
+    __I      uint32_t    ENVM_PROTECT_USER;                        /*0X144 */
+    __I      uint32_t    G4C_ENVM_STATUS;                          /*0X148 */
+    __I      uint32_t    DEVICE_VERSION;                           /*0X14C */
+    __I      uint32_t    MSSDDR_PLL_STATUS;                        /*0X150 */
+    __I      uint32_t    USB_SR;                                   /*0X154 */
+    __I      uint32_t    ENVM_SR;                                  /*0X158 */
+    __I      uint32_t    SPARE_IN;                                 /*0X15C */
+    __I      uint32_t    DDRB_STATUS;                              /*0X160 */
+    __I      uint32_t    MDDR_IO_CALIB_STATUS;                     /*0X164 */
+    __I      uint32_t    MSSDDR_CLK_CALIB_STATUS;                  /*0X168 */
+    __I      uint32_t    WDOGLOAD;                                 /*0X16C */
+    __I      uint32_t    WDOGMVRP;                                 /*0X170 */
+    __I      uint32_t    USERCONFIG0;                              /*0X174 */
+    __I      uint32_t    USERCONFIG1;                              /*0X178 */
+    __I      uint32_t    USERCONFIG2;                              /*0X17C */
+    __I      uint32_t    USERCONFIG3;                              /*0X180 */
+    __I      uint32_t    FAB_PROT_SIZE;                            /*0X184 */
+    __I      uint32_t    FAB_PROT_BASE;                            /*0X188 */
+    __I      uint32_t    MSS_GPIO_DEF;                             /*0X18C */
+    __IO     uint32_t    EDAC_SR;                                  /*0X190 */
+    __IO     uint32_t    MSS_INTERNAL_SR;                          /*0X194 */
+    __IO     uint32_t    MSS_EXTERNAL_SR;                          /*0X198 */
+    __IO     uint32_t    WDOGTIMEOUTEVENT;                         /*0X19C */
+    __IO     uint32_t    CLR_MSS_COUNTERS;                         /*0X1A0 */
+    __IO     uint32_t    CLR_EDAC_COUNTERS;                        /*0X1A4 */
+    __IO     uint32_t    FLUSH_CR;                                 /*0X1A8 */
+    __IO     uint32_t    MAC_STAT_CLR_CR;                          /*0X1AC */
+    __IO     uint32_t    IOMUXCELL_CONFIG[57];                     /*0X1B0 */
+    __I      uint32_t    NVM_PROTECT_FACTORY;                      /*0X294 */
+    __I      uint32_t    DEVICE_STATUS_FIXED;                      /*0X298 */
+    __I      uint32_t    MBIST_ES0;                                /*0X29C */
+    __I      uint32_t    MBIST_ES1;                                /*0X2A0 */
+    __IO     uint32_t    MSDDR_PLL_STAUS_1;                        /*0X2A4 */
+    __I      uint32_t    REDUNDANCY_ESRAM0;                        /*0X2A8 */
+    __I      uint32_t    REDUNDANCY_ESRAM1;                        /*0X2AC */
+    __I      uint32_t    SERDESIF;                                 /*0X2B0 */
+
+} SYSREG_TypeDef;
+
+#define SYSREG_SPI0_SOFTRESET_MASK          ( (uint32_t)( 0x01 << 9) )
+#define SYSREG_SPI1_SOFTRESET_MASK          ( (uint32_t)( 0x01 << 10) )
+
+
+typedef int IRQn_Type;
+#define ASSERT(x)
+
+/***************************************************************************//**
+  There is one instance of this structure for each of the microcontroller
+  subsystem's SPIs. Instances of this structure are used to identify a specific
+  SPI. A pointer to an instance of the mss_spi_instance_t structure is passed as
+  the first parameter to MSS SPI driver functions to identify which SPI should
+  perform the requested operation.
+ */
+typedef struct __mss_spi_instance_t
+{
+    /* CMSIS related defines identifying the SPI hardware. */
+    SPI_REVB_TypeDef *          hw_reg;     /*!< Pointer to SPI registers. */
+    IRQn_Type               irqn;           /*!< SPI's Cortex-M3 NVIC interrupt number. */
+    
+    /* Internal transmit state: */
+    const uint8_t * slave_tx_buffer;    /*!< Pointer to slave transmit buffer. */
+    uint32_t slave_tx_size;             /*!< Size of slave transmit buffer. */
+    uint32_t slave_tx_idx;              /*!< Current index into slave transmit buffer. */
+    
+    /* Slave command response buffer: */
+    const uint8_t * resp_tx_buffer;
+    uint32_t resp_buff_size;
+    uint32_t resp_buff_tx_idx;
+    mss_spi_block_rx_handler_t cmd_handler;
+    
+    /* Internal receive state: */
+    uint8_t * slave_rx_buffer;          /*!< Pointer to buffer where data received by a slave will be stored. */
+    uint32_t slave_rx_size;             /*!< Slave receive buffer size. */
+    uint32_t slave_rx_idx;              /*!< Current index into slave receive buffer. */
+    
+    /* Configuration for each target slave. */
+    mss_spi_slave_cfg_t slaves_cfg[MSS_SPI_MAX_NB_OF_SLAVES];
+    
+    /** Slave received frame handler: */
+    mss_spi_frame_rx_handler_t frame_rx_handler;    /*!< Pointer to function that will be called when a frame is received when the SPI block is configured as slave. */
+    
+    uint32_t slave_tx_frame;                /*!< Value of the data frame that will be transmited when the SPI block is configured as slave. */
+    
+    /* Slave block rx handler: */
+    mss_spi_block_rx_handler_t block_rx_handler;    /*!< Pointer to the function that will be called when a data block has been received. */
+
+} mss_spi_instance_t;
+
+/***************************************************************************//**
+  This instance of mss_spi_instance_t holds all data related to the operations
+  performed by MSS SPI 0. A pointer to g_mss_spi0 is passed as the first
+  parameter to MSS SPI driver functions to indicate that MSS SPI 0 should
+  perform the requested operation.
+ */
+extern mss_spi_instance_t g_mss_spi0;
+
+/***************************************************************************//**
+  This instance of mss_spi_instance_t holds all data related to the operations
+  performed by MSS SPI 1. A pointer to g_mss_spi1 is passed as the first
+  parameter to MSS SPI driver functions to indicate that MSS SPI 1 should
+  perform the requested operation.
+ */
+extern volatile mss_spi_instance_t g_mss_spi1;
+
+/***************************************************************************//**
+  The MSS_SPI_init() function initializes and hardware and data structures of
+  one of the SmartFusion MSS SPIs. The MSS_SPI_init() function must be called
+  before any other MSS SPI driver functions can be called.
+  
+  @param this_spi
+    The this_spi parameter is a pointer to an mss_spi_instance_t structure
+    identifying the MSS SPI hardware block to be initialized. There are two such
+    data structures, g_mss_spi0 and g_mss_spi1, associated with MSS SPI 0 and
+    MSS SPI 1 respectively. This parameter must point to either the g_mss_spi0
+    or g_mss_spi1 global data structure defined within the SPI driver.
+    
+  Example:
+  @code
+  MSS_SPI_init( &g_mss_spi0 );
+  @endcode
+ */
+void MSS_SPI_init
+(
+  volatile  mss_spi_instance_t * this_spi
+);
+
+/***************************************************************************//**
+  The MSS_SPI_configure_slave_mode() function configure a MSS SPI block for
+  operations as a slave SPI device. It configures the SPI hardware with the
+  selected SPI protocol mode and clock speed.
+    
+  @param this_spi
+    The this_spi parameter is a pointer to an mss_spi_instance_t structure
+    identifying the MSS SPI hardware block to be initialized. There are two such
+    data structures, g_mss_spi0 and g_mss_spi1, associated with MSS SPI 0 and
+    MSS SPI 1 respectively. This parameter must point to either the g_mss_spi0
+    or g_mss_spi1 global data structure defined within the SPI driver.
+    
+  @param protocol_mode
+    Serial peripheral interface operating mode. Allowed values are:
+        - MSS_SPI_MODE0
+        - MSS_SPI_MODE1
+        - MSS_SPI_MODE2
+        - MSS_SPI_MODE3
+        - MSS_TI_MODE
+        - MSS_NSC_MODE
+ 
+  @param clk_rate
+    Divider value used to generate serial interface clock signal from PCLK.
+    Allowed values are:
+        - MSS_SPI_PCLK_DIV_2
+        - MSS_SPI_PCLK_DIV_4
+        - MSS_SPI_PCLK_DIV_8
+        - MSS_SPI_PCLK_DIV_16
+        - MSS_SPI_PCLK_DIV_32
+        - MSS_SPI_PCLK_DIV_64
+        - MSS_SPI_PCLK_DIV_128
+        - MSS_SPI_PCLK_DIV_256
+       
+  @param frame_bit_length
+    Number of bits making up the frame. The maximum frame length is 32 bits. You
+    must use the MSS_SPI_BLOCK_TRANSFER_FRAME_SIZE constant as the value for
+    frame_bit_length when configuring the MSS SPI master for block transfer
+    transactions with the target SPI slave.
+  
+  Example:
+  @code
+  MSS_SPI_init( &g_mss_spi0 );
+  MSS_SPI_configure_slave_mode
+    (
+        &g_mss_spi0,
+        MSS_SPI_MODE2,
+        MSS_SPI_PCLK_DIV_64,
+        MSS_SPI_BLOCK_TRANSFER_FRAME_SIZE
+    );
+  @endcode
+  
+ */ 
+void MSS_SPI_configure_slave_mode
+(
+    mss_spi_instance_t * this_spi,
+    mss_spi_protocol_mode_t protocol_mode,
+    mss_spi_pclk_div_t clk_rate,
+    uint8_t frame_bit_length
+);
+
+/***************************************************************************//**
+  The MSS_SPI_configure_master_mode() function configures the protocol mode,
+  serial clock speed and frame size for a specific target SPI slave device. It
+  is used when the MSS SPI hardware block is used as a SPI master. This function
+  must be called once for each target SPI slave the SPI master is going to
+  communicate with. The SPI master hardware will be configured with the
+  configuration specified by this function during calls to
+  MSS_SPI_set_slave_select().
+  
+  @param this_spi
+    The this_spi parameter is a pointer to an mss_spi_instance_t structure
+    identifying the MSS SPI hardware block to be initialized. There are two such
+    data structures, g_mss_spi0 and g_mss_spi1, associated with MSS SPI 0 and
+    MSS SPI 1 respectively. This parameter must point to either the g_mss_spi0
+    or g_mss_spi1 global data structure defined within the SPI driver.
+    
+    
+  @param slave
+    The slave parameter is used to identify a target SPI slave. The driver will
+    hold the MSS SPI master configuration required to communicate with this
+    slave, as specified by the other function parameters. Allowed values are:
+        • MSS_SPI_SLAVE_0
+        • MSS_SPI_SLAVE_1
+        • MSS_SPI_SLAVE_2
+        • MSS_SPI_SLAVE_3
+        • MSS_SPI_SLAVE_4
+        • MSS_SPI_SLAVE_5
+        • MSS_SPI_SLAVE_6
+        • MSS_SPI_SLAVE_7
+    
+  @param protocol_mode
+    Serial peripheral interface operating mode. Allowed values are:
+        • MSS_SPI_MODE0
+        • MSS_SPI_MODE1
+        • MSS_SPI_MODE2
+        • MSS_SPI_MODE3
+        • MSS_SPI_TI_MODE
+        • MSS_SPI_NSC_MODE
+ 
+  @param clk_rate
+    Divider value used to generate serial interface clock signal from PCLK.
+    Allowed values are:
+        • MSS_SPI_PCLK_DIV_2
+        • MSS_SPI_PCLK_DIV_4
+        • MSS_SPI_PCLK_DIV_8
+        • MSS_SPI_PCLK_DIV_16
+        • MSS_SPI_PCLK_DIV_32
+        • MSS_SPI_PCLK_DIV_64
+        • MSS_SPI_PCLK_DIV_128
+        • MSS_SPI_PCLK_DIV_256
+        
+  @param frame_bit_length
+    Number of bits making up the frame. The maximum frame length is 32 bits. You
+    must use the MSS_SPI_BLOCK_TRANSFER_FRAME_SIZE constant as the value for
+    frame_bit_length when configuring the MSS SPI master for block transfer
+    transactions with the target SPI slave.
+    
+  Example:
+  @code
+  MSS_SPI_init( &g_mss_spi0 );
+
+  MSS_SPI_configure_master_mode
+    (
+        &g_mss_spi0,
+        MSS_SPI_SLAVE_0,
+        MSS_SPI_MODE2,
+        MSS_SPI_PCLK_DIV_64,
+        12
+     );
+
+  MSS_SPI_configure_master_mode
+    (
+        &g_mss_spi0,
+        MSS_SPI_SLAVE_1,
+        MSS_SPI_TI_MODE,
+        MSS_SPI_PCLK_DIV_128,
+        MSS_SPI_BLOCK_TRANSFER_FRAME_SIZE
+     );
+  @endcode
+ */ 
+void MSS_SPI_configure_master_mode
+(
+  volatile  mss_spi_instance_t *    this_spi,
+    mss_spi_slave_t         slave,
+    mss_spi_protocol_mode_t protocol_mode,
+    mss_spi_pclk_div_t      clk_rate,
+    uint8_t                 frame_bit_length
+);
+
+/*==============================================================================
+ * Master functions
+ *============================================================================*/
+
+/***************************************************************************//**
+  The MSS_SPI_slave_select() function is used by a MSS SPI master to select a
+  specific slave. This function causes the relevant slave select signal to be
+  asserted.
+ 
+  @param this_spi
+    The this_spi parameter is a pointer to an mss_spi_instance_t structure
+    identifying the MSS SPI hardware block to be initialized. There are two such
+    data structures, g_mss_spi0 and g_mss_spi1, associated with MSS SPI 0 and
+    MSS SPI 1 respectively. This parameter must point to either the g_mss_spi0
+    or g_mss_spi1 global data structure defined within the SPI driver.
+    
+ 
+  @param slave
+    The slave parameter is one of mss_spi_slave_t enumerated constants
+    identifying a slave.
+  
+  Example:
+  @code
+  const uint8_t frame_size = 25;
+  const uint32_t master_tx_frame = 0x0100A0E1;
+
+  MSS_SPI_init( &g_mss_spi0 );
+  MSS_SPI_configure_master_mode
+    (
+        &g_mss_spi0,
+        MSS_SPI_SLAVE_0,
+        MSS_SPI_MODE1,
+        MSS_SPI_PCLK_DIV_256,
+        frame_size
+     );
+
+  MSS_SPI_set_slave_select( &g_mss_spi0, MSS_SPI_SLAVE_0 );
+  MSS_SPI_transfer_frame( &g_mss_spi0, master_tx_frame );
+  MSS_SPI_clear_slave_select( &g_mss_spi0, MSS_SPI_SLAVE_0 );
+  @endcode
+ */
+void MSS_SPI_set_slave_select
+(
+ volatile   mss_spi_instance_t * this_spi,
+    mss_spi_slave_t slave
+);
+
+/***************************************************************************//**
+  The MSS_SPI_clear_slave_select() function is used by a MSS SPI Master to
+  deselect a specific slave. This function causes the relevant slave select
+  signal to be de-asserted.
+ 
+  @param this_spi
+    The this_spi parameter is a pointer to an mss_spi_instance_t structure
+    identifying the MSS SPI hardware block to be initialized. There are two such
+    data structures, g_mss_spi0 and g_mss_spi1, associated with MSS SPI 0 and
+    MSS SPI 1 respectively. This parameter must point to either the g_mss_spi0
+    or g_mss_spi1 global data structure defined within the SPI driver.
+    
+ 
+  @param slave
+    The slave parameter is one of mss_spi_slave_t enumerated constants
+    identifying a slave.
+  
+  Example:
+  @code
+  const uint8_t frame_size = 25;
+  const uint32_t master_tx_frame = 0x0100A0E1;
+
+  MSS_SPI_init( &g_mss_spi0 );
+  MSS_SPI_configure_master_mode
+    (
+        &g_mss_spi0,
+        MSS_SPI_SLAVE_0,
+        MSS_SPI_MODE1,
+        MSS_SPI_PCLK_DIV_256,
+        frame_size
+     );
+  MSS_SPI_set_slave_select( &g_mss_spi0, MSS_SPI_SLAVE_0 );
+  MSS_SPI_transfer_frame( &g_mss_spi0, master_tx_frame );
+  MSS_SPI_clear_slave_select( &g_mss_spi0, MSS_SPI_SLAVE_0 );
+  @endcode
+ */
+void MSS_SPI_clear_slave_select
+(
+    mss_spi_instance_t * this_spi,
+    mss_spi_slave_t slave
+);
+
+/***************************************************************************//**
+  The MSS_SPI_disable() function is used to temporarily disable a MSS SPI
+  hardware block. This function is typically used in conjunction with the
+  SPI_set_transfer_byte_count() function to setup a DMA controlled SPI transmit
+  transaction as the SPI_set_transfer_byte_count() function must only be used
+  when the MSS SPI hardware is disabled.
+ 
+  @param this_spi
+    The this_spi parameter is a pointer to an mss_spi_instance_t structure
+    identifying the MSS SPI hardware block to be initialized. There are two such
+    data structures, g_mss_spi0 and g_mss_spi1, associated with MSS SPI 0 and
+    MSS SPI 1 respectively. This parameter must point to either the g_mss_spi0
+    or g_mss_spi1 global data structure defined within the SPI driver.
+  
+  Example:
+  @code
+  uint32_t transfer_size;
+  uint8_t tx_buffer[8] = { 1, 2, 3, 4, 5, 6, 7, 8 };
+  
+  transfer_size = sizeof(tx_buffer);
+  
+  MSS_SPI_disable( &g_mss_spi0 );
+  MSS_SPI_set_transfer_byte_count( &g_mss_spi0, transfer_size );
+  PDMA_start
+    (
+        PDMA_CHANNEL_0,
+        (uint32_t)tx_buffer,
+        PDMA_SPI1_TX_REGISTER,
+        transfer_size
+    );
+  MSS_SPI_enable( &g_mss_spi0 );
+  
+  while ( !MSS_SPI_tx_done( &g_mss_spi0 ) )
+  {
+      ;
+  }
+  @endcode
+ */
+void MSS_SPI_disable
+(
+  volatile    mss_spi_instance_t * this_spi
+);
+
+/***************************************************************************//**
+  The MSS_SPI_enable() function is used to re-enable a MSS SPI hardware block
+  after it was disabled using the SPI_disable() function.
+ 
+  @param this_spi
+    The this_spi parameter is a pointer to an mss_spi_instance_t structure
+    identifying the MSS SPI hardware block to be initialized. There are two such
+    data structures, g_mss_spi0 and g_mss_spi1, associated with MSS SPI 0 and
+    MSS SPI 1 respectively. This parameter must point to either the g_mss_spi0
+    or g_mss_spi1 global data structure defined within the SPI driver.
+    
+  Example:
+  @code
+  uint32_t transfer_size;
+  uint8_t tx_buffer[8] = { 1, 2, 3, 4, 5, 6, 7, 8 };
+  
+  transfer_size = sizeof(tx_buffer);
+  
+  MSS_SPI_disable( &g_mss_spi0 );
+  MSS_SPI_set_transfer_byte_count( &g_mss_spi0, transfer_size );
+  PDMA_start
+    (
+        PDMA_CHANNEL_0,
+        (uint32_t)tx_buffer,
+        PDMA_SPI1_TX_REGISTER,
+        transfer_size
+    );
+  MSS_SPI_enable( &g_mss_spi0 );
+  
+  while ( !MSS_SPI_tx_done( &g_mss_spi0 ) )
+  {
+      ;
+  }
+  @endcode
+ */
+void MSS_SPI_enable
+(
+ volatile    mss_spi_instance_t * this_spi
+);
+
+/***************************************************************************//**
+  The MSS_SPI_set_transfer_byte_count() function is used as part of setting up
+  a SPI transfer using DMA. It specifies the number of bytes that must be
+  transferred before MSS_SPI_tx_done() indicates that the transfer is complete.
+ 
+  @param this_spi
+    The this_spi parameter is a pointer to an mss_spi_instance_t structure
+    identifying the MSS SPI hardware block to be initialized. There are two such
+    data structures, g_mss_spi0 and g_mss_spi1, associated with MSS SPI 0 and
+    MSS SPI 1 respectively. This parameter must point to either the g_mss_spi0
+    or g_mss_spi1 global data structure defined within the SPI driver.
+    
+ 
+  @param byte_count
+    The byte_count parameter specifies the number of bytes that must be
+    transferred by the SPI hardware block considering that a transaction has
+    been completed.
+  
+  Example:
+  @code
+  uint32_t transfer_size;
+  uint8_t tx_buffer[8] = { 1, 2, 3, 4, 5, 6, 7, 8 };
+  
+  transfer_size = sizeof(tx_buffer);
+  
+  MSS_SPI_disable( &g_mss_spi0 );
+  
+  MSS_SPI_set_transfer_byte_count( &g_mss_spi0, transfer_size );
+  
+  PDMA_start( PDMA_CHANNEL_0, (uint32_t)tx_buffer, 0x40011014, transfer_size );
+  
+  MSS_SPI_enable( &g_mss_spi0 );
+  
+  while ( !MSS_SPI_tx_done( &g_mss_spi0) )
+  {
+      ;
+  }
+  @endcode
+ */
+void MSS_SPI_set_transfer_byte_count
+(
+    mss_spi_instance_t * this_spi,
+    uint16_t byte_count
+);
+
+/***************************************************************************//**
+  The MSS_SPI_tx_done() function is used to find out if a DMA controlled transfer
+  has completed.
+ 
+  @param this_spi
+    The this_spi parameter is a pointer to an mss_spi_instance_t structure
+    identifying the MSS SPI hardware block to be initialized. There are two such
+    data structures, g_mss_spi0 and g_mss_spi1, associated with MSS SPI 0 and
+    MSS SPI 1 respectively. This parameter must point to either the g_mss_spi0
+    or g_mss_spi1 global data structure defined within the SPI driver.
+  
+  Example:
+  @code
+      uint32_t transfer_size;
+      uint8_t tx_buffer[8] = { 1, 2, 3, 4, 5, 6, 7, 8 };
+      
+      transfer_size = sizeof(tx_buffer);
+      
+      MSS_SPI_disable( &g_mss_spi0 );
+      
+      MSS_SPI_set_transfer_byte_count( &g_mss_spi0, transfer_size );
+      
+      PDMA_start
+        (
+            PDMA_CHANNEL_0,
+            (uint32_t)tx_buffer,
+            PDMA_SPI1_TX_REGISTER,
+            transfer_size
+        );
+      
+      MSS_SPI_enable( &g_mss_spi0 );
+      
+      while ( !MSS_SPI_tx_done(&g_mss_spi0) )
+      {
+          ;
+      }
+  @endcode
+ */
+uint32_t MSS_SPI_tx_done
+(
+    mss_spi_instance_t * this_spi
+);
+
+/***************************************************************************//**
+  The MSS_SPI_transfer_frame() function is used by a MSS SPI master to transmit
+  and receive a frame up to 32 bits long. This function is typically used for
+  transactions with a SPI slave where the number of transmit and receive bits is
+  not divisible by 8.
+ 
+  @param this_spi
+    The this_spi parameter is a pointer to an mss_spi_instance_t structure
+    identifying the MSS SPI hardware block to be initialized. There are two such
+    data structures, g_mss_spi0 and g_mss_spi1, associated with MSS SPI 0 and
+    MSS SPI 1 respectively. This parameter must point to either the g_mss_spi0
+    or g_mss_spi1 global data structure defined within the SPI driver.
+    
+ 
+  @param tx_bits
+    The tx_bits parameter is a 32 bits word containing the value that will be
+    transmitted.
+    Note:   The bit length of the value to be transmitted to the slave must be
+            specified as the frame_bit_length parameter in a previous call to
+            the MSS_SPI_configure_master() function.
+
+  @return
+    This function returns a 32 bits word containing the value that is received
+    from the slave.
+ 
+  Example:
+  @code
+      const uint8_t frame_size = 25;
+      const uint32_t master_tx_frame = 0x0100A0E1;
+      uint32_t master_rx;
+      
+      MSS_SPI_init( &g_mss_spi0 );
+      MSS_SPI_configure_master_mode
+        (
+            &g_mss_spi0,
+            MSS_SPI_SLAVE_0,
+            MSS_SPI_MODE1,
+            MSS_SPI_PCLK_DIV_256,
+            frame_size
+         );
+     
+      MSS_SPI_set_slave_select( &g_mss_spi0, MSS_SPI_SLAVE_0 );
+      master_rx = MSS_SPI_transfer_frame( &g_mss_spi0, master_tx_frame );
+      MSS_SPI_clear_slave_select( &g_mss_spi0, MSS_SPI_SLAVE_0 );
+  @endcode
+ */
+uint32_t MSS_SPI_transfer_frame
+(
+ volatile mss_spi_instance_t * this_spi,
+    uint32_t tx_bits
+);
+
+/***************************************************************************//**
+  The MSS_SPI_transfer_block() function is used by MSS SPI masters to transmit
+  and receive blocks of data organized as a specified number of bytes. It can be
+  used for:
+    • Writing a data block to a slave
+    • Reading a data block from a slave
+    • Sending a command to a slave followed by reading the outcome of the
+      command in a single SPI transaction. This function can be used alongside
+      Peripheral DMA functions to perform the actual moving to and from the SPI
+      hardware block using Peripheral DMA.
+ 
+  @param this_spi
+    The this_spi parameter is a pointer to an mss_spi_instance_t structure
+    identifying the MSS SPI hardware block to be initialized. There are two such
+    data structures, g_mss_spi0 and g_mss_spi1, associated with MSS SPI 0 and
+    MSS SPI 1 respectively. This parameter must point to either the g_mss_spi0
+    or g_mss_spi1 global data structure defined within the SPI driver.
+    
+ 
+  @param cmd_buffer
+    The cmd_buffer parameter is a pointer to the buffer containing the data that
+    will be sent by the master from the beginning of the transfer. This pointer
+    can be null (0) if the master does not need to send a command before reading
+    data or if the command part of the transfer is written to the SPI hardware
+    block using DMA.
+ 
+  @param cmd_byte_size
+    The cmd_byte_size parameter specifies the number of bytes contained in
+    cmd_buffer that will be sent. A value of 0 indicates that no data needs to
+    be sent to the slave. A non-zero value while the cmd_buffer pointer is 0 is
+    used to indicate that the command data will be written to the SPI hardware
+    block using DMA.
+ 
+  @param rd_buffer
+    The rd_buffer parameter is a pointer to the buffer where the data received
+    from the slave after the command has been sent will be stored.
+ 
+  @param rd_byte_size
+    The rd_byte_size parameter specifies the number of bytes to be received from
+    the slave and stored in the rd_buffer. A value of 0 indicates that no data
+    is to be read from the slave. A non-zero value while the rd_buffer pointer
+    is null (0) is used to specify the receive size when using DMA to read from
+    the slave. 
+    Note:   All bytes received from the slave, including the bytes received
+            while the command is sent, will be read through DMA.
+  
+  Polled write transfer example:
+  @code
+      uint8_t master_tx_buffer[MASTER_TX_BUFFER] = 
+      {
+          0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A
+      };
+      MSS_SPI_init( &g_mss_spi0 );
+      MSS_SPI_configure_master_mode
+        (
+            &g_mss_spi0,
+            MSS_SPI_SLAVE_0,
+            MSS_SPI_MODE1,
+            MSS_SPI_PCLK_DIV_256,
+            MSS_SPI_BLOCK_TRANSFER_FRAME_SIZE
+         );
+     
+      MSS_SPI_set_slave_select( &g_mss_spi0, MSS_SPI_SLAVE_0 );
+      MSS_SPI_transfer_block
+        (
+            &g_mss_spi0,
+            master_tx_buffer,
+            sizeof(master_tx_buffer),
+            0,
+            0
+        );
+      MSS_SPI_clear_slave_select( &g_mss_spi0, MSS_SPI_SLAVE_0 );
+  @endcode
+ 
+  DMA transfer example:
+  In this example the transmit and receive buffers are not specified as part of
+  the call to MSS_SPI_transfer_block(). MSS_SPI_transfer_block() will only
+  prepare the MSS SPI hardware for a transfer. The MSS SPI transmit hardware
+  FIFO is filled using one DMA channel and a second DMA channel is used to read
+  the content of the MSS SPI receive hardware FIFO. The transmit and receive
+  buffers are specified by two separate calls to PDMA_start() to initiate DMA
+  transfers on the channel used for transmit data and the channel used for
+  receive data. 
+  @code
+      uint8_t master_tx_buffer[MASTER_RX_BUFFER] =
+      {
+          0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, 0xC8, 0xC9, 0xCA
+      };
+      uint8_t slave_rx_buffer[MASTER_RX_BUFFER] = 
+      {
+          0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A
+      };
+      MSS_SPI_init( &g_mss_spi0 );
+
+      MSS_SPI_configure_master_mode
+          (
+            &g_mss_spi0,
+            MSS_SPI_SLAVE_0,
+            MSS_SPI_MODE1,
+            MSS_SPI_PCLK_DIV_256,
+            MSS_SPI_BLOCK_TRANSFER_FRAME_SIZE
+         );
+      MSS_SPI_set_slave_select( &g_mss_spi0, MSS_SPI_SLAVE_0 );
+      MSS_SPI_transfer_block( &g_mss_spi0, 0, 0, 0, 0 );
+      PDMA_start
+        (
+            PDMA_CHANNEL_1,
+            PDMA_SPI0_RX_REGISTER,
+            (uint32_t)master_rx_buffer,
+            sizeof(master_rx_buffer)
+        ); 
+      PDMA_start
+        (
+            PDMA_CHANNEL_2,
+            (uint32_t)master_tx_buffer,
+            PDMA_SPI0_TX_REGISTER,
+            sizeof(master_tx_buffer)
+        ); 
+      while( PDMA_status(PDMA_CHANNEL_1) == 0 )
+      {
+          ;
+      }
+      MSS_SPI_clear_slave_select( &g_mss_spi0, MSS_SPI_SLAVE_0 );
+  @endcode
+ */
+void MSS_SPI_transfer_block
+(
+    mss_spi_instance_t * this_spi,
+    const uint8_t * cmd_buffer,
+    uint16_t cmd_byte_size,
+    uint8_t * rd_buffer,
+    uint16_t rd_byte_size
+);
+
+/*==============================================================================
+ * Slave functions
+ *============================================================================*/
+
+/***************************************************************************//**
+  The MSS_SPI_set_frame_rx_handler() function is used by MSS SPI slaves to
+  specify the receive handler function that will be called by the MSS SPI driver
+  interrupt handler when a a frame of data is received by the MSS SPI slave.
+  
+  @param this_spi
+    The this_spi parameter is a pointer to an mss_spi_instance_t structure
+    identifying the MSS SPI hardware block to be initialized. There are two such
+    data structures, g_mss_spi0 and g_mss_spi1, associated with MSS SPI 0 and
+    MSS SPI 1 respectively. This parameter must point to either the g_mss_spi0
+    or g_mss_spi1 global data structure defined within the SPI driver.
+    
+ 
+  @param rx_handler
+    The rx_handler parameter is a pointer to the frame receive handler that must
+    be called when a frame is received by the MSS SPI slave.
+ 
+  Example:
+  @code
+      uint32_t g_slave_rx_frame = 0;
+
+      void slave_frame_handler( uint32_t rx_frame )
+      {
+          g_slave_rx_frame = rx_frame;
+      }
+
+      int setup_slave( void )
+      {
+          const uint16_t frame_size = 25;
+          MSS_SPI_init( &g_mss_spi1 );
+          MSS_SPI_configure_slave_mode
+            (
+                &g_mss_spi0,
+                MSS_SPI_MODE2,
+                MSS_SPI_PCLK_DIV_64,
+                frame_size
+            );
+          MSS_SPI_set_frame_rx_handler( &g_mss_spi1, slave_frame_handler );
+      }
+  @endcode
+ */
+void MSS_SPI_set_frame_rx_handler
+(
+    mss_spi_instance_t * this_spi,
+    mss_spi_frame_rx_handler_t rx_handler
+);
+
+/***************************************************************************//**
+  The MSS_SPI_set_slave_tx_frame() function is used by MSS SPI slaves to specify
+  the frame that will be transmitted when a transaction is initiated by the SPI
+  master.
+  
+  @param this_spi
+    The this_spi parameter is a pointer to an mss_spi_instance_t structure
+    identifying the MSS SPI hardware block to be initialized. There are two such
+    data structures, g_mss_spi0 and g_mss_spi1, associated with MSS SPI 0 and
+    MSS SPI 1 respectively. This parameter must point to either the g_mss_spi0
+    or g_mss_spi1 global data structure defined within the SPI driver.
+    
+ 
+  @param frame_value
+    The frame_value parameter contains the value of the frame to be sent to the
+    master.
+    Note:   The bit length of the value to be transmitted to the master must be
+            specified as the frame_bit_length parameter in a previous call to
+            the MSS_SPI_configure_slave() function.
+
+  Example:
+  @code
+      const uint16_t frame_size = 25;
+      const uint32_t slave_tx_frame = 0x0110F761;
+      uint32_t master_rx;
+
+      MSS_SPI_init( &g_mss_spi1 );
+      MSS_SPI_configure_slave_mode
+        (
+            &g_mss_spi0,
+            MSS_SPI_MODE2,
+            MSS_SPI_PCLK_DIV_64,
+            frame_size
+        );
+      MSS_SPI_set_slave_tx_frame( &g_mss_spi1, slave_tx_frame );
+  @endcode
+ */
+void MSS_SPI_set_slave_tx_frame
+(
+    mss_spi_instance_t * this_spi,
+    uint32_t frame_value
+);
+
+/***************************************************************************//**
+  The MSS_SPI_set_slave_block_buffers() function is used to configure an MSS
+  SPI slave for block transfer operations. It specifies one or more of the
+  following:
+    - The data that will be transmitted when accessed by a master.
+    - The buffer where data received from a master will be stored.
+    - The handler function that must be called after the receive buffer has been
+      filled.
+    - The number of bytes that must be received from the master before the receive
+      handler function is called.
+  These parameters allow the following use cases:
+    - Slave performing an action after receiving a block of data from a master
+      containing a command. The action will be performed by the receive handler
+      based on the content of the receive data buffer.
+    - Slave returning a block of data to the master. The type of information is
+      always the same but the actual values change over time. For example,
+      returning the voltage of a predefined set of analog inputs.
+    - Slave returning data based on a command contained in the first part of the
+      SPI transaction. For example, reading the voltage of the analog input
+      specified by the first data byte by the master. This is achieved by using
+      the MSS_SPI_set_slave_block_buffers() function in conjunction with
+      functions MSS_SPI_set_cmd_handler() and MSS_SPI_set_cmd_response(). Please
+      refer to the MSS_SPI_set_cmd_handler() function description for details of
+      this use case.
+  
+  @param this_spi
+    The this_spi parameter is a pointer to an mss_spi_instance_t structure
+    identifying the MSS SPI hardware block to be initialized. There are two such
+    data structures, g_mss_spi0 and g_mss_spi1, associated with MSS SPI 0 and
+    MSS SPI 1 respectively. This parameter must point to either the g_mss_spi0
+    or g_mss_spi1 global data structure defined within the SPI driver.
+    
+ 
+  @param tx_buffer
+    The tx_buffer parameter is a pointer to a buffer containing the data that
+    will be sent to the master. This parameter can be set to 0 if the MSS SPI
+    slave is not intended to be the target of SPI read transactions.
+ 
+  @param tx_buff_size
+    The tx_buff_size parameter specifies the number of bytes contained in the
+    tx_buffer. This parameter can be set to 0 if the MSS SPI slave is not
+    intended to be the target of SPI read transactions.
+ 
+  @param rx_buffer
+    The rx_buffer parameter is a pointer to the buffer where data received from
+    the master will be stored. This parameter can be set to 0 if the MSS SPI
+    slave is not intended to be the target of SPI write or write-read
+    transactions.
+ 
+  @param rx_buff_size
+    The rx_buff_size parameter specifies the size of the receive buffer. It is
+    also the number of bytes that must be received before the receive handler
+    is called, if a receive handler is specified using the block_rx_handler
+    parameter. This parameter can be set to 0 if the MSS SPI slave is not
+    intended to be the target of SPI write or write-read transactions.
+ 
+  @param block_rx_handler
+    The block_rx_handler parameter is a pointer to a function that will be
+    called when the receive buffer has been filled. This parameter can be set
+    to 0 if the MSS SPI slave is not intended to be the target of SPI write or
+    write-read transactions.
+ 
+  Slave performing operation based on master command:
+  In this example the SPI slave is configured to receive 10 bytes of data or
+  command from the SPI slave and process the data received from the master.
+  @code
+     uint32_t nb_of_rx_handler_calls = 0;
+     
+     void spi1_block_rx_handler_b
+     (
+         uint8_t * rx_buff,
+         uint16_t rx_size
+     )
+     {
+         ++nb_of_rx_handler_calls;
+     }
+     
+     void setup_slave( void )
+     {
+         uint8_t slave_rx_buffer[10] = 
+         {
+             0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+         };
+         
+         MSS_SPI_init( &g_mss_spi1 );
+         MSS_SPI_configure_slave_mode
+            ( 
+                &g_mss_spi0,
+                MSS_SPI_MODE2,
+                MSS_SPI_PCLK_DIV_64,
+                MSS_SPI_BLOCK_TRANSFER_FRAME_SIZE
+            );
+         
+         MSS_SPI_set_slave_block_buffers
+             (
+                 &g_mss_spi1,
+                 0,
+                 0,
+                 slave_rx_buffer,
+                 sizeof(master_tx_buffer),
+                 spi1_block_rx_handler_b
+             );
+     }
+  @endcode
+  
+  Slave responding to command example:
+  In this example the slave will return data based on a command sent by the
+  master. The first part of the transaction is handled using polled mode where
+  each byte returned to the master is written as part of the interrupt service
+  routine. The second part of the transaction, where the slave returns data
+  based on the command value, is sent using a DMA transfer initiated by the
+  receive handler.
+  The MSS_SPI_set_slave_block_buffers() function specifies that five bytes of
+  preamble data will be transmitted before the actual response is sent by the
+  slave. These five bytes will be transmitted while the one byte command,
+  followed by four turnaround bytes, is received. The turnaround bytes give
+  time to the slave to call the command handler and setup the PDMA transfer
+  that will return the response data.
+ 
+  @code
+     #define SLAVE_NB_OF_COMMANDS    4
+     #define SLAVE_PACKET_LENGTH     8
+
+     const uint8_t g_slave_data_array[SLAVE_NB_OF_COMMANDS][SLAVE_PACKET_LENGTH] =
+     {
+         {0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08},
+         {0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18},
+         {0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28},
+         {0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38}
+     };
+     
+     void spi1_rx_handler_d
+     (
+         uint8_t * rx_buff,
+         uint32_t rx_size
+     )
+     {
+         uint8_t index;
+         const uint8_t * p_response;
+        
+         index = rx_buff[0];
+        
+         if(index < 4)
+         {
+             p_response = &g_slave_data_array[index][0];
+         }
+         else
+         {
+             p_response = &g_slave_data_array[0][0];
+         }
+        
+         PDMA_start
+         (
+             PDMA_CHANNEL_0,
+             (uint32_t)p_response,
+             PDMA_SPI1_TX_REGISTER,
+             SLAVE_PACKET_LENGTH
+         );
+     }
+     
+     void setup_slave( void )
+     {
+         uint8_t slave_tx_buffer[16] = { 0x12, 0x34, 0x56, 0x78, 0x9A };
+
+         PDMA_init();
+         PDMA->RATIO_HIGH_LOW = 0xFF;
+         PDMA_configure
+             (
+                 PDMA_CHANNEL_0,
+                 PDMA_TO_SPI_1,
+                 PDMA_LOW_PRIORITY | PDMA_BYTE_TRANSFER | PDMA_INC_SRC_ONE_BYTE,
+                 PDMA_DEFAULT_WRITE_ADJ
+             );
+    
+         MSS_SPI_init( &g_mss_spi1 );
+
+         MSS_SPI_configure_slave_mode
+             (
+                 &g_mss_spi1,
+                 MSS_SPI_MODE1,
+                 MSS_SPI_PCLK_DIV_256,
+                 MSS_SPI_BLOCK_TRANSFER_FRAME_SIZE
+             );
+        
+         MSS_SPI_set_slave_block_buffers
+             (
+                 &g_mss_spi1,
+                 slave_tx_buffer,
+                 5,
+                 slave_rx_buffer,
+                 sizeof(slave_rx_buffer),
+                 spi1_rx_handler_d
+             );
+        
+         MSS_SPI_set_cmd_handler
+             (
+                 &g_mss_spi1,
+                 spi1_slave_cmd_handler,
+                 1
+             );
+     }
+  @endcode
+ */
+void MSS_SPI_set_slave_block_buffers
+(
+    mss_spi_instance_t * this_spi,
+    const uint8_t * tx_buffer,
+    uint32_t tx_buff_size,
+    uint8_t * rx_buffer,
+    uint32_t rx_buff_size,
+    mss_spi_block_rx_handler_t block_rx_handler
+);
+
+
+/***************************************************************************//**
+  The MSS_SPI_set_cmd_handler() function specifies a command handler function
+  that will be called when the number of bytes received reaches the command size
+  specified as parameter.
+  This function is used by SPI slaves performing block transfers. Its purpose is
+  to allow a SPI slave to decide the data that will be returned to the master
+  while a SPI transaction is taking place. Typically, one of more command bytes
+  are sent by the master to request some specific data. The slave interprets the
+  command byte(s) while one or more turn-around bytes are transmitted. The
+  slave adjusts its transmit data buffer based on the command during the
+  turnaround time.
+  The diagram below provides an example of the use of this function where the
+  SPI slave returns data bytes D0 to D6 based on the value of a command. The
+  3 bytes long command is made up of a command opcode byte followed by an address
+  byte followed by a size byte. The cmd_handler() function specified through an
+  earlier call to MSS_SPI_set_cmd_handler() is called by the SPI driver once the
+  third byte is received. The cmd_handler() function interprets the command bytes
+  and calls MSS_SPI_set_cmd_response() to set the SPI slave's response transmit
+  buffer with the data to be transmitted after the turnaround bytes (T0 to T3).
+  The number of turnaround bytes must be sufficient to give enough time for the
+  cmd_handler() to execute. The number of turnaround bytes is specified by the
+  protocol used on top of the SPI transport layer so that master and slave agree
+  on the number of turn around bytes.
+
+    t0          t1       t2         t3                                 t4
+    |           |        |          |                                  |
+    |------------------------------------------------------------------|
+    |  COMMAND  |    TURN-AROUND    |               DATA               |
+    |------------------------------------------------------------------|
+    | C | A | S | T0 | T1 | T2 | T4 | D0 | D1 | D2 | D3 | D4 | D5 | D6 |
+    |------------------------------------------------------------------|
+                |
+                |
+                --> cmd_handler() called here.
+                         |
+                         |                          
+                         --> MSS_SPI_set_cmd_response() called here by
+                             implementation of cmd_handler() to set the data
+                             that will be transmitted by the SPI slave.
+
+  @param this_spi
+    The this_spi parameter is a pointer to an mss_spi_instance_t structure
+    identifying the MSS SPI hardware block used. There are two such data
+    structures, g_mss_spi0 and g_mss_spi1, associated with MSS SPI 0 and MSS SPI
+    1 respectively. This parameter must point to either the g_mss_spi0 or
+    g_mss_spi1 global data structure defined within the SPI driver.
+
+  @param cmd_handler
+    The cmd_handler parameter is a pointer to a function with prototype:
+        void cmd_handler(uint8_t * rx_buff, uint32_t rx_size);
+    It specifies the function that will be called when the number of bytes
+    specified by parameter cmd_size has been received.
+
+  @param cmd_size
+    The cmd_size parameter specifies the number of bytes that must be received
+    before the command handler function specified by cmd_handler is called.
+  
+  The example below demonstrates how to configure SPI1 to implement the protocol
+  given as example in the diagram above.
+  The configure_slave() function configures SPI1. It sets the receive and transmit
+  buffers. The transmit buffer specified through the call to
+  MSS_SPI_set_slave_block_buffers() specifies the data that will be returned to
+  the master in bytes between t0 and t3. These are the bytes that will be sent
+  to the master while the master transmits the command and dummy bytes.
+  The spi1_slave_cmd_handler() function will be called by the driver at time t1
+  after the 3 command bytes have been received.
+  The spi1_block_rx_handler() function will be called by the driver at time t4
+  when the transaction completes when the slave select signal becomes de-asserted.
+  
+  @code
+    #define COMMAND_SIZE            3
+    #define NB_OF_DUMMY_BYTES       4
+    #define MAX_TRANSACTION_SIZE    16
+    
+    uint8_t slave_tx_buffer[COMMAND_SIZE + NB_OF_DUMMY_BYTES];
+    uint8_t slave_rx_buffer[MAX_TRANSACTION_SIZE];
+    
+    void configure_slave(void)
+    {
+        MSS_SPI_init( &g_mss_spi1 );
+
+        MSS_SPI_configure_slave_mode
+          (
+            &g_mss_spi1,
+            MSS_SPI_MODE1,
+            MSS_SPI_PCLK_DIV_256,
+            MSS_SPI_BLOCK_TRANSFER_FRAME_SIZE
+          );
+      
+        MSS_SPI_set_slave_block_buffers
+            (
+                &g_mss_spi1,
+                slave_tx_buffer,
+                COMMAND_SIZE + NB_OF_DUMMY_BYTES,
+                slave_rx_buffer,
+                sizeof(slave_rx_buffer),
+                spi1_block_rx_handler
+            );
+            
+        
+        MSS_SPI_set_cmd_handler
+            (
+                &g_mss_spi1,
+                spi1_slave_cmd_handler,
+                COMMAND_SIZE
+            );
+    }   
+    
+    void spi1_slave_cmd_handler
+    (
+        uint8_t * rx_buff,
+        uint32_t rx_size
+    )
+    {
+        uint8_t command;
+        uint8_t address;
+        uint8_t size;
+        
+        uint8_t * p_response;
+        uint32_t response_size;
+        
+        command = rx_buff[0];
+        address = rx_buff[1];
+        size = rx_buff[2];
+        
+        p_response = get_response_data(command, address, size, &response_size);
+        
+        MSS_SPI_set_cmd_response(&g_mss_spi1, p_response, response_size);
+    }
+
+    void spi1_block_rx_handler
+    (
+        uint8_t * rx_buff,
+        uint32_t rx_size
+    )
+    {
+        process_rx_data(rx_buff, rx_size);
+    }    
+  @endcode
+ */
+void MSS_SPI_set_cmd_handler
+(
+    mss_spi_instance_t * this_spi,
+    mss_spi_block_rx_handler_t cmd_handler,
+    uint32_t cmd_size
+);
+
+/***************************************************************************//**
+ The MSS_SPI_set_cmd_response() function specifies the data that will be
+ returned to the master. See the description of MSS_SPI_set_cmd_handler() for
+ details.
+ 
+  @param this_spi
+    The this_spi parameter is a pointer to an mss_spi_instance_t structure
+    identifying the MSS SPI hardware block used. There are two such data
+    structures, g_mss_spi0 and g_mss_spi1, associated with MSS SPI 0 and MSS SPI
+    1 respectively. This parameter must point to either the g_mss_spi0 or
+    g_mss_spi1 global data structure defined within the SPI driver.
+
+  @param resp_tx_buffer
+    The resp_tx_buffer parameter is a pointer to the buffer containing the data
+    that must be returned to the host in the data phase of a SPI transaction.
+  
+  @param resp_buff_size
+    The resp_buff_size parameter specifies the size of the buffer pointed to by
+    the resp_tx_buffer parameter.
+ */
+void MSS_SPI_set_cmd_response
+(
+    mss_spi_instance_t * this_spi,
+    const uint8_t * resp_tx_buffer,
+    uint32_t resp_buff_size
+);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* MSS_SPI_H_*/
diff --git a/board/actel/sf2-dev-kit/zl30362_config.c b/board/actel/sf2-dev-kit/zl30362_config.c
new file mode 100644
index 0000000000000000000000000000000000000000..8589737f3f38b4b3a0fd86765d8ae0e13a8f3cdb
--- /dev/null
+++ b/board/actel/sf2-dev-kit/zl30362_config.c
@@ -0,0 +1,856 @@
+/*******************************************************************************
+ * (c) Copyright 2012 Microsemi Corporation.  All rights reserved.
+ *
+ *  Configure ZL30363 device.
+ *
+ * SVN $Revision: $
+ * SVN $Date: $
+ */
+
+#include <common.h>
+#include "mss_spi/mss_spi.h"
+
+/*==============================================================================
+ * ZL30362 configuration.
+ * The values for this configuration were created using the ZL30362 GUI.
+ */
+const uint8_t g_zl30362_config[] =
+{
+    // ClockCenter Register Configuration File
+    // Exported from GUI Ver. 2.1.0, 11:39:15, Nov 26, 2012
+    // Product family ZL30362
+    0x9F,        // Register address 0x0: Ready indicator
+    0x3E,        // Register address 0x1: ID_Register
+    0x02,        // Register address 0x2: HW Revision
+    0x00,        // Register address 0x3: Reserved
+    0x00,        // Register address 0x4: Reserved
+    0x05,        // Register address 0x5: Reserved
+    0xF6,        // Register address 0x6: Reserved
+    0xFF,        // Register address 0x7: Customer identification [31:24]
+    0xFF,        // Register address 0x8: Customer identification [23:16]
+    0xFF,        // Register address 0x9: Customer identification [15:8]
+    0xFF,        // Register address 0xA: Customer identification [7:0]
+    0x04,        // Register address 0xB: Central Freq Offset [31:24]
+    0x6A,        // Register address 0xC: Central Freq Offset [23:16]
+    0xAA,        // Register address 0xD: Central Freq Offset [15:8]
+    0xAB,        // Register address 0xE: Central Freq Offset [7:0]
+    0x00,        // Register address 0xF: Reserved
+    0x00,        // Register address 0x10: APLL Frequency Offset
+    0x00,        // Register address 0x11: Sticky Lock Register
+    0x00,        // Register address 0x12: Reserved
+    0x00,        // Register address 0x13: Reserved
+    0x00,        // Register address 0x14: Reserved
+    0x00,        // Register address 0x15: Reserved
+    0x00,        // Register address 0x16: Reserved
+    0x00,        // Register address 0x17: Reserved
+    0x01,        // Register address 0x18: Reset Status
+    0xF7,        // Register address 0x19: GPIO at Startup [15:8]
+    0x00,        // Register address 0x1A: GPIO at Startup [7:0]
+    0x00,        // Register address 0x1B: Reserved
+    0x00,        // Register address 0x1C: Reserved
+    0x00,        // Register address 0x1D: Reserved
+    0x00,        // Register address 0x1E: Reserved
+    0x00,        // Register address 0x1F: Reserved
+    0x00,        // Register address 0x20: Reference Fail 7-0
+    0x00,        // Register address 0x21: Reference Fail 10-8
+    0x00,        // Register address 0x22: DPLL Status
+    0x00,        // Register address 0x23: Ref Fail Mask 7-0
+    0x00,        // Register address 0x24: Ref Fail Mask 10-8
+    0x00,        // Register address 0x25: DPLL Fail Mask
+    0x1E,        // Register address 0x26: Reference Monitor Fail 0
+    0x1E,        // Register address 0x27: Reference Monitor Fail 1
+    0x1E,        // Register address 0x28: Reference Monitor Fail 2
+    0x1E,        // Register address 0x29: Reference Monitor Fail 3
+    0x1E,        // Register address 0x2A: Reference Monitor Fail 4
+    0x1E,        // Register address 0x2B: Reference Monitor Fail 5
+    0x1E,        // Register address 0x2C: Reference Monitor Fail 6
+    0x1E,        // Register address 0x2D: Reference Monitor Fail 7
+    0x1E,        // Register address 0x2E: Reference Monitor Fail 8
+    0x1E,        // Register address 0x2F: Reference Monitor Fail 9
+    0x1E,        // Register address 0x30: Reference Monitor Fail 10
+    0x00,        // Register address 0x31: Reserved
+    0x00,        // Register address 0x32: Reserved
+    0x00,        // Register address 0x33: Reserved
+    0x00,        // Register address 0x34: Reserved
+    0x00,        // Register address 0x35: Reserved
+    0x16,        // Register address 0x36: Reference Monitor Mask 0
+    0x16,        // Register address 0x37: Reference Monitor Mask 1
+    0x16,        // Register address 0x38: Reference Monitor Mask 2
+    0x16,        // Register address 0x39: Reference Monitor Mask 3
+    0x16,        // Register address 0x3A: Reference Monitor Mask 4
+    0x16,        // Register address 0x3B: Reference Monitor Mask 5
+    0x16,        // Register address 0x3C: Reference Monitor Mask 6
+    0x16,        // Register address 0x3D: Reference Monitor Mask 7
+    0x16,        // Register address 0x3E: Reference Monitor Mask 8
+    0x16,        // Register address 0x3F: Reference Monitor Mask 9
+    0x16,        // Register address 0x40: Reference Monitor Mask 10
+    0x00,        // Register address 0x41: Reserved
+    0x00,        // Register address 0x42: Reserved
+    0x00,        // Register address 0x43: Reserved
+    0x00,        // Register address 0x44: Reserved
+    0x00,        // Register address 0x45: Reserved
+    0xAA,        // Register address 0x46: GST Disqualify Time 3-0
+    0xAA,        // Register address 0x47: GST Disqualify Time 7-4
+    0x2A,        // Register address 0x48: GST Disqualify Time 10-8
+    0x00,        // Register address 0x49: Reserved
+    0x55,        // Register address 0x4A: GST Qualify Time 3-0
+    0x55,        // Register address 0x4B: GST Qualify Time 7-4
+    0x15,        // Register address 0x4C: GST Qualify Time 10-8
+    0x00,        // Register address 0x4D: Reserved
+    0x00,        // Register address 0x4E: Reserved
+    0x00,        // Register address 0x4F: Reserved
+    0x55,        // Register address 0x50: SCM/CFM Limit 0
+    0x55,        // Register address 0x51: SCM/CFM Limit 1
+    0x55,        // Register address 0x52: SCM/CFM Limit 2
+    0x55,        // Register address 0x53: SCM/CFM Limit 3
+    0x55,        // Register address 0x54: SCM/CFM Limit 4
+    0x55,        // Register address 0x55: SCM/CFM Limit 5
+    0x55,        // Register address 0x56: SCM/CFM Limit 6
+    0x55,        // Register address 0x57: SCM/CFM Limit 7
+    0x55,        // Register address 0x58: SCM/CFM Limit 8
+    0x55,        // Register address 0x59: SCM/CFM Limit 9
+    0x55,        // Register address 0x5A: SCM/CFM Limit 10
+    0x00,        // Register address 0x5B: Reserved
+    0x00,        // Register address 0x5C: Reserved
+    0x00,        // Register address 0x5D: Reserved
+    0x00,        // Register address 0x5E: Reserved
+    0x00,        // Register address 0x5F: Reserved
+    0x33,        // Register address 0x60: PFM Limit 1-0
+    0x33,        // Register address 0x61: PFM Limit 3-2
+    0x33,        // Register address 0x62: PFM Limit 5-4
+    0x33,        // Register address 0x63: PFM Limit 7-6
+    0x33,        // Register address 0x64: PFM Limit 9-8
+    0x03,        // Register address 0x65: PFM Limit 10
+    0x00,        // Register address 0x66: Reserved
+    0x00,        // Register address 0x67: Reserved
+    0xFF,        // Register address 0x68: Phase Acquisition Enable 7-0
+    0x07,        // Register address 0x69: Phase Acquisition Enable 10-8
+    0x0A,        // Register address 0x6A: Phase Memory Limit 0
+    0x0A,        // Register address 0x6B: Phase Memory Limit 1
+    0x0A,        // Register address 0x6C: Phase Memory Limit 2
+    0x0A,        // Register address 0x6D: Phase Memory Limit 3
+    0x0A,        // Register address 0x6E: Phase Memory Limit 4
+    0x0A,        // Register address 0x6F: Phase Memory Limit 5
+    0x0A,        // Register address 0x70: Phase Memory Limit 6
+    0x0A,        // Register address 0x71: Phase Memory Limit 7
+    0x0A,        // Register address 0x72: Phase Memory Limit 8
+    0x0A,        // Register address 0x73: Phase Memory Limit 9
+    0x0A,        // Register address 0x74: Phase Memory Limit 10
+    0x00,        // Register address 0x75: Reserved
+    0x00,        // Register address 0x76: Reserved
+    0x00,        // Register address 0x77: Reserved
+    0x00,        // Register address 0x78: Reserved
+    0x00,        // Register address 0x79: Reserved
+    0x00,        // Register address 0x7A: Reference Config 7-0
+    0x00,        // Register address 0x7B: Reference Config 8
+    0x00,        // Register address 0x7C: Reference Pre-divide 7-0
+    0x00,        // Register address 0x7D: Reference Pre-divide 10-8
+    0x00,        // Register address 0x7E: Microport Status
+    0x01,        // Register address 0x7F: Page Select
+    0x9C,        // Register address 0x80: Ref0 Base Freq Br [15:8]
+    0x40,        // Register address 0x81: Ref0 Base Freq Br [7:0]
+    0x0F,        // Register address 0x82: Ref0 Frequency Multiple Kr [15:8]
+    0x30,        // Register address 0x83: Ref0 Frequency Multiple Kr [7:0]
+    0x00,        // Register address 0x84: Ref0 Numerator Mr [15:8]
+    0x01,        // Register address 0x85: Ref0 Numerator Mr [7:0]
+    0x00,        // Register address 0x86: Ref0 Denominator Nr [15:8]
+    0x01,        // Register address 0x87: Ref0 Denominator Nr [7:0]
+    0x9C,        // Register address 0x88: Ref1 Base Freq Br [15:8]
+    0x40,        // Register address 0x89: Ref1 Base Freq Br [7:0]
+    0x01,        // Register address 0x8A: Ref1 Frequency Multiple Kr [15:8]
+    0xE6,        // Register address 0x8B: Ref1 Frequency Multiple Kr [7:0]
+    0x00,        // Register address 0x8C: Ref1 Numerator Mr [15:8]
+    0x01,        // Register address 0x8D: Ref1 Numerator Mr [7:0]
+    0x00,        // Register address 0x8E: Ref1 Denominator Nr [15:8]
+    0x01,        // Register address 0x8F: Ref1 Denominator Nr [7:0]
+    0x9C,        // Register address 0x90: Ref2 Base Freq Br [15:8]
+    0x40,        // Register address 0x91: Ref2 Base Freq Br [7:0]
+    0x01,        // Register address 0x92: Ref2 Frequency Multiple Kr [15:8]
+    0xE6,        // Register address 0x93: Ref2 Frequency Multiple Kr [7:0]
+    0x00,        // Register address 0x94: Ref2 Numerator Mr [15:8]
+    0x01,        // Register address 0x95: Ref2 Numerator Mr [7:0]
+    0x00,        // Register address 0x96: Ref2 Denominator Nr [15:8]
+    0x01,        // Register address 0x97: Ref2 Denominator Nr [7:0]
+    0x9C,        // Register address 0x98: Ref3 Base Freq Br [15:8]
+    0x40,        // Register address 0x99: Ref3 Base Freq Br [7:0]
+    0x01,        // Register address 0x9A: Ref3 Frequency Multiple Kr [15:8]
+    0xE6,        // Register address 0x9B: Ref3 Frequency Multiple Kr [7:0]
+    0x00,        // Register address 0x9C: Ref3 Numerator Mr [15:8]
+    0x01,        // Register address 0x9D: Ref3 Numerator Mr [7:0]
+    0x00,        // Register address 0x9E: Ref3 Denominator Nr [15:8]
+    0x01,        // Register address 0x9F: Ref3 Denominator Nr [7:0]
+    0x9C,        // Register address 0xA0: Ref4 Base Freq Br [15:8]
+    0x40,        // Register address 0xA1: Ref4 Base Freq Br [7:0]
+    0x01,        // Register address 0xA2: Ref4 Frequency Multiple Kr [15:8]
+    0xE6,        // Register address 0xA3: Ref4 Frequency Multiple Kr [7:0]
+    0x00,        // Register address 0xA4: Ref4 Numerator Mr [15:8]
+    0x01,        // Register address 0xA5: Ref4 Numerator Mr [7:0]
+    0x00,        // Register address 0xA6: Ref4 Denominator Nr [15:8]
+    0x01,        // Register address 0xA7: Ref4 Denominator Nr [7:0]
+    0x9C,        // Register address 0xA8: Ref5 Base Freq Br [15:8]
+    0x40,        // Register address 0xA9: Ref5 Base Freq Br [7:0]
+    0x01,        // Register address 0xAA: Ref5 Frequency Multiple Kr [15:8]
+    0xE6,        // Register address 0xAB: Ref5 Frequency Multiple Kr [7:0]
+    0x00,        // Register address 0xAC: Ref5 Numerator Mr [15:8]
+    0x01,        // Register address 0xAD: Ref5 Numerator Mr [7:0]
+    0x00,        // Register address 0xAE: Ref5 Denominator Nr [15:8]
+    0x01,        // Register address 0xAF: Ref5 Denominator Nr [7:0]
+    0x9C,        // Register address 0xB0: Ref6 Base Freq Br [15:8]
+    0x40,        // Register address 0xB1: Ref6 Base Freq Br [7:0]
+    0x01,        // Register address 0xB2: Ref6 Frequency Multiple Kr [15:8]
+    0xE6,        // Register address 0xB3: Ref6 Frequency Multiple Kr [7:0]
+    0x00,        // Register address 0xB4: Ref6 Numerator Mr [15:8]
+    0x01,        // Register address 0xB5: Ref6 Numerator Mr [7:0]
+    0x00,        // Register address 0xB6: Ref6 Denominator Nr [15:8]
+    0x01,        // Register address 0xB7: Ref6 Denominator Nr [7:0]
+    0x9C,        // Register address 0xB8: Ref7 Base Freq Br [15:8]
+    0x40,        // Register address 0xB9: Ref7 Base Freq Br [7:0]
+    0x01,        // Register address 0xBA: Ref7 Frequency Multiple Kr [15:8]
+    0xE6,        // Register address 0xBB: Ref7 Frequency Multiple Kr [7:0]
+    0x00,        // Register address 0xBC: Ref7 Numerator Mr [15:8]
+    0x01,        // Register address 0xBD: Ref7 Numerator Mr [7:0]
+    0x00,        // Register address 0xBE: Ref7 Denominator Nr [15:8]
+    0x01,        // Register address 0xBF: Ref7 Denominator Nr [7:0]
+    0x9C,        // Register address 0xC0: Ref8 Base Freq Br [15:8]
+    0x40,        // Register address 0xC1: Ref8 Base Freq Br [7:0]
+    0x01,        // Register address 0xC2: Ref8 Frequency Multiple Kr [15:8]
+    0xE6,        // Register address 0xC3: Ref8 Frequency Multiple Kr [7:0]
+    0x00,        // Register address 0xC4: Ref8 Numerator Mr [15:8]
+    0x01,        // Register address 0xC5: Ref8 Numerator Mr [7:0]
+    0x00,        // Register address 0xC6: Ref8 Denominator Nr [15:8]
+    0x01,        // Register address 0xC7: Ref8 Denominator Nr [7:0]
+    0x9C,        // Register address 0xC8: Ref9 Base Freq Br [15:8]
+    0x40,        // Register address 0xC9: Ref9 Base Freq Br [7:0]
+    0x01,        // Register address 0xCA: Ref9 Frequency Multiple Kr [15:8]
+    0xE6,        // Register address 0xCB: Ref9 Frequency Multiple Kr [7:0]
+    0x00,        // Register address 0xCC: Ref9 Numerator Mr [15:8]
+    0x01,        // Register address 0xCD: Ref9 Numerator Mr [7:0]
+    0x00,        // Register address 0xCE: Ref9 Denominator Nr [15:8]
+    0x01,        // Register address 0xCF: Ref9 Denominator Nr [7:0]
+    0x9C,        // Register address 0xD0: Ref10 Base Freq Br [15:8]
+    0x40,        // Register address 0xD1: Ref10 Base Freq Br [7:0]
+    0x01,        // Register address 0xD2: Ref10 Frequency Multiple Kr [15:8]
+    0xE6,        // Register address 0xD3: Ref10 Frequency Multiple Kr [7:0]
+    0x00,        // Register address 0xD4: Ref10 Numerator Mr [15:8]
+    0x01,        // Register address 0xD5: Ref10 Numerator Mr [7:0]
+    0x00,        // Register address 0xD6: Ref10 Denominator Nr [15:8]
+    0x01,        // Register address 0xD7: Ref10 Denominator Nr [7:0]
+    0x00,        // Register address 0xD8: Reserved
+    0x00,        // Register address 0xD9: Reserved
+    0x00,        // Register address 0xDA: Reserved
+    0x00,        // Register address 0xDB: Reserved
+    0x00,        // Register address 0xDC: Reserved
+    0x00,        // Register address 0xDD: Reserved
+    0x00,        // Register address 0xDE: Reserved
+    0x00,        // Register address 0xDF: Reserved
+    0x00,        // Register address 0xE0: Reserved
+    0x00,        // Register address 0xE1: Reserved
+    0x00,        // Register address 0xE2: Reserved
+    0x00,        // Register address 0xE3: Reserved
+    0x00,        // Register address 0xE4: Reserved
+    0x00,        // Register address 0xE5: Reserved
+    0x00,        // Register address 0xE6: Reserved
+    0x00,        // Register address 0xE7: Reserved
+    0x00,        // Register address 0xE8: Reserved
+    0x00,        // Register address 0xE9: Reserved
+    0x00,        // Register address 0xEA: Reserved
+    0x00,        // Register address 0xEB: Reserved
+    0x10,        // Register address 0xEC: Clock Sync Pulse 1-0
+    0x32,        // Register address 0xED: Clock Sync Pulse 3-2
+    0x54,        // Register address 0xEE: Clock Sync Pulse 5-4
+    0x76,        // Register address 0xEF: Clock Sync Pulse 7-6
+    0x98,        // Register address 0xF0: Clock Sync Pulse 9-8
+    0x0A,        // Register address 0xF1: Clock Sync Pulse 10
+    0x00,        // Register address 0xF2: Reserved
+    0x00,        // Register address 0xF3: Reserved
+    0x00,        // Register address 0xF4: Reserved
+    0x00,        // Register address 0xF5: Reserved
+    0x00,        // Register address 0xF6: Reserved
+    0x00,        // Register address 0xF7: Reserved
+    0x00,        // Register address 0xF8: Reserved
+    0x00,        // Register address 0xF9: Reserved
+    0x00,        // Register address 0xFA: Reserved
+    0x00,        // Register address 0xFB: Reserved
+    0x00,        // Register address 0xFC: Reserved
+    0x00,        // Register address 0xFD: Reserved
+    0x00,        // Register address 0xFE: Reserved
+    0x02,        // Register address 0xFF: Page Select
+    0x0C,        // Register address 0x100: DPLL0 Control
+    0x00,        // Register address 0x101: DPLL0 Bandwidth Select
+    0x00,        // Register address 0x102: DPLL0 Pull-in/Hold-in Select
+    0x00,        // Register address 0x103: DPLL0 Mode/Reference Select
+    0x00,        // Register address 0x104: DPLL0 Reference Select Status
+    0x10,        // Register address 0x105: DPLL0 Ref Priority 1-0
+    0x32,        // Register address 0x106: DPLL0 Ref Priority 3-2
+    0x54,        // Register address 0x107: DPLL0 Ref Priority 5-4
+    0x76,        // Register address 0x108: DPLL0 Ref Priority 7-6
+    0x98,        // Register address 0x109: DPLL0 Ref Priority 9-8
+    0x0A,        // Register address 0x10A: DPLL0 Ref Priority 10
+    0x00,        // Register address 0x10B: Reserved
+    0x00,        // Register address 0x10C: Reserved
+    0x87,        // Register address 0x10D: DPLL0 Ref Fail Mask
+    0x01,        // Register address 0x10E: DPLL0 PFM Fail Mask
+    0x0B,        // Register address 0x10F: DPLL0 Holdover Delay/Edge Sel
+    0x00,        // Register address 0x110: DPLL0 Phase Buildout Control
+    0x23,        // Register address 0x111: DPLL0 PBO Phase Error Threshold
+    0x70,        // Register address 0x112: DPLL0 PBO Min Phase Slope
+    0x20,        // Register address 0x113: DPLL0 PBO End Interval
+    0x64,        // Register address 0x114: DPLL0 PBO Timeout
+    0x00,        // Register address 0x115: DPLL0 PBO Counter
+    0x00,        // Register address 0x116: DPLL0 PBO Error Count [23:16]
+    0x00,        // Register address 0x117: DPLL0 PBO Error Count [15:8]
+    0x00,        // Register address 0x118: DPLL0 PBO Error Count [7:0]
+    0x05,        // Register address 0x119: Reserved
+    0x05,        // Register address 0x11A: Reserved
+    0x00,        // Register address 0x11B: Reserved
+    0x00,        // Register address 0x11C: Reserved
+    0x00,        // Register address 0x11D: Reserved
+    0x00,        // Register address 0x11E: Reserved
+    0x00,        // Register address 0x11F: Reserved
+    0x0C,        // Register address 0x120: DPLL1 Control
+    0x00,        // Register address 0x121: DPLL1 Bandwidth Select
+    0x00,        // Register address 0x122: DPLL1 Pull-in/Hold-in Select
+    0x03,        // Register address 0x123: DPLL1 Mode/Reference Select
+    0x00,        // Register address 0x124: DPLL1 Reference Select Status
+    0x10,        // Register address 0x125: DPLL1 Ref Priority 1-0
+    0x32,        // Register address 0x126: DPLL1 Ref Priority 3-2
+    0x54,        // Register address 0x127: DPLL1 Ref Priority 5-4
+    0x76,        // Register address 0x128: DPLL1 Ref Priority 7-6
+    0x98,        // Register address 0x129: DPLL1 Ref Priority 9-8
+    0x0A,        // Register address 0x12A: DPLL1 Ref Priority 10
+    0x00,        // Register address 0x12B: Reserved
+    0x00,        // Register address 0x12C: Reserved
+    0x87,        // Register address 0x12D: DPLL1 Ref Fail Mask
+    0x01,        // Register address 0x12E: DPLL1 PFM Fail Mask
+    0x0B,        // Register address 0x12F: DPLL1 Holdover Delay/Edge Sel
+    0x00,        // Register address 0x130: DPLL1 Phase Buildout Control
+    0x23,        // Register address 0x131: DPLL1 PBO Jitter Threshold
+    0x70,        // Register address 0x132: DPLL1 PBO Min Phase Slope
+    0x20,        // Register address 0x133: DPLL1 PBO End Interval
+    0x64,        // Register address 0x134: DPLL1 PBO Timeout
+    0x00,        // Register address 0x135: DPLL1 PBO Counter
+    0x00,        // Register address 0x136: DPLL1 PBO Error Count [23:16]
+    0x00,        // Register address 0x137: DPLL1 PBO Error Count [15:8]
+    0x00,        // Register address 0x138: DPLL1 PBO Error Count [7:0]
+    0x05,        // Register address 0x139: Reserved
+    0x05,        // Register address 0x13A: Reserved
+    0x00,        // Register address 0x13B: Reserved
+    0x00,        // Register address 0x13C: Reserved
+    0x00,        // Register address 0x13D: Reserved
+    0x00,        // Register address 0x13E: Reserved
+    0x00,        // Register address 0x13F: Reserved
+    0x0C,        // Register address 0x140: DPLL2 Control
+    0x00,        // Register address 0x141: DPLL2 Bandwidth Select
+    0x00,        // Register address 0x142: DPLL2 Pull-in/Hold-in Select
+    0x03,        // Register address 0x143: DPLL2 Mode/Reference Select
+    0x00,        // Register address 0x144: DPLL2 Reference Select Status
+    0x10,        // Register address 0x145: DPLL2 Ref Priority 1-0
+    0x32,        // Register address 0x146: DPLL2 Ref Priority 3-2
+    0x54,        // Register address 0x147: DPLL2 Ref Priority 5-4
+    0x76,        // Register address 0x148: DPLL2 Ref Priority 7-6
+    0x98,        // Register address 0x149: DPLL2 Ref Priority 9-8
+    0x0A,        // Register address 0x14A: DPLL2 Ref Priority 10
+    0x00,        // Register address 0x14B: Reserved
+    0x00,        // Register address 0x14C: Reserved
+    0x87,        // Register address 0x14D: DPLL2 Ref Fail Mask
+    0x01,        // Register address 0x14E: DPLL2 PFM Fail Mask
+    0x0B,        // Register address 0x14F: DPLL2 Holdover Delay/Edge Sel
+    0x00,        // Register address 0x150: DPLL2 Phase Buildout Control
+    0x23,        // Register address 0x151: DPLL2 PBO Jitter Threshold
+    0x70,        // Register address 0x152: DPLL2 PBO Min Phase Slope
+    0x20,        // Register address 0x153: DPLL2 PBO End Interval
+    0x64,        // Register address 0x154: DPLL2 PBO Timeout
+    0x00,        // Register address 0x155: DPLL2 PBO Counter
+    0x00,        // Register address 0x156: DPLL2 PBO Error Count [23:16]
+    0x00,        // Register address 0x157: DPLL2 PBO Error Count [15:8]
+    0x00,        // Register address 0x158: DPLL2 PBO Error Count [7:0]
+    0x05,        // Register address 0x159: Reserved
+    0x05,        // Register address 0x15A: Reserved
+    0x00,        // Register address 0x15B: Reserved
+    0x00,        // Register address 0x15C: Reserved
+    0x00,        // Register address 0x15D: Reserved
+    0x00,        // Register address 0x15E: Reserved
+    0x00,        // Register address 0x15F: Reserved
+    0x0C,        // Register address 0x160: DPLL3 Control
+    0x00,        // Register address 0x161: DPLL3 Bandwidth Select
+    0x00,        // Register address 0x162: DPLL3 Pull-in/Hold-in Select
+    0x00,        // Register address 0x163: DPLL3 Mode/Reference Select
+    0x00,        // Register address 0x164: DPLL3 Reference Select Status
+    0x10,        // Register address 0x165: DPLL3 Ref Priority 1-0
+    0x32,        // Register address 0x166: DPLL3 Ref Priority 3-2
+    0x54,        // Register address 0x167: DPLL3 Ref Priority 5-4
+    0x76,        // Register address 0x168: DPLL3 Ref Priority 7-6
+    0x98,        // Register address 0x169: DPLL3 Ref Priority 9-8
+    0x0A,        // Register address 0x16A: DPLL3 Ref Priority 10
+    0x00,        // Register address 0x16B: Reserved
+    0x00,        // Register address 0x16C: Reserved
+    0x87,        // Register address 0x16D: DPLL3 Ref Fail Mask
+    0x01,        // Register address 0x16E: DPLL3 PFM Fail Mask
+    0x0B,        // Register address 0x16F: DPLL3 Holdover Delay/Edge Sel
+    0x00,        // Register address 0x170: DPLL3 Phase Buildout Control
+    0x23,        // Register address 0x171: DPLL3 PBO Jitter Threshold
+    0x70,        // Register address 0x172: DPLL3 PBO Min Phase Slope
+    0x20,        // Register address 0x173: DPLL3 PBO End Interval
+    0x64,        // Register address 0x174: DPLL3 PBO Timeout
+    0x00,        // Register address 0x175: DPLL3 PBO Counter
+    0x00,        // Register address 0x176: DPLL3 PBO Error Count [23:16]
+    0x00,        // Register address 0x177: DPLL3 PBO Error Count [15:8]
+    0x00,        // Register address 0x178: DPLL3 PBO Error Count [7:0]
+    0x05,        // Register address 0x179: Reserved
+    0x05,        // Register address 0x17A: Reserved
+    0x00,        // Register address 0x17B: Reserved
+    0x00,        // Register address 0x17C: Reserved
+    0x00,        // Register address 0x17D: Reserved
+    0x00,        // Register address 0x17E: Reserved
+    0x03,        // Register address 0x17F: Page Select
+    0x14,        // Register address 0x180: DPLL Hold/Lock Status
+    0x00,        // Register address 0x181: External Feedback Control
+    0x04,        // Register address 0x182: DPLL Configuration
+    0x00,        // Register address 0x183: DPLL Lock Selection
+    0x00,        // Register address 0x184: DPLL 1pps Alignment
+    0x00,        // Register address 0x185: Reserved
+    0x00,        // Register address 0x186: Reserved
+    0x00,        // Register address 0x187: Reserved
+    0x00,        // Register address 0x188: Reserved
+    0x00,        // Register address 0x189: Reserved
+    0x00,        // Register address 0x18A: Reserved
+    0x00,        // Register address 0x18B: Reserved
+    0x00,        // Register address 0x18C: Reserved
+    0x00,        // Register address 0x18D: DPLL0 Delta Freq Offset [39:32]
+    0x00,        // Register address 0x18E: DPLL0 Delta Freq Offset [31:24]
+    0x00,        // Register address 0x18F: DPLL0 Delta Freq Offset [23:16]
+    0x00,        // Register address 0x190: DPLL0 Delta Freq Offset [15:8]
+    0x00,        // Register address 0x191: DPLL0 Delta Freq Offset [7:0]
+    0x00,        // Register address 0x192: DPLL1 Delta Freq Offset [39:32]
+    0x00,        // Register address 0x193: DPLL1 Delta Freq Offset [31:24]
+    0x00,        // Register address 0x194: DPLL1 Delta Freq Offset [23:16]
+    0x00,        // Register address 0x195: DPLL1 Delta Freq Offset [15:8]
+    0x00,        // Register address 0x196: DPLL1 Delta Freq Offset [7:0]
+    0x00,        // Register address 0x197: DPLL2 Delta Freq Offset [39:32]
+    0x00,        // Register address 0x198: DPLL2 Delta Freq Offset [31:24]
+    0x00,        // Register address 0x199: DPLL2 Delta Freq Offset [23:16]
+    0x00,        // Register address 0x19A: DPLL2 Delta Freq Offset [15:8]
+    0x00,        // Register address 0x19B: DPLL2 Delta Freq Offset [7:0]
+    0x00,        // Register address 0x19C: DPLL3 Delta Freq Offset [39:32]
+    0x00,        // Register address 0x19D: DPLL3 Delta Freq Offset [31:24]
+    0x00,        // Register address 0x19E: DPLL3 Delta Freq Offset [23:16]
+    0x00,        // Register address 0x19F: DPLL3 Delta Freq Offset [15:8]
+    0x00,        // Register address 0x1A0: DPLL3 Delta Freq Offset [7:0]
+    0x00,        // Register address 0x1A1: Reserved
+    0x00,        // Register address 0x1A2: Reserved
+    0x00,        // Register address 0x1A3: Reserved
+    0x00,        // Register address 0x1A4: Reserved
+    0x00,        // Register address 0x1A5: Reserved
+    0x00,        // Register address 0x1A6: Reserved
+    0x00,        // Register address 0x1A7: Reserved
+    0x00,        // Register address 0x1A8: Reserved
+    0x00,        // Register address 0x1A9: Reserved
+    0x00,        // Register address 0x1AA: Reserved
+    0x00,        // Register address 0x1AB: Reserved
+    0x00,        // Register address 0x1AC: Reserved
+    0x00,        // Register address 0x1AD: Reserved
+    0x00,        // Register address 0x1AE: Reserved
+    0x00,        // Register address 0x1AF: Reserved
+    0xE4,        // Register address 0x1B0: DPLL->Synth Drive Select
+    0x0B,        // Register address 0x1B1: Synthesizer Enable
+    0x00,        // Register address 0x1B2: Synthesizer Filter Select
+    0x00,        // Register address 0x1B3: Reserved
+    0x00,        // Register address 0x1B4: Reserved
+    0x00,        // Register address 0x1B5: Synth Prescale Select
+    0x02,        // Register address 0x1B6: Synth fail Status
+    0x00,        // Register address 0x1B7: Synth Clear Fail Flag
+    0x61,        // Register address 0x1B8: Synth0 Base Frequency Bs [15:8]
+    0xA8,        // Register address 0x1B9: Synth0 Base Frequency Bs [7:0]
+    0x09,        // Register address 0x1BA: Synth0 Freq Multiple Ks [15:8]
+    0xC4,        // Register address 0x1BB: Synth0 Freq Multiple Ks [7:0]
+    0x00,        // Register address 0x1BC: Synth0 Numerator Ms [15:8]
+    0x01,        // Register address 0x1BD: Synth0 Numerator Ms [7:0]
+    0x00,        // Register address 0x1BE: Synth0 Denominator Ns [15:8]
+    0x01,        // Register address 0x1BF: Synth0 Denominator Ns [7:0]
+    0x61,        // Register address 0x1C0: Synth1 Base Frequency [15:8]
+    0xA8,        // Register address 0x1C1: Synth1 Base Frequency [7:0]
+    0x0C,        // Register address 0x1C2: Synth1 Freq Multiple Ks [15:8]
+    0x35,        // Register address 0x1C3: Synth1 Freq Multiple Ks [7:0]
+    0x00,        // Register address 0x1C4: Synth1 Numerator Ms [15:8]
+    0x01,        // Register address 0x1C5: Synth1 Numerator Ms [7:0]
+    0x00,        // Register address 0x1C6: Synth1 Denominator Ns [15:8]
+    0x01,        // Register address 0x1C7: Synth1 Denominator Ns [7:0]
+    0x9C,        // Register address 0x1C8: Synth2 Base Frequency [15:8]
+    0x40,        // Register address 0x1C9: Synth2 Base Frequency [7:0]
+    0x07,        // Register address 0x1CA: Synth2 Freq Multiple Ks [15:8]
+    0x98,        // Register address 0x1CB: Synth2 Freq Multiple Ks [7:0]
+    0x00,        // Register address 0x1CC: Synth2 Numerator Ms [15:8]
+    0x01,        // Register address 0x1CD: Synth2 Numerator Ms [7:0]
+    0x00,        // Register address 0x1CE: Synth2 Denominator Ns [15:8]
+    0x01,        // Register address 0x1CF: Synth2 Denominator Ns [7:0]
+    0x61,        // Register address 0x1D0: Synth3 Base Frequency [15:8]
+    0xA8,        // Register address 0x1D1: Synth3 Base Frequency [7:0]
+    0x09,        // Register address 0x1D2: Synth3 Freq Multiple Ks [15:8]
+    0xC4,        // Register address 0x1D3: Synth3 Freq Multiple Ks [7:0]
+    0x00,        // Register address 0x1D4: Synth3 Numerator Ms [15:8]
+    0x01,        // Register address 0x1D5: Synth3 Numerator Ms [7:0]
+    0x00,        // Register address 0x1D6: Synth3 Denominator Ns [15:8]
+    0x01,        // Register address 0x1D7: Synth3 Denominator Ns [7:0]
+    0x00,        // Register address 0x1D8: Reserved
+    0x00,        // Register address 0x1D9: Reserved
+    0x00,        // Register address 0x1DA: Reserved
+    0x00,        // Register address 0x1DB: Reserved
+    0x00,        // Register address 0x1DC: Reserved
+    0x00,        // Register address 0x1DD: Reserved
+    0x00,        // Register address 0x1DE: Reserved
+    0x00,        // Register address 0x1DF: Reserved
+    0x00,        // Register address 0x1E0: Reserved
+    0x00,        // Register address 0x1E1: Reserved
+    0x00,        // Register address 0x1E2: Reserved
+    0x00,        // Register address 0x1E3: Reserved
+    0x00,        // Register address 0x1E4: Reserved
+    0x00,        // Register address 0x1E5: Reserved
+    0x00,        // Register address 0x1E6: Reserved
+    0x00,        // Register address 0x1E7: Reserved
+    0x00,        // Register address 0x1E8: Reserved
+    0x00,        // Register address 0x1E9: Reserved
+    0x00,        // Register address 0x1EA: Reserved
+    0x00,        // Register address 0x1EB: Reserved
+    0x00,        // Register address 0x1EC: Reserved
+    0x00,        // Register address 0x1ED: Reserved
+    0x00,        // Register address 0x1EE: Reserved
+    0x00,        // Register address 0x1EF: Reserved
+    0x00,        // Register address 0x1F0: Reserved
+    0x00,        // Register address 0x1F1: Reserved
+    0x00,        // Register address 0x1F2: Reserved
+    0x00,        // Register address 0x1F3: Reserved
+    0x00,        // Register address 0x1F4: Reserved
+    0x00,        // Register address 0x1F5: Reserved
+    0x00,        // Register address 0x1F6: Reserved
+    0x00,        // Register address 0x1F7: Reserved
+    0x00,        // Register address 0x1F8: Reserved
+    0x00,        // Register address 0x1F9: Reserved
+    0x00,        // Register address 0x1FA: Reserved
+    0x00,        // Register address 0x1FB: Reserved
+    0x00,        // Register address 0x1FC: Reserved
+    0x00,        // Register address 0x1FD: Reserved
+    0x00,        // Register address 0x1FE: Reserved
+    0x04,        // Register address 0x1FF: Page Select
+    0x00,        // Register address 0x200: Synth 0A Post Divide [23:16]
+    0x00,        // Register address 0x201: Synth 0A Post Divide [15:8]
+    0x08,        // Register address 0x202: Synth 0A Post Divide [7:0]
+    0x00,        // Register address 0x203: Synth 0B Post Divide [23:16]
+    0x00,        // Register address 0x204: Synth 0B Post Divide [15:8]
+    0x08,        // Register address 0x205: Synth 0B Post Divide [7:0]
+    0x00,        // Register address 0x206: Synth 0C Post Divide [23:16]
+    0x00,        // Register address 0x207: Synth 0C Post Divide [15:8]
+    0x28,        // Register address 0x208: Synth 0C Post Divide [7:0]
+    0x00,        // Register address 0x209: Synth 0D Post Divide [23:16]
+    0x00,        // Register address 0x20A: Synth 0D Post Divide [15:8]
+    0x08,        // Register address 0x20B: Synth 0D Post Divide [7:0]
+    0x00,        // Register address 0x20C: Synth 1A Post Divide [23:16]
+    0x00,        // Register address 0x20D: Synth 1A Post Divide [15:8]
+    0x02,        // Register address 0x20E: Synth 1A Post Divide [7:0]
+    0x00,        // Register address 0x20F: Synth 1B Post Divide [23:16]
+    0x00,        // Register address 0x210: Synth 1B Post Divide [15:8]
+    0x02,        // Register address 0x211: Synth 1B Post Divide [7:0]
+    0x00,        // Register address 0x212: Synth 1C Post Divide [23:16]
+    0x00,        // Register address 0x213: Synth 1C Post Divide [15:8]
+    0x32,        // Register address 0x214: Synth 1C Post Divide [7:0]
+    0x00,        // Register address 0x215: Synth 1D Post Divide [23:16]
+    0x00,        // Register address 0x216: Synth 1D Post Divide [15:8]
+    0x32,        // Register address 0x217: Synth 1D Post Divide [7:0]
+    0x00,        // Register address 0x218: Synth 2A Post Divide [23:16]
+    0x00,        // Register address 0x219: Synth 2A Post Divide [15:8]
+    0x00,        // Register address 0x21A: Synth 2A Post Divide [7:0]
+    0x00,        // Register address 0x21B: Synth 2B Post Divide [23:16]
+    0x00,        // Register address 0x21C: Synth 2B Post Divide [15:8]
+    0x00,        // Register address 0x21D: Synth 2B Post Divide [7:0]
+    0x00,        // Register address 0x21E: Synth 2C Post Divide [23:16]
+    0x00,        // Register address 0x21F: Synth 2C Post Divide [15:8]
+    0x00,        // Register address 0x220: Synth 2C Post Divide [7:0]
+    0x00,        // Register address 0x221: Synth 2D Post Divide [23:16]
+    0x00,        // Register address 0x222: Synth 2D Post Divide [15:8]
+    0x00,        // Register address 0x223: Synth 2D Post Divide [7:0]
+    0x00,        // Register address 0x224: Synth 3A Post Divide [23:16]
+    0x00,        // Register address 0x225: Synth 3A Post Divide [15:8]
+    0x08,        // Register address 0x226: Synth 3A Post Divide [7:0]
+    0x00,        // Register address 0x227: Synth 3B Post Divide [23:16]
+    0x00,        // Register address 0x228: Synth 3B Post Divide [15:8]
+    0x08,        // Register address 0x229: Synth 3B Post Divide [7:0]
+    0x00,        // Register address 0x22A: Synth 3C Post Divide [23:16]
+    0x00,        // Register address 0x22B: Synth 3C Post Divide [15:8]
+    0x28,        // Register address 0x22C: Synth 3C Post Divide [7:0]
+    0x00,        // Register address 0x22D: Synth 3D Post Divide [23:16]
+    0x00,        // Register address 0x22E: Synth 3D Post Divide [15:8]
+    0x08,        // Register address 0x22F: Synth 3D Post Divide [7:0]
+    0x00,        // Register address 0x230: Reserved
+    0x00,        // Register address 0x231: Reserved
+    0x00,        // Register address 0x232: Reserved
+    0x00,        // Register address 0x233: Reserved
+    0x00,        // Register address 0x234: Synth 0C Post Div Phase [15:8]
+    0x00,        // Register address 0x235: Synth 0C Post Div Phase [7:0]
+    0x00,        // Register address 0x236: Synth 0D Post Div Phase [15:8]
+    0x00,        // Register address 0x237: Synth 0D Post Div Phase [7:0]
+    0x00,        // Register address 0x238: Reserved
+    0x00,        // Register address 0x239: Reserved
+    0x00,        // Register address 0x23A: Reserved
+    0x00,        // Register address 0x23B: Reserved
+    0x00,        // Register address 0x23C: Synth 1C Post Div Phase [15:8]
+    0x00,        // Register address 0x23D: Synth 1C Post Div Phase [7:0]
+    0x00,        // Register address 0x23E: Synth 1D Post Div Phase [15:8]
+    0x00,        // Register address 0x23F: Synth 1D Post Div Phase [7:0]
+    0x00,        // Register address 0x240: Reserved
+    0x00,        // Register address 0x241: Reserved
+    0x00,        // Register address 0x242: Reserved
+    0x00,        // Register address 0x243: Reserved
+    0x00,        // Register address 0x244: Synth 2C Post Div Phase [15:8]
+    0x00,        // Register address 0x245: Synth 2C Post Div Phase [7:0]
+    0x00,        // Register address 0x246: Synth 2D Post Div Phase [15:8]
+    0x00,        // Register address 0x247: Synth 2D Post Div Phase [7:0]
+    0x00,        // Register address 0x248: Reserved
+    0x00,        // Register address 0x249: Reserved
+    0x00,        // Register address 0x24A: Reserved
+    0x00,        // Register address 0x24B: Reserved
+    0x00,        // Register address 0x24C: Synth 3C Post Div Phase [15:8]
+    0x00,        // Register address 0x24D: Synth 3C Post Div Phase [7:0]
+    0x00,        // Register address 0x24E: Synth 3D Post Div Phase [15:8]
+    0x00,        // Register address 0x24F: Synth 3D Post Div Phase [7:0]
+    0x00,        // Register address 0x250: Synth0 Skew
+    0x00,        // Register address 0x251: Synth1 Skew
+    0x00,        // Register address 0x252: Synth2 Skew
+    0x00,        // Register address 0x253: Synth3 Skew
+    0x00,        // Register address 0x254: Synth Stop Clock 1-0
+    0x00,        // Register address 0x255: Synth Stop Clock 3-2
+    0x00,        // Register address 0x256: Reserved
+    0x00,        // Register address 0x257: Reserved
+    0x00,        // Register address 0x258: Reserved
+    0x00,        // Register address 0x259: Reserved
+    0x00,        // Register address 0x25A: Reserved
+    0x00,        // Register address 0x25B: Reserved
+    0x00,        // Register address 0x25C: Reserved
+    0x00,        // Register address 0x25D: Reserved
+    0x00,        // Register address 0x25E: Reserved
+    0x00,        // Register address 0x25F: Reserved
+    0x00,        // Register address 0x260: Reserved
+    0xC3,        // Register address 0x261: HP Diff Output Enable
+    0x03,        // Register address 0x262: HP CMOS Output Enable
+    0xFF,        // Register address 0x263: HP Ouput Reduced Drive
+    0xFF,        // Register address 0x264: HP CMOS Drive 3-0
+    0xFF,        // Register address 0x265: HP CMOS Drive 7-4
+    0x00,        // Register address 0x266: GPIO-0 Select/Status
+    0x00,        // Register address 0x267: GPIO-1 Select/Status
+    0x60,        // Register address 0x268: GPIO-2 Select/Status
+    0x00,        // Register address 0x269: GPIO-3 Select/Status
+    0x00,        // Register address 0x26A: GPIO-4 Select/Status
+    0x00,        // Register address 0x26B: GPIO-5 Select/Status
+    0x00,        // Register address 0x26C: GPIO-6 Select/Status
+    0x00,        // Register address 0x26D: Reserved
+    0x00,        // Register address 0x26E: Reserved
+    0x00,        // Register address 0x26F: Reserved
+    0x00,        // Register address 0x270: Reserved
+    0x00,        // Register address 0x271: Reserved
+    0x00,        // Register address 0x272: Reserved
+    0x00,        // Register address 0x273: Reserved
+    0x00,        // Register address 0x274: Reserved
+    0x00,        // Register address 0x275: Reserved
+    0x00,        // Register address 0x276: GPIO Input 7-0
+    0xF7,        // Register address 0x277: Reserved
+    0x00,        // Register address 0x278: GPIO Output 7-0
+    0x00,        // Register address 0x279: Reserved
+    0x00,        // Register address 0x27A: GPIO Output Enable 7-0
+    0x00,        // Register address 0x27B: Reserved
+    0x00,        // Register address 0x27C: GPIO Freeze 7-0
+    0x00,        // Register address 0x27D: Reserved
+    0x00,        // Register address 0x27E: Reserved
+    0x05,        // Register address 0x27F: Page Select
+    0x00,        // Register address 0x280: Reserved
+    0x00,        // Register address 0x281: Reserved
+    0x00,        // Register address 0x282: Reserved
+    0x00,        // Register address 0x283: Reserved
+    0x00,        // Register address 0x284: Reserved
+    0x00,        // Register address 0x285: Reserved
+    0x00,        // Register address 0x286: Reserved
+    0x00,        // Register address 0x287: Reserved
+    0x00,        // Register address 0x288: Reserved
+    0x00,        // Register address 0x289: Reserved
+    0x00,        // Register address 0x28A: Reserved
+    0x00,        // Register address 0x28B: Reserved
+    0x00,        // Register address 0x28C: Reserved
+    0x00,        // Register address 0x28D: Reserved
+    0x00,        // Register address 0x28E: Reserved
+    0x00,        // Register address 0x28F: Reserved
+    0x00,        // Register address 0x290: Reserved
+    0x00,        // Register address 0x291: Reserved
+    0x00,        // Register address 0x292: Reserved
+    0x00,        // Register address 0x293: Reserved
+    0x00,        // Register address 0x294: Reserved
+    0x00,        // Register address 0x295: Reserved
+    0x00,        // Register address 0x296: Reserved
+    0x00,        // Register address 0x297: Reserved
+    0x00,        // Register address 0x298: Reserved
+    0x00,        // Register address 0x299: Reserved
+    0x00,        // Register address 0x29A: Reserved
+    0x00,        // Register address 0x29B: Reserved
+    0x00,        // Register address 0x29C: Reserved
+    0x00,        // Register address 0x29D: Reserved
+    0x00,        // Register address 0x29E: Reserved
+    0x00,        // Register address 0x29F: Reserved
+    0x00,        // Register address 0x2A0: Reserved
+    0x00,        // Register address 0x2A1: Reserved
+    0x00,        // Register address 0x2A2: Reserved
+    0x00,        // Register address 0x2A3: Reserved
+    0x00,        // Register address 0x2A4: Reserved
+    0x00,        // Register address 0x2A5: Reserved
+    0x00,        // Register address 0x2A6: Reserved
+    0x00,        // Register address 0x2A7: Reserved
+    0x00,        // Register address 0x2A8: Reserved
+    0x00,        // Register address 0x2A9: Reserved
+    0x00,        // Register address 0x2AA: Reserved
+    0x00,        // Register address 0x2AB: Reserved
+    0x00,        // Register address 0x2AC: Reserved
+    0x00,        // Register address 0x2AD: Reserved
+    0x00,        // Register address 0x2AE: Reserved
+    0x00,        // Register address 0x2AF: Reserved
+    0x00,        // Register address 0x2B0: Reserved
+    0x00,        // Register address 0x2B1: Reserved
+    0x00,        // Register address 0x2B2: Reserved
+    0x00,        // Register address 0x2B3: Reserved
+    0x00,        // Register address 0x2B4: Reserved
+    0x00,        // Register address 0x2B5: Reserved
+    0x00,        // Register address 0x2B6: Reserved
+    0x00,        // Register address 0x2B7: Reserved
+    0x00,        // Register address 0x2B8: Reserved
+    0x00,        // Register address 0x2B9: Reserved
+    0x00,        // Register address 0x2BA: Reserved
+    0x00,        // Register address 0x2BB: Reserved
+    0x00,        // Register address 0x2BC: Reserved
+    0x00,        // Register address 0x2BD: Reserved
+    0x00,        // Register address 0x2BE: Reserved
+    0x00,        // Register address 0x2BF: Reserved
+    0x00,        // Register address 0x2C0: Reserved
+    0x00,        // Register address 0x2C1: Reserved
+    0x00,        // Register address 0x2C2: Reserved
+    0x00,        // Register address 0x2C3: Reserved
+    0x00,        // Register address 0x2C4: Reserved
+    0x00,        // Register address 0x2C5: Reserved
+    0x00,        // Register address 0x2C6: Reserved
+    0x00,        // Register address 0x2C7: Reserved
+    0x00,        // Register address 0x2C8: Reserved
+    0x00,        // Register address 0x2C9: Reserved
+    0x00,        // Register address 0x2CA: Reserved
+    0x00,        // Register address 0x2CB: Reserved
+    0x00,        // Register address 0x2CC: Reserved
+    0x00,        // Register address 0x2CD: Reserved
+    0x00,        // Register address 0x2CE: Reserved
+    0x00,        // Register address 0x2CF: Reserved
+    0x00,        // Register address 0x2D0: Reserved
+    0x00,        // Register address 0x2D1: Reserved
+    0x00,        // Register address 0x2D2: Reserved
+    0x00,        // Register address 0x2D3: Reserved
+    0x00,        // Register address 0x2D4: Reserved
+    0x00,        // Register address 0x2D5: Reserved
+    0x00,        // Register address 0x2D6: Reserved
+    0x00,        // Register address 0x2D7: Reserved
+    0x00,        // Register address 0x2D8: Reserved
+    0x00,        // Register address 0x2D9: Reserved
+    0x00,        // Register address 0x2DA: Reserved
+    0x00,        // Register address 0x2DB: Reserved
+    0x00,        // Register address 0x2DC: Reserved
+    0x00,        // Register address 0x2DD: Reserved
+    0x00,        // Register address 0x2DE: Reserved
+    0x00,        // Register address 0x2DF: Reserved
+    0x00,        // Register address 0x2E0: Reserved
+    0x00,        // Register address 0x2E1: Reserved
+    0x00,        // Register address 0x2E2: Reserved
+    0x00,        // Register address 0x2E3: Reserved
+    0x00,        // Register address 0x2E4: Reserved
+    0x00,        // Register address 0x2E5: Reserved
+    0x00,        // Register address 0x2E6: Reserved
+    0x00,        // Register address 0x2E7: Reserved
+    0x00,        // Register address 0x2E8: Reserved
+    0x00,        // Register address 0x2E9: Reserved
+    0x00,        // Register address 0x2EA: Reserved
+    0x00,        // Register address 0x2EB: Reserved
+    0x00,        // Register address 0x2EC: Reserved
+    0x00,        // Register address 0x2ED: Reserved
+    0x00,        // Register address 0x2EE: Reserved
+    0x00,        // Register address 0x2EF: Reserved
+    0x00,        // Register address 0x2F0: Reserved
+    0x00,        // Register address 0x2F1: Reserved
+    0x00,        // Register address 0x2F2: Reserved
+    0x00,        // Register address 0x2F3: Reserved
+    0x00,        // Register address 0x2F4: Reserved
+    0x00,        // Register address 0x2F5: Reserved
+    0x00,        // Register address 0x2F6: Reserved
+    0x00,        // Register address 0x2F7: Reserved
+    0x00,        // Register address 0x2F8: Reserved
+    0x00,        // Register address 0x2F9: Reserved
+    0x00,        // Register address 0x2FA: Reserved
+    0x00,        // Register address 0x2FB: Reserved
+    0x00,        // Register address 0x2FC: Reserved
+    0x00,        // Register address 0x2FD: Reserved
+    0x00,        // Register address 0x2FE: Reserved
+    0x00         // Register address 0x2FF: Reserved
+};
+
+/*==============================================================================
+ * ZL30362 registers are 8-bit registers.
+ */
+#define ZL_ADDRESS_BITS_MASK    0x0000007Fu
+#define ZL_REG_BITS_MASK        0x000000FFu
+#define ZL_READY_CODE           0x0000009Fu
+
+#define READ_ZL_READY_REG_CMD   0x00008000u
+#define SELECT_ZL_PAGE0_CMD     0x00007F00u
+
+/*==============================================================================
+ * Configure the ZL30362 device through its SPI interface.
+ */
+void configure_zl30362(void)
+{
+    uint32_t inc;
+    uint32_t zl_register;
+    uint32_t zl_ready;
+    const uint8_t frame_size = 16u;
+
+    int count  = 0;
+    
+    /*--------------------------------------------------------------------------
+     * Configure SPI interface.
+     */
+    MSS_SPI_init(&g_mss_spi1);
+    
+    MSS_SPI_configure_master_mode(&g_mss_spi1,
+                                  MSS_SPI_SLAVE_0,
+                                  MSS_SPI_MODE0,
+                                  MSS_SPI_PCLK_DIV_256,
+                                  frame_size);
+    
+	/* printf("%s %d %s\n", __FILE__, __LINE__, __FUNCTION__); */
+    MSS_SPI_set_slave_select(&g_mss_spi1, MSS_SPI_SLAVE_0);
+    
+    /*--------------------------------------------------------------------------
+     * Wait for ZL30362 to become ready.
+     * Compare against full ready register value instead of simply polling the
+     * ready bit. This avoids false ready bit detection when the ZL device has
+     * not fully come out of reset and does not respond to SPI transactions yet.
+     * The SPI transfer would typically return all 1's when there is no SPI
+     * device responding to the transaction.
+     */
+    MSS_SPI_transfer_frame(&g_mss_spi1, SELECT_ZL_PAGE0_CMD);
+    do {
+        zl_register = MSS_SPI_transfer_frame(&g_mss_spi1, READ_ZL_READY_REG_CMD);
+        zl_ready = zl_register  & ZL_REG_BITS_MASK;
+	/* if (count++ > 1000)  { */
+	/* 	printf ("finish timeout\n"); */
+	/* 	return; */
+	/* } */
+    } while(zl_ready != ZL_READY_CODE);
+    
+    /*--------------------------------------------------------------------------
+     * Transfer ZL30362 configuration via SPI.
+     */
+    for(inc = 0; inc < sizeof(g_zl30362_config); ++inc)
+    {
+	uint32_t tx_bits;
+        
+        tx_bits = ((inc & ZL_ADDRESS_BITS_MASK) << 8u) | g_zl30362_config[inc];
+        MSS_SPI_transfer_frame(&g_mss_spi1, tx_bits);
+    }
+}
diff --git a/drivers/net/m2s_eth.c b/drivers/net/m2s_eth.c
index bf90e7641dc65b244ad293e0becd74835cc95554..6634aa14bc62094e11f228ff7563283cf18d2eba 100644
--- a/drivers/net/m2s_eth.c
+++ b/drivers/net/m2s_eth.c
@@ -91,17 +91,45 @@
  * CFG1 register fields
  */
 #define M2S_MAC_CFG1_RST	(1 << 31)	/* PE-MCXMAC full reset	      */
+#define M2S_MAC_CFG1_RXCTL_RST	(1 << 19)
+#define M2S_MAC_CFG1_TXCTL_RST	(1 << 18)
+#define M2S_MAC_CFG1_RX_RST	(1 << 17)
+#define M2S_MAC_CFG1_TX_RST	(1 << 16)
 #define M2S_MAC_CFG1_RX_ENA	(1 << 2)	/* MAC receive enable	      */
 #define M2S_MAC_CFG1_TX_ENA	(1 << 0)	/* MAC transmit enable	      */
 
 /*
  * CFG2 register fields
  */
-#define M2S_MAC_CFG2_MODE_BIT	8		/* MAC interface mode	      */
-#define M2S_MAC_CFG2_MODE_MSK	0x3
-#define M2S_MAC_CFG2_MODE_MII	0x1		/* Nibble mode		      */
-#define M2S_MAC_CFG2_PAD_CRC	(1 << 2)	/* PAD&CRC appending enable   */
-#define M2S_MAC_CFG2_FULL_DUP	(1 << 0)	/* PE-MCXMAC Full duplex      */
+#define M2S_MAC_CFG2_PREAM_LEN_BIT	12
+#define M2S_MAC_CFG2_PREAM_LEN_MSK	0xf
+#define M2S_MAC_CFG2_MODE_BIT		8	/* MAC interface mode	      */
+#define M2S_MAC_CFG2_MODE_MSK		0x3
+#define M2S_MAC_CFG2_MODE_BYTE		0x2	/* Byte mode		      */
+#define M2S_MAC_CFG2_MODE_MII		0x1	/* Nibble mode		      */
+#define M2S_MAC_CFG2_HUGE_FRAME_EN	(1 << 5)
+#define M2S_MAC_CFG2_LEN_CHECK		(1 << 4)
+#define M2S_MAC_CFG2_PAD_CRC		(1 << 2) /* PAD&CRC appending enable   */
+#define M2S_MAC_CFG2_CRC_EN		(1 << 1)
+#define M2S_MAC_CFG2_FULL_DUP		(1 << 0) /* PE-MCXMAC Full duplex      */
+
+/*
+ * IPG/IFG register
+ */
+#define M2S_MAC_IFG_BTBIPG_BIT		0
+#define M2S_MAC_IFG_MINIFGENF_BIT	8
+#define M2S_MAC_IFG_NONBTBIPG_BIT	16
+
+/*
+ * half-duplex register
+ */
+#define M2S_MAC_HALF_DUPLEX_ABEB_TUNC_BIT		20
+#define M2S_MAC_HALF_DUPLEX_ABEB_ENABLE			(1 << 19)
+#define M2S_MAC_HALF_DUPLEX_BACKPRES_NOBACKOFF		(1 << 18)
+#define M2S_MAC_HALF_DUPLEX_NO_BACKOFF			(1 << 17)
+#define M2S_MAC_HALF_DUPLEX_EXCS_DEFER			(1 << 16)
+#define M2S_MAC_HALF_DUPLEX_RETX_MAX_BIT		12
+#define M2S_MAC_HALF_DUPLEX_SLOTTIME_BIT		0
 
 /*
  * MII_COMMAND register fields
@@ -125,6 +153,12 @@
  */
 #define M2S_MAC_DMA_CTRL_ENA	(1 << 0)	/* Enable Tx/Rx DMA xfers     */
 
+/*
+ * Interface Control register fields
+ */
+#define M2S_MAC_INTF_RESET		(1 << 31) /* Reset interface module */
+#define M2S_MAC_INTF_SPEED_100		(1 << 4)  /* MII PHY speed 100Mbit */
+
 /*
  * FIFO_CFG0 register fields
  */
@@ -164,12 +198,15 @@
 /*
  * MAC Configuration Register in Sysreg block fields
  */
-#define M2S_SYS_MAC_CR_PM_BIT 	2		/* PHY mode		      */
+#define M2S_SYS_MAC_CR_PM_BIT	2		/* PHY mode		      */
 #define M2S_SYS_MAC_CR_PM_MSK	0x7
+#define M2S_SYS_MAC_CR_PM_TBI	0x2		/* Use TBI mode		      */
 #define M2S_SYS_MAC_CR_PM_MII	0x3		/* Use MII mode		      */
 #define M2S_SYS_MAC_CR_LS_BIT	0		/* Line speed		      */
 #define M2S_SYS_MAC_CR_LS_MSK	0x3
+#define M2S_SYS_MAC_CR_LS_10	0x0		/* 10 Mbps		      */
 #define M2S_SYS_MAC_CR_LS_100	0x1		/* 100 Mbps		      */
+#define M2S_SYS_MAC_CR_LS_1000	0x2		/* 1000 Mbps		      */
 
 /*
  * Software Reset Control Register fields
@@ -255,8 +292,10 @@ static void m2s_eth_halt(struct eth_device *dev);
 static  int m2s_mii_read(char *devname, u8 addr, u8 reg, u16 *val);
 static  int m2s_mii_write(char *devname, u8 addr, u8 reg, u16 val);
 
+#ifndef CONFIG_M2S_ETH_MODE_SGMII
 static  int m2s_phy_probe(void);
 static  int m2s_phy_link_setup(void);
+#endif
 
 static void m2s_mac_dump_regs(char *who);
 
@@ -277,7 +316,10 @@ static struct eth_device	m2s_eth_dev = {
 /*
  * PHY address
  */
+#ifndef CONFIG_M2S_ETH_MODE_SGMII
 static u8			m2s_phy_addr = 0xFF;
+#endif
+static u8			m2s_mii_speed = M2S_SYS_MAC_CR_LS_100;
 
 /*
  * Current indexes within m2s_bd_Xx[] (idx of BT to process next)
@@ -295,6 +337,238 @@ static volatile struct m2s_eth_dma_bd	m2s_bd_rx[M2S_RX_BD_NUM];
  */
 static u8			m2s_buf_rx[M2S_RX_BD_NUM][M2S_FRM_MAX_LEN];
 
+#define M88E1340_PHY_ADDR 0
+#define SF2_MSGMII_PHY_ADDR 0x1e
+
+/* M88E1340 PHY registers */
+
+/* Advertisement control register. */
+#define MII_ADVERTISE           0x04        /* Advertisement control reg   */
+
+#define ADVERTISE_SLCT          0x001f      /* Selector bits               */
+#define ADVERTISE_CSMA          0x0001      /* Only selector supported     */
+#define ADVERTISE_10HALF        0x0020      /* Try for 10mbps half-duplex  */
+#define ADVERTISE_1000XFULL     0x0020      /* Try for 1000BASE-X full-duplex */
+#define ADVERTISE_10FULL        0x0040      /* Try for 10mbps full-duplex  */
+#define ADVERTISE_1000XHALF     0x0040      /* Try for 1000BASE-X half-duplex */
+#define ADVERTISE_100HALF       0x0080      /* Try for 100mbps half-duplex */
+#define ADVERTISE_1000XPAUSE    0x0080      /* Try for 1000BASE-X pause    */
+#define ADVERTISE_100FULL       0x0100      /* Try for 100mbps full-duplex */
+#define ADVERTISE_1000XPSE_ASYM 0x0100      /* Try for 1000BASE-X asym pause */
+#define ADVERTISE_100BASE4      0x0200      /* Try for 100mbps 4k packets  */
+#define ADVERTISE_PAUSE_CAP     0x0400      /* Try for pause               */
+#define ADVERTISE_PAUSE_ASYM    0x0800      /* Try for asymetric pause     */
+#define ADVERTISE_RESV          0x1000      /* Unused...                   */
+#define ADVERTISE_RFAULT        0x2000      /* Say we can detect faults    */
+#define ADVERTISE_LPACK         0x4000      /* Ack link partners response  */
+#define ADVERTISE_NPAGE         0x8000      /* Next page bit               */
+
+/* 1000BASE-T Control register */
+#define MII_CTRL1000            0x09        /* 1000BASE-T control          */
+
+#define ADVERTISE_1000FULL      0x0200      /* Advertise 1000BASE-T full duplex */
+#define ADVERTISE_1000HALF      0x0100      /* Advertise 1000BASE-T half duplex */
+
+#define M88E1340_EXT_ADDR_PAGE_CR       0x16
+#define PAGE_0                          0x00
+
+#define M88E1340_PHY_STATUS		0x11
+#define M88E1340_PHY_STATUS_1000	0x8000
+#define M88E1340_PHY_STATUS_100	        0x4000
+#define M88E1340_PHY_STATUS_SPD_MASK	0xc000
+#define M88E1340_PHY_STATUS_FULLDUPLEX	0x2000
+#define M88E1340_PHY_STATUS_RESOLVED	0x0800
+#define M88E1340_PHY_STATUS_LINK	0x0400
+
+#ifdef CONFIG_M2S_ETH_MODE_SGMII
+
+static int msgmii_phy_init(void)
+{
+	u16 val;
+	int rv;
+
+	/* Reset M-SGMII. */
+	rv = miiphy_write(M2S_MII_NAME, SF2_MSGMII_PHY_ADDR, 0x00, 0x9000u);
+	if (rv != 0) {
+		return -1;
+	}
+	/* Register 0x04 of M-SGMII must be always be set to 0x0001. */
+	rv = miiphy_write(M2S_MII_NAME, SF2_MSGMII_PHY_ADDR, 0x04, 0x0001);
+	if (rv != 0) {
+		return -1;
+	}
+	/*
+	 * Enable auto-negotiation inside SmartFusion2 SGMII block.
+	 */
+	rv = miiphy_read(M2S_MII_NAME, SF2_MSGMII_PHY_ADDR, 0, &val);
+	if (rv != 0) {
+		return -1;
+	}
+	val |= 0x1000;
+	rv = miiphy_write(M2S_MII_NAME, SF2_MSGMII_PHY_ADDR, 0x0, val);
+	if (rv != 0) {
+		return -1;
+	}
+
+	return 0;
+}
+
+static int m881340_phy_set_link_speed(void)
+{
+	u16 val;
+	int rv;
+        /* Set auto-negotiation advertisement. */
+	/* Set 10Mbps and 100Mbps advertisement. */
+	rv = miiphy_read(M2S_MII_NAME, M88E1340_PHY_ADDR, MII_ADVERTISE, &val);
+	if (rv != 0) {
+		goto out;
+	}
+	val |= (ADVERTISE_10HALF | ADVERTISE_10FULL
+		| ADVERTISE_100HALF | ADVERTISE_100FULL);
+	rv = miiphy_write(M2S_MII_NAME, M88E1340_PHY_ADDR, MII_ADVERTISE, val);
+	if (rv != 0) {
+		goto out;
+	}
+
+	/* Set 1000Mbps advertisement. */
+	rv = miiphy_read(M2S_MII_NAME, M88E1340_PHY_ADDR, MII_CTRL1000, &val);
+	if (rv != 0) {
+		goto out;
+	}
+
+	val |= (ADVERTISE_1000FULL | ADVERTISE_1000HALF);
+	rv = miiphy_write(M2S_MII_NAME, M88E1340_PHY_ADDR, MII_CTRL1000, val);
+	if (rv != 0) {
+		goto out;
+	}
+ out:
+	if (rv) {
+		printf("%s %d %s return %d\n", __FILE__, __LINE__,
+				__func__, rv);
+	}
+	return rv;
+}
+
+static int msgmii_phy_autonegotiate(void)
+{
+	int rv;
+	u16 val;
+	int timeout;
+
+	/* Enable auto-negotiation. */
+	rv = miiphy_write(M2S_MII_NAME, M88E1340_PHY_ADDR,
+			M88E1340_EXT_ADDR_PAGE_CR, PAGE_0);
+	if (rv != 0) {
+		goto out;
+	}
+	val = 0x9340 | PHY_BMCR_100_MBPS;
+	rv = miiphy_write(M2S_MII_NAME, M88E1340_PHY_ADDR, PHY_BMCR, val);
+	if (rv != 0) {
+		goto out;
+	}
+
+	/* Wait for copper auto-negotiation to complete. */
+	timeout = M2S_AUTONEG_TOUT/1000;
+	while (timeout--) {
+		rv = miiphy_read(M2S_MII_NAME, M88E1340_PHY_ADDR,
+				PHY_BMSR, &val);
+		if (rv != 0) {
+			printf("mii err %d.\n", rv);
+			goto out;
+		}
+		if (!(val & PHY_BMSR_AUTN_COMP)) {
+			int i;
+			for (i = 0; i < 1000; i++)
+				udelay(1000);
+			continue;
+		}
+		rv = miiphy_read(M2S_MII_NAME, M88E1340_PHY_ADDR,
+				M88E1340_PHY_STATUS, &val);
+		if (rv != 0) {
+			printf("mii err %d.\n", rv);
+			goto out;
+		}
+		if ((val & M88E1340_PHY_STATUS_SPD_MASK) ==
+				M88E1340_PHY_STATUS_100) {
+			m2s_mii_speed = M2S_SYS_MAC_CR_LS_100;
+		} else if ((val & M88E1340_PHY_STATUS_SPD_MASK) ==
+				M88E1340_PHY_STATUS_1000) {
+			m2s_mii_speed = M2S_SYS_MAC_CR_LS_1000;
+		} else {
+			m2s_mii_speed = M2S_SYS_MAC_CR_LS_10;
+		}
+		break;
+	}
+
+	if (timeout <= 0) {
+		printf("%s %d %s marvel autoneg failed by timeout %02x\n",
+				__FILE__, __LINE__, __func__, val);
+		return -1;
+	}
+
+	rv = miiphy_read(M2S_MII_NAME, SF2_MSGMII_PHY_ADDR, PHY_BMSR, &val);
+	if (rv != 0) {
+		goto out;
+	}
+
+	if (val & PHY_BMSR_AUTN_COMP) {
+		/* no need to start auto-negotiation if it is already done */
+		goto out;
+	}
+
+	rv = miiphy_read(M2S_MII_NAME, SF2_MSGMII_PHY_ADDR, PHY_BMCR, &val);
+	if (rv != 0) {
+		goto out;
+	}
+
+	rv = miiphy_write(M2S_MII_NAME, SF2_MSGMII_PHY_ADDR, PHY_BMCR,
+			val | PHY_BMCR_AUTON | PHY_BMCR_RST_NEG);
+	if (rv != 0) {
+		goto out;
+	}
+
+	/*
+	 * Wait until auto-negotiation completes
+	 */
+	timeout = M2S_AUTONEG_TOUT/10;
+	while (timeout--) {
+		rv = miiphy_read(M2S_MII_NAME, SF2_MSGMII_PHY_ADDR,
+				PHY_BMSR, &val);
+
+		if (rv != 0) {
+			printf("mii err %d.\n", rv);
+			goto out;
+		}
+		if (!(val & PHY_BMSR_AUTN_COMP)) {
+			if (timeout % 100 != 0) {
+				udelay(10000);
+				continue;
+			}
+
+			/* restart auto-negotiation if it is not complete
+			   in a second */
+			rv = miiphy_write(M2S_MII_NAME, SF2_MSGMII_PHY_ADDR,
+					PHY_BMCR,
+					PHY_BMCR_AUTON | PHY_BMCR_RST_NEG);
+			if (rv != 0) {
+				goto out;
+			}
+
+			continue;
+		}
+		break;
+	}
+	if (timeout <= 0)
+		printf("MSGMII PHY auto-negotiaiton timed out!\n");
+    
+ out:
+	return rv;
+
+
+}
+
+#endif
+
 /******************************************************************************
  * Functions exported from the module
  ******************************************************************************/
@@ -334,7 +608,7 @@ out:
 static int m2s_eth_init(struct eth_device *dev, bd_t *bd_unused)
 {
 	volatile struct m2s_eth_dma_bd	*bd;
-	int				i, rv, timeout;
+	int				i, rv = 0, timeout;
 
 	/*
 	 * Release the Ethernet MAC from reset
@@ -343,23 +617,55 @@ static int m2s_eth_init(struct eth_device *dev, bd_t *bd_unused)
 
 	/*
 	 * Set-up CR
-	 * FIXME: set line-speed according to val get from PHY?
 	 */
 	M2S_SYSREG->mac_cr &= ~(M2S_SYS_MAC_CR_PM_MSK << M2S_SYS_MAC_CR_PM_BIT);
 	M2S_SYSREG->mac_cr &= ~(M2S_SYS_MAC_CR_LS_MSK << M2S_SYS_MAC_CR_LS_BIT);
+#ifndef CONFIG_M2S_ETH_MODE_SGMII
 	M2S_SYSREG->mac_cr |= M2S_SYS_MAC_CR_PM_MII << M2S_SYS_MAC_CR_PM_BIT;
-	M2S_SYSREG->mac_cr |= M2S_SYS_MAC_CR_LS_100 << M2S_SYS_MAC_CR_LS_BIT;
+#else
+	/* Interface type: TBI */
+	M2S_SYSREG->mac_cr = M2S_SYS_MAC_CR_PM_TBI << M2S_SYS_MAC_CR_PM_BIT;
+#endif
+
+	M2S_MAC_CFG->mii_config = 7;
 
 	/*
 	 * Reset all PE-MCXMAC modules, and configure
 	 */
 	M2S_MAC_CFG->cfg1 |= M2S_MAC_CFG1_RST;
 	M2S_MAC_CFG->cfg1 &= ~M2S_MAC_CFG1_RST;
+	/* Clear all reset bits */
+	/* Clear MCXMAC TX reset */
+	M2S_MAC_CFG->cfg1 &= ~M2S_MAC_CFG1_TX_RST;
+	/* Clear MCXMAC RX reset */
+	M2S_MAC_CFG->cfg1 &= ~M2S_MAC_CFG1_RX_RST;
+	/* Clear MCXMAC TX reset */
+	M2S_MAC_CFG->cfg1 &= ~M2S_MAC_CFG1_TXCTL_RST;
+	/* Clear MCXMAC RX reset */
+	M2S_MAC_CFG->cfg1 &= ~M2S_MAC_CFG1_RXCTL_RST;
+	/* Clear MCXMAC interface reset */
+	M2S_MAC_CFG->if_ctrl &= ~M2S_MAC_INTF_RESET;
+	/* Clear FIFO watermark reset */
+	/* Clear FIFO Rx system reset */
+	/* Clear FIFO Rx fab reset */
+	/* Clear FIFO Tx system reset */
+	/* Clear FIFO Tx system reset */
+	M2S_MAC_CFG->fifo_cfg[0] &= ~M2S_MAC_FIFO_CFG0_ALL_RST;
+
+	M2S_MAC_CFG->cfg1 = 0;
 
 	M2S_MAC_CFG->cfg2 &= ~(M2S_MAC_CFG2_MODE_MSK << M2S_MAC_CFG2_MODE_BIT);
+#ifndef CONFIG_M2S_ETH_MODE_SGMII
 	M2S_MAC_CFG->cfg2 |= (M2S_MAC_CFG2_MODE_MII << M2S_MAC_CFG2_MODE_BIT) |
 			     M2S_MAC_CFG2_FULL_DUP | M2S_MAC_CFG2_PAD_CRC;
-
+#else
+	M2S_MAC_CFG->cfg2 =
+		M2S_MAC_CFG2_FULL_DUP | M2S_MAC_CFG2_CRC_EN
+		| M2S_MAC_CFG2_PAD_CRC
+		| M2S_MAC_CFG2_LEN_CHECK
+		| (M2S_MAC_CFG2_MODE_BYTE << M2S_MAC_CFG2_MODE_BIT)
+		| (0x7 << M2S_MAC_CFG2_PREAM_LEN_BIT);
+#endif
 	M2S_MAC_CFG->max_frame_length = M2S_FRM_MAX_LEN;
 
 	M2S_MAC_CFG->station_addr[0] = (dev->enetaddr[0] << 24) |
@@ -402,11 +708,6 @@ static int m2s_eth_init(struct eth_device *dev, bd_t *bd_unused)
 	M2S_MAC_DMA->rx_desc = (u32)m2s_bd_rx;
 	M2S_MAC_DMA->rx_ctrl = M2S_MAC_DMA_CTRL_ENA;
 
-	/*
-	 * Enable MAC Rx and Tx
-	 */
-	M2S_MAC_CFG->cfg1 = M2S_MAC_CFG1_RX_ENA | M2S_MAC_CFG1_TX_ENA;
-
 	/*
 	 * Reset and enable FIFOs
 	 */
@@ -427,13 +728,37 @@ static int m2s_eth_init(struct eth_device *dev, bd_t *bd_unused)
 		goto out;
 	}
 
+#ifdef CONFIG_M2S_ETH_MODE_SGMII
+	if (msgmii_phy_init() < 0)
+		goto out;
+	if (m881340_phy_set_link_speed() < 0)
+		goto out;
+	if (msgmii_phy_autonegotiate() < 0)
+		goto out;
+#else
 	/*
 	 * Probe for PHY, and get LINK status
 	 */
 	rv = m2s_phy_probe();
 	if (rv != 0)
 		goto out;
-	m2s_phy_link_setup();
+	if (rv != 0)
+		goto out;
+#endif
+
+	if (m2s_mii_speed == M2S_SYS_MAC_CR_LS_100) {
+		M2S_MAC_CFG->if_ctrl |= M2S_MAC_INTF_SPEED_100;
+	} else {
+		M2S_MAC_CFG->if_ctrl &= ~M2S_MAC_INTF_SPEED_100;
+	}
+	M2S_SYSREG->mac_cr = (M2S_SYSREG->mac_cr & ~M2S_SYS_MAC_CR_LS_MSK) |
+		m2s_mii_speed;
+	M2S_MAC_CFG->cfg2 |= M2S_MAC_CFG2_FULL_DUP;
+
+	/*
+	 * Enable MAC Rx and Tx
+	 */
+	M2S_MAC_CFG->cfg1 = M2S_MAC_CFG1_RX_ENA | M2S_MAC_CFG1_TX_ENA;
 
 	rv = 0;
 out:
@@ -581,7 +906,7 @@ static int m2s_mii_read(char *devname, u8 adr, u8 reg, u16 *val)
 {
 	int	timeout, rv;
 
-	if (adr == 0 || adr > 31 || reg > 31 || !val) {
+	if (adr > 31 || reg > 31 || !val) {
 		printf("%s: bad params %x/%x/%p\n", __func__, adr, reg, val);
 		rv = -EINVAL;
 		goto out;
@@ -617,7 +942,7 @@ static int m2s_mii_write(char *devname, u8 adr, u8 reg, u16 val)
 {
 	int	timeout, rv;
 
-	if (adr == 0 || adr > 31 || reg > 31) {
+	if (adr > 31 || reg > 31) {
 		printf("%s: bad params %x/%x\n", __func__, adr, reg);
 		rv = -EINVAL;
 		goto out;
@@ -641,6 +966,8 @@ out:
 	return rv;
 }
 
+#ifndef CONFIG_M2S_ETH_MODE_SGMII
+
 /******************************************************************************
  * PHY routines
  ******************************************************************************/
@@ -741,6 +1068,8 @@ out:
 	return rv;
 }
 
+#endif
+
 /******************************************************************************
  * Debug stuff
  ******************************************************************************/
diff --git a/include/asm-arm/arch-m2s/m2s.h b/include/asm-arm/arch-m2s/m2s.h
index 40dea65a29fdeef950b0f7e73322aeee864640e8..8e19fc5b6dae5806be06c4709db8cb6b1c5b7f2c 100644
--- a/include/asm-arm/arch-m2s/m2s.h
+++ b/include/asm-arm/arch-m2s/m2s.h
@@ -79,6 +79,15 @@ struct m2s_sysreg {
 #define M2S_SYSREG			((volatile struct m2s_sysreg *)\
 					(M2S_SYSREG_BASE))
 
+struct m2s_coresf2config {
+    unsigned int   config_done;
+    unsigned int   init_done;
+    unsigned int   clr_init_done;
+};
+
+#define CORE_SF2_CFG_BASE		0x40022000u
+#define CORE_SF2_CFG			\
+	((volatile struct m2s_coresf2config *)CORE_SF2_CFG_BASE)
 
 /*
  * Reference clocks enumeration
diff --git a/include/configs/sf2-dev-kit.h b/include/configs/sf2-dev-kit.h
index 27406decfdf85a003d7ba1e606715c17eee4ac0a..29ce1d7273f674d7c0dbf72992b016283d2dadb6 100644
--- a/include/configs/sf2-dev-kit.h
+++ b/include/configs/sf2-dev-kit.h
@@ -141,6 +141,21 @@
 #define CONFIG_SYS_RAM_BASE		0xA0000000
 #define CONFIG_SYS_RAM_SIZE		(256 * 1024 * 1024)
 
+/*
+ * Ethernet driver configuration
+ */
+#define CONFIG_NET_MULTI
+#define CONFIG_M2S_ETH
+#define CONFIG_M2S_ETH_MODE_SGMII
+
+#define CONFIG_SYS_RX_ETH_BUFFER	2
+
+/*
+ * Use standard MII PHY API
+ */
+#define CONFIG_MII
+#define CONFIG_SYS_FAULT_ECHO_LINK_DOWN
+
 /*
  * Configuration of the external Flash
  * No NOR Flash
@@ -241,8 +256,8 @@
 #undef CONFIG_CMD_IMLS
 #define CONFIG_CMD_LOADS
 #undef CONFIG_CMD_MISC
-/* #define CONFIG_CMD_NET */
-#undef CONFIG_CMD_NET
+#define CONFIG_CMD_NET
+#define CONFIG_CMD_PING
 #undef CONFIG_CMD_NETBOOT
 #undef CONFIG_CMD_NFS
 #undef CONFIG_CMD_SOURCE