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

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)