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 static int cc26xx_auto_probe(struct flash_bank *bank);
39 static uint32_t cc26xx_device_type(uint32_t icepick_id, uint32_t user_id)
41 uint32_t device_type = 0;
43 switch (icepick_id & ICEPICK_ID_MASK) {
44 case CC26X0_ICEPICK_ID:
45 device_type = CC26X0_TYPE;
47 case CC26X1_ICEPICK_ID:
48 device_type = CC26X1_TYPE;
50 case CC13X0_ICEPICK_ID:
51 device_type = CC13X0_TYPE;
53 case CC13X2_CC26X2_ICEPICK_ID:
55 if ((user_id & USER_ID_CC13_MASK) != 0)
56 device_type = CC13X2_TYPE;
58 device_type = CC26X2_TYPE;
65 static uint32_t cc26xx_sector_length(uint32_t icepick_id)
67 uint32_t sector_length;
69 switch (icepick_id & ICEPICK_ID_MASK) {
70 case CC26X0_ICEPICK_ID:
71 case CC26X1_ICEPICK_ID:
72 case CC13X0_ICEPICK_ID:
73 /* Chameleon family device */
74 sector_length = CC26X0_SECTOR_LENGTH;
76 case CC13X2_CC26X2_ICEPICK_ID:
78 /* Agama family device */
79 sector_length = CC26X2_SECTOR_LENGTH;
86 static int cc26xx_wait_algo_done(struct flash_bank *bank, uint32_t params_addr)
88 struct target *target = bank->target;
89 struct cc26xx_bank *cc26xx_bank = bank->driver_priv;
91 uint32_t status_addr = params_addr + CC26XX_STATUS_OFFSET;
92 uint32_t status = CC26XX_BUFFER_FULL;
96 int retval = ERROR_OK;
98 start_ms = timeval_ms();
99 while (status == CC26XX_BUFFER_FULL) {
100 retval = target_read_u32(target, status_addr, &status);
101 if (retval != ERROR_OK)
104 elapsed_ms = timeval_ms() - start_ms;
105 if (elapsed_ms > 500)
107 if (elapsed_ms > FLASH_TIMEOUT)
111 if (status != CC26XX_BUFFER_EMPTY) {
112 LOG_ERROR("%s: Flash operation failed", cc26xx_bank->family_name);
119 static int cc26xx_init(struct flash_bank *bank)
121 struct target *target = bank->target;
122 struct cc26xx_bank *cc26xx_bank = bank->driver_priv;
126 /* Make sure we've probed the flash to get the device and size */
127 retval = cc26xx_auto_probe(bank);
128 if (retval != ERROR_OK)
131 /* Check for working area to use for flash helper algorithm */
132 target_free_working_area(target, cc26xx_bank->working_area);
133 cc26xx_bank->working_area = NULL;
135 retval = target_alloc_working_area(target, cc26xx_bank->algo_working_size,
136 &cc26xx_bank->working_area);
137 if (retval != ERROR_OK)
140 /* Confirm the defined working address is the area we need to use */
141 if (cc26xx_bank->working_area->address != CC26XX_ALGO_BASE_ADDRESS)
142 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
144 /* Write flash helper algorithm into target memory */
145 retval = target_write_buffer(target, CC26XX_ALGO_BASE_ADDRESS,
146 cc26xx_bank->algo_size, cc26xx_bank->algo_code);
147 if (retval != ERROR_OK) {
148 LOG_ERROR("%s: Failed to load flash helper algorithm",
149 cc26xx_bank->family_name);
150 target_free_working_area(target, cc26xx_bank->working_area);
151 cc26xx_bank->working_area = NULL;
155 /* Initialize the ARMv7 specific info to run the algorithm */
156 cc26xx_bank->armv7m_info.common_magic = ARMV7M_COMMON_MAGIC;
157 cc26xx_bank->armv7m_info.core_mode = ARM_MODE_THREAD;
159 /* Begin executing the flash helper algorithm */
160 retval = target_start_algorithm(target, 0, NULL, 0, NULL,
161 CC26XX_ALGO_BASE_ADDRESS, 0, &cc26xx_bank->armv7m_info);
162 if (retval != ERROR_OK) {
163 LOG_ERROR("%s: Failed to start flash helper algorithm",
164 cc26xx_bank->family_name);
165 target_free_working_area(target, cc26xx_bank->working_area);
166 cc26xx_bank->working_area = NULL;
171 * At this point, the algorithm is running on the target and
172 * ready to receive commands and data to flash the target
178 static int cc26xx_quit(struct flash_bank *bank)
180 struct target *target = bank->target;
181 struct cc26xx_bank *cc26xx_bank = bank->driver_priv;
185 /* Regardless of the algo's status, attempt to halt the target */
186 (void)target_halt(target);
188 /* Now confirm target halted and clean up from flash helper algorithm */
189 retval = target_wait_algorithm(target, 0, NULL, 0, NULL, 0, FLASH_TIMEOUT,
190 &cc26xx_bank->armv7m_info);
192 target_free_working_area(target, cc26xx_bank->working_area);
193 cc26xx_bank->working_area = NULL;
198 static int cc26xx_mass_erase(struct flash_bank *bank)
200 struct target *target = bank->target;
201 struct cc26xx_bank *cc26xx_bank = bank->driver_priv;
202 struct cc26xx_algo_params algo_params;
206 if (target->state != TARGET_HALTED) {
207 LOG_ERROR("Target not halted");
208 return ERROR_TARGET_NOT_HALTED;
211 retval = cc26xx_init(bank);
212 if (retval != ERROR_OK)
215 /* Initialize algorithm parameters */
216 buf_set_u32(algo_params.address, 0, 32, 0);
217 buf_set_u32(algo_params.length, 0, 32, 4);
218 buf_set_u32(algo_params.command, 0, 32, CC26XX_CMD_ERASE_ALL);
219 buf_set_u32(algo_params.status, 0, 32, CC26XX_BUFFER_FULL);
221 /* Issue flash helper algorithm parameters for mass erase */
222 retval = target_write_buffer(target, cc26xx_bank->params_addr[0],
223 sizeof(algo_params), (uint8_t *)&algo_params);
225 /* Wait for command to complete */
226 if (retval == ERROR_OK)
227 retval = cc26xx_wait_algo_done(bank, cc26xx_bank->params_addr[0]);
229 /* Regardless of errors, try to close down algo */
230 (void)cc26xx_quit(bank);
235 FLASH_BANK_COMMAND_HANDLER(cc26xx_flash_bank_command)
237 struct cc26xx_bank *cc26xx_bank;
240 return ERROR_COMMAND_SYNTAX_ERROR;
242 cc26xx_bank = malloc(sizeof(struct cc26xx_bank));
246 /* Initialize private flash information */
247 memset((void *)cc26xx_bank, 0x00, sizeof(struct cc26xx_bank));
248 cc26xx_bank->family_name = "cc26xx";
249 cc26xx_bank->device_type = CC26XX_NO_TYPE;
250 cc26xx_bank->sector_length = 0x1000;
252 /* Finish initialization of bank */
253 bank->driver_priv = cc26xx_bank;
259 static int cc26xx_erase(struct flash_bank *bank, unsigned int first,
262 struct target *target = bank->target;
263 struct cc26xx_bank *cc26xx_bank = bank->driver_priv;
264 struct cc26xx_algo_params algo_params;
270 if (target->state != TARGET_HALTED) {
271 LOG_ERROR("Target not halted");
272 return ERROR_TARGET_NOT_HALTED;
275 /* Do a mass erase if user requested all sectors of flash */
276 if ((first == 0) && (last == (bank->num_sectors - 1))) {
277 /* Request mass erase of flash */
278 return cc26xx_mass_erase(bank);
281 address = first * cc26xx_bank->sector_length;
282 length = (last - first + 1) * cc26xx_bank->sector_length;
284 retval = cc26xx_init(bank);
285 if (retval != ERROR_OK)
288 /* Set up algorithm parameters for erase command */
289 buf_set_u32(algo_params.address, 0, 32, address);
290 buf_set_u32(algo_params.length, 0, 32, length);
291 buf_set_u32(algo_params.command, 0, 32, CC26XX_CMD_ERASE_SECTORS);
292 buf_set_u32(algo_params.status, 0, 32, CC26XX_BUFFER_FULL);
294 /* Issue flash helper algorithm parameters for erase */
295 retval = target_write_buffer(target, cc26xx_bank->params_addr[0],
296 sizeof(algo_params), (uint8_t *)&algo_params);
298 /* If no error, wait for erase to finish */
299 if (retval == ERROR_OK)
300 retval = cc26xx_wait_algo_done(bank, cc26xx_bank->params_addr[0]);
302 /* Regardless of errors, try to close down algo */
303 (void)cc26xx_quit(bank);
308 static int cc26xx_write(struct flash_bank *bank, const uint8_t *buffer,
309 uint32_t offset, uint32_t count)
311 struct target *target = bank->target;
312 struct cc26xx_bank *cc26xx_bank = bank->driver_priv;
313 struct cc26xx_algo_params algo_params[2];
316 long long elapsed_ms;
322 if (target->state != TARGET_HALTED) {
323 LOG_ERROR("Target not halted");
324 return ERROR_TARGET_NOT_HALTED;
327 retval = cc26xx_init(bank);
328 if (retval != ERROR_OK)
331 /* Initialize algorithm parameters to default values */
332 buf_set_u32(algo_params[0].command, 0, 32, CC26XX_CMD_PROGRAM);
333 buf_set_u32(algo_params[1].command, 0, 32, CC26XX_CMD_PROGRAM);
335 /* Write requested data, ping-ponging between two buffers */
337 start_ms = timeval_ms();
338 address = bank->base + offset;
341 if (count > cc26xx_bank->sector_length)
342 size = cc26xx_bank->sector_length;
346 /* Put next block of data to flash into buffer */
347 retval = target_write_buffer(target, cc26xx_bank->buffer_addr[index],
349 if (retval != ERROR_OK) {
350 LOG_ERROR("Unable to write data to target memory");
354 /* Update algo parameters for next block */
355 buf_set_u32(algo_params[index].address, 0, 32, address);
356 buf_set_u32(algo_params[index].length, 0, 32, size);
357 buf_set_u32(algo_params[index].status, 0, 32, CC26XX_BUFFER_FULL);
359 /* Issue flash helper algorithm parameters for block write */
360 retval = target_write_buffer(target, cc26xx_bank->params_addr[index],
361 sizeof(algo_params[index]), (uint8_t *)&algo_params[index]);
362 if (retval != ERROR_OK)
365 /* Wait for next ping pong buffer to be ready */
367 retval = cc26xx_wait_algo_done(bank, cc26xx_bank->params_addr[index]);
368 if (retval != ERROR_OK)
375 elapsed_ms = timeval_ms() - start_ms;
376 if (elapsed_ms > 500)
380 /* If no error yet, wait for last buffer to finish */
381 if (retval == ERROR_OK) {
383 retval = cc26xx_wait_algo_done(bank, cc26xx_bank->params_addr[index]);
386 /* Regardless of errors, try to close down algo */
387 (void)cc26xx_quit(bank);
392 static int cc26xx_probe(struct flash_bank *bank)
394 struct target *target = bank->target;
395 struct cc26xx_bank *cc26xx_bank = bank->driver_priv;
397 uint32_t sector_length;
404 retval = target_read_u32(target, FCFG1_ICEPICK_ID, &value);
405 if (retval != ERROR_OK)
407 cc26xx_bank->icepick_id = value;
409 retval = target_read_u32(target, FCFG1_USER_ID, &value);
410 if (retval != ERROR_OK)
412 cc26xx_bank->user_id = value;
414 cc26xx_bank->device_type = cc26xx_device_type(cc26xx_bank->icepick_id,
415 cc26xx_bank->user_id);
417 sector_length = cc26xx_sector_length(cc26xx_bank->icepick_id);
419 /* Set up appropriate flash helper algorithm */
420 switch (cc26xx_bank->icepick_id & ICEPICK_ID_MASK) {
421 case CC26X0_ICEPICK_ID:
422 case CC26X1_ICEPICK_ID:
423 case CC13X0_ICEPICK_ID:
424 /* Chameleon family device */
425 cc26xx_bank->algo_code = cc26x0_algo;
426 cc26xx_bank->algo_size = sizeof(cc26x0_algo);
427 cc26xx_bank->algo_working_size = CC26X0_WORKING_SIZE;
428 cc26xx_bank->buffer_addr[0] = CC26X0_ALGO_BUFFER_0;
429 cc26xx_bank->buffer_addr[1] = CC26X0_ALGO_BUFFER_1;
430 cc26xx_bank->params_addr[0] = CC26X0_ALGO_PARAMS_0;
431 cc26xx_bank->params_addr[1] = CC26X0_ALGO_PARAMS_1;
432 max_sectors = CC26X0_MAX_SECTORS;
434 case CC13X2_CC26X2_ICEPICK_ID:
436 /* Agama family device */
437 cc26xx_bank->algo_code = cc26x2_algo;
438 cc26xx_bank->algo_size = sizeof(cc26x2_algo);
439 cc26xx_bank->algo_working_size = CC26X2_WORKING_SIZE;
440 cc26xx_bank->buffer_addr[0] = CC26X2_ALGO_BUFFER_0;
441 cc26xx_bank->buffer_addr[1] = CC26X2_ALGO_BUFFER_1;
442 cc26xx_bank->params_addr[0] = CC26X2_ALGO_PARAMS_0;
443 cc26xx_bank->params_addr[1] = CC26X2_ALGO_PARAMS_1;
444 max_sectors = CC26X2_MAX_SECTORS;
448 retval = target_read_u32(target, CC26XX_FLASH_SIZE_INFO, &value);
449 if (retval != ERROR_OK)
451 num_sectors = value & 0xff;
452 if (num_sectors > max_sectors)
453 num_sectors = max_sectors;
455 bank->sectors = malloc(sizeof(struct flash_sector) * num_sectors);
459 bank->base = CC26XX_FLASH_BASE_ADDR;
460 bank->num_sectors = num_sectors;
461 bank->size = num_sectors * sector_length;
462 bank->write_start_alignment = 0;
463 bank->write_end_alignment = 0;
464 cc26xx_bank->sector_length = sector_length;
466 for (int i = 0; i < num_sectors; i++) {
467 bank->sectors[i].offset = i * sector_length;
468 bank->sectors[i].size = sector_length;
469 bank->sectors[i].is_erased = -1;
470 bank->sectors[i].is_protected = 0;
473 /* We've successfully determined the stats on the flash bank */
474 cc26xx_bank->probed = true;
476 /* If we fall through to here, then all went well */
481 static int cc26xx_auto_probe(struct flash_bank *bank)
483 struct cc26xx_bank *cc26xx_bank = bank->driver_priv;
485 int retval = ERROR_OK;
487 if (!cc26xx_bank->probed)
488 retval = cc26xx_probe(bank);
493 static int cc26xx_info(struct flash_bank *bank, struct command_invocation *cmd)
495 struct cc26xx_bank *cc26xx_bank = bank->driver_priv;
498 switch (cc26xx_bank->device_type) {
516 device = "Unrecognized";
520 command_print_sameline(cmd,
521 "%s device: ICEPick ID 0x%08" PRIx32 ", USER ID 0x%08" PRIx32 "\n",
522 device, cc26xx_bank->icepick_id, cc26xx_bank->user_id);
527 const struct flash_driver cc26xx_flash = {
529 .flash_bank_command = cc26xx_flash_bank_command,
530 .erase = cc26xx_erase,
531 .write = cc26xx_write,
532 .read = default_flash_read,
533 .probe = cc26xx_probe,
534 .auto_probe = cc26xx_auto_probe,
535 .erase_check = default_flash_blank_check,
537 .free_driver_priv = default_flash_free_driver_priv,