flash/nor: remove useless bank->next = NULL
[openocd.git] / src / flash / nor / cc3220sf.c
blob74cb7aea572358bd67c0a71a9c54eaacb5c8cbeb
1 // SPDX-License-Identifier: GPL-2.0-or-later
3 /***************************************************************************
4 * Copyright (C) 2017 by Texas Instruments, Inc. *
5 ***************************************************************************/
7 #ifdef HAVE_CONFIG_H
8 #include "config.h"
9 #endif
11 #include "imp.h"
12 #include "cc3220sf.h"
13 #include <helper/binarybuffer.h>
14 #include <helper/time_support.h>
15 #include <target/algorithm.h>
16 #include <target/armv7m.h>
18 #define FLASH_TIMEOUT 5000
20 struct cc3220sf_bank {
21 bool probed;
22 struct armv7m_algorithm armv7m_info;
25 /* Flash helper algorithm for CC3220SF */
26 static const uint8_t cc3220sf_algo[] = {
27 #include "../../../contrib/loaders/flash/cc3220sf/cc3220sf.inc"
30 static int cc3220sf_mass_erase(struct flash_bank *bank)
32 struct target *target = bank->target;
33 bool done;
34 long long start_ms;
35 long long elapsed_ms;
36 uint32_t value;
38 int retval = ERROR_OK;
40 if (target->state != TARGET_HALTED) {
41 LOG_ERROR("Target not halted");
42 return ERROR_TARGET_NOT_HALTED;
45 /* Set starting address to erase to zero */
46 retval = target_write_u32(target, FMA_REGISTER_ADDR, 0);
47 if (retval != ERROR_OK)
48 return retval;
50 /* Write the MERASE bit of the FMC register */
51 retval = target_write_u32(target, FMC_REGISTER_ADDR, FMC_MERASE_VALUE);
52 if (retval != ERROR_OK)
53 return retval;
55 /* Poll the MERASE bit until the mass erase is complete */
56 done = false;
57 start_ms = timeval_ms();
58 while (!done) {
59 retval = target_read_u32(target, FMC_REGISTER_ADDR, &value);
60 if (retval != ERROR_OK)
61 return retval;
63 if ((value & FMC_MERASE_BIT) == 0) {
64 /* Bit clears when mass erase is finished */
65 done = true;
66 } else {
67 elapsed_ms = timeval_ms() - start_ms;
68 if (elapsed_ms > 500)
69 keep_alive();
70 if (elapsed_ms > FLASH_TIMEOUT)
71 break;
75 if (!done) {
76 /* Mass erase timed out waiting for confirmation */
77 return ERROR_FAIL;
80 return retval;
83 FLASH_BANK_COMMAND_HANDLER(cc3220sf_flash_bank_command)
85 struct cc3220sf_bank *cc3220sf_bank;
87 if (CMD_ARGC < 6)
88 return ERROR_COMMAND_SYNTAX_ERROR;
90 cc3220sf_bank = malloc(sizeof(struct cc3220sf_bank));
91 if (!cc3220sf_bank)
92 return ERROR_FAIL;
94 /* Initialize private flash information */
95 cc3220sf_bank->probed = false;
97 /* Finish initialization of flash bank */
98 bank->driver_priv = cc3220sf_bank;
100 return ERROR_OK;
103 static int cc3220sf_erase(struct flash_bank *bank, unsigned int first,
104 unsigned int last)
106 struct target *target = bank->target;
107 bool done;
108 long long start_ms;
109 long long elapsed_ms;
110 uint32_t address;
111 uint32_t value;
113 int retval = ERROR_OK;
115 if (target->state != TARGET_HALTED) {
116 LOG_ERROR("Target not halted");
117 return ERROR_TARGET_NOT_HALTED;
120 /* Do a mass erase if user requested all sectors of flash */
121 if ((first == 0) && (last == (bank->num_sectors - 1))) {
122 /* Request mass erase of flash */
123 return cc3220sf_mass_erase(bank);
126 /* Erase requested sectors one by one */
127 for (unsigned int i = first; i <= last; i++) {
129 /* Determine address of sector to erase */
130 address = FLASH_BASE_ADDR + i * FLASH_SECTOR_SIZE;
132 /* Set starting address to erase */
133 retval = target_write_u32(target, FMA_REGISTER_ADDR, address);
134 if (retval != ERROR_OK)
135 return retval;
137 /* Write the ERASE bit of the FMC register */
138 retval = target_write_u32(target, FMC_REGISTER_ADDR, FMC_ERASE_VALUE);
139 if (retval != ERROR_OK)
140 return retval;
142 /* Poll the ERASE bit until the erase is complete */
143 done = false;
144 start_ms = timeval_ms();
145 while (!done) {
146 retval = target_read_u32(target, FMC_REGISTER_ADDR, &value);
147 if (retval != ERROR_OK)
148 return retval;
150 if ((value & FMC_ERASE_BIT) == 0) {
151 /* Bit clears when mass erase is finished */
152 done = true;
153 } else {
154 elapsed_ms = timeval_ms() - start_ms;
155 if (elapsed_ms > 500)
156 keep_alive();
157 if (elapsed_ms > FLASH_TIMEOUT)
158 break;
162 if (!done) {
163 /* Sector erase timed out waiting for confirmation */
164 return ERROR_FAIL;
168 return retval;
171 static int cc3220sf_write(struct flash_bank *bank, const uint8_t *buffer,
172 uint32_t offset, uint32_t count)
174 struct target *target = bank->target;
175 struct cc3220sf_bank *cc3220sf_bank = bank->driver_priv;
176 struct working_area *algo_working_area;
177 struct working_area *buffer_working_area;
178 struct reg_param reg_params[3];
179 uint32_t algo_base_address;
180 uint32_t algo_buffer_address;
181 uint32_t algo_buffer_size;
182 uint32_t address;
183 uint32_t remaining;
184 uint32_t words;
185 uint32_t result;
187 int retval = ERROR_OK;
189 if (target->state != TARGET_HALTED) {
190 LOG_ERROR("Target not halted");
191 return ERROR_TARGET_NOT_HALTED;
194 /* Obtain working area to use for flash helper algorithm */
195 retval = target_alloc_working_area(target, sizeof(cc3220sf_algo),
196 &algo_working_area);
197 if (retval != ERROR_OK)
198 return retval;
200 /* Obtain working area to use for flash buffer */
201 retval = target_alloc_working_area(target,
202 target_get_working_area_avail(target), &buffer_working_area);
203 if (retval != ERROR_OK) {
204 target_free_working_area(target, algo_working_area);
205 return retval;
208 algo_base_address = algo_working_area->address;
209 algo_buffer_address = buffer_working_area->address;
210 algo_buffer_size = buffer_working_area->size;
212 /* Make sure buffer size is a multiple of 32 word (0x80 byte) chunks */
213 /* (algo runs more efficiently if it operates on 32 words at a time) */
214 if (algo_buffer_size > 0x80)
215 algo_buffer_size &= ~0x7f;
217 /* Write flash helper algorithm into target memory */
218 retval = target_write_buffer(target, algo_base_address,
219 sizeof(cc3220sf_algo), cc3220sf_algo);
220 if (retval != ERROR_OK) {
221 target_free_working_area(target, algo_working_area);
222 target_free_working_area(target, buffer_working_area);
223 return retval;
226 /* Initialize the ARMv7m specific info to run the algorithm */
227 cc3220sf_bank->armv7m_info.common_magic = ARMV7M_COMMON_MAGIC;
228 cc3220sf_bank->armv7m_info.core_mode = ARM_MODE_THREAD;
230 /* Initialize register params for flash helper algorithm */
231 init_reg_param(&reg_params[0], "r0", 32, PARAM_OUT);
232 init_reg_param(&reg_params[1], "r1", 32, PARAM_OUT);
233 init_reg_param(&reg_params[2], "r2", 32, PARAM_IN_OUT);
235 /* Prepare to write to flash */
236 address = FLASH_BASE_ADDR + offset;
237 remaining = count;
239 /* The flash hardware can only write complete words to flash. If
240 * an unaligned address is passed in, we must do a read-modify-write
241 * on a word with enough bytes to align the rest of the buffer. And
242 * if less than a whole word remains at the end, we must also do a
243 * read-modify-write on a final word to finish up.
246 /* Do one word write to align address on 32-bit boundary if needed */
247 if (0 != (address & 0x3)) {
248 uint8_t head[4];
250 /* Get starting offset for data to write (will be 1 to 3) */
251 uint32_t head_offset = address & 0x03;
253 /* Get the aligned address to write this first word to */
254 uint32_t head_address = address & 0xfffffffc;
256 /* Retrieve what is already in flash at the head address */
257 retval = target_read_buffer(target, head_address, sizeof(head), head);
259 if (retval == ERROR_OK) {
260 /* Substitute in the new data to write */
261 while ((remaining > 0) && (head_offset < 4)) {
262 head[head_offset] = *buffer;
263 head_offset++;
264 address++;
265 buffer++;
266 remaining--;
270 if (retval == ERROR_OK) {
271 /* Helper parameters are passed in registers R0-R2 */
272 /* Set start of data buffer, address to write to, and word count */
273 buf_set_u32(reg_params[0].value, 0, 32, algo_buffer_address);
274 buf_set_u32(reg_params[1].value, 0, 32, head_address);
275 buf_set_u32(reg_params[2].value, 0, 32, 1);
277 /* Write head value into buffer to flash */
278 retval = target_write_buffer(target, algo_buffer_address,
279 sizeof(head), head);
282 if (retval == ERROR_OK) {
283 /* Execute the flash helper algorithm */
284 retval = target_run_algorithm(target, 0, NULL, 3, reg_params,
285 algo_base_address, 0, FLASH_TIMEOUT,
286 &cc3220sf_bank->armv7m_info);
287 if (retval != ERROR_OK)
288 LOG_ERROR("cc3220sf: Flash algorithm failed to run");
290 /* Check that the head value was written to flash */
291 result = buf_get_u32(reg_params[2].value, 0, 32);
292 if (result != 0) {
293 retval = ERROR_FAIL;
294 LOG_ERROR("cc3220sf: Flash operation failed");
299 /* Check if there's data at end of buffer that isn't a full word */
300 uint32_t tail_count = remaining & 0x03;
301 /* Adjust remaining so it is a multiple of whole words */
302 remaining -= tail_count;
304 while ((retval == ERROR_OK) && (remaining > 0)) {
305 /* Set start of data buffer and address to write to */
306 buf_set_u32(reg_params[0].value, 0, 32, algo_buffer_address);
307 buf_set_u32(reg_params[1].value, 0, 32, address);
309 /* Download data to write into memory buffer */
310 if (remaining >= algo_buffer_size) {
311 /* Fill up buffer with data to flash */
312 retval = target_write_buffer(target, algo_buffer_address,
313 algo_buffer_size, buffer);
314 if (retval != ERROR_OK)
315 break;
317 /* Count to write is in 32-bit words */
318 words = algo_buffer_size / 4;
320 /* Bump variables to next data */
321 address += algo_buffer_size;
322 buffer += algo_buffer_size;
323 remaining -= algo_buffer_size;
324 } else {
325 /* Fill buffer with what's left of the data */
326 retval = target_write_buffer(target, algo_buffer_address,
327 remaining, buffer);
328 if (retval != ERROR_OK)
329 break;
331 /* Calculate the final word count to write */
332 words = remaining / 4;
333 if (0 != (remaining % 4))
334 words++;
336 /* Bump variables to any final data */
337 address += remaining;
338 buffer += remaining;
339 remaining = 0;
342 /* Set number of words to write */
343 buf_set_u32(reg_params[2].value, 0, 32, words);
345 /* Execute the flash helper algorithm */
346 retval = target_run_algorithm(target, 0, NULL, 3, reg_params,
347 algo_base_address, 0, FLASH_TIMEOUT,
348 &cc3220sf_bank->armv7m_info);
349 if (retval != ERROR_OK) {
350 LOG_ERROR("cc3220sf: Flash algorithm failed to run");
351 break;
354 /* Check that all words were written to flash */
355 result = buf_get_u32(reg_params[2].value, 0, 32);
356 if (result != 0) {
357 retval = ERROR_FAIL;
358 LOG_ERROR("cc3220sf: Flash operation failed");
359 break;
362 keep_alive();
365 /* Do one word write for any final bytes less than a full word */
366 if ((retval == ERROR_OK) && (tail_count != 0)) {
367 uint8_t tail[4];
369 /* Set starting byte offset for data to write */
370 uint32_t tail_offset = 0;
372 /* Retrieve what is already in flash at the tail address */
373 retval = target_read_buffer(target, address, sizeof(tail), tail);
375 if (retval == ERROR_OK) {
376 /* Substitute in the new data to write */
377 while (tail_count > 0) {
378 tail[tail_offset] = *buffer;
379 tail_offset++;
380 buffer++;
381 tail_count--;
385 if (retval == ERROR_OK) {
386 /* Set start of data buffer, address to write to, and word count */
387 buf_set_u32(reg_params[0].value, 0, 32, algo_buffer_address);
388 buf_set_u32(reg_params[1].value, 0, 32, address);
389 buf_set_u32(reg_params[2].value, 0, 32, 1);
391 /* Write tail value into buffer to flash */
392 retval = target_write_buffer(target, algo_buffer_address,
393 sizeof(tail), tail);
396 if (retval == ERROR_OK) {
397 /* Execute the flash helper algorithm */
398 retval = target_run_algorithm(target, 0, NULL, 3, reg_params,
399 algo_base_address, 0, FLASH_TIMEOUT,
400 &cc3220sf_bank->armv7m_info);
401 if (retval != ERROR_OK)
402 LOG_ERROR("cc3220sf: Flash algorithm failed to run");
404 /* Check that the tail was written to flash */
405 result = buf_get_u32(reg_params[2].value, 0, 32);
406 if (result != 0) {
407 retval = ERROR_FAIL;
408 LOG_ERROR("cc3220sf: Flash operation failed");
413 /* Free resources */
414 destroy_reg_param(&reg_params[0]);
415 destroy_reg_param(&reg_params[1]);
416 destroy_reg_param(&reg_params[2]);
417 target_free_working_area(target, algo_working_area);
418 target_free_working_area(target, buffer_working_area);
420 return retval;
423 static int cc3220sf_probe(struct flash_bank *bank)
425 struct cc3220sf_bank *cc3220sf_bank = bank->driver_priv;
427 uint32_t base;
428 uint32_t size;
429 unsigned int num_sectors;
431 base = FLASH_BASE_ADDR;
432 size = FLASH_NUM_SECTORS * FLASH_SECTOR_SIZE;
433 num_sectors = FLASH_NUM_SECTORS;
435 free(bank->sectors);
437 bank->sectors = malloc(sizeof(struct flash_sector) * num_sectors);
438 if (!bank->sectors)
439 return ERROR_FAIL;
441 bank->base = base;
442 bank->size = size;
443 bank->write_start_alignment = 0;
444 bank->write_end_alignment = 0;
445 bank->num_sectors = num_sectors;
447 for (unsigned int i = 0; i < num_sectors; i++) {
448 bank->sectors[i].offset = i * FLASH_SECTOR_SIZE;
449 bank->sectors[i].size = FLASH_SECTOR_SIZE;
450 bank->sectors[i].is_erased = -1;
451 bank->sectors[i].is_protected = 0;
454 /* We've successfully recorded the stats on this flash bank */
455 cc3220sf_bank->probed = true;
457 /* If we fall through to here, then all went well */
459 return ERROR_OK;
462 static int cc3220sf_auto_probe(struct flash_bank *bank)
464 struct cc3220sf_bank *cc3220sf_bank = bank->driver_priv;
466 int retval = ERROR_OK;
468 if (!cc3220sf_bank->probed)
469 retval = cc3220sf_probe(bank);
471 return retval;
474 static int cc3220sf_info(struct flash_bank *bank, struct command_invocation *cmd)
476 command_print_sameline(cmd, "CC3220SF with 1MB internal flash\n");
477 return ERROR_OK;
480 const struct flash_driver cc3220sf_flash = {
481 .name = "cc3220sf",
482 .flash_bank_command = cc3220sf_flash_bank_command,
483 .erase = cc3220sf_erase,
484 .write = cc3220sf_write,
485 .read = default_flash_read,
486 .probe = cc3220sf_probe,
487 .auto_probe = cc3220sf_auto_probe,
488 .erase_check = default_flash_blank_check,
489 .info = cc3220sf_info,
490 .free_driver_priv = default_flash_free_driver_priv,