+/**
+ * Get aligned start address of a flash write region
+ */
+target_addr_t flash_write_align_start(struct flash_bank *bank, target_addr_t addr)
+{
+ if (addr < bank->base || addr >= bank->base + bank->size
+ || bank->write_start_alignment <= 1)
+ return addr;
+
+ if (bank->write_start_alignment == FLASH_WRITE_ALIGN_SECTOR) {
+ uint32_t offset = addr - bank->base;
+ uint32_t aligned = 0;
+ int sect;
+ for (sect = 0; sect < bank->num_sectors; sect++) {
+ if (bank->sectors[sect].offset > offset)
+ break;
+
+ aligned = bank->sectors[sect].offset;
+ }
+ return bank->base + aligned;
+ }
+
+ return addr & ~(bank->write_start_alignment - 1);
+}
+
+/**
+ * Get aligned end address of a flash write region
+ */
+target_addr_t flash_write_align_end(struct flash_bank *bank, target_addr_t addr)
+{
+ if (addr < bank->base || addr >= bank->base + bank->size
+ || bank->write_end_alignment <= 1)
+ return addr;
+
+ if (bank->write_end_alignment == FLASH_WRITE_ALIGN_SECTOR) {
+ uint32_t offset = addr - bank->base;
+ uint32_t aligned = 0;
+ int sect;
+ for (sect = 0; sect < bank->num_sectors; sect++) {
+ aligned = bank->sectors[sect].offset + bank->sectors[sect].size - 1;
+ if (aligned >= offset)
+ break;
+ }
+ return bank->base + aligned;
+ }
+
+ return addr | (bank->write_end_alignment - 1);
+}
+
+/**
+ * Check if gap between sections is bigger than minimum required to discontinue flash write
+ */
+static bool flash_write_check_gap(struct flash_bank *bank,
+ target_addr_t addr1, target_addr_t addr2)
+{
+ if (bank->minimal_write_gap == FLASH_WRITE_CONTINUOUS
+ || addr1 < bank->base || addr1 >= bank->base + bank->size
+ || addr2 < bank->base || addr2 >= bank->base + bank->size)
+ return false;
+
+ if (bank->minimal_write_gap == FLASH_WRITE_GAP_SECTOR) {
+ int sect;
+ uint32_t offset1 = addr1 - bank->base;
+ /* find the sector following the one containing addr1 */
+ for (sect = 0; sect < bank->num_sectors; sect++) {
+ if (bank->sectors[sect].offset > offset1)
+ break;
+ }
+ if (sect >= bank->num_sectors)
+ return false;
+
+ uint32_t offset2 = addr2 - bank->base;
+ return bank->sectors[sect].offset + bank->sectors[sect].size <= offset2;
+ }
+
+ target_addr_t aligned1 = flash_write_align_end(bank, addr1);
+ target_addr_t aligned2 = flash_write_align_start(bank, addr2);
+ return aligned1 + bank->minimal_write_gap < aligned2;
+}
+
+