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");
Linking to existing account procedure
If you already have an account and want to add another login method
you
MUST first sign in with your existing account and
then change URL to read
https://review.openocd.org/login/?link
to get to this page again but this time it'll work for linking. Thank you.
SSH host keys fingerprints
1024 SHA256:YKx8b7u5ZWdcbp7/4AeXNaqElP49m6QrwfXaqQGJAOk gerrit-code-review@openocd.zylin.com (DSA)
384 SHA256:jHIbSQa4REvwCFG4cq5LBlBLxmxSqelQPem/EXIrxjk gerrit-code-review@openocd.org (ECDSA)
521 SHA256:UAOPYkU9Fjtcao0Ul/Rrlnj/OsQvt+pgdYSZ4jOYdgs gerrit-code-review@openocd.org (ECDSA)
256 SHA256:A13M5QlnozFOvTllybRZH6vm7iSt0XLxbA48yfc2yfY gerrit-code-review@openocd.org (ECDSA)
256 SHA256:spYMBqEYoAOtK7yZBrcwE8ZpYt6b68Cfh9yEVetvbXg gerrit-code-review@openocd.org (ED25519)
+--[ED25519 256]--+
|=.. |
|+o.. . |
|*.o . . |
|+B . . . |
|Bo. = o S |
|Oo.+ + = |
|oB=.* = . o |
| =+=.+ + E |
|. .=o . o |
+----[SHA256]-----+
2048 SHA256:0Onrb7/PHjpo6iVZ7xQX2riKN83FJ3KGU0TvI0TaFG4 gerrit-code-review@openocd.zylin.com (RSA)