flash: nor: ath79: remove base calculation
[openocd.git] / src / flash / nor / cc26xx.c
1 /***************************************************************************
2 * Copyright (C) 2017 by Texas Instruments, Inc. *
3 * *
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. *
8 * *
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. *
13 * *
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 ***************************************************************************/
17
18 #ifdef HAVE_CONFIG_H
19 #include "config.h"
20 #endif
21
22 #include "imp.h"
23 #include "cc26xx.h"
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>
29
30 #define FLASH_TIMEOUT 8000
31
32 struct cc26xx_bank {
33 const char *family_name;
34 uint32_t icepick_id;
35 uint32_t user_id;
36 uint32_t device_type;
37 uint32_t sector_length;
38 bool probed;
39 struct working_area *working_area;
40 struct armv7m_algorithm armv7m_info;
41 const uint8_t *algo_code;
42 uint32_t algo_size;
43 uint32_t algo_working_size;
44 uint32_t buffer_addr[2];
45 uint32_t params_addr[2];
46 };
47
48 static int cc26xx_auto_probe(struct flash_bank *bank);
49
50 static uint32_t cc26xx_device_type(uint32_t icepick_id, uint32_t user_id)
51 {
52 uint32_t device_type = 0;
53
54 switch (icepick_id & ICEPICK_ID_MASK) {
55 case CC26X0_ICEPICK_ID:
56 device_type = CC26X0_TYPE;
57 break;
58 case CC26X1_ICEPICK_ID:
59 device_type = CC26X1_TYPE;
60 break;
61 case CC13X0_ICEPICK_ID:
62 device_type = CC13X0_TYPE;
63 break;
64 case CC13X2_CC26X2_ICEPICK_ID:
65 default:
66 if ((user_id & USER_ID_CC13_MASK) != 0)
67 device_type = CC13X2_TYPE;
68 else
69 device_type = CC26X2_TYPE;
70 break;
71 }
72
73 return device_type;
74 }
75
76 static uint32_t cc26xx_sector_length(uint32_t icepick_id)
77 {
78 uint32_t sector_length;
79
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;
86 break;
87 case CC13X2_CC26X2_ICEPICK_ID:
88 default:
89 /* Agama family device */
90 sector_length = CC26X2_SECTOR_LENGTH;
91 break;
92 }
93
94 return sector_length;
95 }
96
97 static int cc26xx_wait_algo_done(struct flash_bank *bank, uint32_t params_addr)
98 {
99 struct target *target = bank->target;
100 struct cc26xx_bank *cc26xx_bank = bank->driver_priv;
101
102 uint32_t status_addr = params_addr + CC26XX_STATUS_OFFSET;
103 uint32_t status = CC26XX_BUFFER_FULL;
104 long long start_ms;
105 long long elapsed_ms;
106
107 int retval = ERROR_OK;
108
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)
113 return retval;
114
115 elapsed_ms = timeval_ms() - start_ms;
116 if (elapsed_ms > 500)
117 keep_alive();
118 if (elapsed_ms > FLASH_TIMEOUT)
119 break;
120 };
121
122 if (CC26XX_BUFFER_EMPTY != status) {
123 LOG_ERROR("%s: Flash operation failed", cc26xx_bank->family_name);
124 return ERROR_FAIL;
125 }
126
127 return ERROR_OK;
128 }
129
130 static int cc26xx_init(struct flash_bank *bank)
131 {
132 struct target *target = bank->target;
133 struct cc26xx_bank *cc26xx_bank = bank->driver_priv;
134
135 int retval;
136
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)
140 return retval;
141
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)
148 return retval;
149
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;
153
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);
161 return retval;
162 }
163
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;
167
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);
175 return retval;
176 }
177
178 /*
179 * At this point, the algorithm is running on the target and
180 * ready to receive commands and data to flash the target
181 */
182
183 return retval;
184 }
185
186 static int cc26xx_quit(struct flash_bank *bank)
187 {
188 struct target *target = bank->target;
189 struct cc26xx_bank *cc26xx_bank = bank->driver_priv;
190
191 int retval;
192
193 /* Regardless of the algo's status, attempt to halt the target */
194 (void)target_halt(target);
195
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);
199
200 target_free_working_area(target, cc26xx_bank->working_area);
201 cc26xx_bank->working_area = NULL;
202
203 return retval;
204 }
205
206 static int cc26xx_mass_erase(struct flash_bank *bank)
207 {
208 struct target *target = bank->target;
209 struct cc26xx_bank *cc26xx_bank = bank->driver_priv;
210 struct cc26xx_algo_params algo_params;
211
212 int retval;
213
214 if (TARGET_HALTED != target->state) {
215 LOG_ERROR("Target not halted");
216 return ERROR_TARGET_NOT_HALTED;
217 }
218
219 retval = cc26xx_init(bank);
220 if (ERROR_OK != retval)
221 return retval;
222
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);
228
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);
232
233 /* Wait for command to complete */
234 if (ERROR_OK == retval)
235 retval = cc26xx_wait_algo_done(bank, cc26xx_bank->params_addr[0]);
236
237 /* Regardless of errors, try to close down algo */
238 (void)cc26xx_quit(bank);
239
240 return retval;
241 }
242
243 FLASH_BANK_COMMAND_HANDLER(cc26xx_flash_bank_command)
244 {
245 struct cc26xx_bank *cc26xx_bank;
246
247 if (CMD_ARGC < 6)
248 return ERROR_COMMAND_SYNTAX_ERROR;
249
250 cc26xx_bank = malloc(sizeof(struct cc26xx_bank));
251 if (NULL == cc26xx_bank)
252 return ERROR_FAIL;
253
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;
259
260 /* Finish initialization of bank */
261 bank->driver_priv = cc26xx_bank;
262 bank->next = NULL;
263
264 return ERROR_OK;
265 }
266
267 static int cc26xx_erase(struct flash_bank *bank, int first, int last)
268 {
269 struct target *target = bank->target;
270 struct cc26xx_bank *cc26xx_bank = bank->driver_priv;
271 struct cc26xx_algo_params algo_params;
272
273 uint32_t address;
274 uint32_t length;
275 int retval;
276
277 if (TARGET_HALTED != target->state) {
278 LOG_ERROR("Target not halted");
279 return ERROR_TARGET_NOT_HALTED;
280 }
281
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);
286 }
287
288 address = first * cc26xx_bank->sector_length;
289 length = (last - first + 1) * cc26xx_bank->sector_length;
290
291 retval = cc26xx_init(bank);
292 if (ERROR_OK != retval)
293 return retval;
294
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);
300
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);
304
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]);
308
309 /* Regardless of errors, try to close down algo */
310 (void)cc26xx_quit(bank);
311
312 return retval;
313 }
314
315 static int cc26xx_write(struct flash_bank *bank, const uint8_t *buffer,
316 uint32_t offset, uint32_t count)
317 {
318 struct target *target = bank->target;
319 struct cc26xx_bank *cc26xx_bank = bank->driver_priv;
320 struct cc26xx_algo_params algo_params[2];
321 uint32_t size = 0;
322 long long start_ms;
323 long long elapsed_ms;
324 uint32_t address;
325
326 uint32_t index;
327 int retval;
328
329 if (TARGET_HALTED != target->state) {
330 LOG_ERROR("Target not halted");
331 return ERROR_TARGET_NOT_HALTED;
332 }
333
334 retval = cc26xx_init(bank);
335 if (ERROR_OK != retval)
336 return retval;
337
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);
341
342 /* Write requested data, ping-ponging between two buffers */
343 index = 0;
344 start_ms = timeval_ms();
345 address = bank->base + offset;
346 while (count > 0) {
347
348 if (count > cc26xx_bank->sector_length)
349 size = cc26xx_bank->sector_length;
350 else
351 size = count;
352
353 /* Put next block of data to flash into buffer */
354 retval = target_write_buffer(target, cc26xx_bank->buffer_addr[index],
355 size, buffer);
356 if (ERROR_OK != retval) {
357 LOG_ERROR("Unable to write data to target memory");
358 break;
359 }
360
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);
365
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)
370 break;
371
372 /* Wait for next ping pong buffer to be ready */
373 index ^= 1;
374 retval = cc26xx_wait_algo_done(bank, cc26xx_bank->params_addr[index]);
375 if (ERROR_OK != retval)
376 break;
377
378 count -= size;
379 buffer += size;
380 address += size;
381
382 elapsed_ms = timeval_ms() - start_ms;
383 if (elapsed_ms > 500)
384 keep_alive();
385 }
386
387 /* If no error yet, wait for last buffer to finish */
388 if (ERROR_OK == retval) {
389 index ^= 1;
390 retval = cc26xx_wait_algo_done(bank, cc26xx_bank->params_addr[index]);
391 }
392
393 /* Regardless of errors, try to close down algo */
394 (void)cc26xx_quit(bank);
395
396 return retval;
397 }
398
399 static int cc26xx_probe(struct flash_bank *bank)
400 {
401 struct target *target = bank->target;
402 struct cc26xx_bank *cc26xx_bank = bank->driver_priv;
403
404 uint32_t sector_length;
405 uint32_t value;
406 int num_sectors;
407 int max_sectors;
408
409 int retval;
410
411 retval = target_read_u32(target, FCFG1_ICEPICK_ID, &value);
412 if (ERROR_OK != retval)
413 return retval;
414 cc26xx_bank->icepick_id = value;
415
416 retval = target_read_u32(target, FCFG1_USER_ID, &value);
417 if (ERROR_OK != retval)
418 return retval;
419 cc26xx_bank->user_id = value;
420
421 cc26xx_bank->device_type = cc26xx_device_type(cc26xx_bank->icepick_id,
422 cc26xx_bank->user_id);
423
424 sector_length = cc26xx_sector_length(cc26xx_bank->icepick_id);
425
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;
440 break;
441 case CC13X2_CC26X2_ICEPICK_ID:
442 default:
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;
452 break;
453 }
454
455 retval = target_read_u32(target, CC26XX_FLASH_SIZE_INFO, &value);
456 if (ERROR_OK != retval)
457 return retval;
458 num_sectors = value & 0xff;
459 if (num_sectors > max_sectors)
460 num_sectors = max_sectors;
461
462 bank->sectors = malloc(sizeof(struct flash_sector) * num_sectors);
463 if (NULL == bank->sectors)
464 return ERROR_FAIL;
465
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;
472
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;
478 }
479
480 /* We've successfully determined the stats on the flash bank */
481 cc26xx_bank->probed = true;
482
483 /* If we fall through to here, then all went well */
484
485 return ERROR_OK;
486 }
487
488 static int cc26xx_auto_probe(struct flash_bank *bank)
489 {
490 struct cc26xx_bank *cc26xx_bank = bank->driver_priv;
491
492 int retval = ERROR_OK;
493
494 if (!cc26xx_bank->probed)
495 retval = cc26xx_probe(bank);
496
497 return retval;
498 }
499
500 static int cc26xx_info(struct flash_bank *bank, char *buf, int buf_size)
501 {
502 struct cc26xx_bank *cc26xx_bank = bank->driver_priv;
503 int printed = 0;
504 const char *device;
505
506 switch (cc26xx_bank->device_type) {
507 case CC26X0_TYPE:
508 device = "CC26x0";
509 break;
510 case CC26X1_TYPE:
511 device = "CC26x1";
512 break;
513 case CC13X0_TYPE:
514 device = "CC13x0";
515 break;
516 case CC13X2_TYPE:
517 device = "CC13x2";
518 break;
519 case CC26X2_TYPE:
520 device = "CC26x2";
521 break;
522 case CC26XX_NO_TYPE:
523 default:
524 device = "Unrecognized";
525 break;
526 }
527
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);
531
532 if (printed >= buf_size)
533 return ERROR_BUF_TOO_SMALL;
534
535 return ERROR_OK;
536 }
537
538 struct flash_driver cc26xx_flash = {
539 .name = "cc26xx",
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,
547 .info = cc26xx_info,
548 .free_driver_priv = default_flash_free_driver_priv,
549 };