target/xtensa: avoid IHI for writes to non-executable memory
[openocd.git] / src / flash / nor / cc26xx.c
blob54d61421ce272088a161a7214f11650948e4a910
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;
265 return ERROR_OK;
268 static int cc26xx_erase(struct flash_bank *bank, unsigned int first,
269 unsigned int last)
271 struct target *target = bank->target;
272 struct cc26xx_bank *cc26xx_bank = bank->driver_priv;
273 struct cc26xx_algo_params algo_params;
275 uint32_t address;
276 uint32_t length;
277 int retval;
279 if (target->state != TARGET_HALTED) {
280 LOG_ERROR("Target not halted");
281 return ERROR_TARGET_NOT_HALTED;
284 /* Do a mass erase if user requested all sectors of flash */
285 if ((first == 0) && (last == (bank->num_sectors - 1))) {
286 /* Request mass erase of flash */
287 return cc26xx_mass_erase(bank);
290 address = first * cc26xx_bank->sector_length;
291 length = (last - first + 1) * cc26xx_bank->sector_length;
293 retval = cc26xx_init(bank);
294 if (retval != ERROR_OK)
295 return retval;
297 /* Set up algorithm parameters for erase command */
298 buf_set_u32(algo_params.address, 0, 32, address);
299 buf_set_u32(algo_params.length, 0, 32, length);
300 buf_set_u32(algo_params.command, 0, 32, CC26XX_CMD_ERASE_SECTORS);
301 buf_set_u32(algo_params.status, 0, 32, CC26XX_BUFFER_FULL);
303 /* Issue flash helper algorithm parameters for erase */
304 retval = target_write_buffer(target, cc26xx_bank->params_addr[0],
305 sizeof(algo_params), (uint8_t *)&algo_params);
307 /* If no error, wait for erase to finish */
308 if (retval == ERROR_OK)
309 retval = cc26xx_wait_algo_done(bank, cc26xx_bank->params_addr[0]);
311 /* Regardless of errors, try to close down algo */
312 (void)cc26xx_quit(bank);
314 return retval;
317 static int cc26xx_write(struct flash_bank *bank, const uint8_t *buffer,
318 uint32_t offset, uint32_t count)
320 struct target *target = bank->target;
321 struct cc26xx_bank *cc26xx_bank = bank->driver_priv;
322 struct cc26xx_algo_params algo_params[2];
323 uint32_t size = 0;
324 long long start_ms;
325 long long elapsed_ms;
326 uint32_t address;
328 uint32_t index;
329 int retval;
331 if (target->state != TARGET_HALTED) {
332 LOG_ERROR("Target not halted");
333 return ERROR_TARGET_NOT_HALTED;
336 retval = cc26xx_init(bank);
337 if (retval != ERROR_OK)
338 return retval;
340 /* Initialize algorithm parameters to default values */
341 buf_set_u32(algo_params[0].command, 0, 32, CC26XX_CMD_PROGRAM);
342 buf_set_u32(algo_params[1].command, 0, 32, CC26XX_CMD_PROGRAM);
344 /* Write requested data, ping-ponging between two buffers */
345 index = 0;
346 start_ms = timeval_ms();
347 address = bank->base + offset;
348 while (count > 0) {
350 if (count > cc26xx_bank->sector_length)
351 size = cc26xx_bank->sector_length;
352 else
353 size = count;
355 /* Put next block of data to flash into buffer */
356 retval = target_write_buffer(target, cc26xx_bank->buffer_addr[index],
357 size, buffer);
358 if (retval != ERROR_OK) {
359 LOG_ERROR("Unable to write data to target memory");
360 break;
363 /* Update algo parameters for next block */
364 buf_set_u32(algo_params[index].address, 0, 32, address);
365 buf_set_u32(algo_params[index].length, 0, 32, size);
366 buf_set_u32(algo_params[index].status, 0, 32, CC26XX_BUFFER_FULL);
368 /* Issue flash helper algorithm parameters for block write */
369 retval = target_write_buffer(target, cc26xx_bank->params_addr[index],
370 sizeof(algo_params[index]), (uint8_t *)&algo_params[index]);
371 if (retval != ERROR_OK)
372 break;
374 /* Wait for next ping pong buffer to be ready */
375 index ^= 1;
376 retval = cc26xx_wait_algo_done(bank, cc26xx_bank->params_addr[index]);
377 if (retval != ERROR_OK)
378 break;
380 count -= size;
381 buffer += size;
382 address += size;
384 elapsed_ms = timeval_ms() - start_ms;
385 if (elapsed_ms > 500)
386 keep_alive();
389 /* If no error yet, wait for last buffer to finish */
390 if (retval == ERROR_OK) {
391 index ^= 1;
392 retval = cc26xx_wait_algo_done(bank, cc26xx_bank->params_addr[index]);
395 /* Regardless of errors, try to close down algo */
396 (void)cc26xx_quit(bank);
398 return retval;
401 static int cc26xx_probe(struct flash_bank *bank)
403 struct target *target = bank->target;
404 struct cc26xx_bank *cc26xx_bank = bank->driver_priv;
406 uint32_t sector_length;
407 uint32_t value;
408 int num_sectors;
409 int max_sectors;
411 int retval;
413 retval = target_read_u32(target, FCFG1_ICEPICK_ID, &value);
414 if (retval != ERROR_OK)
415 return retval;
416 cc26xx_bank->icepick_id = value;
418 retval = target_read_u32(target, FCFG1_USER_ID, &value);
419 if (retval != ERROR_OK)
420 return retval;
421 cc26xx_bank->user_id = value;
423 cc26xx_bank->device_type = cc26xx_device_type(cc26xx_bank->icepick_id,
424 cc26xx_bank->user_id);
426 sector_length = cc26xx_sector_length(cc26xx_bank->icepick_id);
428 /* Set up appropriate flash helper algorithm */
429 switch (cc26xx_bank->icepick_id & ICEPICK_ID_MASK) {
430 case CC26X0_ICEPICK_ID:
431 case CC26X1_ICEPICK_ID:
432 case CC13X0_ICEPICK_ID:
433 /* Chameleon family device */
434 cc26xx_bank->algo_code = cc26x0_algo;
435 cc26xx_bank->algo_size = sizeof(cc26x0_algo);
436 cc26xx_bank->algo_working_size = CC26X0_WORKING_SIZE;
437 cc26xx_bank->buffer_addr[0] = CC26X0_ALGO_BUFFER_0;
438 cc26xx_bank->buffer_addr[1] = CC26X0_ALGO_BUFFER_1;
439 cc26xx_bank->params_addr[0] = CC26X0_ALGO_PARAMS_0;
440 cc26xx_bank->params_addr[1] = CC26X0_ALGO_PARAMS_1;
441 max_sectors = CC26X0_MAX_SECTORS;
442 break;
443 case CC13X2_CC26X2_ICEPICK_ID:
444 default:
445 /* Agama family device */
446 cc26xx_bank->algo_code = cc26x2_algo;
447 cc26xx_bank->algo_size = sizeof(cc26x2_algo);
448 cc26xx_bank->algo_working_size = CC26X2_WORKING_SIZE;
449 cc26xx_bank->buffer_addr[0] = CC26X2_ALGO_BUFFER_0;
450 cc26xx_bank->buffer_addr[1] = CC26X2_ALGO_BUFFER_1;
451 cc26xx_bank->params_addr[0] = CC26X2_ALGO_PARAMS_0;
452 cc26xx_bank->params_addr[1] = CC26X2_ALGO_PARAMS_1;
453 max_sectors = CC26X2_MAX_SECTORS;
454 break;
457 retval = target_read_u32(target, CC26XX_FLASH_SIZE_INFO, &value);
458 if (retval != ERROR_OK)
459 return retval;
460 num_sectors = value & 0xff;
461 if (num_sectors > max_sectors)
462 num_sectors = max_sectors;
464 bank->sectors = malloc(sizeof(struct flash_sector) * num_sectors);
465 if (!bank->sectors)
466 return ERROR_FAIL;
468 bank->base = CC26XX_FLASH_BASE_ADDR;
469 bank->num_sectors = num_sectors;
470 bank->size = num_sectors * sector_length;
471 bank->write_start_alignment = 0;
472 bank->write_end_alignment = 0;
473 cc26xx_bank->sector_length = sector_length;
475 for (int i = 0; i < num_sectors; i++) {
476 bank->sectors[i].offset = i * sector_length;
477 bank->sectors[i].size = sector_length;
478 bank->sectors[i].is_erased = -1;
479 bank->sectors[i].is_protected = 0;
482 /* We've successfully determined the stats on the flash bank */
483 cc26xx_bank->probed = true;
485 /* If we fall through to here, then all went well */
487 return ERROR_OK;
490 static int cc26xx_auto_probe(struct flash_bank *bank)
492 struct cc26xx_bank *cc26xx_bank = bank->driver_priv;
494 int retval = ERROR_OK;
496 if (!cc26xx_bank->probed)
497 retval = cc26xx_probe(bank);
499 return retval;
502 static int cc26xx_info(struct flash_bank *bank, struct command_invocation *cmd)
504 struct cc26xx_bank *cc26xx_bank = bank->driver_priv;
505 const char *device;
507 switch (cc26xx_bank->device_type) {
508 case CC26X0_TYPE:
509 device = "CC26x0";
510 break;
511 case CC26X1_TYPE:
512 device = "CC26x1";
513 break;
514 case CC13X0_TYPE:
515 device = "CC13x0";
516 break;
517 case CC13X2_TYPE:
518 device = "CC13x2";
519 break;
520 case CC26X2_TYPE:
521 device = "CC26x2";
522 break;
523 case CC26XX_NO_TYPE:
524 default:
525 device = "Unrecognized";
526 break;
529 command_print_sameline(cmd,
530 "%s device: ICEPick ID 0x%08" PRIx32 ", USER ID 0x%08" PRIx32 "\n",
531 device, cc26xx_bank->icepick_id, cc26xx_bank->user_id);
533 return ERROR_OK;
536 const struct flash_driver cc26xx_flash = {
537 .name = "cc26xx",
538 .flash_bank_command = cc26xx_flash_bank_command,
539 .erase = cc26xx_erase,
540 .write = cc26xx_write,
541 .read = default_flash_read,
542 .probe = cc26xx_probe,
543 .auto_probe = cc26xx_auto_probe,
544 .erase_check = default_flash_blank_check,
545 .info = cc26xx_info,
546 .free_driver_priv = default_flash_free_driver_priv,