aboutsummaryrefslogtreecommitdiff
path: root/platform/ext/target/arm/musca_b1/common/CMSIS_Driver/Driver_GFC100_EFlash.c
diff options
context:
space:
mode:
Diffstat (limited to 'platform/ext/target/arm/musca_b1/common/CMSIS_Driver/Driver_GFC100_EFlash.c')
-rw-r--r--platform/ext/target/arm/musca_b1/common/CMSIS_Driver/Driver_GFC100_EFlash.c467
1 files changed, 467 insertions, 0 deletions
diff --git a/platform/ext/target/arm/musca_b1/common/CMSIS_Driver/Driver_GFC100_EFlash.c b/platform/ext/target/arm/musca_b1/common/CMSIS_Driver/Driver_GFC100_EFlash.c
new file mode 100644
index 0000000000..c929e7e0ed
--- /dev/null
+++ b/platform/ext/target/arm/musca_b1/common/CMSIS_Driver/Driver_GFC100_EFlash.c
@@ -0,0 +1,467 @@
+/*
+ * Copyright (c) 2018-2020 Arm Limited. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "Driver_Flash.h"
+#include "gfc100_eflash_drv.h"
+#include "RTE_Device.h"
+#include "device_cfg.h"
+#include "device_definition.h"
+#include "system_core_init.h"
+#include "cmsis_driver_config.h"
+
+/**
+ * \file Driver_GFC100_EFlash.c
+ *
+ * \brief CMSIS Flash driver for GFC100 flash controller
+ */
+
+#ifndef ARG_UNUSED
+#define ARG_UNUSED(arg) (void)arg
+#endif
+
+#ifndef ARG_NOT_USED
+#define ARG_NOT_USED 0U
+#endif
+
+/* Driver version */
+#define ARM_FLASH_DRV_VERSION ARM_DRIVER_VERSION_MAJOR_MINOR(1, 0)
+
+const ARM_DRIVER_VERSION GFC100_EFlash_Driver_Version = {
+ ARM_FLASH_API_VERSION, /* Defined in the CMSIS Flash Driver header file */
+ ARM_FLASH_DRV_VERSION
+};
+
+/**
+ * Event ready values for ARM_FLASH_CAPABILITIES::event_ready
+ * \ref ARM_FLASH_CAPABILITIES
+ */
+enum {
+ EVENT_READY_NOT_AVAILABLE = 0u,
+ EVENT_READY_AVAILABLE
+};
+
+/**
+ * Data width values for ARM_FLASH_CAPABILITIES::data_width
+ * \ref ARM_FLASH_CAPABILITIES
+ */
+ enum {
+ DATA_WIDTH_8BIT = 0u,
+ DATA_WIDTH_16BIT,
+ DATA_WIDTH_32BIT
+};
+
+/**
+ * Erase chip values for ARM_FLASH_CAPABILITIES::erase_chip
+ * \ref ARM_FLASH_CAPABILITIES
+ */
+enum {
+ CHIP_ERASE_NOT_SUPPORTED = 0u,
+ CHIP_ERASE_SUPPORTED
+};
+
+/** Driver Capabilities */
+static const ARM_FLASH_CAPABILITIES DriverCapabilities = {
+ .event_ready = EVENT_READY_NOT_AVAILABLE,
+ .data_width = DATA_WIDTH_32BIT,
+ .erase_chip = CHIP_ERASE_SUPPORTED
+};
+
+/**
+ * \brief Flash busy values flash status \ref ARM_FLASH_STATUS
+ */
+enum {
+ DRIVER_STATUS_IDLE = 0u,
+ DRIVER_STATUS_BUSY
+};
+
+/**
+ * \brief Flash error values flash status \ref ARM_FLASH_STATUS
+ */
+enum {
+ DRIVER_STATUS_NO_ERROR = 0u,
+ DRIVER_STATUS_ERROR
+};
+
+/**
+ * \brief Arm Flash device structure.
+ */
+typedef struct _FLASHx_Resources {
+ struct gfc100_eflash_dev_t* dev; /*!< FLASH memory device structure */
+ ARM_FLASH_INFO *data; /*!< FLASH memory device data */
+ ARM_FLASH_STATUS status;
+} ARM_FLASHx_Resources;
+
+static ARM_DRIVER_VERSION ARM_Flash_GetVersion(void)
+{
+ return GFC100_EFlash_Driver_Version;
+}
+
+static ARM_FLASH_CAPABILITIES ARM_Flash_GetCapabilities(void)
+{
+ return DriverCapabilities;
+}
+
+static int32_t ARM_Flashx_Initialize(ARM_FLASHx_Resources *ARM_FLASHx_DEV,
+ ARM_Flash_SignalEvent_t cb_event)
+{
+ ARG_UNUSED(cb_event);
+
+ uint32_t page_size = gfc100_get_eflash_page_size(ARM_FLASHx_DEV->dev);
+ uint32_t flash_size = gfc100_get_eflash_size(ARM_FLASHx_DEV->dev);
+
+ /* Validate hardcoded parameters of the flash */
+ if ((ARM_FLASHx_DEV->data->page_size != page_size) ||
+ (ARM_FLASHx_DEV->data->sector_size != page_size) ||
+ (ARM_FLASHx_DEV->data->sector_count != (flash_size / page_size))) {
+ return ARM_DRIVER_ERROR_PARAMETER;
+ }
+
+ gfc100_eflash_init(ARM_FLASHx_DEV->dev, SystemCoreClock);
+
+ return ARM_DRIVER_OK;
+}
+
+static int32_t ARM_Flashx_Uninitialize(ARM_FLASHx_Resources *ARM_FLASHx_DEV)
+{
+ ARG_UNUSED(ARM_FLASHx_DEV);
+
+ /* Nothing to do */
+ return ARM_DRIVER_OK;
+}
+
+static int32_t ARM_Flashx_PowerControl(ARM_FLASHx_Resources *ARM_FLASHx_DEV,
+ ARM_POWER_STATE state)
+{
+ ARG_UNUSED(ARM_FLASHx_DEV);
+
+ switch(state) {
+ case ARM_POWER_FULL:
+ /* Nothing to do */
+ return ARM_DRIVER_OK;
+ case ARM_POWER_OFF:
+ case ARM_POWER_LOW:
+ return ARM_DRIVER_ERROR_UNSUPPORTED;
+ default:
+ return ARM_DRIVER_ERROR_PARAMETER;
+ }
+}
+
+static int32_t ARM_Flashx_ReadData(ARM_FLASHx_Resources *ARM_FLASHx_DEV,
+ uint32_t addr, void *data, uint32_t cnt)
+{
+ enum gfc100_error_t err = GFC100_ERROR_NONE;
+ uint32_t flash_size = gfc100_get_eflash_size(ARM_FLASHx_DEV->dev);
+
+ ARM_FLASHx_DEV->status.error = DRIVER_STATUS_NO_ERROR;
+
+ /* Check if range is valid */
+ if ((addr + cnt) > flash_size) {
+ ARM_FLASHx_DEV->status.error = DRIVER_STATUS_ERROR;
+ return ARM_DRIVER_ERROR_PARAMETER;
+ }
+
+ ARM_FLASHx_DEV->status.busy = DRIVER_STATUS_BUSY;
+
+ err = gfc100_eflash_read(ARM_FLASHx_DEV->dev, addr, data, &cnt);
+
+ ARM_FLASHx_DEV->status.busy = DRIVER_STATUS_IDLE;
+
+ if(err != GFC100_ERROR_NONE) {
+ ARM_FLASHx_DEV->status.error = DRIVER_STATUS_ERROR;
+ return ARM_DRIVER_ERROR;
+ }
+
+ return ARM_DRIVER_OK;
+}
+
+static int32_t ARM_Flashx_ProgramData(ARM_FLASHx_Resources *ARM_FLASHx_DEV,
+ uint32_t addr, const void *data,
+ uint32_t cnt)
+{
+ enum gfc100_error_t err = GFC100_ERROR_NONE;
+
+ ARM_FLASHx_DEV->status.error = DRIVER_STATUS_NO_ERROR;
+ ARM_FLASHx_DEV->status.busy = DRIVER_STATUS_BUSY;
+
+ /* Note: There is a significantly faster way to write to the flash using
+ * gfc100_eflash_row_write. It has the disadvantage that all IRQs have
+ * to be disabled, because the implementation is sensitive to timing.
+ * For applications where timing can be guaranteed this can be replaced
+ * with gfc100_eflash_row_write. For generic use, simple write is used here.
+ */
+ err = gfc100_eflash_write(ARM_FLASHx_DEV->dev, addr, data, &cnt);
+
+ ARM_FLASHx_DEV->status.busy = DRIVER_STATUS_IDLE;
+
+ if(err != GFC100_ERROR_NONE) {
+ ARM_FLASHx_DEV->status.error = DRIVER_STATUS_ERROR;
+ if ((err == GFC100_ERROR_OUT_OF_RANGE) ||
+ (err == GFC100_ERROR_UNALIGNED_PARAM)) {
+ /* The native driver checks aligment and range */
+ return ARM_DRIVER_ERROR_PARAMETER;
+ }
+ return ARM_DRIVER_ERROR;
+ }
+
+ return ARM_DRIVER_OK;
+}
+
+static int32_t ARM_Flashx_EraseSector(ARM_FLASHx_Resources *ARM_FLASHx_DEV,
+ uint32_t addr)
+{
+ enum gfc100_error_t err = GFC100_ERROR_NONE;
+
+ ARM_FLASHx_DEV->status.error = DRIVER_STATUS_NO_ERROR;
+ ARM_FLASHx_DEV->status.busy = DRIVER_STATUS_BUSY;
+
+ /* The erase function checks whether the address is within the valid flash
+ * address range, and the HW will align the address to page boundary if
+ * it is not aligned.
+ */
+ err = gfc100_eflash_erase(ARM_FLASHx_DEV->dev, addr, GFC100_ERASE_PAGE);
+
+ ARM_FLASHx_DEV->status.busy = DRIVER_STATUS_IDLE;
+
+ if (err != GFC100_ERROR_NONE) {
+ ARM_FLASHx_DEV->status.error = DRIVER_STATUS_ERROR;
+ if (err == GFC100_ERROR_OUT_OF_RANGE) {
+ return ARM_DRIVER_ERROR_PARAMETER;
+ }
+ return ARM_DRIVER_ERROR;
+ }
+
+ return ARM_DRIVER_OK;
+}
+
+static int32_t ARM_Flashx_EraseChip(ARM_FLASHx_Resources *ARM_FLASHx_DEV)
+{
+ enum gfc100_error_t err = GFC100_ERROR_NONE;
+
+ ARM_FLASHx_DEV->status.error = DRIVER_STATUS_NO_ERROR;
+ ARM_FLASHx_DEV->status.busy = DRIVER_STATUS_BUSY;
+
+ /* The erase function checks whether the address is aligned with
+ * the sector or subsector and checks the Flash memory boundaries.
+ */
+ err = gfc100_eflash_erase(ARM_FLASHx_DEV->dev, ARG_NOT_USED,
+ GFC100_MASS_ERASE_MAIN_AREA);
+
+ ARM_FLASHx_DEV->status.busy = DRIVER_STATUS_IDLE;
+
+ if(err != GFC100_ERROR_NONE) {
+ ARM_FLASHx_DEV->status.error = DRIVER_STATUS_ERROR;
+ return ARM_DRIVER_ERROR;
+ }
+
+ return ARM_DRIVER_OK;
+}
+
+static ARM_FLASH_STATUS
+ARM_Flashx_GetStatus(ARM_FLASHx_Resources *ARM_FLASHx_DEV)
+{
+ return ARM_FLASHx_DEV->status;
+}
+
+static ARM_FLASH_INFO * ARM_Flashx_GetInfo(ARM_FLASHx_Resources *ARM_FLASHx_DEV)
+{
+ return ARM_FLASHx_DEV->data;
+}
+
+#if (RTE_EFLASH0)
+static ARM_FLASH_INFO ARM_FLASH0_DEV_DATA = {
+ .sector_info = NULL, /* Uniform sector layout */
+ .sector_count = (0x200000u / 0x4000u), /* 2MB (flash size) / 16kB */
+ .sector_size = 0x4000u, /* 16kB - as there are no sectors the page size
+ * size is used here
+ */
+ .page_size = 0x4000u, /* 16kB */
+ .program_unit = 4u, /* Minimum write size in bytes */
+ .erased_value = 0xFF
+};
+
+static ARM_FLASHx_Resources ARM_FLASH0_DEV = {
+ .dev = &EFLASH0_DEV,
+ .data = &(ARM_FLASH0_DEV_DATA),
+ .status = {
+ .busy = DRIVER_STATUS_IDLE,
+ .error = DRIVER_STATUS_NO_ERROR,
+ .reserved = 0,
+ },
+};
+
+static ARM_DRIVER_VERSION ARM_Flash0_GetVersion(void)
+{
+ return ARM_Flash_GetVersion();
+}
+
+static ARM_FLASH_CAPABILITIES ARM_Flash0_GetCapabilities(void)
+{
+ return ARM_Flash_GetCapabilities();
+}
+
+static int32_t ARM_Flash0_Initialize(ARM_Flash_SignalEvent_t cb_event)
+{
+ return ARM_Flashx_Initialize(&ARM_FLASH0_DEV, cb_event);
+}
+
+static int32_t ARM_Flash0_Uninitialize(void)
+{
+ return ARM_Flashx_Uninitialize(&ARM_FLASH0_DEV);
+}
+
+static int32_t ARM_Flash0_PowerControl(ARM_POWER_STATE state)
+{
+ return ARM_Flashx_PowerControl(&ARM_FLASH0_DEV, state);
+}
+
+static int32_t ARM_Flash0_ReadData(uint32_t addr, void *data, uint32_t cnt)
+{
+ return ARM_Flashx_ReadData(&ARM_FLASH0_DEV, addr, data, cnt);
+}
+
+static int32_t ARM_Flash0_ProgramData(uint32_t addr, const void *data,
+ uint32_t cnt)
+{
+ return ARM_Flashx_ProgramData(&ARM_FLASH0_DEV, addr, data, cnt);
+}
+
+static int32_t ARM_Flash0_EraseSector(uint32_t addr)
+{
+ return ARM_Flashx_EraseSector(&ARM_FLASH0_DEV, addr);
+}
+
+static int32_t ARM_Flash0_EraseChip(void)
+{
+ return ARM_Flashx_EraseChip(&ARM_FLASH0_DEV);
+}
+
+static ARM_FLASH_STATUS ARM_Flash0_GetStatus(void)
+{
+ return ARM_Flashx_GetStatus(&ARM_FLASH0_DEV);
+}
+
+static ARM_FLASH_INFO * ARM_Flash0_GetInfo(void)
+{
+ return ARM_Flashx_GetInfo(&ARM_FLASH0_DEV);
+}
+
+ARM_DRIVER_FLASH Driver_EFLASH0 = {
+ ARM_Flash0_GetVersion,
+ ARM_Flash0_GetCapabilities,
+ ARM_Flash0_Initialize,
+ ARM_Flash0_Uninitialize,
+ ARM_Flash0_PowerControl,
+ ARM_Flash0_ReadData,
+ ARM_Flash0_ProgramData,
+ ARM_Flash0_EraseSector,
+ ARM_Flash0_EraseChip,
+ ARM_Flash0_GetStatus,
+ ARM_Flash0_GetInfo
+};
+#endif /* RTE_EFLASH0 */
+
+#if (RTE_EFLASH1)
+static ARM_FLASH_INFO ARM_FLASH1_DEV_DATA = {
+ .sector_info = NULL, /* Uniform sector layout */
+ .sector_count = (0x200000u / 0x4000u), /* 2MB (flash size) / 16kB */
+ .sector_size = 0x4000u, /* 16kB - as there are no sectors the page size
+ * size is used here
+ */
+ .page_size = 0x4000u, /* 16kB */
+ .program_unit = 4u, /* Minimum write size in bytes */
+ .erased_value = 0xFF
+};
+
+static ARM_FLASHx_Resources ARM_FLASH1_DEV = {
+ .dev = &EFLASH1_DEV,
+ .data = &ARM_FLASH1_DEV_DATA,
+ .status = {
+ .busy = DRIVER_STATUS_IDLE,
+ .error = DRIVER_STATUS_NO_ERROR,
+ .reserved = 0,
+ },
+};
+
+static ARM_DRIVER_VERSION ARM_Flash1_GetVersion(void)
+{
+ return ARM_Flash_GetVersion();
+}
+
+static ARM_FLASH_CAPABILITIES ARM_Flash1_GetCapabilities(void)
+{
+ return ARM_Flash_GetCapabilities();
+}
+
+static int32_t ARM_Flash1_Initialize(ARM_Flash_SignalEvent_t cb_event)
+{
+ return ARM_Flashx_Initialize(&ARM_FLASH1_DEV, cb_event);
+}
+
+static int32_t ARM_Flash1_Uninitialize(void)
+{
+ return ARM_Flashx_Uninitialize(&ARM_FLASH1_DEV);
+}
+
+static int32_t ARM_Flash1_PowerControl(ARM_POWER_STATE state)
+{
+ return ARM_Flashx_PowerControl(&ARM_FLASH1_DEV, state);
+}
+
+static int32_t ARM_Flash1_ReadData(uint32_t addr, void *data, uint32_t cnt)
+{
+ return ARM_Flashx_ReadData(&ARM_FLASH1_DEV, addr, data, cnt);
+}
+
+static int32_t ARM_Flash1_ProgramData(uint32_t addr, const void *data,
+ uint32_t cnt)
+{
+ return ARM_Flashx_ProgramData(&ARM_FLASH1_DEV, addr, data, cnt);
+}
+
+static int32_t ARM_Flash1_EraseSector(uint32_t addr)
+{
+ return ARM_Flashx_EraseSector(&ARM_FLASH1_DEV, addr);
+}
+
+static int32_t ARM_Flash1_EraseChip(void)
+{
+ return ARM_Flashx_EraseChip(&ARM_FLASH1_DEV);
+}
+
+static ARM_FLASH_STATUS ARM_Flash1_GetStatus(void)
+{
+ return (ARM_Flashx_GetStatus(&ARM_FLASH1_DEV));
+}
+
+static ARM_FLASH_INFO * ARM_Flash1_GetInfo(void)
+{
+ return ARM_Flashx_GetInfo(&ARM_FLASH1_DEV);
+}
+
+ARM_DRIVER_FLASH Driver_EFLASH1 = {
+ ARM_Flash1_GetVersion,
+ ARM_Flash1_GetCapabilities,
+ ARM_Flash1_Initialize,
+ ARM_Flash1_Uninitialize,
+ ARM_Flash1_PowerControl,
+ ARM_Flash1_ReadData,
+ ARM_Flash1_ProgramData,
+ ARM_Flash1_EraseSector,
+ ARM_Flash1_EraseChip,
+ ARM_Flash1_GetStatus,
+ ARM_Flash1_GetInfo
+};
+#endif /* RTE_EFLASH1 */