Merge pull request #2121 from rgrover/develop

introduce a context structure to encompass global state in the K64F Storage driver
pull/2148/head
Martin Kojtal 2016-07-12 10:22:36 +01:00 committed by GitHub
commit 4b441c9e9e
1 changed files with 180 additions and 170 deletions

View File

@ -126,28 +126,8 @@
/*! @brief Access to FTFx->FCCOB */ /*! @brief Access to FTFx->FCCOB */
extern volatile uint32_t *const kFCCOBx; extern volatile uint32_t *const kFCCOBx;
static flash_config_t privateDeviceConfig;
#endif /* #ifdef USING_KSDK2 */ #endif /* #ifdef USING_KSDK2 */
/*
* forward declarations
*/
static int32_t getBlock(uint64_t addr, ARM_STORAGE_BLOCK *blockP);
static int32_t nextBlock(const ARM_STORAGE_BLOCK* prevP, ARM_STORAGE_BLOCK *nextP);
/*
* Global state for the driver.
*/
ARM_Storage_Callback_t commandCompletionCallback;
static bool initialized = false;
ARM_POWER_STATE powerState = ARM_POWER_OFF;
ARM_STORAGE_OPERATION currentCommand;
uint64_t currentOperatingStorageAddress;
size_t sizeofCurrentOperation;
size_t amountLeftToOperate;
const uint8_t *currentOperatingData;
#ifdef USING_KSDK2 #ifdef USING_KSDK2
#define ERASE_UNIT (FSL_FEATURE_FLASH_PFLASH_BLOCK_SECTOR_SIZE) #define ERASE_UNIT (FSL_FEATURE_FLASH_PFLASH_BLOCK_SECTOR_SIZE)
#define BLOCK1_START_ADDR (FSL_FEATURE_FLASH_PFLASH_BLOCK_SIZE) #define BLOCK1_START_ADDR (FSL_FEATURE_FLASH_PFLASH_BLOCK_SIZE)
@ -166,22 +146,44 @@ const uint8_t *currentOperatingData;
#define SIZEOF_DOUBLE_PHRASE (16) #define SIZEOF_DOUBLE_PHRASE (16)
#endif /* #ifdef USING_KSDK2 */ #endif /* #ifdef USING_KSDK2 */
/*
* forward declarations
*/
static int32_t getBlock(uint64_t addr, ARM_STORAGE_BLOCK *blockP);
static int32_t nextBlock(const ARM_STORAGE_BLOCK* prevP, ARM_STORAGE_BLOCK *nextP);
/*
* Global state for the driver.
*/
struct mtd_k64f_data {
ARM_Storage_Callback_t commandCompletionCallback;
bool initialized;
ARM_POWER_STATE powerState;
ARM_STORAGE_OPERATION currentCommand;
uint64_t currentOperatingStorageAddress;
size_t sizeofCurrentOperation;
size_t amountLeftToOperate;
const uint8_t *currentOperatingData;
} mtd_k64f_data;
/* /*
* Static configuration. * Static configuration.
*/ */
static const ARM_STORAGE_BLOCK blockTable[] = { static const ARM_STORAGE_BLOCK blockTable[] = {
{ {
/**< This is the start address of the flash block. */ /**< This is the start address of the flash block. */
#ifdef YOTTA_CFG_CONFIG_HARDWARE_MTD_START_ADDR #ifdef DEVICE_STORAGE_CONFIG_HARDWARE_MTD_START_ADDR
.addr = YOTTA_CFG_CONFIG_HARDWARE_MTD_START_ADDR, .addr = DEVICE_STORAGE_CONFIG_HARDWARE_MTD_START_ADDR,
#else #else
.addr = BLOCK1_START_ADDR, .addr = BLOCK1_START_ADDR,
#endif #endif
/**< This is the size of the flash block, in units of bytes. /**< This is the size of the flash block, in units of bytes.
* Together with addr, it describes a range [addr, addr+size). */ * Together with addr, it describes a range [addr, addr+size). */
#ifdef YOTTA_CFG_CONFIG_HARDWARE_MTD_SIZE #ifdef DEVICE_STORAGE_CONFIG_HARDWARE_MTD_SIZE
.size = YOTTA_CFG_CONFIG_HARDWARE_MTD_SIZE, .size = DEVICE_STORAGE_CONFIG_HARDWARE_MTD_SIZE,
#else #else
.size = BLOCK1_SIZE, .size = BLOCK1_SIZE,
#endif #endif
@ -202,6 +204,13 @@ static const ARM_DRIVER_VERSION version = {
.drv = ARM_DRIVER_VERSION_MAJOR_MINOR(1,00) .drv = ARM_DRIVER_VERSION_MAJOR_MINOR(1,00)
}; };
#if (!defined(DEVICE_STORAGE_CONFIG_HARDWARE_MTD_ASYNC_OPS) || DEVICE_STORAGE_CONFIG_HARDWARE_MTD_ASYNC_OPS)
#define ASYNC_OPS 1
#else
#define ASYNC_OPS 0
#endif
static const ARM_STORAGE_CAPABILITIES caps = { static const ARM_STORAGE_CAPABILITIES caps = {
/**< Signal Flash Ready event. In other words, can APIs like initialize, /**< Signal Flash Ready event. In other words, can APIs like initialize,
* read, erase, program, etc. operate in asynchronous mode? * read, erase, program, etc. operate in asynchronous mode?
@ -212,15 +221,11 @@ static const ARM_STORAGE_CAPABILITIES caps = {
* 1, drivers may still complete asynchronous operations synchronously as * 1, drivers may still complete asynchronous operations synchronously as
* necessary--in which case they return a positive error code to indicate * necessary--in which case they return a positive error code to indicate
* synchronous completion. */ * synchronous completion. */
#ifndef YOTTA_CFG_CONFIG_HARDWARE_MTD_ASYNC_OPS .asynchronous_ops = ASYNC_OPS,
.asynchronous_ops = 1,
#else
.asynchronous_ops = YOTTA_CFG_CONFIG_HARDWARE_MTD_ASYNC_OPS,
#endif
/* Enable chip-erase functionality if we own all of block-1. */ /* Enable chip-erase functionality if we own all of block-1. */
#if ((!defined (YOTTA_CFG_CONFIG_HARDWARE_MTD_START_ADDR) || (YOTTA_CFG_CONFIG_HARDWARE_MTD_START_ADDR == BLOCK1_START_ADDR)) && \ #if ((!defined (DEVICE_STORAGE_CONFIG_HARDWARE_MTD_START_ADDR) || (DEVICE_STORAGE_CONFIG_HARDWARE_MTD_START_ADDR == BLOCK1_START_ADDR)) && \
(!defined (YOTTA_CFG_CONFIG_HARDWARE_MTD_SIZE) || (YOTTA_CFG_CONFIG_HARDWARE_MTD_SIZE == BLOCK1_SIZE))) (!defined (DEVICE_STORAGE_CONFIG_HARDWARE_MTD_SIZE) || (DEVICE_STORAGE_CONFIG_HARDWARE_MTD_SIZE == BLOCK1_SIZE)))
.erase_all = 1, /**< Supports EraseChip operation. */ .erase_all = 1, /**< Supports EraseChip operation. */
#else #else
.erase_all = 0, /**< Supports EraseChip operation. */ .erase_all = 0, /**< Supports EraseChip operation. */
@ -228,7 +233,11 @@ static const ARM_STORAGE_CAPABILITIES caps = {
}; };
static const ARM_STORAGE_INFO info = { static const ARM_STORAGE_INFO info = {
#ifdef DEVICE_STORAGE_CONFIG_HARDWARE_MTD_SIZE
.total_storage = DEVICE_STORAGE_CONFIG_HARDWARE_MTD_SIZE, /**< Total available storage, in units of octets. */
#else
.total_storage = BLOCK1_SIZE, /**< Total available storage, in units of octets. By default, BLOCK0 is reserved to hold program code. */ .total_storage = BLOCK1_SIZE, /**< Total available storage, in units of octets. By default, BLOCK0 is reserved to hold program code. */
#endif
.program_unit = PROGRAM_UNIT, .program_unit = PROGRAM_UNIT,
.optimal_program_unit = OPTIMAL_PROGRAM_UNIT, .optimal_program_unit = OPTIMAL_PROGRAM_UNIT,
@ -265,7 +274,6 @@ enum FlashCommandOps {
SETRAM = (uint8_t)0x81, /* Set FlexRAM. (unused for now) */ SETRAM = (uint8_t)0x81, /* Set FlexRAM. (unused for now) */
}; };
/** /**
* Read out the CCIF (Command Complete Interrupt Flag) to ensure all previous * Read out the CCIF (Command Complete Interrupt Flag) to ensure all previous
* operations have completed. * operations have completed.
@ -388,11 +396,6 @@ static inline bool commandCompletionInterruptEnabled(void)
#endif #endif
} }
static inline bool asyncOperationsEnabled(void)
{
return caps.asynchronous_ops;
}
/** /**
* Once all relevant command parameters have been loaded, the user launches the * Once all relevant command parameters have been loaded, the user launches the
* command by clearing the FSTAT[CCIF] bit by writing a '1' to it. The CCIF flag * command by clearing the FSTAT[CCIF] bit by writing a '1' to it. The CCIF flag
@ -511,22 +514,22 @@ static inline size_t sizeofLargestProgramSection(uint64_t addr, size_t size)
* Advance the state machine for program-data. This function is called only if * Advance the state machine for program-data. This function is called only if
* amountLeftToOperate is non-zero. * amountLeftToOperate is non-zero.
*/ */
static inline void setupNextProgramData(void) static inline void setupNextProgramData(struct mtd_k64f_data *context)
{ {
if ((amountLeftToOperate == PROGRAM_PHRASE_SIZEOF_INLINE_DATA) || if ((context->amountLeftToOperate == PROGRAM_PHRASE_SIZEOF_INLINE_DATA) ||
((currentOperatingStorageAddress % SIZEOF_DOUBLE_PHRASE) == PROGRAM_PHRASE_SIZEOF_INLINE_DATA)) { ((context->currentOperatingStorageAddress % SIZEOF_DOUBLE_PHRASE) == PROGRAM_PHRASE_SIZEOF_INLINE_DATA)) {
setup8ByteWrite(currentOperatingStorageAddress, currentOperatingData); setup8ByteWrite(context->currentOperatingStorageAddress, context->currentOperatingData);
amountLeftToOperate -= PROGRAM_PHRASE_SIZEOF_INLINE_DATA; context->amountLeftToOperate -= PROGRAM_PHRASE_SIZEOF_INLINE_DATA;
currentOperatingStorageAddress += PROGRAM_PHRASE_SIZEOF_INLINE_DATA; context->currentOperatingStorageAddress += PROGRAM_PHRASE_SIZEOF_INLINE_DATA;
currentOperatingData += PROGRAM_PHRASE_SIZEOF_INLINE_DATA; context->currentOperatingData += PROGRAM_PHRASE_SIZEOF_INLINE_DATA;
} else { } else {
size_t amount = sizeofLargestProgramSection(currentOperatingStorageAddress, amountLeftToOperate); size_t amount = sizeofLargestProgramSection(context->currentOperatingStorageAddress, context->amountLeftToOperate);
setupProgramSection(currentOperatingStorageAddress, currentOperatingData, amount); setupProgramSection(context->currentOperatingStorageAddress, context->currentOperatingData, amount);
amountLeftToOperate -= amount; context->amountLeftToOperate -= amount;
currentOperatingStorageAddress += amount; context->currentOperatingStorageAddress += amount;
currentOperatingData += amount; context->currentOperatingData += amount;
} }
} }
@ -534,15 +537,15 @@ static inline void setupNextProgramData(void)
* Advance the state machine for erase. This function is called only if * Advance the state machine for erase. This function is called only if
* amountLeftToOperate is non-zero. * amountLeftToOperate is non-zero.
*/ */
static inline void setupNextErase(void) static inline void setupNextErase(struct mtd_k64f_data *context)
{ {
setupEraseSector(currentOperatingStorageAddress); /* Program FCCOB to load the required command parameters. */ setupEraseSector(context->currentOperatingStorageAddress); /* Program FCCOB to load the required command parameters. */
amountLeftToOperate -= ERASE_UNIT; context->amountLeftToOperate -= ERASE_UNIT;
currentOperatingStorageAddress += ERASE_UNIT; context->currentOperatingStorageAddress += ERASE_UNIT;
} }
static int32_t executeCommand(void) static int32_t executeCommand(struct mtd_k64f_data *context)
{ {
launchCommand(); launchCommand();
@ -550,104 +553,106 @@ static int32_t executeCommand(void)
* parameter checks and protection checks, if applicable, which are unique * parameter checks and protection checks, if applicable, which are unique
* to each command. */ * to each command. */
if (asyncOperationsEnabled()) { #if ASYNC_OPS
/* Asynchronous operation */ /* Asynchronous operation */
/* Spin waiting for the command execution to begin. */ (void)context; /* avoid compiler warning about un-used variables */
while (!controllerCurrentlyBusy() && !failedWithAccessError() && !failedWithProtectionError());
/* Spin waiting for the command execution to begin. */
while (!controllerCurrentlyBusy() && !failedWithAccessError() && !failedWithProtectionError());
if (failedWithAccessError() || failedWithProtectionError()) {
clearErrorStatusBits();
return ARM_DRIVER_ERROR_PARAMETER;
}
enableCommandCompletionInterrupt();
return ARM_DRIVER_OK; /* signal asynchronous completion. An interrupt will signal completion later. */
#else /* #if ASYNC_OPS */
/* Synchronous operation. */
while (1) {
/* Spin waiting for the command execution to complete. */
while (controllerCurrentlyBusy());
/* Execution may result in failure. Check for errors */
if (failedWithAccessError() || failedWithProtectionError()) { if (failedWithAccessError() || failedWithProtectionError()) {
clearErrorStatusBits(); clearErrorStatusBits();
return ARM_DRIVER_ERROR_PARAMETER; return ARM_DRIVER_ERROR_PARAMETER;
} }
if (failedWithRunTimeError()) {
return ARM_DRIVER_ERROR; /* unspecified runtime error. */
}
enableCommandCompletionInterrupt(); /* signal synchronous completion. */
switch (context->currentCommand) {
case ARM_STORAGE_OPERATION_PROGRAM_DATA:
if (context->amountLeftToOperate == 0) {
return context->sizeofCurrentOperation;
}
return ARM_DRIVER_OK; /* signal asynchronous completion. An interrupt will signal completion later. */ /* start the successive program operation */
} else { setupNextProgramData(context);
/* Synchronous operation. */ launchCommand();
/* continue on to the next iteration of the parent loop */
break;
while (1) { case ARM_STORAGE_OPERATION_ERASE:
if (context->amountLeftToOperate == 0) {
return context->sizeofCurrentOperation;
}
/* Spin waiting for the command execution to complete. */ setupNextErase(context); /* start the successive erase operation */
while (controllerCurrentlyBusy()); launchCommand();
/* continue on to the next iteration of the parent loop */
break;
/* Execution may result in failure. Check for errors */ default:
if (failedWithAccessError() || failedWithProtectionError()) { return 1;
clearErrorStatusBits();
return ARM_DRIVER_ERROR_PARAMETER;
}
if (failedWithRunTimeError()) {
return ARM_DRIVER_ERROR; /* unspecified runtime error. */
}
/* signal synchronous completion. */
switch (currentCommand) {
case ARM_STORAGE_OPERATION_PROGRAM_DATA:
if (amountLeftToOperate == 0) {
return sizeofCurrentOperation;
}
/* start the successive program operation */
setupNextProgramData();
launchCommand();
/* continue on to the next iteration of the parent loop */
break;
case ARM_STORAGE_OPERATION_ERASE:
if (amountLeftToOperate == 0) {
return sizeofCurrentOperation;
}
setupNextErase(); /* start the successive erase operation */
launchCommand();
/* continue on to the next iteration of the parent loop */
break;
default:
return 1;
}
} }
} }
#endif /* #ifdef ASYNC_OPS */
} }
#if ASYNC_OPS
static void ftfe_ccie_irq_handler(void) static void ftfe_ccie_irq_handler(void)
{ {
NVIC_ClearPendingIRQ(FTFE_IRQn);
disbleCommandCompletionInterrupt(); disbleCommandCompletionInterrupt();
struct mtd_k64f_data *context = &mtd_k64f_data;
/* check for errors */ /* check for errors */
if (failedWithAccessError() || failedWithProtectionError()) { if (failedWithAccessError() || failedWithProtectionError()) {
clearErrorStatusBits(); clearErrorStatusBits();
if (commandCompletionCallback) { if (context->commandCompletionCallback) {
commandCompletionCallback(ARM_DRIVER_ERROR_PARAMETER, currentCommand); context->commandCompletionCallback(ARM_DRIVER_ERROR_PARAMETER, context->currentCommand);
} }
return; return;
} }
if (failedWithRunTimeError()) { if (failedWithRunTimeError()) {
if (commandCompletionCallback) { if (context->commandCompletionCallback) {
commandCompletionCallback(ARM_DRIVER_ERROR, currentCommand); context->commandCompletionCallback(ARM_DRIVER_ERROR, context->currentCommand);
} }
return; return;
} }
switch (currentCommand) { switch (context->currentCommand) {
case ARM_STORAGE_OPERATION_PROGRAM_DATA: case ARM_STORAGE_OPERATION_PROGRAM_DATA:
if (amountLeftToOperate == 0) { if (context->amountLeftToOperate == 0) {
if (commandCompletionCallback) { if (context->commandCompletionCallback) {
commandCompletionCallback(sizeofCurrentOperation, ARM_STORAGE_OPERATION_PROGRAM_DATA); context->commandCompletionCallback(context->sizeofCurrentOperation, ARM_STORAGE_OPERATION_PROGRAM_DATA);
} }
return; return;
} }
/* start the successive program operation */ /* start the successive program operation */
setupNextProgramData(); setupNextProgramData(context);
launchCommand(); launchCommand();
while (!controllerCurrentlyBusy() && !failedWithAccessError() && !failedWithProtectionError()); while (!controllerCurrentlyBusy() && !failedWithAccessError() && !failedWithProtectionError());
if (failedWithAccessError() || failedWithProtectionError()) { if (failedWithAccessError() || failedWithProtectionError()) {
clearErrorStatusBits(); clearErrorStatusBits();
if (commandCompletionCallback) { if (context->commandCompletionCallback) {
commandCompletionCallback(ARM_DRIVER_ERROR_PARAMETER, ARM_STORAGE_OPERATION_PROGRAM_DATA); context->commandCompletionCallback(ARM_DRIVER_ERROR_PARAMETER, ARM_STORAGE_OPERATION_PROGRAM_DATA);
} }
return; return;
} }
@ -656,21 +661,21 @@ static void ftfe_ccie_irq_handler(void)
break; break;
case ARM_STORAGE_OPERATION_ERASE: case ARM_STORAGE_OPERATION_ERASE:
if (amountLeftToOperate == 0) { if (context->amountLeftToOperate == 0) {
if (commandCompletionCallback) { if (context->commandCompletionCallback) {
commandCompletionCallback(sizeofCurrentOperation, ARM_STORAGE_OPERATION_ERASE); context->commandCompletionCallback(context->sizeofCurrentOperation, ARM_STORAGE_OPERATION_ERASE);
} }
return; return;
} }
setupNextErase(); setupNextErase(context);
launchCommand(); launchCommand();
while (!controllerCurrentlyBusy() && !failedWithAccessError() && !failedWithProtectionError()); while (!controllerCurrentlyBusy() && !failedWithAccessError() && !failedWithProtectionError());
if (failedWithAccessError() || failedWithProtectionError()) { if (failedWithAccessError() || failedWithProtectionError()) {
clearErrorStatusBits(); clearErrorStatusBits();
if (commandCompletionCallback) { if (context->commandCompletionCallback) {
commandCompletionCallback(ARM_DRIVER_ERROR_PARAMETER, ARM_STORAGE_OPERATION_ERASE); context->commandCompletionCallback(ARM_DRIVER_ERROR_PARAMETER, ARM_STORAGE_OPERATION_ERASE);
} }
return; return;
} }
@ -679,12 +684,13 @@ static void ftfe_ccie_irq_handler(void)
break; break;
default: default:
if (commandCompletionCallback) { if (context->commandCompletionCallback) {
commandCompletionCallback(ARM_DRIVER_OK, currentCommand); context->commandCompletionCallback(ARM_DRIVER_OK, context->currentCommand);
} }
break; break;
} }
} }
#endif /* #if ASYNC_OPS */
/** /**
* This is a helper function which can be used to do arbitrary sanity checking * This is a helper function which can be used to do arbitrary sanity checking
@ -707,7 +713,6 @@ static int32_t checkForEachBlockInRange(uint64_t startAddr, uint32_t size, int32
return rc; return rc;
} }
/* move on to the following block */ /* move on to the following block */
if (nextBlock(&block, &block) != ARM_DRIVER_OK) { if (nextBlock(&block, &block) != ARM_DRIVER_OK) {
break; break;
@ -746,21 +751,16 @@ static ARM_STORAGE_CAPABILITIES getCapabilities(void)
static int32_t initialize(ARM_Storage_Callback_t callback) static int32_t initialize(ARM_Storage_Callback_t callback)
{ {
currentCommand = ARM_STORAGE_OPERATION_INITIALIZE; struct mtd_k64f_data *context = &mtd_k64f_data;
memset(context, 0, sizeof(mtd_k64f_data));
context->currentCommand = ARM_STORAGE_OPERATION_INITIALIZE;
if (initialized) { if (context->initialized) {
commandCompletionCallback = callback; context->commandCompletionCallback = callback;
return 1; /* synchronous completion. */ return 1; /* synchronous completion. */
} }
#ifdef USING_KSDK2
status_t rc = FLASH_Init(&privateDeviceConfig);
if (rc != kStatus_FLASH_Success) {
return ARM_DRIVER_ERROR;
}
#endif /* ifdef USING_KSDK2 */
if (controllerCurrentlyBusy()) { if (controllerCurrentlyBusy()) {
/* The user cannot initiate any further FTFE commands until notified that the /* The user cannot initiate any further FTFE commands until notified that the
* current command has completed.*/ * current command has completed.*/
@ -769,52 +769,57 @@ static int32_t initialize(ARM_Storage_Callback_t callback)
clearErrorStatusBits(); clearErrorStatusBits();
commandCompletionCallback = callback; context->commandCompletionCallback = callback;
/* Enable the command-completion interrupt. */ /* Enable the command-completion interrupt. */
if (asyncOperationsEnabled()) { #if ASYNC_OPS
NVIC_SetVector(FTFE_IRQn, (uint32_t)ftfe_ccie_irq_handler); NVIC_SetVector(FTFE_IRQn, (uint32_t)ftfe_ccie_irq_handler);
NVIC_ClearPendingIRQ(FTFE_IRQn); NVIC_ClearPendingIRQ(FTFE_IRQn);
NVIC_EnableIRQ(FTFE_IRQn); NVIC_EnableIRQ(FTFE_IRQn);
} #endif
initialized = true; context->initialized = true;
return 1; /* synchronous completion. */ return 1; /* synchronous completion. */
} }
static int32_t uninitialize(void) { static int32_t uninitialize(void) {
currentCommand = ARM_STORAGE_OPERATION_UNINITIALIZE; struct mtd_k64f_data *context = &mtd_k64f_data;
context->currentCommand = ARM_STORAGE_OPERATION_UNINITIALIZE;
if (!initialized) { if (!context->initialized) {
return ARM_DRIVER_ERROR; return ARM_DRIVER_ERROR;
} }
/* Disable the command-completion interrupt. */ /* Disable the command-completion interrupt. */
if (asyncOperationsEnabled() && commandCompletionInterruptEnabled()) { #if ASYNC_OPS
if (commandCompletionInterruptEnabled()) {
disbleCommandCompletionInterrupt(); disbleCommandCompletionInterrupt();
NVIC_DisableIRQ(FTFE_IRQn); NVIC_DisableIRQ(FTFE_IRQn);
NVIC_ClearPendingIRQ(FTFE_IRQn); NVIC_ClearPendingIRQ(FTFE_IRQn);
} }
#endif
commandCompletionCallback = NULL; context->commandCompletionCallback = NULL;
initialized = false; context->initialized = false;
return 1; /* synchronous completion. */ return 1; /* synchronous completion. */
} }
static int32_t powerControl(ARM_POWER_STATE state) static int32_t powerControl(ARM_POWER_STATE state)
{ {
currentCommand = ARM_STORAGE_OPERATION_POWER_CONTROL; struct mtd_k64f_data *context = &mtd_k64f_data;
context->currentCommand = ARM_STORAGE_OPERATION_POWER_CONTROL;
powerState = state; context->powerState = state;
return 1; /* signal synchronous completion. */ return 1; /* signal synchronous completion. */
} }
static int32_t readData(uint64_t addr, void *data, uint32_t size) static int32_t readData(uint64_t addr, void *data, uint32_t size)
{ {
currentCommand = ARM_STORAGE_OPERATION_READ_DATA; struct mtd_k64f_data *context = &mtd_k64f_data;
context->currentCommand = ARM_STORAGE_OPERATION_READ_DATA;
if (!initialized) { if (!context->initialized) {
return ARM_DRIVER_ERROR; /* illegal */ return ARM_DRIVER_ERROR; /* illegal */
} }
@ -826,13 +831,15 @@ static int32_t readData(uint64_t addr, void *data, uint32_t size)
return ARM_DRIVER_ERROR_PARAMETER; /* illegal address range */ return ARM_DRIVER_ERROR_PARAMETER; /* illegal address range */
} }
context->currentCommand = ARM_STORAGE_OPERATION_READ_DATA;
memcpy(data, (const void *)(uintptr_t)addr, size); memcpy(data, (const void *)(uintptr_t)addr, size);
return size; /* signal synchronous completion. */ return size; /* signal synchronous completion. */
} }
static int32_t programData(uint64_t addr, const void *data, uint32_t size) static int32_t programData(uint64_t addr, const void *data, uint32_t size)
{ {
if (!initialized) { struct mtd_k64f_data *context = &mtd_k64f_data;
if (!context->initialized) {
return (int32_t)ARM_DRIVER_ERROR; /* illegal */ return (int32_t)ARM_DRIVER_ERROR; /* illegal */
} }
@ -853,27 +860,28 @@ static int32_t programData(uint64_t addr, const void *data, uint32_t size)
return ARM_STORAGE_ERROR_NOT_PROGRAMMABLE; return ARM_STORAGE_ERROR_NOT_PROGRAMMABLE;
} }
currentCommand = ARM_STORAGE_OPERATION_PROGRAM_DATA;
if (controllerCurrentlyBusy()) { if (controllerCurrentlyBusy()) {
/* The user cannot initiate any further FTFE commands until notified that the /* The user cannot initiate any further FTFE commands until notified that the
* current command has completed.*/ * current command has completed.*/
return ARM_DRIVER_ERROR_BUSY; return ARM_DRIVER_ERROR_BUSY;
} }
sizeofCurrentOperation = size; context->currentCommand = ARM_STORAGE_OPERATION_PROGRAM_DATA;
amountLeftToOperate = size; context->sizeofCurrentOperation = size;
currentOperatingData = data; context->amountLeftToOperate = size;
currentOperatingStorageAddress = addr; context->currentOperatingData = data;
context->currentOperatingStorageAddress = addr;
clearErrorStatusBits(); clearErrorStatusBits();
setupNextProgramData(); setupNextProgramData(context);
return executeCommand(); return executeCommand(context);
} }
static int32_t erase(uint64_t addr, uint32_t size) static int32_t erase(uint64_t addr, uint32_t size)
{ {
if (!initialized) { struct mtd_k64f_data *context = &mtd_k64f_data;
if (!context->initialized) {
return (int32_t)ARM_DRIVER_ERROR; /* illegal */ return (int32_t)ARM_DRIVER_ERROR; /* illegal */
} }
/* argument validation */ /* argument validation */
@ -893,28 +901,27 @@ static int32_t erase(uint64_t addr, uint32_t size)
return ARM_STORAGE_ERROR_NOT_ERASABLE; return ARM_STORAGE_ERROR_NOT_ERASABLE;
} }
currentCommand = ARM_STORAGE_OPERATION_ERASE;
currentOperatingStorageAddress = addr;
sizeofCurrentOperation = size;
amountLeftToOperate = size;
if (controllerCurrentlyBusy()) { if (controllerCurrentlyBusy()) {
/* The user cannot initiate any further FTFE commands until notified that the /* The user cannot initiate any further FTFE commands until notified that the
* current command has completed.*/ * current command has completed.*/
return (int32_t)ARM_DRIVER_ERROR_BUSY; return (int32_t)ARM_DRIVER_ERROR_BUSY;
} }
context->currentCommand = ARM_STORAGE_OPERATION_ERASE;
context->currentOperatingStorageAddress = addr;
context->sizeofCurrentOperation = size;
context->amountLeftToOperate = size;
clearErrorStatusBits(); clearErrorStatusBits();
setupNextErase(); setupNextErase(context);
return executeCommand(); return executeCommand(context);
} }
static int32_t eraseAll(void) static int32_t eraseAll(void)
{ {
currentCommand = ARM_STORAGE_OPERATION_ERASE_ALL; struct mtd_k64f_data *context = &mtd_k64f_data;
if (!initialized) { if (!context->initialized) {
return (int32_t)ARM_DRIVER_ERROR; /* illegal */ return (int32_t)ARM_DRIVER_ERROR; /* illegal */
} }
@ -932,22 +939,25 @@ static int32_t eraseAll(void)
return (int32_t)ARM_DRIVER_ERROR_BUSY; return (int32_t)ARM_DRIVER_ERROR_BUSY;
} }
context->currentCommand = ARM_STORAGE_OPERATION_ERASE_ALL;
clearErrorStatusBits(); clearErrorStatusBits();
/* Program FCCOB to load the required command parameters. */ /* Program FCCOB to load the required command parameters. */
setupEraseBlock(BLOCK1_START_ADDR); setupEraseBlock(BLOCK1_START_ADDR);
return executeCommand(context);
return executeCommand();
} }
static ARM_STORAGE_STATUS getStatus(void) static ARM_STORAGE_STATUS getStatus(void)
{ {
struct mtd_k64f_data *context = &mtd_k64f_data;
ARM_STORAGE_STATUS status = { ARM_STORAGE_STATUS status = {
.busy = 0, .busy = 0,
.error = 0, .error = 0,
}; };
if (!initialized) { if (!context->initialized) {
status.error = 1; status.error = 1;
return status; return status;
} }