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,