1 /***************************************************************************
2 * Copyright (C) 2017 by Texas Instruments, Inc. *
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. *
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. *
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 ***************************************************************************/
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>
30 #define FLASH_TIMEOUT 8000
33 const char *family_name;
37 uint32_t sector_length;
39 struct working_area *working_area;
40 struct armv7m_algorithm armv7m_info;
41 const uint8_t *algo_code;
43 uint32_t algo_working_size;
44 uint32_t buffer_addr[2];
45 uint32_t params_addr[2];
48 static int cc26xx_auto_probe(struct flash_bank *bank);
50 static uint32_t cc26xx_device_type(uint32_t icepick_id, uint32_t user_id)
52 uint32_t device_type = 0;
54 switch (icepick_id & ICEPICK_ID_MASK) {
55 case CC26X0_ICEPICK_ID:
56 device_type = CC26X0_TYPE;
58 case CC26X1_ICEPICK_ID:
59 device_type = CC26X1_TYPE;
61 case CC13X0_ICEPICK_ID:
62 device_type = CC13X0_TYPE;
64 case CC13X2_CC26X2_ICEPICK_ID:
66 if ((user_id & USER_ID_CC13_MASK) != 0)
67 device_type = CC13X2_TYPE;
69 device_type = CC26X2_TYPE;
76 static uint32_t cc26xx_sector_length(uint32_t icepick_id)
78 uint32_t sector_length;
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;
87 case CC13X2_CC26X2_ICEPICK_ID:
89 /* Agama family device */
90 sector_length = CC26X2_SECTOR_LENGTH;
97 static int cc26xx_wait_algo_done(struct flash_bank *bank, uint32_t params_addr)
99 struct target *target = bank->target;
100 struct cc26xx_bank *cc26xx_bank = bank->driver_priv;
102 uint32_t status_addr = params_addr + CC26XX_STATUS_OFFSET;
103 uint32_t status = CC26XX_BUFFER_FULL;
105 long long elapsed_ms;
107 int retval = ERROR_OK;
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)
115 elapsed_ms = timeval_ms() - start_ms;
116 if (elapsed_ms > 500)
118 if (elapsed_ms > FLASH_TIMEOUT)
122 if (status != CC26XX_BUFFER_EMPTY) {
123 LOG_ERROR("%s: Flash operation failed", cc26xx_bank->family_name);
130 static int cc26xx_init(struct flash_bank *bank)
132 struct target *target = bank->target;
133 struct cc26xx_bank *cc26xx_bank = bank->driver_priv;
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)
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;
146 retval = target_alloc_working_area(target, cc26xx_bank->algo_working_size,
147 &cc26xx_bank->working_area);
148 if (retval != ERROR_OK)
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;
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;
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;
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;
182 * At this point, the algorithm is running on the target and
183 * ready to receive commands and data to flash the target
189 static int cc26xx_quit(struct flash_bank *bank)
191 struct target *target = bank->target;
192 struct cc26xx_bank *cc26xx_bank = bank->driver_priv;
196 /* Regardless of the algo's status, attempt to halt the target */
197 (void)target_halt(target);
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);
203 target_free_working_area(target, cc26xx_bank->working_area);
204 cc26xx_bank->working_area = NULL;
209 static int cc26xx_mass_erase(struct flash_bank *bank)
211 struct target *target = bank->target;
212 struct cc26xx_bank *cc26xx_bank = bank->driver_priv;
213 struct cc26xx_algo_params algo_params;
217 if (target->state != TARGET_HALTED) {
218 LOG_ERROR("Target not halted");
219 return ERROR_TARGET_NOT_HALTED;
222 retval = cc26xx_init(bank);
223 if (retval != ERROR_OK)
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);
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);
236 /* Wait for command to complete */
237 if (retval == ERROR_OK)
238 retval = cc26xx_wait_algo_done(bank, cc26xx_bank->params_addr[0]);
240 /* Regardless of errors, try to close down algo */
241 (void)cc26xx_quit(bank);
246 FLASH_BANK_COMMAND_HANDLER(cc26xx_flash_bank_command)
248 struct cc26xx_bank *cc26xx_bank;
251 return ERROR_COMMAND_SYNTAX_ERROR;
253 cc26xx_bank = malloc(sizeof(struct cc26xx_bank));
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;
263 /* Finish initialization of bank */
264 bank->driver_priv = cc26xx_bank;
270 static int cc26xx_erase(struct flash_bank *bank, unsigned int first,
273 struct target *target = bank->target;
274 struct cc26xx_bank *cc26xx_bank = bank->driver_priv;
275 struct cc26xx_algo_params algo_params;
281 if (target->state != TARGET_HALTED) {
282 LOG_ERROR("Target not halted");
283 return ERROR_TARGET_NOT_HALTED;
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);
292 address = first * cc26xx_bank->sector_length;
293 length = (last - first + 1) * cc26xx_bank->sector_length;
295 retval = cc26xx_init(bank);
296 if (retval != ERROR_OK)
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);
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);
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]);
313 /* Regardless of errors, try to close down algo */
314 (void)cc26xx_quit(bank);
319 static int cc26xx_write(struct flash_bank *bank, const uint8_t *buffer,
320 uint32_t offset, uint32_t count)
322 struct target *target = bank->target;
323 struct cc26xx_bank *cc26xx_bank = bank->driver_priv;
324 struct cc26xx_algo_params algo_params[2];
327 long long elapsed_ms;
333 if (target->state != TARGET_HALTED) {
334 LOG_ERROR("Target not halted");
335 return ERROR_TARGET_NOT_HALTED;
338 retval = cc26xx_init(bank);
339 if (retval != ERROR_OK)
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);
346 /* Write requested data, ping-ponging between two buffers */
348 start_ms = timeval_ms();
349 address = bank->base + offset;
352 if (count > cc26xx_bank->sector_length)
353 size = cc26xx_bank->sector_length;
357 /* Put next block of data to flash into buffer */
358 retval = target_write_buffer(target, cc26xx_bank->buffer_addr[index],
360 if (retval != ERROR_OK) {
361 LOG_ERROR("Unable to write data to target memory");
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);
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)
376 /* Wait for next ping pong buffer to be ready */
378 retval = cc26xx_wait_algo_done(bank, cc26xx_bank->params_addr[index]);
379 if (retval != ERROR_OK)
386 elapsed_ms = timeval_ms() - start_ms;
387 if (elapsed_ms > 500)
391 /* If no error yet, wait for last buffer to finish */
392 if (retval == ERROR_OK) {
394 retval = cc26xx_wait_algo_done(bank, cc26xx_bank->params_addr[index]);
397 /* Regardless of errors, try to close down algo */
398 (void)cc26xx_quit(bank);
403 static int cc26xx_probe(struct flash_bank *bank)
405 struct target *target = bank->target;
406 struct cc26xx_bank *cc26xx_bank = bank->driver_priv;
408 uint32_t sector_length;
415 retval = target_read_u32(target, FCFG1_ICEPICK_ID, &value);
416 if (retval != ERROR_OK)
418 cc26xx_bank->icepick_id = value;
420 retval = target_read_u32(target, FCFG1_USER_ID, &value);
421 if (retval != ERROR_OK)
423 cc26xx_bank->user_id = value;
425 cc26xx_bank->device_type = cc26xx_device_type(cc26xx_bank->icepick_id,
426 cc26xx_bank->user_id);
428 sector_length = cc26xx_sector_length(cc26xx_bank->icepick_id);
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;
445 case CC13X2_CC26X2_ICEPICK_ID:
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;
459 retval = target_read_u32(target, CC26XX_FLASH_SIZE_INFO, &value);
460 if (retval != ERROR_OK)
462 num_sectors = value & 0xff;
463 if (num_sectors > max_sectors)
464 num_sectors = max_sectors;
466 bank->sectors = malloc(sizeof(struct flash_sector) * num_sectors);
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;
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;
484 /* We've successfully determined the stats on the flash bank */
485 cc26xx_bank->probed = true;
487 /* If we fall through to here, then all went well */
492 static int cc26xx_auto_probe(struct flash_bank *bank)
494 struct cc26xx_bank *cc26xx_bank = bank->driver_priv;
496 int retval = ERROR_OK;
498 if (!cc26xx_bank->probed)
499 retval = cc26xx_probe(bank);
504 static int cc26xx_info(struct flash_bank *bank, struct command_invocation *cmd)
506 struct cc26xx_bank *cc26xx_bank = bank->driver_priv;
509 switch (cc26xx_bank->device_type) {
527 device = "Unrecognized";
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);
538 const struct flash_driver cc26xx_flash = {
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,
548 .free_driver_priv = default_flash_free_driver_priv,