blob: f6d003133ebdd140724a9ef4ffd5d97eafee7763 [file] [log] [blame]
/*
* Copyright (c) 2018, Arm Limited. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <assert.h>
#include <io_storage.h>
#include <platform.h>
#include <platform_def.h>
#include <spinlock.h>
#include <status.h>
#include <string.h>
#include <tftf_lib.h>
#if USE_NVM
/* Used to serialize write operations from different CPU's */
static spinlock_t flash_access_lock;
#endif
STATUS tftf_nvm_write(unsigned long long offset, const void *buffer, size_t size)
{
#if USE_NVM
int ret;
uintptr_t nvm_handle;
size_t length_written;
#endif
if (offset + size > TFTF_NVM_SIZE)
return STATUS_OUT_OF_RESOURCES;
#if USE_NVM
/* Obtain a handle to the NVM by querying the platfom layer */
plat_get_nvm_handle(&nvm_handle);
spin_lock(&flash_access_lock);
ret = io_seek(nvm_handle, IO_SEEK_SET,
offset + TFTF_NVM_OFFSET);
if (ret != IO_SUCCESS)
goto fail;
ret = io_write(nvm_handle, (const uintptr_t)buffer, size,
&length_written);
if (ret != IO_SUCCESS)
goto fail;
assert(length_written == size);
fail:
spin_unlock(&flash_access_lock);
if (ret != IO_SUCCESS)
return STATUS_FAIL;
#else
uintptr_t addr = DRAM_BASE + TFTF_NVM_OFFSET + offset;
memcpy((void *)addr, buffer, size);
#endif
return STATUS_SUCCESS;
}
STATUS tftf_nvm_read(unsigned long long offset, void *buffer, size_t size)
{
#if USE_NVM
int ret;
uintptr_t nvm_handle;
size_t length_read;
#endif
if (offset + size > TFTF_NVM_SIZE)
return STATUS_OUT_OF_RESOURCES;
#if USE_NVM
/* Obtain a handle to the NVM by querying the platfom layer */
plat_get_nvm_handle(&nvm_handle);
spin_lock(&flash_access_lock);
ret = io_seek(nvm_handle, IO_SEEK_SET, TFTF_NVM_OFFSET + offset);
if (ret != IO_SUCCESS)
goto fail;
ret = io_read(nvm_handle, (uintptr_t)buffer, size, &length_read);
if (ret != IO_SUCCESS)
goto fail;
assert(length_read == size);
fail:
spin_unlock(&flash_access_lock);
if (ret != IO_SUCCESS)
return STATUS_FAIL;
#else
uintptr_t addr = DRAM_BASE + TFTF_NVM_OFFSET + offset;
memcpy(buffer, (void *)addr, size);
#endif
return STATUS_SUCCESS;
}