1 /* SPDX-License-Identifier: GPL-2.0-or-later */
3 /***************************************************************************
4 * Copyright (C) 2017 by Texas Instruments, Inc. *
5 ***************************************************************************/
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 {
22 struct armv7m_algorithm armv7m_info;
25 static int cc3220sf_mass_erase(struct flash_bank *bank)
27 struct target *target = bank->target;
33 int retval = ERROR_OK;
35 if (target->state != TARGET_HALTED) {
36 LOG_ERROR("Target not halted");
37 return ERROR_TARGET_NOT_HALTED;
40 /* Set starting address to erase to zero */
41 retval = target_write_u32(target, FMA_REGISTER_ADDR, 0);
42 if (retval != ERROR_OK)
45 /* Write the MERASE bit of the FMC register */
46 retval = target_write_u32(target, FMC_REGISTER_ADDR, FMC_MERASE_VALUE);
47 if (retval != ERROR_OK)
50 /* Poll the MERASE bit until the mass erase is complete */
52 start_ms = timeval_ms();
54 retval = target_read_u32(target, FMC_REGISTER_ADDR, &value);
55 if (retval != ERROR_OK)
58 if ((value & FMC_MERASE_BIT) == 0) {
59 /* Bit clears when mass erase is finished */
62 elapsed_ms = timeval_ms() - start_ms;
65 if (elapsed_ms > FLASH_TIMEOUT)
71 /* Mass erase timed out waiting for confirmation */
78 FLASH_BANK_COMMAND_HANDLER(cc3220sf_flash_bank_command)
80 struct cc3220sf_bank *cc3220sf_bank;
83 return ERROR_COMMAND_SYNTAX_ERROR;
85 cc3220sf_bank = malloc(sizeof(struct cc3220sf_bank));
89 /* Initialize private flash information */
90 cc3220sf_bank->probed = false;
92 /* Finish initialization of flash bank */
93 bank->driver_priv = cc3220sf_bank;
99 static int cc3220sf_erase(struct flash_bank *bank, unsigned int first,
102 struct target *target = bank->target;
105 long long elapsed_ms;
109 int retval = ERROR_OK;
111 if (target->state != TARGET_HALTED) {
112 LOG_ERROR("Target not halted");
113 return ERROR_TARGET_NOT_HALTED;
116 /* Do a mass erase if user requested all sectors of flash */
117 if ((first == 0) && (last == (bank->num_sectors - 1))) {
118 /* Request mass erase of flash */
119 return cc3220sf_mass_erase(bank);
122 /* Erase requested sectors one by one */
123 for (unsigned int i = first; i <= last; i++) {
125 /* Determine address of sector to erase */
126 address = FLASH_BASE_ADDR + i * FLASH_SECTOR_SIZE;
128 /* Set starting address to erase */
129 retval = target_write_u32(target, FMA_REGISTER_ADDR, address);
130 if (retval != ERROR_OK)
133 /* Write the ERASE bit of the FMC register */
134 retval = target_write_u32(target, FMC_REGISTER_ADDR, FMC_ERASE_VALUE);
135 if (retval != ERROR_OK)
138 /* Poll the ERASE bit until the erase is complete */
140 start_ms = timeval_ms();
142 retval = target_read_u32(target, FMC_REGISTER_ADDR, &value);
143 if (retval != ERROR_OK)
146 if ((value & FMC_ERASE_BIT) == 0) {
147 /* Bit clears when mass erase is finished */
150 elapsed_ms = timeval_ms() - start_ms;
151 if (elapsed_ms > 500)
153 if (elapsed_ms > FLASH_TIMEOUT)
159 /* Sector erase timed out waiting for confirmation */
167 static int cc3220sf_write(struct flash_bank *bank, const uint8_t *buffer,
168 uint32_t offset, uint32_t count)
170 struct target *target = bank->target;
171 struct cc3220sf_bank *cc3220sf_bank = bank->driver_priv;
172 struct working_area *algo_working_area;
173 struct working_area *buffer_working_area;
174 struct reg_param reg_params[3];
175 uint32_t algo_base_address;
176 uint32_t algo_buffer_address;
177 uint32_t algo_buffer_size;
183 int retval = ERROR_OK;
185 if (target->state != TARGET_HALTED) {
186 LOG_ERROR("Target not halted");
187 return ERROR_TARGET_NOT_HALTED;
190 /* Obtain working area to use for flash helper algorithm */
191 retval = target_alloc_working_area(target, sizeof(cc3220sf_algo),
193 if (retval != ERROR_OK)
196 /* Obtain working area to use for flash buffer */
197 retval = target_alloc_working_area(target,
198 target_get_working_area_avail(target), &buffer_working_area);
199 if (retval != ERROR_OK) {
200 target_free_working_area(target, algo_working_area);
204 algo_base_address = algo_working_area->address;
205 algo_buffer_address = buffer_working_area->address;
206 algo_buffer_size = buffer_working_area->size;
208 /* Make sure buffer size is a multiple of 32 word (0x80 byte) chunks */
209 /* (algo runs more efficiently if it operates on 32 words at a time) */
210 if (algo_buffer_size > 0x80)
211 algo_buffer_size &= ~0x7f;
213 /* Write flash helper algorithm into target memory */
214 retval = target_write_buffer(target, algo_base_address,
215 sizeof(cc3220sf_algo), cc3220sf_algo);
216 if (retval != ERROR_OK) {
217 target_free_working_area(target, algo_working_area);
218 target_free_working_area(target, buffer_working_area);
222 /* Initialize the ARMv7m specific info to run the algorithm */
223 cc3220sf_bank->armv7m_info.common_magic = ARMV7M_COMMON_MAGIC;
224 cc3220sf_bank->armv7m_info.core_mode = ARM_MODE_THREAD;
226 /* Initialize register params for flash helper algorithm */
227 init_reg_param(®_params[0], "r0", 32, PARAM_OUT);
228 init_reg_param(®_params[1], "r1", 32, PARAM_OUT);
229 init_reg_param(®_params[2], "r2", 32, PARAM_IN_OUT);
231 /* Prepare to write to flash */
232 address = FLASH_BASE_ADDR + offset;
235 /* The flash hardware can only write complete words to flash. If
236 * an unaligned address is passed in, we must do a read-modify-write
237 * on a word with enough bytes to align the rest of the buffer. And
238 * if less than a whole word remains at the end, we must also do a
239 * read-modify-write on a final word to finish up.
242 /* Do one word write to align address on 32-bit boundary if needed */
243 if (0 != (address & 0x3)) {
246 /* Get starting offset for data to write (will be 1 to 3) */
247 uint32_t head_offset = address & 0x03;
249 /* Get the aligned address to write this first word to */
250 uint32_t head_address = address & 0xfffffffc;
252 /* Retrieve what is already in flash at the head address */
253 retval = target_read_buffer(target, head_address, sizeof(head), head);
255 if (retval == ERROR_OK) {
256 /* Substitute in the new data to write */
257 while ((remaining > 0) && (head_offset < 4)) {
258 head[head_offset] = *buffer;
266 if (retval == ERROR_OK) {
267 /* Helper parameters are passed in registers R0-R2 */
268 /* Set start of data buffer, address to write to, and word count */
269 buf_set_u32(reg_params[0].value, 0, 32, algo_buffer_address);
270 buf_set_u32(reg_params[1].value, 0, 32, head_address);
271 buf_set_u32(reg_params[2].value, 0, 32, 1);
273 /* Write head value into buffer to flash */
274 retval = target_write_buffer(target, algo_buffer_address,
278 if (retval == ERROR_OK) {
279 /* Execute the flash helper algorithm */
280 retval = target_run_algorithm(target, 0, NULL, 3, reg_params,
281 algo_base_address, 0, FLASH_TIMEOUT,
282 &cc3220sf_bank->armv7m_info);
283 if (retval != ERROR_OK)
284 LOG_ERROR("cc3220sf: Flash algorithm failed to run");
286 /* Check that the head value was written to flash */
287 result = buf_get_u32(reg_params[2].value, 0, 32);
290 LOG_ERROR("cc3220sf: Flash operation failed");
295 /* Check if there's data at end of buffer that isn't a full word */
296 uint32_t tail_count = remaining & 0x03;
297 /* Adjust remaining so it is a multiple of whole words */
298 remaining -= tail_count;
300 while ((retval == ERROR_OK) && (remaining > 0)) {
301 /* Set start of data buffer and address to write to */
302 buf_set_u32(reg_params[0].value, 0, 32, algo_buffer_address);
303 buf_set_u32(reg_params[1].value, 0, 32, address);
305 /* Download data to write into memory buffer */
306 if (remaining >= algo_buffer_size) {
307 /* Fill up buffer with data to flash */
308 retval = target_write_buffer(target, algo_buffer_address,
309 algo_buffer_size, buffer);
310 if (retval != ERROR_OK)
313 /* Count to write is in 32-bit words */
314 words = algo_buffer_size / 4;
316 /* Bump variables to next data */
317 address += algo_buffer_size;
318 buffer += algo_buffer_size;
319 remaining -= algo_buffer_size;
321 /* Fill buffer with what's left of the data */
322 retval = target_write_buffer(target, algo_buffer_address,
324 if (retval != ERROR_OK)
327 /* Calculate the final word count to write */
328 words = remaining / 4;
329 if (0 != (remaining % 4))
332 /* Bump variables to any final data */
333 address += remaining;
338 /* Set number of words to write */
339 buf_set_u32(reg_params[2].value, 0, 32, words);
341 /* Execute the flash helper algorithm */
342 retval = target_run_algorithm(target, 0, NULL, 3, reg_params,
343 algo_base_address, 0, FLASH_TIMEOUT,
344 &cc3220sf_bank->armv7m_info);
345 if (retval != ERROR_OK) {
346 LOG_ERROR("cc3220sf: Flash algorithm failed to run");
350 /* Check that all words were written to flash */
351 result = buf_get_u32(reg_params[2].value, 0, 32);
354 LOG_ERROR("cc3220sf: Flash operation failed");
361 /* Do one word write for any final bytes less than a full word */
362 if ((retval == ERROR_OK) && (tail_count != 0)) {
365 /* Set starting byte offset for data to write */
366 uint32_t tail_offset = 0;
368 /* Retrieve what is already in flash at the tail address */
369 retval = target_read_buffer(target, address, sizeof(tail), tail);
371 if (retval == ERROR_OK) {
372 /* Substitute in the new data to write */
373 while (tail_count > 0) {
374 tail[tail_offset] = *buffer;
381 if (retval == ERROR_OK) {
382 /* Set start of data buffer, address to write to, and word count */
383 buf_set_u32(reg_params[0].value, 0, 32, algo_buffer_address);
384 buf_set_u32(reg_params[1].value, 0, 32, address);
385 buf_set_u32(reg_params[2].value, 0, 32, 1);
387 /* Write tail value into buffer to flash */
388 retval = target_write_buffer(target, algo_buffer_address,
392 if (retval == ERROR_OK) {
393 /* Execute the flash helper algorithm */
394 retval = target_run_algorithm(target, 0, NULL, 3, reg_params,
395 algo_base_address, 0, FLASH_TIMEOUT,
396 &cc3220sf_bank->armv7m_info);
397 if (retval != ERROR_OK)
398 LOG_ERROR("cc3220sf: Flash algorithm failed to run");
400 /* Check that the tail was written to flash */
401 result = buf_get_u32(reg_params[2].value, 0, 32);
404 LOG_ERROR("cc3220sf: Flash operation failed");
410 destroy_reg_param(®_params[0]);
411 destroy_reg_param(®_params[1]);
412 destroy_reg_param(®_params[2]);
413 target_free_working_area(target, algo_working_area);
414 target_free_working_area(target, buffer_working_area);
419 static int cc3220sf_probe(struct flash_bank *bank)
421 struct cc3220sf_bank *cc3220sf_bank = bank->driver_priv;
425 unsigned int num_sectors;
427 base = FLASH_BASE_ADDR;
428 size = FLASH_NUM_SECTORS * FLASH_SECTOR_SIZE;
429 num_sectors = FLASH_NUM_SECTORS;
433 bank->sectors = malloc(sizeof(struct flash_sector) * num_sectors);
439 bank->write_start_alignment = 0;
440 bank->write_end_alignment = 0;
441 bank->num_sectors = num_sectors;
443 for (unsigned int i = 0; i < num_sectors; i++) {
444 bank->sectors[i].offset = i * FLASH_SECTOR_SIZE;
445 bank->sectors[i].size = FLASH_SECTOR_SIZE;
446 bank->sectors[i].is_erased = -1;
447 bank->sectors[i].is_protected = 0;
450 /* We've successfully recorded the stats on this flash bank */
451 cc3220sf_bank->probed = true;
453 /* If we fall through to here, then all went well */
458 static int cc3220sf_auto_probe(struct flash_bank *bank)
460 struct cc3220sf_bank *cc3220sf_bank = bank->driver_priv;
462 int retval = ERROR_OK;
464 if (!cc3220sf_bank->probed)
465 retval = cc3220sf_probe(bank);
470 static int cc3220sf_info(struct flash_bank *bank, struct command_invocation *cmd)
472 command_print_sameline(cmd, "CC3220SF with 1MB internal flash\n");
476 const struct flash_driver cc3220sf_flash = {
478 .flash_bank_command = cc3220sf_flash_bank_command,
479 .erase = cc3220sf_erase,
480 .write = cc3220sf_write,
481 .read = default_flash_read,
482 .probe = cc3220sf_probe,
483 .auto_probe = cc3220sf_auto_probe,
484 .erase_check = default_flash_blank_check,
485 .info = cc3220sf_info,
486 .free_driver_priv = default_flash_free_driver_priv,