978 lines
35 KiB
C
978 lines
35 KiB
C
/******************************************************************************
|
|
*
|
|
* Copyright (C) 2016-2018 Texas Instruments Incorporated - http://www.ti.com/
|
|
*
|
|
* Redistribution and use in source and binary forms, with or without
|
|
* modification, are permitted provided that the following conditions
|
|
* are met:
|
|
*
|
|
* Redistributions of source code must retain the above copyright
|
|
* notice, this list of conditions and the following disclaimer.
|
|
*
|
|
* 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.
|
|
*
|
|
* Neither the name of Texas Instruments Incorporated nor the names of
|
|
* its contributors may be used to endorse or promote products derived
|
|
* from this software without specific prior written permission.
|
|
*
|
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
* "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 COPYRIGHT
|
|
* OWNER OR CONTRIBUTORS 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 <stdint.h>
|
|
#include <stdbool.h>
|
|
#include "flash.h"
|
|
|
|
/******************************************************************************
|
|
*
|
|
* Defines for accesses to the security control in the customer configuration
|
|
* area in flash top sector.
|
|
*
|
|
******************************************************************************/
|
|
#define CCFG_OFFSET_SECURITY CCFG_O_BL_CONFIG
|
|
#define CCFG_SIZE_SECURITY 0x00000014
|
|
|
|
/******************************************************************************
|
|
*
|
|
* Default values for security control in customer configuration area in flash
|
|
* top sector.
|
|
*
|
|
******************************************************************************/
|
|
const uint8_t g_ccfg_default_sec[] = {
|
|
0xFF, 0xFF, 0xFF, 0xC5,
|
|
0xFF, 0xFF, 0xFF, 0xFF,
|
|
0xC5, 0xFF, 0xFF, 0xFF,
|
|
0xC5, 0xC5, 0xC5, 0xFF,
|
|
0xC5, 0xC5, 0xC5, 0xFF
|
|
};
|
|
|
|
typedef uint32_t (*flash_prg_pntr_t) (uint8_t *, uint32_t, uint32_t);
|
|
typedef uint32_t (*flash_sector_erase_pntr_t) (uint32_t);
|
|
|
|
/******************************************************************************
|
|
*
|
|
* Function prototypes for static functions
|
|
*
|
|
******************************************************************************/
|
|
static void issue_fsm_command(flash_state_command_t command);
|
|
static void enable_sectors_for_write(void);
|
|
static uint32_t scale_cycle_values(uint32_t specified_timing,
|
|
uint32_t scale_value);
|
|
static void set_write_mode(void);
|
|
static void trim_for_write(void);
|
|
static void set_read_mode(void);
|
|
|
|
/******************************************************************************
|
|
*
|
|
* Erase a flash sector
|
|
*
|
|
******************************************************************************/
|
|
uint32_t flash_sector_erase(uint32_t sector_address)
|
|
{
|
|
uint32_t error_return;
|
|
flash_sector_erase_pntr_t func_pntr;
|
|
|
|
/* Call ROM function */
|
|
func_pntr = (uint32_t (*)(uint32_t))(ROM_API_FLASH_TABLE[5]);
|
|
error_return = func_pntr(sector_address);
|
|
|
|
/* Enable standby because ROM function might have disabled it */
|
|
HWREGBITW(FLASH_BASE + FLASH_O_CFG, FLASH_CFG_DIS_STANDBY_BITN) = 0;
|
|
|
|
/* Return status of operation. */
|
|
return error_return;
|
|
}
|
|
|
|
/******************************************************************************
|
|
*
|
|
* Erase all unprotected sectors in the flash main bank
|
|
*
|
|
******************************************************************************/
|
|
uint32_t flash_bank_erase(bool force_precondition)
|
|
{
|
|
uint32_t error_return;
|
|
uint32_t sector_address;
|
|
uint32_t reg_val;
|
|
|
|
/* Enable all sectors for erase. */
|
|
enable_sectors_for_write();
|
|
|
|
/* Clear the Status register. */
|
|
issue_fsm_command(FAPI_CLEAR_STATUS);
|
|
|
|
/* Enable erase of all sectors and enable precondition if required. */
|
|
reg_val = HWREG(FLASH_BASE + FLASH_O_FSM_ST_MACHINE);
|
|
HWREG(FLASH_BASE + FLASH_O_FSM_WR_ENA) = FSM_REG_WRT_ENABLE;
|
|
HWREG(FLASH_BASE + FLASH_O_FSM_SECTOR1) = 0x00000000;
|
|
HWREG(FLASH_BASE + FLASH_O_FSM_SECTOR2) = 0x00000000;
|
|
if (force_precondition)
|
|
HWREG(FLASH_BASE + FLASH_O_FSM_ST_MACHINE) |=
|
|
FLASH_FSM_ST_MACHINE_DO_PRECOND;
|
|
HWREG(FLASH_BASE + FLASH_O_FSM_WR_ENA) = FSM_REG_WRT_DISABLE;
|
|
|
|
/* Issue the bank erase command to the FSM. */
|
|
issue_fsm_command(FAPI_ERASE_BANK);
|
|
|
|
/* Wait for erase to finish. */
|
|
while (flash_check_fsm_for_ready() == FAPI_STATUS_FSM_BUSY)
|
|
;
|
|
|
|
/* Update status. */
|
|
error_return = flash_check_fsm_for_error();
|
|
|
|
/* Disable sectors for erase. */
|
|
flash_disable_sectors_for_write();
|
|
|
|
/* Set configured precondition mode since it may have been forced on. */
|
|
if (!(reg_val & FLASH_FSM_ST_MACHINE_DO_PRECOND)) {
|
|
HWREG(FLASH_BASE + FLASH_O_FSM_WR_ENA) = FSM_REG_WRT_ENABLE;
|
|
HWREG(FLASH_BASE + FLASH_O_FSM_ST_MACHINE) &=
|
|
~FLASH_FSM_ST_MACHINE_DO_PRECOND;
|
|
HWREG(FLASH_BASE + FLASH_O_FSM_WR_ENA) = FSM_REG_WRT_DISABLE;
|
|
}
|
|
|
|
/* Program security data to default values in the customer configuration */
|
|
/* area within the flash top sector if erase was successful. */
|
|
if (error_return == FAPI_STATUS_SUCCESS) {
|
|
sector_address = FLASHMEM_BASE + flash_size_get() -
|
|
flash_sector_size_get();
|
|
error_return = flash_program((uint8_t *)g_ccfg_default_sec,
|
|
(sector_address + CCFG_OFFSET_SECURITY),
|
|
CCFG_SIZE_SECURITY);
|
|
}
|
|
|
|
/* Return status of operation. */
|
|
return error_return;
|
|
}
|
|
|
|
/******************************************************************************
|
|
*
|
|
* Programs unprotected main bank flash sectors
|
|
*
|
|
******************************************************************************/
|
|
uint32_t flash_program(uint8_t *data_buffer, uint32_t address, uint32_t count)
|
|
{
|
|
uint32_t error_return;
|
|
flash_prg_pntr_t func_pntr;
|
|
|
|
/* Call ROM function */
|
|
func_pntr = (uint32_t (*)(uint8_t *, uint32_t, uint32_t))
|
|
(ROM_API_FLASH_TABLE[6]);
|
|
error_return = func_pntr(data_buffer, address, count);
|
|
|
|
/* Enable standby because ROM function might have disabled it */
|
|
HWREGBITW(FLASH_BASE + FLASH_O_CFG, FLASH_CFG_DIS_STANDBY_BITN) = 0;
|
|
|
|
/* Return status of operation. */
|
|
return error_return;
|
|
}
|
|
|
|
/******************************************************************************
|
|
*
|
|
* Disables all sectors for erase and programming on the active bank
|
|
*
|
|
******************************************************************************/
|
|
void flash_disable_sectors_for_write(void)
|
|
{
|
|
/* Configure flash back to read mode */
|
|
set_read_mode();
|
|
|
|
/* Disable Level 1 Protection. */
|
|
HWREG(FLASH_BASE + FLASH_O_FBPROT) = FLASH_FBPROT_PROTL1DIS;
|
|
|
|
/* Disable all sectors for erase and programming. */
|
|
HWREG(FLASH_BASE + FLASH_O_FBSE) = 0x0000;
|
|
|
|
/* Enable Level 1 Protection. */
|
|
HWREG(FLASH_BASE + FLASH_O_FBPROT) = 0;
|
|
|
|
/* Protect sectors from sector erase. */
|
|
HWREG(FLASH_BASE + FLASH_O_FSM_WR_ENA) = FSM_REG_WRT_ENABLE;
|
|
HWREG(FLASH_BASE + FLASH_O_FSM_SECTOR1) = 0xFFFFFFFF;
|
|
HWREG(FLASH_BASE + FLASH_O_FSM_SECTOR2) = 0xFFFFFFFF;
|
|
HWREG(FLASH_BASE + FLASH_O_FSM_WR_ENA) = FSM_REG_WRT_DISABLE;
|
|
}
|
|
|
|
/******************************************************************************
|
|
*
|
|
* Issues a command to the Flash State Machine.
|
|
*
|
|
******************************************************************************/
|
|
static void issue_fsm_command(flash_state_command_t command)
|
|
{
|
|
/* Enable write to FSM register. */
|
|
HWREG(FLASH_BASE + FLASH_O_FSM_WR_ENA) = FSM_REG_WRT_ENABLE;
|
|
|
|
/* Issue FSM command. */
|
|
HWREG(FLASH_BASE + FLASH_O_FSM_CMD) = command;
|
|
|
|
/* Start command execute. */
|
|
HWREG(FLASH_BASE + FLASH_O_FSM_EXECUTE) = FLASH_CMD_EXEC;
|
|
|
|
/* Disable write to FSM register. */
|
|
HWREG(FLASH_BASE + FLASH_O_FSM_WR_ENA) = FSM_REG_WRT_DISABLE;
|
|
}
|
|
|
|
/******************************************************************************
|
|
*
|
|
* Enables all sectors for erase and programming on the active bank.
|
|
*
|
|
* This function disables the idle reading power reduction mode, selects the
|
|
* flash bank and enables all sectors for erase and programming on the active
|
|
* bank.
|
|
* Sectors may be protected from programming depending on the value of the
|
|
* FLASH_O_FSM_BSLPx registers.
|
|
* Sectors may be protected from erase depending on the value of the
|
|
* FLASH_O_FSM_BSLEx registers. Additional sector erase protection is set by
|
|
* the FLASH_O_FSM_SECTOR1 register.
|
|
*
|
|
******************************************************************************/
|
|
static void enable_sectors_for_write(void)
|
|
{
|
|
/* Trim flash module for program/erase operation. */
|
|
trim_for_write();
|
|
|
|
/* Configure flash to write mode */
|
|
set_write_mode();
|
|
|
|
/* Select flash bank. */
|
|
HWREG(FLASH_BASE + FLASH_O_FMAC) = 0x00;
|
|
|
|
/* Disable Level 1 Protection. */
|
|
HWREG(FLASH_BASE + FLASH_O_FBPROT) = FLASH_FBPROT_PROTL1DIS;
|
|
|
|
/* Enable all sectors for erase and programming. */
|
|
HWREG(FLASH_BASE + FLASH_O_FBSE) = 0xFFFF;
|
|
|
|
/* Enable Level 1 Protection */
|
|
HWREG(FLASH_BASE + FLASH_O_FBPROT) = 0;
|
|
}
|
|
|
|
/******************************************************************************
|
|
*
|
|
* Trims the Flash Bank and Flash Pump for program/erase functionality
|
|
*
|
|
* This trimming will make it possible to perform erase and program operations
|
|
* of the flash. Trim values are loaded from factory configuration area
|
|
* (referred to as FCGF1). The trimming done by this function is valid until
|
|
* reset of the flash module.
|
|
*
|
|
* Some registers shall be written with a value that is a number of FCLK
|
|
* cycles. The trim values controlling these registers have a value of
|
|
* number of half us. FCLK = SysClk / ((RWAIT+1) x 2).
|
|
*
|
|
******************************************************************************/
|
|
static void trim_for_write(void)
|
|
{
|
|
uint32_t value;
|
|
uint32_t temp_val;
|
|
uint32_t fclk_scale;
|
|
uint32_t rwait;
|
|
|
|
/* Return if flash is already trimmed for program/erase operations. */
|
|
if (HWREG(FLASH_BASE + FLASH_O_FWFLAG) & FW_WRT_TRIMMED)
|
|
return;
|
|
|
|
/* Configure the FSM registers */
|
|
|
|
/* Enable access to the FSM registers. */
|
|
HWREG(FLASH_BASE + FLASH_O_FSM_WR_ENA) = FSM_REG_WRT_ENABLE;
|
|
|
|
/* Determine the scaling value to be used on timing related trim values. */
|
|
/* The value is based on the flash module clock frequency and RWAIT */
|
|
rwait = (HWREG(FLASH_BASE + FLASH_O_FRDCTL) &
|
|
FLASH_FRDCTL_RWAIT_M) >> FLASH_FRDCTL_RWAIT_S;
|
|
fclk_scale = (16 * FLASH_MODULE_CLK_FREQ) / (rwait + 1);
|
|
|
|
/* Configure Program pulse width bits 15:0. */
|
|
/* (FCFG1 offset 0x188 bits 15:0). */
|
|
value = (HWREG(FLASH_CFG_BASE + FCFG1_OFFSET + FCFG1_O_FLASH_PROG_EP) &
|
|
FCFG1_FLASH_PROG_EP_PROGRAM_PW_M) >>
|
|
FCFG1_FLASH_PROG_EP_PROGRAM_PW_S;
|
|
|
|
value = scale_cycle_values(value, fclk_scale);
|
|
|
|
HWREG(FLASH_BASE + FLASH_O_FSM_PRG_PW) =
|
|
(HWREG(FLASH_BASE + FLASH_O_FSM_PRG_PW) &
|
|
~FLASH_FSM_PRG_PW_PROG_PUL_WIDTH_M) |
|
|
((value << FLASH_FSM_PRG_PW_PROG_PUL_WIDTH_S) &
|
|
FLASH_FSM_PRG_PW_PROG_PUL_WIDTH_M);
|
|
|
|
/* Configure Erase pulse width bits 31:0. */
|
|
/* (FCFG1 offset 0x18C bits 31:0). */
|
|
value = (HWREG(FLASH_CFG_BASE + FCFG1_OFFSET + FCFG1_O_FLASH_ERA_PW) &
|
|
FCFG1_FLASH_ERA_PW_ERASE_PW_M) >>
|
|
FCFG1_FLASH_ERA_PW_ERASE_PW_S;
|
|
|
|
value = scale_cycle_values(value, fclk_scale);
|
|
|
|
HWREG(FLASH_BASE + FLASH_O_FSM_ERA_PW) =
|
|
(HWREG(FLASH_BASE + FLASH_O_FSM_ERA_PW) &
|
|
~FLASH_FSM_ERA_PW_FSM_ERA_PW_M) |
|
|
((value << FLASH_FSM_ERA_PW_FSM_ERA_PW_S) &
|
|
FLASH_FSM_ERA_PW_FSM_ERA_PW_M);
|
|
|
|
/* Configure no of flash clock cycles from EXECUTEZ going low to the the
|
|
verify data can be read in the program verify mode bits 7:0. */
|
|
/* (FCFG1 offset 0x174 bits 23:16). */
|
|
value = (HWREG(FLASH_CFG_BASE + FCFG1_OFFSET + FCFG1_O_FLASH_C_E_P_R) &
|
|
FCFG1_FLASH_C_E_P_R_PV_ACCESS_M) >>
|
|
FCFG1_FLASH_C_E_P_R_PV_ACCESS_S;
|
|
|
|
value = scale_cycle_values(value, fclk_scale);
|
|
|
|
HWREG(FLASH_BASE + FLASH_O_FSM_EX_VAL) =
|
|
(HWREG(FLASH_BASE + FLASH_O_FSM_EX_VAL) &
|
|
~FLASH_FSM_EX_VAL_EXE_VALD_M) |
|
|
((value << FLASH_FSM_EX_VAL_EXE_VALD_S) &
|
|
FLASH_FSM_EX_VAL_EXE_VALD_M);
|
|
|
|
/* Configure the number of flash clocks from the start of the Read mode at
|
|
the end of the operations until the FSM clears the BUSY bit in FMSTAT. */
|
|
/* (FCFG1 offset 0x178 bits 23:16). */
|
|
value = (HWREG(FLASH_CFG_BASE + FCFG1_OFFSET + FCFG1_O_FLASH_P_R_PV) &
|
|
FCFG1_FLASH_P_R_PV_RH_M) >>
|
|
FCFG1_FLASH_P_R_PV_RH_S;
|
|
|
|
HWREG(FLASH_BASE + FLASH_O_FSM_RD_H) =
|
|
(HWREG(FLASH_BASE + FLASH_O_FSM_RD_H) &
|
|
~FLASH_FSM_RD_H_RD_H_M) |
|
|
((value << FLASH_FSM_RD_H_RD_H_S) &
|
|
FLASH_FSM_RD_H_RD_H_M);
|
|
|
|
/* Configure Program hold time */
|
|
/* (FCFG1 offset 0x178 bits 31:24). */
|
|
value = (HWREG(FLASH_CFG_BASE + FCFG1_OFFSET + FCFG1_O_FLASH_P_R_PV) &
|
|
FCFG1_FLASH_P_R_PV_PH_M) >>
|
|
FCFG1_FLASH_P_R_PV_PH_S;
|
|
|
|
value = scale_cycle_values(value, fclk_scale);
|
|
|
|
HWREG(FLASH_BASE + FLASH_O_FSM_P_OH) =
|
|
(HWREG(FLASH_BASE + FLASH_O_FSM_P_OH) &
|
|
~FLASH_FSM_P_OH_PGM_OH_M) |
|
|
((value << FLASH_FSM_P_OH_PGM_OH_S) &
|
|
FLASH_FSM_P_OH_PGM_OH_M);
|
|
|
|
/* Configure Erase hold time */
|
|
/* (FCFG1 offset 0x17C bits 31:24). */
|
|
value = (HWREG(FLASH_CFG_BASE + FCFG1_OFFSET + FCFG1_O_FLASH_EH_SEQ) &
|
|
FCFG1_FLASH_EH_SEQ_EH_M) >>
|
|
FCFG1_FLASH_EH_SEQ_EH_S;
|
|
|
|
value = scale_cycle_values(value, fclk_scale);
|
|
|
|
HWREG(FLASH_BASE + FLASH_O_FSM_ERA_OH) =
|
|
(HWREG(FLASH_BASE + FLASH_O_FSM_ERA_OH) &
|
|
~FLASH_FSM_ERA_OH_ERA_OH_M) |
|
|
((value << FLASH_FSM_ERA_OH_ERA_OH_S) &
|
|
FLASH_FSM_ERA_OH_ERA_OH_M);
|
|
|
|
/* Configure Program verify row switch time */
|
|
/* (FCFG1 offset0x178 bits 15:8). */
|
|
value = (HWREG(FLASH_CFG_BASE + FCFG1_OFFSET + FCFG1_O_FLASH_P_R_PV) &
|
|
FCFG1_FLASH_P_R_PV_PVH_M) >>
|
|
FCFG1_FLASH_P_R_PV_PVH_S;
|
|
|
|
value = scale_cycle_values(value, fclk_scale);
|
|
|
|
HWREG(FLASH_BASE + FLASH_O_FSM_PE_VH) =
|
|
(HWREG(FLASH_BASE + FLASH_O_FSM_PE_VH) &
|
|
~FLASH_FSM_PE_VH_PGM_VH_M) |
|
|
((value << FLASH_FSM_PE_VH_PGM_VH_S) &
|
|
FLASH_FSM_PE_VH_PGM_VH_M);
|
|
|
|
/* Configure Program Operation Setup time */
|
|
/* (FCFG1 offset 0x170 bits 31:24). */
|
|
value = (HWREG(FLASH_CFG_BASE + FCFG1_OFFSET + FCFG1_O_FLASH_E_P) &
|
|
FCFG1_FLASH_E_P_PSU_M) >>
|
|
FCFG1_FLASH_E_P_PSU_S;
|
|
|
|
HWREG(FLASH_BASE + FLASH_O_FSM_PE_OSU) =
|
|
(HWREG(FLASH_BASE + FLASH_O_FSM_PE_OSU) &
|
|
~FLASH_FSM_PE_OSU_PGM_OSU_M) |
|
|
((value << FLASH_FSM_PE_OSU_PGM_OSU_S) &
|
|
FLASH_FSM_PE_OSU_PGM_OSU_M);
|
|
|
|
/* Configure Erase Operation Setup time */
|
|
/* (FCGF1 offset 0x170 bits 23:16). */
|
|
value = (HWREG(FLASH_CFG_BASE + FCFG1_OFFSET + FCFG1_O_FLASH_E_P) &
|
|
FCFG1_FLASH_E_P_ESU_M) >>
|
|
FCFG1_FLASH_E_P_ESU_S;
|
|
|
|
HWREG(FLASH_BASE + FLASH_O_FSM_PE_OSU) =
|
|
(HWREG(FLASH_BASE + FLASH_O_FSM_PE_OSU) &
|
|
~FLASH_FSM_PE_OSU_ERA_OSU_M) |
|
|
((value << FLASH_FSM_PE_OSU_ERA_OSU_S) &
|
|
FLASH_FSM_PE_OSU_ERA_OSU_M);
|
|
|
|
/* Confgure Program Verify Setup time */
|
|
/* (FCFG1 offset 0x170 bits 15:8). */
|
|
value = (HWREG(FLASH_CFG_BASE + FCFG1_OFFSET + FCFG1_O_FLASH_E_P) &
|
|
FCFG1_FLASH_E_P_PVSU_M) >>
|
|
FCFG1_FLASH_E_P_PVSU_S;
|
|
|
|
HWREG(FLASH_BASE + FLASH_O_FSM_PE_VSU) =
|
|
(HWREG(FLASH_BASE + FLASH_O_FSM_PE_VSU) &
|
|
~FLASH_FSM_PE_VSU_PGM_VSU_M) |
|
|
((value << FLASH_FSM_PE_VSU_PGM_VSU_S) &
|
|
FLASH_FSM_PE_VSU_PGM_VSU_M);
|
|
|
|
/* Configure Erase Verify Setup time */
|
|
/* (FCFG1 offset 0x170 bits 7:0). */
|
|
value = (HWREG(FLASH_CFG_BASE + FCFG1_OFFSET + FCFG1_O_FLASH_E_P) &
|
|
FCFG1_FLASH_E_P_EVSU_M) >>
|
|
FCFG1_FLASH_E_P_EVSU_S;
|
|
|
|
HWREG(FLASH_BASE + FLASH_O_FSM_PE_VSU) =
|
|
(HWREG(FLASH_BASE + FLASH_O_FSM_PE_VSU) &
|
|
~FLASH_FSM_PE_VSU_ERA_VSU_M) |
|
|
((value << FLASH_FSM_PE_VSU_ERA_VSU_S) &
|
|
FLASH_FSM_PE_VSU_ERA_VSU_M);
|
|
|
|
/* Configure Addr to EXECUTEZ low setup time */
|
|
/* (FCFG1 offset 0x174 bits 15:12). */
|
|
value = (HWREG(FLASH_CFG_BASE + FCFG1_OFFSET + FCFG1_O_FLASH_C_E_P_R) &
|
|
FCFG1_FLASH_C_E_P_R_A_EXEZ_SETUP_M) >>
|
|
FCFG1_FLASH_C_E_P_R_A_EXEZ_SETUP_S;
|
|
|
|
HWREG(FLASH_BASE + FLASH_O_FSM_CMP_VSU) =
|
|
(HWREG(FLASH_BASE + FLASH_O_FSM_CMP_VSU) &
|
|
~FLASH_FSM_CMP_VSU_ADD_EXZ_M) |
|
|
((value << FLASH_FSM_CMP_VSU_ADD_EXZ_S) &
|
|
FLASH_FSM_CMP_VSU_ADD_EXZ_M);
|
|
|
|
/* Configure Voltage Status Count */
|
|
/* (FCFG1 offset 0x17C bits 15:12). */
|
|
value = (HWREG(FLASH_CFG_BASE + FCFG1_OFFSET + FCFG1_O_FLASH_EH_SEQ) &
|
|
FCFG1_FLASH_EH_SEQ_VSTAT_M) >>
|
|
FCFG1_FLASH_EH_SEQ_VSTAT_S;
|
|
|
|
HWREG(FLASH_BASE + FLASH_O_FSM_VSTAT) =
|
|
(HWREG(FLASH_BASE + FLASH_O_FSM_VSTAT) &
|
|
~FLASH_FSM_VSTAT_VSTAT_CNT_M) |
|
|
((value << FLASH_FSM_VSTAT_VSTAT_CNT_S) &
|
|
FLASH_FSM_VSTAT_VSTAT_CNT_M);
|
|
|
|
/* Configure Repeat Verify action setup */
|
|
/* (FCFG1 offset 0x174 bits 31:24). */
|
|
value = (HWREG(FLASH_CFG_BASE + FCFG1_OFFSET + FCFG1_O_FLASH_C_E_P_R) &
|
|
FCFG1_FLASH_C_E_P_R_RVSU_M) >>
|
|
FCFG1_FLASH_C_E_P_R_RVSU_S;
|
|
|
|
HWREG(FLASH_BASE + FLASH_O_FSM_EX_VAL) =
|
|
(HWREG(FLASH_BASE + FLASH_O_FSM_EX_VAL) &
|
|
~FLASH_FSM_EX_VAL_REP_VSU_M) |
|
|
((value << FLASH_FSM_EX_VAL_REP_VSU_S) &
|
|
FLASH_FSM_EX_VAL_REP_VSU_M);
|
|
|
|
/* Configure Maximum Programming Pulses */
|
|
/* (FCFG1 offset 0x184 bits 15:0). */
|
|
value = (HWREG(FLASH_CFG_BASE + FCFG1_OFFSET + FCFG1_O_FLASH_PP) &
|
|
FCFG1_FLASH_PP_MAX_PP_M) >>
|
|
FCFG1_FLASH_PP_MAX_PP_S;
|
|
|
|
HWREG(FLASH_BASE + FLASH_O_FSM_PRG_PUL) =
|
|
(HWREG(FLASH_BASE + FLASH_O_FSM_PRG_PUL) &
|
|
~FLASH_FSM_PRG_PUL_MAX_PRG_PUL_M) |
|
|
((value << FLASH_FSM_PRG_PUL_MAX_PRG_PUL_S) &
|
|
FLASH_FSM_PRG_PUL_MAX_PRG_PUL_M);
|
|
|
|
/* Configure Beginning level for VHVCT used during erase modes */
|
|
/* (FCFG1 offset 0x180 bits 31:16). */
|
|
value = (HWREG(FLASH_CFG_BASE + FCFG1_OFFSET + FCFG1_O_FLASH_VHV_E) &
|
|
FCFG1_FLASH_VHV_E_VHV_E_START_M) >>
|
|
FCFG1_FLASH_VHV_E_VHV_E_START_S;
|
|
|
|
HWREG(FLASH_BASE + FLASH_O_FSM_PRG_PUL) =
|
|
(HWREG(FLASH_BASE + FLASH_O_FSM_PRG_PUL) &
|
|
~FLASH_FSM_PRG_PUL_BEG_EC_LEVEL_M) |
|
|
((value << FLASH_FSM_PRG_PUL_BEG_EC_LEVEL_S) &
|
|
FLASH_FSM_PRG_PUL_BEG_EC_LEVEL_M);
|
|
|
|
/* Configure Maximum EC Level */
|
|
/* (FCFG1 offset 0x2B0 bits 21:18). */
|
|
value = (HWREG(FLASH_CFG_BASE + FCFG1_OFFSET + FCFG1_O_FLASH_OTP_DATA3) &
|
|
FCFG1_FLASH_OTP_DATA3_MAX_EC_LEVEL_M) >>
|
|
FCFG1_FLASH_OTP_DATA3_MAX_EC_LEVEL_S;
|
|
|
|
HWREG(FLASH_BASE + FLASH_O_FSM_ERA_PUL) =
|
|
(HWREG(FLASH_BASE + FLASH_O_FSM_ERA_PUL) &
|
|
~FLASH_FSM_ERA_PUL_MAX_EC_LEVEL_M) |
|
|
((value << FLASH_FSM_ERA_PUL_MAX_EC_LEVEL_S) &
|
|
FLASH_FSM_ERA_PUL_MAX_EC_LEVEL_M);
|
|
|
|
/* Configure Maximum Erase Pulses */
|
|
/* (FCFG1 offset 0x188 bits 31:16). */
|
|
value = (HWREG(FLASH_CFG_BASE + FCFG1_OFFSET + FCFG1_O_FLASH_PROG_EP) &
|
|
FCFG1_FLASH_PROG_EP_MAX_EP_M) >>
|
|
FCFG1_FLASH_PROG_EP_MAX_EP_S;
|
|
|
|
HWREG(FLASH_BASE + FLASH_O_FSM_ERA_PUL) =
|
|
(HWREG(FLASH_BASE + FLASH_O_FSM_ERA_PUL) &
|
|
~FLASH_FSM_ERA_PUL_MAX_ERA_PUL_M) |
|
|
((value << FLASH_FSM_ERA_PUL_MAX_ERA_PUL_S) &
|
|
FLASH_FSM_ERA_PUL_MAX_ERA_PUL_M);
|
|
|
|
/* Configure the VHVCT Step Size. This is the number of erase pulses that
|
|
must be completed for each level before the FSM increments the
|
|
CUR_EC_LEVEL to the next higher level. Actual erase pulses per level
|
|
equals (EC_STEP_SIZE +1). The stepping is only needed for the VHVCT
|
|
voltage. */
|
|
/* (FCFG1 offset 0x2B0 bits 31:23). */
|
|
value = (HWREG(FLASH_CFG_BASE + FCFG1_OFFSET + FCFG1_O_FLASH_OTP_DATA3) &
|
|
FCFG1_FLASH_OTP_DATA3_EC_STEP_SIZE_M) >>
|
|
FCFG1_FLASH_OTP_DATA3_EC_STEP_SIZE_S;
|
|
|
|
HWREG(FLASH_BASE + FLASH_O_FSM_STEP_SIZE) =
|
|
(HWREG(FLASH_BASE + FLASH_O_FSM_STEP_SIZE) &
|
|
~FLASH_FSM_STEP_SIZE_EC_STEP_SIZE_M) |
|
|
((value << FLASH_FSM_STEP_SIZE_EC_STEP_SIZE_S) &
|
|
FLASH_FSM_STEP_SIZE_EC_STEP_SIZE_M);
|
|
|
|
/* Configure the hight of each EC step. This is the number of counts that
|
|
the CUR_EC_LEVEL will increment when going to a new level. Actual count
|
|
size equals (EC_STEP_HEIGHT + 1). The stepping applies only to the VHVCT
|
|
voltage.
|
|
The read trim value is decremented by 1 before written to the register
|
|
since actual counts equals (register value + 1). */
|
|
/* (FCFG1 offset 0x180 bits 15:0). */
|
|
value = (HWREG(FLASH_CFG_BASE + FCFG1_OFFSET + FCFG1_O_FLASH_VHV_E) &
|
|
FCFG1_FLASH_VHV_E_VHV_E_STEP_HIGHT_M) >>
|
|
FCFG1_FLASH_VHV_E_VHV_E_STEP_HIGHT_S;
|
|
|
|
HWREG(FLASH_BASE + FLASH_O_FSM_EC_STEP_HEIGHT) = ((value - 1) &
|
|
FLASH_FSM_EC_STEP_HEIGHT_EC_STEP_HEIGHT_M);
|
|
|
|
/* Configure Precondition used in erase operations */
|
|
/* (FCFG1 offset 0x2B0 bit 22). */
|
|
value = (HWREG(FLASH_CFG_BASE + FCFG1_OFFSET + FCFG1_O_FLASH_OTP_DATA3) &
|
|
FCFG1_FLASH_OTP_DATA3_DO_PRECOND_M) >>
|
|
FCFG1_FLASH_OTP_DATA3_DO_PRECOND_S;
|
|
|
|
HWREG(FLASH_BASE + FLASH_O_FSM_ST_MACHINE) =
|
|
(HWREG(FLASH_BASE + FLASH_O_FSM_ST_MACHINE) &
|
|
~FLASH_FSM_ST_MACHINE_DO_PRECOND_M) |
|
|
((value << FLASH_FSM_ST_MACHINE_DO_PRECOND_S) &
|
|
FLASH_FSM_ST_MACHINE_DO_PRECOND_M);
|
|
|
|
/* Enable the recommended Good Time function. */
|
|
HWREG(FLASH_BASE + FLASH_O_FSM_ST_MACHINE) |=
|
|
FLASH_FSM_ST_MACHINE_ONE_TIME_GOOD;
|
|
|
|
/* Disable write access to FSM registers. */
|
|
HWREG(FLASH_BASE + FLASH_O_FSM_WR_ENA) = FSM_REG_WRT_DISABLE;
|
|
|
|
/* Configure the voltage registers */
|
|
|
|
/* Unlock voltage registers (0x2080 - 0x2098). */
|
|
HWREG(FLASH_BASE + FLASH_O_FLOCK) = 0xAAAA;
|
|
|
|
/* Configure voltage level for the specified pump voltage of high
|
|
voltage supply input during erase operation VHVCT_E and TRIM13_E */
|
|
/* (FCFG1 offset 0x190 bits[3:0] and bits[11:8]). */
|
|
temp_val = HWREG(FLASH_CFG_BASE + FCFG1_OFFSET + FCFG1_O_FLASH_VHV);
|
|
|
|
value = ((temp_val & FCFG1_FLASH_VHV_TRIM13_E_M)>>
|
|
FCFG1_FLASH_VHV_TRIM13_E_S) << FLASH_FVHVCT1_TRIM13_E_S;
|
|
value |= ((temp_val & FCFG1_FLASH_VHV_VHV_E_M)>>
|
|
FCFG1_FLASH_VHV_VHV_E_S) << FLASH_FVHVCT1_VHVCT_E_S;
|
|
|
|
HWREG(FLASH_BASE + FLASH_O_FVHVCT1) = (HWREG(FLASH_BASE + FLASH_O_FVHVCT1) &
|
|
~(FLASH_FVHVCT1_TRIM13_E_M | FLASH_FVHVCT1_VHVCT_E_M)) | value;
|
|
|
|
/* Configure voltage level for the specified pump voltage of high voltage
|
|
supply input during program verify operation VHVCT_PV and TRIM13_PV */
|
|
/* (OTP offset 0x194 bits[19:16] and bits[27:24]). */
|
|
temp_val = HWREG(FLASH_CFG_BASE + FCFG1_OFFSET + FCFG1_O_FLASH_VHV_PV);
|
|
|
|
value = ((temp_val & FCFG1_FLASH_VHV_PV_TRIM13_PV_M) >>
|
|
FCFG1_FLASH_VHV_PV_TRIM13_PV_S) << FLASH_FVHVCT1_TRIM13_PV_S;
|
|
value |= ((temp_val & FCFG1_FLASH_VHV_PV_VHV_PV_M) >>
|
|
FCFG1_FLASH_VHV_PV_VHV_PV_S) << FLASH_FVHVCT1_VHVCT_PV_S;
|
|
|
|
HWREG(FLASH_BASE + FLASH_O_FVHVCT1) = (HWREG(FLASH_BASE + FLASH_O_FVHVCT1) &
|
|
~(FLASH_FVHVCT1_TRIM13_PV_M | FLASH_FVHVCT1_VHVCT_PV_M)) | value;
|
|
|
|
/* Configure voltage level for the specified pump voltage of high voltage
|
|
supply input during program operation VHVCT_P and TRIM13_P */
|
|
/* (FCFG1 offset 0x190 bits[19:16] and bits[27:24]). */
|
|
temp_val = HWREG(FLASH_CFG_BASE + FCFG1_OFFSET + FCFG1_O_FLASH_VHV);
|
|
|
|
value = ((temp_val & FCFG1_FLASH_VHV_TRIM13_P_M) >>
|
|
FCFG1_FLASH_VHV_TRIM13_P_S) << FLASH_FVHVCT2_TRIM13_P_S;
|
|
value |= ((temp_val & FCFG1_FLASH_VHV_VHV_P_M) >>
|
|
FCFG1_FLASH_VHV_VHV_P_S) << FLASH_FVHVCT2_VHVCT_P_S;
|
|
|
|
HWREG(FLASH_BASE + FLASH_O_FVHVCT2) = (HWREG(FLASH_BASE + FLASH_O_FVHVCT2) &
|
|
~(FLASH_FVHVCT2_TRIM13_P_M | FLASH_FVHVCT2_VHVCT_P_M)) | value;
|
|
|
|
/* Configure voltage level for the specified pump voltage of wordline power
|
|
supply for read mode */
|
|
/* (FCFG1 offset 0x198 Bits 15:8). */
|
|
value = (HWREG(FLASH_CFG_BASE + FCFG1_OFFSET + FCFG1_O_FLASH_V) &
|
|
FCFG1_FLASH_V_V_READ_M) >> FCFG1_FLASH_V_V_READ_S;
|
|
|
|
HWREG(FLASH_BASE + FLASH_O_FVREADCT) =
|
|
(HWREG(FLASH_BASE + FLASH_O_FVREADCT) &
|
|
~FLASH_FVREADCT_VREADCT_M) |
|
|
((value << FLASH_FVREADCT_VREADCT_S) &
|
|
FLASH_FVREADCT_VREADCT_M);
|
|
|
|
/* Configure the voltage level for the VCG 2.5 CT pump voltage */
|
|
/* (FCFG1 offset 0x194 bits 15:8). */
|
|
value = (HWREG(FLASH_CFG_BASE + FCFG1_OFFSET + FCFG1_O_FLASH_VHV_PV) &
|
|
FCFG1_FLASH_VHV_PV_VCG2P5_M) >>
|
|
FCFG1_FLASH_VHV_PV_VCG2P5_S;
|
|
|
|
HWREG(FLASH_BASE + FLASH_O_FVNVCT) =
|
|
(HWREG(FLASH_BASE + FLASH_O_FVNVCT) &
|
|
~FLASH_FVNVCT_VCG2P5CT_M) |
|
|
((value << FLASH_FVNVCT_VCG2P5CT_S) &
|
|
FLASH_FVNVCT_VCG2P5CT_M);
|
|
|
|
/* Configure the voltage level for the specified pump voltage of high
|
|
current power input during program operation */
|
|
/* (FCFG1 offset 0x198 bits 31:24). */
|
|
value = (HWREG(FLASH_CFG_BASE + FCFG1_OFFSET + FCFG1_O_FLASH_V) &
|
|
FCFG1_FLASH_V_VSL_P_M) >>
|
|
FCFG1_FLASH_V_VSL_P_S;
|
|
|
|
HWREG(FLASH_BASE + FLASH_O_FVSLP) =
|
|
(HWREG(FLASH_BASE + FLASH_O_FVSLP) &
|
|
~FLASH_FVSLP_VSL_P_M) |
|
|
((value << FLASH_FVSLP_VSL_P_S) &
|
|
FLASH_FVSLP_VSL_P_M);
|
|
|
|
/* Configure the voltage level for the specified pump voltage of wordline
|
|
power supply during programming operations */
|
|
/* (OTP offset 0x198 bits 23:16). */
|
|
value = (HWREG(FLASH_CFG_BASE + FCFG1_OFFSET + FCFG1_O_FLASH_V) &
|
|
FCFG1_FLASH_V_VWL_P_M) >>
|
|
FCFG1_FLASH_V_VWL_P_S;
|
|
|
|
HWREG(FLASH_BASE + FLASH_O_FVWLCT) =
|
|
(HWREG(FLASH_BASE + FLASH_O_FVWLCT) &
|
|
~FLASH_FVWLCT_VWLCT_P_M) |
|
|
((value << FLASH_FVWLCT_VWLCT_P_S) &
|
|
FLASH_FVWLCT_VWLCT_P_M);
|
|
|
|
/* Configure the pump's TRIM_1P7 port pins. */
|
|
/* (FCFG1 offset 0x2B0 bits 17:16). */
|
|
value = (HWREG(FLASH_CFG_BASE + FCFG1_OFFSET + FCFG1_O_FLASH_OTP_DATA3) &
|
|
FCFG1_FLASH_OTP_DATA3_TRIM_1P7_M) >>
|
|
FCFG1_FLASH_OTP_DATA3_TRIM_1P7_S;
|
|
|
|
HWREG(FLASH_BASE + FLASH_O_FSEQPMP) =
|
|
(HWREG(FLASH_BASE + FLASH_O_FSEQPMP) &
|
|
~FLASH_FSEQPMP_TRIM_1P7_M) |
|
|
((value << FLASH_FSEQPMP_TRIM_1P7_S) &
|
|
FLASH_FSEQPMP_TRIM_1P7_M);
|
|
|
|
/* Lock the voltage registers. */
|
|
HWREG(FLASH_BASE + FLASH_O_FLOCK) = 0x55AA;
|
|
|
|
/* Set trimmed flag. */
|
|
HWREG(FLASH_BASE + FLASH_O_FWLOCK) = 5;
|
|
HWREG(FLASH_BASE + FLASH_O_FWFLAG) |= FW_WRT_TRIMMED;
|
|
HWREG(FLASH_BASE + FLASH_O_FWLOCK) = 0;
|
|
}
|
|
|
|
/******************************************************************************
|
|
*
|
|
* Used to scale the TI OTP values based on the FClk scaling value.
|
|
*
|
|
******************************************************************************/
|
|
static uint32_t scale_cycle_values(uint32_t specified_timing,
|
|
uint32_t scale_value)
|
|
{
|
|
uint32_t scaled_value = (specified_timing * scale_value) >> 6;
|
|
return scaled_value;
|
|
}
|
|
|
|
/******************************************************************************
|
|
*
|
|
* Used to set flash in read mode.
|
|
*
|
|
* Flash is configured with values loaded from OTP dependent on the current
|
|
* regulator mode.
|
|
*
|
|
******************************************************************************/
|
|
static void set_read_mode(void)
|
|
{
|
|
uint32_t trim_value;
|
|
uint32_t value;
|
|
|
|
/* Configure the STANDBY_MODE_SEL, STANDBY_PW_SEL, DIS_STANDBY, DIS_IDLE,
|
|
VIN_AT_X and VIN_BY_PASS for read mode */
|
|
if (HWREG(AON_PMCTL_BASE + AON_PMCTL_O_PWRCTL) &
|
|
AON_PMCTL_PWRCTL_EXT_REG_MODE) {
|
|
|
|
/* Select trim values for external regulator mode:
|
|
Configure STANDBY_MODE_SEL (OTP offset 0x308 bit 7)
|
|
Configure STANDBY_PW_SEL (OTP offset 0x308 bit 6:5)
|
|
Must be done while the register bit field CONFIG.DIS_STANDBY = 1 */
|
|
HWREG(FLASH_BASE + FLASH_O_CFG) |= FLASH_CFG_DIS_STANDBY;
|
|
|
|
trim_value =
|
|
HWREG(FLASH_CFG_BASE + FCFG1_OFFSET + FCFG1_O_FLASH_OTP_DATA4);
|
|
|
|
value = ((trim_value &
|
|
FCFG1_FLASH_OTP_DATA4_STANDBY_MODE_SEL_EXT_RD_M) >>
|
|
FCFG1_FLASH_OTP_DATA4_STANDBY_MODE_SEL_EXT_RD_S) <<
|
|
FLASH_CFG_STANDBY_MODE_SEL_S;
|
|
|
|
value |= ((trim_value &
|
|
FCFG1_FLASH_OTP_DATA4_STANDBY_PW_SEL_EXT_RD_M) >>
|
|
FCFG1_FLASH_OTP_DATA4_STANDBY_PW_SEL_EXT_RD_S) <<
|
|
FLASH_CFG_STANDBY_PW_SEL_S;
|
|
|
|
/* Configure DIS_STANDBY (OTP offset 0x308 bit 4).
|
|
Configure DIS_IDLE (OTP offset 0x308 bit 3). */
|
|
value |= ((trim_value &
|
|
(FCFG1_FLASH_OTP_DATA4_DIS_STANDBY_EXT_RD_M |
|
|
FCFG1_FLASH_OTP_DATA4_DIS_IDLE_EXT_RD_M)) >>
|
|
FCFG1_FLASH_OTP_DATA4_DIS_IDLE_EXT_RD_S) <<
|
|
FLASH_CFG_DIS_IDLE_S;
|
|
|
|
HWREG(FLASH_BASE + FLASH_O_CFG) = (HWREG(FLASH_BASE + FLASH_O_CFG) &
|
|
~(FLASH_CFG_STANDBY_MODE_SEL_M | FLASH_CFG_STANDBY_PW_SEL_M |
|
|
FLASH_CFG_DIS_STANDBY_M | FLASH_CFG_DIS_IDLE_M)) | value;
|
|
|
|
/* Check if sample and hold functionality is disabled. */
|
|
if (HWREG(FLASH_BASE + FLASH_O_CFG) & FLASH_CFG_DIS_IDLE) {
|
|
/* Wait for disabled sample and hold functionality to be stable. */
|
|
while (!(HWREG(FLASH_BASE+FLASH_O_STAT) & FLASH_STAT_SAMHOLD_DIS))
|
|
;
|
|
}
|
|
|
|
/* Configure VIN_AT_X (OTP offset 0x308 bits 2:0) */
|
|
value = ((trim_value &
|
|
FCFG1_FLASH_OTP_DATA4_VIN_AT_X_EXT_RD_M) >>
|
|
FCFG1_FLASH_OTP_DATA4_VIN_AT_X_EXT_RD_S) <<
|
|
FLASH_FSEQPMP_VIN_AT_X_S;
|
|
|
|
/* Configure VIN_BY_PASS which is dependent on the VIN_AT_X value.
|
|
If VIN_AT_X = 7 then VIN_BY_PASS should be 0 otherwise
|
|
VIN_BY_PASS should be 1 */
|
|
if (((value & FLASH_FSEQPMP_VIN_AT_X_M) >>
|
|
FLASH_FSEQPMP_VIN_AT_X_S) != 0x7)
|
|
value |= FLASH_FSEQPMP_VIN_BY_PASS;
|
|
|
|
HWREG(FLASH_BASE + FLASH_O_FLOCK) = 0xAAAA;
|
|
HWREG(FLASH_BASE + FLASH_O_FSEQPMP) =
|
|
(HWREG(FLASH_BASE + FLASH_O_FSEQPMP) &
|
|
~(FLASH_FSEQPMP_VIN_BY_PASS_M |
|
|
FLASH_FSEQPMP_VIN_AT_X_M)) | value;
|
|
HWREG(FLASH_BASE + FLASH_O_FLOCK) = 0x55AA;
|
|
} else {
|
|
|
|
/* Select trim values for internal regulator mode:
|
|
Configure STANDBY_MODE_SEL (OTP offset 0x308 bit 15)
|
|
COnfigure STANDBY_PW_SEL (OTP offset 0x308 bit 14:13)
|
|
Must be done while the register bit field CONFIG.DIS_STANDBY = 1 */
|
|
HWREG(FLASH_BASE + FLASH_O_CFG) |= FLASH_CFG_DIS_STANDBY;
|
|
|
|
trim_value =
|
|
HWREG(FLASH_CFG_BASE + FCFG1_OFFSET + FCFG1_O_FLASH_OTP_DATA4);
|
|
|
|
value = ((trim_value &
|
|
FCFG1_FLASH_OTP_DATA4_STANDBY_MODE_SEL_INT_RD_M) >>
|
|
FCFG1_FLASH_OTP_DATA4_STANDBY_MODE_SEL_INT_RD_S) <<
|
|
FLASH_CFG_STANDBY_MODE_SEL_S;
|
|
|
|
value |= ((trim_value &
|
|
FCFG1_FLASH_OTP_DATA4_STANDBY_PW_SEL_INT_RD_M) >>
|
|
FCFG1_FLASH_OTP_DATA4_STANDBY_PW_SEL_INT_RD_S) <<
|
|
FLASH_CFG_STANDBY_PW_SEL_S;
|
|
|
|
/* Configure DIS_STANDBY (OTP offset 0x308 bit 12).
|
|
Configure DIS_IDLE (OTP offset 0x308 bit 11). */
|
|
value |= ((trim_value &
|
|
(FCFG1_FLASH_OTP_DATA4_DIS_STANDBY_INT_RD_M |
|
|
FCFG1_FLASH_OTP_DATA4_DIS_IDLE_INT_RD_M)) >>
|
|
FCFG1_FLASH_OTP_DATA4_DIS_IDLE_INT_RD_S) <<
|
|
FLASH_CFG_DIS_IDLE_S;
|
|
|
|
HWREG(FLASH_BASE + FLASH_O_CFG) = (HWREG(FLASH_BASE + FLASH_O_CFG) &
|
|
~(FLASH_CFG_STANDBY_MODE_SEL_M | FLASH_CFG_STANDBY_PW_SEL_M |
|
|
FLASH_CFG_DIS_STANDBY_M | FLASH_CFG_DIS_IDLE_M)) | value;
|
|
|
|
/* Check if sample and hold functionality is disabled. */
|
|
if (HWREG(FLASH_BASE + FLASH_O_CFG) & FLASH_CFG_DIS_IDLE) {
|
|
/* Wait for disabled sample and hold functionality to be stable. */
|
|
while (!(HWREG(FLASH_BASE + FLASH_O_STAT) & FLASH_STAT_SAMHOLD_DIS))
|
|
;
|
|
}
|
|
|
|
/* Configure VIN_AT_X (OTP offset 0x308 bits 10:8) */
|
|
value = (((trim_value &
|
|
FCFG1_FLASH_OTP_DATA4_VIN_AT_X_INT_RD_M) >>
|
|
FCFG1_FLASH_OTP_DATA4_VIN_AT_X_INT_RD_S) <<
|
|
FLASH_FSEQPMP_VIN_AT_X_S);
|
|
|
|
/* Configure VIN_BY_PASS which is dependent on the VIN_AT_X value.
|
|
If VIN_AT_X = 7 then VIN_BY_PASS should be 0 otherwise
|
|
VIN_BY_PASS should be 1 */
|
|
if (((value & FLASH_FSEQPMP_VIN_AT_X_M) >>
|
|
FLASH_FSEQPMP_VIN_AT_X_S) != 0x7)
|
|
value |= FLASH_FSEQPMP_VIN_BY_PASS;
|
|
|
|
HWREG(FLASH_BASE + FLASH_O_FLOCK) = 0xAAAA;
|
|
HWREG(FLASH_BASE + FLASH_O_FSEQPMP) =
|
|
(HWREG(FLASH_BASE + FLASH_O_FSEQPMP) &
|
|
~(FLASH_FSEQPMP_VIN_BY_PASS_M |
|
|
FLASH_FSEQPMP_VIN_AT_X_M)) | value;
|
|
HWREG(FLASH_BASE + FLASH_O_FLOCK) = 0x55AA;
|
|
}
|
|
}
|
|
|
|
/******************************************************************************
|
|
*
|
|
* Used to set flash in write mode.
|
|
*
|
|
* Flash is configured with values loaded from OTP dependent on the current
|
|
* regulator mode.
|
|
*
|
|
******************************************************************************/
|
|
static void set_write_mode(void)
|
|
{
|
|
uint32_t trim_value;
|
|
uint32_t value;
|
|
|
|
/* Configure the STANDBY_MODE_SEL, STANDBY_PW_SEL, DIS_STANDBY, DIS_IDLE,
|
|
VIN_AT_X and VIN_BY_PASS for program/erase mode */
|
|
if (HWREG(AON_PMCTL_BASE + AON_PMCTL_O_PWRCTL) &
|
|
AON_PMCTL_PWRCTL_EXT_REG_MODE) {
|
|
|
|
/* Select trim values for external regulator mode:
|
|
Configure STANDBY_MODE_SEL (OTP offset 0x308 bit 23)
|
|
Configure STANDBY_PW_SEL (OTP offset 0x308 bit 22:21)
|
|
Must be done while the register bit field CONFIG.DIS_STANDBY = 1 */
|
|
HWREG(FLASH_BASE + FLASH_O_CFG) |= FLASH_CFG_DIS_STANDBY;
|
|
|
|
trim_value =
|
|
HWREG(FLASH_CFG_BASE + FCFG1_OFFSET + FCFG1_O_FLASH_OTP_DATA4);
|
|
|
|
value = ((trim_value &
|
|
FCFG1_FLASH_OTP_DATA4_STANDBY_MODE_SEL_EXT_WRT_M) >>
|
|
FCFG1_FLASH_OTP_DATA4_STANDBY_MODE_SEL_EXT_WRT_S) <<
|
|
FLASH_CFG_STANDBY_MODE_SEL_S;
|
|
|
|
value |= ((trim_value &
|
|
FCFG1_FLASH_OTP_DATA4_STANDBY_PW_SEL_EXT_WRT_M) >>
|
|
FCFG1_FLASH_OTP_DATA4_STANDBY_PW_SEL_EXT_WRT_S) <<
|
|
FLASH_CFG_STANDBY_PW_SEL_S;
|
|
|
|
/* Configure DIS_STANDBY (OTP offset 0x308 bit 20).
|
|
Configure DIS_IDLE (OTP offset 0x308 bit 19). */
|
|
value |= ((trim_value &
|
|
(FCFG1_FLASH_OTP_DATA4_DIS_STANDBY_EXT_WRT_M |
|
|
FCFG1_FLASH_OTP_DATA4_DIS_IDLE_EXT_WRT_M)) >>
|
|
FCFG1_FLASH_OTP_DATA4_DIS_IDLE_EXT_WRT_S) <<
|
|
FLASH_CFG_DIS_IDLE_S;
|
|
|
|
HWREG(FLASH_BASE + FLASH_O_CFG) = (HWREG(FLASH_BASE + FLASH_O_CFG) &
|
|
~(FLASH_CFG_STANDBY_MODE_SEL_M | FLASH_CFG_STANDBY_PW_SEL_M |
|
|
FLASH_CFG_DIS_STANDBY_M | FLASH_CFG_DIS_IDLE_M)) | value;
|
|
|
|
/* Check if sample and hold functionality is disabled. */
|
|
if (HWREG(FLASH_BASE + FLASH_O_CFG) & FLASH_CFG_DIS_IDLE) {
|
|
/* Wait for disabled sample and hold functionality to be stable. */
|
|
while (!(HWREG(FLASH_BASE + FLASH_O_STAT) & FLASH_STAT_SAMHOLD_DIS))
|
|
;
|
|
}
|
|
|
|
/* Configure VIN_AT_X (OTP offset 0x308 bits 18:16) */
|
|
value = ((trim_value &
|
|
FCFG1_FLASH_OTP_DATA4_VIN_AT_X_EXT_WRT_M) >>
|
|
FCFG1_FLASH_OTP_DATA4_VIN_AT_X_EXT_WRT_S) <<
|
|
FLASH_FSEQPMP_VIN_AT_X_S;
|
|
|
|
/* Configure VIN_BY_PASS which is dependent on the VIN_AT_X value.
|
|
If VIN_AT_X = 7 then VIN_BY_PASS should be 0 otherwise
|
|
VIN_BY_PASS should be 1 */
|
|
if (((value & FLASH_FSEQPMP_VIN_AT_X_M) >>
|
|
FLASH_FSEQPMP_VIN_AT_X_S) != 0x7)
|
|
value |= FLASH_FSEQPMP_VIN_BY_PASS;
|
|
|
|
HWREG(FLASH_BASE + FLASH_O_FLOCK) = 0xAAAA;
|
|
HWREG(FLASH_BASE + FLASH_O_FSEQPMP) =
|
|
(HWREG(FLASH_BASE + FLASH_O_FSEQPMP) &
|
|
~(FLASH_FSEQPMP_VIN_BY_PASS_M |
|
|
FLASH_FSEQPMP_VIN_AT_X_M)) | value;
|
|
HWREG(FLASH_BASE + FLASH_O_FLOCK) = 0x55AA;
|
|
} else {
|
|
/* Select trim values for internal regulator mode:
|
|
Configure STANDBY_MODE_SEL (OTP offset 0x308 bit 31)
|
|
COnfigure STANDBY_PW_SEL (OTP offset 0x308 bit 30:29)
|
|
Must be done while the register bit field CONFIG.DIS_STANDBY = 1 */
|
|
HWREG(FLASH_BASE + FLASH_O_CFG) |= FLASH_CFG_DIS_STANDBY;
|
|
|
|
trim_value =
|
|
HWREG(FLASH_CFG_BASE + FCFG1_OFFSET + FCFG1_O_FLASH_OTP_DATA4);
|
|
|
|
value = ((trim_value &
|
|
FCFG1_FLASH_OTP_DATA4_STANDBY_MODE_SEL_INT_WRT_M) >>
|
|
FCFG1_FLASH_OTP_DATA4_STANDBY_MODE_SEL_INT_WRT_S) <<
|
|
FLASH_CFG_STANDBY_MODE_SEL_S;
|
|
|
|
value |= ((trim_value &
|
|
FCFG1_FLASH_OTP_DATA4_STANDBY_PW_SEL_INT_WRT_M) >>
|
|
FCFG1_FLASH_OTP_DATA4_STANDBY_PW_SEL_INT_WRT_S) <<
|
|
FLASH_CFG_STANDBY_PW_SEL_S;
|
|
|
|
/* Configure DIS_STANDBY (OTP offset 0x308 bit 28).
|
|
Configure DIS_IDLE (OTP offset 0x308 bit 27). */
|
|
value |= ((trim_value &
|
|
(FCFG1_FLASH_OTP_DATA4_DIS_STANDBY_INT_WRT_M |
|
|
FCFG1_FLASH_OTP_DATA4_DIS_IDLE_INT_WRT_M)) >>
|
|
FCFG1_FLASH_OTP_DATA4_DIS_IDLE_INT_WRT_S) <<
|
|
FLASH_CFG_DIS_IDLE_S;
|
|
|
|
HWREG(FLASH_BASE + FLASH_O_CFG) = (HWREG(FLASH_BASE + FLASH_O_CFG) &
|
|
~(FLASH_CFG_STANDBY_MODE_SEL_M | FLASH_CFG_STANDBY_PW_SEL_M |
|
|
FLASH_CFG_DIS_STANDBY_M | FLASH_CFG_DIS_IDLE_M)) | value;
|
|
|
|
/* Check if sample and hold functionality is disabled. */
|
|
if (HWREG(FLASH_BASE + FLASH_O_CFG) & FLASH_CFG_DIS_IDLE) {
|
|
/* Wait for disabled sample and hold functionality to be stable. */
|
|
while (!(HWREG(FLASH_BASE + FLASH_O_STAT) & FLASH_STAT_SAMHOLD_DIS))
|
|
;
|
|
}
|
|
|
|
/* Configure VIN_AT_X (OTP offset 0x308 bits 26:24) */
|
|
value = ((trim_value &
|
|
FCFG1_FLASH_OTP_DATA4_VIN_AT_X_INT_WRT_M) >>
|
|
FCFG1_FLASH_OTP_DATA4_VIN_AT_X_INT_WRT_S) <<
|
|
FLASH_FSEQPMP_VIN_AT_X_S;
|
|
|
|
/* Configure VIN_BY_PASS which is dependent on the VIN_AT_X value.
|
|
If VIN_AT_X = 7 then VIN_BY_PASS should be 0 otherwise
|
|
VIN_BY_PASS should be 1 */
|
|
if (((value & FLASH_FSEQPMP_VIN_AT_X_M) >>
|
|
FLASH_FSEQPMP_VIN_AT_X_S) != 0x7)
|
|
value |= FLASH_FSEQPMP_VIN_BY_PASS;
|
|
|
|
HWREG(FLASH_BASE + FLASH_O_FLOCK) = 0xAAAA;
|
|
HWREG(FLASH_BASE + FLASH_O_FSEQPMP) =
|
|
(HWREG(FLASH_BASE + FLASH_O_FSEQPMP) &
|
|
~(FLASH_FSEQPMP_VIN_BY_PASS_M |
|
|
FLASH_FSEQPMP_VIN_AT_X_M)) | value;
|
|
HWREG(FLASH_BASE + FLASH_O_FLOCK) = 0x55AA;
|
|
}
|
|
}
|