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_write(struct flash_bank *bank, const uint8_t *buffer,
316 uint32_t offset, uint32_t count)
318 struct target *target = bank->target;
319 struct cc26xx_bank *cc26xx_bank = bank->driver_priv;
320 struct cc26xx_algo_params algo_params[2];
323 long long elapsed_ms;
329 if (TARGET_HALTED != target->state) {
330 LOG_ERROR("Target not halted");
331 return ERROR_TARGET_NOT_HALTED;
334 retval = cc26xx_init(bank);
335 if (ERROR_OK != retval)
338 /* Initialize algorithm parameters to default values */
339 buf_set_u32(algo_params[0].command, 0, 32, CC26XX_CMD_PROGRAM);
340 buf_set_u32(algo_params[1].command, 0, 32, CC26XX_CMD_PROGRAM);
342 /* Write requested data, ping-ponging between two buffers */
344 start_ms = timeval_ms();
345 address = bank->base + offset;
348 if (count > cc26xx_bank->sector_length)
349 size = cc26xx_bank->sector_length;
353 /* Put next block of data to flash into buffer */
354 retval = target_write_buffer(target, cc26xx_bank->buffer_addr[index],
356 if (ERROR_OK != retval) {
357 LOG_ERROR("Unable to write data to target memory");
361 /* Update algo parameters for next block */
362 buf_set_u32(algo_params[index].address, 0, 32, address);
363 buf_set_u32(algo_params[index].length, 0, 32, size);
364 buf_set_u32(algo_params[index].status, 0, 32, CC26XX_BUFFER_FULL);
366 /* Issue flash helper algorithm parameters for block write */
367 retval = target_write_buffer(target, cc26xx_bank->params_addr[index],
368 sizeof(algo_params[index]), (uint8_t *)&algo_params[index]);
369 if (ERROR_OK != retval)
372 /* Wait for next ping pong buffer to be ready */
374 retval = cc26xx_wait_algo_done(bank, cc26xx_bank->params_addr[index]);
375 if (ERROR_OK != retval)
382 elapsed_ms = timeval_ms() - start_ms;
383 if (elapsed_ms > 500)
387 /* If no error yet, wait for last buffer to finish */
388 if (ERROR_OK == retval) {
390 retval = cc26xx_wait_algo_done(bank, cc26xx_bank->params_addr[index]);
393 /* Regardless of errors, try to close down algo */
394 (void)cc26xx_quit(bank);
399 static int cc26xx_probe(struct flash_bank *bank)
401 struct target *target = bank->target;
402 struct cc26xx_bank *cc26xx_bank = bank->driver_priv;
404 uint32_t sector_length;
411 retval = target_read_u32(target, FCFG1_ICEPICK_ID, &value);
412 if (ERROR_OK != retval)
414 cc26xx_bank->icepick_id = value;
416 retval = target_read_u32(target, FCFG1_USER_ID, &value);
417 if (ERROR_OK != retval)
419 cc26xx_bank->user_id = value;
421 cc26xx_bank->device_type = cc26xx_device_type(cc26xx_bank->icepick_id,
422 cc26xx_bank->user_id);
424 sector_length = cc26xx_sector_length(cc26xx_bank->icepick_id);
426 /* Set up appropriate flash helper algorithm */
427 switch (cc26xx_bank->icepick_id & ICEPICK_ID_MASK) {
428 case CC26X0_ICEPICK_ID:
429 case CC26X1_ICEPICK_ID:
430 case CC13X0_ICEPICK_ID:
431 /* Chameleon family device */
432 cc26xx_bank->algo_code = cc26x0_algo;
433 cc26xx_bank->algo_size = sizeof(cc26x0_algo);
434 cc26xx_bank->algo_working_size = CC26X0_WORKING_SIZE;
435 cc26xx_bank->buffer_addr[0] = CC26X0_ALGO_BUFFER_0;
436 cc26xx_bank->buffer_addr[1] = CC26X0_ALGO_BUFFER_1;
437 cc26xx_bank->params_addr[0] = CC26X0_ALGO_PARAMS_0;
438 cc26xx_bank->params_addr[1] = CC26X0_ALGO_PARAMS_1;
439 max_sectors = CC26X0_MAX_SECTORS;
441 case CC13X2_CC26X2_ICEPICK_ID:
443 /* Agama family device */
444 cc26xx_bank->algo_code = cc26x2_algo;
445 cc26xx_bank->algo_size = sizeof(cc26x2_algo);
446 cc26xx_bank->algo_working_size = CC26X2_WORKING_SIZE;
447 cc26xx_bank->buffer_addr[0] = CC26X2_ALGO_BUFFER_0;
448 cc26xx_bank->buffer_addr[1] = CC26X2_ALGO_BUFFER_1;
449 cc26xx_bank->params_addr[0] = CC26X2_ALGO_PARAMS_0;
450 cc26xx_bank->params_addr[1] = CC26X2_ALGO_PARAMS_1;
451 max_sectors = CC26X2_MAX_SECTORS;
455 retval = target_read_u32(target, CC26XX_FLASH_SIZE_INFO, &value);
456 if (ERROR_OK != retval)
458 num_sectors = value & 0xff;
459 if (num_sectors > max_sectors)
460 num_sectors = max_sectors;
462 bank->sectors = malloc(sizeof(struct flash_sector) * num_sectors);
463 if (NULL == bank->sectors)
466 bank->base = CC26XX_FLASH_BASE_ADDR;
467 bank->num_sectors = num_sectors;
468 bank->size = num_sectors * sector_length;
469 bank->write_start_alignment = 0;
470 bank->write_end_alignment = 0;
471 cc26xx_bank->sector_length = sector_length;
473 for (int i = 0; i < num_sectors; i++) {
474 bank->sectors[i].offset = i * sector_length;
475 bank->sectors[i].size = sector_length;
476 bank->sectors[i].is_erased = -1;
477 bank->sectors[i].is_protected = 0;
480 /* We've successfully determined the stats on the flash bank */
481 cc26xx_bank->probed = true;
483 /* If we fall through to here, then all went well */
488 static int cc26xx_auto_probe(struct flash_bank *bank)
490 struct cc26xx_bank *cc26xx_bank = bank->driver_priv;
492 int retval = ERROR_OK;
494 if (!cc26xx_bank->probed)
495 retval = cc26xx_probe(bank);
500 static int cc26xx_info(struct flash_bank *bank, char *buf, int buf_size)
502 struct cc26xx_bank *cc26xx_bank = bank->driver_priv;
506 switch (cc26xx_bank->device_type) {
524 device = "Unrecognized";
528 printed = snprintf(buf, buf_size,
529 "%s device: ICEPick ID 0x%08x, USER ID 0x%08x\n",
530 device, cc26xx_bank->icepick_id, cc26xx_bank->user_id);
532 if (printed >= buf_size)
533 return ERROR_BUF_TOO_SMALL;
538 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,