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 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_ERROR("%s: Invalid working address", npcx_bank
->family_name
);
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_ERROR("%s: Failed to load flash helper algorithm",
106 npcx_bank
->family_name
);
107 target_free_working_area(target
, npcx_bank
->working_area
);
108 npcx_bank
->working_area
= NULL
;
112 /* Initialize the ARMv7 specific info to run the algorithm */
113 npcx_bank
->armv7m_info
.common_magic
= ARMV7M_COMMON_MAGIC
;
114 npcx_bank
->armv7m_info
.core_mode
= ARM_MODE_THREAD
;
116 /* Begin executing the flash helper algorithm */
117 retval
= target_start_algorithm(target
, 0, NULL
, 0, NULL
,
118 NPCX_FLASH_LOADER_PROGRAM_ADDR
, 0,
119 &npcx_bank
->armv7m_info
);
120 if (retval
!= ERROR_OK
) {
121 LOG_ERROR("%s: Failed to start flash helper algorithm",
122 npcx_bank
->family_name
);
123 target_free_working_area(target
, npcx_bank
->working_area
);
124 npcx_bank
->working_area
= NULL
;
129 * At this point, the algorithm is running on the target and
130 * ready to receive commands and data to flash the target
136 static int npcx_quit(struct flash_bank
*bank
)
138 struct target
*target
= bank
->target
;
139 struct npcx_flash_bank
*npcx_bank
= bank
->driver_priv
;
141 /* Regardless of the algo's status, attempt to halt the target */
142 (void)target_halt(target
);
144 /* Now confirm target halted and clean up from flash helper algorithm */
145 int retval
= target_wait_algorithm(target
, 0, NULL
, 0, NULL
, 0,
146 NPCX_FLASH_TIMEOUT_MS
, &npcx_bank
->armv7m_info
);
148 target_free_working_area(target
, npcx_bank
->working_area
);
149 npcx_bank
->working_area
= NULL
;
154 static int npcx_wait_algo_done(struct flash_bank
*bank
, uint32_t params_addr
)
156 struct target
*target
= bank
->target
;
157 struct npcx_flash_bank
*npcx_bank
= bank
->driver_priv
;
158 uint32_t status_addr
= params_addr
+ offsetof(struct npcx_flash_params
, sync
);
160 int64_t start_ms
= timeval_ms();
163 int retval
= target_read_u32(target
, status_addr
, &status
);
164 if (retval
!= ERROR_OK
)
169 int64_t elapsed_ms
= timeval_ms() - start_ms
;
170 if (elapsed_ms
> NPCX_FLASH_TIMEOUT_MS
)
172 } while (status
== NPCX_FLASH_LOADER_EXECUTE
);
174 if (status
!= NPCX_FLASH_LOADER_WAIT
) {
175 LOG_ERROR("%s: Flash operation failed, status=0x%" PRIx32
,
176 npcx_bank
->family_name
,
184 static enum npcx_flash_device_index
npcx_get_flash_id(struct flash_bank
*bank
, uint32_t *flash_id
)
186 struct target
*target
= bank
->target
;
187 struct npcx_flash_bank
*npcx_bank
= bank
->driver_priv
;
188 struct npcx_flash_params algo_params
;
190 if (target
->state
!= TARGET_HALTED
) {
191 LOG_ERROR("Target not halted");
192 return ERROR_TARGET_NOT_HALTED
;
195 int retval
= npcx_init(bank
);
196 if (retval
!= ERROR_OK
)
199 /* Set up algorithm parameters for get flash ID command */
200 target_buffer_set_u32(target
, (uint8_t *)&algo_params
.cmd
, NPCX_FLASH_CMD_GET_FLASH_ID
);
201 target_buffer_set_u32(target
, (uint8_t *)&algo_params
.sync
, NPCX_FLASH_LOADER_WAIT
);
203 /* Issue flash helper algorithm parameters for get flash ID */
204 retval
= target_write_buffer(target
, npcx_bank
->params_addr
,
205 sizeof(algo_params
), (uint8_t *)&algo_params
);
206 if (retval
!= ERROR_OK
) {
207 (void)npcx_quit(bank
);
211 target_buffer_set_u32(target
, (uint8_t *)&algo_params
.sync
, NPCX_FLASH_LOADER_EXECUTE
);
212 retval
= target_write_buffer(target
, npcx_bank
->params_addr
,
213 sizeof(algo_params
), (uint8_t *)&algo_params
);
215 /* If no error, wait for finishing */
216 if (retval
== ERROR_OK
) {
217 retval
= npcx_wait_algo_done(bank
, npcx_bank
->params_addr
);
218 if (retval
== ERROR_OK
)
219 target_read_u32(target
, NPCX_FLASH_LOADER_BUFFER_ADDR
, flash_id
);
222 /* Regardless of errors, try to close down algo */
223 (void)npcx_quit(bank
);
228 static int npcx_get_flash(uint32_t flash_id
)
230 for (uint32_t i
= 0; i
< ARRAY_SIZE(flash_info
) - 1; i
++) {
231 if (flash_info
[i
].id
== flash_id
)
235 return NPCX_FLASH_UNKNOWN
;
238 static int npcx_probe(struct flash_bank
*bank
)
240 struct npcx_flash_bank
*npcx_bank
= bank
->driver_priv
;
241 uint32_t sector_length
= NPCX_FLASH_ERASE_SIZE
;
244 /* Set up appropriate flash helper algorithm */
245 npcx_bank
->algo_code
= npcx_algo
;
246 npcx_bank
->algo_size
= sizeof(npcx_algo
);
247 npcx_bank
->algo_working_size
= NPCX_FLASH_LOADER_PARAMS_SIZE
+
248 NPCX_FLASH_LOADER_BUFFER_SIZE
+
249 NPCX_FLASH_LOADER_PROGRAM_SIZE
;
250 npcx_bank
->buffer_addr
= NPCX_FLASH_LOADER_BUFFER_ADDR
;
251 npcx_bank
->params_addr
= NPCX_FLASH_LOADER_PARAMS_ADDR
;
253 int retval
= npcx_get_flash_id(bank
, &flash_id
);
254 if (retval
!= ERROR_OK
)
257 npcx_bank
->flash
= npcx_get_flash(flash_id
);
259 unsigned int num_sectors
= flash_info
[npcx_bank
->flash
].size
/ sector_length
;
261 bank
->sectors
= calloc(num_sectors
, sizeof(struct flash_sector
));
262 if (!bank
->sectors
) {
263 LOG_ERROR("Out of memory");
267 bank
->base
= NPCX_FLASH_BASE_ADDR
;
268 bank
->num_sectors
= num_sectors
;
269 bank
->size
= num_sectors
* sector_length
;
270 bank
->write_start_alignment
= 0;
271 bank
->write_end_alignment
= 0;
272 npcx_bank
->sector_length
= sector_length
;
274 for (unsigned int i
= 0; i
< num_sectors
; i
++) {
275 bank
->sectors
[i
].offset
= i
* sector_length
;
276 bank
->sectors
[i
].size
= sector_length
;
277 bank
->sectors
[i
].is_erased
= -1;
278 bank
->sectors
[i
].is_protected
= 0;
281 /* We've successfully determined the stats on the flash bank */
282 npcx_bank
->probed
= true;
284 /* If we fall through to here, then all went well */
288 static int npcx_auto_probe(struct flash_bank
*bank
)
290 struct npcx_flash_bank
*npcx_bank
= bank
->driver_priv
;
291 int retval
= ERROR_OK
;
293 if (!npcx_bank
->probed
)
294 retval
= npcx_probe(bank
);
299 FLASH_BANK_COMMAND_HANDLER(npcx_flash_bank_command
)
301 struct npcx_flash_bank
*npcx_bank
;
304 return ERROR_COMMAND_SYNTAX_ERROR
;
306 npcx_bank
= calloc(1, sizeof(struct npcx_flash_bank
));
308 LOG_ERROR("Out of memory");
312 /* Initialize private flash information */
313 npcx_bank
->family_name
= "npcx";
314 npcx_bank
->sector_length
= NPCX_FLASH_ERASE_SIZE
;
316 /* Finish initialization of bank */
317 bank
->driver_priv
= npcx_bank
;
323 static int npcx_chip_erase(struct flash_bank
*bank
)
325 struct target
*target
= bank
->target
;
326 struct npcx_flash_bank
*npcx_bank
= bank
->driver_priv
;
327 struct npcx_flash_params algo_params
;
329 if (target
->state
!= TARGET_HALTED
) {
330 LOG_ERROR("Target not halted");
331 return ERROR_TARGET_NOT_HALTED
;
334 /* Make sure we've probed the flash to get the device and size */
335 int retval
= npcx_auto_probe(bank
);
336 if (retval
!= ERROR_OK
)
339 retval
= npcx_init(bank
);
340 if (retval
!= ERROR_OK
)
343 /* Set up algorithm parameters for chip erase command */
344 target_buffer_set_u32(target
, (uint8_t *)&algo_params
.cmd
, NPCX_FLASH_CMD_ERASE_ALL
);
345 target_buffer_set_u32(target
, (uint8_t *)&algo_params
.sync
, NPCX_FLASH_LOADER_WAIT
);
347 /* Set algorithm parameters */
348 retval
= target_write_buffer(target
, npcx_bank
->params_addr
,
349 sizeof(algo_params
), (uint8_t *)&algo_params
);
350 if (retval
!= ERROR_OK
) {
351 (void)npcx_quit(bank
);
355 /* Issue flash helper algorithm parameters for chip erase */
356 target_buffer_set_u32(target
, (uint8_t *)&algo_params
.sync
, NPCX_FLASH_LOADER_EXECUTE
);
357 retval
= target_write_buffer(target
, npcx_bank
->params_addr
,
358 sizeof(algo_params
), (uint8_t *)&algo_params
);
360 /* If no error, wait for chip erase finish */
361 if (retval
== ERROR_OK
)
362 retval
= npcx_wait_algo_done(bank
, npcx_bank
->params_addr
);
364 /* Regardless of errors, try to close down algo */
365 (void)npcx_quit(bank
);
370 static int npcx_erase(struct flash_bank
*bank
, unsigned int first
,
373 struct target
*target
= bank
->target
;
374 struct npcx_flash_bank
*npcx_bank
= bank
->driver_priv
;
375 struct npcx_flash_params algo_params
;
377 if (target
->state
!= TARGET_HALTED
) {
378 LOG_ERROR("Target not halted");
379 return ERROR_TARGET_NOT_HALTED
;
382 if ((first
== 0) && (last
== (bank
->num_sectors
- 1))) {
383 /* Request chip erase */
384 return npcx_chip_erase(bank
);
387 uint32_t address
= first
* npcx_bank
->sector_length
;
388 uint32_t length
= (last
- first
+ 1) * npcx_bank
->sector_length
;
390 /* Make sure we've probed the flash to get the device and size */
391 int retval
= npcx_auto_probe(bank
);
392 if (retval
!= ERROR_OK
)
395 retval
= npcx_init(bank
);
396 if (retval
!= ERROR_OK
)
399 /* Set up algorithm parameters for erase command */
400 target_buffer_set_u32(target
, (uint8_t *)&algo_params
.addr
, address
);
401 target_buffer_set_u32(target
, (uint8_t *)&algo_params
.len
, length
);
402 target_buffer_set_u32(target
, (uint8_t *)&algo_params
.cmd
, NPCX_FLASH_CMD_ERASE_SECTORS
);
403 target_buffer_set_u32(target
, (uint8_t *)&algo_params
.sync
, NPCX_FLASH_LOADER_WAIT
);
405 /* Set algorithm parameters */
406 retval
= target_write_buffer(target
, npcx_bank
->params_addr
,
407 sizeof(algo_params
), (uint8_t *)&algo_params
);
408 if (retval
!= ERROR_OK
) {
409 (void)npcx_quit(bank
);
413 /* Issue flash helper algorithm parameters for erase */
414 target_buffer_set_u32(target
, (uint8_t *)&algo_params
.sync
, NPCX_FLASH_LOADER_EXECUTE
);
415 retval
= target_write_buffer(target
, npcx_bank
->params_addr
,
416 sizeof(algo_params
), (uint8_t *)&algo_params
);
418 /* If no error, wait for erase to finish */
419 if (retval
== ERROR_OK
)
420 retval
= npcx_wait_algo_done(bank
, npcx_bank
->params_addr
);
422 /* Regardless of errors, try to close down algo */
423 (void)npcx_quit(bank
);
428 static int npcx_write(struct flash_bank
*bank
, const uint8_t *buffer
,
429 uint32_t offset
, uint32_t count
)
431 struct target
*target
= bank
->target
;
432 struct npcx_flash_bank
*npcx_bank
= bank
->driver_priv
;
433 struct npcx_flash_params algo_params
;
435 if (target
->state
!= TARGET_HALTED
) {
436 LOG_ERROR("Target not halted");
437 return ERROR_TARGET_NOT_HALTED
;
440 /* Make sure we've probed the flash to get the device and size */
441 int retval
= npcx_auto_probe(bank
);
442 if (retval
!= ERROR_OK
)
445 retval
= npcx_init(bank
);
446 if (retval
!= ERROR_OK
)
449 /* Initialize algorithm parameters to default values */
450 target_buffer_set_u32(target
, (uint8_t *)&algo_params
.cmd
, NPCX_FLASH_CMD_PROGRAM
);
452 uint32_t address
= offset
;
455 uint32_t size
= (count
> NPCX_FLASH_LOADER_BUFFER_SIZE
) ?
456 NPCX_FLASH_LOADER_BUFFER_SIZE
: count
;
458 /* Put the data into buffer */
459 retval
= target_write_buffer(target
, npcx_bank
->buffer_addr
,
461 if (retval
!= ERROR_OK
) {
462 LOG_ERROR("Unable to write data to target memory");
466 /* Update algo parameters for flash write */
467 target_buffer_set_u32(target
, (uint8_t *)&algo_params
.addr
, address
);
468 target_buffer_set_u32(target
, (uint8_t *)&algo_params
.len
, size
);
469 target_buffer_set_u32(target
, (uint8_t *)&algo_params
.sync
, NPCX_FLASH_LOADER_WAIT
);
471 /* Set algorithm parameters */
472 retval
= target_write_buffer(target
, npcx_bank
->params_addr
,
473 sizeof(algo_params
), (uint8_t *)&algo_params
);
474 if (retval
!= ERROR_OK
)
477 /* Issue flash helper algorithm parameters for flash write */
478 target_buffer_set_u32(target
, (uint8_t *)&algo_params
.sync
, NPCX_FLASH_LOADER_EXECUTE
);
479 retval
= target_write_buffer(target
, npcx_bank
->params_addr
,
480 sizeof(algo_params
), (uint8_t *)&algo_params
);
481 if (retval
!= ERROR_OK
)
484 /* Wait for flash write finish */
485 retval
= npcx_wait_algo_done(bank
, npcx_bank
->params_addr
);
486 if (retval
!= ERROR_OK
)
494 /* Regardless of errors, try to close down algo */
495 (void)npcx_quit(bank
);
500 static int npcx_info(struct flash_bank
*bank
, struct command_invocation
*cmd
)
502 struct npcx_flash_bank
*npcx_bank
= bank
->driver_priv
;
504 command_print_sameline(cmd
, "%s flash: %s\n",
505 npcx_bank
->family_name
,
506 flash_info
[npcx_bank
->flash
].name
);
511 const struct flash_driver npcx_flash
= {
513 .flash_bank_command
= npcx_flash_bank_command
,
516 .read
= default_flash_read
,
518 .auto_probe
= npcx_auto_probe
,
519 .erase_check
= default_flash_blank_check
,
521 .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)