text: /*
   * Copyright (c) 2016, Freescale Semiconductor, Inc.
   * Copyright 2016-2019 NXP
   * All rights reserved.
   *
   *
   * SPDX-License-Identifier: BSD-3-Clause
   */
  
  #include "fsl_flexspi.h"
  #include "internal_flash.h"
  #include "boards/board.h"
  #include "supervisor/linker.h"
  
  status_t PLACE_IN_ITCM(flexspi_nor_write_enable)(FLEXSPI_Type *base, uint32_t baseAddr)
  {
      flexspi_transfer_t flashXfer;
      status_t status;
  
      /* Write enable */
      flashXfer.deviceAddress = baseAddr;
      flashXfer.port          = kFLEXSPI_PortA1;
      flashXfer.cmdType       = kFLEXSPI_Command;
      flashXfer.SeqNumber     = 1;
      flashXfer.seqIndex      = ROM_INDEX_WRITEENABLE;
  
      status = FLEXSPI_TransferBlocking(base, &flashXfer);
  
      return status;
  }
  
  status_t PLACE_IN_ITCM(flexspi_nor_wait_bus_busy)(FLEXSPI_Type *base)
  {
      /* Wait status ready. */
      bool isBusy;
      uint32_t readValue;
      status_t status;
      flexspi_transfer_t flashXfer;
  
      flashXfer.deviceAddress = 0;
      flashXfer.port          = kFLEXSPI_PortA1;
      flashXfer.cmdType       = kFLEXSPI_Read;
      flashXfer.SeqNumber     = 1;
      flashXfer.seqIndex      = ROM_INDEX_READSTATUSREG;
      flashXfer.data          = &readValue;
      flashXfer.dataSize      = 1;
  
      do
      {
          status = FLEXSPI_TransferBlocking(base, &flashXfer);
  
          if (status != kStatus_Success)
          {
              return status;
          }
          size_t busyBit = readValue & (1U << qspiflash_config.memConfig.busyOffset);
          isBusy = (qspiflash_config.memConfig.busyBitPolarity == 0 && busyBit != 0) ||
                   (qspiflash_config.memConfig.busyBitPolarity == 1 && busyBit == 0);
      } while (isBusy);
  
      return status;
  }
  
  status_t PLACE_IN_ITCM(flexspi_nor_flash_erase_sector)(FLEXSPI_Type *base, uint32_t address)
  {
      status_t status;
      flexspi_transfer_t flashXfer;
  
      /* Write enable */
      flashXfer.deviceAddress = address;
      flashXfer.port          = kFLEXSPI_PortA1;
      flashXfer.cmdType       = kFLEXSPI_Command;
      flashXfer.SeqNumber     = 1;
      flashXfer.seqIndex      = ROM_INDEX_WRITEENABLE;
  
      status = FLEXSPI_TransferBlocking(base, &flashXfer);
  
      if (status != kStatus_Success)
      {
          return status;
      }
  
      flashXfer.deviceAddress = address;
      flashXfer.port          = kFLEXSPI_PortA1;
      flashXfer.cmdType       = kFLEXSPI_Command;
      flashXfer.SeqNumber     = 1;
      flashXfer.seqIndex      = ROM_INDEX_ERASESECTOR;
      status                  = FLEXSPI_TransferBlocking(base, &flashXfer);
  
      if (status != kStatus_Success)
      {
          return status;
      }
  
      status = flexspi_nor_wait_bus_busy(base);
  
      /* Do software reset. */
      FLEXSPI_SoftwareReset(base);
  
      return status;
  }
  
  status_t PLACE_IN_ITCM(flexspi_nor_flash_page_program)(FLEXSPI_Type *base, uint32_t dstAddr, const uint32_t *src)
  {
      status_t status;
      flexspi_transfer_t flashXfer;
  
      /* Write enable */
      status = flexspi_nor_write_enable(base, dstAddr);
  
      if (status != kStatus_Success)
      {
          return status;
      }
  
      /* Prepare page program command */
      flashXfer.deviceAddress = dstAddr;
      flashXfer.port          = kFLEXSPI_PortA1;
      flashXfer.cmdType       = kFLEXSPI_Write;
      flashXfer.SeqNumber     = 1;
      flashXfer.seqIndex      = ROM_INDEX_PAGEPROGRAM;
      flashXfer.data          = (uint32_t *)src;
      flashXfer.dataSize      = FLASH_PAGE_SIZE;
      status                  = FLEXSPI_TransferBlocking(base, &flashXfer);
  
      if (status != kStatus_Success)
      {
          return status;
      }
  
      status = flexspi_nor_wait_bus_busy(base);
  
      /* Do software reset. */
  #if defined(FSL_FEATURE_SOC_OTFAD_COUNT)
      base->AHBCR |= FLEXSPI_AHBCR_CLRAHBRXBUF_MASK | FLEXSPI_AHBCR_CLRAHBTXBUF_MASK;
      base->AHBCR &= ~(FLEXSPI_AHBCR_CLRAHBRXBUF_MASK | FLEXSPI_AHBCR_CLRAHBTXBUF_MASK);
  #else
      FLEXSPI_SoftwareReset(base);
  #endif
  
      return status;
  }
  