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, int first, int last)
269 struct target *target = bank->target;
270 struct cc26xx_bank *cc26xx_bank = bank->driver_priv;
271 struct cc26xx_algo_params algo_params;
277 if (TARGET_HALTED != target->state) {
278 LOG_ERROR("Target not halted");
279 return ERROR_TARGET_NOT_HALTED;
282 /* Do a mass erase if user requested all sectors of flash */
283 if ((first == 0) && (last == (bank->num_sectors - 1))) {
284 /* Request mass erase of flash */
285 return cc26xx_mass_erase(bank);
288 address = first * cc26xx_bank->sector_length;
289 length = (last - first + 1) * cc26xx_bank->sector_length;
291 retval = cc26xx_init(bank);
292 if (ERROR_OK != retval)
295 /* Set up algorithm parameters for erase command */
296 buf_set_u32(algo_params.address, 0, 32, address);
297 buf_set_u32(algo_params.length, 0, 32, length);
298 buf_set_u32(algo_params.command, 0, 32, CC26XX_CMD_ERASE_SECTORS);
299 buf_set_u32(algo_params.status, 0, 32, CC26XX_BUFFER_FULL);
301 /* Issue flash helper algorithm parameters for erase */
302 retval = target_write_buffer(target, cc26xx_bank->params_addr[0],
303 sizeof(algo_params), (uint8_t *)&algo_params);
305 /* If no error, wait for erase to finish */
306 if (ERROR_OK == retval)
307 retval = cc26xx_wait_algo_done(bank, cc26xx_bank->params_addr[0]);
309 /* Regardless of errors, try to close down algo */
310 (void)cc26xx_quit(bank);
315 static int cc26xx_protect(struct flash_bank *bank, int set, int first,
321 static int cc26xx_write(struct flash_bank *bank, const uint8_t *buffer,
322 uint32_t offset, uint32_t count)
324 struct target *target = bank->target;
325 struct cc26xx_bank *cc26xx_bank = bank->driver_priv;
326 struct cc26xx_algo_params algo_params[2];
329 long long elapsed_ms;
335 if (TARGET_HALTED != target->state) {
336 LOG_ERROR("Target not halted");
337 return ERROR_TARGET_NOT_HALTED;
340 retval = cc26xx_init(bank);
341 if (ERROR_OK != retval)
344 /* Initialize algorithm parameters to default values */
345 buf_set_u32(algo_params[0].command, 0, 32, CC26XX_CMD_PROGRAM);
346 buf_set_u32(algo_params[1].command, 0, 32, CC26XX_CMD_PROGRAM);
348 /* Write requested data, ping-ponging between two buffers */
350 start_ms = timeval_ms();
351 address = bank->base + offset;
354 if (count > cc26xx_bank->sector_length)
355 size = cc26xx_bank->sector_length;
359 /* Put next block of data to flash into buffer */
360 retval = target_write_buffer(target, cc26xx_bank->buffer_addr[index],
362 if (ERROR_OK != retval) {
363 LOG_ERROR("Unable to write data to target memory");
367 /* Update algo parameters for next block */
368 buf_set_u32(algo_params[index].address, 0, 32, address);
369 buf_set_u32(algo_params[index].length, 0, 32, size);
370 buf_set_u32(algo_params[index].status, 0, 32, CC26XX_BUFFER_FULL);
372 /* Issue flash helper algorithm parameters for block write */
373 retval = target_write_buffer(target, cc26xx_bank->params_addr[index],
374 sizeof(algo_params[index]), (uint8_t *)&algo_params[index]);
375 if (ERROR_OK != retval)
378 /* Wait for next ping pong buffer to be ready */
380 retval = cc26xx_wait_algo_done(bank, cc26xx_bank->params_addr[index]);
381 if (ERROR_OK != retval)
388 elapsed_ms = timeval_ms() - start_ms;
389 if (elapsed_ms > 500)
393 /* If no error yet, wait for last buffer to finish */
394 if (ERROR_OK == retval) {
396 retval = cc26xx_wait_algo_done(bank, cc26xx_bank->params_addr[index]);
399 /* Regardless of errors, try to close down algo */
400 (void)cc26xx_quit(bank);
405 static int cc26xx_probe(struct flash_bank *bank)
407 struct target *target = bank->target;
408 struct cc26xx_bank *cc26xx_bank = bank->driver_priv;
410 uint32_t sector_length;
417 retval = target_read_u32(target, FCFG1_ICEPICK_ID, &value);
418 if (ERROR_OK != retval)
420 cc26xx_bank->icepick_id = value;
422 retval = target_read_u32(target, FCFG1_USER_ID, &value);
423 if (ERROR_OK != retval)
425 cc26xx_bank->user_id = value;
427 cc26xx_bank->device_type = cc26xx_device_type(cc26xx_bank->icepick_id,
428 cc26xx_bank->user_id);
430 sector_length = cc26xx_sector_length(cc26xx_bank->icepick_id);
432 /* Set up appropriate flash helper algorithm */
433 switch (cc26xx_bank->icepick_id & ICEPICK_ID_MASK) {
434 case CC26X0_ICEPICK_ID:
435 case CC26X1_ICEPICK_ID:
436 case CC13X0_ICEPICK_ID:
437 /* Chameleon family device */
438 cc26xx_bank->algo_code = cc26x0_algo;
439 cc26xx_bank->algo_size = sizeof(cc26x0_algo);
440 cc26xx_bank->algo_working_size = CC26X0_WORKING_SIZE;
441 cc26xx_bank->buffer_addr[0] = CC26X0_ALGO_BUFFER_0;
442 cc26xx_bank->buffer_addr[1] = CC26X0_ALGO_BUFFER_1;
443 cc26xx_bank->params_addr[0] = CC26X0_ALGO_PARAMS_0;
444 cc26xx_bank->params_addr[1] = CC26X0_ALGO_PARAMS_1;
445 max_sectors = CC26X0_MAX_SECTORS;
447 case CC13X2_CC26X2_ICEPICK_ID:
449 /* Agama family device */
450 cc26xx_bank->algo_code = cc26x2_algo;
451 cc26xx_bank->algo_size = sizeof(cc26x2_algo);
452 cc26xx_bank->algo_working_size = CC26X2_WORKING_SIZE;
453 cc26xx_bank->buffer_addr[0] = CC26X2_ALGO_BUFFER_0;
454 cc26xx_bank->buffer_addr[1] = CC26X2_ALGO_BUFFER_1;
455 cc26xx_bank->params_addr[0] = CC26X2_ALGO_PARAMS_0;
456 cc26xx_bank->params_addr[1] = CC26X2_ALGO_PARAMS_1;
457 max_sectors = CC26X2_MAX_SECTORS;
461 retval = target_read_u32(target, CC26XX_FLASH_SIZE_INFO, &value);
462 if (ERROR_OK != retval)
464 num_sectors = value & 0xff;
465 if (num_sectors > max_sectors)
466 num_sectors = max_sectors;
468 bank->sectors = malloc(sizeof(struct flash_sector) * num_sectors);
469 if (NULL == bank->sectors)
472 bank->base = CC26XX_FLASH_BASE_ADDR;
473 bank->num_sectors = num_sectors;
474 bank->size = num_sectors * sector_length;
475 bank->write_start_alignment = 0;
476 bank->write_end_alignment = 0;
477 cc26xx_bank->sector_length = sector_length;
479 for (int i = 0; i < num_sectors; i++) {
480 bank->sectors[i].offset = i * sector_length;
481 bank->sectors[i].size = sector_length;
482 bank->sectors[i].is_erased = -1;
483 bank->sectors[i].is_protected = 0;
486 /* We've successfully determined the stats on the flash bank */
487 cc26xx_bank->probed = true;
489 /* If we fall through to here, then all went well */
494 static int cc26xx_auto_probe(struct flash_bank *bank)
496 struct cc26xx_bank *cc26xx_bank = bank->driver_priv;
498 int retval = ERROR_OK;
500 if (bank->bank_number != 0) {
501 /* Invalid bank number somehow */
505 if (!cc26xx_bank->probed)
506 retval = cc26xx_probe(bank);
511 static int cc26xx_protect_check(struct flash_bank *bank)
516 static int cc26xx_info(struct flash_bank *bank, char *buf, int buf_size)
518 struct cc26xx_bank *cc26xx_bank = bank->driver_priv;
522 switch (cc26xx_bank->device_type) {
540 device = "Unrecognized";
544 printed = snprintf(buf, buf_size,
545 "%s device: ICEPick ID 0x%08x, USER ID 0x%08x\n",
546 device, cc26xx_bank->icepick_id, cc26xx_bank->user_id);
548 if (printed >= buf_size)
549 return ERROR_BUF_TOO_SMALL;
554 struct flash_driver cc26xx_flash = {
556 .flash_bank_command = cc26xx_flash_bank_command,
557 .erase = cc26xx_erase,
558 .protect = cc26xx_protect,
559 .write = cc26xx_write,
560 .read = default_flash_read,
561 .probe = cc26xx_probe,
562 .auto_probe = cc26xx_auto_probe,
563 .erase_check = default_flash_blank_check,
564 .protect_check = cc26xx_protect_check,
566 .free_driver_priv = default_flash_free_driver_priv,