1 /* SPDX-License-Identifier: GPL-2.0-or-later */
4 * Copyright (C) 2020 by Nuvoton Technology Corporation
5 * Mulin Chao <mlchao@nuvoton.com>
6 * Wealian Liao <WHLIAO@nuvoton.com>
11 #include "npcx_flash.h"
13 /*----------------------------------------------------------------------------
15 *----------------------------------------------------------------------------*/
16 static void flash_execute_cmd(uint8_t code, uint8_t cts)
20 /* Execute UMA flash transaction by CTS setting */
22 /* Wait for transaction completed */
23 while (NPCX_IS_BIT_SET(NPCX_UMA_CTS, NPCX_UMA_CTS_EXEC_DONE))
27 static void flash_cs_level(uint8_t level)
29 /* Program chip select pin to high/low level */
31 NPCX_SET_BIT(NPCX_UMA_ECTS, NPCX_UMA_ECTS_SW_CS1);
33 NPCX_CLEAR_BIT(NPCX_UMA_ECTS, NPCX_UMA_ECTS_SW_CS1);
36 static void flash_set_address(uint32_t dest_addr)
38 uint8_t *addr = (uint8_t *)&dest_addr;
40 /* Set target flash address */
41 NPCX_UMA_AB2 = addr[2];
42 NPCX_UMA_AB1 = addr[1];
43 NPCX_UMA_AB0 = addr[0];
46 void delay(uint32_t i)
52 static int flash_wait_ready(uint32_t timeout)
54 /* Chip Select down. -- Burst mode */
57 /* Command for Read status register */
58 flash_execute_cmd(NPCX_CMD_READ_STATUS_REG, NPCX_MASK_CMD_ONLY);
60 /* Read status register */
61 NPCX_UMA_CTS = NPCX_MASK_RD_1BYTE;
62 while (NPCX_IS_BIT_SET(NPCX_UMA_CTS, NPCX_UMA_CTS_EXEC_DONE))
65 if (!(NPCX_UMA_DB0 & NPCX_SPI_FLASH_SR1_BUSY))
71 }; /* Wait for Busy clear */
73 /* Chip Select high. */
77 return NPCX_FLASH_STATUS_FAILED_TIMEOUT;
79 return NPCX_FLASH_STATUS_OK;
82 static int flash_write_enable(void)
84 /* Write enable command */
85 flash_execute_cmd(NPCX_CMD_WRITE_EN, NPCX_MASK_CMD_ONLY);
87 /* Wait for flash is not busy */
88 int status = flash_wait_ready(NPCX_FLASH_ABORT_TIMEOUT);
89 if (status != NPCX_FLASH_STATUS_OK)
92 if (NPCX_UMA_DB0 & NPCX_SPI_FLASH_SR1_WEL)
93 return NPCX_FLASH_STATUS_OK;
95 return NPCX_FLASH_STATUS_FAILED;
98 static void flash_burst_write(uint32_t dest_addr, uint16_t bytes,
101 /* Chip Select down -- Burst mode */
104 /* Set write address */
105 flash_set_address(dest_addr);
106 /* Start programming */
107 flash_execute_cmd(NPCX_CMD_FLASH_PROGRAM, NPCX_MASK_CMD_WR_ADR);
108 for (uint32_t i = 0; i < bytes; i++) {
109 flash_execute_cmd(*data, NPCX_MASK_CMD_WR_ONLY);
117 /* The data to write cannot cross 256 Bytes boundary */
118 static int flash_program_write(uint32_t addr, uint32_t size,
121 int status = flash_write_enable();
122 if (status != NPCX_FLASH_STATUS_OK)
125 flash_burst_write(addr, size, data);
126 return flash_wait_ready(NPCX_FLASH_ABORT_TIMEOUT);
129 int flash_physical_write(uint32_t offset, uint32_t size, const uint8_t *data)
132 uint32_t trunk_start = (offset + 0xff) & ~0xff;
135 uint32_t dest_addr = offset;
136 uint32_t write_len = ((trunk_start - offset) > size) ? size : (trunk_start - offset);
139 status = flash_program_write(dest_addr, write_len, data);
140 if (status != NPCX_FLASH_STATUS_OK)
145 dest_addr = trunk_start;
148 /* write remaining data*/
150 write_len = (size > NPCX_FLASH_WRITE_SIZE) ?
151 NPCX_FLASH_WRITE_SIZE : size;
153 status = flash_program_write(dest_addr, write_len, data);
154 if (status != NPCX_FLASH_STATUS_OK)
158 dest_addr += write_len;
162 return NPCX_FLASH_STATUS_OK;
165 int flash_physical_erase(uint32_t offset, uint32_t size)
167 /* Alignment has been checked in upper layer */
168 for (; size > 0; size -= NPCX_FLASH_ERASE_SIZE,
169 offset += NPCX_FLASH_ERASE_SIZE) {
171 int status = flash_write_enable();
172 if (status != NPCX_FLASH_STATUS_OK)
175 /* Set erase address */
176 flash_set_address(offset);
178 flash_execute_cmd(NPCX_CMD_SECTOR_ERASE, NPCX_MASK_CMD_ADR);
179 /* Wait erase completed */
180 status = flash_wait_ready(NPCX_FLASH_ABORT_TIMEOUT);
181 if (status != NPCX_FLASH_STATUS_OK)
185 return NPCX_FLASH_STATUS_OK;
188 int flash_physical_erase_all(void)
191 int status = flash_write_enable();
192 if (status != NPCX_FLASH_STATUS_OK)
196 flash_execute_cmd(NPCX_CMD_CHIP_ERASE, NPCX_MASK_CMD_ONLY);
198 /* Wait erase completed */
199 status = flash_wait_ready(NPCX_FLASH_ABORT_TIMEOUT);
200 if (status != NPCX_FLASH_STATUS_OK)
203 return NPCX_FLASH_STATUS_OK;
206 int flash_physical_clear_stsreg(void)
209 int status = flash_write_enable();
210 if (status != NPCX_FLASH_STATUS_OK)
216 /* Write status register 1/2 */
217 flash_execute_cmd(NPCX_CMD_WRITE_STATUS_REG, NPCX_MASK_CMD_WR_2BYTE);
219 /* Wait writing completed */
220 status = flash_wait_ready(NPCX_FLASH_ABORT_TIMEOUT);
221 if (status != NPCX_FLASH_STATUS_OK)
224 /* Read status register 1/2 for checking */
225 flash_execute_cmd(NPCX_CMD_READ_STATUS_REG, NPCX_MASK_CMD_RD_1BYTE);
226 if (NPCX_UMA_DB0 != 0x00)
227 return NPCX_FLASH_STATUS_FAILED;
228 flash_execute_cmd(NPCX_CMD_READ_STATUS_REG2, NPCX_MASK_CMD_RD_1BYTE);
229 if (NPCX_UMA_DB0 != 0x00)
230 return NPCX_FLASH_STATUS_FAILED;
232 return NPCX_FLASH_STATUS_OK;
235 int flash_get_id(uint32_t *id)
237 flash_execute_cmd(NPCX_CMD_READ_ID, NPCX_MASK_CMD_RD_3BYTE);
238 *id = NPCX_UMA_DB0 << 16 | NPCX_UMA_DB1 << 8 | NPCX_UMA_DB2;
240 return NPCX_FLASH_STATUS_OK;
243 /*----------------------------------------------------------------------------
244 * flash loader function
245 *----------------------------------------------------------------------------*/
246 uint32_t flashloader_init(struct npcx_flash_params *params)
248 /* Initialize params buffers */
249 memset(params, 0, sizeof(struct npcx_flash_params));
251 return NPCX_FLASH_STATUS_OK;
254 /*----------------------------------------------------------------------------
256 *----------------------------------------------------------------------------*/
257 /* flashloader parameter structure */
258 __attribute__ ((section(".buffers.g_cfg")))
259 volatile struct npcx_flash_params g_cfg;
261 __attribute__ ((section(".buffers.g_buf")))
262 uint8_t g_buf[NPCX_FLASH_LOADER_BUFFER_SIZE];
269 flashloader_init((struct npcx_flash_params *)&g_cfg);
271 /* Avoid F_CS0 toggles while programming the internal flash. */
272 NPCX_SET_BIT(NPCX_DEVALT(0), NPCX_DEVALT0_NO_F_SPI);
274 /* clear flash status registers */
275 int status = flash_physical_clear_stsreg();
276 if (status != NPCX_FLASH_STATUS_OK) {
283 while (g_cfg.sync == NPCX_FLASH_LOADER_WAIT)
286 /* command handler */
288 case NPCX_FLASH_CMD_GET_FLASH_ID:
289 status = flash_get_id(&id);
290 if (status == NPCX_FLASH_STATUS_OK) {
291 g_buf[0] = id & 0xff;
292 g_buf[1] = (id >> 8) & 0xff;
293 g_buf[2] = (id >> 16) & 0xff;
297 case NPCX_FLASH_CMD_ERASE_SECTORS:
298 status = flash_physical_erase(g_cfg.addr, g_cfg.len);
300 case NPCX_FLASH_CMD_ERASE_ALL:
301 status = flash_physical_erase_all();
303 case NPCX_FLASH_CMD_PROGRAM:
304 status = flash_physical_write(g_cfg.addr,
309 status = NPCX_FLASH_STATUS_FAILED_UNKNOWN_COMMAND;
313 /* clear & set result for next command */
314 if (status != NPCX_FLASH_STATUS_OK) {
319 g_cfg.sync = NPCX_FLASH_LOADER_WAIT;
326 __attribute__ ((section(".stack")))
327 __attribute__ ((used))
328 static uint32_t stack[NPCX_FLASH_LOADER_STACK_SIZE / 4];
329 extern uint32_t _estack;
330 extern uint32_t _bss;
331 extern uint32_t _ebss;
333 __attribute__ ((section(".entry")))
336 /* set sp from end of stack */
337 __asm(" ldr sp, =_estack - 4");
341 __asm(" bkpt #0x00");