1 // SPDX-License-Identifier: GPL-2.0-or-later
3 /***************************************************************************
4 * Copyright (C) 2017 by Texas Instruments, Inc. *
5 ***************************************************************************/
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
22 const char *family_name
;
26 uint32_t sector_length
;
28 struct working_area
*working_area
;
29 struct armv7m_algorithm armv7m_info
;
30 const uint8_t *algo_code
;
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
;
57 case CC26X1_ICEPICK_ID
:
58 device_type
= CC26X1_TYPE
;
60 case CC13X0_ICEPICK_ID
:
61 device_type
= CC13X0_TYPE
;
63 case CC13X2_CC26X2_ICEPICK_ID
:
65 if ((user_id
& USER_ID_CC13_MASK
) != 0)
66 device_type
= CC13X2_TYPE
;
68 device_type
= CC26X2_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
;
86 case CC13X2_CC26X2_ICEPICK_ID
:
88 /* Agama family device */
89 sector_length
= CC26X2_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
;
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
)
114 elapsed_ms
= timeval_ms() - start_ms
;
115 if (elapsed_ms
> 500)
117 if (elapsed_ms
> FLASH_TIMEOUT
)
121 if (status
!= CC26XX_BUFFER_EMPTY
) {
122 LOG_ERROR("%s: Flash operation failed", cc26xx_bank
->family_name
);
129 static int cc26xx_init(struct flash_bank
*bank
)
131 struct target
*target
= bank
->target
;
132 struct cc26xx_bank
*cc26xx_bank
= bank
->driver_priv
;
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
)
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
)
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
;
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
;
181 * At this point, the algorithm is running on the target and
182 * ready to receive commands and data to flash the target
188 static int cc26xx_quit(struct flash_bank
*bank
)
190 struct target
*target
= bank
->target
;
191 struct cc26xx_bank
*cc26xx_bank
= bank
->driver_priv
;
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
;
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
;
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
)
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
);
245 FLASH_BANK_COMMAND_HANDLER(cc26xx_flash_bank_command
)
247 struct cc26xx_bank
*cc26xx_bank
;
250 return ERROR_COMMAND_SYNTAX_ERROR
;
252 cc26xx_bank
= malloc(sizeof(struct cc26xx_bank
));
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
;
268 static int cc26xx_erase(struct flash_bank
*bank
, unsigned int first
,
271 struct target
*target
= bank
->target
;
272 struct cc26xx_bank
*cc26xx_bank
= bank
->driver_priv
;
273 struct cc26xx_algo_params algo_params
;
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
)
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
);
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];
325 long long elapsed_ms
;
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
)
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 */
346 start_ms
= timeval_ms();
347 address
= bank
->base
+ offset
;
350 if (count
> cc26xx_bank
->sector_length
)
351 size
= cc26xx_bank
->sector_length
;
355 /* Put next block of data to flash into buffer */
356 retval
= target_write_buffer(target
, cc26xx_bank
->buffer_addr
[index
],
358 if (retval
!= ERROR_OK
) {
359 LOG_ERROR("Unable to write data to target memory");
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
)
374 /* Wait for next ping pong buffer to be ready */
376 retval
= cc26xx_wait_algo_done(bank
, cc26xx_bank
->params_addr
[index
]);
377 if (retval
!= ERROR_OK
)
384 elapsed_ms
= timeval_ms() - start_ms
;
385 if (elapsed_ms
> 500)
389 /* If no error yet, wait for last buffer to finish */
390 if (retval
== ERROR_OK
) {
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
);
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
;
413 retval
= target_read_u32(target
, FCFG1_ICEPICK_ID
, &value
);
414 if (retval
!= ERROR_OK
)
416 cc26xx_bank
->icepick_id
= value
;
418 retval
= target_read_u32(target
, FCFG1_USER_ID
, &value
);
419 if (retval
!= ERROR_OK
)
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
;
443 case CC13X2_CC26X2_ICEPICK_ID
:
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
;
457 retval
= target_read_u32(target
, CC26XX_FLASH_SIZE_INFO
, &value
);
458 if (retval
!= ERROR_OK
)
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
);
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 */
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
);
502 static int cc26xx_info(struct flash_bank
*bank
, struct command_invocation
*cmd
)
504 struct cc26xx_bank
*cc26xx_bank
= bank
->driver_priv
;
507 switch (cc26xx_bank
->device_type
) {
525 device
= "Unrecognized";
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
);
536 const struct flash_driver cc26xx_flash
= {
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
,
546 .free_driver_priv
= default_flash_free_driver_priv
,