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>
7 * Luca Hung <YCHUNG0@nuvoton.com>
15 #include <helper/binarybuffer.h>
16 #include <helper/time_support.h>
17 #include <target/armv7m.h>
18 #include "../../../contrib/loaders/flash/npcx/npcx_flash.h"
20 /* NPCX flash loader */
21 static const uint8_t npcx_algo
[] = {
22 #include "../../../contrib/loaders/flash/npcx/npcx_algo.inc"
25 #define NPCX_FLASH_TIMEOUT_MS 8000
28 enum npcx_flash_device_index
{
35 struct npcx_flash_bank
{
36 uint32_t sector_length
;
38 enum npcx_flash_device_index flash
;
39 struct working_area
*working_area
;
40 struct armv7m_algorithm armv7m_info
;
41 const uint8_t *algo_code
;
43 uint32_t algo_working_size
;
49 struct npcx_flash_info
{
55 static const struct npcx_flash_info flash_info
[] = {
56 [NPCX_FLASH_256KB
] = {
57 .name
= "256KB Flash",
61 [NPCX_FLASH_512KB
] = {
62 .name
= "512KB Flash",
71 [NPCX_FLASH_UNKNOWN
] = {
72 .name
= "Unknown Flash",
77 static int npcx_init(struct flash_bank
*bank
)
79 struct target
*target
= bank
->target
;
80 struct npcx_flash_bank
*npcx_bank
= bank
->driver_priv
;
82 /* Check for working area to use for flash helper algorithm */
83 target_free_working_area(target
, npcx_bank
->working_area
);
84 npcx_bank
->working_area
= NULL
;
86 int retval
= target_alloc_working_area(target
, npcx_bank
->algo_working_size
,
87 &npcx_bank
->working_area
);
88 if (retval
!= ERROR_OK
)
91 /* Confirm the defined working address is the area we need to use */
92 if (npcx_bank
->working_area
->address
!= NPCX_FLASH_LOADER_WORKING_ADDR
) {
93 LOG_TARGET_ERROR(target
, "Invalid working address");
94 LOG_INFO("Hint: Use '-work-area-phys 0x%" PRIx32
"' in your target configuration",
95 NPCX_FLASH_LOADER_WORKING_ADDR
);
96 target_free_working_area(target
, npcx_bank
->working_area
);
97 npcx_bank
->working_area
= NULL
;
98 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE
;
101 /* Write flash helper algorithm into target memory */
102 retval
= target_write_buffer(target
, NPCX_FLASH_LOADER_PROGRAM_ADDR
,
103 npcx_bank
->algo_size
, npcx_bank
->algo_code
);
104 if (retval
!= ERROR_OK
) {
105 LOG_TARGET_ERROR(target
, "Failed to load flash helper algorithm");
106 target_free_working_area(target
, npcx_bank
->working_area
);
107 npcx_bank
->working_area
= NULL
;
111 /* Initialize the ARMv7 specific info to run the algorithm */
112 npcx_bank
->armv7m_info
.common_magic
= ARMV7M_COMMON_MAGIC
;
113 npcx_bank
->armv7m_info
.core_mode
= ARM_MODE_THREAD
;
115 /* Begin executing the flash helper algorithm */
116 retval
= target_start_algorithm(target
, 0, NULL
, 0, NULL
,
117 NPCX_FLASH_LOADER_PROGRAM_ADDR
, 0,
118 &npcx_bank
->armv7m_info
);
119 if (retval
!= ERROR_OK
) {
120 LOG_TARGET_ERROR(target
, "Failed to start flash helper algorithm");
121 target_free_working_area(target
, npcx_bank
->working_area
);
122 npcx_bank
->working_area
= NULL
;
127 * At this point, the algorithm is running on the target and
128 * ready to receive commands and data to flash the target
134 static int npcx_quit(struct flash_bank
*bank
)
136 struct target
*target
= bank
->target
;
137 struct npcx_flash_bank
*npcx_bank
= bank
->driver_priv
;
139 /* Regardless of the algo's status, attempt to halt the target */
140 (void)target_halt(target
);
142 /* Now confirm target halted and clean up from flash helper algorithm */
143 int retval
= target_wait_algorithm(target
, 0, NULL
, 0, NULL
, 0,
144 NPCX_FLASH_TIMEOUT_MS
, &npcx_bank
->armv7m_info
);
146 target_free_working_area(target
, npcx_bank
->working_area
);
147 npcx_bank
->working_area
= NULL
;
152 static int npcx_wait_algo_done(struct flash_bank
*bank
, uint32_t params_addr
)
154 struct target
*target
= bank
->target
;
155 uint32_t status_addr
= params_addr
+ offsetof(struct npcx_flash_params
, sync
);
157 int64_t start_ms
= timeval_ms();
160 int retval
= target_read_u32(target
, status_addr
, &status
);
161 if (retval
!= ERROR_OK
)
166 int64_t elapsed_ms
= timeval_ms() - start_ms
;
167 if (elapsed_ms
> NPCX_FLASH_TIMEOUT_MS
)
169 } while (status
== NPCX_FLASH_LOADER_EXECUTE
);
171 if (status
!= NPCX_FLASH_LOADER_WAIT
) {
172 LOG_TARGET_ERROR(target
, "Flash operation failed, status (%0x" PRIX32
") ", status
);
179 static enum npcx_flash_device_index
npcx_get_flash_id(struct flash_bank
*bank
, uint32_t *flash_id
)
181 struct target
*target
= bank
->target
;
182 struct npcx_flash_bank
*npcx_bank
= bank
->driver_priv
;
183 struct npcx_flash_params algo_params
;
185 if (target
->state
!= TARGET_HALTED
) {
186 LOG_ERROR("Target not halted");
187 return ERROR_TARGET_NOT_HALTED
;
190 int retval
= npcx_init(bank
);
191 if (retval
!= ERROR_OK
)
194 /* Set up algorithm parameters for get flash ID command */
195 target_buffer_set_u32(target
, (uint8_t *)&algo_params
.fiu_ver
, npcx_bank
->fiu_ver
);
196 target_buffer_set_u32(target
, (uint8_t *)&algo_params
.cmd
, NPCX_FLASH_CMD_GET_FLASH_ID
);
197 target_buffer_set_u32(target
, (uint8_t *)&algo_params
.sync
, NPCX_FLASH_LOADER_WAIT
);
199 /* Issue flash helper algorithm parameters for get flash ID */
200 retval
= target_write_buffer(target
, npcx_bank
->params_addr
,
201 sizeof(algo_params
), (uint8_t *)&algo_params
);
202 if (retval
!= ERROR_OK
) {
203 (void)npcx_quit(bank
);
207 target_buffer_set_u32(target
, (uint8_t *)&algo_params
.sync
, NPCX_FLASH_LOADER_EXECUTE
);
208 retval
= target_write_buffer(target
, npcx_bank
->params_addr
,
209 sizeof(algo_params
), (uint8_t *)&algo_params
);
211 /* If no error, wait for finishing */
212 if (retval
== ERROR_OK
) {
213 retval
= npcx_wait_algo_done(bank
, npcx_bank
->params_addr
);
214 if (retval
== ERROR_OK
)
215 target_read_u32(target
, NPCX_FLASH_LOADER_BUFFER_ADDR
, flash_id
);
218 /* Regardless of errors, try to close down algo */
219 (void)npcx_quit(bank
);
224 static int npcx_get_flash(uint32_t flash_id
)
226 for (uint32_t i
= 0; i
< ARRAY_SIZE(flash_info
) - 1; i
++) {
227 if (flash_info
[i
].id
== flash_id
)
231 return NPCX_FLASH_UNKNOWN
;
234 static int npcx_probe(struct flash_bank
*bank
)
236 struct npcx_flash_bank
*npcx_bank
= bank
->driver_priv
;
237 uint32_t sector_length
= NPCX_FLASH_ERASE_SIZE
;
240 /* Set up appropriate flash helper algorithm */
241 npcx_bank
->algo_code
= npcx_algo
;
242 npcx_bank
->algo_size
= sizeof(npcx_algo
);
243 npcx_bank
->algo_working_size
= NPCX_FLASH_LOADER_PARAMS_SIZE
+
244 NPCX_FLASH_LOADER_BUFFER_SIZE
+
245 NPCX_FLASH_LOADER_PROGRAM_SIZE
;
246 npcx_bank
->buffer_addr
= NPCX_FLASH_LOADER_BUFFER_ADDR
;
247 npcx_bank
->params_addr
= NPCX_FLASH_LOADER_PARAMS_ADDR
;
250 int retval
= npcx_get_flash_id(bank
, &flash_id
);
251 if (retval
!= ERROR_OK
)
254 npcx_bank
->flash
= npcx_get_flash(flash_id
);
256 unsigned int num_sectors
= flash_info
[npcx_bank
->flash
].size
/ sector_length
;
258 bank
->sectors
= calloc(num_sectors
, sizeof(struct flash_sector
));
259 if (!bank
->sectors
) {
260 LOG_ERROR("Out of memory");
264 bank
->num_sectors
= num_sectors
;
265 bank
->size
= num_sectors
* sector_length
;
266 bank
->write_start_alignment
= 0;
267 bank
->write_end_alignment
= 0;
268 npcx_bank
->sector_length
= sector_length
;
270 for (unsigned int i
= 0; i
< num_sectors
; i
++) {
271 bank
->sectors
[i
].offset
= i
* sector_length
;
272 bank
->sectors
[i
].size
= sector_length
;
273 bank
->sectors
[i
].is_erased
= -1;
274 bank
->sectors
[i
].is_protected
= 0;
277 /* We've successfully determined the stats on the flash bank */
278 npcx_bank
->probed
= true;
280 /* If we fall through to here, then all went well */
284 static int npcx_auto_probe(struct flash_bank
*bank
)
286 struct npcx_flash_bank
*npcx_bank
= bank
->driver_priv
;
287 int retval
= ERROR_OK
;
289 if (!npcx_bank
->probed
)
290 retval
= npcx_probe(bank
);
295 FLASH_BANK_COMMAND_HANDLER(npcx_flash_bank_command
)
297 struct npcx_flash_bank
*npcx_bank
;
299 if (CMD_ARGC
< 6 || CMD_ARGC
> 7)
300 return ERROR_COMMAND_SYNTAX_ERROR
;
302 npcx_bank
= calloc(1, sizeof(struct npcx_flash_bank
));
304 LOG_ERROR("Out of memory");
310 LOG_WARNING("No FIU is selection, using default.");
311 npcx_bank
->fiu_ver
= NPCX_FIU_NPCX
;
316 if (strcmp(fiu
, "npcx.fiu") == 0) {
317 npcx_bank
->fiu_ver
= NPCX_FIU_NPCX
;
318 } else if (strcmp(fiu
, "npcx_v2.fiu") == 0) {
319 npcx_bank
->fiu_ver
= NPCX_FIU_NPCX_V2
;
320 } else if (strcmp(fiu
, "npck.fiu") == 0) {
321 npcx_bank
->fiu_ver
= NPCX_FIU_NPCK
;
323 LOG_ERROR("%s is not a valid fiu", fiu
);
325 return ERROR_TARGET_INVALID
;
329 /* Initialize private flash information */
330 npcx_bank
->sector_length
= NPCX_FLASH_ERASE_SIZE
;
332 /* Finish initialization of bank */
333 bank
->driver_priv
= npcx_bank
;
339 static int npcx_chip_erase(struct flash_bank
*bank
)
341 struct target
*target
= bank
->target
;
342 struct npcx_flash_bank
*npcx_bank
= bank
->driver_priv
;
343 struct npcx_flash_params algo_params
;
345 if (target
->state
!= TARGET_HALTED
) {
346 LOG_ERROR("Target not halted");
347 return ERROR_TARGET_NOT_HALTED
;
350 /* Make sure we've probed the flash to get the device and size */
351 int retval
= npcx_auto_probe(bank
);
352 if (retval
!= ERROR_OK
)
355 retval
= npcx_init(bank
);
356 if (retval
!= ERROR_OK
)
359 /* Set up algorithm parameters for chip erase command */
360 target_buffer_set_u32(target
, (uint8_t *)&algo_params
.fiu_ver
, npcx_bank
->fiu_ver
);
361 target_buffer_set_u32(target
, (uint8_t *)&algo_params
.cmd
, NPCX_FLASH_CMD_ERASE_ALL
);
362 target_buffer_set_u32(target
, (uint8_t *)&algo_params
.sync
, NPCX_FLASH_LOADER_WAIT
);
364 /* Set algorithm parameters */
365 retval
= target_write_buffer(target
, npcx_bank
->params_addr
,
366 sizeof(algo_params
), (uint8_t *)&algo_params
);
367 if (retval
!= ERROR_OK
) {
368 (void)npcx_quit(bank
);
372 /* Issue flash helper algorithm parameters for chip erase */
373 target_buffer_set_u32(target
, (uint8_t *)&algo_params
.sync
, NPCX_FLASH_LOADER_EXECUTE
);
374 retval
= target_write_buffer(target
, npcx_bank
->params_addr
,
375 sizeof(algo_params
), (uint8_t *)&algo_params
);
377 /* If no error, wait for chip erase finish */
378 if (retval
== ERROR_OK
)
379 retval
= npcx_wait_algo_done(bank
, npcx_bank
->params_addr
);
381 /* Regardless of errors, try to close down algo */
382 (void)npcx_quit(bank
);
387 static int npcx_erase(struct flash_bank
*bank
, unsigned int first
,
390 struct target
*target
= bank
->target
;
391 struct npcx_flash_bank
*npcx_bank
= bank
->driver_priv
;
392 struct npcx_flash_params algo_params
;
394 if (target
->state
!= TARGET_HALTED
) {
395 LOG_ERROR("Target not halted");
396 return ERROR_TARGET_NOT_HALTED
;
399 if ((first
== 0) && (last
== (bank
->num_sectors
- 1))) {
400 /* Request chip erase */
401 return npcx_chip_erase(bank
);
404 uint32_t address
= first
* npcx_bank
->sector_length
;
405 uint32_t length
= (last
- first
+ 1) * npcx_bank
->sector_length
;
407 /* Make sure we've probed the flash to get the device and size */
408 int retval
= npcx_auto_probe(bank
);
409 if (retval
!= ERROR_OK
)
412 retval
= npcx_init(bank
);
413 if (retval
!= ERROR_OK
)
416 /* Set up algorithm parameters for erase command */
417 target_buffer_set_u32(target
, (uint8_t *)&algo_params
.fiu_ver
, npcx_bank
->fiu_ver
);
418 target_buffer_set_u32(target
, (uint8_t *)&algo_params
.addr
, address
);
419 target_buffer_set_u32(target
, (uint8_t *)&algo_params
.len
, length
);
420 target_buffer_set_u32(target
, (uint8_t *)&algo_params
.cmd
, NPCX_FLASH_CMD_ERASE_SECTORS
);
421 target_buffer_set_u32(target
, (uint8_t *)&algo_params
.sync
, NPCX_FLASH_LOADER_WAIT
);
423 /* Set algorithm parameters */
424 retval
= target_write_buffer(target
, npcx_bank
->params_addr
,
425 sizeof(algo_params
), (uint8_t *)&algo_params
);
426 if (retval
!= ERROR_OK
) {
427 (void)npcx_quit(bank
);
431 /* Issue flash helper algorithm parameters for erase */
432 target_buffer_set_u32(target
, (uint8_t *)&algo_params
.sync
, NPCX_FLASH_LOADER_EXECUTE
);
433 retval
= target_write_buffer(target
, npcx_bank
->params_addr
,
434 sizeof(algo_params
), (uint8_t *)&algo_params
);
436 /* If no error, wait for erase to finish */
437 if (retval
== ERROR_OK
)
438 retval
= npcx_wait_algo_done(bank
, npcx_bank
->params_addr
);
440 /* Regardless of errors, try to close down algo */
441 (void)npcx_quit(bank
);
446 static int npcx_write(struct flash_bank
*bank
, const uint8_t *buffer
,
447 uint32_t offset
, uint32_t count
)
449 struct target
*target
= bank
->target
;
450 struct npcx_flash_bank
*npcx_bank
= bank
->driver_priv
;
451 struct npcx_flash_params algo_params
;
453 if (target
->state
!= TARGET_HALTED
) {
454 LOG_ERROR("Target not halted");
455 return ERROR_TARGET_NOT_HALTED
;
458 /* Make sure we've probed the flash to get the device and size */
459 int retval
= npcx_auto_probe(bank
);
460 if (retval
!= ERROR_OK
)
463 retval
= npcx_init(bank
);
464 if (retval
!= ERROR_OK
)
467 /* Initialize algorithm parameters to default values */
468 target_buffer_set_u32(target
, (uint8_t *)&algo_params
.cmd
, NPCX_FLASH_CMD_PROGRAM
);
470 uint32_t address
= offset
;
473 uint32_t size
= (count
> NPCX_FLASH_LOADER_BUFFER_SIZE
) ?
474 NPCX_FLASH_LOADER_BUFFER_SIZE
: count
;
476 /* Put the data into buffer */
477 retval
= target_write_buffer(target
, npcx_bank
->buffer_addr
,
479 if (retval
!= ERROR_OK
) {
480 LOG_ERROR("Unable to write data to target memory");
484 /* Update algo parameters for flash write */
485 target_buffer_set_u32(target
, (uint8_t *)&algo_params
.fiu_ver
, npcx_bank
->fiu_ver
);
486 target_buffer_set_u32(target
, (uint8_t *)&algo_params
.addr
, address
);
487 target_buffer_set_u32(target
, (uint8_t *)&algo_params
.len
, size
);
488 target_buffer_set_u32(target
, (uint8_t *)&algo_params
.sync
, NPCX_FLASH_LOADER_WAIT
);
490 /* Set algorithm parameters */
491 retval
= target_write_buffer(target
, npcx_bank
->params_addr
,
492 sizeof(algo_params
), (uint8_t *)&algo_params
);
493 if (retval
!= ERROR_OK
)
496 /* Issue flash helper algorithm parameters for flash write */
497 target_buffer_set_u32(target
, (uint8_t *)&algo_params
.sync
, NPCX_FLASH_LOADER_EXECUTE
);
498 retval
= target_write_buffer(target
, npcx_bank
->params_addr
,
499 sizeof(algo_params
), (uint8_t *)&algo_params
);
500 if (retval
!= ERROR_OK
)
503 /* Wait for flash write finish */
504 retval
= npcx_wait_algo_done(bank
, npcx_bank
->params_addr
);
505 if (retval
!= ERROR_OK
)
513 /* Regardless of errors, try to close down algo */
514 (void)npcx_quit(bank
);
519 static int npcx_info(struct flash_bank
*bank
, struct command_invocation
*cmd
)
521 struct npcx_flash_bank
*npcx_bank
= bank
->driver_priv
;
523 command_print_sameline(cmd
, "%s flash: %s\n",
524 target_name(bank
->target
),
525 flash_info
[npcx_bank
->flash
].name
);
530 const struct flash_driver npcx_flash
= {
532 .flash_bank_command
= npcx_flash_bank_command
,
535 .read
= default_flash_read
,
537 .auto_probe
= npcx_auto_probe
,
538 .erase_check
= default_flash_blank_check
,
540 .free_driver_priv
= default_flash_free_driver_priv
,
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)