1 // SPDX-License-Identifier: GPL-2.0-or-later
3 /***************************************************************************
4 * Copyright (C) 2017 by Michele Sardo *
6 ***************************************************************************/
12 #include <helper/binarybuffer.h>
13 #include "helper/types.h"
14 #include <target/algorithm.h>
15 #include <target/armv7m.h>
16 #include <target/cortex_m.h>
18 #include "bluenrg-x.h"
20 #define BLUENRG2_JTAG_REG (flash_priv_data_2.jtag_idcode_reg)
21 #define BLUENRGLP_JTAG_REG (flash_priv_data_lp.jtag_idcode_reg)
23 #define DIE_ID_REG(bluenrgx_info) (bluenrgx_info->flash_ptr->die_id_reg)
24 #define JTAG_IDCODE_REG(bluenrgx_info) (bluenrgx_info->flash_ptr->jtag_idcode_reg)
25 #define FLASH_PAGE_SIZE(bluenrgx_info) (bluenrgx_info->flash_ptr->flash_page_size)
27 #define FLASH_SIZE_REG_MASK (0xFFFF)
29 struct flash_ctrl_priv_data {
31 uint32_t jtag_idcode_reg;
33 uint32_t flash_regs_base;
34 uint32_t flash_page_size;
39 static const struct flash_ctrl_priv_data flash_priv_data_1 = {
40 .die_id_reg = 0x4090001C,
41 .jtag_idcode_reg = 0x40900028,
42 .flash_base = 0x10040000,
43 .flash_regs_base = 0x40100000,
44 .flash_page_size = 2048,
45 .jtag_idcode = 0x00000000,
46 .part_name = "BLUENRG-1",
49 static const struct flash_ctrl_priv_data flash_priv_data_2 = {
50 .die_id_reg = 0x4090001C,
51 .jtag_idcode_reg = 0x40900028,
52 .flash_base = 0x10040000,
53 .flash_regs_base = 0x40100000,
54 .flash_page_size = 2048,
55 .jtag_idcode = 0x0200A041,
56 .part_name = "BLUENRG-2",
59 static const struct flash_ctrl_priv_data flash_priv_data_lp = {
60 .die_id_reg = 0x40000000,
61 .jtag_idcode_reg = 0x40000004,
62 .flash_base = 0x10040000,
63 .flash_regs_base = 0x40001000,
64 .flash_page_size = 2048,
65 .jtag_idcode = 0x0201E041,
66 .part_name = "BLUENRG-LP",
69 static const struct flash_ctrl_priv_data flash_priv_data_lps = {
70 .die_id_reg = 0x40000000,
71 .jtag_idcode_reg = 0x40000004,
72 .flash_base = 0x10040000,
73 .flash_regs_base = 0x40001000,
74 .flash_page_size = 2048,
75 .jtag_idcode = 0x02028041,
76 .part_name = "BLUENRG-LPS",
79 struct bluenrgx_flash_bank {
82 const struct flash_ctrl_priv_data *flash_ptr;
85 static const struct flash_ctrl_priv_data *flash_ctrl[] = {
89 &flash_priv_data_lps};
91 /* flash_bank bluenrg-x 0 0 0 0 <target#> */
92 FLASH_BANK_COMMAND_HANDLER(bluenrgx_flash_bank_command)
94 struct bluenrgx_flash_bank *bluenrgx_info;
95 /* Create the bank structure */
96 bluenrgx_info = calloc(1, sizeof(*bluenrgx_info));
98 /* Check allocation */
100 LOG_ERROR("failed to allocate bank structure");
104 bank->write_start_alignment = 16;
105 bank->write_end_alignment = 16;
107 bank->driver_priv = bluenrgx_info;
109 bluenrgx_info->probed = false;
112 return ERROR_COMMAND_SYNTAX_ERROR;
117 static inline uint32_t bluenrgx_get_flash_reg(struct flash_bank *bank, uint32_t reg_offset)
119 struct bluenrgx_flash_bank *bluenrgx_info = bank->driver_priv;
120 return bluenrgx_info->flash_ptr->flash_regs_base + reg_offset;
123 static inline int bluenrgx_read_flash_reg(struct flash_bank *bank, uint32_t reg_offset, uint32_t *value)
125 return target_read_u32(bank->target, bluenrgx_get_flash_reg(bank, reg_offset), value);
128 static inline int bluenrgx_write_flash_reg(struct flash_bank *bank, uint32_t reg_offset, uint32_t value)
130 return target_write_u32(bank->target, bluenrgx_get_flash_reg(bank, reg_offset), value);
133 static int bluenrgx_erase(struct flash_bank *bank, unsigned int first,
136 int retval = ERROR_OK;
137 struct bluenrgx_flash_bank *bluenrgx_info = bank->driver_priv;
138 unsigned int num_sectors = (last - first + 1);
139 const bool mass_erase = (num_sectors == bank->num_sectors);
140 struct target *target = bank->target;
141 uint32_t address, command;
143 /* check preconditions */
144 if (!bluenrgx_info->probed)
145 return ERROR_FLASH_BANK_NOT_PROBED;
147 if (bank->target->state != TARGET_HALTED) {
148 LOG_ERROR("Target not halted");
149 return ERROR_TARGET_NOT_HALTED;
151 /* Disable blue module */
152 if (target_write_u32(target, 0x200000c0, 0) != ERROR_OK) {
153 LOG_ERROR("Blue disable failed");
158 command = FLASH_CMD_MASSERASE;
159 address = bank->base;
160 if (bluenrgx_write_flash_reg(bank, FLASH_REG_IRQRAW, 0x3f) != ERROR_OK) {
161 LOG_ERROR("Register write failed");
165 if (bluenrgx_write_flash_reg(bank, FLASH_REG_ADDRESS,
166 (address - bank->base) >> 2) != ERROR_OK) {
167 LOG_ERROR("Register write failed");
171 if (bluenrgx_write_flash_reg(bank, FLASH_REG_COMMAND, command) != ERROR_OK) {
172 LOG_ERROR("Register write failed");
176 for (unsigned int i = 0; i < 100; i++) {
178 if (bluenrgx_read_flash_reg(bank, FLASH_REG_IRQRAW, &value)) {
179 LOG_ERROR("Register write failed");
182 if (value & FLASH_INT_CMDDONE)
185 LOG_ERROR("Mass erase command failed (timeout)");
191 command = FLASH_CMD_ERASE_PAGE;
192 for (unsigned int i = first; i <= last; i++) {
193 address = bank->base+i*FLASH_PAGE_SIZE(bluenrgx_info);
194 LOG_DEBUG("address = %08" PRIx32 ", index = %u", address, i);
196 if (bluenrgx_write_flash_reg(bank, FLASH_REG_IRQRAW, 0x3f) != ERROR_OK) {
197 LOG_ERROR("Register write failed");
201 if (bluenrgx_write_flash_reg(bank, FLASH_REG_ADDRESS,
202 (address - bank->base) >> 2) != ERROR_OK) {
203 LOG_ERROR("Register write failed");
207 if (bluenrgx_write_flash_reg(bank, FLASH_REG_COMMAND, command) != ERROR_OK) {
212 for (unsigned int j = 0; j < 100; j++) {
214 if (bluenrgx_read_flash_reg(bank, FLASH_REG_IRQRAW, &value)) {
215 LOG_ERROR("Register write failed");
218 if (value & FLASH_INT_CMDDONE)
221 LOG_ERROR("Erase command failed (timeout)");
232 static int bluenrgx_write(struct flash_bank *bank, const uint8_t *buffer,
233 uint32_t offset, uint32_t count)
235 struct bluenrgx_flash_bank *bluenrgx_info = bank->driver_priv;
236 struct target *target = bank->target;
237 uint32_t buffer_size = 16384 + 8;
238 struct working_area *write_algorithm;
239 struct working_area *write_algorithm_stack;
240 struct working_area *source;
241 uint32_t address = bank->base + offset;
242 struct reg_param reg_params[5];
243 struct mem_param mem_params[1];
244 struct armv7m_algorithm armv7m_info;
245 int retval = ERROR_OK;
247 /* See contrib/loaders/flash/bluenrg-x/bluenrg-x_write.c for source and
248 * hints how to generate the data!
250 static const uint8_t bluenrgx_flash_write_code[] = {
251 #include "../../../contrib/loaders/flash/bluenrg-x/bluenrg-x_write.inc"
254 /* check preconditions */
255 if (!bluenrgx_info->probed)
256 return ERROR_FLASH_BANK_NOT_PROBED;
258 if ((offset + count) > bank->size) {
259 LOG_ERROR("Requested write past beyond of flash size: (offset+count) = %" PRIu32 ", size=%" PRIu32,
262 return ERROR_FLASH_DST_OUT_OF_BANK;
265 if (bank->target->state != TARGET_HALTED) {
266 LOG_ERROR("Target not halted");
267 return ERROR_TARGET_NOT_HALTED;
270 if (target_alloc_working_area(target, sizeof(bluenrgx_flash_write_code),
271 &write_algorithm) != ERROR_OK) {
272 LOG_WARNING("no working area available, can't do block memory writes");
273 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
276 retval = target_write_buffer(target, write_algorithm->address,
277 sizeof(bluenrgx_flash_write_code),
278 bluenrgx_flash_write_code);
279 if (retval != ERROR_OK)
283 if (target_alloc_working_area(target, buffer_size, &source)) {
284 LOG_WARNING("no large enough working area available");
285 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
289 if (target_alloc_working_area(target, 128,
290 &write_algorithm_stack) != ERROR_OK) {
291 LOG_DEBUG("no working area for target algorithm stack");
292 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
295 armv7m_info.common_magic = ARMV7M_COMMON_MAGIC;
296 armv7m_info.core_mode = ARM_MODE_THREAD;
298 init_reg_param(®_params[0], "r0", 32, PARAM_IN_OUT);
299 init_reg_param(®_params[1], "r1", 32, PARAM_OUT);
300 init_reg_param(®_params[2], "r2", 32, PARAM_OUT);
301 init_reg_param(®_params[3], "r3", 32, PARAM_OUT);
302 init_reg_param(®_params[4], "sp", 32, PARAM_OUT);
303 /* Put the 4th parameter at the location in the stack frame of target write() function.
304 * See contrib/loaders/flash/bluenrg-x/bluenrg-x_write.lst
305 * 34 ldr r6, [sp, #80]
308 init_mem_param(&mem_params[0], write_algorithm_stack->address + 80, 32, PARAM_OUT);
309 /* Stack for target write algorithm - target write() function has
310 * __attribute__((naked)) so it does not setup the new stack frame.
311 * Therefore the stack frame uses the area from SP upwards!
312 * Interrupts are disabled and no subroutines are called from write()
313 * so no need to allocate stack below SP.
314 * TODO: remove __attribute__((naked)) and use similar parameter passing as stm32l4x */
315 buf_set_u32(reg_params[4].value, 0, 32, write_algorithm_stack->address);
317 /* FIFO start address (first two words used for write and read pointers) */
318 buf_set_u32(reg_params[0].value, 0, 32, source->address);
319 /* FIFO end address (first two words used for write and read pointers) */
320 buf_set_u32(reg_params[1].value, 0, 32, source->address + source->size);
321 /* Flash memory address */
322 buf_set_u32(reg_params[2].value, 0, 32, address);
323 /* Number of bytes */
324 buf_set_u32(reg_params[3].value, 0, 32, count);
325 /* Flash register base address */
326 buf_set_u32(mem_params[0].value, 0, 32, bluenrgx_info->flash_ptr->flash_regs_base);
328 LOG_DEBUG("source->address = " TARGET_ADDR_FMT, source->address);
329 LOG_DEBUG("source->address+ source->size = " TARGET_ADDR_FMT, source->address+source->size);
330 LOG_DEBUG("write_algorithm_stack->address = " TARGET_ADDR_FMT, write_algorithm_stack->address);
331 LOG_DEBUG("address = %08" PRIx32, address);
332 LOG_DEBUG("count = %08" PRIx32, count);
334 retval = target_run_flash_async_algorithm(target,
337 16, /* Block size: we write in block of 16 bytes to enjoy burstwrite speed */
344 write_algorithm->address,
348 if (retval == ERROR_FLASH_OPERATION_FAILED) {
349 LOG_ERROR("error executing bluenrg-x flash write algorithm");
351 uint32_t error = buf_get_u32(reg_params[0].value, 0, 32);
354 LOG_ERROR("flash write failed = %08" PRIx32, error);
356 if (retval == ERROR_OK) {
358 /* Read back rp and check that is valid */
359 retval = target_read_u32(target, source->address+4, &rp);
360 if (retval == ERROR_OK) {
361 if ((rp < source->address+8) || (rp > (source->address + source->size))) {
362 LOG_ERROR("flash write failed = %08" PRIx32, rp);
363 retval = ERROR_FLASH_OPERATION_FAILED;
367 target_free_working_area(target, source);
368 target_free_working_area(target, write_algorithm);
369 target_free_working_area(target, write_algorithm_stack);
371 destroy_reg_param(®_params[0]);
372 destroy_reg_param(®_params[1]);
373 destroy_reg_param(®_params[2]);
374 destroy_reg_param(®_params[3]);
375 destroy_reg_param(®_params[4]);
376 destroy_mem_param(&mem_params[0]);
381 static int bluenrgx_probe(struct flash_bank *bank)
383 struct bluenrgx_flash_bank *bluenrgx_info = bank->driver_priv;
384 uint32_t idcode, size_info, die_id;
385 int retval = target_read_u32(bank->target, BLUENRGLP_JTAG_REG, &idcode);
387 if (retval != ERROR_OK)
390 if ((idcode != flash_priv_data_lp.jtag_idcode) && (idcode != flash_priv_data_lps.jtag_idcode)) {
391 retval = target_read_u32(bank->target, BLUENRG2_JTAG_REG, &idcode);
392 if (retval != ERROR_OK)
396 /* Default device is BlueNRG-1 */
397 bluenrgx_info->flash_ptr = &flash_priv_data_1;
398 bank->base = flash_priv_data_1.flash_base;
400 for (size_t i = 0; i < ARRAY_SIZE(flash_ctrl); i++) {
401 if (idcode == (*flash_ctrl[i]).jtag_idcode) {
402 bluenrgx_info->flash_ptr = flash_ctrl[i];
403 bank->base = (*flash_ctrl[i]).flash_base;
407 retval = bluenrgx_read_flash_reg(bank, FLASH_SIZE_REG, &size_info);
408 size_info = size_info & FLASH_SIZE_REG_MASK;
409 if (retval != ERROR_OK)
412 retval = target_read_u32(bank->target, DIE_ID_REG(bluenrgx_info), &die_id);
413 if (retval != ERROR_OK)
416 bank->size = (size_info + 1) * FLASH_WORD_LEN;
417 bank->num_sectors = bank->size/FLASH_PAGE_SIZE(bluenrgx_info);
418 bank->sectors = realloc(bank->sectors, sizeof(struct flash_sector) * bank->num_sectors);
420 for (unsigned int i = 0; i < bank->num_sectors; i++) {
421 bank->sectors[i].offset = i * FLASH_PAGE_SIZE(bluenrgx_info);
422 bank->sectors[i].size = FLASH_PAGE_SIZE(bluenrgx_info);
423 bank->sectors[i].is_erased = -1;
424 bank->sectors[i].is_protected = 0;
427 bluenrgx_info->probed = true;
428 bluenrgx_info->die_id = die_id;
433 static int bluenrgx_auto_probe(struct flash_bank *bank)
435 struct bluenrgx_flash_bank *bluenrgx_info = bank->driver_priv;
437 if (bluenrgx_info->probed)
440 return bluenrgx_probe(bank);
443 /* This method must return a string displaying information about the bank */
444 static int bluenrgx_get_info(struct flash_bank *bank, struct command_invocation *cmd)
446 struct bluenrgx_flash_bank *bluenrgx_info = bank->driver_priv;
447 int mask_number, cut_number;
449 if (!bluenrgx_info->probed) {
450 int retval = bluenrgx_probe(bank);
451 if (retval != ERROR_OK) {
452 command_print_sameline(cmd, "Unable to find bank information.");
457 mask_number = (bluenrgx_info->die_id >> 4) & 0xF;
458 cut_number = bluenrgx_info->die_id & 0xF;
460 command_print_sameline(cmd, "%s - Rev: %d.%d",
461 bluenrgx_info->flash_ptr->part_name, mask_number, cut_number);
465 const struct flash_driver bluenrgx_flash = {
467 .flash_bank_command = bluenrgx_flash_bank_command,
468 .erase = bluenrgx_erase,
470 .write = bluenrgx_write,
471 .read = default_flash_read,
472 .probe = bluenrgx_probe,
473 .erase_check = default_flash_blank_check,
474 .protect_check = NULL,
475 .auto_probe = bluenrgx_auto_probe,
476 .info = bluenrgx_get_info,