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 (CC26XX_BUFFER_FULL == status) {
111 retval = target_read_u32(target, status_addr, &status);
112 if (ERROR_OK != retval)
115 elapsed_ms = timeval_ms() - start_ms;
116 if (elapsed_ms > 500)
118 if (elapsed_ms > FLASH_TIMEOUT)
122 if (CC26XX_BUFFER_EMPTY != status) {
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 (ERROR_OK != retval)
142 /* Check for working area to use for flash helper algorithm */
143 if (NULL != cc26xx_bank->working_area)
144 target_free_working_area(target, cc26xx_bank->working_area);
145 retval = target_alloc_working_area(target, cc26xx_bank->algo_working_size,
146 &cc26xx_bank->working_area);
147 if (ERROR_OK != retval)
150 /* Confirm the defined working address is the area we need to use */
151 if (CC26XX_ALGO_BASE_ADDRESS != cc26xx_bank->working_area->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 (ERROR_OK != retval) {
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);
164 /* Initialize the ARMv7 specific info to run the algorithm */
165 cc26xx_bank->armv7m_info.common_magic = ARMV7M_COMMON_MAGIC;
166 cc26xx_bank->armv7m_info.core_mode = ARM_MODE_THREAD;
168 /* Begin executing the flash helper algorithm */
169 retval = target_start_algorithm(target, 0, NULL, 0, NULL,
170 CC26XX_ALGO_BASE_ADDRESS, 0, &cc26xx_bank->armv7m_info);
171 if (ERROR_OK != retval) {
172 LOG_ERROR("%s: Failed to start flash helper algorithm",
173 cc26xx_bank->family_name);
174 target_free_working_area(target, cc26xx_bank->working_area);
179 * At this point, the algorithm is running on the target and
180 * ready to receive commands and data to flash the target
186 static int cc26xx_quit(struct flash_bank *bank)
188 struct target *target = bank->target;
189 struct cc26xx_bank *cc26xx_bank = bank->driver_priv;
193 /* Regardless of the algo's status, attempt to halt the target */
194 (void)target_halt(target);
196 /* Now confirm target halted and clean up from flash helper algorithm */
197 retval = target_wait_algorithm(target, 0, NULL, 0, NULL, 0, FLASH_TIMEOUT,
198 &cc26xx_bank->armv7m_info);
200 target_free_working_area(target, cc26xx_bank->working_area);
201 cc26xx_bank->working_area = NULL;
206 static int cc26xx_mass_erase(struct flash_bank *bank)
208 struct target *target = bank->target;
209 struct cc26xx_bank *cc26xx_bank = bank->driver_priv;
210 struct cc26xx_algo_params algo_params;
214 if (TARGET_HALTED != target->state) {
215 LOG_ERROR("Target not halted");
216 return ERROR_TARGET_NOT_HALTED;
219 retval = cc26xx_init(bank);
220 if (ERROR_OK != retval)
223 /* Initialize algorithm parameters */
224 buf_set_u32(algo_params.address, 0, 32, 0);
225 buf_set_u32(algo_params.length, 0, 32, 4);
226 buf_set_u32(algo_params.command, 0, 32, CC26XX_CMD_ERASE_ALL);
227 buf_set_u32(algo_params.status, 0, 32, CC26XX_BUFFER_FULL);
229 /* Issue flash helper algorithm parameters for mass erase */
230 retval = target_write_buffer(target, cc26xx_bank->params_addr[0],
231 sizeof(algo_params), (uint8_t *)&algo_params);
233 /* Wait for command to complete */
234 if (ERROR_OK == retval)
235 retval = cc26xx_wait_algo_done(bank, cc26xx_bank->params_addr[0]);
237 /* Regardless of errors, try to close down algo */
238 (void)cc26xx_quit(bank);
243 FLASH_BANK_COMMAND_HANDLER(cc26xx_flash_bank_command)
245 struct cc26xx_bank *cc26xx_bank;
248 return ERROR_COMMAND_SYNTAX_ERROR;
250 cc26xx_bank = malloc(sizeof(struct cc26xx_bank));
251 if (NULL == cc26xx_bank)
254 /* Initialize private flash information */
255 memset((void *)cc26xx_bank, 0x00, sizeof(struct cc26xx_bank));
256 cc26xx_bank->family_name = "cc26xx";
257 cc26xx_bank->device_type = CC26XX_NO_TYPE;
258 cc26xx_bank->sector_length = 0x1000;
260 /* Finish initialization of bank */
261 bank->driver_priv = cc26xx_bank;
267 static int cc26xx_erase(struct flash_bank *bank, unsigned int first,
270 struct target *target = bank->target;
271 struct cc26xx_bank *cc26xx_bank = bank->driver_priv;
272 struct cc26xx_algo_params algo_params;
278 if (TARGET_HALTED != target->state) {
279 LOG_ERROR("Target not halted");
280 return ERROR_TARGET_NOT_HALTED;
283 /* Do a mass erase if user requested all sectors of flash */
284 if ((first == 0) && (last == (bank->num_sectors - 1))) {
285 /* Request mass erase of flash */
286 return cc26xx_mass_erase(bank);
289 address = first * cc26xx_bank->sector_length;
290 length = (last - first + 1) * cc26xx_bank->sector_length;
292 retval = cc26xx_init(bank);
293 if (ERROR_OK != retval)
296 /* Set up algorithm parameters for erase command */
297 buf_set_u32(algo_params.address, 0, 32, address);
298 buf_set_u32(algo_params.length, 0, 32, length);
299 buf_set_u32(algo_params.command, 0, 32, CC26XX_CMD_ERASE_SECTORS);
300 buf_set_u32(algo_params.status, 0, 32, CC26XX_BUFFER_FULL);
302 /* Issue flash helper algorithm parameters for erase */
303 retval = target_write_buffer(target, cc26xx_bank->params_addr[0],
304 sizeof(algo_params), (uint8_t *)&algo_params);
306 /* If no error, wait for erase to finish */
307 if (ERROR_OK == retval)
308 retval = cc26xx_wait_algo_done(bank, cc26xx_bank->params_addr[0]);
310 /* Regardless of errors, try to close down algo */
311 (void)cc26xx_quit(bank);
316 static int cc26xx_write(struct flash_bank *bank, const uint8_t *buffer,
317 uint32_t offset, uint32_t count)
319 struct target *target = bank->target;
320 struct cc26xx_bank *cc26xx_bank = bank->driver_priv;
321 struct cc26xx_algo_params algo_params[2];
324 long long elapsed_ms;
330 if (TARGET_HALTED != target->state) {
331 LOG_ERROR("Target not halted");
332 return ERROR_TARGET_NOT_HALTED;
335 retval = cc26xx_init(bank);
336 if (ERROR_OK != retval)
339 /* Initialize algorithm parameters to default values */
340 buf_set_u32(algo_params[0].command, 0, 32, CC26XX_CMD_PROGRAM);
341 buf_set_u32(algo_params[1].command, 0, 32, CC26XX_CMD_PROGRAM);
343 /* Write requested data, ping-ponging between two buffers */
345 start_ms = timeval_ms();
346 address = bank->base + offset;
349 if (count > cc26xx_bank->sector_length)
350 size = cc26xx_bank->sector_length;
354 /* Put next block of data to flash into buffer */
355 retval = target_write_buffer(target, cc26xx_bank->buffer_addr[index],
357 if (ERROR_OK != retval) {
358 LOG_ERROR("Unable to write data to target memory");
362 /* Update algo parameters for next block */
363 buf_set_u32(algo_params[index].address, 0, 32, address);
364 buf_set_u32(algo_params[index].length, 0, 32, size);
365 buf_set_u32(algo_params[index].status, 0, 32, CC26XX_BUFFER_FULL);
367 /* Issue flash helper algorithm parameters for block write */
368 retval = target_write_buffer(target, cc26xx_bank->params_addr[index],
369 sizeof(algo_params[index]), (uint8_t *)&algo_params[index]);
370 if (ERROR_OK != retval)
373 /* Wait for next ping pong buffer to be ready */
375 retval = cc26xx_wait_algo_done(bank, cc26xx_bank->params_addr[index]);
376 if (ERROR_OK != retval)
383 elapsed_ms = timeval_ms() - start_ms;
384 if (elapsed_ms > 500)
388 /* If no error yet, wait for last buffer to finish */
389 if (ERROR_OK == retval) {
391 retval = cc26xx_wait_algo_done(bank, cc26xx_bank->params_addr[index]);
394 /* Regardless of errors, try to close down algo */
395 (void)cc26xx_quit(bank);
400 static int cc26xx_probe(struct flash_bank *bank)
402 struct target *target = bank->target;
403 struct cc26xx_bank *cc26xx_bank = bank->driver_priv;
405 uint32_t sector_length;
412 retval = target_read_u32(target, FCFG1_ICEPICK_ID, &value);
413 if (ERROR_OK != retval)
415 cc26xx_bank->icepick_id = value;
417 retval = target_read_u32(target, FCFG1_USER_ID, &value);
418 if (ERROR_OK != retval)
420 cc26xx_bank->user_id = value;
422 cc26xx_bank->device_type = cc26xx_device_type(cc26xx_bank->icepick_id,
423 cc26xx_bank->user_id);
425 sector_length = cc26xx_sector_length(cc26xx_bank->icepick_id);
427 /* Set up appropriate flash helper algorithm */
428 switch (cc26xx_bank->icepick_id & ICEPICK_ID_MASK) {
429 case CC26X0_ICEPICK_ID:
430 case CC26X1_ICEPICK_ID:
431 case CC13X0_ICEPICK_ID:
432 /* Chameleon family device */
433 cc26xx_bank->algo_code = cc26x0_algo;
434 cc26xx_bank->algo_size = sizeof(cc26x0_algo);
435 cc26xx_bank->algo_working_size = CC26X0_WORKING_SIZE;
436 cc26xx_bank->buffer_addr[0] = CC26X0_ALGO_BUFFER_0;
437 cc26xx_bank->buffer_addr[1] = CC26X0_ALGO_BUFFER_1;
438 cc26xx_bank->params_addr[0] = CC26X0_ALGO_PARAMS_0;
439 cc26xx_bank->params_addr[1] = CC26X0_ALGO_PARAMS_1;
440 max_sectors = CC26X0_MAX_SECTORS;
442 case CC13X2_CC26X2_ICEPICK_ID:
444 /* Agama family device */
445 cc26xx_bank->algo_code = cc26x2_algo;
446 cc26xx_bank->algo_size = sizeof(cc26x2_algo);
447 cc26xx_bank->algo_working_size = CC26X2_WORKING_SIZE;
448 cc26xx_bank->buffer_addr[0] = CC26X2_ALGO_BUFFER_0;
449 cc26xx_bank->buffer_addr[1] = CC26X2_ALGO_BUFFER_1;
450 cc26xx_bank->params_addr[0] = CC26X2_ALGO_PARAMS_0;
451 cc26xx_bank->params_addr[1] = CC26X2_ALGO_PARAMS_1;
452 max_sectors = CC26X2_MAX_SECTORS;
456 retval = target_read_u32(target, CC26XX_FLASH_SIZE_INFO, &value);
457 if (ERROR_OK != retval)
459 num_sectors = value & 0xff;
460 if (num_sectors > max_sectors)
461 num_sectors = max_sectors;
463 bank->sectors = malloc(sizeof(struct flash_sector) * num_sectors);
464 if (NULL == bank->sectors)
467 bank->base = CC26XX_FLASH_BASE_ADDR;
468 bank->num_sectors = num_sectors;
469 bank->size = num_sectors * sector_length;
470 bank->write_start_alignment = 0;
471 bank->write_end_alignment = 0;
472 cc26xx_bank->sector_length = sector_length;
474 for (int i = 0; i < num_sectors; i++) {
475 bank->sectors[i].offset = i * sector_length;
476 bank->sectors[i].size = sector_length;
477 bank->sectors[i].is_erased = -1;
478 bank->sectors[i].is_protected = 0;
481 /* We've successfully determined the stats on the flash bank */
482 cc26xx_bank->probed = true;
484 /* If we fall through to here, then all went well */
489 static int cc26xx_auto_probe(struct flash_bank *bank)
491 struct cc26xx_bank *cc26xx_bank = bank->driver_priv;
493 int retval = ERROR_OK;
495 if (!cc26xx_bank->probed)
496 retval = cc26xx_probe(bank);
501 static int cc26xx_info(struct flash_bank *bank, struct command_invocation *cmd)
503 struct cc26xx_bank *cc26xx_bank = bank->driver_priv;
506 switch (cc26xx_bank->device_type) {
524 device = "Unrecognized";
528 command_print_sameline(cmd,
529 "%s device: ICEPick ID 0x%08" PRIx32 ", USER ID 0x%08" PRIx32 "\n",
530 device, cc26xx_bank->icepick_id, cc26xx_bank->user_id);
535 const struct flash_driver cc26xx_flash = {
537 .flash_bank_command = cc26xx_flash_bank_command,
538 .erase = cc26xx_erase,
539 .write = cc26xx_write,
540 .read = default_flash_read,
541 .probe = cc26xx_probe,
542 .auto_probe = cc26xx_auto_probe,
543 .erase_check = default_flash_blank_check,
545 .free_driver_priv = default_flash_free_driver_priv,