/** @brief Type defintions used by the bootloader.
 *
 * @copyright 2020 Remsdaq Ltd.
 *
 * @file bootloader_types.h
 *
 * @date  26 May 2020
 * @author Dan Smithers <dwhs@remsdaq.com>
 *
 *
 *  Created on:
 *      Author: dsmit
 */

#ifndef BOOTLOADER_TYPES_H_
#define BOOTLOADER_TYPES_H_

#include <stdint.h>

/** @brief FlexSPI Configuration Block
 *
 * FlexSPI Configuration block consists of parameters regarding specific Flash devices
 * including read command sequence, quad mode enablement sequence (optional), etc.
 */
typedef struct
{
    uint32_t tag; /** @brief 0x42464346, ascii: 'FCFB'. */
    union {
        struct {
            uint32_t bugfix:8; /**< [07:00] bugfix = 0. */
            uint32_t minor:8;  /**< [15:08] minor */
            uint32_t major:8;  /**< [23:16] major = 1 */
            uint32_t V:8;      /**< [31:24] ascii ‘V’ */
        } B;        /**< Bitfield representation. */
        uint32_t R; /**< Register representation. */
    } version;                    /**< @brief Version 0x56010000 / 0x56010100 */
    uint8_t reserved1[4];         /**< @brief Reserved. */
    uint8_t readSampleClkSrc;     /**< 0 – internal loopback
                                   *   1 – loopback from DQS pad
                                   *   3 – Flash provided DQS */
    uint8_t csHoldTime;           /**< Serial Flash CS Hold Time.
                                   * Recommended default value is 0x03. */
    uint8_t csSetupTime;          /**< @brief Serial Flash CS setup time
                                   * Recommended default value is 0x03. */
    uint8_t columnAdressWidth;    /**< 3 – For HyperFlash
                                   *   12/13 – For Serial NAND, see datasheet to find correct value
                                   *   0 – Other devices */
    uint8_t deviceModeCfgEnable;  /**< @brief Device Mode Configuration Enable feature
                                   *   0 – Disabled
                                   *   1 – Enabled */
    uint8_t reserved2;            /**< Reserved. */
    uint16_t waitTimeCfgCommands; /**< @brief Wait time for all configuration commands, unit 100us.
                                   *
                                   *   Available for device that support v1.1.0 FlexSPI configuration
                                   *   block. If it is greater than 0, ROM will wait
                                   *   waitTimeCfgCommands * 100us for all device memory
                                   *   configuration commands instead of using read status to wait
                                   *   until these commands complete.*/
    union {
        struct {
            uint32_t numLutSeq:8; /**< @brief Bit[7:0] - number of LUT sequences for Device mode configuration command. */
            uint32_t startLut:8;  /**< @brief Bit[15:8] - starting LUT index of Device mode configuration command. */
            uint32_t reserved:16; /**< @brief Bit[31:16] - must be 0 */
        } B;        /**< Bitfield representation. */
        uint32_t R; /**< Register representation. */
    } deviceModeSeq;              /**< @brief Sequence parameter for device mode configuration*/
    uint32_t deviceModeArg;       /**< @brief Device Mode argument, effective only when deviceModeCfgEnable = 1*/
    uint8_t configCmdEnable;      /**< @brief Config Command Enable feature
                                   *   0 – Disabled
                                   *   1 – Enabled */
    uint8_t reserved3[3];         /**< Reserved. */
    uint8_t configCmdSeqs[12];    /**< Sequences for Config Command, allow 3 separate configuration command sequences. */
    uint8_t reserved4[4];         /**< Reserved. */
    uint8_t cfgCmdArgs[12];       /**< Arguments for each separate configuration command sequence. */
    uint8_t reserved5[4];         /**< Reserved */
    union {
        struct {
             uint32_t Bit0:1; /**< @brief Differential clock enable. */
             uint32_t Bit1:1; /**< @brief CK2 enable, must set to 0 in this silicon. */
             uint32_t Bit2:1; /**< @brief ParallelModeEnable, must set to 0 for this silicon. */
             uint32_t Bit3:1; /**< @brief wordAddressableEnable. */
             uint32_t Bit4:1; /**< @brief Safe Configuration Frequency enable set to 1 for the
                               * devices that support DDR Read instructions. */
             uint32_t Bit5:1; /**< @brief  – Pad Setting Override Enable. */
             uint32_t Bit6:1; /**< @brief  – DDR Mode Enable, set to 1 for device supports DDR read command. */
        } B;        /**< Bitfield representation. */
        uint32_t R; /**< Register representation. */
    } controllerMiscOption;
    uint8_t deviceType;           /**< 1 – Serial NOR
                                   * 2 – Serial NAND */
    uint8_t sflashPadType;        /**< Single pad
                                   * 2 – Dual pads
                                   * 4 – Quad pads
                                   * 8 – Octal pads */
    uint8_t serialClkFreq;        /**< 0x046 1 Chip specific value, for this silicon
                                   * 1 – 30 MHz
                                   * 2 – 50 MHz
                                   * 3 – 60 MHz
                                   * 4 – 75 MHz
                                   * 5 – 80 MHz
                                   * 6 – 100 MHz
                                   * 7 – 120 MHz
                                   * 8 – 133 MHz
                                   * 9 – 166 MHz
                                   * Other value: 30 MHz */
    uint8_t lutCustomSeqEnable;   /**< 0 – Use pre-defined LUT sequence index and number
                                   * 1 - Use LUT sequence parameters provided in this block */
    uint8_t reserved6[8];         /**< Reserved */
    uint32_t sflashA1Size;        /**< For SPI NOR, need to fill with actual size.
                                   * For SPI NAND, need to fill with actual size * 2. */
    uint32_t sflashA2Size;        /**< For SPI NOR, need to fill with actual size.
                                   * For SPI NAND, need to fill with actual size * 2. */
    uint32_t sflashB1Size;        /**< For SPI NOR, need to fill with actual size.
                                   * For SPI NAND, need to fill with actual size * 2. */
    uint32_t sflashB2Size;        /**< For SPI NOR, need to fill with actual size.
                                   * For SPI NAND, need to fill with actual size * 2. */
    uint32_t csPadSettingOverride;   /**< Set to 0 if it is not supported */
    uint32_t sclkPadSettingOverride; /**< Set to 0 if it is not supported */
    uint32_t dataPadSettingOverride; /**< Set to 0 if it is not supported */
    uint32_t dqsPadSettingOverride;  /**< Set to 0 if it is not supported */
    uint32_t timeoutInMs;        /**< @brief Maximum wait time during read busy status
                                  *
                                  * 0 – Disabled timeout checking feature
                                  * Other value – Timeout if the wait time exceeds this value. */
    uint32_t commandInterval;      /**<  Unit: ns
                                   * Currently, it is used for SPI NAND only at high frequency. */
    union {
        struct {
            uint32_t DLLA:16;     /**< [15:0] data valid time for DLLA in terms of 0.1 ns. */
            uint32_t DLLB:16;     /**< [31:16] data valid time for DLLB in terms of 0.1 ns */
        } B;        /**< Bitfield representation. */
        uint32_t R; /**< Register representation. */
    } dataValidTimeDLLA;          /**< @brief Time from clock edge to data valid edge, unit ns.
                                   *
                                   * This field is used when the FlexSPI Root clock is less than 100 MHz and
                                   * the read sample clock source is device provided DQS signal without CK2 support.
                                   */

    uint16_t busyOffset;           /**< busy bit offset, valid range :0-31 */
    uint16_t busyBitPolarity;      /**< 0 - busy bit is 1 if device is busy
                                    *   1 – busy bit is 0 if device is busy */
    uint8_t lookupTable[256];      /**<  Lookup table. */
    uint8_t lutCustomSeq[48];      /**< Customized LUT sequence, see below table for details. */
    uint8_t reserved7[16];         /**< Reserved for future use. */
} FlexSPI_Header_t;

/** @brief Serial NOR configuration block
 * Contains FlexSPIheader common block and NOR specific configuration.
 */
typedef struct
{
    FlexSPI_Header_t memCfg;      /**< Common header. */
    uint32_t pageSize;            /**< Page size in terms of bytes, not used by ROM. */
    uint32_t sectorSize;          /**< Sector size in terms of bytes, not used by ROM. */
    uint32_t ipCmdSerialClkFreq;  /**< @brief Chip specific value, not used by ROM
                                   * 0 – No change, keep current serial clock unchanged
                                   * 1 – 30 MHz
                                   * 2 – 50 MHz
                                   * 3 – 60 MHz
                                   * 4 – 75 MHz
                                   * 5 – 80 MHz
                                   * 6 – 100 MHz
                                   * 7 – 120 MHz
                                   * 8 – 133 MHz
                                   * 9 – 166 MHz */
    uint8_t reserved[52];         /**< Reserved for future use. */
} serialNOR_t;

/** @brief Structure to overlay on Image Vector Table
 *
 * The Image Vector Table (IVT) is the data structure that the ROM reads from the boot
 * device supplying the program image containing the required data components to perform
 * a successful boot.
 *
 * The IVT includes the program image entry point, a pointer to Device Configuration Data
 * (DCD) and other pointers used by the ROM during the boot process. The ROM locates
 * the IVT at a fixed address that is determined by the boot device connected to the Chip.
 * The IVT offset from the base address and initial load region size for each boot device
 * type is defined in the table below. The location of the IVT is the only fixed requirement
 * by the ROM. The remainder or the image memory map is flexible and is determined by
 * the contents of the IVT.
 */
typedef struct
{
    union
    {
        struct
        {
          uint32_t tag:8;      /**< A single byte field set to 0xD1. */
          uint32_t length:16;  /**< A two byte field in big endian format containing the overall length of the IVT,
                                * in bytes, including the header. (the length is fixed and must have a value of
                                * 32 bytes). */
          uint32_t version:8;  /**< A single byte field set to 0x40 or 0x41. */
        } B;        /**< @brief Bitfield representation. */
        uint32_t R; /**< @brief Register representation. */
    } header;
    uint32_t entry;     /**< Absolute address of the first instruction to execute from the image. */
    uint32_t reserved1; /**< Reserved and should be zero. */
    uint32_t dcd;       /**< Absolute address of the image DCD. The DCD is optional so this field may be set to NULL if no DCD is required. See
                         *   Device Configuration Data (DCD) for further details on the DCD. */
    uint32_t bootData;  /**< Absolute address of the boot data */
    uint32_t self;      /**< Absolute address of the IVT. Used internally by the ROM. */
    uint32_t csf;       /**< Absolute address of the Command Sequence File (CSF) used by the HAB library. See High-Assurance Boot (HAB) for
                         *   details on the secure boot using HAB. This field must be set to NULL when not performing a secure boot. */
    uint32_t reserved2; /**< Reserved and should be zero */
} IVT_t;

/** Structure to overlay on Boot Parameter Table. */
typedef struct
{
    uint32_t bootStart; /**< Absolute address of the image */
    uint32_t length;    /**< Size of the program image. */
    uint32_t plugin;    /**< Plugin flag (see Plugin image). */
} BPT_t;

/** @brief Device Configuration Data (DCD)
 *
 * Upon reset, the chip uses the default register values for all peripherals in the system.
 * However, these settings typically are not ideal for achieving the optimal system
 * performance and there are even some peripherals that must be configured before they can
 * be used.
 *
 * The DCD is a configuration information contained in the program image (external to the
 * ROM) that the ROM interprets to configure various peripherals on the chip.
 * For example, some components (such as SDRAM) require some sequence of register
 * programming as a part of the configuration before it is ready to be used. The DCD feature
 * can be used to program the SEMC register to the optimal settings.
 * The ROM determines the location of the DCD table based on the information located in
 * the Image Vector Table (IVT). See Image Vector Table and Boot Data for more details.
 * The DCD table shown below is a big-endian byte array of the allowable DCD commands.
 * The maximum size of the DCD is limited to 1768 B.
 */
typedef struct
{

    union
    {
        struct
        {
          uint32_t tag:8;      /**< A single byte field set to 0xD2. */
          uint32_t length:16;  /**< A two byte field in big endian format containing the overall length of the IVT,
                                * in bytes, including the header. (the length is fixed and must have a value of
                                * 32 bytes). */
          uint32_t version:8;  /**< A single byte field set to 0x40 or 0x41. */
        } B;        /**< @brief Bitfield representation. */
        uint32_t R; /**< @brief Register representation. */
    } header;
} DCD_t;
#endif /* BOOTLOADER_TYPES_H_ */
