bluenrg: add support for bluenrg-lps device and board
[fw/openocd] / src / flash / nor / bluenrg-x.c
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  ***************************************************************************/
18
19 #ifdef HAVE_CONFIG_H
20 #include "config.h"
21 #endif
22
23 #include <helper/binarybuffer.h>
24 #include "helper/types.h"
25 #include <target/algorithm.h>
26 #include <target/armv7m.h>
27 #include <target/cortex_m.h>
28 #include "imp.h"
29 #include "bluenrg-x.h"
30
31 #define BLUENRG2_JTAG_REG        (flash_priv_data_2.jtag_idcode_reg)
32 #define BLUENRGLP_JTAG_REG       (flash_priv_data_lp.jtag_idcode_reg)
33
34 #define DIE_ID_REG(bluenrgx_info)           (bluenrgx_info->flash_ptr->die_id_reg)
35 #define JTAG_IDCODE_REG(bluenrgx_info)      (bluenrgx_info->flash_ptr->jtag_idcode_reg)
36 #define FLASH_PAGE_SIZE(bluenrgx_info)      (bluenrgx_info->flash_ptr->flash_page_size)
37
38 #define FLASH_SIZE_REG_MASK (0xFFFF)
39
40 struct flash_ctrl_priv_data {
41         uint32_t die_id_reg;
42         uint32_t jtag_idcode_reg;
43         uint32_t flash_base;
44         uint32_t flash_regs_base;
45         uint32_t flash_page_size;
46         uint32_t jtag_idcode;
47         char *part_name;
48 };
49
50 static const struct flash_ctrl_priv_data flash_priv_data_1 = {
51         .die_id_reg = 0x4090001C,
52         .jtag_idcode_reg = 0x40900028,
53         .flash_base = 0x10040000,
54         .flash_regs_base = 0x40100000,
55         .flash_page_size = 2048,
56         .jtag_idcode = 0x00000000,
57         .part_name = "BLUENRG-1",
58 };
59
60 static const struct flash_ctrl_priv_data flash_priv_data_2 = {
61         .die_id_reg = 0x4090001C,
62         .jtag_idcode_reg = 0x40900028,
63         .flash_base = 0x10040000,
64         .flash_regs_base = 0x40100000,
65         .flash_page_size = 2048,
66         .jtag_idcode = 0x0200A041,
67         .part_name = "BLUENRG-2",
68 };
69
70 static const struct flash_ctrl_priv_data flash_priv_data_lp = {
71         .die_id_reg = 0x40000000,
72         .jtag_idcode_reg = 0x40000004,
73         .flash_base = 0x10040000,
74         .flash_regs_base = 0x40001000,
75         .flash_page_size = 2048,
76         .jtag_idcode = 0x0201E041,
77         .part_name = "BLUENRG-LP",
78 };
79
80 static const struct flash_ctrl_priv_data flash_priv_data_lps = {
81         .die_id_reg = 0x40000000,
82         .jtag_idcode_reg = 0x40000004,
83         .flash_base = 0x10040000,
84         .flash_regs_base = 0x40001000,
85         .flash_page_size = 2048,
86         .jtag_idcode = 0x02028041,
87         .part_name = "BLUENRG-LPS",
88 };
89
90 struct bluenrgx_flash_bank {
91         bool probed;
92         uint32_t die_id;
93         const struct flash_ctrl_priv_data *flash_ptr;
94 };
95
96 static const struct flash_ctrl_priv_data *flash_ctrl[] = {
97         &flash_priv_data_1,
98         &flash_priv_data_2,
99         &flash_priv_data_lp,
100         &flash_priv_data_lps};
101
102 /* flash_bank bluenrg-x 0 0 0 0 <target#> */
103 FLASH_BANK_COMMAND_HANDLER(bluenrgx_flash_bank_command)
104 {
105         struct bluenrgx_flash_bank *bluenrgx_info;
106         /* Create the bank structure */
107         bluenrgx_info = calloc(1, sizeof(*bluenrgx_info));
108
109         /* Check allocation */
110         if (!bluenrgx_info) {
111                 LOG_ERROR("failed to allocate bank structure");
112                 return ERROR_FAIL;
113         }
114
115         bank->write_start_alignment = 16;
116         bank->write_end_alignment = 16;
117
118         bank->driver_priv = bluenrgx_info;
119
120         bluenrgx_info->probed = false;
121
122         if (CMD_ARGC < 6)
123                 return ERROR_COMMAND_SYNTAX_ERROR;
124
125         return ERROR_OK;
126 }
127
128 static inline uint32_t bluenrgx_get_flash_reg(struct flash_bank *bank, uint32_t reg_offset)
129 {
130         struct bluenrgx_flash_bank *bluenrgx_info = bank->driver_priv;
131         return bluenrgx_info->flash_ptr->flash_regs_base + reg_offset;
132 }
133
134 static inline int bluenrgx_read_flash_reg(struct flash_bank *bank, uint32_t reg_offset, uint32_t *value)
135 {
136         return target_read_u32(bank->target, bluenrgx_get_flash_reg(bank, reg_offset), value);
137 }
138
139 static inline int bluenrgx_write_flash_reg(struct flash_bank *bank, uint32_t reg_offset, uint32_t value)
140 {
141         return target_write_u32(bank->target, bluenrgx_get_flash_reg(bank, reg_offset), value);
142 }
143
144 static int bluenrgx_erase(struct flash_bank *bank, unsigned int first,
145                 unsigned int last)
146 {
147         int retval = ERROR_OK;
148         struct bluenrgx_flash_bank *bluenrgx_info = bank->driver_priv;
149         unsigned int num_sectors = (last - first + 1);
150         const bool mass_erase = (num_sectors == bank->num_sectors);
151         struct target *target = bank->target;
152         uint32_t address, command;
153
154         /* check preconditions */
155         if (!bluenrgx_info->probed)
156                 return ERROR_FLASH_BANK_NOT_PROBED;
157
158         if (bank->target->state != TARGET_HALTED) {
159                 LOG_ERROR("Target not halted");
160                 return ERROR_TARGET_NOT_HALTED;
161         }
162         /* Disable blue module */
163         if (target_write_u32(target, 0x200000c0, 0) != ERROR_OK) {
164                 LOG_ERROR("Blue disable failed");
165                 return ERROR_FAIL;
166         }
167
168         if (mass_erase) {
169                 command = FLASH_CMD_MASSERASE;
170                 address = bank->base;
171                 if (bluenrgx_write_flash_reg(bank, FLASH_REG_IRQRAW, 0x3f) != ERROR_OK) {
172                         LOG_ERROR("Register write failed");
173                         return ERROR_FAIL;
174                 }
175
176                 if (bluenrgx_write_flash_reg(bank, FLASH_REG_ADDRESS,
177                                                                 (address - bank->base) >> 2) != ERROR_OK) {
178                         LOG_ERROR("Register write failed");
179                         return ERROR_FAIL;
180                 }
181
182                 if (bluenrgx_write_flash_reg(bank, FLASH_REG_COMMAND, command) != ERROR_OK) {
183                         LOG_ERROR("Register write failed");
184                         return ERROR_FAIL;
185                 }
186
187                 for (unsigned int i = 0; i < 100; i++) {
188                         uint32_t value;
189                         if (bluenrgx_read_flash_reg(bank, FLASH_REG_IRQRAW, &value)) {
190                                 LOG_ERROR("Register write failed");
191                                 return ERROR_FAIL;
192                         }
193                         if (value & FLASH_INT_CMDDONE)
194                                 break;
195                         if (i == 99) {
196                                 LOG_ERROR("Mass erase command failed (timeout)");
197                                 retval = ERROR_FAIL;
198                         }
199                 }
200
201         } else {
202                 command = FLASH_CMD_ERASE_PAGE;
203                 for (unsigned int i = first; i <= last; i++) {
204                         address = bank->base+i*FLASH_PAGE_SIZE(bluenrgx_info);
205                         LOG_DEBUG("address = %08" PRIx32 ", index = %u", address, i);
206
207                         if (bluenrgx_write_flash_reg(bank, FLASH_REG_IRQRAW, 0x3f) != ERROR_OK) {
208                                 LOG_ERROR("Register write failed");
209                                 return ERROR_FAIL;
210                         }
211
212                         if (bluenrgx_write_flash_reg(bank, FLASH_REG_ADDRESS,
213                                                                         (address - bank->base) >> 2) != ERROR_OK) {
214                                 LOG_ERROR("Register write failed");
215                                 return ERROR_FAIL;
216                         }
217
218                         if (bluenrgx_write_flash_reg(bank, FLASH_REG_COMMAND, command) != ERROR_OK) {
219                                 LOG_ERROR("Failed");
220                                 return ERROR_FAIL;
221                         }
222
223                         for (unsigned int j = 0; j < 100; j++) {
224                                 uint32_t value;
225                                 if (bluenrgx_read_flash_reg(bank, FLASH_REG_IRQRAW, &value)) {
226                                         LOG_ERROR("Register write failed");
227                                         return ERROR_FAIL;
228                                 }
229                                 if (value & FLASH_INT_CMDDONE)
230                                         break;
231                                 if (j == 99) {
232                                         LOG_ERROR("Erase command failed (timeout)");
233                                         retval = ERROR_FAIL;
234                                 }
235                         }
236                 }
237         }
238
239         return retval;
240
241 }
242
243 static int bluenrgx_write(struct flash_bank *bank, const uint8_t *buffer,
244                           uint32_t offset, uint32_t count)
245 {
246         struct bluenrgx_flash_bank *bluenrgx_info = bank->driver_priv;
247         struct target *target = bank->target;
248         uint32_t buffer_size = 16384 + 8;
249         struct working_area *write_algorithm;
250         struct working_area *write_algorithm_sp;
251         struct working_area *source;
252         uint32_t address = bank->base + offset;
253         struct reg_param reg_params[5];
254         struct mem_param mem_params[1];
255         struct armv7m_algorithm armv7m_info;
256         int retval = ERROR_OK;
257
258         /* See contrib/loaders/flash/bluenrg-x/bluenrg-x_write.c for source and
259          * hints how to generate the data!
260          */
261         static const uint8_t bluenrgx_flash_write_code[] = {
262 #include "../../../contrib/loaders/flash/bluenrg-x/bluenrg-x_write.inc"
263         };
264
265         /* check preconditions */
266         if (!bluenrgx_info->probed)
267                 return ERROR_FLASH_BANK_NOT_PROBED;
268
269         if ((offset + count) > bank->size) {
270                 LOG_ERROR("Requested write past beyond of flash size: (offset+count) = %" PRIu32 ", size=%" PRIu32,
271                           (offset + count),
272                           bank->size);
273                 return ERROR_FLASH_DST_OUT_OF_BANK;
274         }
275
276         if (bank->target->state != TARGET_HALTED) {
277                 LOG_ERROR("Target not halted");
278                 return ERROR_TARGET_NOT_HALTED;
279         }
280
281         if (target_alloc_working_area(target, sizeof(bluenrgx_flash_write_code),
282                                           &write_algorithm) != ERROR_OK) {
283                 LOG_WARNING("no working area available, can't do block memory writes");
284                 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
285         }
286
287         retval = target_write_buffer(target, write_algorithm->address,
288                                          sizeof(bluenrgx_flash_write_code),
289                                          bluenrgx_flash_write_code);
290         if (retval != ERROR_OK)
291                 return retval;
292
293         /* memory buffer */
294         if (target_alloc_working_area(target, buffer_size, &source)) {
295                 LOG_WARNING("no large enough working area available");
296                 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
297         }
298
299         /* Stack pointer area */
300         if (target_alloc_working_area(target, 128,
301                                           &write_algorithm_sp) != ERROR_OK) {
302                 LOG_DEBUG("no working area for write code stack pointer");
303                 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
304         }
305
306         armv7m_info.common_magic = ARMV7M_COMMON_MAGIC;
307         armv7m_info.core_mode = ARM_MODE_THREAD;
308
309         init_reg_param(&reg_params[0], "r0", 32, PARAM_IN_OUT);
310         init_reg_param(&reg_params[1], "r1", 32, PARAM_OUT);
311         init_reg_param(&reg_params[2], "r2", 32, PARAM_OUT);
312         init_reg_param(&reg_params[3], "r3", 32, PARAM_OUT);
313         init_reg_param(&reg_params[4], "sp", 32, PARAM_OUT);
314         /* Put the parameter at the first available stack location */
315         init_mem_param(&mem_params[0], write_algorithm_sp->address + 80, 32, PARAM_OUT);
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         /* Stack pointer for program working area */
326         buf_set_u32(reg_params[4].value, 0, 32, write_algorithm_sp->address);
327         /* Flash register base address */
328         buf_set_u32(mem_params[0].value, 0, 32, bluenrgx_info->flash_ptr->flash_regs_base);
329
330         LOG_DEBUG("source->address = " TARGET_ADDR_FMT, source->address);
331         LOG_DEBUG("source->address+ source->size = " TARGET_ADDR_FMT, source->address+source->size);
332         LOG_DEBUG("write_algorithm_sp->address = " TARGET_ADDR_FMT, write_algorithm_sp->address);
333         LOG_DEBUG("address = %08" PRIx32, address);
334         LOG_DEBUG("count = %08" PRIx32, count);
335
336         retval = target_run_flash_async_algorithm(target,
337                                                   buffer,
338                                                   count/16,
339                                                   16, /* Block size: we write in block of 16 bytes to enjoy burstwrite speed */
340                                                   1,
341                                                   mem_params,
342                                                   5,
343                                                   reg_params,
344                                                   source->address,
345                                                   source->size,
346                                                   write_algorithm->address,
347                                                   0,
348                                                   &armv7m_info);
349
350         if (retval == ERROR_FLASH_OPERATION_FAILED) {
351                 LOG_ERROR("error executing bluenrg-x flash write algorithm");
352
353                 uint32_t error = buf_get_u32(reg_params[0].value, 0, 32);
354
355                 if (error != 0)
356                         LOG_ERROR("flash write failed = %08" PRIx32, error);
357         }
358         if (retval == ERROR_OK) {
359                 uint32_t rp;
360                 /* Read back rp and check that is valid */
361                 retval = target_read_u32(target, source->address+4, &rp);
362                 if (retval == ERROR_OK) {
363                         if ((rp < source->address+8) || (rp > (source->address + source->size))) {
364                                 LOG_ERROR("flash write failed = %08" PRIx32, rp);
365                                 retval = ERROR_FLASH_OPERATION_FAILED;
366                         }
367                 }
368         }
369         target_free_working_area(target, source);
370         target_free_working_area(target, write_algorithm);
371         target_free_working_area(target, write_algorithm_sp);
372
373         destroy_reg_param(&reg_params[0]);
374         destroy_reg_param(&reg_params[1]);
375         destroy_reg_param(&reg_params[2]);
376         destroy_reg_param(&reg_params[3]);
377         destroy_reg_param(&reg_params[4]);
378         destroy_mem_param(&mem_params[0]);
379
380         return retval;
381 }
382
383 static int bluenrgx_probe(struct flash_bank *bank)
384 {
385         struct bluenrgx_flash_bank *bluenrgx_info = bank->driver_priv;
386         uint32_t idcode, size_info, die_id;
387         int retval = target_read_u32(bank->target, BLUENRGLP_JTAG_REG, &idcode);
388
389         if (retval != ERROR_OK)
390                 return retval;
391
392         if ((idcode != flash_priv_data_lp.jtag_idcode) && (idcode != flash_priv_data_lps.jtag_idcode)) {
393                 retval = target_read_u32(bank->target, BLUENRG2_JTAG_REG, &idcode);
394                 if (retval != ERROR_OK)
395                         return retval;
396         }
397
398         /* Default device is BlueNRG-1 */
399         bluenrgx_info->flash_ptr = &flash_priv_data_1;
400         bank->base = flash_priv_data_1.flash_base;
401
402         for (size_t i = 0; i < ARRAY_SIZE(flash_ctrl); i++) {
403                 if (idcode == (*flash_ctrl[i]).jtag_idcode) {
404                         bluenrgx_info->flash_ptr = flash_ctrl[i];
405                         bank->base = (*flash_ctrl[i]).flash_base;
406                         break;
407                 }
408         }
409         retval = bluenrgx_read_flash_reg(bank, FLASH_SIZE_REG, &size_info);
410         size_info = size_info & FLASH_SIZE_REG_MASK;
411         if (retval != ERROR_OK)
412                 return retval;
413
414         retval = target_read_u32(bank->target, DIE_ID_REG(bluenrgx_info), &die_id);
415         if (retval != ERROR_OK)
416                 return retval;
417
418         bank->size = (size_info + 1) * FLASH_WORD_LEN;
419         bank->num_sectors = bank->size/FLASH_PAGE_SIZE(bluenrgx_info);
420         bank->sectors = realloc(bank->sectors, sizeof(struct flash_sector) * bank->num_sectors);
421
422         for (unsigned int i = 0; i < bank->num_sectors; i++) {
423                 bank->sectors[i].offset = i * FLASH_PAGE_SIZE(bluenrgx_info);
424                 bank->sectors[i].size = FLASH_PAGE_SIZE(bluenrgx_info);
425                 bank->sectors[i].is_erased = -1;
426                 bank->sectors[i].is_protected = 0;
427         }
428
429         bluenrgx_info->probed = true;
430         bluenrgx_info->die_id = die_id;
431
432         return ERROR_OK;
433 }
434
435 static int bluenrgx_auto_probe(struct flash_bank *bank)
436 {
437         struct bluenrgx_flash_bank *bluenrgx_info = bank->driver_priv;
438
439         if (bluenrgx_info->probed)
440                 return ERROR_OK;
441
442         return bluenrgx_probe(bank);
443 }
444
445 /* This method must return a string displaying information about the bank */
446 static int bluenrgx_get_info(struct flash_bank *bank, struct command_invocation *cmd)
447 {
448         struct bluenrgx_flash_bank *bluenrgx_info = bank->driver_priv;
449         int mask_number, cut_number;
450
451         if (!bluenrgx_info->probed) {
452                 int retval = bluenrgx_probe(bank);
453                 if (retval != ERROR_OK) {
454                         command_print_sameline(cmd, "Unable to find bank information.");
455                         return retval;
456                 }
457         }
458
459         mask_number = (bluenrgx_info->die_id >> 4) & 0xF;
460         cut_number = bluenrgx_info->die_id & 0xF;
461
462         command_print_sameline(cmd, "%s - Rev: %d.%d",
463                         bluenrgx_info->flash_ptr->part_name, mask_number, cut_number);
464         return ERROR_OK;
465 }
466
467 const struct flash_driver bluenrgx_flash = {
468         .name = "bluenrg-x",
469         .flash_bank_command = bluenrgx_flash_bank_command,
470         .erase = bluenrgx_erase,
471         .protect = NULL,
472         .write = bluenrgx_write,
473         .read = default_flash_read,
474         .probe = bluenrgx_probe,
475         .erase_check = default_flash_blank_check,
476         .protect_check = NULL,
477         .auto_probe = bluenrgx_auto_probe,
478         .info = bluenrgx_get_info,
479 };