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

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)