+static int cfi_spansion_write_words(struct flash_bank_s *bank, u8 *word, u32 wordcount, u32 address)
+{
+ int retval;
+ cfi_flash_bank_t *cfi_info = bank->driver_priv;
+ target_t *target = bank->target;
+ u8 command[8];
+ cfi_spansion_pri_ext_t *pri_ext = cfi_info->pri_ext;
+
+ /* Calculate buffer size and boundary mask */
+ u32 buffersize = (1UL << cfi_info->max_buf_write_size) * (bank->bus_width / bank->chip_width);
+ u32 buffermask = buffersize-1;
+ u32 bufferwsize;
+
+ /* Check for valid range */
+ if (address & buffermask)
+ {
+ LOG_ERROR("Write address at base 0x%x, address %x not aligned to 2^%d boundary", bank->base, address, cfi_info->max_buf_write_size);
+ return ERROR_FLASH_OPERATION_FAILED;
+ }
+ switch(bank->chip_width)
+ {
+ case 4 : bufferwsize = buffersize / 4; break;
+ case 2 : bufferwsize = buffersize / 2; break;
+ case 1 : bufferwsize = buffersize; break;
+ default:
+ LOG_ERROR("Unsupported chip width %d", bank->chip_width);
+ return ERROR_FLASH_OPERATION_FAILED;
+ }
+
+ bufferwsize/=(bank->bus_width / bank->chip_width);
+
+ /* Check for valid size */
+ if (wordcount > bufferwsize)
+ {
+ LOG_ERROR("Number of data words %d exceeds available buffersize %d", wordcount, buffersize);
+ return ERROR_FLASH_OPERATION_FAILED;
+ }
+
+ // Unlock
+ cfi_command(bank, 0xaa, command);
+ if((retval = target->type->write_memory(target, flash_address(bank, 0, pri_ext->_unlock1), bank->bus_width, 1, command)) != ERROR_OK)
+ {
+ return retval;
+ }
+
+ cfi_command(bank, 0x55, command);
+ if((retval = target->type->write_memory(target, flash_address(bank, 0, pri_ext->_unlock2), bank->bus_width, 1, command)) != ERROR_OK)
+ {
+ return retval;
+ }
+
+ // Buffer load command
+ cfi_command(bank, 0x25, command);
+ if((retval = target->type->write_memory(target, address, bank->bus_width, 1, command)) != ERROR_OK)
+ {
+ return retval;
+ }
+
+ /* Write buffer wordcount-1 and data words */
+ cfi_command(bank, bufferwsize-1, command);
+ if((retval = target->type->write_memory(target, address, bank->bus_width, 1, command)) != ERROR_OK)
+ {
+ return retval;
+ }
+
+ if((retval = target->type->write_memory(target, address, bank->bus_width, bufferwsize, word)) != ERROR_OK)
+ {
+ return retval;
+ }
+
+ /* Commit write operation */
+ cfi_command(bank, 0x29, command);
+ if((retval = target->type->write_memory(target, address, bank->bus_width, 1, command)) != ERROR_OK)
+ {
+ return retval;
+ }
+
+ if (cfi_spansion_wait_status_busy(bank, 1000 * (1 << cfi_info->word_write_timeout_max)) != ERROR_OK)
+ {
+ cfi_command(bank, 0xf0, command);
+ if((retval = target->type->write_memory(target, flash_address(bank, 0, 0x0), bank->bus_width, 1, command)) != ERROR_OK)
+ {
+ return retval;
+ }
+
+ LOG_ERROR("couldn't write block at base 0x%x, address %x, size %x", bank->base, address, bufferwsize);
+ return ERROR_FLASH_OPERATION_FAILED;
+ }
+
+ return ERROR_OK;
+}
+
+static int cfi_write_word(struct flash_bank_s *bank, u8 *word, u32 address)