target/aarch64: Use 'bool' data type
[openocd.git] / src / flash / nor / bluenrg-x.c
blob2b568593ace5f18302790b9769f1b566b7eba291
1 /***************************************************************************
2 * Copyright (C) 2017 by Michele Sardo *
3 * msmttchr@gmail.com *
4 * *
5 * This program is free software; you can redistribute it and/or modify *
6 * it under the terms of the GNU General Public License as published by *
7 * the Free Software Foundation; either version 2 of the License, or *
8 * (at your option) any later version. *
9 * *
10 * This program is distributed in the hope that it will be useful, *
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
13 * GNU General Public License for more details. *
14 * *
15 * You should have received a copy of the GNU General Public License *
16 * along with this program. If not, see <http://www.gnu.org/licenses/>. *
17 ***************************************************************************/
19 #ifdef HAVE_CONFIG_H
20 #include "config.h"
21 #endif
23 #include <target/algorithm.h>
24 #include <target/armv7m.h>
25 #include <target/cortex_m.h>
26 #include "imp.h"
28 #define FLASH_SIZE_REG (0x40100014)
29 #define DIE_ID_REG (0x4090001C)
30 #define JTAG_IDCODE_REG (0x40900028)
31 #define BLUENRG2_IDCODE (0x0200A041)
32 #define FLASH_BASE (0x10040000)
33 #define FLASH_PAGE_SIZE (2048)
34 #define FLASH_REG_COMMAND (0x40100000)
35 #define FLASH_REG_IRQRAW (0x40100010)
36 #define FLASH_REG_ADDRESS (0x40100018)
37 #define FLASH_REG_DATA (0x40100040)
38 #define FLASH_CMD_ERASE_PAGE 0x11
39 #define FLASH_CMD_MASSERASE 0x22
40 #define FLASH_CMD_WRITE 0x33
41 #define FLASH_CMD_BURSTWRITE 0xCC
42 #define FLASH_INT_CMDDONE 0x01
43 #define FLASH_WORD_LEN 4
45 struct bluenrgx_flash_bank {
46 int probed;
47 uint32_t idcode;
48 uint32_t die_id;
51 static int bluenrgx_protect_check(struct flash_bank *bank)
53 /* Nothing to do. Protection is only handled in SW. */
54 return ERROR_OK;
57 /* flash_bank bluenrg-x 0 0 0 0 <target#> */
58 FLASH_BANK_COMMAND_HANDLER(bluenrgx_flash_bank_command)
60 struct bluenrgx_flash_bank *bluenrgx_info;
61 /* Create the bank structure */
62 bluenrgx_info = calloc(1, sizeof(*bluenrgx_info));
64 /* Check allocation */
65 if (bluenrgx_info == NULL) {
66 LOG_ERROR("failed to allocate bank structure");
67 return ERROR_FAIL;
70 bank->driver_priv = bluenrgx_info;
72 bluenrgx_info->probed = 0;
74 if (CMD_ARGC < 6)
75 return ERROR_COMMAND_SYNTAX_ERROR;
77 return ERROR_OK;
80 static int bluenrgx_erase(struct flash_bank *bank, int first, int last)
82 int retval = ERROR_OK;
83 struct bluenrgx_flash_bank *bluenrgx_info = bank->driver_priv;
84 int num_sectors = (last - first + 1);
85 int mass_erase = (num_sectors == bank->num_sectors);
86 struct target *target = bank->target;
87 uint32_t address, command;
89 /* check preconditions */
90 if (bluenrgx_info->probed == 0)
91 return ERROR_FLASH_BANK_NOT_PROBED;
93 if (bank->target->state != TARGET_HALTED) {
94 LOG_ERROR("Target not halted");
95 return ERROR_TARGET_NOT_HALTED;
97 /* Disable blue module */
98 if (target_write_u32(target, 0x200000c0, 0) != ERROR_OK) {
99 LOG_ERROR("Blue disable failed");
100 return ERROR_FAIL;
103 if (mass_erase) {
104 command = FLASH_CMD_MASSERASE;
105 address = bank->base;
106 if (target_write_u32(target, FLASH_REG_IRQRAW, 0x3f) != ERROR_OK) {
107 LOG_ERROR("Register write failed");
108 return ERROR_FAIL;
111 if (target_write_u32(target, FLASH_REG_ADDRESS, address >> 2) != ERROR_OK) {
112 LOG_ERROR("Register write failed");
113 return ERROR_FAIL;
116 if (target_write_u32(target, FLASH_REG_COMMAND, command) != ERROR_OK) {
117 LOG_ERROR("Register write failed");
118 return ERROR_FAIL;
121 for (int i = 0; i < 100; i++) {
122 uint32_t value;
123 if (target_read_u32(target, FLASH_REG_IRQRAW, &value)) {
124 LOG_ERROR("Register write failed");
125 return ERROR_FAIL;
127 if (value & FLASH_INT_CMDDONE)
128 break;
129 if (i == 99) {
130 LOG_ERROR("Mass erase command failed (timeout)");
131 retval = ERROR_FAIL;
135 } else {
136 command = FLASH_CMD_ERASE_PAGE;
137 for (int i = first; i <= last; i++) {
138 address = bank->base+i*FLASH_PAGE_SIZE;
140 if (target_write_u32(target, FLASH_REG_IRQRAW, 0x3f) != ERROR_OK) {
141 LOG_ERROR("Register write failed");
142 return ERROR_FAIL;
145 if (target_write_u32(target, FLASH_REG_ADDRESS, address >> 2) != ERROR_OK) {
146 LOG_ERROR("Register write failed");
147 return ERROR_FAIL;
150 if (target_write_u32(target, FLASH_REG_COMMAND, command) != ERROR_OK) {
151 LOG_ERROR("Failed");
152 return ERROR_FAIL;
155 for (int j = 0; j < 100; j++) {
156 uint32_t value;
157 if (target_read_u32(target, FLASH_REG_IRQRAW, &value)) {
158 LOG_ERROR("Register write failed");
159 return ERROR_FAIL;
161 if (value & FLASH_INT_CMDDONE)
162 break;
163 if (j == 99) {
164 LOG_ERROR("Erase command failed (timeout)");
165 retval = ERROR_FAIL;
171 return retval;
175 static int bluenrgx_protect(struct flash_bank *bank, int set, int first, int last)
177 /* Protection is only handled in software: no hardware write protection
178 available in BlueNRG-x devices */
179 int sector;
181 for (sector = first; sector <= last; sector++)
182 bank->sectors[sector].is_protected = set;
183 return ERROR_OK;
185 static int bluenrgx_write_word(struct target *target, uint32_t address_base, uint8_t *values, uint32_t count)
187 int retval = ERROR_OK;
189 retval = target_write_u32(target, FLASH_REG_IRQRAW, 0x3f);
190 if (retval != ERROR_OK) {
191 LOG_ERROR("Register write failed, error code: %d", retval);
192 return retval;
195 for (uint32_t i = 0; i < count; i++) {
196 uint32_t address = address_base + i * FLASH_WORD_LEN;
198 retval = target_write_u32(target, FLASH_REG_ADDRESS, address >> 2);
199 if (retval != ERROR_OK) {
200 LOG_ERROR("Register write failed, error code: %d", retval);
201 return retval;
204 retval = target_write_buffer(target, FLASH_REG_DATA, FLASH_WORD_LEN, values + i * FLASH_WORD_LEN);
205 if (retval != ERROR_OK) {
206 LOG_ERROR("Register write failed, error code: %d", retval);
207 return retval;
210 retval = target_write_u32(target, FLASH_REG_COMMAND, FLASH_CMD_WRITE);
211 if (retval != ERROR_OK) {
212 LOG_ERROR("Register write failed, error code: %d", retval);
213 return retval;
216 for (int j = 0; j < 100; j++) {
217 uint32_t reg_value;
218 retval = target_read_u32(target, FLASH_REG_IRQRAW, &reg_value);
220 if (retval != ERROR_OK) {
221 LOG_ERROR("Register read failed, error code: %d", retval);
222 return retval;
225 if (reg_value & FLASH_INT_CMDDONE)
226 break;
228 if (j == 99) {
229 LOG_ERROR("Write command failed (timeout)");
230 return ERROR_FAIL;
234 return retval;
237 static int bluenrgx_write_bytes(struct target *target, uint32_t address_base, uint8_t *buffer, uint32_t count)
239 int retval = ERROR_OK;
240 uint8_t *new_buffer = NULL;
241 uint32_t pre_bytes = 0, post_bytes = 0, pre_word, post_word, pre_address, post_address;
243 if (count == 0) {
244 /* Just return if there are no bytes to write */
245 return retval;
248 if (address_base & 3) {
249 pre_bytes = address_base & 3;
250 pre_address = address_base - pre_bytes;
253 if ((count + pre_bytes) & 3) {
254 post_bytes = ((count + pre_bytes + 3) & ~3) - (count + pre_bytes);
255 post_address = (address_base + count) & ~3;
258 if (pre_bytes || post_bytes) {
259 uint32_t old_count = count;
261 count = old_count + pre_bytes + post_bytes;
263 new_buffer = malloc(count);
265 if (new_buffer == NULL) {
266 LOG_ERROR("odd number of bytes to write and no memory "
267 "for padding buffer");
268 return ERROR_FAIL;
271 LOG_INFO("Requested number of bytes to write and/or address not word aligned (%" PRIu32 "), extending to %"
272 PRIu32 " ", old_count, count);
274 if (pre_bytes) {
275 if (target_read_u32(target, pre_address, &pre_word)) {
276 LOG_ERROR("Memory read failed");
277 free(new_buffer);
278 return ERROR_FAIL;
283 if (post_bytes) {
284 if (target_read_u32(target, post_address, &post_word)) {
285 LOG_ERROR("Memory read failed");
286 free(new_buffer);
287 return ERROR_FAIL;
292 memcpy(new_buffer, &pre_word, pre_bytes);
293 memcpy((new_buffer+((pre_bytes+old_count) & ~3)), &post_word, 4);
294 memcpy(new_buffer+pre_bytes, buffer, old_count);
295 buffer = new_buffer;
298 retval = bluenrgx_write_word(target, address_base - pre_bytes, buffer, count/4);
300 if (new_buffer)
301 free(new_buffer);
303 return retval;
306 static int bluenrgx_write(struct flash_bank *bank, const uint8_t *buffer,
307 uint32_t offset, uint32_t count)
309 struct target *target = bank->target;
310 uint32_t buffer_size = 16384 + 8;
311 struct working_area *write_algorithm;
312 struct working_area *write_algorithm_sp;
313 struct working_area *source;
314 uint32_t address = bank->base + offset;
315 struct reg_param reg_params[5];
316 struct armv7m_algorithm armv7m_info;
317 int retval = ERROR_OK;
318 uint32_t pre_size = 0, fast_size = 0, post_size = 0;
319 uint32_t pre_offset = 0, fast_offset = 0, post_offset = 0;
321 /* See contrib/loaders/flash/bluenrg-x/bluenrg-x_write.c for source and
322 * hints how to generate the data!
324 static const uint8_t bluenrgx_flash_write_code[] = {
325 #include "../../../contrib/loaders/flash/bluenrg-x/bluenrg-x_write.inc"
328 if ((offset + count) > bank->size) {
329 LOG_ERROR("Requested write past beyond of flash size: (offset+count) = %d, size=%d",
330 (offset + count),
331 bank->size);
332 return ERROR_FLASH_DST_OUT_OF_BANK;
335 if (bank->target->state != TARGET_HALTED) {
336 LOG_ERROR("Target not halted");
337 return ERROR_TARGET_NOT_HALTED;
340 /* We are good here and we need to compute pre_size, fast_size, post_size */
341 pre_size = MIN(count, ((offset+0xF) & ~0xF) - offset);
342 pre_offset = offset;
343 fast_size = 16*((count - pre_size) / 16);
344 fast_offset = offset + pre_size;
345 post_size = (count-pre_size-fast_size) % 16;
346 post_offset = fast_offset + fast_size;
348 LOG_DEBUG("pre_size = %08x, pre_offset=%08x", pre_size, pre_offset);
349 LOG_DEBUG("fast_size = %08x, fast_offset=%08x", fast_size, fast_offset);
350 LOG_DEBUG("post_size = %08x, post_offset=%08x", post_size, post_offset);
352 /* Program initial chunk not 16 bytes aligned */
353 retval = bluenrgx_write_bytes(target, bank->base+pre_offset, (uint8_t *) buffer, pre_size);
354 if (retval) {
355 LOG_ERROR("bluenrgx_write_bytes failed %d", retval);
356 return ERROR_FAIL;
359 /* Program chunk 16 bytes aligned in fast mode */
360 if (fast_size) {
362 if (target_alloc_working_area(target, sizeof(bluenrgx_flash_write_code),
363 &write_algorithm) != ERROR_OK) {
364 LOG_WARNING("no working area available, can't do block memory writes");
365 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
368 retval = target_write_buffer(target, write_algorithm->address,
369 sizeof(bluenrgx_flash_write_code),
370 bluenrgx_flash_write_code);
371 if (retval != ERROR_OK)
372 return retval;
374 /* memory buffer */
375 if (target_alloc_working_area(target, buffer_size, &source)) {
376 LOG_WARNING("no large enough working area available");
377 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
380 /* Stack pointer area */
381 if (target_alloc_working_area(target, 64,
382 &write_algorithm_sp) != ERROR_OK) {
383 LOG_DEBUG("no working area for write code stack pointer");
384 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
387 armv7m_info.common_magic = ARMV7M_COMMON_MAGIC;
388 armv7m_info.core_mode = ARM_MODE_THREAD;
390 init_reg_param(&reg_params[0], "r0", 32, PARAM_IN_OUT);
391 init_reg_param(&reg_params[1], "r1", 32, PARAM_OUT);
392 init_reg_param(&reg_params[2], "r2", 32, PARAM_OUT);
393 init_reg_param(&reg_params[3], "r3", 32, PARAM_OUT);
394 init_reg_param(&reg_params[4], "sp", 32, PARAM_OUT);
396 /* FIFO start address (first two words used for write and read pointers) */
397 buf_set_u32(reg_params[0].value, 0, 32, source->address);
398 /* FIFO end address (first two words used for write and read pointers) */
399 buf_set_u32(reg_params[1].value, 0, 32, source->address + source->size);
400 /* Flash memory address */
401 buf_set_u32(reg_params[2].value, 0, 32, address+pre_size);
402 /* Number of bytes */
403 buf_set_u32(reg_params[3].value, 0, 32, fast_size);
404 /* Stack pointer for program working area */
405 buf_set_u32(reg_params[4].value, 0, 32, write_algorithm_sp->address);
407 LOG_DEBUG("source->address = %08" TARGET_PRIxADDR, source->address);
408 LOG_DEBUG("source->address+ source->size = %08" TARGET_PRIxADDR, source->address+source->size);
409 LOG_DEBUG("write_algorithm_sp->address = %08" TARGET_PRIxADDR, write_algorithm_sp->address);
410 LOG_DEBUG("address = %08x", address+pre_size);
411 LOG_DEBUG("count = %08x", count);
413 retval = target_run_flash_async_algorithm(target,
414 buffer+pre_size,
415 fast_size/16,
416 16, /* Block size: we write in block of 16 bytes to enjoy burstwrite speed */
418 NULL,
420 reg_params,
421 source->address,
422 source->size,
423 write_algorithm->address,
425 &armv7m_info);
427 if (retval == ERROR_FLASH_OPERATION_FAILED) {
428 LOG_ERROR("error executing bluenrg-x flash write algorithm");
430 uint32_t error = buf_get_u32(reg_params[0].value, 0, 32);
432 if (error != 0)
433 LOG_ERROR("flash write failed = %08" PRIx32, error);
435 if (retval == ERROR_OK) {
436 uint32_t rp;
437 /* Read back rp and check that is valid */
438 retval = target_read_u32(target, source->address+4, &rp);
439 if (retval == ERROR_OK) {
440 if ((rp < source->address+8) || (rp > (source->address + source->size))) {
441 LOG_ERROR("flash write failed = %08" PRIx32, rp);
442 retval = ERROR_FLASH_OPERATION_FAILED;
446 target_free_working_area(target, source);
447 target_free_working_area(target, write_algorithm);
448 target_free_working_area(target, write_algorithm_sp);
450 destroy_reg_param(&reg_params[0]);
451 destroy_reg_param(&reg_params[1]);
452 destroy_reg_param(&reg_params[2]);
453 destroy_reg_param(&reg_params[3]);
454 destroy_reg_param(&reg_params[4]);
455 if (retval != ERROR_OK)
456 return retval;
460 /* Program chunk at end, not addressable by fast burst write algorithm */
461 retval = bluenrgx_write_bytes(target, bank->base+post_offset, (uint8_t *) (buffer+pre_size+fast_size), post_size);
462 if (retval) {
463 LOG_ERROR("bluenrgx_write_bytes failed %d", retval);
464 return ERROR_FAIL;
466 return retval;
469 static int bluenrgx_probe(struct flash_bank *bank)
471 struct bluenrgx_flash_bank *bluenrgx_info = bank->driver_priv;
472 uint32_t idcode, size_info, die_id;
473 int i;
474 int retval = target_read_u32(bank->target, JTAG_IDCODE_REG, &idcode);
475 if (retval != ERROR_OK)
476 return retval;
477 retval = target_read_u32(bank->target, FLASH_SIZE_REG, &size_info);
478 if (retval != ERROR_OK)
479 return retval;
481 retval = target_read_u32(bank->target, DIE_ID_REG, &die_id);
482 if (retval != ERROR_OK)
483 return retval;
485 bank->size = (size_info + 1) * 4;
486 bank->base = FLASH_BASE;
487 bank->num_sectors = bank->size/FLASH_PAGE_SIZE;
488 bank->sectors = realloc(bank->sectors, sizeof(struct flash_sector) * bank->num_sectors);
490 for (i = 0; i < bank->num_sectors; i++) {
491 bank->sectors[i].offset = i * FLASH_PAGE_SIZE;
492 bank->sectors[i].size = FLASH_PAGE_SIZE;
493 bank->sectors[i].is_erased = -1;
494 bank->sectors[i].is_protected = 0;
497 bluenrgx_info->probed = 1;
498 bluenrgx_info->die_id = die_id;
499 bluenrgx_info->idcode = idcode;
500 return ERROR_OK;
503 static int bluenrgx_auto_probe(struct flash_bank *bank)
505 struct bluenrgx_flash_bank *bluenrgx_info = bank->driver_priv;
507 if (bluenrgx_info->probed)
508 return ERROR_OK;
510 return bluenrgx_probe(bank);
513 /* This method must return a string displaying information about the bank */
514 static int bluenrgx_get_info(struct flash_bank *bank, char *buf, int buf_size)
516 struct bluenrgx_flash_bank *bluenrgx_info = bank->driver_priv;
517 int mask_number, cut_number;
518 char *part_name;
520 if (!bluenrgx_info->probed) {
521 int retval = bluenrgx_probe(bank);
522 if (retval != ERROR_OK) {
523 snprintf(buf, buf_size,
524 "Unable to find bank information.");
525 return retval;
529 if (bluenrgx_info->idcode == BLUENRG2_IDCODE)
530 part_name = "BLUENRG-2";
531 else
532 part_name = "BLUENRG-1";
534 mask_number = (bluenrgx_info->die_id >> 4) & 0xF;
535 cut_number = bluenrgx_info->die_id & 0xF;
537 snprintf(buf, buf_size,
538 "%s - Rev: %d.%d", part_name, mask_number, cut_number);
539 return ERROR_OK;
542 struct flash_driver bluenrgx_flash = {
543 .name = "bluenrg-x",
544 .flash_bank_command = bluenrgx_flash_bank_command,
545 .erase = bluenrgx_erase,
546 .protect = bluenrgx_protect,
547 .write = bluenrgx_write,
548 .read = default_flash_read,
549 .probe = bluenrgx_probe,
550 .erase_check = default_flash_blank_check,
551 .protect_check = bluenrgx_protect_check,
552 .auto_probe = bluenrgx_auto_probe,
553 .info = bluenrgx_get_info,