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>
14 #include <helper/binarybuffer.h>
15 #include <helper/time_support.h>
16 #include <target/armv7m.h>
17 #include "../../../contrib/loaders/flash/npcx/npcx_flash.h"
19 /* NPCX flash loader */
20 const uint8_t npcx_algo
[] = {
21 #include "../../../contrib/loaders/flash/npcx/npcx_algo.inc"
24 #define NPCX_FLASH_TIMEOUT_MS 8000
25 #define NPCX_FLASH_BASE_ADDR 0x64000000
28 enum npcx_flash_device_index
{
35 struct npcx_flash_bank
{
36 const char *family_name
;
37 uint32_t sector_length
;
39 enum npcx_flash_device_index flash
;
40 struct working_area
*working_area
;
41 struct armv7m_algorithm armv7m_info
;
42 const uint8_t *algo_code
;
44 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 if (npcx_bank
->working_area
) {
84 target_free_working_area(target
, npcx_bank
->working_area
);
85 npcx_bank
->working_area
= NULL
;
88 int retval
= target_alloc_working_area(target
, npcx_bank
->algo_working_size
,
89 &npcx_bank
->working_area
);
90 if (retval
!= ERROR_OK
)
93 /* Confirm the defined working address is the area we need to use */
94 if (npcx_bank
->working_area
->address
!= NPCX_FLASH_LOADER_WORKING_ADDR
) {
95 LOG_ERROR("%s: Invalid working address", npcx_bank
->family_name
);
96 LOG_INFO("Hint: Use '-work-area-phys 0x%" PRIx32
"' in your target configuration",
97 NPCX_FLASH_LOADER_WORKING_ADDR
);
98 target_free_working_area(target
, npcx_bank
->working_area
);
99 npcx_bank
->working_area
= NULL
;
100 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE
;
103 /* Write flash helper algorithm into target memory */
104 retval
= target_write_buffer(target
, NPCX_FLASH_LOADER_PROGRAM_ADDR
,
105 npcx_bank
->algo_size
, npcx_bank
->algo_code
);
106 if (retval
!= ERROR_OK
) {
107 LOG_ERROR("%s: Failed to load flash helper algorithm",
108 npcx_bank
->family_name
);
109 target_free_working_area(target
, npcx_bank
->working_area
);
110 npcx_bank
->working_area
= NULL
;
114 /* Initialize the ARMv7 specific info to run the algorithm */
115 npcx_bank
->armv7m_info
.common_magic
= ARMV7M_COMMON_MAGIC
;
116 npcx_bank
->armv7m_info
.core_mode
= ARM_MODE_THREAD
;
118 /* Begin executing the flash helper algorithm */
119 retval
= target_start_algorithm(target
, 0, NULL
, 0, NULL
,
120 NPCX_FLASH_LOADER_PROGRAM_ADDR
, 0,
121 &npcx_bank
->armv7m_info
);
122 if (retval
!= ERROR_OK
) {
123 LOG_ERROR("%s: Failed to start flash helper algorithm",
124 npcx_bank
->family_name
);
125 target_free_working_area(target
, npcx_bank
->working_area
);
126 npcx_bank
->working_area
= NULL
;
131 * At this point, the algorithm is running on the target and
132 * ready to receive commands and data to flash the target
138 static int npcx_quit(struct flash_bank
*bank
)
140 struct target
*target
= bank
->target
;
141 struct npcx_flash_bank
*npcx_bank
= bank
->driver_priv
;
143 /* Regardless of the algo's status, attempt to halt the target */
144 (void)target_halt(target
);
146 /* Now confirm target halted and clean up from flash helper algorithm */
147 int retval
= target_wait_algorithm(target
, 0, NULL
, 0, NULL
, 0,
148 NPCX_FLASH_TIMEOUT_MS
, &npcx_bank
->armv7m_info
);
150 target_free_working_area(target
, npcx_bank
->working_area
);
151 npcx_bank
->working_area
= NULL
;
156 static int npcx_wait_algo_done(struct flash_bank
*bank
, uint32_t params_addr
)
158 struct target
*target
= bank
->target
;
159 struct npcx_flash_bank
*npcx_bank
= bank
->driver_priv
;
160 uint32_t status_addr
= params_addr
+ offsetof(struct npcx_flash_params
, sync
);
162 int64_t start_ms
= timeval_ms();
165 int retval
= target_read_u32(target
, status_addr
, &status
);
166 if (retval
!= ERROR_OK
)
171 int64_t elapsed_ms
= timeval_ms() - start_ms
;
172 if (elapsed_ms
> NPCX_FLASH_TIMEOUT_MS
)
174 } while (status
== NPCX_FLASH_LOADER_EXECUTE
);
176 if (status
!= NPCX_FLASH_LOADER_WAIT
) {
177 LOG_ERROR("%s: Flash operation failed, status=0x%" PRIx32
,
178 npcx_bank
->family_name
,
186 static enum npcx_flash_device_index
npcx_get_flash_id(struct flash_bank
*bank
, uint32_t *flash_id
)
188 struct target
*target
= bank
->target
;
189 struct npcx_flash_bank
*npcx_bank
= bank
->driver_priv
;
190 struct npcx_flash_params algo_params
;
192 if (target
->state
!= TARGET_HALTED
) {
193 LOG_ERROR("Target not halted");
194 return ERROR_TARGET_NOT_HALTED
;
197 int retval
= npcx_init(bank
);
198 if (retval
!= ERROR_OK
)
201 /* Set up algorithm parameters for get flash ID command */
202 target_buffer_set_u32(target
, (uint8_t *)&algo_params
.cmd
, NPCX_FLASH_CMD_GET_FLASH_ID
);
203 target_buffer_set_u32(target
, (uint8_t *)&algo_params
.sync
, NPCX_FLASH_LOADER_WAIT
);
205 /* Issue flash helper algorithm parameters for get flash ID */
206 retval
= target_write_buffer(target
, npcx_bank
->params_addr
,
207 sizeof(algo_params
), (uint8_t *)&algo_params
);
208 if (retval
!= ERROR_OK
) {
209 (void)npcx_quit(bank
);
213 target_buffer_set_u32(target
, (uint8_t *)&algo_params
.sync
, NPCX_FLASH_LOADER_EXECUTE
);
214 retval
= target_write_buffer(target
, npcx_bank
->params_addr
,
215 sizeof(algo_params
), (uint8_t *)&algo_params
);
217 /* If no error, wait for finishing */
218 if (retval
== ERROR_OK
) {
219 retval
= npcx_wait_algo_done(bank
, npcx_bank
->params_addr
);
220 if (retval
== ERROR_OK
)
221 target_read_u32(target
, NPCX_FLASH_LOADER_BUFFER_ADDR
, flash_id
);
224 /* Regardless of errors, try to close down algo */
225 (void)npcx_quit(bank
);
230 static int npcx_get_flash(uint32_t flash_id
)
232 for (uint32_t i
= 0; i
< ARRAY_SIZE(flash_info
) - 1; i
++) {
233 if (flash_info
[i
].id
== flash_id
)
237 return NPCX_FLASH_UNKNOWN
;
240 static int npcx_probe(struct flash_bank
*bank
)
242 struct npcx_flash_bank
*npcx_bank
= bank
->driver_priv
;
243 uint32_t sector_length
= NPCX_FLASH_ERASE_SIZE
;
246 /* Set up appropriate flash helper algorithm */
247 npcx_bank
->algo_code
= npcx_algo
;
248 npcx_bank
->algo_size
= sizeof(npcx_algo
);
249 npcx_bank
->algo_working_size
= NPCX_FLASH_LOADER_PARAMS_SIZE
+
250 NPCX_FLASH_LOADER_BUFFER_SIZE
+
251 NPCX_FLASH_LOADER_PROGRAM_SIZE
;
252 npcx_bank
->buffer_addr
= NPCX_FLASH_LOADER_BUFFER_ADDR
;
253 npcx_bank
->params_addr
= NPCX_FLASH_LOADER_PARAMS_ADDR
;
255 int retval
= npcx_get_flash_id(bank
, &flash_id
);
256 if (retval
!= ERROR_OK
)
259 npcx_bank
->flash
= npcx_get_flash(flash_id
);
261 unsigned int num_sectors
= flash_info
[npcx_bank
->flash
].size
/ sector_length
;
263 bank
->sectors
= calloc(num_sectors
, sizeof(struct flash_sector
));
264 if (!bank
->sectors
) {
265 LOG_ERROR("Out of memory");
269 bank
->base
= NPCX_FLASH_BASE_ADDR
;
270 bank
->num_sectors
= num_sectors
;
271 bank
->size
= num_sectors
* sector_length
;
272 bank
->write_start_alignment
= 0;
273 bank
->write_end_alignment
= 0;
274 npcx_bank
->sector_length
= sector_length
;
276 for (unsigned int i
= 0; i
< num_sectors
; i
++) {
277 bank
->sectors
[i
].offset
= i
* sector_length
;
278 bank
->sectors
[i
].size
= sector_length
;
279 bank
->sectors
[i
].is_erased
= -1;
280 bank
->sectors
[i
].is_protected
= 0;
283 /* We've successfully determined the stats on the flash bank */
284 npcx_bank
->probed
= true;
286 /* If we fall through to here, then all went well */
290 static int npcx_auto_probe(struct flash_bank
*bank
)
292 struct npcx_flash_bank
*npcx_bank
= bank
->driver_priv
;
293 int retval
= ERROR_OK
;
295 if (!npcx_bank
->probed
)
296 retval
= npcx_probe(bank
);
301 FLASH_BANK_COMMAND_HANDLER(npcx_flash_bank_command
)
303 struct npcx_flash_bank
*npcx_bank
;
306 return ERROR_COMMAND_SYNTAX_ERROR
;
308 npcx_bank
= calloc(1, sizeof(struct npcx_flash_bank
));
310 LOG_ERROR("Out of memory");
314 /* Initialize private flash information */
315 npcx_bank
->family_name
= "npcx";
316 npcx_bank
->sector_length
= NPCX_FLASH_ERASE_SIZE
;
318 /* Finish initialization of bank */
319 bank
->driver_priv
= npcx_bank
;
325 static int npcx_chip_erase(struct flash_bank
*bank
)
327 struct target
*target
= bank
->target
;
328 struct npcx_flash_bank
*npcx_bank
= bank
->driver_priv
;
329 struct npcx_flash_params algo_params
;
331 if (target
->state
!= TARGET_HALTED
) {
332 LOG_ERROR("Target not halted");
333 return ERROR_TARGET_NOT_HALTED
;
336 /* Make sure we've probed the flash to get the device and size */
337 int retval
= npcx_auto_probe(bank
);
338 if (retval
!= ERROR_OK
)
341 retval
= npcx_init(bank
);
342 if (retval
!= ERROR_OK
)
345 /* Set up algorithm parameters for chip erase command */
346 target_buffer_set_u32(target
, (uint8_t *)&algo_params
.cmd
, NPCX_FLASH_CMD_ERASE_ALL
);
347 target_buffer_set_u32(target
, (uint8_t *)&algo_params
.sync
, NPCX_FLASH_LOADER_WAIT
);
349 /* Set algorithm parameters */
350 retval
= target_write_buffer(target
, npcx_bank
->params_addr
,
351 sizeof(algo_params
), (uint8_t *)&algo_params
);
352 if (retval
!= ERROR_OK
) {
353 (void)npcx_quit(bank
);
357 /* Issue flash helper algorithm parameters for chip erase */
358 target_buffer_set_u32(target
, (uint8_t *)&algo_params
.sync
, NPCX_FLASH_LOADER_EXECUTE
);
359 retval
= target_write_buffer(target
, npcx_bank
->params_addr
,
360 sizeof(algo_params
), (uint8_t *)&algo_params
);
362 /* If no error, wait for chip erase finish */
363 if (retval
== ERROR_OK
)
364 retval
= npcx_wait_algo_done(bank
, npcx_bank
->params_addr
);
366 /* Regardless of errors, try to close down algo */
367 (void)npcx_quit(bank
);
372 static int npcx_erase(struct flash_bank
*bank
, unsigned int first
,
375 struct target
*target
= bank
->target
;
376 struct npcx_flash_bank
*npcx_bank
= bank
->driver_priv
;
377 struct npcx_flash_params algo_params
;
379 if (target
->state
!= TARGET_HALTED
) {
380 LOG_ERROR("Target not halted");
381 return ERROR_TARGET_NOT_HALTED
;
384 if ((first
== 0) && (last
== (bank
->num_sectors
- 1))) {
385 /* Request chip erase */
386 return npcx_chip_erase(bank
);
389 uint32_t address
= first
* npcx_bank
->sector_length
;
390 uint32_t length
= (last
- first
+ 1) * npcx_bank
->sector_length
;
392 /* Make sure we've probed the flash to get the device and size */
393 int retval
= npcx_auto_probe(bank
);
394 if (retval
!= ERROR_OK
)
397 retval
= npcx_init(bank
);
398 if (retval
!= ERROR_OK
)
401 /* Set up algorithm parameters for erase command */
402 target_buffer_set_u32(target
, (uint8_t *)&algo_params
.addr
, address
);
403 target_buffer_set_u32(target
, (uint8_t *)&algo_params
.len
, length
);
404 target_buffer_set_u32(target
, (uint8_t *)&algo_params
.cmd
, NPCX_FLASH_CMD_ERASE_SECTORS
);
405 target_buffer_set_u32(target
, (uint8_t *)&algo_params
.sync
, NPCX_FLASH_LOADER_WAIT
);
407 /* Set algorithm parameters */
408 retval
= target_write_buffer(target
, npcx_bank
->params_addr
,
409 sizeof(algo_params
), (uint8_t *)&algo_params
);
410 if (retval
!= ERROR_OK
) {
411 (void)npcx_quit(bank
);
415 /* Issue flash helper algorithm parameters for erase */
416 target_buffer_set_u32(target
, (uint8_t *)&algo_params
.sync
, NPCX_FLASH_LOADER_EXECUTE
);
417 retval
= target_write_buffer(target
, npcx_bank
->params_addr
,
418 sizeof(algo_params
), (uint8_t *)&algo_params
);
420 /* If no error, wait for erase to finish */
421 if (retval
== ERROR_OK
)
422 retval
= npcx_wait_algo_done(bank
, npcx_bank
->params_addr
);
424 /* Regardless of errors, try to close down algo */
425 (void)npcx_quit(bank
);
430 static int npcx_write(struct flash_bank
*bank
, const uint8_t *buffer
,
431 uint32_t offset
, uint32_t count
)
433 struct target
*target
= bank
->target
;
434 struct npcx_flash_bank
*npcx_bank
= bank
->driver_priv
;
435 struct npcx_flash_params algo_params
;
437 if (target
->state
!= TARGET_HALTED
) {
438 LOG_ERROR("Target not halted");
439 return ERROR_TARGET_NOT_HALTED
;
442 /* Make sure we've probed the flash to get the device and size */
443 int retval
= npcx_auto_probe(bank
);
444 if (retval
!= ERROR_OK
)
447 retval
= npcx_init(bank
);
448 if (retval
!= ERROR_OK
)
451 /* Initialize algorithm parameters to default values */
452 target_buffer_set_u32(target
, (uint8_t *)&algo_params
.cmd
, NPCX_FLASH_CMD_PROGRAM
);
454 uint32_t address
= offset
;
457 uint32_t size
= (count
> NPCX_FLASH_LOADER_BUFFER_SIZE
) ?
458 NPCX_FLASH_LOADER_BUFFER_SIZE
: count
;
460 /* Put the data into buffer */
461 retval
= target_write_buffer(target
, npcx_bank
->buffer_addr
,
463 if (retval
!= ERROR_OK
) {
464 LOG_ERROR("Unable to write data to target memory");
468 /* Update algo parameters for flash write */
469 target_buffer_set_u32(target
, (uint8_t *)&algo_params
.addr
, address
);
470 target_buffer_set_u32(target
, (uint8_t *)&algo_params
.len
, size
);
471 target_buffer_set_u32(target
, (uint8_t *)&algo_params
.sync
, NPCX_FLASH_LOADER_WAIT
);
473 /* Set algorithm parameters */
474 retval
= target_write_buffer(target
, npcx_bank
->params_addr
,
475 sizeof(algo_params
), (uint8_t *)&algo_params
);
476 if (retval
!= ERROR_OK
)
479 /* Issue flash helper algorithm parameters for flash write */
480 target_buffer_set_u32(target
, (uint8_t *)&algo_params
.sync
, NPCX_FLASH_LOADER_EXECUTE
);
481 retval
= target_write_buffer(target
, npcx_bank
->params_addr
,
482 sizeof(algo_params
), (uint8_t *)&algo_params
);
483 if (retval
!= ERROR_OK
)
486 /* Wait for flash write finish */
487 retval
= npcx_wait_algo_done(bank
, npcx_bank
->params_addr
);
488 if (retval
!= ERROR_OK
)
496 /* Regardless of errors, try to close down algo */
497 (void)npcx_quit(bank
);
502 static int npcx_info(struct flash_bank
*bank
, struct command_invocation
*cmd
)
504 struct npcx_flash_bank
*npcx_bank
= bank
->driver_priv
;
506 command_print_sameline(cmd
, "%s flash: %s\n",
507 npcx_bank
->family_name
,
508 flash_info
[npcx_bank
->flash
].name
);
513 const struct flash_driver npcx_flash
= {
515 .flash_bank_command
= npcx_flash_bank_command
,
518 .read
= default_flash_read
,
520 .auto_probe
= npcx_auto_probe
,
521 .erase_check
= default_flash_blank_check
,
523 .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)