openocd: src/flash: replace the GPL-2.0-or-later license tag
[openocd.git] / src / flash / nor / cc26xx.c
1 /* SPDX-License-Identifier: GPL-2.0-or-later */
2
3 /***************************************************************************
4 * Copyright (C) 2017 by Texas Instruments, Inc. *
5 ***************************************************************************/
6
7 #ifdef HAVE_CONFIG_H
8 #include "config.h"
9 #endif
10
11 #include "imp.h"
12 #include "cc26xx.h"
13 #include <helper/binarybuffer.h>
14 #include <helper/time_support.h>
15 #include <target/algorithm.h>
16 #include <target/armv7m.h>
17 #include <target/image.h>
18
19 #define FLASH_TIMEOUT 8000
20
21 struct cc26xx_bank {
22 const char *family_name;
23 uint32_t icepick_id;
24 uint32_t user_id;
25 uint32_t device_type;
26 uint32_t sector_length;
27 bool probed;
28 struct working_area *working_area;
29 struct armv7m_algorithm armv7m_info;
30 const uint8_t *algo_code;
31 uint32_t algo_size;
32 uint32_t algo_working_size;
33 uint32_t buffer_addr[2];
34 uint32_t params_addr[2];
35 };
36
37 static int cc26xx_auto_probe(struct flash_bank *bank);
38
39 static uint32_t cc26xx_device_type(uint32_t icepick_id, uint32_t user_id)
40 {
41 uint32_t device_type = 0;
42
43 switch (icepick_id & ICEPICK_ID_MASK) {
44 case CC26X0_ICEPICK_ID:
45 device_type = CC26X0_TYPE;
46 break;
47 case CC26X1_ICEPICK_ID:
48 device_type = CC26X1_TYPE;
49 break;
50 case CC13X0_ICEPICK_ID:
51 device_type = CC13X0_TYPE;
52 break;
53 case CC13X2_CC26X2_ICEPICK_ID:
54 default:
55 if ((user_id & USER_ID_CC13_MASK) != 0)
56 device_type = CC13X2_TYPE;
57 else
58 device_type = CC26X2_TYPE;
59 break;
60 }
61
62 return device_type;
63 }
64
65 static uint32_t cc26xx_sector_length(uint32_t icepick_id)
66 {
67 uint32_t sector_length;
68
69 switch (icepick_id & ICEPICK_ID_MASK) {
70 case CC26X0_ICEPICK_ID:
71 case CC26X1_ICEPICK_ID:
72 case CC13X0_ICEPICK_ID:
73 /* Chameleon family device */
74 sector_length = CC26X0_SECTOR_LENGTH;
75 break;
76 case CC13X2_CC26X2_ICEPICK_ID:
77 default:
78 /* Agama family device */
79 sector_length = CC26X2_SECTOR_LENGTH;
80 break;
81 }
82
83 return sector_length;
84 }
85
86 static int cc26xx_wait_algo_done(struct flash_bank *bank, uint32_t params_addr)
87 {
88 struct target *target = bank->target;
89 struct cc26xx_bank *cc26xx_bank = bank->driver_priv;
90
91 uint32_t status_addr = params_addr + CC26XX_STATUS_OFFSET;
92 uint32_t status = CC26XX_BUFFER_FULL;
93 long long start_ms;
94 long long elapsed_ms;
95
96 int retval = ERROR_OK;
97
98 start_ms = timeval_ms();
99 while (status == CC26XX_BUFFER_FULL) {
100 retval = target_read_u32(target, status_addr, &status);
101 if (retval != ERROR_OK)
102 return retval;
103
104 elapsed_ms = timeval_ms() - start_ms;
105 if (elapsed_ms > 500)
106 keep_alive();
107 if (elapsed_ms > FLASH_TIMEOUT)
108 break;
109 };
110
111 if (status != CC26XX_BUFFER_EMPTY) {
112 LOG_ERROR("%s: Flash operation failed", cc26xx_bank->family_name);
113 return ERROR_FAIL;
114 }
115
116 return ERROR_OK;
117 }
118
119 static int cc26xx_init(struct flash_bank *bank)
120 {
121 struct target *target = bank->target;
122 struct cc26xx_bank *cc26xx_bank = bank->driver_priv;
123
124 int retval;
125
126 /* Make sure we've probed the flash to get the device and size */
127 retval = cc26xx_auto_probe(bank);
128 if (retval != ERROR_OK)
129 return retval;
130
131 /* Check for working area to use for flash helper algorithm */
132 target_free_working_area(target, cc26xx_bank->working_area);
133 cc26xx_bank->working_area = NULL;
134
135 retval = target_alloc_working_area(target, cc26xx_bank->algo_working_size,
136 &cc26xx_bank->working_area);
137 if (retval != ERROR_OK)
138 return retval;
139
140 /* Confirm the defined working address is the area we need to use */
141 if (cc26xx_bank->working_area->address != CC26XX_ALGO_BASE_ADDRESS)
142 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
143
144 /* Write flash helper algorithm into target memory */
145 retval = target_write_buffer(target, CC26XX_ALGO_BASE_ADDRESS,
146 cc26xx_bank->algo_size, cc26xx_bank->algo_code);
147 if (retval != ERROR_OK) {
148 LOG_ERROR("%s: Failed to load flash helper algorithm",
149 cc26xx_bank->family_name);
150 target_free_working_area(target, cc26xx_bank->working_area);
151 cc26xx_bank->working_area = NULL;
152 return retval;
153 }
154
155 /* Initialize the ARMv7 specific info to run the algorithm */
156 cc26xx_bank->armv7m_info.common_magic = ARMV7M_COMMON_MAGIC;
157 cc26xx_bank->armv7m_info.core_mode = ARM_MODE_THREAD;
158
159 /* Begin executing the flash helper algorithm */
160 retval = target_start_algorithm(target, 0, NULL, 0, NULL,
161 CC26XX_ALGO_BASE_ADDRESS, 0, &cc26xx_bank->armv7m_info);
162 if (retval != ERROR_OK) {
163 LOG_ERROR("%s: Failed to start flash helper algorithm",
164 cc26xx_bank->family_name);
165 target_free_working_area(target, cc26xx_bank->working_area);
166 cc26xx_bank->working_area = NULL;
167 return retval;
168 }
169
170 /*
171 * At this point, the algorithm is running on the target and
172 * ready to receive commands and data to flash the target
173 */
174
175 return retval;
176 }
177
178 static int cc26xx_quit(struct flash_bank *bank)
179 {
180 struct target *target = bank->target;
181 struct cc26xx_bank *cc26xx_bank = bank->driver_priv;
182
183 int retval;
184
185 /* Regardless of the algo's status, attempt to halt the target */
186 (void)target_halt(target);
187
188 /* Now confirm target halted and clean up from flash helper algorithm */
189 retval = target_wait_algorithm(target, 0, NULL, 0, NULL, 0, FLASH_TIMEOUT,
190 &cc26xx_bank->armv7m_info);
191
192 target_free_working_area(target, cc26xx_bank->working_area);
193 cc26xx_bank->working_area = NULL;
194
195 return retval;
196 }
197
198 static int cc26xx_mass_erase(struct flash_bank *bank)
199 {
200 struct target *target = bank->target;
201 struct cc26xx_bank *cc26xx_bank = bank->driver_priv;
202 struct cc26xx_algo_params algo_params;
203
204 int retval;
205
206 if (target->state != TARGET_HALTED) {
207 LOG_ERROR("Target not halted");
208 return ERROR_TARGET_NOT_HALTED;
209 }
210
211 retval = cc26xx_init(bank);
212 if (retval != ERROR_OK)
213 return retval;
214
215 /* Initialize algorithm parameters */
216 buf_set_u32(algo_params.address, 0, 32, 0);
217 buf_set_u32(algo_params.length, 0, 32, 4);
218 buf_set_u32(algo_params.command, 0, 32, CC26XX_CMD_ERASE_ALL);
219 buf_set_u32(algo_params.status, 0, 32, CC26XX_BUFFER_FULL);
220
221 /* Issue flash helper algorithm parameters for mass erase */
222 retval = target_write_buffer(target, cc26xx_bank->params_addr[0],
223 sizeof(algo_params), (uint8_t *)&algo_params);
224
225 /* Wait for command to complete */
226 if (retval == ERROR_OK)
227 retval = cc26xx_wait_algo_done(bank, cc26xx_bank->params_addr[0]);
228
229 /* Regardless of errors, try to close down algo */
230 (void)cc26xx_quit(bank);
231
232 return retval;
233 }
234
235 FLASH_BANK_COMMAND_HANDLER(cc26xx_flash_bank_command)
236 {
237 struct cc26xx_bank *cc26xx_bank;
238
239 if (CMD_ARGC < 6)
240 return ERROR_COMMAND_SYNTAX_ERROR;
241
242 cc26xx_bank = malloc(sizeof(struct cc26xx_bank));
243 if (!cc26xx_bank)
244 return ERROR_FAIL;
245
246 /* Initialize private flash information */
247 memset((void *)cc26xx_bank, 0x00, sizeof(struct cc26xx_bank));
248 cc26xx_bank->family_name = "cc26xx";
249 cc26xx_bank->device_type = CC26XX_NO_TYPE;
250 cc26xx_bank->sector_length = 0x1000;
251
252 /* Finish initialization of bank */
253 bank->driver_priv = cc26xx_bank;
254 bank->next = NULL;
255
256 return ERROR_OK;
257 }
258
259 static int cc26xx_erase(struct flash_bank *bank, unsigned int first,
260 unsigned int last)
261 {
262 struct target *target = bank->target;
263 struct cc26xx_bank *cc26xx_bank = bank->driver_priv;
264 struct cc26xx_algo_params algo_params;
265
266 uint32_t address;
267 uint32_t length;
268 int retval;
269
270 if (target->state != TARGET_HALTED) {
271 LOG_ERROR("Target not halted");
272 return ERROR_TARGET_NOT_HALTED;
273 }
274
275 /* Do a mass erase if user requested all sectors of flash */
276 if ((first == 0) && (last == (bank->num_sectors - 1))) {
277 /* Request mass erase of flash */
278 return cc26xx_mass_erase(bank);
279 }
280
281 address = first * cc26xx_bank->sector_length;
282 length = (last - first + 1) * cc26xx_bank->sector_length;
283
284 retval = cc26xx_init(bank);
285 if (retval != ERROR_OK)
286 return retval;
287
288 /* Set up algorithm parameters for erase command */
289 buf_set_u32(algo_params.address, 0, 32, address);
290 buf_set_u32(algo_params.length, 0, 32, length);
291 buf_set_u32(algo_params.command, 0, 32, CC26XX_CMD_ERASE_SECTORS);
292 buf_set_u32(algo_params.status, 0, 32, CC26XX_BUFFER_FULL);
293
294 /* Issue flash helper algorithm parameters for erase */
295 retval = target_write_buffer(target, cc26xx_bank->params_addr[0],
296 sizeof(algo_params), (uint8_t *)&algo_params);
297
298 /* If no error, wait for erase to finish */
299 if (retval == ERROR_OK)
300 retval = cc26xx_wait_algo_done(bank, cc26xx_bank->params_addr[0]);
301
302 /* Regardless of errors, try to close down algo */
303 (void)cc26xx_quit(bank);
304
305 return retval;
306 }
307
308 static int cc26xx_write(struct flash_bank *bank, const uint8_t *buffer,
309 uint32_t offset, uint32_t count)
310 {
311 struct target *target = bank->target;
312 struct cc26xx_bank *cc26xx_bank = bank->driver_priv;
313 struct cc26xx_algo_params algo_params[2];
314 uint32_t size = 0;
315 long long start_ms;
316 long long elapsed_ms;
317 uint32_t address;
318
319 uint32_t index;
320 int retval;
321
322 if (target->state != TARGET_HALTED) {
323 LOG_ERROR("Target not halted");
324 return ERROR_TARGET_NOT_HALTED;
325 }
326
327 retval = cc26xx_init(bank);
328 if (retval != ERROR_OK)
329 return retval;
330
331 /* Initialize algorithm parameters to default values */
332 buf_set_u32(algo_params[0].command, 0, 32, CC26XX_CMD_PROGRAM);
333 buf_set_u32(algo_params[1].command, 0, 32, CC26XX_CMD_PROGRAM);
334
335 /* Write requested data, ping-ponging between two buffers */
336 index = 0;
337 start_ms = timeval_ms();
338 address = bank->base + offset;
339 while (count > 0) {
340
341 if (count > cc26xx_bank->sector_length)
342 size = cc26xx_bank->sector_length;
343 else
344 size = count;
345
346 /* Put next block of data to flash into buffer */
347 retval = target_write_buffer(target, cc26xx_bank->buffer_addr[index],
348 size, buffer);
349 if (retval != ERROR_OK) {
350 LOG_ERROR("Unable to write data to target memory");
351 break;
352 }
353
354 /* Update algo parameters for next block */
355 buf_set_u32(algo_params[index].address, 0, 32, address);
356 buf_set_u32(algo_params[index].length, 0, 32, size);
357 buf_set_u32(algo_params[index].status, 0, 32, CC26XX_BUFFER_FULL);
358
359 /* Issue flash helper algorithm parameters for block write */
360 retval = target_write_buffer(target, cc26xx_bank->params_addr[index],
361 sizeof(algo_params[index]), (uint8_t *)&algo_params[index]);
362 if (retval != ERROR_OK)
363 break;
364
365 /* Wait for next ping pong buffer to be ready */
366 index ^= 1;
367 retval = cc26xx_wait_algo_done(bank, cc26xx_bank->params_addr[index]);
368 if (retval != ERROR_OK)
369 break;
370
371 count -= size;
372 buffer += size;
373 address += size;
374
375 elapsed_ms = timeval_ms() - start_ms;
376 if (elapsed_ms > 500)
377 keep_alive();
378 }
379
380 /* If no error yet, wait for last buffer to finish */
381 if (retval == ERROR_OK) {
382 index ^= 1;
383 retval = cc26xx_wait_algo_done(bank, cc26xx_bank->params_addr[index]);
384 }
385
386 /* Regardless of errors, try to close down algo */
387 (void)cc26xx_quit(bank);
388
389 return retval;
390 }
391
392 static int cc26xx_probe(struct flash_bank *bank)
393 {
394 struct target *target = bank->target;
395 struct cc26xx_bank *cc26xx_bank = bank->driver_priv;
396
397 uint32_t sector_length;
398 uint32_t value;
399 int num_sectors;
400 int max_sectors;
401
402 int retval;
403
404 retval = target_read_u32(target, FCFG1_ICEPICK_ID, &value);
405 if (retval != ERROR_OK)
406 return retval;
407 cc26xx_bank->icepick_id = value;
408
409 retval = target_read_u32(target, FCFG1_USER_ID, &value);
410 if (retval != ERROR_OK)
411 return retval;
412 cc26xx_bank->user_id = value;
413
414 cc26xx_bank->device_type = cc26xx_device_type(cc26xx_bank->icepick_id,
415 cc26xx_bank->user_id);
416
417 sector_length = cc26xx_sector_length(cc26xx_bank->icepick_id);
418
419 /* Set up appropriate flash helper algorithm */
420 switch (cc26xx_bank->icepick_id & ICEPICK_ID_MASK) {
421 case CC26X0_ICEPICK_ID:
422 case CC26X1_ICEPICK_ID:
423 case CC13X0_ICEPICK_ID:
424 /* Chameleon family device */
425 cc26xx_bank->algo_code = cc26x0_algo;
426 cc26xx_bank->algo_size = sizeof(cc26x0_algo);
427 cc26xx_bank->algo_working_size = CC26X0_WORKING_SIZE;
428 cc26xx_bank->buffer_addr[0] = CC26X0_ALGO_BUFFER_0;
429 cc26xx_bank->buffer_addr[1] = CC26X0_ALGO_BUFFER_1;
430 cc26xx_bank->params_addr[0] = CC26X0_ALGO_PARAMS_0;
431 cc26xx_bank->params_addr[1] = CC26X0_ALGO_PARAMS_1;
432 max_sectors = CC26X0_MAX_SECTORS;
433 break;
434 case CC13X2_CC26X2_ICEPICK_ID:
435 default:
436 /* Agama family device */
437 cc26xx_bank->algo_code = cc26x2_algo;
438 cc26xx_bank->algo_size = sizeof(cc26x2_algo);
439 cc26xx_bank->algo_working_size = CC26X2_WORKING_SIZE;
440 cc26xx_bank->buffer_addr[0] = CC26X2_ALGO_BUFFER_0;
441 cc26xx_bank->buffer_addr[1] = CC26X2_ALGO_BUFFER_1;
442 cc26xx_bank->params_addr[0] = CC26X2_ALGO_PARAMS_0;
443 cc26xx_bank->params_addr[1] = CC26X2_ALGO_PARAMS_1;
444 max_sectors = CC26X2_MAX_SECTORS;
445 break;
446 }
447
448 retval = target_read_u32(target, CC26XX_FLASH_SIZE_INFO, &value);
449 if (retval != ERROR_OK)
450 return retval;
451 num_sectors = value & 0xff;
452 if (num_sectors > max_sectors)
453 num_sectors = max_sectors;
454
455 bank->sectors = malloc(sizeof(struct flash_sector) * num_sectors);
456 if (!bank->sectors)
457 return ERROR_FAIL;
458
459 bank->base = CC26XX_FLASH_BASE_ADDR;
460 bank->num_sectors = num_sectors;
461 bank->size = num_sectors * sector_length;
462 bank->write_start_alignment = 0;
463 bank->write_end_alignment = 0;
464 cc26xx_bank->sector_length = sector_length;
465
466 for (int i = 0; i < num_sectors; i++) {
467 bank->sectors[i].offset = i * sector_length;
468 bank->sectors[i].size = sector_length;
469 bank->sectors[i].is_erased = -1;
470 bank->sectors[i].is_protected = 0;
471 }
472
473 /* We've successfully determined the stats on the flash bank */
474 cc26xx_bank->probed = true;
475
476 /* If we fall through to here, then all went well */
477
478 return ERROR_OK;
479 }
480
481 static int cc26xx_auto_probe(struct flash_bank *bank)
482 {
483 struct cc26xx_bank *cc26xx_bank = bank->driver_priv;
484
485 int retval = ERROR_OK;
486
487 if (!cc26xx_bank->probed)
488 retval = cc26xx_probe(bank);
489
490 return retval;
491 }
492
493 static int cc26xx_info(struct flash_bank *bank, struct command_invocation *cmd)
494 {
495 struct cc26xx_bank *cc26xx_bank = bank->driver_priv;
496 const char *device;
497
498 switch (cc26xx_bank->device_type) {
499 case CC26X0_TYPE:
500 device = "CC26x0";
501 break;
502 case CC26X1_TYPE:
503 device = "CC26x1";
504 break;
505 case CC13X0_TYPE:
506 device = "CC13x0";
507 break;
508 case CC13X2_TYPE:
509 device = "CC13x2";
510 break;
511 case CC26X2_TYPE:
512 device = "CC26x2";
513 break;
514 case CC26XX_NO_TYPE:
515 default:
516 device = "Unrecognized";
517 break;
518 }
519
520 command_print_sameline(cmd,
521 "%s device: ICEPick ID 0x%08" PRIx32 ", USER ID 0x%08" PRIx32 "\n",
522 device, cc26xx_bank->icepick_id, cc26xx_bank->user_id);
523
524 return ERROR_OK;
525 }
526
527 const struct flash_driver cc26xx_flash = {
528 .name = "cc26xx",
529 .flash_bank_command = cc26xx_flash_bank_command,
530 .erase = cc26xx_erase,
531 .write = cc26xx_write,
532 .read = default_flash_read,
533 .probe = cc26xx_probe,
534 .auto_probe = cc26xx_auto_probe,
535 .erase_check = default_flash_blank_check,
536 .info = cc26xx_info,
537 .free_driver_priv = default_flash_free_driver_priv,
538 };

Linking to existing account procedure

If you already have an account and want to add another login method you MUST first sign in with your existing account and then change URL to read https://review.openocd.org/login/?link to get to this page again but this time it'll work for linking. Thank you.

SSH host keys fingerprints

1024 SHA256:YKx8b7u5ZWdcbp7/4AeXNaqElP49m6QrwfXaqQGJAOk gerrit-code-review@openocd.zylin.com (DSA)
384 SHA256:jHIbSQa4REvwCFG4cq5LBlBLxmxSqelQPem/EXIrxjk gerrit-code-review@openocd.org (ECDSA)
521 SHA256:UAOPYkU9Fjtcao0Ul/Rrlnj/OsQvt+pgdYSZ4jOYdgs gerrit-code-review@openocd.org (ECDSA)
256 SHA256:A13M5QlnozFOvTllybRZH6vm7iSt0XLxbA48yfc2yfY gerrit-code-review@openocd.org (ECDSA)
256 SHA256:spYMBqEYoAOtK7yZBrcwE8ZpYt6b68Cfh9yEVetvbXg gerrit-code-review@openocd.org (ED25519)
+--[ED25519 256]--+
|=..              |
|+o..   .         |
|*.o   . .        |
|+B . . .         |
|Bo. = o S        |
|Oo.+ + =         |
|oB=.* = . o      |
| =+=.+   + E     |
|. .=o   . o      |
+----[SHA256]-----+
2048 SHA256:0Onrb7/PHjpo6iVZ7xQX2riKN83FJ3KGU0TvI0TaFG4 gerrit-code-review@openocd.zylin.com (RSA)