flash/nor/avrf: add ATmega32U4 support
[openocd.git] / src / flash / nor / cc26xx.c
blob6256ba6e712b72e4b2afada1455ae231d0afe408
1 // SPDX-License-Identifier: GPL-2.0-or-later
3 /***************************************************************************
4 * Copyright (C) 2017 by Texas Instruments, Inc. *
5 ***************************************************************************/
7 #ifdef HAVE_CONFIG_H
8 #include "config.h"
9 #endif
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>
19 #define FLASH_TIMEOUT 8000
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];
37 /* Flash helper algorithm for CC26x0 Chameleon targets */
38 static const uint8_t cc26x0_algo[] = {
39 #include "../../../contrib/loaders/flash/cc26xx/cc26x0_algo.inc"
42 /* Flash helper algorithm for CC26x2 Agama targets */
43 static const uint8_t cc26x2_algo[] = {
44 #include "../../../contrib/loaders/flash/cc26xx/cc26x2_algo.inc"
47 static int cc26xx_auto_probe(struct flash_bank *bank);
49 static uint32_t cc26xx_device_type(uint32_t icepick_id, uint32_t user_id)
51 uint32_t device_type = 0;
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;
72 return device_type;
75 static uint32_t cc26xx_sector_length(uint32_t icepick_id)
77 uint32_t sector_length;
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;
93 return sector_length;
96 static int cc26xx_wait_algo_done(struct flash_bank *bank, uint32_t params_addr)
98 struct target *target = bank->target;
99 struct cc26xx_bank *cc26xx_bank = bank->driver_priv;
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;
106 int retval = ERROR_OK;
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;
114 elapsed_ms = timeval_ms() - start_ms;
115 if (elapsed_ms > 500)
116 keep_alive();
117 if (elapsed_ms > FLASH_TIMEOUT)
118 break;
121 if (status != CC26XX_BUFFER_EMPTY) {
122 LOG_ERROR("%s: Flash operation failed", cc26xx_bank->family_name);
123 return ERROR_FAIL;
126 return ERROR_OK;
129 static int cc26xx_init(struct flash_bank *bank)
131 struct target *target = bank->target;
132 struct cc26xx_bank *cc26xx_bank = bank->driver_priv;
134 int retval;
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;
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;
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;
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;
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;
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;
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;
181 * At this point, the algorithm is running on the target and
182 * ready to receive commands and data to flash the target
185 return retval;
188 static int cc26xx_quit(struct flash_bank *bank)
190 struct target *target = bank->target;
191 struct cc26xx_bank *cc26xx_bank = bank->driver_priv;
193 int retval;
195 /* Regardless of the algo's status, attempt to halt the target */
196 (void)target_halt(target);
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);
202 target_free_working_area(target, cc26xx_bank->working_area);
203 cc26xx_bank->working_area = NULL;
205 return retval;
208 static int cc26xx_mass_erase(struct flash_bank *bank)
210 struct target *target = bank->target;
211 struct cc26xx_bank *cc26xx_bank = bank->driver_priv;
212 struct cc26xx_algo_params algo_params;
214 int retval;
216 if (target->state != TARGET_HALTED) {
217 LOG_ERROR("Target not halted");
218 return ERROR_TARGET_NOT_HALTED;
221 retval = cc26xx_init(bank);
222 if (retval != ERROR_OK)
223 return retval;
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);
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);
235 /* Wait for command to complete */
236 if (retval == ERROR_OK)
237 retval = cc26xx_wait_algo_done(bank, cc26xx_bank->params_addr[0]);
239 /* Regardless of errors, try to close down algo */
240 (void)cc26xx_quit(bank);
242 return retval;
245 FLASH_BANK_COMMAND_HANDLER(cc26xx_flash_bank_command)
247 struct cc26xx_bank *cc26xx_bank;
249 if (CMD_ARGC < 6)
250 return ERROR_COMMAND_SYNTAX_ERROR;
252 cc26xx_bank = malloc(sizeof(struct cc26xx_bank));
253 if (!cc26xx_bank)
254 return ERROR_FAIL;
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;
262 /* Finish initialization of bank */
263 bank->driver_priv = cc26xx_bank;
264 bank->next = NULL;
266 return ERROR_OK;
269 static int cc26xx_erase(struct flash_bank *bank, unsigned int first,
270 unsigned int last)
272 struct target *target = bank->target;
273 struct cc26xx_bank *cc26xx_bank = bank->driver_priv;
274 struct cc26xx_algo_params algo_params;
276 uint32_t address;
277 uint32_t length;
278 int retval;
280 if (target->state != TARGET_HALTED) {
281 LOG_ERROR("Target not halted");
282 return ERROR_TARGET_NOT_HALTED;
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);
291 address = first * cc26xx_bank->sector_length;
292 length = (last - first + 1) * cc26xx_bank->sector_length;
294 retval = cc26xx_init(bank);
295 if (retval != ERROR_OK)
296 return retval;
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);
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);
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]);
312 /* Regardless of errors, try to close down algo */
313 (void)cc26xx_quit(bank);
315 return retval;
318 static int cc26xx_write(struct flash_bank *bank, const uint8_t *buffer,
319 uint32_t offset, uint32_t count)
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;
329 uint32_t index;
330 int retval;
332 if (target->state != TARGET_HALTED) {
333 LOG_ERROR("Target not halted");
334 return ERROR_TARGET_NOT_HALTED;
337 retval = cc26xx_init(bank);
338 if (retval != ERROR_OK)
339 return retval;
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);
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) {
351 if (count > cc26xx_bank->sector_length)
352 size = cc26xx_bank->sector_length;
353 else
354 size = count;
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;
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);
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;
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;
381 count -= size;
382 buffer += size;
383 address += size;
385 elapsed_ms = timeval_ms() - start_ms;
386 if (elapsed_ms > 500)
387 keep_alive();
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]);
396 /* Regardless of errors, try to close down algo */
397 (void)cc26xx_quit(bank);
399 return retval;
402 static int cc26xx_probe(struct flash_bank *bank)
404 struct target *target = bank->target;
405 struct cc26xx_bank *cc26xx_bank = bank->driver_priv;
407 uint32_t sector_length;
408 uint32_t value;
409 int num_sectors;
410 int max_sectors;
412 int retval;
414 retval = target_read_u32(target, FCFG1_ICEPICK_ID, &value);
415 if (retval != ERROR_OK)
416 return retval;
417 cc26xx_bank->icepick_id = value;
419 retval = target_read_u32(target, FCFG1_USER_ID, &value);
420 if (retval != ERROR_OK)
421 return retval;
422 cc26xx_bank->user_id = value;
424 cc26xx_bank->device_type = cc26xx_device_type(cc26xx_bank->icepick_id,
425 cc26xx_bank->user_id);
427 sector_length = cc26xx_sector_length(cc26xx_bank->icepick_id);
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;
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;
465 bank->sectors = malloc(sizeof(struct flash_sector) * num_sectors);
466 if (!bank->sectors)
467 return ERROR_FAIL;
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;
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;
483 /* We've successfully determined the stats on the flash bank */
484 cc26xx_bank->probed = true;
486 /* If we fall through to here, then all went well */
488 return ERROR_OK;
491 static int cc26xx_auto_probe(struct flash_bank *bank)
493 struct cc26xx_bank *cc26xx_bank = bank->driver_priv;
495 int retval = ERROR_OK;
497 if (!cc26xx_bank->probed)
498 retval = cc26xx_probe(bank);
500 return retval;
503 static int cc26xx_info(struct flash_bank *bank, struct command_invocation *cmd)
505 struct cc26xx_bank *cc26xx_bank = bank->driver_priv;
506 const char *device;
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;
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);
534 return ERROR_OK;
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,