nxp: nv storage api on platforms

NV storage API(s) for NXP platforms, supported on:
- flexspi-nor
- SecMon - General Purpose Registers at Low-Power section,
           retains their content if backed by coined battery.

Signed-off-by: Pankaj Gupta <pankaj.gupta@nxp.com>
Change-Id: Id65dee4f28e7d6d2024407030039de33ebe0fa05
diff --git a/plat/nxp/common/nv_storage/nv_storage.mk b/plat/nxp/common/nv_storage/nv_storage.mk
new file mode 100644
index 0000000..dddba5f
--- /dev/null
+++ b/plat/nxp/common/nv_storage/nv_storage.mk
@@ -0,0 +1,29 @@
+#
+# Copyright 2020 NXP
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+# NXP Non-Volatile data flag storage used and then cleared by SW on boot-up
+
+$(eval $(call add_define,NXP_NV_SW_MAINT_LAST_EXEC_DATA))
+
+ifeq ($(NXP_COINED_BB),yes)
+$(eval $(call add_define,NXP_COINED_BB))
+# BL2 : To read the reset cause from LP SECMON GPR register
+# BL31: To write the reset cause to LP SECMON GPR register
+$(eval $(call SET_NXP_MAKE_FLAG,SNVS_NEEDED,BL_COMM))
+
+# BL2: DDR training data is stored on Flexspi NOR.
+ifneq (${BOOT_MODE},flexspi_nor)
+$(eval $(call SET_NXP_MAKE_FLAG,XSPI_NEEDED,BL2))
+endif
+
+else
+$(eval $(call add_define_val,DEFAULT_NV_STORAGE_BASE_ADDR,'${BL2_BIN_XSPI_NOR_END_ADDRESS} - 2 * ${NXP_XSPI_NOR_UNIT_SIZE}'))
+$(eval $(call SET_NXP_MAKE_FLAG,XSPI_NEEDED,BL_COMM))
+endif
+
+NV_STORAGE_INCLUDES	+=  -I${PLAT_COMMON_PATH}/nv_storage
+
+NV_STORAGE_SOURCES	+=  ${PLAT_COMMON_PATH}/nv_storage/plat_nv_storage.c
diff --git a/plat/nxp/common/nv_storage/plat_nv_storage.c b/plat/nxp/common/nv_storage/plat_nv_storage.c
new file mode 100644
index 0000000..7ec4fdb
--- /dev/null
+++ b/plat/nxp/common/nv_storage/plat_nv_storage.c
@@ -0,0 +1,120 @@
+/*
+ * Copyright 2021 NXP
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#include <assert.h>
+#include <errno.h>
+#include <stddef.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <common/debug.h>
+#ifndef NXP_COINED_BB
+#include <flash_info.h>
+#include <fspi.h>
+#include <fspi_api.h>
+#endif
+#include <lib/mmio.h>
+#ifdef NXP_COINED_BB
+#include <snvs.h>
+#else
+#include <xspi_error_codes.h>
+#endif
+
+#include <plat_nv_storage.h>
+
+/*This structure will be a static structure and
+ * will be populated as first step of BL2 booting-up.
+ * fspi_strorage.c . To be located in the fspi driver folder.
+ */
+
+static nv_app_data_t nv_app_data;
+
+int read_nv_app_data(void)
+{
+	int ret = 0;
+
+#ifdef NXP_COINED_BB
+	uint8_t *nv_app_data_array = (uint8_t *) &nv_app_data;
+	uint8_t offset = 0U;
+
+	ret = snvs_read_app_data();
+	do {
+		nv_app_data_array[offset] = snvs_read_app_data_bit(offset);
+		offset++;
+
+	} while (offset < APP_DATA_MAX_OFFSET);
+	snvs_clear_app_data();
+#else
+	uintptr_t nv_base_addr = NV_STORAGE_BASE_ADDR;
+
+	ret = fspi_init(NXP_FLEXSPI_ADDR, NXP_FLEXSPI_FLASH_ADDR);
+
+	if (ret != XSPI_SUCCESS) {
+		ERROR("Failed to initialized driver flexspi-nor.\n");
+		ERROR("exiting warm-reset request.\n");
+		return -ENODEV;
+	}
+
+	xspi_read(nv_base_addr,
+		  (uint32_t *)&nv_app_data, sizeof(nv_app_data_t));
+	xspi_sector_erase((uint32_t) nv_base_addr,
+				F_SECTOR_ERASE_SZ);
+#endif
+	return ret;
+}
+
+int wr_nv_app_data(int data_offset,
+			uint8_t *data,
+			int data_size)
+{
+	int ret = 0;
+#ifdef NXP_COINED_BB
+#if !TRUSTED_BOARD_BOOT
+	snvs_disable_zeroize_lp_gpr();
+#endif
+	/* In case LP SecMon General purpose register,
+	 * only 1 bit flags can be saved.
+	 */
+	if ((data_size > 1) || (*data != DEFAULT_SET_VALUE)) {
+		ERROR("Only binary value is allowed to be written.\n");
+		ERROR("Use flash instead of SNVS GPR as NV location.\n");
+		return -ENODEV;
+	}
+	snvs_write_app_data_bit(data_offset);
+#else
+	uint8_t read_val[sizeof(nv_app_data_t)];
+	uint8_t ready_to_write_val[sizeof(nv_app_data_t)];
+	uintptr_t nv_base_addr = NV_STORAGE_BASE_ADDR;
+
+	assert((nv_base_addr + data_offset + data_size) > (nv_base_addr + F_SECTOR_ERASE_SZ));
+
+	ret = fspi_init(NXP_FLEXSPI_ADDR, NXP_FLEXSPI_FLASH_ADDR);
+
+	if (ret != XSPI_SUCCESS) {
+		ERROR("Failed to initialized driver flexspi-nor.\n");
+		ERROR("exiting warm-reset request.\n");
+		return -ENODEV;
+	}
+
+	ret = xspi_read(nv_base_addr + data_offset, (uint32_t *)read_val, data_size);
+
+	memset(ready_to_write_val, READY_TO_WRITE_VALUE, ARRAY_SIZE(ready_to_write_val));
+
+	if (memcmp(read_val, ready_to_write_val, data_size) == 0) {
+		xspi_write(nv_base_addr + data_offset, data, data_size);
+	}
+#endif
+
+	return ret;
+}
+
+const nv_app_data_t *get_nv_data(void)
+{
+	return (const nv_app_data_t *) &nv_app_data;
+}
diff --git a/plat/nxp/common/nv_storage/plat_nv_storage.h b/plat/nxp/common/nv_storage/plat_nv_storage.h
new file mode 100644
index 0000000..1f5264a
--- /dev/null
+++ b/plat/nxp/common/nv_storage/plat_nv_storage.h
@@ -0,0 +1,40 @@
+/*
+ * Copyright 2021 NXP
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#ifndef PLAT_NV_STRG_H
+#define PLAT_NV_STRG_H
+
+#define DEFAULT_SET_VALUE 0xA1
+#define READY_TO_WRITE_VALUE 0xFF
+
+#ifndef NV_STORAGE_BASE_ADDR
+#define NV_STORAGE_BASE_ADDR DEFAULT_NV_STORAGE_BASE_ADDR
+#endif
+
+typedef struct {
+uint8_t warm_rst_flag;
+uint8_t wdt_rst_flag;
+uint8_t dummy[2];
+} nv_app_data_t;
+
+
+/*below enum and above structure should be in-sync. */
+enum app_data_offset {
+	WARM_RESET_FLAG_OFFSET,
+	WDT_RESET_FLAG_OFFSET,
+	APP_DATA_MAX_OFFSET,
+};
+
+int read_nv_app_data(void);
+
+int wr_nv_app_data(int data_offset,
+			uint8_t *data,
+			int data_size);
+
+const nv_app_data_t *get_nv_data(void);
+
+#endif /* PLAT_NV_STRG_H */