flash/nor/bluenrg-x: Minor code cleanups
[openocd.git] / src / flash / nor / bluenrg-x.c
blobfbce20d5540d517f2026bb0a8a41e2520ca0ee71
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"
27 #include "bluenrg-x.h"
29 #define BLUENRG2_JTAG_REG (flash_priv_data_2.jtag_idcode_reg)
30 #define BLUENRGLP_JTAG_REG (flash_priv_data_lp.jtag_idcode_reg)
32 #define DIE_ID_REG(bluenrgx_info) (bluenrgx_info->flash_ptr->die_id_reg)
33 #define JTAG_IDCODE_REG(bluenrgx_info) (bluenrgx_info->flash_ptr->jtag_idcode_reg)
34 #define FLASH_PAGE_SIZE(bluenrgx_info) (bluenrgx_info->flash_ptr->flash_page_size)
36 struct flash_ctrl_priv_data {
37 uint32_t die_id_reg;
38 uint32_t jtag_idcode_reg;
39 uint32_t flash_base;
40 uint32_t flash_regs_base;
41 uint32_t flash_page_size;
42 uint32_t jtag_idcode;
43 char *part_name;
46 const struct flash_ctrl_priv_data flash_priv_data_1 = {
47 .die_id_reg = 0x4090001C,
48 .jtag_idcode_reg = 0x40900028,
49 .flash_base = 0x10040000,
50 .flash_regs_base = 0x40100000,
51 .flash_page_size = 2048,
52 .jtag_idcode = 0x00000000,
53 .part_name = "BLUENRG-1",
56 const struct flash_ctrl_priv_data flash_priv_data_2 = {
57 .die_id_reg = 0x4090001C,
58 .jtag_idcode_reg = 0x40900028,
59 .flash_base = 0x10040000,
60 .flash_regs_base = 0x40100000,
61 .flash_page_size = 2048,
62 .jtag_idcode = 0x0200A041,
63 .part_name = "BLUENRG-2",
66 const struct flash_ctrl_priv_data flash_priv_data_lp = {
67 .die_id_reg = 0x40000000,
68 .jtag_idcode_reg = 0x40000004,
69 .flash_base = 0x10040000,
70 .flash_regs_base = 0x40001000,
71 .flash_page_size = 2048,
72 .jtag_idcode = 0x0201E041,
73 .part_name = "BLUENRG-LP",
76 struct bluenrgx_flash_bank {
77 bool probed;
78 uint32_t die_id;
79 const struct flash_ctrl_priv_data *flash_ptr;
82 const struct flash_ctrl_priv_data *flash_ctrl[] = {&flash_priv_data_1, &flash_priv_data_2, &flash_priv_data_lp};
84 /* flash_bank bluenrg-x 0 0 0 0 <target#> */
85 FLASH_BANK_COMMAND_HANDLER(bluenrgx_flash_bank_command)
87 struct bluenrgx_flash_bank *bluenrgx_info;
88 /* Create the bank structure */
89 bluenrgx_info = calloc(1, sizeof(*bluenrgx_info));
91 /* Check allocation */
92 if (bluenrgx_info == NULL) {
93 LOG_ERROR("failed to allocate bank structure");
94 return ERROR_FAIL;
97 bank->write_start_alignment = 16;
98 bank->write_end_alignment = 16;
100 bank->driver_priv = bluenrgx_info;
102 bluenrgx_info->probed = false;
104 if (CMD_ARGC < 6)
105 return ERROR_COMMAND_SYNTAX_ERROR;
107 return ERROR_OK;
110 static inline uint32_t bluenrgx_get_flash_reg(struct flash_bank *bank, uint32_t reg_offset)
112 struct bluenrgx_flash_bank *bluenrgx_info = bank->driver_priv;
113 return bluenrgx_info->flash_ptr->flash_regs_base + reg_offset;
116 static inline int bluenrgx_read_flash_reg(struct flash_bank *bank, uint32_t reg_offset, uint32_t *value)
118 return target_read_u32(bank->target, bluenrgx_get_flash_reg(bank, reg_offset), value);
121 static inline int bluenrgx_write_flash_reg(struct flash_bank *bank, uint32_t reg_offset, uint32_t value)
123 return target_write_u32(bank->target, bluenrgx_get_flash_reg(bank, reg_offset), value);
126 static int bluenrgx_erase(struct flash_bank *bank, int first, int last)
128 int retval = ERROR_OK;
129 struct bluenrgx_flash_bank *bluenrgx_info = bank->driver_priv;
130 int num_sectors = (last - first + 1);
131 int mass_erase = (num_sectors == bank->num_sectors);
132 struct target *target = bank->target;
133 uint32_t address, command;
135 /* check preconditions */
136 if (!bluenrgx_info->probed)
137 return ERROR_FLASH_BANK_NOT_PROBED;
139 if (bank->target->state != TARGET_HALTED) {
140 LOG_ERROR("Target not halted");
141 return ERROR_TARGET_NOT_HALTED;
143 /* Disable blue module */
144 if (target_write_u32(target, 0x200000c0, 0) != ERROR_OK) {
145 LOG_ERROR("Blue disable failed");
146 return ERROR_FAIL;
149 if (mass_erase) {
150 command = FLASH_CMD_MASSERASE;
151 address = bank->base;
152 if (bluenrgx_write_flash_reg(bank, FLASH_REG_IRQRAW, 0x3f) != ERROR_OK) {
153 LOG_ERROR("Register write failed");
154 return ERROR_FAIL;
157 if (bluenrgx_write_flash_reg(bank, FLASH_REG_ADDRESS,
158 (address - bank->base) >> 2) != ERROR_OK) {
159 LOG_ERROR("Register write failed");
160 return ERROR_FAIL;
163 if (bluenrgx_write_flash_reg(bank, FLASH_REG_COMMAND, command) != ERROR_OK) {
164 LOG_ERROR("Register write failed");
165 return ERROR_FAIL;
168 for (unsigned int i = 0; i < 100; i++) {
169 uint32_t value;
170 if (bluenrgx_read_flash_reg(bank, FLASH_REG_IRQRAW, &value)) {
171 LOG_ERROR("Register write failed");
172 return ERROR_FAIL;
174 if (value & FLASH_INT_CMDDONE)
175 break;
176 if (i == 99) {
177 LOG_ERROR("Mass erase command failed (timeout)");
178 retval = ERROR_FAIL;
182 } else {
183 command = FLASH_CMD_ERASE_PAGE;
184 for (int i = first; i <= last; i++) {
185 address = bank->base+i*FLASH_PAGE_SIZE(bluenrgx_info);
186 LOG_DEBUG("address = %08x, index = %d", address, i);
188 if (bluenrgx_write_flash_reg(bank, FLASH_REG_IRQRAW, 0x3f) != ERROR_OK) {
189 LOG_ERROR("Register write failed");
190 return ERROR_FAIL;
193 if (bluenrgx_write_flash_reg(bank, FLASH_REG_ADDRESS,
194 (address - bank->base) >> 2) != ERROR_OK) {
195 LOG_ERROR("Register write failed");
196 return ERROR_FAIL;
199 if (bluenrgx_write_flash_reg(bank, FLASH_REG_COMMAND, command) != ERROR_OK) {
200 LOG_ERROR("Failed");
201 return ERROR_FAIL;
204 for (unsigned int j = 0; j < 100; j++) {
205 uint32_t value;
206 if (bluenrgx_read_flash_reg(bank, FLASH_REG_IRQRAW, &value)) {
207 LOG_ERROR("Register write failed");
208 return ERROR_FAIL;
210 if (value & FLASH_INT_CMDDONE)
211 break;
212 if (j == 99) {
213 LOG_ERROR("Erase command failed (timeout)");
214 retval = ERROR_FAIL;
220 return retval;
224 static int bluenrgx_write(struct flash_bank *bank, const uint8_t *buffer,
225 uint32_t offset, uint32_t count)
227 struct bluenrgx_flash_bank *bluenrgx_info = bank->driver_priv;
228 struct target *target = bank->target;
229 uint32_t buffer_size = 16384 + 8;
230 struct working_area *write_algorithm;
231 struct working_area *write_algorithm_sp;
232 struct working_area *source;
233 uint32_t address = bank->base + offset;
234 struct reg_param reg_params[5];
235 struct mem_param mem_params[1];
236 struct armv7m_algorithm armv7m_info;
237 int retval = ERROR_OK;
239 /* See contrib/loaders/flash/bluenrg-x/bluenrg-x_write.c for source and
240 * hints how to generate the data!
242 static const uint8_t bluenrgx_flash_write_code[] = {
243 #include "../../../contrib/loaders/flash/bluenrg-x/bluenrg-x_write.inc"
246 /* check preconditions */
247 if (!bluenrgx_info->probed)
248 return ERROR_FLASH_BANK_NOT_PROBED;
250 if ((offset + count) > bank->size) {
251 LOG_ERROR("Requested write past beyond of flash size: (offset+count) = %d, size=%d",
252 (offset + count),
253 bank->size);
254 return ERROR_FLASH_DST_OUT_OF_BANK;
257 if (bank->target->state != TARGET_HALTED) {
258 LOG_ERROR("Target not halted");
259 return ERROR_TARGET_NOT_HALTED;
262 if (target_alloc_working_area(target, sizeof(bluenrgx_flash_write_code),
263 &write_algorithm) != ERROR_OK) {
264 LOG_WARNING("no working area available, can't do block memory writes");
265 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
268 retval = target_write_buffer(target, write_algorithm->address,
269 sizeof(bluenrgx_flash_write_code),
270 bluenrgx_flash_write_code);
271 if (retval != ERROR_OK)
272 return retval;
274 /* memory buffer */
275 if (target_alloc_working_area(target, buffer_size, &source)) {
276 LOG_WARNING("no large enough working area available");
277 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
280 /* Stack pointer area */
281 if (target_alloc_working_area(target, 128,
282 &write_algorithm_sp) != ERROR_OK) {
283 LOG_DEBUG("no working area for write code stack pointer");
284 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
287 armv7m_info.common_magic = ARMV7M_COMMON_MAGIC;
288 armv7m_info.core_mode = ARM_MODE_THREAD;
290 init_reg_param(&reg_params[0], "r0", 32, PARAM_IN_OUT);
291 init_reg_param(&reg_params[1], "r1", 32, PARAM_OUT);
292 init_reg_param(&reg_params[2], "r2", 32, PARAM_OUT);
293 init_reg_param(&reg_params[3], "r3", 32, PARAM_OUT);
294 init_reg_param(&reg_params[4], "sp", 32, PARAM_OUT);
295 /* Put the parameter at the first available stack location */
296 init_mem_param(&mem_params[0], write_algorithm_sp->address + 80, 32, PARAM_OUT);
298 /* FIFO start address (first two words used for write and read pointers) */
299 buf_set_u32(reg_params[0].value, 0, 32, source->address);
300 /* FIFO end address (first two words used for write and read pointers) */
301 buf_set_u32(reg_params[1].value, 0, 32, source->address + source->size);
302 /* Flash memory address */
303 buf_set_u32(reg_params[2].value, 0, 32, address);
304 /* Number of bytes */
305 buf_set_u32(reg_params[3].value, 0, 32, count);
306 /* Stack pointer for program working area */
307 buf_set_u32(reg_params[4].value, 0, 32, write_algorithm_sp->address);
308 /* Flash register base address */
309 buf_set_u32(mem_params[0].value, 0, 32, bluenrgx_info->flash_ptr->flash_regs_base);
311 LOG_DEBUG("source->address = " TARGET_ADDR_FMT, source->address);
312 LOG_DEBUG("source->address+ source->size = " TARGET_ADDR_FMT, source->address+source->size);
313 LOG_DEBUG("write_algorithm_sp->address = " TARGET_ADDR_FMT, write_algorithm_sp->address);
314 LOG_DEBUG("address = %08x", address);
315 LOG_DEBUG("count = %08x", count);
317 retval = target_run_flash_async_algorithm(target,
318 buffer,
319 count/16,
320 16, /* Block size: we write in block of 16 bytes to enjoy burstwrite speed */
322 mem_params,
324 reg_params,
325 source->address,
326 source->size,
327 write_algorithm->address,
329 &armv7m_info);
331 if (retval == ERROR_FLASH_OPERATION_FAILED) {
332 LOG_ERROR("error executing bluenrg-x flash write algorithm");
334 uint32_t error = buf_get_u32(reg_params[0].value, 0, 32);
336 if (error != 0)
337 LOG_ERROR("flash write failed = %08" PRIx32, error);
339 if (retval == ERROR_OK) {
340 uint32_t rp;
341 /* Read back rp and check that is valid */
342 retval = target_read_u32(target, source->address+4, &rp);
343 if (retval == ERROR_OK) {
344 if ((rp < source->address+8) || (rp > (source->address + source->size))) {
345 LOG_ERROR("flash write failed = %08" PRIx32, rp);
346 retval = ERROR_FLASH_OPERATION_FAILED;
350 target_free_working_area(target, source);
351 target_free_working_area(target, write_algorithm);
352 target_free_working_area(target, write_algorithm_sp);
354 destroy_reg_param(&reg_params[0]);
355 destroy_reg_param(&reg_params[1]);
356 destroy_reg_param(&reg_params[2]);
357 destroy_reg_param(&reg_params[3]);
358 destroy_reg_param(&reg_params[4]);
359 destroy_mem_param(&mem_params[0]);
361 return retval;
364 static int bluenrgx_probe(struct flash_bank *bank)
366 struct bluenrgx_flash_bank *bluenrgx_info = bank->driver_priv;
367 uint32_t idcode, size_info, die_id;
368 int retval = target_read_u32(bank->target, BLUENRGLP_JTAG_REG, &idcode);
370 if (retval != ERROR_OK)
371 return retval;
373 if (idcode != flash_priv_data_lp.jtag_idcode) {
374 retval = target_read_u32(bank->target, BLUENRG2_JTAG_REG, &idcode);
375 if (retval != ERROR_OK)
376 return retval;
379 /* Default device is BlueNRG-1 */
380 bluenrgx_info->flash_ptr = &flash_priv_data_1;
381 bank->base = flash_priv_data_1.flash_base;
383 for (size_t i = 0; i < ARRAY_SIZE(flash_ctrl); i++) {
384 if (idcode == (*flash_ctrl[i]).jtag_idcode) {
385 bluenrgx_info->flash_ptr = flash_ctrl[i];
386 bank->base = (*flash_ctrl[i]).flash_base;
387 break;
390 retval = bluenrgx_read_flash_reg(bank, FLASH_SIZE_REG, &size_info);
391 if (retval != ERROR_OK)
392 return retval;
394 retval = target_read_u32(bank->target, DIE_ID_REG(bluenrgx_info), &die_id);
395 if (retval != ERROR_OK)
396 return retval;
398 bank->size = (size_info + 1) * FLASH_WORD_LEN;
399 bank->num_sectors = bank->size/FLASH_PAGE_SIZE(bluenrgx_info);
400 bank->sectors = realloc(bank->sectors, sizeof(struct flash_sector) * bank->num_sectors);
402 for (int i = 0; i < bank->num_sectors; i++) {
403 bank->sectors[i].offset = i * FLASH_PAGE_SIZE(bluenrgx_info);
404 bank->sectors[i].size = FLASH_PAGE_SIZE(bluenrgx_info);
405 bank->sectors[i].is_erased = -1;
406 bank->sectors[i].is_protected = 0;
409 bluenrgx_info->probed = true;
410 bluenrgx_info->die_id = die_id;
412 return ERROR_OK;
415 static int bluenrgx_auto_probe(struct flash_bank *bank)
417 struct bluenrgx_flash_bank *bluenrgx_info = bank->driver_priv;
419 if (bluenrgx_info->probed)
420 return ERROR_OK;
422 return bluenrgx_probe(bank);
425 /* This method must return a string displaying information about the bank */
426 static int bluenrgx_get_info(struct flash_bank *bank, char *buf, int buf_size)
428 struct bluenrgx_flash_bank *bluenrgx_info = bank->driver_priv;
429 int mask_number, cut_number;
431 if (!bluenrgx_info->probed) {
432 int retval = bluenrgx_probe(bank);
433 if (retval != ERROR_OK) {
434 snprintf(buf, buf_size,
435 "Unable to find bank information.");
436 return retval;
440 mask_number = (bluenrgx_info->die_id >> 4) & 0xF;
441 cut_number = bluenrgx_info->die_id & 0xF;
443 snprintf(buf, buf_size,
444 "%s - Rev: %d.%d", bluenrgx_info->flash_ptr->part_name, mask_number, cut_number);
445 return ERROR_OK;
448 const struct flash_driver bluenrgx_flash = {
449 .name = "bluenrg-x",
450 .flash_bank_command = bluenrgx_flash_bank_command,
451 .erase = bluenrgx_erase,
452 .protect = NULL,
453 .write = bluenrgx_write,
454 .read = default_flash_read,
455 .probe = bluenrgx_probe,
456 .erase_check = default_flash_blank_check,
457 .protect_check = NULL,
458 .auto_probe = bluenrgx_auto_probe,
459 .info = bluenrgx_get_info,