f1b2062019edf1a550dca1a7a65b160f44e2b2f4
[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 <target/algorithm.h>
24 #include <target/armv7m.h>
25 #include <target/cortex_m.h>
26 #include "imp.h"
27
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
44
45 struct bluenrgx_flash_bank {
46         int probed;
47         uint32_t idcode;
48         uint32_t die_id;
49 };
50
51 static int bluenrgx_protect_check(struct flash_bank *bank)
52 {
53         /* Nothing to do. Protection is only handled in SW. */
54         return ERROR_OK;
55 }
56
57 /* flash_bank bluenrg-x 0 0 0 0 <target#> */
58 FLASH_BANK_COMMAND_HANDLER(bluenrgx_flash_bank_command)
59 {
60         struct bluenrgx_flash_bank *bluenrgx_info;
61         /* Create the bank structure */
62         bluenrgx_info = calloc(1, sizeof(*bluenrgx_info));
63
64         /* Check allocation */
65         if (bluenrgx_info == NULL) {
66                 LOG_ERROR("failed to allocate bank structure");
67                 return ERROR_FAIL;
68         }
69
70         bank->driver_priv = bluenrgx_info;
71
72         bluenrgx_info->probed = 0;
73
74         if (CMD_ARGC < 6)
75                 return ERROR_COMMAND_SYNTAX_ERROR;
76
77         return ERROR_OK;
78 }
79
80 static int bluenrgx_erase(struct flash_bank *bank, int first, int last)
81 {
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;
88
89         /* check preconditions */
90         if (bluenrgx_info->probed == 0)
91                 return ERROR_FLASH_BANK_NOT_PROBED;
92
93         if (bank->target->state != TARGET_HALTED) {
94                 LOG_ERROR("Target not halted");
95                 return ERROR_TARGET_NOT_HALTED;
96         }
97         /* Disable blue module */
98         if (target_write_u32(target, 0x200000c0, 0) != ERROR_OK) {
99                 LOG_ERROR("Blue disable failed");
100                 return ERROR_FAIL;
101         }
102
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;
109                 }
110
111                 if (target_write_u32(target, FLASH_REG_ADDRESS, address >> 2) != ERROR_OK) {
112                         LOG_ERROR("Register write failed");
113                         return ERROR_FAIL;
114                 }
115
116                 if (target_write_u32(target, FLASH_REG_COMMAND, command) != ERROR_OK) {
117                         LOG_ERROR("Register write failed");
118                         return ERROR_FAIL;
119                 }
120
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;
126                         }
127                         if (value & FLASH_INT_CMDDONE)
128                                 break;
129                         if (i == 99) {
130                                 LOG_ERROR("Mass erase command failed (timeout)");
131                                 retval = ERROR_FAIL;
132                         }
133                 }
134
135         } else {
136                 command = FLASH_CMD_ERASE_PAGE;
137                 for (int i = first; i <= last; i++) {
138                         address = bank->base+i*FLASH_PAGE_SIZE;
139
140                         if (target_write_u32(target, FLASH_REG_IRQRAW, 0x3f) != ERROR_OK) {
141                                 LOG_ERROR("Register write failed");
142                                 return ERROR_FAIL;
143                         }
144
145                         if (target_write_u32(target, FLASH_REG_ADDRESS, address >> 2) != ERROR_OK) {
146                                 LOG_ERROR("Register write failed");
147                                 return ERROR_FAIL;
148                         }
149
150                         if (target_write_u32(target, FLASH_REG_COMMAND, command) != ERROR_OK) {
151                                 LOG_ERROR("Failed");
152                                 return ERROR_FAIL;
153                         }
154
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;
160                                 }
161                                 if (value & FLASH_INT_CMDDONE)
162                                         break;
163                                 if (j == 99) {
164                                         LOG_ERROR("Erase command failed (timeout)");
165                                         retval = ERROR_FAIL;
166                                 }
167                         }
168                 }
169         }
170
171         return retval;
172
173 }
174
175 static int bluenrgx_protect(struct flash_bank *bank, int set, int first, int last)
176 {
177         /* Protection is only handled in software: no hardware write protection
178            available in BlueNRG-x devices */
179         int sector;
180
181         for (sector = first; sector <= last; sector++)
182                 bank->sectors[sector].is_protected = set;
183         return ERROR_OK;
184 }
185 static int bluenrgx_write_word(struct target *target, uint32_t address_base, uint8_t *values, uint32_t count)
186 {
187         int retval = ERROR_OK;
188
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;
193         }
194
195         for (uint32_t i = 0; i < count; i++) {
196                 uint32_t address = address_base + i * FLASH_WORD_LEN;
197
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;
202                 }
203
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;
208                 }
209
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;
214                 }
215
216                 for (int j = 0; j < 100; j++) {
217                         uint32_t reg_value;
218                         retval = target_read_u32(target, FLASH_REG_IRQRAW, &reg_value);
219
220                         if (retval != ERROR_OK) {
221                                 LOG_ERROR("Register read failed, error code: %d", retval);
222                                 return retval;
223                         }
224
225                         if (reg_value & FLASH_INT_CMDDONE)
226                                 break;
227
228                         if (j == 99) {
229                                 LOG_ERROR("Write command failed (timeout)");
230                                 return ERROR_FAIL;
231                         }
232                 }
233         }
234         return retval;
235 }
236
237 static int bluenrgx_write_bytes(struct target *target, uint32_t address_base, uint8_t *buffer, uint32_t count)
238 {
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;
242
243         if (count == 0) {
244                 /* Just return if there are no bytes to write */
245                 return retval;
246         }
247
248         if (address_base & 3) {
249                 pre_bytes = address_base & 3;
250                 pre_address = address_base - pre_bytes;
251         }
252
253         if ((count + pre_bytes) & 3) {
254                 post_bytes = ((count + pre_bytes + 3) & ~3) - (count + pre_bytes);
255                 post_address = (address_base + count) & ~3;
256         }
257
258         if (pre_bytes || post_bytes) {
259                 uint32_t old_count = count;
260
261                 count = old_count + pre_bytes + post_bytes;
262
263                 new_buffer = malloc(count);
264
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;
269                 }
270
271                 LOG_INFO("Requested number of bytes to write and/or address not word aligned (%" PRIu32 "), extending to %"
272                          PRIu32 " ", old_count, count);
273
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;
279                         }
280
281                 }
282
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;
288                         }
289
290                 }
291
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;
296         }
297
298         retval = bluenrgx_write_word(target, address_base - pre_bytes, buffer, count/4);
299
300         if (new_buffer)
301                 free(new_buffer);
302
303         return retval;
304 }
305
306 static int bluenrgx_write(struct flash_bank *bank, const uint8_t *buffer,
307                           uint32_t offset, uint32_t count)
308 {
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;
320
321         /* See contrib/loaders/flash/bluenrg-x/bluenrg-x_write.c for source and
322          * hints how to generate the data!
323          */
324         static const uint8_t bluenrgx_flash_write_code[] = {
325 #include "../../../contrib/loaders/flash/bluenrg-x/bluenrg-x_write.inc"
326         };
327
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;
333         }
334
335         if (bank->target->state != TARGET_HALTED) {
336                 LOG_ERROR("Target not halted");
337                 return ERROR_TARGET_NOT_HALTED;
338         }
339
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;
347
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);
351
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;
357         }
358
359         /* Program chunk 16 bytes aligned in fast mode */
360         if (fast_size) {
361
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;
366                 }
367
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;
373
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;
378                 }
379
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;
385                 }
386
387                 armv7m_info.common_magic = ARMV7M_COMMON_MAGIC;
388                 armv7m_info.core_mode = ARM_MODE_THREAD;
389
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);
395
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);
406
407                 LOG_DEBUG("source->address = " TARGET_ADDR_FMT, source->address);
408                 LOG_DEBUG("source->address+ source->size = " TARGET_ADDR_FMT, source->address+source->size);
409                 LOG_DEBUG("write_algorithm_sp->address = " TARGET_ADDR_FMT, write_algorithm_sp->address);
410                 LOG_DEBUG("address = %08x", address+pre_size);
411                 LOG_DEBUG("count = %08x", count);
412
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 */
417                                                           0,
418                                                           NULL,
419                                                           5,
420                                                           reg_params,
421                                                           source->address,
422                                                           source->size,
423                                                           write_algorithm->address,
424                                                           0,
425                                                           &armv7m_info);
426
427                 if (retval == ERROR_FLASH_OPERATION_FAILED) {
428                         LOG_ERROR("error executing bluenrg-x flash write algorithm");
429
430                         uint32_t error = buf_get_u32(reg_params[0].value, 0, 32);
431
432                         if (error != 0)
433                                 LOG_ERROR("flash write failed = %08" PRIx32, error);
434                 }
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;
443                                 }
444                         }
445                 }
446                 target_free_working_area(target, source);
447                 target_free_working_area(target, write_algorithm);
448                 target_free_working_area(target, write_algorithm_sp);
449
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;
457
458         }
459
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;
465         }
466         return retval;
467 }
468
469 static int bluenrgx_probe(struct flash_bank *bank)
470 {
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;
480
481         retval = target_read_u32(bank->target, DIE_ID_REG, &die_id);
482         if (retval != ERROR_OK)
483                 return retval;
484
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);
489
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;
495         }
496
497         bluenrgx_info->probed = 1;
498         bluenrgx_info->die_id = die_id;
499         bluenrgx_info->idcode = idcode;
500         return ERROR_OK;
501 }
502
503 static int bluenrgx_auto_probe(struct flash_bank *bank)
504 {
505         struct bluenrgx_flash_bank *bluenrgx_info = bank->driver_priv;
506
507         if (bluenrgx_info->probed)
508                 return ERROR_OK;
509
510         return bluenrgx_probe(bank);
511 }
512
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)
515 {
516         struct bluenrgx_flash_bank *bluenrgx_info = bank->driver_priv;
517         int mask_number, cut_number;
518         char *part_name;
519
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;
526                 }
527         }
528
529         if (bluenrgx_info->idcode == BLUENRG2_IDCODE)
530                 part_name = "BLUENRG-2";
531         else
532                 part_name = "BLUENRG-1";
533
534         mask_number = (bluenrgx_info->die_id >> 4) & 0xF;
535         cut_number = bluenrgx_info->die_id & 0xF;
536
537         snprintf(buf, buf_size,
538                  "%s - Rev: %d.%d", part_name, mask_number, cut_number);
539         return ERROR_OK;
540 }
541
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,
554 };