norflash: clean-up norflash.c
- Add comments to all the functions
- Simplify nor_poll_dws
- Simplify nor_word_program
Change-Id: I29c0199d2908a4fceb1ac3430fcfdd699be22bb3
Signed-off-by: Roberto Vargas <roberto.vargas@arm.com>
diff --git a/plat/arm/board/common/drivers/norflash/norflash.c b/plat/arm/board/common/drivers/norflash/norflash.c
index cc63d75..053696e 100644
--- a/plat/arm/board/common/drivers/norflash/norflash.c
+++ b/plat/arm/board/common/drivers/norflash/norflash.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2015-2017, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -8,6 +8,14 @@
#include <mmio.h>
#include <norflash.h>
+/*
+ * This file supplies a low level interface to the vexpress NOR flash
+ * memory of juno and fvp. This memory is organized as an interleaved
+ * memory of two chips with a 16 bit word. It means that every 32 bit
+ * access is going to access to two different chips. This is very
+ * important when we send commands or read status of the chips
+ */
+
/* Helper macros to access two flash banks in parallel */
#define NOR_2X16(d) ((d << 16) | (d & 0xffff))
@@ -18,6 +26,9 @@
*/
#define DWS_WORD_PROGRAM_RETRIES 1000
+/* Helper macro to detect end of command */
+#define NOR_CMD_END (NOR_DWS | NOR_DWS << 16l)
+
/*
* Poll Write State Machine. Return values:
* 0 = WSM ready
@@ -25,24 +36,16 @@
*/
static int nor_poll_dws(uintptr_t base_addr, unsigned int retries)
{
- uint32_t status;
- int ret;
+ unsigned long status;
- for (;;) {
+ do {
nor_send_cmd(base_addr, NOR_CMD_READ_STATUS_REG);
status = mmio_read_32(base_addr);
- if ((status & NOR_DWS) &&
- (status & (NOR_DWS << 16))) {
- ret = 0;
- break;
- }
- if (retries-- == 0) {
- ret = -EBUSY;
- break;
- }
- }
+ if ((status & NOR_CMD_END) == NOR_CMD_END)
+ return 0;
+ } while (retries-- > 0);
- return ret;
+ return -EBUSY;
}
void nor_send_cmd(uintptr_t base_addr, unsigned long cmd)
@@ -51,6 +54,9 @@
}
/*
+ * This function programs a word in the flash. Be aware that it only
+ * can reset bits that were previously set. It cannot set bits that
+ * were previously reset. The resulting bits = old_bits & new bits.
* Return values:
* 0 = success
* -EBUSY = WSM not ready
@@ -66,24 +72,24 @@
mmio_write_32(base_addr, data);
ret = nor_poll_dws(base_addr, DWS_WORD_PROGRAM_RETRIES);
- if (ret != 0) {
- goto word_program_end;
- }
-
- /* Full status check */
- nor_send_cmd(base_addr, NOR_CMD_READ_STATUS_REG);
- status = mmio_read_32(base_addr);
+ if (ret == 0) {
+ /* Full status check */
+ nor_send_cmd(base_addr, NOR_CMD_READ_STATUS_REG);
+ status = mmio_read_32(base_addr);
- if (status & (NOR_PS | NOR_BLS)) {
- nor_send_cmd(base_addr, NOR_CMD_CLEAR_STATUS_REG);
- ret = -EPERM;
+ if (status & (NOR_PS | NOR_BLS)) {
+ nor_send_cmd(base_addr, NOR_CMD_CLEAR_STATUS_REG);
+ ret = -EPERM;
+ }
}
-word_program_end:
nor_send_cmd(base_addr, NOR_CMD_READ_ARRAY);
return ret;
}
+/*
+ * Lock a full 256 block
+ */
void nor_lock(uintptr_t base_addr)
{
nor_send_cmd(base_addr, NOR_CMD_LOCK_UNLOCK);
@@ -91,10 +97,12 @@
nor_send_cmd(base_addr, NOR_CMD_READ_ARRAY);
}
+/*
+ * unlock a full 256 block
+ */
void nor_unlock(uintptr_t base_addr)
{
nor_send_cmd(base_addr, NOR_CMD_LOCK_UNLOCK);
mmio_write_32(base_addr, NOR_2X16(NOR_UNLOCK_BLOCK));
nor_send_cmd(base_addr, NOR_CMD_READ_ARRAY);
}
-