b8d18a7d991ab56c876221e2733d0571b5f30d9e
[fw/openocd] / src / flash / nor / cc26xx.c
1 /* SPDX-License-Identifier: GPL-2.0-or-later */
2
3 /***************************************************************************
4  *   Copyright (C) 2017 by Texas Instruments, Inc.                         *
5  ***************************************************************************/
6
7 #ifdef HAVE_CONFIG_H
8 #include "config.h"
9 #endif
10
11 #include "imp.h"
12 #include "cc26xx.h"
13 #include <helper/binarybuffer.h>
14 #include <helper/time_support.h>
15 #include <target/algorithm.h>
16 #include <target/armv7m.h>
17 #include <target/image.h>
18
19 #define FLASH_TIMEOUT 8000
20
21 struct cc26xx_bank {
22         const char *family_name;
23         uint32_t icepick_id;
24         uint32_t user_id;
25         uint32_t device_type;
26         uint32_t sector_length;
27         bool probed;
28         struct working_area *working_area;
29         struct armv7m_algorithm armv7m_info;
30         const uint8_t *algo_code;
31         uint32_t algo_size;
32         uint32_t algo_working_size;
33         uint32_t buffer_addr[2];
34         uint32_t params_addr[2];
35 };
36
37 static int cc26xx_auto_probe(struct flash_bank *bank);
38
39 static uint32_t cc26xx_device_type(uint32_t icepick_id, uint32_t user_id)
40 {
41         uint32_t device_type = 0;
42
43         switch (icepick_id & ICEPICK_ID_MASK) {
44                 case CC26X0_ICEPICK_ID:
45                         device_type = CC26X0_TYPE;
46                         break;
47                 case CC26X1_ICEPICK_ID:
48                         device_type = CC26X1_TYPE;
49                         break;
50                 case CC13X0_ICEPICK_ID:
51                         device_type = CC13X0_TYPE;
52                         break;
53                 case CC13X2_CC26X2_ICEPICK_ID:
54                 default:
55                         if ((user_id & USER_ID_CC13_MASK) != 0)
56                                 device_type = CC13X2_TYPE;
57                         else
58                                 device_type = CC26X2_TYPE;
59                         break;
60         }
61
62         return device_type;
63 }
64
65 static uint32_t cc26xx_sector_length(uint32_t icepick_id)
66 {
67         uint32_t sector_length;
68
69         switch (icepick_id & ICEPICK_ID_MASK) {
70                 case CC26X0_ICEPICK_ID:
71                 case CC26X1_ICEPICK_ID:
72                 case CC13X0_ICEPICK_ID:
73                         /* Chameleon family device */
74                         sector_length = CC26X0_SECTOR_LENGTH;
75                         break;
76                 case CC13X2_CC26X2_ICEPICK_ID:
77                 default:
78                         /* Agama family device */
79                         sector_length = CC26X2_SECTOR_LENGTH;
80                         break;
81         }
82
83         return sector_length;
84 }
85
86 static int cc26xx_wait_algo_done(struct flash_bank *bank, uint32_t params_addr)
87 {
88         struct target *target = bank->target;
89         struct cc26xx_bank *cc26xx_bank = bank->driver_priv;
90
91         uint32_t status_addr = params_addr + CC26XX_STATUS_OFFSET;
92         uint32_t status = CC26XX_BUFFER_FULL;
93         long long start_ms;
94         long long elapsed_ms;
95
96         int retval = ERROR_OK;
97
98         start_ms = timeval_ms();
99         while (status == CC26XX_BUFFER_FULL) {
100                 retval = target_read_u32(target, status_addr, &status);
101                 if (retval != ERROR_OK)
102                         return retval;
103
104                 elapsed_ms = timeval_ms() - start_ms;
105                 if (elapsed_ms > 500)
106                         keep_alive();
107                 if (elapsed_ms > FLASH_TIMEOUT)
108                         break;
109         };
110
111         if (status != CC26XX_BUFFER_EMPTY) {
112                 LOG_ERROR("%s: Flash operation failed", cc26xx_bank->family_name);
113                 return ERROR_FAIL;
114         }
115
116         return ERROR_OK;
117 }
118
119 static int cc26xx_init(struct flash_bank *bank)
120 {
121         struct target *target = bank->target;
122         struct cc26xx_bank *cc26xx_bank = bank->driver_priv;
123
124         int retval;
125
126         /* Make sure we've probed the flash to get the device and size */
127         retval = cc26xx_auto_probe(bank);
128         if (retval != ERROR_OK)
129                 return retval;
130
131         /* Check for working area to use for flash helper algorithm */
132         target_free_working_area(target, cc26xx_bank->working_area);
133         cc26xx_bank->working_area = NULL;
134
135         retval = target_alloc_working_area(target, cc26xx_bank->algo_working_size,
136                                 &cc26xx_bank->working_area);
137         if (retval != ERROR_OK)
138                 return retval;
139
140         /* Confirm the defined working address is the area we need to use */
141         if (cc26xx_bank->working_area->address != CC26XX_ALGO_BASE_ADDRESS)
142                 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
143
144         /* Write flash helper algorithm into target memory */
145         retval = target_write_buffer(target, CC26XX_ALGO_BASE_ADDRESS,
146                                 cc26xx_bank->algo_size, cc26xx_bank->algo_code);
147         if (retval != ERROR_OK) {
148                 LOG_ERROR("%s: Failed to load flash helper algorithm",
149                         cc26xx_bank->family_name);
150                 target_free_working_area(target, cc26xx_bank->working_area);
151                 cc26xx_bank->working_area = NULL;
152                 return retval;
153         }
154
155         /* Initialize the ARMv7 specific info to run the algorithm */
156         cc26xx_bank->armv7m_info.common_magic = ARMV7M_COMMON_MAGIC;
157         cc26xx_bank->armv7m_info.core_mode = ARM_MODE_THREAD;
158
159         /* Begin executing the flash helper algorithm */
160         retval = target_start_algorithm(target, 0, NULL, 0, NULL,
161                                 CC26XX_ALGO_BASE_ADDRESS, 0, &cc26xx_bank->armv7m_info);
162         if (retval != ERROR_OK) {
163                 LOG_ERROR("%s: Failed to start flash helper algorithm",
164                         cc26xx_bank->family_name);
165                 target_free_working_area(target, cc26xx_bank->working_area);
166                 cc26xx_bank->working_area = NULL;
167                 return retval;
168         }
169
170         /*
171          * At this point, the algorithm is running on the target and
172          * ready to receive commands and data to flash the target
173          */
174
175         return retval;
176 }
177
178 static int cc26xx_quit(struct flash_bank *bank)
179 {
180         struct target *target = bank->target;
181         struct cc26xx_bank *cc26xx_bank = bank->driver_priv;
182
183         int retval;
184
185         /* Regardless of the algo's status, attempt to halt the target */
186         (void)target_halt(target);
187
188         /* Now confirm target halted and clean up from flash helper algorithm */
189         retval = target_wait_algorithm(target, 0, NULL, 0, NULL, 0, FLASH_TIMEOUT,
190                                 &cc26xx_bank->armv7m_info);
191
192         target_free_working_area(target, cc26xx_bank->working_area);
193         cc26xx_bank->working_area = NULL;
194
195         return retval;
196 }
197
198 static int cc26xx_mass_erase(struct flash_bank *bank)
199 {
200         struct target *target = bank->target;
201         struct cc26xx_bank *cc26xx_bank = bank->driver_priv;
202         struct cc26xx_algo_params algo_params;
203
204         int retval;
205
206         if (target->state != TARGET_HALTED) {
207                 LOG_ERROR("Target not halted");
208                 return ERROR_TARGET_NOT_HALTED;
209         }
210
211         retval = cc26xx_init(bank);
212         if (retval != ERROR_OK)
213                 return retval;
214
215         /* Initialize algorithm parameters */
216         buf_set_u32(algo_params.address, 0, 32, 0);
217         buf_set_u32(algo_params.length,  0, 32, 4);
218         buf_set_u32(algo_params.command, 0, 32, CC26XX_CMD_ERASE_ALL);
219         buf_set_u32(algo_params.status,  0, 32, CC26XX_BUFFER_FULL);
220
221         /* Issue flash helper algorithm parameters for mass erase */
222         retval = target_write_buffer(target, cc26xx_bank->params_addr[0],
223                                 sizeof(algo_params), (uint8_t *)&algo_params);
224
225         /* Wait for command to complete */
226         if (retval == ERROR_OK)
227                 retval = cc26xx_wait_algo_done(bank, cc26xx_bank->params_addr[0]);
228
229         /* Regardless of errors, try to close down algo */
230         (void)cc26xx_quit(bank);
231
232         return retval;
233 }
234
235 FLASH_BANK_COMMAND_HANDLER(cc26xx_flash_bank_command)
236 {
237         struct cc26xx_bank *cc26xx_bank;
238
239         if (CMD_ARGC < 6)
240                 return ERROR_COMMAND_SYNTAX_ERROR;
241
242         cc26xx_bank = malloc(sizeof(struct cc26xx_bank));
243         if (!cc26xx_bank)
244                 return ERROR_FAIL;
245
246         /* Initialize private flash information */
247         memset((void *)cc26xx_bank, 0x00, sizeof(struct cc26xx_bank));
248         cc26xx_bank->family_name = "cc26xx";
249         cc26xx_bank->device_type = CC26XX_NO_TYPE;
250         cc26xx_bank->sector_length = 0x1000;
251
252         /* Finish initialization of bank */
253         bank->driver_priv = cc26xx_bank;
254         bank->next = NULL;
255
256         return ERROR_OK;
257 }
258
259 static int cc26xx_erase(struct flash_bank *bank, unsigned int first,
260                 unsigned int last)
261 {
262         struct target *target = bank->target;
263         struct cc26xx_bank *cc26xx_bank = bank->driver_priv;
264         struct cc26xx_algo_params algo_params;
265
266         uint32_t address;
267         uint32_t length;
268         int retval;
269
270         if (target->state != TARGET_HALTED) {
271                 LOG_ERROR("Target not halted");
272                 return ERROR_TARGET_NOT_HALTED;
273         }
274
275         /* Do a mass erase if user requested all sectors of flash */
276         if ((first == 0) && (last == (bank->num_sectors - 1))) {
277                 /* Request mass erase of flash */
278                 return cc26xx_mass_erase(bank);
279         }
280
281         address = first * cc26xx_bank->sector_length;
282         length = (last - first + 1) * cc26xx_bank->sector_length;
283
284         retval = cc26xx_init(bank);
285         if (retval != ERROR_OK)
286                 return retval;
287
288         /* Set up algorithm parameters for erase command */
289         buf_set_u32(algo_params.address, 0, 32, address);
290         buf_set_u32(algo_params.length,  0, 32, length);
291         buf_set_u32(algo_params.command, 0, 32, CC26XX_CMD_ERASE_SECTORS);
292         buf_set_u32(algo_params.status,  0, 32, CC26XX_BUFFER_FULL);
293
294         /* Issue flash helper algorithm parameters for erase */
295         retval = target_write_buffer(target, cc26xx_bank->params_addr[0],
296                                 sizeof(algo_params), (uint8_t *)&algo_params);
297
298         /* If no error, wait for erase to finish */
299         if (retval == ERROR_OK)
300                 retval = cc26xx_wait_algo_done(bank, cc26xx_bank->params_addr[0]);
301
302         /* Regardless of errors, try to close down algo */
303         (void)cc26xx_quit(bank);
304
305         return retval;
306 }
307
308 static int cc26xx_write(struct flash_bank *bank, const uint8_t *buffer,
309         uint32_t offset, uint32_t count)
310 {
311         struct target *target = bank->target;
312         struct cc26xx_bank *cc26xx_bank = bank->driver_priv;
313         struct cc26xx_algo_params algo_params[2];
314         uint32_t size = 0;
315         long long start_ms;
316         long long elapsed_ms;
317         uint32_t address;
318
319         uint32_t index;
320         int retval;
321
322         if (target->state != TARGET_HALTED) {
323                 LOG_ERROR("Target not halted");
324                 return ERROR_TARGET_NOT_HALTED;
325         }
326
327         retval = cc26xx_init(bank);
328         if (retval != ERROR_OK)
329                 return retval;
330
331         /* Initialize algorithm parameters to default values */
332         buf_set_u32(algo_params[0].command, 0, 32, CC26XX_CMD_PROGRAM);
333         buf_set_u32(algo_params[1].command, 0, 32, CC26XX_CMD_PROGRAM);
334
335         /* Write requested data, ping-ponging between two buffers */
336         index = 0;
337         start_ms = timeval_ms();
338         address = bank->base + offset;
339         while (count > 0) {
340
341                 if (count > cc26xx_bank->sector_length)
342                         size = cc26xx_bank->sector_length;
343                 else
344                         size = count;
345
346                 /* Put next block of data to flash into buffer */
347                 retval = target_write_buffer(target, cc26xx_bank->buffer_addr[index],
348                                         size, buffer);
349                 if (retval != ERROR_OK) {
350                         LOG_ERROR("Unable to write data to target memory");
351                         break;
352                 }
353
354                 /* Update algo parameters for next block */
355                 buf_set_u32(algo_params[index].address, 0, 32, address);
356                 buf_set_u32(algo_params[index].length,  0, 32, size);
357                 buf_set_u32(algo_params[index].status,  0, 32, CC26XX_BUFFER_FULL);
358
359                 /* Issue flash helper algorithm parameters for block write */
360                 retval = target_write_buffer(target, cc26xx_bank->params_addr[index],
361                                         sizeof(algo_params[index]), (uint8_t *)&algo_params[index]);
362                 if (retval != ERROR_OK)
363                         break;
364
365                 /* Wait for next ping pong buffer to be ready */
366                 index ^= 1;
367                 retval = cc26xx_wait_algo_done(bank, cc26xx_bank->params_addr[index]);
368                 if (retval != ERROR_OK)
369                         break;
370
371                 count -= size;
372                 buffer += size;
373                 address += size;
374
375                 elapsed_ms = timeval_ms() - start_ms;
376                 if (elapsed_ms > 500)
377                         keep_alive();
378         }
379
380         /* If no error yet, wait for last buffer to finish */
381         if (retval == ERROR_OK) {
382                 index ^= 1;
383                 retval = cc26xx_wait_algo_done(bank, cc26xx_bank->params_addr[index]);
384         }
385
386         /* Regardless of errors, try to close down algo */
387         (void)cc26xx_quit(bank);
388
389         return retval;
390 }
391
392 static int cc26xx_probe(struct flash_bank *bank)
393 {
394         struct target *target = bank->target;
395         struct cc26xx_bank *cc26xx_bank = bank->driver_priv;
396
397         uint32_t sector_length;
398         uint32_t value;
399         int num_sectors;
400         int max_sectors;
401
402         int retval;
403
404         retval = target_read_u32(target, FCFG1_ICEPICK_ID, &value);
405         if (retval != ERROR_OK)
406                 return retval;
407         cc26xx_bank->icepick_id = value;
408
409         retval = target_read_u32(target, FCFG1_USER_ID, &value);
410         if (retval != ERROR_OK)
411                 return retval;
412         cc26xx_bank->user_id = value;
413
414         cc26xx_bank->device_type = cc26xx_device_type(cc26xx_bank->icepick_id,
415                 cc26xx_bank->user_id);
416
417         sector_length = cc26xx_sector_length(cc26xx_bank->icepick_id);
418
419         /* Set up appropriate flash helper algorithm */
420         switch (cc26xx_bank->icepick_id & ICEPICK_ID_MASK) {
421                 case CC26X0_ICEPICK_ID:
422                 case CC26X1_ICEPICK_ID:
423                 case CC13X0_ICEPICK_ID:
424                         /* Chameleon family device */
425                         cc26xx_bank->algo_code = cc26x0_algo;
426                         cc26xx_bank->algo_size = sizeof(cc26x0_algo);
427                         cc26xx_bank->algo_working_size = CC26X0_WORKING_SIZE;
428                         cc26xx_bank->buffer_addr[0] = CC26X0_ALGO_BUFFER_0;
429                         cc26xx_bank->buffer_addr[1] = CC26X0_ALGO_BUFFER_1;
430                         cc26xx_bank->params_addr[0] = CC26X0_ALGO_PARAMS_0;
431                         cc26xx_bank->params_addr[1] = CC26X0_ALGO_PARAMS_1;
432                         max_sectors = CC26X0_MAX_SECTORS;
433                         break;
434                 case CC13X2_CC26X2_ICEPICK_ID:
435                 default:
436                         /* Agama family device */
437                         cc26xx_bank->algo_code = cc26x2_algo;
438                         cc26xx_bank->algo_size = sizeof(cc26x2_algo);
439                         cc26xx_bank->algo_working_size = CC26X2_WORKING_SIZE;
440                         cc26xx_bank->buffer_addr[0] = CC26X2_ALGO_BUFFER_0;
441                         cc26xx_bank->buffer_addr[1] = CC26X2_ALGO_BUFFER_1;
442                         cc26xx_bank->params_addr[0] = CC26X2_ALGO_PARAMS_0;
443                         cc26xx_bank->params_addr[1] = CC26X2_ALGO_PARAMS_1;
444                         max_sectors = CC26X2_MAX_SECTORS;
445                         break;
446         }
447
448         retval = target_read_u32(target, CC26XX_FLASH_SIZE_INFO, &value);
449         if (retval != ERROR_OK)
450                 return retval;
451         num_sectors = value & 0xff;
452         if (num_sectors > max_sectors)
453                 num_sectors = max_sectors;
454
455         bank->sectors = malloc(sizeof(struct flash_sector) * num_sectors);
456         if (!bank->sectors)
457                 return ERROR_FAIL;
458
459         bank->base = CC26XX_FLASH_BASE_ADDR;
460         bank->num_sectors = num_sectors;
461         bank->size = num_sectors * sector_length;
462         bank->write_start_alignment = 0;
463         bank->write_end_alignment = 0;
464         cc26xx_bank->sector_length = sector_length;
465
466         for (int i = 0; i < num_sectors; i++) {
467                 bank->sectors[i].offset = i * sector_length;
468                 bank->sectors[i].size = sector_length;
469                 bank->sectors[i].is_erased = -1;
470                 bank->sectors[i].is_protected = 0;
471         }
472
473         /* We've successfully determined the stats on the flash bank */
474         cc26xx_bank->probed = true;
475
476         /* If we fall through to here, then all went well */
477
478         return ERROR_OK;
479 }
480
481 static int cc26xx_auto_probe(struct flash_bank *bank)
482 {
483         struct cc26xx_bank *cc26xx_bank = bank->driver_priv;
484
485         int retval = ERROR_OK;
486
487         if (!cc26xx_bank->probed)
488                 retval = cc26xx_probe(bank);
489
490         return retval;
491 }
492
493 static int cc26xx_info(struct flash_bank *bank, struct command_invocation *cmd)
494 {
495         struct cc26xx_bank *cc26xx_bank = bank->driver_priv;
496         const char *device;
497
498         switch (cc26xx_bank->device_type) {
499                 case CC26X0_TYPE:
500                         device = "CC26x0";
501                         break;
502                 case CC26X1_TYPE:
503                         device = "CC26x1";
504                         break;
505                 case CC13X0_TYPE:
506                         device = "CC13x0";
507                         break;
508                 case CC13X2_TYPE:
509                         device = "CC13x2";
510                         break;
511                 case CC26X2_TYPE:
512                         device = "CC26x2";
513                         break;
514                 case CC26XX_NO_TYPE:
515                 default:
516                         device = "Unrecognized";
517                         break;
518         }
519
520         command_print_sameline(cmd,
521                 "%s device: ICEPick ID 0x%08" PRIx32 ", USER ID 0x%08" PRIx32 "\n",
522                 device, cc26xx_bank->icepick_id, cc26xx_bank->user_id);
523
524         return ERROR_OK;
525 }
526
527 const struct flash_driver cc26xx_flash = {
528         .name = "cc26xx",
529         .flash_bank_command = cc26xx_flash_bank_command,
530         .erase = cc26xx_erase,
531         .write = cc26xx_write,
532         .read = default_flash_read,
533         .probe = cc26xx_probe,
534         .auto_probe = cc26xx_auto_probe,
535         .erase_check = default_flash_blank_check,
536         .info = cc26xx_info,
537         .free_driver_priv = default_flash_free_driver_priv,
538 };