From 76386c1047ea15a05965adcab371bba2147831ba Mon Sep 17 00:00:00 2001 From: Sebastian Huber Date: Tue, 26 Aug 2014 16:00:44 +0200 Subject: bsp/altera-cyclone-v: Add DMA support hwlib files --- c/src/lib/libbsp/arm/altera-cyclone-v/Makefile.am | 21 +- .../hwlib/include/alt_16550_uart.h | 1555 +++++ .../arm/altera-cyclone-v/hwlib/include/alt_cache.h | 964 ++++ .../arm/altera-cyclone-v/hwlib/include/alt_dma.h | 1007 ++++ .../hwlib/include/alt_dma_common.h | 162 + .../hwlib/include/alt_dma_program.h | 951 ++++ .../arm/altera-cyclone-v/hwlib/include/alt_qspi.h | 1535 +++++ .../hwlib/include/alt_qspi_private.h | 167 + .../hwlib/include/socal/alt_dmanonsecure.h | 144 + .../hwlib/include/socal/alt_dmasecure.h | 144 + .../hwlib/include/socal/alt_qspi.h | 5951 ++++++++++++++++++++ .../hwlib/include/socal/alt_qspidata.h | 52 + .../hwlib/src/hwmgr/alt_16550_uart.c | 1179 ++++ .../arm/altera-cyclone-v/hwlib/src/hwmgr/alt_dma.c | 3749 ++++++++++++ .../hwlib/src/hwmgr/alt_dma_program.c | 1064 ++++ .../altera-cyclone-v/hwlib/src/hwmgr/alt_qspi.c | 2619 +++++++++ .../lib/libbsp/arm/altera-cyclone-v/preinstall.am | 40 + 17 files changed, 21297 insertions(+), 7 deletions(-) create mode 100644 c/src/lib/libbsp/arm/altera-cyclone-v/hwlib/include/alt_16550_uart.h create mode 100644 c/src/lib/libbsp/arm/altera-cyclone-v/hwlib/include/alt_cache.h create mode 100644 c/src/lib/libbsp/arm/altera-cyclone-v/hwlib/include/alt_dma.h create mode 100644 c/src/lib/libbsp/arm/altera-cyclone-v/hwlib/include/alt_dma_common.h create mode 100644 c/src/lib/libbsp/arm/altera-cyclone-v/hwlib/include/alt_dma_program.h create mode 100644 c/src/lib/libbsp/arm/altera-cyclone-v/hwlib/include/alt_qspi.h create mode 100644 c/src/lib/libbsp/arm/altera-cyclone-v/hwlib/include/alt_qspi_private.h create mode 100644 c/src/lib/libbsp/arm/altera-cyclone-v/hwlib/include/socal/alt_dmanonsecure.h create mode 100644 c/src/lib/libbsp/arm/altera-cyclone-v/hwlib/include/socal/alt_dmasecure.h create mode 100644 c/src/lib/libbsp/arm/altera-cyclone-v/hwlib/include/socal/alt_qspi.h create mode 100644 c/src/lib/libbsp/arm/altera-cyclone-v/hwlib/include/socal/alt_qspidata.h create mode 100644 c/src/lib/libbsp/arm/altera-cyclone-v/hwlib/src/hwmgr/alt_16550_uart.c create mode 100644 c/src/lib/libbsp/arm/altera-cyclone-v/hwlib/src/hwmgr/alt_dma.c create mode 100644 c/src/lib/libbsp/arm/altera-cyclone-v/hwlib/src/hwmgr/alt_dma_program.c create mode 100644 c/src/lib/libbsp/arm/altera-cyclone-v/hwlib/src/hwmgr/alt_qspi.c diff --git a/c/src/lib/libbsp/arm/altera-cyclone-v/Makefile.am b/c/src/lib/libbsp/arm/altera-cyclone-v/Makefile.am index a581dee90d..aad1db10c3 100644 --- a/c/src/lib/libbsp/arm/altera-cyclone-v/Makefile.am +++ b/c/src/lib/libbsp/arm/altera-cyclone-v/Makefile.am @@ -51,23 +51,25 @@ include_bsp_HEADERS += include/irq.h include_bsp_HEADERS += include/nocache-heap.h # Altera hwlib +include_bsp_HEADERS += hwlib/include/alt_16550_uart.h include_bsp_HEADERS += hwlib/include/alt_address_space.h +include_bsp_HEADERS += hwlib/include/alt_cache.h include_bsp_HEADERS += hwlib/include/alt_clock_group.h include_bsp_HEADERS += hwlib/include/alt_clock_manager.h +include_bsp_HEADERS += hwlib/include/alt_dma_common.h +include_bsp_HEADERS += hwlib/include/alt_dma.h +include_bsp_HEADERS += hwlib/include/alt_dma_program.h include_bsp_HEADERS += hwlib/include/alt_generalpurpose_io.h include_bsp_HEADERS += hwlib/include/alt_hwlibs_ver.h include_bsp_HEADERS += hwlib/include/alt_i2c.h include_bsp_HEADERS += hwlib/include/alt_interrupt_common.h include_bsp_HEADERS += hwlib/include/alt_mpu_registers.h +include_bsp_HEADERS += hwlib/include/alt_qspi_private.h include_bsp_HEADERS += hwlib/include/alt_reset_manager.h include_bsp_HEADERS += hwlib/include/hwlib.h #The following Altera hwlib header files have been left out because so far #they are not required: -#include_bsp_HEADERS += hwlib/include/alt_16550_uart.h #include_bsp_HEADERS += hwlib/include/alt_bridge_manager.h -#include_bsp_HEADERS += hwlib/include/alt_dma_common.h -#include_bsp_HEADERS += hwlib/include/alt_dma_program.h -#include_bsp_HEADERS += hwlib/include/alt_dma.h #include_bsp_HEADERS += hwlib/include/alt_fpga_manager.h #include_bsp_HEADERS += hwlib/include/alt_globaltmr.h #include_bsp_HEADERS += hwlib/include/alt_system_manager.h @@ -79,9 +81,13 @@ include_bsp_HEADERS += hwlib/include/hwlib.h # Some of the headers from hwlib need the files from socal. Install them. include_bsp_socal_HEADERS += hwlib/include/socal/alt_acpidmap.h include_bsp_socal_HEADERS += hwlib/include/socal/alt_clkmgr.h +include_bsp_socal_HEADERS += hwlib/include/socal/alt_dmanonsecure.h +include_bsp_socal_HEADERS += hwlib/include/socal/alt_dmasecure.h include_bsp_socal_HEADERS += hwlib/include/socal/alt_gpio.h include_bsp_socal_HEADERS += hwlib/include/socal/alt_i2c.h include_bsp_socal_HEADERS += hwlib/include/socal/alt_l3.h +include_bsp_socal_HEADERS += hwlib/include/socal/alt_qspidata.h +include_bsp_socal_HEADERS += hwlib/include/socal/alt_qspi.h include_bsp_socal_HEADERS += hwlib/include/socal/alt_rstmgr.h include_bsp_socal_HEADERS += hwlib/include/socal/alt_sdr.h include_bsp_socal_HEADERS += hwlib/include/socal/alt_sysmgr.h @@ -124,17 +130,18 @@ libbsp_a_CPPFLAGS += -std=gnu99 CFLAGS += -Wno-missing-prototypes # hwlib from Altera +libbsp_a_SOURCES += hwlib/src/hwmgr/alt_16550_uart.c libbsp_a_SOURCES += hwlib/src/hwmgr/alt_address_space.c libbsp_a_SOURCES += hwlib/src/hwmgr/alt_clock_manager.c +libbsp_a_SOURCES += hwlib/src/hwmgr/alt_dma.c +libbsp_a_SOURCES += hwlib/src/hwmgr/alt_dma_program.c libbsp_a_SOURCES += hwlib/src/hwmgr/alt_generalpurpose_io.c libbsp_a_SOURCES += hwlib/src/hwmgr/alt_i2c.c +libbsp_a_SOURCES += hwlib/src/hwmgr/alt_qspi.c libbsp_a_SOURCES += hwlib/src/hwmgr/alt_reset_manager.c #The following Altera hwlib source files have been left out because so far #they are not required: -#libbsp_a_SOURCES += hwlib/src/hwmgr/alt_16550_uart.c #libbsp_a_SOURCES += hwlib/src/hwmgr/alt_bridge_manager.c -#libbsp_a_SOURCES += hwlib/src/hwmgr/alt_dma_program.c -#libbsp_a_SOURCES += hwlib/src/hwmgr/alt_dma.c #libbsp_a_SOURCES += hwlib/src/hwmgr/alt_fpga_manager.c #libbsp_a_SOURCES += hwlib/src/hwmgr/alt_globaltmr.c #libbsp_a_SOURCES += hwlib/src/hwmgr/alt_system_manager.c diff --git a/c/src/lib/libbsp/arm/altera-cyclone-v/hwlib/include/alt_16550_uart.h b/c/src/lib/libbsp/arm/altera-cyclone-v/hwlib/include/alt_16550_uart.h new file mode 100644 index 0000000000..bca6f63e00 --- /dev/null +++ b/c/src/lib/libbsp/arm/altera-cyclone-v/hwlib/include/alt_16550_uart.h @@ -0,0 +1,1555 @@ +/* + * Altera - SoC UART Manager + */ + +/***************************************************************************** + * + * Copyright 2013 Altera Corporation. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED. IN NO + * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *****************************************************************************/ + +#ifndef __ALT_16550_UART_H__ +#define __ALT_16550_UART_H__ + +#include "hwlib.h" +#include "alt_clock_manager.h" + +#ifdef __cplusplus +extern "C" +{ +#endif + +/*! + * \addtogroup UART UART Driver API + * + * This module defines the Universal Asynchronous Receiver/Transmitter (UART) + * API for accessing and using the UART resources. The API allows for general + * control of a 16550 compatible UART controller. + * + * This implementation can control the following UARTs: + * * SoCFPGA On-board UARTs + * * Altera 16550 Compatible Soft IP UART + * + * The following reference materials were used in the design of this API: + * * Synopsys® DesignWare DW_apb_uart Databook v3.10a + * + * @{ + */ + +/*! + * \addtogroup UART_BASIC UART Basic + * + * This group of APIs provides basic access to the UART to initialize, + * uninitialize, read, write, and reset the UART. + * + * @{ + */ + +/*! + * This type definition enumerates the list of UARTs available on the system. + */ +typedef enum ALT_16550_DEVICE_e +{ + /*! + * This option selects UART0 in the SoC FPGA. + */ + ALT_16550_DEVICE_SOCFPGA_UART0 = 0, + + /*! + * This option selects UART1 in the SoC FPGA. + */ + ALT_16550_DEVICE_SOCFPGA_UART1 = 1, + + /*! + * This option selects an Altera 16550 Compatible soft IP UART. The memory + * location of the device must be provided as part of the initialization. + */ + ALT_16550_DEVICE_ALTERA_16550_UART = 0x100 +} +ALT_16550_DEVICE_t; + +/*! + * This structure is used to represent a handle to a specific UART on the + * system. The internal members are undocumented and should be not altered + * outside of this API. + */ +typedef struct ALT_16550_HANDLE_s +{ + ALT_16550_DEVICE_t device; + void * location; + alt_freq_t clock_freq; + uint32_t data; + uint32_t fcr; +} +ALT_16550_HANDLE_t; + +/*! + * Performs the initialization steps needed by the UART. This should be the + * first API call made when accessing a particular UART + * + * The default UART setting is 8 databits, no parity, 1 stopbit, and 57600 + * baud. + * + * For the SoCFPGA UARTs, The ALT_CLK_L4_SP clock needs to be setup before + * initialization. + * + * \param device + * The UART device identifier. + * + * \param location + * The memory of the location for the given UART. For SoCFPGA + * UARTs, this parameter is ignored. + * + * \param clock_freq + * The clock frequency of the serial clock for the given UART. + * For SoCFPGA UARTs, this paramter is ignored. + * + * \param handle + * [out] A pointer to a handle that will represent the UART. This + * handle should subsequently be used when calling other UART + * APIs. + * + * \retval ALT_E_SUCCESS The operation was successful. + * \retval ALT_E_ERROR The operation failed. + * \retval ALT_E_BAD_ARG The given UART device identifier is invalid. + * \retval ALT_E_BAD_CLK The required clock is not yet setup. + */ +ALT_STATUS_CODE alt_16550_init(ALT_16550_DEVICE_t device, + void * location, + alt_freq_t clock_freq, + ALT_16550_HANDLE_t * handle); + +/*! + * Performs the uninitialization steps for the UART. This should be the last + * API call made to cleanup the UART. + * + * After calling this function, the handle will need to be initialized again + * before being used by calling alt_16550_init(). + * + * \param handle + * The UART device handle. + * + * \retval ALT_E_SUCCESS The operation was successful. + * \retval ALT_E_ERROR The operation failed. + * \retval ALT_E_BAD_ARG The given UART device handle is invalid. + */ +ALT_STATUS_CODE alt_16550_uninit(ALT_16550_HANDLE_t * handle); + +/*! + * Resets the UART to the default configuration. The UART will be reset and + * reinitialized. + * + * \param handle + * The UART device handle. + * + * \retval ALT_E_SUCCESS The operation was successful. + * \retval ALT_E_ERROR The operation failed. + * \retval ALT_E_BAD_ARG The given UART device handle is invalid. + */ +ALT_STATUS_CODE alt_16550_reset(ALT_16550_HANDLE_t * handle); + +/*! + * Starts the UART after all configuration has been completed. + * + * \param handle + * The UART device handle. + * + * \retval ALT_E_SUCCESS The operation was successful. + * \retval ALT_E_ERROR The operation failed. + * \retval ALT_E_BAD_ARG The given UART device handle is invalid. + */ +ALT_STATUS_CODE alt_16550_enable(ALT_16550_HANDLE_t * handle); + +/*! + * Stops the UART. While UART configuration can be done while enabled, it is + * not recommended. + * + * \param handle + * The UART device handle. + * + * \retval ALT_E_SUCCESS The operation was successful. + * \retval ALT_E_ERROR The operation failed. + * \retval ALT_E_BAD_ARG The given UART device handle is invalid. + */ +ALT_STATUS_CODE alt_16550_disable(ALT_16550_HANDLE_t * handle); + +/*! + * Reads a single character from the UART receiver buffer. This API should + * only be used when FIFOs are disabled. + * + * \param handle + * The UART device handle. + * + * \param item + * [out] Pointer to an output parameter that contains the in + * receiver buffer of the UART. + * + * \retval ALT_E_SUCCESS The operation was successful. + * \retval ALT_E_ERROR The operation failed. + * \retval ALT_E_BAD_ARG The given UART device handle is invalid. + */ +ALT_STATUS_CODE alt_16550_read(ALT_16550_HANDLE_t * handle, + char * item); + +/*! + * Writes a single character to the UART transmitter buffer. This API should + * only be used when FIFOs are disabled. + * + * \param handle + * The UART device handle. + * + * \param item + * The character to write to the transmitter buffer of the UART. + * + * \retval ALT_E_SUCCESS The operation was successful. + * \retval ALT_E_ERROR The operation failed. + * \retval ALT_E_BAD_ARG The given UART device handle is invalid. + */ +ALT_STATUS_CODE alt_16550_write(ALT_16550_HANDLE_t * handle, + char item); + +/*! + * @} + */ + +/*! + * \addtogroup UART_FIFO UART FIFO Interface + * + * This group of APIs provides access, configuration, and control of the UART + * FIFO. The FIFO allows the UART to buffer received data and data to be + * transmitted. + * + * @{ + */ + +/*! + * This type definition enumerates the receiver FIFO level conditions that + * will trigger the receiver FIFO to issue a receiver FIFO full event. + */ +typedef enum ALT_16550_FIFO_TRIGGER_RX_e +{ + /*! + * 1 or more character(s) in the receiver FIFO will trigger an event. + */ + ALT_16550_FIFO_TRIGGER_RX_ANY = 0, + + /*! + * 25% or higher capacity usage in the receiver FIFO will trigger an + * event. + */ + ALT_16550_FIFO_TRIGGER_RX_QUARTER_FULL = 1, + + /*! + * 50% or higher capacity usage in the receiver FIFO will trigger an + * event. + */ + ALT_16550_FIFO_TRIGGER_RX_HALF_FULL = 2, + + /*! + * 2 characters less than the receiver FIFO capacity will trigger an + * event. + */ + ALT_16550_FIFO_TRIGGER_RX_ALMOST_FULL = 3 +} +ALT_16550_FIFO_TRIGGER_RX_t; + +/*! + * This type definition enumerates the transmitter FIFO level conditions that + * will trigger the transmitter FIFO to issue a transmitter FIFO empty event. + */ +typedef enum ALT_16550_FIFO_TRIGGER_TX_e +{ + /*! + * Transmitter FIFO being completely empty will trigger an event. + */ + ALT_16550_FIFO_TRIGGER_TX_EMPTY = 0, + + /*! + * 2 or less character(s) in the transmitter FIFO will trigger an event. + */ + ALT_16550_FIFO_TRIGGER_TX_ALMOST_EMPTY = 1, + + /*! + * 25% or less capacity usage in the transmitter FIFO will trigger an + * event. + */ + ALT_16550_FIFO_TRIGGER_TX_QUARTER_FULL = 2, + + /*! + * 50% or less capacity usage in the transmitter FIFO will trigger an + * event. + */ + ALT_16550_FIFO_TRIGGER_TX_HALF_FULL = 3 +} +ALT_16550_FIFO_TRIGGER_TX_t; + +/*! + * Enables FIFO on the UART. This will enable both the receiver FIFO and + * transmitter FIFO. Both FIFOs will be cleared. + * + * \param handle + * The UART device handle. + * + * \retval ALT_E_SUCCESS The operation was successful. + * \retval ALT_E_ERROR The operation failed. + * \retval ALT_E_BAD_ARG The given UART device handle is invalid. + */ +ALT_STATUS_CODE alt_16550_fifo_enable(ALT_16550_HANDLE_t * handle); + +/*! + * Disables FIFOs on the UART. This will disable both the receiver FIFO and + * transmitter FIFO. Any data left in the FIFOs will be lost. + * + * \param handle + * The UART device handle. + * + * \retval ALT_E_SUCCESS The operation was successful. + * \retval ALT_E_ERROR The operation failed. + * \retval ALT_E_BAD_ARG The given UART device handle is invalid. + */ +ALT_STATUS_CODE alt_16550_fifo_disable(ALT_16550_HANDLE_t * handle); + +/*! + * Reads the given buffer from the receiver FIFO in the UART. + * + * The available characters in the FIFO can be determined by a few ways. Users + * can determine the number of items by calling alt_16550_fifo_level_get_rx(). + * + * Another way is by using the RX trigger and RX interrupt. First determine the + * RX FIFO size by calling alt_16550_fifo_size_get_rx(). Then set the desired + * trigger level by calling alt_16550_fifo_trigger_set_rx(). Calculate the + * triggering point by applying trigger description on the FIFO size. Enable RX + * interrupts by calling alt_16550_int_enable_rx(). When the RX interrupt fires + * due to the ALT_16550_INT_STATUS_RX_DATA condition, the calculated triggering + * point value can be used to determine the RX FIFO level. If the interrupt + * fires due to the ALT_16550_INT_STATUS_RX_TIMEOUT, the RX FIFO can be + * completely emptied by repeatedly polling the Line Status + * ALT_16550_LINE_STATUS_DR condition by calling alt_16550_line_status_get(). + * These steps are necessary if the UART does not implement FIFO level query + * functionality. As of 13.0sp1, this applies to the Altera 16550 Compatible + * Soft UART. + * + * Reading more data than that which is available can result in invalid data + * appearing like valid data. + * + * The FIFO must first be enabled before calling this function by calling + * alt_16550_fifo_enable(). + * + * \param handle + * The UART device handle. + * + * \param buffer + * [out] Pointer to a buffer where the specified count of + * characters from the receiver FIFO will be copied to. + * + * \param count + * The count of characters from the receiver FIFO to be copied. + * + * \retval ALT_E_SUCCESS The operation was successful. + * \retval ALT_E_ERROR The operation failed. + * \retval ALT_E_BAD_ARG The given UART device handle is invalid. + */ +ALT_STATUS_CODE alt_16550_fifo_read(ALT_16550_HANDLE_t * handle, + char * buffer, + size_t count); + +/*! + * Writes the given buffer to the transmitter FIFO in the UART. + * + * The available space in the FIFO can be determined by a few ways. Users can + * determine the number of items by calculating the FIFO capacity minus the + * FIFO level. This can be done by calling alt_16550_fifo_size_get_tx() and + * alt_16550_fifo_level_get_tx() respectively. + * + * Another way is by using the TX trigger and TX interrupt. First determine the + * TX FIFO size by calling alt_16550_fifo_size_get_tx(). The set the desired + * trigger level by calling alt_16550_fifo_trigger_set_tx(). Calculate the + * triggering point by applying the trigger description on the FIFO size. + * Enable TX interrupts by calling alt_16550_int_enable_tx(). When the TX + * interrupt fires, calculate the empty entries in the FIFO by subtracting the + * TX FIFO size and the calculated value. These steps are necessary if the UART + * does not implement FIFO level query functionality. As of 13.0sp1, this + * applies to the Altera 16550 Compatible Soft UART. + * + * Writing more data that there is space can result in data lost due to + * overflowing. + * + * The FIFOs must first be enabled before calling this function by calling + * alt_16550_fifo_enable(). + * + * \param handle + * The UART device handle. + * + * \param buffer + * Pointer to a buffer from where the specified count of + * characters will be copied to the transmitter FIFO. + * + * \param count + * The count of characters from the given buffer to be copied. + * + * \retval ALT_E_SUCCESS The operation was successful. + * \retval ALT_E_ERROR The operation failed. + * \retval ALT_E_BAD_ARG The given UART device handle is invalid. + */ +ALT_STATUS_CODE alt_16550_fifo_write(ALT_16550_HANDLE_t * handle, + const char * buffer, + size_t count); + +/*! + * Clears the contents of the receiver FIFO. Any characters which were + * previously contained in that FIFO will be discarded. + * + * The FIFOs must first be enabled before calling this function by calling + * alt_16550_fifo_enable(). + * + * \param handle + * The UART device handle. + * + * \retval ALT_E_SUCCESS The operation was successful. + * \retval ALT_E_ERROR The operation failed. + * \retval ALT_E_BAD_ARG The given UART device handle is invalid. + */ +ALT_STATUS_CODE alt_16550_fifo_clear_rx(ALT_16550_HANDLE_t * handle); + +/*! + * Clears the contents of the transmitter FIFO. Any characters which were + * previously contained in that FIFO will be discarded. + * + * The FIFOs must first be enabled before calling this function by calling + * alt_16550_fifo_enable(). + * + * \param handle + * The UART device handle. + * + * \retval ALT_E_SUCCESS The operation was successful. + * \retval ALT_E_ERROR The operation failed. + * \retval ALT_E_BAD_ARG The given UART device handle is invalid. + */ +ALT_STATUS_CODE alt_16550_fifo_clear_tx(ALT_16550_HANDLE_t * handle); + +/*! + * Clears the contents of the receiver and transmitter FIFO. Any characters + * which were previously contained on those FIFOs will be discarded. + * + * The FIFOs must first be enabled before calling this function by calling + * alt_16550_fifo_enable(). + * + * \param handle + * The UART device handle. + * + * \retval ALT_E_SUCCESS The operation was successful. + * \retval ALT_E_ERROR The operation failed. + * \retval ALT_E_BAD_ARG The given UART device handle is invalid. + */ +ALT_STATUS_CODE alt_16550_fifo_clear_all(ALT_16550_HANDLE_t * handle); + +/*! + * Queries the size of the receiver FIFO. + * + * \param handle + * The UART device handle. + * + * \param size + * [out] Pointer to an output parameter that contains the size of + * the receiver FIFO. + * + * \retval ALT_E_SUCCESS The operation was successful. + * \retval ALT_E_ERROR The operation failed. + * \retval ALT_E_BAD_ARG The given UART device handle is invalid. + */ +ALT_STATUS_CODE alt_16550_fifo_size_get_rx(ALT_16550_HANDLE_t * handle, + uint32_t * size); + +/*! + * Queries the size of the transmitter FIFO. + * + * \param handle + * The UART device handle. + * + * \param size + * [out] Pointer to an output parameter that contains the size of + * the transmitter FIFO. + * + * \retval ALT_E_SUCCESS The operation was successful. + * \retval ALT_E_ERROR The operation failed. + * \retval ALT_E_BAD_ARG The given UART device handle is invalid. + */ +ALT_STATUS_CODE alt_16550_fifo_size_get_tx(ALT_16550_HANDLE_t * handle, + uint32_t * size); + +/*! + * Queries the current level of the receiver FIFO. + * + * The FIFOs must first be enabled before calling this function by calling + * alt_16550_fifo_enable(). + * + * For the Altera 16550 Compatible UART, it may not be possible to read the + * FIFO level and this function may always report 0. For more information on + * interacting with the FIFO in this situation, see documentation for + * alt_16550_fifo_read(). + * + * \param handle + * The UART device handle. + * + * \param level + * [out] Pointer to an output parameter that contains the level + * or number of characters in the receiver FIFO. + * + * \retval ALT_E_SUCCESS The operation was successful. + * \retval ALT_E_ERROR The operation failed. + * \retval ALT_E_BAD_ARG The given UART device handle is invalid. + */ +ALT_STATUS_CODE alt_16550_fifo_level_get_rx(ALT_16550_HANDLE_t * handle, + uint32_t * level); + +/*! + * Queries the current level of the transmitter FIFO. + * + * The FIFOs must first be enabled before calling this function by calling + * alt_16550_fifo_enable(). + * + * For the Altera 16550 Compatible UART, it may not be possible to read the + * FIFO level and this function may always report 0. For more information on + * interacting with the FIFO in this situation, see documentation for + * alt_16550_fifo_write(). + * + * \param handle + * The UART device handle. + * + * \param level + * [out] Pointer to an output parameter that contains the level + * or number of characters in the transmitter FIFO. + * + * \retval ALT_E_SUCCESS The operation was successful. + * \retval ALT_E_ERROR The operation failed. + * \retval ALT_E_BAD_ARG The given UART device handle is invalid. + */ +ALT_STATUS_CODE alt_16550_fifo_level_get_tx(ALT_16550_HANDLE_t * handle, + uint32_t * level); + +/*! + * Sets the receiver FIFO level which will trigger the receiver FIFO to issue + * receiver FIFO full event. For the list of available receiver FIFO trigger + * levels, see the documentation for ALT_16550_FIFO_TRIGGER_RX_t. + * + * The FIFOs must first be enabled before calling this function by calling + * alt_16550_fifo_enable(). + * + * \param handle + * The UART device handle. + * + * \param trigger + * The level of the receiver FIFO which is needed to trigger a + * receiver FIFO full event. + * + * \retval ALT_E_SUCCESS The operation was successful. + * \retval ALT_E_ERROR The operation failed. + * \retval ALT_E_BAD_ARG The given UART device handle is invalid. + */ +ALT_STATUS_CODE alt_16550_fifo_trigger_set_rx(ALT_16550_HANDLE_t * handle, + ALT_16550_FIFO_TRIGGER_RX_t trigger); + +/*! + * Sets the transmitter FIFO level which will trigger the transmitter FIFO to + * transmitter FIFO empty event. For the list of available transmitter FIFO + * trigger levels, see the documentation for ALT_16550_FIFO_TRIGGER_TX_t. + * + * The FIFOs must first be enabled before calling this function by calling + * alt_16550_fifo_enable(). + * + * \param handle + * The UART device handle. + * + * \param trigger + * The level of the transmitter FIFO which is needed to trigger a + * transmitter FIFO empty event. + * + * \retval ALT_E_SUCCESS The operation was successful. + * \retval ALT_E_ERROR The operation failed. + * \retval ALT_E_BAD_ARG The given UART device handle is invalid. + */ +ALT_STATUS_CODE alt_16550_fifo_trigger_set_tx(ALT_16550_HANDLE_t * handle, + ALT_16550_FIFO_TRIGGER_TX_t trigger); + +/*! + * @} + */ + +/*! + * \addtogroup UART_BAUD UART Baudrate Interface + * + * This group of APIs allows for the configuration of the UART's baudrate + * generation related functions. + * + * The UART baudrate is determined by dividing the ALT_CLK_L4_SP clock with + * the configured divisor. + * + * @{ + */ + +/*! + * This enumeration lists out the common baudrates used with modem and serial + * ports. Not every baudrate is available for the UART due to the limits of + * the serial clock frequency and divisor value. + */ +typedef enum ALT_16550_BAUDRATE_e +{ + ALT_16550_BAUDRATE_50 = 50, /*!< 50 bps baudrate. */ + ALT_16550_BAUDRATE_75 = 75, /*!< 75 bps baudrate. */ + ALT_16550_BAUDRATE_150 = 150, /*!< 150 bps baudrate. */ + ALT_16550_BAUDRATE_300 = 300, /*!< 300 bps baudrate. */ + ALT_16550_BAUDRATE_600 = 600, /*!< 600 bps baudrate. */ + ALT_16550_BAUDRATE_900 = 900, /*!< 900 bps baudrate. */ + ALT_16550_BAUDRATE_1200 = 1200, /*!< 1200 bps baudrate. */ + ALT_16550_BAUDRATE_1800 = 1800, /*!< 1800 bps baudrate. */ + ALT_16550_BAUDRATE_2400 = 2400, /*!< 2400 bps baudrate. */ + ALT_16550_BAUDRATE_3600 = 3600, /*!< 3600 bps baudrate. */ + ALT_16550_BAUDRATE_4800 = 4800, /*!< 4800 bps baudrate. */ + ALT_16550_BAUDRATE_7200 = 7200, /*!< 7200 bps baudrate. */ + ALT_16550_BAUDRATE_9600 = 9600, /*!< 9600 bps baudrate. */ + ALT_16550_BAUDRATE_14400 = 14400, /*!< 14400 bps baudrate. */ + ALT_16550_BAUDRATE_19200 = 19200, /*!< 19200 bps baudrate. */ + ALT_16550_BAUDRATE_28800 = 28800, /*!< 28800 bps baudrate. */ + ALT_16550_BAUDRATE_38400 = 38400, /*!< 38400 bps baudrate. */ + ALT_16550_BAUDRATE_57600 = 57600, /*!< 57600 bps baudrate. */ + ALT_16550_BAUDRATE_115200 = 115200 /*!< 115200 bps baudrate. */ +} +ALT_16550_BAUDRATE_t; + +/*! + * Gets the baudrate for the UART. + * + * This is done by calculating the baudrate from the divisor and the serial + * clock. The reported baudrate may not correspond exactly to the request + * baudrate. + * + * \param handle + * The UART device handle. + * + * \param baudrate + * [out] Pointer to an output paramter that contains the current + * baudrate of the UART. + * + * \retval ALT_E_SUCCESS The operation was successful. + * \retval ALT_E_ERROR The operation failed. + * \retval ALT_E_BAD_ARG The given UART device handle is invalid. + */ +ALT_STATUS_CODE alt_16550_baudrate_get(ALT_16550_HANDLE_t * handle, + uint32_t * baudrate); + +/*! + * Sets the baudrate for the UART. This change will take effect when the UART + * moves from disabled to enabled. + * + * This is done by calculating the correct divisor using the request baudrate + * and the known serial clock. + * + * \param handle + * The UART device handle. + * + * \param baudrate + * The requested baudrate for the UART. + * + * \retval ALT_E_SUCCESS The operation was successful. + * \retval ALT_E_ERROR The operation failed. + * \retval ALT_E_BAD_ARG The given UART device handle is invalid. + * \retval ALT_E_ARG_RANGE The given baudrate is not possible due to + * limitations of the baudrate divisor and/or + * serial clock. + */ +ALT_STATUS_CODE alt_16550_baudrate_set(ALT_16550_HANDLE_t * handle, + uint32_t baudrate); + +/*! + * Gets the baudrate divisor for the UART. + * + * The baudrate is determined by the following formula: + * * Baudrate = (serial clock frequency) / (16 * divisor) + * + * \param handle + * The UART device handle. + * + * \param divisor + * [out] Pointer to an output parameter that contains the current + * divisor used for baudrate generation. + * + * \retval ALT_E_SUCCESS The operation was successful. + * \retval ALT_E_ERROR The operation failed. + * \retval ALT_E_BAD_ARG The given UART device handle is invalid. + */ +ALT_STATUS_CODE alt_16550_divisor_get(ALT_16550_HANDLE_t * handle, + uint32_t * divisor); + +/*! + * Sets the baudrate divisor for the UART. This change will take effect when + * the UART moves from disabled to enabled. + * + * The baudrate is determined by the following formula: + * * Baudrate = (serial clock frequency) / (16 * divisor) + * + * \param handle + * The UART device handle. + * + * \param divisor + * The specified divisor value to use for baudrate generation. + * Valid values are 1 - 65535. + * + * \retval ALT_E_SUCCESS The operation was successful. + * \retval ALT_E_ERROR The operation failed. + * \retval ALT_E_BAD_ARG The given UART identifier is invalid or the + * specified divisor is not supported by the + * UART. + */ +ALT_STATUS_CODE alt_16550_divisor_set(ALT_16550_HANDLE_t * handle, + uint32_t divisor); + +/*! + * @} + */ + +/*! + * \addtogroup UART_INT UART Interrupt Interface + * + * This group of APIs provides access, configuration, and control of the + * UART interrupts. + * + * @{ + */ + +/*! + * This type definition enumerates the different interrupt conditions that can + * be generated by the UART controller. + * + * Interrupts are listed in highest to lowest priority order. + */ +typedef enum ALT_16550_INT_STATUS_e +{ + /*! + * This interrupt signals that a overrun, parity, or framing error + * occurred, or a break event occured. The interrupt is cleared by reading + * the line status by calling alt_16550_line_status_get() or by disabling + * line status interrupts by calling alt_16550_int_disable_line(). + */ + ALT_16550_INT_STATUS_LINE = 0x6, + + /*! + * This interrupt signals that some data is available to be read from the + * UART. The definition of some depends on whether FIFOs are enabled or + * not. + * + * If FIFOs are disabled, this interrupt signals that the receiver + * contains data. In this case, the interrupt is cleared by reading the + * data from the UART by calling alt_16550_read(). + * + * If FIFOs are enabled, this interrupt signals that the receiver FIFO + * level is above the receiver trigger level specified. In this case, the + * interrupt is cleared by reading a sufficiently large buffer from the + * receiver FIFO such that the FIFO is filled below the receiver trigger + * level specified by calling alt_16550_fifo_read() or by adjusting the + * receiver trigger level appropriately by calling + * alt_16550_fifo_trigger_set_rx(). + * + * In either case, this interrupt can also be cleared by disabling + * receiver interrupts by calling alt_16550_int_disable_rx(). + */ + ALT_16550_INT_STATUS_RX_DATA = 0x4, + + /*! + * This interrupt signals that data is available in the receiver FIFO and + * that there has been no activity with the receiver FIFO for the last 4 + * character frames. In essence, the receiver FIFO has temporarily settled + * thus it may be a good time to empty the receiver FIFO. This interrupt + * is only available if FIFOs are enabled. The interrupt is cleared by + * reading from the receiver FIFO by calling alt_16550_fifo_read() or by + * disabling receiver interrupts by calling alt_16550_int_disable_rx(). + */ + ALT_16550_INT_STATUS_RX_TIMEOUT = 0xC, + + /*! + * This interrupt signals that the transmitter is idling. The definition + * of idling depends on whether FIFOs are enabled or not. + * + * If FIFOs are disabled, this interrupt signals that the transmitter + * shift register is empty. In this case, the interrupt is cleared by + * writing data to the UART by calling alt_16550_write(). + * + * If FIFO are enabled, this interrupt signals that the transmitter FIFO + * level is below the transmitter trigger level specified. In this case, + * the interrupt is cleared by writing a sufficiently large buffer to the + * transmitter FIFO such that the FIFO is filled above the transmitter + * trigger level specified by calling alt_16550_fifo_write() or by + * adjusting the transmitter trigger level appropriately by calling + * alt_16550_fifo_trigger_set_tx(). + * + * In either case, this interrupt can also be cleared by disabling + * transmitter interrupts by calling alt_16550_int_disable_tx(). + */ + ALT_16550_INT_STATUS_TX_IDLE = 0x2, + + /*! + * Modem status interrupt pending. The interrupt is cleared by reading the + * modem status by calling alt_16550_modem_status_get() or by disabling + * modem status interrupts by calling alt_16550_int_disable_modem(). + */ + ALT_16550_INT_STATUS_MODEM = 0x0, + + /*! + * No interrupts pending. + */ + ALT_16550_INT_STATUS_NONE = 0x1 +} +ALT_16550_INT_STATUS_t; + +/*! + * Enables the receiver FIFO to generate interrupts. Enabling this interrupt + * allows for the following interrupt signal(s): + * * ALT_16550_INT_STATUS_RX_DATA + * * ALT_16550_INT_STATUS_RX_TIMEOUT + * + * This interrupt is disabled by default. + * + * The FIFOs must also be enabled for this interrupt to actually be generated. + * + * \param handle + * The UART device handle. + * + * \retval ALT_E_SUCCESS The operation was successful. + * \retval ALT_E_ERROR The operation failed. + * \retval ALT_E_BAD_ARG The given UART device handle is invalid. + */ +ALT_STATUS_CODE alt_16550_int_enable_rx(ALT_16550_HANDLE_t * handle); + +/*! + * Disables the receiver FIFO from generating interrupts. + * + * \param handle + * The UART device handle. + * + * \retval ALT_E_SUCCESS The operation was successful. + * \retval ALT_E_ERROR The operation failed. + * \retval ALT_E_BAD_ARG The given UART device handle is invalid. + */ +ALT_STATUS_CODE alt_16550_int_disable_rx(ALT_16550_HANDLE_t * handle); + +/*! + * Enables the transmitter FIFO to generate interrupts. Enabling this + * interrupt allows for the following interrupt signal(s): + * * ALT_16550_INT_STATUS_TX_IDLE + * + * This interrupt is disabled by default. + * + * The FIFOs must also be enabled for this interrupt to actually be generated. + * + * \param handle + * The UART device handle. + * + * \retval ALT_E_SUCCESS The operation was successful. + * \retval ALT_E_ERROR The operation failed. + * \retval ALT_E_BAD_ARG The given UART device handle is invalid. + */ +ALT_STATUS_CODE alt_16550_int_enable_tx(ALT_16550_HANDLE_t * handle); + +/*! + * Disables the transmitter FIFO from generating interrupts. + * + * \param handle + * The UART device handle. + * + * \retval ALT_E_SUCCESS The operation was successful. + * \retval ALT_E_ERROR The operation failed. + * \retval ALT_E_BAD_ARG The given UART device handle is invalid. + */ +ALT_STATUS_CODE alt_16550_int_disable_tx(ALT_16550_HANDLE_t * handle); + +/*! + * Enables the receiver to generate line status interrupts. Enabling this + * interrupt allows for the following interrupt signal(s): + * * ALT_16550_INT_STATUS_LINE + * + * This interrupt is disabled by default. + * + * \param handle + * The UART device handle. + * + * \retval ALT_E_SUCCESS The operation was successful. + * \retval ALT_E_ERROR The operation failed. + * \retval ALT_E_BAD_ARG The given UART device handle is invalid. + */ +ALT_STATUS_CODE alt_16550_int_enable_line(ALT_16550_HANDLE_t * handle); + +/*! + * Disables the receiver from generating line status interrupts. + * + * \param handle + * The UART device handle. + * + * \retval ALT_E_SUCCESS The operation was successful. + * \retval ALT_E_ERROR The operation failed. + * \retval ALT_E_BAD_ARG The given UART device handle is invalid. + */ +ALT_STATUS_CODE alt_16550_int_disable_line(ALT_16550_HANDLE_t * handle); + +/*! + * Enables the UART to generate modem status interrupts. Enabling this + * interrupt allows for the following interrupt signal(s): + * * ALT_16550_INT_STATUS_MODEM + * + * This interrupt is disabled by default. + * + * \param handle + * The UART device handle. + * + * \retval ALT_E_SUCCESS The operation was successful. + * \retval ALT_E_ERROR The operation failed. + * \retval ALT_E_BAD_ARG The given UART device handle is invalid. + */ +ALT_STATUS_CODE alt_16550_int_enable_modem(ALT_16550_HANDLE_t * handle); + +/*! + * Disables the UART from generate modem status interrupts. + * + * \param handle + * The UART device handle. + * + * \retval ALT_E_SUCCESS The operation was successful. + * \retval ALT_E_ERROR The operation failed. + * \retval ALT_E_BAD_ARG The given UART device handle is invalid. + */ +ALT_STATUS_CODE alt_16550_int_disable_modem(ALT_16550_HANDLE_t * handle); + +/*! + * Disables all interrupts on the UART. + * + * \param handle + * The UART device handle. + * + * \retval ALT_E_SUCCESS The operation was successful. + * \retval ALT_E_ERROR The operation failed. + * \retval ALT_E_BAD_ARG The given UART device handle is invalid. + */ +ALT_STATUS_CODE alt_16550_int_disable_all(ALT_16550_HANDLE_t * handle); + +/*! + * Queries the interrupt status of the UART. This returns the highest priority + * interrupt pending. The appropriate interrupts must be enabled for them be + * generated in the UART. + * + * \param handle + * The UART device handle. + * + * \param status + * [out] Pointer to an output parameter that contains the current + * interrupt status of the UART. + * + * \retval ALT_E_SUCCESS The operation was successful. + * \retval ALT_E_ERROR The operation failed. + * \retval ALT_E_BAD_ARG The given UART device handle is invalid. + */ +ALT_STATUS_CODE alt_16550_int_status_get(ALT_16550_HANDLE_t * handle, + ALT_16550_INT_STATUS_t * status); + +/*! + * @} + */ + +/*! + * \addtogroup UART_MODEM UART Modem Interface + * + * This group of APIs provides access, configuration, and control of the UART + * Modem interface. + * + * @{ + */ + +/*! + * This type definition enumerates the set of UART modem status conditions as + * register mask values. + */ +typedef enum ALT_16550_MODEM_STATUS_e +{ + /*! + * Data Carrier Detect. This status indicates that the carrier has been + * detected by the modem. It corresponds to an inverted dcd_n input. DCD + * is unasserted when dcd_n is logic 1 and asserted when dcd_n is logic 0. + */ + ALT_16550_MODEM_STATUS_DCD = 1 << 7, + + /*! + * Ring Indicator. This status indicates that the telephone ringing signal + * has been redeived by the modem. It corresponds to an inverted ri_n + * input. RI is unasserted when ri_n is logic 1 and asserted when ri_n is + * logic 0. + */ + ALT_16550_MODEM_STATUS_RI = 1 << 6, + + /*! + * Data Set Ready. This status indicates that the modem is ready to + * establish communications with the UART. It corresponds to an inverted + * dsr_n input. DSR is unasserted when dsr_n is logic 1 and asserted when + * dsr_n is logic 0. + */ + ALT_16550_MODEM_STATUS_DSR = 1 << 5, + + /*! + * Clear To Send. This status indicates the current state of the modem + * cts_n line. It corresponds to an inverted cts_n input. CTS is + * unasserted when cts_n is logic 1 and asserted when cts_n is logic 0. + */ + ALT_16550_MODEM_STATUS_CTS = 1 << 4, + + /*! + * Delta Data Carrier Detect. This status condition indicates that the + * Data Carrier Detect has changed since the last time the modem status + * was read. Reading the modem status clears this status. For more + * information about the Data Carrier Detect status, see + * ALT_16550_MODEM_STATUS_DCD. + */ + ALT_16550_MODEM_STATUS_DDCD = 1 << 3, + + /*! + * Trailing Edge of Ring Indicator. This status indicates that the Ring + * Indicator has changed from asserted to unasserted. Reading the modem + * status will clear this status. For more information about the Ring + * Indicator status, reference ALT_16550_MODEM_STATUS_RI. + */ + ALT_16550_MODEM_STATUS_TERI = 1 << 2, + + /*! + * Delta Data Set Ready. This status condition indicates that the Data Set + * Ready has changed since the last time the modem status was read. + * Reading the modem status will clear this status. For more information + * about the Data Set Ready status, see ALT_16550_MODEM_STATUS_DSR. + */ + ALT_16550_MODEM_STATUS_DDSR = 1 << 1, + + /*! + * Delta Clear To Send. This status condition indicates that the Clear To + * Send has changed since the last time the modem status was read. Reading + * the modem status will clear this status. For more information about the + * Clear To Send status, see ALT_16550_MODEM_STATUS_CTS. + */ + ALT_16550_MODEM_STATUS_DCTS = 1 << 0 +} +ALT_16550_MODEM_STATUS_t; + +/*! + * Enables automatic flow control in the UART modem. When in this mode, the + * rts_n is gated with the threshold trigger condition of the receiver FIFO. + * + * The Altera 16550 Compatible Soft IP UART may not have this option enabled. + * + * The FIFOs must be enabled for flow control to be used. + * + * The recommended bring up for flow control is as follows: + * * Enable automatic flow control by calling alt_16550_flowcontrol_enable(). + * This will allow both the receiver FIFO and user RTS to control the rts_n + * output. Because the user RTS is not enabled, the rts_n will be inactive + * high. + * * Enable RTS by calling alt_16550_modem_enable_rts(). This will give the + * receiver FIFO to have full control of the rts_n output. + * + * \param handle + * The UART device handle. + * + * \retval ALT_E_SUCCESS The operation was successful. + * \retval ALT_E_ERROR The operation failed. + * \retval ALT_E_BAD_ARG The given UART device handle is invalid. + */ +ALT_STATUS_CODE alt_16550_flowcontrol_enable(ALT_16550_HANDLE_t * handle); + +/*! + * Disables automatic flow control in the UART modem. + * + * The recommended bring down for flow control is as follows: + * * Disable RTS by calling alt_16550_modem_disable_rts(). This will disable + * generation of the rts_n ouput. + * * Disable automatic flow control by calling + * alt_16550_flowcontrol_disable(). + * + * The receiver FIFO will still be active after these steps. + * + * \param handle + * The UART device handle. + * + * \retval ALT_E_SUCCESS The operation was successful. + * \retval ALT_E_ERROR The operation failed. + * \retval ALT_E_BAD_ARG The given UART device handle is invalid. + */ +ALT_STATUS_CODE alt_16550_flowcontrol_disable(ALT_16550_HANDLE_t * handle); + +/*! + * Puts the UART in loopback mode. This is used for diagnostic and test + * purposes. + * + * The SoCFPGA UARTs does not support automatic flow control when in loopback + * mode. + * + * The Altera 16550 Compatible Soft IP UART implements this in 13.0sp1 and + * later. Setting this has no effect with 13.0. + * + * When in this mode, the modem control inputs (dsr_n, cts_n, ri_n, dcd_n) are + * disconnected and the modem control outputs (dtr_n, rts_n, out1_n, out2_n) + * are held inactive high externally and internally looped back to the inputs. + * + * \param handle + * The UART device handle. + * + * \retval ALT_E_SUCCESS The operation was successful. + * \retval ALT_E_ERROR The operation failed. + * \retval ALT_E_BAD_ARG The given UART device handle is invalid. + */ +ALT_STATUS_CODE alt_16550_loopback_enable(ALT_16550_HANDLE_t * handle); + +/*! + * Takes the UART out of loopback mode. + * + * \param handle + * The UART device handle. + * + * \retval ALT_E_SUCCESS The operation was successful. + * \retval ALT_E_ERROR The operation failed. + * \retval ALT_E_BAD_ARG The given UART device handle is invalid. + */ +ALT_STATUS_CODE alt_16550_loopback_disable(ALT_16550_HANDLE_t * handle); + +/*! + * Asserts the OUT1 output. OUT1 is inverted then driven out to out1_n. + * + * There are special considerations when the UART is in loopback mode. See + * alt_16550_loopback_enable() for more information. + * + * \param handle + * The UART device handle. + * + * \retval ALT_E_SUCCESS The operation was successful. + * \retval ALT_E_ERROR The operation failed. + * \retval ALT_E_BAD_ARG The given UART device handle is invalid. + */ +ALT_STATUS_CODE alt_16550_modem_enable_out1(ALT_16550_HANDLE_t * handle); + +/*! + * Unasserts the OUT1 output. OUT1 is inverted then driven out to out1_n. + * + * There are special considerations when the UART is in loopback mode. See + * alt_16550_loopback_enable() for more information. + * + * \param handle + * The UART device handle. + * + * \retval ALT_E_SUCCESS The operation was successful. + * \retval ALT_E_ERROR The operation failed. + * \retval ALT_E_BAD_ARG The given UART device handle is invalid. + */ +ALT_STATUS_CODE alt_16550_modem_disable_out1(ALT_16550_HANDLE_t * handle); + +/*! + * Asserts the OUT2 output. OUT2 is inverted then driven out to out2_n. + * + * There are special considerations when the UART is in loopback mode. See + * alt_16550_loopback_enable() for more information. + * + * \param handle + * The UART device handle. + * + * \retval ALT_E_SUCCESS The operation was successful. + * \retval ALT_E_ERROR The operation failed. + * \retval ALT_E_BAD_ARG The given UART device handle is invalid. + */ +ALT_STATUS_CODE alt_16550_modem_enable_out2(ALT_16550_HANDLE_t * handle); + +/*! + * Unasserts the OUT2 output. OUT2 is inverted then driven out to out2_n. + * + * There are special considerations when the UART is in loopback mode. See + * alt_16550_loopback_enable() for more information. + * + * \param handle + * The UART device handle. + * + * \retval ALT_E_SUCCESS The operation was successful. + * \retval ALT_E_ERROR The operation failed. + * \retval ALT_E_BAD_ARG The given UART device handle is invalid. + */ +ALT_STATUS_CODE alt_16550_modem_disable_out2(ALT_16550_HANDLE_t * handle); + +/*! + * Asserts the RTS (Request To Send) output. RTS is inverted then driven out + * to rts_n. RTS is used to inform the modem that the UART is ready to receive + * data. + * + * There are special considerations when the UART is in automatic flow control + * mode. See alt_16550_flowcontrol_enable() for more information. + * + * There are special considerations when the UART is in loopback mode. See + * alt_16550_loopback_enable() for more information. + * + * \param handle + * The UART device handle. + * + * \retval ALT_E_SUCCESS The operation was successful. + * \retval ALT_E_ERROR The operation failed. + * \retval ALT_E_BAD_ARG The given UART device handle is invalid. + */ +ALT_STATUS_CODE alt_16550_modem_enable_rts(ALT_16550_HANDLE_t * handle); + +/*! + * Deaserts the RTS (Request To Send) output. RTS is inverted then driven out + * to rts_n. + * + * There are special considerations when the UART is in automatic flow control + * mode. See alt_16550_flowcontrol_enable() for more information. + * + * There are special considerations when the UART is in loopback mode. See + * alt_16550_loopback_enable() for more information. + * + * \param handle + * The UART device handle. + * + * \retval ALT_E_SUCCESS The operation was successful. + * \retval ALT_E_ERROR The operation failed. + * \retval ALT_E_BAD_ARG The given UART device handle is invalid. + */ +ALT_STATUS_CODE alt_16550_modem_disable_rts(ALT_16550_HANDLE_t * handle); + +/*! + * Asserts the DTR (Data Terminal Ready) output. DTR is inverted then driven + * out to dtr_n. DTR is used to inform the modem that UART is ready to + * establish communications. + * + * There are special considerations when the UART is in loopback mode. See + * alt_16550_loopback_enable() for more information. + * + * \param handle + * The UART device handle. + * + * \retval ALT_E_SUCCESS The operation was successful. + * \retval ALT_E_ERROR The operation failed. + * \retval ALT_E_BAD_ARG The given UART device handle is invalid. + */ +ALT_STATUS_CODE alt_16550_modem_enable_dtr(ALT_16550_HANDLE_t * handle); + +/*! + * Deasserts the DTR (Data Terminal Ready) output. DTR is inverted then driven + * out to dtr_n. + * + * There are special considerations when the UART is in loopback mode. See + * alt_16550_loopback_enable() for more information. + * + * \param handle + * The UART device handle. + * + * \retval ALT_E_SUCCESS The operation was successful. + * \retval ALT_E_ERROR The operation failed. + * \retval ALT_E_BAD_ARG The given UART device handle is invalid. + */ +ALT_STATUS_CODE alt_16550_modem_disable_dtr(ALT_16550_HANDLE_t * handle); + +/*! + * Reads the modem status from the UART. + * + * \param handle + * The UART device handle. + * + * \param status + * [out] Pointer to an output parameter that contains the current + * modem status of the UART as a register mask. + * + * \retval ALT_E_SUCCESS The operation was successful. + * \retval ALT_E_ERROR The operation failed. + * \retval ALT_E_BAD_ARG The given UART device handle is invalid. + */ +ALT_STATUS_CODE alt_16550_modem_status_get(ALT_16550_HANDLE_t * handle, + uint32_t * status); + +/*! + * @} + */ + +/*! + * \addtogroup UART_LINE UART Line Interface + * + * This group of APIs provides access, configuration, and control of the UART + * Line interface. + * + * @{ + */ + +/*! + * This type definition enumerates the supported databits per frame. + */ +typedef enum ALT_16550_DATABITS_e +{ + /*! + * This option selects 5 databits per frame. + */ + ALT_16550_DATABITS_5 = 0, + + /*! + * This option selects 6 databits per frame. + */ + ALT_16550_DATABITS_6 = 1, + + /*! + * This option selects 7 databits per frame. + */ + ALT_16550_DATABITS_7 = 2, + + /*! + * This option selects 8 databits per frame. + */ + ALT_16550_DATABITS_8 = 3 +} +ALT_16550_DATABITS_t; + +/*! + * This type definition enumerates the supported stopbits per frame. + */ +typedef enum ALT_16550_STOPBITS_e +{ + /*! + * This options specifies 1 stopbit per frame. + */ + ALT_16550_STOPBITS_1 = 0, + + /*! + * This options specifies 2 stopbits per frame. If the frame is + * configured with 5 databits, 1.5 stopbits is used instead. + */ + ALT_16550_STOPBITS_2 = 1 +} +ALT_16550_STOPBITS_t; + +/*! + * This type definition enumerates the possible parity to use per frame. + */ +typedef enum ALT_16550_PARITY_e +{ + /*! + * This option disables the parity error detection bit in the data frame. + */ + ALT_16550_PARITY_DISABLE = 0, + + /*! + * This option enables the odd parity error detection bit in the data + * frame. + */ + ALT_16550_PARITY_ODD = 1, + + /*! + * This option enables the even parity error detection bit in the data + * frame. + */ + ALT_16550_PARITY_EVEN = 2 +} +ALT_16550_PARITY_t; + +/*! + * This type definition enumerates the set of UART line status conditions as + * register mask values. + */ +typedef enum ALT_16550_LINE_STATUS_e +{ + /*! + * Receiver FIFO Error. This status indicates that one or more parity + * error, framing error, or break indication exists in the receiver FIFO. + * It is only set when FIFO is enabled. This status cleared when line + * status is read, the character with the issue is at the top of the FIFO, + * and when no other issues exist in the FIFO. + */ + ALT_16550_LINE_STATUS_RFE = 1 << 7, + + /*! + * Transmitter EMpTy (Empty). This status indicates that transmitter shift + * register is empty. If FIFOs are enabled, the status is set when the + * transmitter FIFO is also empty. This status is cleared when the + * transmitter shift registers is loaded by writing to the UART + * transmitter buffer or transmitter FIFO if FIFOs are enabled. This is + * done by calling alt_16550_write() and alt_16550_fifo_write() + * respectively. + */ + ALT_16550_LINE_STATUS_TEMT = 1 << 6, + + /*! + * Transmitter Holding Register Empty. This status indicates that the + * transmitter will run out of data soon. The definition of soon depends + * on whether the FIFOs are enabled. + * + * If FIFOs are disabled, this status indicates that the transmitter will + * run out of data to send after the current transmit shift register + * completes. In this case, this status is cleared when the data is + * written to the UART. This can be done by calling alt_16550_write(). + * + * If FIFOs are enabled, this status indicates that the transmitter FIFO + * level is below the transmitter trigger level specified. In this case, + * this status is cleared by writing a sufficiently large buffer to the + * transmitter FIFO such that the FIFO is filled above the transmitter + * trigger level specified by calling alt_16550_fifo_write() or by + * adjusting the transmitter trigger level appropriately by calling + * alt_16550_fifo_trigger_set_tx(). + * + * \internal + * The implementation of the UART driver always ensures that IER[7] is + * set. This means that the UART always has Programmable THRE (Transmitter + * Holding Register Empty) Interrupt Mode Enable (PTIME) enabled. + * \endinternal + */ + ALT_16550_LINE_STATUS_THRE = 1 << 5, + + /*! + * Break Interrupt. This status indicates that a break interrupt sequence + * is detected in the incoming serial data. This happens when the the data + * is 0 for longer than a frame would normally be transmitted. The break + * interrupt status is cleared by reading the line status by calling + * alt_16550_line_status_get(). + * + * If FIFOs are enabled, this status will be set when the character with + * the break interrupt status is at the top of the receiver FIFO. + */ + ALT_16550_LINE_STATUS_BI = 1 << 4, + + /*! + * Framing Error. This status indicates that a framing error occurred in + * the receiver. This happens when the receiver detects a missing or + * incorrect number of stopbit(s). + * + * If FIFOs are enabled, this status will be set when the character with + * the framing error is at the top of the FIFO. When a framing error + * occurs, the UART attempts to resynchronize with the transmitting UART. + * This status is also set if break interrupt occurred. + */ + ALT_16550_LINE_STATUS_FE = 1 << 3, + + /*! + * Parity Error. This status indicates that a parity error occurred in the + * receiver. + * + * If FIFOs are enabled, this status will be set when the character with + * the parity error is at the top of the receiver FIFO. This status is + * also set if a break interrupt occurred. + */ + ALT_16550_LINE_STATUS_PE = 1 << 2, + + /*! + * Overrun Error. This status indicates that an overrun occurred in the + * receiver. + * + * If FIFOs are disabled, the arriving character will overwrite the + * existing character in the receiver. Any previously existing + * character(s) will be lost. + * + * If FIFOs are disabled, the arriving character will be discarded. The + * buffer will continue to contain the preexisting characters. + */ + ALT_16550_LINE_STATUS_OE = 1 << 1, + + /*! + * Data Ready. This status indicates that the receiver or receiver FIFO + * contains at least one character. + */ + ALT_16550_LINE_STATUS_DR = 1 << 0 +} +ALT_16550_LINE_STATUS_t; + +/*! + * Sets the configuration for a given character frame. + * + * \param handle + * The UART device handle. + * + * \param databits + * The number of databits for each character frame. + * + * \param parity + * The parity to use for each character frame. + * + * \param stopbits + * The number of stopbits for each character frame. + * + * \retval ALT_E_SUCCESS The operation was successful. + * \retval ALT_E_ERROR The operation failed. + * \retval ALT_E_BAD_ARG The given UART device handle is invalid. + */ +ALT_STATUS_CODE alt_16550_line_config_set(ALT_16550_HANDLE_t * handle, + ALT_16550_DATABITS_t databits, + ALT_16550_PARITY_t parity, + ALT_16550_STOPBITS_t stopbits); + +/*! + * Starts transmitting a break condition by transmitting a logic 0 state + * longer than a frame would normally be transmitted. + * + * \param handle + * The UART device handle. + * + * \retval ALT_E_SUCCESS The operation was successful. + * \retval ALT_E_ERROR The operation failed. + * \retval ALT_E_BAD_ARG The given UART device handle is invalid. + */ +ALT_STATUS_CODE alt_16550_line_break_enable(ALT_16550_HANDLE_t * handle); + +/*! + * Stops transmitting a break condition. + * + * \param handle + * The UART device handle. + * + * \retval ALT_E_SUCCESS The operation was successful. + * \retval ALT_E_ERROR The operation failed. + * \retval ALT_E_BAD_ARG The given UART device handle is invalid. + */ +ALT_STATUS_CODE alt_16550_line_break_disable(ALT_16550_HANDLE_t * handle); + +/*! + * Reads the line status from the UART. + * + * \param handle + * The UART device handle. + * + * \param status + * [out] Pointer to an output parameter that contains the current + * line status of the UART. + * + * \retval ALT_E_SUCCESS The operation was successful. + * \retval ALT_E_ERROR The operation failed. + * \retval ALT_E_BAD_ARG The given UART device handle is invalid. + */ +ALT_STATUS_CODE alt_16550_line_status_get(ALT_16550_HANDLE_t * handle, + uint32_t * status); + +/*! + * @} + */ + +/*! + * @} + */ + +#ifdef __cplusplus +} +#endif + +#endif /* __ALT_16550_UART_H__ */ diff --git a/c/src/lib/libbsp/arm/altera-cyclone-v/hwlib/include/alt_cache.h b/c/src/lib/libbsp/arm/altera-cyclone-v/hwlib/include/alt_cache.h new file mode 100644 index 0000000000..8d088ab744 --- /dev/null +++ b/c/src/lib/libbsp/arm/altera-cyclone-v/hwlib/include/alt_cache.h @@ -0,0 +1,964 @@ +/****************************************************************************** + * + * Copyright 2013 Altera Corporation. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED. IN NO + * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + ******************************************************************************/ + +#ifndef __ALT_CACHE_H__ +#define __ALT_CACHE_H__ + +#include "hwlib.h" + +#ifdef __cplusplus +extern "C" +{ +#endif + +/*! + * \addtogroup CACHE_MGR Cache Management API + * + * This module defines the cache management API for enabling and disabling L1 + * data cache, L1 instruction cache, L1 dynamic branch prediction caches, L1 + * TLB cache, and L2 cache in the SoC. As well, many it allows users to perform + * cache maintenance operations on these caches. This includes the following + * operations: + * * Invalidate: Marks the cache line as being invalid, freeing up the space + * to cache other data. All APIs which enable caches invalidates the memory + * before being enabling the cache. + * * Clean: If the cache line is dirty, it synchronizes the cache line data + * with the upper level memory system and marks that line as clean. All APIs + * which disable caches cleans the memory before disabling the cache. + * * Purge: A term used in this API as a short form for clean and invalidate. + * This operation cleans and invalidates a cache line in that order, as a + * single command to the cache controller. + * + * The following reference materials were used in the design of this API: + * * ARM® Architecture Reference Manual, ARMv7-A and ARMv7-R edition + * * Cortex™-A9 Technical Reference Manual + * * Cortex™-A9 MPCore Technical Reference Manual + * * CoreLink™ Level 2 Cache Controller L2C-310 Technical Reference + * Manual + * + * @{ + */ + +/*! + * \addtogroup CACHE_SYS System Level Cache Management API + * + * This API group provides cache maintenance operations which affects multiple + * cache levels. + * + * The enable and disable functions enables and disables all caches in the + * system respectively. For caches shared by the CPU core(s), particularly the + * L2 cache, once that cache is enabled or disabled it will not be invalidated + * or cleaned again respectively. This allows the safe system-wide enable and + * disable to be used in single-core and multi-core scenarios. + * + * For cache maintenance operations, this API implements the procedures + * outlined in the L2C-310 Technical Reference Manual, section 3.3.10, + * subsection "System cache maintenance considerations". This allows for a + * convenient way to invalidate, clean, or clean and invalidate cache data from + * the L1 to L2 to L3 while avoiding any potential race conditions in + * mutli-core or multi-master scenarios. It assumes that the L1 and L2 cache is + * set in "non-exclusive" mode. This means a segment of data can reside in both + * the L1 and L2 simultaneously. This is the default mode for caches in the + * system. + * + * The current implementation of the system cache APIs assumes that the MMU is + * configured with a flat memory mapping or that every virtual address matches + * perfectly with the physical address. This restriction may be lifted in a + * future release of the cache API implementation. + * + * @{ + */ + +/*! + * Enables support for a non-flat virtual memory. A flat virtual memory is + * where every virtual address matches exactly to the physical address, making + * the virtual to physical translation trivial. Adding support for non-flat + * adds some overhead for the VA to PA translation and error detection. + * + * To enable non-flat virtual memory support, defined + * ALT_CACHE_SUPPORT_NON_FLAT_VIRTUAL_MEMORY=1 in your Makefile when compiling + * HWLibs. + */ +#ifndef ALT_CACHE_SUPPORT_NON_FLAT_VIRTUAL_MEMORY +#define ALT_CACHE_SUPPORT_NON_FLAT_VIRTUAL_MEMORY (0) +#endif + +/*! + * This is the system wide cache line size, given in bytes. + */ +#define ALT_CACHE_LINE_SIZE 32 + +/*! + * Enables all caches and features which improve reliability and speed on all + * cache controllers visible to the current CPU core. This includes parity + * error detection. Cache controllers visible to multiple CPU cores, for + * example the L2, will first be checked to be disabled before being enabled. + * All necessary cache maintenance operations will be done automatically. + * + * \retval ALT_E_SUCCESS The operation was successful. + * \retval ALT_E_ERROR The operation failed. + */ +ALT_STATUS_CODE alt_cache_system_enable(void); + +/*! + * Disables all cache controllers visible to the current CPU core. Cache + * controllers visible to multiple CPU cores, for example the L2, will first + * be checked to be enabled before being disabled. All necessary cache + * maintenance operations will be done automatically. + * + * \retval ALT_E_SUCCESS The operation was successful. + * \retval ALT_E_ERROR The operation failed. + */ +ALT_STATUS_CODE alt_cache_system_disable(void); + +/*! + * Invalidates the specified contents of all cache levels visible to the + * current CPU core for the given memory segment. + * + * The memory segment address and length specified must align to the + * characteristics of the cache line. This means the address and length must be + * multiples of the cache line size. To determine the cache line size, use the + * \b ALT_CACHE_LINE_SIZE macro. + * + * The following pseudocode outlines the operations carried out by this + * function: + * -# L2 invalidate address(es) + * -# L2 cache sync + * -# L1 invalidate address(es) + * -# DSB instruction + * + * The current implementation of the system cache APIs assumes that the MMU is + * configured with a flat memory mapping or that every virtual address matches + * perfectly with the physical address. This restriction may be lifted in a + * future release of the cache API implementation. + * + * \param vaddress + * The virtual address of the memory segment to be invalidated. + * + * \param length + * The length of the memory segment to be invalidated. + * + * \retval ALT_E_SUCCESS The operation was successful. + * \retval ALT_E_ERROR The operation failed. + * \retval ALT_E_BAD_ARG The memory segment is invalid. + * \retval ALT_E_TMO The memory operation timed out. + */ +ALT_STATUS_CODE alt_cache_system_invalidate(void * vaddress, size_t length); + +/*! + * Cleans the specified contents of all cache levels visible to the current + * CPU core for the given memory segment. + * + * The memory segment address and length specified must align to the + * characteristics of the cache line. This means the address and length must be + * multiples of the cache line size. To determine the cache line size, use the + * \b ALT_CACHE_LINE_SIZE macro. + * + * The following pseudocode outlines the operations carried out by this + * function: + * -# L1 clean address(es) + * -# DSB instruction + * -# L2 clean address(es) + * -# L2 cache sync + * + * The current implementation of the system cache APIs assumes that the MMU is + * configured with a flat memory mapping or that every virtual address matches + * perfectly with the physical address. This restriction may be lifted in a + * future release of the cache API implementation. + * + * \param vaddress + * The virtual address of the memory segment to be cleaned. + * + * \param length + * The length of the memory segment to be cleaned. + * + * \retval ALT_E_SUCCESS The operation was successful. + * \retval ALT_E_ERROR The operation failed. + * \retval ALT_E_BAD_ARG The memory segment is invalid. + * \retval ALT_E_TMO The memory operation timed out. + */ +ALT_STATUS_CODE alt_cache_system_clean(void * vaddress, size_t length); + +/*! + * Cleans and invalidates the specified contents of all cache levels visible + * to the current CPU core for the given memory segment. + * + * The memory segment address and length specified must align to the + * characteristics of the cache line. This means the address and length must be + * multiples of the cache line size. To determine the cache line size, use the + * \b ALT_CACHE_LINE_SIZE macro. + * + * The following pseudocode outlines the operations carried out by this + * function: + * -# L1 clean address(es) + * -# DSB instruction + * -# L2 clean and invalidate address(es) + * -# L2 cache sync + * -# L1 invalidate address(es) + * -# DSB instruction + * + * The current implementation of the system cache APIs assumes that the MMU is + * configured with a flat memory mapping or that every virtual address matches + * perfectly with the physical address. This restriction may be lifted in a + * future release of the cache API implementation. + * + * \param vaddress + * The virtual address of the memory segment to be purged. + * + * \param length + * The length of the memory segment to be purged. + * + * \retval ALT_E_SUCCESS The operation was successful. + * \retval ALT_E_ERROR The operation failed. + * \retval ALT_E_BAD_ARG The memory segment is invalid. + * \retval ALT_E_TMO The memory operation timed out. + */ +ALT_STATUS_CODE alt_cache_system_purge(void * vaddress, size_t length); + +/*! + * @} + */ + +/*! + * \addtogroup CACHE_L1 L1 Cache Management API + * + * This API group provides functions to interact with various components of the + * L1 cache on the SoCFPGA. This includes the following cache components: + * * Instruction Cache + * * Data Cache + * * Parity error detection + * * Dynamic branch prediction + * * Data prefetching + * + * The API within this group only affects the L1 cache on the current CPU. To + * interact the L1 cache on another CPU, the API must be called from that other + * CPU. + * + * With respect to bring-up, the L1 and L2 cache controller setups are fully + * independent. The L2 can be setup at any time, before or after the L1 is setup. + * \internal + * Source: Cortex-A9 MPCore TRM, section 5.3.4 "Multiprocessor bring-up". + * \endinternal + * + * @{ + */ + +/*! + * Enables all L1 caches and features on the current CPU core. This includes + * the instruction cache, data cache, parity error detection, branch target + * address cache, global history buffer, and data prefetching. All necessary + * maintenance tasks will be taken care of. + * + * This function should not be mixed with other L1 cache related functions + * which enable or disable caches individually. + * + * \retval ALT_E_SUCCESS The operation was successful. + * \retval ALT_E_ERROR The operation failed. + */ +ALT_STATUS_CODE alt_cache_l1_enable_all(void); + +/*! + * Disables all L1 caches and features on the current CPU core. This includes + * the instruction cache, data cache, parity error detection, branch target + * address cache, global history buffer, and data prefetching. All necessary + * maintenance tasks will be taken care of. + * + * This function should not be mixed with other L1 cache related functions + * which enable or disable caches individually. + * + * \retval ALT_E_SUCCESS The operation was successful. + * \retval ALT_E_ERROR The operation failed. + */ +ALT_STATUS_CODE alt_cache_l1_disable_all(void); + +/*! + * Enables the L1 instruction cache on the current CPU core. If the cache is + * already enabled, nothing is done. Otherwise the instruction cache is first + * invalidated before being enabled. + * + * \retval ALT_E_SUCCESS The operation was successful. + * \retval ALT_E_ERROR The operation failed. + */ +ALT_STATUS_CODE alt_cache_l1_instruction_enable(void); + +/*! + * Disables the L1 instruction cache on the current CPU core. + * + * \retval ALT_E_SUCCESS The operation was successful. + * \retval ALT_E_ERROR The operation failed. + */ +ALT_STATUS_CODE alt_cache_l1_instruction_disable(void); + +/*! + * Returns \b true when the L1 instruction cache is enabled and \b false when + * it is disabled on the current CPU core. + * + * \retval true The L1 instruction cache is enabled. + * \retval false The L1 instruction cache is disabled. + */ +bool alt_cache_l1_instruction_is_enabled(void); + +/*! + * Invalidates the contents of the L1 instruction cache on the current CPU + * core. + * + * Normally this is done automatically as part of + * alt_cache_l1_instruction_enable(), but in certain circumstances it may be + * necessary to invalidate it manually. An example of this situation is when + * the address space is remapped and the processor executes instructions from + * the new memory area. + * + * \retval ALT_E_SUCCESS The operation was successful. + * \retval ALT_E_ERROR The operation failed. + */ +ALT_STATUS_CODE alt_cache_l1_instruction_invalidate(void); + +/*! + * Enables the L1 data cache on the current CPU core. + * + * If the cache is already enabled nothing is done. Otherwise the data cache is + * first invalidated before being enabled. + * + * \retval ALT_E_SUCCESS The operation was successful. + * \retval ALT_E_ERROR The operation failed. + */ +ALT_STATUS_CODE alt_cache_l1_data_enable(void); + +/*! + * Disables the L1 data cache on the current CPU core. + * + * If the cache is already disabled nothing is done. Otherwise the data cache + * is first cleaned before being disabled. + * + * \retval ALT_E_SUCCESS The operation was successful. + * \retval ALT_E_ERROR The operation failed. + */ +ALT_STATUS_CODE alt_cache_l1_data_disable(void); + +/*! + * Returns \b true when the L1 data cache is enabled and \b false when it is + * disabled on the current CPU core. + * + * \retval true The L1 data cache is enabled. + * \retval false The L1 data cache is disabled. + */ +bool alt_cache_l1_data_is_enabled(void); + +/*! + * Invalidates the specified contents of the L1 data cache on the current CPU + * core for the given memory segment. + * + * The memory segment address and length specified must align to the + * characteristics of the cache line. This means the address and length must be + * multiples of the cache line size. To determine the cache line size, use the + * \b ALT_CACHE_LINE_SIZE macro. + * + * \param vaddress + * The virtual address of the memory segment to be invalidated. + * + * \param length + * The length of the memory segment to be invalidated. + * + * \retval ALT_E_SUCCESS The operation was successful. + * \retval ALT_E_ERROR The operation failed. + * \retval ALT_E_BAD_ARG The memory segment is invalid. + */ +ALT_STATUS_CODE alt_cache_l1_data_invalidate(void * vaddress, size_t length); + +/*! + * Invalidates the entire contents of the L1 data cache on the current CPU + * core. + * + * Normally this is done automatically as part of alt_cache_l1_data_enable(), + * but in certain circumstances it may be necessary to invalidate it manually. + * An example of this situation is when the address space is remapped and the + * processor accesses memory from the new memory area. + * + * \retval ALT_E_SUCCESS The operation was successful. + * \retval ALT_E_ERROR The operation failed. + */ +ALT_STATUS_CODE alt_cache_l1_data_invalidate_all(void); + +/*! + * Cleans the specified contents of the L1 data cache on the current CPU core + * for the given memory segment. + * + * The memory segment address and length specified must align to the + * characteristics of the cache line. This means the address and length must be + * multiples of the cache line size. To determine the cache line size, use the + * \b ALT_CACHE_LINE_SIZE macro. + * + * \param vaddress + * The virtual address of the memory segment to be cleaned. + * + * \param length + * The length of the memory segment to be cleaned. + * + * \retval ALT_E_SUCCESS The operation was successful. + * \retval ALT_E_ERROR The operation failed. + * \retval ALT_E_BAD_ARG The memory segment is invalid. + */ +ALT_STATUS_CODE alt_cache_l1_data_clean(void * vaddress, size_t length); + +/*! + * Cleans the entire L1 data cache for the current CPU core. + * + * \retval ALT_E_SUCCESS The operation was successful. + * \retval ALT_E_ERROR The operation failed. + */ +ALT_STATUS_CODE alt_cache_l1_data_clean_all(void); + +/*! + * Cleans and invalidates the specified contents of the L1 data cache on the + * current CPU core for the given memory segment. + * + * The memory segment address and length specified must align to the + * characteristics of the cache line. This means the address and length must be + * multiples of the cache line size. To determine the cache line size, use the + * \b ALT_CACHE_LINE_SIZE macro. + * + * Normally this is done automatically as part of alt_cache_l1_data_disable(), + * but in certain circumstances it may be necessary to purged it manually. + * An example of this situation is when the address space is remapped and the + * processor accesses memory from the new memory area. + * + * \param vaddress + * The virtual address of the memory segment to be purged. + * + * \param length + * The length of the memory segment to be purged. + * + * \retval ALT_E_SUCCESS The operation was successful. + * \retval ALT_E_ERROR The operation failed. + * \retval ALT_E_BAD_ARG The memory segment is invalid. + */ +ALT_STATUS_CODE alt_cache_l1_data_purge(void * vaddress, size_t length); + +/*! + * Cleans and invalidates the entire L1 data cache for the current CPU core. + * + * \retval ALT_E_SUCCESS The operation was successful. + * \retval ALT_E_ERROR The operation failed. + */ +ALT_STATUS_CODE alt_cache_l1_data_purge_all(void); + +/*! + * Enables the parity error detection feature in the L1 caches on the current + * CPU core. + * + * Ideally parity should be enabled before any L1 caches are enabled. If the + * instruction, data, and / or dynamic branch predictor caches are already + * enabled, they will first be cleaned (if needed) and disabled before parity + * is enabled in hardware. Afterwards, the affected caches will be invalidated + * and enabled. + * + * Parity and TLB interaction deserves special attention. The TLB is considered + * to be a L1 cache but is enabled when the MMU, which is grouped in another + * API, is enabled. Due to the system-wide influence of the MMU, it cannot be + * disabled and enabled with impunity as the other L1 caches, which are + * designed to operate as transparently as possible. Thus parity error + * detection must be enabled before the L1 TLB cache, and by extension the MMU, + * is enabled. + * + * For a parity error to be reported, the appropriate CPU PARITYFAIL interrupt + * for the current CPU core must be enabled using the interrupt controller API. + * For CPU0, ALT_INT_INTERRUPT_CPU0_PARITYFAIL is asserted if any parity error + * is detected while the other PARITYFAIL interrupts are for parity errors in a + * specific memory. Refer to the interrupt controller API for more details + * about programming the interrupt controller. + * + * In the event of a parity error is detected, the appropriate CPU parity + * interrupt will be raised. CPU parity interrupts are all edge triggered and + * are cleared by acknowledging them in the interrupt controller API. + * + * \retval ALT_E_SUCCESS The operation was successful. + * \retval ALT_E_ERROR The operation failed. + */ +ALT_STATUS_CODE alt_cache_l1_parity_enable(void); + +/*! + * Disables parity error detection in the L1 caches. + * + * \retval ALT_E_SUCCESS The operation was successful. + * \retval ALT_E_ERROR The operation failed. + */ +ALT_STATUS_CODE alt_cache_l1_parity_disable(void); + +/*! + * Returns \b true when parity error detection is enabled and \b false when it + * is disabled on the current CPU core. + * + * \retval true Parity error detection for L1 caches is + * enabled. + * \retval false Parity error detection for L1 caches is + * disabled. + */ +bool alt_cache_l1_parity_is_enabled(void); + +/*! + * Enables the dynamic branch predictor features on the current CPU core. + * + * This operation enables both the Branch Target Address Cache (BTAC) and + * the Global History Buffer (GHB). Affected caches are automatically + * invalidated before use. + * + * \retval ALT_E_SUCCESS The operation was successful. + * \retval ALT_E_ERROR The operation failed. + */ +ALT_STATUS_CODE alt_cache_l1_branch_enable(void); + +/*! + * Disables the dynamic branch predictor features on the current CPU core. + * + * This operation disables both the Branch Target Address Cache (BTAC) and + * the Global History Buffer (GHB). + * + * \retval ALT_E_SUCCESS The operation was successful. + * \retval ALT_E_ERROR The operation failed. + */ +ALT_STATUS_CODE alt_cache_l1_branch_disable(void); + +/*! + * Returns \b true when both the dynamic predictor features are enabled and + * \b false when they are disabled on the current CPU core. + * + * \retval true The L1 branch predictor caches are all enabled. + * \retval false Some or all L1 branch predictor caches are + * disabled. + */ +bool alt_cache_l1_branch_is_enabled(void); + +/*! + * Invalidates the dynamic branch predictor feature caches on the current CPU + * core. + * + * \retval ALT_E_SUCCESS The operation was successful. + * \retval ALT_E_ERROR The operation failed. + */ +ALT_STATUS_CODE alt_cache_l1_branch_invalidate(void); + +/*! + * Enables the L1 cache data prefetch feature on the current CPU core. + * + * This allows data to be prefetched into the data cache before it is to be + * used. For example in a loop the current iteration may want to preload the + * data which will be used in the next teration. This is done by using the PLD + * instructions. + * + * \retval ALT_E_SUCCESS The operation was successful. + * \retval ALT_E_ERROR The operation failed. + */ +ALT_STATUS_CODE alt_cache_l1_prefetch_enable(void); + +/*! + * Disables the L1 cache data prefetch feature on the current CPU core. + * + * \retval ALT_E_SUCCESS The operation was successful. + * \retval ALT_E_ERROR The operation failed. + */ +ALT_STATUS_CODE alt_cache_l1_prefetch_disable(void); + +/*! + * Returns \b true if the L1 cache data prefetch feature is enabled and + * \b false if it is disabled on the current CPU core. + * + * \retval true The L1 data cache prefetch feature is enabled. + * \retval false The L1 data cache prefetch feature is disabled. + */ +bool alt_cache_l1_prefetch_is_enabled(void); + +/*! + * @} + */ + +/*! + * \addtogroup CACHE_L2 L2 Cache Management API + * + * This API group provides functions to interact with various features of the + * L2 cache on the SoCFPGA. This includes the following features: + * * L2 cache + * * Parity error detection + * * Data prefetching + * * Interrupt Management + * + * \internal + * Additional features that may be implemented in the future: + * * Lockdown + * * Event counter + * \endinternal + * + * The API within this group affects the L2 cache which is visible to all CPUs + * on the system. + * + * With respect to bring-up, the L1 and L2 cache controller setups are fully + * independent. The L2 can be setup at any time, before or after the L1 is setup. + * \internal + * Source: Cortex-A9 MPCore TRM, section 5.3.4 "Multiprocessor bring-up". + * \endinternal + * + * @{ + */ + +/*! + * Initializes the L2 cache controller. + * + * \retval ALT_E_SUCCESS Successful status. + * \retval ALT_E_ERROR Details about error status code + */ +ALT_STATUS_CODE alt_cache_l2_init(void); + +/*! + * Uninitializes the L2 cache controller. + * + * \retval ALT_E_SUCCESS Successful status. + * \retval ALT_E_ERROR Details about error status code + */ +ALT_STATUS_CODE alt_cache_l2_uninit(void); + +/*! + * Enables the L2 cache features for data and instruction prefetching. + * + * Prefetching can be enabled or disabled while the L2 cache is enabled. + * \internal + * Source: Use the Prefetch Control Register. + * \endinternal + * + * \retval ALT_E_SUCCESS The operation was successful. + * \retval ALT_E_ERROR The operation failed. + */ +ALT_STATUS_CODE alt_cache_l2_prefetch_enable(void); + +/*! + * Disables the L2 cache features for data and instruction prefetching. + * + * Prefetching can be enabled or disabled while the L2 cache is enabled. + * \internal + * Source: Use the Prefetch Control Register. + * \endinternal + * + * \retval ALT_E_SUCCESS The operation was successful. + * \retval ALT_E_ERROR The operation failed. + */ +ALT_STATUS_CODE alt_cache_l2_prefetch_disable(void); + +/*! + * Returns \b true if either L2 cache data or instruction prefetch features are + * enabled and \b false if no prefetching features are enabled. + * + * \retval true The L2 data and instruction prefetch features + * are enabled. + * \retval false Some L2 data and instruction prefetch features + * are disabled. + */ +bool alt_cache_l2_prefetch_is_enabled(void); + +/*! + * Enables parity error detection in the L2 cache. + * + * Ideally parity should be enabled before the L2 cache is enabled. If the + * cache is already enabled, it will first be cleaned and disabled before + * parity is enabled in hardware. Afterwards, the cache will be invalidated and + * enabled. + * + * For a parity error to be reported, the ALT_CACHE_L2_INTERRUPT_PARRD and / or + * ALT_CACHE_L2_INTERRUPT_PARRT interrupt condition(s) must be enabled. This is + * done by calling alt_cache_l2_int_enable(). As well, the L2 cache interrupt + * must be enabled using the interrupt controller API. Refer to the interrupt + * controller API for more details about programming the interrupt controller. + * + * In the event of a parity error is detected, the appropriate L2 cache parity + * interrupt will be raised. To clear the parity interrupt(s), the appropriate + * L2 cache parity interrupt must be cleared by calling + * alt_cache_l2_int_status_clear(). + * + * For ECC support, refer to the ECC related API documentation for more + * information. + * + * \retval ALT_E_SUCCESS The operation was successful. + * \retval ALT_E_ERROR The operation failed. + */ +ALT_STATUS_CODE alt_cache_l2_parity_enable(void); + +/*! + * Disables parity error detection in the L2 cache. + * + * \retval ALT_E_SUCCESS The operation was successful. + * \retval ALT_E_ERROR The operation failed. + */ +ALT_STATUS_CODE alt_cache_l2_parity_disable(void); + +/*! + * Returns \b true when parity error detection is enabled and \b false when it + * is disabled. + * + * \retval true The L2 cache parity error detection feature is + * enabled. + * \retval false The L2 cache parity error detection feature is + * disabled. + */ +bool alt_cache_l2_parity_is_enabled(void); + +/*! + * Enables the L2 cache. + * + * If the L2 cache is already enabled, nothing is done. Otherwise the entire + * contents of the cache is first invalidated before being enabled. + * + * \retval ALT_E_SUCCESS The operation was successful. + * \retval ALT_E_ERROR The operation failed. + */ +ALT_STATUS_CODE alt_cache_l2_enable(void); + +/*! + * Disables the L2 cache. + * + * If the L2 cache is already disabled, nothing is done. Otherwise the entire + * contents of the cache is first cleaned before being disabled. + * + * \retval ALT_E_SUCCESS The operation was successful. + * \retval ALT_E_ERROR The operation failed. + */ +ALT_STATUS_CODE alt_cache_l2_disable(void); + +/*! + * Returns \b true when the L2 cache is enabled and \b false when it is + * disabled. + * + * \retval true The L2 cache is enabled. + * \retval false The L2 cache is disabled. + */ +bool alt_cache_l2_is_enabled(void); + +/*! + * Flushes the L2 cache controller hardware buffers. + * + * \retval ALT_E_SUCCESS The operation was successful. + * \retval ALT_E_ERROR The operation failed. + * \retval ALT_E_TMO The memory operation timed out. + */ +ALT_STATUS_CODE alt_cache_l2_sync(void); + +/*! + * Invalidates the specified contents of the L2 cache for the given memory + * segment. + * + * The memory segment address and length specified must align to the + * characteristics of the cache line. This means the address and length must be + * multiples of the cache line size. To determine the cache line size, use the + * \b ALT_CACHE_LINE_SIZE macro. + * + * \param paddress + * The physical address of the memory segment to be invalidated. + * + * \param length + * The length of the memory segment to be invalidated. + * + * \retval ALT_E_SUCCESS The operation was successful. + * \retval ALT_E_ERROR The operation failed. + * \retval ALT_E_BAD_ARG The memory segment is invalid. + * \retval ALT_E_TMO The memory operation timed out. + */ +ALT_STATUS_CODE alt_cache_l2_invalidate(void * paddress, size_t length); + +/*! + * Invalidates th entire contents of the L2 cache. + * + * Normally this is done automatically as part of alt_cache_l2_enable(), but + * in certain circumstances it may be necessary to invalidate it manually. An + * example of this situation is when the address space is remapped and the + * processor accesses memory from the new memory area. + + * \retval ALT_E_SUCCESS The operation was successful. + * \retval ALT_E_ERROR The operation failed. + * \retval ALT_E_TMO The memory operation timed out. + */ +ALT_STATUS_CODE alt_cache_l2_invalidate_all(void); + +/*! + * Cleans the specified contents of the L2 cache for the given memory segment. + * + * The memory segment address and length specified must align to the + * characteristics of the cache line. This means the address and length must be + * multiples of the cache line size. To determine the cache line size, use the + * \b ALT_CACHE_LINE_SIZE macro. + * + * \param paddress + * The physical address of the memory segment to be cleaned. + * + * \param length + * The length of the memory segment to be cleaned. + * + * \retval ALT_E_SUCCESS The operation was successful. + * \retval ALT_E_ERROR The operation failed. + * \retval ALT_E_BAD_ARG The memory segment is invalid. + * \retval ALT_E_TMO The memory operation timed out. + */ +ALT_STATUS_CODE alt_cache_l2_clean(void * paddress, size_t length); + +/*! + * Cleans the entire L2 cache. All L2 cache controller interrupts will be + * temporarily disabled while the clean operation is in progress and restored + * once the it is finished. + * + * \retval ALT_E_SUCCESS The operation was successful. + * \retval ALT_E_ERROR The operation failed. + * \retval ALT_E_TMO The memory operation timed out. + */ +ALT_STATUS_CODE alt_cache_l2_clean_all(void); + +/*! + * Cleans and invalidates the specified contents of the L2 cache for the + * given memory segment. + * + * The memory segment address and length specified must align to the + * characteristics of the cache line. This means the address and length must be + * multiples of the cache line size. To determine the cache line size, use the + * \b ALT_CACHE_LINE_SIZE macro. + * + * \param paddress + * The physical address of the memory segment to be purged. + * + * \param length + * The length of the memory segment to be purged. + * + * \retval ALT_E_SUCCESS The operation was successful. + * \retval ALT_E_ERROR The operation failed. + * \retval ALT_E_BAD_ARG The memory segment is invalid. + */ +ALT_STATUS_CODE alt_cache_l2_purge(void * paddress, size_t length); + +/*! + * Cleans and invalidates the entire L2 cache. All L2 cache controller + * interrupts will be temporarily disabled while the clean and invalidate + * operation is in progress and restored once the it is finished. + * + * \retval ALT_E_SUCCESS The operation was successful. + * \retval ALT_E_ERROR The operation failed. + * \retval ALT_E_TMO The memory operation timed out. + */ +ALT_STATUS_CODE alt_cache_l2_purge_all(void); + +/*! + * This type definition enumerates all the interrupt conditions that can be + * generated by the L2 cache controller as register mask values. + */ +enum ALT_CACHE_L2_INTERRUPT_e +{ + /*! Decode error received on the master ports from L3. */ + ALT_CACHE_L2_INTERRUPT_DECERR = 1 << 8, + + /*! Slave error received on the master ports from L3. */ + ALT_CACHE_L2_INTERRUPT_SLVERR = 1 << 7, + + /*! Error on the L2 data RAM read. */ + ALT_CACHE_L2_INTERRUPT_ERRRD = 1 << 6, + + /*! Error on the L2 tag RAM read. */ + ALT_CACHE_L2_INTERRUPT_ERRRT = 1 << 5, + + /*! Error on the L2 data RAM write. */ + ALT_CACHE_L2_INTERRUPT_ERRWD = 1 << 4, + + /*! Error on the L2 tag RAM write. */ + ALT_CACHE_L2_INTERRUPT_ERRWT = 1 << 3, + + /*! Parity error on the L2 data RAM read. */ + ALT_CACHE_L2_INTERRUPT_PARRD = 1 << 2, + + /*! Parity error on the L2 tag RAM read. */ + ALT_CACHE_L2_INTERRUPT_PARRT = 1 << 1, + + /*! Event counter overflow or increment. */ + ALT_CACHE_L2_INTERRUPT_ECNTR = 1 << 0 +}; +typedef enum ALT_CACHE_L2_INTERRUPT_e ALT_CACHE_L2_INTERRUPT_t; + +/*! + * Enables the L2 cache controller interrupts for the specified set of + * condition(s). + * + * \param interrupt + * A register mask of the selected L2 cache controller + * interrupting conditions. + * + * \retval ALT_E_SUCCESS The operation was successful. + * \retval ALT_E_ERROR The operation failed. + */ +ALT_STATUS_CODE alt_cache_l2_int_enable(uint32_t interrupt); + +/*! + * Disables the L2 cache controller interrupts for the specified set of + * condition(s). + * + * \param interrupt + * A register mask of the selected L2 cache controller + * interrupting conditions. + * + * \retval ALT_E_SUCCESS The operation was successful. + * \retval ALT_E_ERROR The operation failed. + */ +ALT_STATUS_CODE alt_cache_l2_int_disable(uint32_t interrupt); + +/*! + * Gets the condition(s) causing the L2 cache controller to interrupt as a + * register mask. + * + * \returns A register mask of the currently asserted and enabled + * conditions resulting in an interrupt being generated. + */ +uint32_t alt_cache_l2_int_status_get(void); + +/*! + * Clears the specified conditon(s) causing the L2 cache controller to + * interrupt as a mask. Condition(s) specified which are not causing an + * interrupt or condition(s) specified which are not enabled are ignored. + * + * \param interrupt + * A register mask of the selected L2 cache controller + * interrupting conditions. + * + * \retval ALT_E_SUCCESS The operation was successful. + * \retval ALT_E_ERROR The operation failed. + */ +ALT_STATUS_CODE alt_cache_l2_int_status_clear(uint32_t interrupt); + +/*! + * @} + */ + +/*! + * @} + */ + +#ifdef __cplusplus +} +#endif + +#endif /* __ALT_CACHE_H__ */ diff --git a/c/src/lib/libbsp/arm/altera-cyclone-v/hwlib/include/alt_dma.h b/c/src/lib/libbsp/arm/altera-cyclone-v/hwlib/include/alt_dma.h new file mode 100644 index 0000000000..6be93fbd32 --- /dev/null +++ b/c/src/lib/libbsp/arm/altera-cyclone-v/hwlib/include/alt_dma.h @@ -0,0 +1,1007 @@ +/****************************************************************************** +* +* Copyright 2013 Altera Corporation. All Rights Reserved. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions are met: +* +* 1. Redistributions of source code must retain the above copyright notice, +* this list of conditions and the following disclaimer. +* +* 2. Redistributions in binary form must reproduce the above copyright notice, +* this list of conditions and the following disclaimer in the documentation +* and/or other materials provided with the distribution. +* +* 3. The name of the author may not be used to endorse or promote products +* derived from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER "AS IS" AND ANY EXPRESS OR +* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED. IN NO +* EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT +* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING +* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +* OF SUCH DAMAGE. +* +******************************************************************************/ + +#ifndef __ALT_DMA_H__ +#define __ALT_DMA_H__ + +#include "hwlib.h" +#include "alt_dma_common.h" +#include "alt_dma_program.h" + +#ifdef __cplusplus +extern "C" +{ +#endif /* __cplusplus */ + +/*! + * \addtogroup ALT_DMA DMA Controller API + * + * This module defines the API for configuration and use of the general purpose + * DMA controller for the SoC. The DMA controller is an instance of the ARM + * Corelink DMA Controller (DMA-330). + * + * References: + * * ARM DDI 0424C, CoreLink DMA Controller DMA-330 Technical Reference + * Manual. + * * ARM DAI 0239A, Application Note 239 Example Programs for the CoreLink + * DMA Controller DMA-330. + * * Altera, Cyclone V Device Handbook Volume 3: Hard Processor System + * Technical Reference Manual, DMA Controller. + * + * @{ + */ + +/*! + * \addtogroup ALT_DMA_COMPILE DMA API Compile Options + * + * This API provides control over the compile time inclusion of selected + * modules. This can allow for a smaller resulting binary. + * + * @{ + */ + +#ifndef ALT_DMA_PERIPH_PROVISION_16550_SUPPORT +#define ALT_DMA_PERIPH_PROVISION_16550_SUPPORT (1) +#endif + +#ifndef ALT_DMA_PERIPH_PROVISION_QSPI_SUPPORT +#define ALT_DMA_PERIPH_PROVISION_QSPI_SUPPORT (1) +#endif + +/*! + * @} + */ + +/*! + * \addtogroup ALT_DMA_CSR DMA API for Configuration, Control, and Status + * + * This API provides functions for configuration, control, and status queries + * of the DMA controller. + * + * @{ + */ + +/*! + * This type definition enumerates the operational states that the DMA manager + * may have. + */ +typedef enum ALT_DMA_MANAGER_STATE_e +{ + ALT_DMA_MANAGER_STATE_STOPPED = 0, /*!< Stopped */ + ALT_DMA_MANAGER_STATE_EXECUTING = 1, /*!< Executing */ + ALT_DMA_MANAGER_STATE_CACHE_MISS = 2, /*!< Cache Miss */ + ALT_DMA_MANAGER_STATE_UPDATING_PC = 3, /*!< Updating PC */ + ALT_DMA_MANAGER_STATE_WFE = 4, /*!< Waiting for Event */ + ALT_DMA_MANAGER_STATE_FAULTING = 15 /*!< Faulting */ +} +ALT_DMA_MANAGER_STATE_t; + +/*! + * This type definition enumerates the operational states that a DMA channel + * may have. + */ +typedef enum ALT_DMA_CHANNEL_STATE_e +{ + ALT_DMA_CHANNEL_STATE_STOPPED = 0, /*!< Stopped */ + ALT_DMA_CHANNEL_STATE_EXECUTING = 1, /*!< Executing */ + ALT_DMA_CHANNEL_STATE_CACHE_MISS = 2, /*!< Cache Miss */ + ALT_DMA_CHANNEL_STATE_UPDATING_PC = 3, /*!< Updating PC */ + ALT_DMA_CHANNEL_STATE_WFE = 4, /*!< Waiting for Event */ + ALT_DMA_CHANNEL_STATE_AT_BARRIER = 5, /*!< At Barrier */ + ALT_DMA_CHANNEL_STATE_WFP = 7, /*!< Waiting for Peripheral */ + ALT_DMA_CHANNEL_STATE_KILLING = 8, /*!< Killing */ + ALT_DMA_CHANNEL_STATE_COMPLETING = 9, /*!< Completing */ + ALT_DMA_CHANNEL_STATE_FAULTING_COMPLETING = 14, /*!< Faulting Completing */ + ALT_DMA_CHANNEL_STATE_FAULTING = 15 /*!< Faulting */ +} +ALT_DMA_CHANNEL_STATE_t; + +/*! + * This type definition enumerates the possible fault status that the DMA + * manager can have as a register mask. + */ +typedef enum ALT_DMA_MANAGER_FAULT_e +{ + /*! + * The DMA manager abort occured because of an instruction issued through + * the debug interface. + */ + ALT_DMA_MANAGER_FAULT_DBG_INSTR = (int32_t)(1UL << 30), + + /*! + * The DMA manager instruction fetch AXI bus response was not OKAY. + */ + ALT_DMA_MANAGER_FAULT_INSTR_FETCH_ERR = (int32_t)(1UL << 16), + + /*! + * The DMA manager attempted to execute DMAWFE or DMASEV with + * inappropriate security permissions. + */ + ALT_DMA_MANAGER_FAULT_MGR_EVNT_ERR = (int32_t)(1UL << 5), + + /*! + * The DMA manager attempted to execute DMAGO with inappropriate security + * permissions. + */ + ALT_DMA_MANAGER_FAULT_DMAGO_ERR = (int32_t)(1UL << 4), + + /*! + * The DMA manager attempted to execute an instruction operand that was + * not valid for the DMA configuration. + */ + ALT_DMA_MANAGER_FAULT_OPERAND_INVALID = (int32_t)(1UL << 1), + + /*! + * The DMA manager attempted to execute an undefined instruction. + */ + ALT_DMA_MANAGER_FAULT_UNDEF_INSTR = (int32_t)(1UL << 0) +} +ALT_DMA_MANAGER_FAULT_t; + +/*! + * This type definition enumerates the possible fault status that a channel + * may have as a register mask. + */ +typedef enum ALT_DMA_CHANNEL_FAULT_e +{ + /*! + * The DMA channel has locked up due to resource starvation. + */ + ALT_DMA_CHANNEL_FAULT_LOCKUP_ERR = (int32_t)(1UL << 31), + + /*! + * The DMA channel abort occured because of an instruction issued through + * the debug interface. + */ + ALT_DMA_CHANNEL_FAULT_DBG_INSTR = (int32_t)(1UL << 30), + + /*! + * The DMA channel data read AXI bus reponse was not OKAY. + */ + ALT_DMA_CHANNEL_FAULT_DATA_READ_ERR = (int32_t)(1UL << 18), + + /*! + * The DMA channel data write AXI bus response was not OKAY. + */ + ALT_DMA_CHANNEL_FAULT_DATA_WRITE_ERR = (int32_t)(1UL << 17), + + /*! + * The DMA channel instruction fetch AXI bus response was not OKAY. + */ + ALT_DMA_CHANNEL_FAULT_INSTR_FETCH_ERR = (int32_t)(1UL << 16), + + /*! + * The DMA channel MFIFO did not have the data for the DMAST instruction. + */ + ALT_DMA_CHANNEL_FAULT_ST_DATA_UNAVAILABLE = (int32_t)(1UL << 13), + + /*! + * The DMA channel MFIFO is too small to hold the DMALD instruction data, + * or too small to servic the DMAST instruction request. + */ + ALT_DMA_CHANNEL_FAULT_MFIFO_ERR = (int32_t)(1UL << 12), + + /*! + * The DMA channel in non-secure state attempted to perform a secure read + * or write. + */ + ALT_DMA_CHANNEL_FAULT_CH_RDWR_ERR = (int32_t)(1UL << 7), + + /*! + * The DMA channel in non-secure state attempted to execute the DMAWFP, + * DMALDP, DMASTP, or DMAFLUSHP instruction involving a secure peripheral. + */ + ALT_DMA_CHANNEL_FAULT_CH_PERIPH_ERR = (int32_t)(1UL << 6), + + /*! + * The DMA channel in non-secure state attempted to execute the DMAWFE or + * DMASEV instruction for a secure event or secure interrupt (if + * applicable). + */ + ALT_DMA_CHANNEL_FAULT_CH_EVNT_ERR = (int32_t)(1UL << 5), + + /*! + * The DMA channel attempted to execute an instruction operand that was + * not valid for the DMA configuration. + */ + ALT_DMA_CHANNEL_FAULT_OPERAND_INVALID = (int32_t)(1UL << 1), + + /*! + * The DMA channel attempted to execute an undefined instruction. + */ + ALT_DMA_CHANNEL_FAULT_UNDEF_INSTR = (int32_t)(1UL << 0) +} +ALT_DMA_CHANNEL_FAULT_t; + +/*! + * This type definition enumerates the possible DMA event-interrupt behavior + * option selections when a DMASEV instruction is executed. + */ +typedef enum ALT_DMA_EVENT_SELECT_e +{ + /*! + * If the DMA controller executes DMASEV for the event-interrupt resource + * then the DMA sends the event to all of the channel threads. + */ + ALT_DMA_EVENT_SELECT_SEND_EVT, + + /*! + * If the DMA controller executes DMASEV for the event-interrupt resource + * then the DMA sets the \b irq[N] HIGH. + */ + ALT_DMA_EVENT_SELECT_SIG_IRQ +} +ALT_DMA_EVENT_SELECT_t; + +/*! + * This type enumerates the DMA peripheral interface MUX selection options + * available. + */ +typedef enum ALT_DMA_PERIPH_MUX_e +{ + /*! + * Accept the reset default MUX selection + */ + ALT_DMA_PERIPH_MUX_DEFAULT = 0, + + /*! + * Select FPGA as the peripheral interface + */ + ALT_DMA_PERIPH_MUX_FPGA = 1, + + /*! + * Select CAN as the peripheral interface + */ + ALT_DMA_PERIPH_MUX_CAN = 2 +} +ALT_DMA_PERIPH_MUX_t; + +/*! + * This type defines the structure used to specify the configuration of the + * security states and peripheral interface MUX selections for the DMA + * controller. + */ +typedef struct ALT_DMA_CFG_s +{ + /*! + * DMA Manager security state configuration. + */ + ALT_DMA_SECURITY_t manager_sec; + + /*! + * DMA interrupt output security state configurations. Security state + * configurations are 0-based index-aligned with the enumeration values + * ALT_DMA_EVENT_0 through ALT_DMA_EVENT_7 of the ALT_DMA_EVENT_t type. + */ + ALT_DMA_SECURITY_t irq_sec[8]; + + /*! + * Peripheral request interface security state configurations. Security + * state configurations are 0-based index-aligned with the enumeration + * values of the ALT_DMA_PERIPH_t type. + */ + ALT_DMA_SECURITY_t periph_sec[32]; + + /*! + * DMA Peripheral Register Interface MUX Selections. MUX selections are + * 0-based index-aligned with the enumeration values + * ALT_DMA_PERIPH_FPGA_4_OR_CAN0_IF1 through + * ALT_DMA_PERIPH_FPGA_7_OR_CAN1_IF2 of the ALT_DMA_PERIPH_t type. + */ + ALT_DMA_PERIPH_MUX_t periph_mux[4]; +} +ALT_DMA_CFG_t; + +/*! + * Initialize the DMA controller. + * + * Initializes the DMA controller by setting the necessary control values to + * establish the security state and MUXed peripheral request interface selection + * configurations before taking the DMA controller out of reset. + * + * After the DMA is initialized, the following conditions hold true: + * * All DMA channel threads are in the Stopped state. + * * All DMA channel threads are available for allocation. + * * DMA Manager thread is waiting for an instruction from either APB + * interface. + * * The security state configurations of the DMA Manager, interrupt outputs, + * and peripheral request interfaces are established and immutable until the + * DMA is reset. + * * The MUXed peripheral request interface selection configurations are + * established and immutable until the DMA is reset. + * + * \param dma_cfg + * A pointer to a ALT_DMA_CFG_t structure containing the desired + * DMA controller security state and peripheral request interface + * MUX selections. + * + * \retval ALT_E_SUCCESS The operation was successful. + * \retval ALT_E_ERROR The operation failed. + */ +ALT_STATUS_CODE alt_dma_init(const ALT_DMA_CFG_t * dma_cfg); + +/*! + * Uninitializes the DMA controller. + * + * Uninitializes the DMA controller by killing any running channel threads and + * putting the DMA controller into reset. + * + * \retval ALT_E_SUCCESS The operation was successful. + * \retval ALT_E_ERROR The operation failed. + */ +ALT_STATUS_CODE alt_dma_uninit(void); + +/*! + * Allocate a DMA channel resource for use. + * + * \param channel + * A DMA controller channel. + * + * \retval ALT_E_SUCCESS The operation was successful. + * \retval ALT_E_ERROR The operation failed. + */ +ALT_STATUS_CODE alt_dma_channel_alloc(ALT_DMA_CHANNEL_t channel); + +/*! + * Allocate a free DMA channel resource for use if there are any. + * + * \param allocated + * [out] A pointer to an output parameter that will contain the + * channel allocated. + * + * \retval ALT_E_SUCCESS The operation was successful. + * \retval ALT_E_ERROR The operation failed. An unallocated channel + * may not be available at the time of the API + * call. + */ +ALT_STATUS_CODE alt_dma_channel_alloc_any(ALT_DMA_CHANNEL_t * allocated); + +/*! + * Free a DMA channel resource for reuse. + * + * \param channel + * The DMA controller channel resource to free. + * + * \retval ALT_E_SUCCESS The operation was successful. + * \retval ALT_E_ERROR The operation failed. The channel may not be in + * the STOPPED state. + */ +ALT_STATUS_CODE alt_dma_channel_free(ALT_DMA_CHANNEL_t channel); + +/*! + * Start execution of a DMA microcode program on the specified DMA channel + * thread resource. + * + * \param channel + * The DMA channel thread used to execute the microcode program. + * + * \param pgm + * The DMA microcode program. + * + * \retval ALT_E_SUCCESS The operation was successful. + * \retval ALT_E_ERROR The operation failed. + */ +ALT_STATUS_CODE alt_dma_channel_exec(ALT_DMA_CHANNEL_t channel, + ALT_DMA_PROGRAM_t * pgm); + +/*! + * Kill (abort) execution of any microcode program executing on the specified + * DMA channel thread resource. + * + * Terminates the channel thread of execution by issuing a DMAKILL instruction + * using the DMA APB slave interface. + * + * \param channel + * The DMA channel thread to abort any executing microcode program + * on. + * + * \retval ALT_E_SUCCESS The operation was successful. + * \retval ALT_E_ERROR The operation failed. + * \retval ALT_E_TMO Timeout waiting for the channel to change into + * KILLING or STOPPED state. + */ +ALT_STATUS_CODE alt_dma_channel_kill(ALT_DMA_CHANNEL_t channel); + +/*! + * Returns the current register value for the given DMA channel. + * + * \param channel + * The DMA channel thread to abort any executing microcode program + * on. + * + * \param reg + * Register to get the value for. + * + * \param val + * [out] The current value of the requested register. + * + * \retval ALT_E_SUCCESS The operation was successful. + * \retval ALT_E_ERROR The operation failed. + * \retval ALT_E_BAD_ARG The specified channel or register is invalid. + */ +ALT_STATUS_CODE alt_dma_channel_reg_get(ALT_DMA_CHANNEL_t channel, + ALT_DMA_PROGRAM_REG_t reg, uint32_t * val); + +/*! + * Signals the occurrence of an event or interrupt, using the specified event + * number. + * + * Causes the CPU to issue a DMASEV instruction using the DMA APB slave + * interface. + * + * The Interrupt Enable Register (INTEN) register is used to control if each + * event-interrupt resource is either an event or an interrupt. The INTEN + * register sets the event-interrupt resource to function as an: + * * Event - The DMAC generates an event for the specified event-interrupt + * resource. When the DMAC executes a DMAWFE instruction for the + * same event-interrupt resource then it clears the event. + * * Interrupt - The DMAC sets the \b IRQ[N] signal high, where + * \e evt_num is the number of the specified event + * resource. The interrupt must be cleared after being handled. + * + * When the configured to generate an event, this function may be used to + * restart one or more waiting DMA channels (i.e. having executed a DMAWFE + * instruction). + * + * See the following sections from the \e ARM DDI 0424C, CoreLink DMA Controller + * DMA-330 Technical Reference Manual for implementation details and use cases: + * * 2.5.1, Issuing Instructions to the DMAC using a Slave Interface + * * 2.7, Using Events and Interrupts + * + * \param evt_num + * A DMA event-interrupt resource. Allowable event values may be + * ALT_DMA_EVENT_0 .. ALT_DMA_EVENT_7 but ALT_DMA_EVENT_ABORT is + * not. + * + * \retval ALT_E_SUCCESS The operation was successful. + * \retval ALT_E_ERROR The operation failed. + * \retval ALT_E_BAD_ARG The given event number is invalid. + */ +ALT_STATUS_CODE alt_dma_send_event(ALT_DMA_EVENT_t evt_num); + +/*! + * Returns the current operational state of the DMA manager thread. + * + * \param state + * [out] Pointer to an output parameter to contain the DMA + * channel thread state. + * + * \retval ALT_E_SUCCESS The operation was successful. + * \retval ALT_E_ERROR The operation failed. + */ +ALT_STATUS_CODE alt_dma_manager_state_get(ALT_DMA_MANAGER_STATE_t * state); + +/*! + * Returns the current operational state of the specified DMA channel thread. + * + * \param channel + * The DMA channel thread to return the operational state of. + * + * \param state + * [out] Pointer to an output parameter to contain the DMA + * channel thread state. + * + * \retval ALT_E_SUCCESS The operation was successful. + * \retval ALT_E_ERROR The operation failed. + * \retval ALT_E_BAD_ARG The given channel identifier is invalid. + */ +ALT_STATUS_CODE alt_dma_channel_state_get(ALT_DMA_CHANNEL_t channel, + ALT_DMA_CHANNEL_STATE_t * state); + +/*! + * Return the current fault status of the DMA manager thread. + * + * \param fault + * [out] Pointer to an output parameter to contain the DMA + * manager fault status. + * + * \retval ALT_E_SUCCESS The operation was successful. + * \retval ALT_E_ERROR The operation failed. + */ +ALT_STATUS_CODE alt_dma_manager_fault_status_get(ALT_DMA_MANAGER_FAULT_t * fault); + +/*! + * Return the current fault status of the specified DMA channel thread. + * + * \param channel + * The DMA channel thread to return the fault status of. + * + * \param fault + * [out] Pointer to an output parameter to contain the DMA + * channel fault status. + * + * \retval ALT_E_SUCCESS The operation was successful. + * \retval ALT_E_ERROR The operation failed. + * \retval ALT_E_BAD_ARG The given channel identifier is invalid. + */ +ALT_STATUS_CODE alt_dma_channel_fault_status_get(ALT_DMA_CHANNEL_t channel, + ALT_DMA_CHANNEL_FAULT_t * fault); + +/*! + * Select whether the DMA controller sends the specific event to all channel + * threads or signals an interrupt using the corressponding \b irq when a DMASEV + * instruction is executed for the specified event-interrupt resource number. + * + * \param evt_num + * The event-interrupt resource number. Valid values are + * ALT_DMA_EVENT_0 .. ALT_DMA_EVENT_7 and ALT_DMA_EVENT_ABORT. + * + * \param opt + * The desired behavior selection for \e evt_num when a DMASEV is + * executed. + * + * \retval ALT_E_SUCCESS The operation was successful. + * \retval ALT_E_ERROR The operation failed. + * \retval ALT_E_BAD_ARG The given selection identifier is invalid. + */ +ALT_STATUS_CODE alt_dma_event_int_select(ALT_DMA_EVENT_t evt_num, + ALT_DMA_EVENT_SELECT_t opt); + +/*! + * Returns the status of the specified event-interrupt resource. + * + * Returns ALT_E_TRUE if event is active or \b irq[N] is HIGH and returns + * ALT_E_FALSE if event is inactive or \b irq[N] is LOW. + * + * \param evt_num + * The event-interrupt resource number. Valid values are + * ALT_DMA_EVENT_0 .. ALT_DMA_EVENT_7 and ALT_DMA_EVENT_ABORT. + * + * \retval ALT_E_TRUE Event is active or \b irq[N] is HIGH. + * \retval ALT_E_FALSE Event is inactive or \b irq[N] is LOW. + * \retval ALT_E_ERROR The operation failed. + * \retval ALT_E_BAD_ARG The given event identifier is invalid. + */ +ALT_STATUS_CODE alt_dma_event_int_status_get_raw(ALT_DMA_EVENT_t evt_num); + +/*! + * Returns the status of the specified interrupt resource. + * + * Returns ALT_E_TRUE if interrupt is active and therfore \b irq[N] is HIGH and + * returns ALT_E_FALSE if interrupt is inactive and therfore \b irq[N] is LOW. + * + * \param irq_num + * The interrupt resource number. Valid values are + * ALT_DMA_EVENT_0 .. ALT_DMA_EVENT_7 and ALT_DMA_EVENT_ABORT. + * + * \retval ALT_E_TRUE Event is active or \b irq[N] is HIGH. + * \retval ALT_E_FALSE Event is inactive or \b irq[N] is LOW. + * \retval ALT_E_ERROR The operation failed. + * \retval ALT_E_BAD_ARG The given event identifier is invalid. + */ +ALT_STATUS_CODE alt_dma_int_status_get(ALT_DMA_EVENT_t irq_num); + +/*! + * Clear the active (HIGH) status of the specified interrupt resource. + * + * If the specified interrupt is HIGH, then sets \b irq[N] to LOW if the + * event-interrupt resource is configured (see: alt_dma_event_int_enable()) + * to signal an interrupt. Otherwise, the status of \b irq[N] does not change. + * + * \param irq_num + * The interrupt resource number. Valid values are + * ALT_DMA_EVENT_0 .. ALT_DMA_EVENT_7 and ALT_DMA_EVENT_ABORT. + * + * \retval ALT_E_SUCCESS The operation was successful. + * \retval ALT_E_ERROR The operation failed. + * \retval ALT_E_BAD_ARG The given event identifier is invalid. + */ +ALT_STATUS_CODE alt_dma_int_clear(ALT_DMA_EVENT_t irq_num); + +/*! + * @} + */ + +/*! + * \addtogroup ALT_DMA_STD_OPS DMA API for Standard Operations + * + * The functions in this group provide common DMA operations for common bulk + * data transfers between: + * * Memory to Memory + * * Zero to Memory + * * Memory to Peripheral + * * Peripheral to Memory + * + * All DMA operations are asynchronous. The following are the ways to receive + * notification of a DMA transfer complete operation: + * * Use alt_dma_channel_state_get() and poll for the + * ALT_DMA_CHANNEL_STATE_STOPPED status. + * * In conjunction with the interrupt API, use DMA events to signal an + * interrupt. The event first must be configured to signal an interrupt + * using alt_dma_event_int_select(). Configure the DMA program to send an + * event. + * * Construct a custom program which waits for a particular event number by + * assemblying a DMAWFE using alt_dma_program_DMAWFE(). Then run the custom + * program on a different channel. The custom program will wait until the + * DMA program sends the event. Configure the DMA program to send an event. + * + * Cache related maintenance on the source and/or destinatino buffer are not + * handled the DMA API and are the responsibility of the programmer. This is + * because the DMA API does not have visibility into the current configuration + * of the MMU or know about any special considerations regarding the source + * and/or destination memory. The following are some example scenarios and + * cache maintenance related precautions that may need to be taken: + * * alt_dma_memory_to_memory(): Source buffer should be cleaned or purged, + * destination buffer should be invalidated. + * * alt_dma_zero_to_memory(): Destination buffer should be invalidated. + * * alt_dma_memory_to_register(): Source buffer should be cleaned or purged. + * * alt_dma_register_to_memory(): Destination buffer should be invalidated. + * * alt_dma_memory_to_periph(): Source buffer should be cleaned or purged. + * * alt_dma_periph_to_memory(): Destination buffer should be invalidated. + * + * @{ + */ + +/*! + * Uses the DMA engine to asynchronously copy the specified memory from the + * given source address to the given destination address. + * + * Overlapping memory regions are not supported. + * + * \param channel + * The DMA channel thread to use for the transfer. + * + * \param program + * An allocated DMA program buffer to use for the life of the + * transfer. + * + * \param dest + * The destination memory address to copy to. + * + * \param src + * The source memory address to copy from. + * + * \param size + * The size of the transfer in bytes. + * + * \param send_evt + * If set to true, the DMA engine will be instructed to send an + * event upon completion or fault. + * + * \param evt + * If send_evt is true, the event specified will be sent. + * Otherwise the parameter is ignored. + * + * \retval ALT_E_SUCCESS The operation was successful. + * \retval ALT_E_ERROR The operation failed. + * \retval ALT_E_BAD_ARG The given channel or event identifier (if + * used) is invalid, or the memory regions + * specified are overlapping. + */ +ALT_STATUS_CODE alt_dma_memory_to_memory(ALT_DMA_CHANNEL_t channel, + ALT_DMA_PROGRAM_t * program, + void * dest, + const void * src, + size_t size, + bool send_evt, + ALT_DMA_EVENT_t evt); + +/*! + * Uses the DMA engine to asynchronously zero out the specified memory buffer. + * + * \param channel + * The DMA channel thread to use for the transfer. + * + * \param program + * An allocated DMA program buffer to use for the life of the + * transfer. + * + * \param buf + * The buffer memory address to zero out. + * + * \param size + * The size of the buffer in bytes. + * + * \param send_evt + * If set to true, the DMA engine will be instructed to send an + * event upon completion or fault. + * + * \param evt + * If send_evt is true, the event specified will be sent. + * Otherwise the parameter is ignored. + * + * \retval ALT_E_SUCCESS The operation was successful. + * \retval ALT_E_ERROR The operation failed. + * \retval ALT_E_BAD_ARG The given channel or event identifier (if + * used) is invalid. + */ +ALT_STATUS_CODE alt_dma_zero_to_memory(ALT_DMA_CHANNEL_t channel, + ALT_DMA_PROGRAM_t * program, + void * buf, + size_t size, + bool send_evt, + ALT_DMA_EVENT_t evt); + +/*! + * Uses the DMA engine to asynchronously transfer the contents of a memory + * buffer to a keyhole register. + * + * \param channel + * The DMA channel thread to use for the transfer. + * + * \param program + * An allocated DMA program buffer to use for the life of the + * transfer. + * + * \param dst_reg + * The address of the register to write buffer to. + * + * \param src_buf + * The address of the memory buffer for the data. + * + * \param count + * The number of transfers to make. + * + * \param register_width_bits + * The width of the register to transfer to in bits. Valid values + * are 8, 16, 32, and 64. + * + * \param send_evt + * If set to true, the DMA engine will be instructed to send an + * event upon completion or fault. + * + * \param evt + * If send_evt is true, the event specified will be sent. + * Otherwise the parameter is ignored. + * + * \retval ALT_E_SUCCESS The operation was successful. + * \retval ALT_E_ERROR The operation failed. + * \retval ALT_E_BAD_ARG The given channel, event identifier (if used), + * or register width are invalid, or if the + * destination register or source buffer is + * unaligned to the register width. + */ +ALT_STATUS_CODE alt_dma_memory_to_register(ALT_DMA_CHANNEL_t channel, + ALT_DMA_PROGRAM_t * program, + void * dst_reg, + const void * src_buf, + size_t count, + uint32_t register_width_bits, + bool send_evt, + ALT_DMA_EVENT_t evt); + +/*! + * Uses the DMA engine to asynchronously transfer the contents of a keyhole + * register to a memory buffer. + * + * \param channel + * The DMA channel thread to use for the transfer. + * + * \param program + * An allocated DMA program buffer to use for the life of the + * transfer. + * + * \param dst_buf + * The address of the memory buffer to copy to. + * + * \param src_reg + * The address of the keyhole register to read from. + * + * \param count + * The number of transfers to make. + * + * \param register_width_bits + * The width of the register to transfer to in bits. Valid values + * are 8, 16, 32, and 64. + * + * \param send_evt + * If set to true, the DMA engine will be instructed to send an + * event upon completion or fault. + * + * \param evt + * If send_evt is true, the event specified will be sent. + * Otherwise the parameter is ignored. + * + * \retval ALT_E_SUCCESS The operation was successful. + * \retval ALT_E_ERROR The operation failed. + * \retval ALT_E_BAD_ARG The given channel, event identifier (if used), + * or register width are invalid, or if the + * destination buffer or source register is + * unaligned to the register width. + */ +ALT_STATUS_CODE alt_dma_register_to_memory(ALT_DMA_CHANNEL_t channel, + ALT_DMA_PROGRAM_t * program, + void * dst_buf, + const void * src_reg, + size_t count, + uint32_t register_width_bits, + bool send_evt, + ALT_DMA_EVENT_t evt); + +/*! + * Uses the DMA engine to asynchronously copy memory from the given source + * address to the specified peripheral. Because different peripheral has + * different characteristics, individual peripherals need to be explicitly + * supported. + * + * The following lists the peripheral IDs supported by this API: + * * ALT_DMA_PERIPH_QSPI_FLASH_TX + * * ALT_DMA_PERIPH_UART0_TX + * * ALT_DMA_PERIPH_UART1_TX + * + * \param channel + * The DMA channel thread to use for the transfer. + * + * \param program + * An allocated DMA program buffer to use for the life of the + * transfer. + * + * \param dest + * The destination peripheral to copy memory to. + * + * \param src + * The source memory address to copy from. + * + * \param size + * The size of the transfer in bytes. + * + * \param periph_info + * A pointer to a peripheral specific data structure. The + * following list shows what data structure should be used for + * peripherals: + * * ALT_DMA_PERIPH_QSPI_FLASH_TX: This parameter is ignored. + * * ALT_DMA_PERIPH_UART0_TX: Use a pointer to the + * ALT_16550_HANDLE_t used to interact with that UART. + * * ALT_DMA_PERIPH_UART1_TX: Use a pointer to the + * ALT_16550_HANDLE_t used to interact with that UART. + * + * \param send_evt + * If set to true, the DMA engine will be instructed to send an + * event upon completion or fault. + * + * \param evt + * If send_evt is true, the event specified will be sent. + * Otherwise the parameter is ignored. + * + * \retval ALT_E_SUCCESS The operation was successful. + * \retval ALT_E_ERROR The operation failed. + * \retval ALT_E_BAD_ARG The given channel, peripheral, or event + * identifier (if used) is invalid. + * + * \internal + * Priority peripheral IDs to be supported: + * * ALT_DMA_PERIPH_FPGA_0 + * * ALT_DMA_PERIPH_FPGA_1 + * * ALT_DMA_PERIPH_FPGA_2 + * * ALT_DMA_PERIPH_FPGA_3 + * * ALT_DMA_PERIPH_FPGA_4 + * * ALT_DMA_PERIPH_FPGA_5 + * * ALT_DMA_PERIPH_FPGA_6 + * * ALT_DMA_PERIPH_FPGA_7 + * * ALT_DMA_PERIPH_I2C0_TX + * * ALT_DMA_PERIPH_I2C1_TX + * * ALT_DMA_PERIPH_I2C2_TX + * * ALT_DMA_PERIPH_I2C3_TX + * * ALT_DMA_PERIPH_SPI0_MASTER_TX + * * ALT_DMA_PERIPH_SPI0_SLAVE_TX + * * ALT_DMA_PERIPH_SPI1_MASTER_TX + * * ALT_DMA_PERIPH_SPI1_SLAVE_TX + * \endinternal + */ +ALT_STATUS_CODE alt_dma_memory_to_periph(ALT_DMA_CHANNEL_t channel, + ALT_DMA_PROGRAM_t * program, + ALT_DMA_PERIPH_t dest, + const void * src, + size_t size, + void * periph_info, + bool send_evt, + ALT_DMA_EVENT_t evt); + +/*! + * Uses the DMA engine to copy memory from the specified peripheral to the + * given destination address. Because different peripheral has different + * characteristics, individual peripherals need to be explicitly supported. + * + * The following lists the peripheral IDs supported by this API: + * * ALT_DMA_PERIPH_QSPI_FLASH_RX + * * ALT_DMA_PERIPH_UART0_RX + * * ALT_DMA_PERIPH_UART1_RX + * + * \param channel + * The DMA channel thread to use for the transfer. + * + * \param program + * An allocated DMA program buffer to use for the life of the + * transfer. + * + * \param dest + * The destination memory address to copy to. + * + * \param src + * The source peripheral to copy memory from. + * + * \param size + * The size of the transfer in bytes. + * + * \param periph_info + * A pointer to a peripheral specific data structure. The + * following list shows what data structure should be used for + * peripherals: + * * ALT_DMA_PERIPH_QSPI_FLASH_RX: This parameter is ignored. + * * ALT_DMA_PERIPH_UART0_RX: Use a pointer to the + * ALT_16550_HANDLE_t used to interact with that UART. + * * ALT_DMA_PERIPH_UART1_RX: Use a pointer to the + * ALT_16550_HANDLE_t used to interact with that UART. + * + * \param send_evt + * If set to true, the DMA engine will be instructed to send an + * event upon completion or fault. + * + * \param evt + * If send_evt is true, the event specified will be sent. + * Otherwise the parameter is ignored. + * + * \retval ALT_E_SUCCESS The operation was successful. + * \retval ALT_E_ERROR The operation failed. + * \retval ALT_E_BAD_ARG The given channel, peripheral, or event + * identifier (if used) is invalid. +* + * \internal + * Priority peripheral IDs to be supported: + * * ALT_DMA_PERIPH_FPGA_0 + * * ALT_DMA_PERIPH_FPGA_1 + * * ALT_DMA_PERIPH_FPGA_2 + * * ALT_DMA_PERIPH_FPGA_3 + * * ALT_DMA_PERIPH_FPGA_4 + * * ALT_DMA_PERIPH_FPGA_5 + * * ALT_DMA_PERIPH_FPGA_6 + * * ALT_DMA_PERIPH_FPGA_7 + * * ALT_DMA_PERIPH_I2C0_RX + * * ALT_DMA_PERIPH_I2C1_RX + * * ALT_DMA_PERIPH_I2C2_RX + * * ALT_DMA_PERIPH_I2C3_RX + * * ALT_DMA_PERIPH_SPI0_MASTER_RX + * * ALT_DMA_PERIPH_SPI0_SLAVE_RX + * * ALT_DMA_PERIPH_SPI1_MASTER_RX + * * ALT_DMA_PERIPH_SPI1_SLAVE_RX + * \endinternal + */ +ALT_STATUS_CODE alt_dma_periph_to_memory(ALT_DMA_CHANNEL_t channel, + ALT_DMA_PROGRAM_t * program, + void * dest, + ALT_DMA_PERIPH_t src, + size_t size, + void * periph_info, + bool send_evt, + ALT_DMA_EVENT_t evt); + +/*! + * @} + */ + +/*! + * @} + */ + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* __ALT_DMA_H__ */ diff --git a/c/src/lib/libbsp/arm/altera-cyclone-v/hwlib/include/alt_dma_common.h b/c/src/lib/libbsp/arm/altera-cyclone-v/hwlib/include/alt_dma_common.h new file mode 100644 index 0000000000..e82bc1ae4d --- /dev/null +++ b/c/src/lib/libbsp/arm/altera-cyclone-v/hwlib/include/alt_dma_common.h @@ -0,0 +1,162 @@ +/****************************************************************************** + * + * Copyright 2013 Altera Corporation. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED. IN NO + * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + ******************************************************************************/ + +#ifndef __ALT_DMA_COMMON_H__ +#define __ALT_DMA_COMMON_H__ + +#ifdef __cplusplus +extern "C" +{ +#endif /* __cplusplus */ + +/*! + * \addtogroup ALT_DMA_COMMON DMA Controller Common API Definitions + * + * This module contains the common definitions for the DMA controller related + * APIs. + * + * @{ + */ + +/*! + * This type definition enumerates the DMA controller channel threads. + */ +typedef enum ALT_DMA_CHANNEL_e +{ + ALT_DMA_CHANNEL_0 = 0, /*!< DMA Channel Thread 0 */ + ALT_DMA_CHANNEL_1 = 1, /*!< DMA Channel Thread 1 */ + ALT_DMA_CHANNEL_2 = 2, /*!< DMA Channel Thread 2 */ + ALT_DMA_CHANNEL_3 = 3, /*!< DMA Channel Thread 3 */ + ALT_DMA_CHANNEL_4 = 4, /*!< DMA Channel Thread 4 */ + ALT_DMA_CHANNEL_5 = 5, /*!< DMA Channel Thread 5 */ + ALT_DMA_CHANNEL_6 = 6, /*!< DMA Channel Thread 6 */ + ALT_DMA_CHANNEL_7 = 7 /*!< DMA Channel Thread 7 */ +} +ALT_DMA_CHANNEL_t; + +/*! + * This type definition enumerates the SoC system peripherals implementing the + * required request interface that enables direct DMA transfers to/from the + * device. + * + * FPGA soft IP interface to the DMA are required to comply with the Synopsys + * protocol. + * + * Request interface numbers 4 through 7 are multiplexed between the CAN + * controllers and soft logic implemented in the FPGA fabric. The selection + * between the CAN controller and FPGA interfaces is determined at DMA + * initialization. + */ +typedef enum ALT_DMA_PERIPH_e +{ + ALT_DMA_PERIPH_FPGA_0 = 0, /*!< FPGA soft IP interface 0 */ + ALT_DMA_PERIPH_FPGA_1 = 1, /*!< FPGA soft IP interface 1 */ + ALT_DMA_PERIPH_FPGA_2 = 2, /*!< FPGA soft IP interface 2 */ + ALT_DMA_PERIPH_FPGA_3 = 3, /*!< FPGA soft IP interface 3 */ + + ALT_DMA_PERIPH_FPGA_4_OR_CAN0_IF1 = 4, /*!< Selectively MUXed FPGA 4 or CAN 0 interface 1 */ + ALT_DMA_PERIPH_FPGA_5_OR_CAN0_IF2 = 5, /*!< Selectively MUXed FPGA 5 or CAN 0 interface 2 */ + ALT_DMA_PERIPH_FPGA_6_OR_CAN1_IF1 = 6, /*!< Selectively MUXed FPGA 6 or CAN 1 interface 1 */ + ALT_DMA_PERIPH_FPGA_7_OR_CAN1_IF2 = 7, /*!< Selectively MUXed FPGA 7 or CAN 1 interface 2 */ + + ALT_DMA_PERIPH_FPGA_4 = 4, /*!< Alias for ALT_DMA_PERIPH_FPGA_4_OR_CAN0_IF1 */ + ALT_DMA_PERIPH_FPGA_5 = 5, /*!< Alias for ALT_DMA_PERIPH_FPGA_5_OR_CAN0_IF2 */ + ALT_DMA_PERIPH_FPGA_6 = 6, /*!< Alias for ALT_DMA_PERIPH_FPGA_6_OR_CAN1_IF1 */ + ALT_DMA_PERIPH_FPGA_7 = 7, /*!< Alias for ALT_DMA_PERIPH_FPGA_7_OR_CAN1_IF2 */ + + ALT_DMA_PERIPH_CAN0_IF1 = 4, /*!< Alias for ALT_DMA_PERIPH_FPGA_4_OR_CAN0_IF1 */ + ALT_DMA_PERIPH_CAN0_IF2 = 5, /*!< Alias for ALT_DMA_PERIPH_FPGA_5_OR_CAN0_IF2 */ + ALT_DMA_PERIPH_CAN1_IF1 = 6, /*!< Alias for ALT_DMA_PERIPH_FPGA_6_OR_CAN1_IF1 */ + ALT_DMA_PERIPH_CAN1_IF2 = 7, /*!< Alias for ALT_DMA_PERIPH_FPGA_7_OR_CAN1_IF2 */ + + ALT_DMA_PERIPH_I2C0_TX = 8, /*!< I2C 0 TX */ + ALT_DMA_PERIPH_I2C0_RX = 9, /*!< I2C 0 RX */ + ALT_DMA_PERIPH_I2C1_TX = 10, /*!< I2C 1 TX */ + ALT_DMA_PERIPH_I2C1_RX = 11, /*!< I2C 1 RX */ + ALT_DMA_PERIPH_I2C2_TX = 12, /*!< I2C 2 TX */ + ALT_DMA_PERIPH_I2C2_RX = 13, /*!< I2C 2 RX */ + ALT_DMA_PERIPH_I2C3_TX = 14, /*!< I2C 3 TX */ + ALT_DMA_PERIPH_I2C3_RX = 15, /*!< I2C 3 RX */ + ALT_DMA_PERIPH_SPI0_MASTER_TX = 16, /*!< SPI 0 Master TX */ + ALT_DMA_PERIPH_SPI0_MASTER_RX = 17, /*!< SPI 0 Master RX */ + ALT_DMA_PERIPH_SPI0_SLAVE_TX = 18, /*!< SPI 0 Slave TX */ + ALT_DMA_PERIPH_SPI0_SLAVE_RX = 19, /*!< SPI 0 Slave RX */ + ALT_DMA_PERIPH_SPI1_MASTER_TX = 20, /*!< SPI 1 Master TX */ + ALT_DMA_PERIPH_SPI1_MASTER_RX = 21, /*!< SPI 1 Master RX */ + ALT_DMA_PERIPH_SPI1_SLAVE_TX = 22, /*!< SPI 1 Slave TX */ + ALT_DMA_PERIPH_SPI1_SLAVE_RX = 23, /*!< SPI 1 Slave RX */ + ALT_DMA_PERIPH_QSPI_FLASH_TX = 24, /*!< QSPI Flash TX */ + ALT_DMA_PERIPH_QSPI_FLASH_RX = 25, /*!< QSPI Flash RX */ + ALT_DMA_PERIPH_STM = 26, /*!< System Trace Macrocell */ + ALT_DMA_PERIPH_RESERVED = 27, /*!< Reserved */ + ALT_DMA_PERIPH_UART0_TX = 28, /*!< UART 0 TX */ + ALT_DMA_PERIPH_UART0_RX = 29, /*!< UART 0 RX */ + ALT_DMA_PERIPH_UART1_TX = 30, /*!< UART 1 TX */ + ALT_DMA_PERIPH_UART1_RX = 31 /*!< UART 1 RX */ +} +ALT_DMA_PERIPH_t; + +/*! + * This type enumerates the DMA security state options available. + */ +typedef enum ALT_DMA_SECURITY_e +{ + ALT_DMA_SECURITY_DEFAULT = 0, /*!< Use the default security value (e.g. reset default) */ + ALT_DMA_SECURITY_SECURE = 1, /*!< Secure */ + ALT_DMA_SECURITY_NONSECURE = 2 /*!< Non-secure */ +} +ALT_DMA_SECURITY_t; + +/*! + * This type definition enumerates the DMA event-interrupt resources. + */ +typedef enum ALT_DMA_EVENT_e +{ + ALT_DMA_EVENT_0 = 0, /*!< DMA Event 0 */ + ALT_DMA_EVENT_1 = 1, /*!< DMA Event 1 */ + ALT_DMA_EVENT_2 = 2, /*!< DMA Event 2 */ + ALT_DMA_EVENT_3 = 3, /*!< DMA Event 3 */ + ALT_DMA_EVENT_4 = 4, /*!< DMA Event 4 */ + ALT_DMA_EVENT_5 = 5, /*!< DMA Event 5 */ + ALT_DMA_EVENT_6 = 6, /*!< DMA Event 6 */ + ALT_DMA_EVENT_7 = 7, /*!< DMA Event 7 */ + ALT_DMA_EVENT_ABORT = 8 /*!< DMA Abort Event */ +} +ALT_DMA_EVENT_t; + +/*! + * @} + */ + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* __ALT_DMA_COMMON_H__ */ diff --git a/c/src/lib/libbsp/arm/altera-cyclone-v/hwlib/include/alt_dma_program.h b/c/src/lib/libbsp/arm/altera-cyclone-v/hwlib/include/alt_dma_program.h new file mode 100644 index 0000000000..5fa876f237 --- /dev/null +++ b/c/src/lib/libbsp/arm/altera-cyclone-v/hwlib/include/alt_dma_program.h @@ -0,0 +1,951 @@ +/****************************************************************************** + * + * Copyright 2013 Altera Corporation. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED. IN NO + * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + ******************************************************************************/ + +#ifndef __ALT_DMA_PROGRAM_H__ +#define __ALT_DMA_PROGRAM_H__ + +#include "hwlib.h" +#include "alt_dma_common.h" + +#ifdef __cplusplus +extern "C" +{ +#endif /* __cplusplus */ + +/*! + * \addtogroup ALT_DMA_PRG DMA Controller Programming API + * + * This API provides functions for dynamically defining and assembling microcode + * programs for execution on the DMA controller. + * + * The microcode program assembly API provides users with the ability to develop + * highly optimized and tailored algorithms for data transfer between SoC FPGA + * IP blocks and/or system memory. + * + * The same microcode program assembly facilities are also used to implement the + * functions found in the HWLIB Common DMA Operations functional API. + * + * An ALT_DMA_PROGRAM_t structure is used to contain and assemble a DMA + * microcode program. The storage for an ALT_DMA_PROGRAM_t stucture is allocated + * from used specified system memory. Once a microcode program has been + * assembled in a ALT_DMA_PROGRAM_t it may be excecuted on a designated DMA + * channel thread. The microcode program may be rerun on any DMA channel thread + * whenever required as long as the integrity of the ALT_DMA_PROGRAM_t + * containing the program is maintained. + * + * @{ + */ + +/*! + * This preprocessor declares the DMA channel thread microcode instruction + * cache line width in bytes. It is recommended that the program buffers be + * sized to a multiple of the cache line size. This will allow for the most + * efficient microcode speed and space utilization. + */ +#define ALT_DMA_PROGRAM_CACHE_LINE_SIZE (32) + +/*! + * This preprocessor declares the DMA channel thread microcode instruction + * cache line count. Thus the total size of the cache is the cache line size + * multipled by the cache line count. Programs larger than the cache size risk + * having a cache miss while executing. + */ +#define ALT_DMA_PROGRAM_CACHE_LINE_COUNT (16) + +/*! + * This preprocessor definition determines the size of the program buffer + * within the ALT_DMA_PROGRAM_t structure. This size should provide adequate + * size for most DMA microcode programs. If calls within this API are + * reporting out of memory response codes, consider increasing the provisioned + * program buffersize. + * + * To specify another DMA microcode program buffer size, redefine the macro + * below by defining ALT_DMA_PROGRAM_PROVISION_BUFFER_SIZE to another size in + * your Makefile. It is recommended that the size be a multiple of the + * microcode engine cache line size. See ALT_DMA_PROGRAM_CACHE_LINE_SIZE for + * more information. The largest supported buffer size is 65536 bytes. + */ +#ifndef ALT_DMA_PROGRAM_PROVISION_BUFFER_SIZE +#define ALT_DMA_PROGRAM_PROVISION_BUFFER_SIZE (ALT_DMA_PROGRAM_CACHE_LINE_SIZE * ALT_DMA_PROGRAM_CACHE_LINE_COUNT) +#endif + +/*! + * This type defines the structure used to assemble and contain a microcode + * program which can be executed by the DMA controller. The internal members + * are undocumented and should not be altered outside of this API. + */ +typedef struct ALT_DMA_PROGRAM_s +{ + uint32_t flag; + + uint16_t buffer_start; + uint16_t code_size; + + uint16_t loop0; + uint16_t loop1; + + uint16_t sar; + uint16_t dar; + + /* + * Add a little extra space so that regardless of where this structure + * sits in memory, a suitable start address can be aligned to the cache + * line stride while providing the requested buffer space. + */ + uint8_t program[ALT_DMA_PROGRAM_PROVISION_BUFFER_SIZE + + ALT_DMA_PROGRAM_CACHE_LINE_SIZE]; +} +ALT_DMA_PROGRAM_t; + +/*! + * This type definition enumerates the DMA controller register names for use in + * microcode program definition. + */ +typedef enum ALT_DMA_PROGRAM_REG_e +{ + /*! Source Address Register */ + ALT_DMA_PROGRAM_REG_SAR = 0x0, + + /*! Destination Address Register */ + ALT_DMA_PROGRAM_REG_DAR = 0x2, + + /*! Channel Control Register */ + ALT_DMA_PROGRAM_REG_CCR = 0x1 +} +ALT_DMA_PROGRAM_REG_t; + +/*! + * This type definition enumerates the instruction modifier options available + * for use with selected DMA microcode instructions. + * + * The enumerations values are context dependent upon the instruction being + * modified. + * + * For the DMALD[S|B], DMALDP\, DMAST[S|B], and + * DMASTP\ microcode instructions, the enumeration + * ALT_DMA_PROGRAM_INST_MOD_SINGLE specifies the S option modifier + * while the enumeration ALT_DMA_PROGRAM_INST_MOD_BURST specifies the B + * option modifier. The enumeration ALT_DMA_PROGRAM_INST_MOD_NONE specifies + * that no modifier is present for instructions where use of [S|B] is + * optional. + * + * For the DMAWFP microcode instruction, the enumerations + * ALT_DMA_PROGRAM_INST_MOD_SINGLE, ALT_DMA_PROGRAM_INST_MOD_BURST, or + * ALT_DMA_PROGRAM_INST_MOD_PERIPH each specify one of the corresponding + * options \. + */ +typedef enum ALT_DMA_PROGRAM_INST_MOD_e +{ + /*! + * This DMA instruction modifier specifies that no special modifier is + * added to the instruction. + */ + ALT_DMA_PROGRAM_INST_MOD_NONE, + + /*! + * Depending on the DMA microcode instruction modified, this modifier + * specifies S case for a [S|B] or a \ for a + * \. + */ + ALT_DMA_PROGRAM_INST_MOD_SINGLE, + + /*! + * Depending on the DMA microcode instruction modified, this modifier + * specifies B case for a [S|B] or a \ for a + * \. + */ + ALT_DMA_PROGRAM_INST_MOD_BURST, + + /*! + * This DMA instruction modifier specifies a \ for a + * \. + */ + ALT_DMA_PROGRAM_INST_MOD_PERIPH +} +ALT_DMA_PROGRAM_INST_MOD_t; + +/*! + * This function initializes a system memory buffer for use as a DMA microcode + * program buffer. This should be the first API call made on the program + * buffer type. + * + * \param pgm + * A pointer to a DMA program buffer structure. + * + * \retval ALT_E_SUCCESS The operation was successful. + * \retval ALT_E_ERROR Details about error status code + */ +ALT_STATUS_CODE alt_dma_program_init(ALT_DMA_PROGRAM_t * pgm); + +/*! + * This function verifies that the DMA microcode program buffer is no longer + * in use and performs any needed uninitialization steps. + * + * \param pgm + * A pointer to a DMA program buffer structure. + * + * \retval ALT_E_SUCCESS The operation was successful. + * \retval ALT_E_ERROR Details about error status code + */ +ALT_STATUS_CODE alt_dma_program_uninit(ALT_DMA_PROGRAM_t * pgm); + +/*! + * This function clears the existing DMA microcode program in the given + * program buffer. + * + * \param pgm + * A pointer to a DMA program buffer structure. + * + * \retval ALT_E_SUCCESS The operation was successful. + * \retval ALT_E_ERROR Details about error status code. + */ +ALT_STATUS_CODE alt_dma_program_clear(ALT_DMA_PROGRAM_t * pgm); + +/*! + * This function validate that the given DMA microcode program buffer contains + * a well formed program. If caches are enabled, the program buffer contents + * will be cleaned to RAM. + * + * \param pgm + * A pointer to a DMA program buffer structure. + * + * \retval ALT_E_SUCCESS The given program is well formed. + * \retval ALT_E_ERROR The given program is not well formed. + * \retval ALT_E_TMO The cache operation timed out. + */ +ALT_STATUS_CODE alt_dma_program_validate(const ALT_DMA_PROGRAM_t * pgm); + +/*! + * This function reports the number bytes incremented for the register + * specified. The purpose is to determine the progress of an ongoing DMA + * transfer. + * + * It is implemented by calculating the difference of the programmed SAR or DAR + * with the current channel SAR or DAR register value. + * + * \param pgm + * A pointer to a DMA program buffer structure. + * + * \param channel + * The channel that the program is running on. + * + * \param reg + * Register to change the value for. Valid for only + * ALT_DMA_PROGRAM_REG_SAR and ALT_DMA_PROGRAM_REG_DAR. + * + * \param current + * The current snapshot value of the register read from the DMA + * channel. + * + * \param progress + * [out] A pointer to a memory location that will be used to store + * the number of bytes transfered. + * + * \retval ALT_E_SUCCESS The operation was successful. + * \retval ALT_E_ERROR Details about error status code. + * \retval ALT_E_BAD_ARG The specified channel is invalid, the specified + * register is invalid, or the DMAMOV for the + * specified register has not yet been assembled + * in the current program buffer. + */ +ALT_STATUS_CODE alt_dma_program_progress_reg(ALT_DMA_PROGRAM_t * pgm, + ALT_DMA_PROGRAM_REG_t reg, + uint32_t current, uint32_t * progress); + +/*! + * This function updates a pre-existing DMAMOV value affecting the SAR or DAR + * registers. This allows for pre-assembled programs that can be used on + * different source and destination addresses. + * + * \param pgm + * A pointer to a DMA program buffer structure. + * + * \param reg + * Register to change the value for. Valid for only + * ALT_DMA_PROGRAM_REG_SAR and ALT_DMA_PROGRAM_REG_DAR. + * + * \param val + * The value to update to. + * + * \retval ALT_E_SUCCESS The operation was successful. + * \retval ALT_E_ERROR Details about error status code. + * \retval ALT_E_BAD_ARG The specified register is invalid or the DMAMOV + * for the specified register has not yet been + * assembled in the current program buffer. + */ +ALT_STATUS_CODE alt_dma_program_update_reg(ALT_DMA_PROGRAM_t * pgm, + ALT_DMA_PROGRAM_REG_t reg, uint32_t val); + +/*! + */ + +/*! + * Assembles a DMAADDH (Add Halfword) instruction into the microcode program + * buffer. This instruction uses 3 bytes of buffer space. + * + * \param pgm + * The DMA program buffer to contain the assembled instruction. + * + * \param addr_reg + * The channel address register (ALT_DMA_PROGRAM_REG_DAR or + * ALT_DMA_PROGRAM_REG_SAR) to add the value to. + * + * \param val + * The 16-bit unsigned value to add to the channel address + * register. + * + * \retval ALT_E_SUCCESS Successful instruction assembly status. + * \retval ALT_E_DMA_BUF_OVF DMA program buffer overflow. + * \retval ALT_E_BAD_ARG Invalid channel register specified. + */ +// Assembler Syntax: DMAADDH , <16-bit immediate> +ALT_STATUS_CODE alt_dma_program_DMAADDH(ALT_DMA_PROGRAM_t * pgm, + ALT_DMA_PROGRAM_REG_t addr_reg, uint16_t val); + +/*! + * Assembles a DMAADNH (Add Negative Halfword) instruction into the microcode + * program buffer. This instruction uses 3 bytes of buffer space. + * + * \param pgm + * The DMA programm buffer to contain the assembled instruction. + * + * \param addr_reg + * The channel address register (ALT_DMA_PROGRAM_REG_DAR or + * ALT_DMA_PROGRAM_REG_SAR) to add the value to. + * + * \param val + * The 16-bit unsigned value to add to the channel address + * register. + * + * \retval ALT_E_SUCCESS Successful instruction assembly status. + * \retval ALT_E_DMA_BUF_OVF DMA program buffer overflow. + * \retval ALT_E_BAD_ARG Invalid channel register specified. + */ +// Assembler Syntax: DMAADNH , <16-bit immediate> +ALT_STATUS_CODE alt_dma_program_DMAADNH(ALT_DMA_PROGRAM_t * pgm, + ALT_DMA_PROGRAM_REG_t addr_reg, uint16_t val); + +/*! + * Assembles a DMAEND (End) instruction into the microcode program buffer. + * This instruction uses 1 byte of buffer space. + * + * \param pgm + * The DMA programm buffer to contain the assembled instruction. + * + * \retval ALT_E_SUCCESS Successful instruction assembly status. + * \retval ALT_E_DMA_BUF_OVF DMA program buffer overflow. + */ +// Assembler Syntax: DMAEND +ALT_STATUS_CODE alt_dma_program_DMAEND(ALT_DMA_PROGRAM_t * pgm); + +/*! + * Assembles a DMAFLUSHP (Flush Peripheral) instruction into the microcode + * program buffer. This instruction uses 2 bytes of buffer space. + * + * \param pgm + * The DMA programm buffer to contain the assembled instruction. + * + * \param periph + * The peripheral to flush. + * + * \retval ALT_E_SUCCESS Successful instruction assembly status. + * \retval ALT_E_DMA_BUF_OVF DMA program buffer overflow. + * \retval ALT_E_BAD_ARG Invalid peripheral specified. + */ +// Assembler Syntax: DMAFLUSHP +ALT_STATUS_CODE alt_dma_program_DMAFLUSHP(ALT_DMA_PROGRAM_t * pgm, + ALT_DMA_PERIPH_t periph); + +/*! + * Assembles a DMAGO (Go) instruction into the microcode program buffer. This + * instruction uses 6 bytes of buffer space. + * + * \param pgm + * The DMA programm buffer to contain the assembled instruction. + * + * \param channel + * The stopped channel to act upon. + * + * \param val + * The value to write to the channel program counter register. + * + * \param sec + * The security state for the operation. + * + * \retval ALT_E_SUCCESS Successful instruction assembly status. + * \retval ALT_E_DMA_BUF_OVF DMA program buffer overflow. + * \retval ALT_E_BAD_ARG Invalid channel or security specified. + */ +// Assembler Syntax: DMAGO , <32-bit_immediate> [, ns] +ALT_STATUS_CODE alt_dma_program_DMAGO(ALT_DMA_PROGRAM_t * pgm, + ALT_DMA_CHANNEL_t channel, uint32_t val, + ALT_DMA_SECURITY_t sec); + +/*! + * Assembles a DMAKILL (Kill) instruction into the microcode program buffer. + * This instruction uses 1 byte of buffer space. + * + * \param pgm + * The DMA programm buffer to contain the assembled instruction. + * + * \retval ALT_E_SUCCESS Successful instruction assembly status. + * \retval ALT_E_DMA_BUF_OVF DMA program buffer overflow. + */ +// Assembler Syntax: DMAKILL +ALT_STATUS_CODE alt_dma_program_DMAKILL(ALT_DMA_PROGRAM_t * pgm); + +/*! + * Assembles a DMALD (Load) instruction into the microcode program buffer. + * This instruction uses 1 byte of buffer space. + * + * \param pgm + * The DMA programm buffer to contain the assembled instruction. + * + * \param mod + * The program instruction modifier for the type of transfer. + * Only ALT_DMA_PROGRAM_INST_MOD_SINGLE and + * ALT_DMA_PROGRAM_INST_MOD_BURST are valid options. + * + * \retval ALT_E_SUCCESS Successful instruction assembly status. + * \retval ALT_E_DMA_BUF_OVF DMA program buffer overflow. + * \retval ALT_E_BAD_ARG Invalid instruction modifier specified. + */ +// Assembler Syntax: DMALD[S|B] +ALT_STATUS_CODE alt_dma_program_DMALD(ALT_DMA_PROGRAM_t * pgm, + ALT_DMA_PROGRAM_INST_MOD_t mod); + +/*! + * Assembles a DMALDP (Load and notify Peripheral) instruction into the + * microcode program buffer. This instruction uses 2 bytes of buffer space. + * + * \param pgm + * The DMA programm buffer to contain the assembled instruction. + * + * \param mod + * The program instruction modifier for the type of transfer. + * Only ALT_DMA_PROGRAM_INST_MOD_SINGLE and + * ALT_DMA_PROGRAM_INST_MOD_BURST are valid options. + * + * \param periph + * The peripheral to notify. + * + * \retval ALT_E_SUCCESS Successful instruction assembly status. + * \retval ALT_E_DMA_BUF_OVF DMA program buffer overflow. + * \retval ALT_E_BAD_ARG Invalid instruction modifier or peripheral + * specified. + */ +// Assembler Syntax: DMALDP +ALT_STATUS_CODE alt_dma_program_DMALDP(ALT_DMA_PROGRAM_t * pgm, + ALT_DMA_PROGRAM_INST_MOD_t mod, ALT_DMA_PERIPH_t periph); + +/*! + * Assembles a DMALP (Loop) instruction into the microcode program buffer. + * This instruction uses 2 bytes of buffer space. + * + * \param pgm + * The DMA programm buffer to contain the assembled instruction. + * + * \param iterations + * The number of iterations to run for. Valid values are 1 - 256. + * + * \retval ALT_E_SUCCESS Successful instruction assembly status. + * \retval ALT_E_DMA_BUF_OVF DMA program buffer overflow. + * \retval ALT_E_BAD_ARG Invalid iterations specified. + * \retval ALT_E_BAD_OPERATION All loop registers are in use. + */ +// Assembler Syntax: DMALP [|] +ALT_STATUS_CODE alt_dma_program_DMALP(ALT_DMA_PROGRAM_t * pgm, + uint32_t iterations); + +/*! + * Assembles a DMALPEND (Loop End) instruction into the microcode program + * buffer. This instruction uses 2 bytes of buffer space. + * + * \param pgm + * The DMA programm buffer to contain the assembled instruction. + * + * \param mod + * The program instruction modifier for the loop terminator. Only + * ALT_DMA_PROGRAM_INST_MOD_NONE, ALT_DMA_PROGRAM_INST_MOD_SINGLE + * and ALT_DMA_PROGRAM_INST_MOD_BURST are valid options. + * + * \retval ALT_E_SUCCESS Successful instruction assembly status. + * \retval ALT_E_DMA_BUF_OVF DMA program buffer overflow. + * \retval ALT_E_BAD_ARG Invalid instruction modifier specified. + * \retval ALT_E_ARG_RANGE Loop size is too large to be supported. + * \retval ALT_E_BAD_OPERATION A valid DMALP or DMALPFE was not added to + * the program buffer before adding this + * DMALPEND instruction. + */ +// Assembler Syntax: DMALPEND[S|B] +ALT_STATUS_CODE alt_dma_program_DMALPEND(ALT_DMA_PROGRAM_t * pgm, + ALT_DMA_PROGRAM_INST_MOD_t mod); + +/*! + * Assembles a DMALPFE (Loop Forever) instruction into the microcode program + * buffer. No instruction is added to the buffer but a previous DMALPEND to + * create an infinite loop. + * + * \param pgm + * The DMA programm buffer to contain the assembled instruction. + * + * \retval ALT_E_SUCCESS Successful instruction assembly status. + * \retval ALT_E_DMA_BUF_OVF DMA program buffer overflow. + */ +// Assembler Syntax: DMALPFE +ALT_STATUS_CODE alt_dma_program_DMALPFE(ALT_DMA_PROGRAM_t * pgm); + +/*! + * Assembles a DMAMOV (Move) instruction into the microcode program buffer. + * This instruction uses 6 bytes of buffer space. + * + * \param pgm + * The DMA programm buffer to contain the assembled instruction. + * + * \param chan_reg + * The channel non-looping register (ALT_DMA_PROGRAM_REG_SAR, + * ALT_DMA_PROGRAM_REG_DAR or ALT_DMA_PROGRAM_REG_CCR) to copy + * the value to. + * + * \param val + * The value to write to the specified register. + * + * \retval ALT_E_SUCCESS Successful instruction assembly status. + * \retval ALT_E_DMA_BUF_OVF DMA program buffer overflow. + * \retval ALT_E_BAD_ARG Invalid channel register specified. + */ +// Assembler Syntax: DMAMOV , <32-bit_immediate> +ALT_STATUS_CODE alt_dma_program_DMAMOV(ALT_DMA_PROGRAM_t * pgm, + ALT_DMA_PROGRAM_REG_t chan_reg, uint32_t val); + +/*! + * Assembles a DMANOP (No Operation) instruction into the microcode program + * buffer. This instruction uses 1 byte of buffer space. + * + * \param pgm + * The DMA programm buffer to contain the assembled instruction. + * + * \retval ALT_E_SUCCESS Successful instruction assembly status. + * \retval ALT_E_DMA_BUF_OVF DMA program buffer overflow. + */ +// Assembler Syntax: DMANOP +ALT_STATUS_CODE alt_dma_program_DMANOP(ALT_DMA_PROGRAM_t * pgm); + +/*! + * Assembles a DMARMB (Read Memory Barrier) instruction into the microcode + * program buffer. This instruction uses 1 byte of buffer space. + * + * \param pgm + * The DMA programm buffer to contain the assembled instruction. + * + * \retval ALT_E_SUCCESS Successful instruction assembly status. + * \retval ALT_E_DMA_BUF_OVF DMA program buffer overflow. + */ +// Assembler Syntax: DMARMB +ALT_STATUS_CODE alt_dma_program_DMARMB(ALT_DMA_PROGRAM_t * pgm); + +/*! + * Assembles a DMASEV (Send Event) instruction into the microcode program + * buffer. This instruction uses 2 byte of buffer space. + * + * \param pgm + * The DMA programm buffer to contain the assembled instruction. + * + * \param evt + * The event to send. + * + * \retval ALT_E_SUCCESS Successful instruction assembly status. + * \retval ALT_E_DMA_BUF_OVF DMA program buffer overflow. + * \retval ALT_E_BAD_ARG Invalid event specified. + */ +// Assembler Syntax: DMASEV +ALT_STATUS_CODE alt_dma_program_DMASEV(ALT_DMA_PROGRAM_t * pgm, + ALT_DMA_EVENT_t evt); + +/*! + * Assembles a DMAST (Store) instruction into the microcode program buffer. + * This instruction uses 1 byte of buffer space. + * + * \param pgm + * The DMA programm buffer to contain the assembled instruction. + * + * \param mod + * The program instruction modifier for the type of transfer. + * Only ALT_DMA_PROGRAM_INST_MOD_SINGLE and + * ALT_DMA_PROGRAM_INST_MOD_BURST are valid options. + * + * \retval ALT_E_SUCCESS Successful instruction assembly status. + * \retval ALT_E_DMA_BUF_OVF DMA program buffer overflow. + */ +// Assembler Syntax: DMAST[S|B] +ALT_STATUS_CODE alt_dma_program_DMAST(ALT_DMA_PROGRAM_t * pgm, + ALT_DMA_PROGRAM_INST_MOD_t mod); + +/*! + * Assembles a DMASTP (Store and notify Peripheral) instruction into the + * microcode program buffer. This instruction uses 2 bytes of buffer space. + * + * \param pgm + * The DMA programm buffer to contain the assembled instruction. + * + * \param mod + * The program instruction modifier for the type of transfer. + * Only ALT_DMA_PROGRAM_INST_MOD_SINGLE and + * ALT_DMA_PROGRAM_INST_MOD_BURST are valid options. + * + * \param periph + * The peripheral to notify. + * + * \retval ALT_E_SUCCESS Successful instruction assembly status. + * \retval ALT_E_DMA_BUF_OVF DMA program buffer overflow. + * \retval ALT_E_BAD_ARG Invalid instruction modifier or peripheral + * specified. + */ +// Assembler Syntax: DMASTP +ALT_STATUS_CODE alt_dma_program_DMASTP(ALT_DMA_PROGRAM_t * pgm, + ALT_DMA_PROGRAM_INST_MOD_t mod, ALT_DMA_PERIPH_t periph); + +/*! + * Assembles a DMASTZ (Store Zero) instruction into the microcode program + * buffer. This instruction uses 1 byte of buffer space. + * + * \param pgm + * The DMA programm buffer to contain the assembled instruction. + * + * \retval ALT_E_SUCCESS Successful instruction assembly status. + * \retval ALT_E_DMA_BUF_OVF DMA program buffer overflow. + */ +// Assembler Syntax: DMASTZ +ALT_STATUS_CODE alt_dma_program_DMASTZ(ALT_DMA_PROGRAM_t * pgm); + +/*! + * Assembles a DMAWFE (Wait For Event) instruction into the microcode program + * buffer. This instruction uses 2 byte of buffer space. + * + * \param pgm + * The DMA programm buffer to contain the assembled instruction. + * + * \param evt + * The event to wait for. + * + * \param invalid + * If invalid is set to true, the instruction will be configured + * to invalidate the instruction cache for the current DMA + * thread. + * + * \retval ALT_E_SUCCESS Successful instruction assembly status. + * \retval ALT_E_DMA_BUF_OVF DMA program buffer overflow. + * \retval ALT_E_BAD_ARG Invalid event specified. + */ +// Assembler Syntax: DMAWFE [, invalid] +ALT_STATUS_CODE alt_dma_program_DMAWFE(ALT_DMA_PROGRAM_t * pgm, + ALT_DMA_EVENT_t evt, bool invalid); + +/*! + * Assembles a DMAWFP (Wait for Peripheral) instruction into the microcode + * program buffer. This instruction uses 2 bytes of buffer space. + * + * \param pgm + * The DMA programm buffer to contain the assembled instruction. + * + * \param periph + * The peripheral to wait on. + * + * \param mod + * The program instruction modifier for the type of transfer. + * Only ALT_DMA_PROGRAM_INST_MOD_SINGLE, + * ALT_DMA_PROGRAM_INST_MOD_BURST, or + * ALT_DMA_PROGRAM_INST_MOD_PERIPH are valid options. + * + * \retval ALT_E_SUCCESS Successful instruction assembly status. + * \retval ALT_E_DMA_BUF_OVF DMA program buffer overflow. + * \retval ALT_E_BAD_ARG Invalid peripheral or instruction modifier + * specified. + */ +// Assembler Syntax: DMAWFP , +ALT_STATUS_CODE alt_dma_program_DMAWFP(ALT_DMA_PROGRAM_t * pgm, + ALT_DMA_PERIPH_t periph, ALT_DMA_PROGRAM_INST_MOD_t mod); + +/*! + * Assembles a DMAWMB (Write Memory Barrier) instruction into the microcode + * program buffer. This instruction uses 1 byte of buffer space. + * + * \param pgm + * The DMA programm buffer to contain the assembled instruction. + * + * \retval ALT_E_SUCCESS Successful instruction assembly status. + * \retval ALT_E_DMA_BUF_OVF DMA program buffer overflow. + */ +// Assembler Syntax: DMAWMB +ALT_STATUS_CODE alt_dma_program_DMAWMB(ALT_DMA_PROGRAM_t * pgm); + +/*! + * \addtogroup DMA_CCR Support for DMAMOV CCR + * + * The ALT_DMA_CCR_OPT_* macro definitions are defined here to facilitate the + * dynamic microcode programming of the assembler directive: +\verbatim + +DMAMOV CCR, [SB<1-16>] [SS<8|16|32|64|128>] [SA] + [SP] [SC] + [DB<1-16>] [DS<8|16|32|64|128>] [DA] + [DP] [DC] + [ES<8|16|32|64|128>] + +\endverbatim +* with a DMAMOV instruction (see: alt_dma_program_DMAMOV()). +* +* For example the assembler directive: +\verbatim +DMAMOV CCR SB1 SS32 DB1 DS32 +\endverbatim +* would be dynamically programmed with the following API call: +\verbatim +alt_dma_program_DMAMOV( pgm, + ALT_DMA_PROGRAM_REG_CCR, + ( ALT_DMA_CCR_OPT_SB1 + | ALT_DMA_CCR_OPT_SS32 + | ALT_DMA_CCR_OPT_SA_DEFAULT + | ALT_DMA_CCR_OPT_SP_DEFAULT + | ALT_DMA_CCR_OPT_SC_DEFAULT + | ALT_DMA_CCR_OPT_DB1 + | ALT_DMA_CCR_OPT_DS32 + | ALT_DMA_CCR_OPT_DA_DEFAULT + | ALT_DMA_CCR_OPT_DP_DEFAULT + | ALT_DMA_CCR_OPT_DC_DEFAULT + | ALT_DMA_CCR_OPT_ES8 + ) + ); +\endverbatim +* +* Each CCR option category should be specified regardless of whether it +* specifies a custom value or the normal default value (i.e. an +* ALT_DMA_CCR_OPT_*_DEFAULT. +* +* @{ +*/ + +/* + * Source Address {Fixed,Incrementing} + */ +/*! Source Address Fixed address burst. */ +#define ALT_DMA_CCR_OPT_SAF (0 << 0) +/*! Source Address Incrementing address burst. */ +#define ALT_DMA_CCR_OPT_SAI (1 << 0) +/*! Source Address Default value. */ +#define ALT_DMA_CCR_OPT_SA_DEFAULT ALT_DMA_CCR_OPT_SAI + +/* + * Source burst Size (in bits) + */ +/*! Source burst Size of 8 bits. */ +#define ALT_DMA_CCR_OPT_SS8 (0 << 1) +/*! Source burst Size of 16 bits. */ +#define ALT_DMA_CCR_OPT_SS16 (1 << 1) +/*! Source burst Size of 32 bits. */ +#define ALT_DMA_CCR_OPT_SS32 (2 << 1) +/*! Source burst Size of 64 bits. */ +#define ALT_DMA_CCR_OPT_SS64 (3 << 1) +/*! Source burst Size of 128 bits. */ +#define ALT_DMA_CCR_OPT_SS128 (4 << 1) +/*! Source burst Size default bits. */ +#define ALT_DMA_CCR_OPT_SS_DEFAULT ALT_DMA_CCR_OPT_SS8 + +/* + * Source burst Length (in transfer(s)) + */ +/*! Source Burst length of 1 transfer. */ +#define ALT_DMA_CCR_OPT_SB1 (0x0 << 4) +/*! Source Burst length of 2 transfers. */ +#define ALT_DMA_CCR_OPT_SB2 (0x1 << 4) +/*! Source Burst length of 3 transfers. */ +#define ALT_DMA_CCR_OPT_SB3 (0x2 << 4) +/*! Source Burst length of 4 transfers. */ +#define ALT_DMA_CCR_OPT_SB4 (0x3 << 4) +/*! Source Burst length of 5 transfers. */ +#define ALT_DMA_CCR_OPT_SB5 (0x4 << 4) +/*! Source Burst length of 6 transfers. */ +#define ALT_DMA_CCR_OPT_SB6 (0x5 << 4) +/*! Source Burst length of 7 transfers. */ +#define ALT_DMA_CCR_OPT_SB7 (0x6 << 4) +/*! Source Burst length of 8 transfers. */ +#define ALT_DMA_CCR_OPT_SB8 (0x7 << 4) +/*! Source Burst length of 9 transfers. */ +#define ALT_DMA_CCR_OPT_SB9 (0x8 << 4) +/*! Source Burst length of 10 transfers. */ +#define ALT_DMA_CCR_OPT_SB10 (0x9 << 4) +/*! Source Burst length of 11 transfers. */ +#define ALT_DMA_CCR_OPT_SB11 (0xa << 4) +/*! Source Burst length of 12 transfers. */ +#define ALT_DMA_CCR_OPT_SB12 (0xb << 4) +/*! Source Burst length of 13 transfers. */ +#define ALT_DMA_CCR_OPT_SB13 (0xc << 4) +/*! Source Burst length of 14 transfers. */ +#define ALT_DMA_CCR_OPT_SB14 (0xd << 4) +/*! Source Burst length of 15 transfers. */ +#define ALT_DMA_CCR_OPT_SB15 (0xe << 4) +/*! Source Burst length of 16 transfers. */ +#define ALT_DMA_CCR_OPT_SB16 (0xf << 4) +/*! Source Burst length default transfers. */ +#define ALT_DMA_CCR_OPT_SB_DEFAULT ALT_DMA_CCR_OPT_SB1 + +/* + * Source Protection + */ +/*! Source Protection bits for AXI bus ARPROT[2:0]. */ +#define ALT_DMA_CCR_OPT_SP(imm3) ((imm3) << 8) +/*! Source Protection bits default value. */ +#define ALT_DMA_CCR_OPT_SP_DEFAULT ALT_DMA_CCR_OPT_SP(0) + +/* + * Source cache + */ +/*! Source Cache bits for AXI bus ARCACHE[2:0]. */ +#define ALT_DMA_CCR_OPT_SC(imm4) ((imm4) << 11) +/*! Source Cache bits default value. */ +#define ALT_DMA_CCR_OPT_SC_DEFAULT ALT_DMA_CCR_OPT_SC(0) + +/* + * Destination Address {Fixed,Incrementing} + */ +/*! Destination Address Fixed address burst. */ +#define ALT_DMA_CCR_OPT_DAF (0 << 14) +/*! Destination Address Incrementing address burst. */ +#define ALT_DMA_CCR_OPT_DAI (1 << 14) +/*! Destination Address Default value. */ +#define ALT_DMA_CCR_OPT_DA_DEFAULT ALT_DMA_CCR_OPT_DAI + +/* + * Destination burst Size (in bits) + */ +/*! Destination burst Size of 8 bits. */ +#define ALT_DMA_CCR_OPT_DS8 (0 << 15) +/*! Destination burst Size of 16 bits. */ +#define ALT_DMA_CCR_OPT_DS16 (1 << 15) +/*! Destination burst Size of 32 bits. */ +#define ALT_DMA_CCR_OPT_DS32 (2 << 15) +/*! Destination burst Size of 64 bits. */ +#define ALT_DMA_CCR_OPT_DS64 (3 << 15) +/*! Destination burst Size of 128 bits. */ +#define ALT_DMA_CCR_OPT_DS128 (4 << 15) +/*! Destination burst Size default bits. */ +#define ALT_DMA_CCR_OPT_DS_DEFAULT ALT_DMA_CCR_OPT_DS8 + +/* + * Destination Burst length (in transfer(s)) + */ +/*! Destination Burst length of 1 transfer. */ +#define ALT_DMA_CCR_OPT_DB1 (0x0 << 18) +/*! Destination Burst length of 2 transfers. */ +#define ALT_DMA_CCR_OPT_DB2 (0x1 << 18) +/*! Destination Burst length of 3 transfers. */ +#define ALT_DMA_CCR_OPT_DB3 (0x2 << 18) +/*! Destination Burst length of 4 transfers. */ +#define ALT_DMA_CCR_OPT_DB4 (0x3 << 18) +/*! Destination Burst length of 5 transfers. */ +#define ALT_DMA_CCR_OPT_DB5 (0x4 << 18) +/*! Destination Burst length of 6 transfers. */ +#define ALT_DMA_CCR_OPT_DB6 (0x5 << 18) +/*! Destination Burst length of 7 transfers. */ +#define ALT_DMA_CCR_OPT_DB7 (0x6 << 18) +/*! Destination Burst length of 8 transfers. */ +#define ALT_DMA_CCR_OPT_DB8 (0x7 << 18) +/*! Destination Burst length of 9 transfers. */ +#define ALT_DMA_CCR_OPT_DB9 (0x8 << 18) +/*! Destination Burst length of 10 transfers. */ +#define ALT_DMA_CCR_OPT_DB10 (0x9 << 18) +/*! Destination Burst length of 11 transfers. */ +#define ALT_DMA_CCR_OPT_DB11 (0xa << 18) +/*! Destination Burst length of 12 transfers. */ +#define ALT_DMA_CCR_OPT_DB12 (0xb << 18) +/*! Destination Burst length of 13 transfers. */ +#define ALT_DMA_CCR_OPT_DB13 (0xc << 18) +/*! Destination Burst length of 14 transfers. */ +#define ALT_DMA_CCR_OPT_DB14 (0xd << 18) +/*! Destination Burst length of 15 transfers. */ +#define ALT_DMA_CCR_OPT_DB15 (0xe << 18) +/*! Destination Burst length of 16 transfers. */ +#define ALT_DMA_CCR_OPT_DB16 (0xf << 18) +/*! Destination Burst length default transfers. */ +#define ALT_DMA_CCR_OPT_DB_DEFAULT ALT_DMA_CCR_OPT_DB1 + +/* + * Destination Protection + */ +/*! Destination Protection bits for AXI bus AWPROT[2:0]. */ +#define ALT_DMA_CCR_OPT_DP(imm3) ((imm3) << 22) +/*! Destination Protection bits default value. */ +#define ALT_DMA_CCR_OPT_DP_DEFAULT ALT_DMA_CCR_OPT_DP(0) + +/* + * Destination Cache + */ +/*! Destination Cache bits for AXI bus AWCACHE[3,1:0]. */ +#define ALT_DMA_CCR_OPT_DC(imm4) ((imm4) << 25) +/*! Destination Cache bits default value. */ +#define ALT_DMA_CCR_OPT_DC_DEFAULT ALT_DMA_CCR_OPT_DC(0) + +/* + * Endian Swap size (in bits) + */ +/*! Endian Swap: No swap, 8-bit data. */ +#define ALT_DMA_CCR_OPT_ES8 (0 << 28) +/*! Endian Swap: Swap bytes within 16-bit data. */ +#define ALT_DMA_CCR_OPT_ES16 (1 << 28) +/*! Endian Swap: Swap bytes within 32-bit data. */ +#define ALT_DMA_CCR_OPT_ES32 (2 << 28) +/*! Endian Swap: Swap bytes within 64-bit data. */ +#define ALT_DMA_CCR_OPT_ES64 (3 << 28) +/*! Endian Swap: Swap bytes within 128-bit data. */ +#define ALT_DMA_CCR_OPT_ES128 (4 << 28) +/*! Endian Swap: Default byte swap. */ +#define ALT_DMA_CCR_OPT_ES_DEFAULT ALT_DMA_CCR_OPT_ES8 + +/*! Default CCR register options for a DMAMOV CCR assembler directive. */ +#define ALT_DMA_CCR_OPT_DEFAULT \ + (ALT_DMA_CCR_OPT_SB1 | ALT_DMA_CCR_OPT_SS8 | ALT_DMA_CCR_OPT_SAI | \ + ALT_DMA_CCR_OPT_SP(0) | ALT_DMA_CCR_OPT_SC(0) | \ + ALT_DMA_CCR_OPT_DB1 | ALT_DMA_CCR_OPT_DS8 | ALT_DMA_CCR_OPT_DAI | \ + ALT_DMA_CCR_OPT_DP(0) | ALT_DMA_CCR_OPT_DC(0) | \ + ALT_DMA_CCR_OPT_ES8) + +/*! + * @} + */ + +/*! + * @} + */ + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* __ALT_DMA_PROGRAM_H__ */ diff --git a/c/src/lib/libbsp/arm/altera-cyclone-v/hwlib/include/alt_qspi.h b/c/src/lib/libbsp/arm/altera-cyclone-v/hwlib/include/alt_qspi.h new file mode 100644 index 0000000000..d09ccf2f69 --- /dev/null +++ b/c/src/lib/libbsp/arm/altera-cyclone-v/hwlib/include/alt_qspi.h @@ -0,0 +1,1535 @@ +/****************************************************************************** +* +* Copyright 2013 Altera Corporation. All Rights Reserved. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions are met: +* +* 1. Redistributions of source code must retain the above copyright notice, +* this list of conditions and the following disclaimer. +* +* 2. Redistributions in binary form must reproduce the above copyright notice, +* this list of conditions and the following disclaimer in the documentation +* and/or other materials provided with the distribution. +* +* 3. The name of the author may not be used to endorse or promote products +* derived from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER "AS IS" AND ANY EXPRESS OR +* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED. IN NO +* EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT +* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING +* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY +* OF SUCH DAMAGE. +* +******************************************************************************/ + +/****************************************************************************** +* +* !!!! Customer Be Aware, Exception!!! +* +* 1. Qspi Direct Access Mode is not working! +* +* This is because the qspi flash memory installed on our DevKit board, Micro +* part N25Q00xx, 8 Gb, is not completely compatible with our embedded Synopsis +* QSPI controller IP. Therefore there is no viable direct access code offered +* in the lib. All the memory rea/write functionality is offered with indirect +* access only. +* +* Should you install a different flash memory part in your custom board, and +* wondering wether direct access mode works, please contact with us. +* +******************************************************************************/ + +/*! \file + * Altera - QSPI Flash Controller Module + */ + +#ifndef __ALT_QSPI_H__ +#define __ALT_QSPI_H__ + +#include "hwlib.h" + +#ifdef __cplusplus +extern "C" +{ +#endif /* __cplusplus */ + +/******************************************************************************/ +/*! \addtogroup ALT_QSPI QSPI Flash Controller Module + * + * This module defines a low level driver API for the hardware processor system + * (HPS) quad serial peripheral interface (QSPI) flash controller for access to + * serial NOR flash devices. The quad SPI flash controller supports standard SPI + * flash devices as well as high-performance dual and quad SPI flash + * devices. + * + * @{ + */ + +/******************************************************************************/ +/*! \addtogroup ALT_QSPI_CSR General Control and Status Functions + * + * The declarations and functions in this group provide general purpose control + * and status functions for the QSPI Flash Controller. + * + * @{ + */ + +/******************************************************************************/ +/*! + * Initialize the QSPI flash controller for use. + * + * \internal + * Implementation Notes: + * * The QSPI Controller has been designed to wake up in a state that is + * suitable for performing basic reads and writes using the direct access + * controller. + * * Bring out of reset + * * QSPI reference clock validation + * * See Programmer's Guide, Configuring the QSPI Controller for use after + * reset, in QSPI_FLASH_CTRL for full initialization details. + * \endinternal + * + * \retval ALT_E_SUCCESS Indicates successful completion. + * \retval ALT_E_ERROR Indicates an error occurred. + */ +ALT_STATUS_CODE alt_qspi_init(void); + +/******************************************************************************/ +/*! + * Uninitialize the QSPI flash controller. + * + * Uninitialize the QSPI flash controller by cancelling any indirect transfers + * in progress and putting the QSPI controller into reset. + * + * \retval ALT_E_SUCCESS Indicates successful completion. + * \retval ALT_E_ERROR Indicates an error occurred. + */ +ALT_STATUS_CODE alt_qspi_uninit(void); + +/******************************************************************************/ +/*! + * Disable the QSPI Controller. + * + * Disable the QSPI once the current transfer of the data word (FF_W) is + * complete. All output enables are inactive and all pins are set to input + * mode. + * + * \retval ALT_E_SUCCESS Indicates successful completion. + * \retval ALT_E_ERROR Indicates an error occurred. + */ +ALT_STATUS_CODE alt_qspi_disable(void); + +/******************************************************************************/ +/*! + * Enable the QSPI Controller. + * + * \retval ALT_E_SUCCESS Indicates successful completion. + * \retval ALT_E_ERROR Indicates an error occurred. + */ +ALT_STATUS_CODE alt_qspi_enable(void); + +/******************************************************************************/ +/*! + * This type definition enumerates the interrupt status conditions for the QSPI + * controller. + * + * The enumerations serve as masks for the QSPI controller events that can be + * set when the designated conditions occur and the corresponding event is + * enabled. When any of these event source conditions are true, the \b + * ALT_INT_INTERRUPT_QSPI_IRQ interrupt output is asserted high. + * + * Interrupt sources are cleared when software calls alt_qspi_int_clear(). The + * interrupt sources are individually maskable using alt_qspi_int_disable() and + * alt_qspi_int_enable(). + */ +typedef enum ALT_QSPI_INT_STATUS_e +{ + /*! + * Mode fail M - indicates the voltage on pin n_ss_in is inconsistent with + * the SPI mode. Set = 1 if n_ss_in is low in master mode (multi-master + * contention). These conditions will clear the spi_enable bit and disable + * the SPI. + * * 0 = no mode fault has been detected. + * * 1 = a mode fault has occurred. + */ + ALT_QSPI_INT_STATUS_MODE_FAIL = (0x1 << 0), + + /*! + * Underflow Detected. + * * 0 = no underflow has been detected. + * * 1 = underflow is detected and an attempt to transfer data is made + * when the small TX FIFO is empty. This may occur when AHB write + * data is being supplied too slowly to keep up with the requested + * write operation. + */ + ALT_QSPI_INT_STATUS_UFL = (0x1 << 1), + + /*! + * Controller has completed last triggered indirect operation. + */ + ALT_QSPI_INT_STATUS_IDAC_OP_COMPLETE = (0x1 << 2), + + /*! + * Indirect operation was requested but could not be accepted. Two indirect + * operations already in storage. + */ + ALT_QSPI_INT_STATUS_IDAC_OP_REJECT = (0x1 << 3), + + /*! + * Write to protected area was attempted and rejected. + */ + ALT_QSPI_INT_STATUS_WR_PROT_VIOL = (0x1 << 4), + + /*! + * Illegal AHB Access Detected. AHB write wrapping bursts and the use of + * SPLIT/RETRY accesses will cause this interrupt to trigger. + */ + ALT_QSPI_INT_STATUS_ILL_AHB_ACCESS = (0x1 << 5), + + /*! + * Indirect Transfer Watermark Level Breached. + */ + ALT_QSPI_INT_STATUS_IDAC_WTRMK_TRIG = (0x1 << 6), + + /*! + * Receive Overflow. This should only occur in Legacy SPI mode. + * + * Set if an attempt is made to push the RX FIFO when it is full. This bit + * is reset only by a system reset and cleared only when this register is + * read. If a new push to the RX FIFO occurs coincident with a register read + * this flag will remain set. + * * 0 = no overflow has been detected. + * * 1 = an overflow has occurred. + */ + ALT_QSPI_INT_STATUS_RX_OVF = (0x1 << 7), + + /*! + * Small TX FIFO not full (current FIFO status). Can be ignored in non-SPI + * legacy mode. + * * 0 = FIFO has >= THRESHOLD entries. + * * 1 = FIFO has < THRESHOLD entries. + */ + ALT_QSPI_INT_STATUS_TX_FIFO_NOT_FULL = (0x1 << 8), + + /*! + * Small TX FIFO full (current FIFO status). Can be ignored in non-SPI + * legacy mode. + * * 0 = FIFO is not full. + * * 1 = FIFO is full. + */ + ALT_QSPI_INT_STATUS_TX_FIFO_FULL = (0x1 << 9), + + /*! + * Small RX FIFO not empty (current FIFO status). Can be ignored in non-SPI + * legacy mode. + * * 0 = FIFO has < RX THRESHOLD entries. + * * 1 = FIFO has >= THRESHOLD entries. + */ + ALT_QSPI_INT_STATUS_RX_FIFO_NOT_EMPTY = (0x1 << 10), + + /*! + * Small RX FIFO full (current FIFO status). Can be ignored in non-SPI + * legacy mode. + * * 0 = FIFO is not full. + * * 1 = FIFO is full. + */ + ALT_QSPI_INT_STATUS_RX_FIFO_FULL = (0x1 << 11), + + /*! + * Indirect Read partition of SRAM is full and unable to immediately + * complete indirect operation. + */ + ALT_QSPI_INT_STATUS_IDAC_RD_FULL = (0x1 << 12) + +} ALT_QSPI_INT_STATUS_t; + +/******************************************************************************/ +/*! + * Returns the QSPI controller interrupt status register value. + * + * This function returns the current value of the QSPI controller interrupt + * status register value which reflects the current QSPI controller status + * conditions. + * + * \returns The current value of the QSPI controller interrupt status + * register value which reflects the current QSPI controller status + * conditions as defined by the \ref ALT_QSPI_INT_STATUS_t mask. + * If the corresponding bit is set then the condition is asserted. + */ +uint32_t alt_qspi_int_status_get(void); + +/******************************************************************************/ +/*! + * Clears the specified QSPI controller interrupt status conditions identified + * in the mask. + * + * This function clears one or more of the status conditions as contributors to + * the \b ALT_INT_INTERRUPT_QSPI_IRQ interrupt signal state. + * + * \param mask + * Specifies the QSPI interrupt status conditions to clear. \e + * mask is a mask of logically OR'ed \ref ALT_QSPI_INT_STATUS_t + * values that designate the status conditions to clear. + * + * \retval ALT_E_SUCCESS Indicates successful completion. + * \retval ALT_E_ERROR Indicates an error occurred. + */ +ALT_STATUS_CODE alt_qspi_int_clear(const uint32_t mask); + +/******************************************************************************/ +/*! + * Disable the specified QSPI controller interrupt status conditions identified + * in the mask. + * + * This function disables one or more of the status conditions as contributors + * to the \b ALT_INT_INTERRUPT_QSPI_IRQ interrupt signal state. + * + * This API requires that the QSPI controller be idle, as determined by + * alt_qspi_is_idle(). + * + * NOTE: A cleared bit for any status condition in the mask value does not have + * the effect of enabling it as a contributor to the \b + * ALT_INT_INTERRUPT_QSPI_IRQ interrupt signal state. The function + * alt_qspi_int_enable() is used to enable status source conditions. + * + * \param mask + * Specifies the status conditions to disable as interrupt source + * contributors. \e mask is a mask of logically OR'ed + * \ref ALT_QSPI_INT_STATUS_t values that designate the status + * conditions to disable. + * + * \retval ALT_E_SUCCESS Indicates successful completion. + * \retval ALT_E_ERROR Indicates an error occurred. + */ +ALT_STATUS_CODE alt_qspi_int_disable(const uint32_t mask); + +/******************************************************************************/ +/*! + * Enable the specified QSPI controller interrupt status conditions identified + * in the mask. + * + * This function enables one or more of the status conditions as contributors to + * the \b ALT_INT_INTERRUPT_QSPI_IRQ interrupt signal state. + * + * This API requires that the QSPI controller be idle, as determined by + * alt_qspi_is_idle(). + * + * NOTE: A cleared bit for any status condition in the mask value does not have + * the effect of disabling it as a contributor to the \b + * ALT_INT_INTERRUPT_QSPI_IRQ interrupt signal state. The function + * alt_qspi_int_disable() is used to disable status source conditions. + * + * \param mask + * Specifies the status conditions to enable as interrupt source + * contributors. \e mask is a mask of logically OR'ed + * \ref ALT_QSPI_INT_STATUS_t values that designate the status + * conditions to enable. + * + * \retval ALT_E_SUCCESS Indicates successful completion. + * \retval ALT_E_ERROR Indicates an error occurred. + */ +ALT_STATUS_CODE alt_qspi_int_enable(const uint32_t mask); + +/******************************************************************************/ +/*! + * Returns true the serial interface and QSPI pipeline is IDLE. + * + * \returns Returns true the serial interface and QSPI pipeline is IDLE. + */ +bool alt_qspi_is_idle(void); + +/*! @} */ + +/******************************************************************************/ +/*! \addtogroup ALT_QSPI_GP_BLKIO General Purpose Block I/O + * + * The functions in this group provide general purpose block read and + * write flash functions. + * + * \internal + * These functions use Indirect Read/Write transfers to read and write block + * data to the flash device. An outline of the operational flow for these + * operations can be found in: + * //depot/soc/hhp_sw/baremetal_fw/drivers/qspi/qspi.c + * + * The general flow for an indirect block read is to call + * qspi_configure_mode_indirect_read_start() to initiate the read transfer from + * the flash device into the SRAM buffer and follow with a call to either + * qpsi_write_sram_fifo_poll() or qspi_read_sram_fifo_irq() to copy the data + * from SRAM into the user's buffer. + * + * The general flow for an indirect block write is to call + * qspi_configure_mode_indirect_write_start() to initiate the write transfer + * from the SRAM buffer to the flash device and follow with a call to either + * qpsi_write_sram_fifo_poll() or qspi_write_sram_fifo_irq() to fill the SRAM + * buffer with the user's data as space becomes available. + * \endinternal + * + * @{ + */ + +/******************************************************************************/ +/*! + * Read a block of data from the specified flash address. + * + * Reads a block of \e n data bytes from the flash \e src address into the user + * supplied \e dest buffer. The memory address, flash address, and size must be + * word aligned. + * + * \param dest + * The address of a caller supplied destination buffer large enough + * to contain the requested block of flash data. + * + * \param src + * The flash device address to start reading data from. + * + * \param size + * The requested number of data bytes to read from the flash device. + * + * \retval ALT_E_SUCCESS Indicates successful completion. + * \retval ALT_E_ERROR Indicates an error occurred. + */ +ALT_STATUS_CODE alt_qspi_read(void * dest, uint32_t src, size_t size); + +/******************************************************************************/ +/*! + * Write a block of data to the specified flash address. + * + * Writes a block of \e n data bytes to the flash \e dest address from the + * designated \e src buffer. The applicable destination flash address range + * should have been erased prior to calling this function. The flash address, + * memory address, and size must be word aligned. + * + * \param dest + * The destination flash address to begin writing data to. + * + * \param src + * The source address to start writing data from. + * + * \param size + * The requested number of data bytes to write to the flash device. + * + * \retval ALT_E_SUCCESS Indicates successful completion. + * \retval ALT_E_ERROR Indicates an error occurred. + */ +ALT_STATUS_CODE alt_qspi_write(uint32_t dest, const void * src, size_t size); + +/*! @} */ + +/******************************************************************************/ +/*! \addtogroup ALT_QSPI_DEV_CFG Flash Device Configuration + * + * The declarations and functions in this group are used to configure the QSPI + * controller interface to external flash devices. + * + * The following steps describe how to initialize and configure the + * QSPI controller to operate with a flash device. + * + * * Wait until any pending QSPI operations have completed. + * * Disable the QSPI controller using alt_qspi_disable(). + * * Configure the device for optimal read transaction performance using + * alt_qspi_device_read_config_set(). + * * Configure the device for optimal write transaction performance using + * alt_qspi_device_write_config_set(). + * * Enable (alt_qspi_mode_bit_disable()) or disable + * (alt_qspi_mode_bit_disable()) the mode bits per the device + * requirements. If mode bits are enabled, then configure the mode + * bit values using alt_qspi_mode_bit_config_set(). + * * Configure the device size and write protection information using + * alt_qspi_device_size_config_set(). + * * Configure the QSPI device delay and timing settings using + * alt_qspi_device_write_config_set(). + * * Configure the baud divisor setting to define the required clock frequency + * to the device using alt_qspi_baud_rate_div_set(). + * * Enable the QSPI controller using alt_qspi_enable(). + * + * @{ + */ + +/******************************************************************************/ +/*! + * This type enumerates the operational modes the QSPI controller can be + * configured for. It may apply to instruction, address, and/or data width + * interactions between the QSPI controller and the flash device. + */ +typedef enum ALT_QSPI_MODE_e +{ + ALT_QSPI_MODE_SINGLE = 0, /*!< Use Standard Single SPI (SIO-SPI) mode (bits + * always transferred into the device on DQ0 + * only). Supported by all SPI flash devices. + */ + ALT_QSPI_MODE_DUAL = 1, /*!< Use Dual SPI (DIO-SPI) SPI mode where bits are + * transferred on DQ0 and DQ1. + */ + ALT_QSPI_MODE_QUAD = 2 /*!< Use Dual SPI (QIO-SPI) SPI mode where bits are + * transferred on DQ0, DQ1, DQ3, and DQ3. + */ +} ALT_QSPI_MODE_t; + +/******************************************************************************/ +/*! + * This type enumerates the mode configurations available for driving the + * ss_n[3:0] device chip selects. The chip selects may be controlled as either + * in a '1 of 4' or '4 to 16 decode' mode. + */ +typedef enum ALT_QSPI_CS_MODE_e +{ + ALT_QSPI_CS_MODE_SINGLE_SELECT = 0, /*!< Select 1 of 4 chip select ss_n[3:0] + */ + ALT_QSPI_CS_MODE_DECODE = 1 /*!< Select external 4 to 16 decode of + * ss_n[3:0]. + */ +} ALT_QSPI_CS_MODE_t; + +/******************************************************************************/ +/*! + * This type enumerates the QSPI controller master baud rate divisor selections. + */ +typedef enum ALT_QSPI_BAUD_DIV_e +{ + ALT_QSPI_BAUD_DIV_2 = 0x0, /*!< Divide by 2 */ + ALT_QSPI_BAUD_DIV_4 = 0x1, /*!< Divide by 4 */ + ALT_QSPI_BAUD_DIV_6 = 0x2, /*!< Divide by 6 */ + ALT_QSPI_BAUD_DIV_8 = 0x3, /*!< Divide by 8 */ + ALT_QSPI_BAUD_DIV_10 = 0x4, /*!< Divide by 10 */ + ALT_QSPI_BAUD_DIV_12 = 0x5, /*!< Divide by 12 */ + ALT_QSPI_BAUD_DIV_14 = 0x6, /*!< Divide by 14 */ + ALT_QSPI_BAUD_DIV_16 = 0x7, /*!< Divide by 16 */ + ALT_QSPI_BAUD_DIV_18 = 0x8, /*!< Divide by 18 */ + ALT_QSPI_BAUD_DIV_20 = 0x9, /*!< Divide by 20 */ + ALT_QSPI_BAUD_DIV_22 = 0xA, /*!< Divide by 22 */ + ALT_QSPI_BAUD_DIV_24 = 0xB, /*!< Divide by 24 */ + ALT_QSPI_BAUD_DIV_26 = 0xC, /*!< Divide by 26 */ + ALT_QSPI_BAUD_DIV_28 = 0xD, /*!< Divide by 28 */ + ALT_QSPI_BAUD_DIV_30 = 0xE, /*!< Divide by 30 */ + ALT_QSPI_BAUD_DIV_32 = 0xF /*!< Divide by 32 */ +} ALT_QSPI_BAUD_DIV_t; + +/******************************************************************************/ +/*! + * Device Size Configuration + * + * This type defines the structure used to specify flash device size and write + * protect regions. + */ +typedef struct ALT_QSPI_DEV_SIZE_CONFIG_s +{ + uint32_t block_size; /*!< Number of bytes per device block. The + * number is specified as a power of 2. + * That is 0 = 1 byte, 1 = 2 bytes, ... + * 16 = 65535 bytes, etc. + */ + uint32_t page_size; /*!< Number of bytes per device page. This + * is required by the controller for + * performing flash writes up to and + * across page boundaries. + */ + uint32_t addr_size; /*!< Number of bytes used for the flash + * address. The value is \e n + 1 + * based. That is 0 = 1 byte, 1 = 2 bytes, + * 2 = 3 bytes, 3 = 4 bytes. + */ + uint32_t lower_wrprot_block; /*!< The block number that defines the lower + * block in the range of blocks that is + * protected from writing. This field + * is ignored it write protection is + * disabled. + */ + uint32_t upper_wrprot_block; /*!< The block number that defines the upper + * block in the range of blocks that is + * protected from writing. This field + * is ignored it write protection is + * disabled. + */ + bool wrprot_enable; /*!< The write region enable value. A value + * of \b true enables write protection + * on the region specified by the + * \e lower_wrprot_block and + * \e upper_wrprot_block range. + */ +} ALT_QSPI_DEV_SIZE_CONFIG_t; + +/******************************************************************************/ +/*! + * This type enumerates the QSPI clock phase activity options outside the SPI + * word. + */ +typedef enum ALT_QSPI_CLK_PHASE_e +{ + ALT_QSPI_CLK_PHASE_ACTIVE = 0, /*!< The SPI clock is active outside the + * word + */ + ALT_QSPI_CLK_PHASE_INACTIVE = 1 /*!< The SPI clock is inactive outside the + * word + */ +} ALT_QSPI_CLK_PHASE_t; + +/******************************************************************************/ +/*! + * This type enumerates the QSPI clock polarity options outside the SPI word. + */ +typedef enum ALT_QSPI_CLK_POLARITY_e +{ + ALT_QSPI_CLK_POLARITY_LOW = 0, /*!< SPI clock is quiescent low outside the + * word. + */ + ALT_QSPI_CLK_POLARITY_HIGH = 1 /*!< SPI clock is quiescent high outside the + * word. + */ +} ALT_QSPI_CLK_POLARITY_t; + +/******************************************************************************/ +/*! + * QSPI Controller Timing Configuration + * + * This type defines the structure used to configure timing paramaters used by + * the QSPI controller to communicate with a target flash device. + * + * All timing values are defined in cycles of the SPI master ref clock. + */ +typedef struct ALT_QSPI_TIMING_CONFIG_s +{ + ALT_QSPI_CLK_PHASE_t clk_phase; /*!< Selects whether the clock is in an + * active or inactive phase outside the + * SPI word. + */ + + ALT_QSPI_CLK_POLARITY_t clk_pol; /*!< Selects whether the clock is quiescent + * low or high outside the SPI word. + */ + + uint32_t cs_da; /*!< Chip Select De-Assert. Added delay in + * master reference clocks for the length + * that the master mode chip select + * outputs are de-asserted between + * transactions. If CSDA = \e X, then the + * chip select de-assert time will be: 1 + * sclk_out + 1 ref_clk + \e X ref_clks. + */ + uint32_t cs_dads; /*!< Chip Select De-Assert Different + * Slaves. Delay in master reference + * clocks between one chip select being + * de-activated and the activation of + * another. This is used to ensure a quiet + * period between the selection of two + * different slaves. CSDADS is only + * relevant when switching between 2 + * different external flash devices. If + * CSDADS = \e X, then the delay will be: + * 1 sclk_out + 3 ref_clks + \e X + * ref_clks. + */ + uint32_t cs_eot; /*!< Chip Select End Of Transfer. Delay in + * master reference clocks between last + * bit of current transaction and + * de-asserting the device chip select + * (n_ss_out). By default (when CSEOT=0), + * the chip select will be de-asserted on + * the last falling edge of sclk_out at + * the completion of the current + * transaction. If CSEOT = \e X, then chip + * selected will de-assert \e X ref_clks + * after the last falling edge of + * sclk_out. + */ + uint32_t cs_sot; /*!< Chip Select Start Of Transfer. Delay in + * master reference clocks between setting + * n_ss_out low and first bit transfer. By + * default (CSSOT=0), chip select will be + * asserted half a SCLK period before the + * first rising edge of sclk_out. If CSSOT + * = \e X, chip select will be asserted + * half an sclk_out period before the + * first rising edge of sclk_out + \e X + * ref_clks. + */ + + uint32_t rd_datacap; /*!< The additional number of read data + * capture cycles (ref_clk) that should be + * applied to the internal read data + * capture circuit. The large + * clock-to-out delay of the flash memory + * together with trace delays as well as + * other device delays may impose a + * maximum flash clock frequency which is + * less than the flash memory device + * itself can operate at. To compensate, + * software should set this register to a + * value that guarantees robust data + * captures. + */ +} ALT_QSPI_TIMING_CONFIG_t; + +/******************************************************************************/ +/*! + * Device Instruction Configuration + * + * This type defines a structure for specifying the optimal instruction set + * configuration to use with a target flash device. + */ +typedef struct ALT_QSPI_DEV_INST_CONFIG_s +{ + uint32_t op_code; /*!< The read or write op code to use + * for the device transaction. + */ + ALT_QSPI_MODE_t inst_type; /*!< Instruction mode type for the + * controller to use with the + * device. The instruction type + * applies to all instructions + * (reads and writes) issued from + * either the Direct Access + * Controller or the Indirect + * Acces Controller. + */ + ALT_QSPI_MODE_t addr_xfer_type; /*!< Address transfer mode type. The + * value of this field is ignored + * if the \e inst_type data member + * is set to anything other than + * ALT_QSPI_MODE_SINGLE. In that + * case, the addr_xfer_type + * assumes the same mode as the \e + * inst_type. + */ + ALT_QSPI_MODE_t data_xfer_type; /*!< Data transfer mode type. The + * value of this field is ignored + * if the \e inst_type data member + * is set to anything other than + * ALT_QSPI_MODE_SINGLE. In that + * case, the data_xfer_type + * assumes the same mode as the \e + * inst_type. + */ + uint32_t dummy_cycles; /*!< Number of dummy clock cycles + * required by device for a read + * or write instruction. + */ + +} ALT_QSPI_DEV_INST_CONFIG_t; + +/******************************************************************************/ +/*! + * Get the current value of the QSPI master baud rate divisor. + * + * \returns The value of the QSPI master baud rate divisor. + */ +ALT_QSPI_BAUD_DIV_t alt_qspi_baud_rate_div_get(void); + +/******************************************************************************/ +/*! + * Set the current value of the QSPI master baud rate divisor. + * + * Sets the value of the QSPI master baud rate divisor. + * + * \param baud_rate_div + * The master baud rate divisor. Valid range includes + * even values 2 to 32. + * + * \retval ALT_E_SUCCESS Indicates successful completion. + * \retval ALT_E_ERROR Indicates an error occurred. + */ +ALT_STATUS_CODE alt_qspi_baud_rate_div_set(const ALT_QSPI_BAUD_DIV_t baud_rate_div); + +/******************************************************************************/ +/*! + * Get the current QSPI device peripheral chip select output and decode function + * configuration values. + * + * \param cs + * [out] The chip select line output values. + * + * \param cs_mode + * [out] The decode mode to use for the chip selects. + * + * \retval ALT_E_SUCCESS Indicates successful completion. + * \retval ALT_E_ERROR Indicates an error occurred. + */ +ALT_STATUS_CODE alt_qspi_chip_select_config_get(uint32_t* cs, ALT_QSPI_CS_MODE_t* cs_mode); + +/******************************************************************************/ +/*! + * Set the QSPI device peripheral chip select outputs and decode function + * configuration. + * + * The chip select lines output values operate according to the selected chip + * select decode mode. If \e cs_mode is ALT_QSPI_CS_MODE_SINGLE_SELECT then + * cs[3:0] are output thus: + * + * cs[3:0] | n_ss_out[3:0] + * :---------|:---------------------------- + * xxx0 | 1110 + * xx01 | 1101 + * x011 | 1011 + * 0111 | 0111 + * 1111 | 1111 (no peripheral selected) + * + * Otherwise if \e cs_mode is ALT_QSPI_CS_MODE_DECODE then cs[3:0] directly + * drives n_ss_out[3:0]. + * + * \param cs + * The chip select line output values. + * + * \param cs_mode + * The decode mode to use for the chip selects. + * + * \retval ALT_E_SUCCESS Indicates successful completion. + * \retval ALT_E_ERROR Indicates an error occurred. + */ +ALT_STATUS_CODE alt_qspi_chip_select_config_set(const uint32_t cs, + const ALT_QSPI_CS_MODE_t cs_mode); + +/******************************************************************************/ +/*! + * Disable the mode bits from being sent after the address bytes. + * + * Prevent the mode bits defined in the Mode Bit Configuration register from + * being sent following the address bytes. + * + * \retval ALT_E_SUCCESS Indicates successful completion. + * \retval ALT_E_ERROR Indicates an error occurred. + */ +ALT_STATUS_CODE alt_qspi_mode_bit_disable(void); + +/******************************************************************************/ +/*! + * Enable the mode bits to be sent after the address bytes. + * + * Ensure the mode bits defined in the Mode Bit Configuration register to + * be sent following the address bytes. + * + * \retval ALT_E_SUCCESS Indicates successful completion. + * \retval ALT_E_ERROR Indicates an error occurred. + */ +ALT_STATUS_CODE alt_qspi_mode_bit_enable(void); + +/******************************************************************************/ +/*! + * Get the current value of the Mode Bit Configuration register. + * + * \returns The 8 bit value that is sent to the device following the address + * bytes when the mode bit is enabled (see: alt_qspi_mode_bit_enable()) + */ +uint32_t alt_qspi_mode_bit_config_get(void); + +/******************************************************************************/ +/*! + * Set the value of the Mode Bit Configuration register. + * + * Set the value of the 8 bits that are sent to the device following the address + * bytes when the mode bit is enabled (see: alt_qspi_mode_bit_enable()) + * + * This API requires that the QSPI controller be idle, as determined by + * alt_qspi_is_idle(). + * + * \param mode_bits + * The 8 bit value sent to the device following the address bytes. + * + * \retval ALT_E_SUCCESS Indicates successful completion. + * \retval ALT_E_ERROR Indicates an error occurred. + */ +ALT_STATUS_CODE alt_qspi_mode_bit_config_set(const uint32_t mode_bits); + +/******************************************************************************/ +/*! + * Get the current flash device size and write protection configuration. + * + * \param cfg + * [out] Pointer to a ALT_QSPI_DEV_SIZE_CONFIG_t structure to + * contain the returned flash device size and write protection + * configuration. + * + * \retval ALT_E_SUCCESS Indicates successful completion. + * \retval ALT_E_ERROR Indicates an error occurred. + */ +ALT_STATUS_CODE alt_qspi_device_size_config_get(ALT_QSPI_DEV_SIZE_CONFIG_t * cfg); + +/******************************************************************************/ +/*! + * Set the flash device size and write protection configuration. + * + * \param cfg + * Pointer to a ALT_QSPI_DEV_SIZE_CONFIG_t structure containing the + * flash device size and write protection configuration. + * + * \retval ALT_E_SUCCESS Indicates successful completion. + * \retval ALT_E_ERROR Indicates an error occurred. + */ +ALT_STATUS_CODE alt_qspi_device_size_config_set(const ALT_QSPI_DEV_SIZE_CONFIG_t * cfg); + +/******************************************************************************/ +/*! + * Get the current QSPI device read instruction configuration. + * + * \param cfg + * [out] Pointer to a ALT_QSPI_DEV_INST_CONFIG_t structure to + * contain the returned QSPI controller instruction configuration + * used when performing read transactions with the device. + * + * \retval ALT_E_SUCCESS Indicates successful completion. + * \retval ALT_E_ERROR Indicates an error occurred. + */ +ALT_STATUS_CODE alt_qspi_device_read_config_get(ALT_QSPI_DEV_INST_CONFIG_t * cfg); + +/******************************************************************************/ +/*! + * Set the QSPI device read instruction configuration. + * + * This API requires that the QSPI controller be idle, as determined by + * alt_qspi_is_idle(). + * + * \param cfg + * Pointer to a ALT_QSPI_DEV_INST_CONFIG_t structure specifying the + * desired op code, transfer widths, and dummy cycles for the QSPI + * controller to use when performing read transactions with the + * device. + * + * \retval ALT_E_SUCCESS Indicates successful completion. + * \retval ALT_E_ERROR Indicates an error occurred. + */ +ALT_STATUS_CODE alt_qspi_device_read_config_set(const ALT_QSPI_DEV_INST_CONFIG_t * cfg); + +/******************************************************************************/ +/*! + * Get the current QSPI device write instruction configuration. + * + * \param cfg + * [out] Pointer to a ALT_QSPI_DEV_INST_CONFIG_t structure to + * contain the returned QSPI controller instruction configuration + * used when performing write transactions with the device. + * + * \retval ALT_E_SUCCESS Indicates successful completion. + * \retval ALT_E_ERROR Indicates an error occurred. + */ +ALT_STATUS_CODE alt_qspi_device_write_config_get(ALT_QSPI_DEV_INST_CONFIG_t * cfg); + +/******************************************************************************/ +/*! + * Set the QSPI device write instruction configuration. + * + * This API requires that the QSPI controller be idle, as determined by + * alt_qspi_is_idle(). + * + * \param cfg + * Pointer to a ALT_QSPI_DEV_INST_CONFIG_t structure specifying the + * desired op code, transfer widths, and dummy cycles for the QSPI + * controller to use when performing write transactions with the + * device. + * + * \retval ALT_E_SUCCESS Indicates successful completion. + * \retval ALT_E_ERROR Indicates an error occurred. + */ +ALT_STATUS_CODE alt_qspi_device_write_config_set(const ALT_QSPI_DEV_INST_CONFIG_t * cfg); + +/******************************************************************************/ +/*! + * Get the QSPI device delay and timing configuration parameters. + * + * This function returns the settings of the chip select delay and timing + * configurations. + * + * \param cfg + * [out] Pointer to a ALT_QSPI_TIMING_CONFIG_t structure to return + * the device timing and delay settings. + * + * \retval ALT_E_SUCCESS Indicates successful completion. + * \retval ALT_E_ERROR Indicates an error occurred. + */ +ALT_STATUS_CODE alt_qspi_timing_config_get(ALT_QSPI_TIMING_CONFIG_t * cfg); + +/******************************************************************************/ +/*! + * Set the QSPI device delay and timing configuration parameters. + * + * This function allows the user to configure how the chip select is driven + * after each flash access. This is required as each device may have different + * timing requirements. As the serial clock frequency is increased, these + * timing parameters become more important and can be adjusted to meet the + * requirements of a specific flash device. All timings are defined in cycles + * of the SPI master ref clock. + * + * This API requires that the QSPI controller be idle, as determined by + * alt_qspi_is_idle(). + * + * \param cfg + * Pointer to a ALT_QSPI_TIMING_CONFIG_t structure specifying the + * desired timing and delay settings. + * + * \retval ALT_E_SUCCESS Indicates successful completion. + * \retval ALT_E_ERROR Indicates an error occurred. + */ +ALT_STATUS_CODE alt_qspi_timing_config_set(const ALT_QSPI_TIMING_CONFIG_t * cfg); + +/*! @} */ + +/******************************************************************************/ +/*! \addtogroup ALT_QSPI_DAC Direct Access Mode + * + * In direct access mode, an access to the AHB data slave triggers a read or + * write command to the flash memory. To use the direct access mode, enable the + * direct access controller with the alt_qspi_direct_enable() function. An + * external master, for example a processor, triggers the direct access + * controller with a read or write operation to the AHB data slave + * interface. The data slave exposes a 1MB window into the flash device. You can + * remap this window to any 1MB location within the flash device address range. + * + * To remap the AHB data slave to access other 1MB regions of the flash device, + * enable address remapping by calling alt_qspi_ahb_address_remap_enable(). All + * incoming data slave accesses remap to the offset specified in the remap + * address register which is configured by alt_qspi_ahb_remap_address_set(). + * + * The 20 LSBs of incoming addresses are used for accessing the 1MB region and + * the higher bits are ignored. + * + * The quad SPI controller does not issue any error status for accesses that lie + * outside the connected flash memory space. + * + * @{ + */ + +/******************************************************************************/ +/*! + * Disable the QSPI Direct Access Controller. + * + * \retval ALT_E_SUCCESS Indicates successful completion. + * \retval ALT_E_ERROR Indicates an error occurred. + */ +ALT_STATUS_CODE alt_qspi_direct_disable(void); + +/******************************************************************************/ +/*! + * Enable the QSPI Direct Access Controller. + * + * \retval ALT_E_SUCCESS Indicates successful completion. + * \retval ALT_E_ERROR Indicates an error occurred. + */ +ALT_STATUS_CODE alt_qspi_direct_enable(void); + +/******************************************************************************/ +/*! + * Get the current AHB address remap value. + * + * Returns the current value of the AHB remap address register. + * + * \returns The value used to remap an incoming AHB address to a + * different address used by the flash device. + */ +uint32_t alt_qspi_ahb_remap_address_get(void); + +/******************************************************************************/ +/*! + * Set the AHB address remap value. + * + * Sets the value of the AHB remap address register. + * + * This API requires that the QSPI controller be idle, as determined by + * alt_qspi_is_idle(). + * + * \param ahb_remap_addr + * The value used to remap an incoming AHB address to a different + * address used by the flash device. + * + * \retval ALT_E_SUCCESS Indicates successful completion. + * \retval ALT_E_ERROR Indicates an error occurred. + */ +ALT_STATUS_CODE alt_qspi_ahb_remap_address_set(const uint32_t ahb_remap_addr); + +/******************************************************************************/ +/*! + * Disable AHB address remapping. + * + * Disables remapping of incoming AHB addresses so they are sent unmodified to + * the flash device. The incoming AHB address maps directly to the address + * serially sent to the flash device. + * + * \retval ALT_E_SUCCESS Indicates successful completion. + * \retval ALT_E_ERROR Indicates an error occurred. + */ +ALT_STATUS_CODE alt_qspi_ahb_address_remap_disable(void); + +/******************************************************************************/ +/*! + * Enable AHB address remapping. + * + * Enables remapping of incoming AHB addresses so they are modified to + * \ + \e N, where \e N is the configured remap address value. + * + * See: alt_qspi_ahb_remap_address_set(). + * + * \retval ALT_E_SUCCESS Indicates successful completion. + * \retval ALT_E_ERROR Indicates an error occurred. + */ +ALT_STATUS_CODE alt_qspi_ahb_address_remap_enable(void); + +/*! @} */ + +/******************************************************************************/ +/*! \addtogroup ALT_QSPI_INDAC Indirect Access Mode + * + * In indirect access mode, flash data is temporarily buffered in the QSPI + * controller's SRAM. Software controls and triggers indirect accesses through + * the APB register slave interface. The controller transfers data through the + * AHB data slave interface. + * + * An indirect read operation reads data from the flash memory, places the data + * into the SRAM, and transfers the data to an external master through the AHB + * data slave interface. + * + * An indirect write operation programs data from the SRAM to the flash memory. + * + * @{ + */ + +/******************************************************************************/ +/*! + * Starts an indirect read transfer. + * + * Initiates an indirect read transfer of the requested number of bytes from the + * designated flash address. + * + * After calling this function, flash data may be read from the QSPI SRAM buffer + * as it becomes available via one of the following methods: + * * Directly from the AHB data slave interface at the configured AHB trigger + * address. If the requested data is not immediately available in the SRAM + * buffer then AHB wait states will be applied until the data has been read + * from flash into the SRAM buffer. Alternatively, data may be read from the + * AHB data slave as the SRAM is filled. The availability of data in the SRAM + * buffer may be determined by an SRAM watermark interrupt notification or by + * polling the SRAM fill level. + * * Configuring and enabling the QSPI DMA peripheral controller. + * + * The following is a list of restrictions: + * * flash_addr must be word aligned. + * * num_bytes must be word aligned. + * * The transfer must not cross the 3-byte addressing boundary. This + * restriction may be device specific and may be lifted in the future. + * + * \param flash_addr + * The flash source address to read data from. + * + * \param num_bytes + * The number of bytes to read from the flash source address. + * + * \retval ALT_E_SUCCESS Indicates successful completion. + * \retval ALT_E_ERROR Indicates an error occurred. + */ +ALT_STATUS_CODE alt_qspi_indirect_read_start(const uint32_t flash_addr, + const size_t num_bytes); + +/******************************************************************************/ +/*! + * Finish the indirect read operation that was completed or canceled. This + * function should be called before another indirect read is started. + * + * \retval ALT_E_SUCCESS Indicates successful completion. + * \retval ALT_E_ERROR Indicates an error occurred. + */ +ALT_STATUS_CODE alt_qspi_indirect_read_finish(void); + +/******************************************************************************/ +/*! + * Cancel all indirect read transfers in progress. + * + * \retval ALT_E_SUCCESS Indicates successful completion. + * \retval ALT_E_ERROR Indicates an error occurred. + */ +ALT_STATUS_CODE alt_qspi_indirect_read_cancel(void); + +/******************************************************************************/ +/*! + * Get the current indirect read SRAM fill level value. + * + * Returns the SRAM fill level for the indirect read partition in units of SRAM + * words (4 bytes). + * + * \returns The SRAM fill level for the indirect read partition in units of + * SRAM words (4 bytes). + */ +uint32_t alt_qspi_indirect_read_fill_level(void); + +/******************************************************************************/ +/*! + * Get the current indirect read watermark value. + * + * The watermark value (in bytes) represents the minimum fill level of the SRAM + * before a DMA peripheral access is permitted. When the SRAM fill level passes + * the watermark, an interrupt source is also generated. This can be disabled by + * writing a value of all zeroes. + * + * \returns The current indirect read watermark value. + */ +uint32_t alt_qspi_indirect_read_watermark_get(void); + +/******************************************************************************/ +/*! + * Set the indirect read watermark value. + * + * The watermark value (in bytes) represents the minimum fill level of the SRAM + * before a DMA peripheral access is permitted. When the SRAM fill level passes + * the watermark, an interrupt source is also generated. This can be disabled by + * writing a value of all zeroes. The watermark can only be set when no indirect + * read is in progress. + * + * \param watermark + * The watermark value (in bytes). + * + * \retval ALT_E_SUCCESS Indicates successful completion. + * \retval ALT_E_ERROR Indicates an error occurred. + */ +ALT_STATUS_CODE alt_qspi_indirect_read_watermark_set(const uint32_t watermark); + +/******************************************************************************/ +/*! + * Returns true when an indirect read has completed otherwise false. + * + * \internal + * Returns Indirect Read Transfer Control Register bit 5 "Indirect Completion Status". + * \endinternal + * + * \returns Returns true when an indirect read has completed otherwise false. + */ +bool alt_qspi_indirect_read_is_complete(void); + +/******************************************************************************/ +/*! + * Starts an indirect write transfer. + * + * Initiates an indirect write transfer of the requested number of bytes to the + * designated flash address. + * + * After calling this function, flash data may be written to the QSPI SRAM + * buffer there is space via one of the following methods: + * * Directly from the AHB data slave interface at the configured AHB trigger + * address. If the requested space is not immediately available in the SRAM + * buffer then AHB wait states will be applied until the space becomes + * available. Alternatively, the data may be written to the AHB data slave + * as the SRAM is drained. The space in the SRAM buffer may be determined by + * an SRAM watermark interrupt notification or by polling the SRAM fill + * level and subtracting that value from the SRAM space devoted to writes. + * * Configuring and enabling the QSPI DMA peripheral controller. + * + * The following is a list of restrictions: + * * flash_addr must be word aligned. + * * num_bytes must be word aligned. + * * num_bytes must be 256 or below. This is due to a device specific + * limitation and may be lifted in the future. + * * The transfer must not cross the page (256 byte) addressing boundary. This + * restriction may be device specific and may be lifted in the future. + * + * \param flash_addr + * The flash destination address to write data to. + * + * \param num_bytes + * The number of bytes to write to the flash. + * + * \retval ALT_E_SUCCESS Indicates successful completion. + * \retval ALT_E_ERROR Indicates an error occurred. + */ +ALT_STATUS_CODE alt_qspi_indirect_write_start(const uint32_t flash_addr, + const size_t num_bytes); + +/******************************************************************************/ +/*! + * Finish the indirect write operation that was completed or canceled. This + * function should be called before another indirect write is started. + * + * \retval ALT_E_SUCCESS Indicates successful completion. + * \retval ALT_E_ERROR Indicates an error occurred. + */ +ALT_STATUS_CODE alt_qspi_indirect_write_finish(void); + +/******************************************************************************/ +/*! + * Cancel all indirect write transfers in progress. + * + * \retval ALT_E_SUCCESS Indicates successful completion. + * \retval ALT_E_ERROR Indicates an error occurred. + */ +ALT_STATUS_CODE alt_qspi_indirect_write_cancel(void); + +/******************************************************************************/ +/*! + * Get the current indirect write SRAM fill level value. + * + * Returns the SRAM fill level for the indirect write partition in units of SRAM + * words (4 bytes). + * + * \returns The SRAM fill level for the indirect write partition in units of + * SRAM words (4 bytes). + */ +uint32_t alt_qspi_indirect_write_fill_level(void); + +/******************************************************************************/ +/*! + * Get the current indirect write watermark value. + * + * The watermark value (in bytes) represents the maximum fill level of the SRAM + * before a DMA peripheral access is permitted. When the SRAM fill level falls + * below the watermark, an interrupt is also generated. This can be disabled by + * writing a value of all ones. + * + * \returns The current indirect write watermark value. + */ +uint32_t alt_qspi_indirect_write_watermark_get(void); + +/******************************************************************************/ +/*! + * Set the indirect write watermark value. + * + * The watermark value (in bytes) represents the maximum fill level of the SRAM + * before a DMA peripheral access is permitted. When the SRAM fill level falls + * below the watermark, an interrupt is also generated. This can be disabled by + * writing a value of all ones. The watermark can only be set when no indirect + * write is in progress. + * + * \param watermark + * The watermark value (in bytes). + * + * \retval ALT_E_SUCCESS Indicates successful completion. + * \retval ALT_E_ERROR Indicates an error occurred. + */ +ALT_STATUS_CODE alt_qspi_indirect_write_watermark_set(const uint32_t watermark); + +/******************************************************************************/ +/*! + * Returns true when an indirect write has completed otherwise false. + * + * \internal + * Returns Indirect Write Transfer Control Register bit 5 "Indirect Completion + * Status". + * \endinternal + * + * \returns Returns true when an indirect write has completed otherwise + * false. + */ +bool alt_qspi_indirect_write_is_complete(void); + +/******************************************************************************/ +/*! \addtogroup ALT_QSPI_CFG_SRAM SRAM Partition + * + * The SRAM local memory buffer is a 128 by 32-bit (512 total bytes) memory. The + * SRAM has two partitions, with the lower partition reserved for indirect read + * operations and the upper partition for indirect write operations. The size of + * the partitions is specified in the SRAM partition register, based on 32-bit + * word sizes. For example, to specify four bytes of storage, write the value 1. + * The value written to the indirect read partition size field ( addr ) defines + * the number of entries reserved for indirect read operations. For example, write + * the value 32 (0x20) to partition the 128-entry SRAM to 32 entries (25%) for + * read usage and 96 entries (75%) for write usage. + * + * The functions in this section provide accces to configure the SRAM read + * partition allocation. + * + * @{ + */ + +/*! + * The size of the onboard SRAM in bytes. + */ +#define ALT_QSPI_SRAM_FIFO_SIZE (512) + +/* + * The size of the onboard SRAM in entries. Each entry is word (32-bit) sized. + */ +#define ALT_QSPI_SRAM_FIFO_ENTRY_COUNT (512 / sizeof(uint32_t)) + +/******************************************************************************/ +/*! + * Get the entry count (words) of the indirect read partition in the QSPI + * controller SRAM. + * + * There is an additional word of read memory not in the SRAM but used to + * buffer the SRAM and the AHB. As such, the total on board memory buffer for + * indirect read is 1 more than the value reported by this function. + * + * \returns The count of 32-bit words of the indirect read partition in the + * QSPI controller SRAM. + * + * \internal + * The documentation states that the number of locations allocated to indirect + * read = SRAM_PARTITION_REG + 1. Cadence clarified that the +1 comes from an + * additional register slice for read's, implemented in FLOPs, which was done + * to avoid connection the SRAM directly to the AHB interface. This was done + * for performance / timing reasons. The +1 will not be included in the return + * value but documented as an additional entry. + * \endinternal + */ +uint32_t alt_qspi_sram_partition_get(void); + +/******************************************************************************/ +/*! + * Set the entry count (words) of the indirect read partition in the QSPI + * controller SRAM. + * + * Note: It is recommended that setting SRAM partition to 0 or 127 should be + * avoided although it is not prohibited. + * + * \param read_part_size + * The count of 32-bit words to allocate to the indirect read + * partition in the QSPI controller SRAM. + * + * \retval ALT_E_SUCCESS Indicates successful completion. + * \retval ALT_E_ERROR Indicates an error occurred. + */ +ALT_STATUS_CODE alt_qspi_sram_partition_set(const uint32_t read_part_size); + +/*! @} */ + +/*! @} */ + +/******************************************************************************/ +/*! \addtogroup ALT_QSPI_ERASE Flash Erase + * + * The functions in this group are used to erase selected portions of a flash + * device. + * @{ + */ + +/******************************************************************************/ +/*! + * This function erases the designated flash device subsector. + * + * This function erases the flash device subsector containing the designated + * flash address. Any address within the subsector is valid. + * + * \param addr + * A flash address contained within the the subsector to be erased. + * + * \retval ALT_E_SUCCESS Indicates successful completion. + * \retval ALT_E_ERROR Indicates an error occurred. + */ +ALT_STATUS_CODE alt_qspi_erase_subsector(const uint32_t addr); + +/******************************************************************************/ +/*! + * This function erases the designated flash device sector. + * + * This function erases the flash device sector containing the designated flash + * address. Any address within the sector is valid. + * + * \param addr + * A flash address contained within the the sector to be erased. + * + * \retval ALT_E_SUCCESS Indicates successful completion. + * \retval ALT_E_ERROR Indicates an error occurred. + */ +ALT_STATUS_CODE alt_qspi_erase_sector(const uint32_t addr); + +/******************************************************************************/ +/*! + * This function erases the entire flash device. + * + * \retval ALT_E_SUCCESS Indicates successful completion. + * \retval ALT_E_ERROR Indicates an error occurred. + */ +ALT_STATUS_CODE alt_qspi_erase_chip(void); + +/*! @} */ + +/******************************************************************************/ +/*! \addtogroup ALT_QSPI_DMA DMA Peripheral Interface + * + * The DMA peripheral request controller is only used for the indirect mode of + * operation where data is temporarily stored in the SRAM. The QSPI flash + * controller uses the DMA peripheral request interface to trigger the external + * DMA into performing data transfers between memory and the QSPI + * controller. + * + * There are two DMA peripheral request interfaces, one for indirect reads and + * one for indirect writes. The DMA peripheral request controller can issue two + * types of DMA requests, single or burst, to the external DMA. The number of + * bytes for each single or burst request is specified using the + * alt_qspi_dma_config_set(). The DMA peripheral request controller splits the + * total amount of data to be transferred into a number of DMA burst and single + * requests by dividing the total number of bytes by the number of bytes + * specified in the burst request, and then dividing the remainder by the number + * of bytes in a single request. + * + * When programming the DMA controller, the burst request size must match the + * burst request size set in the quad SPI controller to avoid quickly reaching + * an overflow or underflow condition. + * @{ + */ + +/******************************************************************************/ +/*! + * Disable the QSPI DMA peripheral interface. + * + * \retval ALT_E_SUCCESS Indicates successful completion. + * \retval ALT_E_ERROR Indicates an error occurred. + */ +ALT_STATUS_CODE alt_qspi_dma_disable(void); + +/******************************************************************************/ +/*! + * Enable the QSPI DMA peripheral interface. + * + * Enable the QSPI DMA handshaking logic. When enabled the QSPI will trigger DMA + * transfer requests via the DMA peripheral interface. + * + * \retval ALT_E_SUCCESS Indicates successful completion. + * \retval ALT_E_ERROR Indicates an error occurred. + */ +ALT_STATUS_CODE alt_qspi_dma_enable(void); + +/******************************************************************************/ +/*! + * Get the current DMA peripheral configuration. + * + * This function returns the QSPI DMA peripheral interface single and burst type + * transfer size configurations. + * + * \param single_type_sz + * [out] The number of bytes for each DMA single type + * request. Value must be a power of 2 between 1 and 32728. + * + * \param burst_type_sz + * [out] The number of bytes for each DMA burst type request. Value + * must be a power of 2 between 1 and 32728. + * + * \retval ALT_E_SUCCESS Indicates successful completion. + * \retval ALT_E_ERROR Indicates an error occurred. + */ +ALT_STATUS_CODE alt_qspi_dma_config_get(uint32_t * single_type_sz, + uint32_t * burst_type_sz); + +/******************************************************************************/ +/*! + * Set the DMA peripheral configuration. + * + * This function configures the QSPI DMA peripheral interface single and burst + * type transfer sizes. The DMA configruation should be setup while the + * controller is idle. Because all transfers are required to be word aligned, + * the smallest DMA request is 4 bytes. + * + * This API requires that the QSPI controller be idle, as determined by + * alt_qspi_is_idle(). + * + * \param single_type_sz + * The number of bytes for each DMA single type request. Value must + * be a power of 2 between 4 and 32768. + * + * \param burst_type_sz + * The number of bytes for each DMA burst type request. Value must + * be a power of 2 between 4 and 32768. Bursts must be equal or + * larger than single requests. + * + * \retval ALT_E_SUCCESS Indicates successful completion. + * \retval ALT_E_ERROR Indicates an error occurred. + */ +ALT_STATUS_CODE alt_qspi_dma_config_set(const uint32_t single_type_sz, + const uint32_t burst_type_sz); + + +/*! @} */ + +/*! @} */ + +#ifdef __cplusplus +} +#endif /* __cplusplus */ +#endif /* __ALT_QSPI_H__ */ diff --git a/c/src/lib/libbsp/arm/altera-cyclone-v/hwlib/include/alt_qspi_private.h b/c/src/lib/libbsp/arm/altera-cyclone-v/hwlib/include/alt_qspi_private.h new file mode 100644 index 0000000000..21fd3a957d --- /dev/null +++ b/c/src/lib/libbsp/arm/altera-cyclone-v/hwlib/include/alt_qspi_private.h @@ -0,0 +1,167 @@ +/****************************************************************************** + * + * Copyright 2013 Altera Corporation. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED. IN NO + * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + ******************************************************************************/ + +/*! \file + * Altera - QSPI Flash Controller Module + */ + +#ifndef __ALT_QSPI_PRIVATE_H__ +#define __ALT_QSPI_PRIVATE_H__ + +#include "socal/socal.h" + +// +// This section provisions support for various flash devices. +// + +#define ALT_QSPI_PROVISION_MICRON_N25Q_SUPPORT 1 + +///// + +#define ALT_QSPI_PAGE_ADDR_MSK 0xFFFFFF00 +#define ALT_QSPI_PAGE_SIZE 0x00000100 // 256 B +#define ALT_QSPI_SUBSECTOR_ADDR_MSK 0xFFFFF000 +#define ALT_QSPI_SUBSECTOR_SIZE 0x00001000 // 4096 B +#define ALT_QSPI_SECTOR_ADDR_MSK 0xFFFF0000 +#define ALT_QSPI_SECTOR_SIZE 0x00010000 // 64 KiB +#define ALT_QSPI_BANK_ADDR_MSK 0xFF000000 +#define ALT_QSPI_BANK_SIZE 0x01000000 // 16 MiB + +#if ALT_QSPI_PROVISION_MICRON_N25Q_SUPPORT +#define ALT_QSPI_N25Q_DIE_ADDR_MSK 0xFE000000 +#define ALT_QSPI_N25Q_DIE_SIZE 0x02000000 // 32 MiB +#endif + +///// + +// Default delay timing (in ns) for N25Q. +// These values are from the N25Q handbook. The timing correctness is difficult +// to test because the test setup does not feature mutliple chips. +#define ALT_QSPI_TSHSL_NS_DEF (50) +#define ALT_QSPI_TSD2D_NS_DEF (0) +#define ALT_QSPI_TCHSH_NS_DEF (4) +#define ALT_QSPI_TSLCH_NS_DEF (4) + +/* +// Default delay timing (in ns) +#define ALT_QSPI_TSHSL_NS_DEF (200) +#define ALT_QSPI_TSD2D_NS_DEF (255) +#define ALT_QSPI_TCHSH_NS_DEF (20) +#define ALT_QSPI_TSLCH_NS_DEF (20) +*/ + +// Flash commands +#define ALT_QSPI_STIG_OPCODE_READ (0x03) +#define ALT_QSPI_STIG_OPCODE_4BYTE_READ (0x13) +#define ALT_QSPI_STIG_OPCODE_FASTREAD (0x0B) +#define ALT_QSPI_STIG_OPCODE_FASTREAD_DUAL_OUTPUT (0x3B) +#define ALT_QSPI_STIG_OPCODE_FASTREAD_QUAD_OUTPUT (0x6B) +#define ALT_QSPI_STIG_OPCODE_FASTREAD_DUAL_IO (0xBB) +#define ALT_QSPI_STIG_OPCODE_FASTREAD_QUAD_IO (0xEB) +#define ALT_QSPI_STIG_OPCODE_PP (0x02) +#define ALT_QSPI_STIG_OPCODE_DUAL_PP (0xA2) +#define ALT_QSPI_STIG_OPCODE_QUAD_PP (0x32) +#define ALT_QSPI_STIG_OPCODE_RDID (0x9F) +#define ALT_QSPI_STIG_OPCODE_WREN (0x06) +#define ALT_QSPI_STIG_OPCODE_WRDIS (0x04) +#define ALT_QSPI_STIG_OPCODE_RDSR (0x05) +#define ALT_QSPI_STIG_OPCODE_WRSR (0x01) +#define ALT_QSPI_STIG_OPCODE_SUBSEC_ERASE (0x20) +#define ALT_QSPI_STIG_OPCODE_SEC_ERASE (0xD8) +#define ALT_QSPI_STIG_OPCODE_BULK_ERASE (0xC7) +#define ALT_QSPI_STIG_OPCODE_DIE_ERASE (0xC4) +#define ALT_QSPI_STIG_OPCODE_CHIP_ERASE (0x60) +#define ALT_QSPI_STIG_OPCODE_RD_EXT_REG (0xC8) +#define ALT_QSPI_STIG_OPCODE_WR_EXT_REG (0xC5) +#define ALT_QSPI_STIG_OPCODE_RD_STAT_REG (0x05) +#define ALT_QSPI_STIG_OPCODE_WR_STAT_REG (0x01) +#define ALT_QSPI_STIG_OPCODE_ENTER_4BYTE_MODE (0xB7) +#define ALT_QSPI_STIG_OPCODE_EXIT_4BYTE_MODE (0xE9) + +// Micron commands, for 512 Mib, 1 Gib (64 MiB, 128 MiB) parts. +#if ALT_QSPI_PROVISION_MICRON_N25Q_SUPPORT +#define ALT_QSPI_STIG_OPCODE_RESET_EN (0x66) +#define ALT_QSPI_STIG_OPCODE_RESET_MEM (0x99) +#define ALT_QSPI_STIG_OPCODE_RDFLGSR (0x70) +#define ALT_QSPI_STIG_OPCODE_CLRFLGSR (0x50) +#define ALT_QSPI_STIG_OPCODE_DISCVR_PARAM (0x5A) +#endif + +// Spansion commands +// #define OPCODE_ECRM (0xFF) // Exit continuous read mode + +#define QSPI_READ_CLK_MHZ (50) +#define QSPI_FASTREAD_CLK_MHZ (100) + +// Manufacturer ID +#define ALT_QSPI_STIG_RDID_JEDECID_MICRON (0x20) +#define ALT_QSPI_STIG_RDID_JEDECID_NUMONYX (0x20) // Same as Micron +#define ALT_QSPI_STIG_RDID_JEDECID_SPANSION (0xEF) +#define ALT_QSPI_STIG_RDID_JEDECID_WINBOND (0xEF) // Same as Spansion +#define ALT_QSPI_STIG_RDID_JEDECID_MACRONIC (0xC2) +#define ALT_QSPI_STIG_RDID_JEDECID_ATMEL (0x1F) + +#define ALT_QSPI_STIG_RDID_JEDECID_GET(value) ((value >> 0) & 0xff) +#define ALT_QSPI_STIG_RDID_CAPACITYID_GET(value) ((value >> 16) & 0xff) + +#define ALT_QSPI_STIG_FLAGSR_ERASEPROGRAMREADY_GET(value) ((value >> 7) & 0x1) +#define ALT_QSPI_STIG_FLAGSR_ERASEREADY_GET(value) ((value >> 7) & 0x1) +#define ALT_QSPI_STIG_FLAGSR_PROGRAMREADY_GET(value) ((value >> 7) & 0x1) +#define ALT_QSPI_STIG_FLAGSR_ERASEERROR_GET(value) ((value >> 5) & 0x1) +#define ALT_QSPI_STIG_FLAGSR_PROGRAMERROR_GET(value) ((value >> 4) & 0x1) +#define ALT_QSPI_STIG_FLAGSR_ADDRESSINGMODE_GET(value) ((value >> 1) & 0x1) +#define ALT_QSPI_STIG_FLAGSR_PROTECTIONERROR_GET(value) ((value >> 0) & 0x1) + +#define ALT_QSPI_STIG_SR_BUSY_GET(value) ((value >> 0) & 0x1) + +///// + +#define ALT_QSPI_TIMEOUT_INFINITE (0xffffffff) + +ALT_STATUS_CODE alt_qspi_replace(uint32_t dst, const void * src, size_t size); + +ALT_STATUS_CODE alt_qspi_stig_cmd(uint32_t opcode, uint32_t dummy, uint32_t timeout); +ALT_STATUS_CODE alt_qspi_stig_rd_cmd(uint8_t opcode, uint32_t dummy, + uint32_t num_bytes, uint32_t * output, + uint32_t timeout); +ALT_STATUS_CODE alt_qspi_stig_wr_cmd(uint8_t opcode, uint32_t dummy, + uint32_t num_bytes, const uint32_t * input, + uint32_t timeout); +ALT_STATUS_CODE alt_qspi_stig_addr_cmd(uint8_t opcode, uint32_t dummy, + uint32_t address, + uint32_t timeout); + +ALT_STATUS_CODE alt_qspi_device_wren(void); +ALT_STATUS_CODE alt_qspi_device_wrdis(void); +ALT_STATUS_CODE alt_qspi_device_rdid(uint32_t * rdid); +ALT_STATUS_CODE alt_qspi_discovery_parameter(uint32_t * param); +ALT_STATUS_CODE alt_qspi_device_bank_select(uint32_t bank); + +#endif // __ALT_PRIVATE_QSPI_H__ diff --git a/c/src/lib/libbsp/arm/altera-cyclone-v/hwlib/include/socal/alt_dmanonsecure.h b/c/src/lib/libbsp/arm/altera-cyclone-v/hwlib/include/socal/alt_dmanonsecure.h new file mode 100644 index 0000000000..1425708983 --- /dev/null +++ b/c/src/lib/libbsp/arm/altera-cyclone-v/hwlib/include/socal/alt_dmanonsecure.h @@ -0,0 +1,144 @@ +/******************************************************************************* +* * +* Copyright 2013 Altera Corporation. All Rights Reserved. * +* * +* Redistribution and use in source and binary forms, with or without * +* modification, are permitted provided that the following conditions are met: * +* * +* 1. Redistributions of source code must retain the above copyright notice, * +* this list of conditions and the following disclaimer. * +* * +* 2. Redistributions in binary form must reproduce the above copyright notice, * +* this list of conditions and the following disclaimer in the documentation * +* and/or other materials provided with the distribution. * +* * +* 3. The name of the author may not be used to endorse or promote products * +* derived from this software without specific prior written permission. * +* * +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER "AS IS" AND ANY EXPRESS OR * +* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * +* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED. IN NO * +* EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * +* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * +* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; * +* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * +* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR * +* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * +* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * +* * +*******************************************************************************/ + +/* Altera - ALT_DMANONSECURE */ + +#ifndef __ALTERA_ALT_DMANONSECURE_H__ +#define __ALTERA_ALT_DMANONSECURE_H__ + +#ifdef __cplusplus +extern "C" +{ +#endif /* __cplusplus */ + +/* + * Component : nonsecure DMA Module Address Space - ALT_DMANONSECURE + * nonsecure DMA Module Address Space + * + * Address space allocated to the nonsecure DMA. For detailed information about the + * use of this address space, + * [url=http://infocenter.arm.com/help/topic/com.arm.doc.ddi0424b/index.html]click + * here[/url] to access the ARM documentation for the DMA-330. + * + */ +/* + * Register : Empty - reg + * + * Placeholder + * + * Register Layout + * + * Bits | Access | Reset | Description + * :-------|:-------|:--------|:------------ + * [31:0] | RW | Unknown | Empty + * + */ +/* + * Field : Empty - fld + * + * Placeholder + * + * Field Access Macros: + * + */ +/* The Least Significant Bit (LSB) position of the ALT_DMANONSECURE_REG_FLD register field. */ +#define ALT_DMANONSECURE_REG_FLD_LSB 0 +/* The Most Significant Bit (MSB) position of the ALT_DMANONSECURE_REG_FLD register field. */ +#define ALT_DMANONSECURE_REG_FLD_MSB 31 +/* The width in bits of the ALT_DMANONSECURE_REG_FLD register field. */ +#define ALT_DMANONSECURE_REG_FLD_WIDTH 32 +/* The mask used to set the ALT_DMANONSECURE_REG_FLD register field value. */ +#define ALT_DMANONSECURE_REG_FLD_SET_MSK 0xffffffff +/* The mask used to clear the ALT_DMANONSECURE_REG_FLD register field value. */ +#define ALT_DMANONSECURE_REG_FLD_CLR_MSK 0x00000000 +/* The reset value of the ALT_DMANONSECURE_REG_FLD register field is UNKNOWN. */ +#define ALT_DMANONSECURE_REG_FLD_RESET 0x0 +/* Extracts the ALT_DMANONSECURE_REG_FLD field value from a register. */ +#define ALT_DMANONSECURE_REG_FLD_GET(value) (((value) & 0xffffffff) >> 0) +/* Produces a ALT_DMANONSECURE_REG_FLD register field value suitable for setting the register. */ +#define ALT_DMANONSECURE_REG_FLD_SET(value) (((value) << 0) & 0xffffffff) + +#ifndef __ASSEMBLY__ +/* + * WARNING: The C register and register group struct declarations are provided for + * convenience and illustrative purposes. They should, however, be used with + * caution as the C language standard provides no guarantees about the alignment or + * atomicity of device memory accesses. The recommended practice for writing + * hardware drivers is to use the SoCAL access macros and alt_read_word() and + * alt_write_word() functions. + * + * The struct declaration for register ALT_DMANONSECURE_REG. + */ +struct ALT_DMANONSECURE_REG_s +{ + uint32_t fld : 32; /* Empty */ +}; + +/* The typedef declaration for register ALT_DMANONSECURE_REG. */ +typedef volatile struct ALT_DMANONSECURE_REG_s ALT_DMANONSECURE_REG_t; +#endif /* __ASSEMBLY__ */ + +/* The byte offset of the ALT_DMANONSECURE_REG register from the beginning of the component. */ +#define ALT_DMANONSECURE_REG_OFST 0x0 + +#ifndef __ASSEMBLY__ +/* + * WARNING: The C register and register group struct declarations are provided for + * convenience and illustrative purposes. They should, however, be used with + * caution as the C language standard provides no guarantees about the alignment or + * atomicity of device memory accesses. The recommended practice for writing + * hardware drivers is to use the SoCAL access macros and alt_read_word() and + * alt_write_word() functions. + * + * The struct declaration for register group ALT_DMANONSECURE. + */ +struct ALT_DMANONSECURE_s +{ + volatile ALT_DMANONSECURE_REG_t reg; /* ALT_DMANONSECURE_REG */ +}; + +/* The typedef declaration for register group ALT_DMANONSECURE. */ +typedef volatile struct ALT_DMANONSECURE_s ALT_DMANONSECURE_t; +/* The struct declaration for the raw register contents of register group ALT_DMANONSECURE. */ +struct ALT_DMANONSECURE_raw_s +{ + volatile uint32_t reg; /* ALT_DMANONSECURE_REG */ +}; + +/* The typedef declaration for the raw register contents of register group ALT_DMANONSECURE. */ +typedef volatile struct ALT_DMANONSECURE_raw_s ALT_DMANONSECURE_raw_t; +#endif /* __ASSEMBLY__ */ + + +#ifdef __cplusplus +} +#endif /* __cplusplus */ +#endif /* __ALTERA_ALT_DMANONSECURE_H__ */ + diff --git a/c/src/lib/libbsp/arm/altera-cyclone-v/hwlib/include/socal/alt_dmasecure.h b/c/src/lib/libbsp/arm/altera-cyclone-v/hwlib/include/socal/alt_dmasecure.h new file mode 100644 index 0000000000..5941433268 --- /dev/null +++ b/c/src/lib/libbsp/arm/altera-cyclone-v/hwlib/include/socal/alt_dmasecure.h @@ -0,0 +1,144 @@ +/******************************************************************************* +* * +* Copyright 2013 Altera Corporation. All Rights Reserved. * +* * +* Redistribution and use in source and binary forms, with or without * +* modification, are permitted provided that the following conditions are met: * +* * +* 1. Redistributions of source code must retain the above copyright notice, * +* this list of conditions and the following disclaimer. * +* * +* 2. Redistributions in binary form must reproduce the above copyright notice, * +* this list of conditions and the following disclaimer in the documentation * +* and/or other materials provided with the distribution. * +* * +* 3. The name of the author may not be used to endorse or promote products * +* derived from this software without specific prior written permission. * +* * +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER "AS IS" AND ANY EXPRESS OR * +* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * +* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED. IN NO * +* EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * +* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * +* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; * +* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * +* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR * +* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * +* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * +* * +*******************************************************************************/ + +/* Altera - ALT_DMASECURE */ + +#ifndef __ALTERA_ALT_DMASECURE_H__ +#define __ALTERA_ALT_DMASECURE_H__ + +#ifdef __cplusplus +extern "C" +{ +#endif /* __cplusplus */ + +/* + * Component : secure DMA Module Address Space - ALT_DMASECURE + * secure DMA Module Address Space + * + * Address space allocated to the secure DMA. For detailed information about the + * use of this address space, + * [url=http://infocenter.arm.com/help/topic/com.arm.doc.ddi0424b/index.html]click + * here[/url] to access the ARM documentation for the DMA-330. + * + */ +/* + * Register : Empty - reg + * + * Placeholder + * + * Register Layout + * + * Bits | Access | Reset | Description + * :-------|:-------|:--------|:------------ + * [31:0] | RW | Unknown | Empty + * + */ +/* + * Field : Empty - fld + * + * Placeholder + * + * Field Access Macros: + * + */ +/* The Least Significant Bit (LSB) position of the ALT_DMASECURE_REG_FLD register field. */ +#define ALT_DMASECURE_REG_FLD_LSB 0 +/* The Most Significant Bit (MSB) position of the ALT_DMASECURE_REG_FLD register field. */ +#define ALT_DMASECURE_REG_FLD_MSB 31 +/* The width in bits of the ALT_DMASECURE_REG_FLD register field. */ +#define ALT_DMASECURE_REG_FLD_WIDTH 32 +/* The mask used to set the ALT_DMASECURE_REG_FLD register field value. */ +#define ALT_DMASECURE_REG_FLD_SET_MSK 0xffffffff +/* The mask used to clear the ALT_DMASECURE_REG_FLD register field value. */ +#define ALT_DMASECURE_REG_FLD_CLR_MSK 0x00000000 +/* The reset value of the ALT_DMASECURE_REG_FLD register field is UNKNOWN. */ +#define ALT_DMASECURE_REG_FLD_RESET 0x0 +/* Extracts the ALT_DMASECURE_REG_FLD field value from a register. */ +#define ALT_DMASECURE_REG_FLD_GET(value) (((value) & 0xffffffff) >> 0) +/* Produces a ALT_DMASECURE_REG_FLD register field value suitable for setting the register. */ +#define ALT_DMASECURE_REG_FLD_SET(value) (((value) << 0) & 0xffffffff) + +#ifndef __ASSEMBLY__ +/* + * WARNING: The C register and register group struct declarations are provided for + * convenience and illustrative purposes. They should, however, be used with + * caution as the C language standard provides no guarantees about the alignment or + * atomicity of device memory accesses. The recommended practice for writing + * hardware drivers is to use the SoCAL access macros and alt_read_word() and + * alt_write_word() functions. + * + * The struct declaration for register ALT_DMASECURE_REG. + */ +struct ALT_DMASECURE_REG_s +{ + uint32_t fld : 32; /* Empty */ +}; + +/* The typedef declaration for register ALT_DMASECURE_REG. */ +typedef volatile struct ALT_DMASECURE_REG_s ALT_DMASECURE_REG_t; +#endif /* __ASSEMBLY__ */ + +/* The byte offset of the ALT_DMASECURE_REG register from the beginning of the component. */ +#define ALT_DMASECURE_REG_OFST 0x0 + +#ifndef __ASSEMBLY__ +/* + * WARNING: The C register and register group struct declarations are provided for + * convenience and illustrative purposes. They should, however, be used with + * caution as the C language standard provides no guarantees about the alignment or + * atomicity of device memory accesses. The recommended practice for writing + * hardware drivers is to use the SoCAL access macros and alt_read_word() and + * alt_write_word() functions. + * + * The struct declaration for register group ALT_DMASECURE. + */ +struct ALT_DMASECURE_s +{ + volatile ALT_DMASECURE_REG_t reg; /* ALT_DMASECURE_REG */ +}; + +/* The typedef declaration for register group ALT_DMASECURE. */ +typedef volatile struct ALT_DMASECURE_s ALT_DMASECURE_t; +/* The struct declaration for the raw register contents of register group ALT_DMASECURE. */ +struct ALT_DMASECURE_raw_s +{ + volatile uint32_t reg; /* ALT_DMASECURE_REG */ +}; + +/* The typedef declaration for the raw register contents of register group ALT_DMASECURE. */ +typedef volatile struct ALT_DMASECURE_raw_s ALT_DMASECURE_raw_t; +#endif /* __ASSEMBLY__ */ + + +#ifdef __cplusplus +} +#endif /* __cplusplus */ +#endif /* __ALTERA_ALT_DMASECURE_H__ */ + diff --git a/c/src/lib/libbsp/arm/altera-cyclone-v/hwlib/include/socal/alt_qspi.h b/c/src/lib/libbsp/arm/altera-cyclone-v/hwlib/include/socal/alt_qspi.h new file mode 100644 index 0000000000..cbec31b76f --- /dev/null +++ b/c/src/lib/libbsp/arm/altera-cyclone-v/hwlib/include/socal/alt_qspi.h @@ -0,0 +1,5951 @@ +/******************************************************************************* +* * +* Copyright 2013 Altera Corporation. All Rights Reserved. * +* * +* Redistribution and use in source and binary forms, with or without * +* modification, are permitted provided that the following conditions are met: * +* * +* 1. Redistributions of source code must retain the above copyright notice, * +* this list of conditions and the following disclaimer. * +* * +* 2. Redistributions in binary form must reproduce the above copyright notice, * +* this list of conditions and the following disclaimer in the documentation * +* and/or other materials provided with the distribution. * +* * +* 3. The name of the author may not be used to endorse or promote products * +* derived from this software without specific prior written permission. * +* * +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER "AS IS" AND ANY EXPRESS OR * +* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * +* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED. IN NO * +* EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * +* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * +* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; * +* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * +* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR * +* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * +* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * +* * +*******************************************************************************/ + +/* Altera - ALT_QSPI */ + +#ifndef __ALTERA_ALT_QSPI_H__ +#define __ALTERA_ALT_QSPI_H__ + +#ifdef __cplusplus +extern "C" +{ +#endif /* __cplusplus */ + +/* + * Component : QSPI Flash Controller Module Registers - ALT_QSPI + * QSPI Flash Controller Module Registers + * + * Registers in the QSPI Flash Controller module accessible via its APB slave + * + */ +/* + * Register : QSPI Configuration Register - cfg + * + * Register Layout + * + * Bits | Access | Reset | Description + * :--------|:-------|:------|:------------------------------------------- + * [0] | RW | 0x0 | QSPI Enable + * [1] | RW | 0x0 | Clock Polarity + * [2] | RW | 0x0 | Select Clock Phase + * [6:3] | ??? | 0x0 | *UNDEFINED* + * [7] | RW | 0x0 | Enable Direct Access Controller + * [8] | RW | 0x0 | Legacy IP Mode Enable + * [9] | RW | 0x0 | Peripheral select decode + * [13:10] | RW | 0x0 | Peripheral Chip Select Lines + * [14] | RW | 0x0 | Write Protect Flash Pin + * [15] | RW | 0x0 | Enable DMA Peripheral Interface + * [16] | RW | 0x0 | Enable AHB Address Re-mapping + * [17] | RW | 0x0 | Enter XIP Mode on next READ + * [18] | RW | 0x0 | Enter XIP Mode Immediately + * [22:19] | RW | 0xf | Master Mode Baud Rate Divisor + * [30:23] | ??? | 0x0 | *UNDEFINED* + * [31] | R | 0x0 | Serial interface and QSPI pipeline is IDLE + * + */ +/* + * Field : QSPI Enable - en + * + * If this bit is disabled, the QSPI will finish the current transfer of the data + * word (FF_W) and stop sending. When Enabled, and qspi_n_mo_en = 0, all output + * enables are inactive and all pins are set to input mode. + * + * Field Enumeration Values: + * + * Enum | Value | Description + * :----------------------|:------|:----------------- + * ALT_QSPI_CFG_EN_E_DIS | 0x0 | Disable the QSPI + * ALT_QSPI_CFG_EN_E_EN | 0x1 | Enable the QSPI + * + * Field Access Macros: + * + */ +/* + * Enumerated value for register field ALT_QSPI_CFG_EN + * + * Disable the QSPI + */ +#define ALT_QSPI_CFG_EN_E_DIS 0x0 +/* + * Enumerated value for register field ALT_QSPI_CFG_EN + * + * Enable the QSPI + */ +#define ALT_QSPI_CFG_EN_E_EN 0x1 + +/* The Least Significant Bit (LSB) position of the ALT_QSPI_CFG_EN register field. */ +#define ALT_QSPI_CFG_EN_LSB 0 +/* The Most Significant Bit (MSB) position of the ALT_QSPI_CFG_EN register field. */ +#define ALT_QSPI_CFG_EN_MSB 0 +/* The width in bits of the ALT_QSPI_CFG_EN register field. */ +#define ALT_QSPI_CFG_EN_WIDTH 1 +/* The mask used to set the ALT_QSPI_CFG_EN register field value. */ +#define ALT_QSPI_CFG_EN_SET_MSK 0x00000001 +/* The mask used to clear the ALT_QSPI_CFG_EN register field value. */ +#define ALT_QSPI_CFG_EN_CLR_MSK 0xfffffffe +/* The reset value of the ALT_QSPI_CFG_EN register field. */ +#define ALT_QSPI_CFG_EN_RESET 0x0 +/* Extracts the ALT_QSPI_CFG_EN field value from a register. */ +#define ALT_QSPI_CFG_EN_GET(value) (((value) & 0x00000001) >> 0) +/* Produces a ALT_QSPI_CFG_EN register field value suitable for setting the register. */ +#define ALT_QSPI_CFG_EN_SET(value) (((value) << 0) & 0x00000001) + +/* + * Field : Clock Polarity - selclkpol + * + * Controls spiclk modes of operation. + * + * Field Enumeration Values: + * + * Enum | Value | Description + * :------------------------------|:------|:---------------------------- + * ALT_QSPI_CFG_SELCLKPOL_E_LOW | 0x1 | SPI clock is quiescent low + * ALT_QSPI_CFG_SELCLKPOL_E_HIGH | 0x0 | SPI clock is quiescent high + * + * Field Access Macros: + * + */ +/* + * Enumerated value for register field ALT_QSPI_CFG_SELCLKPOL + * + * SPI clock is quiescent low + */ +#define ALT_QSPI_CFG_SELCLKPOL_E_LOW 0x1 +/* + * Enumerated value for register field ALT_QSPI_CFG_SELCLKPOL + * + * SPI clock is quiescent high + */ +#define ALT_QSPI_CFG_SELCLKPOL_E_HIGH 0x0 + +/* The Least Significant Bit (LSB) position of the ALT_QSPI_CFG_SELCLKPOL register field. */ +#define ALT_QSPI_CFG_SELCLKPOL_LSB 1 +/* The Most Significant Bit (MSB) position of the ALT_QSPI_CFG_SELCLKPOL register field. */ +#define ALT_QSPI_CFG_SELCLKPOL_MSB 1 +/* The width in bits of the ALT_QSPI_CFG_SELCLKPOL register field. */ +#define ALT_QSPI_CFG_SELCLKPOL_WIDTH 1 +/* The mask used to set the ALT_QSPI_CFG_SELCLKPOL register field value. */ +#define ALT_QSPI_CFG_SELCLKPOL_SET_MSK 0x00000002 +/* The mask used to clear the ALT_QSPI_CFG_SELCLKPOL register field value. */ +#define ALT_QSPI_CFG_SELCLKPOL_CLR_MSK 0xfffffffd +/* The reset value of the ALT_QSPI_CFG_SELCLKPOL register field. */ +#define ALT_QSPI_CFG_SELCLKPOL_RESET 0x0 +/* Extracts the ALT_QSPI_CFG_SELCLKPOL field value from a register. */ +#define ALT_QSPI_CFG_SELCLKPOL_GET(value) (((value) & 0x00000002) >> 1) +/* Produces a ALT_QSPI_CFG_SELCLKPOL register field value suitable for setting the register. */ +#define ALT_QSPI_CFG_SELCLKPOL_SET(value) (((value) << 1) & 0x00000002) + +/* + * Field : Select Clock Phase - selclkphase + * + * Selects whether the clock is in an active or inactive phase outside the SPI + * word. + * + * Field Enumeration Values: + * + * Enum | Value | Description + * :---------------------------------|:------|:--------------------------- + * ALT_QSPI_CFG_SELCLKPHASE_E_ACT | 0x0 | SPI clock is quiescent low + * ALT_QSPI_CFG_SELCLKPHASE_E_INACT | 0x1 | Clock Inactive + * + * Field Access Macros: + * + */ +/* + * Enumerated value for register field ALT_QSPI_CFG_SELCLKPHASE + * + * SPI clock is quiescent low + */ +#define ALT_QSPI_CFG_SELCLKPHASE_E_ACT 0x0 +/* + * Enumerated value for register field ALT_QSPI_CFG_SELCLKPHASE + * + * Clock Inactive + */ +#define ALT_QSPI_CFG_SELCLKPHASE_E_INACT 0x1 + +/* The Least Significant Bit (LSB) position of the ALT_QSPI_CFG_SELCLKPHASE register field. */ +#define ALT_QSPI_CFG_SELCLKPHASE_LSB 2 +/* The Most Significant Bit (MSB) position of the ALT_QSPI_CFG_SELCLKPHASE register field. */ +#define ALT_QSPI_CFG_SELCLKPHASE_MSB 2 +/* The width in bits of the ALT_QSPI_CFG_SELCLKPHASE register field. */ +#define ALT_QSPI_CFG_SELCLKPHASE_WIDTH 1 +/* The mask used to set the ALT_QSPI_CFG_SELCLKPHASE register field value. */ +#define ALT_QSPI_CFG_SELCLKPHASE_SET_MSK 0x00000004 +/* The mask used to clear the ALT_QSPI_CFG_SELCLKPHASE register field value. */ +#define ALT_QSPI_CFG_SELCLKPHASE_CLR_MSK 0xfffffffb +/* The reset value of the ALT_QSPI_CFG_SELCLKPHASE register field. */ +#define ALT_QSPI_CFG_SELCLKPHASE_RESET 0x0 +/* Extracts the ALT_QSPI_CFG_SELCLKPHASE field value from a register. */ +#define ALT_QSPI_CFG_SELCLKPHASE_GET(value) (((value) & 0x00000004) >> 2) +/* Produces a ALT_QSPI_CFG_SELCLKPHASE register field value suitable for setting the register. */ +#define ALT_QSPI_CFG_SELCLKPHASE_SET(value) (((value) << 2) & 0x00000004) + +/* + * Field : Enable Direct Access Controller - endiracc + * + * If disabled, the Direct Access Controller becomes inactive once the current + * transfer of the data word (FF_W) is complete. When the Direct Access Controller + * and Indirect Access Controller are both disabled, all AHB requests are completed + * with an error response. + * + * Field Enumeration Values: + * + * Enum | Value | Description + * :----------------------------|:------|:--------------------------- + * ALT_QSPI_CFG_ENDIRACC_E_DIS | 0x0 | Disable Direct Access Ctrl + * ALT_QSPI_CFG_ENDIRACC_E_EN | 0x1 | Enable Direct Access Ctrl + * + * Field Access Macros: + * + */ +/* + * Enumerated value for register field ALT_QSPI_CFG_ENDIRACC + * + * Disable Direct Access Ctrl + */ +#define ALT_QSPI_CFG_ENDIRACC_E_DIS 0x0 +/* + * Enumerated value for register field ALT_QSPI_CFG_ENDIRACC + * + * Enable Direct Access Ctrl + */ +#define ALT_QSPI_CFG_ENDIRACC_E_EN 0x1 + +/* The Least Significant Bit (LSB) position of the ALT_QSPI_CFG_ENDIRACC register field. */ +#define ALT_QSPI_CFG_ENDIRACC_LSB 7 +/* The Most Significant Bit (MSB) position of the ALT_QSPI_CFG_ENDIRACC register field. */ +#define ALT_QSPI_CFG_ENDIRACC_MSB 7 +/* The width in bits of the ALT_QSPI_CFG_ENDIRACC register field. */ +#define ALT_QSPI_CFG_ENDIRACC_WIDTH 1 +/* The mask used to set the ALT_QSPI_CFG_ENDIRACC register field value. */ +#define ALT_QSPI_CFG_ENDIRACC_SET_MSK 0x00000080 +/* The mask used to clear the ALT_QSPI_CFG_ENDIRACC register field value. */ +#define ALT_QSPI_CFG_ENDIRACC_CLR_MSK 0xffffff7f +/* The reset value of the ALT_QSPI_CFG_ENDIRACC register field. */ +#define ALT_QSPI_CFG_ENDIRACC_RESET 0x0 +/* Extracts the ALT_QSPI_CFG_ENDIRACC field value from a register. */ +#define ALT_QSPI_CFG_ENDIRACC_GET(value) (((value) & 0x00000080) >> 7) +/* Produces a ALT_QSPI_CFG_ENDIRACC register field value suitable for setting the register. */ +#define ALT_QSPI_CFG_ENDIRACC_SET(value) (((value) << 7) & 0x00000080) + +/* + * Field : Legacy IP Mode Enable - enlegacyip + * + * This bit can select the Direct Access Controller/Indirect Access Controller or + * legacy mode.If legacy mode is selected, any write to the controller via the AHB + * interface is serialized and sent to the FLASH device. Any valid AHB read will + * pop the internal RX-FIFO, retrieving data that was forwarded by the external + * FLASH device on the SPI lines, byte transfers of 4, 2 or 1 are permitted and + * controlled via the HSIZE input. + * + * Field Enumeration Values: + * + * Enum | Value | Description + * :---------------------------------|:------|:-------------------------------------- + * ALT_QSPI_CFG_ENLEGACYIP_E_LEGMOD | 0x1 | Legacy Mode + * ALT_QSPI_CFG_ENLEGACYIP_E_DIMOD | 0x0 | Use Direct/Indirect Access Controller + * + * Field Access Macros: + * + */ +/* + * Enumerated value for register field ALT_QSPI_CFG_ENLEGACYIP + * + * Legacy Mode + */ +#define ALT_QSPI_CFG_ENLEGACYIP_E_LEGMOD 0x1 +/* + * Enumerated value for register field ALT_QSPI_CFG_ENLEGACYIP + * + * Use Direct/Indirect Access Controller + */ +#define ALT_QSPI_CFG_ENLEGACYIP_E_DIMOD 0x0 + +/* The Least Significant Bit (LSB) position of the ALT_QSPI_CFG_ENLEGACYIP register field. */ +#define ALT_QSPI_CFG_ENLEGACYIP_LSB 8 +/* The Most Significant Bit (MSB) position of the ALT_QSPI_CFG_ENLEGACYIP register field. */ +#define ALT_QSPI_CFG_ENLEGACYIP_MSB 8 +/* The width in bits of the ALT_QSPI_CFG_ENLEGACYIP register field. */ +#define ALT_QSPI_CFG_ENLEGACYIP_WIDTH 1 +/* The mask used to set the ALT_QSPI_CFG_ENLEGACYIP register field value. */ +#define ALT_QSPI_CFG_ENLEGACYIP_SET_MSK 0x00000100 +/* The mask used to clear the ALT_QSPI_CFG_ENLEGACYIP register field value. */ +#define ALT_QSPI_CFG_ENLEGACYIP_CLR_MSK 0xfffffeff +/* The reset value of the ALT_QSPI_CFG_ENLEGACYIP register field. */ +#define ALT_QSPI_CFG_ENLEGACYIP_RESET 0x0 +/* Extracts the ALT_QSPI_CFG_ENLEGACYIP field value from a register. */ +#define ALT_QSPI_CFG_ENLEGACYIP_GET(value) (((value) & 0x00000100) >> 8) +/* Produces a ALT_QSPI_CFG_ENLEGACYIP register field value suitable for setting the register. */ +#define ALT_QSPI_CFG_ENLEGACYIP_SET(value) (((value) << 8) & 0x00000100) + +/* + * Field : Peripheral select decode - perseldec + * + * Select between '1 of 4 selects' or 'external 4-to-16 decode'. The + * qspi_n_ss_out[3:0] output signals are controlled. + * + * Field Enumeration Values: + * + * Enum | Value | Description + * :----------------------------------|:------|:---------------------------------- + * ALT_QSPI_CFG_PERSELDEC_E_SEL4TO16 | 0x1 | Select external 4-to-16 decode + * ALT_QSPI_CFG_PERSELDEC_E_SEL1OF4 | 0x0 | Selects 1 of 4 qspi_n_ss_out[3:0] + * + * Field Access Macros: + * + */ +/* + * Enumerated value for register field ALT_QSPI_CFG_PERSELDEC + * + * Select external 4-to-16 decode + */ +#define ALT_QSPI_CFG_PERSELDEC_E_SEL4TO16 0x1 +/* + * Enumerated value for register field ALT_QSPI_CFG_PERSELDEC + * + * Selects 1 of 4 qspi_n_ss_out[3:0] + */ +#define ALT_QSPI_CFG_PERSELDEC_E_SEL1OF4 0x0 + +/* The Least Significant Bit (LSB) position of the ALT_QSPI_CFG_PERSELDEC register field. */ +#define ALT_QSPI_CFG_PERSELDEC_LSB 9 +/* The Most Significant Bit (MSB) position of the ALT_QSPI_CFG_PERSELDEC register field. */ +#define ALT_QSPI_CFG_PERSELDEC_MSB 9 +/* The width in bits of the ALT_QSPI_CFG_PERSELDEC register field. */ +#define ALT_QSPI_CFG_PERSELDEC_WIDTH 1 +/* The mask used to set the ALT_QSPI_CFG_PERSELDEC register field value. */ +#define ALT_QSPI_CFG_PERSELDEC_SET_MSK 0x00000200 +/* The mask used to clear the ALT_QSPI_CFG_PERSELDEC register field value. */ +#define ALT_QSPI_CFG_PERSELDEC_CLR_MSK 0xfffffdff +/* The reset value of the ALT_QSPI_CFG_PERSELDEC register field. */ +#define ALT_QSPI_CFG_PERSELDEC_RESET 0x0 +/* Extracts the ALT_QSPI_CFG_PERSELDEC field value from a register. */ +#define ALT_QSPI_CFG_PERSELDEC_GET(value) (((value) & 0x00000200) >> 9) +/* Produces a ALT_QSPI_CFG_PERSELDEC register field value suitable for setting the register. */ +#define ALT_QSPI_CFG_PERSELDEC_SET(value) (((value) << 9) & 0x00000200) + +/* + * Field : Peripheral Chip Select Lines - percslines + * + * Peripheral chip select line output decode type. As per perseldec, if perseldec = + * 0, the decode is select 1 of 4 decoding on signals, qspi_n_ss_out[3:0], The + * asserted decode line goes to 0. If perseldec = 1, the signals qspi_n_ss_out[3:0] + * require an external 4 to 16 decoder. + * + * Field Access Macros: + * + */ +/* The Least Significant Bit (LSB) position of the ALT_QSPI_CFG_PERCSLINES register field. */ +#define ALT_QSPI_CFG_PERCSLINES_LSB 10 +/* The Most Significant Bit (MSB) position of the ALT_QSPI_CFG_PERCSLINES register field. */ +#define ALT_QSPI_CFG_PERCSLINES_MSB 13 +/* The width in bits of the ALT_QSPI_CFG_PERCSLINES register field. */ +#define ALT_QSPI_CFG_PERCSLINES_WIDTH 4 +/* The mask used to set the ALT_QSPI_CFG_PERCSLINES register field value. */ +#define ALT_QSPI_CFG_PERCSLINES_SET_MSK 0x00003c00 +/* The mask used to clear the ALT_QSPI_CFG_PERCSLINES register field value. */ +#define ALT_QSPI_CFG_PERCSLINES_CLR_MSK 0xffffc3ff +/* The reset value of the ALT_QSPI_CFG_PERCSLINES register field. */ +#define ALT_QSPI_CFG_PERCSLINES_RESET 0x0 +/* Extracts the ALT_QSPI_CFG_PERCSLINES field value from a register. */ +#define ALT_QSPI_CFG_PERCSLINES_GET(value) (((value) & 0x00003c00) >> 10) +/* Produces a ALT_QSPI_CFG_PERCSLINES register field value suitable for setting the register. */ +#define ALT_QSPI_CFG_PERCSLINES_SET(value) (((value) << 10) & 0x00003c00) + +/* + * Field : Write Protect Flash Pin - wp + * + * This bit controls the write protect pin of the flash devices. The signal + * qspi_mo2_wpn needs to be resynchronized to the generated memory clock as + * necessary. + * + * Field Enumeration Values: + * + * Enum | Value | Description + * :-----------------------------|:------|:---------------------- + * ALT_QSPI_CFG_WP_E_WRPROTON | 0x1 | Enable Write Protect + * ALT_QSPI_CFG_WP_E_WRTPROTOFF | 0x0 | Disable Write Protect + * + * Field Access Macros: + * + */ +/* + * Enumerated value for register field ALT_QSPI_CFG_WP + * + * Enable Write Protect + */ +#define ALT_QSPI_CFG_WP_E_WRPROTON 0x1 +/* + * Enumerated value for register field ALT_QSPI_CFG_WP + * + * Disable Write Protect + */ +#define ALT_QSPI_CFG_WP_E_WRTPROTOFF 0x0 + +/* The Least Significant Bit (LSB) position of the ALT_QSPI_CFG_WP register field. */ +#define ALT_QSPI_CFG_WP_LSB 14 +/* The Most Significant Bit (MSB) position of the ALT_QSPI_CFG_WP register field. */ +#define ALT_QSPI_CFG_WP_MSB 14 +/* The width in bits of the ALT_QSPI_CFG_WP register field. */ +#define ALT_QSPI_CFG_WP_WIDTH 1 +/* The mask used to set the ALT_QSPI_CFG_WP register field value. */ +#define ALT_QSPI_CFG_WP_SET_MSK 0x00004000 +/* The mask used to clear the ALT_QSPI_CFG_WP register field value. */ +#define ALT_QSPI_CFG_WP_CLR_MSK 0xffffbfff +/* The reset value of the ALT_QSPI_CFG_WP register field. */ +#define ALT_QSPI_CFG_WP_RESET 0x0 +/* Extracts the ALT_QSPI_CFG_WP field value from a register. */ +#define ALT_QSPI_CFG_WP_GET(value) (((value) & 0x00004000) >> 14) +/* Produces a ALT_QSPI_CFG_WP register field value suitable for setting the register. */ +#define ALT_QSPI_CFG_WP_SET(value) (((value) << 14) & 0x00004000) + +/* + * Field : Enable DMA Peripheral Interface - endma + * + * Allows DMA handshaking mode. When enabled the QSPI will trigger DMA transfer + * requests via the DMA peripheral interface. + * + * Field Enumeration Values: + * + * Enum | Value | Description + * :-------------------------|:------|:----------------- + * ALT_QSPI_CFG_ENDMA_E_EN | 0x1 | Enable DMA Mode + * ALT_QSPI_CFG_ENDMA_E_DIS | 0x0 | Disable DMA Mode + * + * Field Access Macros: + * + */ +/* + * Enumerated value for register field ALT_QSPI_CFG_ENDMA + * + * Enable DMA Mode + */ +#define ALT_QSPI_CFG_ENDMA_E_EN 0x1 +/* + * Enumerated value for register field ALT_QSPI_CFG_ENDMA + * + * Disable DMA Mode + */ +#define ALT_QSPI_CFG_ENDMA_E_DIS 0x0 + +/* The Least Significant Bit (LSB) position of the ALT_QSPI_CFG_ENDMA register field. */ +#define ALT_QSPI_CFG_ENDMA_LSB 15 +/* The Most Significant Bit (MSB) position of the ALT_QSPI_CFG_ENDMA register field. */ +#define ALT_QSPI_CFG_ENDMA_MSB 15 +/* The width in bits of the ALT_QSPI_CFG_ENDMA register field. */ +#define ALT_QSPI_CFG_ENDMA_WIDTH 1 +/* The mask used to set the ALT_QSPI_CFG_ENDMA register field value. */ +#define ALT_QSPI_CFG_ENDMA_SET_MSK 0x00008000 +/* The mask used to clear the ALT_QSPI_CFG_ENDMA register field value. */ +#define ALT_QSPI_CFG_ENDMA_CLR_MSK 0xffff7fff +/* The reset value of the ALT_QSPI_CFG_ENDMA register field. */ +#define ALT_QSPI_CFG_ENDMA_RESET 0x0 +/* Extracts the ALT_QSPI_CFG_ENDMA field value from a register. */ +#define ALT_QSPI_CFG_ENDMA_GET(value) (((value) & 0x00008000) >> 15) +/* Produces a ALT_QSPI_CFG_ENDMA register field value suitable for setting the register. */ +#define ALT_QSPI_CFG_ENDMA_SET(value) (((value) << 15) & 0x00008000) + +/* + * Field : Enable AHB Address Re-mapping - enahbremap + * + * (Direct Access Mode Only) When enabled, the incoming AHB address will be adapted + * and sent to the FLASH device as (address + N), where N is the value stored in + * the remap address register. + * + * Field Enumeration Values: + * + * Enum | Value | Description + * :------------------------------|:------|:----------------------- + * ALT_QSPI_CFG_ENAHBREMAP_E_EN | 0x1 | Enable AHB Re-mapping + * ALT_QSPI_CFG_ENAHBREMAP_E_DIS | 0x0 | Disable AHB Re-mapping + * + * Field Access Macros: + * + */ +/* + * Enumerated value for register field ALT_QSPI_CFG_ENAHBREMAP + * + * Enable AHB Re-mapping + */ +#define ALT_QSPI_CFG_ENAHBREMAP_E_EN 0x1 +/* + * Enumerated value for register field ALT_QSPI_CFG_ENAHBREMAP + * + * Disable AHB Re-mapping + */ +#define ALT_QSPI_CFG_ENAHBREMAP_E_DIS 0x0 + +/* The Least Significant Bit (LSB) position of the ALT_QSPI_CFG_ENAHBREMAP register field. */ +#define ALT_QSPI_CFG_ENAHBREMAP_LSB 16 +/* The Most Significant Bit (MSB) position of the ALT_QSPI_CFG_ENAHBREMAP register field. */ +#define ALT_QSPI_CFG_ENAHBREMAP_MSB 16 +/* The width in bits of the ALT_QSPI_CFG_ENAHBREMAP register field. */ +#define ALT_QSPI_CFG_ENAHBREMAP_WIDTH 1 +/* The mask used to set the ALT_QSPI_CFG_ENAHBREMAP register field value. */ +#define ALT_QSPI_CFG_ENAHBREMAP_SET_MSK 0x00010000 +/* The mask used to clear the ALT_QSPI_CFG_ENAHBREMAP register field value. */ +#define ALT_QSPI_CFG_ENAHBREMAP_CLR_MSK 0xfffeffff +/* The reset value of the ALT_QSPI_CFG_ENAHBREMAP register field. */ +#define ALT_QSPI_CFG_ENAHBREMAP_RESET 0x0 +/* Extracts the ALT_QSPI_CFG_ENAHBREMAP field value from a register. */ +#define ALT_QSPI_CFG_ENAHBREMAP_GET(value) (((value) & 0x00010000) >> 16) +/* Produces a ALT_QSPI_CFG_ENAHBREMAP register field value suitable for setting the register. */ +#define ALT_QSPI_CFG_ENAHBREMAP_SET(value) (((value) << 16) & 0x00010000) + +/* + * Field : Enter XIP Mode on next READ - enterxipnextrd + * + * If XIP is enabled, then setting to disabled will cause the controller to exit + * XIP mode on the next READ instruction. If XIP is disabled, then setting to + * enabled will inform the controller that the device is ready to enter XIP on the + * next READ instruction. The controller will therefore send the appropriate + * command sequence, including mode bits to cause the device to enter XIP mode. Use + * this register after the controller has ensured the FLASH device has been + * configured to be ready to enter XIP mode. Note : To exit XIP mode, this bit + * should be set to 0. This will take effect in the attached device only AFTER the + * next READ instruction is executed. Software should therefore ensure that at + * least one READ instruction is requested after resetting this bit before it can + * be sure XIP mode in the device is exited. + * + * Field Enumeration Values: + * + * Enum | Value | Description + * :----------------------------------|:------|:---------------------------------------- + * ALT_QSPI_CFG_ENTERXIPNEXTRD_E_EN | 0x1 | Enter XIP Mode on next READ instruction + * ALT_QSPI_CFG_ENTERXIPNEXTRD_E_DIS | 0x0 | Exit XIP Mode on next READ instruction + * + * Field Access Macros: + * + */ +/* + * Enumerated value for register field ALT_QSPI_CFG_ENTERXIPNEXTRD + * + * Enter XIP Mode on next READ instruction + */ +#define ALT_QSPI_CFG_ENTERXIPNEXTRD_E_EN 0x1 +/* + * Enumerated value for register field ALT_QSPI_CFG_ENTERXIPNEXTRD + * + * Exit XIP Mode on next READ instruction + */ +#define ALT_QSPI_CFG_ENTERXIPNEXTRD_E_DIS 0x0 + +/* The Least Significant Bit (LSB) position of the ALT_QSPI_CFG_ENTERXIPNEXTRD register field. */ +#define ALT_QSPI_CFG_ENTERXIPNEXTRD_LSB 17 +/* The Most Significant Bit (MSB) position of the ALT_QSPI_CFG_ENTERXIPNEXTRD register field. */ +#define ALT_QSPI_CFG_ENTERXIPNEXTRD_MSB 17 +/* The width in bits of the ALT_QSPI_CFG_ENTERXIPNEXTRD register field. */ +#define ALT_QSPI_CFG_ENTERXIPNEXTRD_WIDTH 1 +/* The mask used to set the ALT_QSPI_CFG_ENTERXIPNEXTRD register field value. */ +#define ALT_QSPI_CFG_ENTERXIPNEXTRD_SET_MSK 0x00020000 +/* The mask used to clear the ALT_QSPI_CFG_ENTERXIPNEXTRD register field value. */ +#define ALT_QSPI_CFG_ENTERXIPNEXTRD_CLR_MSK 0xfffdffff +/* The reset value of the ALT_QSPI_CFG_ENTERXIPNEXTRD register field. */ +#define ALT_QSPI_CFG_ENTERXIPNEXTRD_RESET 0x0 +/* Extracts the ALT_QSPI_CFG_ENTERXIPNEXTRD field value from a register. */ +#define ALT_QSPI_CFG_ENTERXIPNEXTRD_GET(value) (((value) & 0x00020000) >> 17) +/* Produces a ALT_QSPI_CFG_ENTERXIPNEXTRD register field value suitable for setting the register. */ +#define ALT_QSPI_CFG_ENTERXIPNEXTRD_SET(value) (((value) << 17) & 0x00020000) + +/* + * Field : Enter XIP Mode Immediately - enterxipimm + * + * If XIP is enabled, then setting to disabled will cause the controller to exit + * XIP mode on the next READ instruction. If XIP is disabled, then setting enable + * will operate the device in XIP mode immediately. Use this register when the + * external device wakes up in XIP mode (as per the contents of its non- volatile + * configuration register). The controller will assume the next READ instruction + * will be passed to the device as an XIP instruction, and therefore will not + * require the READ opcode to be transferred. Note: To exit XIP mode, this bit + * should be set to 0. This will take effect in the attached device only after the + * next READ instruction is executed. Software therefore should ensure that at + * least one READ instruction is requested after resetting this bit in order to be + * sure that XIP mode is exited. + * + * Field Enumeration Values: + * + * Enum | Value | Description + * :-------------------------------|:------|:--------------------------------------- + * ALT_QSPI_CFG_ENTERXIPIMM_E_EN | 0x1 | Enter XIP Mode immediately + * ALT_QSPI_CFG_ENTERXIPIMM_E_DIS | 0x0 | Exit XIP Mode on next READ instruction + * + * Field Access Macros: + * + */ +/* + * Enumerated value for register field ALT_QSPI_CFG_ENTERXIPIMM + * + * Enter XIP Mode immediately + */ +#define ALT_QSPI_CFG_ENTERXIPIMM_E_EN 0x1 +/* + * Enumerated value for register field ALT_QSPI_CFG_ENTERXIPIMM + * + * Exit XIP Mode on next READ instruction + */ +#define ALT_QSPI_CFG_ENTERXIPIMM_E_DIS 0x0 + +/* The Least Significant Bit (LSB) position of the ALT_QSPI_CFG_ENTERXIPIMM register field. */ +#define ALT_QSPI_CFG_ENTERXIPIMM_LSB 18 +/* The Most Significant Bit (MSB) position of the ALT_QSPI_CFG_ENTERXIPIMM register field. */ +#define ALT_QSPI_CFG_ENTERXIPIMM_MSB 18 +/* The width in bits of the ALT_QSPI_CFG_ENTERXIPIMM register field. */ +#define ALT_QSPI_CFG_ENTERXIPIMM_WIDTH 1 +/* The mask used to set the ALT_QSPI_CFG_ENTERXIPIMM register field value. */ +#define ALT_QSPI_CFG_ENTERXIPIMM_SET_MSK 0x00040000 +/* The mask used to clear the ALT_QSPI_CFG_ENTERXIPIMM register field value. */ +#define ALT_QSPI_CFG_ENTERXIPIMM_CLR_MSK 0xfffbffff +/* The reset value of the ALT_QSPI_CFG_ENTERXIPIMM register field. */ +#define ALT_QSPI_CFG_ENTERXIPIMM_RESET 0x0 +/* Extracts the ALT_QSPI_CFG_ENTERXIPIMM field value from a register. */ +#define ALT_QSPI_CFG_ENTERXIPIMM_GET(value) (((value) & 0x00040000) >> 18) +/* Produces a ALT_QSPI_CFG_ENTERXIPIMM register field value suitable for setting the register. */ +#define ALT_QSPI_CFG_ENTERXIPIMM_SET(value) (((value) << 18) & 0x00040000) + +/* + * Field : Master Mode Baud Rate Divisor - bauddiv + * + * SPI baud rate = ref_clk / (2 * baud_rate_divisor) + * + * Field Enumeration Values: + * + * Enum | Value | Description + * :------------------------------|:------|:----------------- + * ALT_QSPI_CFG_BAUDDIV_E_BAUD2 | 0x0 | Baud Rate Div/2 + * ALT_QSPI_CFG_BAUDDIV_E_BAUD4 | 0x1 | Baud Rate Div/4 + * ALT_QSPI_CFG_BAUDDIV_E_BAUD6 | 0x2 | Baud Rate Div/6 + * ALT_QSPI_CFG_BAUDDIV_E_BAUD8 | 0x3 | Baud Rate Div/8 + * ALT_QSPI_CFG_BAUDDIV_E_BAUD10 | 0x4 | Baud Rate Div/10 + * ALT_QSPI_CFG_BAUDDIV_E_BAUD12 | 0x5 | Baud Rate Div/12 + * ALT_QSPI_CFG_BAUDDIV_E_BAUD14 | 0x6 | Baud Rate Div/14 + * ALT_QSPI_CFG_BAUDDIV_E_BAUD16 | 0x7 | Baud Rate Div/16 + * ALT_QSPI_CFG_BAUDDIV_E_BAUD18 | 0x8 | Baud Rate Div/18 + * ALT_QSPI_CFG_BAUDDIV_E_BAUD20 | 0x9 | Baud Rate Div/20 + * ALT_QSPI_CFG_BAUDDIV_E_BAUD22 | 0xa | Baud Rate Div/22 + * ALT_QSPI_CFG_BAUDDIV_E_BAUD24 | 0xb | Baud Rate Div/24 + * ALT_QSPI_CFG_BAUDDIV_E_BAUD26 | 0xc | Baud Rate Div/26 + * ALT_QSPI_CFG_BAUDDIV_E_BAUD28 | 0xd | Baud Rate Div/28 + * ALT_QSPI_CFG_BAUDDIV_E_BAUD30 | 0xe | Baud Rate Div/30 + * ALT_QSPI_CFG_BAUDDIV_E_BAUD32 | 0xf | Baud Rate Div/32 + * + * Field Access Macros: + * + */ +/* + * Enumerated value for register field ALT_QSPI_CFG_BAUDDIV + * + * Baud Rate Div/2 + */ +#define ALT_QSPI_CFG_BAUDDIV_E_BAUD2 0x0 +/* + * Enumerated value for register field ALT_QSPI_CFG_BAUDDIV + * + * Baud Rate Div/4 + */ +#define ALT_QSPI_CFG_BAUDDIV_E_BAUD4 0x1 +/* + * Enumerated value for register field ALT_QSPI_CFG_BAUDDIV + * + * Baud Rate Div/6 + */ +#define ALT_QSPI_CFG_BAUDDIV_E_BAUD6 0x2 +/* + * Enumerated value for register field ALT_QSPI_CFG_BAUDDIV + * + * Baud Rate Div/8 + */ +#define ALT_QSPI_CFG_BAUDDIV_E_BAUD8 0x3 +/* + * Enumerated value for register field ALT_QSPI_CFG_BAUDDIV + * + * Baud Rate Div/10 + */ +#define ALT_QSPI_CFG_BAUDDIV_E_BAUD10 0x4 +/* + * Enumerated value for register field ALT_QSPI_CFG_BAUDDIV + * + * Baud Rate Div/12 + */ +#define ALT_QSPI_CFG_BAUDDIV_E_BAUD12 0x5 +/* + * Enumerated value for register field ALT_QSPI_CFG_BAUDDIV + * + * Baud Rate Div/14 + */ +#define ALT_QSPI_CFG_BAUDDIV_E_BAUD14 0x6 +/* + * Enumerated value for register field ALT_QSPI_CFG_BAUDDIV + * + * Baud Rate Div/16 + */ +#define ALT_QSPI_CFG_BAUDDIV_E_BAUD16 0x7 +/* + * Enumerated value for register field ALT_QSPI_CFG_BAUDDIV + * + * Baud Rate Div/18 + */ +#define ALT_QSPI_CFG_BAUDDIV_E_BAUD18 0x8 +/* + * Enumerated value for register field ALT_QSPI_CFG_BAUDDIV + * + * Baud Rate Div/20 + */ +#define ALT_QSPI_CFG_BAUDDIV_E_BAUD20 0x9 +/* + * Enumerated value for register field ALT_QSPI_CFG_BAUDDIV + * + * Baud Rate Div/22 + */ +#define ALT_QSPI_CFG_BAUDDIV_E_BAUD22 0xa +/* + * Enumerated value for register field ALT_QSPI_CFG_BAUDDIV + * + * Baud Rate Div/24 + */ +#define ALT_QSPI_CFG_BAUDDIV_E_BAUD24 0xb +/* + * Enumerated value for register field ALT_QSPI_CFG_BAUDDIV + * + * Baud Rate Div/26 + */ +#define ALT_QSPI_CFG_BAUDDIV_E_BAUD26 0xc +/* + * Enumerated value for register field ALT_QSPI_CFG_BAUDDIV + * + * Baud Rate Div/28 + */ +#define ALT_QSPI_CFG_BAUDDIV_E_BAUD28 0xd +/* + * Enumerated value for register field ALT_QSPI_CFG_BAUDDIV + * + * Baud Rate Div/30 + */ +#define ALT_QSPI_CFG_BAUDDIV_E_BAUD30 0xe +/* + * Enumerated value for register field ALT_QSPI_CFG_BAUDDIV + * + * Baud Rate Div/32 + */ +#define ALT_QSPI_CFG_BAUDDIV_E_BAUD32 0xf + +/* The Least Significant Bit (LSB) position of the ALT_QSPI_CFG_BAUDDIV register field. */ +#define ALT_QSPI_CFG_BAUDDIV_LSB 19 +/* The Most Significant Bit (MSB) position of the ALT_QSPI_CFG_BAUDDIV register field. */ +#define ALT_QSPI_CFG_BAUDDIV_MSB 22 +/* The width in bits of the ALT_QSPI_CFG_BAUDDIV register field. */ +#define ALT_QSPI_CFG_BAUDDIV_WIDTH 4 +/* The mask used to set the ALT_QSPI_CFG_BAUDDIV register field value. */ +#define ALT_QSPI_CFG_BAUDDIV_SET_MSK 0x00780000 +/* The mask used to clear the ALT_QSPI_CFG_BAUDDIV register field value. */ +#define ALT_QSPI_CFG_BAUDDIV_CLR_MSK 0xff87ffff +/* The reset value of the ALT_QSPI_CFG_BAUDDIV register field. */ +#define ALT_QSPI_CFG_BAUDDIV_RESET 0xf +/* Extracts the ALT_QSPI_CFG_BAUDDIV field value from a register. */ +#define ALT_QSPI_CFG_BAUDDIV_GET(value) (((value) & 0x00780000) >> 19) +/* Produces a ALT_QSPI_CFG_BAUDDIV register field value suitable for setting the register. */ +#define ALT_QSPI_CFG_BAUDDIV_SET(value) (((value) << 19) & 0x00780000) + +/* + * Field : Serial interface and QSPI pipeline is IDLE - idle + * + * This is a STATUS read-only bit. Note this is a retimed signal, so there will be + * some inherent delay on the generation of this status signal. + * + * Field Enumeration Values: + * + * Enum | Value | Description + * :---------------------------|:------|:-------------- + * ALT_QSPI_CFG_IDLE_E_SET | 0x1 | Idle Mode + * ALT_QSPI_CFG_IDLE_E_NOTSET | 0x0 | Non-Idle Mode + * + * Field Access Macros: + * + */ +/* + * Enumerated value for register field ALT_QSPI_CFG_IDLE + * + * Idle Mode + */ +#define ALT_QSPI_CFG_IDLE_E_SET 0x1 +/* + * Enumerated value for register field ALT_QSPI_CFG_IDLE + * + * Non-Idle Mode + */ +#define ALT_QSPI_CFG_IDLE_E_NOTSET 0x0 + +/* The Least Significant Bit (LSB) position of the ALT_QSPI_CFG_IDLE register field. */ +#define ALT_QSPI_CFG_IDLE_LSB 31 +/* The Most Significant Bit (MSB) position of the ALT_QSPI_CFG_IDLE register field. */ +#define ALT_QSPI_CFG_IDLE_MSB 31 +/* The width in bits of the ALT_QSPI_CFG_IDLE register field. */ +#define ALT_QSPI_CFG_IDLE_WIDTH 1 +/* The mask used to set the ALT_QSPI_CFG_IDLE register field value. */ +#define ALT_QSPI_CFG_IDLE_SET_MSK 0x80000000 +/* The mask used to clear the ALT_QSPI_CFG_IDLE register field value. */ +#define ALT_QSPI_CFG_IDLE_CLR_MSK 0x7fffffff +/* The reset value of the ALT_QSPI_CFG_IDLE register field. */ +#define ALT_QSPI_CFG_IDLE_RESET 0x0 +/* Extracts the ALT_QSPI_CFG_IDLE field value from a register. */ +#define ALT_QSPI_CFG_IDLE_GET(value) (((value) & 0x80000000) >> 31) +/* Produces a ALT_QSPI_CFG_IDLE register field value suitable for setting the register. */ +#define ALT_QSPI_CFG_IDLE_SET(value) (((value) << 31) & 0x80000000) + +#ifndef __ASSEMBLY__ +/* + * WARNING: The C register and register group struct declarations are provided for + * convenience and illustrative purposes. They should, however, be used with + * caution as the C language standard provides no guarantees about the alignment or + * atomicity of device memory accesses. The recommended practice for writing + * hardware drivers is to use the SoCAL access macros and alt_read_word() and + * alt_write_word() functions. + * + * The struct declaration for register ALT_QSPI_CFG. + */ +struct ALT_QSPI_CFG_s +{ + uint32_t en : 1; /* QSPI Enable */ + uint32_t selclkpol : 1; /* Clock Polarity */ + uint32_t selclkphase : 1; /* Select Clock Phase */ + uint32_t : 4; /* *UNDEFINED* */ + uint32_t endiracc : 1; /* Enable Direct Access Controller */ + uint32_t enlegacyip : 1; /* Legacy IP Mode Enable */ + uint32_t perseldec : 1; /* Peripheral select decode */ + uint32_t percslines : 4; /* Peripheral Chip Select Lines */ + uint32_t wp : 1; /* Write Protect Flash Pin */ + uint32_t endma : 1; /* Enable DMA Peripheral Interface */ + uint32_t enahbremap : 1; /* Enable AHB Address Re-mapping */ + uint32_t enterxipnextrd : 1; /* Enter XIP Mode on next READ */ + uint32_t enterxipimm : 1; /* Enter XIP Mode Immediately */ + uint32_t bauddiv : 4; /* Master Mode Baud Rate Divisor */ + uint32_t : 8; /* *UNDEFINED* */ + const uint32_t idle : 1; /* Serial interface and QSPI pipeline is IDLE */ +}; + +/* The typedef declaration for register ALT_QSPI_CFG. */ +typedef volatile struct ALT_QSPI_CFG_s ALT_QSPI_CFG_t; +#endif /* __ASSEMBLY__ */ + +/* The byte offset of the ALT_QSPI_CFG register from the beginning of the component. */ +#define ALT_QSPI_CFG_OFST 0x0 + +/* + * Register : Device Read Instruction Register - devrd + * + * Register Layout + * + * Bits | Access | Reset | Description + * :--------|:-------|:------|:---------------------------- + * [7:0] | RW | 0x3 | Read Opcode in non-XIP mode + * [9:8] | RW | 0x0 | Instruction Transfer Width + * [11:10] | ??? | 0x0 | *UNDEFINED* + * [13:12] | RW | 0x0 | Address Transfer Width + * [15:14] | ??? | 0x0 | *UNDEFINED* + * [17:16] | RW | 0x0 | Data Transfer Width + * [19:18] | ??? | 0x0 | *UNDEFINED* + * [20] | RW | 0x0 | Mode Bit Enable + * [23:21] | ??? | 0x0 | *UNDEFINED* + * [28:24] | RW | 0x0 | Dummy Read Clock Cycles + * [31:29] | ??? | 0x0 | *UNDEFINED* + * + */ +/* + * Field : Read Opcode in non-XIP mode - rdopcode + * + * Read Opcode to use when not in XIP mode + * + * Field Enumeration Values: + * + * Enum | Value | Description + * :---------------------------------|:------|:---------------------------- + * ALT_QSPI_DEVRD_RDOPCODE_E_RD | 0x3 | Read Opcode in Non-XIP mode + * ALT_QSPI_DEVRD_RDOPCODE_E_FASTRD | 0xb | Fast Read in Non-XIP mode + * + * Field Access Macros: + * + */ +/* + * Enumerated value for register field ALT_QSPI_DEVRD_RDOPCODE + * + * Read Opcode in Non-XIP mode + */ +#define ALT_QSPI_DEVRD_RDOPCODE_E_RD 0x3 +/* + * Enumerated value for register field ALT_QSPI_DEVRD_RDOPCODE + * + * Fast Read in Non-XIP mode + */ +#define ALT_QSPI_DEVRD_RDOPCODE_E_FASTRD 0xb + +/* The Least Significant Bit (LSB) position of the ALT_QSPI_DEVRD_RDOPCODE register field. */ +#define ALT_QSPI_DEVRD_RDOPCODE_LSB 0 +/* The Most Significant Bit (MSB) position of the ALT_QSPI_DEVRD_RDOPCODE register field. */ +#define ALT_QSPI_DEVRD_RDOPCODE_MSB 7 +/* The width in bits of the ALT_QSPI_DEVRD_RDOPCODE register field. */ +#define ALT_QSPI_DEVRD_RDOPCODE_WIDTH 8 +/* The mask used to set the ALT_QSPI_DEVRD_RDOPCODE register field value. */ +#define ALT_QSPI_DEVRD_RDOPCODE_SET_MSK 0x000000ff +/* The mask used to clear the ALT_QSPI_DEVRD_RDOPCODE register field value. */ +#define ALT_QSPI_DEVRD_RDOPCODE_CLR_MSK 0xffffff00 +/* The reset value of the ALT_QSPI_DEVRD_RDOPCODE register field. */ +#define ALT_QSPI_DEVRD_RDOPCODE_RESET 0x3 +/* Extracts the ALT_QSPI_DEVRD_RDOPCODE field value from a register. */ +#define ALT_QSPI_DEVRD_RDOPCODE_GET(value) (((value) & 0x000000ff) >> 0) +/* Produces a ALT_QSPI_DEVRD_RDOPCODE register field value suitable for setting the register. */ +#define ALT_QSPI_DEVRD_RDOPCODE_SET(value) (((value) << 0) & 0x000000ff) + +/* + * Field : Instruction Transfer Width - instwidth + * + * Sets instruction transfer width (1, 2, or 4 bits). Applies to all instructions + * sent to SPI flash device (not just read instructions). + * + * Field Enumeration Values: + * + * Enum | Value | Description + * :----------------------------------|:------|:------------------------------------------------- + * ALT_QSPI_DEVRD_INSTWIDTH_E_SINGLE | 0x0 | Instruction transferred on DQ0. Supported by all + * : | | SPI flash devices. + * ALT_QSPI_DEVRD_INSTWIDTH_E_DUAL | 0x1 | Instruction transferred on DQ0 and DQ1. + * : | | Supported by all SPI flash devices that support + * : | | the Dual SP (DIO-SPI) Protocol. + * ALT_QSPI_DEVRD_INSTWIDTH_E_QUAD | 0x2 | Instruction transferred on DQ0, DQ1, DQ2, and + * : | | DQ3. Supported by all SPI flash devices that + * : | | support the Quad SP (QIO-SPI) Protocol. + * + * Field Access Macros: + * + */ +/* + * Enumerated value for register field ALT_QSPI_DEVRD_INSTWIDTH + * + * Instruction transferred on DQ0. Supported by all SPI flash devices. + */ +#define ALT_QSPI_DEVRD_INSTWIDTH_E_SINGLE 0x0 +/* + * Enumerated value for register field ALT_QSPI_DEVRD_INSTWIDTH + * + * Instruction transferred on DQ0 and DQ1. Supported by all SPI flash devices that + * support the Dual SP (DIO-SPI) Protocol. + */ +#define ALT_QSPI_DEVRD_INSTWIDTH_E_DUAL 0x1 +/* + * Enumerated value for register field ALT_QSPI_DEVRD_INSTWIDTH + * + * Instruction transferred on DQ0, DQ1, DQ2, and DQ3. Supported by all SPI flash + * devices that support the Quad SP (QIO-SPI) Protocol. + */ +#define ALT_QSPI_DEVRD_INSTWIDTH_E_QUAD 0x2 + +/* The Least Significant Bit (LSB) position of the ALT_QSPI_DEVRD_INSTWIDTH register field. */ +#define ALT_QSPI_DEVRD_INSTWIDTH_LSB 8 +/* The Most Significant Bit (MSB) position of the ALT_QSPI_DEVRD_INSTWIDTH register field. */ +#define ALT_QSPI_DEVRD_INSTWIDTH_MSB 9 +/* The width in bits of the ALT_QSPI_DEVRD_INSTWIDTH register field. */ +#define ALT_QSPI_DEVRD_INSTWIDTH_WIDTH 2 +/* The mask used to set the ALT_QSPI_DEVRD_INSTWIDTH register field value. */ +#define ALT_QSPI_DEVRD_INSTWIDTH_SET_MSK 0x00000300 +/* The mask used to clear the ALT_QSPI_DEVRD_INSTWIDTH register field value. */ +#define ALT_QSPI_DEVRD_INSTWIDTH_CLR_MSK 0xfffffcff +/* The reset value of the ALT_QSPI_DEVRD_INSTWIDTH register field. */ +#define ALT_QSPI_DEVRD_INSTWIDTH_RESET 0x0 +/* Extracts the ALT_QSPI_DEVRD_INSTWIDTH field value from a register. */ +#define ALT_QSPI_DEVRD_INSTWIDTH_GET(value) (((value) & 0x00000300) >> 8) +/* Produces a ALT_QSPI_DEVRD_INSTWIDTH register field value suitable for setting the register. */ +#define ALT_QSPI_DEVRD_INSTWIDTH_SET(value) (((value) << 8) & 0x00000300) + +/* + * Field : Address Transfer Width - addrwidth + * + * Sets read address transfer width (1, 2, or 4 bits). + * + * Field Enumeration Values: + * + * Enum | Value | Description + * :----------------------------------|:------|:------------------------------------------------- + * ALT_QSPI_DEVRD_ADDRWIDTH_E_SINGLE | 0x0 | Read address transferred on DQ0. Supported by + * : | | all SPI flash devices + * ALT_QSPI_DEVRD_ADDRWIDTH_E_DUAL | 0x1 | Read address transferred on DQ0 and DQ1. + * : | | Supported by some SPI flash devices that support + * : | | the Extended SPI Protocol and by all SPI flash + * : | | devices that support the Dual SP (DIO-SPI) + * : | | Protocol. + * ALT_QSPI_DEVRD_ADDRWIDTH_E_QUAD | 0x2 | Read address transferred on DQ0, DQ1, DQ2, and + * : | | DQ3. Supported by some SPI flash devices that + * : | | support the Extended SPI Protocol and by all SPI + * : | | flash devices that support the Quad SP (QIO-SPI) + * : | | Protocol. + * + * Field Access Macros: + * + */ +/* + * Enumerated value for register field ALT_QSPI_DEVRD_ADDRWIDTH + * + * Read address transferred on DQ0. Supported by all SPI flash devices + */ +#define ALT_QSPI_DEVRD_ADDRWIDTH_E_SINGLE 0x0 +/* + * Enumerated value for register field ALT_QSPI_DEVRD_ADDRWIDTH + * + * Read address transferred on DQ0 and DQ1. Supported by some SPI flash devices + * that support the Extended SPI Protocol and by all SPI flash devices that support + * the Dual SP (DIO-SPI) Protocol. + */ +#define ALT_QSPI_DEVRD_ADDRWIDTH_E_DUAL 0x1 +/* + * Enumerated value for register field ALT_QSPI_DEVRD_ADDRWIDTH + * + * Read address transferred on DQ0, DQ1, DQ2, and DQ3. Supported by some SPI flash + * devices that support the Extended SPI Protocol and by all SPI flash devices that + * support the Quad SP (QIO-SPI) Protocol. + */ +#define ALT_QSPI_DEVRD_ADDRWIDTH_E_QUAD 0x2 + +/* The Least Significant Bit (LSB) position of the ALT_QSPI_DEVRD_ADDRWIDTH register field. */ +#define ALT_QSPI_DEVRD_ADDRWIDTH_LSB 12 +/* The Most Significant Bit (MSB) position of the ALT_QSPI_DEVRD_ADDRWIDTH register field. */ +#define ALT_QSPI_DEVRD_ADDRWIDTH_MSB 13 +/* The width in bits of the ALT_QSPI_DEVRD_ADDRWIDTH register field. */ +#define ALT_QSPI_DEVRD_ADDRWIDTH_WIDTH 2 +/* The mask used to set the ALT_QSPI_DEVRD_ADDRWIDTH register field value. */ +#define ALT_QSPI_DEVRD_ADDRWIDTH_SET_MSK 0x00003000 +/* The mask used to clear the ALT_QSPI_DEVRD_ADDRWIDTH register field value. */ +#define ALT_QSPI_DEVRD_ADDRWIDTH_CLR_MSK 0xffffcfff +/* The reset value of the ALT_QSPI_DEVRD_ADDRWIDTH register field. */ +#define ALT_QSPI_DEVRD_ADDRWIDTH_RESET 0x0 +/* Extracts the ALT_QSPI_DEVRD_ADDRWIDTH field value from a register. */ +#define ALT_QSPI_DEVRD_ADDRWIDTH_GET(value) (((value) & 0x00003000) >> 12) +/* Produces a ALT_QSPI_DEVRD_ADDRWIDTH register field value suitable for setting the register. */ +#define ALT_QSPI_DEVRD_ADDRWIDTH_SET(value) (((value) << 12) & 0x00003000) + +/* + * Field : Data Transfer Width - datawidth + * + * Sets read data transfer width (1, 2, or 4 bits). + * + * Field Enumeration Values: + * + * Enum | Value | Description + * :----------------------------------|:------|:------------------------------------------------- + * ALT_QSPI_DEVRD_DATAWIDTH_E_SINGLE | 0x0 | Read data transferred on DQ0. Supported by all + * : | | SPI flash devices + * ALT_QSPI_DEVRD_DATAWIDTH_E_DUAL | 0x1 | Read data transferred on DQ0 and DQ1. Supported + * : | | by some SPI flash devices that support the + * : | | Extended SPI Protocol and by all SPI flash + * : | | devices that support the Dual SP (DIO-SPI) + * : | | Protocol. + * ALT_QSPI_DEVRD_DATAWIDTH_E_QUAD | 0x2 | Read data transferred on DQ0, DQ1, DQ2, and DQ3. + * : | | Supported by some SPI flash devices that support + * : | | the Extended SPI Protocol and by all SPI flash + * : | | devices that support the Quad SP (QIO-SPI) + * : | | Protocol. + * + * Field Access Macros: + * + */ +/* + * Enumerated value for register field ALT_QSPI_DEVRD_DATAWIDTH + * + * Read data transferred on DQ0. Supported by all SPI flash devices + */ +#define ALT_QSPI_DEVRD_DATAWIDTH_E_SINGLE 0x0 +/* + * Enumerated value for register field ALT_QSPI_DEVRD_DATAWIDTH + * + * Read data transferred on DQ0 and DQ1. Supported by some SPI flash devices that + * support the Extended SPI Protocol and by all SPI flash devices that support the + * Dual SP (DIO-SPI) Protocol. + */ +#define ALT_QSPI_DEVRD_DATAWIDTH_E_DUAL 0x1 +/* + * Enumerated value for register field ALT_QSPI_DEVRD_DATAWIDTH + * + * Read data transferred on DQ0, DQ1, DQ2, and DQ3. Supported by some SPI flash + * devices that support the Extended SPI Protocol and by all SPI flash devices that + * support the Quad SP (QIO-SPI) Protocol. + */ +#define ALT_QSPI_DEVRD_DATAWIDTH_E_QUAD 0x2 + +/* The Least Significant Bit (LSB) position of the ALT_QSPI_DEVRD_DATAWIDTH register field. */ +#define ALT_QSPI_DEVRD_DATAWIDTH_LSB 16 +/* The Most Significant Bit (MSB) position of the ALT_QSPI_DEVRD_DATAWIDTH register field. */ +#define ALT_QSPI_DEVRD_DATAWIDTH_MSB 17 +/* The width in bits of the ALT_QSPI_DEVRD_DATAWIDTH register field. */ +#define ALT_QSPI_DEVRD_DATAWIDTH_WIDTH 2 +/* The mask used to set the ALT_QSPI_DEVRD_DATAWIDTH register field value. */ +#define ALT_QSPI_DEVRD_DATAWIDTH_SET_MSK 0x00030000 +/* The mask used to clear the ALT_QSPI_DEVRD_DATAWIDTH register field value. */ +#define ALT_QSPI_DEVRD_DATAWIDTH_CLR_MSK 0xfffcffff +/* The reset value of the ALT_QSPI_DEVRD_DATAWIDTH register field. */ +#define ALT_QSPI_DEVRD_DATAWIDTH_RESET 0x0 +/* Extracts the ALT_QSPI_DEVRD_DATAWIDTH field value from a register. */ +#define ALT_QSPI_DEVRD_DATAWIDTH_GET(value) (((value) & 0x00030000) >> 16) +/* Produces a ALT_QSPI_DEVRD_DATAWIDTH register field value suitable for setting the register. */ +#define ALT_QSPI_DEVRD_DATAWIDTH_SET(value) (((value) << 16) & 0x00030000) + +/* + * Field : Mode Bit Enable - enmodebits + * + * If this bit is set, the mode bits as defined in the Mode Bit Configuration + * register are sent following the address bytes. + * + * Field Enumeration Values: + * + * Enum | Value | Description + * :-----------------------------------|:------|:------------------------------- + * ALT_QSPI_DEVRD_ENMODBITS_E_NOORDER | 0x0 | No Order + * ALT_QSPI_DEVRD_ENMODBITS_E_ORDER | 0x1 | Mode Bits follow address bytes + * + * Field Access Macros: + * + */ +/* + * Enumerated value for register field ALT_QSPI_DEVRD_ENMODBITS + * + * No Order + */ +#define ALT_QSPI_DEVRD_ENMODBITS_E_NOORDER 0x0 +/* + * Enumerated value for register field ALT_QSPI_DEVRD_ENMODBITS + * + * Mode Bits follow address bytes + */ +#define ALT_QSPI_DEVRD_ENMODBITS_E_ORDER 0x1 + +/* The Least Significant Bit (LSB) position of the ALT_QSPI_DEVRD_ENMODBITS register field. */ +#define ALT_QSPI_DEVRD_ENMODBITS_LSB 20 +/* The Most Significant Bit (MSB) position of the ALT_QSPI_DEVRD_ENMODBITS register field. */ +#define ALT_QSPI_DEVRD_ENMODBITS_MSB 20 +/* The width in bits of the ALT_QSPI_DEVRD_ENMODBITS register field. */ +#define ALT_QSPI_DEVRD_ENMODBITS_WIDTH 1 +/* The mask used to set the ALT_QSPI_DEVRD_ENMODBITS register field value. */ +#define ALT_QSPI_DEVRD_ENMODBITS_SET_MSK 0x00100000 +/* The mask used to clear the ALT_QSPI_DEVRD_ENMODBITS register field value. */ +#define ALT_QSPI_DEVRD_ENMODBITS_CLR_MSK 0xffefffff +/* The reset value of the ALT_QSPI_DEVRD_ENMODBITS register field. */ +#define ALT_QSPI_DEVRD_ENMODBITS_RESET 0x0 +/* Extracts the ALT_QSPI_DEVRD_ENMODBITS field value from a register. */ +#define ALT_QSPI_DEVRD_ENMODBITS_GET(value) (((value) & 0x00100000) >> 20) +/* Produces a ALT_QSPI_DEVRD_ENMODBITS register field value suitable for setting the register. */ +#define ALT_QSPI_DEVRD_ENMODBITS_SET(value) (((value) << 20) & 0x00100000) + +/* + * Field : Dummy Read Clock Cycles - dummyrdclks + * + * Number of dummy clock cycles required by device for read instruction. + * + * Field Access Macros: + * + */ +/* The Least Significant Bit (LSB) position of the ALT_QSPI_DEVRD_DUMMYRDCLKS register field. */ +#define ALT_QSPI_DEVRD_DUMMYRDCLKS_LSB 24 +/* The Most Significant Bit (MSB) position of the ALT_QSPI_DEVRD_DUMMYRDCLKS register field. */ +#define ALT_QSPI_DEVRD_DUMMYRDCLKS_MSB 28 +/* The width in bits of the ALT_QSPI_DEVRD_DUMMYRDCLKS register field. */ +#define ALT_QSPI_DEVRD_DUMMYRDCLKS_WIDTH 5 +/* The mask used to set the ALT_QSPI_DEVRD_DUMMYRDCLKS register field value. */ +#define ALT_QSPI_DEVRD_DUMMYRDCLKS_SET_MSK 0x1f000000 +/* The mask used to clear the ALT_QSPI_DEVRD_DUMMYRDCLKS register field value. */ +#define ALT_QSPI_DEVRD_DUMMYRDCLKS_CLR_MSK 0xe0ffffff +/* The reset value of the ALT_QSPI_DEVRD_DUMMYRDCLKS register field. */ +#define ALT_QSPI_DEVRD_DUMMYRDCLKS_RESET 0x0 +/* Extracts the ALT_QSPI_DEVRD_DUMMYRDCLKS field value from a register. */ +#define ALT_QSPI_DEVRD_DUMMYRDCLKS_GET(value) (((value) & 0x1f000000) >> 24) +/* Produces a ALT_QSPI_DEVRD_DUMMYRDCLKS register field value suitable for setting the register. */ +#define ALT_QSPI_DEVRD_DUMMYRDCLKS_SET(value) (((value) << 24) & 0x1f000000) + +#ifndef __ASSEMBLY__ +/* + * WARNING: The C register and register group struct declarations are provided for + * convenience and illustrative purposes. They should, however, be used with + * caution as the C language standard provides no guarantees about the alignment or + * atomicity of device memory accesses. The recommended practice for writing + * hardware drivers is to use the SoCAL access macros and alt_read_word() and + * alt_write_word() functions. + * + * The struct declaration for register ALT_QSPI_DEVRD. + */ +struct ALT_QSPI_DEVRD_s +{ + uint32_t rdopcode : 8; /* Read Opcode in non-XIP mode */ + uint32_t instwidth : 2; /* Instruction Transfer Width */ + uint32_t : 2; /* *UNDEFINED* */ + uint32_t addrwidth : 2; /* Address Transfer Width */ + uint32_t : 2; /* *UNDEFINED* */ + uint32_t datawidth : 2; /* Data Transfer Width */ + uint32_t : 2; /* *UNDEFINED* */ + uint32_t enmodebits : 1; /* Mode Bit Enable */ + uint32_t : 3; /* *UNDEFINED* */ + uint32_t dummyrdclks : 5; /* Dummy Read Clock Cycles */ + uint32_t : 3; /* *UNDEFINED* */ +}; + +/* The typedef declaration for register ALT_QSPI_DEVRD. */ +typedef volatile struct ALT_QSPI_DEVRD_s ALT_QSPI_DEVRD_t; +#endif /* __ASSEMBLY__ */ + +/* The byte offset of the ALT_QSPI_DEVRD register from the beginning of the component. */ +#define ALT_QSPI_DEVRD_OFST 0x4 + +/* + * Register : Device Write Instruction Register - devwr + * + * Register Layout + * + * Bits | Access | Reset | Description + * :--------|:-------|:------|:------------------------- + * [7:0] | RW | 0x2 | Write Opcode + * [11:8] | ??? | 0x0 | *UNDEFINED* + * [13:12] | RW | 0x0 | Address Transfer Width + * [15:14] | ??? | 0x0 | *UNDEFINED* + * [17:16] | RW | 0x0 | Data Transfer Width + * [23:18] | ??? | 0x0 | *UNDEFINED* + * [28:24] | RW | 0x0 | Dummy Write Clock Cycles + * [31:29] | ??? | 0x0 | *UNDEFINED* + * + */ +/* + * Field : Write Opcode - wropcode + * + * Write Opcode + * + * Field Access Macros: + * + */ +/* The Least Significant Bit (LSB) position of the ALT_QSPI_DEVWR_WROPCODE register field. */ +#define ALT_QSPI_DEVWR_WROPCODE_LSB 0 +/* The Most Significant Bit (MSB) position of the ALT_QSPI_DEVWR_WROPCODE register field. */ +#define ALT_QSPI_DEVWR_WROPCODE_MSB 7 +/* The width in bits of the ALT_QSPI_DEVWR_WROPCODE register field. */ +#define ALT_QSPI_DEVWR_WROPCODE_WIDTH 8 +/* The mask used to set the ALT_QSPI_DEVWR_WROPCODE register field value. */ +#define ALT_QSPI_DEVWR_WROPCODE_SET_MSK 0x000000ff +/* The mask used to clear the ALT_QSPI_DEVWR_WROPCODE register field value. */ +#define ALT_QSPI_DEVWR_WROPCODE_CLR_MSK 0xffffff00 +/* The reset value of the ALT_QSPI_DEVWR_WROPCODE register field. */ +#define ALT_QSPI_DEVWR_WROPCODE_RESET 0x2 +/* Extracts the ALT_QSPI_DEVWR_WROPCODE field value from a register. */ +#define ALT_QSPI_DEVWR_WROPCODE_GET(value) (((value) & 0x000000ff) >> 0) +/* Produces a ALT_QSPI_DEVWR_WROPCODE register field value suitable for setting the register. */ +#define ALT_QSPI_DEVWR_WROPCODE_SET(value) (((value) << 0) & 0x000000ff) + +/* + * Field : Address Transfer Width - addrwidth + * + * Sets write address transfer width (1, 2, or 4 bits). + * + * Field Enumeration Values: + * + * Enum | Value | Description + * :----------------------------------|:------|:------------------------------------------------- + * ALT_QSPI_DEVWR_ADDRWIDTH_E_SINGLE | 0x0 | Write address transferred on DQ0. Supported by + * : | | all SPI flash devices + * ALT_QSPI_DEVWR_ADDRWIDTH_E_DUAL | 0x1 | Read address transferred on DQ0 and DQ1. + * : | | Supported by some SPI flash devices that support + * : | | the Extended SPI Protocol and by all SPI flash + * : | | devices that support the Dual SP (DIO-SPI) + * : | | Protocol. + * ALT_QSPI_DEVWR_ADDRWIDTH_E_QUAD | 0x2 | Read address transferred on DQ0, DQ1, DQ2, and + * : | | DQ3. Supported by some SPI flash devices that + * : | | support the Extended SPI Protocol and by all SPI + * : | | flash devices that support the Quad SP (QIO-SPI) + * : | | Protocol. + * + * Field Access Macros: + * + */ +/* + * Enumerated value for register field ALT_QSPI_DEVWR_ADDRWIDTH + * + * Write address transferred on DQ0. Supported by all SPI flash devices + */ +#define ALT_QSPI_DEVWR_ADDRWIDTH_E_SINGLE 0x0 +/* + * Enumerated value for register field ALT_QSPI_DEVWR_ADDRWIDTH + * + * Read address transferred on DQ0 and DQ1. Supported by some SPI flash devices + * that support the Extended SPI Protocol and by all SPI flash devices that support + * the Dual SP (DIO-SPI) Protocol. + */ +#define ALT_QSPI_DEVWR_ADDRWIDTH_E_DUAL 0x1 +/* + * Enumerated value for register field ALT_QSPI_DEVWR_ADDRWIDTH + * + * Read address transferred on DQ0, DQ1, DQ2, and DQ3. Supported by some SPI flash + * devices that support the Extended SPI Protocol and by all SPI flash devices that + * support the Quad SP (QIO-SPI) Protocol. + */ +#define ALT_QSPI_DEVWR_ADDRWIDTH_E_QUAD 0x2 + +/* The Least Significant Bit (LSB) position of the ALT_QSPI_DEVWR_ADDRWIDTH register field. */ +#define ALT_QSPI_DEVWR_ADDRWIDTH_LSB 12 +/* The Most Significant Bit (MSB) position of the ALT_QSPI_DEVWR_ADDRWIDTH register field. */ +#define ALT_QSPI_DEVWR_ADDRWIDTH_MSB 13 +/* The width in bits of the ALT_QSPI_DEVWR_ADDRWIDTH register field. */ +#define ALT_QSPI_DEVWR_ADDRWIDTH_WIDTH 2 +/* The mask used to set the ALT_QSPI_DEVWR_ADDRWIDTH register field value. */ +#define ALT_QSPI_DEVWR_ADDRWIDTH_SET_MSK 0x00003000 +/* The mask used to clear the ALT_QSPI_DEVWR_ADDRWIDTH register field value. */ +#define ALT_QSPI_DEVWR_ADDRWIDTH_CLR_MSK 0xffffcfff +/* The reset value of the ALT_QSPI_DEVWR_ADDRWIDTH register field. */ +#define ALT_QSPI_DEVWR_ADDRWIDTH_RESET 0x0 +/* Extracts the ALT_QSPI_DEVWR_ADDRWIDTH field value from a register. */ +#define ALT_QSPI_DEVWR_ADDRWIDTH_GET(value) (((value) & 0x00003000) >> 12) +/* Produces a ALT_QSPI_DEVWR_ADDRWIDTH register field value suitable for setting the register. */ +#define ALT_QSPI_DEVWR_ADDRWIDTH_SET(value) (((value) << 12) & 0x00003000) + +/* + * Field : Data Transfer Width - datawidth + * + * Sets write data transfer width (1, 2, or 4 bits). + * + * Field Enumeration Values: + * + * Enum | Value | Description + * :----------------------------------|:------|:------------------------------------------------- + * ALT_QSPI_DEVWR_DATAWIDTH_E_SINGLE | 0x0 | Write data transferred on DQ0. Supported by all + * : | | SPI flash devices + * ALT_QSPI_DEVWR_DATAWIDTH_E_DUAL | 0x1 | Read data transferred on DQ0 and DQ1. Supported + * : | | by some SPI flash devices that support the + * : | | Extended SPI Protocol and by all SPI flash + * : | | devices that support the Dual SP (DIO-SPI) + * : | | Protocol. + * ALT_QSPI_DEVWR_DATAWIDTH_E_QUAD | 0x2 | Read data transferred on DQ0, DQ1, DQ2, and DQ3. + * : | | Supported by some SPI flash devices that support + * : | | the Extended SPI Protocol and by all SPI flash + * : | | devices that support the Quad SP (QIO-SPI) + * : | | Protocol. + * + * Field Access Macros: + * + */ +/* + * Enumerated value for register field ALT_QSPI_DEVWR_DATAWIDTH + * + * Write data transferred on DQ0. Supported by all SPI flash devices + */ +#define ALT_QSPI_DEVWR_DATAWIDTH_E_SINGLE 0x0 +/* + * Enumerated value for register field ALT_QSPI_DEVWR_DATAWIDTH + * + * Read data transferred on DQ0 and DQ1. Supported by some SPI flash devices that + * support the Extended SPI Protocol and by all SPI flash devices that support the + * Dual SP (DIO-SPI) Protocol. + */ +#define ALT_QSPI_DEVWR_DATAWIDTH_E_DUAL 0x1 +/* + * Enumerated value for register field ALT_QSPI_DEVWR_DATAWIDTH + * + * Read data transferred on DQ0, DQ1, DQ2, and DQ3. Supported by some SPI flash + * devices that support the Extended SPI Protocol and by all SPI flash devices that + * support the Quad SP (QIO-SPI) Protocol. + */ +#define ALT_QSPI_DEVWR_DATAWIDTH_E_QUAD 0x2 + +/* The Least Significant Bit (LSB) position of the ALT_QSPI_DEVWR_DATAWIDTH register field. */ +#define ALT_QSPI_DEVWR_DATAWIDTH_LSB 16 +/* The Most Significant Bit (MSB) position of the ALT_QSPI_DEVWR_DATAWIDTH register field. */ +#define ALT_QSPI_DEVWR_DATAWIDTH_MSB 17 +/* The width in bits of the ALT_QSPI_DEVWR_DATAWIDTH register field. */ +#define ALT_QSPI_DEVWR_DATAWIDTH_WIDTH 2 +/* The mask used to set the ALT_QSPI_DEVWR_DATAWIDTH register field value. */ +#define ALT_QSPI_DEVWR_DATAWIDTH_SET_MSK 0x00030000 +/* The mask used to clear the ALT_QSPI_DEVWR_DATAWIDTH register field value. */ +#define ALT_QSPI_DEVWR_DATAWIDTH_CLR_MSK 0xfffcffff +/* The reset value of the ALT_QSPI_DEVWR_DATAWIDTH register field. */ +#define ALT_QSPI_DEVWR_DATAWIDTH_RESET 0x0 +/* Extracts the ALT_QSPI_DEVWR_DATAWIDTH field value from a register. */ +#define ALT_QSPI_DEVWR_DATAWIDTH_GET(value) (((value) & 0x00030000) >> 16) +/* Produces a ALT_QSPI_DEVWR_DATAWIDTH register field value suitable for setting the register. */ +#define ALT_QSPI_DEVWR_DATAWIDTH_SET(value) (((value) << 16) & 0x00030000) + +/* + * Field : Dummy Write Clock Cycles - dummywrclks + * + * Number of dummy clock cycles required by device for write instruction. + * + * Field Access Macros: + * + */ +/* The Least Significant Bit (LSB) position of the ALT_QSPI_DEVWR_DUMMYWRCLKS register field. */ +#define ALT_QSPI_DEVWR_DUMMYWRCLKS_LSB 24 +/* The Most Significant Bit (MSB) position of the ALT_QSPI_DEVWR_DUMMYWRCLKS register field. */ +#define ALT_QSPI_DEVWR_DUMMYWRCLKS_MSB 28 +/* The width in bits of the ALT_QSPI_DEVWR_DUMMYWRCLKS register field. */ +#define ALT_QSPI_DEVWR_DUMMYWRCLKS_WIDTH 5 +/* The mask used to set the ALT_QSPI_DEVWR_DUMMYWRCLKS register field value. */ +#define ALT_QSPI_DEVWR_DUMMYWRCLKS_SET_MSK 0x1f000000 +/* The mask used to clear the ALT_QSPI_DEVWR_DUMMYWRCLKS register field value. */ +#define ALT_QSPI_DEVWR_DUMMYWRCLKS_CLR_MSK 0xe0ffffff +/* The reset value of the ALT_QSPI_DEVWR_DUMMYWRCLKS register field. */ +#define ALT_QSPI_DEVWR_DUMMYWRCLKS_RESET 0x0 +/* Extracts the ALT_QSPI_DEVWR_DUMMYWRCLKS field value from a register. */ +#define ALT_QSPI_DEVWR_DUMMYWRCLKS_GET(value) (((value) & 0x1f000000) >> 24) +/* Produces a ALT_QSPI_DEVWR_DUMMYWRCLKS register field value suitable for setting the register. */ +#define ALT_QSPI_DEVWR_DUMMYWRCLKS_SET(value) (((value) << 24) & 0x1f000000) + +#ifndef __ASSEMBLY__ +/* + * WARNING: The C register and register group struct declarations are provided for + * convenience and illustrative purposes. They should, however, be used with + * caution as the C language standard provides no guarantees about the alignment or + * atomicity of device memory accesses. The recommended practice for writing + * hardware drivers is to use the SoCAL access macros and alt_read_word() and + * alt_write_word() functions. + * + * The struct declaration for register ALT_QSPI_DEVWR. + */ +struct ALT_QSPI_DEVWR_s +{ + uint32_t wropcode : 8; /* Write Opcode */ + uint32_t : 4; /* *UNDEFINED* */ + uint32_t addrwidth : 2; /* Address Transfer Width */ + uint32_t : 2; /* *UNDEFINED* */ + uint32_t datawidth : 2; /* Data Transfer Width */ + uint32_t : 6; /* *UNDEFINED* */ + uint32_t dummywrclks : 5; /* Dummy Write Clock Cycles */ + uint32_t : 3; /* *UNDEFINED* */ +}; + +/* The typedef declaration for register ALT_QSPI_DEVWR. */ +typedef volatile struct ALT_QSPI_DEVWR_s ALT_QSPI_DEVWR_t; +#endif /* __ASSEMBLY__ */ + +/* The byte offset of the ALT_QSPI_DEVWR register from the beginning of the component. */ +#define ALT_QSPI_DEVWR_OFST 0x8 + +/* + * Register : QSPI Device Delay Register - delay + * + * This register is used to introduce relative delays into the generation of the + * master output signals. All timings are defined in cycles of the qspi_clk. + * + * Register Layout + * + * Bits | Access | Reset | Description + * :--------|:-------|:------|:----------------------------------------- + * [7:0] | RW | 0x0 | Clock Delay with qspi_n_ss_out + * [15:8] | RW | 0x0 | Clock Delay for Last Transaction Bit + * [23:16] | RW | 0x0 | Clock Delay for Chip Select Deactivation + * [31:24] | RW | 0x0 | Clock Delay for Chip Select Deassert + * + */ +/* + * Field : Clock Delay with qspi_n_ss_out - init + * + * Delay in master reference clocks between setting qspi_n_ss_out low and first bit + * transfer. + * + * Field Access Macros: + * + */ +/* The Least Significant Bit (LSB) position of the ALT_QSPI_DELAY_INIT register field. */ +#define ALT_QSPI_DELAY_INIT_LSB 0 +/* The Most Significant Bit (MSB) position of the ALT_QSPI_DELAY_INIT register field. */ +#define ALT_QSPI_DELAY_INIT_MSB 7 +/* The width in bits of the ALT_QSPI_DELAY_INIT register field. */ +#define ALT_QSPI_DELAY_INIT_WIDTH 8 +/* The mask used to set the ALT_QSPI_DELAY_INIT register field value. */ +#define ALT_QSPI_DELAY_INIT_SET_MSK 0x000000ff +/* The mask used to clear the ALT_QSPI_DELAY_INIT register field value. */ +#define ALT_QSPI_DELAY_INIT_CLR_MSK 0xffffff00 +/* The reset value of the ALT_QSPI_DELAY_INIT register field. */ +#define ALT_QSPI_DELAY_INIT_RESET 0x0 +/* Extracts the ALT_QSPI_DELAY_INIT field value from a register. */ +#define ALT_QSPI_DELAY_INIT_GET(value) (((value) & 0x000000ff) >> 0) +/* Produces a ALT_QSPI_DELAY_INIT register field value suitable for setting the register. */ +#define ALT_QSPI_DELAY_INIT_SET(value) (((value) << 0) & 0x000000ff) + +/* + * Field : Clock Delay for Last Transaction Bit - after + * + * Delay in master reference clocks between last bit of current transaction and + * deasserting the device chip select (qspi_n_ss_out). By default, the chip select + * will be deasserted on the cycle following the completion of the current + * transaction. + * + * Field Access Macros: + * + */ +/* The Least Significant Bit (LSB) position of the ALT_QSPI_DELAY_AFTER register field. */ +#define ALT_QSPI_DELAY_AFTER_LSB 8 +/* The Most Significant Bit (MSB) position of the ALT_QSPI_DELAY_AFTER register field. */ +#define ALT_QSPI_DELAY_AFTER_MSB 15 +/* The width in bits of the ALT_QSPI_DELAY_AFTER register field. */ +#define ALT_QSPI_DELAY_AFTER_WIDTH 8 +/* The mask used to set the ALT_QSPI_DELAY_AFTER register field value. */ +#define ALT_QSPI_DELAY_AFTER_SET_MSK 0x0000ff00 +/* The mask used to clear the ALT_QSPI_DELAY_AFTER register field value. */ +#define ALT_QSPI_DELAY_AFTER_CLR_MSK 0xffff00ff +/* The reset value of the ALT_QSPI_DELAY_AFTER register field. */ +#define ALT_QSPI_DELAY_AFTER_RESET 0x0 +/* Extracts the ALT_QSPI_DELAY_AFTER field value from a register. */ +#define ALT_QSPI_DELAY_AFTER_GET(value) (((value) & 0x0000ff00) >> 8) +/* Produces a ALT_QSPI_DELAY_AFTER register field value suitable for setting the register. */ +#define ALT_QSPI_DELAY_AFTER_SET(value) (((value) << 8) & 0x0000ff00) + +/* + * Field : Clock Delay for Chip Select Deactivation - btwn + * + * Delay in master reference clocks between one chip select being de-activated and + * the activation of another. This is used to ensure a quiet period between the + * selection of two different slaves and requires the transmit FIFO to be empty. + * + * Field Access Macros: + * + */ +/* The Least Significant Bit (LSB) position of the ALT_QSPI_DELAY_BTWN register field. */ +#define ALT_QSPI_DELAY_BTWN_LSB 16 +/* The Most Significant Bit (MSB) position of the ALT_QSPI_DELAY_BTWN register field. */ +#define ALT_QSPI_DELAY_BTWN_MSB 23 +/* The width in bits of the ALT_QSPI_DELAY_BTWN register field. */ +#define ALT_QSPI_DELAY_BTWN_WIDTH 8 +/* The mask used to set the ALT_QSPI_DELAY_BTWN register field value. */ +#define ALT_QSPI_DELAY_BTWN_SET_MSK 0x00ff0000 +/* The mask used to clear the ALT_QSPI_DELAY_BTWN register field value. */ +#define ALT_QSPI_DELAY_BTWN_CLR_MSK 0xff00ffff +/* The reset value of the ALT_QSPI_DELAY_BTWN register field. */ +#define ALT_QSPI_DELAY_BTWN_RESET 0x0 +/* Extracts the ALT_QSPI_DELAY_BTWN field value from a register. */ +#define ALT_QSPI_DELAY_BTWN_GET(value) (((value) & 0x00ff0000) >> 16) +/* Produces a ALT_QSPI_DELAY_BTWN register field value suitable for setting the register. */ +#define ALT_QSPI_DELAY_BTWN_SET(value) (((value) << 16) & 0x00ff0000) + +/* + * Field : Clock Delay for Chip Select Deassert - nss + * + * Delay in master reference clocks for the length that the master mode chip select + * outputs are de-asserted between transactions. The minimum delay is always + * qspi_sck_out period to ensure the chip select is never re-asserted within an + * qspi_sck_out period. + * + * Field Access Macros: + * + */ +/* The Least Significant Bit (LSB) position of the ALT_QSPI_DELAY_NSS register field. */ +#define ALT_QSPI_DELAY_NSS_LSB 24 +/* The Most Significant Bit (MSB) position of the ALT_QSPI_DELAY_NSS register field. */ +#define ALT_QSPI_DELAY_NSS_MSB 31 +/* The width in bits of the ALT_QSPI_DELAY_NSS register field. */ +#define ALT_QSPI_DELAY_NSS_WIDTH 8 +/* The mask used to set the ALT_QSPI_DELAY_NSS register field value. */ +#define ALT_QSPI_DELAY_NSS_SET_MSK 0xff000000 +/* The mask used to clear the ALT_QSPI_DELAY_NSS register field value. */ +#define ALT_QSPI_DELAY_NSS_CLR_MSK 0x00ffffff +/* The reset value of the ALT_QSPI_DELAY_NSS register field. */ +#define ALT_QSPI_DELAY_NSS_RESET 0x0 +/* Extracts the ALT_QSPI_DELAY_NSS field value from a register. */ +#define ALT_QSPI_DELAY_NSS_GET(value) (((value) & 0xff000000) >> 24) +/* Produces a ALT_QSPI_DELAY_NSS register field value suitable for setting the register. */ +#define ALT_QSPI_DELAY_NSS_SET(value) (((value) << 24) & 0xff000000) + +#ifndef __ASSEMBLY__ +/* + * WARNING: The C register and register group struct declarations are provided for + * convenience and illustrative purposes. They should, however, be used with + * caution as the C language standard provides no guarantees about the alignment or + * atomicity of device memory accesses. The recommended practice for writing + * hardware drivers is to use the SoCAL access macros and alt_read_word() and + * alt_write_word() functions. + * + * The struct declaration for register ALT_QSPI_DELAY. + */ +struct ALT_QSPI_DELAY_s +{ + uint32_t init : 8; /* Clock Delay with qspi_n_ss_out */ + uint32_t after : 8; /* Clock Delay for Last Transaction Bit */ + uint32_t btwn : 8; /* Clock Delay for Chip Select Deactivation */ + uint32_t nss : 8; /* Clock Delay for Chip Select Deassert */ +}; + +/* The typedef declaration for register ALT_QSPI_DELAY. */ +typedef volatile struct ALT_QSPI_DELAY_s ALT_QSPI_DELAY_t; +#endif /* __ASSEMBLY__ */ + +/* The byte offset of the ALT_QSPI_DELAY register from the beginning of the component. */ +#define ALT_QSPI_DELAY_OFST 0xc + +/* + * Register : Read Data Capture Register - rddatacap + * + * Register Layout + * + * Bits | Access | Reset | Description + * :-------|:-------|:------|:------------ + * [0] | RW | 0x1 | Bypass + * [4:1] | RW | 0x0 | Read Delay + * [31:5] | ??? | 0x0 | *UNDEFINED* + * + */ +/* + * Field : Bypass - byp + * + * Controls bypass of the adapted loopback clock circuit + * + * Field Enumeration Values: + * + * Enum | Value | Description + * :----------------------------------|:------|:------------------------------ + * ALT_QSPI_RDDATACAP_BYP_E_NOBYPASS | 0x0 | No Bypass + * ALT_QSPI_RDDATACAP_BYP_E_BYPASS | 0x1 | Bypass loopback clock circuit + * + * Field Access Macros: + * + */ +/* + * Enumerated value for register field ALT_QSPI_RDDATACAP_BYP + * + * No Bypass + */ +#define ALT_QSPI_RDDATACAP_BYP_E_NOBYPASS 0x0 +/* + * Enumerated value for register field ALT_QSPI_RDDATACAP_BYP + * + * Bypass loopback clock circuit + */ +#define ALT_QSPI_RDDATACAP_BYP_E_BYPASS 0x1 + +/* The Least Significant Bit (LSB) position of the ALT_QSPI_RDDATACAP_BYP register field. */ +#define ALT_QSPI_RDDATACAP_BYP_LSB 0 +/* The Most Significant Bit (MSB) position of the ALT_QSPI_RDDATACAP_BYP register field. */ +#define ALT_QSPI_RDDATACAP_BYP_MSB 0 +/* The width in bits of the ALT_QSPI_RDDATACAP_BYP register field. */ +#define ALT_QSPI_RDDATACAP_BYP_WIDTH 1 +/* The mask used to set the ALT_QSPI_RDDATACAP_BYP register field value. */ +#define ALT_QSPI_RDDATACAP_BYP_SET_MSK 0x00000001 +/* The mask used to clear the ALT_QSPI_RDDATACAP_BYP register field value. */ +#define ALT_QSPI_RDDATACAP_BYP_CLR_MSK 0xfffffffe +/* The reset value of the ALT_QSPI_RDDATACAP_BYP register field. */ +#define ALT_QSPI_RDDATACAP_BYP_RESET 0x1 +/* Extracts the ALT_QSPI_RDDATACAP_BYP field value from a register. */ +#define ALT_QSPI_RDDATACAP_BYP_GET(value) (((value) & 0x00000001) >> 0) +/* Produces a ALT_QSPI_RDDATACAP_BYP register field value suitable for setting the register. */ +#define ALT_QSPI_RDDATACAP_BYP_SET(value) (((value) << 0) & 0x00000001) + +/* + * Field : Read Delay - delay + * + * Delay the read data capturing logic by the programmed number of qspi_clk cycles + * + * Field Access Macros: + * + */ +/* The Least Significant Bit (LSB) position of the ALT_QSPI_RDDATACAP_DELAY register field. */ +#define ALT_QSPI_RDDATACAP_DELAY_LSB 1 +/* The Most Significant Bit (MSB) position of the ALT_QSPI_RDDATACAP_DELAY register field. */ +#define ALT_QSPI_RDDATACAP_DELAY_MSB 4 +/* The width in bits of the ALT_QSPI_RDDATACAP_DELAY register field. */ +#define ALT_QSPI_RDDATACAP_DELAY_WIDTH 4 +/* The mask used to set the ALT_QSPI_RDDATACAP_DELAY register field value. */ +#define ALT_QSPI_RDDATACAP_DELAY_SET_MSK 0x0000001e +/* The mask used to clear the ALT_QSPI_RDDATACAP_DELAY register field value. */ +#define ALT_QSPI_RDDATACAP_DELAY_CLR_MSK 0xffffffe1 +/* The reset value of the ALT_QSPI_RDDATACAP_DELAY register field. */ +#define ALT_QSPI_RDDATACAP_DELAY_RESET 0x0 +/* Extracts the ALT_QSPI_RDDATACAP_DELAY field value from a register. */ +#define ALT_QSPI_RDDATACAP_DELAY_GET(value) (((value) & 0x0000001e) >> 1) +/* Produces a ALT_QSPI_RDDATACAP_DELAY register field value suitable for setting the register. */ +#define ALT_QSPI_RDDATACAP_DELAY_SET(value) (((value) << 1) & 0x0000001e) + +#ifndef __ASSEMBLY__ +/* + * WARNING: The C register and register group struct declarations are provided for + * convenience and illustrative purposes. They should, however, be used with + * caution as the C language standard provides no guarantees about the alignment or + * atomicity of device memory accesses. The recommended practice for writing + * hardware drivers is to use the SoCAL access macros and alt_read_word() and + * alt_write_word() functions. + * + * The struct declaration for register ALT_QSPI_RDDATACAP. + */ +struct ALT_QSPI_RDDATACAP_s +{ + uint32_t byp : 1; /* Bypass */ + uint32_t delay : 4; /* Read Delay */ + uint32_t : 27; /* *UNDEFINED* */ +}; + +/* The typedef declaration for register ALT_QSPI_RDDATACAP. */ +typedef volatile struct ALT_QSPI_RDDATACAP_s ALT_QSPI_RDDATACAP_t; +#endif /* __ASSEMBLY__ */ + +/* The byte offset of the ALT_QSPI_RDDATACAP register from the beginning of the component. */ +#define ALT_QSPI_RDDATACAP_OFST 0x10 + +/* + * Register : Device Size Register - devsz + * + * Register Layout + * + * Bits | Access | Reset | Description + * :--------|:-------|:------|:-------------------------------- + * [3:0] | RW | 0x2 | Number of address Bytes + * [15:4] | RW | 0x100 | Number of Bytes per Device Page + * [20:16] | RW | 0x10 | Number of Bytes per Block + * [31:21] | ??? | 0x0 | *UNDEFINED* + * + */ +/* + * Field : Number of address Bytes - numaddrbytes + * + * Number of address bytes. A value of 0 indicates 1 byte. + * + * Field Access Macros: + * + */ +/* The Least Significant Bit (LSB) position of the ALT_QSPI_DEVSZ_NUMADDRBYTES register field. */ +#define ALT_QSPI_DEVSZ_NUMADDRBYTES_LSB 0 +/* The Most Significant Bit (MSB) position of the ALT_QSPI_DEVSZ_NUMADDRBYTES register field. */ +#define ALT_QSPI_DEVSZ_NUMADDRBYTES_MSB 3 +/* The width in bits of the ALT_QSPI_DEVSZ_NUMADDRBYTES register field. */ +#define ALT_QSPI_DEVSZ_NUMADDRBYTES_WIDTH 4 +/* The mask used to set the ALT_QSPI_DEVSZ_NUMADDRBYTES register field value. */ +#define ALT_QSPI_DEVSZ_NUMADDRBYTES_SET_MSK 0x0000000f +/* The mask used to clear the ALT_QSPI_DEVSZ_NUMADDRBYTES register field value. */ +#define ALT_QSPI_DEVSZ_NUMADDRBYTES_CLR_MSK 0xfffffff0 +/* The reset value of the ALT_QSPI_DEVSZ_NUMADDRBYTES register field. */ +#define ALT_QSPI_DEVSZ_NUMADDRBYTES_RESET 0x2 +/* Extracts the ALT_QSPI_DEVSZ_NUMADDRBYTES field value from a register. */ +#define ALT_QSPI_DEVSZ_NUMADDRBYTES_GET(value) (((value) & 0x0000000f) >> 0) +/* Produces a ALT_QSPI_DEVSZ_NUMADDRBYTES register field value suitable for setting the register. */ +#define ALT_QSPI_DEVSZ_NUMADDRBYTES_SET(value) (((value) << 0) & 0x0000000f) + +/* + * Field : Number of Bytes per Device Page - bytesperdevicepage + * + * Number of bytes per device page. This is required by the controller for + * performing FLASH writes up to and across page boundaries. + * + * Field Access Macros: + * + */ +/* The Least Significant Bit (LSB) position of the ALT_QSPI_DEVSZ_BYTESPERDEVICEPAGE register field. */ +#define ALT_QSPI_DEVSZ_BYTESPERDEVICEPAGE_LSB 4 +/* The Most Significant Bit (MSB) position of the ALT_QSPI_DEVSZ_BYTESPERDEVICEPAGE register field. */ +#define ALT_QSPI_DEVSZ_BYTESPERDEVICEPAGE_MSB 15 +/* The width in bits of the ALT_QSPI_DEVSZ_BYTESPERDEVICEPAGE register field. */ +#define ALT_QSPI_DEVSZ_BYTESPERDEVICEPAGE_WIDTH 12 +/* The mask used to set the ALT_QSPI_DEVSZ_BYTESPERDEVICEPAGE register field value. */ +#define ALT_QSPI_DEVSZ_BYTESPERDEVICEPAGE_SET_MSK 0x0000fff0 +/* The mask used to clear the ALT_QSPI_DEVSZ_BYTESPERDEVICEPAGE register field value. */ +#define ALT_QSPI_DEVSZ_BYTESPERDEVICEPAGE_CLR_MSK 0xffff000f +/* The reset value of the ALT_QSPI_DEVSZ_BYTESPERDEVICEPAGE register field. */ +#define ALT_QSPI_DEVSZ_BYTESPERDEVICEPAGE_RESET 0x100 +/* Extracts the ALT_QSPI_DEVSZ_BYTESPERDEVICEPAGE field value from a register. */ +#define ALT_QSPI_DEVSZ_BYTESPERDEVICEPAGE_GET(value) (((value) & 0x0000fff0) >> 4) +/* Produces a ALT_QSPI_DEVSZ_BYTESPERDEVICEPAGE register field value suitable for setting the register. */ +#define ALT_QSPI_DEVSZ_BYTESPERDEVICEPAGE_SET(value) (((value) << 4) & 0x0000fff0) + +/* + * Field : Number of Bytes per Block - bytespersubsector + * + * Number of bytes per Block. This is required by the controller for performing the + * write protection logic. The number of bytes per block must be a power of 2 + * number. + * + * Field Access Macros: + * + */ +/* The Least Significant Bit (LSB) position of the ALT_QSPI_DEVSZ_BYTESPERSUBSECTOR register field. */ +#define ALT_QSPI_DEVSZ_BYTESPERSUBSECTOR_LSB 16 +/* The Most Significant Bit (MSB) position of the ALT_QSPI_DEVSZ_BYTESPERSUBSECTOR register field. */ +#define ALT_QSPI_DEVSZ_BYTESPERSUBSECTOR_MSB 20 +/* The width in bits of the ALT_QSPI_DEVSZ_BYTESPERSUBSECTOR register field. */ +#define ALT_QSPI_DEVSZ_BYTESPERSUBSECTOR_WIDTH 5 +/* The mask used to set the ALT_QSPI_DEVSZ_BYTESPERSUBSECTOR register field value. */ +#define ALT_QSPI_DEVSZ_BYTESPERSUBSECTOR_SET_MSK 0x001f0000 +/* The mask used to clear the ALT_QSPI_DEVSZ_BYTESPERSUBSECTOR register field value. */ +#define ALT_QSPI_DEVSZ_BYTESPERSUBSECTOR_CLR_MSK 0xffe0ffff +/* The reset value of the ALT_QSPI_DEVSZ_BYTESPERSUBSECTOR register field. */ +#define ALT_QSPI_DEVSZ_BYTESPERSUBSECTOR_RESET 0x10 +/* Extracts the ALT_QSPI_DEVSZ_BYTESPERSUBSECTOR field value from a register. */ +#define ALT_QSPI_DEVSZ_BYTESPERSUBSECTOR_GET(value) (((value) & 0x001f0000) >> 16) +/* Produces a ALT_QSPI_DEVSZ_BYTESPERSUBSECTOR register field value suitable for setting the register. */ +#define ALT_QSPI_DEVSZ_BYTESPERSUBSECTOR_SET(value) (((value) << 16) & 0x001f0000) + +#ifndef __ASSEMBLY__ +/* + * WARNING: The C register and register group struct declarations are provided for + * convenience and illustrative purposes. They should, however, be used with + * caution as the C language standard provides no guarantees about the alignment or + * atomicity of device memory accesses. The recommended practice for writing + * hardware drivers is to use the SoCAL access macros and alt_read_word() and + * alt_write_word() functions. + * + * The struct declaration for register ALT_QSPI_DEVSZ. + */ +struct ALT_QSPI_DEVSZ_s +{ + uint32_t numaddrbytes : 4; /* Number of address Bytes */ + uint32_t bytesperdevicepage : 12; /* Number of Bytes per Device Page */ + uint32_t bytespersubsector : 5; /* Number of Bytes per Block */ + uint32_t : 11; /* *UNDEFINED* */ +}; + +/* The typedef declaration for register ALT_QSPI_DEVSZ. */ +typedef volatile struct ALT_QSPI_DEVSZ_s ALT_QSPI_DEVSZ_t; +#endif /* __ASSEMBLY__ */ + +/* The byte offset of the ALT_QSPI_DEVSZ register from the beginning of the component. */ +#define ALT_QSPI_DEVSZ_OFST 0x14 + +/* + * Register : SRAM Partition Register - srampart + * + * Register Layout + * + * Bits | Access | Reset | Description + * :-------|:-------|:------|:----------------------------- + * [6:0] | RW | 0x40 | Indirect Read Partition Size + * [31:7] | ??? | 0x0 | *UNDEFINED* + * + */ +/* + * Field : Indirect Read Partition Size - addr + * + * Defines the size of the indirect read partition in the SRAM, in units of SRAM + * locations. By default, half of the SRAM is reserved for indirect read operations + * and half for indirect write operations. + * + * Field Access Macros: + * + */ +/* The Least Significant Bit (LSB) position of the ALT_QSPI_SRAMPART_ADDR register field. */ +#define ALT_QSPI_SRAMPART_ADDR_LSB 0 +/* The Most Significant Bit (MSB) position of the ALT_QSPI_SRAMPART_ADDR register field. */ +#define ALT_QSPI_SRAMPART_ADDR_MSB 6 +/* The width in bits of the ALT_QSPI_SRAMPART_ADDR register field. */ +#define ALT_QSPI_SRAMPART_ADDR_WIDTH 7 +/* The mask used to set the ALT_QSPI_SRAMPART_ADDR register field value. */ +#define ALT_QSPI_SRAMPART_ADDR_SET_MSK 0x0000007f +/* The mask used to clear the ALT_QSPI_SRAMPART_ADDR register field value. */ +#define ALT_QSPI_SRAMPART_ADDR_CLR_MSK 0xffffff80 +/* The reset value of the ALT_QSPI_SRAMPART_ADDR register field. */ +#define ALT_QSPI_SRAMPART_ADDR_RESET 0x40 +/* Extracts the ALT_QSPI_SRAMPART_ADDR field value from a register. */ +#define ALT_QSPI_SRAMPART_ADDR_GET(value) (((value) & 0x0000007f) >> 0) +/* Produces a ALT_QSPI_SRAMPART_ADDR register field value suitable for setting the register. */ +#define ALT_QSPI_SRAMPART_ADDR_SET(value) (((value) << 0) & 0x0000007f) + +#ifndef __ASSEMBLY__ +/* + * WARNING: The C register and register group struct declarations are provided for + * convenience and illustrative purposes. They should, however, be used with + * caution as the C language standard provides no guarantees about the alignment or + * atomicity of device memory accesses. The recommended practice for writing + * hardware drivers is to use the SoCAL access macros and alt_read_word() and + * alt_write_word() functions. + * + * The struct declaration for register ALT_QSPI_SRAMPART. + */ +struct ALT_QSPI_SRAMPART_s +{ + uint32_t addr : 7; /* Indirect Read Partition Size */ + uint32_t : 25; /* *UNDEFINED* */ +}; + +/* The typedef declaration for register ALT_QSPI_SRAMPART. */ +typedef volatile struct ALT_QSPI_SRAMPART_s ALT_QSPI_SRAMPART_t; +#endif /* __ASSEMBLY__ */ + +/* The byte offset of the ALT_QSPI_SRAMPART register from the beginning of the component. */ +#define ALT_QSPI_SRAMPART_OFST 0x18 + +/* + * Register : Indirect AHB Address Trigger Register - indaddrtrig + * + * Register Layout + * + * Bits | Access | Reset | Description + * :-------|:-------|:------|:---------------- + * [31:0] | RW | 0x0 | Trigger Address + * + */ +/* + * Field : Trigger Address - addr + * + * This is the base address that will be used by the AHB controller. When the + * incoming AHB read access address matches a range of addresses from this trigger + * address to the trigger address + 15, then the AHB request will be completed by + * fetching data from the Indirect Controllers SRAM. + * + * Field Access Macros: + * + */ +/* The Least Significant Bit (LSB) position of the ALT_QSPI_INDADDRTRIG_ADDR register field. */ +#define ALT_QSPI_INDADDRTRIG_ADDR_LSB 0 +/* The Most Significant Bit (MSB) position of the ALT_QSPI_INDADDRTRIG_ADDR register field. */ +#define ALT_QSPI_INDADDRTRIG_ADDR_MSB 31 +/* The width in bits of the ALT_QSPI_INDADDRTRIG_ADDR register field. */ +#define ALT_QSPI_INDADDRTRIG_ADDR_WIDTH 32 +/* The mask used to set the ALT_QSPI_INDADDRTRIG_ADDR register field value. */ +#define ALT_QSPI_INDADDRTRIG_ADDR_SET_MSK 0xffffffff +/* The mask used to clear the ALT_QSPI_INDADDRTRIG_ADDR register field value. */ +#define ALT_QSPI_INDADDRTRIG_ADDR_CLR_MSK 0x00000000 +/* The reset value of the ALT_QSPI_INDADDRTRIG_ADDR register field. */ +#define ALT_QSPI_INDADDRTRIG_ADDR_RESET 0x0 +/* Extracts the ALT_QSPI_INDADDRTRIG_ADDR field value from a register. */ +#define ALT_QSPI_INDADDRTRIG_ADDR_GET(value) (((value) & 0xffffffff) >> 0) +/* Produces a ALT_QSPI_INDADDRTRIG_ADDR register field value suitable for setting the register. */ +#define ALT_QSPI_INDADDRTRIG_ADDR_SET(value) (((value) << 0) & 0xffffffff) + +#ifndef __ASSEMBLY__ +/* + * WARNING: The C register and register group struct declarations are provided for + * convenience and illustrative purposes. They should, however, be used with + * caution as the C language standard provides no guarantees about the alignment or + * atomicity of device memory accesses. The recommended practice for writing + * hardware drivers is to use the SoCAL access macros and alt_read_word() and + * alt_write_word() functions. + * + * The struct declaration for register ALT_QSPI_INDADDRTRIG. + */ +struct ALT_QSPI_INDADDRTRIG_s +{ + uint32_t addr : 32; /* Trigger Address */ +}; + +/* The typedef declaration for register ALT_QSPI_INDADDRTRIG. */ +typedef volatile struct ALT_QSPI_INDADDRTRIG_s ALT_QSPI_INDADDRTRIG_t; +#endif /* __ASSEMBLY__ */ + +/* The byte offset of the ALT_QSPI_INDADDRTRIG register from the beginning of the component. */ +#define ALT_QSPI_INDADDRTRIG_OFST 0x1c + +/* + * Register : DMA Peripheral Register - dmaper + * + * Register Layout + * + * Bits | Access | Reset | Description + * :--------|:-------|:------|:----------------------- + * [3:0] | RW | 0x0 | Number of Single Bytes + * [7:4] | ??? | 0x0 | *UNDEFINED* + * [11:8] | RW | 0x0 | Number of Burst Bytes + * [31:12] | ??? | 0x0 | *UNDEFINED* + * + */ +/* + * Field : Number of Single Bytes - numsglreqbytes + * + * Number of bytes in a single type request on the DMA peripheral request. A + * programmed value of 0 represents a single byte. This should be setup before + * starting the indirect read or write operation. The actual number of bytes used + * is 2**(value in this register) which will simplify implementation. + * + * Field Access Macros: + * + */ +/* The Least Significant Bit (LSB) position of the ALT_QSPI_DMAPER_NUMSGLREQBYTES register field. */ +#define ALT_QSPI_DMAPER_NUMSGLREQBYTES_LSB 0 +/* The Most Significant Bit (MSB) position of the ALT_QSPI_DMAPER_NUMSGLREQBYTES register field. */ +#define ALT_QSPI_DMAPER_NUMSGLREQBYTES_MSB 3 +/* The width in bits of the ALT_QSPI_DMAPER_NUMSGLREQBYTES register field. */ +#define ALT_QSPI_DMAPER_NUMSGLREQBYTES_WIDTH 4 +/* The mask used to set the ALT_QSPI_DMAPER_NUMSGLREQBYTES register field value. */ +#define ALT_QSPI_DMAPER_NUMSGLREQBYTES_SET_MSK 0x0000000f +/* The mask used to clear the ALT_QSPI_DMAPER_NUMSGLREQBYTES register field value. */ +#define ALT_QSPI_DMAPER_NUMSGLREQBYTES_CLR_MSK 0xfffffff0 +/* The reset value of the ALT_QSPI_DMAPER_NUMSGLREQBYTES register field. */ +#define ALT_QSPI_DMAPER_NUMSGLREQBYTES_RESET 0x0 +/* Extracts the ALT_QSPI_DMAPER_NUMSGLREQBYTES field value from a register. */ +#define ALT_QSPI_DMAPER_NUMSGLREQBYTES_GET(value) (((value) & 0x0000000f) >> 0) +/* Produces a ALT_QSPI_DMAPER_NUMSGLREQBYTES register field value suitable for setting the register. */ +#define ALT_QSPI_DMAPER_NUMSGLREQBYTES_SET(value) (((value) << 0) & 0x0000000f) + +/* + * Field : Number of Burst Bytes - numburstreqbytes + * + * Number of bytes in a burst type request on the DMA peripheral request. A + * programmed value of 0 represents a single byte. This should be setup before + * starting the indirect read or write operation. The actual number of bytes used + * is 2**(value in this register) which will simplify implementation. + * + * Field Access Macros: + * + */ +/* The Least Significant Bit (LSB) position of the ALT_QSPI_DMAPER_NUMBURSTREQBYTES register field. */ +#define ALT_QSPI_DMAPER_NUMBURSTREQBYTES_LSB 8 +/* The Most Significant Bit (MSB) position of the ALT_QSPI_DMAPER_NUMBURSTREQBYTES register field. */ +#define ALT_QSPI_DMAPER_NUMBURSTREQBYTES_MSB 11 +/* The width in bits of the ALT_QSPI_DMAPER_NUMBURSTREQBYTES register field. */ +#define ALT_QSPI_DMAPER_NUMBURSTREQBYTES_WIDTH 4 +/* The mask used to set the ALT_QSPI_DMAPER_NUMBURSTREQBYTES register field value. */ +#define ALT_QSPI_DMAPER_NUMBURSTREQBYTES_SET_MSK 0x00000f00 +/* The mask used to clear the ALT_QSPI_DMAPER_NUMBURSTREQBYTES register field value. */ +#define ALT_QSPI_DMAPER_NUMBURSTREQBYTES_CLR_MSK 0xfffff0ff +/* The reset value of the ALT_QSPI_DMAPER_NUMBURSTREQBYTES register field. */ +#define ALT_QSPI_DMAPER_NUMBURSTREQBYTES_RESET 0x0 +/* Extracts the ALT_QSPI_DMAPER_NUMBURSTREQBYTES field value from a register. */ +#define ALT_QSPI_DMAPER_NUMBURSTREQBYTES_GET(value) (((value) & 0x00000f00) >> 8) +/* Produces a ALT_QSPI_DMAPER_NUMBURSTREQBYTES register field value suitable for setting the register. */ +#define ALT_QSPI_DMAPER_NUMBURSTREQBYTES_SET(value) (((value) << 8) & 0x00000f00) + +#ifndef __ASSEMBLY__ +/* + * WARNING: The C register and register group struct declarations are provided for + * convenience and illustrative purposes. They should, however, be used with + * caution as the C language standard provides no guarantees about the alignment or + * atomicity of device memory accesses. The recommended practice for writing + * hardware drivers is to use the SoCAL access macros and alt_read_word() and + * alt_write_word() functions. + * + * The struct declaration for register ALT_QSPI_DMAPER. + */ +struct ALT_QSPI_DMAPER_s +{ + uint32_t numsglreqbytes : 4; /* Number of Single Bytes */ + uint32_t : 4; /* *UNDEFINED* */ + uint32_t numburstreqbytes : 4; /* Number of Burst Bytes */ + uint32_t : 20; /* *UNDEFINED* */ +}; + +/* The typedef declaration for register ALT_QSPI_DMAPER. */ +typedef volatile struct ALT_QSPI_DMAPER_s ALT_QSPI_DMAPER_t; +#endif /* __ASSEMBLY__ */ + +/* The byte offset of the ALT_QSPI_DMAPER register from the beginning of the component. */ +#define ALT_QSPI_DMAPER_OFST 0x20 + +/* + * Register : Remap Address Register - remapaddr + * + * This register is used to remap an incoming AHB address to a different address + * used by the FLASH device. + * + * Register Layout + * + * Bits | Access | Reset | Description + * :-------|:-------|:------|:--------------------- + * [31:0] | RW | 0x0 | Remap Address Offset + * + */ +/* + * Field : Remap Address Offset - value + * + * This offset is added to the incoming AHB address to determine the address used + * by the FLASH device. + * + * Field Access Macros: + * + */ +/* The Least Significant Bit (LSB) position of the ALT_QSPI_REMAPADDR_VALUE register field. */ +#define ALT_QSPI_REMAPADDR_VALUE_LSB 0 +/* The Most Significant Bit (MSB) position of the ALT_QSPI_REMAPADDR_VALUE register field. */ +#define ALT_QSPI_REMAPADDR_VALUE_MSB 31 +/* The width in bits of the ALT_QSPI_REMAPADDR_VALUE register field. */ +#define ALT_QSPI_REMAPADDR_VALUE_WIDTH 32 +/* The mask used to set the ALT_QSPI_REMAPADDR_VALUE register field value. */ +#define ALT_QSPI_REMAPADDR_VALUE_SET_MSK 0xffffffff +/* The mask used to clear the ALT_QSPI_REMAPADDR_VALUE register field value. */ +#define ALT_QSPI_REMAPADDR_VALUE_CLR_MSK 0x00000000 +/* The reset value of the ALT_QSPI_REMAPADDR_VALUE register field. */ +#define ALT_QSPI_REMAPADDR_VALUE_RESET 0x0 +/* Extracts the ALT_QSPI_REMAPADDR_VALUE field value from a register. */ +#define ALT_QSPI_REMAPADDR_VALUE_GET(value) (((value) & 0xffffffff) >> 0) +/* Produces a ALT_QSPI_REMAPADDR_VALUE register field value suitable for setting the register. */ +#define ALT_QSPI_REMAPADDR_VALUE_SET(value) (((value) << 0) & 0xffffffff) + +#ifndef __ASSEMBLY__ +/* + * WARNING: The C register and register group struct declarations are provided for + * convenience and illustrative purposes. They should, however, be used with + * caution as the C language standard provides no guarantees about the alignment or + * atomicity of device memory accesses. The recommended practice for writing + * hardware drivers is to use the SoCAL access macros and alt_read_word() and + * alt_write_word() functions. + * + * The struct declaration for register ALT_QSPI_REMAPADDR. + */ +struct ALT_QSPI_REMAPADDR_s +{ + uint32_t value : 32; /* Remap Address Offset */ +}; + +/* The typedef declaration for register ALT_QSPI_REMAPADDR. */ +typedef volatile struct ALT_QSPI_REMAPADDR_s ALT_QSPI_REMAPADDR_t; +#endif /* __ASSEMBLY__ */ + +/* The byte offset of the ALT_QSPI_REMAPADDR register from the beginning of the component. */ +#define ALT_QSPI_REMAPADDR_OFST 0x24 + +/* + * Register : Mode Bit Register - modebit + * + * Register Layout + * + * Bits | Access | Reset | Description + * :-------|:-------|:------|:------------ + * [7:0] | RW | 0x0 | Mode + * [31:8] | ??? | 0x0 | *UNDEFINED* + * + */ +/* + * Field : Mode - mode + * + * These are the 8 mode bits that are sent to the device following the address + * bytes if mode bit transmission has been enabled. + * + * Field Access Macros: + * + */ +/* The Least Significant Bit (LSB) position of the ALT_QSPI_MODBIT_MOD register field. */ +#define ALT_QSPI_MODBIT_MOD_LSB 0 +/* The Most Significant Bit (MSB) position of the ALT_QSPI_MODBIT_MOD register field. */ +#define ALT_QSPI_MODBIT_MOD_MSB 7 +/* The width in bits of the ALT_QSPI_MODBIT_MOD register field. */ +#define ALT_QSPI_MODBIT_MOD_WIDTH 8 +/* The mask used to set the ALT_QSPI_MODBIT_MOD register field value. */ +#define ALT_QSPI_MODBIT_MOD_SET_MSK 0x000000ff +/* The mask used to clear the ALT_QSPI_MODBIT_MOD register field value. */ +#define ALT_QSPI_MODBIT_MOD_CLR_MSK 0xffffff00 +/* The reset value of the ALT_QSPI_MODBIT_MOD register field. */ +#define ALT_QSPI_MODBIT_MOD_RESET 0x0 +/* Extracts the ALT_QSPI_MODBIT_MOD field value from a register. */ +#define ALT_QSPI_MODBIT_MOD_GET(value) (((value) & 0x000000ff) >> 0) +/* Produces a ALT_QSPI_MODBIT_MOD register field value suitable for setting the register. */ +#define ALT_QSPI_MODBIT_MOD_SET(value) (((value) << 0) & 0x000000ff) + +#ifndef __ASSEMBLY__ +/* + * WARNING: The C register and register group struct declarations are provided for + * convenience and illustrative purposes. They should, however, be used with + * caution as the C language standard provides no guarantees about the alignment or + * atomicity of device memory accesses. The recommended practice for writing + * hardware drivers is to use the SoCAL access macros and alt_read_word() and + * alt_write_word() functions. + * + * The struct declaration for register ALT_QSPI_MODBIT. + */ +struct ALT_QSPI_MODBIT_s +{ + uint32_t mode : 8; /* Mode */ + uint32_t : 24; /* *UNDEFINED* */ +}; + +/* The typedef declaration for register ALT_QSPI_MODBIT. */ +typedef volatile struct ALT_QSPI_MODBIT_s ALT_QSPI_MODBIT_t; +#endif /* __ASSEMBLY__ */ + +/* The byte offset of the ALT_QSPI_MODBIT register from the beginning of the component. */ +#define ALT_QSPI_MODBIT_OFST 0x28 + +/* + * Register : SRAM Fill Register - sramfill + * + * Register Layout + * + * Bits | Access | Reset | Description + * :--------|:-------|:------|:------------------------------------------------------------------- + * [15:0] | R | 0x0 | SRAM Fill Level (Indirect Read Partition). In units of SRAM WORDS + * [31:16] | R | 0x0 | SRAM Fill Level (Indirect Write Partition). In units of SRAM WORDS + * + */ +/* + * Field : SRAM Fill Level (Indirect Read Partition). In units of SRAM WORDS - indrdpart + * + * Field Access Macros: + * + */ +/* The Least Significant Bit (LSB) position of the ALT_QSPI_SRAMFILL_INDRDPART register field. */ +#define ALT_QSPI_SRAMFILL_INDRDPART_LSB 0 +/* The Most Significant Bit (MSB) position of the ALT_QSPI_SRAMFILL_INDRDPART register field. */ +#define ALT_QSPI_SRAMFILL_INDRDPART_MSB 15 +/* The width in bits of the ALT_QSPI_SRAMFILL_INDRDPART register field. */ +#define ALT_QSPI_SRAMFILL_INDRDPART_WIDTH 16 +/* The mask used to set the ALT_QSPI_SRAMFILL_INDRDPART register field value. */ +#define ALT_QSPI_SRAMFILL_INDRDPART_SET_MSK 0x0000ffff +/* The mask used to clear the ALT_QSPI_SRAMFILL_INDRDPART register field value. */ +#define ALT_QSPI_SRAMFILL_INDRDPART_CLR_MSK 0xffff0000 +/* The reset value of the ALT_QSPI_SRAMFILL_INDRDPART register field. */ +#define ALT_QSPI_SRAMFILL_INDRDPART_RESET 0x0 +/* Extracts the ALT_QSPI_SRAMFILL_INDRDPART field value from a register. */ +#define ALT_QSPI_SRAMFILL_INDRDPART_GET(value) (((value) & 0x0000ffff) >> 0) +/* Produces a ALT_QSPI_SRAMFILL_INDRDPART register field value suitable for setting the register. */ +#define ALT_QSPI_SRAMFILL_INDRDPART_SET(value) (((value) << 0) & 0x0000ffff) + +/* + * Field : SRAM Fill Level (Indirect Write Partition). In units of SRAM WORDS - indwrpart + * + * Field Access Macros: + * + */ +/* The Least Significant Bit (LSB) position of the ALT_QSPI_SRAMFILL_INDWRPART register field. */ +#define ALT_QSPI_SRAMFILL_INDWRPART_LSB 16 +/* The Most Significant Bit (MSB) position of the ALT_QSPI_SRAMFILL_INDWRPART register field. */ +#define ALT_QSPI_SRAMFILL_INDWRPART_MSB 31 +/* The width in bits of the ALT_QSPI_SRAMFILL_INDWRPART register field. */ +#define ALT_QSPI_SRAMFILL_INDWRPART_WIDTH 16 +/* The mask used to set the ALT_QSPI_SRAMFILL_INDWRPART register field value. */ +#define ALT_QSPI_SRAMFILL_INDWRPART_SET_MSK 0xffff0000 +/* The mask used to clear the ALT_QSPI_SRAMFILL_INDWRPART register field value. */ +#define ALT_QSPI_SRAMFILL_INDWRPART_CLR_MSK 0x0000ffff +/* The reset value of the ALT_QSPI_SRAMFILL_INDWRPART register field. */ +#define ALT_QSPI_SRAMFILL_INDWRPART_RESET 0x0 +/* Extracts the ALT_QSPI_SRAMFILL_INDWRPART field value from a register. */ +#define ALT_QSPI_SRAMFILL_INDWRPART_GET(value) (((value) & 0xffff0000) >> 16) +/* Produces a ALT_QSPI_SRAMFILL_INDWRPART register field value suitable for setting the register. */ +#define ALT_QSPI_SRAMFILL_INDWRPART_SET(value) (((value) << 16) & 0xffff0000) + +#ifndef __ASSEMBLY__ +/* + * WARNING: The C register and register group struct declarations are provided for + * convenience and illustrative purposes. They should, however, be used with + * caution as the C language standard provides no guarantees about the alignment or + * atomicity of device memory accesses. The recommended practice for writing + * hardware drivers is to use the SoCAL access macros and alt_read_word() and + * alt_write_word() functions. + * + * The struct declaration for register ALT_QSPI_SRAMFILL. + */ +struct ALT_QSPI_SRAMFILL_s +{ + const uint32_t indrdpart : 16; /* SRAM Fill Level (Indirect Read Partition). In units of SRAM WORDS */ + const uint32_t indwrpart : 16; /* SRAM Fill Level (Indirect Write Partition). In units of SRAM WORDS */ +}; + +/* The typedef declaration for register ALT_QSPI_SRAMFILL. */ +typedef volatile struct ALT_QSPI_SRAMFILL_s ALT_QSPI_SRAMFILL_t; +#endif /* __ASSEMBLY__ */ + +/* The byte offset of the ALT_QSPI_SRAMFILL register from the beginning of the component. */ +#define ALT_QSPI_SRAMFILL_OFST 0x2c + +/* + * Register : TX Threshold Register - txthresh + * + * Register Layout + * + * Bits | Access | Reset | Description + * :-------|:-------|:------|:------------ + * [3:0] | RW | 0x1 | Level + * [31:4] | ??? | 0x0 | *UNDEFINED* + * + */ +/* + * Field : Level - level + * + * Defines the level at which the transmit FIFO not full interrupt is generated + * + * Field Access Macros: + * + */ +/* The Least Significant Bit (LSB) position of the ALT_QSPI_TXTHRESH_LEVEL register field. */ +#define ALT_QSPI_TXTHRESH_LEVEL_LSB 0 +/* The Most Significant Bit (MSB) position of the ALT_QSPI_TXTHRESH_LEVEL register field. */ +#define ALT_QSPI_TXTHRESH_LEVEL_MSB 3 +/* The width in bits of the ALT_QSPI_TXTHRESH_LEVEL register field. */ +#define ALT_QSPI_TXTHRESH_LEVEL_WIDTH 4 +/* The mask used to set the ALT_QSPI_TXTHRESH_LEVEL register field value. */ +#define ALT_QSPI_TXTHRESH_LEVEL_SET_MSK 0x0000000f +/* The mask used to clear the ALT_QSPI_TXTHRESH_LEVEL register field value. */ +#define ALT_QSPI_TXTHRESH_LEVEL_CLR_MSK 0xfffffff0 +/* The reset value of the ALT_QSPI_TXTHRESH_LEVEL register field. */ +#define ALT_QSPI_TXTHRESH_LEVEL_RESET 0x1 +/* Extracts the ALT_QSPI_TXTHRESH_LEVEL field value from a register. */ +#define ALT_QSPI_TXTHRESH_LEVEL_GET(value) (((value) & 0x0000000f) >> 0) +/* Produces a ALT_QSPI_TXTHRESH_LEVEL register field value suitable for setting the register. */ +#define ALT_QSPI_TXTHRESH_LEVEL_SET(value) (((value) << 0) & 0x0000000f) + +#ifndef __ASSEMBLY__ +/* + * WARNING: The C register and register group struct declarations are provided for + * convenience and illustrative purposes. They should, however, be used with + * caution as the C language standard provides no guarantees about the alignment or + * atomicity of device memory accesses. The recommended practice for writing + * hardware drivers is to use the SoCAL access macros and alt_read_word() and + * alt_write_word() functions. + * + * The struct declaration for register ALT_QSPI_TXTHRESH. + */ +struct ALT_QSPI_TXTHRESH_s +{ + uint32_t level : 4; /* Level */ + uint32_t : 28; /* *UNDEFINED* */ +}; + +/* The typedef declaration for register ALT_QSPI_TXTHRESH. */ +typedef volatile struct ALT_QSPI_TXTHRESH_s ALT_QSPI_TXTHRESH_t; +#endif /* __ASSEMBLY__ */ + +/* The byte offset of the ALT_QSPI_TXTHRESH register from the beginning of the component. */ +#define ALT_QSPI_TXTHRESH_OFST 0x30 + +/* + * Register : RX Threshold Register - rxthresh + * + * Device Instruction Register + * + * Register Layout + * + * Bits | Access | Reset | Description + * :-------|:-------|:------|:------------ + * [3:0] | RW | 0x1 | Level + * [31:4] | ??? | 0x0 | *UNDEFINED* + * + */ +/* + * Field : Level - level + * + * Defines the level at which the receive FIFO not empty interrupt is generated + * + * Field Access Macros: + * + */ +/* The Least Significant Bit (LSB) position of the ALT_QSPI_RXTHRESH_LEVEL register field. */ +#define ALT_QSPI_RXTHRESH_LEVEL_LSB 0 +/* The Most Significant Bit (MSB) position of the ALT_QSPI_RXTHRESH_LEVEL register field. */ +#define ALT_QSPI_RXTHRESH_LEVEL_MSB 3 +/* The width in bits of the ALT_QSPI_RXTHRESH_LEVEL register field. */ +#define ALT_QSPI_RXTHRESH_LEVEL_WIDTH 4 +/* The mask used to set the ALT_QSPI_RXTHRESH_LEVEL register field value. */ +#define ALT_QSPI_RXTHRESH_LEVEL_SET_MSK 0x0000000f +/* The mask used to clear the ALT_QSPI_RXTHRESH_LEVEL register field value. */ +#define ALT_QSPI_RXTHRESH_LEVEL_CLR_MSK 0xfffffff0 +/* The reset value of the ALT_QSPI_RXTHRESH_LEVEL register field. */ +#define ALT_QSPI_RXTHRESH_LEVEL_RESET 0x1 +/* Extracts the ALT_QSPI_RXTHRESH_LEVEL field value from a register. */ +#define ALT_QSPI_RXTHRESH_LEVEL_GET(value) (((value) & 0x0000000f) >> 0) +/* Produces a ALT_QSPI_RXTHRESH_LEVEL register field value suitable for setting the register. */ +#define ALT_QSPI_RXTHRESH_LEVEL_SET(value) (((value) << 0) & 0x0000000f) + +#ifndef __ASSEMBLY__ +/* + * WARNING: The C register and register group struct declarations are provided for + * convenience and illustrative purposes. They should, however, be used with + * caution as the C language standard provides no guarantees about the alignment or + * atomicity of device memory accesses. The recommended practice for writing + * hardware drivers is to use the SoCAL access macros and alt_read_word() and + * alt_write_word() functions. + * + * The struct declaration for register ALT_QSPI_RXTHRESH. + */ +struct ALT_QSPI_RXTHRESH_s +{ + uint32_t level : 4; /* Level */ + uint32_t : 28; /* *UNDEFINED* */ +}; + +/* The typedef declaration for register ALT_QSPI_RXTHRESH. */ +typedef volatile struct ALT_QSPI_RXTHRESH_s ALT_QSPI_RXTHRESH_t; +#endif /* __ASSEMBLY__ */ + +/* The byte offset of the ALT_QSPI_RXTHRESH register from the beginning of the component. */ +#define ALT_QSPI_RXTHRESH_OFST 0x34 + +/* + * Register : Interrupt Status Register - irqstat + * + * The status fields in this register are set when the described event occurs and + * the interrupt is enabled in the mask register. When any of these bit fields are + * set, the interrupt output is asserted high. The fields are each cleared by + * writing a 1 to the field. Note that bit fields 7 thru 11 are only valid when + * legacy SPI mode is active. + * + * Register Layout + * + * Bits | Access | Reset | Description + * :--------|:-------|:------|:------------------------------------ + * [0] | ??? | 0x0 | *UNDEFINED* + * [1] | RW | 0x0 | Underflow Detected + * [2] | RW | 0x0 | Indirect Operation Complete + * [3] | RW | 0x0 | Indirect Read Reject + * [4] | RW | 0x0 | Protected Area Write Attempt + * [5] | RW | 0x0 | Illegal AHB Access Detected + * [6] | RW | 0x0 | Transfer Watermark Reached + * [7] | RW | 0x0 | Receive Overflow + * [8] | RW | 0x1 | Transmit FIFO Compared to Threshold + * [9] | RW | 0x0 | Transmit FIFO Full + * [10] | RW | 0x0 | Receive FIFO Compared to Threshold + * [11] | RW | 0x0 | Receive FIFO Full + * [12] | RW | 0x0 | Indirect Read Partition overflow + * [31:13] | ??? | 0x0 | *UNDEFINED* + * + */ +/* + * Field : Underflow Detected - underflowdet + * + * An underflow is detected when an attempt to transfer data is made when the + * transmit FIFO is empty. This may occur when the AHB write data is being supplied + * too slowly to keep up with the requested write operation. This bit is reset only + * by a system reset and cleared only when the register is read. + * + * Field Enumeration Values: + * + * Enum | Value | Description + * :--------------------------------------------|:------|:------------- + * ALT_QSPI_IRQSTAT_UNDERFLOWDET_E_UNDERFLOW | 0x1 | Underflow + * ALT_QSPI_IRQSTAT_UNDERFLOWDET_E_NOUNDERFLOW | 0x0 | No Underflow + * + * Field Access Macros: + * + */ +/* + * Enumerated value for register field ALT_QSPI_IRQSTAT_UNDERFLOWDET + * + * Underflow + */ +#define ALT_QSPI_IRQSTAT_UNDERFLOWDET_E_UNDERFLOW 0x1 +/* + * Enumerated value for register field ALT_QSPI_IRQSTAT_UNDERFLOWDET + * + * No Underflow + */ +#define ALT_QSPI_IRQSTAT_UNDERFLOWDET_E_NOUNDERFLOW 0x0 + +/* The Least Significant Bit (LSB) position of the ALT_QSPI_IRQSTAT_UNDERFLOWDET register field. */ +#define ALT_QSPI_IRQSTAT_UNDERFLOWDET_LSB 1 +/* The Most Significant Bit (MSB) position of the ALT_QSPI_IRQSTAT_UNDERFLOWDET register field. */ +#define ALT_QSPI_IRQSTAT_UNDERFLOWDET_MSB 1 +/* The width in bits of the ALT_QSPI_IRQSTAT_UNDERFLOWDET register field. */ +#define ALT_QSPI_IRQSTAT_UNDERFLOWDET_WIDTH 1 +/* The mask used to set the ALT_QSPI_IRQSTAT_UNDERFLOWDET register field value. */ +#define ALT_QSPI_IRQSTAT_UNDERFLOWDET_SET_MSK 0x00000002 +/* The mask used to clear the ALT_QSPI_IRQSTAT_UNDERFLOWDET register field value. */ +#define ALT_QSPI_IRQSTAT_UNDERFLOWDET_CLR_MSK 0xfffffffd +/* The reset value of the ALT_QSPI_IRQSTAT_UNDERFLOWDET register field. */ +#define ALT_QSPI_IRQSTAT_UNDERFLOWDET_RESET 0x0 +/* Extracts the ALT_QSPI_IRQSTAT_UNDERFLOWDET field value from a register. */ +#define ALT_QSPI_IRQSTAT_UNDERFLOWDET_GET(value) (((value) & 0x00000002) >> 1) +/* Produces a ALT_QSPI_IRQSTAT_UNDERFLOWDET register field value suitable for setting the register. */ +#define ALT_QSPI_IRQSTAT_UNDERFLOWDET_SET(value) (((value) << 1) & 0x00000002) + +/* + * Field : Indirect Operation Complete - indopdone + * + * Controller has completed last triggered indirect operation + * + * Field Enumeration Values: + * + * Enum | Value | Description + * :------------------------------------------|:------|:----------------------------- + * ALT_QSPI_IRQSTAT_INDOPDONE_E_INDIRECTOP | 0x1 | Completed Indirect Operation + * ALT_QSPI_IRQSTAT_INDOPDONE_E_NOINDIRECTOP | 0x0 | No Indirect Operation + * + * Field Access Macros: + * + */ +/* + * Enumerated value for register field ALT_QSPI_IRQSTAT_INDOPDONE + * + * Completed Indirect Operation + */ +#define ALT_QSPI_IRQSTAT_INDOPDONE_E_INDIRECTOP 0x1 +/* + * Enumerated value for register field ALT_QSPI_IRQSTAT_INDOPDONE + * + * No Indirect Operation + */ +#define ALT_QSPI_IRQSTAT_INDOPDONE_E_NOINDIRECTOP 0x0 + +/* The Least Significant Bit (LSB) position of the ALT_QSPI_IRQSTAT_INDOPDONE register field. */ +#define ALT_QSPI_IRQSTAT_INDOPDONE_LSB 2 +/* The Most Significant Bit (MSB) position of the ALT_QSPI_IRQSTAT_INDOPDONE register field. */ +#define ALT_QSPI_IRQSTAT_INDOPDONE_MSB 2 +/* The width in bits of the ALT_QSPI_IRQSTAT_INDOPDONE register field. */ +#define ALT_QSPI_IRQSTAT_INDOPDONE_WIDTH 1 +/* The mask used to set the ALT_QSPI_IRQSTAT_INDOPDONE register field value. */ +#define ALT_QSPI_IRQSTAT_INDOPDONE_SET_MSK 0x00000004 +/* The mask used to clear the ALT_QSPI_IRQSTAT_INDOPDONE register field value. */ +#define ALT_QSPI_IRQSTAT_INDOPDONE_CLR_MSK 0xfffffffb +/* The reset value of the ALT_QSPI_IRQSTAT_INDOPDONE register field. */ +#define ALT_QSPI_IRQSTAT_INDOPDONE_RESET 0x0 +/* Extracts the ALT_QSPI_IRQSTAT_INDOPDONE field value from a register. */ +#define ALT_QSPI_IRQSTAT_INDOPDONE_GET(value) (((value) & 0x00000004) >> 2) +/* Produces a ALT_QSPI_IRQSTAT_INDOPDONE register field value suitable for setting the register. */ +#define ALT_QSPI_IRQSTAT_INDOPDONE_SET(value) (((value) << 2) & 0x00000004) + +/* + * Field : Indirect Read Reject - indrdreject + * + * Indirect operation was requested but could not be accepted. Two indirect + * operations already in storage. + * + * Field Enumeration Values: + * + * Enum | Value | Description + * :---------------------------------------------|:------|:----------------------------- + * ALT_QSPI_IRQSTAT_INDRDREJECT_E_INDIRECTREQ | 0x1 | Indirect Operation Requested + * ALT_QSPI_IRQSTAT_INDRDREJECT_E_NOINDIRECTREQ | 0x0 | No Indirect Operation + * + * Field Access Macros: + * + */ +/* + * Enumerated value for register field ALT_QSPI_IRQSTAT_INDRDREJECT + * + * Indirect Operation Requested + */ +#define ALT_QSPI_IRQSTAT_INDRDREJECT_E_INDIRECTREQ 0x1 +/* + * Enumerated value for register field ALT_QSPI_IRQSTAT_INDRDREJECT + * + * No Indirect Operation + */ +#define ALT_QSPI_IRQSTAT_INDRDREJECT_E_NOINDIRECTREQ 0x0 + +/* The Least Significant Bit (LSB) position of the ALT_QSPI_IRQSTAT_INDRDREJECT register field. */ +#define ALT_QSPI_IRQSTAT_INDRDREJECT_LSB 3 +/* The Most Significant Bit (MSB) position of the ALT_QSPI_IRQSTAT_INDRDREJECT register field. */ +#define ALT_QSPI_IRQSTAT_INDRDREJECT_MSB 3 +/* The width in bits of the ALT_QSPI_IRQSTAT_INDRDREJECT register field. */ +#define ALT_QSPI_IRQSTAT_INDRDREJECT_WIDTH 1 +/* The mask used to set the ALT_QSPI_IRQSTAT_INDRDREJECT register field value. */ +#define ALT_QSPI_IRQSTAT_INDRDREJECT_SET_MSK 0x00000008 +/* The mask used to clear the ALT_QSPI_IRQSTAT_INDRDREJECT register field value. */ +#define ALT_QSPI_IRQSTAT_INDRDREJECT_CLR_MSK 0xfffffff7 +/* The reset value of the ALT_QSPI_IRQSTAT_INDRDREJECT register field. */ +#define ALT_QSPI_IRQSTAT_INDRDREJECT_RESET 0x0 +/* Extracts the ALT_QSPI_IRQSTAT_INDRDREJECT field value from a register. */ +#define ALT_QSPI_IRQSTAT_INDRDREJECT_GET(value) (((value) & 0x00000008) >> 3) +/* Produces a ALT_QSPI_IRQSTAT_INDRDREJECT register field value suitable for setting the register. */ +#define ALT_QSPI_IRQSTAT_INDRDREJECT_SET(value) (((value) << 3) & 0x00000008) + +/* + * Field : Protected Area Write Attempt - protwrattempt + * + * Write to protected area was attempted and rejected. + * + * Field Enumeration Values: + * + * Enum | Value | Description + * :------------------------------------------|:------|:-------------------------------- + * ALT_QSPI_IRQSTAT_PROTWRATTEMPT_E_WRPROT | 0x1 | Write Attempt to protected area + * ALT_QSPI_IRQSTAT_PROTWRATTEMPT_E_NOWRPROT | 0x0 | No Write Attempt + * + * Field Access Macros: + * + */ +/* + * Enumerated value for register field ALT_QSPI_IRQSTAT_PROTWRATTEMPT + * + * Write Attempt to protected area + */ +#define ALT_QSPI_IRQSTAT_PROTWRATTEMPT_E_WRPROT 0x1 +/* + * Enumerated value for register field ALT_QSPI_IRQSTAT_PROTWRATTEMPT + * + * No Write Attempt + */ +#define ALT_QSPI_IRQSTAT_PROTWRATTEMPT_E_NOWRPROT 0x0 + +/* The Least Significant Bit (LSB) position of the ALT_QSPI_IRQSTAT_PROTWRATTEMPT register field. */ +#define ALT_QSPI_IRQSTAT_PROTWRATTEMPT_LSB 4 +/* The Most Significant Bit (MSB) position of the ALT_QSPI_IRQSTAT_PROTWRATTEMPT register field. */ +#define ALT_QSPI_IRQSTAT_PROTWRATTEMPT_MSB 4 +/* The width in bits of the ALT_QSPI_IRQSTAT_PROTWRATTEMPT register field. */ +#define ALT_QSPI_IRQSTAT_PROTWRATTEMPT_WIDTH 1 +/* The mask used to set the ALT_QSPI_IRQSTAT_PROTWRATTEMPT register field value. */ +#define ALT_QSPI_IRQSTAT_PROTWRATTEMPT_SET_MSK 0x00000010 +/* The mask used to clear the ALT_QSPI_IRQSTAT_PROTWRATTEMPT register field value. */ +#define ALT_QSPI_IRQSTAT_PROTWRATTEMPT_CLR_MSK 0xffffffef +/* The reset value of the ALT_QSPI_IRQSTAT_PROTWRATTEMPT register field. */ +#define ALT_QSPI_IRQSTAT_PROTWRATTEMPT_RESET 0x0 +/* Extracts the ALT_QSPI_IRQSTAT_PROTWRATTEMPT field value from a register. */ +#define ALT_QSPI_IRQSTAT_PROTWRATTEMPT_GET(value) (((value) & 0x00000010) >> 4) +/* Produces a ALT_QSPI_IRQSTAT_PROTWRATTEMPT register field value suitable for setting the register. */ +#define ALT_QSPI_IRQSTAT_PROTWRATTEMPT_SET(value) (((value) << 4) & 0x00000010) + +/* + * Field : Illegal AHB Access Detected - illegalacc + * + * Illegal AHB access has been detected. AHB wrapping bursts and the use of + * SPLIT/RETRY accesses will cause this error interrupt to trigger. + * + * Field Enumeration Values: + * + * Enum | Value | Description + * :-------------------------------------------|:------|:----------------------- + * ALT_QSPI_IRQSTAT_ILLEGALACC_E_ILLEGALAHB | 0x1 | Illegal AHB attempt + * ALT_QSPI_IRQSTAT_ILLEGALACC_E_NOILLEGALAHB | 0x0 | No Illegal AHB attempt + * + * Field Access Macros: + * + */ +/* + * Enumerated value for register field ALT_QSPI_IRQSTAT_ILLEGALACC + * + * Illegal AHB attempt + */ +#define ALT_QSPI_IRQSTAT_ILLEGALACC_E_ILLEGALAHB 0x1 +/* + * Enumerated value for register field ALT_QSPI_IRQSTAT_ILLEGALACC + * + * No Illegal AHB attempt + */ +#define ALT_QSPI_IRQSTAT_ILLEGALACC_E_NOILLEGALAHB 0x0 + +/* The Least Significant Bit (LSB) position of the ALT_QSPI_IRQSTAT_ILLEGALACC register field. */ +#define ALT_QSPI_IRQSTAT_ILLEGALACC_LSB 5 +/* The Most Significant Bit (MSB) position of the ALT_QSPI_IRQSTAT_ILLEGALACC register field. */ +#define ALT_QSPI_IRQSTAT_ILLEGALACC_MSB 5 +/* The width in bits of the ALT_QSPI_IRQSTAT_ILLEGALACC register field. */ +#define ALT_QSPI_IRQSTAT_ILLEGALACC_WIDTH 1 +/* The mask used to set the ALT_QSPI_IRQSTAT_ILLEGALACC register field value. */ +#define ALT_QSPI_IRQSTAT_ILLEGALACC_SET_MSK 0x00000020 +/* The mask used to clear the ALT_QSPI_IRQSTAT_ILLEGALACC register field value. */ +#define ALT_QSPI_IRQSTAT_ILLEGALACC_CLR_MSK 0xffffffdf +/* The reset value of the ALT_QSPI_IRQSTAT_ILLEGALACC register field. */ +#define ALT_QSPI_IRQSTAT_ILLEGALACC_RESET 0x0 +/* Extracts the ALT_QSPI_IRQSTAT_ILLEGALACC field value from a register. */ +#define ALT_QSPI_IRQSTAT_ILLEGALACC_GET(value) (((value) & 0x00000020) >> 5) +/* Produces a ALT_QSPI_IRQSTAT_ILLEGALACC register field value suitable for setting the register. */ +#define ALT_QSPI_IRQSTAT_ILLEGALACC_SET(value) (((value) << 5) & 0x00000020) + +/* + * Field : Transfer Watermark Reached - indxfrlvl + * + * Indirect Transfer Watermark Level Reached + * + * Field Enumeration Values: + * + * Enum | Value | Description + * :----------------------------------------|:------|:----------------------- + * ALT_QSPI_IRQSTAT_INDXFRLVL_E_WATERLEVL | 0x1 | Water level reached + * ALT_QSPI_IRQSTAT_INDXFRLVL_E_NOWATERLVL | 0x0 | No water level reached + * + * Field Access Macros: + * + */ +/* + * Enumerated value for register field ALT_QSPI_IRQSTAT_INDXFRLVL + * + * Water level reached + */ +#define ALT_QSPI_IRQSTAT_INDXFRLVL_E_WATERLEVL 0x1 +/* + * Enumerated value for register field ALT_QSPI_IRQSTAT_INDXFRLVL + * + * No water level reached + */ +#define ALT_QSPI_IRQSTAT_INDXFRLVL_E_NOWATERLVL 0x0 + +/* The Least Significant Bit (LSB) position of the ALT_QSPI_IRQSTAT_INDXFRLVL register field. */ +#define ALT_QSPI_IRQSTAT_INDXFRLVL_LSB 6 +/* The Most Significant Bit (MSB) position of the ALT_QSPI_IRQSTAT_INDXFRLVL register field. */ +#define ALT_QSPI_IRQSTAT_INDXFRLVL_MSB 6 +/* The width in bits of the ALT_QSPI_IRQSTAT_INDXFRLVL register field. */ +#define ALT_QSPI_IRQSTAT_INDXFRLVL_WIDTH 1 +/* The mask used to set the ALT_QSPI_IRQSTAT_INDXFRLVL register field value. */ +#define ALT_QSPI_IRQSTAT_INDXFRLVL_SET_MSK 0x00000040 +/* The mask used to clear the ALT_QSPI_IRQSTAT_INDXFRLVL register field value. */ +#define ALT_QSPI_IRQSTAT_INDXFRLVL_CLR_MSK 0xffffffbf +/* The reset value of the ALT_QSPI_IRQSTAT_INDXFRLVL register field. */ +#define ALT_QSPI_IRQSTAT_INDXFRLVL_RESET 0x0 +/* Extracts the ALT_QSPI_IRQSTAT_INDXFRLVL field value from a register. */ +#define ALT_QSPI_IRQSTAT_INDXFRLVL_GET(value) (((value) & 0x00000040) >> 6) +/* Produces a ALT_QSPI_IRQSTAT_INDXFRLVL register field value suitable for setting the register. */ +#define ALT_QSPI_IRQSTAT_INDXFRLVL_SET(value) (((value) << 6) & 0x00000040) + +/* + * Field : Receive Overflow - rxover + * + * This should only occur in Legacy SPI mode. Set if an attempt is made to push the + * RX FIFO when it is full. This bit is reset only by a system reset and cleared + * only when this register is read. If a new push to the RX FIFO occurs coincident + * with a register read this flag will remain set. 0 : no overflow has been + * detected. 1 : an overflow has occurred. + * + * Field Enumeration Values: + * + * Enum | Value | Description + * :------------------------------------|:------|:-------------------- + * ALT_QSPI_IRQSTAT_RXOVER_E_RCVOVER | 0x1 | Receive Overflow + * ALT_QSPI_IRQSTAT_RXOVER_E_NORCVOVER | 0x0 | No Receive Overflow + * + * Field Access Macros: + * + */ +/* + * Enumerated value for register field ALT_QSPI_IRQSTAT_RXOVER + * + * Receive Overflow + */ +#define ALT_QSPI_IRQSTAT_RXOVER_E_RCVOVER 0x1 +/* + * Enumerated value for register field ALT_QSPI_IRQSTAT_RXOVER + * + * No Receive Overflow + */ +#define ALT_QSPI_IRQSTAT_RXOVER_E_NORCVOVER 0x0 + +/* The Least Significant Bit (LSB) position of the ALT_QSPI_IRQSTAT_RXOVER register field. */ +#define ALT_QSPI_IRQSTAT_RXOVER_LSB 7 +/* The Most Significant Bit (MSB) position of the ALT_QSPI_IRQSTAT_RXOVER register field. */ +#define ALT_QSPI_IRQSTAT_RXOVER_MSB 7 +/* The width in bits of the ALT_QSPI_IRQSTAT_RXOVER register field. */ +#define ALT_QSPI_IRQSTAT_RXOVER_WIDTH 1 +/* The mask used to set the ALT_QSPI_IRQSTAT_RXOVER register field value. */ +#define ALT_QSPI_IRQSTAT_RXOVER_SET_MSK 0x00000080 +/* The mask used to clear the ALT_QSPI_IRQSTAT_RXOVER register field value. */ +#define ALT_QSPI_IRQSTAT_RXOVER_CLR_MSK 0xffffff7f +/* The reset value of the ALT_QSPI_IRQSTAT_RXOVER register field. */ +#define ALT_QSPI_IRQSTAT_RXOVER_RESET 0x0 +/* Extracts the ALT_QSPI_IRQSTAT_RXOVER field value from a register. */ +#define ALT_QSPI_IRQSTAT_RXOVER_GET(value) (((value) & 0x00000080) >> 7) +/* Produces a ALT_QSPI_IRQSTAT_RXOVER register field value suitable for setting the register. */ +#define ALT_QSPI_IRQSTAT_RXOVER_SET(value) (((value) << 7) & 0x00000080) + +/* + * Field : Transmit FIFO Compared to Threshold - txthreshcmp + * + * Indicates the number of entries in the transmit FIFO with respect to the + * threshold specified in the TXTHRESH register. Only relevant in SPI legacy mode. + * + * Field Enumeration Values: + * + * Enum | Value | Description + * :----------------------------------|:------|:----------------------------- + * ALT_QSPI_IRQSTAT_TXTHRESHCMP_E_GT | 0x0 | FIFO has > TXTHRESH entries + * ALT_QSPI_IRQSTAT_TXTHRESHCMP_E_LE | 0x1 | FIFO has <= TXTHRESH entries + * + * Field Access Macros: + * + */ +/* + * Enumerated value for register field ALT_QSPI_IRQSTAT_TXTHRESHCMP + * + * FIFO has > TXTHRESH entries + */ +#define ALT_QSPI_IRQSTAT_TXTHRESHCMP_E_GT 0x0 +/* + * Enumerated value for register field ALT_QSPI_IRQSTAT_TXTHRESHCMP + * + * FIFO has <= TXTHRESH entries + */ +#define ALT_QSPI_IRQSTAT_TXTHRESHCMP_E_LE 0x1 + +/* The Least Significant Bit (LSB) position of the ALT_QSPI_IRQSTAT_TXTHRESHCMP register field. */ +#define ALT_QSPI_IRQSTAT_TXTHRESHCMP_LSB 8 +/* The Most Significant Bit (MSB) position of the ALT_QSPI_IRQSTAT_TXTHRESHCMP register field. */ +#define ALT_QSPI_IRQSTAT_TXTHRESHCMP_MSB 8 +/* The width in bits of the ALT_QSPI_IRQSTAT_TXTHRESHCMP register field. */ +#define ALT_QSPI_IRQSTAT_TXTHRESHCMP_WIDTH 1 +/* The mask used to set the ALT_QSPI_IRQSTAT_TXTHRESHCMP register field value. */ +#define ALT_QSPI_IRQSTAT_TXTHRESHCMP_SET_MSK 0x00000100 +/* The mask used to clear the ALT_QSPI_IRQSTAT_TXTHRESHCMP register field value. */ +#define ALT_QSPI_IRQSTAT_TXTHRESHCMP_CLR_MSK 0xfffffeff +/* The reset value of the ALT_QSPI_IRQSTAT_TXTHRESHCMP register field. */ +#define ALT_QSPI_IRQSTAT_TXTHRESHCMP_RESET 0x1 +/* Extracts the ALT_QSPI_IRQSTAT_TXTHRESHCMP field value from a register. */ +#define ALT_QSPI_IRQSTAT_TXTHRESHCMP_GET(value) (((value) & 0x00000100) >> 8) +/* Produces a ALT_QSPI_IRQSTAT_TXTHRESHCMP register field value suitable for setting the register. */ +#define ALT_QSPI_IRQSTAT_TXTHRESHCMP_SET(value) (((value) << 8) & 0x00000100) + +/* + * Field : Transmit FIFO Full - txfull + * + * Indicates that the transmit FIFO is full or not. Only relevant in SPI legacy + * mode. + * + * Field Enumeration Values: + * + * Enum | Value | Description + * :----------------------------------|:------|:----------------------- + * ALT_QSPI_IRQSTAT_TXFULL_E_NOTFULL | 0x0 | Transmit FIFO Not Full + * ALT_QSPI_IRQSTAT_TXFULL_E_FULL | 0x1 | Transmit FIFO Full + * + * Field Access Macros: + * + */ +/* + * Enumerated value for register field ALT_QSPI_IRQSTAT_TXFULL + * + * Transmit FIFO Not Full + */ +#define ALT_QSPI_IRQSTAT_TXFULL_E_NOTFULL 0x0 +/* + * Enumerated value for register field ALT_QSPI_IRQSTAT_TXFULL + * + * Transmit FIFO Full + */ +#define ALT_QSPI_IRQSTAT_TXFULL_E_FULL 0x1 + +/* The Least Significant Bit (LSB) position of the ALT_QSPI_IRQSTAT_TXFULL register field. */ +#define ALT_QSPI_IRQSTAT_TXFULL_LSB 9 +/* The Most Significant Bit (MSB) position of the ALT_QSPI_IRQSTAT_TXFULL register field. */ +#define ALT_QSPI_IRQSTAT_TXFULL_MSB 9 +/* The width in bits of the ALT_QSPI_IRQSTAT_TXFULL register field. */ +#define ALT_QSPI_IRQSTAT_TXFULL_WIDTH 1 +/* The mask used to set the ALT_QSPI_IRQSTAT_TXFULL register field value. */ +#define ALT_QSPI_IRQSTAT_TXFULL_SET_MSK 0x00000200 +/* The mask used to clear the ALT_QSPI_IRQSTAT_TXFULL register field value. */ +#define ALT_QSPI_IRQSTAT_TXFULL_CLR_MSK 0xfffffdff +/* The reset value of the ALT_QSPI_IRQSTAT_TXFULL register field. */ +#define ALT_QSPI_IRQSTAT_TXFULL_RESET 0x0 +/* Extracts the ALT_QSPI_IRQSTAT_TXFULL field value from a register. */ +#define ALT_QSPI_IRQSTAT_TXFULL_GET(value) (((value) & 0x00000200) >> 9) +/* Produces a ALT_QSPI_IRQSTAT_TXFULL register field value suitable for setting the register. */ +#define ALT_QSPI_IRQSTAT_TXFULL_SET(value) (((value) << 9) & 0x00000200) + +/* + * Field : Receive FIFO Compared to Threshold - rxthreshcmp + * + * Indicates the number of entries in the receive FIFO with respect to the + * threshold specified in the RXTHRESH register. Only relevant in SPI legacy mode. + * + * Field Enumeration Values: + * + * Enum | Value | Description + * :----------------------------------|:------|:----------------------------- + * ALT_QSPI_IRQSTAT_RXTHRESHCMP_E_LE | 0x0 | FIFO has <= RXTHRESH entries + * ALT_QSPI_IRQSTAT_RXTHRESHCMP_E_GT | 0x1 | FIFO has > RXTHRESH entries + * + * Field Access Macros: + * + */ +/* + * Enumerated value for register field ALT_QSPI_IRQSTAT_RXTHRESHCMP + * + * FIFO has <= RXTHRESH entries + */ +#define ALT_QSPI_IRQSTAT_RXTHRESHCMP_E_LE 0x0 +/* + * Enumerated value for register field ALT_QSPI_IRQSTAT_RXTHRESHCMP + * + * FIFO has > RXTHRESH entries + */ +#define ALT_QSPI_IRQSTAT_RXTHRESHCMP_E_GT 0x1 + +/* The Least Significant Bit (LSB) position of the ALT_QSPI_IRQSTAT_RXTHRESHCMP register field. */ +#define ALT_QSPI_IRQSTAT_RXTHRESHCMP_LSB 10 +/* The Most Significant Bit (MSB) position of the ALT_QSPI_IRQSTAT_RXTHRESHCMP register field. */ +#define ALT_QSPI_IRQSTAT_RXTHRESHCMP_MSB 10 +/* The width in bits of the ALT_QSPI_IRQSTAT_RXTHRESHCMP register field. */ +#define ALT_QSPI_IRQSTAT_RXTHRESHCMP_WIDTH 1 +/* The mask used to set the ALT_QSPI_IRQSTAT_RXTHRESHCMP register field value. */ +#define ALT_QSPI_IRQSTAT_RXTHRESHCMP_SET_MSK 0x00000400 +/* The mask used to clear the ALT_QSPI_IRQSTAT_RXTHRESHCMP register field value. */ +#define ALT_QSPI_IRQSTAT_RXTHRESHCMP_CLR_MSK 0xfffffbff +/* The reset value of the ALT_QSPI_IRQSTAT_RXTHRESHCMP register field. */ +#define ALT_QSPI_IRQSTAT_RXTHRESHCMP_RESET 0x0 +/* Extracts the ALT_QSPI_IRQSTAT_RXTHRESHCMP field value from a register. */ +#define ALT_QSPI_IRQSTAT_RXTHRESHCMP_GET(value) (((value) & 0x00000400) >> 10) +/* Produces a ALT_QSPI_IRQSTAT_RXTHRESHCMP register field value suitable for setting the register. */ +#define ALT_QSPI_IRQSTAT_RXTHRESHCMP_SET(value) (((value) << 10) & 0x00000400) + +/* + * Field : Receive FIFO Full - rxfull + * + * Indicates that the receive FIFO is full or not. Only relevant in SPI legacy + * mode. + * + * Field Enumeration Values: + * + * Enum | Value | Description + * :----------------------------------|:------|:---------------------- + * ALT_QSPI_IRQSTAT_RXFULL_E_NOTFULL | 0x0 | Receive FIFO Not Full + * ALT_QSPI_IRQSTAT_RXFULL_E_FULL | 0x1 | Receive FIFO Full + * + * Field Access Macros: + * + */ +/* + * Enumerated value for register field ALT_QSPI_IRQSTAT_RXFULL + * + * Receive FIFO Not Full + */ +#define ALT_QSPI_IRQSTAT_RXFULL_E_NOTFULL 0x0 +/* + * Enumerated value for register field ALT_QSPI_IRQSTAT_RXFULL + * + * Receive FIFO Full + */ +#define ALT_QSPI_IRQSTAT_RXFULL_E_FULL 0x1 + +/* The Least Significant Bit (LSB) position of the ALT_QSPI_IRQSTAT_RXFULL register field. */ +#define ALT_QSPI_IRQSTAT_RXFULL_LSB 11 +/* The Most Significant Bit (MSB) position of the ALT_QSPI_IRQSTAT_RXFULL register field. */ +#define ALT_QSPI_IRQSTAT_RXFULL_MSB 11 +/* The width in bits of the ALT_QSPI_IRQSTAT_RXFULL register field. */ +#define ALT_QSPI_IRQSTAT_RXFULL_WIDTH 1 +/* The mask used to set the ALT_QSPI_IRQSTAT_RXFULL register field value. */ +#define ALT_QSPI_IRQSTAT_RXFULL_SET_MSK 0x00000800 +/* The mask used to clear the ALT_QSPI_IRQSTAT_RXFULL register field value. */ +#define ALT_QSPI_IRQSTAT_RXFULL_CLR_MSK 0xfffff7ff +/* The reset value of the ALT_QSPI_IRQSTAT_RXFULL register field. */ +#define ALT_QSPI_IRQSTAT_RXFULL_RESET 0x0 +/* Extracts the ALT_QSPI_IRQSTAT_RXFULL field value from a register. */ +#define ALT_QSPI_IRQSTAT_RXFULL_GET(value) (((value) & 0x00000800) >> 11) +/* Produces a ALT_QSPI_IRQSTAT_RXFULL register field value suitable for setting the register. */ +#define ALT_QSPI_IRQSTAT_RXFULL_SET(value) (((value) << 11) & 0x00000800) + +/* + * Field : Indirect Read Partition overflow - indsramfull + * + * Indirect Read Partition of SRAM is full and unable to immediately complete + * indirect operation + * + * Field Enumeration Values: + * + * Enum | Value | Description + * :---------------------------------------------|:------|:----------------- + * ALT_QSPI_IRQSTAT_INDSRAMFULL_E_RDPARTFULL | 0x1 | SRAM is full + * ALT_QSPI_IRQSTAT_INDSRAMFULL_E_RDPARTNOTFULL | 0x0 | SRAM is not full + * + * Field Access Macros: + * + */ +/* + * Enumerated value for register field ALT_QSPI_IRQSTAT_INDSRAMFULL + * + * SRAM is full + */ +#define ALT_QSPI_IRQSTAT_INDSRAMFULL_E_RDPARTFULL 0x1 +/* + * Enumerated value for register field ALT_QSPI_IRQSTAT_INDSRAMFULL + * + * SRAM is not full + */ +#define ALT_QSPI_IRQSTAT_INDSRAMFULL_E_RDPARTNOTFULL 0x0 + +/* The Least Significant Bit (LSB) position of the ALT_QSPI_IRQSTAT_INDSRAMFULL register field. */ +#define ALT_QSPI_IRQSTAT_INDSRAMFULL_LSB 12 +/* The Most Significant Bit (MSB) position of the ALT_QSPI_IRQSTAT_INDSRAMFULL register field. */ +#define ALT_QSPI_IRQSTAT_INDSRAMFULL_MSB 12 +/* The width in bits of the ALT_QSPI_IRQSTAT_INDSRAMFULL register field. */ +#define ALT_QSPI_IRQSTAT_INDSRAMFULL_WIDTH 1 +/* The mask used to set the ALT_QSPI_IRQSTAT_INDSRAMFULL register field value. */ +#define ALT_QSPI_IRQSTAT_INDSRAMFULL_SET_MSK 0x00001000 +/* The mask used to clear the ALT_QSPI_IRQSTAT_INDSRAMFULL register field value. */ +#define ALT_QSPI_IRQSTAT_INDSRAMFULL_CLR_MSK 0xffffefff +/* The reset value of the ALT_QSPI_IRQSTAT_INDSRAMFULL register field. */ +#define ALT_QSPI_IRQSTAT_INDSRAMFULL_RESET 0x0 +/* Extracts the ALT_QSPI_IRQSTAT_INDSRAMFULL field value from a register. */ +#define ALT_QSPI_IRQSTAT_INDSRAMFULL_GET(value) (((value) & 0x00001000) >> 12) +/* Produces a ALT_QSPI_IRQSTAT_INDSRAMFULL register field value suitable for setting the register. */ +#define ALT_QSPI_IRQSTAT_INDSRAMFULL_SET(value) (((value) << 12) & 0x00001000) + +#ifndef __ASSEMBLY__ +/* + * WARNING: The C register and register group struct declarations are provided for + * convenience and illustrative purposes. They should, however, be used with + * caution as the C language standard provides no guarantees about the alignment or + * atomicity of device memory accesses. The recommended practice for writing + * hardware drivers is to use the SoCAL access macros and alt_read_word() and + * alt_write_word() functions. + * + * The struct declaration for register ALT_QSPI_IRQSTAT. + */ +struct ALT_QSPI_IRQSTAT_s +{ + uint32_t : 1; /* *UNDEFINED* */ + uint32_t underflowdet : 1; /* Underflow Detected */ + uint32_t indopdone : 1; /* Indirect Operation Complete */ + uint32_t indrdreject : 1; /* Indirect Read Reject */ + uint32_t protwrattempt : 1; /* Protected Area Write Attempt */ + uint32_t illegalacc : 1; /* Illegal AHB Access Detected */ + uint32_t indxfrlvl : 1; /* Transfer Watermark Reached */ + uint32_t rxover : 1; /* Receive Overflow */ + uint32_t txthreshcmp : 1; /* Transmit FIFO Compared to Threshold */ + uint32_t txfull : 1; /* Transmit FIFO Full */ + uint32_t rxthreshcmp : 1; /* Receive FIFO Compared to Threshold */ + uint32_t rxfull : 1; /* Receive FIFO Full */ + uint32_t indsramfull : 1; /* Indirect Read Partition overflow */ + uint32_t : 19; /* *UNDEFINED* */ +}; + +/* The typedef declaration for register ALT_QSPI_IRQSTAT. */ +typedef volatile struct ALT_QSPI_IRQSTAT_s ALT_QSPI_IRQSTAT_t; +#endif /* __ASSEMBLY__ */ + +/* The byte offset of the ALT_QSPI_IRQSTAT register from the beginning of the component. */ +#define ALT_QSPI_IRQSTAT_OFST 0x40 + +/* + * Register : Interrupt Mask - irqmask + * + * If disabled, the interrupt for the corresponding interrupt status register bit + * is disabled. If enabled, the interrupt for the corresponding interrupt status + * register bit is enabled. + * + * Register Layout + * + * Bits | Access | Reset | Description + * :--------|:-------|:------|:-------------------------------------- + * [0] | ??? | 0x0 | *UNDEFINED* + * [1] | RW | 0x0 | Underflow Detected Mask + * [2] | RW | 0x0 | Mask + * [3] | RW | 0x0 | Indirect Read Reject Mask + * [4] | RW | 0x0 | Protected Area Write Attempt Mask + * [5] | RW | 0x0 | Illegal Access Detected Mask + * [6] | RW | 0x0 | Transfer Watermark Breach Mask + * [7] | RW | 0x0 | Receive Overflow Mask + * [8] | RW | 0x0 | Transmit FIFO Threshold Compare Mask + * [9] | RW | 0x0 | Transmit FIFO Full Mask + * [10] | RW | 0x0 | Receive FIFO Threshold Compare Mask + * [11] | RW | 0x0 | Receive FIFO full Mask + * [12] | RW | 0x0 | Indirect Read Partition overflow mask + * [31:13] | ??? | 0x0 | *UNDEFINED* + * + */ +/* + * Field : Underflow Detected Mask - underflowdet + * + * Field Enumeration Values: + * + * Enum | Value | Description + * :------------------------------------|:------|:----------------------------- + * ALT_QSPI_IRQMSK_UNDERFLOWDET_E_DISD | 0x0 | Disable Interrupt by Masking + * ALT_QSPI_IRQMSK_UNDERFLOWDET_E_END | 0x1 | Enable Interrupt + * + * Field Access Macros: + * + */ +/* + * Enumerated value for register field ALT_QSPI_IRQMSK_UNDERFLOWDET + * + * Disable Interrupt by Masking + */ +#define ALT_QSPI_IRQMSK_UNDERFLOWDET_E_DISD 0x0 +/* + * Enumerated value for register field ALT_QSPI_IRQMSK_UNDERFLOWDET + * + * Enable Interrupt + */ +#define ALT_QSPI_IRQMSK_UNDERFLOWDET_E_END 0x1 + +/* The Least Significant Bit (LSB) position of the ALT_QSPI_IRQMSK_UNDERFLOWDET register field. */ +#define ALT_QSPI_IRQMSK_UNDERFLOWDET_LSB 1 +/* The Most Significant Bit (MSB) position of the ALT_QSPI_IRQMSK_UNDERFLOWDET register field. */ +#define ALT_QSPI_IRQMSK_UNDERFLOWDET_MSB 1 +/* The width in bits of the ALT_QSPI_IRQMSK_UNDERFLOWDET register field. */ +#define ALT_QSPI_IRQMSK_UNDERFLOWDET_WIDTH 1 +/* The mask used to set the ALT_QSPI_IRQMSK_UNDERFLOWDET register field value. */ +#define ALT_QSPI_IRQMSK_UNDERFLOWDET_SET_MSK 0x00000002 +/* The mask used to clear the ALT_QSPI_IRQMSK_UNDERFLOWDET register field value. */ +#define ALT_QSPI_IRQMSK_UNDERFLOWDET_CLR_MSK 0xfffffffd +/* The reset value of the ALT_QSPI_IRQMSK_UNDERFLOWDET register field. */ +#define ALT_QSPI_IRQMSK_UNDERFLOWDET_RESET 0x0 +/* Extracts the ALT_QSPI_IRQMSK_UNDERFLOWDET field value from a register. */ +#define ALT_QSPI_IRQMSK_UNDERFLOWDET_GET(value) (((value) & 0x00000002) >> 1) +/* Produces a ALT_QSPI_IRQMSK_UNDERFLOWDET register field value suitable for setting the register. */ +#define ALT_QSPI_IRQMSK_UNDERFLOWDET_SET(value) (((value) << 1) & 0x00000002) + +/* + * Field : Mask - indopdone + * + * Field Enumeration Values: + * + * Enum | Value | Description + * :---------------------------------|:------|:----------------------------- + * ALT_QSPI_IRQMSK_INDOPDONE_E_DISD | 0x0 | Disable Interrupt by Masking + * ALT_QSPI_IRQMSK_INDOPDONE_E_END | 0x1 | Enable Interrupt + * + * Field Access Macros: + * + */ +/* + * Enumerated value for register field ALT_QSPI_IRQMSK_INDOPDONE + * + * Disable Interrupt by Masking + */ +#define ALT_QSPI_IRQMSK_INDOPDONE_E_DISD 0x0 +/* + * Enumerated value for register field ALT_QSPI_IRQMSK_INDOPDONE + * + * Enable Interrupt + */ +#define ALT_QSPI_IRQMSK_INDOPDONE_E_END 0x1 + +/* The Least Significant Bit (LSB) position of the ALT_QSPI_IRQMSK_INDOPDONE register field. */ +#define ALT_QSPI_IRQMSK_INDOPDONE_LSB 2 +/* The Most Significant Bit (MSB) position of the ALT_QSPI_IRQMSK_INDOPDONE register field. */ +#define ALT_QSPI_IRQMSK_INDOPDONE_MSB 2 +/* The width in bits of the ALT_QSPI_IRQMSK_INDOPDONE register field. */ +#define ALT_QSPI_IRQMSK_INDOPDONE_WIDTH 1 +/* The mask used to set the ALT_QSPI_IRQMSK_INDOPDONE register field value. */ +#define ALT_QSPI_IRQMSK_INDOPDONE_SET_MSK 0x00000004 +/* The mask used to clear the ALT_QSPI_IRQMSK_INDOPDONE register field value. */ +#define ALT_QSPI_IRQMSK_INDOPDONE_CLR_MSK 0xfffffffb +/* The reset value of the ALT_QSPI_IRQMSK_INDOPDONE register field. */ +#define ALT_QSPI_IRQMSK_INDOPDONE_RESET 0x0 +/* Extracts the ALT_QSPI_IRQMSK_INDOPDONE field value from a register. */ +#define ALT_QSPI_IRQMSK_INDOPDONE_GET(value) (((value) & 0x00000004) >> 2) +/* Produces a ALT_QSPI_IRQMSK_INDOPDONE register field value suitable for setting the register. */ +#define ALT_QSPI_IRQMSK_INDOPDONE_SET(value) (((value) << 2) & 0x00000004) + +/* + * Field : Indirect Read Reject Mask - indrdreject + * + * Field Enumeration Values: + * + * Enum | Value | Description + * :-----------------------------------|:------|:----------------------------- + * ALT_QSPI_IRQMSK_INDRDREJECT_E_DISD | 0x0 | Disable Interrupt by Masking + * ALT_QSPI_IRQMSK_INDRDREJECT_E_END | 0x1 | Enable Interrupt + * + * Field Access Macros: + * + */ +/* + * Enumerated value for register field ALT_QSPI_IRQMSK_INDRDREJECT + * + * Disable Interrupt by Masking + */ +#define ALT_QSPI_IRQMSK_INDRDREJECT_E_DISD 0x0 +/* + * Enumerated value for register field ALT_QSPI_IRQMSK_INDRDREJECT + * + * Enable Interrupt + */ +#define ALT_QSPI_IRQMSK_INDRDREJECT_E_END 0x1 + +/* The Least Significant Bit (LSB) position of the ALT_QSPI_IRQMSK_INDRDREJECT register field. */ +#define ALT_QSPI_IRQMSK_INDRDREJECT_LSB 3 +/* The Most Significant Bit (MSB) position of the ALT_QSPI_IRQMSK_INDRDREJECT register field. */ +#define ALT_QSPI_IRQMSK_INDRDREJECT_MSB 3 +/* The width in bits of the ALT_QSPI_IRQMSK_INDRDREJECT register field. */ +#define ALT_QSPI_IRQMSK_INDRDREJECT_WIDTH 1 +/* The mask used to set the ALT_QSPI_IRQMSK_INDRDREJECT register field value. */ +#define ALT_QSPI_IRQMSK_INDRDREJECT_SET_MSK 0x00000008 +/* The mask used to clear the ALT_QSPI_IRQMSK_INDRDREJECT register field value. */ +#define ALT_QSPI_IRQMSK_INDRDREJECT_CLR_MSK 0xfffffff7 +/* The reset value of the ALT_QSPI_IRQMSK_INDRDREJECT register field. */ +#define ALT_QSPI_IRQMSK_INDRDREJECT_RESET 0x0 +/* Extracts the ALT_QSPI_IRQMSK_INDRDREJECT field value from a register. */ +#define ALT_QSPI_IRQMSK_INDRDREJECT_GET(value) (((value) & 0x00000008) >> 3) +/* Produces a ALT_QSPI_IRQMSK_INDRDREJECT register field value suitable for setting the register. */ +#define ALT_QSPI_IRQMSK_INDRDREJECT_SET(value) (((value) << 3) & 0x00000008) + +/* + * Field : Protected Area Write Attempt Mask - protwrattempt + * + * Field Enumeration Values: + * + * Enum | Value | Description + * :-------------------------------------|:------|:----------------------------- + * ALT_QSPI_IRQMSK_PROTWRATTEMPT_E_DISD | 0x0 | Disable Interrupt by Masking + * ALT_QSPI_IRQMSK_PROTWRATTEMPT_E_END | 0x1 | Enable Interrupt + * + * Field Access Macros: + * + */ +/* + * Enumerated value for register field ALT_QSPI_IRQMSK_PROTWRATTEMPT + * + * Disable Interrupt by Masking + */ +#define ALT_QSPI_IRQMSK_PROTWRATTEMPT_E_DISD 0x0 +/* + * Enumerated value for register field ALT_QSPI_IRQMSK_PROTWRATTEMPT + * + * Enable Interrupt + */ +#define ALT_QSPI_IRQMSK_PROTWRATTEMPT_E_END 0x1 + +/* The Least Significant Bit (LSB) position of the ALT_QSPI_IRQMSK_PROTWRATTEMPT register field. */ +#define ALT_QSPI_IRQMSK_PROTWRATTEMPT_LSB 4 +/* The Most Significant Bit (MSB) position of the ALT_QSPI_IRQMSK_PROTWRATTEMPT register field. */ +#define ALT_QSPI_IRQMSK_PROTWRATTEMPT_MSB 4 +/* The width in bits of the ALT_QSPI_IRQMSK_PROTWRATTEMPT register field. */ +#define ALT_QSPI_IRQMSK_PROTWRATTEMPT_WIDTH 1 +/* The mask used to set the ALT_QSPI_IRQMSK_PROTWRATTEMPT register field value. */ +#define ALT_QSPI_IRQMSK_PROTWRATTEMPT_SET_MSK 0x00000010 +/* The mask used to clear the ALT_QSPI_IRQMSK_PROTWRATTEMPT register field value. */ +#define ALT_QSPI_IRQMSK_PROTWRATTEMPT_CLR_MSK 0xffffffef +/* The reset value of the ALT_QSPI_IRQMSK_PROTWRATTEMPT register field. */ +#define ALT_QSPI_IRQMSK_PROTWRATTEMPT_RESET 0x0 +/* Extracts the ALT_QSPI_IRQMSK_PROTWRATTEMPT field value from a register. */ +#define ALT_QSPI_IRQMSK_PROTWRATTEMPT_GET(value) (((value) & 0x00000010) >> 4) +/* Produces a ALT_QSPI_IRQMSK_PROTWRATTEMPT register field value suitable for setting the register. */ +#define ALT_QSPI_IRQMSK_PROTWRATTEMPT_SET(value) (((value) << 4) & 0x00000010) + +/* + * Field : Illegal Access Detected Mask - illegalacc + * + * Field Enumeration Values: + * + * Enum | Value | Description + * :----------------------------------|:------|:----------------------------- + * ALT_QSPI_IRQMSK_ILLEGALACC_E_DISD | 0x0 | Disable Interrupt by Masking + * ALT_QSPI_IRQMSK_ILLEGALACC_E_END | 0x1 | Enable Interrupt + * + * Field Access Macros: + * + */ +/* + * Enumerated value for register field ALT_QSPI_IRQMSK_ILLEGALACC + * + * Disable Interrupt by Masking + */ +#define ALT_QSPI_IRQMSK_ILLEGALACC_E_DISD 0x0 +/* + * Enumerated value for register field ALT_QSPI_IRQMSK_ILLEGALACC + * + * Enable Interrupt + */ +#define ALT_QSPI_IRQMSK_ILLEGALACC_E_END 0x1 + +/* The Least Significant Bit (LSB) position of the ALT_QSPI_IRQMSK_ILLEGALACC register field. */ +#define ALT_QSPI_IRQMSK_ILLEGALACC_LSB 5 +/* The Most Significant Bit (MSB) position of the ALT_QSPI_IRQMSK_ILLEGALACC register field. */ +#define ALT_QSPI_IRQMSK_ILLEGALACC_MSB 5 +/* The width in bits of the ALT_QSPI_IRQMSK_ILLEGALACC register field. */ +#define ALT_QSPI_IRQMSK_ILLEGALACC_WIDTH 1 +/* The mask used to set the ALT_QSPI_IRQMSK_ILLEGALACC register field value. */ +#define ALT_QSPI_IRQMSK_ILLEGALACC_SET_MSK 0x00000020 +/* The mask used to clear the ALT_QSPI_IRQMSK_ILLEGALACC register field value. */ +#define ALT_QSPI_IRQMSK_ILLEGALACC_CLR_MSK 0xffffffdf +/* The reset value of the ALT_QSPI_IRQMSK_ILLEGALACC register field. */ +#define ALT_QSPI_IRQMSK_ILLEGALACC_RESET 0x0 +/* Extracts the ALT_QSPI_IRQMSK_ILLEGALACC field value from a register. */ +#define ALT_QSPI_IRQMSK_ILLEGALACC_GET(value) (((value) & 0x00000020) >> 5) +/* Produces a ALT_QSPI_IRQMSK_ILLEGALACC register field value suitable for setting the register. */ +#define ALT_QSPI_IRQMSK_ILLEGALACC_SET(value) (((value) << 5) & 0x00000020) + +/* + * Field : Transfer Watermark Breach Mask - indxfrlvl + * + * Field Enumeration Values: + * + * Enum | Value | Description + * :---------------------------------|:------|:----------------------------- + * ALT_QSPI_IRQMSK_INDXFRLVL_E_DISD | 0x0 | Disable Interrupt by Masking + * ALT_QSPI_IRQMSK_INDXFRLVL_E_END | 0x1 | Enable Interrupt + * + * Field Access Macros: + * + */ +/* + * Enumerated value for register field ALT_QSPI_IRQMSK_INDXFRLVL + * + * Disable Interrupt by Masking + */ +#define ALT_QSPI_IRQMSK_INDXFRLVL_E_DISD 0x0 +/* + * Enumerated value for register field ALT_QSPI_IRQMSK_INDXFRLVL + * + * Enable Interrupt + */ +#define ALT_QSPI_IRQMSK_INDXFRLVL_E_END 0x1 + +/* The Least Significant Bit (LSB) position of the ALT_QSPI_IRQMSK_INDXFRLVL register field. */ +#define ALT_QSPI_IRQMSK_INDXFRLVL_LSB 6 +/* The Most Significant Bit (MSB) position of the ALT_QSPI_IRQMSK_INDXFRLVL register field. */ +#define ALT_QSPI_IRQMSK_INDXFRLVL_MSB 6 +/* The width in bits of the ALT_QSPI_IRQMSK_INDXFRLVL register field. */ +#define ALT_QSPI_IRQMSK_INDXFRLVL_WIDTH 1 +/* The mask used to set the ALT_QSPI_IRQMSK_INDXFRLVL register field value. */ +#define ALT_QSPI_IRQMSK_INDXFRLVL_SET_MSK 0x00000040 +/* The mask used to clear the ALT_QSPI_IRQMSK_INDXFRLVL register field value. */ +#define ALT_QSPI_IRQMSK_INDXFRLVL_CLR_MSK 0xffffffbf +/* The reset value of the ALT_QSPI_IRQMSK_INDXFRLVL register field. */ +#define ALT_QSPI_IRQMSK_INDXFRLVL_RESET 0x0 +/* Extracts the ALT_QSPI_IRQMSK_INDXFRLVL field value from a register. */ +#define ALT_QSPI_IRQMSK_INDXFRLVL_GET(value) (((value) & 0x00000040) >> 6) +/* Produces a ALT_QSPI_IRQMSK_INDXFRLVL register field value suitable for setting the register. */ +#define ALT_QSPI_IRQMSK_INDXFRLVL_SET(value) (((value) << 6) & 0x00000040) + +/* + * Field : Receive Overflow Mask - rxover + * + * Field Enumeration Values: + * + * Enum | Value | Description + * :------------------------------|:------|:----------------------------- + * ALT_QSPI_IRQMSK_RXOVER_E_DISD | 0x0 | Disable Interrupt by Masking + * ALT_QSPI_IRQMSK_RXOVER_E_END | 0x1 | Enable Interrupt + * + * Field Access Macros: + * + */ +/* + * Enumerated value for register field ALT_QSPI_IRQMSK_RXOVER + * + * Disable Interrupt by Masking + */ +#define ALT_QSPI_IRQMSK_RXOVER_E_DISD 0x0 +/* + * Enumerated value for register field ALT_QSPI_IRQMSK_RXOVER + * + * Enable Interrupt + */ +#define ALT_QSPI_IRQMSK_RXOVER_E_END 0x1 + +/* The Least Significant Bit (LSB) position of the ALT_QSPI_IRQMSK_RXOVER register field. */ +#define ALT_QSPI_IRQMSK_RXOVER_LSB 7 +/* The Most Significant Bit (MSB) position of the ALT_QSPI_IRQMSK_RXOVER register field. */ +#define ALT_QSPI_IRQMSK_RXOVER_MSB 7 +/* The width in bits of the ALT_QSPI_IRQMSK_RXOVER register field. */ +#define ALT_QSPI_IRQMSK_RXOVER_WIDTH 1 +/* The mask used to set the ALT_QSPI_IRQMSK_RXOVER register field value. */ +#define ALT_QSPI_IRQMSK_RXOVER_SET_MSK 0x00000080 +/* The mask used to clear the ALT_QSPI_IRQMSK_RXOVER register field value. */ +#define ALT_QSPI_IRQMSK_RXOVER_CLR_MSK 0xffffff7f +/* The reset value of the ALT_QSPI_IRQMSK_RXOVER register field. */ +#define ALT_QSPI_IRQMSK_RXOVER_RESET 0x0 +/* Extracts the ALT_QSPI_IRQMSK_RXOVER field value from a register. */ +#define ALT_QSPI_IRQMSK_RXOVER_GET(value) (((value) & 0x00000080) >> 7) +/* Produces a ALT_QSPI_IRQMSK_RXOVER register field value suitable for setting the register. */ +#define ALT_QSPI_IRQMSK_RXOVER_SET(value) (((value) << 7) & 0x00000080) + +/* + * Field : Transmit FIFO Threshold Compare Mask - txthreshcmp + * + * Field Enumeration Values: + * + * Enum | Value | Description + * :-----------------------------------|:------|:----------------------------- + * ALT_QSPI_IRQMSK_TXTHRESHCMP_E_DISD | 0x0 | Disable Interrupt by Masking + * ALT_QSPI_IRQMSK_TXTHRESHCMP_E_END | 0x1 | Enable Interrupt + * + * Field Access Macros: + * + */ +/* + * Enumerated value for register field ALT_QSPI_IRQMSK_TXTHRESHCMP + * + * Disable Interrupt by Masking + */ +#define ALT_QSPI_IRQMSK_TXTHRESHCMP_E_DISD 0x0 +/* + * Enumerated value for register field ALT_QSPI_IRQMSK_TXTHRESHCMP + * + * Enable Interrupt + */ +#define ALT_QSPI_IRQMSK_TXTHRESHCMP_E_END 0x1 + +/* The Least Significant Bit (LSB) position of the ALT_QSPI_IRQMSK_TXTHRESHCMP register field. */ +#define ALT_QSPI_IRQMSK_TXTHRESHCMP_LSB 8 +/* The Most Significant Bit (MSB) position of the ALT_QSPI_IRQMSK_TXTHRESHCMP register field. */ +#define ALT_QSPI_IRQMSK_TXTHRESHCMP_MSB 8 +/* The width in bits of the ALT_QSPI_IRQMSK_TXTHRESHCMP register field. */ +#define ALT_QSPI_IRQMSK_TXTHRESHCMP_WIDTH 1 +/* The mask used to set the ALT_QSPI_IRQMSK_TXTHRESHCMP register field value. */ +#define ALT_QSPI_IRQMSK_TXTHRESHCMP_SET_MSK 0x00000100 +/* The mask used to clear the ALT_QSPI_IRQMSK_TXTHRESHCMP register field value. */ +#define ALT_QSPI_IRQMSK_TXTHRESHCMP_CLR_MSK 0xfffffeff +/* The reset value of the ALT_QSPI_IRQMSK_TXTHRESHCMP register field. */ +#define ALT_QSPI_IRQMSK_TXTHRESHCMP_RESET 0x0 +/* Extracts the ALT_QSPI_IRQMSK_TXTHRESHCMP field value from a register. */ +#define ALT_QSPI_IRQMSK_TXTHRESHCMP_GET(value) (((value) & 0x00000100) >> 8) +/* Produces a ALT_QSPI_IRQMSK_TXTHRESHCMP register field value suitable for setting the register. */ +#define ALT_QSPI_IRQMSK_TXTHRESHCMP_SET(value) (((value) << 8) & 0x00000100) + +/* + * Field : Transmit FIFO Full Mask - txfull + * + * Field Enumeration Values: + * + * Enum | Value | Description + * :------------------------------|:------|:----------------------------- + * ALT_QSPI_IRQMSK_TXFULL_E_DISD | 0x0 | Disable Interrupt by Masking + * ALT_QSPI_IRQMSK_TXFULL_E_END | 0x1 | Enable Interrupt + * + * Field Access Macros: + * + */ +/* + * Enumerated value for register field ALT_QSPI_IRQMSK_TXFULL + * + * Disable Interrupt by Masking + */ +#define ALT_QSPI_IRQMSK_TXFULL_E_DISD 0x0 +/* + * Enumerated value for register field ALT_QSPI_IRQMSK_TXFULL + * + * Enable Interrupt + */ +#define ALT_QSPI_IRQMSK_TXFULL_E_END 0x1 + +/* The Least Significant Bit (LSB) position of the ALT_QSPI_IRQMSK_TXFULL register field. */ +#define ALT_QSPI_IRQMSK_TXFULL_LSB 9 +/* The Most Significant Bit (MSB) position of the ALT_QSPI_IRQMSK_TXFULL register field. */ +#define ALT_QSPI_IRQMSK_TXFULL_MSB 9 +/* The width in bits of the ALT_QSPI_IRQMSK_TXFULL register field. */ +#define ALT_QSPI_IRQMSK_TXFULL_WIDTH 1 +/* The mask used to set the ALT_QSPI_IRQMSK_TXFULL register field value. */ +#define ALT_QSPI_IRQMSK_TXFULL_SET_MSK 0x00000200 +/* The mask used to clear the ALT_QSPI_IRQMSK_TXFULL register field value. */ +#define ALT_QSPI_IRQMSK_TXFULL_CLR_MSK 0xfffffdff +/* The reset value of the ALT_QSPI_IRQMSK_TXFULL register field. */ +#define ALT_QSPI_IRQMSK_TXFULL_RESET 0x0 +/* Extracts the ALT_QSPI_IRQMSK_TXFULL field value from a register. */ +#define ALT_QSPI_IRQMSK_TXFULL_GET(value) (((value) & 0x00000200) >> 9) +/* Produces a ALT_QSPI_IRQMSK_TXFULL register field value suitable for setting the register. */ +#define ALT_QSPI_IRQMSK_TXFULL_SET(value) (((value) << 9) & 0x00000200) + +/* + * Field : Receive FIFO Threshold Compare Mask - rxthreshcmp + * + * Field Enumeration Values: + * + * Enum | Value | Description + * :-----------------------------------|:------|:----------------------------- + * ALT_QSPI_IRQMSK_RXTHRESHCMP_E_DISD | 0x0 | Disable Interrupt by Masking + * ALT_QSPI_IRQMSK_RXTHRESHCMP_E_END | 0x1 | Enable Interrupt + * + * Field Access Macros: + * + */ +/* + * Enumerated value for register field ALT_QSPI_IRQMSK_RXTHRESHCMP + * + * Disable Interrupt by Masking + */ +#define ALT_QSPI_IRQMSK_RXTHRESHCMP_E_DISD 0x0 +/* + * Enumerated value for register field ALT_QSPI_IRQMSK_RXTHRESHCMP + * + * Enable Interrupt + */ +#define ALT_QSPI_IRQMSK_RXTHRESHCMP_E_END 0x1 + +/* The Least Significant Bit (LSB) position of the ALT_QSPI_IRQMSK_RXTHRESHCMP register field. */ +#define ALT_QSPI_IRQMSK_RXTHRESHCMP_LSB 10 +/* The Most Significant Bit (MSB) position of the ALT_QSPI_IRQMSK_RXTHRESHCMP register field. */ +#define ALT_QSPI_IRQMSK_RXTHRESHCMP_MSB 10 +/* The width in bits of the ALT_QSPI_IRQMSK_RXTHRESHCMP register field. */ +#define ALT_QSPI_IRQMSK_RXTHRESHCMP_WIDTH 1 +/* The mask used to set the ALT_QSPI_IRQMSK_RXTHRESHCMP register field value. */ +#define ALT_QSPI_IRQMSK_RXTHRESHCMP_SET_MSK 0x00000400 +/* The mask used to clear the ALT_QSPI_IRQMSK_RXTHRESHCMP register field value. */ +#define ALT_QSPI_IRQMSK_RXTHRESHCMP_CLR_MSK 0xfffffbff +/* The reset value of the ALT_QSPI_IRQMSK_RXTHRESHCMP register field. */ +#define ALT_QSPI_IRQMSK_RXTHRESHCMP_RESET 0x0 +/* Extracts the ALT_QSPI_IRQMSK_RXTHRESHCMP field value from a register. */ +#define ALT_QSPI_IRQMSK_RXTHRESHCMP_GET(value) (((value) & 0x00000400) >> 10) +/* Produces a ALT_QSPI_IRQMSK_RXTHRESHCMP register field value suitable for setting the register. */ +#define ALT_QSPI_IRQMSK_RXTHRESHCMP_SET(value) (((value) << 10) & 0x00000400) + +/* + * Field : Receive FIFO full Mask - rxfull + * + * Field Enumeration Values: + * + * Enum | Value | Description + * :------------------------------|:------|:----------------------------- + * ALT_QSPI_IRQMSK_RXFULL_E_DISD | 0x0 | Disable Interrupt by Masking + * ALT_QSPI_IRQMSK_RXFULL_E_END | 0x1 | Enable Interrupt + * + * Field Access Macros: + * + */ +/* + * Enumerated value for register field ALT_QSPI_IRQMSK_RXFULL + * + * Disable Interrupt by Masking + */ +#define ALT_QSPI_IRQMSK_RXFULL_E_DISD 0x0 +/* + * Enumerated value for register field ALT_QSPI_IRQMSK_RXFULL + * + * Enable Interrupt + */ +#define ALT_QSPI_IRQMSK_RXFULL_E_END 0x1 + +/* The Least Significant Bit (LSB) position of the ALT_QSPI_IRQMSK_RXFULL register field. */ +#define ALT_QSPI_IRQMSK_RXFULL_LSB 11 +/* The Most Significant Bit (MSB) position of the ALT_QSPI_IRQMSK_RXFULL register field. */ +#define ALT_QSPI_IRQMSK_RXFULL_MSB 11 +/* The width in bits of the ALT_QSPI_IRQMSK_RXFULL register field. */ +#define ALT_QSPI_IRQMSK_RXFULL_WIDTH 1 +/* The mask used to set the ALT_QSPI_IRQMSK_RXFULL register field value. */ +#define ALT_QSPI_IRQMSK_RXFULL_SET_MSK 0x00000800 +/* The mask used to clear the ALT_QSPI_IRQMSK_RXFULL register field value. */ +#define ALT_QSPI_IRQMSK_RXFULL_CLR_MSK 0xfffff7ff +/* The reset value of the ALT_QSPI_IRQMSK_RXFULL register field. */ +#define ALT_QSPI_IRQMSK_RXFULL_RESET 0x0 +/* Extracts the ALT_QSPI_IRQMSK_RXFULL field value from a register. */ +#define ALT_QSPI_IRQMSK_RXFULL_GET(value) (((value) & 0x00000800) >> 11) +/* Produces a ALT_QSPI_IRQMSK_RXFULL register field value suitable for setting the register. */ +#define ALT_QSPI_IRQMSK_RXFULL_SET(value) (((value) << 11) & 0x00000800) + +/* + * Field : Indirect Read Partition overflow mask - indsramfull + * + * Field Enumeration Values: + * + * Enum | Value | Description + * :-----------------------------------|:------|:----------------------------- + * ALT_QSPI_IRQMSK_INDSRAMFULL_E_DISD | 0x0 | Disable Interrupt by Masking + * ALT_QSPI_IRQMSK_INDSRAMFULL_E_END | 0x1 | Enable Interrupt + * + * Field Access Macros: + * + */ +/* + * Enumerated value for register field ALT_QSPI_IRQMSK_INDSRAMFULL + * + * Disable Interrupt by Masking + */ +#define ALT_QSPI_IRQMSK_INDSRAMFULL_E_DISD 0x0 +/* + * Enumerated value for register field ALT_QSPI_IRQMSK_INDSRAMFULL + * + * Enable Interrupt + */ +#define ALT_QSPI_IRQMSK_INDSRAMFULL_E_END 0x1 + +/* The Least Significant Bit (LSB) position of the ALT_QSPI_IRQMSK_INDSRAMFULL register field. */ +#define ALT_QSPI_IRQMSK_INDSRAMFULL_LSB 12 +/* The Most Significant Bit (MSB) position of the ALT_QSPI_IRQMSK_INDSRAMFULL register field. */ +#define ALT_QSPI_IRQMSK_INDSRAMFULL_MSB 12 +/* The width in bits of the ALT_QSPI_IRQMSK_INDSRAMFULL register field. */ +#define ALT_QSPI_IRQMSK_INDSRAMFULL_WIDTH 1 +/* The mask used to set the ALT_QSPI_IRQMSK_INDSRAMFULL register field value. */ +#define ALT_QSPI_IRQMSK_INDSRAMFULL_SET_MSK 0x00001000 +/* The mask used to clear the ALT_QSPI_IRQMSK_INDSRAMFULL register field value. */ +#define ALT_QSPI_IRQMSK_INDSRAMFULL_CLR_MSK 0xffffefff +/* The reset value of the ALT_QSPI_IRQMSK_INDSRAMFULL register field. */ +#define ALT_QSPI_IRQMSK_INDSRAMFULL_RESET 0x0 +/* Extracts the ALT_QSPI_IRQMSK_INDSRAMFULL field value from a register. */ +#define ALT_QSPI_IRQMSK_INDSRAMFULL_GET(value) (((value) & 0x00001000) >> 12) +/* Produces a ALT_QSPI_IRQMSK_INDSRAMFULL register field value suitable for setting the register. */ +#define ALT_QSPI_IRQMSK_INDSRAMFULL_SET(value) (((value) << 12) & 0x00001000) + +#ifndef __ASSEMBLY__ +/* + * WARNING: The C register and register group struct declarations are provided for + * convenience and illustrative purposes. They should, however, be used with + * caution as the C language standard provides no guarantees about the alignment or + * atomicity of device memory accesses. The recommended practice for writing + * hardware drivers is to use the SoCAL access macros and alt_read_word() and + * alt_write_word() functions. + * + * The struct declaration for register ALT_QSPI_IRQMSK. + */ +struct ALT_QSPI_IRQMSK_s +{ + uint32_t : 1; /* *UNDEFINED* */ + uint32_t underflowdet : 1; /* Underflow Detected Mask */ + uint32_t indopdone : 1; /* Mask */ + uint32_t indrdreject : 1; /* Indirect Read Reject Mask */ + uint32_t protwrattempt : 1; /* Protected Area Write Attempt Mask */ + uint32_t illegalacc : 1; /* Illegal Access Detected Mask */ + uint32_t indxfrlvl : 1; /* Transfer Watermark Breach Mask */ + uint32_t rxover : 1; /* Receive Overflow Mask */ + uint32_t txthreshcmp : 1; /* Transmit FIFO Threshold Compare Mask */ + uint32_t txfull : 1; /* Transmit FIFO Full Mask */ + uint32_t rxthreshcmp : 1; /* Receive FIFO Threshold Compare Mask */ + uint32_t rxfull : 1; /* Receive FIFO full Mask */ + uint32_t indsramfull : 1; /* Indirect Read Partition overflow mask */ + uint32_t : 19; /* *UNDEFINED* */ +}; + +/* The typedef declaration for register ALT_QSPI_IRQMSK. */ +typedef volatile struct ALT_QSPI_IRQMSK_s ALT_QSPI_IRQMSK_t; +#endif /* __ASSEMBLY__ */ + +/* The byte offset of the ALT_QSPI_IRQMSK register from the beginning of the component. */ +#define ALT_QSPI_IRQMSK_OFST 0x44 + +/* + * Register : Lower Write Protection Register - lowwrprot + * + * Register Layout + * + * Bits | Access | Reset | Description + * :-------|:-------|:------|:------------- + * [31:0] | RW | 0x0 | Block Number + * + */ +/* + * Field : Block Number - subsector + * + * The block number that defines the lower block in the range of blocks that is to + * be locked from writing. The definition of a block in terms of number of bytes is + * programmable via the Device Size Configuration register. + * + * Field Access Macros: + * + */ +/* The Least Significant Bit (LSB) position of the ALT_QSPI_LOWWRPROT_SUBSECTOR register field. */ +#define ALT_QSPI_LOWWRPROT_SUBSECTOR_LSB 0 +/* The Most Significant Bit (MSB) position of the ALT_QSPI_LOWWRPROT_SUBSECTOR register field. */ +#define ALT_QSPI_LOWWRPROT_SUBSECTOR_MSB 31 +/* The width in bits of the ALT_QSPI_LOWWRPROT_SUBSECTOR register field. */ +#define ALT_QSPI_LOWWRPROT_SUBSECTOR_WIDTH 32 +/* The mask used to set the ALT_QSPI_LOWWRPROT_SUBSECTOR register field value. */ +#define ALT_QSPI_LOWWRPROT_SUBSECTOR_SET_MSK 0xffffffff +/* The mask used to clear the ALT_QSPI_LOWWRPROT_SUBSECTOR register field value. */ +#define ALT_QSPI_LOWWRPROT_SUBSECTOR_CLR_MSK 0x00000000 +/* The reset value of the ALT_QSPI_LOWWRPROT_SUBSECTOR register field. */ +#define ALT_QSPI_LOWWRPROT_SUBSECTOR_RESET 0x0 +/* Extracts the ALT_QSPI_LOWWRPROT_SUBSECTOR field value from a register. */ +#define ALT_QSPI_LOWWRPROT_SUBSECTOR_GET(value) (((value) & 0xffffffff) >> 0) +/* Produces a ALT_QSPI_LOWWRPROT_SUBSECTOR register field value suitable for setting the register. */ +#define ALT_QSPI_LOWWRPROT_SUBSECTOR_SET(value) (((value) << 0) & 0xffffffff) + +#ifndef __ASSEMBLY__ +/* + * WARNING: The C register and register group struct declarations are provided for + * convenience and illustrative purposes. They should, however, be used with + * caution as the C language standard provides no guarantees about the alignment or + * atomicity of device memory accesses. The recommended practice for writing + * hardware drivers is to use the SoCAL access macros and alt_read_word() and + * alt_write_word() functions. + * + * The struct declaration for register ALT_QSPI_LOWWRPROT. + */ +struct ALT_QSPI_LOWWRPROT_s +{ + uint32_t subsector : 32; /* Block Number */ +}; + +/* The typedef declaration for register ALT_QSPI_LOWWRPROT. */ +typedef volatile struct ALT_QSPI_LOWWRPROT_s ALT_QSPI_LOWWRPROT_t; +#endif /* __ASSEMBLY__ */ + +/* The byte offset of the ALT_QSPI_LOWWRPROT register from the beginning of the component. */ +#define ALT_QSPI_LOWWRPROT_OFST 0x50 + +/* + * Register : Upper Write Protection Register - uppwrprot + * + * Register Layout + * + * Bits | Access | Reset | Description + * :-------|:-------|:------|:------------- + * [31:0] | RW | 0x0 | Block Number + * + */ +/* + * Field : Block Number - subsector + * + * The block number that defines the upper block in the range of blocks that is to + * be locked from writing. The definition of a block in terms of number of bytes is + * programmable via the Device Size Configuration register. + * + * Field Access Macros: + * + */ +/* The Least Significant Bit (LSB) position of the ALT_QSPI_UPPWRPROT_SUBSECTOR register field. */ +#define ALT_QSPI_UPPWRPROT_SUBSECTOR_LSB 0 +/* The Most Significant Bit (MSB) position of the ALT_QSPI_UPPWRPROT_SUBSECTOR register field. */ +#define ALT_QSPI_UPPWRPROT_SUBSECTOR_MSB 31 +/* The width in bits of the ALT_QSPI_UPPWRPROT_SUBSECTOR register field. */ +#define ALT_QSPI_UPPWRPROT_SUBSECTOR_WIDTH 32 +/* The mask used to set the ALT_QSPI_UPPWRPROT_SUBSECTOR register field value. */ +#define ALT_QSPI_UPPWRPROT_SUBSECTOR_SET_MSK 0xffffffff +/* The mask used to clear the ALT_QSPI_UPPWRPROT_SUBSECTOR register field value. */ +#define ALT_QSPI_UPPWRPROT_SUBSECTOR_CLR_MSK 0x00000000 +/* The reset value of the ALT_QSPI_UPPWRPROT_SUBSECTOR register field. */ +#define ALT_QSPI_UPPWRPROT_SUBSECTOR_RESET 0x0 +/* Extracts the ALT_QSPI_UPPWRPROT_SUBSECTOR field value from a register. */ +#define ALT_QSPI_UPPWRPROT_SUBSECTOR_GET(value) (((value) & 0xffffffff) >> 0) +/* Produces a ALT_QSPI_UPPWRPROT_SUBSECTOR register field value suitable for setting the register. */ +#define ALT_QSPI_UPPWRPROT_SUBSECTOR_SET(value) (((value) << 0) & 0xffffffff) + +#ifndef __ASSEMBLY__ +/* + * WARNING: The C register and register group struct declarations are provided for + * convenience and illustrative purposes. They should, however, be used with + * caution as the C language standard provides no guarantees about the alignment or + * atomicity of device memory accesses. The recommended practice for writing + * hardware drivers is to use the SoCAL access macros and alt_read_word() and + * alt_write_word() functions. + * + * The struct declaration for register ALT_QSPI_UPPWRPROT. + */ +struct ALT_QSPI_UPPWRPROT_s +{ + uint32_t subsector : 32; /* Block Number */ +}; + +/* The typedef declaration for register ALT_QSPI_UPPWRPROT. */ +typedef volatile struct ALT_QSPI_UPPWRPROT_s ALT_QSPI_UPPWRPROT_t; +#endif /* __ASSEMBLY__ */ + +/* The byte offset of the ALT_QSPI_UPPWRPROT register from the beginning of the component. */ +#define ALT_QSPI_UPPWRPROT_OFST 0x54 + +/* + * Register : Write Protection Register - wrprot + * + * Register Layout + * + * Bits | Access | Reset | Description + * :-------|:-------|:------|:------------------------------- + * [0] | RW | 0x0 | Write Protection Inversion Bit + * [1] | RW | 0x0 | Write Protection Enable Bit + * [31:2] | ??? | 0x0 | *UNDEFINED* + * + */ +/* + * Field : Write Protection Inversion Bit - inv + * + * When enabled, the protection region defined in the lower and upper write + * protection registers is inverted meaning it is the region that the system is + * permitted to write to. When disabled, the protection region defined in the lower + * and upper write protection registers is the region that the system is not + * permitted to write to. + * + * Field Enumeration Values: + * + * Enum | Value | Description + * :--------------------------|:------|:------------------------- + * ALT_QSPI_WRPROT_INV_E_EN | 0x1 | Write Region allowed + * ALT_QSPI_WRPROT_INV_E_DIS | 0x0 | Write Region not allowed + * + * Field Access Macros: + * + */ +/* + * Enumerated value for register field ALT_QSPI_WRPROT_INV + * + * Write Region allowed + */ +#define ALT_QSPI_WRPROT_INV_E_EN 0x1 +/* + * Enumerated value for register field ALT_QSPI_WRPROT_INV + * + * Write Region not allowed + */ +#define ALT_QSPI_WRPROT_INV_E_DIS 0x0 + +/* The Least Significant Bit (LSB) position of the ALT_QSPI_WRPROT_INV register field. */ +#define ALT_QSPI_WRPROT_INV_LSB 0 +/* The Most Significant Bit (MSB) position of the ALT_QSPI_WRPROT_INV register field. */ +#define ALT_QSPI_WRPROT_INV_MSB 0 +/* The width in bits of the ALT_QSPI_WRPROT_INV register field. */ +#define ALT_QSPI_WRPROT_INV_WIDTH 1 +/* The mask used to set the ALT_QSPI_WRPROT_INV register field value. */ +#define ALT_QSPI_WRPROT_INV_SET_MSK 0x00000001 +/* The mask used to clear the ALT_QSPI_WRPROT_INV register field value. */ +#define ALT_QSPI_WRPROT_INV_CLR_MSK 0xfffffffe +/* The reset value of the ALT_QSPI_WRPROT_INV register field. */ +#define ALT_QSPI_WRPROT_INV_RESET 0x0 +/* Extracts the ALT_QSPI_WRPROT_INV field value from a register. */ +#define ALT_QSPI_WRPROT_INV_GET(value) (((value) & 0x00000001) >> 0) +/* Produces a ALT_QSPI_WRPROT_INV register field value suitable for setting the register. */ +#define ALT_QSPI_WRPROT_INV_SET(value) (((value) << 0) & 0x00000001) + +/* + * Field : Write Protection Enable Bit - en + * + * When enabled, any AHB write access with an address within the protection region + * defined in the lower and upper write protection registers is rejected. An AHB + * error response is generated and an interrupt source triggered. When disabled, + * the protection region is disabled. + * + * Field Enumeration Values: + * + * Enum | Value | Description + * :-------------------------|:------|:--------------------------- + * ALT_QSPI_WRPROT_EN_E_EN | 0x1 | AHB Write Access rejected + * ALT_QSPI_WRPROT_EN_E_DIS | 0x0 | Protection Region Disabled + * + * Field Access Macros: + * + */ +/* + * Enumerated value for register field ALT_QSPI_WRPROT_EN + * + * AHB Write Access rejected + */ +#define ALT_QSPI_WRPROT_EN_E_EN 0x1 +/* + * Enumerated value for register field ALT_QSPI_WRPROT_EN + * + * Protection Region Disabled + */ +#define ALT_QSPI_WRPROT_EN_E_DIS 0x0 + +/* The Least Significant Bit (LSB) position of the ALT_QSPI_WRPROT_EN register field. */ +#define ALT_QSPI_WRPROT_EN_LSB 1 +/* The Most Significant Bit (MSB) position of the ALT_QSPI_WRPROT_EN register field. */ +#define ALT_QSPI_WRPROT_EN_MSB 1 +/* The width in bits of the ALT_QSPI_WRPROT_EN register field. */ +#define ALT_QSPI_WRPROT_EN_WIDTH 1 +/* The mask used to set the ALT_QSPI_WRPROT_EN register field value. */ +#define ALT_QSPI_WRPROT_EN_SET_MSK 0x00000002 +/* The mask used to clear the ALT_QSPI_WRPROT_EN register field value. */ +#define ALT_QSPI_WRPROT_EN_CLR_MSK 0xfffffffd +/* The reset value of the ALT_QSPI_WRPROT_EN register field. */ +#define ALT_QSPI_WRPROT_EN_RESET 0x0 +/* Extracts the ALT_QSPI_WRPROT_EN field value from a register. */ +#define ALT_QSPI_WRPROT_EN_GET(value) (((value) & 0x00000002) >> 1) +/* Produces a ALT_QSPI_WRPROT_EN register field value suitable for setting the register. */ +#define ALT_QSPI_WRPROT_EN_SET(value) (((value) << 1) & 0x00000002) + +#ifndef __ASSEMBLY__ +/* + * WARNING: The C register and register group struct declarations are provided for + * convenience and illustrative purposes. They should, however, be used with + * caution as the C language standard provides no guarantees about the alignment or + * atomicity of device memory accesses. The recommended practice for writing + * hardware drivers is to use the SoCAL access macros and alt_read_word() and + * alt_write_word() functions. + * + * The struct declaration for register ALT_QSPI_WRPROT. + */ +struct ALT_QSPI_WRPROT_s +{ + uint32_t inv : 1; /* Write Protection Inversion Bit */ + uint32_t en : 1; /* Write Protection Enable Bit */ + uint32_t : 30; /* *UNDEFINED* */ +}; + +/* The typedef declaration for register ALT_QSPI_WRPROT. */ +typedef volatile struct ALT_QSPI_WRPROT_s ALT_QSPI_WRPROT_t; +#endif /* __ASSEMBLY__ */ + +/* The byte offset of the ALT_QSPI_WRPROT register from the beginning of the component. */ +#define ALT_QSPI_WRPROT_OFST 0x58 + +/* + * Register : Indirect Read Transfer Register - indrd + * + * Register Layout + * + * Bits | Access | Reset | Description + * :-------|:-------|:--------|:-------------------------------- + * [0] | RW | 0x0 | Start Indirect Read + * [1] | RW | 0x0 | Cancel Indirect Read + * [2] | R | Unknown | Indirect Read Status + * [3] | RW | Unknown | SRAM Full + * [4] | R | Unknown | Queued Indirect Read Operations + * [5] | RW | Unknown | Indirect Completion Status + * [7:6] | R | Unknown | Completed Indirect Operations + * [31:8] | ??? | 0x0 | *UNDEFINED* + * + */ +/* + * Field : Start Indirect Read - start + * + * When this bit is enabled, it will trigger an indirect read operation. The + * assumption is that the indirect start address and the indirect number of bytes + * register is setup before triggering the indirect read operation. + * + * Field Enumeration Values: + * + * Enum | Value | Description + * :----------------------------|:------|:---------------------- + * ALT_QSPI_INDRD_START_E_END | 0x1 | Trigger Indirect Read + * ALT_QSPI_INDRD_START_E_DISD | 0x0 | No Indirect Read + * + * Field Access Macros: + * + */ +/* + * Enumerated value for register field ALT_QSPI_INDRD_START + * + * Trigger Indirect Read + */ +#define ALT_QSPI_INDRD_START_E_END 0x1 +/* + * Enumerated value for register field ALT_QSPI_INDRD_START + * + * No Indirect Read + */ +#define ALT_QSPI_INDRD_START_E_DISD 0x0 + +/* The Least Significant Bit (LSB) position of the ALT_QSPI_INDRD_START register field. */ +#define ALT_QSPI_INDRD_START_LSB 0 +/* The Most Significant Bit (MSB) position of the ALT_QSPI_INDRD_START register field. */ +#define ALT_QSPI_INDRD_START_MSB 0 +/* The width in bits of the ALT_QSPI_INDRD_START register field. */ +#define ALT_QSPI_INDRD_START_WIDTH 1 +/* The mask used to set the ALT_QSPI_INDRD_START register field value. */ +#define ALT_QSPI_INDRD_START_SET_MSK 0x00000001 +/* The mask used to clear the ALT_QSPI_INDRD_START register field value. */ +#define ALT_QSPI_INDRD_START_CLR_MSK 0xfffffffe +/* The reset value of the ALT_QSPI_INDRD_START register field. */ +#define ALT_QSPI_INDRD_START_RESET 0x0 +/* Extracts the ALT_QSPI_INDRD_START field value from a register. */ +#define ALT_QSPI_INDRD_START_GET(value) (((value) & 0x00000001) >> 0) +/* Produces a ALT_QSPI_INDRD_START register field value suitable for setting the register. */ +#define ALT_QSPI_INDRD_START_SET(value) (((value) << 0) & 0x00000001) + +/* + * Field : Cancel Indirect Read - cancel + * + * This bit will cancel all ongoing indirect read operations. + * + * Field Enumeration Values: + * + * Enum | Value | Description + * :---------------------------------|:------|:---------------------------- + * ALT_QSPI_INDRD_CANCEL_E_CANCEL | 0x1 | Cancel Indirect Read + * ALT_QSPI_INDRD_CANCEL_E_NOACTION | 0x0 | Do Not Cancel Indirect Read + * + * Field Access Macros: + * + */ +/* + * Enumerated value for register field ALT_QSPI_INDRD_CANCEL + * + * Cancel Indirect Read + */ +#define ALT_QSPI_INDRD_CANCEL_E_CANCEL 0x1 +/* + * Enumerated value for register field ALT_QSPI_INDRD_CANCEL + * + * Do Not Cancel Indirect Read + */ +#define ALT_QSPI_INDRD_CANCEL_E_NOACTION 0x0 + +/* The Least Significant Bit (LSB) position of the ALT_QSPI_INDRD_CANCEL register field. */ +#define ALT_QSPI_INDRD_CANCEL_LSB 1 +/* The Most Significant Bit (MSB) position of the ALT_QSPI_INDRD_CANCEL register field. */ +#define ALT_QSPI_INDRD_CANCEL_MSB 1 +/* The width in bits of the ALT_QSPI_INDRD_CANCEL register field. */ +#define ALT_QSPI_INDRD_CANCEL_WIDTH 1 +/* The mask used to set the ALT_QSPI_INDRD_CANCEL register field value. */ +#define ALT_QSPI_INDRD_CANCEL_SET_MSK 0x00000002 +/* The mask used to clear the ALT_QSPI_INDRD_CANCEL register field value. */ +#define ALT_QSPI_INDRD_CANCEL_CLR_MSK 0xfffffffd +/* The reset value of the ALT_QSPI_INDRD_CANCEL register field. */ +#define ALT_QSPI_INDRD_CANCEL_RESET 0x0 +/* Extracts the ALT_QSPI_INDRD_CANCEL field value from a register. */ +#define ALT_QSPI_INDRD_CANCEL_GET(value) (((value) & 0x00000002) >> 1) +/* Produces a ALT_QSPI_INDRD_CANCEL register field value suitable for setting the register. */ +#define ALT_QSPI_INDRD_CANCEL_SET(value) (((value) << 1) & 0x00000002) + +/* + * Field : Indirect Read Status - rd_status + * + * Indirect read operation in progress (status) + * + * Field Enumeration Values: + * + * Enum | Value | Description + * :----------------------------------|:------|:------------------------------ + * ALT_QSPI_INDRD_RD_STAT_E_RDOP | 0x1 | Read Operation in progress + * ALT_QSPI_INDRD_RD_STAT_E_NOACTION | 0x0 | No read operation in progress + * + * Field Access Macros: + * + */ +/* + * Enumerated value for register field ALT_QSPI_INDRD_RD_STAT + * + * Read Operation in progress + */ +#define ALT_QSPI_INDRD_RD_STAT_E_RDOP 0x1 +/* + * Enumerated value for register field ALT_QSPI_INDRD_RD_STAT + * + * No read operation in progress + */ +#define ALT_QSPI_INDRD_RD_STAT_E_NOACTION 0x0 + +/* The Least Significant Bit (LSB) position of the ALT_QSPI_INDRD_RD_STAT register field. */ +#define ALT_QSPI_INDRD_RD_STAT_LSB 2 +/* The Most Significant Bit (MSB) position of the ALT_QSPI_INDRD_RD_STAT register field. */ +#define ALT_QSPI_INDRD_RD_STAT_MSB 2 +/* The width in bits of the ALT_QSPI_INDRD_RD_STAT register field. */ +#define ALT_QSPI_INDRD_RD_STAT_WIDTH 1 +/* The mask used to set the ALT_QSPI_INDRD_RD_STAT register field value. */ +#define ALT_QSPI_INDRD_RD_STAT_SET_MSK 0x00000004 +/* The mask used to clear the ALT_QSPI_INDRD_RD_STAT register field value. */ +#define ALT_QSPI_INDRD_RD_STAT_CLR_MSK 0xfffffffb +/* The reset value of the ALT_QSPI_INDRD_RD_STAT register field is UNKNOWN. */ +#define ALT_QSPI_INDRD_RD_STAT_RESET 0x0 +/* Extracts the ALT_QSPI_INDRD_RD_STAT field value from a register. */ +#define ALT_QSPI_INDRD_RD_STAT_GET(value) (((value) & 0x00000004) >> 2) +/* Produces a ALT_QSPI_INDRD_RD_STAT register field value suitable for setting the register. */ +#define ALT_QSPI_INDRD_RD_STAT_SET(value) (((value) << 2) & 0x00000004) + +/* + * Field : SRAM Full - sram_full + * + * SRAM full and unable to immediately complete an indirect operation. Write a 1 to + * this field to clear it. ; indirect operation (status) + * + * Field Enumeration Values: + * + * Enum | Value | Description + * :------------------------------------|:------|:----------------------------------- + * ALT_QSPI_INDRD_SRAM_FULL_E_SRAMFULL | 0x1 | Sram Full- Cant complete operation + * ALT_QSPI_INDRD_SRAM_FULL_E_NOACTION | 0x0 | SRram Not Full + * + * Field Access Macros: + * + */ +/* + * Enumerated value for register field ALT_QSPI_INDRD_SRAM_FULL + * + * Sram Full- Cant complete operation + */ +#define ALT_QSPI_INDRD_SRAM_FULL_E_SRAMFULL 0x1 +/* + * Enumerated value for register field ALT_QSPI_INDRD_SRAM_FULL + * + * SRram Not Full + */ +#define ALT_QSPI_INDRD_SRAM_FULL_E_NOACTION 0x0 + +/* The Least Significant Bit (LSB) position of the ALT_QSPI_INDRD_SRAM_FULL register field. */ +#define ALT_QSPI_INDRD_SRAM_FULL_LSB 3 +/* The Most Significant Bit (MSB) position of the ALT_QSPI_INDRD_SRAM_FULL register field. */ +#define ALT_QSPI_INDRD_SRAM_FULL_MSB 3 +/* The width in bits of the ALT_QSPI_INDRD_SRAM_FULL register field. */ +#define ALT_QSPI_INDRD_SRAM_FULL_WIDTH 1 +/* The mask used to set the ALT_QSPI_INDRD_SRAM_FULL register field value. */ +#define ALT_QSPI_INDRD_SRAM_FULL_SET_MSK 0x00000008 +/* The mask used to clear the ALT_QSPI_INDRD_SRAM_FULL register field value. */ +#define ALT_QSPI_INDRD_SRAM_FULL_CLR_MSK 0xfffffff7 +/* The reset value of the ALT_QSPI_INDRD_SRAM_FULL register field is UNKNOWN. */ +#define ALT_QSPI_INDRD_SRAM_FULL_RESET 0x0 +/* Extracts the ALT_QSPI_INDRD_SRAM_FULL field value from a register. */ +#define ALT_QSPI_INDRD_SRAM_FULL_GET(value) (((value) & 0x00000008) >> 3) +/* Produces a ALT_QSPI_INDRD_SRAM_FULL register field value suitable for setting the register. */ +#define ALT_QSPI_INDRD_SRAM_FULL_SET(value) (((value) << 3) & 0x00000008) + +/* + * Field : Queued Indirect Read Operations - rd_queued + * + * Two indirect read operations have been queued + * + * Field Enumeration Values: + * + * Enum | Value | Description + * :----------------------------------------|:------|:--------------------- + * ALT_QSPI_INDRD_RD_QUEUED_E_QUINDIRECTRD | 0x1 | Queued Indirect Read + * ALT_QSPI_INDRD_RD_QUEUED_E_NOACTION | 0x0 | No Queued Read + * + * Field Access Macros: + * + */ +/* + * Enumerated value for register field ALT_QSPI_INDRD_RD_QUEUED + * + * Queued Indirect Read + */ +#define ALT_QSPI_INDRD_RD_QUEUED_E_QUINDIRECTRD 0x1 +/* + * Enumerated value for register field ALT_QSPI_INDRD_RD_QUEUED + * + * No Queued Read + */ +#define ALT_QSPI_INDRD_RD_QUEUED_E_NOACTION 0x0 + +/* The Least Significant Bit (LSB) position of the ALT_QSPI_INDRD_RD_QUEUED register field. */ +#define ALT_QSPI_INDRD_RD_QUEUED_LSB 4 +/* The Most Significant Bit (MSB) position of the ALT_QSPI_INDRD_RD_QUEUED register field. */ +#define ALT_QSPI_INDRD_RD_QUEUED_MSB 4 +/* The width in bits of the ALT_QSPI_INDRD_RD_QUEUED register field. */ +#define ALT_QSPI_INDRD_RD_QUEUED_WIDTH 1 +/* The mask used to set the ALT_QSPI_INDRD_RD_QUEUED register field value. */ +#define ALT_QSPI_INDRD_RD_QUEUED_SET_MSK 0x00000010 +/* The mask used to clear the ALT_QSPI_INDRD_RD_QUEUED register field value. */ +#define ALT_QSPI_INDRD_RD_QUEUED_CLR_MSK 0xffffffef +/* The reset value of the ALT_QSPI_INDRD_RD_QUEUED register field is UNKNOWN. */ +#define ALT_QSPI_INDRD_RD_QUEUED_RESET 0x0 +/* Extracts the ALT_QSPI_INDRD_RD_QUEUED field value from a register. */ +#define ALT_QSPI_INDRD_RD_QUEUED_GET(value) (((value) & 0x00000010) >> 4) +/* Produces a ALT_QSPI_INDRD_RD_QUEUED register field value suitable for setting the register. */ +#define ALT_QSPI_INDRD_RD_QUEUED_SET(value) (((value) << 4) & 0x00000010) + +/* + * Field : Indirect Completion Status - ind_ops_done_status + * + * This field is set to 1 when an indirect operation has completed. Write a 1 to + * this field to clear it. + * + * Field Enumeration Values: + * + * Enum | Value | Description + * :--------------------------------------------|:------|:------------------------------- + * ALT_QSPI_INDRD_IND_OPS_DONE_STAT_E_INDCOMP | 0x1 | Indirect Op Complete operation + * ALT_QSPI_INDRD_IND_OPS_DONE_STAT_E_NOACTION | 0x0 | Indirect Op Not Complete + * + * Field Access Macros: + * + */ +/* + * Enumerated value for register field ALT_QSPI_INDRD_IND_OPS_DONE_STAT + * + * Indirect Op Complete operation + */ +#define ALT_QSPI_INDRD_IND_OPS_DONE_STAT_E_INDCOMP 0x1 +/* + * Enumerated value for register field ALT_QSPI_INDRD_IND_OPS_DONE_STAT + * + * Indirect Op Not Complete + */ +#define ALT_QSPI_INDRD_IND_OPS_DONE_STAT_E_NOACTION 0x0 + +/* The Least Significant Bit (LSB) position of the ALT_QSPI_INDRD_IND_OPS_DONE_STAT register field. */ +#define ALT_QSPI_INDRD_IND_OPS_DONE_STAT_LSB 5 +/* The Most Significant Bit (MSB) position of the ALT_QSPI_INDRD_IND_OPS_DONE_STAT register field. */ +#define ALT_QSPI_INDRD_IND_OPS_DONE_STAT_MSB 5 +/* The width in bits of the ALT_QSPI_INDRD_IND_OPS_DONE_STAT register field. */ +#define ALT_QSPI_INDRD_IND_OPS_DONE_STAT_WIDTH 1 +/* The mask used to set the ALT_QSPI_INDRD_IND_OPS_DONE_STAT register field value. */ +#define ALT_QSPI_INDRD_IND_OPS_DONE_STAT_SET_MSK 0x00000020 +/* The mask used to clear the ALT_QSPI_INDRD_IND_OPS_DONE_STAT register field value. */ +#define ALT_QSPI_INDRD_IND_OPS_DONE_STAT_CLR_MSK 0xffffffdf +/* The reset value of the ALT_QSPI_INDRD_IND_OPS_DONE_STAT register field is UNKNOWN. */ +#define ALT_QSPI_INDRD_IND_OPS_DONE_STAT_RESET 0x0 +/* Extracts the ALT_QSPI_INDRD_IND_OPS_DONE_STAT field value from a register. */ +#define ALT_QSPI_INDRD_IND_OPS_DONE_STAT_GET(value) (((value) & 0x00000020) >> 5) +/* Produces a ALT_QSPI_INDRD_IND_OPS_DONE_STAT register field value suitable for setting the register. */ +#define ALT_QSPI_INDRD_IND_OPS_DONE_STAT_SET(value) (((value) << 5) & 0x00000020) + +/* + * Field : Completed Indirect Operations - num_ind_ops_done + * + * This field contains the number of indirect operations which have been completed. + * This is used in conjunction with the indirect completion status field (bit 5). + * + * Field Access Macros: + * + */ +/* The Least Significant Bit (LSB) position of the ALT_QSPI_INDRD_NUM_IND_OPS_DONE register field. */ +#define ALT_QSPI_INDRD_NUM_IND_OPS_DONE_LSB 6 +/* The Most Significant Bit (MSB) position of the ALT_QSPI_INDRD_NUM_IND_OPS_DONE register field. */ +#define ALT_QSPI_INDRD_NUM_IND_OPS_DONE_MSB 7 +/* The width in bits of the ALT_QSPI_INDRD_NUM_IND_OPS_DONE register field. */ +#define ALT_QSPI_INDRD_NUM_IND_OPS_DONE_WIDTH 2 +/* The mask used to set the ALT_QSPI_INDRD_NUM_IND_OPS_DONE register field value. */ +#define ALT_QSPI_INDRD_NUM_IND_OPS_DONE_SET_MSK 0x000000c0 +/* The mask used to clear the ALT_QSPI_INDRD_NUM_IND_OPS_DONE register field value. */ +#define ALT_QSPI_INDRD_NUM_IND_OPS_DONE_CLR_MSK 0xffffff3f +/* The reset value of the ALT_QSPI_INDRD_NUM_IND_OPS_DONE register field is UNKNOWN. */ +#define ALT_QSPI_INDRD_NUM_IND_OPS_DONE_RESET 0x0 +/* Extracts the ALT_QSPI_INDRD_NUM_IND_OPS_DONE field value from a register. */ +#define ALT_QSPI_INDRD_NUM_IND_OPS_DONE_GET(value) (((value) & 0x000000c0) >> 6) +/* Produces a ALT_QSPI_INDRD_NUM_IND_OPS_DONE register field value suitable for setting the register. */ +#define ALT_QSPI_INDRD_NUM_IND_OPS_DONE_SET(value) (((value) << 6) & 0x000000c0) + +#ifndef __ASSEMBLY__ +/* + * WARNING: The C register and register group struct declarations are provided for + * convenience and illustrative purposes. They should, however, be used with + * caution as the C language standard provides no guarantees about the alignment or + * atomicity of device memory accesses. The recommended practice for writing + * hardware drivers is to use the SoCAL access macros and alt_read_word() and + * alt_write_word() functions. + * + * The struct declaration for register ALT_QSPI_INDRD. + */ +struct ALT_QSPI_INDRD_s +{ + uint32_t start : 1; /* Start Indirect Read */ + uint32_t cancel : 1; /* Cancel Indirect Read */ + const uint32_t rd_status : 1; /* Indirect Read Status */ + uint32_t sram_full : 1; /* SRAM Full */ + const uint32_t rd_queued : 1; /* Queued Indirect Read Operations */ + uint32_t ind_ops_done_status : 1; /* Indirect Completion Status */ + const uint32_t num_ind_ops_done : 2; /* Completed Indirect Operations */ + uint32_t : 24; /* *UNDEFINED* */ +}; + +/* The typedef declaration for register ALT_QSPI_INDRD. */ +typedef volatile struct ALT_QSPI_INDRD_s ALT_QSPI_INDRD_t; +#endif /* __ASSEMBLY__ */ + +/* The byte offset of the ALT_QSPI_INDRD register from the beginning of the component. */ +#define ALT_QSPI_INDRD_OFST 0x60 + +/* + * Register : Indirect Read Transfer Watermark Register - indrdwater + * + * Register Layout + * + * Bits | Access | Reset | Description + * :-------|:-------|:------|:---------------- + * [31:0] | RW | 0x0 | Watermark Value + * + */ +/* + * Field : Watermark Value - level + * + * This represents the minimum fill level of the SRAM before a DMA peripheral + * access is permitted. When the SRAM fill level passes the watermark, an interrupt + * is also generated. This field can be disabled by writing a value of all zeroes. + * The units of this register are BYTES + * + * Field Access Macros: + * + */ +/* The Least Significant Bit (LSB) position of the ALT_QSPI_INDRDWATER_LEVEL register field. */ +#define ALT_QSPI_INDRDWATER_LEVEL_LSB 0 +/* The Most Significant Bit (MSB) position of the ALT_QSPI_INDRDWATER_LEVEL register field. */ +#define ALT_QSPI_INDRDWATER_LEVEL_MSB 31 +/* The width in bits of the ALT_QSPI_INDRDWATER_LEVEL register field. */ +#define ALT_QSPI_INDRDWATER_LEVEL_WIDTH 32 +/* The mask used to set the ALT_QSPI_INDRDWATER_LEVEL register field value. */ +#define ALT_QSPI_INDRDWATER_LEVEL_SET_MSK 0xffffffff +/* The mask used to clear the ALT_QSPI_INDRDWATER_LEVEL register field value. */ +#define ALT_QSPI_INDRDWATER_LEVEL_CLR_MSK 0x00000000 +/* The reset value of the ALT_QSPI_INDRDWATER_LEVEL register field. */ +#define ALT_QSPI_INDRDWATER_LEVEL_RESET 0x0 +/* Extracts the ALT_QSPI_INDRDWATER_LEVEL field value from a register. */ +#define ALT_QSPI_INDRDWATER_LEVEL_GET(value) (((value) & 0xffffffff) >> 0) +/* Produces a ALT_QSPI_INDRDWATER_LEVEL register field value suitable for setting the register. */ +#define ALT_QSPI_INDRDWATER_LEVEL_SET(value) (((value) << 0) & 0xffffffff) + +#ifndef __ASSEMBLY__ +/* + * WARNING: The C register and register group struct declarations are provided for + * convenience and illustrative purposes. They should, however, be used with + * caution as the C language standard provides no guarantees about the alignment or + * atomicity of device memory accesses. The recommended practice for writing + * hardware drivers is to use the SoCAL access macros and alt_read_word() and + * alt_write_word() functions. + * + * The struct declaration for register ALT_QSPI_INDRDWATER. + */ +struct ALT_QSPI_INDRDWATER_s +{ + uint32_t level : 32; /* Watermark Value */ +}; + +/* The typedef declaration for register ALT_QSPI_INDRDWATER. */ +typedef volatile struct ALT_QSPI_INDRDWATER_s ALT_QSPI_INDRDWATER_t; +#endif /* __ASSEMBLY__ */ + +/* The byte offset of the ALT_QSPI_INDRDWATER register from the beginning of the component. */ +#define ALT_QSPI_INDRDWATER_OFST 0x64 + +/* + * Register : Indirect Read Transfer Start Address Register - indrdstaddr + * + * Register Layout + * + * Bits | Access | Reset | Description + * :-------|:-------|:------|:--------------------------------- + * [31:0] | RW | 0x0 | Start Address of Indirect Access + * + */ +/* + * Field : Start Address of Indirect Access - addr + * + * This is the start address from which the indirect access will commence its READ + * operation. + * + * Field Access Macros: + * + */ +/* The Least Significant Bit (LSB) position of the ALT_QSPI_INDRDSTADDR_ADDR register field. */ +#define ALT_QSPI_INDRDSTADDR_ADDR_LSB 0 +/* The Most Significant Bit (MSB) position of the ALT_QSPI_INDRDSTADDR_ADDR register field. */ +#define ALT_QSPI_INDRDSTADDR_ADDR_MSB 31 +/* The width in bits of the ALT_QSPI_INDRDSTADDR_ADDR register field. */ +#define ALT_QSPI_INDRDSTADDR_ADDR_WIDTH 32 +/* The mask used to set the ALT_QSPI_INDRDSTADDR_ADDR register field value. */ +#define ALT_QSPI_INDRDSTADDR_ADDR_SET_MSK 0xffffffff +/* The mask used to clear the ALT_QSPI_INDRDSTADDR_ADDR register field value. */ +#define ALT_QSPI_INDRDSTADDR_ADDR_CLR_MSK 0x00000000 +/* The reset value of the ALT_QSPI_INDRDSTADDR_ADDR register field. */ +#define ALT_QSPI_INDRDSTADDR_ADDR_RESET 0x0 +/* Extracts the ALT_QSPI_INDRDSTADDR_ADDR field value from a register. */ +#define ALT_QSPI_INDRDSTADDR_ADDR_GET(value) (((value) & 0xffffffff) >> 0) +/* Produces a ALT_QSPI_INDRDSTADDR_ADDR register field value suitable for setting the register. */ +#define ALT_QSPI_INDRDSTADDR_ADDR_SET(value) (((value) << 0) & 0xffffffff) + +#ifndef __ASSEMBLY__ +/* + * WARNING: The C register and register group struct declarations are provided for + * convenience and illustrative purposes. They should, however, be used with + * caution as the C language standard provides no guarantees about the alignment or + * atomicity of device memory accesses. The recommended practice for writing + * hardware drivers is to use the SoCAL access macros and alt_read_word() and + * alt_write_word() functions. + * + * The struct declaration for register ALT_QSPI_INDRDSTADDR. + */ +struct ALT_QSPI_INDRDSTADDR_s +{ + uint32_t addr : 32; /* Start Address of Indirect Access */ +}; + +/* The typedef declaration for register ALT_QSPI_INDRDSTADDR. */ +typedef volatile struct ALT_QSPI_INDRDSTADDR_s ALT_QSPI_INDRDSTADDR_t; +#endif /* __ASSEMBLY__ */ + +/* The byte offset of the ALT_QSPI_INDRDSTADDR register from the beginning of the component. */ +#define ALT_QSPI_INDRDSTADDR_OFST 0x68 + +/* + * Register : Indirect Read Transfer Number Bytes Register - indrdcnt + * + * Register Layout + * + * Bits | Access | Reset | Description + * :-------|:-------|:------|:--------------- + * [31:0] | RW | 0x0 | Indirect Count + * + */ +/* + * Field : Indirect Count - value + * + * This is the number of bytes that the indirect access will consume. This can be + * bigger than the configured size of SRAM. + * + * Field Access Macros: + * + */ +/* The Least Significant Bit (LSB) position of the ALT_QSPI_INDRDCNT_VALUE register field. */ +#define ALT_QSPI_INDRDCNT_VALUE_LSB 0 +/* The Most Significant Bit (MSB) position of the ALT_QSPI_INDRDCNT_VALUE register field. */ +#define ALT_QSPI_INDRDCNT_VALUE_MSB 31 +/* The width in bits of the ALT_QSPI_INDRDCNT_VALUE register field. */ +#define ALT_QSPI_INDRDCNT_VALUE_WIDTH 32 +/* The mask used to set the ALT_QSPI_INDRDCNT_VALUE register field value. */ +#define ALT_QSPI_INDRDCNT_VALUE_SET_MSK 0xffffffff +/* The mask used to clear the ALT_QSPI_INDRDCNT_VALUE register field value. */ +#define ALT_QSPI_INDRDCNT_VALUE_CLR_MSK 0x00000000 +/* The reset value of the ALT_QSPI_INDRDCNT_VALUE register field. */ +#define ALT_QSPI_INDRDCNT_VALUE_RESET 0x0 +/* Extracts the ALT_QSPI_INDRDCNT_VALUE field value from a register. */ +#define ALT_QSPI_INDRDCNT_VALUE_GET(value) (((value) & 0xffffffff) >> 0) +/* Produces a ALT_QSPI_INDRDCNT_VALUE register field value suitable for setting the register. */ +#define ALT_QSPI_INDRDCNT_VALUE_SET(value) (((value) << 0) & 0xffffffff) + +#ifndef __ASSEMBLY__ +/* + * WARNING: The C register and register group struct declarations are provided for + * convenience and illustrative purposes. They should, however, be used with + * caution as the C language standard provides no guarantees about the alignment or + * atomicity of device memory accesses. The recommended practice for writing + * hardware drivers is to use the SoCAL access macros and alt_read_word() and + * alt_write_word() functions. + * + * The struct declaration for register ALT_QSPI_INDRDCNT. + */ +struct ALT_QSPI_INDRDCNT_s +{ + uint32_t value : 32; /* Indirect Count */ +}; + +/* The typedef declaration for register ALT_QSPI_INDRDCNT. */ +typedef volatile struct ALT_QSPI_INDRDCNT_s ALT_QSPI_INDRDCNT_t; +#endif /* __ASSEMBLY__ */ + +/* The byte offset of the ALT_QSPI_INDRDCNT register from the beginning of the component. */ +#define ALT_QSPI_INDRDCNT_OFST 0x6c + +/* + * Register : Indirect Write Transfer Register - indwr + * + * Register Layout + * + * Bits | Access | Reset | Description + * :-------|:-------|:--------|:--------------------------------- + * [0] | RW | 0x0 | Start Indirect Write + * [1] | RW | 0x0 | Cancel Indirect Write + * [2] | R | Unknown | Indirect Write Status + * [3] | R | 0x0 | Reserved + * [4] | R | Unknown | Queued Indirect Write Operations + * [5] | RW | Unknown | Indirect Completion Status + * [7:6] | R | Unknown | Completed Indirect Operations + * [31:8] | ??? | 0x0 | *UNDEFINED* + * + */ +/* + * Field : Start Indirect Write - start + * + * Writing a 1 to this bit will trigger an indirect write operation. The assumption + * is that the indirect start address and the indirect number of bytes register is + * setup before triggering the indirect write operation. + * + * Field Enumeration Values: + * + * Enum | Value | Description + * :----------------------------|:------|:--------------------------------- + * ALT_QSPI_INDWR_START_E_END | 0x1 | Trigger indirect write operation + * ALT_QSPI_INDWR_START_E_DISD | 0x0 | No Action + * + * Field Access Macros: + * + */ +/* + * Enumerated value for register field ALT_QSPI_INDWR_START + * + * Trigger indirect write operation + */ +#define ALT_QSPI_INDWR_START_E_END 0x1 +/* + * Enumerated value for register field ALT_QSPI_INDWR_START + * + * No Action + */ +#define ALT_QSPI_INDWR_START_E_DISD 0x0 + +/* The Least Significant Bit (LSB) position of the ALT_QSPI_INDWR_START register field. */ +#define ALT_QSPI_INDWR_START_LSB 0 +/* The Most Significant Bit (MSB) position of the ALT_QSPI_INDWR_START register field. */ +#define ALT_QSPI_INDWR_START_MSB 0 +/* The width in bits of the ALT_QSPI_INDWR_START register field. */ +#define ALT_QSPI_INDWR_START_WIDTH 1 +/* The mask used to set the ALT_QSPI_INDWR_START register field value. */ +#define ALT_QSPI_INDWR_START_SET_MSK 0x00000001 +/* The mask used to clear the ALT_QSPI_INDWR_START register field value. */ +#define ALT_QSPI_INDWR_START_CLR_MSK 0xfffffffe +/* The reset value of the ALT_QSPI_INDWR_START register field. */ +#define ALT_QSPI_INDWR_START_RESET 0x0 +/* Extracts the ALT_QSPI_INDWR_START field value from a register. */ +#define ALT_QSPI_INDWR_START_GET(value) (((value) & 0x00000001) >> 0) +/* Produces a ALT_QSPI_INDWR_START register field value suitable for setting the register. */ +#define ALT_QSPI_INDWR_START_SET(value) (((value) << 0) & 0x00000001) + +/* + * Field : Cancel Indirect Write - cancel + * + * Writing a 1 to this bit will cancel all ongoing indirect write operations. + * + * Field Enumeration Values: + * + * Enum | Value | Description + * :-----------------------------------|:------|:-------------------------------- + * ALT_QSPI_INDWR_CANCEL_E_CANCEINDWR | 0x1 | Cancel Indirect write operation + * ALT_QSPI_INDWR_CANCEL_E_NOACTION | 0x0 | No Action + * + * Field Access Macros: + * + */ +/* + * Enumerated value for register field ALT_QSPI_INDWR_CANCEL + * + * Cancel Indirect write operation + */ +#define ALT_QSPI_INDWR_CANCEL_E_CANCEINDWR 0x1 +/* + * Enumerated value for register field ALT_QSPI_INDWR_CANCEL + * + * No Action + */ +#define ALT_QSPI_INDWR_CANCEL_E_NOACTION 0x0 + +/* The Least Significant Bit (LSB) position of the ALT_QSPI_INDWR_CANCEL register field. */ +#define ALT_QSPI_INDWR_CANCEL_LSB 1 +/* The Most Significant Bit (MSB) position of the ALT_QSPI_INDWR_CANCEL register field. */ +#define ALT_QSPI_INDWR_CANCEL_MSB 1 +/* The width in bits of the ALT_QSPI_INDWR_CANCEL register field. */ +#define ALT_QSPI_INDWR_CANCEL_WIDTH 1 +/* The mask used to set the ALT_QSPI_INDWR_CANCEL register field value. */ +#define ALT_QSPI_INDWR_CANCEL_SET_MSK 0x00000002 +/* The mask used to clear the ALT_QSPI_INDWR_CANCEL register field value. */ +#define ALT_QSPI_INDWR_CANCEL_CLR_MSK 0xfffffffd +/* The reset value of the ALT_QSPI_INDWR_CANCEL register field. */ +#define ALT_QSPI_INDWR_CANCEL_RESET 0x0 +/* Extracts the ALT_QSPI_INDWR_CANCEL field value from a register. */ +#define ALT_QSPI_INDWR_CANCEL_GET(value) (((value) & 0x00000002) >> 1) +/* Produces a ALT_QSPI_INDWR_CANCEL register field value suitable for setting the register. */ +#define ALT_QSPI_INDWR_CANCEL_SET(value) (((value) << 1) & 0x00000002) + +/* + * Field : Indirect Write Status - rdstat + * + * Indirect write operation in progress (status) + * + * Field Enumeration Values: + * + * Enum | Value | Description + * :----------------------------------|:------|:------------------------- + * ALT_QSPI_INDWR_RDSTAT_E_INDWRSTAT | 0x1 | Indirect write operation + * ALT_QSPI_INDWR_RDSTAT_E_NOACTION | 0x0 | No Action + * + * Field Access Macros: + * + */ +/* + * Enumerated value for register field ALT_QSPI_INDWR_RDSTAT + * + * Indirect write operation + */ +#define ALT_QSPI_INDWR_RDSTAT_E_INDWRSTAT 0x1 +/* + * Enumerated value for register field ALT_QSPI_INDWR_RDSTAT + * + * No Action + */ +#define ALT_QSPI_INDWR_RDSTAT_E_NOACTION 0x0 + +/* The Least Significant Bit (LSB) position of the ALT_QSPI_INDWR_RDSTAT register field. */ +#define ALT_QSPI_INDWR_RDSTAT_LSB 2 +/* The Most Significant Bit (MSB) position of the ALT_QSPI_INDWR_RDSTAT register field. */ +#define ALT_QSPI_INDWR_RDSTAT_MSB 2 +/* The width in bits of the ALT_QSPI_INDWR_RDSTAT register field. */ +#define ALT_QSPI_INDWR_RDSTAT_WIDTH 1 +/* The mask used to set the ALT_QSPI_INDWR_RDSTAT register field value. */ +#define ALT_QSPI_INDWR_RDSTAT_SET_MSK 0x00000004 +/* The mask used to clear the ALT_QSPI_INDWR_RDSTAT register field value. */ +#define ALT_QSPI_INDWR_RDSTAT_CLR_MSK 0xfffffffb +/* The reset value of the ALT_QSPI_INDWR_RDSTAT register field is UNKNOWN. */ +#define ALT_QSPI_INDWR_RDSTAT_RESET 0x0 +/* Extracts the ALT_QSPI_INDWR_RDSTAT field value from a register. */ +#define ALT_QSPI_INDWR_RDSTAT_GET(value) (((value) & 0x00000004) >> 2) +/* Produces a ALT_QSPI_INDWR_RDSTAT register field value suitable for setting the register. */ +#define ALT_QSPI_INDWR_RDSTAT_SET(value) (((value) << 2) & 0x00000004) + +/* + * Field : Reserved - sramfull + * + * Field Access Macros: + * + */ +/* The Least Significant Bit (LSB) position of the ALT_QSPI_INDWR_SRAMFULL register field. */ +#define ALT_QSPI_INDWR_SRAMFULL_LSB 3 +/* The Most Significant Bit (MSB) position of the ALT_QSPI_INDWR_SRAMFULL register field. */ +#define ALT_QSPI_INDWR_SRAMFULL_MSB 3 +/* The width in bits of the ALT_QSPI_INDWR_SRAMFULL register field. */ +#define ALT_QSPI_INDWR_SRAMFULL_WIDTH 1 +/* The mask used to set the ALT_QSPI_INDWR_SRAMFULL register field value. */ +#define ALT_QSPI_INDWR_SRAMFULL_SET_MSK 0x00000008 +/* The mask used to clear the ALT_QSPI_INDWR_SRAMFULL register field value. */ +#define ALT_QSPI_INDWR_SRAMFULL_CLR_MSK 0xfffffff7 +/* The reset value of the ALT_QSPI_INDWR_SRAMFULL register field. */ +#define ALT_QSPI_INDWR_SRAMFULL_RESET 0x0 +/* Extracts the ALT_QSPI_INDWR_SRAMFULL field value from a register. */ +#define ALT_QSPI_INDWR_SRAMFULL_GET(value) (((value) & 0x00000008) >> 3) +/* Produces a ALT_QSPI_INDWR_SRAMFULL register field value suitable for setting the register. */ +#define ALT_QSPI_INDWR_SRAMFULL_SET(value) (((value) << 3) & 0x00000008) + +/* + * Field : Queued Indirect Write Operations - rdqueued + * + * Two indirect write operations have been queued + * + * Field Enumeration Values: + * + * Enum | Value | Description + * :-----------------------------------|:------|:----------------------------- + * ALT_QSPI_INDWR_RDQUEUED_E_INDWROP | 0x1 | Two Indirect write operation + * ALT_QSPI_INDWR_RDQUEUED_E_NOACTION | 0x0 | No Action + * + * Field Access Macros: + * + */ +/* + * Enumerated value for register field ALT_QSPI_INDWR_RDQUEUED + * + * Two Indirect write operation + */ +#define ALT_QSPI_INDWR_RDQUEUED_E_INDWROP 0x1 +/* + * Enumerated value for register field ALT_QSPI_INDWR_RDQUEUED + * + * No Action + */ +#define ALT_QSPI_INDWR_RDQUEUED_E_NOACTION 0x0 + +/* The Least Significant Bit (LSB) position of the ALT_QSPI_INDWR_RDQUEUED register field. */ +#define ALT_QSPI_INDWR_RDQUEUED_LSB 4 +/* The Most Significant Bit (MSB) position of the ALT_QSPI_INDWR_RDQUEUED register field. */ +#define ALT_QSPI_INDWR_RDQUEUED_MSB 4 +/* The width in bits of the ALT_QSPI_INDWR_RDQUEUED register field. */ +#define ALT_QSPI_INDWR_RDQUEUED_WIDTH 1 +/* The mask used to set the ALT_QSPI_INDWR_RDQUEUED register field value. */ +#define ALT_QSPI_INDWR_RDQUEUED_SET_MSK 0x00000010 +/* The mask used to clear the ALT_QSPI_INDWR_RDQUEUED register field value. */ +#define ALT_QSPI_INDWR_RDQUEUED_CLR_MSK 0xffffffef +/* The reset value of the ALT_QSPI_INDWR_RDQUEUED register field is UNKNOWN. */ +#define ALT_QSPI_INDWR_RDQUEUED_RESET 0x0 +/* Extracts the ALT_QSPI_INDWR_RDQUEUED field value from a register. */ +#define ALT_QSPI_INDWR_RDQUEUED_GET(value) (((value) & 0x00000010) >> 4) +/* Produces a ALT_QSPI_INDWR_RDQUEUED register field value suitable for setting the register. */ +#define ALT_QSPI_INDWR_RDQUEUED_SET(value) (((value) << 4) & 0x00000010) + +/* + * Field : Indirect Completion Status - inddone + * + * This field is set to 1 when an indirect operation has completed. Write a 1 to + * this field to clear it. + * + * Field Enumeration Values: + * + * Enum | Value | Description + * :-----------------------------------|:------|:----------------------------- + * ALT_QSPI_INDWR_INDDONE_E_INDCOMPST | 0x1 | Indirect operation completed + * ALT_QSPI_INDWR_INDDONE_E_NOACTION | 0x0 | No Action + * + * Field Access Macros: + * + */ +/* + * Enumerated value for register field ALT_QSPI_INDWR_INDDONE + * + * Indirect operation completed + */ +#define ALT_QSPI_INDWR_INDDONE_E_INDCOMPST 0x1 +/* + * Enumerated value for register field ALT_QSPI_INDWR_INDDONE + * + * No Action + */ +#define ALT_QSPI_INDWR_INDDONE_E_NOACTION 0x0 + +/* The Least Significant Bit (LSB) position of the ALT_QSPI_INDWR_INDDONE register field. */ +#define ALT_QSPI_INDWR_INDDONE_LSB 5 +/* The Most Significant Bit (MSB) position of the ALT_QSPI_INDWR_INDDONE register field. */ +#define ALT_QSPI_INDWR_INDDONE_MSB 5 +/* The width in bits of the ALT_QSPI_INDWR_INDDONE register field. */ +#define ALT_QSPI_INDWR_INDDONE_WIDTH 1 +/* The mask used to set the ALT_QSPI_INDWR_INDDONE register field value. */ +#define ALT_QSPI_INDWR_INDDONE_SET_MSK 0x00000020 +/* The mask used to clear the ALT_QSPI_INDWR_INDDONE register field value. */ +#define ALT_QSPI_INDWR_INDDONE_CLR_MSK 0xffffffdf +/* The reset value of the ALT_QSPI_INDWR_INDDONE register field is UNKNOWN. */ +#define ALT_QSPI_INDWR_INDDONE_RESET 0x0 +/* Extracts the ALT_QSPI_INDWR_INDDONE field value from a register. */ +#define ALT_QSPI_INDWR_INDDONE_GET(value) (((value) & 0x00000020) >> 5) +/* Produces a ALT_QSPI_INDWR_INDDONE register field value suitable for setting the register. */ +#define ALT_QSPI_INDWR_INDDONE_SET(value) (((value) << 5) & 0x00000020) + +/* + * Field : Completed Indirect Operations - indcnt + * + * This field contains the count of indirect operations which have been completed. + * This is used in conjunction with the indirect completion status field (bit 5). + * + * Field Access Macros: + * + */ +/* The Least Significant Bit (LSB) position of the ALT_QSPI_INDWR_INDCNT register field. */ +#define ALT_QSPI_INDWR_INDCNT_LSB 6 +/* The Most Significant Bit (MSB) position of the ALT_QSPI_INDWR_INDCNT register field. */ +#define ALT_QSPI_INDWR_INDCNT_MSB 7 +/* The width in bits of the ALT_QSPI_INDWR_INDCNT register field. */ +#define ALT_QSPI_INDWR_INDCNT_WIDTH 2 +/* The mask used to set the ALT_QSPI_INDWR_INDCNT register field value. */ +#define ALT_QSPI_INDWR_INDCNT_SET_MSK 0x000000c0 +/* The mask used to clear the ALT_QSPI_INDWR_INDCNT register field value. */ +#define ALT_QSPI_INDWR_INDCNT_CLR_MSK 0xffffff3f +/* The reset value of the ALT_QSPI_INDWR_INDCNT register field is UNKNOWN. */ +#define ALT_QSPI_INDWR_INDCNT_RESET 0x0 +/* Extracts the ALT_QSPI_INDWR_INDCNT field value from a register. */ +#define ALT_QSPI_INDWR_INDCNT_GET(value) (((value) & 0x000000c0) >> 6) +/* Produces a ALT_QSPI_INDWR_INDCNT register field value suitable for setting the register. */ +#define ALT_QSPI_INDWR_INDCNT_SET(value) (((value) << 6) & 0x000000c0) + +#ifndef __ASSEMBLY__ +/* + * WARNING: The C register and register group struct declarations are provided for + * convenience and illustrative purposes. They should, however, be used with + * caution as the C language standard provides no guarantees about the alignment or + * atomicity of device memory accesses. The recommended practice for writing + * hardware drivers is to use the SoCAL access macros and alt_read_word() and + * alt_write_word() functions. + * + * The struct declaration for register ALT_QSPI_INDWR. + */ +struct ALT_QSPI_INDWR_s +{ + uint32_t start : 1; /* Start Indirect Write */ + uint32_t cancel : 1; /* Cancel Indirect Write */ + const uint32_t rdstat : 1; /* Indirect Write Status */ + const uint32_t sramfull : 1; /* Reserved */ + const uint32_t rdqueued : 1; /* Queued Indirect Write Operations */ + uint32_t inddone : 1; /* Indirect Completion Status */ + const uint32_t indcnt : 2; /* Completed Indirect Operations */ + uint32_t : 24; /* *UNDEFINED* */ +}; + +/* The typedef declaration for register ALT_QSPI_INDWR. */ +typedef volatile struct ALT_QSPI_INDWR_s ALT_QSPI_INDWR_t; +#endif /* __ASSEMBLY__ */ + +/* The byte offset of the ALT_QSPI_INDWR register from the beginning of the component. */ +#define ALT_QSPI_INDWR_OFST 0x70 + +/* + * Register : Indirect Write Transfer Watermark Register - indwrwater + * + * Register Layout + * + * Bits | Access | Reset | Description + * :-------|:-------|:-----------|:---------------- + * [31:0] | RW | 0xffffffff | Watermark Value + * + */ +/* + * Field : Watermark Value - level + * + * This represents the maximum fill level of the SRAM before a DMA peripheral + * access is permitted. When the SRAM fill level falls below the watermark, an + * interrupt is also generated. This field can be disabled by writing a value of + * all ones. The units of this register are bytes. + * + * Field Access Macros: + * + */ +/* The Least Significant Bit (LSB) position of the ALT_QSPI_INDWRWATER_LEVEL register field. */ +#define ALT_QSPI_INDWRWATER_LEVEL_LSB 0 +/* The Most Significant Bit (MSB) position of the ALT_QSPI_INDWRWATER_LEVEL register field. */ +#define ALT_QSPI_INDWRWATER_LEVEL_MSB 31 +/* The width in bits of the ALT_QSPI_INDWRWATER_LEVEL register field. */ +#define ALT_QSPI_INDWRWATER_LEVEL_WIDTH 32 +/* The mask used to set the ALT_QSPI_INDWRWATER_LEVEL register field value. */ +#define ALT_QSPI_INDWRWATER_LEVEL_SET_MSK 0xffffffff +/* The mask used to clear the ALT_QSPI_INDWRWATER_LEVEL register field value. */ +#define ALT_QSPI_INDWRWATER_LEVEL_CLR_MSK 0x00000000 +/* The reset value of the ALT_QSPI_INDWRWATER_LEVEL register field. */ +#define ALT_QSPI_INDWRWATER_LEVEL_RESET 0xffffffff +/* Extracts the ALT_QSPI_INDWRWATER_LEVEL field value from a register. */ +#define ALT_QSPI_INDWRWATER_LEVEL_GET(value) (((value) & 0xffffffff) >> 0) +/* Produces a ALT_QSPI_INDWRWATER_LEVEL register field value suitable for setting the register. */ +#define ALT_QSPI_INDWRWATER_LEVEL_SET(value) (((value) << 0) & 0xffffffff) + +#ifndef __ASSEMBLY__ +/* + * WARNING: The C register and register group struct declarations are provided for + * convenience and illustrative purposes. They should, however, be used with + * caution as the C language standard provides no guarantees about the alignment or + * atomicity of device memory accesses. The recommended practice for writing + * hardware drivers is to use the SoCAL access macros and alt_read_word() and + * alt_write_word() functions. + * + * The struct declaration for register ALT_QSPI_INDWRWATER. + */ +struct ALT_QSPI_INDWRWATER_s +{ + uint32_t level : 32; /* Watermark Value */ +}; + +/* The typedef declaration for register ALT_QSPI_INDWRWATER. */ +typedef volatile struct ALT_QSPI_INDWRWATER_s ALT_QSPI_INDWRWATER_t; +#endif /* __ASSEMBLY__ */ + +/* The byte offset of the ALT_QSPI_INDWRWATER register from the beginning of the component. */ +#define ALT_QSPI_INDWRWATER_OFST 0x74 + +/* + * Register : Indirect Write Transfer Start Address Register - indwrstaddr + * + * Register Layout + * + * Bits | Access | Reset | Description + * :-------|:-------|:------|:------------------------- + * [31:0] | RW | 0x0 | Start of Indirect Access + * + */ +/* + * Field : Start of Indirect Access - addr + * + * This is the start address from which the indirect access will commence its write + * operation. + * + * Field Access Macros: + * + */ +/* The Least Significant Bit (LSB) position of the ALT_QSPI_INDWRSTADDR_ADDR register field. */ +#define ALT_QSPI_INDWRSTADDR_ADDR_LSB 0 +/* The Most Significant Bit (MSB) position of the ALT_QSPI_INDWRSTADDR_ADDR register field. */ +#define ALT_QSPI_INDWRSTADDR_ADDR_MSB 31 +/* The width in bits of the ALT_QSPI_INDWRSTADDR_ADDR register field. */ +#define ALT_QSPI_INDWRSTADDR_ADDR_WIDTH 32 +/* The mask used to set the ALT_QSPI_INDWRSTADDR_ADDR register field value. */ +#define ALT_QSPI_INDWRSTADDR_ADDR_SET_MSK 0xffffffff +/* The mask used to clear the ALT_QSPI_INDWRSTADDR_ADDR register field value. */ +#define ALT_QSPI_INDWRSTADDR_ADDR_CLR_MSK 0x00000000 +/* The reset value of the ALT_QSPI_INDWRSTADDR_ADDR register field. */ +#define ALT_QSPI_INDWRSTADDR_ADDR_RESET 0x0 +/* Extracts the ALT_QSPI_INDWRSTADDR_ADDR field value from a register. */ +#define ALT_QSPI_INDWRSTADDR_ADDR_GET(value) (((value) & 0xffffffff) >> 0) +/* Produces a ALT_QSPI_INDWRSTADDR_ADDR register field value suitable for setting the register. */ +#define ALT_QSPI_INDWRSTADDR_ADDR_SET(value) (((value) << 0) & 0xffffffff) + +#ifndef __ASSEMBLY__ +/* + * WARNING: The C register and register group struct declarations are provided for + * convenience and illustrative purposes. They should, however, be used with + * caution as the C language standard provides no guarantees about the alignment or + * atomicity of device memory accesses. The recommended practice for writing + * hardware drivers is to use the SoCAL access macros and alt_read_word() and + * alt_write_word() functions. + * + * The struct declaration for register ALT_QSPI_INDWRSTADDR. + */ +struct ALT_QSPI_INDWRSTADDR_s +{ + uint32_t addr : 32; /* Start of Indirect Access */ +}; + +/* The typedef declaration for register ALT_QSPI_INDWRSTADDR. */ +typedef volatile struct ALT_QSPI_INDWRSTADDR_s ALT_QSPI_INDWRSTADDR_t; +#endif /* __ASSEMBLY__ */ + +/* The byte offset of the ALT_QSPI_INDWRSTADDR register from the beginning of the component. */ +#define ALT_QSPI_INDWRSTADDR_OFST 0x78 + +/* + * Register : Indirect Write Transfer Count Register - indwrcnt + * + * Register Layout + * + * Bits | Access | Reset | Description + * :-------|:-------|:------|:------------------------- + * [31:0] | RW | 0x0 | Indirect Number of Bytes + * + */ +/* + * Field : Indirect Number of Bytes - value + * + * This is the number of bytes that the indirect access will consume. This can be + * bigger than the configured size of SRAM. + * + * Field Access Macros: + * + */ +/* The Least Significant Bit (LSB) position of the ALT_QSPI_INDWRCNT_VALUE register field. */ +#define ALT_QSPI_INDWRCNT_VALUE_LSB 0 +/* The Most Significant Bit (MSB) position of the ALT_QSPI_INDWRCNT_VALUE register field. */ +#define ALT_QSPI_INDWRCNT_VALUE_MSB 31 +/* The width in bits of the ALT_QSPI_INDWRCNT_VALUE register field. */ +#define ALT_QSPI_INDWRCNT_VALUE_WIDTH 32 +/* The mask used to set the ALT_QSPI_INDWRCNT_VALUE register field value. */ +#define ALT_QSPI_INDWRCNT_VALUE_SET_MSK 0xffffffff +/* The mask used to clear the ALT_QSPI_INDWRCNT_VALUE register field value. */ +#define ALT_QSPI_INDWRCNT_VALUE_CLR_MSK 0x00000000 +/* The reset value of the ALT_QSPI_INDWRCNT_VALUE register field. */ +#define ALT_QSPI_INDWRCNT_VALUE_RESET 0x0 +/* Extracts the ALT_QSPI_INDWRCNT_VALUE field value from a register. */ +#define ALT_QSPI_INDWRCNT_VALUE_GET(value) (((value) & 0xffffffff) >> 0) +/* Produces a ALT_QSPI_INDWRCNT_VALUE register field value suitable for setting the register. */ +#define ALT_QSPI_INDWRCNT_VALUE_SET(value) (((value) << 0) & 0xffffffff) + +#ifndef __ASSEMBLY__ +/* + * WARNING: The C register and register group struct declarations are provided for + * convenience and illustrative purposes. They should, however, be used with + * caution as the C language standard provides no guarantees about the alignment or + * atomicity of device memory accesses. The recommended practice for writing + * hardware drivers is to use the SoCAL access macros and alt_read_word() and + * alt_write_word() functions. + * + * The struct declaration for register ALT_QSPI_INDWRCNT. + */ +struct ALT_QSPI_INDWRCNT_s +{ + uint32_t value : 32; /* Indirect Number of Bytes */ +}; + +/* The typedef declaration for register ALT_QSPI_INDWRCNT. */ +typedef volatile struct ALT_QSPI_INDWRCNT_s ALT_QSPI_INDWRCNT_t; +#endif /* __ASSEMBLY__ */ + +/* The byte offset of the ALT_QSPI_INDWRCNT register from the beginning of the component. */ +#define ALT_QSPI_INDWRCNT_OFST 0x7c + +/* + * Register : Flash Command Register - flashcmd + * + * Register Layout + * + * Bits | Access | Reset | Description + * :--------|:-------|:------|:--------------------------- + * [0] | RW | 0x0 | Execute Command + * [1] | R | 0x0 | Command Execution Status + * [6:2] | ??? | 0x0 | *UNDEFINED* + * [11:7] | RW | 0x0 | Number of Dummy Bytes + * [14:12] | RW | 0x0 | Number of Write Data Bytes + * [15] | RW | 0x0 | Write Data Enable + * [17:16] | RW | 0x0 | Number of Address Bytes + * [18] | RW | 0x0 | Mode Bit Enable + * [19] | RW | 0x0 | Command Address Enable + * [22:20] | RW | 0x0 | Number of Read Data Bytes + * [23] | RW | 0x0 | Read Data Enable + * [31:24] | RW | 0x0 | Command Opcode + * + */ +/* + * Field : Execute Command - execcmd + * + * Execute the command. + * + * Field Enumeration Values: + * + * Enum | Value | Description + * :------------------------------------|:------|:---------------- + * ALT_QSPI_FLSHCMD_EXECCMD_E_EXECUTE | 0x1 | Execute Command + * ALT_QSPI_FLSHCMD_EXECCMD_E_NOACTION | 0x0 | No Action + * + * Field Access Macros: + * + */ +/* + * Enumerated value for register field ALT_QSPI_FLSHCMD_EXECCMD + * + * Execute Command + */ +#define ALT_QSPI_FLSHCMD_EXECCMD_E_EXECUTE 0x1 +/* + * Enumerated value for register field ALT_QSPI_FLSHCMD_EXECCMD + * + * No Action + */ +#define ALT_QSPI_FLSHCMD_EXECCMD_E_NOACTION 0x0 + +/* The Least Significant Bit (LSB) position of the ALT_QSPI_FLSHCMD_EXECCMD register field. */ +#define ALT_QSPI_FLSHCMD_EXECCMD_LSB 0 +/* The Most Significant Bit (MSB) position of the ALT_QSPI_FLSHCMD_EXECCMD register field. */ +#define ALT_QSPI_FLSHCMD_EXECCMD_MSB 0 +/* The width in bits of the ALT_QSPI_FLSHCMD_EXECCMD register field. */ +#define ALT_QSPI_FLSHCMD_EXECCMD_WIDTH 1 +/* The mask used to set the ALT_QSPI_FLSHCMD_EXECCMD register field value. */ +#define ALT_QSPI_FLSHCMD_EXECCMD_SET_MSK 0x00000001 +/* The mask used to clear the ALT_QSPI_FLSHCMD_EXECCMD register field value. */ +#define ALT_QSPI_FLSHCMD_EXECCMD_CLR_MSK 0xfffffffe +/* The reset value of the ALT_QSPI_FLSHCMD_EXECCMD register field. */ +#define ALT_QSPI_FLSHCMD_EXECCMD_RESET 0x0 +/* Extracts the ALT_QSPI_FLSHCMD_EXECCMD field value from a register. */ +#define ALT_QSPI_FLSHCMD_EXECCMD_GET(value) (((value) & 0x00000001) >> 0) +/* Produces a ALT_QSPI_FLSHCMD_EXECCMD register field value suitable for setting the register. */ +#define ALT_QSPI_FLSHCMD_EXECCMD_SET(value) (((value) << 0) & 0x00000001) + +/* + * Field : Command Execution Status - cmdexecstat + * + * Command execution in progress. + * + * Field Enumeration Values: + * + * Enum | Value | Description + * :-------------------------------------------|:------|:------------------------- + * ALT_QSPI_FLSHCMD_CMDEXECSTAT_E_EXECUTESTAT | 0x1 | Command Execution Status + * ALT_QSPI_FLSHCMD_CMDEXECSTAT_E_NOACTION | 0x0 | No Action + * + * Field Access Macros: + * + */ +/* + * Enumerated value for register field ALT_QSPI_FLSHCMD_CMDEXECSTAT + * + * Command Execution Status + */ +#define ALT_QSPI_FLSHCMD_CMDEXECSTAT_E_EXECUTESTAT 0x1 +/* + * Enumerated value for register field ALT_QSPI_FLSHCMD_CMDEXECSTAT + * + * No Action + */ +#define ALT_QSPI_FLSHCMD_CMDEXECSTAT_E_NOACTION 0x0 + +/* The Least Significant Bit (LSB) position of the ALT_QSPI_FLSHCMD_CMDEXECSTAT register field. */ +#define ALT_QSPI_FLSHCMD_CMDEXECSTAT_LSB 1 +/* The Most Significant Bit (MSB) position of the ALT_QSPI_FLSHCMD_CMDEXECSTAT register field. */ +#define ALT_QSPI_FLSHCMD_CMDEXECSTAT_MSB 1 +/* The width in bits of the ALT_QSPI_FLSHCMD_CMDEXECSTAT register field. */ +#define ALT_QSPI_FLSHCMD_CMDEXECSTAT_WIDTH 1 +/* The mask used to set the ALT_QSPI_FLSHCMD_CMDEXECSTAT register field value. */ +#define ALT_QSPI_FLSHCMD_CMDEXECSTAT_SET_MSK 0x00000002 +/* The mask used to clear the ALT_QSPI_FLSHCMD_CMDEXECSTAT register field value. */ +#define ALT_QSPI_FLSHCMD_CMDEXECSTAT_CLR_MSK 0xfffffffd +/* The reset value of the ALT_QSPI_FLSHCMD_CMDEXECSTAT register field. */ +#define ALT_QSPI_FLSHCMD_CMDEXECSTAT_RESET 0x0 +/* Extracts the ALT_QSPI_FLSHCMD_CMDEXECSTAT field value from a register. */ +#define ALT_QSPI_FLSHCMD_CMDEXECSTAT_GET(value) (((value) & 0x00000002) >> 1) +/* Produces a ALT_QSPI_FLSHCMD_CMDEXECSTAT register field value suitable for setting the register. */ +#define ALT_QSPI_FLSHCMD_CMDEXECSTAT_SET(value) (((value) << 1) & 0x00000002) + +/* + * Field : Number of Dummy Bytes - numdummybytes + * + * Set to the number of dummy bytes required This should be setup before triggering + * the command via the execute field of this register. + * + * Field Access Macros: + * + */ +/* The Least Significant Bit (LSB) position of the ALT_QSPI_FLSHCMD_NUMDUMMYBYTES register field. */ +#define ALT_QSPI_FLSHCMD_NUMDUMMYBYTES_LSB 7 +/* The Most Significant Bit (MSB) position of the ALT_QSPI_FLSHCMD_NUMDUMMYBYTES register field. */ +#define ALT_QSPI_FLSHCMD_NUMDUMMYBYTES_MSB 11 +/* The width in bits of the ALT_QSPI_FLSHCMD_NUMDUMMYBYTES register field. */ +#define ALT_QSPI_FLSHCMD_NUMDUMMYBYTES_WIDTH 5 +/* The mask used to set the ALT_QSPI_FLSHCMD_NUMDUMMYBYTES register field value. */ +#define ALT_QSPI_FLSHCMD_NUMDUMMYBYTES_SET_MSK 0x00000f80 +/* The mask used to clear the ALT_QSPI_FLSHCMD_NUMDUMMYBYTES register field value. */ +#define ALT_QSPI_FLSHCMD_NUMDUMMYBYTES_CLR_MSK 0xfffff07f +/* The reset value of the ALT_QSPI_FLSHCMD_NUMDUMMYBYTES register field. */ +#define ALT_QSPI_FLSHCMD_NUMDUMMYBYTES_RESET 0x0 +/* Extracts the ALT_QSPI_FLSHCMD_NUMDUMMYBYTES field value from a register. */ +#define ALT_QSPI_FLSHCMD_NUMDUMMYBYTES_GET(value) (((value) & 0x00000f80) >> 7) +/* Produces a ALT_QSPI_FLSHCMD_NUMDUMMYBYTES register field value suitable for setting the register. */ +#define ALT_QSPI_FLSHCMD_NUMDUMMYBYTES_SET(value) (((value) << 7) & 0x00000f80) + +/* + * Field : Number of Write Data Bytes - numwrdatabytes + * + * Up to 8 Data bytes may be written using this command. + * + * Field Enumeration Values: + * + * Enum | Value | Description + * :------------------------------------------|:------|:------------- + * ALT_QSPI_FLSHCMD_NUMWRDATABYTES_E_WRBYTE1 | 0x0 | Write 1 Byte + * ALT_QSPI_FLSHCMD_NUMWRDATABYTES_E_WRBYTE2 | 0x1 | Write 2 Byte + * ALT_QSPI_FLSHCMD_NUMWRDATABYTES_E_WRBYTE3 | 0x2 | Write 3 Byte + * ALT_QSPI_FLSHCMD_NUMWRDATABYTES_E_WRBYTE4 | 0x3 | Write 4 Byte + * ALT_QSPI_FLSHCMD_NUMWRDATABYTES_E_WRBYTE5 | 0x4 | Write 5 Byte + * ALT_QSPI_FLSHCMD_NUMWRDATABYTES_E_WRBYTE6 | 0x5 | Write 6 Byte + * ALT_QSPI_FLSHCMD_NUMWRDATABYTES_E_WRBYTE7 | 0x6 | Write 7 Byte + * ALT_QSPI_FLSHCMD_NUMWRDATABYTES_E_WRBYTE8 | 0x7 | Write 8 Byte + * + * Field Access Macros: + * + */ +/* + * Enumerated value for register field ALT_QSPI_FLSHCMD_NUMWRDATABYTES + * + * Write 1 Byte + */ +#define ALT_QSPI_FLSHCMD_NUMWRDATABYTES_E_WRBYTE1 0x0 +/* + * Enumerated value for register field ALT_QSPI_FLSHCMD_NUMWRDATABYTES + * + * Write 2 Byte + */ +#define ALT_QSPI_FLSHCMD_NUMWRDATABYTES_E_WRBYTE2 0x1 +/* + * Enumerated value for register field ALT_QSPI_FLSHCMD_NUMWRDATABYTES + * + * Write 3 Byte + */ +#define ALT_QSPI_FLSHCMD_NUMWRDATABYTES_E_WRBYTE3 0x2 +/* + * Enumerated value for register field ALT_QSPI_FLSHCMD_NUMWRDATABYTES + * + * Write 4 Byte + */ +#define ALT_QSPI_FLSHCMD_NUMWRDATABYTES_E_WRBYTE4 0x3 +/* + * Enumerated value for register field ALT_QSPI_FLSHCMD_NUMWRDATABYTES + * + * Write 5 Byte + */ +#define ALT_QSPI_FLSHCMD_NUMWRDATABYTES_E_WRBYTE5 0x4 +/* + * Enumerated value for register field ALT_QSPI_FLSHCMD_NUMWRDATABYTES + * + * Write 6 Byte + */ +#define ALT_QSPI_FLSHCMD_NUMWRDATABYTES_E_WRBYTE6 0x5 +/* + * Enumerated value for register field ALT_QSPI_FLSHCMD_NUMWRDATABYTES + * + * Write 7 Byte + */ +#define ALT_QSPI_FLSHCMD_NUMWRDATABYTES_E_WRBYTE7 0x6 +/* + * Enumerated value for register field ALT_QSPI_FLSHCMD_NUMWRDATABYTES + * + * Write 8 Byte + */ +#define ALT_QSPI_FLSHCMD_NUMWRDATABYTES_E_WRBYTE8 0x7 + +/* The Least Significant Bit (LSB) position of the ALT_QSPI_FLSHCMD_NUMWRDATABYTES register field. */ +#define ALT_QSPI_FLSHCMD_NUMWRDATABYTES_LSB 12 +/* The Most Significant Bit (MSB) position of the ALT_QSPI_FLSHCMD_NUMWRDATABYTES register field. */ +#define ALT_QSPI_FLSHCMD_NUMWRDATABYTES_MSB 14 +/* The width in bits of the ALT_QSPI_FLSHCMD_NUMWRDATABYTES register field. */ +#define ALT_QSPI_FLSHCMD_NUMWRDATABYTES_WIDTH 3 +/* The mask used to set the ALT_QSPI_FLSHCMD_NUMWRDATABYTES register field value. */ +#define ALT_QSPI_FLSHCMD_NUMWRDATABYTES_SET_MSK 0x00007000 +/* The mask used to clear the ALT_QSPI_FLSHCMD_NUMWRDATABYTES register field value. */ +#define ALT_QSPI_FLSHCMD_NUMWRDATABYTES_CLR_MSK 0xffff8fff +/* The reset value of the ALT_QSPI_FLSHCMD_NUMWRDATABYTES register field. */ +#define ALT_QSPI_FLSHCMD_NUMWRDATABYTES_RESET 0x0 +/* Extracts the ALT_QSPI_FLSHCMD_NUMWRDATABYTES field value from a register. */ +#define ALT_QSPI_FLSHCMD_NUMWRDATABYTES_GET(value) (((value) & 0x00007000) >> 12) +/* Produces a ALT_QSPI_FLSHCMD_NUMWRDATABYTES register field value suitable for setting the register. */ +#define ALT_QSPI_FLSHCMD_NUMWRDATABYTES_SET(value) (((value) << 12) & 0x00007000) + +/* + * Field : Write Data Enable - enwrdata + * + * Set to 1 if the command specified in the command opcode field requires write + * data bytes to be sent to the device. + * + * Field Enumeration Values: + * + * Enum | Value | Description + * :----------------------------------------|:------|:---------------------------------- + * ALT_QSPI_FLSHCMD_ENWRDATA_E_WRDATABYTES | 0x1 | Command requires write data bytes + * ALT_QSPI_FLSHCMD_ENWRDATA_E_NOACTION | 0x0 | No Action + * + * Field Access Macros: + * + */ +/* + * Enumerated value for register field ALT_QSPI_FLSHCMD_ENWRDATA + * + * Command requires write data bytes + */ +#define ALT_QSPI_FLSHCMD_ENWRDATA_E_WRDATABYTES 0x1 +/* + * Enumerated value for register field ALT_QSPI_FLSHCMD_ENWRDATA + * + * No Action + */ +#define ALT_QSPI_FLSHCMD_ENWRDATA_E_NOACTION 0x0 + +/* The Least Significant Bit (LSB) position of the ALT_QSPI_FLSHCMD_ENWRDATA register field. */ +#define ALT_QSPI_FLSHCMD_ENWRDATA_LSB 15 +/* The Most Significant Bit (MSB) position of the ALT_QSPI_FLSHCMD_ENWRDATA register field. */ +#define ALT_QSPI_FLSHCMD_ENWRDATA_MSB 15 +/* The width in bits of the ALT_QSPI_FLSHCMD_ENWRDATA register field. */ +#define ALT_QSPI_FLSHCMD_ENWRDATA_WIDTH 1 +/* The mask used to set the ALT_QSPI_FLSHCMD_ENWRDATA register field value. */ +#define ALT_QSPI_FLSHCMD_ENWRDATA_SET_MSK 0x00008000 +/* The mask used to clear the ALT_QSPI_FLSHCMD_ENWRDATA register field value. */ +#define ALT_QSPI_FLSHCMD_ENWRDATA_CLR_MSK 0xffff7fff +/* The reset value of the ALT_QSPI_FLSHCMD_ENWRDATA register field. */ +#define ALT_QSPI_FLSHCMD_ENWRDATA_RESET 0x0 +/* Extracts the ALT_QSPI_FLSHCMD_ENWRDATA field value from a register. */ +#define ALT_QSPI_FLSHCMD_ENWRDATA_GET(value) (((value) & 0x00008000) >> 15) +/* Produces a ALT_QSPI_FLSHCMD_ENWRDATA register field value suitable for setting the register. */ +#define ALT_QSPI_FLSHCMD_ENWRDATA_SET(value) (((value) << 15) & 0x00008000) + +/* + * Field : Number of Address Bytes - numaddrbytes + * + * Set to the number of address bytes required (the address itself is programmed in + * the FLASH COMMAND ADDRESS REGISTERS). This should be setup before triggering the + * command via bit 0 of this register. 2'b00 : 1 address byte 2'b01 : 2 address + * bytes 2'b10 : 3 address bytes 2'b11 : 4 address bytes + * + * Field Enumeration Values: + * + * Enum | Value | Description + * :------------------------------------------|:------|:---------------------- + * ALT_QSPI_FLSHCMD_NUMADDRBYTES_E_ADDRBYTE1 | 0x0 | Write 1 Address Byte + * ALT_QSPI_FLSHCMD_NUMADDRBYTES_E_ADDRBYTE2 | 0x1 | Write 2 Address Bytes + * ALT_QSPI_FLSHCMD_NUMADDRBYTES_E_ADDRBYTE3 | 0x2 | Write 3 Address Bytes + * ALT_QSPI_FLSHCMD_NUMADDRBYTES_E_ADDRBYTE4 | 0x3 | Write 4 Address Bytes + * + * Field Access Macros: + * + */ +/* + * Enumerated value for register field ALT_QSPI_FLSHCMD_NUMADDRBYTES + * + * Write 1 Address Byte + */ +#define ALT_QSPI_FLSHCMD_NUMADDRBYTES_E_ADDRBYTE1 0x0 +/* + * Enumerated value for register field ALT_QSPI_FLSHCMD_NUMADDRBYTES + * + * Write 2 Address Bytes + */ +#define ALT_QSPI_FLSHCMD_NUMADDRBYTES_E_ADDRBYTE2 0x1 +/* + * Enumerated value for register field ALT_QSPI_FLSHCMD_NUMADDRBYTES + * + * Write 3 Address Bytes + */ +#define ALT_QSPI_FLSHCMD_NUMADDRBYTES_E_ADDRBYTE3 0x2 +/* + * Enumerated value for register field ALT_QSPI_FLSHCMD_NUMADDRBYTES + * + * Write 4 Address Bytes + */ +#define ALT_QSPI_FLSHCMD_NUMADDRBYTES_E_ADDRBYTE4 0x3 + +/* The Least Significant Bit (LSB) position of the ALT_QSPI_FLSHCMD_NUMADDRBYTES register field. */ +#define ALT_QSPI_FLSHCMD_NUMADDRBYTES_LSB 16 +/* The Most Significant Bit (MSB) position of the ALT_QSPI_FLSHCMD_NUMADDRBYTES register field. */ +#define ALT_QSPI_FLSHCMD_NUMADDRBYTES_MSB 17 +/* The width in bits of the ALT_QSPI_FLSHCMD_NUMADDRBYTES register field. */ +#define ALT_QSPI_FLSHCMD_NUMADDRBYTES_WIDTH 2 +/* The mask used to set the ALT_QSPI_FLSHCMD_NUMADDRBYTES register field value. */ +#define ALT_QSPI_FLSHCMD_NUMADDRBYTES_SET_MSK 0x00030000 +/* The mask used to clear the ALT_QSPI_FLSHCMD_NUMADDRBYTES register field value. */ +#define ALT_QSPI_FLSHCMD_NUMADDRBYTES_CLR_MSK 0xfffcffff +/* The reset value of the ALT_QSPI_FLSHCMD_NUMADDRBYTES register field. */ +#define ALT_QSPI_FLSHCMD_NUMADDRBYTES_RESET 0x0 +/* Extracts the ALT_QSPI_FLSHCMD_NUMADDRBYTES field value from a register. */ +#define ALT_QSPI_FLSHCMD_NUMADDRBYTES_GET(value) (((value) & 0x00030000) >> 16) +/* Produces a ALT_QSPI_FLSHCMD_NUMADDRBYTES register field value suitable for setting the register. */ +#define ALT_QSPI_FLSHCMD_NUMADDRBYTES_SET(value) (((value) << 16) & 0x00030000) + +/* + * Field : Mode Bit Enable - enmodebit + * + * Set to 1 to ensure the mode bits as defined in the Mode Bit Configuration + * register are sent following the address bytes. + * + * Field Enumeration Values: + * + * Enum | Value | Description + * :---------------------------------|:------|:------------------------------- + * ALT_QSPI_FLSHCMD_ENMODBIT_E_END | 0x1 | Mode Bit follows address bytes + * ALT_QSPI_FLSHCMD_ENMODBIT_E_DISD | 0x0 | No Action + * + * Field Access Macros: + * + */ +/* + * Enumerated value for register field ALT_QSPI_FLSHCMD_ENMODBIT + * + * Mode Bit follows address bytes + */ +#define ALT_QSPI_FLSHCMD_ENMODBIT_E_END 0x1 +/* + * Enumerated value for register field ALT_QSPI_FLSHCMD_ENMODBIT + * + * No Action + */ +#define ALT_QSPI_FLSHCMD_ENMODBIT_E_DISD 0x0 + +/* The Least Significant Bit (LSB) position of the ALT_QSPI_FLSHCMD_ENMODBIT register field. */ +#define ALT_QSPI_FLSHCMD_ENMODBIT_LSB 18 +/* The Most Significant Bit (MSB) position of the ALT_QSPI_FLSHCMD_ENMODBIT register field. */ +#define ALT_QSPI_FLSHCMD_ENMODBIT_MSB 18 +/* The width in bits of the ALT_QSPI_FLSHCMD_ENMODBIT register field. */ +#define ALT_QSPI_FLSHCMD_ENMODBIT_WIDTH 1 +/* The mask used to set the ALT_QSPI_FLSHCMD_ENMODBIT register field value. */ +#define ALT_QSPI_FLSHCMD_ENMODBIT_SET_MSK 0x00040000 +/* The mask used to clear the ALT_QSPI_FLSHCMD_ENMODBIT register field value. */ +#define ALT_QSPI_FLSHCMD_ENMODBIT_CLR_MSK 0xfffbffff +/* The reset value of the ALT_QSPI_FLSHCMD_ENMODBIT register field. */ +#define ALT_QSPI_FLSHCMD_ENMODBIT_RESET 0x0 +/* Extracts the ALT_QSPI_FLSHCMD_ENMODBIT field value from a register. */ +#define ALT_QSPI_FLSHCMD_ENMODBIT_GET(value) (((value) & 0x00040000) >> 18) +/* Produces a ALT_QSPI_FLSHCMD_ENMODBIT register field value suitable for setting the register. */ +#define ALT_QSPI_FLSHCMD_ENMODBIT_SET(value) (((value) << 18) & 0x00040000) + +/* + * Field : Command Address Enable - encmdaddr + * + * If enabled, the command specified in bits 31:24 requires an address. This should + * be setup before triggering the command via writing a 1 to the execute field. + * + * Field Enumeration Values: + * + * Enum | Value | Description + * :----------------------------------|:------|:--------------------------------------- + * ALT_QSPI_FLSHCMD_ENCMDADDR_E_END | 0x1 | Command in bits 31:24 requires address + * ALT_QSPI_FLSHCMD_ENCMDADDR_E_DISD | 0x0 | No Action + * + * Field Access Macros: + * + */ +/* + * Enumerated value for register field ALT_QSPI_FLSHCMD_ENCMDADDR + * + * Command in bits 31:24 requires address + */ +#define ALT_QSPI_FLSHCMD_ENCMDADDR_E_END 0x1 +/* + * Enumerated value for register field ALT_QSPI_FLSHCMD_ENCMDADDR + * + * No Action + */ +#define ALT_QSPI_FLSHCMD_ENCMDADDR_E_DISD 0x0 + +/* The Least Significant Bit (LSB) position of the ALT_QSPI_FLSHCMD_ENCMDADDR register field. */ +#define ALT_QSPI_FLSHCMD_ENCMDADDR_LSB 19 +/* The Most Significant Bit (MSB) position of the ALT_QSPI_FLSHCMD_ENCMDADDR register field. */ +#define ALT_QSPI_FLSHCMD_ENCMDADDR_MSB 19 +/* The width in bits of the ALT_QSPI_FLSHCMD_ENCMDADDR register field. */ +#define ALT_QSPI_FLSHCMD_ENCMDADDR_WIDTH 1 +/* The mask used to set the ALT_QSPI_FLSHCMD_ENCMDADDR register field value. */ +#define ALT_QSPI_FLSHCMD_ENCMDADDR_SET_MSK 0x00080000 +/* The mask used to clear the ALT_QSPI_FLSHCMD_ENCMDADDR register field value. */ +#define ALT_QSPI_FLSHCMD_ENCMDADDR_CLR_MSK 0xfff7ffff +/* The reset value of the ALT_QSPI_FLSHCMD_ENCMDADDR register field. */ +#define ALT_QSPI_FLSHCMD_ENCMDADDR_RESET 0x0 +/* Extracts the ALT_QSPI_FLSHCMD_ENCMDADDR field value from a register. */ +#define ALT_QSPI_FLSHCMD_ENCMDADDR_GET(value) (((value) & 0x00080000) >> 19) +/* Produces a ALT_QSPI_FLSHCMD_ENCMDADDR register field value suitable for setting the register. */ +#define ALT_QSPI_FLSHCMD_ENCMDADDR_SET(value) (((value) << 19) & 0x00080000) + +/* + * Field : Number of Read Data Bytes - numrddatabytes + * + * Up to 8 data bytes may be read using this command. Set to 0 for 1 byte and 7 for + * 8 bytes. + * + * Field Enumeration Values: + * + * Enum | Value | Description + * :------------------------------------------|:------|:------------ + * ALT_QSPI_FLSHCMD_NUMRDDATABYTES_E_RDBYTE1 | 0x0 | Read 1 Byte + * ALT_QSPI_FLSHCMD_NUMRDDATABYTES_E_RDBYTE2 | 0x1 | Read 2 Byte + * ALT_QSPI_FLSHCMD_NUMRDDATABYTES_E_RDBYTE3 | 0x2 | Read 3 Byte + * ALT_QSPI_FLSHCMD_NUMRDDATABYTES_E_RDBYTE4 | 0x3 | Read 4 Byte + * ALT_QSPI_FLSHCMD_NUMRDDATABYTES_E_RDBYTE5 | 0x4 | Read 5 Byte + * ALT_QSPI_FLSHCMD_NUMRDDATABYTES_E_RDBYTE6 | 0x5 | Read 6 Byte + * ALT_QSPI_FLSHCMD_NUMRDDATABYTES_E_RDBYTE7 | 0x6 | Read 7 Byte + * ALT_QSPI_FLSHCMD_NUMRDDATABYTES_E_RDBYTE8 | 0x7 | Read 8 Byte + * + * Field Access Macros: + * + */ +/* + * Enumerated value for register field ALT_QSPI_FLSHCMD_NUMRDDATABYTES + * + * Read 1 Byte + */ +#define ALT_QSPI_FLSHCMD_NUMRDDATABYTES_E_RDBYTE1 0x0 +/* + * Enumerated value for register field ALT_QSPI_FLSHCMD_NUMRDDATABYTES + * + * Read 2 Byte + */ +#define ALT_QSPI_FLSHCMD_NUMRDDATABYTES_E_RDBYTE2 0x1 +/* + * Enumerated value for register field ALT_QSPI_FLSHCMD_NUMRDDATABYTES + * + * Read 3 Byte + */ +#define ALT_QSPI_FLSHCMD_NUMRDDATABYTES_E_RDBYTE3 0x2 +/* + * Enumerated value for register field ALT_QSPI_FLSHCMD_NUMRDDATABYTES + * + * Read 4 Byte + */ +#define ALT_QSPI_FLSHCMD_NUMRDDATABYTES_E_RDBYTE4 0x3 +/* + * Enumerated value for register field ALT_QSPI_FLSHCMD_NUMRDDATABYTES + * + * Read 5 Byte + */ +#define ALT_QSPI_FLSHCMD_NUMRDDATABYTES_E_RDBYTE5 0x4 +/* + * Enumerated value for register field ALT_QSPI_FLSHCMD_NUMRDDATABYTES + * + * Read 6 Byte + */ +#define ALT_QSPI_FLSHCMD_NUMRDDATABYTES_E_RDBYTE6 0x5 +/* + * Enumerated value for register field ALT_QSPI_FLSHCMD_NUMRDDATABYTES + * + * Read 7 Byte + */ +#define ALT_QSPI_FLSHCMD_NUMRDDATABYTES_E_RDBYTE7 0x6 +/* + * Enumerated value for register field ALT_QSPI_FLSHCMD_NUMRDDATABYTES + * + * Read 8 Byte + */ +#define ALT_QSPI_FLSHCMD_NUMRDDATABYTES_E_RDBYTE8 0x7 + +/* The Least Significant Bit (LSB) position of the ALT_QSPI_FLSHCMD_NUMRDDATABYTES register field. */ +#define ALT_QSPI_FLSHCMD_NUMRDDATABYTES_LSB 20 +/* The Most Significant Bit (MSB) position of the ALT_QSPI_FLSHCMD_NUMRDDATABYTES register field. */ +#define ALT_QSPI_FLSHCMD_NUMRDDATABYTES_MSB 22 +/* The width in bits of the ALT_QSPI_FLSHCMD_NUMRDDATABYTES register field. */ +#define ALT_QSPI_FLSHCMD_NUMRDDATABYTES_WIDTH 3 +/* The mask used to set the ALT_QSPI_FLSHCMD_NUMRDDATABYTES register field value. */ +#define ALT_QSPI_FLSHCMD_NUMRDDATABYTES_SET_MSK 0x00700000 +/* The mask used to clear the ALT_QSPI_FLSHCMD_NUMRDDATABYTES register field value. */ +#define ALT_QSPI_FLSHCMD_NUMRDDATABYTES_CLR_MSK 0xff8fffff +/* The reset value of the ALT_QSPI_FLSHCMD_NUMRDDATABYTES register field. */ +#define ALT_QSPI_FLSHCMD_NUMRDDATABYTES_RESET 0x0 +/* Extracts the ALT_QSPI_FLSHCMD_NUMRDDATABYTES field value from a register. */ +#define ALT_QSPI_FLSHCMD_NUMRDDATABYTES_GET(value) (((value) & 0x00700000) >> 20) +/* Produces a ALT_QSPI_FLSHCMD_NUMRDDATABYTES register field value suitable for setting the register. */ +#define ALT_QSPI_FLSHCMD_NUMRDDATABYTES_SET(value) (((value) << 20) & 0x00700000) + +/* + * Field : Read Data Enable - enrddata + * + * If enabled, the command specified in the command opcode field (bits 31:24) + * requires read data bytes to be received from the device. + * + * Field Enumeration Values: + * + * Enum | Value | Description + * :-------------------------------------|:------|:--------------------------- + * ALT_QSPI_FLSHCMD_ENRDDATA_E_EN | 0x1 | Command Requires read data + * ALT_QSPI_FLSHCMD_ENRDDATA_E_NOACTION | 0x0 | No Action + * + * Field Access Macros: + * + */ +/* + * Enumerated value for register field ALT_QSPI_FLSHCMD_ENRDDATA + * + * Command Requires read data + */ +#define ALT_QSPI_FLSHCMD_ENRDDATA_E_EN 0x1 +/* + * Enumerated value for register field ALT_QSPI_FLSHCMD_ENRDDATA + * + * No Action + */ +#define ALT_QSPI_FLSHCMD_ENRDDATA_E_NOACTION 0x0 + +/* The Least Significant Bit (LSB) position of the ALT_QSPI_FLSHCMD_ENRDDATA register field. */ +#define ALT_QSPI_FLSHCMD_ENRDDATA_LSB 23 +/* The Most Significant Bit (MSB) position of the ALT_QSPI_FLSHCMD_ENRDDATA register field. */ +#define ALT_QSPI_FLSHCMD_ENRDDATA_MSB 23 +/* The width in bits of the ALT_QSPI_FLSHCMD_ENRDDATA register field. */ +#define ALT_QSPI_FLSHCMD_ENRDDATA_WIDTH 1 +/* The mask used to set the ALT_QSPI_FLSHCMD_ENRDDATA register field value. */ +#define ALT_QSPI_FLSHCMD_ENRDDATA_SET_MSK 0x00800000 +/* The mask used to clear the ALT_QSPI_FLSHCMD_ENRDDATA register field value. */ +#define ALT_QSPI_FLSHCMD_ENRDDATA_CLR_MSK 0xff7fffff +/* The reset value of the ALT_QSPI_FLSHCMD_ENRDDATA register field. */ +#define ALT_QSPI_FLSHCMD_ENRDDATA_RESET 0x0 +/* Extracts the ALT_QSPI_FLSHCMD_ENRDDATA field value from a register. */ +#define ALT_QSPI_FLSHCMD_ENRDDATA_GET(value) (((value) & 0x00800000) >> 23) +/* Produces a ALT_QSPI_FLSHCMD_ENRDDATA register field value suitable for setting the register. */ +#define ALT_QSPI_FLSHCMD_ENRDDATA_SET(value) (((value) << 23) & 0x00800000) + +/* + * Field : Command Opcode - cmdopcode + * + * The command opcode field should be setup before triggering the command. For + * example, 0x20 maps to SubSector Erase. Writeing to the execute field (bit 0) of + * this register launches the command. NOTE : Using this approach to issue commands + * to the device will make use of the instruction type of the device instruction + * configuration register. If this field is set to 2'b00, then the command opcode, + * command address, command dummy bytes and command data will all be transferred in + * a serial fashion. If this field is set to 2'b01, then the command opcode, + * command address, command dummy bytes and command data will all be transferred in + * parallel using DQ0 and DQ1 pins. If this field is set to 2'b10, then the command + * opcode, command address, command dummy bytes and command data will all be + * transferred in parallel using DQ0, DQ1, DQ2 and DQ3 pins. + * + * Field Access Macros: + * + */ +/* The Least Significant Bit (LSB) position of the ALT_QSPI_FLSHCMD_CMDOPCODE register field. */ +#define ALT_QSPI_FLSHCMD_CMDOPCODE_LSB 24 +/* The Most Significant Bit (MSB) position of the ALT_QSPI_FLSHCMD_CMDOPCODE register field. */ +#define ALT_QSPI_FLSHCMD_CMDOPCODE_MSB 31 +/* The width in bits of the ALT_QSPI_FLSHCMD_CMDOPCODE register field. */ +#define ALT_QSPI_FLSHCMD_CMDOPCODE_WIDTH 8 +/* The mask used to set the ALT_QSPI_FLSHCMD_CMDOPCODE register field value. */ +#define ALT_QSPI_FLSHCMD_CMDOPCODE_SET_MSK 0xff000000 +/* The mask used to clear the ALT_QSPI_FLSHCMD_CMDOPCODE register field value. */ +#define ALT_QSPI_FLSHCMD_CMDOPCODE_CLR_MSK 0x00ffffff +/* The reset value of the ALT_QSPI_FLSHCMD_CMDOPCODE register field. */ +#define ALT_QSPI_FLSHCMD_CMDOPCODE_RESET 0x0 +/* Extracts the ALT_QSPI_FLSHCMD_CMDOPCODE field value from a register. */ +#define ALT_QSPI_FLSHCMD_CMDOPCODE_GET(value) (((value) & 0xff000000) >> 24) +/* Produces a ALT_QSPI_FLSHCMD_CMDOPCODE register field value suitable for setting the register. */ +#define ALT_QSPI_FLSHCMD_CMDOPCODE_SET(value) (((value) << 24) & 0xff000000) + +#ifndef __ASSEMBLY__ +/* + * WARNING: The C register and register group struct declarations are provided for + * convenience and illustrative purposes. They should, however, be used with + * caution as the C language standard provides no guarantees about the alignment or + * atomicity of device memory accesses. The recommended practice for writing + * hardware drivers is to use the SoCAL access macros and alt_read_word() and + * alt_write_word() functions. + * + * The struct declaration for register ALT_QSPI_FLSHCMD. + */ +struct ALT_QSPI_FLSHCMD_s +{ + uint32_t execcmd : 1; /* Execute Command */ + const uint32_t cmdexecstat : 1; /* Command Execution Status */ + uint32_t : 5; /* *UNDEFINED* */ + uint32_t numdummybytes : 5; /* Number of Dummy Bytes */ + uint32_t numwrdatabytes : 3; /* Number of Write Data Bytes */ + uint32_t enwrdata : 1; /* Write Data Enable */ + uint32_t numaddrbytes : 2; /* Number of Address Bytes */ + uint32_t enmodebit : 1; /* Mode Bit Enable */ + uint32_t encmdaddr : 1; /* Command Address Enable */ + uint32_t numrddatabytes : 3; /* Number of Read Data Bytes */ + uint32_t enrddata : 1; /* Read Data Enable */ + uint32_t cmdopcode : 8; /* Command Opcode */ +}; + +/* The typedef declaration for register ALT_QSPI_FLSHCMD. */ +typedef volatile struct ALT_QSPI_FLSHCMD_s ALT_QSPI_FLSHCMD_t; +#endif /* __ASSEMBLY__ */ + +/* The byte offset of the ALT_QSPI_FLSHCMD register from the beginning of the component. */ +#define ALT_QSPI_FLSHCMD_OFST 0x90 + +/* + * Register : Flash Command Address Registers - flashcmdaddr + * + * Register Layout + * + * Bits | Access | Reset | Description + * :-------|:-------|:------|:---------------- + * [31:0] | RW | 0x0 | Command Address + * + */ +/* + * Field : Command Address - addr + * + * This should be setup before triggering the command with execute field (bit 0) of + * the Flash Command Control register. It is the address used by the command + * specified in the opcode field (bits 31:24) of the Flash Command Control + * register. + * + * Field Access Macros: + * + */ +/* The Least Significant Bit (LSB) position of the ALT_QSPI_FLSHCMDADDR_ADDR register field. */ +#define ALT_QSPI_FLSHCMDADDR_ADDR_LSB 0 +/* The Most Significant Bit (MSB) position of the ALT_QSPI_FLSHCMDADDR_ADDR register field. */ +#define ALT_QSPI_FLSHCMDADDR_ADDR_MSB 31 +/* The width in bits of the ALT_QSPI_FLSHCMDADDR_ADDR register field. */ +#define ALT_QSPI_FLSHCMDADDR_ADDR_WIDTH 32 +/* The mask used to set the ALT_QSPI_FLSHCMDADDR_ADDR register field value. */ +#define ALT_QSPI_FLSHCMDADDR_ADDR_SET_MSK 0xffffffff +/* The mask used to clear the ALT_QSPI_FLSHCMDADDR_ADDR register field value. */ +#define ALT_QSPI_FLSHCMDADDR_ADDR_CLR_MSK 0x00000000 +/* The reset value of the ALT_QSPI_FLSHCMDADDR_ADDR register field. */ +#define ALT_QSPI_FLSHCMDADDR_ADDR_RESET 0x0 +/* Extracts the ALT_QSPI_FLSHCMDADDR_ADDR field value from a register. */ +#define ALT_QSPI_FLSHCMDADDR_ADDR_GET(value) (((value) & 0xffffffff) >> 0) +/* Produces a ALT_QSPI_FLSHCMDADDR_ADDR register field value suitable for setting the register. */ +#define ALT_QSPI_FLSHCMDADDR_ADDR_SET(value) (((value) << 0) & 0xffffffff) + +#ifndef __ASSEMBLY__ +/* + * WARNING: The C register and register group struct declarations are provided for + * convenience and illustrative purposes. They should, however, be used with + * caution as the C language standard provides no guarantees about the alignment or + * atomicity of device memory accesses. The recommended practice for writing + * hardware drivers is to use the SoCAL access macros and alt_read_word() and + * alt_write_word() functions. + * + * The struct declaration for register ALT_QSPI_FLSHCMDADDR. + */ +struct ALT_QSPI_FLSHCMDADDR_s +{ + uint32_t addr : 32; /* Command Address */ +}; + +/* The typedef declaration for register ALT_QSPI_FLSHCMDADDR. */ +typedef volatile struct ALT_QSPI_FLSHCMDADDR_s ALT_QSPI_FLSHCMDADDR_t; +#endif /* __ASSEMBLY__ */ + +/* The byte offset of the ALT_QSPI_FLSHCMDADDR register from the beginning of the component. */ +#define ALT_QSPI_FLSHCMDADDR_OFST 0x94 + +/* + * Register : Flash Command Read Data Register (Lower) - flashcmdrddatalo + * + * Register Layout + * + * Bits | Access | Reset | Description + * :-------|:-------|:------|:------------------------------- + * [31:0] | RW | 0x0 | Command Read Data (Lower byte) + * + */ +/* + * Field : Command Read Data (Lower byte) - data + * + * This is the data that is returned by the flash device for any status or + * configuration read operation carried out by triggering the event in the control + * register. The register will be valid when the polling bit in the control + * register is low. + * + * Field Access Macros: + * + */ +/* The Least Significant Bit (LSB) position of the ALT_QSPI_FLSHCMDRDDATALO_DATA register field. */ +#define ALT_QSPI_FLSHCMDRDDATALO_DATA_LSB 0 +/* The Most Significant Bit (MSB) position of the ALT_QSPI_FLSHCMDRDDATALO_DATA register field. */ +#define ALT_QSPI_FLSHCMDRDDATALO_DATA_MSB 31 +/* The width in bits of the ALT_QSPI_FLSHCMDRDDATALO_DATA register field. */ +#define ALT_QSPI_FLSHCMDRDDATALO_DATA_WIDTH 32 +/* The mask used to set the ALT_QSPI_FLSHCMDRDDATALO_DATA register field value. */ +#define ALT_QSPI_FLSHCMDRDDATALO_DATA_SET_MSK 0xffffffff +/* The mask used to clear the ALT_QSPI_FLSHCMDRDDATALO_DATA register field value. */ +#define ALT_QSPI_FLSHCMDRDDATALO_DATA_CLR_MSK 0x00000000 +/* The reset value of the ALT_QSPI_FLSHCMDRDDATALO_DATA register field. */ +#define ALT_QSPI_FLSHCMDRDDATALO_DATA_RESET 0x0 +/* Extracts the ALT_QSPI_FLSHCMDRDDATALO_DATA field value from a register. */ +#define ALT_QSPI_FLSHCMDRDDATALO_DATA_GET(value) (((value) & 0xffffffff) >> 0) +/* Produces a ALT_QSPI_FLSHCMDRDDATALO_DATA register field value suitable for setting the register. */ +#define ALT_QSPI_FLSHCMDRDDATALO_DATA_SET(value) (((value) << 0) & 0xffffffff) + +#ifndef __ASSEMBLY__ +/* + * WARNING: The C register and register group struct declarations are provided for + * convenience and illustrative purposes. They should, however, be used with + * caution as the C language standard provides no guarantees about the alignment or + * atomicity of device memory accesses. The recommended practice for writing + * hardware drivers is to use the SoCAL access macros and alt_read_word() and + * alt_write_word() functions. + * + * The struct declaration for register ALT_QSPI_FLSHCMDRDDATALO. + */ +struct ALT_QSPI_FLSHCMDRDDATALO_s +{ + uint32_t data : 32; /* Command Read Data (Lower byte) */ +}; + +/* The typedef declaration for register ALT_QSPI_FLSHCMDRDDATALO. */ +typedef volatile struct ALT_QSPI_FLSHCMDRDDATALO_s ALT_QSPI_FLSHCMDRDDATALO_t; +#endif /* __ASSEMBLY__ */ + +/* The byte offset of the ALT_QSPI_FLSHCMDRDDATALO register from the beginning of the component. */ +#define ALT_QSPI_FLSHCMDRDDATALO_OFST 0xa0 + +/* + * Register : Flash Command Read Data Register (Upper) - flashcmdrddataup + * + * Device Instruction Register + * + * Register Layout + * + * Bits | Access | Reset | Description + * :-------|:-------|:------|:------------------------------- + * [31:0] | RW | 0x0 | Command Read Data (Upper byte) + * + */ +/* + * Field : Command Read Data (Upper byte) - data + * + * This is the data that is returned by the FLASH device for any status or + * configuration read operation carried out by triggering the event in the control + * register. The register will be valid when the polling bit in the control + * register is low. + * + * Field Access Macros: + * + */ +/* The Least Significant Bit (LSB) position of the ALT_QSPI_FLSHCMDRDDATAUP_DATA register field. */ +#define ALT_QSPI_FLSHCMDRDDATAUP_DATA_LSB 0 +/* The Most Significant Bit (MSB) position of the ALT_QSPI_FLSHCMDRDDATAUP_DATA register field. */ +#define ALT_QSPI_FLSHCMDRDDATAUP_DATA_MSB 31 +/* The width in bits of the ALT_QSPI_FLSHCMDRDDATAUP_DATA register field. */ +#define ALT_QSPI_FLSHCMDRDDATAUP_DATA_WIDTH 32 +/* The mask used to set the ALT_QSPI_FLSHCMDRDDATAUP_DATA register field value. */ +#define ALT_QSPI_FLSHCMDRDDATAUP_DATA_SET_MSK 0xffffffff +/* The mask used to clear the ALT_QSPI_FLSHCMDRDDATAUP_DATA register field value. */ +#define ALT_QSPI_FLSHCMDRDDATAUP_DATA_CLR_MSK 0x00000000 +/* The reset value of the ALT_QSPI_FLSHCMDRDDATAUP_DATA register field. */ +#define ALT_QSPI_FLSHCMDRDDATAUP_DATA_RESET 0x0 +/* Extracts the ALT_QSPI_FLSHCMDRDDATAUP_DATA field value from a register. */ +#define ALT_QSPI_FLSHCMDRDDATAUP_DATA_GET(value) (((value) & 0xffffffff) >> 0) +/* Produces a ALT_QSPI_FLSHCMDRDDATAUP_DATA register field value suitable for setting the register. */ +#define ALT_QSPI_FLSHCMDRDDATAUP_DATA_SET(value) (((value) << 0) & 0xffffffff) + +#ifndef __ASSEMBLY__ +/* + * WARNING: The C register and register group struct declarations are provided for + * convenience and illustrative purposes. They should, however, be used with + * caution as the C language standard provides no guarantees about the alignment or + * atomicity of device memory accesses. The recommended practice for writing + * hardware drivers is to use the SoCAL access macros and alt_read_word() and + * alt_write_word() functions. + * + * The struct declaration for register ALT_QSPI_FLSHCMDRDDATAUP. + */ +struct ALT_QSPI_FLSHCMDRDDATAUP_s +{ + uint32_t data : 32; /* Command Read Data (Upper byte) */ +}; + +/* The typedef declaration for register ALT_QSPI_FLSHCMDRDDATAUP. */ +typedef volatile struct ALT_QSPI_FLSHCMDRDDATAUP_s ALT_QSPI_FLSHCMDRDDATAUP_t; +#endif /* __ASSEMBLY__ */ + +/* The byte offset of the ALT_QSPI_FLSHCMDRDDATAUP register from the beginning of the component. */ +#define ALT_QSPI_FLSHCMDRDDATAUP_OFST 0xa4 + +/* + * Register : Flash Command Write Data Register (Lower) - flashcmdwrdatalo + * + * Register Layout + * + * Bits | Access | Reset | Description + * :-------|:-------|:------|:------------------------------ + * [31:0] | RW | 0x0 | Command Write Data Lower Byte + * + */ +/* + * Field : Command Write Data Lower Byte - data + * + * This is the command write data lower byte. This should be setup before + * triggering the command with execute field (bit 0) of the Flash Command Control + * register. It is the data that is to be written to the flash for any status or + * configuration write operation carried out by triggering the event in the Flash + * Command Control register. + * + * Field Access Macros: + * + */ +/* The Least Significant Bit (LSB) position of the ALT_QSPI_FLSHCMDWRDATALO_DATA register field. */ +#define ALT_QSPI_FLSHCMDWRDATALO_DATA_LSB 0 +/* The Most Significant Bit (MSB) position of the ALT_QSPI_FLSHCMDWRDATALO_DATA register field. */ +#define ALT_QSPI_FLSHCMDWRDATALO_DATA_MSB 31 +/* The width in bits of the ALT_QSPI_FLSHCMDWRDATALO_DATA register field. */ +#define ALT_QSPI_FLSHCMDWRDATALO_DATA_WIDTH 32 +/* The mask used to set the ALT_QSPI_FLSHCMDWRDATALO_DATA register field value. */ +#define ALT_QSPI_FLSHCMDWRDATALO_DATA_SET_MSK 0xffffffff +/* The mask used to clear the ALT_QSPI_FLSHCMDWRDATALO_DATA register field value. */ +#define ALT_QSPI_FLSHCMDWRDATALO_DATA_CLR_MSK 0x00000000 +/* The reset value of the ALT_QSPI_FLSHCMDWRDATALO_DATA register field. */ +#define ALT_QSPI_FLSHCMDWRDATALO_DATA_RESET 0x0 +/* Extracts the ALT_QSPI_FLSHCMDWRDATALO_DATA field value from a register. */ +#define ALT_QSPI_FLSHCMDWRDATALO_DATA_GET(value) (((value) & 0xffffffff) >> 0) +/* Produces a ALT_QSPI_FLSHCMDWRDATALO_DATA register field value suitable for setting the register. */ +#define ALT_QSPI_FLSHCMDWRDATALO_DATA_SET(value) (((value) << 0) & 0xffffffff) + +#ifndef __ASSEMBLY__ +/* + * WARNING: The C register and register group struct declarations are provided for + * convenience and illustrative purposes. They should, however, be used with + * caution as the C language standard provides no guarantees about the alignment or + * atomicity of device memory accesses. The recommended practice for writing + * hardware drivers is to use the SoCAL access macros and alt_read_word() and + * alt_write_word() functions. + * + * The struct declaration for register ALT_QSPI_FLSHCMDWRDATALO. + */ +struct ALT_QSPI_FLSHCMDWRDATALO_s +{ + uint32_t data : 32; /* Command Write Data Lower Byte */ +}; + +/* The typedef declaration for register ALT_QSPI_FLSHCMDWRDATALO. */ +typedef volatile struct ALT_QSPI_FLSHCMDWRDATALO_s ALT_QSPI_FLSHCMDWRDATALO_t; +#endif /* __ASSEMBLY__ */ + +/* The byte offset of the ALT_QSPI_FLSHCMDWRDATALO register from the beginning of the component. */ +#define ALT_QSPI_FLSHCMDWRDATALO_OFST 0xa8 + +/* + * Register : Flash Command Write Data Register (Upper) - flashcmdwrdataup + * + * Register Layout + * + * Bits | Access | Reset | Description + * :-------|:-------|:------|:------------------------------ + * [31:0] | RW | 0x0 | ALT_QSPI_FLSHCMDWRDATAUP_DATA + * + */ +/* + * Field : data + * + * This is the command write data upper byte. This should be setup before + * triggering the command with execute field (bit 0) of the Flash Command Control + * register. It is the data that is to be written to the flash for any status or + * configuration write operation carried out by triggering the event in the Flash + * Command Control register. + * + * Field Access Macros: + * + */ +/* The Least Significant Bit (LSB) position of the ALT_QSPI_FLSHCMDWRDATAUP_DATA register field. */ +#define ALT_QSPI_FLSHCMDWRDATAUP_DATA_LSB 0 +/* The Most Significant Bit (MSB) position of the ALT_QSPI_FLSHCMDWRDATAUP_DATA register field. */ +#define ALT_QSPI_FLSHCMDWRDATAUP_DATA_MSB 31 +/* The width in bits of the ALT_QSPI_FLSHCMDWRDATAUP_DATA register field. */ +#define ALT_QSPI_FLSHCMDWRDATAUP_DATA_WIDTH 32 +/* The mask used to set the ALT_QSPI_FLSHCMDWRDATAUP_DATA register field value. */ +#define ALT_QSPI_FLSHCMDWRDATAUP_DATA_SET_MSK 0xffffffff +/* The mask used to clear the ALT_QSPI_FLSHCMDWRDATAUP_DATA register field value. */ +#define ALT_QSPI_FLSHCMDWRDATAUP_DATA_CLR_MSK 0x00000000 +/* The reset value of the ALT_QSPI_FLSHCMDWRDATAUP_DATA register field. */ +#define ALT_QSPI_FLSHCMDWRDATAUP_DATA_RESET 0x0 +/* Extracts the ALT_QSPI_FLSHCMDWRDATAUP_DATA field value from a register. */ +#define ALT_QSPI_FLSHCMDWRDATAUP_DATA_GET(value) (((value) & 0xffffffff) >> 0) +/* Produces a ALT_QSPI_FLSHCMDWRDATAUP_DATA register field value suitable for setting the register. */ +#define ALT_QSPI_FLSHCMDWRDATAUP_DATA_SET(value) (((value) << 0) & 0xffffffff) + +#ifndef __ASSEMBLY__ +/* + * WARNING: The C register and register group struct declarations are provided for + * convenience and illustrative purposes. They should, however, be used with + * caution as the C language standard provides no guarantees about the alignment or + * atomicity of device memory accesses. The recommended practice for writing + * hardware drivers is to use the SoCAL access macros and alt_read_word() and + * alt_write_word() functions. + * + * The struct declaration for register ALT_QSPI_FLSHCMDWRDATAUP. + */ +struct ALT_QSPI_FLSHCMDWRDATAUP_s +{ + uint32_t data : 32; /* ALT_QSPI_FLSHCMDWRDATAUP_DATA */ +}; + +/* The typedef declaration for register ALT_QSPI_FLSHCMDWRDATAUP. */ +typedef volatile struct ALT_QSPI_FLSHCMDWRDATAUP_s ALT_QSPI_FLSHCMDWRDATAUP_t; +#endif /* __ASSEMBLY__ */ + +/* The byte offset of the ALT_QSPI_FLSHCMDWRDATAUP register from the beginning of the component. */ +#define ALT_QSPI_FLSHCMDWRDATAUP_OFST 0xac + +/* + * Register : Module ID Register - moduleid + * + * Register Layout + * + * Bits | Access | Reset | Description + * :--------|:-------|:-------|:----------------- + * [24:0] | R | 0x1001 | Module ID number + * [31:25] | ??? | 0x0 | *UNDEFINED* + * + */ +/* + * Field : Module ID number - value + * + * Field Access Macros: + * + */ +/* The Least Significant Bit (LSB) position of the ALT_QSPI_MODULEID_VALUE register field. */ +#define ALT_QSPI_MODULEID_VALUE_LSB 0 +/* The Most Significant Bit (MSB) position of the ALT_QSPI_MODULEID_VALUE register field. */ +#define ALT_QSPI_MODULEID_VALUE_MSB 24 +/* The width in bits of the ALT_QSPI_MODULEID_VALUE register field. */ +#define ALT_QSPI_MODULEID_VALUE_WIDTH 25 +/* The mask used to set the ALT_QSPI_MODULEID_VALUE register field value. */ +#define ALT_QSPI_MODULEID_VALUE_SET_MSK 0x01ffffff +/* The mask used to clear the ALT_QSPI_MODULEID_VALUE register field value. */ +#define ALT_QSPI_MODULEID_VALUE_CLR_MSK 0xfe000000 +/* The reset value of the ALT_QSPI_MODULEID_VALUE register field. */ +#define ALT_QSPI_MODULEID_VALUE_RESET 0x1001 +/* Extracts the ALT_QSPI_MODULEID_VALUE field value from a register. */ +#define ALT_QSPI_MODULEID_VALUE_GET(value) (((value) & 0x01ffffff) >> 0) +/* Produces a ALT_QSPI_MODULEID_VALUE register field value suitable for setting the register. */ +#define ALT_QSPI_MODULEID_VALUE_SET(value) (((value) << 0) & 0x01ffffff) + +#ifndef __ASSEMBLY__ +/* + * WARNING: The C register and register group struct declarations are provided for + * convenience and illustrative purposes. They should, however, be used with + * caution as the C language standard provides no guarantees about the alignment or + * atomicity of device memory accesses. The recommended practice for writing + * hardware drivers is to use the SoCAL access macros and alt_read_word() and + * alt_write_word() functions. + * + * The struct declaration for register ALT_QSPI_MODULEID. + */ +struct ALT_QSPI_MODULEID_s +{ + const uint32_t value : 25; /* Module ID number */ + uint32_t : 7; /* *UNDEFINED* */ +}; + +/* The typedef declaration for register ALT_QSPI_MODULEID. */ +typedef volatile struct ALT_QSPI_MODULEID_s ALT_QSPI_MODULEID_t; +#endif /* __ASSEMBLY__ */ + +/* The byte offset of the ALT_QSPI_MODULEID register from the beginning of the component. */ +#define ALT_QSPI_MODULEID_OFST 0xfc + +#ifndef __ASSEMBLY__ +/* + * WARNING: The C register and register group struct declarations are provided for + * convenience and illustrative purposes. They should, however, be used with + * caution as the C language standard provides no guarantees about the alignment or + * atomicity of device memory accesses. The recommended practice for writing + * hardware drivers is to use the SoCAL access macros and alt_read_word() and + * alt_write_word() functions. + * + * The struct declaration for register group ALT_QSPI. + */ +struct ALT_QSPI_s +{ + volatile ALT_QSPI_CFG_t cfg; /* ALT_QSPI_CFG */ + volatile ALT_QSPI_DEVRD_t devrd; /* ALT_QSPI_DEVRD */ + volatile ALT_QSPI_DEVWR_t devwr; /* ALT_QSPI_DEVWR */ + volatile ALT_QSPI_DELAY_t delay; /* ALT_QSPI_DELAY */ + volatile ALT_QSPI_RDDATACAP_t rddatacap; /* ALT_QSPI_RDDATACAP */ + volatile ALT_QSPI_DEVSZ_t devsz; /* ALT_QSPI_DEVSZ */ + volatile ALT_QSPI_SRAMPART_t srampart; /* ALT_QSPI_SRAMPART */ + volatile ALT_QSPI_INDADDRTRIG_t indaddrtrig; /* ALT_QSPI_INDADDRTRIG */ + volatile ALT_QSPI_DMAPER_t dmaper; /* ALT_QSPI_DMAPER */ + volatile ALT_QSPI_REMAPADDR_t remapaddr; /* ALT_QSPI_REMAPADDR */ + volatile ALT_QSPI_MODBIT_t modebit; /* ALT_QSPI_MODBIT */ + volatile ALT_QSPI_SRAMFILL_t sramfill; /* ALT_QSPI_SRAMFILL */ + volatile ALT_QSPI_TXTHRESH_t txthresh; /* ALT_QSPI_TXTHRESH */ + volatile ALT_QSPI_RXTHRESH_t rxthresh; /* ALT_QSPI_RXTHRESH */ + volatile uint32_t _pad_0x38_0x3f[2]; /* *UNDEFINED* */ + volatile ALT_QSPI_IRQSTAT_t irqstat; /* ALT_QSPI_IRQSTAT */ + volatile ALT_QSPI_IRQMSK_t irqmask; /* ALT_QSPI_IRQMSK */ + volatile uint32_t _pad_0x48_0x4f[2]; /* *UNDEFINED* */ + volatile ALT_QSPI_LOWWRPROT_t lowwrprot; /* ALT_QSPI_LOWWRPROT */ + volatile ALT_QSPI_UPPWRPROT_t uppwrprot; /* ALT_QSPI_UPPWRPROT */ + volatile ALT_QSPI_WRPROT_t wrprot; /* ALT_QSPI_WRPROT */ + volatile uint32_t _pad_0x5c_0x5f; /* *UNDEFINED* */ + volatile ALT_QSPI_INDRD_t indrd; /* ALT_QSPI_INDRD */ + volatile ALT_QSPI_INDRDWATER_t indrdwater; /* ALT_QSPI_INDRDWATER */ + volatile ALT_QSPI_INDRDSTADDR_t indrdstaddr; /* ALT_QSPI_INDRDSTADDR */ + volatile ALT_QSPI_INDRDCNT_t indrdcnt; /* ALT_QSPI_INDRDCNT */ + volatile ALT_QSPI_INDWR_t indwr; /* ALT_QSPI_INDWR */ + volatile ALT_QSPI_INDWRWATER_t indwrwater; /* ALT_QSPI_INDWRWATER */ + volatile ALT_QSPI_INDWRSTADDR_t indwrstaddr; /* ALT_QSPI_INDWRSTADDR */ + volatile ALT_QSPI_INDWRCNT_t indwrcnt; /* ALT_QSPI_INDWRCNT */ + volatile uint32_t _pad_0x80_0x8f[4]; /* *UNDEFINED* */ + volatile ALT_QSPI_FLSHCMD_t flashcmd; /* ALT_QSPI_FLSHCMD */ + volatile ALT_QSPI_FLSHCMDADDR_t flashcmdaddr; /* ALT_QSPI_FLSHCMDADDR */ + volatile uint32_t _pad_0x98_0x9f[2]; /* *UNDEFINED* */ + volatile ALT_QSPI_FLSHCMDRDDATALO_t flashcmdrddatalo; /* ALT_QSPI_FLSHCMDRDDATALO */ + volatile ALT_QSPI_FLSHCMDRDDATAUP_t flashcmdrddataup; /* ALT_QSPI_FLSHCMDRDDATAUP */ + volatile ALT_QSPI_FLSHCMDWRDATALO_t flashcmdwrdatalo; /* ALT_QSPI_FLSHCMDWRDATALO */ + volatile ALT_QSPI_FLSHCMDWRDATAUP_t flashcmdwrdataup; /* ALT_QSPI_FLSHCMDWRDATAUP */ + volatile uint32_t _pad_0xb0_0xfb[19]; /* *UNDEFINED* */ + volatile ALT_QSPI_MODULEID_t moduleid; /* ALT_QSPI_MODULEID */ +}; + +/* The typedef declaration for register group ALT_QSPI. */ +typedef volatile struct ALT_QSPI_s ALT_QSPI_t; +/* The struct declaration for the raw register contents of register group ALT_QSPI. */ +struct ALT_QSPI_raw_s +{ + volatile uint32_t cfg; /* ALT_QSPI_CFG */ + volatile uint32_t devrd; /* ALT_QSPI_DEVRD */ + volatile uint32_t devwr; /* ALT_QSPI_DEVWR */ + volatile uint32_t delay; /* ALT_QSPI_DELAY */ + volatile uint32_t rddatacap; /* ALT_QSPI_RDDATACAP */ + volatile uint32_t devsz; /* ALT_QSPI_DEVSZ */ + volatile uint32_t srampart; /* ALT_QSPI_SRAMPART */ + volatile uint32_t indaddrtrig; /* ALT_QSPI_INDADDRTRIG */ + volatile uint32_t dmaper; /* ALT_QSPI_DMAPER */ + volatile uint32_t remapaddr; /* ALT_QSPI_REMAPADDR */ + volatile uint32_t modebit; /* ALT_QSPI_MODBIT */ + volatile uint32_t sramfill; /* ALT_QSPI_SRAMFILL */ + volatile uint32_t txthresh; /* ALT_QSPI_TXTHRESH */ + volatile uint32_t rxthresh; /* ALT_QSPI_RXTHRESH */ + volatile uint32_t _pad_0x38_0x3f[2]; /* *UNDEFINED* */ + volatile uint32_t irqstat; /* ALT_QSPI_IRQSTAT */ + volatile uint32_t irqmask; /* ALT_QSPI_IRQMSK */ + volatile uint32_t _pad_0x48_0x4f[2]; /* *UNDEFINED* */ + volatile uint32_t lowwrprot; /* ALT_QSPI_LOWWRPROT */ + volatile uint32_t uppwrprot; /* ALT_QSPI_UPPWRPROT */ + volatile uint32_t wrprot; /* ALT_QSPI_WRPROT */ + volatile uint32_t _pad_0x5c_0x5f; /* *UNDEFINED* */ + volatile uint32_t indrd; /* ALT_QSPI_INDRD */ + volatile uint32_t indrdwater; /* ALT_QSPI_INDRDWATER */ + volatile uint32_t indrdstaddr; /* ALT_QSPI_INDRDSTADDR */ + volatile uint32_t indrdcnt; /* ALT_QSPI_INDRDCNT */ + volatile uint32_t indwr; /* ALT_QSPI_INDWR */ + volatile uint32_t indwrwater; /* ALT_QSPI_INDWRWATER */ + volatile uint32_t indwrstaddr; /* ALT_QSPI_INDWRSTADDR */ + volatile uint32_t indwrcnt; /* ALT_QSPI_INDWRCNT */ + volatile uint32_t _pad_0x80_0x8f[4]; /* *UNDEFINED* */ + volatile uint32_t flashcmd; /* ALT_QSPI_FLSHCMD */ + volatile uint32_t flashcmdaddr; /* ALT_QSPI_FLSHCMDADDR */ + volatile uint32_t _pad_0x98_0x9f[2]; /* *UNDEFINED* */ + volatile uint32_t flashcmdrddatalo; /* ALT_QSPI_FLSHCMDRDDATALO */ + volatile uint32_t flashcmdrddataup; /* ALT_QSPI_FLSHCMDRDDATAUP */ + volatile uint32_t flashcmdwrdatalo; /* ALT_QSPI_FLSHCMDWRDATALO */ + volatile uint32_t flashcmdwrdataup; /* ALT_QSPI_FLSHCMDWRDATAUP */ + volatile uint32_t _pad_0xb0_0xfb[19]; /* *UNDEFINED* */ + volatile uint32_t moduleid; /* ALT_QSPI_MODULEID */ +}; + +/* The typedef declaration for the raw register contents of register group ALT_QSPI. */ +typedef volatile struct ALT_QSPI_raw_s ALT_QSPI_raw_t; +#endif /* __ASSEMBLY__ */ + + +#ifdef __cplusplus +} +#endif /* __cplusplus */ +#endif /* __ALTERA_ALT_QSPI_H__ */ + diff --git a/c/src/lib/libbsp/arm/altera-cyclone-v/hwlib/include/socal/alt_qspidata.h b/c/src/lib/libbsp/arm/altera-cyclone-v/hwlib/include/socal/alt_qspidata.h new file mode 100644 index 0000000000..19383eefe5 --- /dev/null +++ b/c/src/lib/libbsp/arm/altera-cyclone-v/hwlib/include/socal/alt_qspidata.h @@ -0,0 +1,52 @@ +/******************************************************************************* +* * +* Copyright 2013 Altera Corporation. All Rights Reserved. * +* * +* Redistribution and use in source and binary forms, with or without * +* modification, are permitted provided that the following conditions are met: * +* * +* 1. Redistributions of source code must retain the above copyright notice, * +* this list of conditions and the following disclaimer. * +* * +* 2. Redistributions in binary form must reproduce the above copyright notice, * +* this list of conditions and the following disclaimer in the documentation * +* and/or other materials provided with the distribution. * +* * +* 3. The name of the author may not be used to endorse or promote products * +* derived from this software without specific prior written permission. * +* * +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER "AS IS" AND ANY EXPRESS OR * +* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * +* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED. IN NO * +* EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * +* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * +* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; * +* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * +* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR * +* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * +* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * +* * +*******************************************************************************/ + +/* Altera - ALT_QSPIDATA */ + +#ifndef __ALTERA_ALT_QSPIDATA_H__ +#define __ALTERA_ALT_QSPIDATA_H__ + +#ifdef __cplusplus +extern "C" +{ +#endif /* __cplusplus */ + +/* + * Component : QSPI Flash Module Data (AHB Slave) - ALT_QSPIDATA + * QSPI Flash Module Data (AHB Slave) + * + * + */ + +#ifdef __cplusplus +} +#endif /* __cplusplus */ +#endif /* __ALTERA_ALT_QSPIDATA_H__ */ + diff --git a/c/src/lib/libbsp/arm/altera-cyclone-v/hwlib/src/hwmgr/alt_16550_uart.c b/c/src/lib/libbsp/arm/altera-cyclone-v/hwlib/src/hwmgr/alt_16550_uart.c new file mode 100644 index 0000000000..a5dfc5f22c --- /dev/null +++ b/c/src/lib/libbsp/arm/altera-cyclone-v/hwlib/src/hwmgr/alt_16550_uart.c @@ -0,0 +1,1179 @@ +/****************************************************************************** + * + * Copyright 2013 Altera Corporation. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED. IN NO + * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + ******************************************************************************/ + +#include "alt_16550_uart.h" +#include "alt_clock_manager.h" +#include "socal/alt_rstmgr.h" +#include "socal/alt_uart.h" +#include "socal/hps.h" +#include "socal/socal.h" + +///// + +#define ALT_16550_HANDLE_DATA_UART_ENABLED_MSK (1UL << 31) +#define ALT_16550_HANDLE_DATA_DIVISOR_VALUE_GET(value) (value & 0xffff) + +#define ALT_ALTERA_16550_CPR_OFST (0xF4) +#define ALT_ALTERA_16550_CPR_ADDR(base) ALT_CAST(void *, (ALT_CAST(char *, (base)) + ALT_ALTERA_16550_CPR_OFST)) +#define ALT_ALTERA_16550_CPR_FIFO_MODE_GET(value) (((value) >> 16) & 0xff) +#define ALT_ALTERA_16550_CPR_AFCE_MODE_SET_MSK (1 << 4) + +///// + +// Remove these macros as part of case:123835. +#define ALT_UART_IER_DLH_VALUE_SET(value) ((value) & 0xff) +#define ALT_UART_IER_DLH_ETBEI_DLH1_SET_MSK ALT_UART_IER_DLH_ETBEI_DLHL_SET_MSK + +///// + +// +// Helper function which resets the UART and if requested, initializes the UART +// to the default settings. Currently the default settings are: +// - 8 databits +// - no parity +// - 1 stopbit +// - 57600 baudrate +// The reset routines depends on the hardware implementation of the UART. +// + +// This helper is needed because the regular alt_read_word(src) essentially +// resolves to "*(volatile uint32_t *)src". As there is no assignment, this +// could potentially be optimized away. With the helper, the actual register +// read should occur and be returned (and subsequently discarded). +static inline uint32_t alt_read_word_helper(const void * addr) +{ + return alt_read_word(addr); +} + +// +// Helper function write the divisor in hardware. +// +static ALT_STATUS_CODE alt_16550_write_divisor_helper(ALT_16550_HANDLE_t * handle, + uint32_t divisor) +{ + // Validate the divisor parameter. + if (divisor > 0xffff) + { + // This should never happen as it is verified in divisor_set. + return ALT_E_ERROR; + } + + switch (handle->device) + { + case ALT_16550_DEVICE_SOCFPGA_UART0: + case ALT_16550_DEVICE_SOCFPGA_UART1: + case ALT_16550_DEVICE_ALTERA_16550_UART: + // Set LCR::DLAB (Line Control Register :: Divisor Latch Access Bit) + alt_setbits_word(ALT_UART_LCR_ADDR(handle->location), ALT_UART_LCR_DLAB_SET_MSK); + + // Write DLL (Divisor Latch Low). + alt_write_word(ALT_UART_RBR_THR_DLL_ADDR(handle->location), ALT_UART_RBR_THR_DLL_VALUE_SET(divisor)); + + // Write DLH (Divisor Latch High). + alt_write_word(ALT_UART_IER_DLH_ADDR(handle->location), ALT_UART_IER_DLH_VALUE_SET(divisor >> 8)); + + // Clear LCR::DLAB (Line Control Register :: Divisor Latch Access Bit) + alt_clrbits_word(ALT_UART_LCR_ADDR(handle->location), ALT_UART_LCR_DLAB_SET_MSK); + + break; + + default: + return ALT_E_ERROR; + } + + // Update the enabled state in the handle data. + if (divisor != 0) + { + handle->data |= ALT_16550_HANDLE_DATA_UART_ENABLED_MSK; + } + else + { + handle->data &= ~ALT_16550_HANDLE_DATA_UART_ENABLED_MSK; + } + + return ALT_E_SUCCESS; +} + +// +// Helper function to reset the UART. +// +static ALT_STATUS_CODE alt_16550_reset_helper(ALT_16550_HANDLE_t * handle, bool enable_init) +{ + switch (handle->device) + { + case ALT_16550_DEVICE_SOCFPGA_UART0: + case ALT_16550_DEVICE_SOCFPGA_UART1: + // Write SRR::UR (Shadow Reset Register :: UART Reset) + alt_write_word(ALT_UART_SRR_ADDR(handle->location), ALT_UART_SRR_UR_SET_MSK); + + // Read the MSR to work around case:119085. + alt_read_word_helper(ALT_UART_MSR_ADDR(handle->location)); + break; + + case ALT_16550_DEVICE_ALTERA_16550_UART: + alt_16550_write_divisor_helper(handle, 0); // Disable UART + alt_16550_int_disable_all(handle); // Disable interrupts + alt_16550_fifo_disable(handle); // Disable FIFOs + alt_write_word(ALT_UART_MCR_ADDR(handle->location), 0); // 0 -> MCR (AFCE, LP, OUT2, OUT1, RTS, DTR) + break; + + default: + return ALT_E_ERROR; + } + + // If we are initializing (as opposed to just uninitializing) + if (enable_init) + { + ALT_STATUS_CODE status; + + // Set bit IER::PTIME (Interrupt Enable Register :: Programmable THRE Mode Enable) + alt_setbits_word(ALT_UART_IER_DLH_ADDR(handle->location), ALT_UART_IER_DLH_PTIME_DLH7_SET_MSK); + + // Set the line configuration to use 8-N-1. + status = alt_16550_line_config_set(handle, ALT_16550_DATABITS_8, + ALT_16550_PARITY_DISABLE, + ALT_16550_STOPBITS_1); + if (status != ALT_E_SUCCESS) + { + return status; + } + + uint32_t divisor = ALT_16550_HANDLE_DATA_DIVISOR_VALUE_GET(handle->data); + if (divisor == 0) + { + // Set the default baudrate to 57600. + status = alt_16550_baudrate_set(handle, ALT_16550_BAUDRATE_57600); + if (status != ALT_E_SUCCESS) + { + return status; + } + } + } + + return ALT_E_SUCCESS; +} + +ALT_STATUS_CODE alt_16550_init(ALT_16550_DEVICE_t device, + void * location, + alt_freq_t clock_freq, + ALT_16550_HANDLE_t * handle) +{ + handle->device = device; + handle->data = 0; + handle->fcr = 0; + + switch (device) + { + case ALT_16550_DEVICE_SOCFPGA_UART0: + case ALT_16550_DEVICE_SOCFPGA_UART1: + // The ALT_CLK_L4_SP is required for all SoCFPGA UARTs. Check that it's enabled. + if (alt_clk_is_enabled(ALT_CLK_L4_SP) != ALT_E_TRUE) + { + return ALT_E_BAD_CLK; + } + else + { + ALT_STATUS_CODE status; + status = alt_clk_freq_get(ALT_CLK_L4_SP, &handle->clock_freq); + if (status != ALT_E_SUCCESS) + { + return status; + } + + if (device == ALT_16550_DEVICE_SOCFPGA_UART0) + { + handle->location = ALT_UART0_ADDR; + + // Bring UART0 out of reset. + alt_clrbits_word(ALT_RSTMGR_PERMODRST_ADDR, ALT_RSTMGR_PERMODRST_UART0_SET_MSK); + } + else // device == ALT_16550_DEVICE_SOCFPGA_UART1 + { + handle->location = ALT_UART1_ADDR; + + // Bring UART1 out of reset. + alt_clrbits_word(ALT_RSTMGR_PERMODRST_ADDR, ALT_RSTMGR_PERMODRST_UART1_SET_MSK); + } + + // Verify the UCR (UART Component Version) + uint32_t ucr = alt_read_word(ALT_UART_UCV_ADDR(handle->location)); + if (ucr != ALT_UART_UCV_UART_COMPONENT_VER_RESET) + { + return ALT_E_ERROR; + } + } + break; + case ALT_16550_DEVICE_ALTERA_16550_UART: + handle->location = location; + handle->clock_freq = clock_freq; + break; + default: + return ALT_E_BAD_ARG; + } + + return alt_16550_reset_helper(handle, true); +} + +ALT_STATUS_CODE alt_16550_uninit(ALT_16550_HANDLE_t * handle) +{ + switch (handle->device) + { + case ALT_16550_DEVICE_SOCFPGA_UART0: + alt_setbits_word(ALT_RSTMGR_PERMODRST_ADDR, ALT_RSTMGR_PERMODRST_UART0_SET_MSK); + return ALT_E_SUCCESS; + case ALT_16550_DEVICE_SOCFPGA_UART1: + alt_setbits_word(ALT_RSTMGR_PERMODRST_ADDR, ALT_RSTMGR_PERMODRST_UART1_SET_MSK); + return ALT_E_SUCCESS; + case ALT_16550_DEVICE_ALTERA_16550_UART: + default: + return alt_16550_reset_helper(handle, false); + } +} + +ALT_STATUS_CODE alt_16550_reset(ALT_16550_HANDLE_t * handle) +{ + return alt_16550_reset_helper(handle, true); +} + +ALT_STATUS_CODE alt_16550_enable(ALT_16550_HANDLE_t * handle) +{ + // Write the divisor cached in the handle data to the divisor registers. + // This will effectively enable the UART. + return alt_16550_write_divisor_helper(handle, + ALT_16550_HANDLE_DATA_DIVISOR_VALUE_GET(handle->data)); +} + +ALT_STATUS_CODE alt_16550_disable(ALT_16550_HANDLE_t * handle) +{ + // Write 0 to the divisor the divisor registers. This will effectively + // disable the UART. + return alt_16550_write_divisor_helper(handle, 0); +} + +ALT_STATUS_CODE alt_16550_read(ALT_16550_HANDLE_t * handle, + char * item) +{ + // Verify that the UART is enabled + if (!(handle->data & ALT_16550_HANDLE_DATA_UART_ENABLED_MSK)) + { + return ALT_E_ERROR; + } + + // Verify that the FIFO is disabled + if (handle->fcr & ALT_UART_FCR_FIFOE_SET_MSK) + { + return ALT_E_ERROR; + } + + switch (handle->device) + { + case ALT_16550_DEVICE_SOCFPGA_UART0: + case ALT_16550_DEVICE_SOCFPGA_UART1: + case ALT_16550_DEVICE_ALTERA_16550_UART: + // Read the RBR (Receive Buffer Register) into *item. + *item = ALT_UART_RBR_THR_DLL_VALUE_GET(alt_read_word(ALT_UART_RBR_THR_DLL_ADDR(handle->location))); + break; + default: + return ALT_E_ERROR; + } + return ALT_E_SUCCESS; +} + +ALT_STATUS_CODE alt_16550_write(ALT_16550_HANDLE_t * handle, + char item) +{ + // Verify that the UART is enabled + if (!(handle->data & ALT_16550_HANDLE_DATA_UART_ENABLED_MSK)) + { + return ALT_E_ERROR; + } + + // Verify that the FIFO is disabled + if (handle->fcr & ALT_UART_FCR_FIFOE_SET_MSK) + { + return ALT_E_ERROR; + } + + switch (handle->device) + { + case ALT_16550_DEVICE_SOCFPGA_UART0: + case ALT_16550_DEVICE_SOCFPGA_UART1: + case ALT_16550_DEVICE_ALTERA_16550_UART: + // Write the buffer into the THR (Transmit Holding Register) + alt_write_word(ALT_UART_RBR_THR_DLL_ADDR(handle->location), item); + break; + default: + return ALT_E_ERROR; + } + + return ALT_E_SUCCESS; +} + +///// + +ALT_STATUS_CODE alt_16550_fifo_enable(ALT_16550_HANDLE_t * handle) +{ + switch (handle->device) + { + case ALT_16550_DEVICE_SOCFPGA_UART0: + case ALT_16550_DEVICE_SOCFPGA_UART1: + case ALT_16550_DEVICE_ALTERA_16550_UART: + // Set FCR::FIFOE (FIFO Control Register :: FIFO Enable) bit. + handle->fcr |= ALT_UART_FCR_FIFOE_SET_MSK; + alt_write_word(ALT_UART_FCR_ADDR(handle->location), handle->fcr); + break; + default: + return ALT_E_ERROR; + } + + // No need to reset / clear the FIFOs. This is done automatically when + // FCR::FIFOE is changed. + return ALT_E_SUCCESS; +} + +ALT_STATUS_CODE alt_16550_fifo_disable(ALT_16550_HANDLE_t * handle) +{ + switch (handle->device) + { + case ALT_16550_DEVICE_SOCFPGA_UART0: + case ALT_16550_DEVICE_SOCFPGA_UART1: + case ALT_16550_DEVICE_ALTERA_16550_UART: + // Clear FCR::FIFOE (FIFO Control Register :: FIFO Enable) bit. + handle->fcr &= ~ALT_UART_FCR_FIFOE_SET_MSK; + alt_write_word(ALT_UART_FCR_ADDR(handle->location), handle->fcr); + break; + default: + return ALT_E_ERROR; + } + + return ALT_E_SUCCESS; +} + +ALT_STATUS_CODE alt_16550_fifo_read(ALT_16550_HANDLE_t * handle, + char * buffer, + size_t count) +{ + // Verify that the UART is enabled + if (!(handle->data & ALT_16550_HANDLE_DATA_UART_ENABLED_MSK)) + { + return ALT_E_ERROR; + } + + // Verify that the FIFO is enabled + if (!(handle->fcr & ALT_UART_FCR_FIFOE_SET_MSK)) + { + return ALT_E_ERROR; + } + + switch (handle->device) + { + case ALT_16550_DEVICE_SOCFPGA_UART0: + case ALT_16550_DEVICE_SOCFPGA_UART1: + case ALT_16550_DEVICE_ALTERA_16550_UART: + // Read the RBR (Receive Buffer Register) into the buffer + for (size_t i = 0; i < count; ++i) + { + buffer[i] = ALT_UART_RBR_THR_DLL_VALUE_GET(alt_read_word(ALT_UART_RBR_THR_DLL_ADDR(handle->location))); + } + break; + default: + return ALT_E_ERROR; + } + + return ALT_E_SUCCESS; +} + +ALT_STATUS_CODE alt_16550_fifo_write(ALT_16550_HANDLE_t * handle, + const char * buffer, + size_t count) +{ + // Verify that the UART is enabled + if (!(handle->data & ALT_16550_HANDLE_DATA_UART_ENABLED_MSK)) + { + return ALT_E_ERROR; + } + + // Verify that the FIFO is enabled + if (!(handle->fcr & ALT_UART_FCR_FIFOE_SET_MSK)) + { + return ALT_E_ERROR; + } + + switch (handle->device) + { + case ALT_16550_DEVICE_SOCFPGA_UART0: + case ALT_16550_DEVICE_SOCFPGA_UART1: + case ALT_16550_DEVICE_ALTERA_16550_UART: + // Write the buffer into the THR (Transmit Holding Register) + for (size_t i = 0; i < count; ++i) + { + alt_write_word(ALT_UART_RBR_THR_DLL_ADDR(handle->location), buffer[i]); + } + break; + default: + return ALT_E_ERROR; + } + + return ALT_E_SUCCESS; +} + +ALT_STATUS_CODE alt_16550_fifo_clear_rx(ALT_16550_HANDLE_t * handle) +{ + // Verify that the FIFO is enabled + if (!(handle->fcr & ALT_UART_FCR_FIFOE_SET_MSK)) + { + return ALT_E_ERROR; + } + + switch (handle->device) + { + case ALT_16550_DEVICE_SOCFPGA_UART0: + case ALT_16550_DEVICE_SOCFPGA_UART1: + // Write SRR::RFR (Shadow Reset Register :: Receiver FIFO Reset) bit. + alt_write_word(ALT_UART_SRR_ADDR(handle->location), ALT_UART_SRR_RFR_SET_MSK); + break; + case ALT_16550_DEVICE_ALTERA_16550_UART: + // Write FCR::RFIFOR (FIFO Control Register :: Receiver FIFO Reset) bit. + alt_write_word(ALT_UART_FCR_ADDR(handle->location), handle->fcr | ALT_UART_FCR_RFIFOR_SET_MSK); + break; + default: + return ALT_E_ERROR; + } + + return ALT_E_SUCCESS; +} + +ALT_STATUS_CODE alt_16550_fifo_clear_tx(ALT_16550_HANDLE_t * handle) +{ + // Verify that the FIFO is enabled + if (!(handle->fcr & ALT_UART_FCR_FIFOE_SET_MSK)) + { + return ALT_E_ERROR; + } + + switch (handle->device) + { + case ALT_16550_DEVICE_SOCFPGA_UART0: + case ALT_16550_DEVICE_SOCFPGA_UART1: + // Write SRR::XFR (Shadow Reset Register :: Xmitter FIFO Reset) bit. + alt_write_word(ALT_UART_SRR_ADDR(handle->location), ALT_UART_SRR_XFR_SET_MSK); + break; + case ALT_16550_DEVICE_ALTERA_16550_UART: + // Write FCR::XFIFOR (FIFO Control Register :: Xmitter FIFO Reset) bit. + alt_write_word(ALT_UART_FCR_ADDR(handle->location), handle->fcr | ALT_UART_FCR_XFIFOR_SET_MSK); + break; + default: + return ALT_E_ERROR; + } + + return ALT_E_SUCCESS; +} + +ALT_STATUS_CODE alt_16550_fifo_clear_all(ALT_16550_HANDLE_t * handle) +{ + // Verify that the FIFO is enabled + if (!(handle->fcr & ALT_UART_FCR_FIFOE_SET_MSK)) + { + return ALT_E_ERROR; + } + + switch (handle->device) + { + case ALT_16550_DEVICE_SOCFPGA_UART0: + case ALT_16550_DEVICE_SOCFPGA_UART1: + // Write SRR::(RFR | XFR) + // (Shadow Reset Register :: (Receiver FIFO Reset | Xmitter FIFO Reset)) bits. + alt_write_word(ALT_UART_SRR_ADDR(handle->location), + ALT_UART_SRR_RFR_SET_MSK | ALT_UART_SRR_XFR_SET_MSK); + break; + case ALT_16550_DEVICE_ALTERA_16550_UART: + // Write FCR::(RFIFOR |XFIFOR) + // (FIFO Control Register :: (Receiver FIFO Reset | Xmitter FIFO Reset)) bits. + alt_write_word(ALT_UART_FCR_ADDR(handle->location), + handle->fcr | ALT_UART_FCR_RFIFOR_SET_MSK | ALT_UART_FCR_XFIFOR_SET_MSK); + break; + default: + return ALT_E_ERROR; + } + + return ALT_E_SUCCESS; +} + +ALT_STATUS_CODE alt_16550_fifo_size_get_rx(ALT_16550_HANDLE_t * handle, + uint32_t * size) +{ + switch (handle->device) + { + case ALT_16550_DEVICE_SOCFPGA_UART0: + case ALT_16550_DEVICE_SOCFPGA_UART1: + // Read the CPR::FIFO_Mod (Component Parameter Register :: FIFO Mode). + // The FIFO size is 16x this value. + *size = ALT_UART_CPR_FIFO_MOD_GET(alt_read_word(ALT_UART_CPR_ADDR(handle->location))) << 4; + break; + case ALT_16550_DEVICE_ALTERA_16550_UART: + // Altera 16550 Compatible Soft UARTs have a configurable size and is + // stored in the CPR::FIFO_Mode (Component Parameter Register :: FIFO Depth). + *size = ALT_ALTERA_16550_CPR_FIFO_MODE_GET(alt_read_word(ALT_ALTERA_16550_CPR_ADDR(handle->location))) << 4; + break; + default: + return ALT_E_ERROR; + } + + return ALT_E_SUCCESS; +} + +ALT_STATUS_CODE alt_16550_fifo_size_get_tx(ALT_16550_HANDLE_t * handle, + uint32_t * size) +{ + switch (handle->device) + { + case ALT_16550_DEVICE_SOCFPGA_UART0: + case ALT_16550_DEVICE_SOCFPGA_UART1: + // Read the CPR::FIFO_Mod (Component Parameter Register :: FIFO Mode). + // The FIFO size is 16x this value. + *size = ALT_UART_CPR_FIFO_MOD_GET(alt_read_word(ALT_UART_CPR_ADDR(handle->location))) << 4; + break; + case ALT_16550_DEVICE_ALTERA_16550_UART: + // Altera 16550 Compatible Soft UARTs have a configurable size and is + // stored in the CPR::FIFO_Mode (Component Parameter Register :: FIFO Depth). + // The FIFO size is 16x this value. + *size = ALT_ALTERA_16550_CPR_FIFO_MODE_GET(alt_read_word(ALT_ALTERA_16550_CPR_ADDR(handle->location))) << 4; + break; + default: + return ALT_E_ERROR; + } + + return ALT_E_SUCCESS; +} + +ALT_STATUS_CODE alt_16550_fifo_level_get_rx(ALT_16550_HANDLE_t * handle, + uint32_t * level) +{ + // Verify that the FIFO is enabled + if (!(handle->fcr & ALT_UART_FCR_FIFOE_SET_MSK)) + { + return ALT_E_ERROR; + } + + switch (handle->device) + { + case ALT_16550_DEVICE_SOCFPGA_UART0: + case ALT_16550_DEVICE_SOCFPGA_UART1: + // Read RFL (Receive FIFO Level). + *level = alt_read_word(ALT_UART_RFL_ADDR(handle->location)); + break; + case ALT_16550_DEVICE_ALTERA_16550_UART: + // RFL not implemented. Return 0. + *level = 0; + break; + default: + return ALT_E_ERROR; + } + + return ALT_E_SUCCESS; +} + +ALT_STATUS_CODE alt_16550_fifo_level_get_tx(ALT_16550_HANDLE_t * handle, + uint32_t * level) +{ + // Verify that the FIFO is enabled + if (!(handle->fcr & ALT_UART_FCR_FIFOE_SET_MSK)) + { + return ALT_E_ERROR; + } + + switch (handle->device) + { + case ALT_16550_DEVICE_SOCFPGA_UART0: + case ALT_16550_DEVICE_SOCFPGA_UART1: + // Read TFL (Transmit FIFO Level). + *level = alt_read_word(ALT_UART_TFL_ADDR(handle->location)); + break; + case ALT_16550_DEVICE_ALTERA_16550_UART: + // TFL not implemented. Return 0. + *level = 0; + break; + default: + return ALT_E_ERROR; + } + + return ALT_E_SUCCESS; +} + +ALT_STATUS_CODE alt_16550_fifo_trigger_set_rx(ALT_16550_HANDLE_t * handle, + ALT_16550_FIFO_TRIGGER_RX_t trigger) +{ + // Verify that the FIFO is enabled + if (!(handle->fcr & ALT_UART_FCR_FIFOE_SET_MSK)) + { + return ALT_E_ERROR; + } + + // Verify triggering parameter + switch (trigger) + { + case ALT_16550_FIFO_TRIGGER_RX_ANY: + case ALT_16550_FIFO_TRIGGER_RX_QUARTER_FULL: + case ALT_16550_FIFO_TRIGGER_RX_HALF_FULL: + case ALT_16550_FIFO_TRIGGER_RX_ALMOST_FULL: + break; + default: + return ALT_E_BAD_ARG; + } + + switch (handle->device) + { + case ALT_16550_DEVICE_SOCFPGA_UART0: + case ALT_16550_DEVICE_SOCFPGA_UART1: + case ALT_16550_DEVICE_ALTERA_16550_UART: + // Update FCR::RT (FIFO Control Register :: Receiver Trigger) + handle->fcr &= ~ALT_UART_FCR_RT_SET_MSK; + handle->fcr |= ALT_UART_FCR_RT_SET(trigger); + alt_write_word(ALT_UART_FCR_ADDR(handle->location), handle->fcr); + break; + default: + return ALT_E_ERROR; + } + + return ALT_E_SUCCESS; +} + +ALT_STATUS_CODE alt_16550_fifo_trigger_set_tx(ALT_16550_HANDLE_t * handle, + ALT_16550_FIFO_TRIGGER_TX_t trigger) +{ + // Verify that the FIFO is enabled + if (!(handle->fcr & ALT_UART_FCR_FIFOE_SET_MSK)) + { + return ALT_E_ERROR; + } + + // Verify triggering parameter + switch (trigger) + { + case ALT_16550_FIFO_TRIGGER_TX_EMPTY: + case ALT_16550_FIFO_TRIGGER_TX_ALMOST_EMPTY: + case ALT_16550_FIFO_TRIGGER_TX_QUARTER_FULL: + case ALT_16550_FIFO_TRIGGER_TX_HALF_FULL: + break; + default: + return ALT_E_BAD_ARG; + } + + switch (handle->device) + { + case ALT_16550_DEVICE_SOCFPGA_UART0: + case ALT_16550_DEVICE_SOCFPGA_UART1: + case ALT_16550_DEVICE_ALTERA_16550_UART: + // Update FCR::TET (FIFO Control Register :: Transmit Empty Trigger) + handle->fcr &= ~ALT_UART_FCR_TET_SET_MSK; + handle->fcr |= ALT_UART_FCR_TET_SET(trigger); + alt_write_word(ALT_UART_FCR_ADDR(handle->location), handle->fcr); + break; + default: + return ALT_E_ERROR; + } + + return ALT_E_SUCCESS; +} + +///// + +ALT_STATUS_CODE alt_16550_baudrate_get(ALT_16550_HANDLE_t * handle, + uint32_t * baudrate) +{ + // Query the divisor cached in the handle data + uint32_t divisor = ALT_16550_HANDLE_DATA_DIVISOR_VALUE_GET(handle->data); + + // The divisor should never be zero. It is set to allow for a baud of 57600 + // on initialization and a valid value is checked at + // alt_16550_divisor_set(). We do not check for users altering the data in + // the handle structure. + + // Formula for calculating the baudrate: + // baudrate = clock / (16 * divisor) + + *baudrate = (handle->clock_freq >> 4) / divisor; + + return ALT_E_SUCCESS; +} + +ALT_STATUS_CODE alt_16550_baudrate_set(ALT_16550_HANDLE_t * handle, + uint32_t baudrate) +{ + if (baudrate == 0) + { + return ALT_E_ARG_RANGE; + } + + // Formula for calculating the divisor: + // baudrate = clock / (16 * divisor) + // => baudrate * 16 * divisor = clock + // => divisor = clock / (baudrate * 16) + // => divisor = (clock / 16) / baudrate + + // Add half of the denominator to address rounding errors. + uint32_t divisor = ((handle->clock_freq + (8 * baudrate)) / (16 * baudrate)); + + // Check for divisor range is in alt_16550_divisor_set(). + return alt_16550_divisor_set(handle, divisor); +} + +ALT_STATUS_CODE alt_16550_divisor_get(ALT_16550_HANDLE_t * handle, + uint32_t * divisor) +{ + // Just read the divisor portion of the handle data. + *divisor = ALT_16550_HANDLE_DATA_DIVISOR_VALUE_GET(handle->data); + + return ALT_E_SUCCESS; +} + +ALT_STATUS_CODE alt_16550_divisor_set(ALT_16550_HANDLE_t * handle, + uint32_t divisor) +{ + // Verify divisor value is in range. + if ((divisor > 0xffff) || (divisor == 0)) + { + return ALT_E_ARG_RANGE; + } + + // Set the divisor portion of the handle data. + handle->data &= ~(0xffff); + handle->data |= divisor; + + // Even if the UART is enabled, don't do anything. It is documented that + // the change will take effect when the UART move to the enabled state. + + return ALT_E_SUCCESS; +} + +///// + +static ALT_STATUS_CODE alt_16550_ier_mask_set_helper(ALT_16550_HANDLE_t * handle, uint32_t setmask) +{ + switch (handle->device) + { + case ALT_16550_DEVICE_SOCFPGA_UART0: + case ALT_16550_DEVICE_SOCFPGA_UART1: + case ALT_16550_DEVICE_ALTERA_16550_UART: + // Set bit in IER (Interrupt Enable Register) + alt_setbits_word(ALT_UART_IER_DLH_ADDR(handle->location), setmask); + break; + default: + return ALT_E_ERROR; + } + + return ALT_E_SUCCESS; +} + +static ALT_STATUS_CODE alt_16550_ier_mask_clr_helper(ALT_16550_HANDLE_t * handle, uint32_t setmask) +{ + switch (handle->device) + { + case ALT_16550_DEVICE_SOCFPGA_UART0: + case ALT_16550_DEVICE_SOCFPGA_UART1: + case ALT_16550_DEVICE_ALTERA_16550_UART: + // Clear bit in IER (Interrupt Enable Register) + alt_clrbits_word(ALT_UART_IER_DLH_ADDR(handle->location), setmask); + break; + default: + return ALT_E_ERROR; + } + + return ALT_E_SUCCESS; +} + +ALT_STATUS_CODE alt_16550_int_enable_rx(ALT_16550_HANDLE_t * handle) +{ + // Set the IER::ERBFI (Interrupt Enable Register :: Enable Receive Buffer Full Interrupt) bit. + return alt_16550_ier_mask_set_helper(handle, ALT_UART_IER_DLH_ERBFI_DLH0_SET_MSK); +} + +ALT_STATUS_CODE alt_16550_int_disable_rx(ALT_16550_HANDLE_t * handle) +{ + // Clear the IER::ERBFI (Interrupt Enable Register :: Enable Receive Buffer Full Interrupt) bit. + return alt_16550_ier_mask_clr_helper(handle, ALT_UART_IER_DLH_ERBFI_DLH0_SET_MSK); +} + +ALT_STATUS_CODE alt_16550_int_enable_tx(ALT_16550_HANDLE_t * handle) +{ + // Set the IER::ETBEI (Interrupt Enable Register :: Enable Transmit Buffer Empty Interrupt) bit. + return alt_16550_ier_mask_set_helper(handle, ALT_UART_IER_DLH_ETBEI_DLH1_SET_MSK); +} + +ALT_STATUS_CODE alt_16550_int_disable_tx(ALT_16550_HANDLE_t * handle) +{ + // Clear the IER::ETBEI (Interrupt Enable Register :: Enable Transmit Buffer Empty Interrupt) bit. + return alt_16550_ier_mask_clr_helper(handle, ALT_UART_IER_DLH_ETBEI_DLH1_SET_MSK); +} + +ALT_STATUS_CODE alt_16550_int_enable_line(ALT_16550_HANDLE_t * handle) +{ + // Set the IER::ELSI (Interrupt Enable Register :: Enable Line Status Interrupt) bit. + return alt_16550_ier_mask_set_helper(handle, ALT_UART_IER_DLH_ELSI_DHL2_SET_MSK); +} + +ALT_STATUS_CODE alt_16550_int_disable_line(ALT_16550_HANDLE_t * handle) +{ + // Clear the IER::ELSI (Interrupt Enable Register :: Enable Line Status Interrupt) bit. + return alt_16550_ier_mask_clr_helper(handle, ALT_UART_IER_DLH_ELSI_DHL2_SET_MSK); +} + +ALT_STATUS_CODE alt_16550_int_enable_modem(ALT_16550_HANDLE_t * handle) +{ + // Set the IER::EDSSI (Interrupt Enable Register :: Enable Modem Status Interrupt) bit. + return alt_16550_ier_mask_set_helper(handle, ALT_UART_IER_DLH_EDSSI_DHL3_SET_MSK); +} + +ALT_STATUS_CODE alt_16550_int_disable_modem(ALT_16550_HANDLE_t * handle) +{ + // Clear the IER::EDSSI (Interrupt Enable Register :: Enable Modem Status Interrupt) bit. + return alt_16550_ier_mask_clr_helper(handle, ALT_UART_IER_DLH_EDSSI_DHL3_SET_MSK); +} + +ALT_STATUS_CODE alt_16550_int_disable_all(ALT_16550_HANDLE_t * handle) +{ + // Clear the IER::(ERBFI | ETBEI | ELSI | EDSSI) + // (Interrupt Enable Register :: (Enable Receive Buffer Full Interrupt | + // Enable Transmit Buffer Empty Interrupt | + // Enable Line Status Interrupt | + // Enable Modem Status Interrupt)) bits + return alt_16550_ier_mask_clr_helper(handle, ALT_UART_IER_DLH_ERBFI_DLH0_SET_MSK | + ALT_UART_IER_DLH_ETBEI_DLH1_SET_MSK | + ALT_UART_IER_DLH_ELSI_DHL2_SET_MSK | + ALT_UART_IER_DLH_EDSSI_DHL3_SET_MSK); +} + +ALT_STATUS_CODE alt_16550_int_status_get(ALT_16550_HANDLE_t * handle, + ALT_16550_INT_STATUS_t * status) +{ + switch (handle->device) + { + case ALT_16550_DEVICE_SOCFPGA_UART0: + case ALT_16550_DEVICE_SOCFPGA_UART1: + case ALT_16550_DEVICE_ALTERA_16550_UART: + // Read IIR::IID (Interrupt Identity Register :: Interrupt ID) + *status = (ALT_16550_INT_STATUS_t) ALT_UART_IIR_ID_GET(alt_read_word(ALT_UART_IIR_ADDR(handle->location))); + break; + default: + return ALT_E_ERROR; + } + + return ALT_E_SUCCESS; +} + +///// + +ALT_STATUS_CODE alt_16550_line_config_set(ALT_16550_HANDLE_t * handle, + ALT_16550_DATABITS_t databits, + ALT_16550_PARITY_t parity, + ALT_16550_STOPBITS_t stopbits) +{ + // Validate the databits parameter. + switch (databits) + { + case ALT_16550_DATABITS_5: + case ALT_16550_DATABITS_6: + case ALT_16550_DATABITS_7: + case ALT_16550_DATABITS_8: + break; + default: + return ALT_E_ERROR; + } + + // Validate the parity parameter. + switch (parity) + { + case ALT_16550_PARITY_DISABLE: + case ALT_16550_PARITY_ODD: + case ALT_16550_PARITY_EVEN: + break; + default: + return ALT_E_ERROR; + } + + // Validate the stopbits parameter. + switch (stopbits) + { + case ALT_16550_STOPBITS_1: + case ALT_16550_STOPBITS_2: + break; + default: + return ALT_E_ERROR; + } + + // LCR (Line Control Register) cache. + uint32_t lcr = 0; + + switch (handle->device) + { + case ALT_16550_DEVICE_SOCFPGA_UART0: + case ALT_16550_DEVICE_SOCFPGA_UART1: + case ALT_16550_DEVICE_ALTERA_16550_UART: + + // Configure the number of databits + lcr |= ALT_UART_LCR_DLS_SET(databits); + + // Configure the number of stopbits + lcr |= ALT_UART_LCR_STOP_SET(stopbits); + + // Configure the parity + if (parity != ALT_16550_PARITY_DISABLE) + { + // Enable parity in LCR + lcr |= ALT_UART_LCR_PEN_SET_MSK; + + if (parity == ALT_16550_PARITY_EVEN) + { + // Enable even parity in LCR; otherwise it's odd parity. + lcr |= ALT_UART_LCR_EPS_SET_MSK; + } + } + + // Update LCR (Line Control Register) + alt_replbits_word(ALT_UART_LCR_ADDR(handle->location), + ALT_UART_LCR_DLS_SET_MSK + | ALT_UART_LCR_STOP_SET_MSK + | ALT_UART_LCR_PEN_SET_MSK + | ALT_UART_LCR_EPS_SET_MSK, + lcr); + + break; + + default: + return ALT_E_ERROR; + } + + return ALT_E_SUCCESS; +} + +ALT_STATUS_CODE alt_16550_line_break_enable(ALT_16550_HANDLE_t * handle) +{ + switch (handle->device) + { + case ALT_16550_DEVICE_SOCFPGA_UART0: + case ALT_16550_DEVICE_SOCFPGA_UART1: + case ALT_16550_DEVICE_ALTERA_16550_UART: + // Set the LCR::Break (Line Control Register :: Break) bit. + alt_setbits_word(ALT_UART_LCR_ADDR(handle->location), ALT_UART_LCR_BREAK_SET_MSK); + break; + + default: + return ALT_E_ERROR; + } + + return ALT_E_SUCCESS; +} + +ALT_STATUS_CODE alt_16550_line_break_disable(ALT_16550_HANDLE_t * handle) +{ + switch (handle->device) + { + case ALT_16550_DEVICE_SOCFPGA_UART0: + case ALT_16550_DEVICE_SOCFPGA_UART1: + case ALT_16550_DEVICE_ALTERA_16550_UART: + // Clear the LCR::Break (Line Control Register :: Break) bit. + alt_clrbits_word(ALT_UART_LCR_ADDR(handle->location), ALT_UART_LCR_BREAK_SET_MSK); + break; + + default: + return ALT_E_ERROR; + } + + + return ALT_E_SUCCESS; +} + +ALT_STATUS_CODE alt_16550_line_status_get(ALT_16550_HANDLE_t * handle, + uint32_t * status) +{ + switch (handle->device) + { + case ALT_16550_DEVICE_SOCFPGA_UART0: + case ALT_16550_DEVICE_SOCFPGA_UART1: + case ALT_16550_DEVICE_ALTERA_16550_UART: + // Read the LSR (Line Status Register). + *status = alt_read_word(ALT_UART_LSR_ADDR(handle->location)); + break; + default: + return ALT_E_ERROR; + } + + return ALT_E_SUCCESS; +} + +///// + +static ALT_STATUS_CODE alt_16550_mcr_mask_set_helper(ALT_16550_HANDLE_t * handle, + uint32_t setmask) +{ + switch (handle->device) + { + case ALT_16550_DEVICE_SOCFPGA_UART0: + case ALT_16550_DEVICE_SOCFPGA_UART1: + case ALT_16550_DEVICE_ALTERA_16550_UART: + // Set the bit in MCR (Modem Control Register). + alt_setbits_word(ALT_UART_MCR_ADDR(handle->location), setmask); + break; + default: + return ALT_E_ERROR; + } + + return ALT_E_SUCCESS; +} + +static ALT_STATUS_CODE alt_16550_mcr_mask_clr_helper(ALT_16550_HANDLE_t * handle, uint32_t setmask) +{ + switch (handle->device) + { + case ALT_16550_DEVICE_SOCFPGA_UART0: + case ALT_16550_DEVICE_SOCFPGA_UART1: + case ALT_16550_DEVICE_ALTERA_16550_UART: + // Clear the bit in MCR (Modem Control Register). + alt_clrbits_word(ALT_UART_MCR_ADDR(handle->location), setmask); + break; + default: + return ALT_E_ERROR; + } + + return ALT_E_SUCCESS; +} + +ALT_STATUS_CODE alt_16550_flowcontrol_enable(ALT_16550_HANDLE_t * handle) +{ + // Verify that the FIFO is enabled + if (!(handle->fcr & ALT_UART_FCR_FIFOE_SET_MSK)) + { + return ALT_E_ERROR; + } + + // For the Altera 16550 Compatible Soft UART, check that Hardware Flowcontrol is enabled. + if (handle->device == ALT_16550_DEVICE_ALTERA_16550_UART) + { + // Read the CPR::AFCE_Mode (Component Parameter Register :: Auto Flow Control mode) bit. + uint32_t cpr = alt_read_word(ALT_ALTERA_16550_CPR_ADDR(handle->location)); + if (!(ALT_ALTERA_16550_CPR_AFCE_MODE_SET_MSK & cpr)) + { + return ALT_E_ERROR; + } + } + + // Set MCR::AFCE (Modem Control Register :: Automatic FlowControl Enable) bit. + return alt_16550_mcr_mask_set_helper(handle, ALT_UART_MCR_AFCE_SET_MSK); +} + +ALT_STATUS_CODE alt_16550_flowcontrol_disable(ALT_16550_HANDLE_t * handle) +{ + // Clear MCR::AFCE (Modem Control Register :: Automatic FlowControl Enable) bit. + return alt_16550_mcr_mask_clr_helper(handle, ALT_UART_MCR_AFCE_SET_MSK); +} + +ALT_STATUS_CODE alt_16550_loopback_enable(ALT_16550_HANDLE_t * handle) +{ + // Loopback is not implemented in the Altera 16550 Compatible Soft UART. + if (handle->device == ALT_16550_DEVICE_ALTERA_16550_UART) + { + return ALT_E_ERROR; + } + + // Set MCR::Loopback (Modem Control Register :: Loopback) bit. + return alt_16550_mcr_mask_set_helper(handle, ALT_UART_MCR_LOOPBACK_SET_MSK); +} + +ALT_STATUS_CODE alt_16550_loopback_disable(ALT_16550_HANDLE_t * handle) +{ + // Clear MCR::Loopback (Modem Control Register :: Loopback) bit. + return alt_16550_mcr_mask_clr_helper(handle, ALT_UART_MCR_LOOPBACK_SET_MSK); +} + +ALT_STATUS_CODE alt_16550_modem_enable_out1(ALT_16550_HANDLE_t * handle) +{ + // Set MCR::Out1 (Modem Control Register :: Out1) bit. + return alt_16550_mcr_mask_set_helper(handle, ALT_UART_MCR_OUT1_SET_MSK); +} + +ALT_STATUS_CODE alt_16550_modem_disable_out1(ALT_16550_HANDLE_t * handle) +{ + // Clear MCR::Out1 (Modem Control Register :: Out1) bit. + return alt_16550_mcr_mask_clr_helper(handle, ALT_UART_MCR_OUT1_SET_MSK); +} + +ALT_STATUS_CODE alt_16550_modem_enable_out2(ALT_16550_HANDLE_t * handle) +{ + // Set MCR::Out2 (Modem Control Register :: Out2) bit. + return alt_16550_mcr_mask_set_helper(handle, ALT_UART_MCR_OUT2_SET_MSK); +} + +ALT_STATUS_CODE alt_16550_modem_disable_out2(ALT_16550_HANDLE_t * handle) +{ + // Clear MCR::Out2 (Modem Control Register :: Out2) bit. + return alt_16550_mcr_mask_clr_helper(handle, ALT_UART_MCR_OUT2_SET_MSK); +} + +ALT_STATUS_CODE alt_16550_modem_enable_rts(ALT_16550_HANDLE_t * handle) +{ + // Set MCR::RTS (Modem Control Register :: Request To Send) bit. + return alt_16550_mcr_mask_set_helper(handle, ALT_UART_MCR_RTS_SET_MSK); +} + +ALT_STATUS_CODE alt_16550_modem_disable_rts(ALT_16550_HANDLE_t * handle) +{ + // Clear MCR::RTS (Modem Control Register :: Request To Send) bit. + return alt_16550_mcr_mask_clr_helper(handle, ALT_UART_MCR_RTS_SET_MSK); +} + +ALT_STATUS_CODE alt_16550_modem_enable_dtr(ALT_16550_HANDLE_t * handle) +{ + // Set MCR::DTR (Modem Control Register :: Data Terminal Ready) bit. + return alt_16550_mcr_mask_set_helper(handle, ALT_UART_MCR_DTR_SET_MSK); +} + +ALT_STATUS_CODE alt_16550_modem_disable_dtr(ALT_16550_HANDLE_t * handle) +{ + // Clear MCR::DTR (Modem Control Register :: Data Terminal Ready) bit. + return alt_16550_mcr_mask_clr_helper(handle, ALT_UART_MCR_DTR_SET_MSK); +} + +ALT_STATUS_CODE alt_16550_modem_status_get(ALT_16550_HANDLE_t * handle, + uint32_t * status) +{ + switch (handle->device) + { + case ALT_16550_DEVICE_SOCFPGA_UART0: + case ALT_16550_DEVICE_SOCFPGA_UART1: + case ALT_16550_DEVICE_ALTERA_16550_UART: + // Read the MSR (Modem Status Register). + *status = alt_read_word(ALT_UART_MSR_ADDR(handle->location)); + break; + default: + return ALT_E_ERROR; + } + + return ALT_E_SUCCESS; +} diff --git a/c/src/lib/libbsp/arm/altera-cyclone-v/hwlib/src/hwmgr/alt_dma.c b/c/src/lib/libbsp/arm/altera-cyclone-v/hwlib/src/hwmgr/alt_dma.c new file mode 100644 index 0000000000..2bdc519eee --- /dev/null +++ b/c/src/lib/libbsp/arm/altera-cyclone-v/hwlib/src/hwmgr/alt_dma.c @@ -0,0 +1,3749 @@ +/****************************************************************************** + * + * Copyright 2013 Altera Corporation. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED. IN NO + * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + ******************************************************************************/ + +#include +#include "alt_dma.h" +#include "socal/socal.h" +#include "socal/hps.h" +#include "socal/alt_rstmgr.h" +#include "socal/alt_sysmgr.h" + +#if ALT_DMA_PERIPH_PROVISION_16550_SUPPORT +#include "alt_16550_uart.h" +#include "socal/alt_uart.h" +#endif + +#if ALT_DMA_PERIPH_PROVISION_QSPI_SUPPORT +#include "socal/alt_qspi.h" +#endif + +///// + +#ifndef MIN +#define MIN(a, b) ((a) > (b) ? (b) : (a)) +#endif // MIN + +#ifndef ARRAY_COUNT +#define ARRAY_COUNT(array) (sizeof(array) / sizeof(array[0])) +#endif + +// NOTE: To enable debugging output, delete the next line and uncomment the +// line after. +#define dprintf(...) +// #define dprintf(fmt, ...) printf(fmt, ##__VA_ARGS__) + +///// + +// +// SoCAL stand in for DMA Controller registers +// +// The base can be one of the following: +// - ALT_DMANONSECURE_ADDR +// - ALT_DMASECURE_ADDR +// +// Macros which have a channel parameter does no validation. +// + +// DMA Manager Status Register +#define ALT_DMA_DSR_OFST 0x0 +#define ALT_DMA_DSR_ADDR(base) ALT_CAST(void *, (ALT_CAST(char *, (base)) + ALT_DMA_DSR_OFST)) +#define ALT_DMA_DSR_DMASTATUS_SET_MSK 0x0000000f +#define ALT_DMA_DSR_DMASTATUS_GET(value) ((value) & 0x0000000f) + +// DMA Program Counter Register +#define ALT_DMA_DPC_OFST 0x4 +#define ALT_DMA_DPC_ADDR(base) ALT_CAST(void *, (ALT_CAST(char *, (base)) + ALT_DMA_DPC_OFST)) + +// Interrupt Enable Register +#define ALT_DMA_INTEN_OFST 0x20 +#define ALT_DMA_INTEN_ADDR(base) ALT_CAST(void *, (ALT_CAST(char *, (base)) + ALT_DMA_INTEN_OFST)) + +// Event-Interrupt Raw Status Register +#define ALT_DMA_INT_EVENT_RIS_OFST 0x24 +#define ALT_DMA_INT_EVENT_RIS_ADDR(base) ALT_CAST(void *, (ALT_CAST(char *, (base)) + ALT_DMA_INT_EVENT_RIS_OFST)) + +// Interrupt Status Register +#define ALT_DMA_INTMIS_OFST 0x28 +#define ALT_DMA_INTMIS_ADDR(base) ALT_CAST(void *, (ALT_CAST(char *, (base)) + ALT_DMA_INTMIS_OFST)) + +// Interrupt Clear Register +#define ALT_DMA_INTCLR_OFST 0x2c +#define ALT_DMA_INTCLR_ADDR(base) ALT_CAST(void *, (ALT_CAST(char *, (base)) + ALT_DMA_INTCLR_OFST)) + +// Fault Status DMA Manager Register +#define ALT_DMA_FSRD_OFST 0x30 +#define ALT_DMA_FSRD_ADDR(base) ALT_CAST(void *, (ALT_CAST(char *, (base)) + ALT_DMA_FSRD_OFST)) + +// Fault Status DMA Channel Register +#define ALT_DMA_FSRC_OFST 0x34 +#define ALT_DMA_FSRC_ADDR(base) ALT_CAST(void *, (ALT_CAST(char *, (base)) + ALT_DMA_FSRC_OFST)) + +// Fault Type DMA Manager Register +#define ALT_DMA_FTRD_OFST 0x38 +#define ALT_DMA_FTRD_ADDR(base) ALT_CAST(void *, (ALT_CAST(char *, (base)) + ALT_DMA_FSRD_OFST)) + +// Fault Type DMA Channel Registers +#define ALT_DMA_FTRx_OFST(channel) (0x40 + 0x4 * (channel)) +#define ALT_DMA_FTRx_ADDR(base, channel) ALT_CAST(void *, (ALT_CAST(char *, (base)) + ALT_DMA_FTRx_OFST(channel))) + +// Channel Status Registers +#define ALT_DMA_CSRx_OFST(channel) (0x100 + 0x8 * (channel)) +#define ALT_DMA_CSRx_ADDR(base, channel) ALT_CAST(void *, (ALT_CAST(char *, (base)) + ALT_DMA_CSRx_OFST(channel))) +#define ALT_DMA_CSRx_CHANNELSTATUS_SET_MSK 0x0000000f +#define ALT_DMA_CSRx_CHANNELSTATUS_GET(value) ((value) & 0x0000000f) + +// Channel Program Counter Registers +#define ALT_DMA_CPCx_OFST(channel) (0x104 + 0x8 * (channel)) +#define ALT_DMA_CPCx_ADDR(base, channel) ALT_CAST(void *, (ALT_CAST(char *, (base)) + ALT_DMA_CPCx_OFST(channel))) + +// Source Address Registers +#define ALT_DMA_SARx_OFST(channel) (0x400 + 0x20 * (channel)) +#define ALT_DMA_SARx_ADDR(base, channel) ALT_CAST(void *, (ALT_CAST(char *, (base)) + ALT_DMA_SARx_OFST(channel))) + +// Destination Address Registers +#define ALT_DMA_DARx_OFST(channel) (0x404 + 0x20 * (channel)) +#define ALT_DMA_DARx_ADDR(base, channel) ALT_CAST(void *, (ALT_CAST(char *, (base)) + ALT_DMA_DARx_OFST(channel))) + +// Channel Control Registers +#define ALT_DMA_CCRx_OFST(channel) (0x408 + 0x20 * (channel)) +#define ALT_DMA_CCRx_ADDR(base, channel) ALT_CAST(void *, (ALT_CAST(char *, (base)) + ALT_DMA_CCRx_OFST(channel))) + +// Loop Counter 0 Registers +#define ALT_DMA_LC0_x_OFST(channel) (0x40c + 0x20 * (channel)) +#define ALT_DMA_LC0_x_ADDR(base, channel) ALT_CAST(void *, (ALT_CAST(char *, (base)) + ALT_DMA_LC0_x_OFST(channel))) + +// Loop Counter 1 Registers +#define ALT_DMA_LC1_x_OFST(channel) (0x410 + 0x20 * (channel)) +#define ALT_DMA_LC1_x_ADDR(base, channel) ALT_CAST(void *, (ALT_CAST(char *, (base)) + ALT_DMA_LC1_x_OFST(channel))) + +// Debug Status Register +#define ALT_DMA_DBGSTATUS_OFST 0xd00 +#define ALT_DMA_DBGSTATUS_ADDR(base) ALT_CAST(void *, (ALT_CAST(char *, (base)) + ALT_DMA_DBGSTATUS_OFST)) + +// Debug Command Register +#define ALT_DMA_DBGCMD_OFST 0xd04 +#define ALT_DMA_DBGCMD_ADDR(base) ALT_CAST(void *, (ALT_CAST(char *, (base)) + ALT_DMA_DBGCMD_OFST)) + +// Debug Instruction-0 Register +#define ALT_DMA_DBGINST0_OFST 0xd08 +#define ALT_DMA_DBGINST0_ADDR(base) ALT_CAST(void *, (ALT_CAST(char *, (base)) + ALT_DMA_DBGINST0_OFST)) +#define ALT_DMA_DBGINST0_CHANNELNUMBER_SET(value) (((value) & 0x7) << 8) +#define ALT_DMA_DBGINST0_DEBUGTHREAD_SET(value) ((value) & 0x1) +#define ALT_DMA_DBGINST0_DEBUGTHREAD_E_MANAGER 0 +#define ALT_DMA_DBGINST0_DEBUGTHREAD_E_CHANNEL 1 +#define ALT_DMA_DBGINST0_INSTRUCTIONBYTE0_SET(value) (((value) & 0xff) << 16) +#define ALT_DMA_DBGINST0_INSTRUCTIONBYTE1_SET(value) (((value) & 0xff) << 24) + +// Debug Instruction-1 Register +#define ALT_DMA_DBGINST1_OFST 0xd0c +#define ALT_DMA_DBGINST1_ADDR(base) ALT_CAST(void *, (ALT_CAST(char *, (base)) + ALT_DMA_DBGINST1_OFST)) + +// Configuration Registers 0 - 4 +#define ALT_DMA_CR0_OFST 0xe00 +#define ALT_DMA_CR1_OFST 0xe04 +#define ALT_DMA_CR2_OFST 0xe08 +#define ALT_DMA_CR3_OFST 0xe0c +#define ALT_DMA_CR4_OFST 0xe10 +#define ALT_DMA_CR0_ADDR(base) ALT_CAST(void *, (ALT_CAST(char *, (base)) + ALT_DMA_CR0_OFST)) +#define ALT_DMA_CR1_ADDR(base) ALT_CAST(void *, (ALT_CAST(char *, (base)) + ALT_DMA_CR1_OFST)) +#define ALT_DMA_CR2_ADDR(base) ALT_CAST(void *, (ALT_CAST(char *, (base)) + ALT_DMA_CR2_OFST)) +#define ALT_DMA_CR3_ADDR(base) ALT_CAST(void *, (ALT_CAST(char *, (base)) + ALT_DMA_CR3_OFST)) +#define ALT_DMA_CR4_ADDR(base) ALT_CAST(void *, (ALT_CAST(char *, (base)) + ALT_DMA_CR4_OFST)) + +// DMA Configuration Register +#define ALT_DMA_CRD_OFST 0xe14 +#define ALT_DMA_CRD_ADDR(base) ALT_CAST(void *, (ALT_CAST(char *, (base)) + ALT_DMA_CRD_OFST)) + +// Watchdog Register +#define ALT_DMA_WD_OFST 0xe80 +#define ALT_DMA_WD_ADDR(base) ALT_CAST(void *, (ALT_CAST(char *, (base)) + ALT_DMA_WD_OFST)) + +///// + +// +// Internal Data structures +// + +// This flag marks the channel as being allocated. +#define ALT_DMA_CHANNEL_INFO_FLAG_ALLOCED (1 << 0) + +typedef struct ALT_DMA_CHANNEL_INFO_s +{ + uint8_t flag; +} +ALT_DMA_CHANNEL_INFO_t; + +static ALT_DMA_CHANNEL_INFO_t channel_info_array[8]; + +///// + +ALT_STATUS_CODE alt_dma_init(const ALT_DMA_CFG_t * dma_cfg) +{ + // Initialize the channel information array + for (int i = 0; i < 8; ++i) + { + channel_info_array[i].flag = 0; + } + + // Update the System Manager DMA configuration items + + uint32_t dmactrl = 0; + + // Handle FPGA / CAN muxing + for (int i = 0; i < 4; ++i) + { + // The default is FPGA. + switch (dma_cfg->periph_mux[i]) + { + case ALT_DMA_PERIPH_MUX_DEFAULT: + case ALT_DMA_PERIPH_MUX_FPGA: + break; + case ALT_DMA_PERIPH_MUX_CAN: + dmactrl |= (ALT_SYSMGR_DMA_CTL_CHANSEL_0_SET_MSK << i); + break; + default: + return ALT_E_ERROR; + } + } + + // Handle Manager security + // Default is Secure state. + switch (dma_cfg->manager_sec) + { + case ALT_DMA_SECURITY_DEFAULT: + case ALT_DMA_SECURITY_SECURE: + break; + case ALT_DMA_SECURITY_NONSECURE: + dmactrl |= ALT_SYSMGR_DMA_CTL_MGRNONSECURE_SET_MSK; + break; + default: + return ALT_E_ERROR; + } + + // Handle IRQ security + for (int i = 0; i < ALT_SYSMGR_DMA_CTL_IRQNONSECURE_WIDTH; ++i) + { + // Default is Secure state. + switch (dma_cfg->irq_sec[i]) + { + case ALT_DMA_SECURITY_DEFAULT: + case ALT_DMA_SECURITY_SECURE: + break; + case ALT_DMA_SECURITY_NONSECURE: + dmactrl |= (1 << (i + ALT_SYSMGR_DMA_CTL_IRQNONSECURE_LSB)); + break; + default: + return ALT_E_ERROR; + } + } + + alt_write_word(ALT_SYSMGR_DMA_CTL_ADDR, dmactrl); + + // Update the System Manager DMA peripheral security items + + uint32_t dmapersecurity = 0; + + for (int i = 0; i < 32; ++i) + { + // Default is Secure state. + switch (dma_cfg->periph_sec[i]) + { + case ALT_DMA_SECURITY_DEFAULT: + case ALT_DMA_SECURITY_SECURE: + break; + case ALT_DMA_SECURITY_NONSECURE: + dmapersecurity |= (1 << i); + break; + default: + return ALT_E_ERROR; + } + } + + alt_write_word(ALT_SYSMGR_DMA_PERSECURITY_ADDR, dmapersecurity); + + // Take DMA out of reset. + + alt_clrbits_word(ALT_RSTMGR_PERMODRST_ADDR, ALT_RSTMGR_PERMODRST_DMA_SET_MSK); + + return ALT_E_SUCCESS; +} + +ALT_STATUS_CODE alt_dma_uninit(void) +{ + // DMAKILL all channel and free all allocated channels. + for (int i = 0; i < 8; ++i) + { + if (channel_info_array[i].flag & ALT_DMA_CHANNEL_INFO_FLAG_ALLOCED) + { + alt_dma_channel_kill((ALT_DMA_CHANNEL_t)i); + alt_dma_channel_free((ALT_DMA_CHANNEL_t)i); + } + } + + // Put DMA into reset. + + alt_setbits_word(ALT_RSTMGR_PERMODRST_ADDR, ALT_RSTMGR_PERMODRST_DMA_SET_MSK); + + return ALT_E_SUCCESS; +} + +ALT_STATUS_CODE alt_dma_channel_alloc(ALT_DMA_CHANNEL_t channel) +{ + // Validate channel + switch (channel) + { + case ALT_DMA_CHANNEL_0: + case ALT_DMA_CHANNEL_1: + case ALT_DMA_CHANNEL_2: + case ALT_DMA_CHANNEL_3: + case ALT_DMA_CHANNEL_4: + case ALT_DMA_CHANNEL_5: + case ALT_DMA_CHANNEL_6: + case ALT_DMA_CHANNEL_7: + break; + default: + return ALT_E_BAD_ARG; + } + + // Verify channel is unallocated + + if (channel_info_array[channel].flag & ALT_DMA_CHANNEL_INFO_FLAG_ALLOCED) + { + return ALT_E_ERROR; + } + + // Mark channel as allocated + + channel_info_array[channel].flag |= ALT_DMA_CHANNEL_INFO_FLAG_ALLOCED; + + return ALT_E_SUCCESS; +} + +ALT_STATUS_CODE alt_dma_channel_alloc_any(ALT_DMA_CHANNEL_t * allocated) +{ + // Sweep channel array for unallocated channel + + for (int i = 0; i < 8; ++i) + { + if (!(channel_info_array[i].flag & ALT_DMA_CHANNEL_INFO_FLAG_ALLOCED)) + { + // Allocate that free channel. + + ALT_STATUS_CODE status = alt_dma_channel_alloc((ALT_DMA_CHANNEL_t)i); + if (status == ALT_E_SUCCESS) + { + *allocated = (ALT_DMA_CHANNEL_t)i; + } + return status; + } + } + + // No free channels found. + + return ALT_E_ERROR; +} + +ALT_STATUS_CODE alt_dma_channel_free(ALT_DMA_CHANNEL_t channel) +{ + // Validate channel + switch (channel) + { + case ALT_DMA_CHANNEL_0: + case ALT_DMA_CHANNEL_1: + case ALT_DMA_CHANNEL_2: + case ALT_DMA_CHANNEL_3: + case ALT_DMA_CHANNEL_4: + case ALT_DMA_CHANNEL_5: + case ALT_DMA_CHANNEL_6: + case ALT_DMA_CHANNEL_7: + break; + default: + return ALT_E_BAD_ARG; + } + + // Verify channel is allocated + + if (!(channel_info_array[channel].flag & ALT_DMA_CHANNEL_INFO_FLAG_ALLOCED)) + { + return ALT_E_ERROR; + } + + // Verify channel is stopped + + ALT_DMA_CHANNEL_STATE_t state; + ALT_STATUS_CODE status = alt_dma_channel_state_get(channel, &state); + if (status != ALT_E_SUCCESS) + { + return status; + } + if (state != ALT_DMA_CHANNEL_STATE_STOPPED) + { + return ALT_E_ERROR; + } + + // Mark channel as unallocated. + + channel_info_array[channel].flag &= ~ALT_DMA_CHANNEL_INFO_FLAG_ALLOCED; + + return ALT_E_SUCCESS; +} + +ALT_STATUS_CODE alt_dma_channel_exec(ALT_DMA_CHANNEL_t channel, ALT_DMA_PROGRAM_t * pgm) +{ + // Validate channel + switch (channel) + { + case ALT_DMA_CHANNEL_0: + case ALT_DMA_CHANNEL_1: + case ALT_DMA_CHANNEL_2: + case ALT_DMA_CHANNEL_3: + case ALT_DMA_CHANNEL_4: + case ALT_DMA_CHANNEL_5: + case ALT_DMA_CHANNEL_6: + case ALT_DMA_CHANNEL_7: + break; + default: + return ALT_E_BAD_ARG; + } + + // Verify channel is allocated + + if (!(channel_info_array[channel].flag & ALT_DMA_CHANNEL_INFO_FLAG_ALLOCED)) + { + return ALT_E_ERROR; + } + + // Verify channel is stopped + + ALT_DMA_CHANNEL_STATE_t state; + ALT_STATUS_CODE status = alt_dma_channel_state_get(channel, &state); + if (status != ALT_E_SUCCESS) + { + return status; + } + if (state != ALT_DMA_CHANNEL_STATE_STOPPED) + { + return ALT_E_ERROR; + } + + // Validate the program + + if (alt_dma_program_validate(pgm) != ALT_E_SUCCESS) + { + return ALT_E_ERROR; + } + + // + // Execute the program + // + + // Get the start address + + uint32_t start = (uint32_t) &pgm->program[pgm->buffer_start]; + + dprintf("DMA[exec]: pgm->program = %p.\n", pgm->program); + dprintf("DMA[exec]: start = %p.\n", (void *)start); + + // Configure DBGINST0 and DBGINST1 to execute DMAGO targetting the requested channel. + + // For information on APB Interface, see PL330, section 2.5.1. + // For information on DBGINSTx, see PL330, section 3.3.20 - 3.3.21. + // For information on DMAGO, see PL330, section 4.3.5. + + alt_write_word(ALT_DMA_DBGINST0_ADDR(ALT_DMASECURE_ADDR), + ALT_DMA_DBGINST0_INSTRUCTIONBYTE0_SET(0xa0) | + ALT_DMA_DBGINST0_INSTRUCTIONBYTE1_SET(channel)); + + alt_write_word(ALT_DMA_DBGINST1_ADDR(ALT_DMASECURE_ADDR), start); + + // Execute the instruction held in DBGINST{0,1} + + // For information on DBGCMD, see PL330, section 3.3.19. + + alt_write_word(ALT_DMA_DBGCMD_ADDR(ALT_DMASECURE_ADDR), 0); + + return ALT_E_SUCCESS; +} + +ALT_STATUS_CODE alt_dma_channel_kill(ALT_DMA_CHANNEL_t channel) +{ + // Validate channel + switch (channel) + { + case ALT_DMA_CHANNEL_0: + case ALT_DMA_CHANNEL_1: + case ALT_DMA_CHANNEL_2: + case ALT_DMA_CHANNEL_3: + case ALT_DMA_CHANNEL_4: + case ALT_DMA_CHANNEL_5: + case ALT_DMA_CHANNEL_6: + case ALT_DMA_CHANNEL_7: + break; + default: + return ALT_E_BAD_ARG; + } + + // Verify channel is allocated + + if (!(channel_info_array[channel].flag & ALT_DMA_CHANNEL_INFO_FLAG_ALLOCED)) + { + return ALT_E_ERROR; + } + + // NOTE: Don't worry about the current channel state. Just issue DMAKILL + // instruction. The channel state cannot move from from Stopped back to + // Killing. + + // Configure DBGINST0 to execute DMAKILL on the requested channel thread. + // DMAKILL is short enough not to use DBGINST1 register. + + // For information on APB Interface, see PL330, section 2.5.1. + // For information on DBGINSTx, see PL330, section 3.3.20 - 3.3.21. + // For information on DMAKILL, see PL330, section 4.3.6. + + alt_write_word(ALT_DMA_DBGINST0_ADDR(ALT_DMASECURE_ADDR), + ALT_DMA_DBGINST0_INSTRUCTIONBYTE0_SET(0x1) | + ALT_DMA_DBGINST0_CHANNELNUMBER_SET(channel) | + ALT_DMA_DBGINST0_DEBUGTHREAD_SET(ALT_DMA_DBGINST0_DEBUGTHREAD_E_CHANNEL)); + + // Execute the instruction held in DBGINST0 + + // For information on DBGCMD, see PL330, section 3.3.19. + + alt_write_word(ALT_DMA_DBGCMD_ADDR(ALT_DMASECURE_ADDR), 0); + + // Wait for channel to move to KILLING or STOPPED state. Do not wait for + // the STOPPED only. If the AXI transaction hangs permanently, it can be + // waiting indefinately. + + ALT_STATUS_CODE status = ALT_E_SUCCESS; + ALT_DMA_CHANNEL_STATE_t current; + uint32_t i = 20000; + + while (--i) + { + status = alt_dma_channel_state_get(channel, ¤t); + if (status != ALT_E_SUCCESS) + { + break; + } + if ( (current == ALT_DMA_CHANNEL_STATE_KILLING) + || (current == ALT_DMA_CHANNEL_STATE_STOPPED)) + { + break; + } + } + + if (i == 0) + { + status = ALT_E_TMO; + } + + return status; +} + +ALT_STATUS_CODE alt_dma_channel_reg_get(ALT_DMA_CHANNEL_t channel, + ALT_DMA_PROGRAM_REG_t reg, uint32_t * val) +{ + // Validate channel + switch (channel) + { + case ALT_DMA_CHANNEL_0: + case ALT_DMA_CHANNEL_1: + case ALT_DMA_CHANNEL_2: + case ALT_DMA_CHANNEL_3: + case ALT_DMA_CHANNEL_4: + case ALT_DMA_CHANNEL_5: + case ALT_DMA_CHANNEL_6: + case ALT_DMA_CHANNEL_7: + break; + default: + return ALT_E_BAD_ARG; + } + + // For information on SAR, see PL330, section 3.3.13. + // For information on DAR, see PL330, section 3.3.14. + // For information on CCR, see PL330, section 3.3.15. + + switch (reg) + { + case ALT_DMA_PROGRAM_REG_SAR: + *val = alt_read_word(ALT_DMA_SARx_ADDR(ALT_DMASECURE_ADDR, channel)); + break; + case ALT_DMA_PROGRAM_REG_DAR: + *val = alt_read_word(ALT_DMA_DARx_ADDR(ALT_DMASECURE_ADDR, channel)); + break; + case ALT_DMA_PROGRAM_REG_CCR: + *val = alt_read_word(ALT_DMA_CCRx_ADDR(ALT_DMASECURE_ADDR, channel)); + break; + default: + return ALT_E_BAD_ARG; + } + + return ALT_E_SUCCESS; +} + +ALT_STATUS_CODE alt_dma_send_event(ALT_DMA_EVENT_t evt_num) +{ + // Validate evt_num + + switch (evt_num) + { + case ALT_DMA_EVENT_0: + case ALT_DMA_EVENT_1: + case ALT_DMA_EVENT_2: + case ALT_DMA_EVENT_3: + case ALT_DMA_EVENT_4: + case ALT_DMA_EVENT_5: + case ALT_DMA_EVENT_6: + case ALT_DMA_EVENT_7: + case ALT_DMA_EVENT_ABORT: + break; + default: + return ALT_E_BAD_ARG; + } + + // Issue the DMASEV on the DMA manager thread. + // DMASEV is short enough not to use DBGINST1 register. + + // For information on APB Interface, see PL330, section 2.5.1. + // For information on DBGINSTx, see PL330, section 3.3.20 - 3.3.21. + // For information on DMASEV, see PL330, section 4.3.15. + + alt_write_word(ALT_DMA_DBGINST0_ADDR(ALT_DMASECURE_ADDR), + ALT_DMA_DBGINST0_INSTRUCTIONBYTE0_SET(0x34) | // opcode for DMASEV + ALT_DMA_DBGINST0_INSTRUCTIONBYTE1_SET(evt_num << 3) | + ALT_DMA_DBGINST0_DEBUGTHREAD_SET(ALT_DMA_DBGINST0_DEBUGTHREAD_E_MANAGER) + ); + + // Execute the instruction held in DBGINST0 + + // For information on DBGCMD, see PL330, section 3.3.19. + + alt_write_word(ALT_DMA_DBGCMD_ADDR(ALT_DMASECURE_ADDR), 0); + + return ALT_E_SUCCESS; +} + +ALT_STATUS_CODE alt_dma_manager_state_get(ALT_DMA_MANAGER_STATE_t * state) +{ + // For information on DSR, see PL330, section 3.3.1. + + uint32_t raw_state = alt_read_word(ALT_DMA_DSR_ADDR(ALT_DMASECURE_ADDR)); + + *state = (ALT_DMA_MANAGER_STATE_t)ALT_DMA_DSR_DMASTATUS_GET(raw_state); + + return ALT_E_SUCCESS; +} + +ALT_STATUS_CODE alt_dma_channel_state_get(ALT_DMA_CHANNEL_t channel, + ALT_DMA_CHANNEL_STATE_t * state) +{ + // Validate channel + switch (channel) + { + case ALT_DMA_CHANNEL_0: + case ALT_DMA_CHANNEL_1: + case ALT_DMA_CHANNEL_2: + case ALT_DMA_CHANNEL_3: + case ALT_DMA_CHANNEL_4: + case ALT_DMA_CHANNEL_5: + case ALT_DMA_CHANNEL_6: + case ALT_DMA_CHANNEL_7: + break; + default: + return ALT_E_BAD_ARG; + } + + // For information on CSR, see PL330, section 3.3.11. + + uint32_t raw_state = alt_read_word(ALT_DMA_CSRx_ADDR(ALT_DMASECURE_ADDR, channel)); + + *state = (ALT_DMA_CHANNEL_STATE_t)ALT_DMA_CSRx_CHANNELSTATUS_GET(raw_state); + + return ALT_E_SUCCESS; +} + +ALT_STATUS_CODE alt_dma_manager_fault_status_get(ALT_DMA_MANAGER_FAULT_t * fault) +{ + // For information on FTRD, see PL330, section 3.3.9. + + *fault = (ALT_DMA_MANAGER_FAULT_t)alt_read_word(ALT_DMA_FTRD_ADDR(ALT_DMASECURE_ADDR)); + + return ALT_E_SUCCESS; +} + +ALT_STATUS_CODE alt_dma_channel_fault_status_get(ALT_DMA_CHANNEL_t channel, + ALT_DMA_CHANNEL_FAULT_t * fault) +{ + // Validate channel + switch (channel) + { + case ALT_DMA_CHANNEL_0: + case ALT_DMA_CHANNEL_1: + case ALT_DMA_CHANNEL_2: + case ALT_DMA_CHANNEL_3: + case ALT_DMA_CHANNEL_4: + case ALT_DMA_CHANNEL_5: + case ALT_DMA_CHANNEL_6: + case ALT_DMA_CHANNEL_7: + break; + default: + return ALT_E_BAD_ARG; + } + + // For information on FTR, see PL330, section 3.3.10. + + *fault = (ALT_DMA_CHANNEL_FAULT_t)alt_read_word(ALT_DMA_FTRx_ADDR(ALT_DMASECURE_ADDR, channel)); + + return ALT_E_SUCCESS; +} + +ALT_STATUS_CODE alt_dma_event_int_select(ALT_DMA_EVENT_t evt_num, + ALT_DMA_EVENT_SELECT_t opt) +{ + // Validate evt_num + switch (evt_num) + { + case ALT_DMA_EVENT_0: + case ALT_DMA_EVENT_1: + case ALT_DMA_EVENT_2: + case ALT_DMA_EVENT_3: + case ALT_DMA_EVENT_4: + case ALT_DMA_EVENT_5: + case ALT_DMA_EVENT_6: + case ALT_DMA_EVENT_7: + case ALT_DMA_EVENT_ABORT: + break; + default: + return ALT_E_BAD_ARG; + } + + // For information on INTEN, see PL330, section 3.3.3. + + switch (opt) + { + case ALT_DMA_EVENT_SELECT_SEND_EVT: + alt_clrbits_word(ALT_DMA_INTEN_ADDR(ALT_DMASECURE_ADDR), 1 << evt_num); + break; + case ALT_DMA_EVENT_SELECT_SIG_IRQ: + alt_setbits_word(ALT_DMA_INTEN_ADDR(ALT_DMASECURE_ADDR), 1 << evt_num); + break; + default: + return ALT_E_BAD_ARG; + } + + return ALT_E_SUCCESS; +} + +ALT_STATUS_CODE alt_dma_event_int_status_get_raw(ALT_DMA_EVENT_t evt_num) +{ + // Validate evt_num + switch (evt_num) + { + case ALT_DMA_EVENT_0: + case ALT_DMA_EVENT_1: + case ALT_DMA_EVENT_2: + case ALT_DMA_EVENT_3: + case ALT_DMA_EVENT_4: + case ALT_DMA_EVENT_5: + case ALT_DMA_EVENT_6: + case ALT_DMA_EVENT_7: + case ALT_DMA_EVENT_ABORT: + break; + default: + return ALT_E_BAD_ARG; + } + + // For information on INT_EVENT_RIS, see PL330, section 3.3.4. + + uint32_t status_raw = alt_read_word(ALT_DMA_INT_EVENT_RIS_ADDR(ALT_DMASECURE_ADDR)); + + if (status_raw & (1 << evt_num)) + { + return ALT_E_TRUE; + } + else + { + return ALT_E_FALSE; + } +} + +ALT_STATUS_CODE alt_dma_int_status_get(ALT_DMA_EVENT_t irq_num) +{ + // Validate evt_num + switch (irq_num) + { + case ALT_DMA_EVENT_0: + case ALT_DMA_EVENT_1: + case ALT_DMA_EVENT_2: + case ALT_DMA_EVENT_3: + case ALT_DMA_EVENT_4: + case ALT_DMA_EVENT_5: + case ALT_DMA_EVENT_6: + case ALT_DMA_EVENT_7: + case ALT_DMA_EVENT_ABORT: + break; + default: + return ALT_E_BAD_ARG; + } + + // For information on INTMIS, see PL330, section 3.3.5. + + uint32_t int_status = alt_read_word(ALT_DMA_INTMIS_ADDR(ALT_DMASECURE_ADDR)); + + if (int_status & (1 << irq_num)) + { + return ALT_E_TRUE; + } + else + { + return ALT_E_FALSE; + } +} + +ALT_STATUS_CODE alt_dma_int_clear(ALT_DMA_EVENT_t irq_num) +{ + // Validate evt_num + switch (irq_num) + { + case ALT_DMA_EVENT_0: + case ALT_DMA_EVENT_1: + case ALT_DMA_EVENT_2: + case ALT_DMA_EVENT_3: + case ALT_DMA_EVENT_4: + case ALT_DMA_EVENT_5: + case ALT_DMA_EVENT_6: + case ALT_DMA_EVENT_7: + case ALT_DMA_EVENT_ABORT: + break; + default: + return ALT_E_BAD_ARG; + } + + // For information on INTCLR, see PL330, section 3.3.6. + + alt_write_word(ALT_DMA_INTCLR_ADDR(ALT_DMASECURE_ADDR), 1 << irq_num); + + return ALT_E_SUCCESS; +} + +///// + +ALT_STATUS_CODE alt_dma_memory_to_memory(ALT_DMA_CHANNEL_t channel, + ALT_DMA_PROGRAM_t * program, + void * dst, + const void * src, + size_t size, + bool send_evt, + ALT_DMA_EVENT_t evt) +{ + ALT_STATUS_CODE status = ALT_E_SUCCESS; + + // If the size is zero, and no event is requested, just return success. + if ((size == 0) && (send_evt == false)) + { + return status; + } + + if (status == ALT_E_SUCCESS) + { + status = alt_dma_program_init(program); + } + + if (size != 0) + { + uintptr_t udst = (uintptr_t)dst; + uintptr_t usrc = (uintptr_t)src; + + dprintf("DMA[M->M]: dst = %p.\n", dst); + dprintf("DMA[M->M]: src = %p.\n", src); + dprintf("DMA[M->M]: size = 0x%x.\n", size); + + // Detect if memory regions overshoots the address space. + + if (udst + size - 1 < udst) + { + return ALT_E_BAD_ARG; + } + if (usrc + size - 1 < usrc) + { + return ALT_E_BAD_ARG; + } + + // Detect if memory regions overlaps. + + if (udst > usrc) + { + if (usrc + size - 1 > udst) + { + return ALT_E_BAD_ARG; + } + } + else + { + if (udst + size - 1 > usrc) + { + return ALT_E_BAD_ARG; + } + } + + if (status == ALT_E_SUCCESS) + { + status = alt_dma_program_DMAMOV(program, ALT_DMA_PROGRAM_REG_SAR, usrc); + } + if (status == ALT_E_SUCCESS) + { + status = alt_dma_program_DMAMOV(program, ALT_DMA_PROGRAM_REG_DAR, udst); + } + + size_t sizeleft = size; + + // + // The algorithm uses the strategy described in PL330 B.3.1. + // It is extended for 2-byte and 1-byte unaligned cases. + // + + // First see how many byte(s) we need to transfer to get src to be 8 byte aligned + if (usrc & 0x7) + { + uint32_t aligncount = MIN(8 - (usrc & 0x7), sizeleft); + sizeleft -= aligncount; + + dprintf("DMA[M->M]: Total pre-alignment 1-byte burst size tranfer(s): %lu.\n", aligncount); + + // Program in the following parameters: + // - SS8 (Source burst size of 1-byte) + // - DS8 (Destination burst size of 1-byte) + // - SBx (Source burst length of [aligncount] transfers) + // - DBx (Destination burst length of [aligncount] transfers) + // - All other options default. + + if (status == ALT_E_SUCCESS) + { + status = alt_dma_program_DMAMOV(program, ALT_DMA_PROGRAM_REG_CCR, + ( ((aligncount - 1) << 4) // SB + | ALT_DMA_CCR_OPT_SS8 + | ALT_DMA_CCR_OPT_SA_DEFAULT + | ALT_DMA_CCR_OPT_SP_DEFAULT + | ALT_DMA_CCR_OPT_SC_DEFAULT + | ((aligncount - 1) << 18) // DB + | ALT_DMA_CCR_OPT_DS8 + | ALT_DMA_CCR_OPT_DA_DEFAULT + | ALT_DMA_CCR_OPT_DP_DEFAULT + | ALT_DMA_CCR_OPT_DC_DEFAULT + | ALT_DMA_CCR_OPT_ES_DEFAULT + ) + ); + } + if (status == ALT_E_SUCCESS) + { + status = alt_dma_program_DMALD(program, ALT_DMA_PROGRAM_INST_MOD_NONE); + } + if (status == ALT_E_SUCCESS) + { + status = alt_dma_program_DMAST(program, ALT_DMA_PROGRAM_INST_MOD_NONE); + } + } + + // This is the number of 8-byte bursts + uint32_t burstcount = sizeleft >> 3; + + bool correction = (burstcount != 0); + + // Update the size left to transfer + sizeleft &= 0x7; + + dprintf("DMA[M->M]: Total Main 8-byte burst size transfer(s): %lu.\n", burstcount); + dprintf("DMA[M->M]: Total Main 1-byte burst size transfer(s): %u.\n", sizeleft); + + // Determine how many 16 length bursts can be done + + if (burstcount >> 4) + { + uint32_t length16burstcount = burstcount >> 4; + burstcount &= 0xf; + + dprintf("DMA[M->M]: Number of 16 burst length 8-byte transfer(s): %lu.\n", length16burstcount); + dprintf("DMA[M->M]: Number of remaining 8-byte transfer(s): %lu.\n", burstcount); + + // Program in the following parameters: + // - SS64 (Source burst size of 8-byte) + // - DS64 (Destination burst size of 8-byte) + // - SB16 (Source burst length of 16 transfers) + // - DB16 (Destination burst length of 16 transfers) + // - All other options default. + + if (status == ALT_E_SUCCESS) + { + status = alt_dma_program_DMAMOV(program, ALT_DMA_PROGRAM_REG_CCR, + ( ALT_DMA_CCR_OPT_SB16 + | ALT_DMA_CCR_OPT_SS64 + | ALT_DMA_CCR_OPT_SA_DEFAULT + | ALT_DMA_CCR_OPT_SP_DEFAULT + | ALT_DMA_CCR_OPT_SC_DEFAULT + | ALT_DMA_CCR_OPT_DB16 + | ALT_DMA_CCR_OPT_DS64 + | ALT_DMA_CCR_OPT_DA_DEFAULT + | ALT_DMA_CCR_OPT_DP_DEFAULT + | ALT_DMA_CCR_OPT_DC_DEFAULT + | ALT_DMA_CCR_OPT_ES_DEFAULT + ) + ); + } + + while (length16burstcount > 0) + { + if (status != ALT_E_SUCCESS) + { + break; + } + + uint32_t loopcount = MIN(length16burstcount, 256); + length16burstcount -= loopcount; + + dprintf("DMA[M->M]: Looping %lux 16 burst length 8-byte transfer(s).\n", loopcount); + + if ((status == ALT_E_SUCCESS) && (loopcount > 1)) + { + status = alt_dma_program_DMALP(program, loopcount); + } + if (status == ALT_E_SUCCESS) + { + status = alt_dma_program_DMALD(program, ALT_DMA_PROGRAM_INST_MOD_NONE); + } + if (status == ALT_E_SUCCESS) + { + status = alt_dma_program_DMAST(program, ALT_DMA_PROGRAM_INST_MOD_NONE); + } + if ((status == ALT_E_SUCCESS) && (loopcount > 1)) + { + status = alt_dma_program_DMALPEND(program, ALT_DMA_PROGRAM_INST_MOD_NONE); + } + } + } + + // At this point, we should have [burstcount] 8-byte transfer(s) + // remaining. [burstcount] should be less than 16. + + // Do one more burst with a SB / DB of length [burstcount]. + + if (burstcount) + { + // Program in the following parameters: + // - SS64 (Source burst size of 8-byte) + // - DS64 (Destination burst size of 8-byte) + // - SBx (Source burst length of [burstlength] transfers) + // - DBx (Destination burst length of [burstlength] transfers) + // - All other options default. + + if (status == ALT_E_SUCCESS) + { + status = alt_dma_program_DMAMOV(program, ALT_DMA_PROGRAM_REG_CCR, + ( ((burstcount - 1) << 4) // SB + | ALT_DMA_CCR_OPT_SS64 + | ALT_DMA_CCR_OPT_SA_DEFAULT + | ALT_DMA_CCR_OPT_SP_DEFAULT + | ALT_DMA_CCR_OPT_SC_DEFAULT + | ((burstcount - 1) << 18) // DB + | ALT_DMA_CCR_OPT_DS64 + | ALT_DMA_CCR_OPT_DA_DEFAULT + | ALT_DMA_CCR_OPT_DP_DEFAULT + | ALT_DMA_CCR_OPT_DC_DEFAULT + | ALT_DMA_CCR_OPT_ES_DEFAULT + ) + ); + } + if (status == ALT_E_SUCCESS) + { + status = alt_dma_program_DMALD(program, ALT_DMA_PROGRAM_INST_MOD_NONE); + } + if (status == ALT_E_SUCCESS) + { + status = alt_dma_program_DMAST(program, ALT_DMA_PROGRAM_INST_MOD_NONE); + } + } + + // This is where the last DMAMOV CCR and DMAST is done if an + // alignment correction required. + + if ( (correction == true) + && ((usrc & 0x7) != (udst & 0x7)) // If src and dst are mod-8 congruent, no correction is needed. + ) + { + if (status == ALT_E_SUCCESS) + { + // Determine what type of correction. + + // Set the source parameters to match that of the destination + // parameters. This way the SAR is increment in the same fashion as + // DAR. This will allow the non 8-byte transfers to copy correctly. + + uint32_t ccr; + + if ((usrc & 0x3) == (udst & 0x3)) + { + dprintf("DMA[M->M]: Single correction 4-byte burst size tranfer.\n"); + + // Program in the following parameters: + // - SS32 (Source burst size of 4-byte) + // - DS32 (Destination burst size of 4-byte) + // - SB1 (Source burst length of 1 transfer) + // - DB1 (Destination burst length of 1 transfer) + // - All other options default. + + ccr = ( ALT_DMA_CCR_OPT_SB1 + | ALT_DMA_CCR_OPT_SS32 + | ALT_DMA_CCR_OPT_SA_DEFAULT + | ALT_DMA_CCR_OPT_SP_DEFAULT + | ALT_DMA_CCR_OPT_SC_DEFAULT + | ALT_DMA_CCR_OPT_DB1 + | ALT_DMA_CCR_OPT_DS32 + | ALT_DMA_CCR_OPT_DA_DEFAULT + | ALT_DMA_CCR_OPT_DP_DEFAULT + | ALT_DMA_CCR_OPT_DC_DEFAULT + | ALT_DMA_CCR_OPT_ES_DEFAULT + ); + } + else if ((usrc & 0x1) == (udst & 0x1)) + { + dprintf("DMA[M->M]: Single correction 2-byte burst size tranfer.\n"); + + // Program in the following parameters: + // - SS16 (Source burst size of 2-byte) + // - DS16 (Destination burst size of 2-byte) + // - SB1 (Source burst length of 1 transfer) + // - DB1 (Destination burst length of 1 transfer) + // - All other options default. + + ccr = ( ALT_DMA_CCR_OPT_SB1 + | ALT_DMA_CCR_OPT_SS16 + | ALT_DMA_CCR_OPT_SA_DEFAULT + | ALT_DMA_CCR_OPT_SP_DEFAULT + | ALT_DMA_CCR_OPT_SC_DEFAULT + | ALT_DMA_CCR_OPT_DB1 + | ALT_DMA_CCR_OPT_DS16 + | ALT_DMA_CCR_OPT_DA_DEFAULT + | ALT_DMA_CCR_OPT_DP_DEFAULT + | ALT_DMA_CCR_OPT_DC_DEFAULT + | ALT_DMA_CCR_OPT_ES_DEFAULT + ); + } + else + { + dprintf("DMA[M->M]: Single correction 1-byte burst size tranfer.\n"); + + // Program in the following parameters: + // - SS8 (Source burst size of 1-byte) + // - DS8 (Destination burst size of 1-byte) + // - SB1 (Source burst length of 1 transfer) + // - DB1 (Destination burst length of 1 transfer) + // - All other options default. + + ccr = ( ALT_DMA_CCR_OPT_SB1 + | ALT_DMA_CCR_OPT_SS8 + | ALT_DMA_CCR_OPT_SA_DEFAULT + | ALT_DMA_CCR_OPT_SP_DEFAULT + | ALT_DMA_CCR_OPT_SC_DEFAULT + | ALT_DMA_CCR_OPT_DB1 + | ALT_DMA_CCR_OPT_DS8 + | ALT_DMA_CCR_OPT_DA_DEFAULT + | ALT_DMA_CCR_OPT_DP_DEFAULT + | ALT_DMA_CCR_OPT_DC_DEFAULT + | ALT_DMA_CCR_OPT_ES_DEFAULT + ); + } + + status = alt_dma_program_DMAMOV(program, ALT_DMA_PROGRAM_REG_CCR, + ccr); + } + if (status == ALT_E_SUCCESS) + { + status = alt_dma_program_DMAST(program, ALT_DMA_PROGRAM_INST_MOD_NONE); + } + } + + // At this point, there should be 0 - 7 1-byte transfers remaining. + + if (sizeleft) + { + dprintf("DMA[M->M]: Total post 1-byte burst size tranfer(s): %u.\n", sizeleft); + + // Program in the following parameters: + // - SS8 (Source burst size of 1-byte) + // - DS8 (Destination burst size of 1-byte) + // - SBx (Source burst length of [sizeleft] transfers) + // - DBx (Destination burst length of [sizeleft] transfers) + // - All other options default. + + if (status == ALT_E_SUCCESS) + { + status = alt_dma_program_DMAMOV(program, ALT_DMA_PROGRAM_REG_CCR, + ( ((sizeleft - 1) << 4) // SB + | ALT_DMA_CCR_OPT_SS8 + | ALT_DMA_CCR_OPT_SA_DEFAULT + | ALT_DMA_CCR_OPT_SP_DEFAULT + | ALT_DMA_CCR_OPT_SC_DEFAULT + | ((sizeleft - 1) << 18) // DB + | ALT_DMA_CCR_OPT_DS8 + | ALT_DMA_CCR_OPT_DA_DEFAULT + | ALT_DMA_CCR_OPT_DP_DEFAULT + | ALT_DMA_CCR_OPT_DC_DEFAULT + | ALT_DMA_CCR_OPT_ES_DEFAULT + ) + ); + } + if (status == ALT_E_SUCCESS) + { + status = alt_dma_program_DMALD(program, ALT_DMA_PROGRAM_INST_MOD_NONE); + } + if (status == ALT_E_SUCCESS) + { + status = alt_dma_program_DMAST(program, ALT_DMA_PROGRAM_INST_MOD_NONE); + } + } + } // if (size != 0) + + // Send event if requested. + if (send_evt) + { + if (status == ALT_E_SUCCESS) + { + dprintf("DMA[M->M]: Adding event ...\n"); + status = alt_dma_program_DMASEV(program, evt); + } + } + + // Now that everything is done, end the program. + if (status == ALT_E_SUCCESS) + { + status = alt_dma_program_DMAEND(program); + } + + // If there was a problem assembling the program, clean up the buffer and exit. + if (status != ALT_E_SUCCESS) + { + // Do not report the status for the clear operation. A failure should be + // reported regardless of if the clear is successful. + alt_dma_program_clear(program); + return status; + } + + // Execute the program on the given channel. + return alt_dma_channel_exec(channel, program); +} + +ALT_STATUS_CODE alt_dma_zero_to_memory(ALT_DMA_CHANNEL_t channel, + ALT_DMA_PROGRAM_t * program, + void * buf, + size_t size, + bool send_evt, + ALT_DMA_EVENT_t evt) +{ + ALT_STATUS_CODE status = ALT_E_SUCCESS; + + // If the size is zero, and no event is requested, just return success. + if ((size == 0) && (send_evt == false)) + { + return status; + } + + if (status == ALT_E_SUCCESS) + { + status = alt_dma_program_init(program); + } + + if (size != 0) + { + if (status == ALT_E_SUCCESS) + { + status = alt_dma_program_DMAMOV(program, ALT_DMA_PROGRAM_REG_DAR, (uint32_t)buf); + } + + dprintf("DMA[Z->M]: buf = %p.\n", buf); + dprintf("DMA[Z->M]: size = 0x%x.\n", size); + + size_t sizeleft = size; + + // First see how many byte(s) we need to transfer to get dst to be 8 byte aligned. + if ((uint32_t)buf & 0x7) + { + uint32_t aligncount = MIN(8 - ((uint32_t)buf & 0x7), sizeleft); + sizeleft -= aligncount; + + dprintf("DMA[Z->M]: Total pre-alignment 1-byte burst size tranfer(s): %lu.\n", aligncount); + + // Program in the following parameters: + // - DS8 (Destination burst size of 1-byte) + // - DBx (Destination burst length of [aligncount] transfers) + // - All other options default. + + if (status == ALT_E_SUCCESS) + { + status = alt_dma_program_DMAMOV(program, ALT_DMA_PROGRAM_REG_CCR, + ( ALT_DMA_CCR_OPT_SB_DEFAULT + | ALT_DMA_CCR_OPT_SS_DEFAULT + | ALT_DMA_CCR_OPT_SA_DEFAULT + | ALT_DMA_CCR_OPT_SP_DEFAULT + | ALT_DMA_CCR_OPT_SC_DEFAULT + | ((aligncount - 1) << 18) // DB + | ALT_DMA_CCR_OPT_DS8 + | ALT_DMA_CCR_OPT_DA_DEFAULT + | ALT_DMA_CCR_OPT_DP_DEFAULT + | ALT_DMA_CCR_OPT_DC_DEFAULT + | ALT_DMA_CCR_OPT_ES_DEFAULT + ) + ); + } + if (status == ALT_E_SUCCESS) + { + status = alt_dma_program_DMASTZ(program); + } + } + + // This is the number of 8-byte bursts left + uint32_t burstcount = sizeleft >> 3; + + // Update the size left to transfer + sizeleft &= 0x7; + + dprintf("DMA[Z->M]: Total Main 8-byte burst size transfer(s): %lu.\n", burstcount); + dprintf("DMA[Z->M]: Total Main 1-byte burst size transfer(s): %u.\n", sizeleft); + + // Determine how many 16 length bursts can be done + if (burstcount >> 4) + { + uint32_t length16burstcount = burstcount >> 4; + burstcount &= 0xf; + + dprintf("DMA[Z->M]: Number of 16 burst length 8-byte transfer(s): %lu.\n", length16burstcount); + dprintf("DMA[Z->M]: Number of remaining 8-byte transfer(s): %lu.\n", burstcount); + + // Program in the following parameters: + // - DS64 (Destination burst size of 8-byte) + // - DB16 (Destination burst length of 16 transfers) + // - All other options default. + + if (status == ALT_E_SUCCESS) + { + status = alt_dma_program_DMAMOV(program, ALT_DMA_PROGRAM_REG_CCR, + ( ALT_DMA_CCR_OPT_SB_DEFAULT + | ALT_DMA_CCR_OPT_SS_DEFAULT + | ALT_DMA_CCR_OPT_SA_DEFAULT + | ALT_DMA_CCR_OPT_SP_DEFAULT + | ALT_DMA_CCR_OPT_SC_DEFAULT + | ALT_DMA_CCR_OPT_DB16 + | ALT_DMA_CCR_OPT_DS64 + | ALT_DMA_CCR_OPT_DA_DEFAULT + | ALT_DMA_CCR_OPT_DP_DEFAULT + | ALT_DMA_CCR_OPT_DC_DEFAULT + | ALT_DMA_CCR_OPT_ES_DEFAULT + ) + ); + } + + while (length16burstcount > 0) + { + if (status != ALT_E_SUCCESS) + { + break; + } + + uint32_t loopcount = MIN(length16burstcount, 256); + length16burstcount -= loopcount; + + dprintf("DMA[Z->M]: Looping %lux 16 burst length 8-byte transfer(s).\n", loopcount); + + if ((status == ALT_E_SUCCESS) && (loopcount > 1)) + { + status = alt_dma_program_DMALP(program, loopcount); + } + if (status == ALT_E_SUCCESS) + { + status = alt_dma_program_DMASTZ(program); + } + if ((status == ALT_E_SUCCESS) && (loopcount > 1)) + { + status = alt_dma_program_DMALPEND(program, ALT_DMA_PROGRAM_INST_MOD_NONE); + } + } + } + + // At this point, we should have [burstcount] 8-byte transfer(s) + // remaining. [burstcount] should be less than 16. + + // Do one more burst with a SB / DB of length [burstcount]. + + if (burstcount) + { + // Program in the following parameters: + // - DS64 (Destination burst size of 8-byte) + // - DBx (Destination burst length of [burstlength] transfers) + // - All other options default. + + if (status == ALT_E_SUCCESS) + { + status = alt_dma_program_DMAMOV(program, ALT_DMA_PROGRAM_REG_CCR, + ( ALT_DMA_CCR_OPT_SB_DEFAULT + | ALT_DMA_CCR_OPT_SS_DEFAULT + | ALT_DMA_CCR_OPT_SA_DEFAULT + | ALT_DMA_CCR_OPT_SP_DEFAULT + | ALT_DMA_CCR_OPT_SC_DEFAULT + | ((burstcount - 1) << 18) // DB + | ALT_DMA_CCR_OPT_DS64 + | ALT_DMA_CCR_OPT_DA_DEFAULT + | ALT_DMA_CCR_OPT_DP_DEFAULT + | ALT_DMA_CCR_OPT_DC_DEFAULT + | ALT_DMA_CCR_OPT_ES_DEFAULT + ) + ); + } + if (status == ALT_E_SUCCESS) + { + status = alt_dma_program_DMASTZ(program); + } + } + + // At this point, there should be 0 - 7 1-byte transfers remaining. + + if (sizeleft) + { + dprintf("DMA[Z->M]: Total post 1-byte burst size tranfer(s): %u.\n", sizeleft); + + // Program in the following parameters: + // - DS8 (Destination burst size of 1-byte) + // - DBx (Destination burst length of [sizeleft] transfers) + // - All other options default. + + if (status == ALT_E_SUCCESS) + { + status = alt_dma_program_DMAMOV(program, ALT_DMA_PROGRAM_REG_CCR, + ( ALT_DMA_CCR_OPT_SB_DEFAULT + | ALT_DMA_CCR_OPT_SS_DEFAULT + | ALT_DMA_CCR_OPT_SA_DEFAULT + | ALT_DMA_CCR_OPT_SP_DEFAULT + | ALT_DMA_CCR_OPT_SC_DEFAULT + | ((sizeleft - 1) << 18) // DB + | ALT_DMA_CCR_OPT_DS8 + | ALT_DMA_CCR_OPT_DA_DEFAULT + | ALT_DMA_CCR_OPT_DP_DEFAULT + | ALT_DMA_CCR_OPT_DC_DEFAULT + | ALT_DMA_CCR_OPT_ES_DEFAULT + ) + ); + } + if (status == ALT_E_SUCCESS) + { + status = alt_dma_program_DMASTZ(program); + } + } + } // if (size != 0) + + // Send event if requested. + if (send_evt) + { + if (status == ALT_E_SUCCESS) + { + dprintf("DMA[Z->M]: Adding event ...\n"); + status = alt_dma_program_DMASEV(program, evt); + } + } + + // Now that everything is done, end the program. + if (status == ALT_E_SUCCESS) + { + status = alt_dma_program_DMAEND(program); + } + + // If there was a problem assembling the program, clean up the buffer and exit. + if (status != ALT_E_SUCCESS) + { + // Do not report the status for the clear operation. A failure should be + // reported regardless of if the clear is successful. + alt_dma_program_clear(program); + return status; + } + + // Execute the program on the given channel. + return alt_dma_channel_exec(channel, program); +} + +ALT_STATUS_CODE alt_dma_memory_to_register(ALT_DMA_CHANNEL_t channel, + ALT_DMA_PROGRAM_t * program, + void * dst_reg, + const void * src_buf, + size_t count, + uint32_t register_width_bits, + bool send_evt, + ALT_DMA_EVENT_t evt) +{ + ALT_STATUS_CODE status = ALT_E_SUCCESS; + + // If the count is zero, and no event is requested, just return success. + if ((count == 0) && (send_evt == false)) + { + return status; + } + + if (status == ALT_E_SUCCESS) + { + status = alt_dma_program_init(program); + } + + if (count != 0) + { + // Verify valid register_width_bits and construct the CCR SS and DS parameters. + uint32_t ccr_ss_ds_mask = 0; + + if (status == ALT_E_SUCCESS) + { + switch (register_width_bits) + { + case 8: + // Program in the following parameters: + // - SS8 (Source burst size of 8 bits) + // - DS8 (Destination burst size of 8 bits) + ccr_ss_ds_mask = ALT_DMA_CCR_OPT_SS8 | ALT_DMA_CCR_OPT_DS8; + break; + case 16: + // Program in the following parameters: + // - SS16 (Source burst size of 16 bits) + // - DS16 (Destination burst size of 16 bits) + ccr_ss_ds_mask = ALT_DMA_CCR_OPT_SS16 | ALT_DMA_CCR_OPT_DS16; + break; + case 32: + // Program in the following parameters: + // - SS32 (Source burst size of 32 bits) + // - DS32 (Destination burst size of 32 bits) + ccr_ss_ds_mask = ALT_DMA_CCR_OPT_SS32 | ALT_DMA_CCR_OPT_DS32; + break; + case 64: + // Program in the following parameters: + // - SS64 (Source burst size of 64 bits) + // - DS64 (Destination burst size of 64 bits) + ccr_ss_ds_mask = ALT_DMA_CCR_OPT_SS64 | ALT_DMA_CCR_OPT_DS64; + break; + default: + status = ALT_E_BAD_ARG; + break; + } + } + + // Verify that the dst_reg and src_buf are aligned to the register width + if (status == ALT_E_SUCCESS) + { + if (((uintptr_t)dst_reg & ((register_width_bits >> 3) - 1)) != 0) + { + status = ALT_E_BAD_ARG; + } + else if (((uintptr_t)src_buf & ((register_width_bits >> 3) - 1)) != 0) + { + status = ALT_E_BAD_ARG; + } + else + { + dprintf("DMA[M->R]: dst_reg = %p.\n", dst_reg); + dprintf("DMA[M->R]: src_buf = %p.\n", src_buf); + dprintf("DMA[M->R]: count = 0x%x.\n", count); + } + } + + if (status == ALT_E_SUCCESS) + { + status = alt_dma_program_DMAMOV(program, ALT_DMA_PROGRAM_REG_SAR, (uint32_t)src_buf); + } + if (status == ALT_E_SUCCESS) + { + status = alt_dma_program_DMAMOV(program, ALT_DMA_PROGRAM_REG_DAR, (uint32_t)dst_reg); + } + + // This is the remaining count left to process. + uint32_t countleft = count; + + // See how many 16-length bursts we can use + if (countleft >> 4) + { + // Program in the following parameters: + // - SSx (Source burst size of [ccr_ss_ds_mask]) + // - DSx (Destination burst size of [ccr_ss_ds_mask]) + // - DAF (Destination address fixed) + // - SB16 (Source burst length of 16 transfers) + // - DB16 (Destination burst length of 16 transfers) + // - All other options default. + + if (status == ALT_E_SUCCESS) + { + status = alt_dma_program_DMAMOV(program, ALT_DMA_PROGRAM_REG_CCR, + ( ccr_ss_ds_mask + | ALT_DMA_CCR_OPT_SB16 + | ALT_DMA_CCR_OPT_SA_DEFAULT + | ALT_DMA_CCR_OPT_SP_DEFAULT + | ALT_DMA_CCR_OPT_SC_DEFAULT + | ALT_DMA_CCR_OPT_DB16 + | ALT_DMA_CCR_OPT_DAF + | ALT_DMA_CCR_OPT_DP_DEFAULT + | ALT_DMA_CCR_OPT_DC_DEFAULT + | ALT_DMA_CCR_OPT_ES_DEFAULT + ) + ); + } + + uint32_t length16burst = countleft >> 4; + countleft &= 0xf; + + dprintf("DMA[M->R]: Number of 16 burst length transfer(s): %lu.\n", length16burst); + dprintf("DMA[M->R]: Number of remaining transfer(s): %lu.\n", countleft); + + // See how many 256x 16-length bursts we can use + if (length16burst >> 8) + { + uint32_t loop256length16burst = length16burst >> 8; + length16burst &= ((1 << 8) - 1); + + dprintf("DMA[M->R]: Number of 256-looped 16 burst length transfer(s): %lu.\n", loop256length16burst); + dprintf("DMA[M->R]: Number of remaining 16 burst length transfer(s): %lu.\n", length16burst); + + while (loop256length16burst > 0) + { + if (status != ALT_E_SUCCESS) + { + break; + } + + uint32_t loopcount = MIN(loop256length16burst, 256); + loop256length16burst -= loopcount; + + dprintf("DMA[M->R]: Looping %lux super loop transfer(s).\n", loopcount); + + if ((status == ALT_E_SUCCESS) && (loopcount > 1)) + { + status = alt_dma_program_DMALP(program, loopcount); + } + + if (status == ALT_E_SUCCESS) + { + status = alt_dma_program_DMALP(program, 256); + } + if (status == ALT_E_SUCCESS) + { + status = alt_dma_program_DMALD(program, ALT_DMA_PROGRAM_INST_MOD_NONE); + } + if (status == ALT_E_SUCCESS) + { + status = alt_dma_program_DMAST(program, ALT_DMA_PROGRAM_INST_MOD_NONE); + } + if (status == ALT_E_SUCCESS) + { + status = alt_dma_program_DMALPEND(program, ALT_DMA_PROGRAM_INST_MOD_NONE); + } + + if ((status == ALT_E_SUCCESS) && (loopcount > 1)) + { + status = alt_dma_program_DMALPEND(program, ALT_DMA_PROGRAM_INST_MOD_NONE); + } + } + } + + // The super loop above ensures that the length16burst is below 256. + if (length16burst > 0) + { + uint32_t loopcount = length16burst; + length16burst = 0; + + dprintf("DMA[M->R]: Looping %lux 16 burst length transfer(s).\n", loopcount); + + if ((status == ALT_E_SUCCESS) && (loopcount > 1)) + { + status = alt_dma_program_DMALP(program, loopcount); + } + if (status == ALT_E_SUCCESS) + { + status = alt_dma_program_DMALD(program, ALT_DMA_PROGRAM_INST_MOD_NONE); + } + if (status == ALT_E_SUCCESS) + { + status = alt_dma_program_DMAST(program, ALT_DMA_PROGRAM_INST_MOD_NONE); + } + if ((status == ALT_E_SUCCESS) && (loopcount > 1)) + { + status = alt_dma_program_DMALPEND(program, ALT_DMA_PROGRAM_INST_MOD_NONE); + } + } + } + + // At this point, we should have [countleft] transfer(s) remaining. + // [countleft] should be less than 16. + + if (countleft) + { + // Program in the following parameters: + // - SSx (Source burst size of [ccr_ss_ds_mask]) + // - DSx (Destination burst size of [ccr_ss_ds_mask]) + // - DAF (Destination address fixed) + // - SBx (Source burst length of [countleft] transfer(s)) + // - DBx (Destination burst length of [countleft] transfer(s)) + // - All other options default. + + if (status == ALT_E_SUCCESS) + { + dprintf("DMA[M->R]: Tail end %lux transfer(s).\n", countleft); + + status = alt_dma_program_DMAMOV(program, ALT_DMA_PROGRAM_REG_CCR, + ( ccr_ss_ds_mask + | ((countleft - 1) << 4) // SB + | ALT_DMA_CCR_OPT_SA_DEFAULT + | ALT_DMA_CCR_OPT_SP_DEFAULT + | ALT_DMA_CCR_OPT_SC_DEFAULT + | ((countleft - 1) << 18) // DB + | ALT_DMA_CCR_OPT_DAF + | ALT_DMA_CCR_OPT_DP_DEFAULT + | ALT_DMA_CCR_OPT_DC_DEFAULT + | ALT_DMA_CCR_OPT_ES_DEFAULT + ) + ); + } + if (status == ALT_E_SUCCESS) + { + status = alt_dma_program_DMALD(program, ALT_DMA_PROGRAM_INST_MOD_NONE); + } + if (status == ALT_E_SUCCESS) + { + status = alt_dma_program_DMAST(program, ALT_DMA_PROGRAM_INST_MOD_NONE); + } + } + + } // if (count != 0) + + // Send event if requested. + if (send_evt) + { + if (status == ALT_E_SUCCESS) + { + dprintf("DMA[M->R]: Adding event ...\n"); + status = alt_dma_program_DMASEV(program, evt); + } + } + + // Now that everything is done, end the program. + if (status == ALT_E_SUCCESS) + { + dprintf("DMA[M->R]: DMAEND program.\n"); + status = alt_dma_program_DMAEND(program); + } + + // If there was a problem assembling the program, clean up the buffer and exit. + if (status != ALT_E_SUCCESS) + { + // Do not report the status for the clear operation. A failure should be + // reported regardless of if the clear is successful. + alt_dma_program_clear(program); + return status; + } + + // Execute the program on the given channel. + return alt_dma_channel_exec(channel, program); +} + +ALT_STATUS_CODE alt_dma_register_to_memory(ALT_DMA_CHANNEL_t channel, + ALT_DMA_PROGRAM_t * program, + void * dst_buf, + const void * src_reg, + size_t count, + uint32_t register_width_bits, + bool send_evt, + ALT_DMA_EVENT_t evt) +{ + ALT_STATUS_CODE status = ALT_E_SUCCESS; + + // If the count is zero, and no event is requested, just return success. + if ((count == 0) && (send_evt == false)) + { + return status; + } + + if (status == ALT_E_SUCCESS) + { + status = alt_dma_program_init(program); + } + + if (count != 0) + { + // Verify valid register_width_bits and construct the CCR SS and DS parameters. + uint32_t ccr_ss_ds_mask = 0; + + if (status == ALT_E_SUCCESS) + { + switch (register_width_bits) + { + case 8: + // Program in the following parameters: + // - SS8 (Source burst size of 8 bits) + // - DS8 (Destination burst size of 8 bits) + ccr_ss_ds_mask = ALT_DMA_CCR_OPT_SS8 | ALT_DMA_CCR_OPT_DS8; + break; + case 16: + // Program in the following parameters: + // - SS16 (Source burst size of 16 bits) + // - DS16 (Destination burst size of 16 bits) + ccr_ss_ds_mask = ALT_DMA_CCR_OPT_SS16 | ALT_DMA_CCR_OPT_DS16; + break; + case 32: + // Program in the following parameters: + // - SS32 (Source burst size of 32 bits) + // - DS32 (Destination burst size of 32 bits) + ccr_ss_ds_mask = ALT_DMA_CCR_OPT_SS32 | ALT_DMA_CCR_OPT_DS32; + break; + case 64: + // Program in the following parameters: + // - SS64 (Source burst size of 64 bits) + // - DS64 (Destination burst size of 64 bits) + ccr_ss_ds_mask = ALT_DMA_CCR_OPT_SS64 | ALT_DMA_CCR_OPT_DS64; + break; + default: + dprintf("DMA[R->M]: Invalid register width.\n"); + status = ALT_E_BAD_ARG; + break; + } + } + + // Verify that the dst_buf and src_reg are aligned to the register width + if (status == ALT_E_SUCCESS) + { + if (((uintptr_t)dst_buf & ((register_width_bits >> 3) - 1)) != 0) + { + status = ALT_E_BAD_ARG; + } + else if (((uintptr_t)src_reg & ((register_width_bits >> 3) - 1)) != 0) + { + status = ALT_E_BAD_ARG; + } + else + { + dprintf("DMA[R->M]: dst_reg = %p.\n", dst_buf); + dprintf("DMA[R->M]: src_buf = %p.\n", src_reg); + dprintf("DMA[R->M]: count = 0x%x.\n", count); + } + } + + if (status == ALT_E_SUCCESS) + { + status = alt_dma_program_DMAMOV(program, ALT_DMA_PROGRAM_REG_SAR, (uint32_t)src_reg); + } + if (status == ALT_E_SUCCESS) + { + status = alt_dma_program_DMAMOV(program, ALT_DMA_PROGRAM_REG_DAR, (uint32_t)dst_buf); + } + + // This is the remaining count left to process. + uint32_t countleft = count; + + // See how many 16-length bursts we can use + if (countleft >> 4) + { + uint32_t length16burst = countleft >> 4; + countleft &= 0xf; + + dprintf("DMA[R->M]: Number of 16 burst length transfer(s): %lu.\n", length16burst); + dprintf("DMA[R->M]: Number of remaining transfer(s): %lu.\n", countleft); + + // + // The algorithm uses the strategy described in PL330 B.2.3. + // Not sure if registers will accept burst transfers so read the register in its own transfer. + // + + // Program in the following parameters: + // - SAF (Source address fixed) + // - SSx (Source burst size of [ccr_ss_ds_mask]) + // - DSx (Destination burst size of [ccr_ss_ds_mask]) + // - SB16 (Source burst length of 16 transfers) + // - DB16 (Destination burst length of 16 transfers) + // - All other options default. + + if (status == ALT_E_SUCCESS) + { + status = alt_dma_program_DMAMOV(program, ALT_DMA_PROGRAM_REG_CCR, + ( ccr_ss_ds_mask + | ALT_DMA_CCR_OPT_SB16 + | ALT_DMA_CCR_OPT_SAF + | ALT_DMA_CCR_OPT_SP_DEFAULT + | ALT_DMA_CCR_OPT_SC_DEFAULT + | ALT_DMA_CCR_OPT_DB16 + | ALT_DMA_CCR_OPT_DA_DEFAULT + | ALT_DMA_CCR_OPT_DP_DEFAULT + | ALT_DMA_CCR_OPT_DC_DEFAULT + | ALT_DMA_CCR_OPT_ES_DEFAULT + ) + ); + } + + // See how many 256x 16-length bursts we can do + if (length16burst >> 8) + { + uint32_t loop256length16burst = length16burst >> 8; + length16burst &= ((1 << 8) - 1); + + dprintf("DMA[R->M]: Number of 256-looped 16 burst length transfer(s): %lu.\n", loop256length16burst); + dprintf("DMA[R->M]: Number of remaining 16 burst length transfer(s): %lu.\n", length16burst); + + while (loop256length16burst > 0) + { + if (status != ALT_E_SUCCESS) + { + break; + } + + uint32_t loopcount = MIN(loop256length16burst, 256); + loop256length16burst -= loopcount; + + dprintf("DMA[R->M]: Looping %lux super loop transfer(s).\n", loopcount); + + if ((status == ALT_E_SUCCESS) && (loopcount > 1)) + { + status = alt_dma_program_DMALP(program, loopcount); + } + + if (status == ALT_E_SUCCESS) + { + status = alt_dma_program_DMALP(program, 256); + } + if (status == ALT_E_SUCCESS) + { + status = alt_dma_program_DMALD(program, ALT_DMA_PROGRAM_INST_MOD_NONE); + } + if (status == ALT_E_SUCCESS) + { + status = alt_dma_program_DMAST(program, ALT_DMA_PROGRAM_INST_MOD_NONE); + } + if (status == ALT_E_SUCCESS) + { + status = alt_dma_program_DMALPEND(program, ALT_DMA_PROGRAM_INST_MOD_NONE); + } + + if ((status == ALT_E_SUCCESS) && (loopcount > 1)) + { + status = alt_dma_program_DMALPEND(program, ALT_DMA_PROGRAM_INST_MOD_NONE); + } + } + } + + // The super loop above ensures that the length16burst is below 256. + if (length16burst > 0) + { + uint32_t loopcount = length16burst; + length16burst = 0; + + dprintf("DMA[R->M]: Looping %lux 16 burst length transfer(s).\n", loopcount); + + if ((status == ALT_E_SUCCESS) && (loopcount > 1)) + { + status = alt_dma_program_DMALP(program, loopcount); + } + if (status == ALT_E_SUCCESS) + { + status = alt_dma_program_DMALD(program, ALT_DMA_PROGRAM_INST_MOD_NONE); + } + if (status == ALT_E_SUCCESS) + { + status = alt_dma_program_DMAST(program, ALT_DMA_PROGRAM_INST_MOD_NONE); + } + if ((status == ALT_E_SUCCESS) && (loopcount > 1)) + { + status = alt_dma_program_DMALPEND(program, ALT_DMA_PROGRAM_INST_MOD_NONE); + } + } + } + + // At this point, we should have [countleft] transfer(s) remaining. + // [countleft] should be less than 16. + + if (countleft) + { + dprintf("DMA[R->M]: Tail end %lux transfer(s).\n", countleft); + + // Program in the following parameters: + // - SAF (Source address fixed) + // - SSx (Source burst size of [ccr_ss_ds_mask]) + // - DSx (Destination burst size of [ccr_ss_ds_mask]) + // - SBx (Source burst length of [countleft] transfer(s)) + // - DBx (Destination burst length of [countleft] transfer(s)) + // - All other options default. + + if (status == ALT_E_SUCCESS) + { + status = alt_dma_program_DMAMOV(program, ALT_DMA_PROGRAM_REG_CCR, + ( ccr_ss_ds_mask + | ((countleft - 1) << 4) // SB + | ALT_DMA_CCR_OPT_SAF + | ALT_DMA_CCR_OPT_SP_DEFAULT + | ALT_DMA_CCR_OPT_SC_DEFAULT + | ((countleft - 1) << 18) // DB + | ALT_DMA_CCR_OPT_DA_DEFAULT + | ALT_DMA_CCR_OPT_DP_DEFAULT + | ALT_DMA_CCR_OPT_DC_DEFAULT + | ALT_DMA_CCR_OPT_ES_DEFAULT + ) + ); + } + + if (status == ALT_E_SUCCESS) + { + status = alt_dma_program_DMALD(program, ALT_DMA_PROGRAM_INST_MOD_NONE); + } + if (status == ALT_E_SUCCESS) + { + status = alt_dma_program_DMAST(program, ALT_DMA_PROGRAM_INST_MOD_NONE); + } + } + + } // if (count != 0) + + // Send event if requested. + if (send_evt) + { + if (status == ALT_E_SUCCESS) + { + dprintf("DMA[R->M]: Adding event ...\n"); + status = alt_dma_program_DMASEV(program, evt); + } + } + + // Now that everything is done, end the program. + if (status == ALT_E_SUCCESS) + { + status = alt_dma_program_DMAEND(program); + } + + // If there was a problem assembling the program, clean up the buffer and exit. + if (status != ALT_E_SUCCESS) + { + // Do not report the status for the clear operation. A failure should be + // reported regardless of if the clear is successful. + alt_dma_program_clear(program); + return status; + } + + // Execute the program on the given channel. + return alt_dma_channel_exec(channel, program); +} + +#if ALT_DMA_PERIPH_PROVISION_QSPI_SUPPORT +static ALT_STATUS_CODE alt_dma_memory_to_qspi(ALT_DMA_PROGRAM_t * program, + const char * src, + size_t size) +{ + if ((uintptr_t)src & 0x3) + { + return ALT_E_ERROR; + } + + if (size & 0x3) + { + return ALT_E_ERROR; + } + + ///// + + ALT_STATUS_CODE status = ALT_E_SUCCESS; + + if (status == ALT_E_SUCCESS) + { + status = alt_dma_program_DMAMOV(program, ALT_DMA_PROGRAM_REG_DAR, + (uint32_t)ALT_QSPIDATA_ADDR); + } + if (status == ALT_E_SUCCESS) + { + status = alt_dma_program_DMAMOV(program, ALT_DMA_PROGRAM_REG_SAR, + (uint32_t)src); + } + + ///// + + uint32_t dmaper = alt_read_word(ALT_QSPI_DMAPER_ADDR); + uint32_t qspi_single_size_log2 = ALT_QSPI_DMAPER_NUMSGLREQBYTES_GET(dmaper); + uint32_t qspi_burst_size_log2 = ALT_QSPI_DMAPER_NUMBURSTREQBYTES_GET(dmaper); + uint32_t qspi_single_size = 1 << qspi_single_size_log2; + uint32_t qspi_burst_size = 1 << qspi_burst_size_log2; + + dprintf("DMA[M->P][QSPI]: QSPI Single = %lu; Burst = %lu.\n", qspi_single_size, qspi_burst_size); + + // Because single transfers are equal or smaller than burst (and in the + // smaller case, it is always a clean multiple), only the single size + // check is needed for transfer composability. + if (size & (qspi_single_size - 1)) + { + dprintf("DMA[M->P][QSPI]: QSPI DMA size configuration not suitable for transfer request.\n"); + return ALT_E_ERROR; + } + + ///// + + if ((uintptr_t)src & 0x7) + { + // Source address is not 8-byte aligned. Do 1x 32-bit transfer to get it 8-byte aligned. + + dprintf("DMA[M->P][QSPI]: Creating 1x 4-byte aligning transfer.\n"); + + if (status == ALT_E_SUCCESS) + { + status = alt_dma_program_DMAMOV(program, ALT_DMA_PROGRAM_REG_CCR, + ( ALT_DMA_CCR_OPT_SAI + | ALT_DMA_CCR_OPT_SS32 + | ALT_DMA_CCR_OPT_SB1 + | ALT_DMA_CCR_OPT_SP_DEFAULT + | ALT_DMA_CCR_OPT_SC_DEFAULT + | ALT_DMA_CCR_OPT_DAF + | ALT_DMA_CCR_OPT_DS32 + | ALT_DMA_CCR_OPT_DB1 + | ALT_DMA_CCR_OPT_DP_DEFAULT + | ALT_DMA_CCR_OPT_DC_DEFAULT + | ALT_DMA_CCR_OPT_ES_DEFAULT + ) + ); + } + + if (status == ALT_E_SUCCESS) + { + status = alt_dma_program_DMAFLUSHP(program, ALT_DMA_PERIPH_QSPI_FLASH_TX); + } + + if (status == ALT_E_SUCCESS) + { + status = alt_dma_program_DMAWFP(program, ALT_DMA_PERIPH_QSPI_FLASH_TX, ALT_DMA_PROGRAM_INST_MOD_SINGLE); + } + + if (status == ALT_E_SUCCESS) + { + status = alt_dma_program_DMALD(program, ALT_DMA_PROGRAM_INST_MOD_SINGLE); + } + + if (status == ALT_E_SUCCESS) + { + status = alt_dma_program_DMAST(program, ALT_DMA_PROGRAM_INST_MOD_SINGLE); + } + + size -= sizeof(uint32_t); + } + + uint32_t qspi_single_count = 0; + uint32_t qspi_burst_count = size >> qspi_burst_size_log2; + + // Use QSPI burst transfers if: + // - QSPI bursts are larger than QSPI singles [AND] + // - Size is large enough that at least 1 burst will be used. + + if ( (qspi_burst_size_log2 > qspi_single_size_log2) + && (qspi_burst_count != 0) + ) + { + // qspi_burst_count = size >> qspi_burst_size_log2; + qspi_single_count = (size & (qspi_burst_size - 1)) >> qspi_single_size_log2; + + dprintf("DMA[M->P][QSPI][B]: Burst size = %lu bytes, count = %lu.\n", qspi_burst_size, qspi_burst_count); + + // 1 << 3 => 8 bytes => 64 bits, which is the width of the AXI bus. + uint32_t src_size_log2 = MIN(3, qspi_burst_size_log2); + + uint32_t src_length = 0; + uint32_t src_multiple = 0; + + if ((qspi_burst_size >> src_size_log2) <= 16) + { + src_length = qspi_burst_size >> src_size_log2; + src_multiple = 1; + } + else + { + src_length = 16; + src_multiple = (qspi_burst_size >> src_size_log2) >> 4; // divide by 16 + + if (src_multiple == 0) + { + dprintf("DEBUG[QSPI][B]: src_multiple is 0.\n"); + status = ALT_E_ERROR; + } + } + + // uint32_t dst_length = 1; // dst_length is always 1 because the address is fixed. + uint32_t dst_multiple = qspi_burst_size >> 2; // divide by sizeof(uint32_t) + + dprintf("DMA[M->P][QSPI][B]: dst_size = %u bits, dst_length = %u, dst_multiple = %lu.\n", + 32, 1, dst_multiple); + dprintf("DMA[M->P][QSPI][B]: src_size = %u bits, src_length = %lu, src_multiple = %lu.\n", + (1 << src_size_log2) * 8, src_length, src_multiple); + + ///// + + // Program in the following parameters: + // - SAI (Source address increment) + // - SSx (Source burst size of [1 << src_size_log2]-bytes) + // - SBx (Source burst length of [src_length] transfer(s)) + // - DAF (Destination address fixed) + // - DS32 (Destination burst size of 4-bytes) + // - DB1 (Destination burst length of 1 transfer) + // - All other parameters default + + if (status == ALT_E_SUCCESS) + { + status = alt_dma_program_DMAMOV(program, ALT_DMA_PROGRAM_REG_CCR, + ( ALT_DMA_CCR_OPT_SAI + | (src_size_log2 << 1) // SS + | ((src_length - 1) << 4) // SB + | ALT_DMA_CCR_OPT_SP_DEFAULT + | ALT_DMA_CCR_OPT_SC_DEFAULT + | ALT_DMA_CCR_OPT_DAF + | ALT_DMA_CCR_OPT_DS32 + | ALT_DMA_CCR_OPT_DB1 + | ALT_DMA_CCR_OPT_DP_DEFAULT + | ALT_DMA_CCR_OPT_DC_DEFAULT + | ALT_DMA_CCR_OPT_ES_DEFAULT + ) + ); + } + + // NOTE: We do not do the 256x bursts for M->P case because we only + // write up to 256 B at a time. + + while (qspi_burst_count > 0) + { + if (status != ALT_E_SUCCESS) + { + break; + } + + uint32_t loopcount = MIN(qspi_burst_count, 256); + qspi_burst_count -= loopcount; + + dprintf("DMA[M->P][QSPI][B]: Creating %lu burst-type transfer(s).\n", loopcount); + + if ((status == ALT_E_SUCCESS) && (loopcount > 1)) + { + status = alt_dma_program_DMALP(program, loopcount); + } + + if (status == ALT_E_SUCCESS) + { + status = alt_dma_program_DMAFLUSHP(program, ALT_DMA_PERIPH_QSPI_FLASH_TX); + } + if (status == ALT_E_SUCCESS) + { + status = alt_dma_program_DMAWFP(program, ALT_DMA_PERIPH_QSPI_FLASH_TX, ALT_DMA_PROGRAM_INST_MOD_BURST); + } + for (uint32_t j = 0; j < src_multiple; ++j) + { + if (status == ALT_E_SUCCESS) + { + status = alt_dma_program_DMALD(program, ALT_DMA_PROGRAM_INST_MOD_BURST); + } + } + for (uint32_t k = 0; k < dst_multiple; ++k) + { + if (status == ALT_E_SUCCESS) + { + status = alt_dma_program_DMAST(program, ALT_DMA_PROGRAM_INST_MOD_BURST); + } + } + + if ((status == ALT_E_SUCCESS) && (loopcount > 1)) + { + status = alt_dma_program_DMALPEND(program, ALT_DMA_PROGRAM_INST_MOD_NONE); + } + } + } + else + { + qspi_single_count = size >> qspi_single_size_log2; + } + + // Assemble the single portion of the DMA program. + if (qspi_single_count) + { + dprintf("DMA[M->P][QSPI][S]: Single size = %lu bytes, count = %lu.\n", qspi_single_size, qspi_single_count); + + // 1 << 3 => 8 bytes => 64 bits, which is the width of the AXI bus. + uint32_t src_size_log2 = MIN(3, qspi_single_size_log2); + + uint32_t src_length = 0; + uint32_t src_multiple = 0; + + if ((qspi_single_size >> src_size_log2) <= 16) + { + src_length = qspi_single_size >> src_size_log2; + src_multiple = 1; + } + else + { + src_length = 16; + src_multiple = (qspi_single_size >> src_size_log2) >> 4; // divide by 16 + + if (src_multiple == 0) + { + dprintf("DEBUG[QSPI][S]: src_multiple is 0.\n"); + status = ALT_E_ERROR; + } + } + + // uint32_t dst_length = 1; // dst_length is always 1 becaus the address is fixed. + uint32_t dst_multiple = qspi_single_size >> 2; // divide by sizeof(uint32_t) + + dprintf("DMA[M->P][QSPI][S]: dst_size = %u bits, dst_length = %u, dst_multiple = %lu.\n", + 32, 1, dst_multiple); + dprintf("DMA[M->P][QSPI][S]: src_size = %u bits, src_length = %lu, src_multiple = %lu.\n", + (1 <P case because we only + // write up to 256 B at a time. + + while (qspi_single_count > 0) + { + if (status != ALT_E_SUCCESS) + { + break; + } + + uint32_t loopcount = MIN(qspi_single_count, 256); + qspi_single_count -= loopcount; + + dprintf("DMA[M->P][QSPI][S]: Creating %lu single-type transfer(s).\n", loopcount); + + if ((status == ALT_E_SUCCESS) && (loopcount > 1)) + { + status = alt_dma_program_DMALP(program, loopcount); + } + + if (status == ALT_E_SUCCESS) + { + status = alt_dma_program_DMAFLUSHP(program, ALT_DMA_PERIPH_QSPI_FLASH_TX); + } + if (status == ALT_E_SUCCESS) + { + status = alt_dma_program_DMAWFP(program, ALT_DMA_PERIPH_QSPI_FLASH_TX, ALT_DMA_PROGRAM_INST_MOD_SINGLE); + } + for (uint32_t j = 0; j < src_multiple; ++j) + { + if (status == ALT_E_SUCCESS) + { + status = alt_dma_program_DMALD(program, ALT_DMA_PROGRAM_INST_MOD_SINGLE); + } + } + for (uint32_t k = 0; k < dst_multiple; ++k) + { + if (status == ALT_E_SUCCESS) + { + status = alt_dma_program_DMAST(program, ALT_DMA_PROGRAM_INST_MOD_SINGLE); + } + } + + if ((status == ALT_E_SUCCESS) && (loopcount > 1)) + { + status = alt_dma_program_DMALPEND(program, ALT_DMA_PROGRAM_INST_MOD_NONE); + } + } + + } // if (qspi_single_count != 0) + + return status; +} + +static ALT_STATUS_CODE alt_dma_qspi_to_memory(ALT_DMA_PROGRAM_t * program, + char * dst, + size_t size) +{ + if ((uintptr_t)dst & 0x3) + { + return ALT_E_ERROR; + } + + if (size & 0x3) + { + return ALT_E_ERROR; + } + + ///// + + ALT_STATUS_CODE status = ALT_E_SUCCESS; + + if (status == ALT_E_SUCCESS) + { + status = alt_dma_program_DMAMOV(program, ALT_DMA_PROGRAM_REG_DAR, + (uint32_t)dst); + } + if (status == ALT_E_SUCCESS) + { + status = alt_dma_program_DMAMOV(program, ALT_DMA_PROGRAM_REG_SAR, + (uint32_t)ALT_QSPIDATA_ADDR); + } + + ///// + + uint32_t dmaper = alt_read_word(ALT_QSPI_DMAPER_ADDR); + uint32_t qspi_single_size_log2 = ALT_QSPI_DMAPER_NUMSGLREQBYTES_GET(dmaper); + uint32_t qspi_burst_size_log2 = ALT_QSPI_DMAPER_NUMBURSTREQBYTES_GET(dmaper); + uint32_t qspi_single_size = 1 << qspi_single_size_log2; + uint32_t qspi_burst_size = 1 << qspi_burst_size_log2; + + dprintf("DMA[P->M][QSPI]: QSPI Single = %lu; Burst = %lu.\n", qspi_single_size, qspi_burst_size); + + // Because single transfers are equal or smaller than burst (and in the + // smaller case, it is always a clean multiple), only the single size + // check is needed for transfer composability. + if (size & (qspi_single_size - 1)) + { + dprintf("DMA[P->M][QSPI]: QSPI DMA size configuration not suitable for transfer request.\n"); + return ALT_E_ERROR; + } + + ///// + + if ((uintptr_t)dst & 0x7) + { + // Destination address is not 8-byte aligned. Do 1x 32-bit transfer to get it 8-byte aligned. + + dprintf("DMA[P->M][QSPI]: Creating 1x 4-byte aligning transfer.\n"); + + if (status == ALT_E_SUCCESS) + { + status = alt_dma_program_DMAMOV(program, ALT_DMA_PROGRAM_REG_CCR, + ( ALT_DMA_CCR_OPT_SAF + | ALT_DMA_CCR_OPT_SS32 + | ALT_DMA_CCR_OPT_SB1 + | ALT_DMA_CCR_OPT_SP_DEFAULT + | ALT_DMA_CCR_OPT_SC_DEFAULT + | ALT_DMA_CCR_OPT_DAI + | ALT_DMA_CCR_OPT_DS32 + | ALT_DMA_CCR_OPT_DB1 + | ALT_DMA_CCR_OPT_DP_DEFAULT + | ALT_DMA_CCR_OPT_DC_DEFAULT + | ALT_DMA_CCR_OPT_ES_DEFAULT + ) + ); + } + + if (status == ALT_E_SUCCESS) + { + status = alt_dma_program_DMAFLUSHP(program, ALT_DMA_PERIPH_QSPI_FLASH_RX); + } + + if (status == ALT_E_SUCCESS) + { + status = alt_dma_program_DMAWFP(program, ALT_DMA_PERIPH_QSPI_FLASH_RX, ALT_DMA_PROGRAM_INST_MOD_SINGLE); + } + + if (status == ALT_E_SUCCESS) + { + status = alt_dma_program_DMALD(program, ALT_DMA_PROGRAM_INST_MOD_SINGLE); + } + + if (status == ALT_E_SUCCESS) + { + status = alt_dma_program_DMAST(program, ALT_DMA_PROGRAM_INST_MOD_SINGLE); + } + + size -= sizeof(uint32_t); + } + + uint32_t qspi_single_count = 0; + uint32_t qspi_burst_count = size >> qspi_burst_size_log2; + + // Use QSPI burst transfers if: + // - QSPI bursts are larger than QSPI singles [AND] + // - Size is large enough that at least 1 burst will be used. + + if ( (qspi_burst_size_log2 > qspi_single_size_log2) + && (qspi_burst_count != 0) + ) + { + // qspi_burst_count = size >> qspi_burst_size_log2; + qspi_single_count = (size & (qspi_burst_size - 1)) >> qspi_single_size_log2; + + dprintf("DMA[P->M][QSPI][B]: Burst size = %lu bytes, count = %lu.\n", qspi_burst_size, qspi_burst_count); + + // 1 << 3 => 8 bytes => 64 bits, which is the width of the AXI bus. + uint32_t dst_size_log2 = MIN(3, qspi_burst_size_log2); + + uint32_t dst_length = 0; + uint32_t dst_multiple = 0; + + if ((qspi_burst_size >> dst_size_log2) <= 16) + { + dst_length = qspi_burst_size >> dst_size_log2; + dst_multiple = 1; + } + else + { + dst_length = 16; + dst_multiple = (qspi_burst_size >> dst_size_log2) >> 4; // divide by 16 + + if (dst_multiple == 0) + { + dprintf("DEBUG[QSPI][B]: dst_multiple is 0.\n"); + status = ALT_E_ERROR; + } + } + + // uint32_t src_length = 1; // src_length is always 1 because the address is fixed. + uint32_t src_multiple = qspi_burst_size >> 2; // divide by sizeof(uint32_t) + + dprintf("DMA[P->M][QSPI][B]: dst_size = %u bits, dst_length = %lu, dst_multiple = %lu.\n", + (1 << dst_size_log2) * 8, dst_length, dst_multiple); + dprintf("DMA[P->M][QSPI][B]: src_size = %u bits, src_length = %u, src_multiple = %lu.\n", + 32, 1, src_multiple); + + ///// + + // Program in the following parameters: + // - SAF (Source address fixed) + // - SS32 (Source burst size of 4-bytes) + // - SB1 (Source burst length of 1 transfer) + // - DAI (Destination address increment) + // - DSx (Destination burst size of [1 << dst_size_log2]-bytes]) + // - DBx (Destination burst length of [dst_length] transfer(s)) + // - All other parameters default + + if (status == ALT_E_SUCCESS) + { + status = alt_dma_program_DMAMOV(program, ALT_DMA_PROGRAM_REG_CCR, + ( ALT_DMA_CCR_OPT_SAF + | ALT_DMA_CCR_OPT_SS32 + | ALT_DMA_CCR_OPT_SB1 + | ALT_DMA_CCR_OPT_SP_DEFAULT + | ALT_DMA_CCR_OPT_SC_DEFAULT + | ALT_DMA_CCR_OPT_DAI + | (dst_size_log2 << 15) // DS + | ((dst_length - 1) << 18) // DB + | ALT_DMA_CCR_OPT_DP_DEFAULT + | ALT_DMA_CCR_OPT_DC_DEFAULT + | ALT_DMA_CCR_OPT_ES_DEFAULT + ) + ); + } + + // See how many 256x bursts we can construct. This will allow for extremely large requests. + + if (qspi_burst_count >> 8) + { + uint32_t qspi_burst256_count = qspi_burst_count >> 8; + qspi_burst_count &= (1 << 8) - 1; + + while (qspi_burst256_count > 0) + { + if (status != ALT_E_SUCCESS) + { + break; + } + + uint32_t loopcount = MIN(qspi_burst256_count, 256); + qspi_burst256_count -= loopcount; + + dprintf("DMA[P->M][QSPI][B]: Creating %lu 256x burst-type transfer(s).\n", loopcount); + + // Outer loop { + + if ((status == ALT_E_SUCCESS) && (loopcount > 1)) + { + status = alt_dma_program_DMALP(program, loopcount); + } + + // Inner loop { + + if (status == ALT_E_SUCCESS) + { + status = alt_dma_program_DMALP(program, 256); + } + + if (status == ALT_E_SUCCESS) + { + status = alt_dma_program_DMAFLUSHP(program, ALT_DMA_PERIPH_QSPI_FLASH_RX); + } + if (status == ALT_E_SUCCESS) + { + status = alt_dma_program_DMAWFP(program, ALT_DMA_PERIPH_QSPI_FLASH_RX, ALT_DMA_PROGRAM_INST_MOD_BURST); + } + for (uint32_t j = 0; j < src_multiple; ++j) + { + if (status == ALT_E_SUCCESS) + { + status = alt_dma_program_DMALD(program, ALT_DMA_PROGRAM_INST_MOD_BURST); + } + } + for (uint32_t k = 0; k < dst_multiple; ++k) + { + if (status == ALT_E_SUCCESS) + { + status = alt_dma_program_DMAST(program, ALT_DMA_PROGRAM_INST_MOD_BURST); + } + } + + if (status == ALT_E_SUCCESS) + { + status = alt_dma_program_DMALPEND(program, ALT_DMA_PROGRAM_INST_MOD_NONE); + } + + // } Inner loop + + if ((status == ALT_E_SUCCESS) && (loopcount > 1)) + { + status = alt_dma_program_DMALPEND(program, ALT_DMA_PROGRAM_INST_MOD_NONE); + } + + // } Outer loop + } + } + + while (qspi_burst_count > 0) + { + if (status != ALT_E_SUCCESS) + { + break; + } + + uint32_t loopcount = MIN(qspi_burst_count, 256); + qspi_burst_count -= loopcount; + + dprintf("DMA[P->M][QSPI][B]: Creating %lu burst-type transfer(s).\n", loopcount); + + if ((status == ALT_E_SUCCESS) && (loopcount > 1)) + { + status = alt_dma_program_DMALP(program, loopcount); + } + + if (status == ALT_E_SUCCESS) + { + status = alt_dma_program_DMAFLUSHP(program, ALT_DMA_PERIPH_QSPI_FLASH_RX); + } + if (status == ALT_E_SUCCESS) + { + status = alt_dma_program_DMAWFP(program, ALT_DMA_PERIPH_QSPI_FLASH_RX, ALT_DMA_PROGRAM_INST_MOD_BURST); + } + for (uint32_t j = 0; j < src_multiple; ++j) + { + if (status == ALT_E_SUCCESS) + { + status = alt_dma_program_DMALD(program, ALT_DMA_PROGRAM_INST_MOD_BURST); + } + } + for (uint32_t k = 0; k < dst_multiple; ++k) + { + if (status == ALT_E_SUCCESS) + { + status = alt_dma_program_DMAST(program, ALT_DMA_PROGRAM_INST_MOD_BURST); + } + } + + if ((status == ALT_E_SUCCESS) && (loopcount > 1)) + { + status = alt_dma_program_DMALPEND(program, ALT_DMA_PROGRAM_INST_MOD_NONE); + } + } + } + else + { + qspi_single_count = size >> qspi_single_size_log2; + } + + // Assemble the single portion of the DMA program. + if (qspi_single_count) + { + dprintf("DMA[P->M][QSPI][S]: Single size = %lu bytes, count = %lu.\n", qspi_single_size, qspi_single_count); + + // 1 << 3 => 8 bytes => 64 bits, which is the width of the AXI bus. + uint32_t dst_size_log2 = MIN(3, qspi_single_size_log2); + + uint32_t dst_length = 0; + uint32_t dst_multiple = 0; + + if ((qspi_single_size >> dst_size_log2) <= 16) + { + dst_length = qspi_single_size >> dst_size_log2; + dst_multiple = 1; + } + else + { + dst_length = 16; + dst_multiple = (qspi_single_size >> dst_size_log2) >> 4; // divide by 16 + + if (dst_multiple == 0) + { + dprintf("DEBUG[QSPI][S]: dst_multiple is 0.\n"); + status = ALT_E_ERROR; + } + } + + // uint32_t src_length = 1; // src_length is always 1 because the address is fixed. + uint32_t src_multiple = qspi_single_size >> 2; // divide by sizeof(uint32_t) + + dprintf("DMA[P->M][QSPI][S]: dst_size = %u bits, dst_length = %lu, dst_multiple = %lu.\n", + (1 << dst_size_log2) * 8, dst_length, dst_multiple); + dprintf("DMA[P->M][QSPI][S]: src_size = %u bits, src_length = %u, src_multiple = %lu.\n", + 32, 1, src_multiple); + + ///// + + // Program in the following parameters: + // - SAF (Source address fixed) + // - SS32 (Source burst size of 4-bytes) + // - SB1 (Source burst length of 1 transfer) + // - DAI (Destination address increment) + // - DSx (Destination burst size of [1 << dst_size_log2]-bytes]) + // - DBx (Destination burst length of [dst_length] transfer(s)) + // - All other parameters default + + if (status == ALT_E_SUCCESS) + { + status = alt_dma_program_DMAMOV(program, ALT_DMA_PROGRAM_REG_CCR, + ( ALT_DMA_CCR_OPT_SAF + | ALT_DMA_CCR_OPT_SS32 + | ALT_DMA_CCR_OPT_SB1 + | ALT_DMA_CCR_OPT_SP_DEFAULT + | ALT_DMA_CCR_OPT_SC_DEFAULT + | ALT_DMA_CCR_OPT_DAI + | (dst_size_log2 << 15) // DS + | ((dst_length - 1) << 18) // DB + | ALT_DMA_CCR_OPT_DP_DEFAULT + | ALT_DMA_CCR_OPT_DC_DEFAULT + | ALT_DMA_CCR_OPT_ES_DEFAULT + ) + ); + } + + // See how many 256x bursts we can construct. This will allow for extremely large requests. + + if (qspi_single_count >> 8) + { + uint32_t qspi_single256_count = qspi_single_count >> 8; + qspi_single_count &= (1 << 8) - 1; + + while (qspi_single256_count > 0) + { + if (status != ALT_E_SUCCESS) + { + break; + } + + uint32_t loopcount = MIN(qspi_single256_count, 256); + qspi_single256_count -= loopcount; + + dprintf("DMA[P->M][QSPI][S]: Creating %lu 256x single-type transfer(s).\n", loopcount); + + // Outer loop { + + if ((status == ALT_E_SUCCESS) && (loopcount > 1)) + { + status = alt_dma_program_DMALP(program, loopcount); + } + + // Inner loop { + + if (status == ALT_E_SUCCESS) + { + status = alt_dma_program_DMALP(program, 256); + } + + if (status == ALT_E_SUCCESS) + { + status = alt_dma_program_DMAFLUSHP(program, ALT_DMA_PERIPH_QSPI_FLASH_RX); + } + if (status == ALT_E_SUCCESS) + { + status = alt_dma_program_DMAWFP(program, ALT_DMA_PERIPH_QSPI_FLASH_RX, ALT_DMA_PROGRAM_INST_MOD_SINGLE); + } + for (uint32_t j = 0; j < src_multiple; ++j) + { + if (status == ALT_E_SUCCESS) + { + status = alt_dma_program_DMALD(program, ALT_DMA_PROGRAM_INST_MOD_SINGLE); + } + } + for (uint32_t k = 0; k < dst_multiple; ++k) + { + if (status == ALT_E_SUCCESS) + { + status = alt_dma_program_DMAST(program, ALT_DMA_PROGRAM_INST_MOD_SINGLE); + } + } + + if (status == ALT_E_SUCCESS) + { + status = alt_dma_program_DMALPEND(program, ALT_DMA_PROGRAM_INST_MOD_NONE); + } + + // } Inner loop + + if ((status == ALT_E_SUCCESS) && (loopcount > 1)) + { + status = alt_dma_program_DMALPEND(program, ALT_DMA_PROGRAM_INST_MOD_NONE); + } + + // } Outer loop + } + } + + while (qspi_single_count > 0) + { + if (status != ALT_E_SUCCESS) + { + break; + } + + uint32_t loopcount = MIN(qspi_single_count, 256); + qspi_single_count -= loopcount; + + dprintf("DMA[P->M][QSPI][S]: Creating %lu single-type transfer(s).\n", loopcount); + + if ((status == ALT_E_SUCCESS) && (loopcount > 1)) + { + status = alt_dma_program_DMALP(program, loopcount); + } + + if (status == ALT_E_SUCCESS) + { + status = alt_dma_program_DMAFLUSHP(program, ALT_DMA_PERIPH_QSPI_FLASH_RX); + } + if (status == ALT_E_SUCCESS) + { + status = alt_dma_program_DMAWFP(program, ALT_DMA_PERIPH_QSPI_FLASH_RX, ALT_DMA_PROGRAM_INST_MOD_SINGLE); + } + for (uint32_t j = 0; j < src_multiple; ++j) + { + if (status == ALT_E_SUCCESS) + { + status = alt_dma_program_DMALD(program, ALT_DMA_PROGRAM_INST_MOD_SINGLE); + } + } + for (uint32_t k = 0; k < dst_multiple; ++k) + { + if (status == ALT_E_SUCCESS) + { + status = alt_dma_program_DMAST(program, ALT_DMA_PROGRAM_INST_MOD_SINGLE); + } + } + + if ((status == ALT_E_SUCCESS) && (loopcount > 1)) + { + status = alt_dma_program_DMALPEND(program, ALT_DMA_PROGRAM_INST_MOD_NONE); + } + } + + } // if (qspi_single_count != 0) + + return status; +} +#endif // ALT_DMA_PERIPH_PROVISION_QSPI_SUPPORT + +#if ALT_DMA_PERIPH_PROVISION_16550_SUPPORT +static ALT_STATUS_CODE alt_dma_memory_to_16550_single(ALT_DMA_PROGRAM_t * program, + ALT_DMA_PERIPH_t periph, + size_t size) +{ + ALT_STATUS_CODE status = ALT_E_SUCCESS; + + // Program in the following parameters: + // - SS8 (Source burst size of 1-byte) + // - DS8 (Destination burst size of 1-byte) + // - SB1 (Source burst length of 1 transfer) + // - DB1 (Destination burst length of 1 transfer) + // - DAF (Destination address fixed) + // - All other options default. + + if (status == ALT_E_SUCCESS) + { + status = alt_dma_program_DMAMOV(program, ALT_DMA_PROGRAM_REG_CCR, + ( ALT_DMA_CCR_OPT_SB1 + | ALT_DMA_CCR_OPT_SS8 + | ALT_DMA_CCR_OPT_SA_DEFAULT + | ALT_DMA_CCR_OPT_SP_DEFAULT + | ALT_DMA_CCR_OPT_SC_DEFAULT + | ALT_DMA_CCR_OPT_DB1 + | ALT_DMA_CCR_OPT_DS8 + | ALT_DMA_CCR_OPT_DAF + | ALT_DMA_CCR_OPT_DP_DEFAULT + | ALT_DMA_CCR_OPT_DC_DEFAULT + | ALT_DMA_CCR_OPT_ES_DEFAULT + ) + ); + } + + uint32_t sizeleft = size; + + while (sizeleft > 0) + { + if (status != ALT_E_SUCCESS) + { + break; + } + + uint32_t loopcount = MIN(sizeleft, 256); + sizeleft -= loopcount; + + dprintf("DMA[M->P][16550][S]: Creating %lu transfer(s).\n", loopcount); + + if ((status == ALT_E_SUCCESS) && (loopcount > 1)) + { + status = alt_dma_program_DMALP(program, loopcount); + } + + if (status == ALT_E_SUCCESS) + { + status = alt_dma_program_DMAFLUSHP(program, periph); + } + if (status == ALT_E_SUCCESS) + { + status = alt_dma_program_DMAWFP(program, periph, ALT_DMA_PROGRAM_INST_MOD_SINGLE); + } + if (status == ALT_E_SUCCESS) + { + status = alt_dma_program_DMALD(program, ALT_DMA_PROGRAM_INST_MOD_SINGLE); + } + if (status == ALT_E_SUCCESS) + { + status = alt_dma_program_DMAST(program, ALT_DMA_PROGRAM_INST_MOD_SINGLE); + } + + if ((status == ALT_E_SUCCESS) && (loopcount > 1)) + { + status = alt_dma_program_DMALPEND(program, ALT_DMA_PROGRAM_INST_MOD_SINGLE); + } + } + + return status; +} + +static ALT_STATUS_CODE alt_dma_memory_to_16550_burst(ALT_DMA_PROGRAM_t * program, + ALT_DMA_PERIPH_t periph, + size_t burst_size, + size_t burst_count) +{ + ALT_STATUS_CODE status = ALT_E_SUCCESS; + + // Program in the following parameters: + // - SS8 (Source burst size of 1-byte) + // - DS8 (Destination burst size of 1-byte) + // - SB16 (Source burst length of 16 transfers) + // - DB16 (Destination burst length of 16 transfers) + // - DAF (Source address fixed) + // - All other options default. + + if (status == ALT_E_SUCCESS) + { + status = alt_dma_program_DMAMOV(program, ALT_DMA_PROGRAM_REG_CCR, + ( ALT_DMA_CCR_OPT_SB16 + | ALT_DMA_CCR_OPT_SS8 + | ALT_DMA_CCR_OPT_SA_DEFAULT + | ALT_DMA_CCR_OPT_SP_DEFAULT + | ALT_DMA_CCR_OPT_SC_DEFAULT + | ALT_DMA_CCR_OPT_DB16 + | ALT_DMA_CCR_OPT_DS8 + | ALT_DMA_CCR_OPT_DAF + | ALT_DMA_CCR_OPT_DP_DEFAULT + | ALT_DMA_CCR_OPT_DC_DEFAULT + | ALT_DMA_CCR_OPT_ES_DEFAULT + ) + ); + } + + while (burst_count > 0) + { + if (status != ALT_E_SUCCESS) + { + break; + } + + uint32_t loopcount = MIN(burst_count, 256); + burst_count -= loopcount; + + dprintf("DMA[M->P][16550][B]: Creating outer %lu inner loop(s).\n", loopcount); + + // Outer loop { + + if ((status == ALT_E_SUCCESS) && (loopcount > 1)) + { + status = alt_dma_program_DMALP(program, loopcount); + } + if (status == ALT_E_SUCCESS) + { + status = alt_dma_program_DMAFLUSHP(program, periph); + } + if (status == ALT_E_SUCCESS) + { + status = alt_dma_program_DMAWFP(program, periph, ALT_DMA_PROGRAM_INST_MOD_BURST); + } + + // Inner loop { + + // Loop [burst_size / 16] times. The burst_size was trimmed to the + // nearest multiple of 16 by the caller. Each burst does 16 transfers + // hence the need for the divide. + + dprintf("DMA[M->P][16550][B]: Creating inner %u transfer(s).\n", burst_size >> 4); + + if (status == ALT_E_SUCCESS) + { + status = alt_dma_program_DMALP(program, burst_size >> 4); // divide by 16. + } + if (status == ALT_E_SUCCESS) + { + status = alt_dma_program_DMALD(program, ALT_DMA_PROGRAM_INST_MOD_BURST); + } + if (status == ALT_E_SUCCESS) + { + status = alt_dma_program_DMAST(program, ALT_DMA_PROGRAM_INST_MOD_BURST); + } + if (status == ALT_E_SUCCESS) + { + status = alt_dma_program_DMALPEND(program, ALT_DMA_PROGRAM_INST_MOD_BURST); + } + + // } Inner loop + + if ((status == ALT_E_SUCCESS) && (loopcount > 1)) + { + status = alt_dma_program_DMALPEND(program, ALT_DMA_PROGRAM_INST_MOD_BURST); + } + + // } Outer loop + } + + return status; +} + +static ALT_STATUS_CODE alt_dma_memory_to_16550(ALT_DMA_PROGRAM_t * program, + ALT_DMA_PERIPH_t periph, + ALT_16550_HANDLE_t * handle, + const void * src, + size_t size) +{ + ALT_STATUS_CODE status = ALT_E_SUCCESS; + + if (status == ALT_E_SUCCESS) + { + status = alt_dma_program_DMAMOV(program, ALT_DMA_PROGRAM_REG_DAR, + (uint32_t)ALT_UART_RBR_THR_DLL_ADDR(handle->location)); + } + if (status == ALT_E_SUCCESS) + { + status = alt_dma_program_DMAMOV(program, ALT_DMA_PROGRAM_REG_SAR, + (uint32_t)src); + } + + // Determine if FIFOs are enabled from the FCR cache + + if (ALT_UART_FCR_FIFOE_GET(handle->fcr) != 0) + { + dprintf("DMA[M->P][16550]: FIFOs enabled.\n"); + + // + // FIFOs are enabled. + // + + uint32_t tx_size; + uint32_t burst_size; + ALT_16550_FIFO_TRIGGER_TX_t trig_tx; + + // Get the TX FIFO Size + // Use the register interface to avoid coupling the 16550 and DMA. + tx_size = ALT_UART_CPR_FIFO_MOD_GET(alt_read_word(ALT_UART_CPR_ADDR(handle->location))) << 4; + + // Get the TX FIFO Trigger Level from the FCR cache + trig_tx = (ALT_16550_FIFO_TRIGGER_TX_t)ALT_UART_FCR_TET_GET(handle->fcr); + + switch (trig_tx) + { + case ALT_16550_FIFO_TRIGGER_TX_EMPTY: + burst_size = tx_size; + break; + case ALT_16550_FIFO_TRIGGER_TX_ALMOST_EMPTY: + burst_size = tx_size - 2; + break; + case ALT_16550_FIFO_TRIGGER_TX_QUARTER_FULL: + burst_size = 3 * (tx_size >> 2); + break; + case ALT_16550_FIFO_TRIGGER_TX_HALF_FULL: + burst_size = tx_size >> 1; + break; + default: + // This case should never happen. + return ALT_E_ERROR; + } + + if (burst_size < 16) + { + // There's no point bursting 1 byte at a time per notify, so just do single transfers. + if (status == ALT_E_SUCCESS) + { + status = alt_dma_memory_to_16550_single(program, + periph, + size); + } + } + else + { + uint32_t sizeleft = size; + + // Now trip the burst size to a multiple of 16. + // This will optimize the bursting in the fewest possible commands. + dprintf("DMA[M->P][16550]: Untrimmed burst size = %lu.\n", burst_size); + burst_size &= ~0xf; + dprintf("DMA[M->P][16550]: Trimmed burst size = %lu.\n", burst_size); + + // Determine how many burst transfers can be done + uint32_t burst_count = 0; + + burst_count = sizeleft / burst_size; + sizeleft -= burst_count * burst_size; + + if (burst_count == 0) + { + // Do the transfer + if (status == ALT_E_SUCCESS) + { + status = alt_dma_memory_to_16550_single(program, + periph, + sizeleft); + } + } + else + { + // Do the burst transfers + if (status == ALT_E_SUCCESS) + { + status = alt_dma_memory_to_16550_burst(program, + periph, + burst_size, + burst_count); + } + + // Program the DMA engine to transfer the non-burstable items in single tranfers + if (status == ALT_E_SUCCESS) + { + status = alt_dma_memory_to_16550_single(program, + periph, + sizeleft); + } + + } // else if (burst_count == 0) + } + } + else + { + dprintf("DMA[M->P][16550]: FIFOs disabled.\n"); + + // + // FIFOs are disabled. + // + + status = alt_dma_memory_to_16550_single(program, + periph, + size); + } + + return status; +} + +static ALT_STATUS_CODE alt_dma_16550_to_memory_single(ALT_DMA_PROGRAM_t * program, + ALT_DMA_PERIPH_t periph, + size_t size) +{ + ALT_STATUS_CODE status = ALT_E_SUCCESS; + + // Program in the following parameters: + // - SS8 (Source burst size of 1-byte) + // - DS8 (Destination burst size of 1-byte) + // - SB1 (Source burst length of 1 transfer) + // - DB1 (Destination burst length of 1 transfer) + // - SAF (Source address fixed) + // - All other options default. + + if (status == ALT_E_SUCCESS) + { + status = alt_dma_program_DMAMOV(program, ALT_DMA_PROGRAM_REG_CCR, + ( ALT_DMA_CCR_OPT_SB1 + | ALT_DMA_CCR_OPT_SS8 + | ALT_DMA_CCR_OPT_SAF + | ALT_DMA_CCR_OPT_SP_DEFAULT + | ALT_DMA_CCR_OPT_SC_DEFAULT + | ALT_DMA_CCR_OPT_DB1 + | ALT_DMA_CCR_OPT_DS8 + | ALT_DMA_CCR_OPT_DA_DEFAULT + | ALT_DMA_CCR_OPT_DP_DEFAULT + | ALT_DMA_CCR_OPT_DC_DEFAULT + | ALT_DMA_CCR_OPT_ES_DEFAULT + ) + ); + } + + uint32_t sizeleft = size; + + while (sizeleft > 0) + { + if (status != ALT_E_SUCCESS) + { + break; + } + + uint32_t loopcount = MIN(sizeleft, 256); + sizeleft -= loopcount; + + dprintf("DMA[P->M][16550][S]: Creating %lu transfer(s).\n", loopcount); + + if ((status == ALT_E_SUCCESS) && (loopcount > 1)) + { + status = alt_dma_program_DMALP(program, loopcount); + } + if (status == ALT_E_SUCCESS) + { + status = alt_dma_program_DMAFLUSHP(program, periph); + } + if (status == ALT_E_SUCCESS) + { + status = alt_dma_program_DMAWFP(program, periph, ALT_DMA_PROGRAM_INST_MOD_SINGLE); + } + if (status == ALT_E_SUCCESS) + { + status = alt_dma_program_DMALD(program, ALT_DMA_PROGRAM_INST_MOD_SINGLE); + } + if (status == ALT_E_SUCCESS) + { + status = alt_dma_program_DMAST(program, ALT_DMA_PROGRAM_INST_MOD_SINGLE); + } + if ((status == ALT_E_SUCCESS) && (loopcount > 1)) + { + status = alt_dma_program_DMALPEND(program, ALT_DMA_PROGRAM_INST_MOD_SINGLE); + } + } + + return status; +} + +static ALT_STATUS_CODE alt_dma_16550_to_memory_burst(ALT_DMA_PROGRAM_t * program, + ALT_DMA_PERIPH_t periph, + size_t burst_size, + size_t burst_count) +{ + ALT_STATUS_CODE status = ALT_E_SUCCESS; + + // Program in the following parameters: + // - SS8 (Source burst size of 1-byte) + // - DS8 (Destination burst size of 1-byte) + // - SB16 (Source burst length of 16 transfers) + // - DB16 (Destination burst length of 16 transfers) + // - SAF (Source address fixed) + // - All other options default. + + if (status == ALT_E_SUCCESS) + { + status = alt_dma_program_DMAMOV(program, ALT_DMA_PROGRAM_REG_CCR, + ( ALT_DMA_CCR_OPT_SB16 + | ALT_DMA_CCR_OPT_SS8 + | ALT_DMA_CCR_OPT_SAF + | ALT_DMA_CCR_OPT_SP_DEFAULT + | ALT_DMA_CCR_OPT_SC_DEFAULT + | ALT_DMA_CCR_OPT_DB16 + | ALT_DMA_CCR_OPT_DS8 + | ALT_DMA_CCR_OPT_DA_DEFAULT + | ALT_DMA_CCR_OPT_DP_DEFAULT + | ALT_DMA_CCR_OPT_DC_DEFAULT + | ALT_DMA_CCR_OPT_ES_DEFAULT + ) + ); + } + + while (burst_count > 0) + { + if (status != ALT_E_SUCCESS) + { + break; + } + + uint32_t loopcount = MIN(burst_count, 256); + burst_count -= loopcount; + + dprintf("DMA[P->M][16550][B]: Creating outer %lu inner loop(s).\n", loopcount); + + // Outer loop { + + if ((status == ALT_E_SUCCESS) && (loopcount > 1)) + { + status = alt_dma_program_DMALP(program, loopcount); + } + if (status == ALT_E_SUCCESS) + { + status = alt_dma_program_DMAFLUSHP(program, periph); + } + if (status == ALT_E_SUCCESS) + { + status = alt_dma_program_DMAWFP(program, periph, ALT_DMA_PROGRAM_INST_MOD_BURST); + } + + // Inner loop { + + // Loop [burst_size / 16] times. The burst_size was trimmed to the + // nearest multiple of 16 by the caller. Each burst does 16 transfers + // hence the need for the divide. + + dprintf("DMA[P->M][16550][B]: Creating inner %u transfer(s).\n", burst_size >> 4); + + if (status == ALT_E_SUCCESS) + { + status = alt_dma_program_DMALP(program, burst_size >> 4); // divide by 16. + } + if (status == ALT_E_SUCCESS) + { + status = alt_dma_program_DMALD(program, ALT_DMA_PROGRAM_INST_MOD_BURST); + } + if (status == ALT_E_SUCCESS) + { + status = alt_dma_program_DMAST(program, ALT_DMA_PROGRAM_INST_MOD_BURST); + } + if (status == ALT_E_SUCCESS) + { + status = alt_dma_program_DMALPEND(program, ALT_DMA_PROGRAM_INST_MOD_BURST); + } + + // } Inner loop + + if ((status == ALT_E_SUCCESS) && (loopcount > 1)) + { + status = alt_dma_program_DMALPEND(program, ALT_DMA_PROGRAM_INST_MOD_BURST); + } + + // } Outer loop + } + + return status; +} + +static ALT_STATUS_CODE alt_dma_16550_to_memory(ALT_DMA_PROGRAM_t * program, + ALT_DMA_PERIPH_t periph, + ALT_16550_HANDLE_t * handle, + void * dst, + size_t size) +{ + ALT_STATUS_CODE status = ALT_E_SUCCESS; + + if (status == ALT_E_SUCCESS) + { + status = alt_dma_program_DMAMOV(program, ALT_DMA_PROGRAM_REG_DAR, (uint32_t)dst); + } + if (status == ALT_E_SUCCESS) + { + status = alt_dma_program_DMAMOV(program, ALT_DMA_PROGRAM_REG_SAR, (uint32_t)ALT_UART_RBR_THR_DLL_ADDR(handle->location)); + } + + // Determine if FIFOs are enabled from the FCR cache + + if (ALT_UART_FCR_FIFOE_GET(handle->fcr) != 0) + { + dprintf("DMA[P->M][16550]: FIFOs enabled.\n"); + + // + // FIFOs are enabled. + // + + uint32_t rx_size; + uint32_t burst_size; + ALT_16550_FIFO_TRIGGER_RX_t trig_rx; + + // Get the RX FIFO Size + // Use the register interface to avoid coupling the 16550 and DMA. + rx_size = ALT_UART_CPR_FIFO_MOD_GET(alt_read_word(ALT_UART_CPR_ADDR(handle->location))) << 4; + + // Get the RX FIFO Trigger Level from the FCR cache + trig_rx = (ALT_16550_FIFO_TRIGGER_RX_t)ALT_UART_FCR_RT_GET(handle->fcr); + + switch (trig_rx) + { + case ALT_16550_FIFO_TRIGGER_RX_ANY: + burst_size = 1; + break; + case ALT_16550_FIFO_TRIGGER_RX_QUARTER_FULL: + burst_size = rx_size >> 2; // divide by 4 + break; + case ALT_16550_FIFO_TRIGGER_RX_HALF_FULL: + burst_size = rx_size >> 1; // divide by 2 + break; + case ALT_16550_FIFO_TRIGGER_RX_ALMOST_FULL: + burst_size = rx_size - 2; + break; + default: + // This case should never happen. + return ALT_E_ERROR; + } + + if (burst_size < 16) + { + // There's no point bursting 1 byte at a time per notify, so just do single transfers. + if (status == ALT_E_SUCCESS) + { + status = alt_dma_16550_to_memory_single(program, + periph, + size); + } + } + else + { + uint32_t sizeleft = size; + + // Now trim the burst size to a multiple of 16. + // This will optimize the bursting in the fewest possible commands. + dprintf("DMA[P->M][16550]: Untrimmed burst size = %lu.\n", burst_size); + burst_size &= ~0xf; + dprintf("DMA[P->M][16550]: Trimmed burst size = %lu.\n", burst_size); + + // Determine how many burst transfers can be done + uint32_t burst_count = 0; + + burst_count = sizeleft / burst_size; + sizeleft -= burst_count * burst_size; + + if (burst_count == 0) + { + // Do the transfer. + if (status == ALT_E_SUCCESS) + { + status = alt_dma_16550_to_memory_single(program, + periph, + sizeleft); + } + } + else + { + // Do the burst transfers + if (status == ALT_E_SUCCESS) + { + status = alt_dma_16550_to_memory_burst(program, + periph, + burst_size, + burst_count); + } + + // Program the DMA engine to transfer the non-burstable items in single transfers. + if (status == ALT_E_SUCCESS) + { + status = alt_dma_16550_to_memory_single(program, + periph, + sizeleft); + } + + } // if (burst_count == 0) + } + } + else + { + dprintf("DMA[P->M][16550]: FIFOs disabled.\n"); + + // + // FIFOs are disabled. + // + + status = alt_dma_16550_to_memory_single(program, + periph, + size); + } + + return status; +} +#endif // ALT_DMA_PERIPH_PROVISION_16550_SUPPORT + +ALT_STATUS_CODE alt_dma_memory_to_periph(ALT_DMA_CHANNEL_t channel, + ALT_DMA_PROGRAM_t * program, + ALT_DMA_PERIPH_t dstp, + const void * src, + size_t size, + void * periph_info, + bool send_evt, + ALT_DMA_EVENT_t evt) +{ + ALT_STATUS_CODE status = ALT_E_SUCCESS; + + if ((size == 0) && (send_evt == false)) + { + return status; + } + + if (status == ALT_E_SUCCESS) + { + dprintf("DMA[M->P]: Init Program.\n"); + status = alt_dma_program_init(program); + } + + if ((status == ALT_E_SUCCESS) && (size != 0)) + { + switch (dstp) + { +#if ALT_DMA_PERIPH_PROVISION_QSPI_SUPPORT + case ALT_DMA_PERIPH_QSPI_FLASH_TX: + status = alt_dma_memory_to_qspi(program, src, size); + break; +#endif + +#if ALT_DMA_PERIPH_PROVISION_16550_SUPPORT + case ALT_DMA_PERIPH_UART0_TX: + case ALT_DMA_PERIPH_UART1_TX: + status = alt_dma_memory_to_16550(program, dstp, + (ALT_16550_HANDLE_t *)periph_info, src, size); + break; +#endif + + case ALT_DMA_PERIPH_FPGA_0: + case ALT_DMA_PERIPH_FPGA_1: + case ALT_DMA_PERIPH_FPGA_2: + case ALT_DMA_PERIPH_FPGA_3: + case ALT_DMA_PERIPH_FPGA_4: + case ALT_DMA_PERIPH_FPGA_5: + case ALT_DMA_PERIPH_FPGA_6: + case ALT_DMA_PERIPH_FPGA_7: + case ALT_DMA_PERIPH_I2C0_TX: + case ALT_DMA_PERIPH_I2C1_TX: + case ALT_DMA_PERIPH_I2C2_TX: + case ALT_DMA_PERIPH_I2C3_TX: + case ALT_DMA_PERIPH_SPI0_MASTER_TX: + case ALT_DMA_PERIPH_SPI0_SLAVE_TX: + case ALT_DMA_PERIPH_SPI1_MASTER_TX: + case ALT_DMA_PERIPH_SPI1_SLAVE_TX: + + default: + status = ALT_E_BAD_ARG; + break; + } + } + + // Send event if requested. + if (send_evt) + { + if (status == ALT_E_SUCCESS) + { + dprintf("DMA[M->P]: Adding event.\n"); + status = alt_dma_program_DMASEV(program, evt); + } + } + + // Now that everything is done, end the program. + if (status == ALT_E_SUCCESS) + { + status = alt_dma_program_DMAEND(program); + } + + // If there was a problem assembling the program, clean up the buffer and exit. + if (status != ALT_E_SUCCESS) + { + // Do not report the status for the clear operation. A failure should be + // reported regardless of if the clear is successful. + alt_dma_program_clear(program); + return status; + } + + // Execute the program on the given channel. + + return alt_dma_channel_exec(channel, program); +} + +ALT_STATUS_CODE alt_dma_periph_to_memory(ALT_DMA_CHANNEL_t channel, + ALT_DMA_PROGRAM_t * program, + void * dst, + ALT_DMA_PERIPH_t srcp, + size_t size, + void * periph_info, + bool send_evt, + ALT_DMA_EVENT_t evt) +{ + ALT_STATUS_CODE status = ALT_E_SUCCESS; + + if ((size == 0) && (send_evt == false)) + { + return ALT_E_SUCCESS; + } + + if (status == ALT_E_SUCCESS) + { + dprintf("DMA[P->M]: Init Program.\n"); + status = alt_dma_program_init(program); + } + + if ((status == ALT_E_SUCCESS) && (size != 0)) + { + switch (srcp) + { +#if ALT_DMA_PERIPH_PROVISION_QSPI_SUPPORT + case ALT_DMA_PERIPH_QSPI_FLASH_RX: + status = alt_dma_qspi_to_memory(program, dst, size); + break; +#endif + +#if ALT_DMA_PERIPH_PROVISION_16550_SUPPORT + case ALT_DMA_PERIPH_UART0_RX: + case ALT_DMA_PERIPH_UART1_RX: + status = alt_dma_16550_to_memory(program, srcp, + (ALT_16550_HANDLE_t *)periph_info, dst, size); + break; +#endif + + case ALT_DMA_PERIPH_FPGA_0: + case ALT_DMA_PERIPH_FPGA_1: + case ALT_DMA_PERIPH_FPGA_2: + case ALT_DMA_PERIPH_FPGA_3: + case ALT_DMA_PERIPH_FPGA_4: + case ALT_DMA_PERIPH_FPGA_5: + case ALT_DMA_PERIPH_FPGA_6: + case ALT_DMA_PERIPH_FPGA_7: + case ALT_DMA_PERIPH_I2C0_RX: + case ALT_DMA_PERIPH_I2C1_RX: + case ALT_DMA_PERIPH_I2C2_RX: + case ALT_DMA_PERIPH_I2C3_RX: + case ALT_DMA_PERIPH_SPI0_MASTER_RX: + case ALT_DMA_PERIPH_SPI0_SLAVE_RX: + case ALT_DMA_PERIPH_SPI1_MASTER_RX: + case ALT_DMA_PERIPH_SPI1_SLAVE_RX: + + default: + status = ALT_E_BAD_ARG; + break; + } + } + + // Send event if requested. + if (send_evt) + { + if (status == ALT_E_SUCCESS) + { + dprintf("DMA[P->M]: Adding event.\n"); + status = alt_dma_program_DMASEV(program, evt); + } + } + + // Now that everything is done, end the program. + if (status == ALT_E_SUCCESS) + { + status = alt_dma_program_DMAEND(program); + } + + // If there was a problem assembling the program, clean up the buffer and exit. + if (status != ALT_E_SUCCESS) + { + // Do not report the status for the clear operation. A failure should be + // reported regardless of if the clear is successful. + alt_dma_program_clear(program); + return status; + } + + // Execute the program on the given channel. + + return alt_dma_channel_exec(channel, program); +} + +///// + +static bool alt_dma_is_init(void) +{ + uint32_t permodrst = alt_read_word(ALT_RSTMGR_PERMODRST_ADDR); + + if (permodrst & ALT_RSTMGR_PERMODRST_DMA_SET_MSK) + { + return false; + } + else + { + return true; + } +} + +ALT_STATUS_CODE alt_dma_ecc_start(void * block, size_t size) +{ + if (alt_dma_is_init() == false) + { + return ALT_E_ERROR; + } + + if ((uintptr_t)block & (sizeof(uint64_t) - 1)) + { + return ALT_E_ERROR; + } + + // Verify that all channels are either unallocated or allocated and idle. + + for (int i = 0; i < ARRAY_COUNT(channel_info_array); ++i) + { + if (channel_info_array[i].flag & ALT_DMA_CHANNEL_INFO_FLAG_ALLOCED) + { + ALT_DMA_CHANNEL_STATE_t state; + alt_dma_channel_state_get((ALT_DMA_CHANNEL_t)i, &state); + + if (state != ALT_DMA_CHANNEL_STATE_STOPPED) + { + dprintf("DMA[ECC]: Error: Channel %d state is non-stopped (%d).\n", i, (int)state); + return ALT_E_ERROR; + } + } + } + + ///// + + // Enable ECC for DMA RAM + + dprintf("DEBUG[DMA][ECC]: Enable ECC in SysMgr.\n"); + alt_write_word(ALT_SYSMGR_ECC_DMA_ADDR, ALT_SYSMGR_ECC_DMA_EN_SET_MSK); + + // Clear any pending spurious DMA ECC interrupts. + + dprintf("DEBUG[DMA][ECC]: Clear any pending spurious ECC status in SysMgr.\n"); + alt_write_word(ALT_SYSMGR_ECC_DMA_ADDR, + ALT_SYSMGR_ECC_DMA_EN_SET_MSK + | ALT_SYSMGR_ECC_DMA_SERR_SET_MSK + | ALT_SYSMGR_ECC_DMA_DERR_SET_MSK); + + return ALT_E_SUCCESS; +} diff --git a/c/src/lib/libbsp/arm/altera-cyclone-v/hwlib/src/hwmgr/alt_dma_program.c b/c/src/lib/libbsp/arm/altera-cyclone-v/hwlib/src/hwmgr/alt_dma_program.c new file mode 100644 index 0000000000..26de4c7f0c --- /dev/null +++ b/c/src/lib/libbsp/arm/altera-cyclone-v/hwlib/src/hwmgr/alt_dma_program.c @@ -0,0 +1,1064 @@ +/****************************************************************************** + * + * Copyright 2013 Altera Corporation. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED. IN NO + * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + ******************************************************************************/ + +#include "alt_dma_program.h" +#include "alt_cache.h" +#include + +///// + +// NOTE: To enable debugging output, delete the next line and uncomment the +// line after. +#define dprintf(...) +// #define dprintf(fmt, ...) printf(fmt, ##__VA_ARGS__) + +///// + +// +// The following section describes how the bits are used in the "flag" field: +// + +// [17:16] Which loop registers (LOOP0, LOOP1) are currently being used by a +// partially assembled program. LOOP0 is always used before LOOP1. LOOP1 is +// always ended before LOOP0. +#define ALT_DMA_PROGRAM_FLAG_LOOP0 (1UL << 16) +#define ALT_DMA_PROGRAM_FLAG_LOOP1 (1UL << 17) +#define ALT_DMA_PROGRAM_FLAG_LOOP_ALL (ALT_DMA_PROGRAM_FLAG_LOOP0 | ALT_DMA_PROGRAM_FLAG_LOOP1) + +// [18] Flag that marks LOOP0 as a forever loop. Said another way, LOOP0 is +// being used to execute the DMALPFE directive. +#define ALT_DMA_PROGRAM_FLAG_LOOP0_IS_FE (1UL << 18) +// [19] Flag that marks LOOP1 as a forever loop. Said another way, LOOP1 is +// being used to execute the DMALPFE directive. +#define ALT_DMA_PROGRAM_FLAG_LOOP1_IS_FE (1UL << 19) + +// [24] Flag that the first SAR has been programmed. The SAR field is valid and +// is the offset from the start of the buffer where SAR is located. +#define ALT_DMA_PROGRAM_FLAG_SAR (1UL << 24) +// [25] Flag that the first DAR has been programmed. The DAR field is valid and +// is the offset from the start of the buffer where DAR is located. +#define ALT_DMA_PROGRAM_FLAG_DAR (1UL << 25) + +// [31] Flag that marks the last assembled instruction as DMAEND. +#define ALT_DMA_PROGRAM_FLAG_ENDED (1UL << 31) + +///// + +ALT_STATUS_CODE alt_dma_program_init(ALT_DMA_PROGRAM_t * pgm) +{ + // Clear the variables that matter. + pgm->flag = 0; + pgm->code_size = 0; + + // Calculate the cache aligned start location of the buffer. + size_t buffer = (size_t)pgm->program; + size_t offset = ((buffer + ALT_DMA_PROGRAM_CACHE_LINE_SIZE - 1) & ~(ALT_DMA_PROGRAM_CACHE_LINE_SIZE - 1)) - buffer; + + // It is safe to cast to uint16_t because the extra offset can only be up to + // (ALT_DMA_PROGRAM_CACHE_LINE_SIZE - 1) or 31, which is within range of the + // uint16_t. + pgm->buffer_start = (uint16_t)offset; + + return ALT_E_SUCCESS; +} + +ALT_STATUS_CODE alt_dma_program_uninit(ALT_DMA_PROGRAM_t * pgm) +{ + return ALT_E_SUCCESS; +} + +ALT_STATUS_CODE alt_dma_program_clear(ALT_DMA_PROGRAM_t * pgm) +{ + // Clear the variables that matter + pgm->flag = 0; + pgm->code_size = 0; + + return ALT_E_SUCCESS; +} + +__attribute__((weak)) ALT_STATUS_CODE alt_cache_system_clean(void * address, size_t length) +{ + return ALT_E_SUCCESS; +} + +ALT_STATUS_CODE alt_dma_program_validate(const ALT_DMA_PROGRAM_t * pgm) +{ + // Verify that at least one instruction is in the buffer + if (pgm->code_size == 0) + { + return ALT_E_ERROR; + } + + // Verify all loops are completed. + if (pgm->flag & ALT_DMA_PROGRAM_FLAG_LOOP_ALL) + { + return ALT_E_ERROR; + } + + // Verify last item is DMAEND + if (!(pgm->flag & ALT_DMA_PROGRAM_FLAG_ENDED)) + { + return ALT_E_ERROR; + } + + // Sync the DMA program to RAM. + void * vaddr = (void *)((uintptr_t)(pgm->program + pgm->buffer_start) & ~(ALT_CACHE_LINE_SIZE - 1)); + size_t length = (pgm->code_size + ALT_CACHE_LINE_SIZE) & ~(ALT_CACHE_LINE_SIZE - 1); + + dprintf("DEBUG[DMAP]: Program (real) @ %p, length = 0x%x.\n", pgm->program + pgm->buffer_start, pgm->code_size); + dprintf("DEBUG[DMAP]: Clean: addr = %p, length = 0x%x.\n", vaddr, length); + + return alt_cache_system_clean(vaddr, length); +} + +ALT_STATUS_CODE alt_dma_program_progress_reg(ALT_DMA_PROGRAM_t * pgm, + ALT_DMA_PROGRAM_REG_t reg, + uint32_t current, uint32_t * progress) +{ + // Pointer to where the register is initialized in the program buffer. + uint8_t * buffer = NULL; + + switch (reg) + { + case ALT_DMA_PROGRAM_REG_SAR: + if (!(pgm->flag & ALT_DMA_PROGRAM_FLAG_SAR)) + { + return ALT_E_BAD_ARG; + } + buffer = pgm->program + pgm->buffer_start + pgm->sar; + break; + + case ALT_DMA_PROGRAM_REG_DAR: + if (!(pgm->flag & ALT_DMA_PROGRAM_FLAG_DAR)) + { + return ALT_E_BAD_ARG; + } + buffer = pgm->program + pgm->buffer_start + pgm->dar; + break; + + default: + return ALT_E_BAD_ARG; + } + + uint32_t initial = + (buffer[3] << 24) | + (buffer[2] << 16) | + (buffer[1] << 8) | + (buffer[0] << 0); + + *progress = current - initial; + + return ALT_E_SUCCESS; +} + +ALT_STATUS_CODE alt_dma_program_update_reg(ALT_DMA_PROGRAM_t * pgm, + ALT_DMA_PROGRAM_REG_t reg, uint32_t val) +{ + uint8_t * buffer = NULL; + + switch (reg) + { + case ALT_DMA_PROGRAM_REG_SAR: + if (!(pgm->flag & ALT_DMA_PROGRAM_FLAG_SAR)) + { + return ALT_E_BAD_ARG; + } + buffer = pgm->program + pgm->buffer_start + pgm->sar; + break; + + case ALT_DMA_PROGRAM_REG_DAR: + if (!(pgm->flag & ALT_DMA_PROGRAM_FLAG_DAR)) + { + return ALT_E_BAD_ARG; + } + buffer = pgm->program + pgm->buffer_start + pgm->dar; + break; + + default: + return ALT_E_BAD_ARG; + } + + buffer[0] = (uint8_t)((val >> 0) & 0xff); + buffer[1] = (uint8_t)((val >> 8) & 0xff); + buffer[2] = (uint8_t)((val >> 16) & 0xff); + buffer[3] = (uint8_t)((val >> 24) & 0xff); + + return ALT_E_SUCCESS; +} + +ALT_STATUS_CODE alt_dma_program_DMAADDH(ALT_DMA_PROGRAM_t * pgm, + ALT_DMA_PROGRAM_REG_t addr_reg, uint16_t val) +{ + // For information on DMAADDH, see PL330, section 4.3.1. + + // Check for sufficient space in buffer + if ((pgm->code_size + 3) > ALT_DMA_PROGRAM_PROVISION_BUFFER_SIZE) + { + return ALT_E_BUF_OVF; + } + + // Verify valid register; construct instruction modifier. + uint8_t ra_mask = 0; + switch (addr_reg) + { + case ALT_DMA_PROGRAM_REG_SAR: + ra_mask = 0x0; + break; + case ALT_DMA_PROGRAM_REG_DAR: + ra_mask = 0x2; + break; + default: + return ALT_E_BAD_ARG; + } + + // Buffer of where to assemble the instruction. + uint8_t * buffer = pgm->program + pgm->buffer_start + pgm->code_size; + + // Assemble DMAADDH + buffer[0] = 0x54 | ra_mask; + buffer[1] = (uint8_t)(val & 0xff); + buffer[2] = (uint8_t)(val >> 8); + + // Update the code size. + pgm->code_size += 3; + + return ALT_E_SUCCESS; +} + +ALT_STATUS_CODE alt_dma_program_DMAADNH(ALT_DMA_PROGRAM_t * pgm, + ALT_DMA_PROGRAM_REG_t addr_reg, uint16_t val) +{ + // For information on DMAADNH, see PL330, section 4.3.2. + + // Check for sufficient space in buffer + if ((pgm->code_size + 3) > ALT_DMA_PROGRAM_PROVISION_BUFFER_SIZE) + { + return ALT_E_BUF_OVF; + } + + // Verify valid register; construct instruction modifier. + uint8_t ra_mask = 0; + switch (addr_reg) + { + case ALT_DMA_PROGRAM_REG_SAR: + ra_mask = 0x0; + break; + case ALT_DMA_PROGRAM_REG_DAR: + ra_mask = 0x2; + break; + default: + return ALT_E_BAD_ARG; + } + + // Buffer of where to assemble the instruction. + uint8_t * buffer = pgm->program + pgm->buffer_start + pgm->code_size; + + // Assemble DMAADNH + buffer[0] = 0x5c | ra_mask; + buffer[1] = (uint8_t)(val & 0xff); + buffer[2] = (uint8_t)(val >> 8); + + // Update the code size. + pgm->code_size += 3; + + return ALT_E_SUCCESS; +} + +ALT_STATUS_CODE alt_dma_program_DMAEND(ALT_DMA_PROGRAM_t * pgm) +{ + // For information on DMAEND, see PL330, section 4.3.3. + + // Check for sufficient space in buffer + if ((pgm->code_size + 1) > ALT_DMA_PROGRAM_PROVISION_BUFFER_SIZE) + { + return ALT_E_BUF_OVF; + } + + // Buffer of where to assemble the instruction. + uint8_t * buffer = pgm->program + pgm->buffer_start + pgm->code_size; + + // Assemble DMAEND + buffer[0] = 0x00; + + // Update the code size. + pgm->code_size += 1; + + // Mark program as ended. + pgm->flag |= ALT_DMA_PROGRAM_FLAG_ENDED; + + return ALT_E_SUCCESS; +} + +ALT_STATUS_CODE alt_dma_program_DMAFLUSHP(ALT_DMA_PROGRAM_t * pgm, + ALT_DMA_PERIPH_t periph) +{ + // For information on DMAFLUSHP, see PL330, section 4.3.4. + + // Check for sufficient space in buffer + if ((pgm->code_size + 2) > ALT_DMA_PROGRAM_PROVISION_BUFFER_SIZE) + { + return ALT_E_BUF_OVF; + } + + // Verify valid peripheral identifier. + if (periph > ((1 << 5) - 1)) + { + return ALT_E_BAD_ARG; + } + + // Buffer of where to assemble the instruction. + uint8_t * buffer = pgm->program + pgm->buffer_start + pgm->code_size; + + // Assemble DMAFLUSHP + buffer[0] = 0x35; + buffer[1] = (uint8_t)(periph) << 3; + + // Update the code size. + pgm->code_size += 2; + + return ALT_E_SUCCESS; +} + +ALT_STATUS_CODE alt_dma_program_DMAGO(ALT_DMA_PROGRAM_t * pgm, + ALT_DMA_CHANNEL_t channel, uint32_t val, + ALT_DMA_SECURITY_t sec) +{ + // For information on DMAGO, see PL330, section 4.3.5. + + // Check for sufficient space in buffer + if ((pgm->code_size + 6) > ALT_DMA_PROGRAM_PROVISION_BUFFER_SIZE) + { + return ALT_E_BUF_OVF; + } + + // Verify channel + switch (channel) + { + case ALT_DMA_CHANNEL_0: + case ALT_DMA_CHANNEL_1: + case ALT_DMA_CHANNEL_2: + case ALT_DMA_CHANNEL_3: + case ALT_DMA_CHANNEL_4: + case ALT_DMA_CHANNEL_5: + case ALT_DMA_CHANNEL_6: + case ALT_DMA_CHANNEL_7: + break; + default: + return ALT_E_BAD_ARG; + } + + // Verify security; construct ns mask value + uint8_t ns_mask = 0; + switch (sec) + { + case ALT_DMA_SECURITY_DEFAULT: + case ALT_DMA_SECURITY_SECURE: + ns_mask = 0x0; + break; + case ALT_DMA_SECURITY_NONSECURE: + ns_mask = 0x2; + break; + default: + return ALT_E_BAD_ARG; + } + + // Buffer of where to assemble the instruction. + uint8_t * buffer = pgm->program + pgm->buffer_start + pgm->code_size; + + // Assemble DMAGO + buffer[0] = 0xa0 | ns_mask; + buffer[1] = (uint8_t)channel; + buffer[2] = (uint8_t)((val >> 0) & 0xff); + buffer[3] = (uint8_t)((val >> 8) & 0xff); + buffer[4] = (uint8_t)((val >> 16) & 0xff); + buffer[5] = (uint8_t)((val >> 24) & 0xff); + + // Update the code size. + pgm->code_size += 6; + + return ALT_E_SUCCESS; +} + +ALT_STATUS_CODE alt_dma_program_DMAKILL(ALT_DMA_PROGRAM_t * pgm) +{ + // For information on DMAKILL, see PL330, section 4.3.6. + + // Check for sufficient space in buffer + if ((pgm->code_size + 1) > ALT_DMA_PROGRAM_PROVISION_BUFFER_SIZE) + { + return ALT_E_BUF_OVF; + } + + // Buffer of where to assemble the instruction. + uint8_t * buffer = pgm->program + pgm->buffer_start + pgm->code_size; + + // Assemble DMAKILL + buffer[0] = 0x01; + + // Update the code size. + pgm->code_size += 1; + + return ALT_E_SUCCESS; +} + +ALT_STATUS_CODE alt_dma_program_DMALD(ALT_DMA_PROGRAM_t * pgm, + ALT_DMA_PROGRAM_INST_MOD_t mod) +{ + // For information on DMALD, see PL330, section 4.3.7. + + // Check for sufficient space in buffer + if ((pgm->code_size + 1) > ALT_DMA_PROGRAM_PROVISION_BUFFER_SIZE) + { + return ALT_E_BUF_OVF; + } + + // Verify instruction modifier; construct bs, x mask value. + uint8_t bsx_mask = 0; + switch (mod) + { + case ALT_DMA_PROGRAM_INST_MOD_NONE: + bsx_mask = 0x0; + break; + case ALT_DMA_PROGRAM_INST_MOD_SINGLE: + bsx_mask = 0x1; + break; + case ALT_DMA_PROGRAM_INST_MOD_BURST: + bsx_mask = 0x3; + break; + default: + return ALT_E_BAD_ARG; + } + + // Buffer of where to assemble the instruction. + uint8_t * buffer = pgm->program + pgm->buffer_start + pgm->code_size; + + // Assemble DMALD + buffer[0] = 0x04 | bsx_mask; + + // Update the code size. + pgm->code_size += 1; + + return ALT_E_SUCCESS; +} + +ALT_STATUS_CODE alt_dma_program_DMALDP(ALT_DMA_PROGRAM_t * pgm, + ALT_DMA_PROGRAM_INST_MOD_t mod, ALT_DMA_PERIPH_t periph) +{ + // For information on DMALDP, see PL330, section 4.3.8. + + // Check for sufficient space in buffer + if ((pgm->code_size + 2) > ALT_DMA_PROGRAM_PROVISION_BUFFER_SIZE) + { + return ALT_E_BUF_OVF; + } + + // Verify instruction modifier; construct bs mask value. + uint8_t bs_mask = 0; + switch (mod) + { + case ALT_DMA_PROGRAM_INST_MOD_SINGLE: + bs_mask = 0x0; + break; + case ALT_DMA_PROGRAM_INST_MOD_BURST: + bs_mask = 0x2; + break; + default: + return ALT_E_BAD_ARG; + } + + // Verify valid peripheral identifier. + if (periph > ((1 << 5) - 1)) + { + return ALT_E_BAD_ARG; + } + + // Buffer of where to assemble the instruction. + uint8_t * buffer = pgm->program + pgm->buffer_start + pgm->code_size; + + // Assemble DMALDP + buffer[0] = 0x25 | bs_mask; + buffer[1] = (uint8_t)(periph) << 3; + + // Update the code size. + pgm->code_size += 2; + + return ALT_E_SUCCESS; +} + +ALT_STATUS_CODE alt_dma_program_DMALP(ALT_DMA_PROGRAM_t * pgm, + uint32_t iterations) +{ + // For information on DMALP, see PL330, section 4.3.9. + + // Check for sufficient space in buffer + if ((pgm->code_size + 2) > ALT_DMA_PROGRAM_PROVISION_BUFFER_SIZE) + { + return ALT_E_BUF_OVF; + } + + // Verify iterations in range + if ((iterations == 0) || (iterations > 256)) + { + return ALT_E_BAD_ARG; + } + + // Find suitable LOOPx register to use; construct lc mask value. + uint8_t lc_mask = 0; + switch (pgm->flag & ALT_DMA_PROGRAM_FLAG_LOOP_ALL) + { + case 0: // No LOOPx in use. Use LOOP0. + pgm->flag |= ALT_DMA_PROGRAM_FLAG_LOOP0; + pgm->loop0 = pgm->code_size + 2; // This is the first instruction after the DMALP + lc_mask = 0x0; + break; + + case ALT_DMA_PROGRAM_FLAG_LOOP0: // LOOP0 in use. Use LOOP1. + pgm->flag |= ALT_DMA_PROGRAM_FLAG_LOOP1; + pgm->loop1 = pgm->code_size + 2; // This is the first instruction after the DMALP + lc_mask = 0x2; + break; + + case ALT_DMA_PROGRAM_FLAG_LOOP_ALL: // All LOOPx in use. Report error. + return ALT_E_BAD_OPERATION; + + default: // Catastrophic error !!! + return ALT_E_ERROR; + } + + // Buffer of where to assemble the instruction. + uint8_t * buffer = pgm->program + pgm->buffer_start + pgm->code_size; + + // Assemble DMALP + buffer[0] = 0x20 | lc_mask; + buffer[1] = (uint8_t)(iterations - 1); + + // Update the code size. + pgm->code_size += 2; + + return ALT_E_SUCCESS; +} + +ALT_STATUS_CODE alt_dma_program_DMALPEND(ALT_DMA_PROGRAM_t * pgm, + ALT_DMA_PROGRAM_INST_MOD_t mod) +{ + // For information on DMALPEND, see PL330, section 4.3.10. + + // Check for sufficient space in buffer + if ((pgm->code_size + 2) > ALT_DMA_PROGRAM_PROVISION_BUFFER_SIZE) + { + return ALT_E_BUF_OVF; + } + + // Verify instruction modifier; construct bs, x mask value. + uint8_t bsx_mask = 0; + switch (mod) + { + case ALT_DMA_PROGRAM_INST_MOD_NONE: + bsx_mask = 0x0; + break; + case ALT_DMA_PROGRAM_INST_MOD_SINGLE: + bsx_mask = 0x1; + break; + case ALT_DMA_PROGRAM_INST_MOD_BURST: + bsx_mask = 0x3; + break; + default: + return ALT_E_BAD_ARG; + } + + // Determine the loop to end, if it is a forever loop; construct lc mask, nf mask, and backwards jump value. + uint8_t lc_mask = 0; + uint8_t nf_mask = 0; + uint16_t backwards_jump = 0; + switch (pgm->flag & ALT_DMA_PROGRAM_FLAG_LOOP_ALL) + { + case ALT_DMA_PROGRAM_FLAG_LOOP0: // LOOP0 in use. End LOOP0. + + backwards_jump = pgm->code_size - pgm->loop0; + + pgm->flag &= ~ALT_DMA_PROGRAM_FLAG_LOOP0; + pgm->loop0 = 0; + + lc_mask = 0x0; + + if (pgm->flag & ALT_DMA_PROGRAM_FLAG_LOOP0_IS_FE) + { + pgm->flag &= ~ALT_DMA_PROGRAM_FLAG_LOOP0_IS_FE; + } + else + { + nf_mask = 0x10; + } + break; + + case ALT_DMA_PROGRAM_FLAG_LOOP_ALL: // All LOOPx in use. End LOOP1. + + backwards_jump = pgm->code_size - pgm->loop1; + + pgm->flag &= ~ALT_DMA_PROGRAM_FLAG_LOOP1; + pgm->loop1 = 0; + + lc_mask = 0x4; + + if (pgm->flag & ALT_DMA_PROGRAM_FLAG_LOOP1_IS_FE) + { + pgm->flag &= ~ALT_DMA_PROGRAM_FLAG_LOOP1_IS_FE; + } + else + { + nf_mask = 0x10; + } + break; + + case 0: // No LOOPx in use. Report error! + return ALT_E_BAD_OPERATION; + + default: // Catastrophic error !!! + return ALT_E_ERROR; + } + + // Verify that the jump size is suitable + if (backwards_jump > 255) + { + return ALT_E_ARG_RANGE; + } + + // Buffer of where to assemble the instruction. + uint8_t * buffer = pgm->program + pgm->buffer_start + pgm->code_size; + + // Assemble DMALPEND + buffer[0] = 0x28 | nf_mask | lc_mask | bsx_mask; + buffer[1] = (uint8_t)(backwards_jump); + + // Update the code size. + pgm->code_size += 2; + + return ALT_E_SUCCESS; +} + +ALT_STATUS_CODE alt_dma_program_DMALPFE(ALT_DMA_PROGRAM_t * pgm) +{ + // For information on DMALPFE, see PL330, section 4.3.11. + + // Find suitable LOOPx register to use; + switch (pgm->flag & ALT_DMA_PROGRAM_FLAG_LOOP_ALL) + { + case 0: // No LOOPx in use. Use LOOP0. + pgm->flag |= ALT_DMA_PROGRAM_FLAG_LOOP0; + pgm->flag |= ALT_DMA_PROGRAM_FLAG_LOOP0_IS_FE; + pgm->loop0 = pgm->code_size; + break; + + case ALT_DMA_PROGRAM_FLAG_LOOP0: // LOOP0 in use. Use LOOP1. + pgm->flag |= ALT_DMA_PROGRAM_FLAG_LOOP1; + pgm->flag |= ALT_DMA_PROGRAM_FLAG_LOOP1_IS_FE; + pgm->loop1 = pgm->code_size; + break; + + case ALT_DMA_PROGRAM_FLAG_LOOP_ALL: // All LOOPx in use. Report error. + return ALT_E_BAD_OPERATION; + + default: // Catastrophic error !!! + return ALT_E_ERROR; + } + + // Nothing to assemble. + + return ALT_E_SUCCESS; +} + +ALT_STATUS_CODE alt_dma_program_DMAMOV(ALT_DMA_PROGRAM_t * pgm, + ALT_DMA_PROGRAM_REG_t chan_reg, uint32_t val) +{ + // For information on DMAMOV, see PL330, section 4.3.12. + + // Check for sufficient space in buffer + if ((pgm->code_size + 6) > ALT_DMA_PROGRAM_PROVISION_BUFFER_SIZE) + { + return ALT_E_BUF_OVF; + } + + // Verify channel register; construct rd mask value + uint8_t rd_mask = 0; + switch (chan_reg) + { + case ALT_DMA_PROGRAM_REG_SAR: + rd_mask = 0; + // If SAR has not been set before, mark the location of where SAR is in the buffer. + if (!(pgm->flag & ALT_DMA_PROGRAM_FLAG_SAR)) + { + pgm->flag |= ALT_DMA_PROGRAM_FLAG_SAR; + pgm->sar = pgm->code_size + 2; + } + break; + + case ALT_DMA_PROGRAM_REG_CCR: + rd_mask = 1; + break; + + case ALT_DMA_PROGRAM_REG_DAR: + rd_mask = 2; + // If DAR has not been set before, mark the location of where DAR is in the buffer. + if (!(pgm->flag & ALT_DMA_PROGRAM_FLAG_DAR)) + { + pgm->flag |= ALT_DMA_PROGRAM_FLAG_DAR; + pgm->dar = pgm->code_size + 2; + } + break; + + default: + return ALT_E_BAD_ARG; + } + + // Buffer of where to assemble the instruction. + uint8_t * buffer = pgm->program + pgm->buffer_start + pgm->code_size; + + // Assemble DMAMOV + buffer[0] = 0xbc;; + buffer[1] = rd_mask; + buffer[2] = (uint8_t)((val >> 0) & 0xff); + buffer[3] = (uint8_t)((val >> 8) & 0xff); + buffer[4] = (uint8_t)((val >> 16) & 0xff); + buffer[5] = (uint8_t)((val >> 24) & 0xff); + + // Update the code size. + pgm->code_size += 6; + + return ALT_E_SUCCESS; + +} + +ALT_STATUS_CODE alt_dma_program_DMANOP(ALT_DMA_PROGRAM_t * pgm) +{ + // For information on DMANOP, see PL330, section 4.3.13. + + // Check for sufficient space in buffer + if ((pgm->code_size + 1) > ALT_DMA_PROGRAM_PROVISION_BUFFER_SIZE) + { + return ALT_E_BUF_OVF; + } + + // Buffer of where to assemble the instruction. + uint8_t * buffer = pgm->program + pgm->buffer_start + pgm->code_size; + + // Assemble DMANOP + buffer[0] = 0x18; + + // Update the code size. + pgm->code_size += 1; + + return ALT_E_SUCCESS; +} + +ALT_STATUS_CODE alt_dma_program_DMARMB(ALT_DMA_PROGRAM_t * pgm) +{ + // For information on DMARMB, see PL330, section 4.3.14. + + // Check for sufficient space in buffer + if ((pgm->code_size + 1) > ALT_DMA_PROGRAM_PROVISION_BUFFER_SIZE) + { + return ALT_E_BUF_OVF; + } + + // Buffer of where to assemble the instruction. + uint8_t * buffer = pgm->program + pgm->buffer_start + pgm->code_size; + + // Assemble DMARMB + buffer[0] = 0x12; + + // Update the code size. + pgm->code_size += 1; + + return ALT_E_SUCCESS; +} + +ALT_STATUS_CODE alt_dma_program_DMASEV(ALT_DMA_PROGRAM_t * pgm, + ALT_DMA_EVENT_t evt) +{ + // For information on DMA, see PL330, section 4.3.15. + + // Check for sufficient space in buffer + if ((pgm->code_size + 2) > ALT_DMA_PROGRAM_PROVISION_BUFFER_SIZE) + { + return ALT_E_BUF_OVF; + } + + // Validate evt selection + switch (evt) + { + case ALT_DMA_EVENT_0: + case ALT_DMA_EVENT_1: + case ALT_DMA_EVENT_2: + case ALT_DMA_EVENT_3: + case ALT_DMA_EVENT_4: + case ALT_DMA_EVENT_5: + case ALT_DMA_EVENT_6: + case ALT_DMA_EVENT_7: + case ALT_DMA_EVENT_ABORT: + break; + default: + return ALT_E_BAD_ARG; + } + + // Buffer of where to assemble the instruction. + uint8_t * buffer = pgm->program + pgm->buffer_start + pgm->code_size; + + // Assemble DMASEV + buffer[0] = 0x34; + buffer[1] = (uint8_t)(evt) << 3; + + // Update the code size. + pgm->code_size += 2; + + return ALT_E_SUCCESS; +} + +ALT_STATUS_CODE alt_dma_program_DMAST(ALT_DMA_PROGRAM_t * pgm, + ALT_DMA_PROGRAM_INST_MOD_t mod) +{ + // For information on DMAST, see PL330, section 4.3.16. + + // Check for sufficient space in buffer + if ((pgm->code_size + 1) > ALT_DMA_PROGRAM_PROVISION_BUFFER_SIZE) + { + return ALT_E_BUF_OVF; + } + + // Verify instruction modifier; construct bs, x mask value. + uint8_t bsx_mask = 0; + switch (mod) + { + case ALT_DMA_PROGRAM_INST_MOD_NONE: + bsx_mask = 0x0; + break; + case ALT_DMA_PROGRAM_INST_MOD_SINGLE: + bsx_mask = 0x1; + break; + case ALT_DMA_PROGRAM_INST_MOD_BURST: + bsx_mask = 0x3; + break; + default: + return ALT_E_BAD_ARG; + } + + // Buffer of where to assemble the instruction. + uint8_t * buffer = pgm->program + pgm->buffer_start + pgm->code_size; + + // Assemble DMAST + buffer[0] = 0x08 | bsx_mask; + + // Update the code size. + pgm->code_size += 1; + + return ALT_E_SUCCESS; +} + +ALT_STATUS_CODE alt_dma_program_DMASTP(ALT_DMA_PROGRAM_t * pgm, + ALT_DMA_PROGRAM_INST_MOD_t mod, ALT_DMA_PERIPH_t periph) +{ + // For information on DMASTP, see PL330, section 4.3.17. + + // Check for sufficient space in buffer + if ((pgm->code_size + 2) > ALT_DMA_PROGRAM_PROVISION_BUFFER_SIZE) + { + return ALT_E_BUF_OVF; + } + + // Verify instruction modifier; construct bs mask value. + uint8_t bs_mask = 0; + switch (mod) + { + case ALT_DMA_PROGRAM_INST_MOD_SINGLE: + bs_mask = 0x0; + break; + case ALT_DMA_PROGRAM_INST_MOD_BURST: + bs_mask = 0x2; + break; + default: + return ALT_E_BAD_ARG; + } + + // Verify valid peripheral identifier. + if (periph > ((1 << 5) - 1)) + { + return ALT_E_BAD_ARG; + } + + // Buffer of where to assemble the instruction. + uint8_t * buffer = pgm->program + pgm->buffer_start + pgm->code_size; + + // Assemble DMASTP + buffer[0] = 0x29 | bs_mask; + buffer[1] = (uint8_t)(periph) << 3; + + // Update the code size. + pgm->code_size += 2; + + return ALT_E_SUCCESS; +} + +ALT_STATUS_CODE alt_dma_program_DMASTZ(ALT_DMA_PROGRAM_t * pgm) +{ + // For information on DMASTZ, see PL330, section 4.3.18. + + // Check for sufficient space in buffer + if ((pgm->code_size + 1) > ALT_DMA_PROGRAM_PROVISION_BUFFER_SIZE) + { + return ALT_E_BUF_OVF; + } + + // Buffer of where to assemble the instruction. + uint8_t * buffer = pgm->program + pgm->buffer_start + pgm->code_size; + + // Assemble DMASTZ + buffer[0] = 0x0c; + + // Update the code size. + pgm->code_size += 1; + + return ALT_E_SUCCESS; +} + +ALT_STATUS_CODE alt_dma_program_DMAWFE(ALT_DMA_PROGRAM_t * pgm, + ALT_DMA_EVENT_t evt, bool invalid) +{ + // For information on DMAWFE, see PL330, section 4.3.19. + + // Check for sufficient space in buffer + if ((pgm->code_size + 2) > ALT_DMA_PROGRAM_PROVISION_BUFFER_SIZE) + { + return ALT_E_BUF_OVF; + } + + // Validate evt selection + switch (evt) + { + case ALT_DMA_EVENT_0: + case ALT_DMA_EVENT_1: + case ALT_DMA_EVENT_2: + case ALT_DMA_EVENT_3: + case ALT_DMA_EVENT_4: + case ALT_DMA_EVENT_5: + case ALT_DMA_EVENT_6: + case ALT_DMA_EVENT_7: + case ALT_DMA_EVENT_ABORT: + break; + default: + return ALT_E_BAD_ARG; + } + + // Construct i mask value + uint8_t i_mask = 0; + if (invalid) + { + i_mask = 0x2; + } + + // Buffer of where to assemble the instruction. + uint8_t * buffer = pgm->program + pgm->buffer_start + pgm->code_size; + + // Assemble DMAWFE + buffer[0] = 0x36; + buffer[1] = ((uint8_t)(evt) << 3) | i_mask; + + // Update the code size. + pgm->code_size += 2; + + return ALT_E_SUCCESS; +} + +ALT_STATUS_CODE alt_dma_program_DMAWFP(ALT_DMA_PROGRAM_t * pgm, + ALT_DMA_PERIPH_t periph, ALT_DMA_PROGRAM_INST_MOD_t mod) +{ + // For information on DMAWFP, see PL330, section 4.3.20. + + // Check for sufficient space in buffer + if ((pgm->code_size + 2) > ALT_DMA_PROGRAM_PROVISION_BUFFER_SIZE) + { + return ALT_E_BUF_OVF; + } + + // Verify valid peripheral identifier. + if (periph > ((1 << 5) - 1)) + { + return ALT_E_BAD_ARG; + } + + // Verify instruction modifier; construct bs, p mask value. + uint8_t bsp_mask = 0; + switch (mod) + { + case ALT_DMA_PROGRAM_INST_MOD_SINGLE: + bsp_mask = 0x0; + break; + case ALT_DMA_PROGRAM_INST_MOD_BURST: + bsp_mask = 0x2; + break; + case ALT_DMA_PROGRAM_INST_MOD_PERIPH: + bsp_mask = 0x1; + break; + default: + return ALT_E_BAD_ARG; + } + + // Buffer of where to assemble the instruction. + uint8_t * buffer = pgm->program + pgm->buffer_start + pgm->code_size; + + // Assemble DMAWFP + buffer[0] = 0x30 | bsp_mask; + buffer[1] = (uint8_t)(periph) << 3; + + // Update the code size. + pgm->code_size += 2; + + return ALT_E_SUCCESS; +} + +ALT_STATUS_CODE alt_dma_program_DMAWMB(ALT_DMA_PROGRAM_t * pgm) +{ + // For information on DMAWMB, see PL330, section 4.3.21. + + // Check for sufficient space in buffer + if ((pgm->code_size + 1) > ALT_DMA_PROGRAM_PROVISION_BUFFER_SIZE) + { + return ALT_E_BUF_OVF; + } + + // Buffer of where to assemble the instruction. + uint8_t * buffer = pgm->program + pgm->buffer_start + pgm->code_size; + + // Assemble DMAWMB + buffer[0] = 0x13; + + // Update the code size. + pgm->code_size += 1; + + return ALT_E_SUCCESS; +} diff --git a/c/src/lib/libbsp/arm/altera-cyclone-v/hwlib/src/hwmgr/alt_qspi.c b/c/src/lib/libbsp/arm/altera-cyclone-v/hwlib/src/hwmgr/alt_qspi.c new file mode 100644 index 0000000000..458ef71f46 --- /dev/null +++ b/c/src/lib/libbsp/arm/altera-cyclone-v/hwlib/src/hwmgr/alt_qspi.c @@ -0,0 +1,2619 @@ +/****************************************************************************** +* +* alt_qspi.c - API for the Altera SoC FPGA QSPI device. +* +******************************************************************************/ + +/****************************************************************************** + * + * Copyright 2013 Altera Corporation. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED. IN NO + * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT + * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY + * OF SUCH DAMAGE. + * + ******************************************************************************/ + +#include +#include +#include +#include "hwlib.h" +#include "alt_clock_manager.h" +#include "alt_qspi.h" +#include "alt_qspi_private.h" +#include "socal/alt_qspi.h" +#include "socal/alt_rstmgr.h" +#include "socal/alt_sysmgr.h" +#include "socal/hps.h" +#include "socal/socal.h" + +///// + +// NOTE: To enable debugging output, delete the next line and uncomment the +// line after. +#define dprintf(...) +// #define dprintf printf + +///// + +#define MIN(a, b) ((a) > (b) ? (b) : (a)) + +// qspi_clk operating frequency range. +#define ALT_QSPI_CLK_FREQ_MIN ((alt_freq_t)0) +#define ALT_QSPI_CLK_FREQ_MAX ((alt_freq_t)432000000) + +// The set of all valid QSPI controller interrupt status mask values. +#define ALT_QSPI_INT_STATUS_ALL ( \ + ALT_QSPI_INT_STATUS_MODE_FAIL | \ + ALT_QSPI_INT_STATUS_UFL | \ + ALT_QSPI_INT_STATUS_IDAC_OP_COMPLETE | \ + ALT_QSPI_INT_STATUS_IDAC_OP_REJECT | \ + ALT_QSPI_INT_STATUS_WR_PROT_VIOL | \ + ALT_QSPI_INT_STATUS_ILL_AHB_ACCESS | \ + ALT_QSPI_INT_STATUS_IDAC_WTRMK_TRIG | \ + ALT_QSPI_INT_STATUS_RX_OVF | \ + ALT_QSPI_INT_STATUS_TX_FIFO_NOT_FULL | \ + ALT_QSPI_INT_STATUS_TX_FIFO_FULL | \ + ALT_QSPI_INT_STATUS_RX_FIFO_NOT_EMPTY | \ + ALT_QSPI_INT_STATUS_RX_FIFO_FULL | \ + ALT_QSPI_INT_STATUS_IDAC_RD_FULL \ + ) + +static uint32_t qspi_device_size = 0; + +///// + +static ALT_STATUS_CODE alt_qspi_device_status(uint32_t * status) +{ + // Read flag status register through STIG + return alt_qspi_stig_rd_cmd(ALT_QSPI_STIG_OPCODE_RDSR, 0, 1, status, 10000); +} + +#if ALT_QSPI_PROVISION_MICRON_N25Q_SUPPORT +static ALT_STATUS_CODE alt_qspi_N25Q_device_flag(uint32_t * flagsr) +{ + if (qspi_device_size < 0x4000000) + { + return ALT_E_SUCCESS; + } + + // Read flag status register through STIG + return alt_qspi_stig_rd_cmd(ALT_QSPI_STIG_OPCODE_RDFLGSR, 0, 1, flagsr, 10000); +} + +// NOTE: This must be called after QSPI has been enabled. Communications with +// the device will not happen until QSPI is enabled. +static inline ALT_STATUS_CODE alt_qspi_N25Q_enable(void) +{ + ALT_STATUS_CODE status = ALT_E_SUCCESS; + + // Reset the volatile memory on the N25Q + + if (status == ALT_E_SUCCESS) + { + status = alt_qspi_stig_cmd(ALT_QSPI_STIG_OPCODE_RESET_EN, 0, 10000); + } + + if (status == ALT_E_SUCCESS) + { + status = alt_qspi_stig_cmd(ALT_QSPI_STIG_OPCODE_RESET_MEM, 0, 10000); + } + + ///// + + if (status == ALT_E_SUCCESS) + { + ALT_QSPI_DEV_INST_CONFIG_t cfg = + { + .op_code = ALT_QSPI_STIG_OPCODE_FASTREAD_QUAD_IO, + .inst_type = ALT_QSPI_MODE_SINGLE, // RDID does not support QUAD. + .addr_xfer_type = ALT_QSPI_MODE_QUAD, + .data_xfer_type = ALT_QSPI_MODE_QUAD, + .dummy_cycles = 10 + }; + + status = alt_qspi_device_read_config_set(&cfg); + } + +/* + // CASE 157096: Investigate using QUAD for writes. + if (status == ALT_E_SUCCESS) + { + ALT_QSPI_DEV_INST_CONFIG_t cfg = + { + .op_code = ALT_QSPI_STIG_OPCODE_PP, + .inst_type = ALT_QSPI_MODE_SINGLE, + .addr_xfer_type = ALT_QSPI_MODE_QUAD, + .data_xfer_type = ALT_QSPI_MODE_QUAD, + .dummy_cycles = 0 + }; + + status = alt_qspi_device_write_config_set(&cfg); + } +*/ + + return status; +} + +static ALT_STATUS_CODE alt_qspi_N25Q_flag_wait_for_program(uint32_t timeout) +{ + // The flag status register is only available on the 512 Mib and 1 Gib + // (64 MiB and 128 MiB) Micron parts. + if (qspi_device_size < 0x4000000) + { + return ALT_E_SUCCESS; + } + + ALT_STATUS_CODE status = ALT_E_SUCCESS; + + uint32_t time_out = timeout; + uint32_t stat = 0; + bool infinite = (timeout == ALT_QSPI_TIMEOUT_INFINITE); + + do + { + status = alt_qspi_device_status(&stat); + if (status != ALT_E_SUCCESS) + { + break; + } + if (!ALT_QSPI_STIG_SR_BUSY_GET(stat)) + { + break; + } + } + while (time_out-- || infinite); + + if (time_out == (uint32_t)-1 && !infinite) + { + status = ALT_E_TMO; + } + + if (status == ALT_E_SUCCESS) + { + uint32_t flagsr = 0; + + do + { + status = alt_qspi_N25Q_device_flag(&flagsr); + if (status != ALT_E_SUCCESS) + { + break; + } + if (ALT_QSPI_STIG_FLAGSR_PROGRAMREADY_GET(flagsr)) + { + break; + } + } + while (timeout-- || infinite); + + if (timeout == (uint32_t)-1 && !infinite) + { + status = ALT_E_TMO; + } + + if (status == ALT_E_SUCCESS) + { + if (ALT_QSPI_STIG_FLAGSR_PROGRAMERROR_GET(flagsr)) + { + status = ALT_E_ERROR; + } + } + } + return status; +} + +static ALT_STATUS_CODE alt_qspi_N25Q_flag_wait_for_erase(uint32_t timeout) +{ + // The flag status register is only available on the 512 Mib and 1 Gib + // (64 MiB and 128 MiB) Micron parts. + if (qspi_device_size < 0x4000000) + { + return ALT_E_SUCCESS; + } + + ALT_STATUS_CODE status = ALT_E_SUCCESS; + + uint32_t time_out = timeout; + uint32_t stat = 0; + bool infinite = (timeout == ALT_QSPI_TIMEOUT_INFINITE); + + do + { + status = alt_qspi_device_status(&stat); + if (status != ALT_E_SUCCESS) + { + break; + } + if (!ALT_QSPI_STIG_SR_BUSY_GET(stat)) + { + break; + } + } + while (time_out-- || infinite); + + if (time_out == (uint32_t)-1 && !infinite) + { + status = ALT_E_TMO; + } + + if (status == ALT_E_SUCCESS) + { + + uint32_t flagsr = 0; + + do + { + status = alt_qspi_N25Q_device_flag(&flagsr); + if (status != ALT_E_SUCCESS) + { + break; + } + if (ALT_QSPI_STIG_FLAGSR_ERASEREADY_GET(flagsr)) + { + break; + } + } + while (timeout-- || infinite); + + if (timeout == (uint32_t)-1 && !infinite) + { + status = ALT_E_TMO; + } + + if (status == ALT_E_SUCCESS) + { + if (ALT_QSPI_STIG_FLAGSR_ERASEERROR_GET(flagsr)) + { + status = ALT_E_ERROR; + } + } + } + + return status; +} +#endif + +// +// A helper function which converts a ns interval into a delay interval for a given MHz. +// The +999 is there to round up the result. +// +static inline int alt_qspi_ns_to_multiplier(int ns, int mhz) +{ + return ((ns * mhz) + 999) / 1000; +} + +ALT_STATUS_CODE alt_qspi_init(void) +{ + ALT_STATUS_CODE status = ALT_E_SUCCESS; + alt_freq_t qspi_clk_freq = 0; + + // Validate QSPI module input clocks. + // - pclk - l4_mp_clk + // - hclk - l4_mp_clk + // - ref_clk - qspi_clk + + // Check and validate the QSPI ref_clk which is connected to the HPS qspi_clk. + if (status == ALT_E_SUCCESS) + { + if (alt_clk_is_enabled(ALT_CLK_QSPI) != ALT_E_TRUE) + { + status = ALT_E_BAD_CLK; + } + } + + if (status == ALT_E_SUCCESS) + { + status = alt_clk_freq_get(ALT_CLK_QSPI, &qspi_clk_freq); + if (status == ALT_E_SUCCESS) + { + if (qspi_clk_freq > ALT_QSPI_CLK_FREQ_MAX) + { + return ALT_E_BAD_CLK; + } + } + } + + int qspi_clk_mhz = qspi_clk_freq / 1000000; + + ///// + + // Take QSPI controller out of reset. + alt_clrbits_word(ALT_RSTMGR_PERMODRST_ADDR, ALT_RSTMGR_PERMODRST_QSPI_SET_MSK); + + ///// + + // Configure the device timing + + if (status == ALT_E_SUCCESS) + { + ALT_QSPI_TIMING_CONFIG_t timing_cfg = + { + .clk_phase = (ALT_QSPI_CLK_PHASE_t)ALT_QSPI_CFG_SELCLKPHASE_RESET, + .clk_pol = (ALT_QSPI_CLK_POLARITY_t)ALT_QSPI_CFG_SELCLKPOL_RESET, + .cs_da = alt_qspi_ns_to_multiplier(ALT_QSPI_TSHSL_NS_DEF, qspi_clk_mhz), + .cs_dads = alt_qspi_ns_to_multiplier(ALT_QSPI_TSD2D_NS_DEF, qspi_clk_mhz), + .cs_eot = alt_qspi_ns_to_multiplier(ALT_QSPI_TCHSH_NS_DEF, qspi_clk_mhz), + .cs_sot = alt_qspi_ns_to_multiplier(ALT_QSPI_TSLCH_NS_DEF, qspi_clk_mhz), + .rd_datacap = 1 + }; + + dprintf("DEBUG[QSPI]: cs_da = %" PRIu32 ".\n", timing_cfg.cs_da); + dprintf("DEBUG[QSPI]: cs_dads = %" PRIu32 ".\n", timing_cfg.cs_dads); + dprintf("DEBUG[QSPI]: cs_eot = %" PRIu32 ".\n", timing_cfg.cs_eot); + dprintf("DEBUG[QSPI]: cs_sot = %" PRIu32 ".\n", timing_cfg.cs_sot); + + status = alt_qspi_timing_config_set(&timing_cfg); + } + + ///// + + // Configure the remap address register, no remap + + if (status == ALT_E_SUCCESS) + { + status = alt_qspi_ahb_remap_address_set(0); + } + + // Configure the interrupt mask register, disabled all first + + if (status == ALT_E_SUCCESS) + { + status = alt_qspi_int_disable(ALT_QSPI_INT_STATUS_ALL); + } + + // Configure the baud rate divisor + // CASE 157095: Investigate using 108 MHz, and tweaking the rd_datacap param. + + if (status == ALT_E_SUCCESS) + { + uint32_t device_sclk_mhz = 54; + uint32_t div_actual = (qspi_clk_mhz + (device_sclk_mhz - 1)) / device_sclk_mhz; + dprintf("DEBUG[QSPI]: div_actual = %" PRIu32 ".\n", div_actual); + + ALT_QSPI_BAUD_DIV_t div_bits = (ALT_QSPI_BAUD_DIV_t)(((div_actual + 1) / 2) - 1); + status = alt_qspi_baud_rate_div_set(div_bits); + } + + return status; +} + +ALT_STATUS_CODE alt_qspi_uninit(void) +{ + // Put QSPI controller into reset. + alt_setbits_word(ALT_RSTMGR_PERMODRST_ADDR, ALT_RSTMGR_PERMODRST_QSPI_SET_MSK); + + return ALT_E_SUCCESS; +} + +ALT_STATUS_CODE alt_qspi_disable(void) +{ + alt_clrbits_word(ALT_QSPI_CFG_ADDR, ALT_QSPI_CFG_EN_SET_MSK); + + return ALT_E_SUCCESS; +} + +ALT_STATUS_CODE alt_qspi_enable(void) +{ + alt_setbits_word(ALT_QSPI_CFG_ADDR, ALT_QSPI_CFG_EN_SET_MSK); + + ALT_STATUS_CODE status = ALT_E_SUCCESS; + + ///// + + // Device specific configuration + +#if ALT_QSPI_PROVISION_MICRON_N25Q_SUPPORT + if (status == ALT_E_SUCCESS) + { + status = alt_qspi_N25Q_enable(); + } +#endif + + uint32_t rdid = 0; + + // Query device capabilities + // This requires QSPI to be enabled. + + if (status == ALT_E_SUCCESS) + { + status = alt_qspi_device_rdid(&rdid); + } + + if (status == ALT_E_SUCCESS) + { + // NOTE: The size code seems to be a form of BCD (binary coded decimal). + // The first nibble is the 10's digit and the second nibble is the 1's + // digit in the number of bytes. + + // Capacity ID samples: + // 0x15 : 16 Mb => 2 MiB => 1 << 21 ; BCD=15 + // 0x16 : 32 Mb => 4 MiB => 1 << 22 ; BCD=16 + // 0x17 : 64 Mb => 8 MiB => 1 << 23 ; BCD=17 + // 0x18 : 128 Mb => 16 MiB => 1 << 24 ; BCD=18 + // 0x19 : 256 Mb => 32 MiB => 1 << 25 ; BCD=19 + // 0x1a + // 0x1b + // 0x1c + // 0x1d + // 0x1e + // 0x1f + // 0x20 : 512 Mb => 64 MiB => 1 << 26 ; BCD=20 + // 0x21 : 1024 Mb => 128 MiB => 1 << 27 ; BCD=21 + + int cap_code = ALT_QSPI_STIG_RDID_CAPACITYID_GET(rdid); + + if ( ((cap_code >> 4) > 0x9) || ((cap_code & 0xf) > 0x9)) + { + // If a non-valid BCD value is detected at the top or bottom nibble, chances + // are that the chip has a problem. + + dprintf("DEBUG[QSPI]: Invalid CapacityID encountered: 0x%02x.\n", cap_code); + status = ALT_E_ERROR; + } + else + { + int cap_decoded = ((cap_code >> 4) * 10) + (cap_code & 0xf); + + qspi_device_size = 1 << (cap_decoded + 6); + + dprintf("DEBUG[QSPI]: Device size = 0x%" PRIx32 ".\n", qspi_device_size); + } + } + + // Configure the device size and address bytes + + if (status == ALT_E_SUCCESS) + { + ALT_QSPI_DEV_SIZE_CONFIG_t size_cfg = + { + .block_size = ALT_QSPI_DEVSZ_BYTESPERSUBSECTOR_RESET, // 0x10 => 2^16 = 64 KiB + .page_size = ALT_QSPI_DEVSZ_BYTESPERDEVICEPAGE_RESET, // 0x100 => 256 B + .addr_size = ALT_QSPI_DEVSZ_NUMADDRBYTES_RESET, // 0x2 => 3 bytes or 0x00ffffff mask. + .lower_wrprot_block = 0, + .upper_wrprot_block = (qspi_device_size - 1) >> 16, + .wrprot_enable = ALT_QSPI_WRPROT_EN_RESET + }; + + status = alt_qspi_device_size_config_set(&size_cfg); + } + + ///// + + // Configure the DMA parameters + + // This will allow DMA to work well without much intervention by users. + + if (status == ALT_E_SUCCESS) + { + status = alt_qspi_dma_config_set(4, 32); + } + + ///// + + return status; +} + +///// + +uint32_t alt_qspi_int_status_get(void) +{ + // Read and return the value of the QSPI controller Interrupt Status + // Register (irqstat). + return alt_read_word(ALT_QSPI_IRQSTAT_ADDR); +} + +ALT_STATUS_CODE alt_qspi_int_clear(const uint32_t mask) +{ + // Check that the [mask] contains valid interrupt status conditions values. + if ((ALT_QSPI_INT_STATUS_ALL & mask) == 0) + { + return ALT_E_BAD_ARG; + } + + // Write 1's to clear the desired interrupt status condition(s). + alt_write_word(ALT_QSPI_IRQSTAT_ADDR, mask); + + return ALT_E_SUCCESS; +} + +ALT_STATUS_CODE alt_qspi_int_disable(const uint32_t mask) +{ + if (alt_qspi_is_idle() == false) + { + return ALT_E_ERROR; + } + + // Check that the [mask] contains valid interrupt status conditions values. + if ((ALT_QSPI_INT_STATUS_ALL & mask) == 0) + { + return ALT_E_BAD_ARG; + } + + // Write 0's to disable the desired interrupt status condition(s). + alt_clrbits_word(ALT_QSPI_IRQMSK_ADDR, mask); + + return ALT_E_SUCCESS; +} + +ALT_STATUS_CODE alt_qspi_int_enable(const uint32_t mask) +{ + if (alt_qspi_is_idle() == false) + { + return ALT_E_ERROR; + } + + // Check that the [mask] contains valid interrupt status conditions values. + if ((ALT_QSPI_INT_STATUS_ALL & mask) == 0) + { + return ALT_E_BAD_ARG; + } + + // Write 1's to enable the desired interrupt status condition(s). + alt_setbits_word(ALT_QSPI_IRQMSK_ADDR, mask); + + return ALT_E_SUCCESS; +} + +///// + +bool alt_qspi_is_idle(void) +{ + // If the idle field of the QSPI configuration register is 1 then the serial + // interface and QSPI pipeline is idle. + return ALT_QSPI_CFG_IDLE_GET(alt_read_word(ALT_QSPI_CFG_ADDR)) == 1; +} + +///// + +static ALT_STATUS_CODE alt_qspi_indirect_write_start_bank(uint32_t dst, size_t length); + +static ALT_STATUS_CODE alt_qspi_indirect_page_bound_write_helper(uint32_t dst, const char * src, size_t length) +{ + ALT_STATUS_CODE status = ALT_E_SUCCESS; + + if (status == ALT_E_SUCCESS) + { + status = alt_qspi_indirect_write_start_bank(dst, length); + } + + if (status == ALT_E_SUCCESS) + { + uint32_t write_count = 0; + uint32_t write_capacity = ALT_QSPI_SRAM_FIFO_ENTRY_COUNT - alt_qspi_sram_partition_get(); + + while (write_count < length) + { + uint32_t space = write_capacity - alt_qspi_indirect_write_fill_level(); + space = MIN(space, (length - write_count)/ sizeof(uint32_t)); + + const uint32_t * data = (const uint32_t *)(src + write_count); + for (uint32_t i = 0; i < space; ++i) + { + alt_write_word(ALT_QSPIDATA_ADDR, *data++); + } + + write_count += space * sizeof(uint32_t); + } + } + + if (status == ALT_E_SUCCESS) + { + status = alt_qspi_indirect_write_finish(); + } + + return status; +} + +static ALT_STATUS_CODE alt_qspi_indirect_subsector_aligned_write_helper(const char * data, uint32_t subsec_addr) +{ + ALT_STATUS_CODE status = ALT_E_SUCCESS; + + for (int i = 0; i < ALT_QSPI_SUBSECTOR_SIZE / ALT_QSPI_PAGE_SIZE; i++) + { + int offset = i * ALT_QSPI_PAGE_SIZE; + + status = alt_qspi_indirect_page_bound_write_helper(subsec_addr + offset, data + offset, ALT_QSPI_PAGE_SIZE); + if (status != ALT_E_SUCCESS) + { + break; + } + } + + return status; +} + +static ALT_STATUS_CODE alt_qspi_indirect_read_start_bank(uint32_t src, size_t size); + +// +// This helper function reads a segment of data, which is limited to 1 bank +// (24 bits of addressing). +// +static ALT_STATUS_CODE alt_qspi_read_bank(char * dst, uint32_t src, size_t size) +{ + ALT_STATUS_CODE status = ALT_E_SUCCESS; + + if (status == ALT_E_SUCCESS) + { + status = alt_qspi_indirect_read_start_bank(src, size); + } + + if (status == ALT_E_SUCCESS) + { + uint32_t read_count = 0; + + while (!alt_qspi_indirect_read_is_complete()) + { + uint32_t level = alt_qspi_indirect_read_fill_level(); +// level = MIN(level, (size - read_count) / sizeof(uint32_t)); + + uint32_t * data = (uint32_t *)(dst + read_count); + for (uint32_t i = 0; i < level; ++i) + { + *data++ = alt_read_word(ALT_QSPIDATA_ADDR); + } + + read_count += level * sizeof(uint32_t); + } + } + + if (status == ALT_E_SUCCESS) + { + status = alt_qspi_indirect_read_finish(); + } + + return status; +} + +ALT_STATUS_CODE alt_qspi_read(void * dst, uint32_t src, size_t size) +{ + if (src >= qspi_device_size) + { + return ALT_E_ERROR; + } + + if (src + size - 1 >= qspi_device_size) + { + return ALT_E_ERROR; + } + + if (size == 0) + { + return ALT_E_SUCCESS; + } + + if ((uintptr_t)dst & 0x3) + { + return ALT_E_ERROR; + } + + if (src & 0x3) + { + return ALT_E_ERROR; + } + + if (size & 0x3) + { + return ALT_E_ERROR; + } + + ///// + + // Verify that there is not already a read in progress. + if (ALT_QSPI_INDRD_RD_STAT_GET(alt_read_word(ALT_QSPI_INDRD_ADDR))) + { + return ALT_E_ERROR; + } + + ///// + + ALT_STATUS_CODE status = ALT_E_SUCCESS; + + // + // bank_count : The number of bank(s) affected, including partial banks. + // bank_addr : The aligned address of the first affected bank, including partial bank(s). + // bank_ofst : The offset of the bank to read. Only used when reading the first bank. + // + uint32_t bank_count = ((src + size - 1) >> 24) - (src >> 24) + 1; + uint32_t bank_addr = src & ALT_QSPI_BANK_ADDR_MSK; + uint32_t bank_ofst = src & (ALT_QSPI_BANK_SIZE - 1); + + char * data = (char *)dst; + + uint32_t copy_length = MIN(size, ALT_QSPI_BANK_SIZE - bank_ofst); + + dprintf("DEBUG[QSPI]: read(): bulk: mem_addr = %p; flash_addr = 0x%" PRIx32 ".\n", data, src); + dprintf("DEBUG[QSPI]: read(): bulk: bank_count = 0x%" PRIx32 ", bank_ofst = 0x%" PRIx32 ".\n", bank_count, bank_ofst); + + for (uint32_t i = 0; i < bank_count; ++i) + { + dprintf("DEBUG[QSPI]: read(): bank 0x%" PRIx32 "; copy_length = 0x%" PRIx32 ".\n", bank_addr >> 24, copy_length); + + status = alt_qspi_device_bank_select(bank_addr >> 24); + if (status != ALT_E_SUCCESS) + { + break; + } + + status = alt_qspi_read_bank(dst, bank_ofst, copy_length); + if (status != ALT_E_SUCCESS) + { + break; + } + + bank_addr += ALT_QSPI_BANK_SIZE; + data += copy_length; + size -= copy_length; + + copy_length = MIN(size, ALT_QSPI_BANK_SIZE); + } + + return status; +} + +static ALT_STATUS_CODE alt_qspi_write_bank(uint32_t dst, const char * src, size_t size) +{ + ALT_STATUS_CODE status = ALT_E_SUCCESS; + + ///// + + uint32_t page_ofst = dst & (ALT_QSPI_PAGE_SIZE - 1); + uint32_t write_size = MIN(size, ALT_QSPI_PAGE_SIZE - page_ofst); + + while (size) + { + dprintf("DEBUG[QSPI]: write(): flash dst = 0x%" PRIx32 ", mem src = %p, write size = 0x%" PRIx32 ", size left = 0x%x.\n", dst, src, write_size, size); + + status = alt_qspi_indirect_page_bound_write_helper(dst, src, write_size); + if (status != ALT_E_SUCCESS) + { + break; + } + + dst += write_size; + src += write_size; + size -= write_size; + + write_size = MIN(size, ALT_QSPI_PAGE_SIZE); + } + + return status; +} + +ALT_STATUS_CODE alt_qspi_write(uint32_t dst, const void * src, size_t size) +{ + if (dst >= qspi_device_size) + { + return ALT_E_ERROR; + } + + if (dst + size - 1 >= qspi_device_size) + { + return ALT_E_ERROR; + } + + if (size == 0) + { + return ALT_E_SUCCESS; + } + + if ((uintptr_t)src & 0x3) + { + return ALT_E_ERROR; + } + + if (dst & 0x3) + { + return ALT_E_ERROR; + } + + if (size & 0x3) + { + return ALT_E_ERROR; + } + + ///// + + // Verify that there is not already a write in progress. + if (ALT_QSPI_INDWR_RDSTAT_GET(alt_read_word(ALT_QSPI_INDWR_ADDR))) + { + return ALT_E_ERROR; + } + + ///// + + ALT_STATUS_CODE status = ALT_E_SUCCESS; + + uint32_t bank_count = ((dst + size - 1) >> 24) - (dst >> 24) + 1; + uint32_t bank_addr = dst & ALT_QSPI_BANK_ADDR_MSK; + uint32_t bank_ofst = dst & (ALT_QSPI_BANK_SIZE - 1); + + const char * data = src; + + uint32_t copy_length = MIN(size, ALT_QSPI_BANK_SIZE - bank_ofst); + + dprintf("DEBUG[QSPI]: write(): bulk: flash_addr = 0x%" PRIx32 "; mem_addr = %p.\n", dst, data); + dprintf("DEBUG[QSPI]: write(): bulk: bank_count = 0x%" PRIx32 ", bank_ofst = 0x%" PRIx32 ".\n", bank_count, bank_ofst); + + for (uint32_t i = 0; i < bank_count; ++i) + { + dprintf("DEBUG[QSPI]: write(): bank 0x%" PRIx32 "; copy_length = 0x%" PRIx32 ".\n", bank_addr >> 24, copy_length); + + status = alt_qspi_device_bank_select(bank_addr >> 24); + if (status != ALT_E_SUCCESS) + { + break; + } + + status = alt_qspi_write_bank(bank_ofst, data, copy_length); + if (status != ALT_E_SUCCESS) + { + break; + } + + bank_addr += ALT_QSPI_BANK_SIZE; + data += copy_length; + size -= copy_length; + + copy_length = MIN(size, ALT_QSPI_BANK_SIZE); + } + + return status; +} + +static ALT_STATUS_CODE alt_qspi_erase_subsector_bank(uint32_t addr); + +static ALT_STATUS_CODE alt_qspi_replace_bank(uint32_t dst, const char * src, size_t size) +{ + ALT_STATUS_CODE status = ALT_E_SUCCESS; + + // + // subsec_count : The total number of affected subsector(s), + // including partial subsector(s). + // subsec_addr : The aligned address of the next affected subsector, + // including partial subsector(s). + // subsec_partial_head : The number of subsector unaligned data to be + // written out at the start of the flash write + // request. This data ends at the end of the subsector + // or earlier depending on the number of data to be + // written. + // subsec_partial_tail : The number of subsector unaligned data to be + // written out at the end of the flash write request. + // This data starts at the start of the subsector. If + // only a single subsector is written (partial or + // full), this value will be zero. + // + + uint32_t subsec_count = ((dst + size - 1) >> 12) - (dst >> 12) + 1; + uint32_t subsec_addr = dst & ALT_QSPI_SUBSECTOR_ADDR_MSK; + + uint32_t subsec_partial_head = MIN(ALT_QSPI_SUBSECTOR_SIZE - (dst & (ALT_QSPI_SUBSECTOR_SIZE - 1)), size) & (ALT_QSPI_SUBSECTOR_SIZE - 1); + uint32_t subsec_partial_tail = (size - subsec_partial_head) & (ALT_QSPI_SUBSECTOR_SIZE - 1); + + dprintf("DEBUG[QSPI]: replace(): report: dst = 0x%" PRIx32 "; size = 0x%x.\n", + dst, size); + dprintf("DEBUG[QSPI]: replace(): report: subsec_count = 0x%" PRIx32 "; subsec_addr = 0x%" PRIx32 ".\n", + subsec_count, subsec_addr); + dprintf("DEBUG[QSPI]: replace(): report: partial_head = 0x%" PRIx32 "; partial_tail = 0x%" PRIx32 ".\n", + subsec_partial_head, subsec_partial_tail); + + // Write the first subsector, partial case. + + if (subsec_partial_head) + { + // The write request is not aligned to a subsector so we must do the + // Read-Modify-Write cycle to preserve the existing data at the head of + // the subsector not affected by the write. + + char subsec_buf[ALT_QSPI_SUBSECTOR_SIZE]; + + uint32_t subsec_ofst = dst & ~ALT_QSPI_SUBSECTOR_ADDR_MSK; + + // - Read the subsector into buffer + // - Erase that subsector + // - Copy in the user data into buffer + // - Write out buffer to subsector + + if (status == ALT_E_SUCCESS) + { + status = alt_qspi_read_bank(subsec_buf, subsec_addr, subsec_ofst); + } + if (status == ALT_E_SUCCESS) + { + status = alt_qspi_erase_subsector_bank(subsec_addr); + } + if (status == ALT_E_SUCCESS) + { + memcpy(subsec_buf + subsec_ofst, src, subsec_partial_head); + status = alt_qspi_indirect_subsector_aligned_write_helper(subsec_buf, subsec_addr); + } + + // Do some bookkeeping on the user buffer information + src += subsec_partial_head; + size -= subsec_partial_head; + + // Do some bookkeeping on the subsector tracking + subsec_count--; + subsec_addr += ALT_QSPI_SUBSECTOR_SIZE; + + dprintf("DEBUG[QSPI]: replace(): partial head: subsec_ofst = 0x%" PRIx32 "; size left = 0x%x; status = %" PRIi32 ".\n", + subsec_ofst, size, status); + } + + // If there is a partial tail, then take 1 off the subsec_count. This way + // the following loop will write out all the complete subsectors. The tail + // will be written out afterwards. + + if (subsec_partial_tail) + { + subsec_count--; + } + + // Write the aligned subsectors following any partial subsectors. + + for (uint32_t i = 0; i < subsec_count; ++i) + { + // - Erase subsector + // - Write out buffer to subsector + + if (status == ALT_E_SUCCESS) + { + status = alt_qspi_erase_subsector_bank(subsec_addr); + } + if (status == ALT_E_SUCCESS) + { + status = alt_qspi_indirect_subsector_aligned_write_helper(src, subsec_addr); + } + + src += ALT_QSPI_SUBSECTOR_SIZE; + size -= ALT_QSPI_SUBSECTOR_SIZE; + + // Don't modify subsec_count as it's being used by the loop. + subsec_addr += ALT_QSPI_SUBSECTOR_SIZE; + + dprintf("DEBUG[QSPI]: replace(): subsec aligned: size left = 0x%x, status = %" PRIi32 ".\n", + size, status); + } + + // Write the last subsector, partial case. + + if (subsec_partial_tail) + { + // The write request is not aligned to a subsector so we must do the + // Read-Modify-Write cycle to preserve the existing data at the end of + // the subsector not affected by the write. + + char subsec_buf[ALT_QSPI_SUBSECTOR_SIZE]; + + // - Read the subsector into buffer + // - Erase that subsector + // - Copy in the user data into buffer + // - Write out buffer to subsector + + if (status == ALT_E_SUCCESS) + { + status = alt_qspi_read_bank(subsec_buf + subsec_partial_tail, + subsec_addr + subsec_partial_tail, + ALT_QSPI_SUBSECTOR_SIZE - subsec_partial_tail); + } + if (status == ALT_E_SUCCESS) + { + status = alt_qspi_erase_subsector_bank(subsec_addr); + } + if (status == ALT_E_SUCCESS) + { + memcpy(subsec_buf, src, subsec_partial_tail); + status = alt_qspi_indirect_subsector_aligned_write_helper(subsec_buf, subsec_addr); + } + + src += subsec_partial_tail; + size -= subsec_partial_tail; + + dprintf("DEBUG[QSPI]: replace(): partial tail: size left = 0x%x, status = %" PRIi32 ".\n", + size, status); + } + + return status; +} + +ALT_STATUS_CODE alt_qspi_replace(uint32_t dst, const void * src, size_t size) +{ + if (dst >= qspi_device_size) + { + return ALT_E_ERROR; + } + + if (dst + size - 1 >= qspi_device_size) + { + return ALT_E_ERROR; + } + + if (size == 0) + { + return ALT_E_SUCCESS; + } + + if ((uintptr_t)src & 0x3) + { + return ALT_E_ERROR; + } + + if (dst & 0x3) + { + return ALT_E_ERROR; + } + + if (size & 0x3) + { + return ALT_E_ERROR; + } + + ///// + + // Verify that there is not already a read in progress. + if (ALT_QSPI_INDRD_RD_STAT_GET(alt_read_word(ALT_QSPI_INDRD_ADDR))) + { + return ALT_E_ERROR; + } + + // Verify that there is not already a write in progress. + if (ALT_QSPI_INDWR_RDSTAT_GET(alt_read_word(ALT_QSPI_INDWR_ADDR))) + { + return ALT_E_ERROR; + } + + ///// + + ALT_STATUS_CODE status = ALT_E_SUCCESS; + + uint32_t bank_count = ((dst + size - 1) >> 24) - (dst >> 24) + 1; + uint32_t bank_addr = dst & ALT_QSPI_BANK_ADDR_MSK; + uint32_t bank_ofst = dst & (ALT_QSPI_BANK_SIZE - 1); + + const char * data = (const char *)src; + + uint32_t copy_length = MIN(size, ALT_QSPI_BANK_SIZE - bank_ofst); + + dprintf("DEBUG[QSPI]: replace(): bulk: flash_addr = 0x%" PRIx32 "; mem_addr = %p.\n", dst, data); + dprintf("DEBUG[QSPI]: replace(): bulk: bank_count = 0x%" PRIx32 ", bank_ofst = 0x%" PRIx32 ".\n", bank_count, bank_ofst); + + for (uint32_t i = 0; i < bank_count; ++i) + { + dprintf("DEBUG[QSPI]: replace(): bank 0x%" PRIx32 "; copy_length = 0x%" PRIx32 ".\n", bank_addr >> 24, copy_length); + + status = alt_qspi_device_bank_select(bank_addr >> 24); + if (status != ALT_E_SUCCESS) + { + break; + } + + status = alt_qspi_replace_bank(bank_ofst, data, copy_length); + if (status != ALT_E_SUCCESS) + { + break; + } + + bank_addr += ALT_QSPI_BANK_SIZE; + data += copy_length; + size -= copy_length; + + copy_length = MIN(size, ALT_QSPI_BANK_SIZE); + } + + return status; +} + +///// + +ALT_QSPI_BAUD_DIV_t alt_qspi_baud_rate_div_get(void) +{ + uint32_t baud_rate_div = ALT_QSPI_CFG_BAUDDIV_GET(alt_read_word(ALT_QSPI_CFG_ADDR)); + return (ALT_QSPI_BAUD_DIV_t) baud_rate_div; +} + +ALT_STATUS_CODE alt_qspi_baud_rate_div_set(const ALT_QSPI_BAUD_DIV_t baud_rate_div) +{ + if (0xf < (uint32_t)baud_rate_div) + { + // Invalid baud rate divisor value. + return ALT_E_BAD_ARG; + } + + // Set the Master Mode Baud Rate Divisor Field of the QSPI Configuration Register. + alt_replbits_word(ALT_QSPI_CFG_ADDR, + ALT_QSPI_CFG_BAUDDIV_SET_MSK, + ALT_QSPI_CFG_BAUDDIV_SET(baud_rate_div)); + + return ALT_E_SUCCESS; +} + +ALT_STATUS_CODE alt_qspi_chip_select_config_get(uint32_t* cs, + ALT_QSPI_CS_MODE_t* cs_mode) +{ + uint32_t cfg = alt_read_word(ALT_QSPI_CFG_ADDR); + + *cs = ALT_QSPI_CFG_PERCSLINES_GET(cfg); + *cs_mode = (ALT_QSPI_CS_MODE_t) ALT_QSPI_CFG_PERSELDEC_GET(cfg); + + return ALT_E_SUCCESS; +} + +ALT_STATUS_CODE alt_qspi_chip_select_config_set(const uint32_t cs, + const ALT_QSPI_CS_MODE_t cs_mode) +{ + // chip select cs: + // four bit value, bit 0 = cs0, bit 1 = cs1, bit 2 = cs2, bit 3 = cs3 + // since cs is low true, the value of each bit should be zero if enable the cs. + // + // also allows multiple cs line enabled together. + + if (cs > ((1 << ALT_QSPI_CFG_PERCSLINES_WIDTH) - 1)) + { + // [cs] not within possible 4 bit chip select line value range. + return ALT_E_ARG_RANGE; + } + + if ((cs_mode != ALT_QSPI_CS_MODE_SINGLE_SELECT) && (cs_mode != ALT_QSPI_CS_MODE_DECODE)) + { + return ALT_E_INV_OPTION; + } + + // Update the Peripheral Chip Select Lines and Peripheral Select Decode + // Fields of the QSPI Configuration Register value with the chip select + // options. + uint32_t cfg = alt_read_word(ALT_QSPI_CFG_ADDR); + cfg &= ALT_QSPI_CFG_PERCSLINES_CLR_MSK & ALT_QSPI_CFG_PERSELDEC_CLR_MSK; + cfg |= ALT_QSPI_CFG_PERCSLINES_SET(cs) | ALT_QSPI_CFG_PERSELDEC_SET(cs_mode); + alt_write_word(ALT_QSPI_CFG_ADDR, cfg); + + return ALT_E_SUCCESS; +} + +ALT_STATUS_CODE alt_qspi_mode_bit_disable(void) +{ + // Clear the Mode Bit Enable Field of the Device Read Instruction Register + // to disable mode bits from being sent after the address bytes. + alt_clrbits_word(ALT_QSPI_DEVRD_ADDR, ALT_QSPI_DEVRD_ENMODBITS_SET_MSK); + + return ALT_E_SUCCESS; +} + +ALT_STATUS_CODE alt_qspi_mode_bit_enable(void) +{ + // Set the Mode Bit Enable Field of the Device Read Instruction Register + // to enable mode bits to be sent after the address bytes. + alt_setbits_word(ALT_QSPI_DEVRD_ADDR, ALT_QSPI_DEVRD_ENMODBITS_SET_MSK); + + return ALT_E_SUCCESS; +} + +uint32_t alt_qspi_mode_bit_config_get(void) +{ + // Return the 8 bit value from the Mode Field of the Mode Bit Configuration + // Register. + return ALT_QSPI_MODBIT_MOD_GET(alt_read_word(ALT_QSPI_MODBIT_ADDR)); +} + +ALT_STATUS_CODE alt_qspi_mode_bit_config_set(const uint32_t mode_bits) +{ + if (alt_qspi_is_idle() == false) + { + return ALT_E_ERROR; + } + + if (mode_bits > ((1 << ALT_QSPI_MODBIT_MOD_WIDTH) - 1)) + { + // 'mode_bits' not within possible 8 bit mode value range. + return ALT_E_ARG_RANGE; + } + + // Set the 8 bit value in the Mode Field of the Mode Bit Configuration + // Register. + alt_replbits_word(ALT_QSPI_MODBIT_ADDR, + ALT_QSPI_MODBIT_MOD_SET_MSK, + ALT_QSPI_MODBIT_MOD_SET(mode_bits)); + + return ALT_E_SUCCESS; +} + +ALT_STATUS_CODE alt_qspi_device_size_config_get(ALT_QSPI_DEV_SIZE_CONFIG_t * cfg) +{ + // Although not required, it is recommended that the write protect feature + // be enabled prior to enabling the QSPI controller. This will block any AHB + // writes from taking effect. This also means the write protection registers + // (Lower Write Protection, Upper Write Protection, and Write Protection) + // should be setup and the number of bytes per device block in the device + // size configuration register should be setup prior to enabling the QSPI + // controller. + + // Read Device Size Register and get the Number of Bytes per Block, Number + // of Bytes per Device, and Number of Address Bytes Fields. + + uint32_t devsz = alt_read_word(ALT_QSPI_DEVSZ_ADDR); + + cfg->block_size = ALT_QSPI_DEVSZ_BYTESPERSUBSECTOR_GET(devsz); + cfg->page_size = ALT_QSPI_DEVSZ_BYTESPERDEVICEPAGE_GET(devsz); + cfg->addr_size = ALT_QSPI_DEVSZ_NUMADDRBYTES_GET(devsz); + + // Read Lower Write Protection, Upper Write Protection, and Write Protection + // Registers. + + cfg->lower_wrprot_block = ALT_QSPI_LOWWRPROT_SUBSECTOR_GET(alt_read_word(ALT_QSPI_LOWWRPROT_ADDR)); + cfg->upper_wrprot_block = ALT_QSPI_UPPWRPROT_SUBSECTOR_GET(alt_read_word(ALT_QSPI_UPPWRPROT_ADDR)); + cfg->wrprot_enable = ALT_QSPI_WRPROT_EN_GET(alt_read_word(ALT_QSPI_WRPROT_ADDR)); + + return ALT_E_SUCCESS; +} + +ALT_STATUS_CODE alt_qspi_device_size_config_set(const ALT_QSPI_DEV_SIZE_CONFIG_t * cfg) +{ + if (cfg->block_size > ((1 << ALT_QSPI_DEVSZ_BYTESPERSUBSECTOR_WIDTH) - 1)) + { + return ALT_E_ARG_RANGE; + } + + if (cfg->page_size > ((1 << ALT_QSPI_DEVSZ_BYTESPERDEVICEPAGE_WIDTH) - 1)) + { + return ALT_E_ARG_RANGE; + } + + if (cfg->addr_size > ((1 << ALT_QSPI_DEVSZ_NUMADDRBYTES_WIDTH) - 1)) + { + return ALT_E_ARG_RANGE; + } + + if (cfg->lower_wrprot_block > cfg->upper_wrprot_block) + { + // Null write protection regions are not allowed. + return ALT_E_ARG_RANGE; + } + + ///// + + uint32_t value = ALT_QSPI_DEVSZ_BYTESPERSUBSECTOR_SET(cfg->block_size) | + ALT_QSPI_DEVSZ_BYTESPERDEVICEPAGE_SET(cfg->page_size) | + ALT_QSPI_DEVSZ_NUMADDRBYTES_SET(cfg->addr_size); + + alt_write_word(ALT_QSPI_DEVSZ_ADDR, value); + + if (cfg->wrprot_enable) + { + alt_write_word(ALT_QSPI_LOWWRPROT_ADDR, cfg->lower_wrprot_block); + alt_write_word(ALT_QSPI_UPPWRPROT_ADDR, cfg->upper_wrprot_block); + } + + // Read Upper Write Protection Register - uppwrprot. + // Set the Write Protection Enable Bit Field of the Write Protection + // Register accordingly. + if (cfg->wrprot_enable) + { + alt_setbits_word(ALT_QSPI_WRPROT_ADDR, ALT_QSPI_WRPROT_EN_SET(1)); + } + else + { + alt_clrbits_word(ALT_QSPI_WRPROT_ADDR, ALT_QSPI_WRPROT_EN_SET(1)); + } + return ALT_E_SUCCESS; +} + +ALT_STATUS_CODE alt_qspi_device_read_config_get(ALT_QSPI_DEV_INST_CONFIG_t * cfg) +{ + // Read the Device Read Instruction Register - devrd. + uint32_t devrd = alt_read_word(ALT_QSPI_DEVRD_ADDR); + + cfg->op_code = ALT_QSPI_DEVRD_RDOPCODE_GET(devrd); + cfg->inst_type = (ALT_QSPI_MODE_t) ALT_QSPI_DEVRD_INSTWIDTH_GET(devrd); + cfg->addr_xfer_type = (ALT_QSPI_MODE_t) ALT_QSPI_DEVRD_ADDRWIDTH_GET(devrd); + cfg->data_xfer_type = (ALT_QSPI_MODE_t) ALT_QSPI_DEVRD_DATAWIDTH_GET(devrd); + cfg->dummy_cycles = ALT_QSPI_DEVRD_DUMMYRDCLKS_GET(devrd); + + return ALT_E_SUCCESS; +} + +ALT_STATUS_CODE alt_qspi_device_read_config_set(const ALT_QSPI_DEV_INST_CONFIG_t * cfg) +{ + if (alt_qspi_is_idle() == false) + { + return ALT_E_ERROR; + } + + // Validate input + + if (cfg->op_code > ((1 << ALT_QSPI_DEVRD_RDOPCODE_WIDTH) - 1)) + { + return ALT_E_BAD_ARG; + } + + switch (cfg->inst_type) + { + case ALT_QSPI_MODE_SINGLE: + case ALT_QSPI_MODE_DUAL: + case ALT_QSPI_MODE_QUAD: + break; + default: + return ALT_E_BAD_ARG; + } + + switch (cfg->addr_xfer_type) + { + case ALT_QSPI_MODE_SINGLE: + case ALT_QSPI_MODE_DUAL: + case ALT_QSPI_MODE_QUAD: + break; + default: + return ALT_E_BAD_ARG; + } + + switch (cfg->data_xfer_type) + { + case ALT_QSPI_MODE_SINGLE: + case ALT_QSPI_MODE_DUAL: + case ALT_QSPI_MODE_QUAD: + break; + default: + return ALT_E_BAD_ARG; + } + + if (cfg->dummy_cycles > ((1 << ALT_QSPI_DEVRD_DUMMYRDCLKS_WIDTH) - 1)) + { + return ALT_E_BAD_ARG; + } + + ///// + + // Read the Device Read Instruction Register - devrd. + uint32_t devrd = alt_read_word(ALT_QSPI_DEVRD_ADDR); + + devrd &= ALT_QSPI_DEVRD_RDOPCODE_CLR_MSK & + ALT_QSPI_DEVRD_INSTWIDTH_CLR_MSK & + ALT_QSPI_DEVRD_ADDRWIDTH_CLR_MSK & + ALT_QSPI_DEVRD_DATAWIDTH_CLR_MSK & + ALT_QSPI_DEVRD_DUMMYRDCLKS_CLR_MSK; + + devrd |= ALT_QSPI_DEVRD_RDOPCODE_SET(cfg->op_code) | + ALT_QSPI_DEVRD_INSTWIDTH_SET(cfg->inst_type) | + ALT_QSPI_DEVRD_ADDRWIDTH_SET(cfg->addr_xfer_type) | + ALT_QSPI_DEVRD_DATAWIDTH_SET(cfg->data_xfer_type) | + ALT_QSPI_DEVRD_DUMMYRDCLKS_SET(cfg->dummy_cycles); + + alt_write_word(ALT_QSPI_DEVRD_ADDR, devrd); + + return ALT_E_SUCCESS; +} + +ALT_STATUS_CODE alt_qspi_device_write_config_get(ALT_QSPI_DEV_INST_CONFIG_t * cfg) +{ + // Device Write Instruction Register - devwr. + uint32_t devwr = alt_read_word(ALT_QSPI_DEVWR_ADDR); + + cfg->op_code = ALT_QSPI_DEVWR_WROPCODE_GET(devwr); + // The Instruction Type field in the Device READ Instruction Register only appears + // once and applies to both READ and WRITE opertions. it is not included in the + // Device WRITE Instruction Register. + cfg->inst_type = (ALT_QSPI_MODE_t) ALT_QSPI_DEVRD_INSTWIDTH_GET(alt_read_word(ALT_QSPI_DEVRD_ADDR)); + cfg->addr_xfer_type = (ALT_QSPI_MODE_t) ALT_QSPI_DEVWR_ADDRWIDTH_GET(devwr); + cfg->data_xfer_type = (ALT_QSPI_MODE_t) ALT_QSPI_DEVWR_DATAWIDTH_GET(devwr); + cfg->dummy_cycles = ALT_QSPI_DEVWR_DUMMYWRCLKS_GET(devwr); + + return ALT_E_SUCCESS; +} + +ALT_STATUS_CODE alt_qspi_device_write_config_set(const ALT_QSPI_DEV_INST_CONFIG_t * cfg) +{ + if (alt_qspi_is_idle() == false) + { + return ALT_E_ERROR; + } + + // Validate input + + if (cfg->op_code > ((1 << ALT_QSPI_DEVWR_WROPCODE_WIDTH) - 1)) + { + return ALT_E_BAD_ARG; + } + + switch (cfg->inst_type) + { + case ALT_QSPI_MODE_SINGLE: + case ALT_QSPI_MODE_DUAL: + case ALT_QSPI_MODE_QUAD: + break; + default: + return ALT_E_BAD_ARG; + } + + switch (cfg->addr_xfer_type) + { + case ALT_QSPI_MODE_SINGLE: + case ALT_QSPI_MODE_DUAL: + case ALT_QSPI_MODE_QUAD: + break; + default: + return ALT_E_BAD_ARG; + } + + switch (cfg->data_xfer_type) + { + case ALT_QSPI_MODE_SINGLE: + case ALT_QSPI_MODE_DUAL: + case ALT_QSPI_MODE_QUAD: + break; + default: + return ALT_E_BAD_ARG; + } + + if (cfg->dummy_cycles > ((1 << ALT_QSPI_DEVWR_DUMMYWRCLKS_WIDTH) - 1)) + { + return ALT_E_BAD_ARG; + } + + ///// + + // Read the Device Write Instruction Register - devwr. + uint32_t devwr = alt_read_word(ALT_QSPI_DEVWR_ADDR); + + devwr &= ALT_QSPI_DEVWR_WROPCODE_CLR_MSK & + ALT_QSPI_DEVWR_ADDRWIDTH_CLR_MSK & + ALT_QSPI_DEVWR_DATAWIDTH_CLR_MSK & + ALT_QSPI_DEVWR_DUMMYWRCLKS_CLR_MSK; + + devwr |= ALT_QSPI_DEVWR_WROPCODE_SET(cfg->op_code) | + ALT_QSPI_DEVWR_ADDRWIDTH_SET(cfg->addr_xfer_type) | + ALT_QSPI_DEVWR_DATAWIDTH_SET(cfg->data_xfer_type) | + ALT_QSPI_DEVWR_DUMMYWRCLKS_SET(cfg->dummy_cycles); + + alt_write_word(ALT_QSPI_DEVWR_ADDR, devwr); + + // The Instruction Type field in the Device READ Instruction Register only appears + // once and applies to both READ and WRITE operations - it is not included in the + // Device WRITE Instruction Register. Therefore, modify the Instruction Type + // Field in the Device Read Register. + alt_replbits_word(ALT_QSPI_DEVRD_ADDR, + ALT_QSPI_DEVRD_INSTWIDTH_SET_MSK, + ALT_QSPI_DEVRD_INSTWIDTH_SET((uint32_t) cfg->inst_type)); + + return ALT_E_SUCCESS; +} + +ALT_STATUS_CODE alt_qspi_timing_config_get(ALT_QSPI_TIMING_CONFIG_t * cfg) +{ + // QSPI Configuration Register - cfg + uint32_t cfgreg = alt_read_word(ALT_QSPI_CFG_ADDR); + cfg->clk_phase = (ALT_QSPI_CLK_PHASE_t) ALT_QSPI_CFG_SELCLKPHASE_GET(cfgreg); + cfg->clk_pol = (ALT_QSPI_CLK_POLARITY_t) ALT_QSPI_CFG_SELCLKPOL_GET(cfgreg); + + // QSPI Device Delay Register + uint32_t delayreg = alt_read_word(ALT_QSPI_DELAY_ADDR); + cfg->cs_sot = ALT_QSPI_DELAY_INIT_GET(delayreg); + cfg->cs_eot = ALT_QSPI_DELAY_AFTER_GET(delayreg); + cfg->cs_dads = ALT_QSPI_DELAY_BTWN_GET(delayreg); + cfg->cs_da = ALT_QSPI_DELAY_NSS_GET(delayreg); + + // Read Data Capture Register + cfg->rd_datacap = ALT_QSPI_RDDATACAP_DELAY_GET(alt_read_word(ALT_QSPI_RDDATACAP_ADDR)); + + return ALT_E_SUCCESS; +} + +ALT_STATUS_CODE alt_qspi_timing_config_set(const ALT_QSPI_TIMING_CONFIG_t * cfg) +{ + if (alt_qspi_is_idle() == false) + { + return ALT_E_ERROR; + } + + // Validate parameter(s) + + switch (cfg->clk_phase) + { + case ALT_QSPI_CLK_PHASE_ACTIVE: + case ALT_QSPI_CLK_PHASE_INACTIVE: + break; + default: + return ALT_E_BAD_ARG; + } + + switch (cfg->clk_pol) + { + case ALT_QSPI_CLK_POLARITY_LOW: + case ALT_QSPI_CLK_POLARITY_HIGH: + break; + default: + return ALT_E_BAD_ARG; + } + + if (cfg->cs_da > ((1 << ALT_QSPI_DELAY_NSS_WIDTH) - 1)) + { + return ALT_E_BAD_ARG; + } + if (cfg->cs_dads > ((1 << ALT_QSPI_DELAY_BTWN_WIDTH) - 1)) + { + return ALT_E_BAD_ARG; + } + if (cfg->cs_eot > ((1 << ALT_QSPI_DELAY_AFTER_WIDTH) - 1)) + { + return ALT_E_BAD_ARG; + } + if (cfg->cs_sot > ((1 << ALT_QSPI_DELAY_INIT_WIDTH) - 1)) + { + return ALT_E_BAD_ARG; + } + + if (cfg->rd_datacap > ((1 << ALT_QSPI_RDDATACAP_DELAY_WIDTH) - 1)) + { + return ALT_E_BAD_ARG; + } + + ///// + + // QSPI Configuration Register - cfg + uint32_t cfgreg = alt_read_word(ALT_QSPI_CFG_ADDR); + cfgreg &= ALT_QSPI_CFG_SELCLKPHASE_CLR_MSK & + ALT_QSPI_CFG_SELCLKPOL_CLR_MSK; + cfgreg |= ALT_QSPI_CFG_SELCLKPHASE_SET(cfg->clk_phase) | + ALT_QSPI_CFG_SELCLKPOL_SET(cfg->clk_pol); + alt_write_word(ALT_QSPI_CFG_ADDR, cfgreg); + + // QSPI Device Delay Register + uint32_t delayreg = ALT_QSPI_DELAY_INIT_SET(cfg->cs_sot) | + ALT_QSPI_DELAY_AFTER_SET(cfg->cs_eot) | + ALT_QSPI_DELAY_BTWN_SET(cfg->cs_dads) | + ALT_QSPI_DELAY_NSS_SET(cfg->cs_da); + alt_write_word(ALT_QSPI_DELAY_ADDR, delayreg); + + // Read Data Capture Register + + alt_write_word(ALT_QSPI_RDDATACAP_ADDR, + ALT_QSPI_RDDATACAP_BYP_SET(1) | + ALT_QSPI_RDDATACAP_DELAY_SET(cfg->rd_datacap)); + + return ALT_E_SUCCESS; +} + +///// + +ALT_STATUS_CODE alt_qspi_direct_disable(void) +{ + // Clear (set to 0) the Enable Direct Access Controller Field of the QSPI + // Configuration Register to disable the Direct Access Controller. + alt_clrbits_word(ALT_QSPI_CFG_ADDR, ALT_QSPI_CFG_ENDIRACC_SET_MSK); + + return ALT_E_SUCCESS; +} + +ALT_STATUS_CODE alt_qspi_direct_enable(void) +{ + // Set (set to 1) the Enable Direct Access Controller Field of the QSPI + // Configuration Register to enable the Direct Access Controller. + alt_setbits_word(ALT_QSPI_CFG_ADDR, ALT_QSPI_CFG_ENDIRACC_SET_MSK); + + return ALT_E_SUCCESS; +} + +uint32_t alt_qspi_ahb_remap_address_get(void) +{ + // Read and return the value of the Remap Address Register. + return ALT_QSPI_REMAPADDR_VALUE_GET(alt_read_word(ALT_QSPI_REMAPADDR_ADDR)); +} + +ALT_STATUS_CODE alt_qspi_ahb_remap_address_set(const uint32_t ahb_remap_addr) +{ + if (alt_qspi_is_idle() == false) + { + return ALT_E_ERROR; + } + + // Read and return the value of the Remap Address Register. + alt_setbits_word(ALT_QSPI_REMAPADDR_ADDR, ALT_QSPI_REMAPADDR_VALUE_SET(ahb_remap_addr)); + + return ALT_E_SUCCESS; +} + +ALT_STATUS_CODE alt_qspi_ahb_address_remap_disable(void) +{ + // Clear (set to 0) the Enable AHB Address Remapping Field of the QSPI + // Configuration Register to disable AHB address remapping. + alt_clrbits_word(ALT_QSPI_CFG_ADDR, ALT_QSPI_CFG_ENAHBREMAP_SET_MSK); + + return ALT_E_SUCCESS; +} + +ALT_STATUS_CODE alt_qspi_ahb_address_remap_enable(void) +{ + // Set (set to 1) the Enable AHB Address Remapping Field of the QSPI + // Configuration Register to enable AHB address remapping. + alt_setbits_word(ALT_QSPI_CFG_ADDR, ALT_QSPI_CFG_ENAHBREMAP_SET_MSK); + + return ALT_E_SUCCESS; +} + +///// + +static ALT_STATUS_CODE alt_qspi_indirect_read_start_bank(uint32_t flash_addr, + size_t num_bytes) +{ + alt_write_word(ALT_QSPI_INDRDSTADDR_ADDR, flash_addr); + alt_write_word(ALT_QSPI_INDRDCNT_ADDR, num_bytes); + alt_write_word(ALT_QSPI_INDRD_ADDR, ALT_QSPI_INDRD_START_SET_MSK | + ALT_QSPI_INDRD_IND_OPS_DONE_STAT_SET_MSK); + + return ALT_E_SUCCESS; +} + +ALT_STATUS_CODE alt_qspi_indirect_read_start(const uint32_t flash_addr, + const size_t num_bytes) +{ + // flash_addr and num_bytes restriction is to prevent possible unaligned + // exceptions. + + if (flash_addr & 0x3) + { + return ALT_E_ERROR; + } + + if (num_bytes & 0x3) + { + return ALT_E_ERROR; + } + + if (num_bytes == 0) + { + // Do not report this as a success. If a indirect read was not + // previously completed, it may be cleared already, at which point + // alt_qspi_indirect_read_is_complete() will never report true. + return ALT_E_ERROR; + } + + if (flash_addr > qspi_device_size) + { + return ALT_E_ERROR; + } + + if (flash_addr + num_bytes > qspi_device_size) + { + return ALT_E_ERROR; + } + + // Verify request does not cross bank boundary. + // This limitation is due to the 3-byte addressing limitation. + if ((flash_addr & ALT_QSPI_BANK_ADDR_MSK) != ((flash_addr + num_bytes - 1) & ALT_QSPI_BANK_ADDR_MSK)) + { + return ALT_E_ERROR; + } + + // Verify that there is not already a read in progress. + if (ALT_QSPI_INDRD_RD_STAT_GET(alt_read_word(ALT_QSPI_INDRD_ADDR))) + { + return ALT_E_ERROR; + } + + ///// + + ALT_STATUS_CODE status; + status = alt_qspi_device_bank_select(flash_addr >> 24); + if (status != ALT_E_SUCCESS) + { + return status; + } + + ///// + + return alt_qspi_indirect_read_start_bank(flash_addr, + num_bytes); + +} + +ALT_STATUS_CODE alt_qspi_indirect_read_finish(void) +{ + return ALT_E_SUCCESS; +} + +ALT_STATUS_CODE alt_qspi_indirect_read_cancel(void) +{ + // An indirect operation may be cancelled at any time by setting Indirect + // Transfer Control Register bit [1]. + alt_write_word(ALT_QSPI_INDRD_ADDR, ALT_QSPI_INDRD_CANCEL_SET_MSK); + + return ALT_E_SUCCESS; +} + +uint32_t alt_qspi_indirect_read_fill_level(void) +{ + // Return the SRAM Fill Level (Indirect Read Partition) Field of the SRAM + // Fill Register to get the SRAM Fill Level for the Indirect Read Partition + // in units of SRAM Words (4 bytes). + return ALT_QSPI_SRAMFILL_INDRDPART_GET(alt_read_word(ALT_QSPI_SRAMFILL_ADDR)); +} + +uint32_t alt_qspi_indirect_read_watermark_get(void) +{ + // Return the Watermark value in the Indirect Read Transfer Watermark Register. + return alt_read_word(ALT_QSPI_INDRDWATER_ADDR); +} + +ALT_STATUS_CODE alt_qspi_indirect_read_watermark_set(const uint32_t watermark) +{ + // Verify that there is not already a read in progress. + if (ALT_QSPI_INDRD_RD_STAT_GET(alt_read_word(ALT_QSPI_INDRD_ADDR))) + { + return ALT_E_ERROR; + } + + // Set the Watermark value in the Indirect Read Transfer Watermark Register. + alt_write_word(ALT_QSPI_INDRDWATER_ADDR, watermark); + + return ALT_E_SUCCESS; +} + +bool alt_qspi_indirect_read_is_complete(void) +{ + // The value of the Indirect Completion Status Field of the Indirect Read + // Transfer Control Register is set by hardware when an indirect read + // operation has completed. + return (alt_read_word(ALT_QSPI_INDRD_ADDR) & ALT_QSPI_INDRD_IND_OPS_DONE_STAT_SET_MSK) != 0; +} + +static ALT_STATUS_CODE alt_qspi_indirect_write_start_bank(uint32_t flash_addr, + size_t num_bytes) +{ + alt_write_word(ALT_QSPI_INDWRSTADDR_ADDR, flash_addr); + alt_write_word(ALT_QSPI_INDWRCNT_ADDR, num_bytes); + alt_write_word(ALT_QSPI_INDWR_ADDR, ALT_QSPI_INDWR_START_SET_MSK | + ALT_QSPI_INDWR_INDDONE_SET_MSK); + + return ALT_E_SUCCESS; +} + +ALT_STATUS_CODE alt_qspi_indirect_write_start(const uint32_t flash_addr, + const size_t num_bytes) +{ + // flash_addr and num_bytes restriction is to prevent possible unaligned + // exceptions. + + if (flash_addr & 0x3) + { + return ALT_E_ERROR; + } + + if (num_bytes & 0x3) + { + return ALT_E_ERROR; + } + + if (num_bytes == 0) + { + // Do not report this as a success. If a indirect write was not + // previously completed, it may be cleared already, at which point + // alt_qspi_indirect_write_is_complete() will never report true. + return ALT_E_ERROR; + } + + if (num_bytes > 256) + { + // The Micron part can only write up to 256 bytes at a time. + return ALT_E_ERROR; + } + + if (flash_addr > qspi_device_size) + { + return ALT_E_ERROR; + } + + if (flash_addr + num_bytes > qspi_device_size) + { + return ALT_E_ERROR; + } + +/* + // Verify request does not cross bank boundary. + // This limitation is due to the 3-byte addressing limitation. + if ((flash_addr & ALT_QSPI_BANK_ADDR_MSK) != ((flash_addr + num_bytes - 1) & ALT_QSPI_BANK_ADDR_MSK)) + { + return ALT_E_ERROR; + } +*/ + // Verify request does not cross page boundary. + // This limitation is in place for the Micron part used. + if ((flash_addr & ALT_QSPI_PAGE_ADDR_MSK) != ((flash_addr + num_bytes - 1) & ALT_QSPI_PAGE_ADDR_MSK)) + { + return ALT_E_ERROR; + } + + // Verify that there is not already a write in progress. + if (ALT_QSPI_INDWR_RDSTAT_GET(alt_read_word(ALT_QSPI_INDWR_ADDR))) + { + return ALT_E_ERROR; + } + + ///// + + ALT_STATUS_CODE status = ALT_E_SUCCESS; + status = alt_qspi_device_bank_select(flash_addr >> 24); + if (status != ALT_E_SUCCESS) + { + return status; + } + + ///// + + return alt_qspi_indirect_write_start_bank(flash_addr, + num_bytes); +} + +ALT_STATUS_CODE alt_qspi_indirect_write_finish(void) +{ +#if ALT_QSPI_PROVISION_MICRON_N25Q_SUPPORT + return alt_qspi_N25Q_flag_wait_for_program(ALT_QSPI_TIMEOUT_INFINITE); +#else + return ALT_E_SUCCESS; +#endif +} + +ALT_STATUS_CODE alt_qspi_indirect_write_cancel(void) +{ + ALT_STATUS_CODE status = ALT_E_SUCCESS; + +#if ALT_QSPI_PROVISION_MICRON_N25Q_SUPPORT + if (status == ALT_E_SUCCESS) + { + status = alt_qspi_N25Q_flag_wait_for_program(ALT_QSPI_TIMEOUT_INFINITE); + } +#endif + + if (status == ALT_E_SUCCESS) + { + // An indirect operation may be cancelled at any time by setting Indirect + // Transfer Control Register bit [1]. + alt_write_word(ALT_QSPI_INDWR_ADDR, ALT_QSPI_INDWR_CANCEL_SET_MSK); + } + + return status; +} + +uint32_t alt_qspi_indirect_write_fill_level(void) +{ + // Return the SRAM Fill Level (Indirect Write Partition) Field of the SRAM + // Fill Register to get the SRAM Fill Level for the Indirect Write Partition + // in units of SRAM Words (4 bytes). + return ALT_QSPI_SRAMFILL_INDWRPART_GET(alt_read_word(ALT_QSPI_SRAMFILL_ADDR)); +} + +uint32_t alt_qspi_indirect_write_watermark_get(void) +{ + // Return the Watermark value in the Indirect Write Transfer Watermark Register. + return alt_read_word(ALT_QSPI_INDWRWATER_ADDR); +} + +ALT_STATUS_CODE alt_qspi_indirect_write_watermark_set(const uint32_t watermark) +{ + // Verify that there is not already a write in progress. + if (ALT_QSPI_INDWR_RDSTAT_GET(alt_read_word(ALT_QSPI_INDWR_ADDR))) + { + return ALT_E_ERROR; + } + + // Set the Watermark value in the Indirect Write Transfer Watermark Register. + alt_write_word(ALT_QSPI_INDWRWATER_ADDR, watermark); + + return ALT_E_SUCCESS; +} + +bool alt_qspi_indirect_write_is_complete(void) +{ + // The value of the Indirect Completion Status Field of the Indirect Write + // Transfer Control Register is set by hardware when an indirect write + // operation has completed. + return (alt_read_word(ALT_QSPI_INDWR_ADDR) & ALT_QSPI_INDWR_INDDONE_SET_MSK) != 0; +} + +///// + +uint32_t alt_qspi_sram_partition_get(void) +{ + // The number of locations allocated to indirect read is equal to the value + // of the SRAM partition register. See the documentation for this function + // regarding the + 1 in the IP documentation. This way the get() and set() + // will be symmetrical. + + return ALT_QSPI_SRAMPART_ADDR_GET(alt_read_word(ALT_QSPI_SRAMPART_ADDR)); +} + +ALT_STATUS_CODE alt_qspi_sram_partition_set(const uint32_t read_part_size) +{ + if (read_part_size > ((1 << ALT_QSPI_SRAMPART_ADDR_WIDTH) - 1)) + { + return ALT_E_ARG_RANGE; + } + + alt_replbits_word(ALT_QSPI_SRAMPART_ADDR, + ALT_QSPI_SRAMPART_ADDR_SET_MSK, + ALT_QSPI_SRAMPART_ADDR_SET(read_part_size)); + + return ALT_E_SUCCESS; +} + +///// + + +static ALT_STATUS_CODE alt_qspi_erase_subsector_bank(uint32_t addr) +{ + ALT_STATUS_CODE status = ALT_E_SUCCESS; + + if (status == ALT_E_SUCCESS) + { + status = alt_qspi_device_wren(); + } + + if (status == ALT_E_SUCCESS) + { + status = alt_qspi_stig_addr_cmd(ALT_QSPI_STIG_OPCODE_SUBSEC_ERASE, 0, addr, 10000); + } + +#if ALT_QSPI_PROVISION_MICRON_N25Q_SUPPORT + if (status == ALT_E_SUCCESS) + { + status = alt_qspi_N25Q_flag_wait_for_erase(ALT_QSPI_TIMEOUT_INFINITE); + } +#endif + + return status; +} + +ALT_STATUS_CODE alt_qspi_erase_subsector(const uint32_t addr) +{ + ALT_STATUS_CODE status = ALT_E_SUCCESS; + + if (status == ALT_E_SUCCESS) + { + status = alt_qspi_device_bank_select(addr >> 24); + } + + if (status == ALT_E_SUCCESS) + { + status = alt_qspi_erase_subsector_bank(addr); + } + + return status; +} + +ALT_STATUS_CODE alt_qspi_erase_sector(const uint32_t addr) +{ + ALT_STATUS_CODE status = ALT_E_SUCCESS; + + if (status == ALT_E_SUCCESS) + { + status = alt_qspi_device_bank_select(addr >> 24); + } + + if (status == ALT_E_SUCCESS) + { + status = alt_qspi_device_wren(); + } + + if (status == ALT_E_SUCCESS) + { + status = alt_qspi_stig_addr_cmd(ALT_QSPI_STIG_OPCODE_SEC_ERASE, 0, addr, ALT_QSPI_TIMEOUT_INFINITE); + } + +#if ALT_QSPI_PROVISION_MICRON_N25Q_SUPPORT + if (status == ALT_E_SUCCESS) + { + status = alt_qspi_N25Q_flag_wait_for_erase(ALT_QSPI_TIMEOUT_INFINITE); + } +#endif + + return status; +} + +ALT_STATUS_CODE alt_qspi_erase_chip(void) +{ + ALT_STATUS_CODE status = ALT_E_SUCCESS; + + if (qspi_device_size >= (2 * ALT_QSPI_N25Q_DIE_SIZE)) + { + // NOTE: This path is specifically for 512 Mib and 1 Gib Micron N25Q + // chips only. + + dprintf("DEBUG[QSPI]: erase[chip]: FYI, wait time is ~800s for 128 MiB.\n"); + + uint32_t die_count = qspi_device_size / ALT_QSPI_N25Q_DIE_SIZE; + + for (int i = 0; i < die_count; ++i) + { + if (status != ALT_E_SUCCESS) + { + break; + } + + dprintf("DEBUG[QSPI]: Erase chip: die = %d, total = %" PRIu32 ".\n", i, die_count); + + if (status == ALT_E_SUCCESS) + { + status = alt_qspi_device_bank_select(i * (ALT_QSPI_N25Q_DIE_SIZE / ALT_QSPI_BANK_SIZE)); + } + + if (status == ALT_E_SUCCESS) + { + status = alt_qspi_device_wren(); + } + + if (status == ALT_E_SUCCESS) + { + status = alt_qspi_stig_addr_cmd(ALT_QSPI_STIG_OPCODE_DIE_ERASE, 0, + i * ALT_QSPI_N25Q_DIE_SIZE, + ALT_QSPI_TIMEOUT_INFINITE); + } + +#if ALT_QSPI_PROVISION_MICRON_N25Q_SUPPORT + if (status == ALT_E_SUCCESS) + { + status = alt_qspi_N25Q_flag_wait_for_erase(ALT_QSPI_TIMEOUT_INFINITE); + } +#endif + } + } + else + { + // NOTE: Untested path. + + dprintf("DEBUG[QSPI]: Bulk erase.\n"); + + if (status == ALT_E_SUCCESS) + { + status = alt_qspi_device_bank_select(0); + } + + if (status == ALT_E_SUCCESS) + { + status = alt_qspi_device_wren(); + } + + if (status == ALT_E_SUCCESS) + { + // If BULK_ERASE is like other ERASE, it needs the address command. + status = alt_qspi_stig_addr_cmd(ALT_QSPI_STIG_OPCODE_BULK_ERASE, 0, + 0, + ALT_QSPI_TIMEOUT_INFINITE); + } + +#if ALT_QSPI_PROVISION_MICRON_N25Q_SUPPORT + if (status == ALT_E_SUCCESS) + { + status = alt_qspi_N25Q_flag_wait_for_erase(ALT_QSPI_TIMEOUT_INFINITE); + } +#endif + } + + return status; +} + +///// + +ALT_STATUS_CODE alt_qspi_dma_disable(void) +{ + // Clear (set to 0) the Enable DMA Peripheral Interface Field of the QSPI + // Configuration Register to disable the DMA peripheral interface. + alt_clrbits_word(ALT_QSPI_CFG_ADDR, ALT_QSPI_CFG_ENDMA_SET_MSK); + + return ALT_E_SUCCESS; +} + +ALT_STATUS_CODE alt_qspi_dma_enable(void) +{ + // Set (set to 1) the Enable DMA Peripheral Interface Field of the QSPI + // Configuration Register to enable the DMA peripheral interface. + alt_setbits_word(ALT_QSPI_CFG_ADDR, ALT_QSPI_CFG_ENDMA_SET_MSK); + + return ALT_E_SUCCESS; +} + +ALT_STATUS_CODE alt_qspi_dma_config_get(uint32_t * single_type_sz, + uint32_t * burst_type_sz) +{ + // Get the current value of the DMA Peripheral Register - dmaper + uint32_t dmaper = alt_read_word(ALT_QSPI_DMAPER_ADDR); + + // For both values, a programmed value of 0 represents a single byte. The + // actual number of bytes used is 2 ** (value in this register field). + *single_type_sz = 1 << ALT_QSPI_DMAPER_NUMSGLREQBYTES_GET(dmaper); + *burst_type_sz = 1 << ALT_QSPI_DMAPER_NUMBURSTREQBYTES_GET(dmaper); + + return ALT_E_SUCCESS; +} + +// +// Returns true if [n] is a power of 2 value otherwise returns false. +// +static bool is_pow_2(uint32_t n) +{ + return ((n > 0) && ((n & (n - 1)) == 0)); +} + +// +// Return the log base 2 value of a number that is known to be a power of 2. +// +static uint32_t log2u(uint32_t value) +{ + uint32_t exp = 0; + while ((exp < 32) && (value != (1 << exp))) + { + ++exp; + } + return exp; +} + +ALT_STATUS_CODE alt_qspi_dma_config_set(const uint32_t single_type_sz, + const uint32_t burst_type_sz) +{ + if (alt_qspi_is_idle() == false) + { + return ALT_E_ERROR; + } + + if (single_type_sz < 4) + { + return ALT_E_ERROR; + } + + if (burst_type_sz < 4) + { + return ALT_E_ERROR; + } + + if (burst_type_sz < single_type_sz) + { + return ALT_E_ERROR; + } + + const uint32_t single_type_sz_max = 1 << ((1 << ALT_QSPI_DMAPER_NUMSGLREQBYTES_WIDTH) - 1); + const uint32_t burst_type_sz_max = 1 << ((1 << ALT_QSPI_DMAPER_NUMBURSTREQBYTES_WIDTH) - 1); + + // Both parameter values must be a power of 2 between 1 and 32728. + if ( (single_type_sz > single_type_sz_max) || !is_pow_2(single_type_sz) + || (burst_type_sz > burst_type_sz_max) || !is_pow_2(burst_type_sz) + ) + { + return ALT_E_ARG_RANGE; + } + + // Get the current value of the DMA Peripheral Register - dmaper + uint32_t dmaper = alt_read_word(ALT_QSPI_DMAPER_ADDR); + dmaper &= ALT_QSPI_DMAPER_NUMBURSTREQBYTES_CLR_MSK & + ALT_QSPI_DMAPER_NUMSGLREQBYTES_CLR_MSK; + dmaper |= ALT_QSPI_DMAPER_NUMBURSTREQBYTES_SET(log2u(burst_type_sz)) | + ALT_QSPI_DMAPER_NUMSGLREQBYTES_SET(log2u(single_type_sz)); + alt_write_word(ALT_QSPI_DMAPER_ADDR, dmaper); + + return ALT_E_SUCCESS; +} + +///// + +// +// Private STIG and device commands +// + +static ALT_STATUS_CODE alt_qspi_stig_cmd_helper(uint32_t reg_value, uint32_t timeout) +{ + ALT_STATUS_CODE status = ALT_E_SUCCESS; + bool infinite = (timeout == ALT_QSPI_TIMEOUT_INFINITE); + + alt_write_word(ALT_QSPI_FLSHCMD_ADDR, reg_value); + alt_write_word(ALT_QSPI_FLSHCMD_ADDR, reg_value | ALT_QSPI_FLSHCMD_EXECCMD_E_EXECUTE); + + do + { + reg_value = alt_read_word(ALT_QSPI_FLSHCMD_ADDR); + if (!(reg_value & ALT_QSPI_FLSHCMD_CMDEXECSTAT_SET_MSK)) + { + break; + } + + } while (timeout-- || infinite); + + if (timeout == (uint32_t)-1 && !infinite) + { + status = ALT_E_TMO; + } + + return status; +} + +ALT_STATUS_CODE alt_qspi_stig_cmd(uint32_t opcode, uint32_t dummy, uint32_t timeout) +{ + if (dummy > ((1 << ALT_QSPI_FLSHCMD_NUMDUMMYBYTES_WIDTH) - 1)) + { + return ALT_E_ERROR; + } + + uint32_t reg = ALT_QSPI_FLSHCMD_CMDOPCODE_SET(opcode) | + ALT_QSPI_FLSHCMD_NUMDUMMYBYTES_SET(dummy); + + return alt_qspi_stig_cmd_helper(reg, timeout); +} + +ALT_STATUS_CODE alt_qspi_stig_rd_cmd(uint8_t opcode, + uint32_t dummy, + uint32_t num_bytes, + uint32_t * output, + uint32_t timeout) +{ + if (dummy > ((1 << ALT_QSPI_FLSHCMD_NUMDUMMYBYTES_WIDTH) - 1)) + { + return ALT_E_ERROR; + } + + // STIG read can only return up to 8 bytes. + if ((num_bytes > 8) || (num_bytes == 0)) + { + return ALT_E_BAD_ARG; + } + + uint32_t reg_value = + ALT_QSPI_FLSHCMD_CMDOPCODE_SET(opcode) | + ALT_QSPI_FLSHCMD_ENRDDATA_SET(ALT_QSPI_FLSHCMD_ENRDDATA_E_EN) | + ALT_QSPI_FLSHCMD_NUMRDDATABYTES_SET(num_bytes - 1) | + ALT_QSPI_FLSHCMD_ENCMDADDR_SET(ALT_QSPI_FLSHCMD_ENCMDADDR_E_DISD) | + ALT_QSPI_FLSHCMD_ENMODBIT_SET(ALT_QSPI_FLSHCMD_ENMODBIT_E_DISD) | + ALT_QSPI_FLSHCMD_NUMADDRBYTES_SET(0) | + ALT_QSPI_FLSHCMD_ENWRDATA_SET(ALT_QSPI_FLSHCMD_ENWRDATA_E_NOACTION) | + ALT_QSPI_FLSHCMD_NUMWRDATABYTES_SET(0) | + ALT_QSPI_FLSHCMD_NUMDUMMYBYTES_SET(dummy); + + ALT_STATUS_CODE status = ALT_E_SUCCESS; + + status = alt_qspi_stig_cmd_helper(reg_value, timeout); + if (status != ALT_E_SUCCESS) + { + return status; + } + + output[0] = alt_read_word(ALT_QSPI_FLSHCMDRDDATALO_ADDR); + + if (num_bytes > 4) + { + output[1] = alt_read_word(ALT_QSPI_FLSHCMDRDDATAUP_ADDR); + } + + return ALT_E_SUCCESS; +} + +ALT_STATUS_CODE alt_qspi_stig_wr_cmd(uint8_t opcode, + uint32_t dummy, + uint32_t num_bytes, + const uint32_t * input, + uint32_t timeout) +{ + if (dummy > ((1 << ALT_QSPI_FLSHCMD_NUMDUMMYBYTES_WIDTH) - 1)) + { + return ALT_E_ERROR; + } + + // STIG can only write up to 8 bytes. + if ((num_bytes > 8) || (num_bytes == 0)) + { + return ALT_E_BAD_ARG; + } + + uint32_t reg_value = + ALT_QSPI_FLSHCMD_CMDOPCODE_SET(opcode) | + ALT_QSPI_FLSHCMD_ENRDDATA_SET(ALT_QSPI_FLSHCMD_ENRDDATA_E_NOACTION) | + ALT_QSPI_FLSHCMD_NUMRDDATABYTES_SET(0) | + ALT_QSPI_FLSHCMD_ENCMDADDR_SET(ALT_QSPI_FLSHCMD_ENCMDADDR_E_DISD) | + ALT_QSPI_FLSHCMD_ENMODBIT_SET(ALT_QSPI_FLSHCMD_ENMODBIT_E_DISD) | + ALT_QSPI_FLSHCMD_NUMADDRBYTES_SET(0) | + ALT_QSPI_FLSHCMD_ENWRDATA_SET(ALT_QSPI_FLSHCMD_ENWRDATA_E_WRDATABYTES) | + ALT_QSPI_FLSHCMD_NUMWRDATABYTES_SET(num_bytes - 1) | + ALT_QSPI_FLSHCMD_NUMDUMMYBYTES_SET(dummy); + + alt_write_word(ALT_QSPI_FLSHCMDWRDATALO_ADDR, input[0]); + + if (num_bytes > 4) + { + alt_write_word(ALT_QSPI_FLSHCMDWRDATAUP_ADDR, input[1]); + } + + return alt_qspi_stig_cmd_helper(reg_value, timeout); +} + +ALT_STATUS_CODE alt_qspi_stig_addr_cmd(uint8_t opcode, + uint32_t dummy, + uint32_t address, + uint32_t timeout) +{ + if (dummy > ((1 << ALT_QSPI_FLSHCMD_NUMDUMMYBYTES_WIDTH) - 1)) + { + return ALT_E_ERROR; + } + + uint32_t reg = ALT_QSPI_FLSHCMD_CMDOPCODE_SET(opcode) | + ALT_QSPI_FLSHCMD_NUMDUMMYBYTES_SET(dummy); + + reg |= ALT_QSPI_FLSHCMD_ENCMDADDR_SET(ALT_QSPI_FLSHCMD_ENCMDADDR_E_END); + reg |= ALT_QSPI_FLSHCMD_NUMADDRBYTES_SET(ALT_QSPI_FLSHCMD_NUMADDRBYTES_E_ADDRBYTE3); + + alt_write_word(ALT_QSPI_FLSHCMDADDR_ADDR, address); + + return alt_qspi_stig_cmd_helper(reg, timeout); +} + +///// + +ALT_STATUS_CODE alt_qspi_device_wren(void) +{ + // Write enable through STIG (not required, auto send by controller during write) + return alt_qspi_stig_cmd(ALT_QSPI_STIG_OPCODE_WREN, 0, 10000); +} + +ALT_STATUS_CODE alt_qspi_device_wrdis(void) +{ + // Write disable through STIG (not required, auto send by controller during write) + return alt_qspi_stig_cmd(ALT_QSPI_STIG_OPCODE_WRDIS, 0, 10000); +} + +ALT_STATUS_CODE alt_qspi_device_rdid(uint32_t * rdid) +{ + // Read flash device ID through STIG + return alt_qspi_stig_rd_cmd(ALT_QSPI_STIG_OPCODE_RDID, 0, 4, rdid, 10000); +} + +ALT_STATUS_CODE alt_qspi_discovery_parameter(uint32_t * param) +{ + // Read flash discovery parameters through STIG + + return alt_qspi_stig_rd_cmd(ALT_QSPI_STIG_OPCODE_DISCVR_PARAM, 8, 8, param, 10000); +} + +ALT_STATUS_CODE alt_qspi_device_bank_select(uint32_t bank) +{ + ALT_STATUS_CODE status = ALT_E_SUCCESS; + dprintf("DEBUG[QSPI]: bank_select(): switching to bank 0x%" PRIu32 ".\n", bank); + + if (status == ALT_E_SUCCESS) + { + status = alt_qspi_device_wren(); + } + + if (status == ALT_E_SUCCESS) + { + status = alt_qspi_stig_wr_cmd(ALT_QSPI_STIG_OPCODE_WR_EXT_REG, 0, 1, &bank, 10000); + } + + if (status == ALT_E_SUCCESS) + { + status = alt_qspi_device_wrdis(); + } + + return status; +} + +///// + +static bool alt_qspi_is_enabled(void) +{ + uint32_t cfg = alt_read_word(ALT_QSPI_CFG_ADDR); + + if (cfg & ALT_QSPI_CFG_EN_SET_MSK) + { + return true; + } + else + { + return false; + } +} + +ALT_STATUS_CODE alt_qspi_ecc_start(void * block, size_t size) +{ + if (size < (ALT_QSPI_PAGE_SIZE * 8)) + { + return ALT_E_ERROR; + } + + if (alt_qspi_is_enabled() == false) + { + return ALT_E_ERROR; + } + + if (alt_qspi_is_idle() == false) + { + return ALT_E_ERROR; + } + + ALT_STATUS_CODE status = ALT_E_SUCCESS; + + // 1. Configure SRAM Partition Register to 126 words for read, 2 words for write. + // 2. Enable ECC on QSPI RAM + // 3. Trigger an indirect read transfer that will fill up 126 words in FIFO by + // monitoring read FIFO fill level; Do not read out data through AHB. + // 4. Start AHB read and start indirect write operation to write back to the same + // device location, this will fill up and initilaize the write partition RAM. + // 5. To clear spurious interrupts, reset the QSPI controller. + + // Save the previous partition size + + uint32_t sram_orig = alt_qspi_sram_partition_get(); + dprintf("DEBUG[QSPI][ECC]: Save original SRAM as %" PRIu32 ".\n", sram_orig); + + // Step 1 + + uint32_t sram_fill = (1 << ALT_QSPI_SRAMPART_ADDR_WIDTH) - 2; + alt_qspi_sram_partition_set(sram_fill); + dprintf("DEBUG[QSPI][ECC]: Set new SRAM as %" PRIu32 ".\n", sram_fill); + + // Step 2 + + dprintf("DEBUG[QSPI][ECC]: Enable ECC in SysMgr.\n"); + alt_write_word(ALT_SYSMGR_ECC_QSPI_ADDR, ALT_SYSMGR_ECC_QSPI_EN_SET_MSK); + + // Step 3 + + // Issue a read ~ 2x larger than the read partition. We will read out 1 page, + // which will be used as the buffer to write back to QSPI. This way no data + // actually changes thus no erase will be needed. + + if (status == ALT_E_SUCCESS) + { + dprintf("DEBUG[QSPI][ECC]: Start indirect read PAGE * 8.\n"); + status = alt_qspi_indirect_read_start(0x0, ALT_QSPI_PAGE_SIZE * 8); + } + + // Read out 1 page for the write data + + if (status == ALT_E_SUCCESS) + { + dprintf("DEBUG[QSPI][ECC]: Reading out 1 page ...\n"); + + uint32_t read_size = 0; + char * buffer = block; + while (read_size < ALT_QSPI_PAGE_SIZE) + { + uint32_t level = alt_qspi_indirect_read_fill_level(); + level = MIN(level, (ALT_QSPI_PAGE_SIZE - read_size) / sizeof(uint32_t)); + + uint32_t * data = (uint32_t *)(&buffer[read_size]); + for (uint32_t i = 0; i < level; ++i) + { + *data = alt_read_word(ALT_QSPIDATA_ADDR); + ++data; + } + + read_size += level * sizeof(uint32_t); + } + + if (read_size != ALT_QSPI_PAGE_SIZE) + { + status = ALT_E_ERROR; + } + } + + // Wait for read FIFO to report it is up to the specified fill level. + + if (status == ALT_E_SUCCESS) + { + dprintf("DEBUG[QSPI][ECC]: Waiting for read fill level ...\n"); + + uint32_t timeout = 10000; + + while (alt_qspi_indirect_read_fill_level() < sram_fill) + { + if (--timeout == 0) + { + dprintf("DEBUG[QSPI][ECC]: Waiting for read fill timeout !!!\n"); + status = ALT_E_TMO; + break; + } + } + } + + // Step 4 + + // Issue a write of 1 page of the same data from 0x0. + + if (status == ALT_E_SUCCESS) + { + dprintf("DEBUG[QSPI][ECC]: Start indirect write PAGE.\n"); + status = alt_qspi_indirect_write_start(0x0, ALT_QSPI_PAGE_SIZE); + } + + if (status == ALT_E_SUCCESS) + { + dprintf("DEBUG[QSPI][ECC]: Writing in 1 page ...\n"); + + uint32_t write_size = 0; + char * buffer = block; + + while (write_size < ALT_QSPI_PAGE_SIZE) + { + uint32_t space = 2 - alt_qspi_indirect_write_fill_level(); + if (space == 0) + { + dprintf("DEBUG[QSPI][ECC]: Write FIFO filled at write_size = %" PRIu32 ".\n", write_size); + // Space = 0; which means all 2 positions in the write FIFO is filled, + // meaning it has been initialized with respect to ECC. + break; + } + + space = MIN(space, (ALT_QSPI_PAGE_SIZE - write_size) / sizeof(uint32_t)); + + uint32_t * data = (uint32_t *)(&buffer[write_size]); + for (uint32_t i = 0; i < space; ++i) + { + alt_write_word(ALT_QSPIDATA_ADDR, *data); + ++data; + } + + write_size += space * sizeof(uint32_t); + } + + if (write_size != ALT_QSPI_PAGE_SIZE) + { + dprintf("DEBUG[QSPI][ECC]: Cancel indirect write.\n"); + status = alt_qspi_indirect_write_cancel(); + } + } + + if (status == ALT_E_SUCCESS) + { + dprintf("DEBUG[QSPI][ECC]: Finish indirect write.\n"); + status = alt_qspi_indirect_write_finish(); + } + + // Cancel the indirect read as it has initialized the read FIFO partition. + + if (status == ALT_E_SUCCESS) + { + dprintf("DEBUG[QSPI][ECC]: Cancel indirect read.\n"); + status = alt_qspi_indirect_read_cancel(); + } + + if (status == ALT_E_SUCCESS) + { + dprintf("DEBUG[QSPI][ECC]: Finish indirect read.\n"); + status = alt_qspi_indirect_read_finish(); + } + + // Step 5 + + if (status == ALT_E_SUCCESS) + { + dprintf("DEBUG[QSPI][ECC]: Clear any pending spurious QSPI ECC interrupts.\n"); + + alt_write_word(ALT_SYSMGR_ECC_QSPI_ADDR, + ALT_SYSMGR_ECC_QSPI_EN_SET_MSK + | ALT_SYSMGR_ECC_QSPI_SERR_SET_MSK + | ALT_SYSMGR_ECC_QSPI_DERR_SET_MSK); + } + + ///// + + // Restore original partition + + if (status == ALT_E_SUCCESS) + { + dprintf("DEBUG[QSPI][ECC]: Restore original SRAM as %" PRIu32 ".\n", sram_orig); + status = alt_qspi_sram_partition_set(sram_orig); + } + + return status; +} diff --git a/c/src/lib/libbsp/arm/altera-cyclone-v/preinstall.am b/c/src/lib/libbsp/arm/altera-cyclone-v/preinstall.am index 4093831f3d..768c01da72 100644 --- a/c/src/lib/libbsp/arm/altera-cyclone-v/preinstall.am +++ b/c/src/lib/libbsp/arm/altera-cyclone-v/preinstall.am @@ -143,10 +143,18 @@ $(PROJECT_INCLUDE)/bsp/nocache-heap.h: include/nocache-heap.h $(PROJECT_INCLUDE) $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/bsp/nocache-heap.h PREINSTALL_FILES += $(PROJECT_INCLUDE)/bsp/nocache-heap.h +$(PROJECT_INCLUDE)/bsp/alt_16550_uart.h: hwlib/include/alt_16550_uart.h $(PROJECT_INCLUDE)/bsp/$(dirstamp) + $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/bsp/alt_16550_uart.h +PREINSTALL_FILES += $(PROJECT_INCLUDE)/bsp/alt_16550_uart.h + $(PROJECT_INCLUDE)/bsp/alt_address_space.h: hwlib/include/alt_address_space.h $(PROJECT_INCLUDE)/bsp/$(dirstamp) $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/bsp/alt_address_space.h PREINSTALL_FILES += $(PROJECT_INCLUDE)/bsp/alt_address_space.h +$(PROJECT_INCLUDE)/bsp/alt_cache.h: hwlib/include/alt_cache.h $(PROJECT_INCLUDE)/bsp/$(dirstamp) + $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/bsp/alt_cache.h +PREINSTALL_FILES += $(PROJECT_INCLUDE)/bsp/alt_cache.h + $(PROJECT_INCLUDE)/bsp/alt_clock_group.h: hwlib/include/alt_clock_group.h $(PROJECT_INCLUDE)/bsp/$(dirstamp) $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/bsp/alt_clock_group.h PREINSTALL_FILES += $(PROJECT_INCLUDE)/bsp/alt_clock_group.h @@ -155,6 +163,18 @@ $(PROJECT_INCLUDE)/bsp/alt_clock_manager.h: hwlib/include/alt_clock_manager.h $( $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/bsp/alt_clock_manager.h PREINSTALL_FILES += $(PROJECT_INCLUDE)/bsp/alt_clock_manager.h +$(PROJECT_INCLUDE)/bsp/alt_dma_common.h: hwlib/include/alt_dma_common.h $(PROJECT_INCLUDE)/bsp/$(dirstamp) + $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/bsp/alt_dma_common.h +PREINSTALL_FILES += $(PROJECT_INCLUDE)/bsp/alt_dma_common.h + +$(PROJECT_INCLUDE)/bsp/alt_dma.h: hwlib/include/alt_dma.h $(PROJECT_INCLUDE)/bsp/$(dirstamp) + $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/bsp/alt_dma.h +PREINSTALL_FILES += $(PROJECT_INCLUDE)/bsp/alt_dma.h + +$(PROJECT_INCLUDE)/bsp/alt_dma_program.h: hwlib/include/alt_dma_program.h $(PROJECT_INCLUDE)/bsp/$(dirstamp) + $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/bsp/alt_dma_program.h +PREINSTALL_FILES += $(PROJECT_INCLUDE)/bsp/alt_dma_program.h + $(PROJECT_INCLUDE)/bsp/alt_generalpurpose_io.h: hwlib/include/alt_generalpurpose_io.h $(PROJECT_INCLUDE)/bsp/$(dirstamp) $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/bsp/alt_generalpurpose_io.h PREINSTALL_FILES += $(PROJECT_INCLUDE)/bsp/alt_generalpurpose_io.h @@ -175,6 +195,10 @@ $(PROJECT_INCLUDE)/bsp/alt_mpu_registers.h: hwlib/include/alt_mpu_registers.h $( $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/bsp/alt_mpu_registers.h PREINSTALL_FILES += $(PROJECT_INCLUDE)/bsp/alt_mpu_registers.h +$(PROJECT_INCLUDE)/bsp/alt_qspi_private.h: hwlib/include/alt_qspi_private.h $(PROJECT_INCLUDE)/bsp/$(dirstamp) + $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/bsp/alt_qspi_private.h +PREINSTALL_FILES += $(PROJECT_INCLUDE)/bsp/alt_qspi_private.h + $(PROJECT_INCLUDE)/bsp/alt_reset_manager.h: hwlib/include/alt_reset_manager.h $(PROJECT_INCLUDE)/bsp/$(dirstamp) $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/bsp/alt_reset_manager.h PREINSTALL_FILES += $(PROJECT_INCLUDE)/bsp/alt_reset_manager.h @@ -191,6 +215,14 @@ $(PROJECT_INCLUDE)/bsp/socal/alt_clkmgr.h: hwlib/include/socal/alt_clkmgr.h $(PR $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/bsp/socal/alt_clkmgr.h PREINSTALL_FILES += $(PROJECT_INCLUDE)/bsp/socal/alt_clkmgr.h +$(PROJECT_INCLUDE)/bsp/socal/alt_dmanonsecure.h: hwlib/include/socal/alt_dmanonsecure.h $(PROJECT_INCLUDE)/bsp/socal/$(dirstamp) + $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/bsp/socal/alt_dmanonsecure.h +PREINSTALL_FILES += $(PROJECT_INCLUDE)/bsp/socal/alt_dmanonsecure.h + +$(PROJECT_INCLUDE)/bsp/socal/alt_dmasecure.h: hwlib/include/socal/alt_dmasecure.h $(PROJECT_INCLUDE)/bsp/socal/$(dirstamp) + $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/bsp/socal/alt_dmasecure.h +PREINSTALL_FILES += $(PROJECT_INCLUDE)/bsp/socal/alt_dmasecure.h + $(PROJECT_INCLUDE)/bsp/socal/alt_gpio.h: hwlib/include/socal/alt_gpio.h $(PROJECT_INCLUDE)/bsp/socal/$(dirstamp) $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/bsp/socal/alt_gpio.h PREINSTALL_FILES += $(PROJECT_INCLUDE)/bsp/socal/alt_gpio.h @@ -203,6 +235,14 @@ $(PROJECT_INCLUDE)/bsp/socal/alt_l3.h: hwlib/include/socal/alt_l3.h $(PROJECT_IN $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/bsp/socal/alt_l3.h PREINSTALL_FILES += $(PROJECT_INCLUDE)/bsp/socal/alt_l3.h +$(PROJECT_INCLUDE)/bsp/socal/alt_qspidata.h: hwlib/include/socal/alt_qspidata.h $(PROJECT_INCLUDE)/bsp/socal/$(dirstamp) + $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/bsp/socal/alt_qspidata.h +PREINSTALL_FILES += $(PROJECT_INCLUDE)/bsp/socal/alt_qspidata.h + +$(PROJECT_INCLUDE)/bsp/socal/alt_qspi.h: hwlib/include/socal/alt_qspi.h $(PROJECT_INCLUDE)/bsp/socal/$(dirstamp) + $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/bsp/socal/alt_qspi.h +PREINSTALL_FILES += $(PROJECT_INCLUDE)/bsp/socal/alt_qspi.h + $(PROJECT_INCLUDE)/bsp/socal/alt_rstmgr.h: hwlib/include/socal/alt_rstmgr.h $(PROJECT_INCLUDE)/bsp/socal/$(dirstamp) $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/bsp/socal/alt_rstmgr.h PREINSTALL_FILES += $(PROJECT_INCLUDE)/bsp/socal/alt_rstmgr.h -- cgit v1.2.3