2019-11-02 11:52:26 -04:00
|
|
|
/*
|
|
|
|
* 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"
|
2020-12-02 21:05:29 -05:00
|
|
|
#include "boards/flash_config.h"
|
2021-11-12 20:30:24 -05:00
|
|
|
#include "supervisor/internal_flash.h"
|
2020-09-28 22:21:17 -04:00
|
|
|
#include "supervisor/linker.h"
|
2019-11-02 11:52:26 -04:00
|
|
|
|
2021-11-12 20:30:24 -05:00
|
|
|
STATIC status_t PLACE_IN_ITCM(flexspi_nor_write_enable)(FLEXSPI_Type * base, uint32_t baseAddr)
|
2019-11-02 11:52:26 -04:00
|
|
|
{
|
|
|
|
flexspi_transfer_t flashXfer;
|
|
|
|
status_t status;
|
|
|
|
|
|
|
|
/* Write enable */
|
|
|
|
flashXfer.deviceAddress = baseAddr;
|
2021-03-15 09:57:36 -04:00
|
|
|
flashXfer.port = kFLEXSPI_PortA1;
|
|
|
|
flashXfer.cmdType = kFLEXSPI_Command;
|
|
|
|
flashXfer.SeqNumber = 1;
|
|
|
|
flashXfer.seqIndex = ROM_INDEX_WRITEENABLE;
|
2019-11-02 11:52:26 -04:00
|
|
|
|
|
|
|
status = FLEXSPI_TransferBlocking(base, &flashXfer);
|
|
|
|
|
|
|
|
return status;
|
|
|
|
}
|
|
|
|
|
2021-11-12 20:30:24 -05:00
|
|
|
STATIC status_t PLACE_IN_ITCM(flexspi_nor_wait_bus_busy)(FLEXSPI_Type * base)
|
2019-11-02 11:52:26 -04:00
|
|
|
{
|
|
|
|
/* Wait status ready. */
|
|
|
|
bool isBusy;
|
|
|
|
uint32_t readValue;
|
|
|
|
status_t status;
|
|
|
|
flexspi_transfer_t flashXfer;
|
|
|
|
|
|
|
|
flashXfer.deviceAddress = 0;
|
2021-03-15 09:57:36 -04:00
|
|
|
flashXfer.port = kFLEXSPI_PortA1;
|
|
|
|
flashXfer.cmdType = kFLEXSPI_Read;
|
|
|
|
flashXfer.SeqNumber = 1;
|
|
|
|
flashXfer.seqIndex = ROM_INDEX_READSTATUSREG;
|
|
|
|
flashXfer.data = &readValue;
|
|
|
|
flashXfer.dataSize = 1;
|
2019-11-02 11:52:26 -04:00
|
|
|
|
|
|
|
do
|
|
|
|
{
|
|
|
|
status = FLEXSPI_TransferBlocking(base, &flashXfer);
|
|
|
|
|
2021-03-15 09:57:36 -04:00
|
|
|
if (status != kStatus_Success) {
|
2019-11-02 11:52:26 -04:00
|
|
|
return status;
|
|
|
|
}
|
2020-09-28 22:21:17 -04:00
|
|
|
size_t busyBit = readValue & (1U << qspiflash_config.memConfig.busyOffset);
|
|
|
|
isBusy = (qspiflash_config.memConfig.busyBitPolarity == 0 && busyBit != 0) ||
|
2021-03-15 09:57:36 -04:00
|
|
|
(qspiflash_config.memConfig.busyBitPolarity == 1 && busyBit == 0);
|
2019-11-02 11:52:26 -04:00
|
|
|
} while (isBusy);
|
|
|
|
|
|
|
|
return status;
|
|
|
|
}
|
|
|
|
|
2021-03-15 09:57:36 -04:00
|
|
|
status_t PLACE_IN_ITCM(flexspi_nor_flash_erase_sector)(FLEXSPI_Type * base, uint32_t address)
|
2019-11-02 11:52:26 -04:00
|
|
|
{
|
|
|
|
status_t status;
|
|
|
|
flexspi_transfer_t flashXfer;
|
|
|
|
|
|
|
|
/* Write enable */
|
|
|
|
flashXfer.deviceAddress = address;
|
2021-03-15 09:57:36 -04:00
|
|
|
flashXfer.port = kFLEXSPI_PortA1;
|
|
|
|
flashXfer.cmdType = kFLEXSPI_Command;
|
|
|
|
flashXfer.SeqNumber = 1;
|
|
|
|
flashXfer.seqIndex = ROM_INDEX_WRITEENABLE;
|
2019-11-02 11:52:26 -04:00
|
|
|
|
|
|
|
status = FLEXSPI_TransferBlocking(base, &flashXfer);
|
|
|
|
|
2021-03-15 09:57:36 -04:00
|
|
|
if (status != kStatus_Success) {
|
2019-11-02 11:52:26 -04:00
|
|
|
return status;
|
|
|
|
}
|
|
|
|
|
|
|
|
flashXfer.deviceAddress = address;
|
2021-03-15 09:57:36 -04:00
|
|
|
flashXfer.port = kFLEXSPI_PortA1;
|
|
|
|
flashXfer.cmdType = kFLEXSPI_Command;
|
|
|
|
flashXfer.SeqNumber = 1;
|
|
|
|
flashXfer.seqIndex = ROM_INDEX_ERASESECTOR;
|
|
|
|
status = FLEXSPI_TransferBlocking(base, &flashXfer);
|
2019-11-02 11:52:26 -04:00
|
|
|
|
2021-03-15 09:57:36 -04:00
|
|
|
if (status != kStatus_Success) {
|
2019-11-02 11:52:26 -04:00
|
|
|
return status;
|
|
|
|
}
|
|
|
|
|
|
|
|
status = flexspi_nor_wait_bus_busy(base);
|
|
|
|
|
|
|
|
/* Do software reset. */
|
|
|
|
FLEXSPI_SoftwareReset(base);
|
|
|
|
|
|
|
|
return status;
|
|
|
|
}
|
|
|
|
|
2021-03-15 09:57:36 -04:00
|
|
|
status_t PLACE_IN_ITCM(flexspi_nor_flash_page_program)(FLEXSPI_Type * base, uint32_t dstAddr, const uint32_t *src)
|
2019-11-02 11:52:26 -04:00
|
|
|
{
|
|
|
|
status_t status;
|
|
|
|
flexspi_transfer_t flashXfer;
|
|
|
|
|
|
|
|
/* Write enable */
|
|
|
|
status = flexspi_nor_write_enable(base, dstAddr);
|
|
|
|
|
2021-03-15 09:57:36 -04:00
|
|
|
if (status != kStatus_Success) {
|
2019-11-02 11:52:26 -04:00
|
|
|
return status;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Prepare page program command */
|
|
|
|
flashXfer.deviceAddress = dstAddr;
|
2021-03-15 09:57:36 -04:00
|
|
|
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) {
|
2019-11-02 11:52:26 -04:00
|
|
|
return status;
|
|
|
|
}
|
|
|
|
|
|
|
|
status = flexspi_nor_wait_bus_busy(base);
|
|
|
|
|
|
|
|
/* Do software reset. */
|
2021-03-15 09:57:36 -04:00
|
|
|
#if defined(FSL_FEATURE_SOC_OTFAD_COUNT)
|
2019-11-02 11:52:26 -04:00
|
|
|
base->AHBCR |= FLEXSPI_AHBCR_CLRAHBRXBUF_MASK | FLEXSPI_AHBCR_CLRAHBTXBUF_MASK;
|
|
|
|
base->AHBCR &= ~(FLEXSPI_AHBCR_CLRAHBRXBUF_MASK | FLEXSPI_AHBCR_CLRAHBTXBUF_MASK);
|
2021-03-15 09:57:36 -04:00
|
|
|
#else
|
2019-11-02 11:52:26 -04:00
|
|
|
FLEXSPI_SoftwareReset(base);
|
2021-03-15 09:57:36 -04:00
|
|
|
#endif
|
2019-11-02 11:52:26 -04:00
|
|
|
|
|
|
|
return status;
|
|
|
|
}
|