openocd: fix SPDX tag format for files .c
[fw/openocd] / src / flash / nor / bluenrg-x.c
1 // SPDX-License-Identifier: GPL-2.0-or-later
2
3 /***************************************************************************
4  *   Copyright (C) 2017 by Michele Sardo                                   *
5  *   msmttchr@gmail.com                                                    *
6  ***************************************************************************/
7
8 #ifdef HAVE_CONFIG_H
9 #include "config.h"
10 #endif
11
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>
17 #include "imp.h"
18 #include "bluenrg-x.h"
19
20 #define BLUENRG2_JTAG_REG        (flash_priv_data_2.jtag_idcode_reg)
21 #define BLUENRGLP_JTAG_REG       (flash_priv_data_lp.jtag_idcode_reg)
22
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)
26
27 #define FLASH_SIZE_REG_MASK (0xFFFF)
28
29 struct flash_ctrl_priv_data {
30         uint32_t die_id_reg;
31         uint32_t jtag_idcode_reg;
32         uint32_t flash_base;
33         uint32_t flash_regs_base;
34         uint32_t flash_page_size;
35         uint32_t jtag_idcode;
36         char *part_name;
37 };
38
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",
47 };
48
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",
57 };
58
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",
67 };
68
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",
77 };
78
79 struct bluenrgx_flash_bank {
80         bool probed;
81         uint32_t die_id;
82         const struct flash_ctrl_priv_data *flash_ptr;
83 };
84
85 static const struct flash_ctrl_priv_data *flash_ctrl[] = {
86         &flash_priv_data_1,
87         &flash_priv_data_2,
88         &flash_priv_data_lp,
89         &flash_priv_data_lps};
90
91 /* flash_bank bluenrg-x 0 0 0 0 <target#> */
92 FLASH_BANK_COMMAND_HANDLER(bluenrgx_flash_bank_command)
93 {
94         struct bluenrgx_flash_bank *bluenrgx_info;
95         /* Create the bank structure */
96         bluenrgx_info = calloc(1, sizeof(*bluenrgx_info));
97
98         /* Check allocation */
99         if (!bluenrgx_info) {
100                 LOG_ERROR("failed to allocate bank structure");
101                 return ERROR_FAIL;
102         }
103
104         bank->write_start_alignment = 16;
105         bank->write_end_alignment = 16;
106
107         bank->driver_priv = bluenrgx_info;
108
109         bluenrgx_info->probed = false;
110
111         if (CMD_ARGC < 6)
112                 return ERROR_COMMAND_SYNTAX_ERROR;
113
114         return ERROR_OK;
115 }
116
117 static inline uint32_t bluenrgx_get_flash_reg(struct flash_bank *bank, uint32_t reg_offset)
118 {
119         struct bluenrgx_flash_bank *bluenrgx_info = bank->driver_priv;
120         return bluenrgx_info->flash_ptr->flash_regs_base + reg_offset;
121 }
122
123 static inline int bluenrgx_read_flash_reg(struct flash_bank *bank, uint32_t reg_offset, uint32_t *value)
124 {
125         return target_read_u32(bank->target, bluenrgx_get_flash_reg(bank, reg_offset), value);
126 }
127
128 static inline int bluenrgx_write_flash_reg(struct flash_bank *bank, uint32_t reg_offset, uint32_t value)
129 {
130         return target_write_u32(bank->target, bluenrgx_get_flash_reg(bank, reg_offset), value);
131 }
132
133 static int bluenrgx_erase(struct flash_bank *bank, unsigned int first,
134                 unsigned int last)
135 {
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;
142
143         /* check preconditions */
144         if (!bluenrgx_info->probed)
145                 return ERROR_FLASH_BANK_NOT_PROBED;
146
147         if (bank->target->state != TARGET_HALTED) {
148                 LOG_ERROR("Target not halted");
149                 return ERROR_TARGET_NOT_HALTED;
150         }
151         /* Disable blue module */
152         if (target_write_u32(target, 0x200000c0, 0) != ERROR_OK) {
153                 LOG_ERROR("Blue disable failed");
154                 return ERROR_FAIL;
155         }
156
157         if (mass_erase) {
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");
162                         return ERROR_FAIL;
163                 }
164
165                 if (bluenrgx_write_flash_reg(bank, FLASH_REG_ADDRESS,
166                                                                 (address - bank->base) >> 2) != ERROR_OK) {
167                         LOG_ERROR("Register write failed");
168                         return ERROR_FAIL;
169                 }
170
171                 if (bluenrgx_write_flash_reg(bank, FLASH_REG_COMMAND, command) != ERROR_OK) {
172                         LOG_ERROR("Register write failed");
173                         return ERROR_FAIL;
174                 }
175
176                 for (unsigned int i = 0; i < 100; i++) {
177                         uint32_t value;
178                         if (bluenrgx_read_flash_reg(bank, FLASH_REG_IRQRAW, &value)) {
179                                 LOG_ERROR("Register write failed");
180                                 return ERROR_FAIL;
181                         }
182                         if (value & FLASH_INT_CMDDONE)
183                                 break;
184                         if (i == 99) {
185                                 LOG_ERROR("Mass erase command failed (timeout)");
186                                 retval = ERROR_FAIL;
187                         }
188                 }
189
190         } else {
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);
195
196                         if (bluenrgx_write_flash_reg(bank, FLASH_REG_IRQRAW, 0x3f) != ERROR_OK) {
197                                 LOG_ERROR("Register write failed");
198                                 return ERROR_FAIL;
199                         }
200
201                         if (bluenrgx_write_flash_reg(bank, FLASH_REG_ADDRESS,
202                                                                         (address - bank->base) >> 2) != ERROR_OK) {
203                                 LOG_ERROR("Register write failed");
204                                 return ERROR_FAIL;
205                         }
206
207                         if (bluenrgx_write_flash_reg(bank, FLASH_REG_COMMAND, command) != ERROR_OK) {
208                                 LOG_ERROR("Failed");
209                                 return ERROR_FAIL;
210                         }
211
212                         for (unsigned int j = 0; j < 100; j++) {
213                                 uint32_t value;
214                                 if (bluenrgx_read_flash_reg(bank, FLASH_REG_IRQRAW, &value)) {
215                                         LOG_ERROR("Register write failed");
216                                         return ERROR_FAIL;
217                                 }
218                                 if (value & FLASH_INT_CMDDONE)
219                                         break;
220                                 if (j == 99) {
221                                         LOG_ERROR("Erase command failed (timeout)");
222                                         retval = ERROR_FAIL;
223                                 }
224                         }
225                 }
226         }
227
228         return retval;
229
230 }
231
232 static int bluenrgx_write(struct flash_bank *bank, const uint8_t *buffer,
233                           uint32_t offset, uint32_t count)
234 {
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;
246
247         /* See contrib/loaders/flash/bluenrg-x/bluenrg-x_write.c for source and
248          * hints how to generate the data!
249          */
250         static const uint8_t bluenrgx_flash_write_code[] = {
251 #include "../../../contrib/loaders/flash/bluenrg-x/bluenrg-x_write.inc"
252         };
253
254         /* check preconditions */
255         if (!bluenrgx_info->probed)
256                 return ERROR_FLASH_BANK_NOT_PROBED;
257
258         if ((offset + count) > bank->size) {
259                 LOG_ERROR("Requested write past beyond of flash size: (offset+count) = %" PRIu32 ", size=%" PRIu32,
260                           (offset + count),
261                           bank->size);
262                 return ERROR_FLASH_DST_OUT_OF_BANK;
263         }
264
265         if (bank->target->state != TARGET_HALTED) {
266                 LOG_ERROR("Target not halted");
267                 return ERROR_TARGET_NOT_HALTED;
268         }
269
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;
274         }
275
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)
280                 return retval;
281
282         /* memory buffer */
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;
286         }
287
288         /* Stack area */
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;
293         }
294
295         armv7m_info.common_magic = ARMV7M_COMMON_MAGIC;
296         armv7m_info.core_mode = ARM_MODE_THREAD;
297
298         init_reg_param(&reg_params[0], "r0", 32, PARAM_IN_OUT);
299         init_reg_param(&reg_params[1], "r1", 32, PARAM_OUT);
300         init_reg_param(&reg_params[2], "r2", 32, PARAM_OUT);
301         init_reg_param(&reg_params[3], "r3", 32, PARAM_OUT);
302         init_reg_param(&reg_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]
306          *                     ^^^ offset
307          */
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);
316
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);
327
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);
333
334         retval = target_run_flash_async_algorithm(target,
335                                                   buffer,
336                                                   count/16,
337                                                   16, /* Block size: we write in block of 16 bytes to enjoy burstwrite speed */
338                                                   1,
339                                                   mem_params,
340                                                   5,
341                                                   reg_params,
342                                                   source->address,
343                                                   source->size,
344                                                   write_algorithm->address,
345                                                   0,
346                                                   &armv7m_info);
347
348         if (retval == ERROR_FLASH_OPERATION_FAILED) {
349                 LOG_ERROR("error executing bluenrg-x flash write algorithm");
350
351                 uint32_t error = buf_get_u32(reg_params[0].value, 0, 32);
352
353                 if (error != 0)
354                         LOG_ERROR("flash write failed = %08" PRIx32, error);
355         }
356         if (retval == ERROR_OK) {
357                 uint32_t rp;
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;
364                         }
365                 }
366         }
367         target_free_working_area(target, source);
368         target_free_working_area(target, write_algorithm);
369         target_free_working_area(target, write_algorithm_stack);
370
371         destroy_reg_param(&reg_params[0]);
372         destroy_reg_param(&reg_params[1]);
373         destroy_reg_param(&reg_params[2]);
374         destroy_reg_param(&reg_params[3]);
375         destroy_reg_param(&reg_params[4]);
376         destroy_mem_param(&mem_params[0]);
377
378         return retval;
379 }
380
381 static int bluenrgx_probe(struct flash_bank *bank)
382 {
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);
386
387         if (retval != ERROR_OK)
388                 return retval;
389
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)
393                         return retval;
394         }
395
396         /* Default device is BlueNRG-1 */
397         bluenrgx_info->flash_ptr = &flash_priv_data_1;
398         bank->base = flash_priv_data_1.flash_base;
399
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;
404                         break;
405                 }
406         }
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)
410                 return retval;
411
412         retval = target_read_u32(bank->target, DIE_ID_REG(bluenrgx_info), &die_id);
413         if (retval != ERROR_OK)
414                 return retval;
415
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);
419
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;
425         }
426
427         bluenrgx_info->probed = true;
428         bluenrgx_info->die_id = die_id;
429
430         return ERROR_OK;
431 }
432
433 static int bluenrgx_auto_probe(struct flash_bank *bank)
434 {
435         struct bluenrgx_flash_bank *bluenrgx_info = bank->driver_priv;
436
437         if (bluenrgx_info->probed)
438                 return ERROR_OK;
439
440         return bluenrgx_probe(bank);
441 }
442
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)
445 {
446         struct bluenrgx_flash_bank *bluenrgx_info = bank->driver_priv;
447         int mask_number, cut_number;
448
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.");
453                         return retval;
454                 }
455         }
456
457         mask_number = (bluenrgx_info->die_id >> 4) & 0xF;
458         cut_number = bluenrgx_info->die_id & 0xF;
459
460         command_print_sameline(cmd, "%s - Rev: %d.%d",
461                         bluenrgx_info->flash_ptr->part_name, mask_number, cut_number);
462         return ERROR_OK;
463 }
464
465 const struct flash_driver bluenrgx_flash = {
466         .name = "bluenrg-x",
467         .flash_bank_command = bluenrgx_flash_bank_command,
468         .erase = bluenrgx_erase,
469         .protect = NULL,
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,
477 };