scripts: runners: ezflashcli: Add support to flash images for MCUboot

Internal bootloader will only run application image if valid product
header is present on flash. This means product header is required for
application that are not linked to code partition. Other applications
that are linked to code partition are meant to be run by MCUboot and
should not touch product header, with the exception of MCUboot itself
which is also run by internal bootloader so requires product header.

Default flash load offset for applications not linked to code partition
is set to 0x2400 as this is where internal bootloader looks for an
application image to run based on product header written by flasher.

Flash load offset for MCUboot is set from boot partition.

Valid product header is added by ezFlashCLI when using "flash_image"
command.

Co-authored-by: Andrzej Kaczmarek <andrzej.kaczmarek@codecoup.pl>
Signed-off-by: Andrzej Kaczmarek <andrzej.kaczmarek@codecoup.pl>
Signed-off-by: Niek Ilmer <niek.ilmer.aj@renesas.com>
diff --git a/scripts/west_commands/runners/ezflashcli.py b/scripts/west_commands/runners/ezflashcli.py
index e92bcd1..4d9d3d3 100644
--- a/scripts/west_commands/runners/ezflashcli.py
+++ b/scripts/west_commands/runners/ezflashcli.py
@@ -39,13 +39,30 @@
         return EzFlashCliBinaryRunner(cfg, tool=args.tool, sn=args.sn,
                                       erase=args.erase)
 
+    def needs_product_header(self):
+        # Applications linked to code partition are meant to be run by MCUboot
+        # and do not require product header. Other applications and MCUboot itself
+        # are run by internal bootloader and thus require valid product header.
+
+        is_mcuboot = self.build_conf.getboolean('CONFIG_MCUBOOT')
+        uses_code_partition = self.build_conf.getboolean('CONFIG_USE_DT_CODE_PARTITION')
+
+        return is_mcuboot or not uses_code_partition
+
     def program_bin(self):
+
         if self.erase:
             self.logger.info("Erasing flash...")
             self.check_call([self.tool] + self.sn_arg + ["erase_flash"])
 
         self.logger.info(f"Flashing {self.bin_}...")
-        self.check_call([self.tool] + self.sn_arg + ["image_flash", self.bin_])
+        if self.needs_product_header():
+            # Write product header and application image at fixed offset as required
+            # by internal bootloader.
+            self.check_call([self.tool] + self.sn_arg + ["image_flash", self.bin_])
+        else:
+            load_offset = self.build_conf['CONFIG_FLASH_LOAD_OFFSET']
+            self.check_call([self.tool] + self.sn_arg + ["write_flash", f'0x{load_offset:x}', self.bin_])
 
     def reset(self):
         self.logger.info("Resetting...")
diff --git a/soc/arm/renesas_smartbond/da1469x/Kconfig.defconfig.series b/soc/arm/renesas_smartbond/da1469x/Kconfig.defconfig.series
index ecbc761..801ae9a 100644
--- a/soc/arm/renesas_smartbond/da1469x/Kconfig.defconfig.series
+++ b/soc/arm/renesas_smartbond/da1469x/Kconfig.defconfig.series
@@ -17,9 +17,15 @@
 config SRAM_VECTOR_TABLE
 	default y
 
+config USE_DT_CODE_PARTITION
+	default y if MCUBOOT
+
 config FLASH_BASE_ADDRESS
 	default $(dt_chosen_reg_addr_hex,$(DT_CHOSEN_Z_FLASH))
 
+config FLASH_LOAD_OFFSET
+	default 0x2400 if !USE_DT_CODE_PARTITION
+
 config PLATFORM_SPECIFIC_INIT
 	default y