diff --git a/.restyled.yaml b/.restyled.yaml
index f55a0e367d91bd..c201729d30e41a 100644
--- a/.restyled.yaml
+++ b/.restyled.yaml
@@ -72,7 +72,6 @@ exclude:
     - "scripts/tools/zap/tests/outputs/**/*" # Matches generated output 1:1
     - "examples/chef/sample_app_util/test_files/*.yaml"
     - "examples/chef/zzz_generated/**/*"
-    - "examples/platform/nxp/k32w/k32w0/scripts/demo_generated_certs/**/*"
     - "examples/tv-casting-app/darwin/MatterTvCastingBridge/MatterTvCastingBridge/zap-generated/*" # zap-generated files
     - "integrations/cloudbuild/*.yaml" # uglier long command line content
     - "scripts/run_codegen_targets.sh" # shellharden breaks for loops over command outputs
diff --git a/BUILD.gn b/BUILD.gn
index 82c8d855bfd291..8a78d8f55f3bd0 100644
--- a/BUILD.gn
+++ b/BUILD.gn
@@ -689,7 +689,7 @@ if (current_toolchain != "${dir_pw_toolchain}/default:default") {
 
   if (enable_k32w_lighting_app_build) {
     group("k32w_lighting_app") {
-      deps = [ "${chip_root}/examples/lighting-app/nxp/k32w/k32w0/(${chip_root}/config/k32w/toolchain:k32w_lighting_app)" ]
+      deps = [ "${chip_root}/examples/lighting-app/nxp/k32w0/(${chip_root}/config/k32w/toolchain:k32w_lighting_app)" ]
     }
 
     extra_build_deps += [ ":k32w_lighting_app" ]
@@ -697,7 +697,7 @@ if (current_toolchain != "${dir_pw_toolchain}/default:default") {
 
   if (enable_k32w_lock_app_build) {
     group("k32w_lock_app") {
-      deps = [ "${chip_root}/examples/lock-app/nxp/k32w/k32w0/(${chip_root}/config/k32w/toolchain:k32w_lock_app)" ]
+      deps = [ "${chip_root}/examples/lock-app/nxp/k32w0/(${chip_root}/config/k32w/toolchain:k32w_lock_app)" ]
     }
 
     extra_build_deps += [ ":k32w_lock_app" ]
@@ -705,7 +705,7 @@ if (current_toolchain != "${dir_pw_toolchain}/default:default") {
 
   if (enable_k32w_shell_app_build) {
     group("k32w_shell_app") {
-      deps = [ "${chip_root}/examples/shell/nxp/k32w/k32w0/(${chip_root}/config/k32w/toolchain:k32w_shell_app)" ]
+      deps = [ "${chip_root}/examples/shell/nxp/k32w0/(${chip_root}/config/k32w/toolchain:k32w_shell_app)" ]
     }
 
     extra_build_deps += [ ":k32w_shell_app" ]
diff --git a/config/k32w/toolchain/BUILD.gn b/config/k32w/toolchain/BUILD.gn
index f386bcd0cd4c97..5189a17eff5a67 100644
--- a/config/k32w/toolchain/BUILD.gn
+++ b/config/k32w/toolchain/BUILD.gn
@@ -20,27 +20,27 @@ import("${build_root}/toolchain/arm_gcc/arm_toolchain.gni")
 arm_toolchain("k32w_lighting_app") {
   toolchain_args = {
     current_os = "freertos"
-    import("${chip_root}/examples/lighting-app/nxp/k32w/k32w0/args.gni")
+    import("${chip_root}/examples/lighting-app/nxp/k32w0/args.gni")
   }
 }
 
 arm_toolchain("k32w_lock_app") {
   toolchain_args = {
     current_os = "freertos"
-    import("${chip_root}/examples/lock-app/nxp/k32w/k32w0/args.gni")
+    import("${chip_root}/examples/lock-app/nxp/k32w0/args.gni")
   }
 }
 
 arm_toolchain("k32w_contact_sensor_app") {
   toolchain_args = {
     current_os = "freertos"
-    import("${chip_root}/examples/contact-sensor-app/nxp/k32w/k32w0/args.gni")
+    import("${chip_root}/examples/contact-sensor-app/nxp/k32w0/args.gni")
   }
 }
 
 arm_toolchain("k32w_shell_app") {
   toolchain_args = {
     current_os = "freertos"
-    import("${chip_root}/examples/shell/nxp/k32w/k32w0/args.gni")
+    import("${chip_root}/examples/shell/nxp/k32w0/args.gni")
   }
 }
diff --git a/docs/QUICK_START.md b/docs/QUICK_START.md
index 10833e0c0c1ed7..d5d80703c5e61f 100644
--- a/docs/QUICK_START.md
+++ b/docs/QUICK_START.md
@@ -17,10 +17,10 @@ and platforms.
 Use one of the controllers listed above and then a Border Router and Node
 combination listed below.
 
-| <div style="width:200px">Border Router</div>                                                                   | <div style="width:200px">Node</div>                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      | Description                                                                                                                                                         |
-| -------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
-| [**ot-br**](https://openthread.io/guides/border-router/build)<br>Thread Border Router <li>RasPi <li>BeagleBone | **lighting-app** <li>[Nordic nRF5x](https://github.com/project-chip/connectedhomeip/tree/master/examples/lighting-app/nrfconnect/README.md) <li> [NXP K32W](https://github.com/project-chip/connectedhomeip/tree/master/examples/lighting-app/nxp/k32w/k32w0/README.md) <li> [Qorvo QPG6100](https://github.com/project-chip/connectedhomeip/tree/master/examples/lighting-app/qpg) <li> [Silicon Labs EFR32](https://github.com/project-chip/connectedhomeip/tree/master/examples/lighting-app/silabs/README.md)                                                                                                        | The Lighting example is supported by many of the available Thread platforms. See the chip-tool controller instructions for how to actuate the light on/off cluster. |
-| [**ot-br**](https://openthread.io/guides/border-router/build)<br>Thread Border Router <li>RasPi <li>BeagleBone | **lock-app** <li>[Nordic nRF5x](https://github.com/project-chip/connectedhomeip/tree/master/examples/lock-app/nrfconnect/README.md) <li> [NXP K32W](https://github.com/project-chip/connectedhomeip/tree/master/examples/lock-app/nxp/k32w/k32w0/README.md) <li> [Qorvo QPG6100](https://github.com/project-chip/connectedhomeip/tree/master/examples/lock-app/qpg) <li> [Silicon Labs EFR32](https://github.com/project-chip/connectedhomeip/tree/master/examples/lock-app/efr32/README.md) <li> [TI CC13x2x7](https://github.com/project-chip/connectedhomeip/tree/master/examples/lock-app/cc13x2x7_26x2x7/README.md) | The Lock example is supported by many of the available Thread and Wi-Fi platforms.                                                                                  |
+| <div style="width:200px">Border Router</div>                                                                   | <div style="width:200px">Node</div>                                                                                                                                                                                                                                                                                                                                                                                                                                                                          | Description                                                                                                                                                         |
+| -------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
+| [**ot-br**](https://openthread.io/guides/border-router/build)<br>Thread Border Router <li>RasPi <li>BeagleBone | **lighting-app** <li>[Nordic nRF5x](https://github.com/project-chip/connectedhomeip/tree/master/examples/lighting-app/nrfconnect/README.md) <li> [NXP K32W](https://github.com/project-chip/connectedhomeip/tree/master/examples/lighting-app/nxp/k32w0/README.md) <li> [Qorvo QPG6100](https://github.com/project-chip/connectedhomeip/tree/master/examples/lighting-app/qpg) <li> [Silicon Labs EFR32](https://github.com/project-chip/connectedhomeip/tree/master/examples/lighting-app/silabs/README.md) | The Lighting example is supported by many of the available Thread platforms. See the chip-tool controller instructions for how to actuate the light on/off cluster. |
+| [**ot-br**](https://openthread.io/guides/border-router/build)<br>Thread Border Router <li>RasPi <li>BeagleBone | **lock-app** <li>[Nordic nRF5x](https://github.com/project-chip/connectedhomeip/tree/master/examples/lock-app/nrfconnect/README.md) <li> [Qorvo QPG6100](https://github.com/project-chip/connectedhomeip/tree/master/examples/lock-app/qpg) <li> [Silicon Labs EFR32](https://github.com/project-chip/connectedhomeip/tree/master/examples/lock-app/efr32/README.md) <li> [TI CC13x2x7](https://github.com/project-chip/connectedhomeip/tree/master/examples/lock-app/cc13x2x7_26x2x7/README.md)             | The Lock example is supported by many of the available Thread and Wi-Fi platforms.                                                                                  |
 
 ## Controllers
 
diff --git a/docs/guides/nxp/nxp_k32w0_ota_guide.md b/docs/guides/nxp/nxp_k32w0_ota_guide.md
new file mode 100644
index 00000000000000..147bfdf2ee97e4
--- /dev/null
+++ b/docs/guides/nxp/nxp_k32w0_ota_guide.md
@@ -0,0 +1,232 @@
+# NXP K32W0x1 OTA guide
+
+## The Secondary Stage Bootloader (SSBL)
+
+There are multiple SSBL binaries provided by the SDK:
+
+| description                     | github SDK path                                                                              | package SDK path                                                                           |
+| ------------------------------- | -------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------ |
+| Default SSBL                    | NA                                                                                           | `boards/k32w061dk6/wireless_examples/framework/ssbl/binary/ssbl.bin`                       |
+| SSBL with PDM in external flash | `examples/k32w061dk6/wireless_examples/framework/ssbl/binary/ssbl_ext_flash_pdm_support.bin` | `boards/k32w061dk6/wireless_examples/framework/ssbl/binary/ssbl_ext_flash_pdm_support.bin` |
+
+The SSBL is also built alongside the reference application and it can be
+configured according to the following table:
+
+| gn arg                            | default                     | description                                                                              |
+| --------------------------------- | --------------------------- | ---------------------------------------------------------------------------------------- |
+| `ssbl_pdm_external_flash`         | true                        | Enable/disable PDM in external flash                                                     |
+| `ssbl_multi_image_support`        | true                        | Enable/disable multi-image OTA feature                                                   |
+| `ssbl_ota_entry_storage`          | "OTACustomStorage_ExtFlash" | Configure custom OTA entry storage type                                                  |
+| `ssbl_simple_hash_verification`   | false                       | Enable/disable simple hash verification alternative to secure boot                       |
+| `ssbl_optimize_spifi_flash`       | false                       | Optimize `SPIFI` flash driver size                                                       |
+| `ssbl_spifi_dual_mode`            | false                       | Enable/disable `SPIFI` dual mode support (e.g. used by K32W041AM variant)                |
+| `ssbl_version`                    | 0                           | Set SSBL version                                                                         |
+| `ssbl_use_redlib`                 | false                       | Enable/disable usage of `redlib` NXP library. If false, the build will use `newlib` nano |
+| `ssbl_ota_data_in_external_flash` | false                       | Enable/disable OTA support for application with sections stored in external flash        |
+
+## Simple hash verification
+
+When secure boot is not used, a simple hash can be appended at the end of the
+image for integrity check. Applications should be built with
+`chip_simple_hash_verification=1`.
+
+## Writing the SSBL
+
+Before writing the SSBL, it it recommanded to fully erase the internal flash.
+
+Using DK6Programmer utility from Windows:
+
+```
+DK6Programmer.exe -V 5 -P 1000000 -s <COM_PORT> -e Flash
+```
+
+Using `dk6prog` from `SPSDK`:
+
+```
+$ dk6prog listdev
+This is an experimental utility. Use with caution!
+
+List of available devices:
+DEVICE ID: DN038ZH3, VID: 0x403, PID: 0x6015, Serial number: DN038ZH3, Description: DK6 Carrier Board, Address: 9, Backend: Backend.PYFTDI
+$ dk6prog -d DN038ZH3 erase 0 0x9de00
+
+This is an experimental utility. Use with caution!
+
+Erasing memory  [####################################]  100%
+```
+
+`chip-k32w0x-ssbl.bin` must be written at address 0 in the internal flash:
+
+Using DK6Programmer utility from Windows:
+
+```
+DK6Programmer.exe -V2 -s <COM_PORT> -P 1000000 -Y -p FLASH@0x00="chip-k32w0x-ssbl.bin"
+```
+
+Using `dk6prog` from `SPSDK`:
+
+```
+$ dk6prog -d DN038ZH3 write 0 ~/path/to/bin/chip-k32w0x-ssbl.bin
+
+This is an experimental utility. Use with caution!
+
+Writing memory  [####################################]  100%
+Written 7890 bytes to memory ID 0 at address 0x0
+```
+
+### Writing the PSECT
+
+This is the list of all supported partitions:
+
+```
+0000000010000000 : SSBL partition
+
+    00000000 -----------> Start Address
+    1000 ---------------> 0x0010 Number of 512-bytes pages
+    00 -----------------> 0x00 Bootable flag
+    00 -----------------> 0x00 Image type (0x00 = SSBL)
+
+00400000c9040101: Application partition
+
+    00400000 -----------> 0x00004000 Start Address
+    c904 ---------------> 0x04c9 Number of 512-bytes pages
+    01 -----------------> 0x01 Bootable flag
+    01 -----------------> 0x01 Image type (0x01 = Application)
+
+00000010800000fe: Ext Flash text partition
+
+    00000010 -----------> 0x10000000 Start Address (external flash)
+    8000 ---------------> 0x0080 Number of 512-bytes pages
+    00 -----------------> 0x00 Bootable flag
+    fe -----------------> 0xFE Image type (0xFE = Ext Flash text)
+
+00000110300200fc : OTA Image partition
+
+    00000110 -----------> 0x10010000 Start Address
+    3002----------------> 0x0230 Number of 512-bytes pages
+    00 -----------------> 0x00 Bootable flag
+    fc -----------------> 0xFC Image type (0xFC = OTA partition)
+
+00000510100000fd: NVM partition
+
+    00000510 -----------> 0x10050000 Start Address
+    1000 ---------------> 0x0010 Number of 512-bytes pages
+    00 -----------------> 0x00 Bootable flag
+    fd -----------------> 0xFD Image type (0xFD = NVM partition)
+```
+
+First, image directory 0 (SSBL partition) must be written:
+
+Using DK6Programmer utility from Windows:
+
+```
+DK6Programmer.exe -V5 -s <COM port> -P 1000000 -w image_dir_0=0000000010000000
+```
+
+Using `dk6prog` from `SPSDK`:
+
+```
+$ dk6prog -d DN038ZH3 write 0x160 [[0000000010000000]] 8 PSECT
+
+This is an experimental utility. Use with caution!
+
+Writing memory  [####################################]  100%
+Written 8 bytes to memory ID PSECT at address 0x160
+```
+
+Here is the interpretation of the fields:
+
+```
+00000000 -> start address 0x00000000
+1000     -> size = 0x0010 pages of 512-bytes (= 8kB)
+00       -> not bootable (only used by the SSBL to support SSBL update)
+00       -> SSBL Image Type
+```
+
+Second, image directory 1 (application partition) must be written:
+
+Using DK6Programmer utility from Windows:
+
+```
+DK6Programmer.exe -V5 -s <COM port> -P 1000000 -w image_dir_1=00400000C9040101
+```
+
+Using `dk6prog` from `SPSDK`:
+
+```
+$ dk6prog -d DN038ZH3 write 0x168 [[00400000C9040101]] 8 PSECT
+
+This is an experimental utility. Use with caution!
+
+Writing memory  [####################################]  100%
+Written 8 bytes to memory ID PSECT at address 0x168
+```
+
+Here is the interpretation of the fields:
+
+```
+00400000 -> start address 0x00004000
+C904     -> 0x4C9 pages of 512-bytes (= 612.5kB)
+01       -> bootable flag
+01       -> image type for the application
+```
+
+Please note the user can write additional partitions by writing
+`image_dir_2/3/4` with the wanted configuration. In case of using the `SPSDK`
+tool, the appropriate offset must be calculated
+
+## Removing SSBL Upgrade Region
+
+The example also offers the possibility to remove SSBL upgrade region, for
+reserving more space for application level.
+
+A new flag `chip_reduce_ssbl_size` is introduced. In order to remove the SSBL
+upgrade region, `chip_reduce_ssbl_size=true` must be provided to the build
+system
+
+The programming method will change:
+
+-   Writing image directory 1 should change to Using DK6Programmer utility from
+    Windows:
+
+    ```
+    DK6Programmer.exe -V5 -s <COM port> -P 1000000 -w image_dir_1=00200000D9040101
+    ```
+
+    Using `dk6prog` from `SPSDK`:
+
+    ```
+    $ dk6prog -d DN038ZH3 write 0x168 [[00200000D9040101]] 8 PSECT
+
+    This is an experimental utility. Use with caution!
+
+    Writing memory  [####################################]  100%
+    Written 8 bytes to memory ID PSECT at address 0x168
+    ```
+
+    Here is the interpretation of the fields:
+
+    ```
+    00200000 -> start address 0x00002000
+    D904     -> 0x4D9 pages of 512-bytes (= 620.5kB)
+    01       -> bootable flag
+    01       -> image type for the application
+    ```
+
+-   Matter application offset address should change to Using DK6Programmer
+    utility from Windows:
+
+    ```
+    DK6Programmer.exe -V2 -s <COM_PORT> -P 1000000 -Y -p FLASH@0x2000="chip-k32w0x-contact-example.bin"
+    ```
+
+    Using `dk6prog` from `SPSDK`:
+
+    ```
+    $ dk6prog -d DN038ZH3 write 0x2000 ~/path/to/bin/chip-k32w0x-contact-example.bin
+
+    This is an experimental utility. Use with caution!
+
+    Writing memory  [####################################]  100%
+    Written 596450 bytes to memory ID 0 at address 0x2000
+    ```
diff --git a/docs/guides/nxp/nxp_k32w_android_commissioning.md b/docs/guides/nxp/nxp_k32w_android_commissioning.md
index 6d872f5f7ba268..a37d60f0f0ba4e 100644
--- a/docs/guides/nxp/nxp_k32w_android_commissioning.md
+++ b/docs/guides/nxp/nxp_k32w_android_commissioning.md
@@ -8,16 +8,17 @@ onto a CHIP-enabled Thread network.
 
 <hr>
 
--   [Overview](#overview)
--   [Requirements](#requirements)
--   [Building and programming OpenThread RCP firmware](#building-and-programming-openthread-rcp-firmware)
--   [Configuring PC as Thread Border Router](#configuring-pc-as-a-thread-border-router)
--   [Building and programming NXP K32W Light Example Application](#building-and-programming-nxp-k32w-light-example-application)
--   [Building and installing Android CHIPTool](#building-and-installing-android-chiptool)
--   [Forming a Thread network on the Border Router](#forming-a-thread-network-on-the-border-router)
--   [Preparing accessory device](#preparing-accessory-device)
--   [Commissioning accessory device](#commissioning-accessory-device)
--   [Sending CHIP commands](#sending-chip-commands)
+-   [Commissioning NXP K32W using Android CHIPTool](#commissioning-nxp-k32w-using-android-chiptool)
+    -   [Overview](#overview)
+    -   [Requirements](#requirements)
+    -   [Building and programming OpenThread RCP firmware](#building-and-programming-openthread-rcp-firmware)
+    -   [Configuring PC as a Thread Border Router](#configuring-pc-as-a-thread-border-router)
+    -   [Building and programming NXP K32W Light Example Application](#building-and-programming-nxp-k32w-light-example-application)
+    -   [Building and installing Android CHIPTool](#building-and-installing-android-chiptool)
+    -   [Forming a Thread network on the Border Router](#forming-a-thread-network-on-the-border-router)
+    -   [Preparing accessory device](#preparing-accessory-device)
+    -   [Commissioning accessory device](#commissioning-accessory-device)
+    -   [Sending CHIP commands](#sending-chip-commands)
 
 <hr>
 
@@ -47,7 +48,7 @@ The following diagram shows the connectivity between network components required
 to allow communication between devices running the CHIPTool and Light
 applications:
 
-![nxp_hw_connectivity](../../../examples/platform/nxp/k32w/k32w0/doc/images/nxp_hw_connectivity.JPG)
+![nxp_hw_connectivity](../../../examples/platform/nxp/k32w0/doc/images/nxp_hw_connectivity.JPG)
 
 <hr>
 
@@ -111,7 +112,7 @@ the RCP firmware onto an K32W061 DK6:
     This creates an RCP image in the `bin/ot-rcp` directory.
 
 6.  Program the RCP firmware using the official
-    [OpenThread Flash Instructions](https://github.com/openthread/openthread/blob/master/examples/platforms/k32w/k32w061/README.md#flash-binaries).
+    [OpenThread Flash Instructions](https://github.com/openthread/openthread/blob/master/examples/platforms/k32w061/README.md#flash-binaries).
 
 7.  Plug-in the K32W061 DK6 to the PC.
 
@@ -348,7 +349,7 @@ To make your PC work as a Thread Border Router, complete the following tasks:
 ## Building and programming NXP K32W Light Example Application
 
 See
-[NXP K32W Light Example Application README](../../../examples/lighting-app/nxp/k32w/k32w0/README.md)
+[NXP K32W Light Example Application README](../../../examples/lighting-app/nxp/k32w0/README.md)
 to learn how to build and program the light example onto an K32W061 DK6.
 
 <hr>
@@ -396,7 +397,7 @@ CHIPTool is now ready to be used for commissioning.
 
 3.  Navigate to the _Form_ tab then push the _Form_ button using the default
     parameters:
-    ![nxp_form_nwk](../../../examples/platform/nxp/k32w/k32w0/doc/images/form_web.JPG)
+    ![nxp_form_nwk](../../../examples/platform/nxp/k32w0/doc/images/form_web.JPG)
 
 4.  The message _Form operation is successful_ should be display after a few
     seconds.
@@ -430,7 +431,7 @@ To prepare the accessory device for commissioning, complete the following steps:
 
 1.  Make sure that JP4 and JP7 jumpers are in leftmost position and a mini-USB
     cable is connected between the LPC connector and PC
-    ![nxp_connectors](../../../examples/platform/nxp/k32w/k32w0/doc/images/k32w-dk6-connectors.jpg)
+    ![nxp_connectors](../../../examples/platform/nxp/k32w0/doc/images/k32w-dk6-connectors.jpg)
 
 2.  Use a terminal emulator (e.g.: Putty) to connect to the UART console of the
     accessory device. Use a baudrate of 115200.
@@ -466,14 +467,14 @@ section, complete the following steps:
    progress with scanning, connection, and pairing. At the end of this process,
    the Thread network settings screen appears.
 
-    ![chiptool_main_screen](../../../examples/platform/nxp/k32w/k32w0/doc/images/chiptool_main_screen.png)
+    ![chiptool_main_screen](../../../examples/platform/nxp/k32w0/doc/images/chiptool_main_screen.png)
 
 6. In the Thread network settings screen, use the default settings and tap the
    _SAVE NETWORK_ button to send a Thread provisioning message to the accessory
    device. You will see the "Network provisioning completed" message when the
    accessory device successfully joins the Thread network.
 
-    ![chiptool_credentials](../../../examples/platform/nxp/k32w/k32w0/doc/images/thread_credentials.png)
+    ![chiptool_credentials](../../../examples/platform/nxp/k32w0/doc/images/thread_credentials.png)
 
 <hr>
 
@@ -483,7 +484,7 @@ section, complete the following steps:
    the provisioning is completed successfully and you are connected to the
    device.
 
-    ![on_off_cluster.png](../../../examples/platform/nxp/k32w/k32w0/doc/images/on_off_cluster.png)
+    ![on_off_cluster.png](../../../examples/platform/nxp/k32w0/doc/images/on_off_cluster.png)
 
 2. Verify that the text box on the screen is not empty and contains the IPv6
    address of the accessory device.
diff --git a/examples/contact-sensor-app/nxp/k32w/k32w0/build_overrides b/examples/contact-sensor-app/nxp/k32w/k32w0/build_overrides
deleted file mode 120000
index ad07557834803a..00000000000000
--- a/examples/contact-sensor-app/nxp/k32w/k32w0/build_overrides
+++ /dev/null
@@ -1 +0,0 @@
-../../../../build_overrides/
\ No newline at end of file
diff --git a/examples/contact-sensor-app/nxp/k32w/k32w0/third_party/connectedhomeip b/examples/contact-sensor-app/nxp/k32w/k32w0/third_party/connectedhomeip
deleted file mode 120000
index 305f2077ffe860..00000000000000
--- a/examples/contact-sensor-app/nxp/k32w/k32w0/third_party/connectedhomeip
+++ /dev/null
@@ -1 +0,0 @@
-../../../../../..
\ No newline at end of file
diff --git a/examples/contact-sensor-app/nxp/k32w/k32w0/.gn b/examples/contact-sensor-app/nxp/k32w0/.gn
similarity index 93%
rename from examples/contact-sensor-app/nxp/k32w/k32w0/.gn
rename to examples/contact-sensor-app/nxp/k32w0/.gn
index 363727423ce903..1f7e4941f8d9fc 100644
--- a/examples/contact-sensor-app/nxp/k32w/k32w0/.gn
+++ b/examples/contact-sensor-app/nxp/k32w0/.gn
@@ -27,5 +27,5 @@ default_args = {
   import("//args.gni")
 
   # Import default platform configs
-  import("${chip_root}/src/platform/nxp/k32w/k32w0/args.gni")
+  import("${chip_root}/src/platform/nxp/k32w0/args.gni")
 }
diff --git a/examples/contact-sensor-app/nxp/k32w/k32w0/BUILD.gn b/examples/contact-sensor-app/nxp/k32w0/BUILD.gn
similarity index 90%
rename from examples/contact-sensor-app/nxp/k32w/k32w0/BUILD.gn
rename to examples/contact-sensor-app/nxp/k32w0/BUILD.gn
index b69897172a1e8d..c51b8787ea2922 100644
--- a/examples/contact-sensor-app/nxp/k32w/k32w0/BUILD.gn
+++ b/examples/contact-sensor-app/nxp/k32w0/BUILD.gn
@@ -41,7 +41,7 @@ if (chip_pw_tokenizer_logging) {
 
 assert(current_os == "freertos")
 
-k32w0_platform_dir = "${chip_root}/examples/platform/nxp/k32w/k32w0"
+k32w0_platform_dir = "${nxp_sdk_matter_support_root}/examples/platform/k32w0"
 
 k32w0_sdk("sdk") {
   sources = [
@@ -88,6 +88,7 @@ k32w0_executable("contact_sensor_app") {
   defines = []
 
   sources = [
+    "${k32w0_platform_dir}/util/DefaultTestEventTriggerDelegate.cpp",
     "${k32w0_platform_dir}/util/LEDWidget.cpp",
     "${k32w0_platform_dir}/util/include/LEDWidget.h",
     "main/AppTask.cpp",
@@ -119,17 +120,12 @@ k32w0_executable("contact_sensor_app") {
     "${k32w0_platform_dir}/app/support:freertos_mbedtls_utils",
   ]
 
-  if (chip_openthread_ftd) {
-    deps += [
-      "${chip_root}/third_party/openthread/repo:libopenthread-cli-ftd",
-      "${chip_root}/third_party/openthread/repo:libopenthread-ftd",
-    ]
-  } else {
-    deps += [
-      "${chip_root}/third_party/openthread/repo:libopenthread-cli-mtd",
-      "${chip_root}/third_party/openthread/repo:libopenthread-mtd",
-    ]
-  }
+  defines += [ "CONNECTIVITY_MANAGER_THREAD_DEVICE_TYPE=ConnectivityManager::kThreadDeviceType_SleepyEndDevice" ]
+
+  deps += [
+    "${chip_root}/third_party/openthread/repo:libopenthread-cli-mtd",
+    "${chip_root}/third_party/openthread/repo:libopenthread-mtd",
+  ]
 
   #lit and sit are using different zap files
   if (chip_enable_icd_lit) {
@@ -187,6 +183,11 @@ group("k32w0") {
     ":binsign",
     ":contact_sensor_app",
   ]
+
+  if (chip_enable_ota_requestor) {
+    deps += [ "${k32w0_platform_dir}/ssbl:ssbl" ]
+  }
+
   if (chip_pw_tokenizer_logging) {
     deps += [ ":contact_sensor_app.database" ]
   }
@@ -201,6 +202,10 @@ action("binsign") {
   if (chip_simple_hash_verification == 1) {
     args = [ "--simple-hash" ]
   }
+
+  if (chip_enable_ota_requestor) {
+    args = [ "--ota-enabled" ]
+  }
 }
 
 group("default") {
diff --git a/examples/contact-sensor-app/nxp/k32w/k32w0/README.md b/examples/contact-sensor-app/nxp/k32w0/README.md
similarity index 72%
rename from examples/contact-sensor-app/nxp/k32w/k32w0/README.md
rename to examples/contact-sensor-app/nxp/k32w0/README.md
index ac418ecbd4aa77..305aa0b176af2a 100644
--- a/examples/contact-sensor-app/nxp/k32w/k32w0/README.md
+++ b/examples/contact-sensor-app/nxp/k32w0/README.md
@@ -30,6 +30,8 @@ network.
     -   [Rotating device id](#rotating-device-id)
     -   [Manufacturing data](#manufacturing-data)
     -   [Flashing and debugging](#flashing-and-debugging)
+        -   [Using DK6programmer](#using-dk6programmer)
+        -   [Using MCUXpresso](#using-mcuxpresso)
     -   [Pigweed tokenizer](#pigweed-tokenizer)
         -   [Detokenizer script](#detokenizer-script)
         -   [Notes](#notes)
@@ -39,21 +41,14 @@ network.
     -   [Tinycrypt ECC library](#tinycrypt-ecc-library)
         -   [Building steps](#building-steps-1)
     -   [OTA](#ota)
-        -   [Writing the SSBL](#writing-the-ssbl)
-        -   [Features](#features)
-            -   [Multi image](#multi-image)
-            -   [Simple hash verification](#simple-hash-verification)
-        -   [Writing the PSECT](#writing-the-psect)
-        -   [Writing the application](#writing-the-application)
         -   [OTA Testing](#ota-testing)
-        -   [Known issues ota](#known-issues-ota)
+        -   [Known issues OTA](#known-issues-ota)
     -   [Low power](#low-power)
         -   [Known issues low power](#known-issues-low-power)
-    -   [Removing SSBL Upgrade Region](#removing-ssbl-upgrade-region)
 
 ## Introduction
 
-![K32W061 DK6](../../../../platform/nxp/k32w/k32w0/doc/images/k32w-dk6.jpg)
+![K32W061 DK6](../../../platform/nxp/k32w0/doc/images/k32w-dk6.jpg)
 
 The K32W061 contact sensor example application provides a working demonstration
 of a connected contact sensor device, built using the Project CHIP codebase and
@@ -83,7 +78,7 @@ Deployment of this firmware configuration requires the K32W061 board setups
 using the K32W061 module board, SE051 Expansion board and Generic Expansion
 board as shown below:
 
-![SE051H  + K32W061 DK6](../../../../platform/nxp/k32w/k32w0/doc/images/k32w-se.jpg)
+![SE051H  + K32W061 DK6](../../../platform/nxp/k32w0/doc/images/k32w-se.jpg)
 
 The SE051H Secure Element extension may be used for best in class security and
 offloading some of the Project CHIP cryptographic operations. Depending on your
@@ -186,10 +181,10 @@ contact status.
 
 In order to build the Project CHIP example, we recommend using a Linux
 distribution (supported Operating Systems are listed in
-[BUILDING.md](../../../../../docs/guides/BUILDING.md#tested-operating systems)).
+[BUILDING.md](../../../../docs/guides/BUILDING.md#tested-operating-systems)).
 
 -   Make sure that below prerequisites are correctly installed (as described in
-    [BUILDING.md](../../../../../docs/guides/BUILDING.md#prerequisites)))
+    [BUILDING.md](../../../../docs/guides/BUILDING.md#prerequisites))
 
 ```
 sudo apt-get install git gcc g++ pkg-config libssl-dev libdbus-1-dev \
@@ -219,18 +214,18 @@ user@ubuntu:~/Desktop/git/connectedhomeip$ source scripts/bootstrap.sh
 -   Step 3: Init NXP SDK(s)
 
 ```
-user@ubuntu:~/Desktop/git/connectedhomeip$ scripts/setup/nxp/update_nxp_sdk.py --platform k32w0
+user@ubuntu:~/Desktop/git/connectedhomeip$ third_party/nxp/nxp_matter_support/scripts/update_nxp_sdk.py --platform k32w0
 ```
 
-Note: By default setup/nxp/update_nxp_sdk.py will try to initialize all NXP
-SDKs. Arg "-- help" could be used to view all available options.
+Note: By default update_nxp_sdk.py will try to initialize all NXP SDKs. Arg "--
+help" could be used to view all available options.
 
 -   Start building the application:
 
 ```bash
-user@ubuntu:~/Desktop/git/connectedhomeip$ cd examples/contact-sensor-app/nxp/k32w/k32w0
-user@ubuntu:~/Desktop/git/connectedhomeip/examples/contact-sensor-app/nxp/k32w/k32w0$ gn gen out/debug
-user@ubuntu:~/Desktop/git/connectedhomeip/examples/contact-sensor-app/nxp/k32w/k32w0$ ninja -C out/debug
+user@ubuntu:~/Desktop/git/connectedhomeip$ cd examples/contact-sensor-app/nxp/k32w0
+user@ubuntu:~/Desktop/git/connectedhomeip/examples/contact-sensor-app/nxp/k32w0$ gn gen out/debug
+user@ubuntu:~/Desktop/git/connectedhomeip/examples/contact-sensor-app/nxp/k32w0$ ninja -C out/debug
 ```
 
 To build with Secure Element, follow the same steps as above but set
@@ -267,7 +262,7 @@ used to control an antenna switch. In order to use this feature, user must set
 
 In case signing errors are encountered when running the "sign_images.sh" script
 (run automatically) install the recommanded packages (python version > 3, pip3,
-pycrypto, pycryptodome):
+pycryptodome):
 
 ```
 user@ubuntu:~$ python3 --version
@@ -275,7 +270,6 @@ Python 3.8.2
 user@ubuntu:~$ pip3 --version
 pip 20.0.2 from /usr/lib/python3/dist-packages/pip (python 3.8)
 user@ubuntu:~$ pip3 list | grep -i pycrypto
-pycrypto               2.6.1
 pycryptodome           3.9.8
 ```
 
@@ -357,20 +351,20 @@ Please use the following build args:
 ## Manufacturing data
 
 See
-[Guide for writing manufacturing data on NXP devices](../../../../../docs/guides/nxp/nxp_manufacturing_flow.md).
+[Guide for writing manufacturing data on NXP devices](../../../../docs/guides/nxp/nxp_manufacturing_flow.md).
 
 There are factory data generated binaries available in
-examples/platform/nxp/k32w/k32w0/scripts/demo_generated_factory_data folder.
-These are based on the DAC, PAI and PAA certificates found in
+`third_party/nxp/nxp_matter_support/examples/platform/k32w0/scripts/demo_generated_factory_data`
+folder. These are based on the DAC, PAI and PAA certificates found in
 scripts/tools/nxp/demo_generated_certs folder. The demo_factory_data_dut1.bin
 uses the DAC certificate and private key found in
-examples/platform/nxp/k32w/k32w0/scripts/demo_generated_factory_data/dac/dut1
+`third_party/nxp/nxp_matter_support/examples/platform/k32w0/scripts/demo_generated_factory_data/dac/dut1`
 folder. The demo_factory_data_dut2.bin uses the DAC certificate and private key
 found in
-examples/platform/nxp/k32w/k32w0/scripts/demo_generated_factory_data/dac/dut2
+`third_party/nxp/nxp_matter_support/examples/platform/k32w0/scripts/demo_generated_factory_data/dac/dut2`
 folder. These two factory data binaries can be used for testing topologies with
 2 DUTS. They contain the corresponding DACs/PAIs generated using
-generate_nxp_chip_factory_bin.py script. The discriminator is 14014 and the
+`generate_nxp_chip_factory_bin.py` script. The discriminator is 14014 and the
 passcode is 1000. These demo certificates are working with the CDs installed in
 CHIPProjectConfig.h.
 
@@ -379,18 +373,140 @@ Regarding factory data provider, there are two options:
 -   use the default factory data provider: `FactoryDataProviderImpl` by setting
     `chip_with_factory_data=1` in the gn build command.
 -   use a custom factory data provider: please see
-    [Guide for implementing a custom factory data provider](../../../../platform/nxp/k32w/k32w0/common/README.md).
+    [Guide for implementing a custom factory data provider](../../../platform/nxp/k32w0/doc/CustomFactoryDataProvider.md).
     This can be enabled when `chip_with_factory_data=1` by setting
     `use_custom_factory_provider=1` in the gn build command.
 
 ## Flashing and debugging
 
-Program the firmware using the official
+Instructions to program the firmware can be found also at
 [OpenThread Flash Instructions](https://github.com/openthread/ot-nxp/tree/main/src/k32w0/k32w061#flash-binaries).
 
-All you have to do is to replace the Openthread binaries from the above
-documentation with _out/debug/chip-k32w0x-contact-example.bin_ if DK6Programmer
-is used or with _out/debug/chip-k32w0x-contact-example_ if MCUXpresso is used.
+### Using DK6programmer
+
+The application binary's path is _out/debug/chip-k32w0x-contact-example.bin_.
+
+DK6Programmer can be used for flashing the application. There are two available
+versions of the DK6Programmer tool.
+
+The legacy version consists of a Windows executable found inside the
+[SDK](https://mcuxpresso.nxp.com/en/welcome) at path
+`tools/JN-SW-4407-DK6-Flash-Programmer`. This is a Windows application that can
+be installed using the .exe file. Once the application is installed, the COM
+port for K32W061 must be identified:
+
+```
+C:\nxp\DK6ProductionFlashProgrammer>DK6Programmer.exe  --list
+Available connections:
+<COM_PORT>
+```
+
+Once the COM port is identified, the required binary can be flashed:
+
+```
+DK6Programmer.exe -V2 -s <COM_PORT> -P 1000000 -Y -p FLASH@0x4000="chip-k32w0x-contact-example.bin"
+```
+
+> **_Note:_** The above example takes into account that the binary uses the
+> `chip_enable_ota_requestor=true` option. The address offset corresponds to the
+> space left for the SSBL binary and the OTA space for the SSBL. If
+> `chip_enable_ota_requestor` is set to `false`, then `0x4000` needs to be
+> replaced with `0x0`.
+
+DK6 Flash Programmer tool has also been integrated part of
+[NXP Secure Provisioning SDK (SPSDK)](https://github.com/nxp-mcuxpresso/spsdk).
+This tool is supported by environments like Windows, Linux or Mac.
+
+`SPSDK` can be installed and run from a Python environment using
+[these instructions](https://spsdk.readthedocs.io/en/latest/usage/installation.html).
+This enables the user to have transparent access to the dk6 programming tool
+through `SPSDK`.
+
+```
+# after specific environment installation steps
+$ spsdk --help
+...
+  +-- dk6prog                             Tool for reading and programming flash memory of DK6 target devices.
+  �   +-- erase                           Erase the memory.
+  �   +-- info                            Prints the information about the connected device.
+  �   +-- isp                             Issues ISP sequence as defined in Driver interface.
+  �   +-- listdev                         Prints the information about the connected devices.
+  �   +-- read                            Reads the memory and writes it to the file or stdout.
+  �   +-- write                           Write the memory.
+...
+```
+
+Dependencies for the `dk6prog` module can be installed using the following
+command, more details
+[here](https://spsdk.readthedocs.io/en/latest/usage/installation.html#dk6-tools):
+
+```
+$ pip install spsdk[dk6]
+```
+
+The `SPSDK` installation adds `dk6prog` as executable to system path, so user
+can use directly `dk6prog` from terminal. The following commands are to be used
+to write the chip-k32w0x-contact-example binary to the board.
+
+```
+$ dk6prog listdev
+This is an experimental utility. Use with caution!
+
+List of available devices:
+DEVICE ID: DN038ZH3, VID: 0x403, PID: 0x6015, Serial number: DN038ZH3, Description: DK6 Carrier Board, Address: 9, Backend: Backend.PYFTDI
+$ dk6prog -d DN038ZH3 write 0x4000 ~/path/to/bin/chip-k32w0x-contact-example.bin
+
+This is an experimental utility. Use with caution!
+
+Writing memory  [####################################]  100%
+Written 596450 bytes to memory ID 0 at address 0x4000
+```
+
+> **_Note:_** Running `dk6prog` from Windows OS command line requires an integer
+> value for DEVICE ID.
+
+```
+C:\nxp\spsdk>dk6prog listdev
+
+This is an experimental utility. Use with caution!
+
+List of available devices:
+DEVICE ID: 0, VID: 0x0, PID: 0x0, Serial number: b'DN038ZH3', Description: b'DK6 Carrier Board', Address: 67330069, Backend: Backend.FTD2xx
+
+C:\nxp\spsdk>dk6prog -d 0 info
+
+This is an experimental utility. Use with caution!
+
+Chip ID: 0x88888888
+ROM Version: 0x140000cc
+MAC Address: A8:2B:1F:03:00:8D:15:00
+
+Detected DEVICE: UNKNOWN
+
+  Memory   Memory ID   Base Address   Length    Sector Size   Memory Type   Access
+----------------------------------------------------------------------------------------------
+  FLASH    0           0x0            0x9de00   0x200         FLASH         All is available
+  PSECT    1           0x0            0x1e0     0x10          FLASH         All is available
+  pFLASH   2           0x0            0x1e0     0x10          FLASH         All is available
+  Config   3           0x9fc00        0x200     0x200         FLASH         All is available
+  EFUSE    4           0x0            0x80      0x2           EFUSE (OTP)   Write Enabled
+  ROM      5           0x3000000      0x20000   0x1           ROM           Write Enabled
+  RAM0     6           0x4000000      0x16000   0x1           RAM           Write Enabled
+  RAM1     7           0x4020000      0x10000   0x1           RAM           Write Enabled
+```
+
+> **_Note:_** The above example takes into account that the binary uses the
+> `chip_enable_ota_requestor=true` option. The address offset corresponds to the
+> space left for the SSBL binary and the OTA space for the SSBL. If
+> `chip_enable_ota_requestor` is set to `false`, then `0x4000` needs to be
+> replaced with `0x0`.
+
+### Using MCUXpresso
+
+If flashing and debugging is required, MCUXpresso can be used as instructed in
+[MCUXpresso flashing and debugging instructions](https://github.com/openthread/ot-nxp/tree/main/src/k32w0/k32w061#using-mcuxpresso-ide).
+The file needed to be used in MCUXpresso is
+_out/debug/chip-k32w0x-contact-example_.
 
 ## Pigweed tokenizer
 
@@ -403,7 +519,7 @@ needed for parsing the hashed scripts.
 
 The python3 script detokenizer.py is a script that decodes the tokenized logs
 either from a file or from a serial port. It is located in the following path
-`examples/platform/nxp/k32w/k32w0/scripts/detokenizer.py`.
+`third_party/nxp/nxp_matter_support/examples/platform/k32w0/scripts/detokenizer.py`.
 
 The script can be used in the following ways:
 
@@ -438,7 +554,7 @@ by the script is loaded by the environment. An example of running the
 detokenizer script to see logs of a contact-sensor app:
 
 ```
-python3 ../../../../../examples/platform/nxp/k32w/k32w0/scripts/detokenizer.py serial -i /dev/ttyACM0 -d out/debug/chip-k32w0x-contact-example-database.bin -o device.txt
+python3 ../../../../third_party/nxp/nxp_matter_support/examples/platform/k32w0/scripts/detokenizer.py serial -i /dev/ttyACM0 -d out/debug/chip-k32w0x-contact-example-database.bin -o device.txt
 ```
 
 ### Known issues tokenizer
@@ -483,179 +599,49 @@ In order to use the Tinycrypt ECC library, use the following build arguments:
 
 ## OTA
 
-The internal flash needs to be prepared for the OTA process. First 16K of the
-internal flash needs to be populated with a Secondary Stage Bootloader (SSBL)
-related data while the last 8.5K of flash space is holding image directory
-related data (PSECT). The space between these two zones will be filled by the
+Over the air updates (OTA) require several software components running on the
+K32W0x1. Firstly, a Secondary Stage Bootloader (SSBL) is required written in the
+first part of the internal flash memory, usually starting at address 0x0. This
+enables the board to boot and check if a new OTA binary has been received. If
+this is true, the bootloader writes the OTA binary to the appropriate storage,
+internal and/or external flash, after which it reboots the board. If no new OTA
+binaries have been found, then the bootloader gives execution control to the
 application.
 
-### Writing the SSBL
-
-The SDK already provides an SSBL binary compiled with external flash support:
-`boards/k32w061dk6/wireless_examples/framework/ssbl/binary/ssbl_ext_flash_pdm_support.bin`,
-but it does not offer multi-image OTA support.
-
-Alternatively, the SSBL can ge generated from one of the SDK demo examples. The
-SSBL demo application can be imported from the `Quickstart panel`:
-`Import SDK example(s) -> select wireless -> framework -> ssbl` application.
-
-![SSBL Application Select](../../../../platform/nxp/k32w/k32w0/doc/images/ssbl_select.JPG)
-
-### Features
-
-#### Multi image
-
-To support multi-image OTA feature, the SSBL project must be compiled using the
-following defines:
-
--   `PDM_EXT_FLASH=1` - support PDM in external flash.
--   `gOTAUseCustomOtaEntry=1` - support custom OTA entry for multi-image.
--   `gOTACustomOtaEntryMemory=OTACustomStorage_ExtFlash` - K32W0 uses
-    `OTACustomStorage_ExtFlash` (1) by default.
--   `SPIFI_DUAL_MODE_SUPPORT=1` - only for configurations that use dual `SPIFI`
-    flash (e.g. K32W041AM variant).
-
-Optionally, add the following defines:
-
--   `SPIFI_OPTIM_SIZE=1` - to optimize SSBL size.
--   `EXTERNAL_FLASH_DATA_OTA=1` - to support external read only data.
-
-![SSBL_MULTI_IMAGE](../../../../platform/nxp/k32w/k32w0/doc/images/ssbl_multi_image.JPG)
-
-#### Simple hash verification
-
-When secure boot is not used, a simple hash can be appended at the end of the
-image for integrity check. Applications should be built with
-`chip_simple_hash_verification=1`.
-
-To support simple hash verification feature, the SSBL project must be compiled
-with:
-
--   `gSimpleHashVerification=1`
-
-and update the post-build command to use simple hash verification instead of the
-default options. Go to
-`Project -> Properties -> C/C++ Build -> Settings -> Build steps` and press
-`Edit` under `Post-build steps` subsection. The command should look similar to:
-
-![SSBL_SIMPLE_HASH_VERIFICATION](../../../../platform/nxp/k32w/k32w0/doc/images/ssbl_simple_hash.JPG)
-
-Once compiled, the required SSBL file is called `k32w061dk6_ssbl.bin`.
-
-![SSBL_BIN](../../../../platform/nxp/k32w/k32w0/doc/images/ssbl_bin.JPG)
-
-Before writing the SSBL, it it recommanded to fully erase the internal flash:
-
-```
-DK6Programmer.exe -V 5 -P 1000000 -s <COM_PORT> -e Flash
-```
-
-`k32w061dk6_ssbl.bin` must be written at address 0 in the internal flash:
-
-```
-DK6Programmer.exe -V2 -s <COM_PORT> -P 1000000 -Y -p FLASH@0x00="k32w061dk6_ssbl.bin"
-```
-
-### Writing the PSECT
-
-This is the list of all supported partitions:
-
-```
-0000000010000000 : SSBL partition
-
-    00000000 -----------> Start Address
-    1000 ---------------> 0x0010 Number of 512-bytes pages
-    00 -----------------> 0x00 Bootable flag
-    00 -----------------> 0x00 Image type (0x00 = SSBL)
-
-00400000c9040101: Application partition
-
-    00400000 -----------> 0x00004000 Start Address
-    c904 ---------------> 0x04c9 Number of 512-bytes pages
-    01 -----------------> 0x01 Bootable flag
-    01 -----------------> 0x01 Image type (0x01 = Application)
-
-00000010800000fe: Ext Flash text partition
-
-    00000010 -----------> 0x10000000 Start Address (external flash)
-    8000 ---------------> 0x0080 Number of 512-bytes pages
-    00 -----------------> 0x00 Bootable flag
-    fe -----------------> 0xFE Image type (0xFE = Ext Flash text)
-
-00000110300200fc : OTA Image partition
-
-    00000110 -----------> 0x10010000 Start Address
-    3002----------------> 0x0230 Number of 512-bytes pages
-    00 -----------------> 0x00 Bootable flag
-    fc -----------------> 0xFC Image type (0xFC = OTA partition)
-
-00000510100000fd: NVM partition
-
-    00000510 -----------> 0x10050000 Start Address
-    1000 ---------------> 0x0010 Number of 512-bytes pages
-    00 -----------------> 0x00 Bootable flag
-    fd -----------------> 0xFD Image type (0xFD = NVM partition)
-```
-
-First, image directory 0 (SSBL partition) must be written:
-
-```
-DK6Programmer.exe -V5 -s <COM port> -P 1000000 -w image_dir_0=0000000010000000
-```
-
-Here is the interpretation of the fields:
-
-```
-00000000 -> start address 0x00000000
-1000     -> size = 0x0010 pages of 512-bytes (= 8kB)
-00       -> not bootable (only used by the SSBL to support SSBL update)
-00       -> SSBL Image Type
-```
-
-Second, image directory 1 (application partition) must be written:
-
-```
-DK6Programmer.exe -V5 -s <COM port> -P 1000000 -w image_dir_1=00400000C9040101
-```
-
-Here is the interpretation of the fields:
-
-```
-00400000 -> start address 0x00004000
-C904     -> 0x4C9 pages of 512-bytes (= 612.5kB)
-01       -> bootable flag
-01       -> image type for the application
-```
-
-Please note the user can write additional partitions by writing
-`image_dir_2/3/4` with the wanted configuration.
-
-### Writing the application
+The internal flash needs to be prepared for the OTA process. First 16K of the
+internal flash needs to be populated with SSBL related data while the last 8.5K
+of flash space is holding flash configuration related data. The space between
+these two zones will be filled by the application. More details regarding the
+internal flash space can be found in the
+[linker file](../../../../third_party/nxp/nxp_matter_support/examples/platform/k32w0/app/ldscripts/chip-k32w0x-linker.ld).
 
-DK6Programmer can be used for flashing the application:
+The steps for building the SSBL binary with appropriate configuration and
+writing to the board the binary and other OTA related configurations are
+described in the
+[K32W0x1 OTA guide](../../../../docs/guides/nxp/nxp_k32w0_ota_guide.md).
 
-```
-DK6Programmer.exe -V2 -s <COM_PORT> -P 1000000 -Y -p FLASH@0x4000="chip-k32w0x-contact-example.bin"
-```
+Note that the application needs to be built using the
+`chip_enable_ota_requestor=true` option. This is enabled in the configuration by
+default if no `chip_enable_ota_requestor` explicit setting is done.
 
-If debugging is needed, MCUXpresso can be used then for flashing the
-application. Please make sure that the application is written at address 0x4000:
-
-![FLASH_LOCATION](../../../../platform/nxp/k32w/k32w0/doc/images/flash_location.JPG)
+Please also note that, by default, the device expects the OTA image to be
+encrypted with the same key specified by `chip_with_ota_key`. See `args.gni` for
+the default gn configuration.
 
 ### OTA Testing
 
 The OTA topology used for OTA testing is illustrated in the figure below.
 Topology is similar with the one used for Matter Test Events.
 
-![OTA_TOPOLOGY](../../../../platform/nxp/k32w/k32w0/doc/images/ota_topology.JPG)
+![OTA_TOPOLOGY](../../../platform/nxp/k32w0/doc/images/ota_topology.JPG)
 
 The concept for OTA is the next one:
 
 -   there is an OTA Provider Application that holds the OTA image. In our case,
     this is a Linux application running on an Ubuntu based-system;
--   the OTA Requestor functionality is embedded inside the Lighting Application.
-    It will be used for requesting OTA blocks from the OTA Provider;
+-   the OTA Requestor functionality is embedded inside the Contact Sensor
+    Application. It will be used for requesting OTA blocks from the OTA
+    Provider;
 -   the controller (a linux application called chip-tool) will be used for
     commissioning both the device and the OTA Provider App. The device will be
     commissioned using the standard Matter flow (BLE + IEEE 802.15.4) while the
@@ -663,19 +649,19 @@ The concept for OTA is the next one:
     of chip-tool;
 -   during commissioning, each device is assigned a node id by the chip-tool
     (can be specified manually by the user). Using the node id of the device and
-    of the lighting application, chip-tool triggers the OTA transfer by invoking
-    the _announce-ota-provider_ command - basically, the OTA Requestor is
-    informed of the node id of the OTA Provider Application.
+    of the contact sensor application, chip-tool triggers the OTA transfer by
+    invoking the _announce-ota-provider_ command - basically, the OTA Requestor
+    is informed of the node id of the OTA Provider Application.
 
 _Computer #1_ can be any system running an Ubuntu distribution. We recommand
-using TE 7.5 instructions from
-[here](https://groups.csa-iot.org/wg/matter-csg/document/24839), where RPi 4 are
-proposed. Also, TE 7.5 instructions document point to the OS/Docker images that
-should be used on the RPis. For compatibility reasons, we recommand compiling
-chip-tool and OTA Provider applications with the same commit id that was used
-for compiling the Lighting Application. Also, please note that there is a single
-controller (chip-tool) running on Computer #1 which is used for commissioning
-both the device and the OTA Provider Application. If needed,
+using CSA official instructions from
+[here](https://groups.csa-iot.org/wg/matter-csg/document/28566), where RPi 4 are
+proposed. Also, CSA official instructions document point to the OS/Docker images
+that should be used on the RPis. For compatibility reasons, we recommand
+compiling chip-tool and OTA Provider applications with the same commit id that
+was used for compiling the Contact Sensor Application. Also, please note that
+there is a single controller (chip-tool) running on Computer #1 which is used
+for commissioning both the device and the OTA Provider Application. If needed,
 [these instructions](https://itsfoss.com/connect-wifi-terminal-ubuntu/) could be
 used for connecting the RPis to WiFi.
 
@@ -696,7 +682,7 @@ Build OTA image:
 In order to build an OTA image, use NXP wrapper over the standard tool
 `src/app/ota_image_tool.py`:
 
--   `scripts/tools/nxp/ota/ota_image_tool.py`.
+-   `scripts/tools/nxp/ota/ota_image_tool.py`
 
 The tool can be used to generate an OTA image with the following format:
 
@@ -725,7 +711,7 @@ The address for storing the custom OTA entry can also be specified:
     address that does not overlap with anything else.
 
 Please see more in the
-[OTA image tool guide](../../../../../scripts/tools/nxp/ota/README.md).
+[OTA image tool guide](../../../../scripts/tools/nxp/ota/README.md).
 
 Here is an example that generates an OTA image with application update TLV:
 
@@ -735,16 +721,16 @@ Here is an example that generates an OTA image with application update TLV:
 
 Please note the two options `--enc_enable` and `--input_ota_key`, which are
 mandatory when `chip_with_ota_encryption=1`. The value of `--input_ota_key` must
-match the value of `chip_with_ota_key`. See `args.gni` for the default gn
-configuration.
+match the value of `chip_with_ota_key`.
 
 A note regarding OTA image header version (`-vn` option). An application binary
 has its own software version, given by
-`CHIP_DEVICE_CONFIG_DEVICE_SOFTWARE_VERSION` (`42020` by default), which can be
+`CHIP_DEVICE_CONFIG_DEVICE_SOFTWARE_VERSION` (`1` by default), which can be
 overwritten. For having a correct OTA process, the OTA header version should be
-the same as the binary embedded software version. A user can set a custom
-software version in the gn build args by setting `chip_software_version` to the
-wanted version.
+the same as the binary embedded software version. When building the update
+image, the build arguments `nxp_software_version=2` and
+`nxp_sofware_version_string=\"2.0\"` can be added to the gn gen command in order
+to specify the upgraded version.
 
 Start the OTA Provider Application:
 
@@ -774,7 +760,7 @@ Start the OTA process:
 user@computer1:~/connectedhomeip$ : ./out/chip-tool-app/chip-tool otasoftwareupdaterequestor announce-otaprovider 1 0 0 0 2 0
 ```
 
-### Known issues ota
+### Known issues OTA
 
 -   SRP cache on the openthread border router needs to flushed each time a new
     commissioning process is attempted. For this, factory reset the device, then
@@ -827,13 +813,13 @@ Power Measurement Tool can be used inside MCUXpresso for checking the power
 consumption pattern: Window -> Show View -> Other -> Power Measurement Tool. The
 configuration for this tool is the next one:
 
-![POWER_CONF](../../../../platform/nxp/k32w/k32w0/doc/images/power_conf.JPG)
+![POWER_CONF](../../../platform/nxp/k32w0/doc/images/power_conf.JPG)
 
 Also, please make sure that the J14 jumper is set to the _ENABLED_ position and
 no expansion board is attached to the DK6. A view from this tool is illustrated
 below:
 
-![POWER_VIEW](../../../../platform/nxp/k32w/k32w0/doc/images/power_view.JPG)
+![POWER_VIEW](../../../platform/nxp/k32w0/doc/images/power_view.JPG)
 
 Please note that that the Power Measurement Tool is not very accurate and
 professional tools must be used if exact power consumption needs to be known.
@@ -842,34 +828,3 @@ professional tools must be used if exact power consumption needs to be known.
 
 -   Power Measurement Tool may not work correctly in MCUXpresso versions greater
     that 11.0.1.
-
-## Removing SSBL Upgrade Region
-
-The example also offers the possibility to remove SSBL upgrade region, for
-reserving more space for application level.
-
-A new flag `chip_reduce_ssbl_size` is introduced. In order to remove the SSBL
-upgrade region, `chip_reduce_ssbl_size=true` must be provided to the build
-system
-
-The programming method will change:
-
--   writing image directory 1 should change to
-
-    ```
-    DK6Programmer.exe -V5 -s <COM port> -P 1000000 -w image_dir_1=00200000D9040101
-    ```
-
-    Here is the interpretation of the fields:
-
-    ```
-    00200000 -> start address 0x00002000
-    D904     -> 0x4D9 pages of 512-bytes (= 620.5kB)
-    01       -> bootable flag
-    01       -> image type for the application
-    ```
-
--   Matter application offset address should change to
-    ```
-    DK6Programmer.exe -V2 -s <COM_PORT> -P 1000000 -Y -p FLASH@0x2000="chip-k32w0x-contact-example.bin"
-    ```
diff --git a/examples/contact-sensor-app/nxp/k32w/k32w0/args.gni b/examples/contact-sensor-app/nxp/k32w0/args.gni
similarity index 97%
rename from examples/contact-sensor-app/nxp/k32w/k32w0/args.gni
rename to examples/contact-sensor-app/nxp/k32w0/args.gni
index e328a6ede9011f..1709f1da735d5d 100644
--- a/examples/contact-sensor-app/nxp/k32w/k32w0/args.gni
+++ b/examples/contact-sensor-app/nxp/k32w0/args.gni
@@ -24,6 +24,7 @@ chip_with_ota_key = "1234567890ABCDEFA1B2C3D4E5F6F1B4"
 
 chip_stack_lock_tracking = "fatal"
 chip_enable_ble = true
+chip_generate_link_map_file = true
 
 chip_enable_icd_server = true
 chip_enable_icd_lit = false
diff --git a/examples/contact-sensor-app/nxp/k32w0/build_overrides b/examples/contact-sensor-app/nxp/k32w0/build_overrides
new file mode 120000
index 00000000000000..ee19c065d619a2
--- /dev/null
+++ b/examples/contact-sensor-app/nxp/k32w0/build_overrides
@@ -0,0 +1 @@
+../../../build_overrides/
\ No newline at end of file
diff --git a/examples/contact-sensor-app/nxp/k32w/k32w0/include/CHIPProjectConfig.h b/examples/contact-sensor-app/nxp/k32w0/include/CHIPProjectConfig.h
similarity index 98%
rename from examples/contact-sensor-app/nxp/k32w/k32w0/include/CHIPProjectConfig.h
rename to examples/contact-sensor-app/nxp/k32w0/include/CHIPProjectConfig.h
index 301d53824a7e55..2b0afde85d56fe 100644
--- a/examples/contact-sensor-app/nxp/k32w/k32w0/include/CHIPProjectConfig.h
+++ b/examples/contact-sensor-app/nxp/k32w0/include/CHIPProjectConfig.h
@@ -145,11 +145,11 @@
  * {MAJOR_VERSION}.0d{MINOR_VERSION}
  */
 #ifndef CHIP_DEVICE_CONFIG_DEVICE_SOFTWARE_VERSION_STRING
-#define CHIP_DEVICE_CONFIG_DEVICE_SOFTWARE_VERSION_STRING "03-2022-te8"
+#define CHIP_DEVICE_CONFIG_DEVICE_SOFTWARE_VERSION_STRING NXP_CONFIG_DEVICE_SOFTWARE_VERSION_STRING
 #endif
 
 #ifndef CHIP_DEVICE_CONFIG_DEVICE_SOFTWARE_VERSION
-#define CHIP_DEVICE_CONFIG_DEVICE_SOFTWARE_VERSION 42020
+#define CHIP_DEVICE_CONFIG_DEVICE_SOFTWARE_VERSION NXP_CONFIG_DEVICE_SOFTWARE_VERSION
 #endif
 
 #ifndef CHIP_DEVICE_CONFIG_DEVICE_VENDOR_NAME
diff --git a/examples/contact-sensor-app/nxp/k32w/k32w0/include/FreeRTOSConfig.h b/examples/contact-sensor-app/nxp/k32w0/include/FreeRTOSConfig.h
similarity index 100%
rename from examples/contact-sensor-app/nxp/k32w/k32w0/include/FreeRTOSConfig.h
rename to examples/contact-sensor-app/nxp/k32w0/include/FreeRTOSConfig.h
diff --git a/examples/contact-sensor-app/nxp/k32w/k32w0/main/AppTask.cpp b/examples/contact-sensor-app/nxp/k32w0/main/AppTask.cpp
similarity index 96%
rename from examples/contact-sensor-app/nxp/k32w/k32w0/main/AppTask.cpp
rename to examples/contact-sensor-app/nxp/k32w0/main/AppTask.cpp
index d7d9763e491a62..d350a4527d281c 100644
--- a/examples/contact-sensor-app/nxp/k32w/k32w0/main/AppTask.cpp
+++ b/examples/contact-sensor-app/nxp/k32w0/main/AppTask.cpp
@@ -42,11 +42,12 @@
 #include <app/clusters/ota-requestor/DefaultOTARequestor.h>
 #include <app/clusters/ota-requestor/DefaultOTARequestorDriver.h>
 #include <app/clusters/ota-requestor/DefaultOTARequestorStorage.h>
-#include <src/platform/nxp/k32w/common/OTAImageProcessorImpl.h>
+#include <src/platform/nxp/common/legacy/OTAImageProcessorImpl.h>
 #endif
 
-#include <src/platform/nxp/k32w/k32w0/BLEManagerImpl.h>
+#include <src/platform/nxp/k32w0/BLEManagerImpl.h>
 
+#include "DefaultTestEventTriggerDelegate.h"
 #include "Keyboard.h"
 #include "LED.h"
 #include "LEDWidget.h"
@@ -94,6 +95,11 @@ static chip::DeviceLayer::CustomFactoryDataProvider sCustomFactoryDataProvider;
 #endif
 #endif
 
+// This key is for testing/certification only and should not be used in production devices.
+// For production devices this key must be provided from factory data.
+uint8_t sTestEventTriggerEnableKey[TestEventTriggerDelegate::kEnableKeyLength] = { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
+                                                                                   0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff };
+
 static Identify gIdentify = { chip::EndpointId{ 1 }, AppTask::OnIdentifyStart, AppTask::OnIdentifyStop,
                               Clusters::Identify::IdentifyTypeEnum::kVisibleIndicator };
 
@@ -107,7 +113,7 @@ static BDXDownloader gDownloader;
 constexpr uint16_t requestedOtaBlockSize = 1024;
 #endif
 
-#if CONFIG_CHIP_LOAD_REAL_FACTORY_DATA && CONFIG_CHIP_K32W0_OTA_FACTORY_DATA_PROCESSOR
+#if CONFIG_CHIP_LOAD_REAL_FACTORY_DATA && CONFIG_CHIP_OTA_FACTORY_DATA_PROCESSOR
 CHIP_ERROR CustomFactoryDataRestoreMechanism(void)
 {
     K32W_LOG("This is a custom factory data restore mechanism.");
@@ -154,7 +160,7 @@ static void CheckOtaEntry()
         if (ota_entries.ota_state == otaApplied)
         {
             K32W_LOG("OTA successfully applied");
-#if CONFIG_CHIP_LOAD_REAL_FACTORY_DATA && CONFIG_CHIP_K32W0_OTA_FACTORY_DATA_PROCESSOR
+#if CONFIG_CHIP_LOAD_REAL_FACTORY_DATA && CONFIG_CHIP_OTA_FACTORY_DATA_PROCESSOR
             // If this point is reached, it means OTA_CommitCustomEntries was successfully called.
             // Delete the factory data backup to stop doing a restore when the factory data provider
             // is initialized. This ensures that both the factory data and app were updated, otherwise
@@ -184,7 +190,7 @@ CHIP_ERROR AppTask::Init()
     if (ContactSensorMgr().Init() != 0)
     {
         K32W_LOG("ContactSensorMgr().Init() failed");
-        assert(status == 0);
+        assert(0);
     }
 
     PlatformMgr().AddEventHandler(MatterEventHandler, 0);
@@ -196,9 +202,8 @@ CHIP_ERROR AppTask::Init()
     CheckOtaEntry();
 #endif
 
-    // Initialize device attestation config
 #if CONFIG_CHIP_LOAD_REAL_FACTORY_DATA
-#if CONFIG_CHIP_K32W0_OTA_FACTORY_DATA_PROCESSOR
+#if CONFIG_CHIP_OTA_FACTORY_DATA_PROCESSOR
     sFactoryDataProvider.RegisterRestoreMechanism(CustomFactoryDataRestoreMechanism);
 #endif
     ReturnErrorOnFailure(sFactoryDataProvider.Init());
@@ -299,6 +304,8 @@ void AppTask::InitServer(intptr_t arg)
     chip::DeviceLayer::SetDeviceInfoProvider(&infoProvider);
 
     // Init ZCL Data Model and start server
+    static DefaultTestEventTriggerDelegate sTestEventTriggerDelegate{ ByteSpan(sTestEventTriggerEnableKey) };
+    initParams.testEventTriggerDelegate = &sTestEventTriggerDelegate;
     chip::Inet::EndPointStateOpenThread::OpenThreadEndpointInitParam nativeParams;
     nativeParams.lockCb                = LockOpenThreadTask;
     nativeParams.unlockCb              = UnlockOpenThreadTask;
diff --git a/examples/contact-sensor-app/nxp/k32w/k32w0/main/ContactSensorManager.cpp b/examples/contact-sensor-app/nxp/k32w0/main/ContactSensorManager.cpp
similarity index 100%
rename from examples/contact-sensor-app/nxp/k32w/k32w0/main/ContactSensorManager.cpp
rename to examples/contact-sensor-app/nxp/k32w0/main/ContactSensorManager.cpp
diff --git a/examples/contact-sensor-app/nxp/k32w/k32w0/main/ZclCallbacks.cpp b/examples/contact-sensor-app/nxp/k32w0/main/ZclCallbacks.cpp
similarity index 100%
rename from examples/contact-sensor-app/nxp/k32w/k32w0/main/ZclCallbacks.cpp
rename to examples/contact-sensor-app/nxp/k32w0/main/ZclCallbacks.cpp
diff --git a/examples/contact-sensor-app/nxp/k32w/k32w0/main/include/AppEvent.h b/examples/contact-sensor-app/nxp/k32w0/main/include/AppEvent.h
similarity index 100%
rename from examples/contact-sensor-app/nxp/k32w/k32w0/main/include/AppEvent.h
rename to examples/contact-sensor-app/nxp/k32w0/main/include/AppEvent.h
diff --git a/examples/contact-sensor-app/nxp/k32w/k32w0/main/include/AppTask.h b/examples/contact-sensor-app/nxp/k32w0/main/include/AppTask.h
similarity index 95%
rename from examples/contact-sensor-app/nxp/k32w/k32w0/main/include/AppTask.h
rename to examples/contact-sensor-app/nxp/k32w0/main/include/AppTask.h
index c3203d78eb543e..3f81915dca23f9 100644
--- a/examples/contact-sensor-app/nxp/k32w/k32w0/main/include/AppTask.h
+++ b/examples/contact-sensor-app/nxp/k32w0/main/include/AppTask.h
@@ -27,7 +27,7 @@
 #include "CHIPProjectConfig.h"
 
 #if CONFIG_CHIP_LOAD_REAL_FACTORY_DATA
-#include <platform/nxp/k32w/k32w0/FactoryDataProviderImpl.h>
+#include <platform/nxp/k32w0/FactoryDataProviderImpl.h>
 #if CHIP_DEVICE_CONFIG_USE_CUSTOM_PROVIDER
 #include "CustomFactoryDataProvider.h"
 #endif
@@ -50,6 +50,9 @@
 class AppTask
 {
 public:
+#if CONFIG_CHIP_LOAD_REAL_FACTORY_DATA
+    using FactoryDataProvider = chip::DeviceLayer::FactoryDataProviderImpl;
+#endif
     CHIP_ERROR StartAppTask();
     static void AppTaskMain(void * pvParameter);
 
diff --git a/examples/contact-sensor-app/nxp/k32w/k32w0/main/include/ContactSensorManager.h b/examples/contact-sensor-app/nxp/k32w0/main/include/ContactSensorManager.h
similarity index 100%
rename from examples/contact-sensor-app/nxp/k32w/k32w0/main/include/ContactSensorManager.h
rename to examples/contact-sensor-app/nxp/k32w0/main/include/ContactSensorManager.h
diff --git a/examples/contact-sensor-app/nxp/k32w/k32w0/main/include/app_config.h b/examples/contact-sensor-app/nxp/k32w0/main/include/app_config.h
similarity index 100%
rename from examples/contact-sensor-app/nxp/k32w/k32w0/main/include/app_config.h
rename to examples/contact-sensor-app/nxp/k32w0/main/include/app_config.h
diff --git a/examples/contact-sensor-app/nxp/k32w/k32w0/main/main.cpp b/examples/contact-sensor-app/nxp/k32w0/main/main.cpp
similarity index 98%
rename from examples/contact-sensor-app/nxp/k32w/k32w0/main/main.cpp
rename to examples/contact-sensor-app/nxp/k32w0/main/main.cpp
index 56288842a3f5de..9517d7e2cf4309 100644
--- a/examples/contact-sensor-app/nxp/k32w/k32w0/main/main.cpp
+++ b/examples/contact-sensor-app/nxp/k32w0/main/main.cpp
@@ -154,7 +154,7 @@ extern "C" void main_task(void const * argument)
      */
     sched_enable();
 
-    err = ConnectivityMgr().SetThreadDeviceType(ConnectivityManager::kThreadDeviceType_SleepyEndDevice);
+    err = ConnectivityMgr().SetThreadDeviceType(CONNECTIVITY_MANAGER_THREAD_DEVICE_TYPE);
     if (err != CHIP_NO_ERROR)
     {
         goto exit;
diff --git a/examples/contact-sensor-app/nxp/k32w0/third_party/connectedhomeip b/examples/contact-sensor-app/nxp/k32w0/third_party/connectedhomeip
new file mode 120000
index 00000000000000..3efed95be5dbe9
--- /dev/null
+++ b/examples/contact-sensor-app/nxp/k32w0/third_party/connectedhomeip
@@ -0,0 +1 @@
+../../../../../
\ No newline at end of file
diff --git a/examples/lighting-app/nxp/k32w/k32w0/build_overrides b/examples/lighting-app/nxp/k32w/k32w0/build_overrides
deleted file mode 120000
index ad07557834803a..00000000000000
--- a/examples/lighting-app/nxp/k32w/k32w0/build_overrides
+++ /dev/null
@@ -1 +0,0 @@
-../../../../build_overrides/
\ No newline at end of file
diff --git a/examples/lighting-app/nxp/k32w/k32w0/third_party/connectedhomeip b/examples/lighting-app/nxp/k32w/k32w0/third_party/connectedhomeip
deleted file mode 120000
index 305f2077ffe860..00000000000000
--- a/examples/lighting-app/nxp/k32w/k32w0/third_party/connectedhomeip
+++ /dev/null
@@ -1 +0,0 @@
-../../../../../..
\ No newline at end of file
diff --git a/examples/lighting-app/nxp/k32w/k32w0/.gn b/examples/lighting-app/nxp/k32w0/.gn
similarity index 94%
rename from examples/lighting-app/nxp/k32w/k32w0/.gn
rename to examples/lighting-app/nxp/k32w0/.gn
index cfa8fcb8c07dc4..e0a89b885879e6 100644
--- a/examples/lighting-app/nxp/k32w/k32w0/.gn
+++ b/examples/lighting-app/nxp/k32w0/.gn
@@ -31,5 +31,5 @@ default_args = {
       [ "${chip_root}/scripts/setup/requirements.build.txt" ]
 
   # Import default platform configs
-  import("${chip_root}/src/platform/nxp/k32w/k32w0/args.gni")
+  import("${chip_root}/src/platform/nxp/k32w0/args.gni")
 }
diff --git a/examples/lighting-app/nxp/k32w/k32w0/BUILD.gn b/examples/lighting-app/nxp/k32w0/BUILD.gn
similarity index 87%
rename from examples/lighting-app/nxp/k32w/k32w0/BUILD.gn
rename to examples/lighting-app/nxp/k32w0/BUILD.gn
index 82afd7ad22864d..a63a5967c3948b 100644
--- a/examples/lighting-app/nxp/k32w/k32w0/BUILD.gn
+++ b/examples/lighting-app/nxp/k32w0/BUILD.gn
@@ -40,7 +40,7 @@ if (chip_pw_tokenizer_logging) {
 
 assert(current_os == "freertos")
 
-k32w0_platform_dir = "${chip_root}/examples/platform/nxp/k32w/k32w0"
+k32w0_platform_dir = "${nxp_sdk_matter_support_root}/examples/platform/k32w0"
 
 k32w0_sdk("sdk") {
   sources = [
@@ -84,7 +84,10 @@ k32w0_sdk("sdk") {
 k32w0_executable("light_app") {
   output_name = "chip-k32w0x-light-example"
 
+  defines = []
+
   sources = [
+    "${k32w0_platform_dir}/util/DefaultTestEventTriggerDelegate.cpp",
     "${k32w0_platform_dir}/util/LEDWidget.cpp",
     "${k32w0_platform_dir}/util/include/LEDWidget.h",
     "main/AppTask.cpp",
@@ -96,15 +99,13 @@ k32w0_executable("light_app") {
     "main/main.cpp",
   ]
 
-  public = [ "${chip_root}/src/platform/nxp/k32w/k32w0/DefaultTestEventTriggerDelegate.h" ]
-
   if (chip_with_factory_data == 1 && use_custom_factory_provider == 1) {
     sources += [
       "${k32w0_platform_dir}/common/CustomFactoryDataProvider.cpp",
       "${k32w0_platform_dir}/common/CustomFactoryDataProvider.h",
     ]
 
-    defines = [ "CHIP_DEVICE_CONFIG_USE_CUSTOM_PROVIDER=1" ]
+    defines += [ "CHIP_DEVICE_CONFIG_USE_CUSTOM_PROVIDER=1" ]
   }
 
   deps = [
@@ -112,7 +113,6 @@ k32w0_executable("light_app") {
     "${chip_root}/examples/common/QRCode",
     "${chip_root}/examples/lighting-app/nxp/zap/",
     "${chip_root}/examples/providers:device_info_provider",
-    "${chip_root}/src/app:test-event-trigger",
     "${chip_root}/src/lib",
     "${chip_root}/src/platform:syscalls_stub",
     "${chip_root}/src/platform/logging:default",
@@ -120,17 +120,12 @@ k32w0_executable("light_app") {
     "${k32w0_platform_dir}/app/support:freertos_mbedtls_utils",
   ]
 
-  if (chip_openthread_ftd) {
-    deps += [
-      "${chip_root}/third_party/openthread/repo:libopenthread-cli-ftd",
-      "${chip_root}/third_party/openthread/repo:libopenthread-ftd",
-    ]
-  } else {
-    deps += [
-      "${chip_root}/third_party/openthread/repo:libopenthread-cli-mtd",
-      "${chip_root}/third_party/openthread/repo:libopenthread-mtd",
-    ]
-  }
+  defines += [ "CONNECTIVITY_MANAGER_THREAD_DEVICE_TYPE=ConnectivityManager::kThreadDeviceType_MinimalEndDevice" ]
+
+  deps += [
+    "${chip_root}/third_party/openthread/repo:libopenthread-cli-mtd",
+    "${chip_root}/third_party/openthread/repo:libopenthread-mtd",
+  ]
 
   cflags = [ "-Wconversion" ]
 
@@ -169,6 +164,11 @@ group("k32w0") {
     ":binsign",
     ":light_app",
   ]
+
+  if (chip_enable_ota_requestor) {
+    deps += [ "${k32w0_platform_dir}/ssbl:ssbl" ]
+  }
+
   if (chip_pw_tokenizer_logging) {
     deps += [ ":light_app.database" ]
   }
@@ -183,6 +183,10 @@ action("binsign") {
   if (chip_simple_hash_verification == 1) {
     args = [ "--simple-hash" ]
   }
+
+  if (chip_enable_ota_requestor) {
+    args = [ "--ota-enabled" ]
+  }
 }
 
 group("default") {
diff --git a/examples/lighting-app/nxp/k32w/k32w0/README.md b/examples/lighting-app/nxp/k32w0/README.md
similarity index 73%
rename from examples/lighting-app/nxp/k32w/k32w0/README.md
rename to examples/lighting-app/nxp/k32w0/README.md
index a0f560e2e884c4..518e0232a4f6cb 100644
--- a/examples/lighting-app/nxp/k32w/k32w0/README.md
+++ b/examples/lighting-app/nxp/k32w0/README.md
@@ -27,10 +27,12 @@ network.
         -   [Identify cluster LED state](#identify-cluster-led-state)
     -   [Building](#building)
         -   [Overwrite board config files](#overwrite-board-config-files)
-    -   [Known issues building](#known-issues-building)
+        -   [Known issues building](#known-issues-building)
     -   [Rotating device id](#rotating-device-id)
     -   [Manufacturing data](#manufacturing-data)
     -   [Flashing and debugging](#flashing-and-debugging)
+        -   [Using DK6programmer](#using-dk6programmer)
+        -   [Using MCUXpresso](#using-mcuxpresso)
     -   [Pigweed tokenizer](#pigweed-tokenizer)
         -   [Detokenizer script](#detokenizer-script)
         -   [Notes](#notes)
@@ -40,18 +42,12 @@ network.
     -   [Tinycrypt ECC library](#tinycrypt-ecc-library)
         -   [Building steps](#building-steps-1)
     -   [OTA](#ota)
-        -   [Writing the SSBL](#writing-the-ssbl)
-        -   [Features](#features)
-            -   [Multi image](#multi-image)
-            -   [Simple hash verification](#simple-hash-verification)
-        -   [Writing the PSECT](#writing-the-psect)
-        -   [Writing the application](#writing-the-application)
         -   [OTA Testing](#ota-testing)
-    -   [Known issues ota](#known-issues-ota)
+        -   [Known issues OTA](#known-issues-ota)
 
 ## Introduction
 
-![K32W061 DK6](../../../../platform/nxp/k32w/k32w0/doc/images/k32w-dk6.jpg)
+![K32W061 DK6](../../../platform/nxp/k32w0/doc/images/k32w-dk6.jpg)
 
 The K32W061 lighting example application provides a working demonstration of a
 light bulb device, built using the Project CHIP codebase and the NXP K32W061
@@ -81,7 +77,7 @@ Deployment of this firmware configuration requires the K32W061 board setups
 using the K32W061 module board, SE051 Expansion board and Generic Expansion
 board as shown below:
 
-![SE051H  + K32W061 DK6](../../../../platform/nxp/k32w/k32w0/doc/images/k32w-se.jpg)
+![SE051H  + K32W061 DK6](../../../platform/nxp/k32w0/doc/images/k32w-se.jpg)
 
 The SE051H Secure Element extension may be used for best in class security and
 offloading some of the Project CHIP cryptographic operations. Depending on your
@@ -198,10 +194,10 @@ effects:
 
 In order to build the Project CHIP example, we recommend using a Linux
 distribution (supported Operating Systems are listed in
-[BUILDING.md](../../../../../docs/guides/BUILDING.md#tested-operating systems)).
+[BUILDING.md](../../../../docs/guides/BUILDING.md#tested-operating-systems)).
 
 -   Make sure that below prerequisites are correctly installed (as described in
-    [BUILDING.md](../../../../../docs/guides/BUILDING.md#prerequisites)))
+    [BUILDING.md](../../../../docs/guides/BUILDING.md#prerequisites))
 
 ```
 sudo apt-get install git gcc g++ pkg-config libssl-dev libdbus-1-dev \
@@ -231,18 +227,18 @@ user@ubuntu:~/Desktop/git/connectedhomeip$ source scripts/bootstrap.sh
 -   Step 3: Init NXP SDK(s)
 
 ```
-user@ubuntu:~/Desktop/git/connectedhomeip$ scripts/setup/nxp/update_nxp_sdk.py --platform k32w0
+user@ubuntu:~/Desktop/git/connectedhomeip$ third_party/nxp/nxp_matter_support/scripts/update_nxp_sdk.py --platform k32w0
 ```
 
-Note: By default setup/nxp/update_nxp_sdk.py will try to initialize all NXP
-SDKs. Arg "-- help" could be used to view all available options.
+Note: By default update_nxp_sdk.py will try to initialize all NXP SDKs. Arg "--
+help" could be used to view all available options.
 
 -   Start building the application:
 
 ```bash
-user@ubuntu:~/Desktop/git/connectedhomeip$ cd examples/lighting-app/nxp/k32w/k32w0
-user@ubuntu:~/Desktop/git/connectedhomeip/examples/lighting-app/nxp/k32w/k32w0$ gn gen out/debug
-user@ubuntu:~/Desktop/git/connectedhomeip/examples/lighting-app/nxp/k32w/k32w0$ ninja -C out/debug
+user@ubuntu:~/Desktop/git/connectedhomeip$ cd examples/lighting-app/nxp/k32w0
+user@ubuntu:~/Desktop/git/connectedhomeip/examples/lighting-app/nxp/k32w0$ gn gen out/debug
+user@ubuntu:~/Desktop/git/connectedhomeip/examples/lighting-app/nxp/k32w0$ ninja -C out/debug
 ```
 
 To build with Secure Element, follow the same steps as above but set
@@ -279,7 +275,7 @@ used to control an antenna switch. In order to use this feature, user must set
 
 In case signing errors are encountered when running the "sign_images.sh" script
 (run automatically) install the recommanded packages (python version > 3, pip3,
-pycrypto, pycryptodome):
+pycryptodome):
 
 ```
 user@ubuntu:~$ python3 --version
@@ -287,7 +283,6 @@ Python 3.8.2
 user@ubuntu:~$ pip3 --version
 pip 20.0.2 from /usr/lib/python3/dist-packages/pip (python 3.8)
 user@ubuntu:~$ pip3 list | grep -i pycrypto
-pycrypto               2.6.1
 pycryptodome           3.9.8
 ```
 
@@ -310,7 +305,7 @@ k32w0_sdk("sdk") {
 This variable will be used by `k32w0_sdk.gni` to overwrite `chip_with_DK6`
 option, thus the reference board configuration files will no longer be used.
 
-## Known issues building
+### Known issues building
 
 -   When using Secure element and cross-compiling on Linux, log messages from
     the Plug&Trust middleware stack may not echo to the console.
@@ -333,20 +328,20 @@ Please use the following build args:
 ## Manufacturing data
 
 See
-[Guide for writing manufacturing data on NXP devices](../../../../../docs/guides/nxp/nxp_manufacturing_flow.md).
+[Guide for writing manufacturing data on NXP devices](../../../../docs/guides/nxp/nxp_manufacturing_flow.md).
 
 There are factory data generated binaries available in
-examples/platform/nxp/k32w/k32w0/scripts/demo_generated_factory_data folder.
-These are based on the DAC, PAI and PAA certificates found in
+`third_party/nxp/nxp_matter_support/examples/platform/k32w0/scripts/demo_generated_factory_data`
+folder. These are based on the DAC, PAI and PAA certificates found in
 scripts/tools/nxp/demo_generated_certs folder. The demo_factory_data_dut1.bin
 uses the DAC certificate and private key found in
-examples/platform/nxp/k32w/k32w0/scripts/demo_generated_factory_data/dac/dut1
+`third_party/nxp/nxp_matter_support/examples/platform/k32w0/scripts/demo_generated_factory_data/dac/dut1`
 folder. The demo_factory_data_dut2.bin uses the DAC certificate and private key
 found in
-examples/platform/nxp/k32w/k32w0/scripts/demo_generated_factory_data/dac/dut2
+`third_party/nxp/nxp_matter_support/examples/platform/k32w0/scripts/demo_generated_factory_data/dac/dut2`
 folder. These two factory data binaries can be used for testing topologies with
 2 DUTS. They contain the corresponding DACs/PAIs generated using
-generate_nxp_chip_factory_bin.py script. The discriminator is 14014 and the
+`generate_nxp_chip_factory_bin.py` script. The discriminator is 14014 and the
 passcode is 1000. These demo certificates are working with the CDs installed in
 CHIPProjectConfig.h.
 
@@ -355,18 +350,140 @@ Regarding factory data provider, there are two options:
 -   use the default factory data provider: `FactoryDataProviderImpl` by setting
     `chip_with_factory_data=1` in the gn build command.
 -   use a custom factory data provider: please see
-    [Guide for implementing a custom factory data provider](../../../../platform/nxp/k32w/k32w0/common/README.md).
+    [Guide for implementing a custom factory data provider](../../../platform/nxp/k32w0/doc/CustomFactoryDataProvider.md).
     This can be enabled when `chip_with_factory_data=1` by setting
     `use_custom_factory_provider=1` in the gn build command.
 
 ## Flashing and debugging
 
-Program the firmware using the official
+Instructions to program the firmware can be found also at
 [OpenThread Flash Instructions](https://github.com/openthread/ot-nxp/tree/main/src/k32w0/k32w061#flash-binaries).
 
-All you have to do is to replace the Openthread binaries from the above
-documentation with _out/debug/chip-k32w0x-light-example.bin_ if DK6Programmer is
-used or with _out/debug/chip-k32w0x-light-example_ if MCUXpresso is used.
+### Using DK6programmer
+
+The application binary's path is _out/debug/chip-k32w0x-light-example.bin_.
+
+DK6Programmer can be used for flashing the application. There are two available
+versions of the DK6Programmer tool.
+
+The legacy version consists of a Windows executable found inside the
+[SDK](https://mcuxpresso.nxp.com/en/welcome) at path
+`tools/JN-SW-4407-DK6-Flash-Programmer`. This is a Windows application that can
+be installed using the .exe file. Once the application is installed, the COM
+port for K32W061 must be identified:
+
+```
+C:\nxp\DK6ProductionFlashProgrammer>DK6Programmer.exe  --list
+Available connections:
+<COM_PORT>
+```
+
+Once the COM port is identified, the required binary can be flashed:
+
+```
+DK6Programmer.exe -V2 -s <COM_PORT> -P 1000000 -Y -p FLASH@0x4000="chip-k32w0x-light-example.bin"
+```
+
+> **_Note:_** The above example takes into account that the binary uses the
+> `chip_enable_ota_requestor=true` option. The address offset corresponds to the
+> space left for the SSBL binary and the OTA space for the SSBL. If
+> `chip_enable_ota_requestor` is set to `false`, then `0x4000` needs to be
+> replaced with `0x0`.
+
+DK6 Flash Programmer tool has also been integrated part of
+[NXP Secure Provisioning SDK (SPSDK)](https://github.com/nxp-mcuxpresso/spsdk).
+This tool is supported by environments like Windows, Linux or Mac.
+
+`SPSDK` can be installed and run from a Python environment using
+[these instructions](https://spsdk.readthedocs.io/en/latest/usage/installation.html).
+This enables the user to have transparent access to the dk6 programming tool
+through `SPSDK`.
+
+```
+# after specific environment installation steps
+$ spsdk --help
+...
+  +-- dk6prog                             Tool for reading and programming flash memory of DK6 target devices.
+  �   +-- erase                           Erase the memory.
+  �   +-- info                            Prints the information about the connected device.
+  �   +-- isp                             Issues ISP sequence as defined in Driver interface.
+  �   +-- listdev                         Prints the information about the connected devices.
+  �   +-- read                            Reads the memory and writes it to the file or stdout.
+  �   +-- write                           Write the memory.
+...
+```
+
+Dependencies for the `dk6prog` module can be installed using the following
+command, more details
+[here](https://spsdk.readthedocs.io/en/latest/usage/installation.html#dk6-tools):
+
+```
+$ pip install spsdk[dk6]
+```
+
+The `SPSDK` installation adds `dk6prog` as executable to system path, so user
+can use directly `dk6prog` from terminal. The following commands are to be used
+to write the chip-k32w0x-light-example binary to the board.
+
+```
+$ dk6prog listdev
+This is an experimental utility. Use with caution!
+
+List of available devices:
+DEVICE ID: DN038ZH3, VID: 0x403, PID: 0x6015, Serial number: DN038ZH3, Description: DK6 Carrier Board, Address: 9, Backend: Backend.PYFTDI
+$ dk6prog -d DN038ZH3 write 0x4000 ~/path/to/bin/chip-k32w0x-light-example.bin
+
+This is an experimental utility. Use with caution!
+
+Writing memory  [####################################]  100%
+Written 596450 bytes to memory ID 0 at address 0x4000
+```
+
+> **_Note:_** Running `dk6prog` from Windows OS command line requires an integer
+> value for DEVICE ID.
+
+```
+C:\nxp\spsdk>dk6prog listdev
+
+This is an experimental utility. Use with caution!
+
+List of available devices:
+DEVICE ID: 0, VID: 0x0, PID: 0x0, Serial number: b'DN038ZH3', Description: b'DK6 Carrier Board', Address: 67330069, Backend: Backend.FTD2xx
+
+C:\nxp\spsdk>dk6prog -d 0 info
+
+This is an experimental utility. Use with caution!
+
+Chip ID: 0x88888888
+ROM Version: 0x140000cc
+MAC Address: A8:2B:1F:03:00:8D:15:00
+
+Detected DEVICE: UNKNOWN
+
+  Memory   Memory ID   Base Address   Length    Sector Size   Memory Type   Access
+----------------------------------------------------------------------------------------------
+  FLASH    0           0x0            0x9de00   0x200         FLASH         All is available
+  PSECT    1           0x0            0x1e0     0x10          FLASH         All is available
+  pFLASH   2           0x0            0x1e0     0x10          FLASH         All is available
+  Config   3           0x9fc00        0x200     0x200         FLASH         All is available
+  EFUSE    4           0x0            0x80      0x2           EFUSE (OTP)   Write Enabled
+  ROM      5           0x3000000      0x20000   0x1           ROM           Write Enabled
+  RAM0     6           0x4000000      0x16000   0x1           RAM           Write Enabled
+  RAM1     7           0x4020000      0x10000   0x1           RAM           Write Enabled
+```
+
+> **_Note:_** The above example takes into account that the binary uses the
+> `chip_enable_ota_requestor=true` option. The address offset corresponds to the
+> space left for the SSBL binary and the OTA space for the SSBL. If
+> `chip_enable_ota_requestor` is set to `false`, then `0x4000` needs to be
+> replaced with `0x0`.
+
+### Using MCUXpresso
+
+If flashing and debugging is required, MCUXpresso can be used as instructed in
+[MCUXpresso flashing and debugging instructions](https://github.com/openthread/ot-nxp/tree/main/src/k32w0/k32w061#using-mcuxpresso-ide).
+The file needed to be used in MCUXpresso is
+_out/debug/chip-k32w0x-light-example_.
 
 ## Pigweed tokenizer
 
@@ -379,7 +496,7 @@ needed for parsing the hashed scripts.
 
 The python3 script detokenizer.py is a script that decodes the tokenized logs
 either from a file or from a serial port. It is located in the following path
-`examples/platform/nxp/k32w/k32w0/scripts/detokenizer.py`.
+`third_party/nxp/nxp_matter_support/examples/platform/k32w0/scripts/detokenizer.py`.
 
 The script can be used in the following ways:
 
@@ -414,7 +531,7 @@ by the script is loaded by the environment. An example of running the
 detokenizer script to see logs of a lighting app:
 
 ```
-python3 ../../../../../examples/platform/nxp/k32w/k32w0/scripts/detokenizer.py serial -i /dev/ttyACM0 -d out/debug/chip-k32w0x-light-example-database.bin -o device.txt
+python3 ../../../../third_party/nxp/nxp_matter_support/examples/platform/k32w0/scripts/detokenizer.py serial -i /dev/ttyACM0 -d out/debug/chip-k32w0x-light-example-database.bin -o device.txt
 ```
 
 ### Known issues tokenizer
@@ -459,172 +576,37 @@ In order to use the Tinycrypt ECC library, use the following build arguments:
 
 ## OTA
 
-The internal flash needs to be prepared for the OTA process. First 16K of the
-internal flash needs to be populated with a Secondary Stage Bootloader (SSBL)
-related data while the last 8.5K of flash space is holding image directory
-related data (PSECT). The space between these two zones will be filled by the
+Over the air updates (OTA) require several software components running on the
+K32W0x1. Firstly, a Secondary Stage Bootloader (SSBL) is required written in the
+first part of the internal flash memory, usually starting at address 0x0. This
+enables the board to boot and check if a new OTA binary has been received. If
+this is true, the bootloader writes the OTA binary to the appropriate storage,
+internal and/or external flash, after which it reboots the board. If no new OTA
+binaries have been found, then the bootloader gives execution control to the
 application.
 
-### Writing the SSBL
-
-The SDK already provides an SSBL binary compiled with external flash support:
-`boards/k32w061dk6/wireless_examples/framework/ssbl/binary/ssbl_ext_flash_pdm_support.bin`,
-but it does not offer multi-image OTA support.
-
-Alternatively, the SSBL can ge generated from one of the SDK demo examples. The
-SSBL demo application can be imported from the `Quickstart panel`:
-`Import SDK example(s) -> select wireless -> framework -> ssbl` application.
-
-![SSBL Application Select](../../../../platform/nxp/k32w/k32w0/doc/images/ssbl_select.JPG)
-
-### Features
-
-#### Multi image
-
-To support multi-image OTA feature, the SSBL project must be compiled using the
-following defines:
-
--   `PDM_EXT_FLASH=1` - support PDM in external flash.
--   `gOTAUseCustomOtaEntry=1` - support custom OTA entry for multi-image.
--   `gOTACustomOtaEntryMemory=OTACustomStorage_ExtFlash` - K32W0 uses
-    `OTACustomStorage_ExtFlash` (1) by default.
--   `SPIFI_DUAL_MODE_SUPPORT=1` - only for configurations that use dual `SPIFI`
-    flash (e.g. K32W041AM variant).
-
-Optionally, add the following defines:
-
--   `SPIFI_OPTIM_SIZE=1` - to optimize SSBL size.
--   `EXTERNAL_FLASH_DATA_OTA=1` - to support external read only data.
-
-![SSBL_MULTI_IMAGE](../../../../platform/nxp/k32w/k32w0/doc/images/ssbl_multi_image.JPG)
-
-#### Simple hash verification
-
-When secure boot is not used, a simple hash can be appended at the end of the
-image for integrity check. Applications should be built with
-`chip_simple_hash_verification=1`.
-
-To support simple hash verification feature, the SSBL project must be compiled
-with:
-
--   `gSimpleHashVerification=1`
-
-and update the post-build command to use simple hash verification instead of the
-default options. Go to
-`Project -> Properties -> C/C++ Build -> Settings -> Build steps` and press
-`Edit` under `Post-build steps` subsection. The command should look similar to:
-
-![SSBL_SIMPLE_HASH_VERIFICATION](../../../../platform/nxp/k32w/k32w0/doc/images/ssbl_simple_hash.JPG)
-
-Once compiled, the required SSBL file is called `k32w061dk6_ssbl.bin`.
-
-![SSBL_BIN](../../../../platform/nxp/k32w/k32w0/doc/images/ssbl_bin.JPG)
-
-Before writing the SSBL, it it recommanded to fully erase the internal flash:
-
-```
-DK6Programmer.exe -V 5 -P 1000000 -s <COM_PORT> -e Flash
-```
-
-`k32w061dk6_ssbl.bin` must be written at address 0 in the internal flash:
-
-```
-DK6Programmer.exe -V2 -s <COM_PORT> -P 1000000 -Y -p FLASH@0x00="k32w061dk6_ssbl.bin"
-```
-
-### Writing the PSECT
-
-This is the list of all supported partitions:
-
-```
-0000000010000000 : SSBL partition
-
-    00000000 -----------> Start Address
-    1000 ---------------> 0x0010 Number of 512-bytes pages
-    00 -----------------> 0x00 Bootable flag
-    00 -----------------> 0x00 Image type (0x00 = SSBL)
-
-00400000c9040101: Application partition
-
-    00400000 -----------> 0x00004000 Start Address
-    c904 ---------------> 0x04c9 Number of 512-bytes pages
-    01 -----------------> 0x01 Bootable flag
-    01 -----------------> 0x01 Image type (0x01 = Application)
-
-00000010800000fe: Ext Flash text partition
-
-    00000010 -----------> 0x10000000 Start Address (external flash)
-    8000 ---------------> 0x0080 Number of 512-bytes pages
-    00 -----------------> 0x00 Bootable flag
-    fe -----------------> 0xFE Image type (0xFE = Ext Flash text)
-
-00000110300200fc : OTA Image partition
-
-    00000110 -----------> 0x10010000 Start Address
-    3002----------------> 0x0230 Number of 512-bytes pages
-    00 -----------------> 0x00 Bootable flag
-    fc -----------------> 0xFC Image type (0xFC = OTA partition)
-
-00000510100000fd: NVM partition
-
-    00000510 -----------> 0x10050000 Start Address
-    1000 ---------------> 0x0010 Number of 512-bytes pages
-    00 -----------------> 0x00 Bootable flag
-    fd -----------------> 0xFD Image type (0xFD = NVM partition)
-```
-
-First, image directory 0 (SSBL partition) must be written:
-
-```
-DK6Programmer.exe -V5 -s <COM port> -P 1000000 -w image_dir_0=0000000010000000
-```
-
-Here is the interpretation of the fields:
-
-```
-00000000 -> start address 0x00000000
-1000     -> size = 0x0010 pages of 512-bytes (= 8kB)
-00       -> not bootable (only used by the SSBL to support SSBL update)
-00       -> SSBL Image Type
-```
-
-Second, image directory 1 (application partition) must be written:
-
-```
-DK6Programmer.exe -V5 -s <COM port> -P 1000000 -w image_dir_1=00400000C9040101
-```
-
-Here is the interpretation of the fields:
-
-```
-00400000 -> start address 0x00004000
-C904     -> 0x4C9 pages of 512-bytes (= 612.5kB)
-01       -> bootable flag
-01       -> image type for the application
-```
-
-Please note the user can write additional partitions by writing
-`image_dir_2/3/4` with the wanted configuration.
-
-### Writing the application
-
-DK6Programmer can be used for flashing the application:
-
-```
-DK6Programmer.exe -V2 -s <COM_PORT> -P 1000000 -Y -p FLASH@0x4000="chip-k32w0x-light-example.bin"
-```
+The internal flash needs to be prepared for the OTA process. First 16K of the
+internal flash needs to be populated with SSBL related data while the last 8.5K
+of flash space is holding flash configuration related data. The space between
+these two zones will be filled by the application. More details regarding the
+internal flash space can be found in the
+[linker file](../../../../third_party/nxp/nxp_matter_support/examples/platform/k32w0/app/ldscripts/chip-k32w0x-linker.ld).
 
-If debugging is needed, MCUXpresso can be used then for flashing the
-application. Please make sure that the application is written at address 0x4000:
+The steps for building the SSBL binary with appropriate configuration and
+writing to the board the binary and other OTA related configurations are
+described in the
+[K32W0x1 OTA guide](../../../../docs/guides/nxp/nxp_k32w0_ota_guide.md).
 
-![FLASH_LOCATION](../../../../platform/nxp/k32w/k32w0/doc/images/flash_location.JPG)
+Note that the application needs to be built using the
+`chip_enable_ota_requestor=true` option. This is enabled in the configuration by
+default if no `chip_enable_ota_requestor` explicit setting is done.
 
 ### OTA Testing
 
 The OTA topology used for OTA testing is illustrated in the figure below.
 Topology is similar with the one used for Matter Test Events.
 
-![OTA_TOPOLOGY](../../../../platform/nxp/k32w/k32w0/doc/images/ota_topology.JPG)
+![OTA_TOPOLOGY](../../../platform/nxp/k32w0/doc/images/ota_topology.JPG)
 
 The concept for OTA is the next one:
 
@@ -701,21 +683,22 @@ The address for storing the custom OTA entry can also be specified:
     address that does not overlap with anything else.
 
 Please see more in the
-[OTA image tool guide](../../../../../scripts/tools/nxp/ota/README.md).
+[OTA image tool guide](../../../../scripts/tools/nxp/ota/README.md).
 
 Here is an example that generates an OTA image with application update TLV:
 
 ```
-./scripts/tools/nxp/ota/ota_image_tool.py create -v 0xDEAD -p 0xBEEF -vn 42021 -vs "1.0" -da sha256 --app-input-file chip-k32w0x-light-example.bin chip-k32w0x-light-example.ota
+./scripts/tools/nxp/ota/ota_image_tool.py create -v 0xDEAD -p 0xBEEF -vn 2 -vs "2.0" -da sha256 --app-input-file chip-k32w0x-light-example.bin chip-k32w0x-light-example.ota
 ```
 
 A note regarding OTA image header version (`-vn` option). An application binary
 has its own software version, given by
-`CHIP_DEVICE_CONFIG_DEVICE_SOFTWARE_VERSION` (`42020` by default), which can be
+`CHIP_DEVICE_CONFIG_DEVICE_SOFTWARE_VERSION` (`1` by default), which can be
 overwritten. For having a correct OTA process, the OTA header version should be
-the same as the binary embedded software version. A user can set a custom
-software version in the gn build args by setting `chip_software_version` to the
-wanted version.
+the same as the binary embedded software version. When building the update
+image, the build arguments `nxp_software_version=2` and
+`nxp_sofware_version_string=\"2.0\"` can be added to the gn gen command in order
+to specify the upgraded version.
 
 Start the OTA Provider Application:
 
@@ -745,7 +728,7 @@ Start the OTA process:
 user@computer1:~/connectedhomeip$ : ./out/chip-tool-app/chip-tool otasoftwareupdaterequestor announce-otaprovider 1 0 0 0 2 0
 ```
 
-## Known issues ota
+### Known issues OTA
 
 -   SRP cache on the openthread border router needs to flushed each time a new
     commissioning process is attempted. For this, factory reset the device, then
diff --git a/examples/lighting-app/nxp/k32w/k32w0/args.gni b/examples/lighting-app/nxp/k32w0/args.gni
similarity index 96%
rename from examples/lighting-app/nxp/k32w/k32w0/args.gni
rename to examples/lighting-app/nxp/k32w0/args.gni
index f5fd7a83cd9005..7126cf38ad5f3b 100644
--- a/examples/lighting-app/nxp/k32w/k32w0/args.gni
+++ b/examples/lighting-app/nxp/k32w0/args.gni
@@ -20,6 +20,7 @@ k32w0_sdk_target = get_label_info(":sdk", "label_no_toolchain")
 chip_enable_ota_requestor = true
 chip_stack_lock_tracking = "fatal"
 chip_enable_ble = true
+chip_generate_link_map_file = true
 
 is_debug = false
 
diff --git a/examples/lighting-app/nxp/k32w0/build_overrides b/examples/lighting-app/nxp/k32w0/build_overrides
new file mode 120000
index 00000000000000..ee19c065d619a2
--- /dev/null
+++ b/examples/lighting-app/nxp/k32w0/build_overrides
@@ -0,0 +1 @@
+../../../build_overrides/
\ No newline at end of file
diff --git a/examples/lighting-app/nxp/k32w/k32w0/include/CHIPProjectConfig.h b/examples/lighting-app/nxp/k32w0/include/CHIPProjectConfig.h
similarity index 97%
rename from examples/lighting-app/nxp/k32w/k32w0/include/CHIPProjectConfig.h
rename to examples/lighting-app/nxp/k32w0/include/CHIPProjectConfig.h
index e32575e55ff5c4..62b2b0273f1da4 100644
--- a/examples/lighting-app/nxp/k32w/k32w0/include/CHIPProjectConfig.h
+++ b/examples/lighting-app/nxp/k32w0/include/CHIPProjectConfig.h
@@ -86,7 +86,7 @@
             0xe4, 0x76, 0x1b, 0xfd, 0x05,                                                                                          \
     }
 
-// All remaining data will be pulled from provisioning region of flash.
+// All remaining data will be pulled from the provisioning region of flash.
 #endif
 
 #else
@@ -146,11 +146,11 @@
  * {MAJOR_VERSION}.0d{MINOR_VERSION}
  */
 #ifndef CHIP_DEVICE_CONFIG_DEVICE_SOFTWARE_VERSION_STRING
-#define CHIP_DEVICE_CONFIG_DEVICE_SOFTWARE_VERSION_STRING "03-2022-te8"
+#define CHIP_DEVICE_CONFIG_DEVICE_SOFTWARE_VERSION_STRING NXP_CONFIG_DEVICE_SOFTWARE_VERSION_STRING
 #endif
 
 #ifndef CHIP_DEVICE_CONFIG_DEVICE_SOFTWARE_VERSION
-#define CHIP_DEVICE_CONFIG_DEVICE_SOFTWARE_VERSION 42020
+#define CHIP_DEVICE_CONFIG_DEVICE_SOFTWARE_VERSION NXP_CONFIG_DEVICE_SOFTWARE_VERSION
 #endif
 
 #ifndef CHIP_DEVICE_CONFIG_DEVICE_VENDOR_NAME
diff --git a/examples/lighting-app/nxp/k32w/k32w0/include/FreeRTOSConfig.h b/examples/lighting-app/nxp/k32w0/include/FreeRTOSConfig.h
similarity index 100%
rename from examples/lighting-app/nxp/k32w/k32w0/include/FreeRTOSConfig.h
rename to examples/lighting-app/nxp/k32w0/include/FreeRTOSConfig.h
diff --git a/examples/lighting-app/nxp/k32w/k32w0/main/AppTask.cpp b/examples/lighting-app/nxp/k32w0/main/AppTask.cpp
similarity index 98%
rename from examples/lighting-app/nxp/k32w/k32w0/main/AppTask.cpp
rename to examples/lighting-app/nxp/k32w0/main/AppTask.cpp
index 22535a1c974c92..7db25b0a7c0451 100644
--- a/examples/lighting-app/nxp/k32w/k32w0/main/AppTask.cpp
+++ b/examples/lighting-app/nxp/k32w0/main/AppTask.cpp
@@ -29,7 +29,6 @@
 #include <lib/support/ThreadOperationalDataset.h>
 #include <platform/CHIPDeviceLayer.h>
 #include <platform/internal/DeviceNetworkInfo.h>
-#include <src/platform/nxp/k32w/k32w0/DefaultTestEventTriggerDelegate.h>
 
 #include <app-common/zap-generated/attributes/Accessors.h>
 #include <app-common/zap-generated/ids/Clusters.h>
@@ -44,9 +43,10 @@
 #include <app/clusters/ota-requestor/DefaultOTARequestor.h>
 #include <app/clusters/ota-requestor/DefaultOTARequestorDriver.h>
 #include <app/clusters/ota-requestor/DefaultOTARequestorStorage.h>
-#include <src/platform/nxp/k32w/common/OTAImageProcessorImpl.h>
+#include <src/platform/nxp/common/legacy/OTAImageProcessorImpl.h>
 #endif
 
+#include "DefaultTestEventTriggerDelegate.h"
 #include "Keyboard.h"
 #include "LED.h"
 #include "LEDWidget.h"
@@ -116,7 +116,7 @@ static BDXDownloader gDownloader;
 constexpr uint16_t requestedOtaBlockSize = 1024;
 #endif
 
-#if CONFIG_CHIP_LOAD_REAL_FACTORY_DATA && CONFIG_CHIP_K32W0_OTA_FACTORY_DATA_PROCESSOR
+#if CONFIG_CHIP_LOAD_REAL_FACTORY_DATA && CONFIG_CHIP_OTA_FACTORY_DATA_PROCESSOR
 CHIP_ERROR CustomFactoryDataRestoreMechanism(void)
 {
     K32W_LOG("This is a custom factory data restore mechanism.");
@@ -151,7 +151,7 @@ static void CheckOtaEntry()
         if (ota_entries.ota_state == otaApplied)
         {
             K32W_LOG("OTA successfully applied");
-#if CONFIG_CHIP_LOAD_REAL_FACTORY_DATA && CONFIG_CHIP_K32W0_OTA_FACTORY_DATA_PROCESSOR
+#if CONFIG_CHIP_LOAD_REAL_FACTORY_DATA && CONFIG_CHIP_OTA_FACTORY_DATA_PROCESSOR
             // If this point is reached, it means OTA_CommitCustomEntries was successfully called.
             // Delete the factory data backup to stop doing a restore when the factory data provider
             // is initialized. This ensures that both the factory data and app were updated, otherwise
@@ -187,9 +187,8 @@ CHIP_ERROR AppTask::Init()
     CheckOtaEntry();
 #endif
 
-    // Initialize device attestation config
 #if CONFIG_CHIP_LOAD_REAL_FACTORY_DATA
-#if CONFIG_CHIP_K32W0_OTA_FACTORY_DATA_PROCESSOR
+#if CONFIG_CHIP_OTA_FACTORY_DATA_PROCESSOR
     sFactoryDataProvider.RegisterRestoreMechanism(CustomFactoryDataRestoreMechanism);
 #endif
     ReturnErrorOnFailure(sFactoryDataProvider.Init());
diff --git a/examples/lighting-app/nxp/k32w/k32w0/main/LightingManager.cpp b/examples/lighting-app/nxp/k32w0/main/LightingManager.cpp
similarity index 100%
rename from examples/lighting-app/nxp/k32w/k32w0/main/LightingManager.cpp
rename to examples/lighting-app/nxp/k32w0/main/LightingManager.cpp
diff --git a/examples/lighting-app/nxp/k32w/k32w0/main/ZclCallbacks.cpp b/examples/lighting-app/nxp/k32w0/main/ZclCallbacks.cpp
similarity index 100%
rename from examples/lighting-app/nxp/k32w/k32w0/main/ZclCallbacks.cpp
rename to examples/lighting-app/nxp/k32w0/main/ZclCallbacks.cpp
diff --git a/examples/lighting-app/nxp/k32w/k32w0/main/include/AppEvent.h b/examples/lighting-app/nxp/k32w0/main/include/AppEvent.h
similarity index 100%
rename from examples/lighting-app/nxp/k32w/k32w0/main/include/AppEvent.h
rename to examples/lighting-app/nxp/k32w0/main/include/AppEvent.h
diff --git a/examples/lighting-app/nxp/k32w/k32w0/main/include/AppTask.h b/examples/lighting-app/nxp/k32w0/main/include/AppTask.h
similarity index 95%
rename from examples/lighting-app/nxp/k32w/k32w0/main/include/AppTask.h
rename to examples/lighting-app/nxp/k32w0/main/include/AppTask.h
index 0c455f431a8cf4..7dca1f700f6b89 100644
--- a/examples/lighting-app/nxp/k32w/k32w0/main/include/AppTask.h
+++ b/examples/lighting-app/nxp/k32w0/main/include/AppTask.h
@@ -27,7 +27,7 @@
 #include "CHIPProjectConfig.h"
 
 #if CONFIG_CHIP_LOAD_REAL_FACTORY_DATA
-#include <platform/nxp/k32w/k32w0/FactoryDataProviderImpl.h>
+#include <platform/nxp/k32w0/FactoryDataProviderImpl.h>
 #if CHIP_DEVICE_CONFIG_USE_CUSTOM_PROVIDER
 #include "CustomFactoryDataProvider.h"
 #endif
@@ -50,6 +50,9 @@
 class AppTask
 {
 public:
+#if CONFIG_CHIP_LOAD_REAL_FACTORY_DATA
+    using FactoryDataProvider = chip::DeviceLayer::FactoryDataProviderImpl;
+#endif
     CHIP_ERROR StartAppTask();
     static void AppTaskMain(void * pvParameter);
 
diff --git a/examples/lighting-app/nxp/k32w/k32w0/main/include/LightingManager.h b/examples/lighting-app/nxp/k32w0/main/include/LightingManager.h
similarity index 100%
rename from examples/lighting-app/nxp/k32w/k32w0/main/include/LightingManager.h
rename to examples/lighting-app/nxp/k32w0/main/include/LightingManager.h
diff --git a/examples/lighting-app/nxp/k32w/k32w0/main/include/app_config.h b/examples/lighting-app/nxp/k32w0/main/include/app_config.h
similarity index 100%
rename from examples/lighting-app/nxp/k32w/k32w0/main/include/app_config.h
rename to examples/lighting-app/nxp/k32w0/main/include/app_config.h
diff --git a/examples/lighting-app/nxp/k32w/k32w0/main/main.cpp b/examples/lighting-app/nxp/k32w0/main/main.cpp
similarity index 97%
rename from examples/lighting-app/nxp/k32w/k32w0/main/main.cpp
rename to examples/lighting-app/nxp/k32w0/main/main.cpp
index a8963a17c09096..6d95f10fe1168b 100644
--- a/examples/lighting-app/nxp/k32w/k32w0/main/main.cpp
+++ b/examples/lighting-app/nxp/k32w0/main/main.cpp
@@ -139,7 +139,7 @@ extern "C" void main_task(void const * argument)
      */
     sched_enable();
 
-    err = ConnectivityMgr().SetThreadDeviceType(ConnectivityManager::kThreadDeviceType_MinimalEndDevice);
+    err = ConnectivityMgr().SetThreadDeviceType(CONNECTIVITY_MANAGER_THREAD_DEVICE_TYPE);
     if (err != CHIP_NO_ERROR)
     {
         goto exit;
diff --git a/examples/lighting-app/nxp/k32w0/third_party/connectedhomeip b/examples/lighting-app/nxp/k32w0/third_party/connectedhomeip
new file mode 120000
index 00000000000000..3efed95be5dbe9
--- /dev/null
+++ b/examples/lighting-app/nxp/k32w0/third_party/connectedhomeip
@@ -0,0 +1 @@
+../../../../../
\ No newline at end of file
diff --git a/examples/platform/nxp/k32w/k32w0/BUILD.gn b/examples/platform/nxp/k32w/k32w0/BUILD.gn
deleted file mode 100644
index eb0c79742f3b99..00000000000000
--- a/examples/platform/nxp/k32w/k32w0/BUILD.gn
+++ /dev/null
@@ -1,35 +0,0 @@
-# Copyright (c) 2020 Project CHIP Authors
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-import("//build_overrides/chip.gni")
-import("//build_overrides/nxp_sdk.gni")
-
-import("${nxp_sdk_build_root}/nxp_sdk.gni")
-
-import("${nxp_sdk_build_root}/${nxp_sdk_name}/${nxp_sdk_name}.gni")
-
-config("chip_examples_project_config") {
-  include_dirs = [
-    "app/project_include",
-    "${chip_root}",
-  ]
-}
-
-source_set("openthread_core_config_k32w0_chip_examples") {
-  sources = [ "app/project_include/OpenThreadConfig.h" ]
-
-  public_deps = [ "${chip_root}/third_party/openthread/platforms/nxp/k32w/k32w0:openthread_core_config_k32w0" ]
-
-  public_configs = [ ":chip_examples_project_config" ]
-}
diff --git a/examples/platform/nxp/k32w/k32w0/app/BUILD.gn b/examples/platform/nxp/k32w/k32w0/app/BUILD.gn
deleted file mode 100644
index 8651bd56be4ecd..00000000000000
--- a/examples/platform/nxp/k32w/k32w0/app/BUILD.gn
+++ /dev/null
@@ -1,27 +0,0 @@
-# Copyright (c) 2020 Project CHIP Authors
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-import("//build_overrides/chip.gni")
-
-config("chip_examples_project_config") {
-  include_dirs = [ "app/project_include" ]
-}
-
-source_set("openthread_core_config_k32w0_chip_examples") {
-  sources = [ "app/project_include/OpenThreadConfig.h" ]
-
-  public_deps = [ "${chip_root}/third_party/openthread/platforms/nxp/k32w/k32w0:openthread_core_config_k32w0" ]
-
-  public_configs = [ ":chip_examples_project_config" ]
-}
diff --git a/examples/platform/nxp/k32w/k32w0/app/args.gni b/examples/platform/nxp/k32w/k32w0/app/args.gni
deleted file mode 100644
index 44a96b88a65b1b..00000000000000
--- a/examples/platform/nxp/k32w/k32w0/app/args.gni
+++ /dev/null
@@ -1,28 +0,0 @@
-# Copyright (c) 2020 Project CHIP Authors
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-import("//build_overrides/chip.gni")
-
-import("${chip_root}/src/platform/nxp/k32w/k32w0/args.gni")
-
-openthread_project_core_config_file = "OpenThreadConfig.h"
-
-chip_ble_project_config_include = "<CHIPProjectConfig.h>"
-chip_device_project_config_include = "<CHIPProjectConfig.h>"
-chip_project_config_include = "<CHIPProjectConfig.h>"
-chip_inet_project_config_include = "<CHIPProjectConfig.h>"
-chip_system_project_config_include = "<CHIPProjectConfig.h>"
-
-chip_system_config_provide_statistics = false
-chip_with_nlfaultinjection = true
diff --git a/examples/platform/nxp/k32w/k32w0/app/ldscripts/chip-k32w0x-linker.ld b/examples/platform/nxp/k32w/k32w0/app/ldscripts/chip-k32w0x-linker.ld
deleted file mode 100644
index c51182b104ec53..00000000000000
--- a/examples/platform/nxp/k32w/k32w0/app/ldscripts/chip-k32w0x-linker.ld
+++ /dev/null
@@ -1,448 +0,0 @@
-/*
- *  Copyright (c) 2019, The OpenThread Authors.
- *  All rights reserved.
- *
- *  Redistribution and use in source and binary forms, with or without
- *  modification, are permitted provided that the following conditions are met:
- *  1. Redistributions of source code must retain the above copyright
- *     notice, this list of conditions and the following disclaimer.
- *  2. Redistributions in binary form must reproduce the above copyright
- *     notice, this list of conditions and the following disclaimer in the
- *     documentation and/or other materials provided with the distribution.
- *  3. Neither the name of the copyright holder nor the
- *     names of its contributors may be used to endorse or promote products
- *     derived from this software without specific prior written permission.
- *
- *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- *  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- *  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- *  ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
- *  LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- *  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- *  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- *  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- *  CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- *  POSSIBILITY OF SUCH DAMAGE.
- */
-
-/**
- * @file
- *   GCC linker script for K32W061/K32W041.
- */
-
-/******************* Map of K32W0 internal flash ***********************************
-
-             0x000A_0000
-    - - - +---------------+ - - - - - - - -
-          |               |
-    8.5K  | Flash config  |
-          |   RESERVED    | 0x0009_DE00
-    - - - +---------------+ - - - - - - - -
-          |               |
-     2K   | Factory data  |
-          |               | 0x0009_D600
-    - - - +---------------+ - - - - - - - -
-          |               |
-     1K   | App metadata  |
-          |               | 0x0009_D200
-    - - - +---------------+ - - - - - - - -
-          |               |
-   612.5K |  Application  |
-          |               | 0x0000_4000
-    - - - +---------------+ - - - - - - - -
-          |               |
-     8K   |  SSBL update  |
-          |               | 0x0000_2000
-    - - - +---------------+ - - - - - - - -
-          |               |
-     8K   |     SSBL      |
-          |               | 0x0000_0000
-    - - - +---------------+ - - - - - - - -
-             0x0000_0000
-
-* - If OTA is disabled, SSBL and SSBL updated region are not present.
-  - The only address range that changes is the application, which will span from
-    0x0000_0000 to 0x0009_D200, having 628.5K max size.
- *****************************************************************************/
-
-/******************* Map of DK6 external flash ***********************************
-
-             0x0010_0000
-    - - - +---------------+ - - - - - - - -
-          |               |
-    252K  |   PDM area    |
-          |               | 0x000C_1000
-    - - - +---------------+ - - - - - - - -
-          |               |
-     4K   |   OTA entry   |
-          |               | 0x000C_0000
-    - - - +---------------+ - - - - - - - -
-          |               |
-    768K  |   OTA area    |
-          |               |
-    - - - +---------------+ - - - - - - - -
-             0x0000_0000
-
- *****************************************************************************/
-
-OUTPUT_FORMAT ("elf32-littlearm", "elf32-bigarm", "elf32-littlearm")
-
-/*
- * stack size for the boot rom during warm boot and application
- * 256 is sufficient (pwrm_test) but keep it large to 1024
- */
-BOOT_RESUME_STACK_SIZE = 1024;
-
-STACK_SIZE             = DEFINED(__stack_size__) ? __stack_size__ : 0x01000;
-
-MEM_RAM0_BASE          = 0x4000400;
-MEM_RAM0_SIZE          = 0x0015c00;
-
-MEM_RAM1_BASE          = 0x4020000;
-MEM_RAM1_SIZE          = 0x10000;
-
-/* internal flash size: 640K */
-m_int_flash_size       = 0xA0000;
-m_int_sector_size      = 512;
-
-/* first 8K: SSBL, next 8K: SSBL update region */
-m_app_start            = DEFINED(__app_load_address__) ? __app_load_address__ : 0x0;
-
-/* flash_config: 8.5K */
-m_flash_config_size           = 0x2200;
-
-/* sizeof(BOOT_BLOCK_T) + sizeof(IMAGE_CERT_T) + SIGNATURE_LEN + alignment = 1024 bytes */
-m_app_meta_data        = 0x400;
-
-/* manufacturing data: 2K */
-m_factory_data_size    = 0x800;
-
-/* 16K: SSBL + SSBL update region */
-m_ssbl_size            = 0x4000;
-
-/* default app size, without OTA */
-m_app_default_size     = m_int_flash_size - m_flash_config_size - m_app_meta_data - m_factory_data_size;
-
-m_app_size     = DEFINED(__app_stated_size__) ? __app_stated_size__ : m_app_default_size;
-
-MEMORY
-{
-  Flash640 (rx)     : ORIGIN = m_app_start, LENGTH = m_app_size
-  
-  SCRATCH_RAM(rwx)  : ORIGIN = 0x4000000,   LENGTH = 0x400        /* 1K bytes (alias SCRATCH_RAM) */
-  RAM0 (rwx)        : ORIGIN = 0x4000400,   LENGTH = 0x0015BE0    /* [87K - 32] bytes (alias RAM) */
-  reserved (rwx)    : ORIGIN = 0x4015FE0,   LENGTH = 0x20         /* 32 bytes (reserved for ROM code) */
-  RAM1 (rwx)        : ORIGIN = 0x4020000,   LENGTH = 0x10000      /* 64K bytes (alias RAM2) */
-}
-
-/* Define a symbol for the top of each memory region */
-__top_RAM1 = MEM_RAM1_BASE + MEM_RAM1_SIZE; /* 64K bytes */
-
-/* The second RAM bank is dedicated entirely to heap + stack. */
-HEAP_SIZE = MEM_RAM1_SIZE - STACK_SIZE;
-ASSERT(((HEAP_SIZE + STACK_SIZE) == MEM_RAM1_SIZE), "Heap size + stack size should total RAM1 size.");
-
-/* set external flash properties - external flash is present on the DK6 board */
-m_ext_flash_size          = 0x00100000;
-m_ext_flash_base          = 0x00000000;
-m_ext_flash_sector_size   = 4096;
-
-NVMSectorCountLink        = 63;
-
-NV_STORAGE_SIZE           = NVMSectorCountLink * m_ext_flash_sector_size;
-NV_STORAGE_MAX_SECTORS    = NVMSectorCountLink;
-NV_STORAGE_SECTOR_SIZE    = m_ext_flash_sector_size;
-NV_STORAGE_START_ADDRESS  = m_ext_flash_size - 1;
-NV_STORAGE_END_ADDRESS    = NV_STORAGE_START_ADDRESS - NV_STORAGE_SIZE + 1;
-
-INT_STORAGE_START         = m_int_flash_size - 1;
-INT_STORAGE_SIZE          = m_int_flash_size;
-INT_STORAGE_END           = 0x00000000;
-INT_STORAGE_SECTOR_SIZE   = m_int_sector_size;
-
-FACTORY_DATA_START_ADDRESS = m_int_flash_size - m_flash_config_size - m_factory_data_size;
-FACTORY_DATA_END_ADDRESS   = FACTORY_DATA_START_ADDRESS + m_factory_data_size - 1;
-
-__ram_vector_table__      = 1;
-vector_table_size         = 0x120;
-M_VECTOR_RAM_SIZE         = DEFINED(__ram_vector_table__) ? vector_table_size : 0x0;
-
-__base_RAM0               = 0x4000400;
-
-ENTRY(ResetISR)
-
-SECTIONS
-{
-    /* MAIN TEXT SECTION */
-    .header : ALIGN(4)
-    {
-        _flash_start = ABSOLUTE(.);
-        _flash_beg = ABSOLUTE(.);
-
-        FILL(0xff)
-        __vectors_start__ = ABSOLUTE(.) ;
-        __VECTOR_TABLE = .;
-        __Vectors = .;
-        KEEP(*(.isr_vector))
-        /* Global Section Table */
-        . = ALIGN(4) ;
-        __section_table_start = .;
-        __data_section_table = .;
-        LONG(LOADADDR(.data));
-        LONG(    ADDR(.data));
-        LONG(  SIZEOF(.data));
-        __data_section_table_end = .;
-        __bss_section_table = .;
-        LONG(    ADDR(.bss));
-        LONG(  SIZEOF(.bss));
-        __bss_section_table_end = .;
-        __section_table_end = . ;
-        /* End of Global Section Table */
-
-        FILL(0xff)
-        . = ALIGN (0x10);
-    } >Flash640
-
-    .ro_nonce : ALIGN(0x10)
-    {
-        _FlsNonceStart = ABSOLUTE(.);
-        *(.ro_nonce) /* nonce value is 16 bytes.*/
-        FILL(0xff)
-        . = ALIGN (0x10);
-    } > Flash640
-
-    .ro_ota_header : ALIGN(0x10)
-    {
-        _enc_start = ABSOLUTE(.);
-        _enc_offset = (_enc_start & 0x0000000F);
-        _FlsOtaHeader = ABSOLUTE(.);
-        *(.ro_ota_header) /* Ota Header 69 bytes*/
-        FILL(0xff)
-        . = ALIGN (0x10);
-    } > Flash640
-
-    .ro_se_lnkKey (ALIGN((. - _enc_offset), 16) + _enc_offset):
-    {
-        _FlsLinkKey = ABSOLUTE(.);
-        *(.ro_se_lnkKey)  /* Link Key 16 bytes*/
-        FILL(0xff)
-        . = ALIGN (0x10);
-    } > Flash640
-
-    .filler :
-    {
-        BYTE(0xff);
-        FILL(0xff);
-        . = ALIGN(0x40);
-    } > Flash640
-
-    .text : ALIGN(0x40)
-    {
-        FILL(0xff)
-
-       *(.after_vectors*)
-       *(.text*)
-
-        KEEP(*(.init))
-        KEEP(*(.fini))
-
-         /* .ctors */
-        *crtbegin.o(.ctors)
-        *crtbegin?.o(.ctors)
-        *(EXCLUDE_FILE(*crtend?.o *crtend.o) .ctors)
-        *(SORT(.ctors.*))
-        *(.ctors)
-
-        /* .dtors */
-        *crtbegin.o(.dtors)
-        *crtbegin?.o(.dtors)
-        *(EXCLUDE_FILE(*crtend?.o *crtend.o) .dtors)
-        *(SORT(.dtors.*))
-        *(.dtors)
-
-        *(.rodata .rodata.* .constdata .constdata.*)
-
-        . = ALIGN(4);
-    } > Flash640
-    /*
-     * for exception handling/unwind - some Newlib functions (in common
-     * with C++ and STDC++) use this.
-     */
-    .ARM.extab : ALIGN(4)
-    {
-       FILL(0xff)
-        *(.ARM.extab* .gnu.linkonce.armextab.*)
-    } > Flash640
-    __exidx_start = .;
-
-    .ARM.exidx : ALIGN(4)
-    {
-       FILL(0xff)
-        *(.ARM.exidx* .gnu.linkonce.armexidx.*)
-    } > Flash640
-    __exidx_end = .;
-
-    _etext = .;
-
-    .heap (COPY):
-    {
-        __HeapBase = .;
-         _heap = .;
-        KEEP(*(.heap*))
-        PROVIDE(end = .);
-         . = ALIGN(4);
-        __end__ = .;
-         _end_heap = .;
-        __HeapLimit = .;
-    } > RAM1
-
-    .interrupts_ram : ALIGN(0x200)
-    {
-        . = ALIGN(4);
-        __VECTOR_RAM__ = .;
-        __interrupts_ram_start__ = .;   /* Create a global symbol at data start */
-        *(.m_interrupts_ram)            /* This is a user defined section */
-        . += M_VECTOR_RAM_SIZE;
-        . = ALIGN(4);
-        __interrupts_ram_end__ = .;     /* Define a global symbol at data end */
-    } > RAM0
-    .scratch_area (NOLOAD): ALIGN(4)
-    {
-       __scratch_area_start__ = .;
-       . = ALIGN(4) ;
-       . += 0x400;
-       __scratch_area_top__ = .;
-    } > SCRATCH_RAM
-
-    /* MAIN DATA SECTION */
-    .uninit_RESERVED : ALIGN(4)
-    {
-        KEEP(*(.bss.$RESERVED*))
-        . = ALIGN(4) ;
-        _end_uninit_RESERVED = .;
-    } > RAM0
-
-    /* Main DATA section (RAM0) */
-    .data : ALIGN(4)
-    {
-       FILL(0xff)
-       _data = . ;
-       *(vtable)
-       *(.ramfunc*)
-       *(.data*)
-
-        . = ALIGN(4);
-        /* preinit data */
-        PROVIDE_HIDDEN (__preinit_array_start = .);
-        KEEP(*(.preinit_array))
-        PROVIDE_HIDDEN (__preinit_array_end = .);
-
-        . = ALIGN(4);
-        /* init data */
-        __init_array_start = . ;
-        KEEP(*(SORT(.init_array.*)))
-        KEEP(*(.init_array))
-        __init_array_end = . ;
-
-        . = ALIGN(4);
-        /* finit data */
-        PROVIDE_HIDDEN (__fini_array_start = .);
-        KEEP(*(SORT(.fini_array.*)))
-        KEEP(*(.fini_array))
-        PROVIDE_HIDDEN (__fini_array_end = .);
-
-        KEEP(*(.jcr*))
-
-       . = ALIGN(4) ;
-       _edata = . ;
-    } > RAM0 AT>Flash640
-
-    __VECTOR_RAM = __VECTOR_RAM__;
-    __RAM_VECTOR_TABLE_SIZE_BYTES = DEFINED(__ram_vector_table__) ? (__interrupts_ram_end__ - __interrupts_ram_start__) : 0x0;
-
-    /* MAIN BSS SECTION */
-    .bss (NOLOAD) : ALIGN(4)
-    {
-        _bss = .;
-        *(.bss*)
-        *(COMMON)
-        *(g_u32NwkFrameCounter)
-        . = ALIGN(4) ;
-        _ebss = .;
-
-        PROVIDE(end = .);
-    } > RAM0
-
-    /* BSS section for MAC buffers */
-    .bss_MAC (NOLOAD) : ALIGN(4)
-    {
-       /* MAC buffer section: must be within 128kB block. __mac_buffer_base is
-          defined further down to be on 128kB alignment */
-        __mac_buffer_start = .;
-       *(.mac_buffer)
-
-        . = ALIGN (. != 0 ? 4 : 1) ; /* avoid empty segment */
-    } > RAM0
-
-    /* BSS section for unretained contents */
-    .bss_discard (NOLOAD) : ALIGN(4)
-    {
-       *(.discard.bss.pdm)
-
-        . = ALIGN (. != 0 ? 4 : 1) ; /* avoid empty segment */
-    } > RAM0
-
-    /* DEFAULT NOINIT SECTION */
-    .noinit (NOLOAD): ALIGN(4)
-    {
-        _noinit = .;
-        *(.noinit*)
-        . = ALIGN(4) ;
-        _end_noinit = .;
-    } > RAM0
-
-    /* end of firmware RAM to be retained in power down mode */
-    _end_fw_retention = .;
-
-    /* non retained RAM section */
-    /* stack for rom boot during warm resume */
-    .boot_resume_stack (NOLOAD): ALIGN(4)
-    {
-        _boot_resume_stack = .;
-        *(.boot_resume_stack*)
-        . += BOOT_RESUME_STACK_SIZE;
-        . = ALIGN(4) ;
-        _end_boot_resume_stack = .;
-    } > RAM0
-
-    __nv_storage_end_address = NV_STORAGE_END_ADDRESS;
-    __nv_storage_start_address = NV_STORAGE_START_ADDRESS;
-
-    PROVIDE(_vStackTop = __top_RAM1);
-    PROVIDE(__mac_buffer_base = (__mac_buffer_start & 0xfffe0000));
-    PROVIDE(BOOT_GetStartPowerMode = 0x03000e9d);
-    PROVIDE(ROM_GetFlash = 0x03000e0d);
-    PROVIDE(pmc_reset_get_cause = 0x030046e9);
-    PROVIDE(psector_ReadIeee802_15_4_MacId1 = 0x030053b1);
-    PROVIDE(Chip_LOWPOWER_ChipSoftwareReset = 0x03003fa1);
-    PROVIDE(_pvHeapStart = _heap);
-    PROVIDE(_pvHeapLimit = _pvHeapStart + (HEAP_SIZE));
-    PROVIDE(_scratch_buf_start = __scratch_area_start__);
-    PROVIDE(_scratch_buf_end = __scratch_area_top__);
-
-    __StackLimit = _vStackTop - STACK_SIZE;
-    ASSERT(__StackLimit >= _end_heap, "Stack and heap spaces are overlapping!")
-
-    __MATTER_FACTORY_DATA_START = FACTORY_DATA_START_ADDRESS;
-    __MATTER_FACTORY_DATA_SIZE = m_factory_data_size;
-
-    /* The .ro_version section inside SSBL is set after the .m_interrupts sections,
-     * which is assumed to never change, so the offset remains the same across different
-     * SSBL versions. This symbol is used in Matter Application to retrieve the SSBL version. */
-    __MATTER_SSBL_VERSION_START = 0x00000120;
-     
-    ASSERT(((m_app_start + m_app_size + m_app_meta_data + m_factory_data_size + m_flash_config_size) <= m_int_flash_size),
-            "Internal flash capacity exceeded")
-
-}
diff --git a/examples/platform/nxp/k32w/k32w0/app/project_include/OpenThreadConfig.h b/examples/platform/nxp/k32w/k32w0/app/project_include/OpenThreadConfig.h
deleted file mode 100644
index d76a51a6fbb55b..00000000000000
--- a/examples/platform/nxp/k32w/k32w0/app/project_include/OpenThreadConfig.h
+++ /dev/null
@@ -1,116 +0,0 @@
-/*
- *
- *    Copyright (c) 2020 Google LLC.
- *    All rights reserved.
- *
- *    Licensed under the Apache License, Version 2.0 (the "License");
- *    you may not use this file except in compliance with the License.
- *    You may obtain a copy of the License at
- *
- *        http://www.apache.org/licenses/LICENSE-2.0
- *
- *    Unless required by applicable law or agreed to in writing, software
- *    distributed under the License is distributed on an "AS IS" BASIS,
- *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *    See the License for the specific language governing permissions and
- *    limitations under the License.
- */
-
-/**
- *    @file
- *      Overrides to default OpenThread configuration.
- *
- */
-
-#include "openthread-core-k32w061-config.h"
-
-#pragma once
-
-// Disable the Nxp-supplied OpenThread logging facilities
-// and use the facilities provided by the Device Layer
-// (see src/platform/K32W/Logging.cpp).
-#undef OPENTHREAD_CONFIG_LOG_OUTPUT
-#define OPENTHREAD_CONFIG_LOG_OUTPUT OPENTHREAD_CONFIG_LOG_OUTPUT_APP
-
-// When operating in a less than ideal RF environment, having a more forgiving configuration
-// of OpenThread makes thread a great deal more reliable.
-#undef OPENTHREAD_CONFIG_TMF_ADDRESS_QUERY_MAX_RETRY_DELAY
-#define OPENTHREAD_CONFIG_TMF_ADDRESS_QUERY_MAX_RETRY_DELAY 120 // default is 28800
-
-#undef OPENTHREAD_CONFIG_MAC_DEFAULT_MAX_FRAME_RETRIES_DIRECT
-#define OPENTHREAD_CONFIG_MAC_DEFAULT_MAX_FRAME_RETRIES_DIRECT 15 // default is 3
-
-#undef OPENTHREAD_CONFIG_MAC_DEFAULT_MAX_FRAME_RETRIES_INDIRECT
-#define OPENTHREAD_CONFIG_MAC_DEFAULT_MAX_FRAME_RETRIES_INDIRECT 1 // default is 0
-
-#undef OPENTHREAD_CONFIG_MAC_MAX_TX_ATTEMPTS_INDIRECT_POLLS
-#define OPENTHREAD_CONFIG_MAC_MAX_TX_ATTEMPTS_INDIRECT_POLLS 16 // default is 4
-
-// Enable periodic parent search to speed up finding a better parent.
-#undef OPENTHREAD_CONFIG_PARENT_SEARCH_ENABLE
-#define OPENTHREAD_CONFIG_PARENT_SEARCH_ENABLE 1 // default is 0
-
-#undef OPENTHREAD_CONFIG_PARENT_SEARCH_RSS_THRESHOLD
-#define OPENTHREAD_CONFIG_PARENT_SEARCH_RSS_THRESHOLD -45 // default is -65
-
-#undef OPENTHREAD_CONFIG_MLE_INFORM_PREVIOUS_PARENT_ON_REATTACH
-#define OPENTHREAD_CONFIG_MLE_INFORM_PREVIOUS_PARENT_ON_REATTACH 1 // default is 0
-
-// Use smaller maximum interval to speed up reattaching.
-#undef OPENTHREAD_CONFIG_MLE_ATTACH_BACKOFF_MAXIMUM_INTERVAL
-#define OPENTHREAD_CONFIG_MLE_ATTACH_BACKOFF_MAXIMUM_INTERVAL (60 * 10 * 1000) // default 1200000 ms
-
-// disable unused features
-#undef OPENTHREAD_CONFIG_COAP_API_ENABLE
-#define OPENTHREAD_CONFIG_COAP_API_ENABLE 0
-
-#undef OPENTHREAD_CONFIG_JOINER_ENABLE
-#define OPENTHREAD_CONFIG_JOINER_ENABLE 0
-
-#undef OPENTHREAD_CONFIG_COMMISSIONER_ENABLE
-#define OPENTHREAD_CONFIG_COMMISSIONER_ENABLE 0
-
-#undef OPENTHREAD_CONFIG_UDP_FORWARD_ENABLE
-#define OPENTHREAD_CONFIG_UDP_FORWARD_ENABLE 0
-
-#undef OPENTHREAD_CONFIG_BORDER_ROUTER_ENABLE
-#define OPENTHREAD_CONFIG_BORDER_ROUTER_ENABLE 0
-
-#undef OPENTHREAD_CONFIG_DHCP6_CLIENT_ENABLE
-#define OPENTHREAD_CONFIG_DHCP6_CLIENT_ENABLE 0
-
-#undef OPENTHREAD_CONFIG_DHCP6_SERVER_ENABLE
-#define OPENTHREAD_CONFIG_DHCP6_SERVER_ENABLE 0
-
-#undef OPENTHREAD_CONFIG_TCP_ENABLE
-#define OPENTHREAD_CONFIG_TCP_ENABLE 0
-
-#undef OPENTHREAD_CONFIG_MLE_LINK_METRICS_SUBJECT_ENABLE
-#define OPENTHREAD_CONFIG_MLE_LINK_METRICS_SUBJECT_ENABLE 0
-
-#undef OPENTHREAD_CONFIG_MLE_LINK_METRICS_INITIATOR_ENABLE
-#define OPENTHREAD_CONFIG_MLE_LINK_METRICS_INITIATOR_ENABLE 0
-
-#undef OPENTHREAD_CONFIG_NUM_MESSAGE_BUFFERS
-#define OPENTHREAD_CONFIG_NUM_MESSAGE_BUFFERS 44
-
-#undef OPENTHREAD_CONFIG_DNSSD_SERVER_ENABLE
-#define OPENTHREAD_CONFIG_DNSSD_SERVER_ENABLE 0
-
-#undef OPENTHREAD_CONFIG_SRP_SERVER_ENABLE
-#define OPENTHREAD_CONFIG_SRP_SERVER_ENABLE 0
-
-#undef OPENTHREAD_CONFIG_TMF_NETDATA_SERVICE_ENABLE
-#define OPENTHREAD_CONFIG_TMF_NETDATA_SERVICE_ENABLE 0
-
-#define UART_USE_SERIAL_MGR 1
-#define UART_USE_SERIAL_MGR_LOG 1
-
-// #define OPENTHREAD_CONFIG_LOG_LEVEL                            OT_LOG_LEVEL_DEBG
-
-// Use the NXP-supplied default platform configuration for remainder
-// of OpenThread config options.
-//
-// NB: This file gets included during the build of OpenThread.  Hence
-// it cannot use "openthread" in the path to the included file.
-//
diff --git a/examples/platform/nxp/k32w/k32w0/app/support/BUILD.gn b/examples/platform/nxp/k32w/k32w0/app/support/BUILD.gn
deleted file mode 100644
index 7b10c468a02fe6..00000000000000
--- a/examples/platform/nxp/k32w/k32w0/app/support/BUILD.gn
+++ /dev/null
@@ -1,52 +0,0 @@
-# Copyright (c) 2020 Project CHIP Authors
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-import("//build_overrides/chip.gni")
-import("//build_overrides/nxp_sdk.gni")
-
-config("support_config") {
-  include_dirs = [ "../../../../.." ]
-
-  # Link options that provides replace dynamic memory operations in standard
-  # library with the FreeRTOS malloc in platform code.
-  ldflags = [
-    # memory allocation -- these must be re-entrant and do locking
-    "-Wl,--wrap=malloc",
-    "-Wl,--wrap=free",
-    "-Wl,--wrap=realloc",
-    "-Wl,--wrap=calloc",
-    "-Wl,--wrap=MemoryAlloc",
-
-    # Wrap these in case internal newlib call them (e.g. strdup will)
-    # directly call _malloc_r)
-    "-Wl,--wrap=_malloc_r",
-    "-Wl,--wrap=_realloc_r",
-    "-Wl,--wrap=_free_r",
-    "-Wl,--wrap=_calloc_r",
-  ]
-}
-
-source_set("freertos_mbedtls_utils") {
-  sources = [
-    "FreeRtosHooks.c",
-    "FreeRtosHooks.h",
-    "Memconfig.cpp",
-  ]
-
-  deps = [ "${chip_root}/src/lib/support" ]
-
-  cflags = [ "-Wconversion" ]
-
-  public_configs = [ ":support_config" ]
-}
diff --git a/examples/platform/nxp/k32w/k32w0/app/support/FreeRtosHooks.c b/examples/platform/nxp/k32w/k32w0/app/support/FreeRtosHooks.c
deleted file mode 100644
index 59cae3f6d14cf9..00000000000000
--- a/examples/platform/nxp/k32w/k32w0/app/support/FreeRtosHooks.c
+++ /dev/null
@@ -1,274 +0,0 @@
-/*
- *
- *    Copyright (c) 2020 Google LLC.
- *    All rights reserved.
- *
- *    Licensed under the Apache License, Version 2.0 (the "License");
- *    you may not use this file except in compliance with the License.
- *    You may obtain a copy of the License at
- *
- *        http://www.apache.org/licenses/LICENSE-2.0
- *
- *    Unless required by applicable law or agreed to in writing, software
- *    distributed under the License is distributed on an "AS IS" BASIS,
- *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *    See the License for the specific language governing permissions and
- *    limitations under the License.
- *
- */
-
-#include "FreeRtosHooks.h"
-
-#include "FreeRTOS.h"
-#include "semphr.h"
-
-#include <assert.h>
-
-#include <stdio.h>
-#include <string.h>
-
-#include "PDM.h"
-#include "PWR_Interface.h"
-#include "TimersManager.h"
-#include "board.h"
-#include "pdm_ram_storage_glue.h"
-
-/* Bluetooth Low Energy */
-#include "ble_config.h"
-#include "l2ca_cb_interface.h"
-
-#include "controller_interface.h"
-
-#if defined gLoggingActive_d && (gLoggingActive_d > 0)
-#include "dbg_logging.h"
-#ifndef DBG_APP
-#define DBG_APP 0
-#endif
-#define APP_DBG_LOG(fmt, ...)                                                                                                      \
-    if (DBG_APP)                                                                                                                   \
-        do                                                                                                                         \
-        {                                                                                                                          \
-            DbgLogAdd(__FUNCTION__, fmt, VA_NUM_ARGS(__VA_ARGS__), ##__VA_ARGS__);                                                 \
-        } while (0);
-#else
-#define APP_DBG_LOG(...)
-#endif
-
-#if (configUSE_TICKLESS_IDLE != 0)
-#define DBG_PostStepTickAssess 0
-#if DBG_PostStepTickAssess && !gTimestampUseWtimer_c
-#error "gTimestampUseWtimer_c required for DBG_PostStepTickAssess"
-#endif
-#if defined(gPWR_FreqScalingWFI) && (gPWR_FreqScalingWFI != 0)
-/* this MACRO is required when gPWR_FreqScalingWFI is not equal to zero (system clock frequency
-    reduced in WFI)           */
-#define App_SuppressTickInStopMode 1
-#else
-#define App_SuppressTickInStopMode 0
-#endif
-#if gPWR_CpuClk_48MHz
-/* for systick accuracy, this is recommended to enable FRO calibration */
-#define gApp_SystemClockCalibration 1
-#endif
-#endif
-
-#define PDM_MAX_WRITES_INFINITE 0xFF
-
-static inline void mutex_init(mbedtls_threading_mutex_t * p_mutex)
-{
-    assert(p_mutex != NULL);
-    *p_mutex = xSemaphoreCreateMutex();
-    assert(*p_mutex != NULL);
-}
-
-static inline void mutex_free(mbedtls_threading_mutex_t * p_mutex)
-{
-    assert(p_mutex != NULL);
-    assert(*p_mutex != NULL);
-    vSemaphoreDelete(*p_mutex);
-}
-
-static inline int mutex_lock(mbedtls_threading_mutex_t * p_mutex)
-{
-    assert(p_mutex != NULL);
-    assert(*p_mutex != NULL);
-    return xSemaphoreTake(*p_mutex, portMAX_DELAY) != pdTRUE;
-}
-
-static inline int mutex_unlock(mbedtls_threading_mutex_t * p_mutex)
-{
-    assert(p_mutex != NULL);
-    assert(*p_mutex != NULL);
-    return xSemaphoreGive(*p_mutex) != pdTRUE;
-}
-
-void freertos_mbedtls_mutex_init(void)
-{
-    mbedtls_threading_set_alt(mutex_init, mutex_free, mutex_lock, mutex_unlock);
-}
-
-void freertos_mbedtls_mutex_free(void)
-{
-    mbedtls_threading_free_alt();
-}
-
-#if (configUSE_TICKLESS_IDLE != 0)
-
-/*
- * Setup the systick timer to generate the tick interrupts at the required
- * frequency.
- */
-void vPortSetupTimerInterrupt(void)
-{
-    /* Stop and clear the SysTick. */
-    SysTick->CTRL = 0UL;
-    SysTick->VAL  = 0UL;
-
-#if DBG_PostStepTickAssess
-    tickless_SystickCheckDriftInit();
-#endif
-
-    /* configure module for tickless mode */
-    tickless_init();
-
-#if gApp_SystemClockCalibration
-    /* calibration on the internal FRO48MHz clock - this clock is inaccurate (2%),
-     * so it needs calibration if we want the systick to be accurate to less
-     * than 500pp. */
-    tickless_StartFroCalibration();
-#endif
-
-    /* Configure SysTick to interrupt at the requested rate. */
-    SysTick_Config(CLOCK_GetFreq(kCLOCK_CoreSysClk) / configTICK_RATE_HZ);
-}
-
-void vPortSuppressTicksAndSleep(TickType_t xExpectedIdleTime)
-{
-    tmrlp_tickless_systick_t lp_ctx;
-    APP_DBG_LOG("xExpectedIdleTime = %d ticks %d ms", xExpectedIdleTime, xExpectedIdleTime * portTICK_PERIOD_MS);
-    OSA_InterruptDisable();
-
-    /* Do not go to sleep, lowpower or WFI if there is a pending task to schedule
-     * Scheduler is suspended when calling vPortSuppressTicksAndSleep,
-     * as interrupt are disabled if one is pending, eTaskConfirmSleepModeStatus
-     * will prevent sleep.
-     */
-    if (eTaskConfirmSleepModeStatus() == eAbortSleep)
-    {
-        APP_DBG_LOG("task to schedule");
-        /* Do nothing */
-    }
-#if gApp_SystemClockCalibration
-    /* Prevent lowpower / tickless mode if cal ongoing - get estimated core freq */
-    else if (tickless_EstimateCoreClockFreq())
-    {
-        /* can eventually enter sleep or re evaluate on next idle loop, the calibration shall take 4 ms average */
-        // PWR_EnterSleep();
-    }
-#endif
-
-    /* Do not go to power down if:
-     * - the RTOS is expecting a wake-up too close to the current date
-     * To worth a power down the xExpectedIdleTime should be
-     * > to 2 rtos tick (which includes residual_count worst margin + carry after wake-up worst margin)
-     * + enter/exist power down duration converted in RTOS tick
-     * - power down is not allowed
-     */
-    else if ((xExpectedIdleTime >
-              (2 + ((PWR_SYSTEM_EXIT_LOW_POWER_DURATION_MS + PWR_SYSTEM_ENTER_LOW_POWER_DURATION_MS) / portTICK_PERIOD_MS) + 1)))
-    {
-        int result = PWR_CheckIfDeviceCanGoToSleepExt();
-        if (result >= kPmPowerDown0)
-        {
-            PWR_WakeupReason_t wakeupReason;
-            lp_ctx.exitTicklessDuration32kTick = MILLISECONDS_TO_TICKS32K(PWR_SYSTEM_EXIT_LOW_POWER_DURATION_MS);
-            /* Tickless pre processing */
-            tickless_PreProcessing(&lp_ctx, xExpectedIdleTime);
-
-            /* Enter power down */
-            wakeupReason = PWR_EnterPowerDown();
-
-            APP_DBG_LOG("wakeReason=%x", (uint16_t) wakeupReason.AllBits);
-            (void) wakeupReason;
-
-            /* Tickless post processing */
-            tickless_PostProcessing(&lp_ctx);
-
-#if DBG_PostStepTickAssess
-            if (wakeupReason.Bits.FromTMR == 1)
-                configASSERT(lp_ctx.idle_tick_jump == xExpectedIdleTime);
-            if (wakeupReason.Bits.DidPowerDown == 1)
-                configASSERT((wakeupReason.AllBits & ~0x8000U) != 0);
-#endif
-        }
-        else if ((result == kPmSleep) || (result < 0))
-        {
-#if App_SuppressTickInStopMode
-            lp_ctx.exitTicklessDuration32kTick = 0;
-            /* Tickless pre processing */
-            tickless_PreProcessing(&lp_ctx, xExpectedIdleTime);
-#endif
-
-            PWR_EnterSleep();
-
-#if App_SuppressTickInStopMode
-            /* Tickless post processing */
-            tickless_PostProcessing(&lp_ctx);
-#endif
-        }
-    }
-    else
-    {
-#if App_SuppressTickInStopMode
-        lp_ctx.exitTicklessDuration32kTick = 0;
-        /* Tickless pre processing */
-        tickless_PreProcessing(&lp_ctx, xExpectedIdleTime);
-#endif
-
-        PWR_EnterSleep();
-
-#if App_SuppressTickInStopMode
-        /* Tickless post processing */
-        tickless_PostProcessing(&lp_ctx);
-#endif
-    }
-
-#if DBG_PostStepTickAssess
-    tickless_SystickCheckDrift();
-#endif
-
-    OSA_InterruptEnable();
-}
-#endif /* (configUSE_TICKLESS_IDLE != 0) */
-
-static void BOARD_ActionOnIdle(void)
-{
-#if ((defined gTcxo32k_ModeEn_c) && (gTcxo32k_ModeEn_c != 0))
-    BOARD_tcxo32k_compensation_run(2, 0);
-#endif
-#if ((defined gTcxo32M_ModeEn_c) && (gTcxo32M_ModeEn_c != 0))
-    BOARD_tcxo32M_compensation_run(2, 10); /* 2 degrees - wait for 10us */
-#endif
-}
-
-extern void OTAIdleActivities(void);
-extern bool AppHaveBLEConnections(void);
-
-void vApplicationIdleHook(void)
-{
-#if PDM_SAVE_IDLE
-    /* While in BLE connection during commissioning, PDM saves should be paused */
-    if (!AppHaveBLEConnections())
-    {
-        FS_vIdleTask(PDM_MAX_WRITES_INFINITE);
-    }
-#endif
-
-    OTAIdleActivities();
-
-#if gAdcUsed_d
-    BOARD_ADCMeasure();
-#endif
-
-    BOARD_ActionOnIdle();
-}
diff --git a/examples/platform/nxp/k32w/k32w0/app/support/FreeRtosHooks.h b/examples/platform/nxp/k32w/k32w0/app/support/FreeRtosHooks.h
deleted file mode 100644
index a27f72d498f81d..00000000000000
--- a/examples/platform/nxp/k32w/k32w0/app/support/FreeRtosHooks.h
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- *
- *    Copyright (c) 2020 Nest Labs, Inc.
- *    All rights reserved.
- *
- *    Licensed under the Apache License, Version 2.0 (the "License");
- *    you may not use this file except in compliance with the License.
- *    You may obtain a copy of the License at
- *
- *        http://www.apache.org/licenses/LICENSE-2.0
- *
- *    Unless required by applicable law or agreed to in writing, software
- *    distributed under the License is distributed on an "AS IS" BASIS,
- *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *    See the License for the specific language governing permissions and
- *    limitations under the License.
- */
-
-#pragma once
-
-typedef void * mbedtls_threading_mutex_t;
-
-extern void mbedtls_threading_set_alt(void (*mutex_init)(mbedtls_threading_mutex_t *),
-                                      void (*mutex_free)(mbedtls_threading_mutex_t *),
-                                      int (*mutex_lock)(mbedtls_threading_mutex_t *),
-                                      int (*mutex_unlock)(mbedtls_threading_mutex_t *));
-
-extern void mbedtls_threading_free_alt(void);
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/**@brief Function for initializing alternative MbedTLS mutexes to enable the usage of the FreeRTOS implementation. */
-void freertos_mbedtls_mutex_init(void);
-
-/**@brief Function for releasing MbedTLS alternative mutexes. */
-void freertos_mbedtls_mutex_free(void);
-
-#ifdef __cplusplus
-}
-#endif
diff --git a/examples/platform/nxp/k32w/k32w0/app/support/Memconfig.cpp b/examples/platform/nxp/k32w/k32w0/app/support/Memconfig.cpp
deleted file mode 100644
index e5acf5ea3ceecb..00000000000000
--- a/examples/platform/nxp/k32w/k32w0/app/support/Memconfig.cpp
+++ /dev/null
@@ -1,184 +0,0 @@
-/*
- *
- *    Copyright (c) 2020-2021 Project CHIP Authors
- *    All rights reserved.
- *
- *    Licensed under the Apache License, Version 2.0 (the "License");
- *    you may not use this file except in compliance with the License.
- *    You may obtain a copy of the License at
- *
- *        http://www.apache.org/licenses/LICENSE-2.0
- *
- *    Unless required by applicable law or agreed to in writing, software
- *    distributed under the License is distributed on an "AS IS" BASIS,
- *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *    See the License for the specific language governing permissions and
- *    limitations under the License.
- */
-
-/**
- *    @file
- *      This file contains platform specific implementations for stdlib malloc/calloc/realloc/free
- *      functions, so that CHIPPlatformMemory* works as intended with the platform's heap.
- */
-
-#include "FreeRTOS.h"
-#include "task.h"
-#include <cstring>
-#include <stdint.h>
-#include <stdlib.h>
-
-#ifndef NDEBUG
-#include <atomic>
-#include <cstdio>
-#endif
-
-#include <src/lib/support/logging/CHIPLogging.h>
-
-#if CHIP_CONFIG_MEMORY_DEBUG_DMALLOC
-#include <dmalloc.h>
-#include <lib/support/SafeInt.h>
-#endif // CHIP_CONFIG_MEMORY_DEBUG_DMALLOC
-
-/* Assumes 8bit bytes! */
-#define heapBITS_PER_BYTE ((size_t) 8)
-
-/* Define the linked list structure.  This is used to link free blocks in order
-of their memory address. */
-typedef struct A_BLOCK_LINK
-{
-    struct A_BLOCK_LINK * pxNextFreeBlock; /*<< The next free block in the list. */
-    size_t xBlockSize;                     /*<< The size of the free block. */
-} BlockLink_t;
-
-/* The size of the structure placed at the beginning of each allocated memory
-block must by correctly byte aligned. */
-static const size_t xHeapStructSize =
-    (sizeof(BlockLink_t) + ((size_t) (portBYTE_ALIGNMENT - 1))) & ~((size_t) portBYTE_ALIGNMENT_MASK);
-
-/* Gets set to the top bit of an size_t type.  When this bit in the xBlockSize
-member of an BlockLink_t structure is set then the block belongs to the
-application.  When the bit is free the block is still part of the free heap
-space. */
-static size_t xBlockAllocatedBit = ((size_t) 1) << ((sizeof(size_t) * heapBITS_PER_BYTE) - 1);
-
-extern "C" {
-
-/* xPortMallocUsableSize relies on heap4 implementation.
-It returns the size of an allocated block and it is
-called by __wrap_realloc.
-Thus it is validated in __wrap_realloc function that the allocated size
-of the old_ptr is smaller than the allocated size of new_ptr */
-size_t xPortMallocUsableSize(void * pv)
-{
-    uint8_t * puc = (uint8_t *) pv;
-    BlockLink_t * pxLink;
-    void * voidp;
-    size_t sz = 0;
-
-    if (pv != NULL)
-    {
-        vTaskSuspendAll();
-        {
-            /* The memory being checked will have an BlockLink_t structure immediately
-            before it. */
-            puc -= xHeapStructSize;
-
-            /* This casting is to keep the compiler from issuing warnings. */
-            voidp  = (void *) puc;
-            pxLink = (BlockLink_t *) voidp;
-
-            /* Check if the block is actually allocated. */
-            configASSERT((pxLink->xBlockSize & xBlockAllocatedBit) != 0);
-            configASSERT(pxLink->pxNextFreeBlock == NULL);
-
-            sz = (pxLink->xBlockSize & ~xBlockAllocatedBit) - xHeapStructSize;
-        }
-        (void) xTaskResumeAll();
-    }
-
-    return sz;
-}
-
-void * __wrap_malloc(size_t size)
-{
-    return pvPortMalloc(size);
-}
-
-void __wrap_free(void * ptr)
-{
-    vPortFree(ptr);
-}
-
-void * __wrap_calloc(size_t num, size_t size)
-{
-    size_t total_size = num * size;
-
-    // Handle overflow from (num * size)
-    if ((size != 0) && ((total_size / size) != num))
-    {
-        return nullptr;
-    }
-
-    void * ptr = pvPortMalloc(total_size);
-    if (ptr)
-    {
-        memset(ptr, 0, total_size);
-    }
-    else
-    {
-        ChipLogError(DeviceLayer, "__wrap_calloc: Could not allocate memory!");
-    }
-
-    return ptr;
-}
-
-void * __wrap_realloc(void * ptr, size_t new_size)
-{
-
-    void * new_ptr = NULL;
-
-    if (new_size)
-    {
-        size_t old_ptr_size = xPortMallocUsableSize(ptr);
-        if (new_size <= old_ptr_size)
-        {
-            /* Return old pointer if the newly allocated size is smaller
-                    or equal to the allocated size for old_ptr */
-            return ptr;
-        }
-
-        /* if old_ptr is NULL, then old_ptr_size is zero and new_ptr will be returned */
-        new_ptr = pvPortMalloc(new_size);
-
-        if (!new_ptr)
-        {
-            ChipLogError(DeviceLayer, "__wrap_realloc: Could not allocate memory!");
-            return NULL;
-        }
-
-        memset(reinterpret_cast<uint8_t *>(new_ptr) + old_ptr_size, 0, (new_size - old_ptr_size));
-        memcpy(new_ptr, ptr, old_ptr_size);
-    }
-
-    vPortFree(ptr);
-
-    return new_ptr;
-}
-
-void * __wrap__malloc_r(void * REENT, size_t size)
-{
-    return __wrap_malloc(size);
-}
-
-void __wrap__free_r(void * REENT, void * ptr)
-{
-    __wrap_free(ptr);
-}
-
-void * __wrap__realloc_r(void * REENT, void * ptr, size_t new_size)
-{
-    return __wrap_realloc(ptr, new_size);
-}
-
-} // extern "C"
diff --git a/examples/platform/nxp/k32w/k32w0/args.gni b/examples/platform/nxp/k32w/k32w0/args.gni
deleted file mode 100644
index 5af5e1d18b3123..00000000000000
--- a/examples/platform/nxp/k32w/k32w0/args.gni
+++ /dev/null
@@ -1,32 +0,0 @@
-# Copyright (c) 2020 Project CHIP Authors
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-import("//build_overrides/chip.gni")
-
-import("${chip_root}/src/platform/nxp/k32w/k32w0/args.gni")
-
-openthread_core_config_deps = []
-openthread_core_config_deps = [ "${chip_root}/examples/platform/nxp/k32w/k32w0:openthread_core_config_k32w0_chip_examples" ]
-
-chip_ble_project_config_include = "<CHIPProjectConfig.h>"
-chip_device_project_config_include = "<CHIPProjectConfig.h>"
-chip_project_config_include = "<CHIPProjectConfig.h>"
-chip_inet_project_config_include = "<CHIPProjectConfig.h>"
-chip_system_project_config_include = "<CHIPProjectConfig.h>"
-
-chip_system_config_provide_statistics = false
-chip_with_nlfaultinjection = true
-
-chip_system_config_use_open_thread_inet_endpoints = true
-chip_with_lwip = false
diff --git a/examples/platform/nxp/k32w/k32w0/common/CustomFactoryDataProvider.cpp b/examples/platform/nxp/k32w/k32w0/common/CustomFactoryDataProvider.cpp
deleted file mode 100644
index 7f2f6d9bc0cad0..00000000000000
--- a/examples/platform/nxp/k32w/k32w0/common/CustomFactoryDataProvider.cpp
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- *
- *    Copyright (c) 2022 Project CHIP Authors
- *
- *    Licensed under the Apache License, Version 2.0 (the "License");
- *    you may not use this file except in compliance with the License.
- *    You may obtain a copy of the License at
- *
- *        http://www.apache.org/licenses/LICENSE-2.0
- *
- *    Unless required by applicable law or agreed to in writing, software
- *    distributed under the License is distributed on an "AS IS" BASIS,
- *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *    See the License for the specific language governing permissions and
- *    limitations under the License.
- */
-
-#include "CustomFactoryDataProvider.h"
-
-namespace chip {
-namespace DeviceLayer {
-
-static constexpr size_t kMaxLengthCustomId1 = 10;
-static constexpr size_t kMaxLengthCustomId2 = 50;
-static constexpr size_t kMaxLengthCustomId3 = 100;
-
-CustomFactoryDataProvider::CustomFactoryDataProvider()
-{
-    // Custom ids should be from a range that does not overlap with the standard factory data range.
-    static_assert((uint16_t) CustomFactoryIds::kCustomId1 >= (uint16_t) FactoryDataProvider::FactoryDataId::kMaxId);
-}
-
-CHIP_ERROR CustomFactoryDataProvider::ParseFunctionExample()
-{
-    uint8_t data_buf[kMaxLengthCustomId1];
-    MutableByteSpan buffer(data_buf);
-    memset(buffer.data(), 0, buffer.size());
-    uint16_t userDataSize = 0;
-    // A user can use FactoryDataProvider::SearchForId to read an id from internal
-    // flash factory data section.
-    auto * provider = static_cast<FactoryDataProvider *>(DeviceLayer::GetDeviceInstanceInfoProvider());
-    ReturnErrorOnFailure((provider != nullptr) ? CHIP_NO_ERROR : CHIP_ERROR_INVALID_ADDRESS);
-    ReturnErrorOnFailure(provider->SearchForId(CustomFactoryIds::kCustomId1, buffer.data(), buffer.size(), userDataSize));
-
-    // Data should now be ready for custom parsing.
-
-    return CHIP_NO_ERROR;
-}
-
-} // namespace DeviceLayer
-} // namespace chip
diff --git a/examples/platform/nxp/k32w/k32w0/common/CustomFactoryDataProvider.h b/examples/platform/nxp/k32w/k32w0/common/CustomFactoryDataProvider.h
deleted file mode 100644
index dfb722d67fdc11..00000000000000
--- a/examples/platform/nxp/k32w/k32w0/common/CustomFactoryDataProvider.h
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- *
- *    Copyright (c) 2022 Project CHIP Authors
- *
- *    Licensed under the Apache License, Version 2.0 (the "License");
- *    you may not use this file except in compliance with the License.
- *    You may obtain a copy of the License at
- *
- *        http://www.apache.org/licenses/LICENSE-2.0
- *
- *    Unless required by applicable law or agreed to in writing, software
- *    distributed under the License is distributed on an "AS IS" BASIS,
- *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *    See the License for the specific language governing permissions and
- *    limitations under the License.
- */
-#pragma once
-
-#include <platform/nxp/k32w/k32w0/FactoryDataProviderImpl.h>
-
-namespace chip {
-namespace DeviceLayer {
-
-/**
- * @brief This is an example class that extends the platform factory data provider
- *        to support custom functionality. Users should implement their own custom
- *        provider based on this example.
- */
-
-class CustomFactoryDataProvider
-{
-public:
-    /* Custom IDs should start from at least FactoryDataId::kMaxId, which is
-     * the next available valid ID. Last default ID is kMaxId - 1.
-     */
-    enum CustomFactoryIds
-    {
-        kCustomId1 = 200, // Random id that is greater than FactoryDataId::kMaxId.
-        kCustomId2,
-        kCustomId3,
-        kCustomMaxId
-    };
-
-    CustomFactoryDataProvider();
-
-    /* Declare here custom functions to be implemented. */
-    CHIP_ERROR ParseFunctionExample();
-};
-
-} // namespace DeviceLayer
-} // namespace chip
diff --git a/examples/platform/nxp/k32w/k32w0/doc/images/ssbl_bin.JPG b/examples/platform/nxp/k32w/k32w0/doc/images/ssbl_bin.JPG
deleted file mode 100644
index fb871d45aeb5f9..00000000000000
Binary files a/examples/platform/nxp/k32w/k32w0/doc/images/ssbl_bin.JPG and /dev/null differ
diff --git a/examples/platform/nxp/k32w/k32w0/doc/images/ssbl_multi_image.JPG b/examples/platform/nxp/k32w/k32w0/doc/images/ssbl_multi_image.JPG
deleted file mode 100644
index 31449b25cf269e..00000000000000
Binary files a/examples/platform/nxp/k32w/k32w0/doc/images/ssbl_multi_image.JPG and /dev/null differ
diff --git a/examples/platform/nxp/k32w/k32w0/doc/images/ssbl_select.JPG b/examples/platform/nxp/k32w/k32w0/doc/images/ssbl_select.JPG
deleted file mode 100644
index 79ea51b62698e8..00000000000000
Binary files a/examples/platform/nxp/k32w/k32w0/doc/images/ssbl_select.JPG and /dev/null differ
diff --git a/examples/platform/nxp/k32w/k32w0/doc/images/ssbl_simple_hash.JPG b/examples/platform/nxp/k32w/k32w0/doc/images/ssbl_simple_hash.JPG
deleted file mode 100755
index 9ec701b0bb1d86..00000000000000
Binary files a/examples/platform/nxp/k32w/k32w0/doc/images/ssbl_simple_hash.JPG and /dev/null differ
diff --git a/examples/platform/nxp/k32w/k32w0/scripts/demo_generated_factory_data/demo_factory_data_dut1.bin b/examples/platform/nxp/k32w/k32w0/scripts/demo_generated_factory_data/demo_factory_data_dut1.bin
deleted file mode 100644
index 44370e1deb3a2f..00000000000000
Binary files a/examples/platform/nxp/k32w/k32w0/scripts/demo_generated_factory_data/demo_factory_data_dut1.bin and /dev/null differ
diff --git a/examples/platform/nxp/k32w/k32w0/scripts/demo_generated_factory_data/demo_factory_data_dut2.bin b/examples/platform/nxp/k32w/k32w0/scripts/demo_generated_factory_data/demo_factory_data_dut2.bin
deleted file mode 100644
index f47a8b4c53a908..00000000000000
Binary files a/examples/platform/nxp/k32w/k32w0/scripts/demo_generated_factory_data/demo_factory_data_dut2.bin and /dev/null differ
diff --git a/examples/platform/nxp/k32w/k32w0/scripts/detokenizer.py b/examples/platform/nxp/k32w/k32w0/scripts/detokenizer.py
deleted file mode 100644
index 6f76903e97f8a5..00000000000000
--- a/examples/platform/nxp/k32w/k32w0/scripts/detokenizer.py
+++ /dev/null
@@ -1,148 +0,0 @@
-import argparse
-import os
-import sys
-
-import pw_tokenizer
-import serial
-
-
-def parse_args():
-    """Parse input arguments
-
-    Return:
-        parsed arguments struncture
-    """
-
-    parser = argparse.ArgumentParser()
-    subparsers = parser.add_subparsers(dest='type')
-    subparsers.required = True
-
-    parser_file = subparsers.add_parser('file')
-    parser_file.add_argument(
-        "-i", "--input", help="Input file name.", required=True)
-    parser_file.add_argument(
-        "-d", "--database", help="Token database.", required=True)
-    parser_file.add_argument(
-        "-o", "--output", help="Output file name.", required=True)
-
-    parser_file = subparsers.add_parser('serial')
-    parser_file.add_argument(
-        "-i", "--input", help="Input serial port name.", required=True)
-    parser_file.add_argument(
-        "-d", "--database", help="Token database.", required=True)
-    parser_file.add_argument(
-        "-o", "--output", help="Output file name. Write to stdout and to file.")
-
-    return parser.parse_args()
-
-
-def decode_string(tstr, detok):
-    """Decodes a single token.
-
-    Args:
-        tstr        - encoded input string
-        detok       - detokenizer
-
-    Return:
-        decoded string or None
-    """
-    try:
-        t = bytes.fromhex(tstr)
-        s = str(detok.detokenize(t))
-
-        if s.find('$') == 0:
-            return None
-        return s
-    except ValueError:
-        return None
-
-
-def decode_serial(serialport, outfile, database):
-    """Decodes logs from serial port.
-
-    Args:
-        infile      - path to input file
-        outfile     - path to output file
-        database    - path to token database
-    """
-
-    detokenizer = pw_tokenizer.Detokenizer(database)
-    input = serial.Serial(serialport, 115200, timeout=None)
-
-    output = None
-    if outfile:
-        output = open(outfile, 'w')
-
-    if input:
-
-        try:
-            while (True):
-                # read line from serial port and ascii decode
-                line = input.readline().decode('ascii').strip()
-                # find token start and detokenize
-                idx = line.rfind(']')
-                dstr = decode_string(line[idx + 1:], detokenizer)
-                if dstr:
-                    line = line[:idx+1] + dstr
-                print(line, file=sys.stdout)
-                if output:
-                    print(line, file=output)
-        except Exception:
-            print("Serial error or program closed", file=sys.stderr)
-
-        if output:
-            input.close()
-            output.close()
-
-    else:
-        print("Invalid or closed serial port.", file=sys.stderr)
-
-
-def decode_file(infile, outfile, database):
-    """Decodes logs from input file.
-
-    Args:
-        infile      - path to input file
-        outfile     - path to output file
-        database    - path to token database
-    """
-
-    if os.path.isfile(infile):
-
-        detokenizer = pw_tokenizer.Detokenizer(database)
-
-        output = open(outfile, 'w')
-
-        with open(infile, 'rb') as file:
-            for line in file:
-                try:
-                    # ascii decode line
-                    # serial terminals may include non ascii characters
-                    line = line.decode('ascii').strip()
-                except Exception:
-                    continue
-                # find token start and detokenize
-                idx = line.rfind(']')
-                dstr = decode_string(line[idx + 1:], detokenizer)
-                if dstr:
-                    line = line[:idx+1] + dstr
-                print(line, file=output)
-        output.close()
-
-    else:
-        print("File does not exist or is not a file.", file=sys.stderr)
-
-
-def detokenize_input():
-
-    args = parse_args()
-
-    if args.type == 'file':
-        decode_file(args.input, args.output, args.database)
-    if args.type == 'serial':
-        decode_serial(args.input, args.output, args.database)
-
-
-if __name__ == '__main__':
-    detokenize_input()
-    sys.exit(0)
diff --git a/examples/platform/nxp/k32w/k32w0/scripts/sign-outdir.py b/examples/platform/nxp/k32w/k32w0/scripts/sign-outdir.py
deleted file mode 100644
index 8660b4bc5f4b06..00000000000000
--- a/examples/platform/nxp/k32w/k32w0/scripts/sign-outdir.py
+++ /dev/null
@@ -1,37 +0,0 @@
-import argparse
-import os
-import subprocess
-
-
-def main(args):
-    if "NXP_K32W0_SDK_ROOT" in os.environ and os.environ["NXP_K32W0_SDK_ROOT"] != "":
-        sign_images_path = os.environ["NXP_K32W0_SDK_ROOT"] + "/tools/imagetool/sign_images.sh"
-    else:
-        sign_images_path = os.path.abspath(
-            __file__ + "/../../../../../../../third_party/nxp/k32w0_sdk/repo/core/tools/imagetool/sign_images.sh")
-
-    # Give execute permission if needed
-    if os.access(sign_images_path, os.X_OK) is False:
-        os.chmod(sign_images_path, 0o766)
-
-    # Convert script to unix format if needed
-    subprocess.call("(file " + sign_images_path + " | grep CRLF > /dev/null) && (dos2unix " + sign_images_path + ")", shell=True)
-
-    # Call sign_images.sh script with the output directory
-    cmd = sign_images_path + " " + os.getcwd()
-    if args.simple_hash:
-        cmd = cmd + " -SimpleHashVerification"
-
-    subprocess.call(cmd, shell=True)
-
-
-if __name__ == "__main__":
-    parser = argparse.ArgumentParser()
-    parser.add_argument(
-        "--simple-hash",
-        help="When enabled, adds a hash of the whole image at the end of the binary.",
-        action="store_true"
-    )
-    args = parser.parse_args()
-
-    main(args)
diff --git a/examples/platform/nxp/k32w/k32w0/util/LEDWidget.cpp b/examples/platform/nxp/k32w/k32w0/util/LEDWidget.cpp
deleted file mode 100644
index fec3a5b0afca70..00000000000000
--- a/examples/platform/nxp/k32w/k32w0/util/LEDWidget.cpp
+++ /dev/null
@@ -1,86 +0,0 @@
-/*
- *
- *    Copyright (c) 2020 Project CHIP Authors
- *    Copyright (c) 2019 Google LLC.
- *    All rights reserved.
- *
- *    Licensed under the Apache License, Version 2.0 (the "License");
- *    you may not use this file except in compliance with the License.
- *    You may obtain a copy of the License at
- *
- *        http://www.apache.org/licenses/LICENSE-2.0
- *
- *    Unless required by applicable law or agreed to in writing, software
- *    distributed under the License is distributed on an "AS IS" BASIS,
- *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *    See the License for the specific language governing permissions and
- *    limitations under the License.
- */
-
-#include "LEDWidget.h"
-
-#include <system/SystemClock.h>
-
-void LEDWidget::Init(LED_t led)
-{
-    mLastChangeTimeMS = 0;
-    mBlinkOnTimeMS    = 0;
-    mBlinkOffTimeMS   = 0;
-    mGPIONum          = led;
-    mState            = false;
-
-    Set(false);
-}
-
-void LEDWidget::Invert(void)
-{
-    Set(!mState);
-}
-
-void LEDWidget::Set(bool state)
-{
-    mLastChangeTimeMS = mBlinkOnTimeMS = mBlinkOffTimeMS = 0;
-    DoSet(state);
-}
-
-void LEDWidget::Blink(uint32_t changeRateMS)
-{
-    Blink(changeRateMS, changeRateMS);
-}
-
-void LEDWidget::Blink(uint32_t onTimeMS, uint32_t offTimeMS)
-{
-    mBlinkOnTimeMS  = onTimeMS;
-    mBlinkOffTimeMS = offTimeMS;
-    Animate();
-}
-
-void LEDWidget::Animate()
-{
-    if (mBlinkOnTimeMS != 0 && mBlinkOffTimeMS != 0)
-    {
-        uint64_t nowMS            = chip::System::SystemClock().GetMonotonicMilliseconds64().count();
-        uint64_t stateDurMS       = mState ? mBlinkOnTimeMS : mBlinkOffTimeMS;
-        uint64_t nextChangeTimeMS = mLastChangeTimeMS + stateDurMS;
-
-        if (nextChangeTimeMS < nowMS)
-        {
-            DoSet(!mState);
-            mLastChangeTimeMS = nowMS;
-        }
-    }
-}
-
-void LEDWidget::DoSet(bool state)
-{
-    mState = state;
-
-    if (state)
-    {
-        LED_TurnOnLed(mGPIONum);
-    }
-    else
-    {
-        LED_TurnOffLed(mGPIONum);
-    }
-}
diff --git a/examples/platform/nxp/k32w/k32w0/util/include/LEDWidget.h b/examples/platform/nxp/k32w/k32w0/util/include/LEDWidget.h
deleted file mode 100644
index f725eeaa9d74f5..00000000000000
--- a/examples/platform/nxp/k32w/k32w0/util/include/LEDWidget.h
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- *
- *    Copyright (c) 2020 Google LLC.
- *    All rights reserved.
- *
- *    Licensed under the Apache License, Version 2.0 (the "License");
- *    you may not use this file except in compliance with the License.
- *    You may obtain a copy of the License at
- *
- *        http://www.apache.org/licenses/LICENSE-2.0
- *
- *    Unless required by applicable law or agreed to in writing, software
- *    distributed under the License is distributed on an "AS IS" BASIS,
- *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *    See the License for the specific language governing permissions and
- *    limitations under the License.
- */
-
-#include "LED.h"
-
-#pragma once
-
-class LEDWidget
-{
-public:
-    void Init(LED_t gpioNum);
-    void Set(bool state);
-    void Invert(void);
-    void Blink(uint32_t changeRateMS);
-    void Blink(uint32_t onTimeMS, uint32_t offTimeMS);
-    void Animate();
-
-private:
-    uint64_t mLastChangeTimeMS;
-    uint32_t mBlinkOnTimeMS;
-    uint32_t mBlinkOffTimeMS;
-    LED_t mGPIONum;
-    bool mState;
-
-    void DoSet(bool state);
-};
diff --git a/examples/platform/nxp/k32w/k32w0/common/README.md b/examples/platform/nxp/k32w0/doc/CustomFactoryDataProvider.md
similarity index 100%
rename from examples/platform/nxp/k32w/k32w0/common/README.md
rename to examples/platform/nxp/k32w0/doc/CustomFactoryDataProvider.md
diff --git a/examples/platform/nxp/k32w/k32w0/doc/images/chiptool_main_screen.png b/examples/platform/nxp/k32w0/doc/images/chiptool_main_screen.png
similarity index 100%
rename from examples/platform/nxp/k32w/k32w0/doc/images/chiptool_main_screen.png
rename to examples/platform/nxp/k32w0/doc/images/chiptool_main_screen.png
diff --git a/examples/platform/nxp/k32w/k32w0/doc/images/flash_location.JPG b/examples/platform/nxp/k32w0/doc/images/flash_location.JPG
similarity index 100%
rename from examples/platform/nxp/k32w/k32w0/doc/images/flash_location.JPG
rename to examples/platform/nxp/k32w0/doc/images/flash_location.JPG
diff --git a/examples/platform/nxp/k32w/k32w0/doc/images/form_web.JPG b/examples/platform/nxp/k32w0/doc/images/form_web.JPG
similarity index 100%
rename from examples/platform/nxp/k32w/k32w0/doc/images/form_web.JPG
rename to examples/platform/nxp/k32w0/doc/images/form_web.JPG
diff --git a/examples/platform/nxp/k32w/k32w0/doc/images/k32w-dk6-connectors.jpg b/examples/platform/nxp/k32w0/doc/images/k32w-dk6-connectors.jpg
similarity index 100%
rename from examples/platform/nxp/k32w/k32w0/doc/images/k32w-dk6-connectors.jpg
rename to examples/platform/nxp/k32w0/doc/images/k32w-dk6-connectors.jpg
diff --git a/examples/platform/nxp/k32w/k32w0/doc/images/k32w-dk6.jpg b/examples/platform/nxp/k32w0/doc/images/k32w-dk6.jpg
similarity index 100%
rename from examples/platform/nxp/k32w/k32w0/doc/images/k32w-dk6.jpg
rename to examples/platform/nxp/k32w0/doc/images/k32w-dk6.jpg
diff --git a/examples/platform/nxp/k32w/k32w0/doc/images/k32w-se.jpg b/examples/platform/nxp/k32w0/doc/images/k32w-se.jpg
similarity index 100%
rename from examples/platform/nxp/k32w/k32w0/doc/images/k32w-se.jpg
rename to examples/platform/nxp/k32w0/doc/images/k32w-se.jpg
diff --git a/examples/platform/nxp/k32w/k32w0/doc/images/mcux-sdk-download.JPG b/examples/platform/nxp/k32w0/doc/images/mcux-sdk-download.JPG
similarity index 100%
rename from examples/platform/nxp/k32w/k32w0/doc/images/mcux-sdk-download.JPG
rename to examples/platform/nxp/k32w0/doc/images/mcux-sdk-download.JPG
diff --git a/examples/platform/nxp/k32w/k32w0/doc/images/nxp_hw_connectivity.JPG b/examples/platform/nxp/k32w0/doc/images/nxp_hw_connectivity.JPG
similarity index 100%
rename from examples/platform/nxp/k32w/k32w0/doc/images/nxp_hw_connectivity.JPG
rename to examples/platform/nxp/k32w0/doc/images/nxp_hw_connectivity.JPG
diff --git a/examples/platform/nxp/k32w/k32w0/doc/images/on_off_cluster.png b/examples/platform/nxp/k32w0/doc/images/on_off_cluster.png
similarity index 100%
rename from examples/platform/nxp/k32w/k32w0/doc/images/on_off_cluster.png
rename to examples/platform/nxp/k32w0/doc/images/on_off_cluster.png
diff --git a/examples/platform/nxp/k32w/k32w0/doc/images/ota_topology.JPG b/examples/platform/nxp/k32w0/doc/images/ota_topology.JPG
similarity index 100%
rename from examples/platform/nxp/k32w/k32w0/doc/images/ota_topology.JPG
rename to examples/platform/nxp/k32w0/doc/images/ota_topology.JPG
diff --git a/examples/platform/nxp/k32w/k32w0/doc/images/pdm_ext_flash.JPG b/examples/platform/nxp/k32w0/doc/images/pdm_ext_flash.JPG
similarity index 100%
rename from examples/platform/nxp/k32w/k32w0/doc/images/pdm_ext_flash.JPG
rename to examples/platform/nxp/k32w0/doc/images/pdm_ext_flash.JPG
diff --git a/examples/platform/nxp/k32w/k32w0/doc/images/power_conf.JPG b/examples/platform/nxp/k32w0/doc/images/power_conf.JPG
similarity index 100%
rename from examples/platform/nxp/k32w/k32w0/doc/images/power_conf.JPG
rename to examples/platform/nxp/k32w0/doc/images/power_conf.JPG
diff --git a/examples/platform/nxp/k32w/k32w0/doc/images/power_view.JPG b/examples/platform/nxp/k32w0/doc/images/power_view.JPG
similarity index 100%
rename from examples/platform/nxp/k32w/k32w0/doc/images/power_view.JPG
rename to examples/platform/nxp/k32w0/doc/images/power_view.JPG
diff --git a/examples/platform/nxp/k32w/k32w0/doc/images/select-sdk.JPG b/examples/platform/nxp/k32w0/doc/images/select-sdk.JPG
similarity index 100%
rename from examples/platform/nxp/k32w/k32w0/doc/images/select-sdk.JPG
rename to examples/platform/nxp/k32w0/doc/images/select-sdk.JPG
diff --git a/examples/platform/nxp/k32w/k32w0/doc/images/thread_credentials.png b/examples/platform/nxp/k32w0/doc/images/thread_credentials.png
similarity index 100%
rename from examples/platform/nxp/k32w/k32w0/doc/images/thread_credentials.png
rename to examples/platform/nxp/k32w0/doc/images/thread_credentials.png
diff --git a/gn_build.sh b/gn_build.sh
index 9f6c76571da593..e9110442a52293 100755
--- a/gn_build.sh
+++ b/gn_build.sh
@@ -164,7 +164,7 @@ if [[ ! -d "$NXP_K32W0_SDK_ROOT" ]]; then
     echo "Hint: Set \$NXP_K32W0_SDK_ROOT to enable building for K32W061"
 else
     echo 'To build the K32W lock sample as a standalone project':
-    echo "(cd $CHIP_ROOT/examples/lock-app/nxp/k32w/k32w0; gn gen out/debug --args='$k32w_sdk_args'; ninja -C out/debug)"
+    echo "(cd $CHIP_ROOT/examples/lock-app/nxp/k32w0; gn gen out/debug --args='$k32w_sdk_args'; ninja -C out/debug)"
 fi
 echo
 
diff --git a/scripts/build/builders/nxp.py b/scripts/build/builders/nxp.py
index b72015f0afc677..e119a78b5e2cc2 100644
--- a/scripts/build/builders/nxp.py
+++ b/scripts/build/builders/nxp.py
@@ -54,7 +54,7 @@ def Name(self, os_env):
 
     def FolderName(self, os_env):
         if self == NxpBoard.K32W0:
-            return 'k32w/k32w0'
+            return 'k32w0'
         elif self == NxpBoard.K32W1:
             return 'k32w/k32w1'
         elif self == NxpBoard.RW61X:
diff --git a/scripts/setup/requirements.nxp.txt b/scripts/setup/requirements.nxp.txt
index a78e1f0fc6230d..615e170ce83ce4 100644
--- a/scripts/setup/requirements.nxp.txt
+++ b/scripts/setup/requirements.nxp.txt
@@ -1,4 +1,3 @@
 crc>=7.0.0
 jsonschema>=4.17.0
-pycrypto>=2.6.1
 pycryptodome>=3.20.0
diff --git a/src/platform/nxp/common/legacy/BLEManagerCommon.cpp b/src/platform/nxp/common/legacy/BLEManagerCommon.cpp
new file mode 100644
index 00000000000000..d9dbde88f3a614
--- /dev/null
+++ b/src/platform/nxp/common/legacy/BLEManagerCommon.cpp
@@ -0,0 +1,1435 @@
+/*
+ *
+ *    Copyright (c) 2020-2021 Project CHIP Authors
+ *    Copyright (c) 2020 Nest Labs, Inc.
+ *    All rights reserved.
+ *
+ *    Licensed under the Apache License, Version 2.0 (the "License");
+ *    you may not use this file except in compliance with the License.
+ *    You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *    Unless required by applicable law or agreed to in writing, software
+ *    distributed under the License is distributed on an "AS IS" BASIS,
+ *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *    See the License for the specific language governing permissions and
+ *    limitations under the License.
+ */
+
+/**
+ *    @file
+ *          Provides an implementation of the BLEManager singleton object
+ *          for the K32W platforms.
+ */
+
+/* this file behaves like a config.h, comes first */
+#include <platform/internal/CHIPDeviceLayerInternal.h>
+
+#include <platform/CommissionableDataProvider.h>
+
+#include <crypto/CHIPCryptoPAL.h>
+
+#if CHIP_DEVICE_CONFIG_ENABLE_CHIPOBLE
+
+#include <ble/Ble.h>
+
+#include "board.h"
+#include "gatt_db_app_interface.h"
+#include "gatt_db_handles.h"
+#include "stdio.h"
+#include "timers.h"
+
+#if defined(CPU_JN518X) && defined(chip_with_low_power) && (chip_with_low_power == 1)
+#include "PWR_Configuration.h"
+#endif
+
+#if CHIP_ENABLE_ADDITIONAL_DATA_ADVERTISING
+#include <platform/DeviceInstanceInfoProvider.h>
+#include <setup_payload/AdditionalDataPayloadGenerator.h>
+#endif
+
+/*******************************************************************************
+ * Local data types
+ *******************************************************************************/
+extern "C" bool_t Ble_ConfigureHostStackConfig(void);
+
+#if defined(chip_with_low_power) && (chip_with_low_power == 1)
+extern "C" void PWR_DisallowDeviceToSleep(void);
+extern "C" void PWR_AllowDeviceToSleep(void);
+#endif
+
+using namespace ::chip;
+using namespace ::chip::Ble;
+
+namespace chip {
+namespace DeviceLayer {
+namespace Internal {
+
+namespace {
+/*******************************************************************************
+ * Macros & Constants definitions
+ *******************************************************************************/
+/* Timeout of BLE commands */
+#define CHIP_BLE_KW_EVNT_TIMEOUT 1000 / portTICK_PERIOD_MS
+
+/** BLE advertisement state changed */
+#define CHIP_BLE_KW_EVNT_ADV_CHANGED 0x0001
+/** BLE advertisement command failed */
+#define CHIP_BLE_KW_EVNT_ADV_FAILED 0x0002
+/** BLE advertisement setup failed */
+#define CHIP_BLE_KW_EVNT_ADV_SETUP_FAILED 0x0004
+/** BLE advertisement parameters setup complete */
+#define CHIP_BLE_KW_EVNT_ADV_PAR_SETUP_COMPLETE 0x0008
+/** BLE advertisement data setup complete */
+#define CHIP_BLE_KW_EVNT_ADV_DAT_SETUP_COMPLETE 0x0010
+/** BLE random address set */
+#define CHIP_BLE_KW_EVNT_RND_ADDR_SET 0x0020
+/** BLE Initialization complete */
+#define CHIP_BLE_KW_EVNT_INIT_COMPLETE 0x0040
+/** BLE Received a handle value confirmation from the client */
+#define CHIP_BLE_KW_EVNT_INDICATION_CONFIRMED 0x0080
+/** BLE send indication failed */
+#define CHIP_BLE_KW_EVNT_INDICATION_FAILED 0x0100
+/** TX Power Level Set */
+#define CHIP_BLE_KW_EVNT_POWER_LEVEL_SET 0x0200
+/** Maximal time of connection without activity */
+#define CHIP_BLE_KW_CONN_TIMEOUT 60000
+/** Maximum number of pending BLE events */
+#define CHIP_BLE_EVENT_QUEUE_MAX_ENTRIES 10
+
+#define LOOP_EV_BLE (0x08)
+
+/* controller task configuration */
+#define CONTROLLER_TASK_PRIORITY (6U)
+#define CONTROLLER_TASK_STACK_SIZE (gControllerTaskStackSize_c / sizeof(StackType_t))
+
+/* host task configuration */
+#define HOST_TASK_PRIORITY (4U)
+#define HOST_TASK_STACK_SIZE (gHost_TaskStackSize_c / sizeof(StackType_t))
+
+/* advertising configuration */
+#define BLEKW_ADV_MAX_NO (2)
+#define BLEKW_SCAN_RSP_MAX_NO (2)
+#define BLEKW_MAX_ADV_DATA_LEN (31)
+#define CHIP_ADV_SHORT_UUID_LEN (2)
+
+/* FreeRTOS sw timer */
+TimerHandle_t sbleAdvTimeoutTimer;
+
+/* Queue used to synchronize asynchronous messages from the KW BLE tasks */
+QueueHandle_t sBleEventQueue;
+
+/* Used to manage asynchronous events from BLE Stack: e.g.: GAP setup finished */
+EventGroupHandle_t sEventGroup;
+
+TimerHandle_t connectionTimeout;
+
+const uint8_t ShortUUID_CHIPoBLEService[] = { 0xF6, 0xFF };
+
+#if defined(chip_with_low_power) && (chip_with_low_power == 1)
+static bool bleAppStopInProgress;
+#endif
+
+BLEManagerCommon * sImplInstance = nullptr;
+
+} // namespace
+
+CHIP_ERROR BLEManagerCommon::_Init()
+{
+    CHIP_ERROR err = CHIP_NO_ERROR;
+    EventBits_t eventBits;
+    uint16_t attChipRxHandle[1] = { (uint16_t) value_chipoble_rx };
+
+#if CHIP_ENABLE_ADDITIONAL_DATA_ADVERTISING
+    uint16_t attChipC3Handle[1] = { (uint16_t) value_chipoble_c3 };
+#endif
+
+    mServiceMode = ConnectivityManager::kCHIPoBLEServiceMode_Enabled;
+
+    // Check if BLE stack is initialized
+    VerifyOrExit(!mFlags.Has(Flags::kK32WBLEStackInitialized), err = CHIP_ERROR_INCORRECT_STATE);
+
+    // Initialize the Chip BleLayer.
+    err = BleLayer::Init(this, this, &DeviceLayer::SystemLayer());
+    SuccessOrExit(err);
+
+    /* Initialization of message wait events -
+     * used for receiving BLE Stack events */
+    sEventGroup = xEventGroupCreate();
+    VerifyOrExit(sEventGroup != NULL, err = CHIP_ERROR_INCORRECT_STATE);
+
+    /* Prepare callback input queue.*/
+    sBleEventQueue = xQueueCreate(CHIP_BLE_EVENT_QUEUE_MAX_ENTRIES, sizeof(blekw_msg_t *));
+    VerifyOrExit(sBleEventQueue != NULL, err = CHIP_ERROR_INCORRECT_STATE);
+
+    /* Create the connection timeout timer. */
+    connectionTimeout =
+        xTimerCreate("bleTimeoutTmr", pdMS_TO_TICKS(CHIP_BLE_KW_CONN_TIMEOUT), pdFALSE, (void *) 0, blekw_connection_timeout_cb);
+    VerifyOrExit(connectionTimeout != NULL, err = CHIP_ERROR_INCORRECT_STATE);
+
+    sImplInstance = GetImplInstance();
+
+    /* BLE platform code initialization */
+    SuccessOrExit(err = InitHostController(&blekw_generic_cb));
+
+    /* Register the GATT server callback */
+    VerifyOrExit(GattServer_RegisterCallback(blekw_gatt_server_cb) == gBleSuccess_c, err = CHIP_ERROR_INCORRECT_STATE);
+
+    /* Wait until BLE Stack is ready */
+    eventBits = xEventGroupWaitBits(sEventGroup, CHIP_BLE_KW_EVNT_INIT_COMPLETE, pdTRUE, pdTRUE, CHIP_BLE_KW_EVNT_TIMEOUT);
+    VerifyOrExit(eventBits & CHIP_BLE_KW_EVNT_INIT_COMPLETE, err = CHIP_ERROR_INCORRECT_STATE);
+
+#if BLE_HIGH_TX_POWER
+    /* Set Adv Power */
+    Gap_SetTxPowerLevel(gAdvertisingPowerLeveldBm_c, gTxPowerAdvChannel_c);
+    eventBits = xEventGroupWaitBits(sEventGroup, CHIP_BLE_KW_EVNT_POWER_LEVEL_SET, pdTRUE, pdTRUE, CHIP_BLE_KW_EVNT_TIMEOUT);
+    VerifyOrExit(eventBits & CHIP_BLE_KW_EVNT_POWER_LEVEL_SET, err = CHIP_ERROR_INCORRECT_STATE);
+
+    /* Set Connect Power */
+    Gap_SetTxPowerLevel(gConnectPowerLeveldBm_c, gTxPowerConnChannel_c);
+    eventBits = xEventGroupWaitBits(sEventGroup, CHIP_BLE_KW_EVNT_POWER_LEVEL_SET, pdTRUE, pdTRUE, CHIP_BLE_KW_EVNT_TIMEOUT);
+    VerifyOrExit(eventBits & CHIP_BLE_KW_EVNT_POWER_LEVEL_SET, err = CHIP_ERROR_INCORRECT_STATE);
+#endif
+
+#if defined(CPU_JN518X) && defined(chip_with_low_power) && (chip_with_low_power == 1)
+    PWR_ChangeDeepSleepMode(cPWR_PowerDown_RamRet);
+#endif
+
+    GattServer_RegisterHandlesForWriteNotifications(1, attChipRxHandle);
+#if CHIP_ENABLE_ADDITIONAL_DATA_ADVERTISING
+    VerifyOrExit(GattServer_RegisterHandlesForReadNotifications(1, attChipC3Handle) == gBleSuccess_c,
+                 err = CHIP_ERROR_INCORRECT_STATE);
+#endif
+
+    mFlags.Set(Flags::kK32WBLEStackInitialized);
+    mFlags.Set(Flags::kAdvertisingEnabled, CHIP_DEVICE_CONFIG_CHIPOBLE_ENABLE_ADVERTISING_AUTOSTART ? true : false);
+    mFlags.Set(Flags::kFastAdvertisingEnabled);
+
+    // Create FreeRTOS sw timer for BLE timeouts and interval change.
+    sbleAdvTimeoutTimer = xTimerCreate("BleAdvTimer",       // Just a text name, not used by the RTOS kernel
+                                       pdMS_TO_TICKS(100),  // == default timer period (mS)
+                                       false,               // no timer reload (==one-shot)
+                                       (void *) this,       // init timer id = ble obj context
+                                       BleAdvTimeoutHandler // timer callback handler
+    );
+    VerifyOrExit(sbleAdvTimeoutTimer != NULL, err = CHIP_ERROR_INCORRECT_STATE);
+
+exit:
+    return err;
+}
+
+uint16_t BLEManagerCommon::_NumConnections(void)
+{
+    return static_cast<uint16_t>(mDeviceConnected == true);
+}
+
+bool BLEManagerCommon::_IsAdvertisingEnabled(void)
+{
+    return mFlags.Has(Flags::kAdvertisingEnabled);
+}
+
+bool BLEManagerCommon::_IsAdvertising(void)
+{
+    return mFlags.Has(Flags::kAdvertising);
+}
+
+CHIP_ERROR BLEManagerCommon::_SetAdvertisingEnabled(bool val)
+{
+    CHIP_ERROR err = CHIP_NO_ERROR;
+
+    VerifyOrExit(mServiceMode != ConnectivityManager::kCHIPoBLEServiceMode_NotSupported, err = CHIP_ERROR_UNSUPPORTED_CHIP_FEATURE);
+
+    if (mFlags.Has(Flags::kAdvertisingEnabled) != val)
+    {
+        mFlags.Set(Flags::kAdvertisingEnabled, val);
+        PlatformMgr().ScheduleWork(DriveBLEState, 0);
+    }
+
+exit:
+    return err;
+}
+
+CHIP_ERROR BLEManagerCommon::_SetAdvertisingMode(BLEAdvertisingMode mode)
+{
+    switch (mode)
+    {
+    case BLEAdvertisingMode::kFastAdvertising:
+        mFlags.Set(Flags::kFastAdvertisingEnabled);
+        break;
+    case BLEAdvertisingMode::kSlowAdvertising: {
+        // We are in FreeRTOS timer service context, which is a default daemon task and has
+        // the highest priority. Stop advertising should be scheduled to run from Matter task.
+        mFlags.Clear(Flags::kFastAdvertisingEnabled);
+        PlatformMgr().ScheduleWork(StopAdvertisingPriorToSwitchingMode, 0);
+        break;
+    }
+    default:
+        return CHIP_ERROR_INVALID_ARGUMENT;
+    }
+    mFlags.Set(Flags::kRestartAdvertising);
+    PlatformMgr().ScheduleWork(DriveBLEState, 0);
+    return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR BLEManagerCommon::_GetDeviceName(char * buf, size_t bufSize)
+{
+    if (strlen(mDeviceName) >= bufSize)
+    {
+        return CHIP_ERROR_BUFFER_TOO_SMALL;
+    }
+    strcpy(buf, mDeviceName);
+    return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR BLEManagerCommon::_SetDeviceName(const char * deviceName)
+{
+    if (mServiceMode == ConnectivityManager::kCHIPoBLEServiceMode_NotSupported)
+    {
+        return CHIP_ERROR_UNSUPPORTED_CHIP_FEATURE;
+    }
+    if (deviceName != NULL && deviceName[0] != 0)
+    {
+        if (strlen(deviceName) >= kMaxDeviceNameLength)
+        {
+            return CHIP_ERROR_INVALID_ARGUMENT;
+        }
+        memset(mDeviceName, 0, kMaxDeviceNameLength);
+        strcpy(mDeviceName, deviceName);
+        mFlags.Set(Flags::kDeviceNameSet);
+        ChipLogProgress(DeviceLayer, "Setting device name to : \"%s\"", deviceName);
+    }
+    else
+    {
+        mDeviceName[0] = 0;
+        mFlags.Clear(Flags::kDeviceNameSet);
+    }
+
+    return CHIP_NO_ERROR;
+}
+
+void BLEManagerCommon::_OnPlatformEvent(const ChipDeviceEvent * event)
+{
+    switch (event->Type)
+    {
+    case DeviceEventType::kCHIPoBLESubscribe:
+        ChipDeviceEvent connEstEvent;
+
+        HandleSubscribeReceived(event->CHIPoBLESubscribe.ConId, &CHIP_BLE_SVC_ID, &Ble::CHIP_BLE_CHAR_2_UUID);
+        connEstEvent.Type = DeviceEventType::kCHIPoBLEConnectionEstablished;
+        PlatformMgr().PostEventOrDie(&connEstEvent);
+        break;
+
+    case DeviceEventType::kCHIPoBLEUnsubscribe:
+        HandleUnsubscribeReceived(event->CHIPoBLEUnsubscribe.ConId, &CHIP_BLE_SVC_ID, &Ble::CHIP_BLE_CHAR_2_UUID);
+        break;
+
+    case DeviceEventType::kCHIPoBLEWriteReceived:
+        HandleWriteReceived(event->CHIPoBLEWriteReceived.ConId, &CHIP_BLE_SVC_ID, &Ble::CHIP_BLE_CHAR_1_UUID,
+                            PacketBufferHandle::Adopt(event->CHIPoBLEWriteReceived.Data));
+        break;
+
+    case DeviceEventType::kCHIPoBLEConnectionError:
+        HandleConnectionError(event->CHIPoBLEConnectionError.ConId, event->CHIPoBLEConnectionError.Reason);
+        break;
+
+    case DeviceEventType::kCHIPoBLEIndicateConfirm:
+        HandleIndicationConfirmation(event->CHIPoBLEIndicateConfirm.ConId, &CHIP_BLE_SVC_ID, &Ble::CHIP_BLE_CHAR_2_UUID);
+        break;
+
+    default:
+        break;
+    }
+}
+
+CHIP_ERROR BLEManagerCommon::SubscribeCharacteristic(BLE_CONNECTION_OBJECT conId, const ChipBleUUID * svcId,
+                                                     const ChipBleUUID * charId)
+{
+    ChipLogProgress(DeviceLayer, "BLEManagerCommon::SubscribeCharacteristic() not supported");
+    return CHIP_ERROR_NOT_IMPLEMENTED;
+}
+
+CHIP_ERROR BLEManagerCommon::UnsubscribeCharacteristic(BLE_CONNECTION_OBJECT conId, const ChipBleUUID * svcId,
+                                                       const ChipBleUUID * charId)
+{
+    ChipLogProgress(DeviceLayer, "BLEManagerCommon::UnsubscribeCharacteristic() not supported");
+    return CHIP_ERROR_NOT_IMPLEMENTED;
+}
+
+CHIP_ERROR BLEManagerCommon::CloseConnection(BLE_CONNECTION_OBJECT conId)
+{
+    return blekw_stop_connection_internal(conId);
+}
+
+uint16_t BLEManagerCommon::GetMTU(BLE_CONNECTION_OBJECT conId) const
+{
+    uint16_t tempMtu = 0;
+    (void) Gatt_GetMtu(conId, &tempMtu);
+
+    return tempMtu;
+}
+
+CHIP_ERROR BLEManagerCommon::SendWriteRequest(BLE_CONNECTION_OBJECT conId, const ChipBleUUID * svcId, const ChipBleUUID * charId,
+                                              PacketBufferHandle pBuf)
+{
+    ChipLogProgress(DeviceLayer, "BLEManagerCommon::SendWriteRequest() not supported");
+    return CHIP_ERROR_NOT_IMPLEMENTED;
+}
+
+void BLEManagerCommon::NotifyChipConnectionClosed(BLE_CONNECTION_OBJECT conId)
+{
+    BLEMgrImpl().CloseConnection(conId);
+}
+
+CHIP_ERROR BLEManagerCommon::SendIndication(BLE_CONNECTION_OBJECT conId, const ChipBleUUID * svcId, const ChipBleUUID * charId,
+                                            PacketBufferHandle data)
+{
+    VerifyOrReturnError(UUIDsMatch(&Ble::CHIP_BLE_CHAR_2_UUID, charId), BLE_ERROR_GATT_WRITE_FAILED);
+
+    CHIP_ERROR err = CHIP_NO_ERROR;
+
+    if (blekw_send_event(conId, value_chipoble_tx, data->Start(), data->DataLength()) != BLE_OK)
+    {
+        err = CHIP_ERROR_SENDING_BLOCKED;
+    }
+    else
+    {
+        ChipDeviceEvent event;
+        event.Type                          = DeviceEventType::kCHIPoBLEIndicateConfirm;
+        event.CHIPoBLEIndicateConfirm.ConId = conId;
+        err                                 = PlatformMgr().PostEvent(&event);
+    }
+
+    return err;
+}
+
+BLEManagerCommon::ble_err_t BLEManagerCommon::blekw_send_event(int8_t connection_handle, uint16_t handle, uint8_t * data,
+                                                               uint32_t len)
+{
+    EventBits_t eventBits;
+
+#if CHIP_DEVICE_CHIP0BLE_DEBUG
+    ChipLogProgress(DeviceLayer, "Trying to send event.");
+#endif
+
+    if (connection_handle < 0 || handle <= 0)
+    {
+        ChipLogProgress(DeviceLayer, "BLE Event - Bad Handle");
+        return BLE_E_FAIL;
+    }
+
+    if (len > 0 && data == NULL)
+    {
+        ChipLogProgress(DeviceLayer, "BLE Event - Invalid Data");
+        return BLE_E_FAIL;
+    }
+
+    /************* Send the indication *************/
+    xEventGroupClearBits(sEventGroup, CHIP_BLE_KW_EVNT_INDICATION_CONFIRMED | CHIP_BLE_KW_EVNT_INDICATION_FAILED);
+
+    if (GattServer_SendInstantValueIndication(connection_handle, handle, len, data) != gBleSuccess_c)
+    {
+        ChipLogProgress(DeviceLayer, "BLE Event - Can't sent indication");
+        return BLE_E_FAIL;
+    }
+
+    /* Wait until BLE Stack is ready */
+    eventBits = xEventGroupWaitBits(sEventGroup, CHIP_BLE_KW_EVNT_INDICATION_CONFIRMED | CHIP_BLE_KW_EVNT_INDICATION_FAILED, pdTRUE,
+                                    pdFALSE, CHIP_BLE_KW_EVNT_TIMEOUT);
+
+    if (eventBits & CHIP_BLE_KW_EVNT_INDICATION_FAILED)
+    {
+        ChipLogProgress(DeviceLayer, "BLE Event - Sent Failed");
+        return BLE_E_FAIL;
+    }
+
+#if CHIP_DEVICE_CHIP0BLE_DEBUG
+    ChipLogProgress(DeviceLayer, "BLE Event - Sent :-) ");
+#endif
+
+    return BLE_OK;
+}
+/*******************************************************************************
+ * Private functions
+ *******************************************************************************/
+
+BLEManagerCommon::ble_err_t BLEManagerCommon::blekw_start_advertising(gapAdvertisingParameters_t * adv_params,
+                                                                      gapAdvertisingData_t * adv, gapScanResponseData_t * scnrsp)
+{
+    EventBits_t eventBits;
+
+    /************* Set the advertising parameters *************/
+    xEventGroupClearBits(sEventGroup, CHIP_BLE_KW_EVNT_ADV_SETUP_FAILED | CHIP_BLE_KW_EVNT_ADV_PAR_SETUP_COMPLETE);
+
+    /* Set the advertising parameters */
+    if (Gap_SetAdvertisingParameters(adv_params) != gBleSuccess_c)
+    {
+        vTaskDelay(1);
+
+        /* Retry, just to make sure before giving up and sending an error. */
+        if (Gap_SetAdvertisingParameters(adv_params) != gBleSuccess_c)
+        {
+            return BLE_E_SET_ADV_PARAMS;
+        }
+    }
+
+    eventBits = xEventGroupWaitBits(sEventGroup, CHIP_BLE_KW_EVNT_ADV_SETUP_FAILED | CHIP_BLE_KW_EVNT_ADV_PAR_SETUP_COMPLETE,
+                                    pdTRUE, pdFALSE, CHIP_BLE_KW_EVNT_TIMEOUT);
+
+    if (!(eventBits & CHIP_BLE_KW_EVNT_ADV_PAR_SETUP_COMPLETE))
+    {
+        return BLE_E_ADV_PARAMS_FAILED;
+    }
+
+    /************* Set the advertising data *************/
+    xEventGroupClearBits(sEventGroup, CHIP_BLE_KW_EVNT_ADV_SETUP_FAILED | CHIP_BLE_KW_EVNT_ADV_DAT_SETUP_COMPLETE);
+
+    /* Set the advertising data */
+    if (Gap_SetAdvertisingData(adv, scnrsp) != gBleSuccess_c)
+    {
+        return BLE_E_SET_ADV_DATA;
+    }
+
+    eventBits = xEventGroupWaitBits(sEventGroup, CHIP_BLE_KW_EVNT_ADV_SETUP_FAILED | CHIP_BLE_KW_EVNT_ADV_DAT_SETUP_COMPLETE,
+                                    pdTRUE, pdFALSE, CHIP_BLE_KW_EVNT_TIMEOUT);
+
+    if (!(eventBits & CHIP_BLE_KW_EVNT_ADV_DAT_SETUP_COMPLETE))
+    {
+        return BLE_E_ADV_SETUP_FAILED;
+    }
+
+    /************* Start the advertising *************/
+    xEventGroupClearBits(sEventGroup, CHIP_BLE_KW_EVNT_ADV_CHANGED | CHIP_BLE_KW_EVNT_ADV_FAILED);
+
+    if (gBleSuccess_c != Gap_CreateRandomDeviceAddress(NULL, NULL))
+    {
+        return BLE_E_SET_ADV_PARAMS;
+    }
+
+    eventBits = xEventGroupWaitBits(sEventGroup, CHIP_BLE_KW_EVNT_RND_ADDR_SET, pdTRUE, pdTRUE, CHIP_BLE_KW_EVNT_TIMEOUT);
+
+    if (!(eventBits & CHIP_BLE_KW_EVNT_RND_ADDR_SET))
+    {
+        return BLE_E_ADV_PARAMS_FAILED;
+    }
+
+    /* Start the advertising */
+    if (Gap_StartAdvertising(blekw_gap_advertising_cb, blekw_gap_connection_cb) != gBleSuccess_c)
+    {
+        return BLE_E_START_ADV;
+    }
+
+#if defined(chip_with_low_power) && (chip_with_low_power == 1)
+    PWR_DisallowDeviceToSleep();
+#endif
+
+    eventBits = xEventGroupWaitBits(sEventGroup, CHIP_BLE_KW_EVNT_ADV_CHANGED | CHIP_BLE_KW_EVNT_ADV_FAILED, pdTRUE, pdFALSE,
+                                    CHIP_BLE_KW_EVNT_TIMEOUT);
+    if (!(eventBits & CHIP_BLE_KW_EVNT_ADV_CHANGED))
+    {
+#if defined(chip_with_low_power) && (chip_with_low_power == 1)
+        PWR_AllowDeviceToSleep();
+#endif
+        return BLE_E_START_ADV_FAILED;
+    }
+
+#if defined(chip_with_low_power) && (chip_with_low_power == 1)
+    PWR_AllowDeviceToSleep();
+#endif
+
+    return BLE_OK;
+}
+
+BLEManagerCommon::ble_err_t BLEManagerCommon::blekw_stop_advertising(void)
+{
+    EventBits_t eventBits;
+    bleResult_t res;
+
+    xEventGroupClearBits(sEventGroup, CHIP_BLE_KW_EVNT_ADV_CHANGED | CHIP_BLE_KW_EVNT_ADV_FAILED);
+
+    /* Stop the advertising data */
+    res = Gap_StopAdvertising();
+    if (res != gBleSuccess_c)
+    {
+        ChipLogProgress(DeviceLayer, "Failed to stop advertising %d", res);
+        return BLE_E_STOP;
+    }
+
+    eventBits = xEventGroupWaitBits(sEventGroup, CHIP_BLE_KW_EVNT_ADV_CHANGED | CHIP_BLE_KW_EVNT_ADV_FAILED, pdTRUE, pdFALSE,
+                                    CHIP_BLE_KW_EVNT_TIMEOUT);
+
+    if (eventBits & CHIP_BLE_KW_EVNT_ADV_FAILED)
+    {
+        ChipLogProgress(DeviceLayer, "Stop advertising flat out failed.");
+        return BLE_E_ADV_FAILED;
+    }
+    else if (!(eventBits & CHIP_BLE_KW_EVNT_ADV_CHANGED))
+    {
+        ChipLogProgress(DeviceLayer, "Stop advertising event timeout.");
+        return BLE_E_ADV_CHANGED;
+    }
+
+    return BLE_OK;
+}
+
+CHIP_ERROR BLEManagerCommon::ConfigureAdvertisingData(void)
+{
+    ble_err_t err;
+    CHIP_ERROR chipErr;
+    uint16_t discriminator;
+    uint16_t advInterval                                  = 0;
+    gapAdvertisingData_t adv                              = { 0 };
+    gapAdStructure_t adv_data[BLEKW_ADV_MAX_NO]           = { { 0 } };
+    gapAdStructure_t scan_rsp_data[BLEKW_SCAN_RSP_MAX_NO] = { { 0 } };
+    uint8_t advPayload[BLEKW_MAX_ADV_DATA_LEN]            = { 0 };
+    gapScanResponseData_t scanRsp                         = { 0 };
+    gapAdvertisingParameters_t adv_params                 = { 0 };
+    uint8_t chipAdvDataFlags                              = (gLeGeneralDiscoverableMode_c | gBrEdrNotSupported_c);
+    uint8_t chipOverBleService[2];
+    ChipBLEDeviceIdentificationInfo mDeviceIdInfo = { 0 };
+    uint8_t mDeviceIdInfoLength                   = 0;
+
+    chipErr = GetCommissionableDataProvider()->GetSetupDiscriminator(discriminator);
+    if (chipErr != CHIP_NO_ERROR)
+    {
+        return chipErr;
+    }
+
+    if (!mFlags.Has(Flags::kDeviceNameSet))
+    {
+        memset(mDeviceName, 0, kMaxDeviceNameLength);
+        snprintf(mDeviceName, kMaxDeviceNameLength, "%s%04u", CHIP_DEVICE_CONFIG_BLE_DEVICE_NAME_PREFIX, discriminator);
+    }
+
+    /**************** Prepare advertising data *******************************************/
+    adv.cNumAdStructures = BLEKW_ADV_MAX_NO;
+
+    chipErr = ConfigurationMgr().GetBLEDeviceIdentificationInfo(mDeviceIdInfo);
+    SuccessOrExit(chipErr);
+    mDeviceIdInfoLength = sizeof(mDeviceIdInfo);
+
+    if ((mDeviceIdInfoLength + CHIP_ADV_SHORT_UUID_LEN + 1) > BLEKW_MAX_ADV_DATA_LEN)
+    {
+        return CHIP_ERROR_INCORRECT_STATE;
+    }
+
+    adv_data[0].length = 0x02;
+    adv_data[0].adType = gAdFlags_c;
+    adv_data[0].aData  = (uint8_t *) (&chipAdvDataFlags);
+
+    adv_data[1].length = static_cast<uint8_t>(mDeviceIdInfoLength + CHIP_ADV_SHORT_UUID_LEN + 1);
+    adv_data[1].adType = gAdServiceData16bit_c;
+    memcpy(advPayload, ShortUUID_CHIPoBLEService, CHIP_ADV_SHORT_UUID_LEN);
+    memcpy(&advPayload[CHIP_ADV_SHORT_UUID_LEN], (void *) &mDeviceIdInfo, mDeviceIdInfoLength);
+    adv_data[1].aData = advPayload;
+
+    adv.aAdStructures = adv_data;
+
+#if CHIP_ENABLE_ADDITIONAL_DATA_ADVERTISING
+    ReturnErrorOnFailure(EncodeAdditionalDataTlv());
+#endif
+
+    /**************** Prepare scan response data *******************************************/
+    scanRsp.cNumAdStructures = BLEKW_SCAN_RSP_MAX_NO;
+
+    scan_rsp_data[0].length = static_cast<uint8_t>(strlen(mDeviceName) + 1);
+    scan_rsp_data[0].adType = gAdCompleteLocalName_c;
+    scan_rsp_data[0].aData  = (uint8_t *) mDeviceName;
+
+    scan_rsp_data[1].length = sizeof(chipOverBleService) + 1;
+    scan_rsp_data[1].adType = gAdComplete16bitServiceList_c;
+    chipOverBleService[0]   = ShortUUID_CHIPoBLEService[0];
+    chipOverBleService[1]   = ShortUUID_CHIPoBLEService[1];
+    scan_rsp_data[1].aData  = (uint8_t *) chipOverBleService;
+
+    scanRsp.aAdStructures = scan_rsp_data;
+
+    /**************** Prepare advertising parameters *************************************/
+    if (mFlags.Has(Flags::kFastAdvertisingEnabled))
+    {
+        advInterval = CHIP_DEVICE_CONFIG_BLE_FAST_ADVERTISING_INTERVAL_MAX;
+    }
+    else
+    {
+        advInterval = CHIP_DEVICE_CONFIG_BLE_SLOW_ADVERTISING_INTERVAL_MAX;
+    }
+    advInterval = (uint16_t) (advInterval * 0.625F);
+
+    adv_params.minInterval = adv_params.maxInterval = advInterval;
+    adv_params.advertisingType                      = gAdvConnectableUndirected_c;
+    adv_params.ownAddressType                       = gBleAddrTypeRandom_c;
+    adv_params.peerAddressType                      = gBleAddrTypePublic_c;
+    memset(adv_params.peerAddress, 0, gcBleDeviceAddressSize_c);
+    adv_params.channelMap   = (gapAdvertisingChannelMapFlags_t) (gAdvChanMapFlag37_c | gAdvChanMapFlag38_c | gAdvChanMapFlag39_c);
+    adv_params.filterPolicy = gProcessAll_c;
+
+    err = blekw_start_advertising(&adv_params, &adv, &scanRsp);
+    if (err == BLE_OK)
+    {
+        ChipLogProgress(DeviceLayer, "Started Advertising at %d ms", advInterval);
+    }
+    else
+    {
+        ChipLogProgress(DeviceLayer, "Advertising error 0x%x!", err);
+        mFlags.Clear(Flags::kAdvertising);
+        return CHIP_ERROR_INCORRECT_STATE;
+    }
+
+exit:
+    return chipErr;
+}
+
+#if CHIP_ENABLE_ADDITIONAL_DATA_ADVERTISING
+CHIP_ERROR BLEManagerCommon::EncodeAdditionalDataTlv()
+{
+    CHIP_ERROR err = CHIP_NO_ERROR;
+    BitFlags<AdditionalDataFields> dataFields;
+    AdditionalDataPayloadGeneratorParams params;
+
+#if CHIP_ENABLE_ROTATING_DEVICE_ID && defined(CHIP_DEVICE_CONFIG_ROTATING_DEVICE_ID_UNIQUE_ID)
+    uint8_t rotatingDeviceIdUniqueId[ConfigurationManager::kRotatingDeviceIDUniqueIDLength] = {};
+    MutableByteSpan rotatingDeviceIdUniqueIdSpan(rotatingDeviceIdUniqueId);
+
+    err = DeviceLayer::GetDeviceInstanceInfoProvider()->GetRotatingDeviceIdUniqueId(rotatingDeviceIdUniqueIdSpan);
+    SuccessOrExit(err);
+    err = ConfigurationMgr().GetLifetimeCounter(params.rotatingDeviceIdLifetimeCounter);
+    SuccessOrExit(err);
+    params.rotatingDeviceIdUniqueId = rotatingDeviceIdUniqueIdSpan;
+    dataFields.Set(AdditionalDataFields::RotatingDeviceId);
+#endif /* CHIP_ENABLE_ROTATING_DEVICE_ID && defined(CHIP_DEVICE_CONFIG_ROTATING_DEVICE_ID_UNIQUE_ID) */
+    err = AdditionalDataPayloadGenerator().generateAdditionalDataPayload(params, sImplInstance->c3AdditionalDataBufferHandle,
+                                                                         dataFields);
+
+exit:
+    if (err != CHIP_NO_ERROR)
+    {
+        ChipLogError(DeviceLayer, "Failed to generate TLV encoded Additional Data (%s)", __func__);
+    }
+
+    return err;
+}
+
+void BLEManagerCommon::HandleC3ReadRequest(blekw_msg_t * msg)
+{
+    bleResult_t result;
+    blekw_att_read_data_t * att_rd_data = (blekw_att_read_data_t *) msg->data.data;
+    deviceId_t deviceId                 = att_rd_data->device_id;
+    uint16_t handle                     = att_rd_data->handle;
+    uint16_t length                     = sImplInstance->c3AdditionalDataBufferHandle->DataLength();
+    const uint8_t * data                = (const uint8_t *) sImplInstance->c3AdditionalDataBufferHandle->Start();
+
+    result = GattDb_WriteAttribute(handle, length, data);
+    if (result != gBleSuccess_c)
+    {
+        ChipLogError(DeviceLayer, "Failed to write C3 characteristic: %d", result);
+    }
+
+    result = GattServer_SendAttributeReadStatus(deviceId, handle, gAttErrCodeNoError_c);
+    if (result != gBleSuccess_c)
+    {
+        ChipLogError(DeviceLayer, "Failed to send response to C3 read request: %d", result);
+    }
+}
+#endif /* CHIP_ENABLE_ADDITIONAL_DATA_ADVERTISING */
+
+CHIP_ERROR BLEManagerCommon::StartAdvertising(void)
+{
+    CHIP_ERROR err = CHIP_NO_ERROR;
+
+    mFlags.Set(Flags::kAdvertising);
+    mFlags.Clear(Flags::kRestartAdvertising);
+
+    if (mFlags.Has(Flags::kFastAdvertisingEnabled))
+    {
+        StartBleAdvTimeoutTimer(CHIP_DEVICE_CONFIG_BLE_FAST_ADVERTISING_TIMEOUT);
+    }
+
+    err = ConfigureAdvertisingData();
+
+    if (err == CHIP_NO_ERROR)
+    /* schedule NFC emulation stop */
+    {
+        ChipDeviceEvent advChange;
+        advChange.Type                             = DeviceEventType::kCHIPoBLEAdvertisingChange;
+        advChange.CHIPoBLEAdvertisingChange.Result = kActivity_Started;
+        err                                        = PlatformMgr().PostEvent(&advChange);
+    }
+
+    return err;
+}
+
+CHIP_ERROR BLEManagerCommon::StopAdvertising(void)
+{
+    CHIP_ERROR error = CHIP_NO_ERROR;
+
+    if (mFlags.Has(Flags::kAdvertising))
+    {
+        mFlags.Clear(Flags::kAdvertising);
+        mFlags.Clear(Flags::kRestartAdvertising);
+
+        if (!mDeviceConnected)
+        {
+            ble_err_t err = blekw_stop_advertising();
+            VerifyOrReturnError(err == BLE_OK, CHIP_ERROR_INCORRECT_STATE);
+            CancelBleAdvTimeoutTimer();
+        }
+
+#if CONFIG_CHIP_NFC_COMMISSIONING
+        /* schedule NFC emulation stop */
+        ChipDeviceEvent advChange;
+        advChange.Type                             = DeviceEventType::kCHIPoBLEAdvertisingChange;
+        advChange.CHIPoBLEAdvertisingChange.Result = kActivity_Stopped;
+        error                                      = PlatformMgr().PostEvent(&advChange);
+#endif
+    }
+
+    return error;
+}
+
+void BLEManagerCommon::DriveBLEState(void)
+{
+    CHIP_ERROR err = CHIP_NO_ERROR;
+
+    // Check if BLE stack is initialized
+    VerifyOrExit(mFlags.Has(Flags::kK32WBLEStackInitialized), err = CHIP_ERROR_INCORRECT_STATE);
+
+    // Start advertising if needed...
+    if (mServiceMode == ConnectivityManager::kCHIPoBLEServiceMode_Enabled && mFlags.Has(Flags::kAdvertisingEnabled))
+    {
+        // Start/re-start advertising if not already started, or if there is a pending change
+        // to the advertising configuration.
+        if (!mFlags.Has(Flags::kAdvertising) || mFlags.Has(Flags::kRestartAdvertising))
+        {
+            err = StartAdvertising();
+            SuccessOrExit(err);
+        }
+    }
+    // Otherwise, stop advertising if it is enabled.
+    else if (mFlags.Has(Flags::kAdvertising))
+    {
+        err = StopAdvertising();
+        SuccessOrExit(err);
+        // Reset to fast advertising mode only if SetBLEAdvertisingEnabled(false) was called (usually from app).
+        mFlags.Set(Flags::kFastAdvertisingEnabled);
+    }
+
+exit:
+    if (err != CHIP_NO_ERROR)
+    {
+        ChipLogError(DeviceLayer, "Disabling CHIPoBLE service due to error: %s", ErrorStr(err));
+        mServiceMode = ConnectivityManager::kCHIPoBLEServiceMode_Disabled;
+    }
+}
+
+void BLEManagerCommon::DriveBLEState(intptr_t arg)
+{
+    sImplInstance->DriveBLEState();
+}
+
+void BLEManagerCommon::StopAdvertisingPriorToSwitchingMode(intptr_t arg)
+{
+    if (CHIP_NO_ERROR != sImplInstance->StopAdvertising())
+    {
+        ChipLogProgress(DeviceLayer, "Failed to stop advertising");
+    }
+}
+
+void BLEManagerCommon::DoBleProcessing(void)
+{
+    blekw_msg_t * msg = NULL;
+
+    while ((xQueueReceive(sBleEventQueue, &msg, 0) == pdTRUE) && msg)
+    {
+        if (msg->type == BLE_KW_MSG_ERROR)
+        {
+            if (msg->data.u8 == BLE_KW_MSG_2M_UPGRADE_ERROR)
+            {
+                ChipLogProgress(DeviceLayer,
+                                "Warning. BLE is using 1Mbps. Couldn't upgrade to 2Mbps, "
+                                "maybe the peer is missing 2Mbps support.");
+            }
+            else
+            {
+                ChipLogProgress(DeviceLayer, "BLE Error: %d.\n", msg->data.u8);
+            }
+        }
+        else if (msg->type == BLE_KW_MSG_CONNECTED)
+        {
+            sImplInstance->HandleConnectEvent(msg);
+        }
+        else if (msg->type == BLE_KW_MSG_DISCONNECTED)
+        {
+            sImplInstance->HandleConnectionCloseEvent(msg);
+        }
+        else if (msg->type == BLE_KW_MSG_MTU_CHANGED)
+        {
+            blekw_start_connection_timeout();
+            ChipLogProgress(DeviceLayer, "BLE MTU size has been changed to %d.", msg->data.u16);
+        }
+        else if (msg->type == BLE_KW_MSG_ATT_WRITTEN || msg->type == BLE_KW_MSG_ATT_LONG_WRITTEN ||
+                 msg->type == BLE_KW_MSG_ATT_CCCD_WRITTEN)
+        {
+            sImplInstance->HandleWriteEvent(msg);
+        }
+        else if (msg->type == BLE_KW_MSG_ATT_READ)
+        {
+#if CHIP_ENABLE_ADDITIONAL_DATA_ADVERTISING
+            blekw_att_read_data_t * att_rd_data = (blekw_att_read_data_t *) msg->data.data;
+            if (value_chipoble_c3 == att_rd_data->handle)
+                sImplInstance->HandleC3ReadRequest(msg);
+#endif
+        }
+        else if (msg->type == BLE_KW_MSG_FORCE_DISCONNECT)
+        {
+            sImplInstance->HandleForceDisconnect();
+        }
+
+        /* Free the message from the queue */
+        free(msg);
+        msg = NULL;
+    }
+}
+
+void BLEManagerCommon::RegisterAppCallbacks(BLECallbackDelegate::GapGenericCallback gapCallback,
+                                            BLECallbackDelegate::GattServerCallback gattCallback)
+{
+    callbackDelegate.gapCallback  = gapCallback;
+    callbackDelegate.gattCallback = gattCallback;
+}
+
+void BLEManagerCommon::HandleConnectEvent(blekw_msg_t * msg)
+{
+    uint8_t deviceId = msg->data.u8;
+    ChipLogProgress(DeviceLayer, "BLE is connected with device: %d.\n", deviceId);
+
+#if gClkUseFro32K && defined(chip_with_low_power) && (chip_with_low_power == 1)
+    PWR_DisallowDeviceToSleep();
+#endif
+
+    mDeviceId        = deviceId;
+    mDeviceConnected = true;
+
+    blekw_start_connection_timeout();
+    PlatformMgr().ScheduleWork(DriveBLEState, 0);
+}
+
+void BLEManagerCommon::HandleConnectionCloseEvent(blekw_msg_t * msg)
+{
+    uint8_t deviceId = msg->data.u8;
+    ChipLogProgress(DeviceLayer, "BLE is disconnected with device: %d.\n", deviceId);
+
+#if gClkUseFro32K && defined(chip_with_low_power) && (chip_with_low_power == 1)
+    PWR_AllowDeviceToSleep();
+#endif
+
+    mDeviceConnected = false;
+
+    ChipDeviceEvent event;
+    event.Type                           = DeviceEventType::kCHIPoBLEConnectionClosed;
+    event.CHIPoBLEConnectionError.ConId  = deviceId;
+    event.CHIPoBLEConnectionError.Reason = BLE_ERROR_REMOTE_DEVICE_DISCONNECTED;
+
+    CancelBleAdvTimeoutTimer();
+
+    PlatformMgr().PostEventOrDie(&event);
+    mFlags.Set(Flags::kRestartAdvertising);
+    mFlags.Set(Flags::kFastAdvertisingEnabled);
+    PlatformMgr().ScheduleWork(DriveBLEState, 0);
+}
+
+void BLEManagerCommon::HandleWriteEvent(blekw_msg_t * msg)
+{
+    blekw_att_written_data_t * att_wr_data = (blekw_att_written_data_t *) msg->data.data;
+    attErrorCode_t status                  = gAttErrCodeNoError_c;
+
+#if CHIP_DEVICE_CHIP0BLE_DEBUG
+    ChipLogProgress(DeviceLayer, "Attribute write request(device: %d,handle: %d).", att_wr_data->device_id, att_wr_data->handle);
+#endif
+
+    blekw_start_connection_timeout();
+
+    if (value_chipoble_rx == att_wr_data->handle)
+    {
+        sImplInstance->HandleRXCharWrite(msg);
+    }
+    else if (cccd_chipoble_tx == att_wr_data->handle)
+    {
+        sImplInstance->HandleTXCharCCCDWrite(msg);
+    }
+
+    /* TODO: do we need to send the status also for CCCD_WRITTEN? */
+    if (msg->type != BLE_KW_MSG_ATT_CCCD_WRITTEN)
+    {
+        bleResult_t res = GattServer_SendAttributeWrittenStatus(att_wr_data->device_id, att_wr_data->handle, status);
+
+        if (res != gBleSuccess_c)
+        {
+            ChipLogProgress(DeviceLayer, "GattServer_SendAttributeWrittenStatus returned %d", res);
+        }
+    }
+}
+
+void BLEManagerCommon::HandleTXCharCCCDWrite(blekw_msg_t * msg)
+{
+    CHIP_ERROR err                         = CHIP_NO_ERROR;
+    blekw_att_written_data_t * att_wr_data = (blekw_att_written_data_t *) msg->data.data;
+    ChipDeviceEvent event;
+
+    VerifyOrExit(att_wr_data->length != 0, err = CHIP_ERROR_INCORRECT_STATE);
+    VerifyOrExit(att_wr_data->data != nullptr, err = CHIP_ERROR_INCORRECT_STATE);
+
+#if CHIP_DEVICE_CHIP0BLE_DEBUG
+    ChipLogProgress(DeviceLayer, "CHIPoBLE %s received", *att_wr_data->data ? "subscribe" : "unsubscribe");
+#endif
+
+    if (*att_wr_data->data)
+    {
+        if (!mDeviceSubscribed)
+        {
+            mDeviceSubscribed             = true;
+            event.Type                    = DeviceEventType::kCHIPoBLESubscribe;
+            event.CHIPoBLESubscribe.ConId = att_wr_data->device_id;
+            err                           = PlatformMgr().PostEvent(&event);
+        }
+    }
+    else
+    {
+        mDeviceSubscribed             = false;
+        event.Type                    = DeviceEventType::kCHIPoBLEUnsubscribe;
+        event.CHIPoBLESubscribe.ConId = att_wr_data->device_id;
+        err                           = PlatformMgr().PostEvent(&event);
+    }
+
+exit:
+    if (err != CHIP_NO_ERROR)
+    {
+        ChipLogError(DeviceLayer, "HandleTXCharCCCDWrite() failed: %s", ErrorStr(err));
+    }
+}
+
+void BLEManagerCommon::HandleRXCharWrite(blekw_msg_t * msg)
+{
+    CHIP_ERROR err = CHIP_NO_ERROR;
+    System::PacketBufferHandle buf;
+    blekw_att_written_data_t * att_wr_data = (blekw_att_written_data_t *) msg->data.data;
+
+    VerifyOrExit(att_wr_data->length != 0, err = CHIP_ERROR_INCORRECT_STATE);
+    VerifyOrExit(att_wr_data->data != nullptr, err = CHIP_ERROR_INCORRECT_STATE);
+
+    // Copy the data to a PacketBuffer.
+    buf = System::PacketBufferHandle::NewWithData(att_wr_data->data, att_wr_data->length);
+    VerifyOrExit(!buf.IsNull(), err = CHIP_ERROR_NO_MEMORY);
+
+#if CHIP_DEVICE_CHIP0BLE_DEBUG
+    ChipLogDetail(DeviceLayer,
+                  "Write request/command received for"
+                  "CHIPoBLE RX characteristic (con %u, len %u)",
+                  att_wr_data->device_id, buf->DataLength());
+#endif
+
+    // Post an event to the CHIP queue to deliver the data into the CHIP stack.
+    {
+        ChipDeviceEvent event;
+        event.Type                        = DeviceEventType::kCHIPoBLEWriteReceived;
+        event.CHIPoBLEWriteReceived.ConId = att_wr_data->device_id;
+        event.CHIPoBLEWriteReceived.Data  = std::move(buf).UnsafeRelease();
+        err                               = PlatformMgr().PostEvent(&event);
+    }
+exit:
+    if (err != CHIP_NO_ERROR)
+    {
+        ChipLogError(DeviceLayer, "HandleRXCharWrite() failed: %s", ErrorStr(err));
+    }
+}
+
+void BLEManagerCommon::HandleForceDisconnect()
+{
+    ChipLogProgress(DeviceLayer, "BLE connection timeout: Forcing disconnection.");
+
+    /* Set the advertising parameters */
+    if (Gap_Disconnect(mDeviceId) != gBleSuccess_c)
+    {
+        ChipLogProgress(DeviceLayer, "Gap_Disconnect() failed.");
+    }
+
+#if defined(chip_with_low_power) && (chip_with_low_power == 1)
+    PWR_AllowDeviceToSleep();
+#endif
+}
+
+/*******************************************************************************
+ * BLE stack callbacks
+ *******************************************************************************/
+void BLEManagerCommon::blekw_generic_cb(gapGenericEvent_t * pGenericEvent)
+{
+    /* Call BLE Conn Manager */
+    BleConnManager_GenericEvent(pGenericEvent);
+
+    if (sImplInstance && sImplInstance->callbackDelegate.gapCallback)
+    {
+        sImplInstance->callbackDelegate.gapCallback(pGenericEvent);
+    }
+
+    switch (pGenericEvent->eventType)
+    {
+    case gInternalError_c:
+        /* Notify the CHIP that the BLE hardware report fail */
+        ChipLogProgress(DeviceLayer, "BLE Internal Error: Code 0x%04X, Source 0x%08X, HCI OpCode %d.\n",
+                        pGenericEvent->eventData.internalError.errorCode, pGenericEvent->eventData.internalError.errorSource,
+                        pGenericEvent->eventData.internalError.hciCommandOpcode);
+        if ((gHciUnsupportedRemoteFeature_c == pGenericEvent->eventData.internalError.errorCode) &&
+            (gLeSetPhy_c == pGenericEvent->eventData.internalError.errorSource))
+        {
+            (void) blekw_msg_add_u8(BLE_KW_MSG_ERROR, BLE_KW_MSG_2M_UPGRADE_ERROR);
+        }
+        else
+        {
+            (void) blekw_msg_add_u8(BLE_KW_MSG_ERROR, BLE_INTERNAL_ERROR);
+        }
+        break;
+
+    case gAdvertisingSetupFailed_c:
+        xEventGroupSetBits(sEventGroup, CHIP_BLE_KW_EVNT_ADV_SETUP_FAILED);
+        break;
+
+    case gAdvertisingParametersSetupComplete_c:
+        xEventGroupSetBits(sEventGroup, CHIP_BLE_KW_EVNT_ADV_PAR_SETUP_COMPLETE);
+        break;
+
+    case gAdvertisingDataSetupComplete_c:
+        xEventGroupSetBits(sEventGroup, CHIP_BLE_KW_EVNT_ADV_DAT_SETUP_COMPLETE);
+        break;
+
+    case gRandomAddressReady_c:
+        Gap_SetRandomAddress(pGenericEvent->eventData.addrReady.aAddress);
+        break;
+
+    case gRandomAddressSet_c:
+        xEventGroupSetBits(sEventGroup, CHIP_BLE_KW_EVNT_RND_ADDR_SET);
+        break;
+
+#if BLE_HIGH_TX_POWER
+    case gTxPowerLevelSetComplete_c:
+        if (gBleSuccess_c == pGenericEvent->eventData.txPowerLevelSetStatus)
+        {
+            xEventGroupSetBits(sEventGroup, CHIP_BLE_KW_EVNT_POWER_LEVEL_SET);
+        }
+        break;
+#endif
+
+    case gInitializationComplete_c:
+        /* Common GAP configuration */
+        BleConnManager_GapCommonConfig();
+
+        /* Set the local synchronization event */
+        xEventGroupSetBits(sEventGroup, CHIP_BLE_KW_EVNT_INIT_COMPLETE);
+        break;
+    default:
+        break;
+    }
+}
+
+void BLEManagerCommon::blekw_gap_advertising_cb(gapAdvertisingEvent_t * pAdvertisingEvent)
+{
+    if (pAdvertisingEvent->eventType == gAdvertisingStateChanged_c)
+    {
+        /* Set the local synchronization event */
+        xEventGroupSetBits(sEventGroup, CHIP_BLE_KW_EVNT_ADV_CHANGED);
+    }
+    else
+    {
+        /* The advertisement start failed */
+        ChipLogProgress(DeviceLayer, "Advertising failed: event=%d reason=0x%04X\n", pAdvertisingEvent->eventType,
+                        pAdvertisingEvent->eventData.failReason);
+
+        /* Set the local synchronization event */
+        xEventGroupSetBits(sEventGroup, CHIP_BLE_KW_EVNT_ADV_FAILED);
+    }
+}
+
+void BLEManagerCommon::blekw_gap_connection_cb(deviceId_t deviceId, gapConnectionEvent_t * pConnectionEvent)
+{
+    /* Call BLE Conn Manager */
+    BleConnManager_GapPeripheralEvent(deviceId, pConnectionEvent);
+
+    if (pConnectionEvent->eventType == gConnEvtConnected_c)
+    {
+#if CHIP_DEVICE_K32W1
+#if defined(chip_with_low_power) && (chip_with_low_power == 1)
+        /* Disallow must be called here for K32W1, otherwise an assert will be reached.
+         * Disclaimer: this is a workaround until a better cross platform solution is found. */
+        PWR_DisallowDeviceToSleep();
+#endif
+#endif
+
+#if CHIP_DEVICE_CONFIG_BLE_SET_PHY_2M_REQ
+        ChipLogProgress(DeviceLayer, "BLE K32W: Trying to set the PHY to 2M");
+
+        (void) Gap_LeSetPhy(FALSE, deviceId, 0, gConnPhyUpdateReqTxPhySettings_c, gConnPhyUpdateReqRxPhySettings_c,
+                            (uint16_t) gConnPhyUpdateReqPhyOptions_c);
+#endif
+
+        /* Notify App Task that the BLE is connected now */
+        (void) blekw_msg_add_u8(BLE_KW_MSG_CONNECTED, (uint8_t) deviceId);
+#if defined(chip_with_low_power) && (chip_with_low_power == 1)
+        PWR_AllowDeviceToSleep();
+#endif
+    }
+    else if (pConnectionEvent->eventType == gConnEvtDisconnected_c)
+    {
+        blekw_stop_connection_timeout();
+
+        /* Notify App Task that the BLE is disconnected now */
+        (void) blekw_msg_add_u8(BLE_KW_MSG_DISCONNECTED, (uint8_t) deviceId);
+
+#if defined(chip_with_low_power) && (chip_with_low_power == 1)
+        if (bleAppStopInProgress == TRUE)
+        {
+            bleAppStopInProgress = FALSE;
+            PWR_AllowDeviceToSleep();
+        }
+#endif
+    }
+    else if (pConnectionEvent->eventType == gConnEvtPairingRequest_c)
+    {
+        /* Reject request for pairing */
+        Gap_RejectPairing(deviceId, gPairingNotSupported_c);
+    }
+    else if (pConnectionEvent->eventType == gConnEvtAuthenticationRejected_c)
+    {
+        ChipLogProgress(DeviceLayer, "BLE Authentication rejected (reason:%d).\n",
+                        pConnectionEvent->eventData.authenticationRejectedEvent.rejectReason);
+    }
+}
+
+void BLEManagerCommon::blekw_connection_timeout_cb(TimerHandle_t timer)
+{
+    (void) blekw_msg_add_u8(BLE_KW_MSG_FORCE_DISCONNECT, 0);
+}
+
+void BLEManagerCommon::blekw_start_connection_timeout(void)
+{
+    xTimerReset(connectionTimeout, 0);
+}
+
+void BLEManagerCommon::blekw_stop_connection_timeout(void)
+{
+    ChipLogProgress(DeviceLayer, "Stopped connectionTimeout timer.");
+    xTimerStop(connectionTimeout, 0);
+}
+
+void BLEManagerCommon::blekw_gatt_server_cb(deviceId_t deviceId, gattServerEvent_t * pServerEvent)
+{
+    if (sImplInstance && sImplInstance->callbackDelegate.gattCallback)
+    {
+        sImplInstance->callbackDelegate.gattCallback(deviceId, pServerEvent);
+    }
+
+    switch (pServerEvent->eventType)
+    {
+    case gEvtMtuChanged_c: {
+        uint16_t tempMtu = 0;
+
+        (void) Gatt_GetMtu(deviceId, &tempMtu);
+        blekw_msg_add_u16(BLE_KW_MSG_MTU_CHANGED, tempMtu);
+        break;
+    }
+
+    case gEvtAttributeWritten_c:
+        blekw_msg_add_att_written(BLE_KW_MSG_ATT_WRITTEN, deviceId, pServerEvent->eventData.attributeWrittenEvent.handle,
+                                  pServerEvent->eventData.attributeWrittenEvent.aValue,
+                                  pServerEvent->eventData.attributeWrittenEvent.cValueLength);
+        break;
+
+    case gEvtLongCharacteristicWritten_c:
+        blekw_msg_add_att_written(BLE_KW_MSG_ATT_LONG_WRITTEN, deviceId, pServerEvent->eventData.longCharWrittenEvent.handle,
+                                  pServerEvent->eventData.longCharWrittenEvent.aValue,
+                                  pServerEvent->eventData.longCharWrittenEvent.cValueLength);
+        break;
+
+    case gEvtAttributeRead_c:
+        blekw_msg_add_att_read(BLE_KW_MSG_ATT_READ, deviceId, pServerEvent->eventData.attributeReadEvent.handle);
+        break;
+
+    case gEvtCharacteristicCccdWritten_c: {
+        uint16_t cccd_val = pServerEvent->eventData.charCccdWrittenEvent.newCccd;
+
+        blekw_msg_add_att_written(BLE_KW_MSG_ATT_CCCD_WRITTEN, deviceId, pServerEvent->eventData.charCccdWrittenEvent.handle,
+                                  (uint8_t *) &cccd_val, 2);
+        break;
+    }
+
+    case gEvtHandleValueConfirmation_c:
+        /* Set the local synchronization event */
+        xEventGroupSetBits(sEventGroup, CHIP_BLE_KW_EVNT_INDICATION_CONFIRMED);
+        break;
+
+    case gEvtError_c:
+        if (pServerEvent->eventData.procedureError.procedureType == gSendIndication_c)
+        {
+            /* Set the local synchronization event */
+            xEventGroupSetBits(sEventGroup, CHIP_BLE_KW_EVNT_INDICATION_FAILED);
+        }
+        else
+        {
+            ChipLogProgress(DeviceLayer, "BLE Gatt Server Error: Code 0x%04X, Source %d.\n",
+                            pServerEvent->eventData.procedureError.error, pServerEvent->eventData.procedureError.procedureType);
+
+            /* Notify CHIP BLE App Task that the BLE hardware report fail */
+            (void) blekw_msg_add_u8(BLE_KW_MSG_ERROR, BLE_INTERNAL_GATT_ERROR);
+        }
+        break;
+
+    default:
+        break;
+    }
+}
+/*******************************************************************************
+ * Add to message queue functions
+ *******************************************************************************/
+CHIP_ERROR BLEManagerCommon::blekw_msg_add_att_written(blekw_msg_type_t type, uint8_t device_id, uint16_t handle, uint8_t * data,
+                                                       uint16_t length)
+{
+    CHIP_ERROR err    = CHIP_NO_ERROR;
+    blekw_msg_t * msg = NULL;
+    blekw_att_written_data_t * att_wr_data;
+
+    /* Allocate a buffer with enough space to store the packet */
+    msg = (blekw_msg_t *) malloc(sizeof(blekw_msg_t) + sizeof(blekw_att_written_data_t) + length);
+    VerifyOrExit(msg, err = CHIP_ERROR_NO_MEMORY);
+
+    msg->type              = type;
+    msg->length            = sizeof(blekw_att_written_data_t) + length;
+    att_wr_data            = (blekw_att_written_data_t *) msg->data.data;
+    att_wr_data->device_id = device_id;
+    att_wr_data->handle    = handle;
+    att_wr_data->length    = length;
+    FLib_MemCpy(att_wr_data->data, data, length);
+
+    VerifyOrExit(xQueueSend(sBleEventQueue, &msg, 0) == pdTRUE, err = CHIP_ERROR_NO_MEMORY);
+    otTaskletsSignalPending(NULL);
+
+exit:
+    return err;
+}
+
+CHIP_ERROR BLEManagerCommon::blekw_msg_add_att_read(blekw_msg_type_t type, uint8_t device_id, uint16_t handle)
+{
+    CHIP_ERROR err    = CHIP_NO_ERROR;
+    blekw_msg_t * msg = NULL;
+    blekw_att_read_data_t * att_rd_data;
+
+    /* Allocate a buffer with enough space to store the packet */
+    msg = (blekw_msg_t *) malloc(sizeof(blekw_msg_t) + sizeof(blekw_att_read_data_t));
+    VerifyOrExit(msg, err = CHIP_ERROR_NO_MEMORY);
+
+    msg->type              = type;
+    msg->length            = sizeof(blekw_att_read_data_t);
+    att_rd_data            = (blekw_att_read_data_t *) msg->data.data;
+    att_rd_data->device_id = device_id;
+    att_rd_data->handle    = handle;
+
+    VerifyOrExit(xQueueSend(sBleEventQueue, &msg, 0) == pdTRUE, err = CHIP_ERROR_NO_MEMORY);
+    otTaskletsSignalPending(NULL);
+
+exit:
+    return err;
+}
+
+CHIP_ERROR BLEManagerCommon::blekw_msg_add_u8(blekw_msg_type_t type, uint8_t data)
+{
+    CHIP_ERROR err    = CHIP_NO_ERROR;
+    blekw_msg_t * msg = NULL;
+
+    /* Allocate a buffer with enough space to store the packet */
+    msg = (blekw_msg_t *) malloc(sizeof(blekw_msg_t));
+    VerifyOrExit(msg, err = CHIP_ERROR_NO_MEMORY);
+
+    msg->type    = type;
+    msg->length  = 0;
+    msg->data.u8 = data;
+
+    VerifyOrExit(xQueueSend(sBleEventQueue, &msg, 0) == pdTRUE, err = CHIP_ERROR_NO_MEMORY);
+    otTaskletsSignalPending(NULL);
+
+exit:
+    return err;
+}
+
+CHIP_ERROR BLEManagerCommon::blekw_msg_add_u16(blekw_msg_type_t type, uint16_t data)
+{
+    CHIP_ERROR err    = CHIP_NO_ERROR;
+    blekw_msg_t * msg = NULL;
+
+    /* Allocate a buffer with enough space to store the packet */
+    msg = (blekw_msg_t *) malloc(sizeof(blekw_msg_t));
+    VerifyOrExit(msg, err = CHIP_ERROR_NO_MEMORY);
+
+    msg->type     = type;
+    msg->length   = 0;
+    msg->data.u16 = data;
+
+    VerifyOrExit(xQueueSend(sBleEventQueue, &msg, 0) == pdTRUE, err = CHIP_ERROR_NO_MEMORY);
+    otTaskletsSignalPending(NULL);
+
+exit:
+    return err;
+}
+
+void BLEManagerCommon::BleAdvTimeoutHandler(TimerHandle_t xTimer)
+{
+    if (BLEMgrImpl().mFlags.Has(Flags::kFastAdvertisingEnabled))
+    {
+        ChipLogDetail(DeviceLayer, "Start slow advertisement");
+        BLEMgr().SetAdvertisingMode(BLEAdvertisingMode::kSlowAdvertising);
+    }
+}
+
+void BLEManagerCommon::CancelBleAdvTimeoutTimer(void)
+{
+    if (xTimerStop(sbleAdvTimeoutTimer, 0) == pdFAIL)
+    {
+        ChipLogError(DeviceLayer, "Failed to stop BledAdv timeout timer");
+    }
+}
+
+void BLEManagerCommon::StartBleAdvTimeoutTimer(uint32_t aTimeoutInMs)
+{
+    if (xTimerIsTimerActive(sbleAdvTimeoutTimer))
+    {
+        CancelBleAdvTimeoutTimer();
+    }
+
+    // timer is not active, change its period to required value (== restart).
+    // FreeRTOS- Block for a maximum of 100 ticks if the change period command
+    // cannot immediately be sent to the timer command queue.
+    if (xTimerChangePeriod(sbleAdvTimeoutTimer, aTimeoutInMs / portTICK_PERIOD_MS, 100) != pdPASS)
+    {
+        ChipLogError(DeviceLayer, "Failed to start BledAdv timeout timer");
+    }
+}
+
+CHIP_ERROR BLEManagerCommon::blekw_stop_connection_internal(BLE_CONNECTION_OBJECT conId)
+{
+    ChipLogProgress(DeviceLayer, "Closing BLE GATT connection (con %u)", conId);
+
+    if (Gap_Disconnect(conId) != gBleSuccess_c)
+    {
+        ChipLogProgress(DeviceLayer, "Gap_Disconnect() failed.");
+        return CHIP_ERROR_INTERNAL;
+    }
+#if defined(chip_with_low_power) && (chip_with_low_power == 1)
+    else
+    {
+        bleAppStopInProgress = TRUE;
+        PWR_DisallowDeviceToSleep();
+    }
+#endif
+
+    return CHIP_NO_ERROR;
+}
+
+} // namespace Internal
+} // namespace DeviceLayer
+} // namespace chip
+#endif // CHIP_DEVICE_CONFIG_ENABLE_CHIPOBLE
diff --git a/src/platform/nxp/common/legacy/BLEManagerCommon.h b/src/platform/nxp/common/legacy/BLEManagerCommon.h
new file mode 100644
index 00000000000000..b7fc1275d2501f
--- /dev/null
+++ b/src/platform/nxp/common/legacy/BLEManagerCommon.h
@@ -0,0 +1,249 @@
+/*
+ *
+ *    Copyright (c) 2020-2021 Project CHIP Authors
+ *    Copyright (c) 2020 Nest Labs, Inc.
+ *    All rights reserved.
+ *
+ *    Licensed under the Apache License, Version 2.0 (the "License");
+ *    you may not use this file except in compliance with the License.
+ *    You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *    Unless required by applicable law or agreed to in writing, software
+ *    distributed under the License is distributed on an "AS IS" BASIS,
+ *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *    See the License for the specific language governing permissions and
+ *    limitations under the License.
+ */
+
+/**
+ *    @file
+ *          Provides an implementation of the BLEManager singleton object
+ *          for the K32W platforms.
+ */
+
+#pragma once
+
+#if CHIP_DEVICE_CONFIG_ENABLE_CHIPOBLE
+
+#include "fsl_os_abstraction.h"
+
+#include "ble_conn_manager.h"
+#include "ble_general.h"
+#include "ble_host_task_config.h"
+#include "ble_host_tasks.h"
+#include "gap_interface.h"
+#include "gatt_db_dynamic.h"
+#include "gatt_server_interface.h"
+
+#include "FreeRTOS.h"
+#include "event_groups.h"
+#include "timers.h"
+
+namespace chip {
+namespace DeviceLayer {
+namespace Internal {
+
+using namespace chip::Ble;
+
+/**
+ * A delegate class that can be used by the application to subscribe to BLE events.
+ */
+struct BLECallbackDelegate
+{
+    using GapGenericCallback = void (*)(gapGenericEvent_t * event);
+    using GattServerCallback = void (*)(deviceId_t id, gattServerEvent_t * event);
+
+    GapGenericCallback gapCallback  = nullptr;
+    GattServerCallback gattCallback = nullptr;
+};
+
+/**
+ * Base class for different platform implementations (K32W0 and K32W1 for now).
+ */
+class BLEManagerCommon : public BLEManager, protected BleLayer, private BlePlatformDelegate, private BleApplicationDelegate
+{
+protected:
+    // ===== Members that implement the BLEManager internal interface.
+
+    CHIP_ERROR _Init(void);
+    CHIP_ERROR _Shutdown() { return CHIP_NO_ERROR; }
+    CHIPoBLEServiceMode _GetCHIPoBLEServiceMode(void);
+    CHIP_ERROR _SetCHIPoBLEServiceMode(CHIPoBLEServiceMode val);
+    bool _IsAdvertisingEnabled(void);
+    CHIP_ERROR _SetAdvertisingEnabled(bool val);
+    bool _IsAdvertising(void);
+    CHIP_ERROR _SetAdvertisingMode(BLEAdvertisingMode mode);
+    CHIP_ERROR _GetDeviceName(char * buf, size_t bufSize);
+    CHIP_ERROR _SetDeviceName(const char * deviceName);
+    uint16_t _NumConnections(void);
+    void _OnPlatformEvent(const ChipDeviceEvent * event);
+
+    // ===== Members that implement virtual methods on BlePlatformDelegate.
+
+    CHIP_ERROR SubscribeCharacteristic(BLE_CONNECTION_OBJECT conId, const Ble::ChipBleUUID * svcId,
+                                       const Ble::ChipBleUUID * charId) override;
+    CHIP_ERROR UnsubscribeCharacteristic(BLE_CONNECTION_OBJECT conId, const Ble::ChipBleUUID * svcId,
+                                         const Ble::ChipBleUUID * charId) override;
+    CHIP_ERROR CloseConnection(BLE_CONNECTION_OBJECT conId) override;
+    uint16_t GetMTU(BLE_CONNECTION_OBJECT conId) const override;
+    CHIP_ERROR SendIndication(BLE_CONNECTION_OBJECT conId, const Ble::ChipBleUUID * svcId, const Ble::ChipBleUUID * charId,
+                              System::PacketBufferHandle pBuf) override;
+    CHIP_ERROR SendWriteRequest(BLE_CONNECTION_OBJECT conId, const Ble::ChipBleUUID * svcId, const Ble::ChipBleUUID * charId,
+                                System::PacketBufferHandle pBuf) override;
+
+    // ===== Members that implement virtual methods on BleApplicationDelegate.
+
+    void NotifyChipConnectionClosed(BLE_CONNECTION_OBJECT conId) override;
+
+    // ===== Private members reserved for use by this class only.
+
+    enum class Flags : uint8_t
+    {
+        kAdvertisingEnabled      = 0x0001,
+        kFastAdvertisingEnabled  = 0x0002,
+        kAdvertising             = 0x0004,
+        kRestartAdvertising      = 0x0008,
+        kK32WBLEStackInitialized = 0x0010,
+        kDeviceNameSet           = 0x0020,
+    };
+    BitFlags<BLEManagerCommon::Flags> mFlags;
+
+    enum
+    {
+        kMaxDeviceNameLength = 16,
+        kUnusedIndex         = 0xFF,
+    };
+
+    typedef enum
+    {
+        BLE_KW_MSG_ERROR = 0x01,
+        BLE_KW_MSG_CONNECTED,
+        BLE_KW_MSG_DISCONNECTED,
+        BLE_KW_MSG_MTU_CHANGED,
+        BLE_KW_MSG_ATT_WRITTEN,
+        BLE_KW_MSG_ATT_LONG_WRITTEN,
+        BLE_KW_MSG_ATT_READ,
+        BLE_KW_MSG_ATT_CCCD_WRITTEN,
+        BLE_KW_MSG_FORCE_DISCONNECT,
+    } blekw_msg_type_t;
+
+    typedef struct hk_ble_kw_msg_s
+    {
+        blekw_msg_type_t type;
+        uint16_t length;
+        union
+        {
+            uint8_t u8;
+            uint16_t u16;
+            uint32_t u32;
+            uint8_t data[1];
+            char * str;
+        } data;
+    } blekw_msg_t;
+
+    typedef enum ble_err_t
+    {
+        BLE_OK = 0,
+        BLE_INTERNAL_GATT_ERROR,
+        BLE_E_SET_ADV_PARAMS,
+        BLE_E_ADV_PARAMS_FAILED,
+        BLE_E_SET_ADV_DATA,
+        BLE_E_ADV_CHANGED,
+        BLE_E_ADV_FAILED,
+        BLE_E_ADV_SETUP_FAILED,
+        BLE_E_START_ADV,
+        BLE_E_STOP,
+        BLE_E_FAIL,
+        BLE_E_START_ADV_FAILED,
+        BLE_KW_MSG_2M_UPGRADE_ERROR,
+        BLE_INTERNAL_ERROR,
+    } ble_err_t;
+
+    typedef struct ble_att_written_data_s
+    {
+        uint8_t device_id;
+        uint16_t handle;
+        uint16_t length;
+        uint8_t data[1];
+    } blekw_att_written_data_t;
+
+    typedef struct hk_ble_att_read_data_s
+    {
+        uint8_t device_id;
+        uint16_t handle;
+    } blekw_att_read_data_t;
+
+    CHIPoBLEServiceMode mServiceMode;
+    char mDeviceName[kMaxDeviceNameLength + 1];
+#if CHIP_ENABLE_ADDITIONAL_DATA_ADVERTISING
+    chip::System::PacketBufferHandle c3AdditionalDataBufferHandle;
+#endif
+    uint8_t mDeviceId;
+    bool mDeviceSubscribed = false;
+    bool mDeviceConnected  = false;
+
+    void DriveBLEState(void);
+    CHIP_ERROR ConfigureAdvertising(void);
+    CHIP_ERROR ConfigureAdvertisingData(void);
+    CHIP_ERROR StartAdvertising(void);
+    CHIP_ERROR StopAdvertising(void);
+
+    void HandleConnectEvent(blekw_msg_t * msg);
+    void HandleConnectionCloseEvent(blekw_msg_t * msg);
+    void HandleWriteEvent(blekw_msg_t * msg);
+    void HandleRXCharWrite(blekw_msg_t * msg);
+    void HandleTXCharCCCDWrite(blekw_msg_t * msg);
+    void HandleForceDisconnect();
+
+#if CHIP_ENABLE_ADDITIONAL_DATA_ADVERTISING
+    CHIP_ERROR EncodeAdditionalDataTlv();
+    void HandleC3ReadRequest(blekw_msg_t * msg);
+#endif
+    BLEManagerCommon::ble_err_t blekw_send_event(int8_t connection_handle, uint16_t handle, uint8_t * data, uint32_t len);
+
+    static void DriveBLEState(intptr_t arg);
+    static void StopAdvertisingPriorToSwitchingMode(intptr_t arg);
+    static void BleAdvTimeoutHandler(TimerHandle_t xTimer);
+    static void CancelBleAdvTimeoutTimer(void);
+    static void StartBleAdvTimeoutTimer(uint32_t aTimeoutInMs);
+
+    static void blekw_connection_timeout_cb(TimerHandle_t timer);
+    static void blekw_generic_cb(gapGenericEvent_t * pGenericEvent);
+    static void blekw_gatt_server_cb(deviceId_t deviceId, gattServerEvent_t * pServerEvent);
+    static CHIP_ERROR blekw_msg_add_u8(blekw_msg_type_t type, uint8_t data);
+    static CHIP_ERROR blekw_msg_add_u16(blekw_msg_type_t type, uint16_t data);
+    static CHIP_ERROR blekw_msg_add_att_written(blekw_msg_type_t type, uint8_t device_id, uint16_t handle, uint8_t * data,
+                                                uint16_t length);
+    static CHIP_ERROR blekw_msg_add_att_read(blekw_msg_type_t type, uint8_t device_id, uint16_t handle);
+    static BLEManagerCommon::ble_err_t blekw_start_advertising(gapAdvertisingParameters_t * adv_params, gapAdvertisingData_t * adv,
+                                                               gapScanResponseData_t * scnrsp);
+    static BLEManagerCommon::ble_err_t blekw_stop_advertising(void);
+    static void blekw_gap_advertising_cb(gapAdvertisingEvent_t * pAdvertisingEvent);
+    static void blekw_gap_connection_cb(deviceId_t deviceId, gapConnectionEvent_t * pConnectionEvent);
+    static void blekw_start_connection_timeout(void);
+    static void blekw_stop_connection_timeout(void);
+    static CHIP_ERROR blekw_stop_connection_internal(BLE_CONNECTION_OBJECT conId);
+
+public:
+    virtual CHIP_ERROR InitHostController(BLECallbackDelegate::GapGenericCallback cb_fp) = 0;
+    virtual BLEManagerCommon * GetImplInstance()                                         = 0;
+    virtual CHIP_ERROR ResetController() { return CHIP_NO_ERROR; }
+    void DoBleProcessing(void);
+
+    BLECallbackDelegate callbackDelegate;
+    void RegisterAppCallbacks(BLECallbackDelegate::GapGenericCallback gapCallback,
+                              BLECallbackDelegate::GattServerCallback gattCallback);
+};
+
+inline BLEManager::CHIPoBLEServiceMode BLEManagerCommon::_GetCHIPoBLEServiceMode(void)
+{
+    return mServiceMode;
+}
+
+} // namespace Internal
+} // namespace DeviceLayer
+} // namespace chip
+
+#endif // CHIP_DEVICE_CONFIG_ENABLE_CHIPOBLE
diff --git a/src/platform/nxp/common/legacy/FactoryDataDriver.cpp b/src/platform/nxp/common/legacy/FactoryDataDriver.cpp
new file mode 100644
index 00000000000000..6ddbedc3ca35c8
--- /dev/null
+++ b/src/platform/nxp/common/legacy/FactoryDataDriver.cpp
@@ -0,0 +1,76 @@
+/*
+ *
+ *    Copyright (c) 2024 Project CHIP Authors
+ *
+ *    Licensed under the Apache License, Version 2.0 (the "License");
+ *    you may not use this file except in compliance with the License.
+ *    You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *    Unless required by applicable law or agreed to in writing, software
+ *    distributed under the License is distributed on an "AS IS" BASIS,
+ *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *    See the License for the specific language governing permissions and
+ *    limitations under the License.
+ */
+
+#include <lib/support/CodeUtils.h>
+#include <lib/support/Span.h>
+#include <platform/nxp/common/legacy/FactoryDataDriver.h>
+#include <platform/nxp/common/legacy/FactoryDataProvider.h>
+
+namespace chip {
+namespace DeviceLayer {
+
+FactoryDataDriver::~FactoryDataDriver() {}
+
+CHIP_ERROR FactoryDataDriver::UpdateValueInRam(uint8_t tag, ByteSpan & newValue)
+{
+    uint16_t oldLength                   = 0;
+    uint16_t newLength                   = newValue.size();
+    uint32_t offset                      = 0;
+    uint8_t * factoryData                = mFactoryDataRamBuff;
+    FactoryDataProvider::Header * header = (FactoryDataProvider::Header *) factoryData;
+    uint8_t * data                       = factoryData + sizeof(FactoryDataProvider::Header);
+
+    while (offset < header->size)
+    {
+        memcpy(&oldLength, &data[offset + FactoryDataProvider::kLengthOffset], sizeof(oldLength));
+
+        if (tag != data[offset])
+        {
+            offset += FactoryDataProvider::kValueOffset + oldLength;
+            continue;
+        }
+
+        if (oldLength == newLength)
+        {
+            memcpy(&data[offset + FactoryDataProvider::kValueOffset], newValue.data(), newLength);
+        }
+        else
+        {
+            uint32_t oldEndOffset = offset + FactoryDataProvider::kValueOffset + oldLength;
+
+            memcpy(&data[offset + FactoryDataProvider::kLengthOffset], &newLength, sizeof(newLength));
+            memmove(&data[offset + FactoryDataProvider::kValueOffset + newLength], &data[oldEndOffset],
+                    header->size - oldEndOffset);
+            memcpy(&data[offset + FactoryDataProvider::kValueOffset], newValue.data(), newLength);
+        }
+
+        header->size = header->size - oldLength + newLength;
+
+        uint8_t sha256Output[SHA256_HASH_SIZE] = { 0 };
+        SHA256_Hash(data, header->size, sha256Output);
+        memcpy(header->hash, sha256Output, sizeof(header->hash));
+
+        ChipLogProgress(DeviceLayer, "Value at tag %d updated successfully.", tag);
+        return CHIP_NO_ERROR;
+    }
+
+    ChipLogError(DeviceLayer, "Failed to find tag %d.", tag);
+    return CHIP_ERROR_NOT_FOUND;
+}
+
+} // namespace DeviceLayer
+} // namespace chip
diff --git a/src/platform/nxp/common/legacy/FactoryDataDriver.h b/src/platform/nxp/common/legacy/FactoryDataDriver.h
new file mode 100644
index 00000000000000..93eb43a183e23c
--- /dev/null
+++ b/src/platform/nxp/common/legacy/FactoryDataDriver.h
@@ -0,0 +1,113 @@
+/*
+ *
+ *    Copyright (c) 2024 Project CHIP Authors
+ *
+ *    Licensed under the Apache License, Version 2.0 (the "License");
+ *    you may not use this file except in compliance with the License.
+ *    You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *    Unless required by applicable law or agreed to in writing, software
+ *    distributed under the License is distributed on an "AS IS" BASIS,
+ *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *    See the License for the specific language governing permissions and
+ *    limitations under the License.
+ */
+#pragma once
+
+namespace chip {
+namespace DeviceLayer {
+
+// Forward declaration to define the getter for factory data provider impl instance
+class FactoryDataDriverImpl;
+
+/**
+ * @brief This interface provides the functions that should be implemented
+ * to handle factory data update and factory data ram backup operations.
+ * This interface must be implemented by each platform.
+ */
+
+class FactoryDataDriver
+{
+public:
+    virtual ~FactoryDataDriver();
+
+    /*!
+     * \brief Initializes the FactoryDataDriver instance.
+     *
+     * @retval CHIP_NO_ERROR if operation was successful.
+     */
+    virtual CHIP_ERROR Init() = 0;
+
+    /*!
+     * \brief Checks whether the backup of the factory data exists (e.g in persistent storage).
+     *
+     * @retval true if backup exists otherwise return false.
+     */
+    virtual bool DoesBackupExist(uint16_t * size) = 0;
+
+    /*!
+     * \brief Deletes the backup of the factory data (e.g. from persistent storage).
+     *
+     * @retval CHIP_NO_ERROR if operation was successful.
+     */
+    virtual CHIP_ERROR DeleteBackup(void) = 0;
+
+    /*!
+     * \brief Allocates and initializes the factory data ram backup and copies
+     * factory data into it.
+     *
+     * @retval CHIP_NO_ERROR if operation was successful.
+     */
+    virtual CHIP_ERROR InitRamBackup(void) = 0;
+
+    /*!
+     * \brief Clear and deallocate the factory data ram backup.
+     *
+     * @retval CHIP_NO_ERROR if operation was successful.
+     */
+    virtual CHIP_ERROR ClearRamBackup(void) = 0;
+
+    /*!
+     * \brief Read the factory data from persistent storage into the factory data
+     * ram backup.
+     *
+     * @retval CHIP_NO_ERROR if operation was successful.
+     */
+    virtual CHIP_ERROR ReadBackupInRam(void) = 0;
+
+    /*!
+     * \brief Save / Backup the factory data into the persistent storage
+     *
+     * @retval CHIP_NO_ERROR if operation was successful.
+     */
+    virtual CHIP_ERROR BackupFactoryData(void) = 0;
+
+    /*!
+     * \brief Update / Write the factory data from the ram buffer
+     *
+     * @retval CHIP_NO_ERROR if operation was successful.
+     */
+    virtual CHIP_ERROR UpdateFactoryData(void) = 0;
+
+    /*!
+     * \brief Update TLV value from factory data based on tag
+     * @param tag         TLV tag of component to update
+     * @param newValue    Reference to the new value of the TLV component
+     * @retval CHIP_NO_ERROR if operation was successful.
+     */
+    CHIP_ERROR UpdateValueInRam(uint8_t tag, ByteSpan & newValue);
+
+protected:
+    uint8_t * mFactoryDataRamBuff = nullptr;
+    uint32_t mSize                = 0;
+    uint32_t mMaxSize             = 0;
+};
+
+extern FactoryDataDriver & FactoryDataDrv();
+
+extern FactoryDataDriverImpl & FactoryDataDrvImpl();
+
+} // namespace DeviceLayer
+} // namespace chip
diff --git a/src/platform/nxp/common/legacy/FactoryDataProvider.cpp b/src/platform/nxp/common/legacy/FactoryDataProvider.cpp
new file mode 100644
index 00000000000000..7ecc29a54cf077
--- /dev/null
+++ b/src/platform/nxp/common/legacy/FactoryDataProvider.cpp
@@ -0,0 +1,442 @@
+/*
+ *
+ *    Copyright (c) 2022 Project CHIP Authors
+ *
+ *    Licensed under the Apache License, Version 2.0 (the "License");
+ *    you may not use this file except in compliance with the License.
+ *    You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *    Unless required by applicable law or agreed to in writing, software
+ *    distributed under the License is distributed on an "AS IS" BASIS,
+ *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *    See the License for the specific language governing permissions and
+ *    limitations under the License.
+ */
+
+#if (!CONFIG_CHIP_LOAD_REAL_FACTORY_DATA || !(defined CONFIG_CHIP_LOAD_REAL_FACTORY_DATA))
+#include <credentials/examples/DeviceAttestationCredsExample.h>
+#include <credentials/examples/ExampleDACs.h>
+#include <credentials/examples/ExamplePAI.h>
+#endif
+
+#include <credentials/CHIPCert.h>
+#include <credentials/CertificationDeclaration.h>
+#include <crypto/CHIPCryptoPAL.h>
+#include <lib/core/CHIPError.h>
+#include <lib/core/TLV.h>
+#include <lib/support/Base64.h>
+#include <lib/support/Span.h>
+#include <platform/ConfigurationManager.h>
+#include <platform/nxp/common/legacy/FactoryDataProvider.h>
+
+#include <cctype>
+
+namespace chip {
+namespace DeviceLayer {
+
+static constexpr size_t kSpake2pSerializedVerifier_MaxBase64Len =
+    BASE64_ENCODED_LEN(chip::Crypto::kSpake2p_VerifierSerialized_Length) + 1;
+static constexpr size_t kSpake2pSalt_MaxBase64Len = BASE64_ENCODED_LEN(chip::Crypto::kSpake2p_Max_PBKDF_Salt_Length) + 1;
+/* Secure subsystem private key blob size is 32 + 24 = 56.
+ * DAC private key may be used to store an SSS exported blob instead of the private key.
+ */
+static constexpr size_t kDacPrivateKey_MaxLen = Crypto::kP256_PrivateKey_Length + 24;
+
+FactoryDataProvider::~FactoryDataProvider() {}
+
+#if CONFIG_CHIP_OTA_FACTORY_DATA_PROCESSOR
+
+CHIP_ERROR FactoryDataProvider::ValidateWithRestore()
+{
+    CHIP_ERROR error = CHIP_NO_ERROR;
+
+    VerifyOrReturnError(mRestoreMechanisms.size() > 0, CHIP_FACTORY_DATA_RESTORE_MECHANISM);
+
+    for (auto & restore : mRestoreMechanisms)
+    {
+        error = restore();
+        if (error != CHIP_NO_ERROR)
+        {
+            continue;
+        }
+
+        error = Validate();
+        if (error != CHIP_NO_ERROR)
+        {
+            continue;
+        }
+
+        break;
+    }
+
+    if (error == CHIP_NO_ERROR)
+    {
+        error = mFactoryDataDriver->DeleteBackup();
+    }
+
+    return error;
+}
+
+void FactoryDataProvider::RegisterRestoreMechanism(RestoreMechanism restore)
+{
+    mRestoreMechanisms.insert(mRestoreMechanisms.end(), restore);
+}
+
+#endif
+
+CHIP_ERROR FactoryDataProvider::SignWithDacKey(const ByteSpan & messageToSign, MutableByteSpan & outSignBuffer)
+{
+    CHIP_ERROR error = CHIP_NO_ERROR;
+    Crypto::P256ECDSASignature signature;
+    Crypto::P256Keypair keypair;
+    Crypto::P256SerializedKeypair serializedKeypair;
+    uint8_t keyBuf[Crypto::kP256_PrivateKey_Length];
+    MutableByteSpan dacPrivateKeySpan(keyBuf);
+    uint16_t keySize = 0;
+
+    VerifyOrExit(!outSignBuffer.empty(), error = CHIP_ERROR_INVALID_ARGUMENT);
+    VerifyOrExit(!messageToSign.empty(), error = CHIP_ERROR_INVALID_ARGUMENT);
+    VerifyOrExit(outSignBuffer.size() >= signature.Capacity(), error = CHIP_ERROR_BUFFER_TOO_SMALL);
+
+    /* Get private key of DAC certificate from reserved section */
+    error = SearchForId(FactoryDataId::kDacPrivateKeyId, dacPrivateKeySpan.data(), dacPrivateKeySpan.size(), keySize);
+    SuccessOrExit(error);
+    dacPrivateKeySpan.reduce_size(keySize);
+
+    /* Only the private key is used when signing */
+    error = serializedKeypair.SetLength(Crypto::kP256_PublicKey_Length + dacPrivateKeySpan.size());
+    SuccessOrExit(error);
+    memcpy(serializedKeypair.Bytes() + Crypto::kP256_PublicKey_Length, dacPrivateKeySpan.data(), dacPrivateKeySpan.size());
+
+    error = keypair.Deserialize(serializedKeypair);
+    SuccessOrExit(error);
+
+    error = keypair.ECDSA_sign_msg(messageToSign.data(), messageToSign.size(), signature);
+    SuccessOrExit(error);
+
+    error = CopySpanToMutableSpan(ByteSpan{ signature.ConstBytes(), signature.Length() }, outSignBuffer);
+
+exit:
+    /* Sanitize temporary buffer */
+    memset(keyBuf, 0, Crypto::kP256_PrivateKey_Length);
+    return error;
+}
+
+CHIP_ERROR FactoryDataProvider::Validate()
+{
+    uint8_t output[Crypto::kSHA256_Hash_Length] = { 0 };
+
+    memcpy(&mHeader, (void *) mConfig.start, sizeof(Header));
+    ReturnErrorCodeIf(mHeader.hashId != kHashId, CHIP_FACTORY_DATA_HASH_ID);
+
+    ReturnErrorOnFailure(Crypto::Hash_SHA256((uint8_t *) mConfig.payload, mHeader.size, output));
+    ReturnErrorCodeIf(memcmp(output, mHeader.hash, kHashLen) != 0, CHIP_FACTORY_DATA_SHA_CHECK);
+
+    return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR FactoryDataProvider::SearchForId(uint8_t searchedType, uint8_t * pBuf, size_t bufLength, uint16_t & length,
+                                            uint32_t * offset)
+{
+    uint32_t addr = mConfig.payload;
+    uint8_t type  = 0;
+
+    while (addr < (mConfig.payload + mHeader.size))
+    {
+        memcpy(&type, (void *) addr, sizeof(type));
+        memcpy(&length, (void *) (addr + 1), sizeof(length));
+
+        if (searchedType == type)
+        {
+            ReturnErrorCodeIf(bufLength < length, CHIP_ERROR_BUFFER_TOO_SMALL);
+            memcpy(pBuf, (void *) (addr + kValueOffset), length);
+
+            if (offset)
+                *offset = (addr - mConfig.payload);
+
+            return CHIP_NO_ERROR;
+        }
+        else
+        {
+            /* Jump past 3 bytes of length and then use length to jump to next data */
+            addr = addr + kValueOffset + length;
+        }
+    }
+
+    return CHIP_ERROR_NOT_FOUND;
+}
+
+CHIP_ERROR FactoryDataProvider::GetCertificationDeclaration(MutableByteSpan & outBuffer)
+{
+#if CHIP_USE_DEVICE_CONFIG_CERTIFICATION_DECLARATION
+    constexpr uint8_t kCdForAllExamples[] = CHIP_DEVICE_CONFIG_CERTIFICATION_DECLARATION;
+
+    return CopySpanToMutableSpan(ByteSpan{ kCdForAllExamples }, outBuffer);
+#else
+    uint16_t declarationSize = 0;
+    ReturnErrorOnFailure(SearchForId(FactoryDataId::kCertDeclarationId, outBuffer.data(), outBuffer.size(), declarationSize));
+    outBuffer.reduce_size(declarationSize);
+
+    return CHIP_NO_ERROR;
+#endif
+}
+
+CHIP_ERROR FactoryDataProvider::GetFirmwareInformation(MutableByteSpan & out_firmware_info_buffer)
+{
+    return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR FactoryDataProvider::GetDeviceAttestationCert(MutableByteSpan & outBuffer)
+{
+    uint16_t certificateSize = 0;
+    ReturnErrorOnFailure(SearchForId(FactoryDataId::kDacCertificateId, outBuffer.data(), outBuffer.size(), certificateSize));
+    outBuffer.reduce_size(certificateSize);
+    return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR FactoryDataProvider::GetProductAttestationIntermediateCert(MutableByteSpan & outBuffer)
+{
+    uint16_t certificateSize = 0;
+    ReturnErrorOnFailure(SearchForId(FactoryDataId::kPaiCertificateId, outBuffer.data(), outBuffer.size(), certificateSize));
+    outBuffer.reduce_size(certificateSize);
+    return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR FactoryDataProvider::SignWithDeviceAttestationKey(const ByteSpan & messageToSign, MutableByteSpan & outSignBuffer)
+{
+    return SignWithDacKey(messageToSign, outSignBuffer);
+}
+
+CHIP_ERROR FactoryDataProvider::GetSetupDiscriminator(uint16_t & setupDiscriminator)
+{
+    uint32_t discriminator = 0;
+    uint16_t temp          = 0;
+
+    ReturnErrorOnFailure(SearchForId(FactoryDataId::kDiscriminatorId, (uint8_t *) &discriminator, sizeof(discriminator), temp));
+    setupDiscriminator = (uint16_t) (discriminator & 0x0000FFFF);
+
+    return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR FactoryDataProvider::SetSetupDiscriminator(uint16_t setupDiscriminator)
+{
+    return CHIP_ERROR_NOT_IMPLEMENTED;
+}
+
+CHIP_ERROR FactoryDataProvider::GetSpake2pIterationCount(uint32_t & iterationCount)
+{
+    uint16_t temp = 0;
+    ReturnErrorOnFailure(SearchForId(FactoryDataId::kIcId, (uint8_t *) &iterationCount, sizeof(iterationCount), temp));
+
+    return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR FactoryDataProvider::GetSpake2pSalt(MutableByteSpan & saltBuf)
+{
+    char saltB64[kSpake2pSalt_MaxBase64Len] = { 0 };
+    uint16_t saltB64Len                     = 0;
+
+    ReturnErrorOnFailure(SearchForId(FactoryDataId::kSaltId, (uint8_t *) (&saltB64[0]), sizeof(saltB64), saltB64Len));
+    size_t saltLen = chip::Base64Decode32(saltB64, saltB64Len, reinterpret_cast<uint8_t *>(saltB64));
+
+    ReturnErrorCodeIf(saltLen > saltBuf.size(), CHIP_ERROR_BUFFER_TOO_SMALL);
+    memcpy(saltBuf.data(), saltB64, saltLen);
+    saltBuf.reduce_size(saltLen);
+
+    return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR FactoryDataProvider::GetSpake2pVerifier(MutableByteSpan & verifierBuf, size_t & verifierLen)
+{
+    char verifierB64[kSpake2pSerializedVerifier_MaxBase64Len] = { 0 };
+    uint16_t verifierB64Len                                   = 0;
+    ReturnErrorOnFailure(SearchForId(FactoryDataId::kVerifierId, (uint8_t *) &verifierB64[0], sizeof(verifierB64), verifierB64Len));
+
+    verifierLen = chip::Base64Decode32(verifierB64, verifierB64Len, reinterpret_cast<uint8_t *>(verifierB64));
+    ReturnErrorCodeIf(verifierLen > verifierBuf.size(), CHIP_ERROR_BUFFER_TOO_SMALL);
+    memcpy(verifierBuf.data(), verifierB64, verifierLen);
+    verifierBuf.reduce_size(verifierLen);
+
+    return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR FactoryDataProvider::GetSetupPasscode(uint32_t & setupPasscode)
+{
+    uint16_t length = 0;
+    ReturnErrorOnFailure(SearchForId(FactoryDataId::kSetupPasscodeId, (uint8_t *) &setupPasscode, sizeof(setupPasscode), length));
+
+    return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR FactoryDataProvider::SetSetupPasscode(uint32_t setupPasscode)
+{
+    return CHIP_ERROR_NOT_IMPLEMENTED;
+}
+
+CHIP_ERROR FactoryDataProvider::GetVendorName(char * buf, size_t bufSize)
+{
+    uint16_t length = 0;
+    ReturnErrorOnFailure(SearchForId(FactoryDataId::kVendorNameId, (uint8_t *) buf, bufSize, length));
+    buf[length] = '\0';
+
+    return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR FactoryDataProvider::GetVendorId(uint16_t & vendorId)
+{
+    uint16_t length = 0;
+    ReturnErrorOnFailure(SearchForId(FactoryDataId::kVidId, (uint8_t *) &vendorId, sizeof(vendorId), length));
+
+    return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR FactoryDataProvider::GetProductName(char * buf, size_t bufSize)
+{
+    uint16_t length = 0;
+    ReturnErrorOnFailure(SearchForId(FactoryDataId::kProductNameId, (uint8_t *) buf, bufSize, length));
+    buf[length] = '\0';
+
+    return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR FactoryDataProvider::GetProductId(uint16_t & productId)
+{
+    uint16_t length = 0;
+    ReturnErrorOnFailure(SearchForId(FactoryDataId::kPidId, (uint8_t *) &productId, sizeof(productId), length));
+
+    return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR FactoryDataProvider::GetPartNumber(char * buf, size_t bufSize)
+{
+    uint16_t length = 0;
+    ReturnErrorOnFailure(SearchForId(FactoryDataId::kPartNumber, (uint8_t *) buf, bufSize, length));
+    buf[length] = '\0';
+
+    return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR FactoryDataProvider::GetProductURL(char * buf, size_t bufSize)
+{
+    uint16_t length = 0;
+    ReturnErrorOnFailure(SearchForId(FactoryDataId::kProductURL, (uint8_t *) buf, bufSize, length));
+    buf[length] = '\0';
+
+    return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR FactoryDataProvider::GetProductLabel(char * buf, size_t bufSize)
+{
+    uint16_t length = 0;
+    ReturnErrorOnFailure(SearchForId(FactoryDataId::kProductLabel, (uint8_t *) buf, bufSize, length));
+    buf[length] = '\0';
+
+    return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR FactoryDataProvider::GetSerialNumber(char * buf, size_t bufSize)
+{
+    uint16_t length = 0;
+    ReturnErrorOnFailure(SearchForId(FactoryDataId::kSerialNumberId, (uint8_t *) buf, bufSize, length));
+    buf[length] = '\0';
+
+    return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR FactoryDataProvider::GetManufacturingDate(uint16_t & year, uint8_t & month, uint8_t & day)
+{
+    uint16_t length = 0;
+    uint8_t date[ConfigurationManager::kMaxManufacturingDateLength];
+
+    ReturnErrorOnFailure(
+        SearchForId(FactoryDataId::kManufacturingDateId, date, ConfigurationManager::kMaxManufacturingDateLength, length));
+    date[length] = '\0';
+
+    if (length == 10 && isdigit(date[0]) && isdigit(date[1]) && isdigit(date[2]) && isdigit(date[3]) && date[4] == '-' &&
+        isdigit(date[5]) && isdigit(date[6]) && date[7] == '-' && isdigit(date[8]) && isdigit(date[9]))
+    {
+        year  = 1000 * (date[0] - '0') + 100 * (date[1] - '0') + 10 * (date[2] - '0') + date[3] - '0';
+        month = 10 * (date[5] - '0') + date[6] - '0';
+        day   = 10 * (date[8] - '0') + date[9] - '0';
+    }
+    else
+    {
+        ChipLogError(DeviceLayer, "Manufacturing date is not formatted correctly: YYYY-MM-DD.");
+        return CHIP_ERROR_INVALID_ARGUMENT;
+    }
+
+    return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR FactoryDataProvider::GetHardwareVersion(uint16_t & hardwareVersion)
+{
+    uint16_t length = 0;
+    ReturnErrorOnFailure(
+        SearchForId(FactoryDataId::kHardwareVersionId, (uint8_t *) &hardwareVersion, sizeof(hardwareVersion), length));
+
+    return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR FactoryDataProvider::GetHardwareVersionString(char * buf, size_t bufSize)
+{
+    uint16_t length = 0;
+    ReturnErrorOnFailure(SearchForId(FactoryDataId::kHardwareVersionStrId, (uint8_t *) buf, bufSize, length));
+    buf[length] = '\0';
+
+    return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR FactoryDataProvider::GetRotatingDeviceIdUniqueId(MutableByteSpan & uniqueIdSpan)
+{
+    CHIP_ERROR err = CHIP_ERROR_NOT_IMPLEMENTED;
+#if CHIP_ENABLE_ROTATING_DEVICE_ID
+    static_assert(ConfigurationManager::kRotatingDeviceIDUniqueIDLength >= ConfigurationManager::kMinRotatingDeviceIDUniqueIDLength,
+                  "Length of unique ID for rotating device ID is smaller than minimum.");
+    uint16_t uniqueIdLen = 0;
+    err                  = SearchForId(FactoryDataId::kUniqueId, (uint8_t *) uniqueIdSpan.data(), uniqueIdSpan.size(), uniqueIdLen);
+#if defined(CHIP_DEVICE_CONFIG_ROTATING_DEVICE_ID_UNIQUE_ID)
+    if (err != CHIP_NO_ERROR)
+    {
+        constexpr uint8_t uniqueId[] = CHIP_DEVICE_CONFIG_ROTATING_DEVICE_ID_UNIQUE_ID;
+
+        ReturnErrorCodeIf(sizeof(uniqueId) > uniqueIdSpan.size(), CHIP_ERROR_BUFFER_TOO_SMALL);
+        memcpy(uniqueIdSpan.data(), uniqueId, sizeof(uniqueId));
+        uniqueIdLen = sizeof(uniqueId);
+        err         = CHIP_NO_ERROR;
+    }
+#endif // CHIP_DEVICE_CONFIG_ROTATING_DEVICE_ID_UNIQUE_ID
+    ReturnErrorOnFailure(err);
+    uniqueIdSpan.reduce_size(uniqueIdLen);
+#endif
+
+    return err;
+}
+
+CHIP_ERROR FactoryDataProvider::GetProductFinish(app::Clusters::BasicInformation::ProductFinishEnum * finish)
+{
+    uint8_t productFinish;
+    uint16_t length = 0;
+    auto err        = SearchForId(FactoryDataId::kProductFinish, &productFinish, sizeof(productFinish), length);
+    ReturnErrorCodeIf(err != CHIP_NO_ERROR, CHIP_ERROR_NOT_IMPLEMENTED);
+
+    *finish = static_cast<app::Clusters::BasicInformation::ProductFinishEnum>(productFinish);
+
+    return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR FactoryDataProvider::GetProductPrimaryColor(app::Clusters::BasicInformation::ColorEnum * primaryColor)
+{
+    uint8_t color;
+    uint16_t length = 0;
+    auto err        = SearchForId(FactoryDataId::kProductPrimaryColor, &color, sizeof(color), length);
+    ReturnErrorCodeIf(err != CHIP_NO_ERROR, CHIP_ERROR_NOT_IMPLEMENTED);
+
+    *primaryColor = static_cast<app::Clusters::BasicInformation::ColorEnum>(color);
+
+    return CHIP_NO_ERROR;
+}
+
+} // namespace DeviceLayer
+} // namespace chip
diff --git a/src/platform/nxp/common/legacy/FactoryDataProvider.h b/src/platform/nxp/common/legacy/FactoryDataProvider.h
new file mode 100644
index 00000000000000..f7d05c3f1da1f4
--- /dev/null
+++ b/src/platform/nxp/common/legacy/FactoryDataProvider.h
@@ -0,0 +1,177 @@
+/*
+ *
+ *    Copyright (c) 2022 Project CHIP Authors
+ *
+ *    Licensed under the Apache License, Version 2.0 (the "License");
+ *    you may not use this file except in compliance with the License.
+ *    You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *    Unless required by applicable law or agreed to in writing, software
+ *    distributed under the License is distributed on an "AS IS" BASIS,
+ *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *    See the License for the specific language governing permissions and
+ *    limitations under the License.
+ */
+#pragma once
+
+#include <credentials/DeviceAttestationCredsProvider.h>
+#include <platform/CommissionableDataProvider.h>
+#include <platform/internal/GenericDeviceInstanceInfoProvider.h>
+#include <src/lib/core/CHIPError.h>
+
+#include <platform/nxp/common/legacy/FactoryDataDriver.h>
+
+#include <vector>
+
+#include "CHIPPlatformConfig.h"
+
+#include <vector>
+
+namespace chip {
+namespace DeviceLayer {
+
+#define CHIP_FACTORY_DATA_ERROR(e)                                                                                                 \
+    ChipError(ChipError::Range::kLastRange, ((uint8_t) ChipError::Range::kLastRange << 2) | e, __FILE__, __LINE__)
+
+#define CHIP_FACTORY_DATA_SHA_CHECK CHIP_FACTORY_DATA_ERROR(0x01)
+#define CHIP_FACTORY_DATA_HEADER_READ CHIP_FACTORY_DATA_ERROR(0x02)
+#define CHIP_FACTORY_DATA_HASH_ID CHIP_FACTORY_DATA_ERROR(0x03)
+#define CHIP_FACTORY_DATA_PDM_RESTORE CHIP_FACTORY_DATA_ERROR(0x04)
+#define CHIP_FACTORY_DATA_NULL CHIP_FACTORY_DATA_ERROR(0x05)
+#define CHIP_FACTORY_DATA_FLASH_ERASE CHIP_FACTORY_DATA_ERROR(0x06)
+#define CHIP_FACTORY_DATA_FLASH_PROGRAM CHIP_FACTORY_DATA_ERROR(0x07)
+#define CHIP_FACTORY_DATA_INTERNAL_FLASH_READ CHIP_FACTORY_DATA_ERROR(0x08)
+#define CHIP_FACTORY_DATA_PDM_SAVE_RECORD CHIP_FACTORY_DATA_ERROR(0x09)
+#define CHIP_FACTORY_DATA_PDM_READ_RECORD CHIP_FACTORY_DATA_ERROR(0x0A)
+#define CHIP_FACTORY_DATA_RESTORE_MECHANISM CHIP_FACTORY_DATA_ERROR(0x0B)
+
+// Forward declaration to define the getter for factory data provider impl instance
+class FactoryDataProviderImpl;
+
+/**
+ * @brief This class provides Commissionable data, Device Attestation Credentials,
+ *        and Device Instance Info.
+ */
+
+class FactoryDataProvider : public DeviceInstanceInfoProvider,
+                            public CommissionableDataProvider,
+                            public Credentials::DeviceAttestationCredentialsProvider
+{
+public:
+    struct Header
+    {
+        uint32_t hashId;
+        uint32_t size;
+        uint8_t hash[4];
+    };
+
+    struct FactoryDataConfig
+    {
+        uint32_t start;
+        uint32_t size;
+        uint32_t payload;
+    };
+
+    // Default factory data IDs
+    enum FactoryDataId
+    {
+        kVerifierId = 1,
+        kSaltId,
+        kIcId,
+        kDacPrivateKeyId,
+        kDacCertificateId,
+        kPaiCertificateId,
+        kDiscriminatorId,
+        kSetupPasscodeId,
+        kVidId,
+        kPidId,
+        kCertDeclarationId,
+        kVendorNameId,
+        kProductNameId,
+        kSerialNumberId,
+        kManufacturingDateId,
+        kHardwareVersionId,
+        kHardwareVersionStrId,
+        kUniqueId,
+        kPartNumber,
+        kProductURL,
+        kProductLabel,
+        kProductFinish,
+        kProductPrimaryColor,
+        kMaxId
+    };
+
+    static uint32_t kFactoryDataMaxSize;
+    static constexpr uint32_t kLengthOffset = 1;
+    static constexpr uint32_t kValueOffset  = 3;
+    static constexpr uint32_t kHashLen      = 4;
+    static constexpr size_t kHashId         = 0xCE47BA5E;
+
+    virtual ~FactoryDataProvider();
+
+    virtual CHIP_ERROR Init() = 0;
+    virtual CHIP_ERROR SignWithDacKey(const ByteSpan & messageToSign, MutableByteSpan & outSignBuffer);
+    virtual CHIP_ERROR Validate();
+
+    virtual CHIP_ERROR SearchForId(uint8_t searchedType, uint8_t * pBuf, size_t bufLength, uint16_t & length,
+                                   uint32_t * offset = nullptr);
+
+#if CONFIG_CHIP_OTA_FACTORY_DATA_PROCESSOR
+    using RestoreMechanism = CHIP_ERROR (*)(void);
+
+    CHIP_ERROR ValidateWithRestore();
+    void RegisterRestoreMechanism(RestoreMechanism mechanism);
+
+    virtual CHIP_ERROR PreResetCheck()  = 0;
+    virtual CHIP_ERROR PostResetCheck() = 0;
+#endif
+
+    // ===== Members functions that implement the CommissionableDataProvider
+    CHIP_ERROR GetSetupDiscriminator(uint16_t & setupDiscriminator) override;
+    CHIP_ERROR SetSetupDiscriminator(uint16_t setupDiscriminator) override;
+    CHIP_ERROR GetSpake2pIterationCount(uint32_t & iterationCount) override;
+    CHIP_ERROR GetSpake2pSalt(MutableByteSpan & saltBuf) override;
+    CHIP_ERROR GetSpake2pVerifier(MutableByteSpan & verifierBuf, size_t & verifierLen) override;
+    CHIP_ERROR GetSetupPasscode(uint32_t & setupPasscode) override;
+    CHIP_ERROR SetSetupPasscode(uint32_t setupPasscode) override;
+
+    // ===== Members functions that implement the DeviceAttestationCredentialsProvider
+    CHIP_ERROR GetCertificationDeclaration(MutableByteSpan & outBuffer) override;
+    CHIP_ERROR GetFirmwareInformation(MutableByteSpan & out_firmware_info_buffer) override;
+    CHIP_ERROR GetDeviceAttestationCert(MutableByteSpan & outBuffer) override;
+    CHIP_ERROR GetProductAttestationIntermediateCert(MutableByteSpan & outBuffer) override;
+    CHIP_ERROR SignWithDeviceAttestationKey(const ByteSpan & messageToSign, MutableByteSpan & outSignBuffer) override;
+
+    // ===== Members functions that implement the GenericDeviceInstanceInfoProvider
+    CHIP_ERROR GetVendorName(char * buf, size_t bufSize) override;
+    CHIP_ERROR GetVendorId(uint16_t & vendorId) override;
+    CHIP_ERROR GetProductName(char * buf, size_t bufSize) override;
+    CHIP_ERROR GetProductId(uint16_t & productId) override;
+    CHIP_ERROR GetPartNumber(char * buf, size_t bufSize) override;
+    CHIP_ERROR GetProductURL(char * buf, size_t bufSize) override;
+    CHIP_ERROR GetProductLabel(char * buf, size_t bufSize) override;
+    CHIP_ERROR GetHardwareVersionString(char * buf, size_t bufSize) override;
+    CHIP_ERROR GetSerialNumber(char * buf, size_t bufSize) override;
+    CHIP_ERROR GetManufacturingDate(uint16_t & year, uint8_t & month, uint8_t & day) override;
+    CHIP_ERROR GetHardwareVersion(uint16_t & hardwareVersion) override;
+    CHIP_ERROR GetRotatingDeviceIdUniqueId(MutableByteSpan & uniqueIdSpan) override;
+    CHIP_ERROR GetProductFinish(app::Clusters::BasicInformation::ProductFinishEnum * finish) override;
+    CHIP_ERROR GetProductPrimaryColor(app::Clusters::BasicInformation::ColorEnum * primaryColor) override;
+
+protected:
+    Header mHeader;
+    FactoryDataConfig mConfig;
+#if CONFIG_CHIP_OTA_FACTORY_DATA_PROCESSOR
+    std::vector<RestoreMechanism> mRestoreMechanisms;
+    FactoryDataDriver * mFactoryDataDriver = nullptr;
+#endif
+};
+
+extern FactoryDataProvider & FactoryDataPrvd();
+
+extern FactoryDataProviderImpl & FactoryDataPrvdImpl();
+
+} // namespace DeviceLayer
+} // namespace chip
diff --git a/src/platform/nxp/common/legacy/OTAFactoryDataProcessor.cpp b/src/platform/nxp/common/legacy/OTAFactoryDataProcessor.cpp
new file mode 100644
index 00000000000000..4960ca2c4e0669
--- /dev/null
+++ b/src/platform/nxp/common/legacy/OTAFactoryDataProcessor.cpp
@@ -0,0 +1,165 @@
+/*
+ *
+ *    Copyright (c) 2023 Project CHIP Authors
+ *    All rights reserved.
+ *
+ *    Licensed under the Apache License, Version 2.0 (the "License");
+ *    you may not use this file except in compliance with the License.
+ *    You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *    Unless required by applicable law or agreed to in writing, software
+ *    distributed under the License is distributed on an "AS IS" BASIS,
+ *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *    See the License for the specific language governing permissions and
+ *    limitations under the License.
+ */
+
+#include <app/server/Server.h>
+#include <lib/core/TLV.h>
+#include <platform/internal/CHIPDeviceLayerInternal.h>
+#include <platform/nxp/common/legacy/OTAFactoryDataProcessor.h>
+
+namespace chip {
+
+CHIP_ERROR OTAFactoryDataProcessor::Init()
+{
+    mAccumulator.Init(mLength);
+    mFactoryDataDriver = &chip::DeviceLayer::FactoryDataDrv();
+
+    return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR OTAFactoryDataProcessor::Clear()
+{
+    OTATlvProcessor::ClearInternal();
+    mAccumulator.Clear();
+    mPayload.Clear();
+    mFactoryDataDriver->ClearRamBackup();
+
+    return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR OTAFactoryDataProcessor::ProcessInternal(ByteSpan & block)
+{
+    CHIP_ERROR error = CHIP_NO_ERROR;
+
+    ReturnErrorOnFailure(mAccumulator.Accumulate(block));
+#if OTA_ENCRYPTION_ENABLE
+    MutableByteSpan mBlock = MutableByteSpan(mAccumulator.data(), mAccumulator.GetThreshold());
+    OTATlvProcessor::vOtaProcessInternalEncryption(mBlock);
+#endif
+    error = DecodeTlv();
+
+    if (error != CHIP_NO_ERROR)
+    {
+        // The factory data payload can contain a variable number of fields
+        // to be updated. CHIP_END_OF_TLV is returned if no more fields are
+        // found.
+        if (error == CHIP_END_OF_TLV)
+        {
+            return CHIP_NO_ERROR;
+        }
+
+        Clear();
+    }
+
+    return error;
+}
+
+CHIP_ERROR OTAFactoryDataProcessor::ApplyAction()
+{
+    CHIP_ERROR error = CHIP_NO_ERROR;
+    FactoryProvider * provider;
+
+    ReturnErrorOnFailure(mFactoryDataDriver->InitRamBackup());
+    ReturnErrorOnFailure(mFactoryDataDriver->BackupFactoryData());
+
+    SuccessOrExit(error = Update((uint8_t) Tags::kDacPrivateKeyId, mPayload.mCertDacKey));
+    SuccessOrExit(error = Update((uint8_t) Tags::kDacCertificateId, mPayload.mCertDac));
+    SuccessOrExit(error = Update((uint8_t) Tags::kPaiCertificateId, mPayload.mCertPai));
+    SuccessOrExit(error = Update((uint8_t) Tags::kCertDeclarationId, mPayload.mCertDeclaration));
+
+    SuccessOrExit(error = mFactoryDataDriver->UpdateFactoryData());
+
+    provider = &chip::DeviceLayer::FactoryDataPrvd();
+    VerifyOrReturnError(provider != nullptr, CHIP_ERROR_INTERNAL);
+
+    SuccessOrExit(error = provider->PreResetCheck());
+
+exit:
+    if (error != CHIP_NO_ERROR)
+    {
+        ChipLogError(DeviceLayer, "Failed to update factory data. Error: %s", ErrorStr(error));
+    }
+    else
+    {
+        ChipLogProgress(DeviceLayer, "Factory data update finished.");
+    }
+
+    return error;
+}
+
+CHIP_ERROR OTAFactoryDataProcessor::AbortAction()
+{
+    CHIP_ERROR error = CHIP_NO_ERROR;
+    ReturnErrorOnFailure(mFactoryDataDriver->ReadBackupInRam());
+    ReturnErrorOnFailure(mFactoryDataDriver->UpdateFactoryData());
+
+    error = mFactoryDataDriver->DeleteBackup();
+    ReturnErrorOnFailure(error);
+
+    return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR OTAFactoryDataProcessor::DecodeTlv()
+{
+    TLV::TLVReader tlvReader;
+    tlvReader.Init(mAccumulator.data(), mLength);
+    ReturnErrorOnFailure(tlvReader.Next(TLV::TLVType::kTLVType_Structure, TLV::AnonymousTag()));
+
+    TLV::TLVType outerType;
+    ReturnErrorOnFailure(tlvReader.EnterContainer(outerType));
+    ReturnErrorOnFailure(tlvReader.Next());
+
+    if (tlvReader.GetTag() == TLV::ContextTag((uint8_t) Tags::kDacPrivateKeyId))
+    {
+        ReturnErrorOnFailure(tlvReader.Get(mPayload.mCertDacKey.Emplace()));
+        ReturnErrorOnFailure(tlvReader.Next());
+    }
+
+    if (tlvReader.GetTag() == TLV::ContextTag((uint8_t) Tags::kDacCertificateId))
+    {
+        ReturnErrorOnFailure(tlvReader.Get(mPayload.mCertDac.Emplace()));
+        ReturnErrorOnFailure(tlvReader.Next());
+    }
+
+    if (tlvReader.GetTag() == TLV::ContextTag((uint8_t) Tags::kPaiCertificateId))
+    {
+        ReturnErrorOnFailure(tlvReader.Get(mPayload.mCertPai.Emplace()));
+        ReturnErrorOnFailure(tlvReader.Next());
+    }
+
+    if (tlvReader.GetTag() == TLV::ContextTag((uint8_t) Tags::kCertDeclarationId))
+    {
+        ReturnErrorOnFailure(tlvReader.Get(mPayload.mCertDeclaration.Emplace()));
+    }
+
+    ReturnErrorOnFailure(tlvReader.ExitContainer(outerType));
+
+    return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR OTAFactoryDataProcessor::Update(uint8_t tag, Optional<ByteSpan> & optional)
+{
+    CHIP_ERROR error = CHIP_NO_ERROR;
+    if (optional.HasValue())
+    {
+        error = mFactoryDataDriver->UpdateValueInRam(tag, optional.Value());
+    }
+
+    return error;
+}
+
+} // namespace chip
diff --git a/src/platform/nxp/common/legacy/OTAFactoryDataProcessor.h b/src/platform/nxp/common/legacy/OTAFactoryDataProcessor.h
new file mode 100644
index 00000000000000..862aad2d9a6341
--- /dev/null
+++ b/src/platform/nxp/common/legacy/OTAFactoryDataProcessor.h
@@ -0,0 +1,78 @@
+/*
+ *
+ *    Copyright (c) 2023 Project CHIP Authors
+ *    All rights reserved.
+ *
+ *    Licensed under the Apache License, Version 2.0 (the "License");
+ *    you may not use this file except in compliance with the License.
+ *    You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *    Unless required by applicable law or agreed to in writing, software
+ *    distributed under the License is distributed on an "AS IS" BASIS,
+ *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *    See the License for the specific language governing permissions and
+ *    limitations under the License.
+ */
+
+#pragma once
+
+#include <lib/core/Optional.h>
+#include <lib/support/ScopedBuffer.h>
+#include <lib/support/Span.h>
+#include <platform/nxp/common/legacy/FactoryDataDriver.h>
+#include <platform/nxp/common/legacy/FactoryDataProvider.h>
+#include <platform/nxp/common/legacy/OTATlvProcessor.h>
+#include PLATFORM_FACTORY_DATA_PROVIDER_IMPL_HEADER
+
+namespace chip {
+
+using FactoryProvider     = DeviceLayer::FactoryDataProvider;
+using FactoryProviderImpl = DeviceLayer::FactoryDataProviderImpl;
+using FactoryDataDriver   = DeviceLayer::FactoryDataDriver;
+using Tags                = FactoryProvider::FactoryDataId;
+
+/**
+ * OTA custom payload that uses Matter TLVs.
+ * The custom payload is used when factory data needs updating.
+ * Factory data will be encoded using Matter TLV format to make
+ * use of the ChipTlv reader. A payload contains metadata (size of
+ * TLVs) and the TLVs themselves contained in a structure.
+ * If no factory data need to be updated, the metadata will be 0
+ */
+struct OTAFactoryPayload
+{
+    Optional<ByteSpan> mCertDacKey;
+    Optional<ByteSpan> mCertDac;
+    Optional<ByteSpan> mCertPai;
+    Optional<ByteSpan> mCertDeclaration;
+
+    void Clear()
+    {
+        mCertDacKey.ClearValue();
+        mCertDac.ClearValue();
+        mCertPai.ClearValue();
+        mCertDeclaration.ClearValue();
+    }
+};
+
+class OTAFactoryDataProcessor : public OTATlvProcessor
+{
+public:
+    CHIP_ERROR Init() override;
+    CHIP_ERROR Clear() override;
+    CHIP_ERROR ApplyAction() override;
+    CHIP_ERROR AbortAction() override;
+
+private:
+    CHIP_ERROR ProcessInternal(ByteSpan & block) override;
+    CHIP_ERROR DecodeTlv();
+    CHIP_ERROR Update(uint8_t tag, Optional<ByteSpan> & optional);
+
+    OTAFactoryPayload mPayload;
+    OTADataAccumulator mAccumulator;
+    FactoryDataDriver * mFactoryDataDriver = nullptr;
+};
+
+} // namespace chip
diff --git a/src/platform/nxp/common/legacy/OTAImageProcessorImpl.cpp b/src/platform/nxp/common/legacy/OTAImageProcessorImpl.cpp
new file mode 100644
index 00000000000000..249b51b7681c22
--- /dev/null
+++ b/src/platform/nxp/common/legacy/OTAImageProcessorImpl.cpp
@@ -0,0 +1,424 @@
+/*
+ *
+ *    Copyright (c) 2021-2023 Project CHIP Authors
+ *    All rights reserved.
+ *
+ *    Licensed under the Apache License, Version 2.0 (the "License");
+ *    you may not use this file except in compliance with the License.
+ *    You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *    Unless required by applicable law or agreed to in writing, software
+ *    distributed under the License is distributed on an "AS IS" BASIS,
+ *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *    See the License for the specific language governing permissions and
+ *    limitations under the License.
+ */
+
+#include <lib/support/BufferReader.h>
+#include <platform/DiagnosticDataProvider.h>
+#include <platform/internal/CHIPDeviceLayerInternal.h>
+#include <platform/internal/GenericConfigurationManagerImpl.h>
+#include <src/app/clusters/ota-requestor/OTADownloader.h>
+#include <src/app/clusters/ota-requestor/OTARequestorInterface.h>
+
+#include <platform/nxp/common/legacy/OTAImageProcessorImpl.h>
+
+using namespace chip::DeviceLayer;
+using namespace ::chip::DeviceLayer::Internal;
+
+#if USE_SMU2_STATIC
+// The attribute specifier should not be changed.
+static chip::OTAImageProcessorImpl gImageProcessor __attribute__((section(".smu2")));
+#else
+static chip::OTAImageProcessorImpl gImageProcessor;
+#endif
+
+namespace chip {
+
+CHIP_ERROR OTAImageProcessorImpl::Init(OTADownloader * downloader)
+{
+    ReturnErrorCodeIf(downloader == nullptr, CHIP_ERROR_INVALID_ARGUMENT);
+    mDownloader = downloader;
+
+    OtaHookInit();
+
+    return CHIP_NO_ERROR;
+}
+
+void OTAImageProcessorImpl::Clear()
+{
+    mHeaderParser.Clear();
+    mAccumulator.Clear();
+    mParams.totalFileBytes  = 0;
+    mParams.downloadedBytes = 0;
+    mCurrentProcessor       = nullptr;
+
+    ReleaseBlock();
+}
+
+CHIP_ERROR OTAImageProcessorImpl::PrepareDownload()
+{
+    DeviceLayer::PlatformMgr().ScheduleWork(HandlePrepareDownload, reinterpret_cast<intptr_t>(this));
+    return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR OTAImageProcessorImpl::Finalize()
+{
+    DeviceLayer::PlatformMgr().ScheduleWork(HandleFinalize, reinterpret_cast<intptr_t>(this));
+    return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR OTAImageProcessorImpl::Apply()
+{
+    DeviceLayer::PlatformMgr().ScheduleWork(HandleApply, reinterpret_cast<intptr_t>(this));
+    return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR OTAImageProcessorImpl::Abort()
+{
+    DeviceLayer::PlatformMgr().ScheduleWork(HandleAbort, reinterpret_cast<intptr_t>(this));
+    return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR OTAImageProcessorImpl::ProcessBlock(ByteSpan & block)
+{
+    if ((block.data() == nullptr) || block.empty())
+    {
+        return CHIP_ERROR_INVALID_ARGUMENT;
+    }
+
+    // Store block data for HandleProcessBlock to access
+    CHIP_ERROR err = SetBlock(block);
+    if (err != CHIP_NO_ERROR)
+    {
+        ChipLogError(SoftwareUpdate, "Cannot set block data: %" CHIP_ERROR_FORMAT, err.Format());
+    }
+
+    DeviceLayer::PlatformMgr().ScheduleWork(HandleProcessBlock, reinterpret_cast<intptr_t>(this));
+    return CHIP_NO_ERROR;
+}
+
+void OTAImageProcessorImpl::HandlePrepareDownload(intptr_t context)
+{
+    auto * imageProcessor = reinterpret_cast<OTAImageProcessorImpl *>(context);
+
+    VerifyOrReturn(imageProcessor != nullptr, ChipLogError(SoftwareUpdate, "ImageProcessor context is null"));
+
+    VerifyOrReturn(imageProcessor->mDownloader != nullptr, ChipLogError(SoftwareUpdate, "mDownloader is null"));
+
+    GetRequestorInstance()->GetProviderLocation(imageProcessor->mBackupProviderLocation);
+
+    imageProcessor->mHeaderParser.Init();
+    imageProcessor->mAccumulator.Init(sizeof(OTATlvHeader));
+    imageProcessor->mDownloader->OnPreparedForDownload(CHIP_NO_ERROR);
+}
+
+CHIP_ERROR OTAImageProcessorImpl::ProcessHeader(ByteSpan & block)
+{
+    OTAImageHeader header;
+    ReturnErrorOnFailure(mHeaderParser.AccumulateAndDecode(block, header));
+
+    mParams.totalFileBytes = header.mPayloadSize;
+    mHeaderParser.Clear();
+    ChipLogError(SoftwareUpdate, "Processed header successfully");
+
+    return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR OTAImageProcessorImpl::ProcessPayload(ByteSpan & block)
+{
+    CHIP_ERROR status = CHIP_NO_ERROR;
+
+    while (true)
+    {
+        if (!mCurrentProcessor)
+        {
+            ReturnErrorOnFailure(mAccumulator.Accumulate(block));
+            ByteSpan tlvHeader{ mAccumulator.data(), sizeof(OTATlvHeader) };
+            ReturnErrorOnFailure(SelectProcessor(tlvHeader));
+            ReturnErrorOnFailure(mCurrentProcessor->Init());
+        }
+
+        status = mCurrentProcessor->Process(block);
+        if (status == CHIP_ERROR_OTA_CHANGE_PROCESSOR)
+        {
+            mAccumulator.Clear();
+            mAccumulator.Init(sizeof(OTATlvHeader));
+
+            mCurrentProcessor = nullptr;
+
+            // If the block size is 0, it means that the processed data was a multiple of
+            // received BDX block size (e.g. 8 blocks of 1024 bytes were transferred).
+            // After state for selecting next processor is reset, a request for fetching next
+            // data must be sent.
+            if (block.size() == 0)
+            {
+                status = CHIP_NO_ERROR;
+                break;
+            }
+        }
+        else
+        {
+            break;
+        }
+    }
+
+    return status;
+}
+
+CHIP_ERROR OTAImageProcessorImpl::SelectProcessor(ByteSpan & block)
+{
+    OTATlvHeader header;
+    Encoding::LittleEndian::Reader reader(block.data(), sizeof(header));
+
+    ReturnErrorOnFailure(reader.Read32(&header.tag).StatusCode());
+    ReturnErrorOnFailure(reader.Read32(&header.length).StatusCode());
+
+    auto pair = mProcessorMap.find(header.tag);
+    if (pair == mProcessorMap.end())
+    {
+        ChipLogError(SoftwareUpdate, "There is no registered processor for tag: %" PRIu32, header.tag);
+        return CHIP_ERROR_OTA_PROCESSOR_NOT_REGISTERED;
+    }
+
+    ChipLogDetail(SoftwareUpdate, "Selected processor with tag: %ld", pair->first);
+    mCurrentProcessor = pair->second;
+    mCurrentProcessor->SetLength(header.length);
+    mCurrentProcessor->SetWasSelected(true);
+
+    return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR OTAImageProcessorImpl::RegisterProcessor(uint32_t tag, OTATlvProcessor * processor)
+{
+    auto pair = mProcessorMap.find(tag);
+    if (pair != mProcessorMap.end())
+    {
+        ChipLogError(SoftwareUpdate, "A processor for tag %" PRIu32 " is already registered.", tag);
+        return CHIP_ERROR_OTA_PROCESSOR_ALREADY_REGISTERED;
+    }
+
+    mProcessorMap.insert({ tag, processor });
+
+    return CHIP_NO_ERROR;
+}
+
+void OTAImageProcessorImpl::HandleAbort(intptr_t context)
+{
+    ChipLogError(SoftwareUpdate, "OTA was aborted");
+    auto * imageProcessor = reinterpret_cast<OTAImageProcessorImpl *>(context);
+    if (imageProcessor != nullptr)
+    {
+        imageProcessor->AbortAllProcessors();
+    }
+    imageProcessor->Clear();
+
+    OtaHookAbort();
+}
+
+void OTAImageProcessorImpl::HandleProcessBlock(intptr_t context)
+{
+    auto * imageProcessor = reinterpret_cast<OTAImageProcessorImpl *>(context);
+
+    VerifyOrReturn(imageProcessor != nullptr, ChipLogError(SoftwareUpdate, "ImageProcessor context is null"));
+
+    VerifyOrReturn(imageProcessor->mDownloader != nullptr, ChipLogError(SoftwareUpdate, "mDownloader is null"));
+
+    CHIP_ERROR status;
+    auto block = ByteSpan(imageProcessor->mBlock.data(), imageProcessor->mBlock.size());
+
+    if (imageProcessor->mHeaderParser.IsInitialized())
+    {
+        status = imageProcessor->ProcessHeader(block);
+        if (status != CHIP_NO_ERROR)
+        {
+            imageProcessor->HandleStatus(status);
+        }
+    }
+
+    status = imageProcessor->ProcessPayload(block);
+    imageProcessor->HandleStatus(status);
+}
+
+void OTAImageProcessorImpl::HandleStatus(CHIP_ERROR status)
+{
+    if (status == CHIP_NO_ERROR || status == CHIP_ERROR_BUFFER_TOO_SMALL)
+    {
+        mParams.downloadedBytes += mBlock.size();
+        FetchNextData(0);
+    }
+    else if (status == CHIP_ERROR_OTA_FETCH_ALREADY_SCHEDULED)
+    {
+        mParams.downloadedBytes += mBlock.size();
+    }
+    else
+    {
+        ChipLogError(SoftwareUpdate, "Image update canceled. Failed to process OTA block: %s", ErrorStr(status));
+        GetRequestorInstance()->CancelImageUpdate();
+    }
+}
+
+void OTAImageProcessorImpl::AbortAllProcessors()
+{
+    ChipLogError(SoftwareUpdate, "All selected processors will call abort action");
+
+    for (auto const & pair : mProcessorMap)
+    {
+        if (pair.second->WasSelected())
+        {
+            pair.second->AbortAction();
+            pair.second->Clear();
+            pair.second->SetWasSelected(false);
+        }
+    }
+}
+
+bool OTAImageProcessorImpl::IsFirstImageRun()
+{
+    OTARequestorInterface * requestor = chip::GetRequestorInstance();
+    if (requestor == nullptr)
+    {
+        return false;
+    }
+
+    return requestor->GetCurrentUpdateState() == OTARequestorInterface::OTAUpdateStateEnum::kApplying;
+}
+
+CHIP_ERROR OTAImageProcessorImpl::ConfirmCurrentImage()
+{
+    uint32_t currentVersion;
+    uint32_t targetVersion;
+
+    OTARequestorInterface * requestor = chip::GetRequestorInstance();
+    ReturnErrorCodeIf(requestor == nullptr, CHIP_ERROR_INTERNAL);
+
+    targetVersion = requestor->GetTargetVersion();
+    ReturnErrorOnFailure(DeviceLayer::ConfigurationMgr().GetSoftwareVersion(currentVersion));
+    if (currentVersion != targetVersion)
+    {
+        ChipLogError(SoftwareUpdate, "Current sw version %" PRIu32 " is different than the expected sw version = %" PRIu32,
+                     currentVersion, targetVersion);
+        return CHIP_ERROR_INCORRECT_STATE;
+    }
+
+    return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR OTAImageProcessorImpl::SetBlock(ByteSpan & block)
+{
+    if (!IsSpanUsable(block))
+    {
+        return CHIP_NO_ERROR;
+    }
+
+    if (mBlock.size() < block.size())
+    {
+        if (!mBlock.empty())
+        {
+            ReleaseBlock();
+        }
+        uint8_t * mBlock_ptr = static_cast<uint8_t *>(chip::Platform::MemoryAlloc(block.size()));
+        if (mBlock_ptr == nullptr)
+        {
+            return CHIP_ERROR_NO_MEMORY;
+        }
+        mBlock = MutableByteSpan(mBlock_ptr, block.size());
+    }
+
+    CHIP_ERROR err = CopySpanToMutableSpan(block, mBlock);
+    if (err != CHIP_NO_ERROR)
+    {
+        ChipLogError(SoftwareUpdate, "Cannot copy block data: %" CHIP_ERROR_FORMAT, err.Format());
+        return err;
+    }
+    return CHIP_NO_ERROR;
+}
+
+void OTAImageProcessorImpl::HandleFinalize(intptr_t context)
+{
+    auto * imageProcessor = reinterpret_cast<OTAImageProcessorImpl *>(context);
+    if (imageProcessor == nullptr)
+    {
+        return;
+    }
+
+    imageProcessor->ReleaseBlock();
+}
+
+void OTAImageProcessorImpl::HandleApply(intptr_t context)
+{
+    CHIP_ERROR error      = CHIP_NO_ERROR;
+    auto * imageProcessor = reinterpret_cast<OTAImageProcessorImpl *>(context);
+    if (imageProcessor == nullptr)
+    {
+        return;
+    }
+
+    for (auto const & pair : imageProcessor->mProcessorMap)
+    {
+        if (pair.second->WasSelected())
+        {
+            error = pair.second->ApplyAction();
+            if (error != CHIP_NO_ERROR)
+            {
+                ChipLogError(SoftwareUpdate, "Apply action for tag %d processor failed.", (uint8_t) pair.first);
+                // Revert all previously applied actions if current apply action fails.
+                // Reset image processor and requestor states.
+                imageProcessor->AbortAllProcessors();
+                imageProcessor->Clear();
+                GetRequestorInstance()->Reset();
+
+                return;
+            }
+        }
+    }
+
+    for (auto const & pair : imageProcessor->mProcessorMap)
+    {
+        pair.second->Clear();
+        pair.second->SetWasSelected(false);
+    }
+
+    imageProcessor->mAccumulator.Clear();
+
+    ConfigurationManagerImpl().StoreSoftwareUpdateCompleted();
+    PlatformMgr().HandleServerShuttingDown();
+
+    // Set the necessary information to inform the SSBL that a new image is available
+    // and trigger the actual device reboot after some time, to take into account
+    // queued actions, e.g. sending events to a subscription
+    SystemLayer().StartTimer(
+        chip::System::Clock::Milliseconds32(CHIP_DEVICE_LAYER_OTA_REBOOT_DELAY),
+        [](chip::System::Layer *, void *) { OtaHookReset(); }, nullptr);
+}
+
+CHIP_ERROR OTAImageProcessorImpl::ReleaseBlock()
+{
+    if (mBlock.data() != nullptr)
+    {
+        chip::Platform::MemoryFree(mBlock.data());
+    }
+
+    mBlock = MutableByteSpan();
+    return CHIP_NO_ERROR;
+}
+
+void OTAImageProcessorImpl::FetchNextData(uint32_t context)
+{
+    auto * imageProcessor = &OTAImageProcessorImpl::GetDefaultInstance();
+    SystemLayer().ScheduleLambda([imageProcessor] {
+        if (imageProcessor->mDownloader)
+        {
+            imageProcessor->mDownloader->FetchNextData();
+        }
+    });
+}
+
+OTAImageProcessorImpl & OTAImageProcessorImpl::GetDefaultInstance()
+{
+    return gImageProcessor;
+}
+
+} // namespace chip
diff --git a/src/platform/nxp/common/legacy/OTAImageProcessorImpl.h b/src/platform/nxp/common/legacy/OTAImageProcessorImpl.h
new file mode 100644
index 00000000000000..a30677037ea7f4
--- /dev/null
+++ b/src/platform/nxp/common/legacy/OTAImageProcessorImpl.h
@@ -0,0 +1,114 @@
+/*
+ *
+ *    Copyright (c) 2021-2023 Project CHIP Authors
+ *    All rights reserved.
+ *
+ *    Licensed under the Apache License, Version 2.0 (the "License");
+ *    you may not use this file except in compliance with the License.
+ *    You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *    Unless required by applicable law or agreed to in writing, software
+ *    distributed under the License is distributed on an "AS IS" BASIS,
+ *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *    See the License for the specific language governing permissions and
+ *    limitations under the License.
+ */
+
+#pragma once
+
+#include <lib/core/OTAImageHeader.h>
+#include <map>
+#include <platform/nxp/common/legacy/OTATlvProcessor.h>
+#include <src/app/clusters/ota-requestor/OTADownloader.h>
+#include <src/app/clusters/ota-requestor/OTARequestorInterface.h>
+#include <src/include/platform/CHIPDeviceLayer.h>
+#include <src/include/platform/OTAImageProcessor.h>
+
+/*
+ * OTA hooks that can be overwritten by application.
+ * Default behavior is implemented as WEAK symbols in platform OtaHooks.cpp.
+ */
+
+/*
+ * This hook is called at the end of OTAImageProcessorImpl::Init.
+ * It should generally register the OTATlvProcessor instances.
+ */
+extern "C" CHIP_ERROR OtaHookInit();
+
+/*
+ * This hook is called at the end of OTAImageProcessorImpl::HandleApply.
+ * The default implementation saves the internal OTA entry structure and resets the device.
+ */
+extern "C" void OtaHookReset();
+
+/*
+ * This hook is called at the end of OTAImageProcessorImpl::HandleAbort.
+ * For example, it can be used to schedule a retry.
+ */
+extern "C" void OtaHookAbort();
+
+namespace chip {
+
+class OTAImageProcessorImpl : public OTAImageProcessorInterface
+{
+public:
+    using ProviderLocation = chip::OTARequestorInterface::ProviderLocationType;
+
+    CHIP_ERROR Init(OTADownloader * downloader);
+    void Clear();
+
+    //////////// OTAImageProcessorInterface Implementation ///////////////
+    CHIP_ERROR PrepareDownload() override;
+    CHIP_ERROR Finalize() override;
+    CHIP_ERROR Apply() override;
+    CHIP_ERROR Abort() override;
+    CHIP_ERROR ProcessBlock(ByteSpan & block) override;
+    bool IsFirstImageRun() override;
+    CHIP_ERROR ConfirmCurrentImage() override;
+
+    CHIP_ERROR ProcessHeader(ByteSpan & block);
+    CHIP_ERROR ProcessPayload(ByteSpan & block);
+    CHIP_ERROR SelectProcessor(ByteSpan & block);
+    CHIP_ERROR RegisterProcessor(uint32_t tag, OTATlvProcessor * processor);
+    Optional<ProviderLocation> & GetBackupProvider() { return mBackupProviderLocation; }
+
+    static void FetchNextData(uint32_t context);
+    static OTAImageProcessorImpl & GetDefaultInstance();
+
+private:
+    //////////// Actual handlers for the OTAImageProcessorInterface ///////////////
+    static void HandlePrepareDownload(intptr_t context);
+    static void HandleFinalize(intptr_t context);
+    static void HandleApply(intptr_t context);
+    static void HandleAbort(intptr_t context);
+    static void HandleProcessBlock(intptr_t context);
+
+    void HandleStatus(CHIP_ERROR status);
+
+    /**
+     * Called to allocate memory for mBlock if necessary and set it to block
+     */
+    CHIP_ERROR SetBlock(ByteSpan & block);
+
+    /**
+     * Called to release allocated memory for mBlock
+     */
+    CHIP_ERROR ReleaseBlock();
+
+    /**
+     * Call AbortAction for all processors that were used
+     */
+    void AbortAllProcessors();
+
+    MutableByteSpan mBlock;
+    OTADownloader * mDownloader;
+    OTAImageHeaderParser mHeaderParser;
+    OTATlvProcessor * mCurrentProcessor = nullptr;
+    OTADataAccumulator mAccumulator;
+    std::map<uint32_t, OTATlvProcessor *> mProcessorMap;
+    Optional<ProviderLocation> mBackupProviderLocation;
+};
+
+} // namespace chip
diff --git a/src/platform/nxp/common/legacy/OTATlvProcessor.cpp b/src/platform/nxp/common/legacy/OTATlvProcessor.cpp
new file mode 100644
index 00000000000000..e50da13cecdd31
--- /dev/null
+++ b/src/platform/nxp/common/legacy/OTATlvProcessor.cpp
@@ -0,0 +1,178 @@
+/*
+ *
+ *    Copyright (c) 2023 Project CHIP Authors
+ *    All rights reserved.
+ *
+ *    Licensed under the Apache License, Version 2.0 (the "License");
+ *    you may not use this file except in compliance with the License.
+ *    You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *    Unless required by applicable law or agreed to in writing, software
+ *    distributed under the License is distributed on an "AS IS" BASIS,
+ *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *    See the License for the specific language governing permissions and
+ *    limitations under the License.
+ */
+
+#include <lib/core/TLV.h>
+#include <lib/support/BufferReader.h>
+#include <platform/internal/CHIPDeviceLayerInternal.h>
+
+#include <platform/nxp/common/legacy/OTAImageProcessorImpl.h>
+#include <platform/nxp/common/legacy/OTATlvProcessor.h>
+#if OTA_ENCRYPTION_ENABLE
+#include "OtaUtils.h"
+#include "rom_aes.h"
+#endif
+namespace chip {
+
+#if OTA_ENCRYPTION_ENABLE
+constexpr uint8_t au8Iv[] = { 0x00, 0x00, 0x00, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x00, 0x00, 0x00, 0x00 };
+#endif
+
+CHIP_ERROR OTATlvProcessor::ApplyAction()
+{
+    return mApplyState == ApplyState::kApply ? CHIP_NO_ERROR : CHIP_ERROR_OTA_PROCESSOR_DO_NOT_APPLY;
+}
+
+CHIP_ERROR OTATlvProcessor::Process(ByteSpan & block)
+{
+    CHIP_ERROR status     = CHIP_NO_ERROR;
+    uint32_t bytes        = chip::min(mLength - mProcessedLength, static_cast<uint32_t>(block.size()));
+    ByteSpan relevantData = block.SubSpan(0, bytes);
+
+    status = ProcessInternal(relevantData);
+    if (!IsError(status))
+    {
+        mProcessedLength += bytes;
+        block = block.SubSpan(bytes);
+        if (mProcessedLength == mLength)
+        {
+            status = ExitAction();
+            if (!IsError(status))
+            {
+                // If current block was processed fully and the block still contains data, it
+                // means that the block contains another TLV's data and the current processor
+                // should be changed by OTAImageProcessorImpl.
+                return CHIP_ERROR_OTA_CHANGE_PROCESSOR;
+            }
+        }
+    }
+
+    return status;
+}
+
+void OTATlvProcessor::ClearInternal()
+{
+    mLength          = 0;
+    mProcessedLength = 0;
+    mWasSelected     = false;
+    mApplyState      = ApplyState::kApply;
+#if OTA_ENCRYPTION_ENABLE
+    mIVOffset = 0;
+#endif
+}
+
+bool OTATlvProcessor::IsError(CHIP_ERROR & status)
+{
+    return status != CHIP_NO_ERROR && status != CHIP_ERROR_BUFFER_TOO_SMALL && status != CHIP_ERROR_OTA_FETCH_ALREADY_SCHEDULED;
+}
+
+void OTADataAccumulator::Init(uint32_t threshold)
+{
+    mThreshold    = threshold;
+    mBufferOffset = 0;
+    mBuffer.Alloc(mThreshold);
+}
+
+void OTADataAccumulator::Clear()
+{
+    mThreshold    = 0;
+    mBufferOffset = 0;
+    mBuffer.Free();
+}
+
+CHIP_ERROR OTADataAccumulator::Accumulate(ByteSpan & block)
+{
+    uint32_t numBytes = chip::min(mThreshold - mBufferOffset, static_cast<uint32_t>(block.size()));
+    memcpy(&mBuffer[mBufferOffset], block.data(), numBytes);
+    mBufferOffset += numBytes;
+    block = block.SubSpan(numBytes);
+
+    if (mBufferOffset < mThreshold)
+    {
+        return CHIP_ERROR_BUFFER_TOO_SMALL;
+    }
+
+    return CHIP_NO_ERROR;
+}
+
+#if OTA_ENCRYPTION_ENABLE
+CHIP_ERROR OTATlvProcessor::vOtaProcessInternalEncryption(MutableByteSpan & block)
+{
+    uint8_t iv[16];
+    uint8_t key[kOTAEncryptionKeyLength];
+    uint8_t dataOut[16] = { 0 };
+    uint32_t u32IVCount;
+    uint32_t Offset = 0;
+    uint8_t data;
+    tsReg128 sKey;
+    aesContext_t Context;
+
+    memcpy(iv, au8Iv, sizeof(au8Iv));
+
+    u32IVCount = (((uint32_t) iv[12]) << 24) | (((uint32_t) iv[13]) << 16) | (((uint32_t) iv[14]) << 8) | (iv[15]);
+    u32IVCount += (mIVOffset >> 4);
+
+    iv[12] = (uint8_t) ((u32IVCount >> 24) & 0xff);
+    iv[13] = (uint8_t) ((u32IVCount >> 16) & 0xff);
+    iv[14] = (uint8_t) ((u32IVCount >> 8) & 0xff);
+    iv[15] = (uint8_t) (u32IVCount & 0xff);
+
+    if (Encoding::HexToBytes(OTA_ENCRYPTION_KEY, strlen(OTA_ENCRYPTION_KEY), key, kOTAEncryptionKeyLength) !=
+        kOTAEncryptionKeyLength)
+    {
+        // Failed to convert the OTAEncryptionKey string to octstr type value
+        return CHIP_ERROR_INVALID_STRING_LENGTH;
+    }
+
+    ByteSpan KEY = ByteSpan(key);
+    Encoding::LittleEndian::Reader reader_key(KEY.data(), KEY.size());
+    ReturnErrorOnFailure(reader_key.Read32(&sKey.u32register0)
+                             .Read32(&sKey.u32register1)
+                             .Read32(&sKey.u32register2)
+                             .Read32(&sKey.u32register3)
+                             .StatusCode());
+
+    while (Offset + 16 <= block.size())
+    {
+        /*Encrypt the IV*/
+        Context.mode         = AES_MODE_ECB_ENCRYPT;
+        Context.pSoftwareKey = (uint32_t *) &sKey;
+        AES_128_ProcessBlocks(&Context, (uint32_t *) &iv[0], (uint32_t *) &dataOut[0], 1);
+
+        /* Decrypt a block of the buffer */
+        for (uint8_t i = 0; i < 16; i++)
+        {
+            data = block[Offset + i] ^ dataOut[i];
+            memcpy(&block[Offset + i], &data, sizeof(uint8_t));
+        }
+
+        /* increment the IV for the next block  */
+        u32IVCount++;
+
+        iv[12] = (uint8_t) ((u32IVCount >> 24) & 0xff);
+        iv[13] = (uint8_t) ((u32IVCount >> 16) & 0xff);
+        iv[14] = (uint8_t) ((u32IVCount >> 8) & 0xff);
+        iv[15] = (uint8_t) (u32IVCount & 0xff);
+
+        Offset += 16; /* increment the buffer offset */
+        mIVOffset += 16;
+    }
+
+    return CHIP_NO_ERROR;
+}
+#endif
+} // namespace chip
diff --git a/src/platform/nxp/common/legacy/OTATlvProcessor.h b/src/platform/nxp/common/legacy/OTATlvProcessor.h
new file mode 100644
index 00000000000000..f1faef7e8eecf9
--- /dev/null
+++ b/src/platform/nxp/common/legacy/OTATlvProcessor.h
@@ -0,0 +1,180 @@
+/*
+ *
+ *    Copyright (c) 2023 Project CHIP Authors
+ *    All rights reserved.
+ *
+ *    Licensed under the Apache License, Version 2.0 (the "License");
+ *    you may not use this file except in compliance with the License.
+ *    You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *    Unless required by applicable law or agreed to in writing, software
+ *    distributed under the License is distributed on an "AS IS" BASIS,
+ *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *    See the License for the specific language governing permissions and
+ *    limitations under the License.
+ */
+
+#pragma once
+
+#include <lib/core/Optional.h>
+#include <lib/support/ScopedBuffer.h>
+#include <lib/support/Span.h>
+
+namespace chip {
+
+#define CHIP_ERROR_TLV_PROCESSOR(e)                                                                                                \
+    ChipError(ChipError::Range::kLastRange, ((uint8_t) ChipError::Range::kLastRange << 3) | e, __FILE__, __LINE__)
+
+#define CHIP_ERROR_OTA_CHANGE_PROCESSOR CHIP_ERROR_TLV_PROCESSOR(0x02)
+#define CHIP_ERROR_OTA_PROCESSOR_NOT_REGISTERED CHIP_ERROR_TLV_PROCESSOR(0x03)
+#define CHIP_ERROR_OTA_PROCESSOR_ALREADY_REGISTERED CHIP_ERROR_TLV_PROCESSOR(0x04)
+#define CHIP_ERROR_OTA_PROCESSOR_CLIENT_INIT CHIP_ERROR_TLV_PROCESSOR(0x05)
+#define CHIP_ERROR_OTA_PROCESSOR_MAKE_ROOM CHIP_ERROR_TLV_PROCESSOR(0x06)
+#define CHIP_ERROR_OTA_PROCESSOR_PUSH_CHUNK CHIP_ERROR_TLV_PROCESSOR(0x07)
+#define CHIP_ERROR_OTA_PROCESSOR_IMG_AUTH CHIP_ERROR_TLV_PROCESSOR(0x08)
+#define CHIP_ERROR_OTA_FETCH_ALREADY_SCHEDULED CHIP_ERROR_TLV_PROCESSOR(0x09)
+#define CHIP_ERROR_OTA_PROCESSOR_IMG_COMMIT CHIP_ERROR_TLV_PROCESSOR(0x0A)
+#define CHIP_ERROR_OTA_PROCESSOR_CB_NOT_REGISTERED CHIP_ERROR_TLV_PROCESSOR(0x0B)
+#define CHIP_ERROR_OTA_PROCESSOR_EEPROM_OFFSET CHIP_ERROR_TLV_PROCESSOR(0x0C)
+#define CHIP_ERROR_OTA_PROCESSOR_EXTERNAL_STORAGE CHIP_ERROR_TLV_PROCESSOR(0x0D)
+#define CHIP_ERROR_OTA_PROCESSOR_START_IMAGE CHIP_ERROR_TLV_PROCESSOR(0x0E)
+#define CHIP_ERROR_OTA_PROCESSOR_DO_NOT_APPLY CHIP_ERROR_TLV_PROCESSOR(0x0F)
+
+// Descriptor constants
+constexpr size_t kVersionStringSize = 64;
+constexpr size_t kBuildDateSize     = 64;
+
+constexpr uint16_t requestedOtaMaxBlockSize = 1024;
+
+/**
+ * Used alongside RegisterDescriptorCallback to register
+ * a custom descriptor processing function with a certain
+ * TLV processor.
+ */
+typedef CHIP_ERROR (*ProcessDescriptor)(void * descriptor);
+
+struct OTATlvHeader
+{
+    uint32_t tag;
+    uint32_t length;
+};
+
+/**
+ * This class defines an interface for a Matter TLV processor.
+ * Instances of derived classes can be registered as processors
+ * in OTAImageProcessorImpl. Based on the TLV type, a certain
+ * processor is used to process subsequent blocks until the number
+ * of bytes found in the metadata is processed. In case a block contains
+ * data from two different TLVs, the processor should ensure the remaining
+ * data is returned in the block passed as input.
+ * The default processors: application, SSBL and factory data are registered
+ * in OTAImageProcessorImpl::Init through OtaHookInit.
+ * Applications should use OTAImageProcessorImpl::RegisterProcessor
+ * to register additional processors.
+ */
+class OTATlvProcessor
+{
+public:
+    enum class ApplyState : uint8_t
+    {
+        kApply = 0,
+        kDoNotApply
+    };
+
+    virtual ~OTATlvProcessor() {}
+
+    virtual CHIP_ERROR Init()        = 0;
+    virtual CHIP_ERROR Clear()       = 0;
+    virtual CHIP_ERROR AbortAction() = 0;
+    virtual CHIP_ERROR ExitAction() { return CHIP_NO_ERROR; }
+    virtual CHIP_ERROR ApplyAction();
+
+    CHIP_ERROR Process(ByteSpan & block);
+    void RegisterDescriptorCallback(ProcessDescriptor callback) { mCallbackProcessDescriptor = callback; }
+    void SetLength(uint32_t length) { mLength = length; }
+    void SetWasSelected(bool selected) { mWasSelected = selected; }
+    bool WasSelected() { return mWasSelected; }
+#if OTA_ENCRYPTION_ENABLE
+    CHIP_ERROR vOtaProcessInternalEncryption(MutableByteSpan & block);
+#endif
+
+protected:
+    /**
+     * @brief Process custom TLV payload
+     *
+     * The method takes subsequent chunks of the Matter OTA image file and processes them.
+     * If more image chunks are needed, CHIP_ERROR_BUFFER_TOO_SMALL error is returned.
+     * Other error codes indicate that an error occurred during processing. Fetching
+     * next data is scheduled automatically by OTAImageProcessorImpl if the return value
+     * is neither an error code, nor CHIP_ERROR_OTA_FETCH_ALREADY_SCHEDULED (which implies the
+     * scheduling is done inside ProcessInternal or will be done in the future, through a
+     * callback).
+     *
+     * @param block Byte span containing a subsequent Matter OTA image chunk. When the method
+     *              returns CHIP_NO_ERROR, the byte span is used to return a remaining part
+     *              of the chunk, not used by current TLV processor.
+     *
+     * @retval CHIP_NO_ERROR                          Block was processed successfully.
+     * @retval CHIP_ERROR_BUFFER_TOO_SMALL            Provided buffers are insufficient to decode some
+     *                                                metadata (e.g. a descriptor).
+     * @retval CHIP_ERROR_OTA_FETCH_ALREADY_SCHEDULED Should be returned if ProcessInternal schedules
+     *                                                fetching next data (e.g. through a callback).
+     * @retval Error code                             Something went wrong. Current OTA process will be
+     *                                                canceled.
+     */
+    virtual CHIP_ERROR ProcessInternal(ByteSpan & block) = 0;
+
+    void ClearInternal();
+
+    bool IsError(CHIP_ERROR & status);
+
+#if OTA_ENCRYPTION_ENABLE
+    /*ota decryption*/
+    uint32_t mIVOffset = 0;
+    /* Expected byte size of the OTAEncryptionKeyLength */
+    static constexpr size_t kOTAEncryptionKeyLength = 16;
+#endif
+    uint32_t mLength          = 0;
+    uint32_t mProcessedLength = 0;
+    bool mWasSelected         = false;
+
+    /**
+     * @brief A flag to account for corner cases during OTA apply
+     *
+     * Used by the default ApplyAction implementation.
+     *
+     * If something goes wrong during ExitAction of the TLV processor,
+     * then mApplyState should be set to kDoNotApply and the image processor
+     * should abort. In this case, the BDX transfer was already finished
+     * and calling CancelImageUpdate will not abort the transfer, hence
+     * the device will reboot even though it should not have. If ApplyAction
+     * fails during HandleApply, then the process will be aborted.
+     */
+    ApplyState mApplyState                       = ApplyState::kApply;
+    ProcessDescriptor mCallbackProcessDescriptor = nullptr;
+};
+
+/**
+ * This class can be used to accumulate data until a given threshold.
+ * Should be used by OTATlvProcessor derived classes if they need
+ * metadata accumulation (e.g. for custom header decoding).
+ */
+class OTADataAccumulator
+{
+public:
+    void Init(uint32_t threshold);
+    void Clear();
+    CHIP_ERROR Accumulate(ByteSpan & block);
+
+    inline uint8_t * data() { return mBuffer.Get(); }
+    inline uint32_t GetThreshold() { return mThreshold; }
+
+private:
+    uint32_t mThreshold;
+    uint32_t mBufferOffset;
+    Platform::ScopedMemoryBuffer<uint8_t> mBuffer;
+};
+
+} // namespace chip
diff --git a/src/platform/nxp/common/legacy/OTA_README.md b/src/platform/nxp/common/legacy/OTA_README.md
new file mode 100644
index 00000000000000..0c9715b4610ff8
--- /dev/null
+++ b/src/platform/nxp/common/legacy/OTA_README.md
@@ -0,0 +1,149 @@
+# K32W OTA
+
+The OTA processing is now delegated to instances of `OTATlvProcessor` derived
+classes. These instances are registered with the `OTAImageProcessorImpl`
+instance, which manages the selection of processors that should process the next
+blocks, until a full TLV block was transferred.
+
+The application is able to define its own processors, thus extending the default
+OTA functionality. The application can also opt to disable the default
+processors (application, SSBL and factory data).
+
+Please note that if an OTA image containing multiple TLV is transferred, then
+the action for each TLV is applied sequentially, If one of the actions fails,
+the remaining actions will not be applied and OTA abort is called. TBD: should
+all actions be applied only if there is no error? Or should each action be
+applied separately?
+
+## Default processors
+
+The default processors for K32W0 are already implemented in:
+
+-   `OTAFirmwareProcessor` for application/SSBL update. Enabled by default.
+-   `OTAFactoryDataProcessor` for factory data update. Disabled by default, user
+    has to specify `chip_ota_enable_factory_data_processor=1` in the build args.
+
+Some SDK OTA module flags are defined to support additional features:
+
+-   `gOTAAllowCustomStartAddress=1` - enable `EEPROM` offset value. Used
+    internally by SDK OTA module.
+-   `gOTAUseCustomOtaEntry=1` - support custom OTA entry for multi-image.
+-   `gOTACustomOtaEntryMemory=1` - K32W0 uses `OTACustomStorage_ExtFlash` (1) by
+    default.
+
+## Implementing custom processors
+
+A custom processor should implement the abstract interface defined in
+`OTATlvProcessor.h`. Below is a compact version:
+
+```
+class OTATlvProcessor
+{
+public:
+    virtual CHIP_ERROR Init() = 0;
+    virtual CHIP_ERROR Clear() = 0;
+    virtual CHIP_ERROR ApplyAction() = 0;
+    virtual CHIP_ERROR AbortAction() = 0;
+    virtual CHIP_ERROR ExitAction();
+
+    CHIP_ERROR Process(ByteSpan & block);
+    void RegisterDescriptorCallback(ProcessDescriptor callback);
+protected:
+    virtual CHIP_ERROR ProcessInternal(ByteSpan & block) = 0;
+};
+
+```
+
+Some details regarding the interface:
+
+-   `Init` will be called whenever the processor is selected.
+-   `Clear` will be called when abort occurs or after the apply action takes
+    place.
+-   `ApplyAction` will be called in `OTAImageProcessorImpl::HandleApply`, before
+    the board is reset.
+-   `AbortAction` will be called in `OTAImageProcessorImpl::HandleAbort`.
+    Processors should reset state here.
+-   `ExitAction` is optional and should be implemented by the processors that
+    want to execute an action after all data has been transferred, but before
+    `HandleApply` is called. It's called before the new processor selection
+    takes place. This is useful in the context of multiple TLV transferred in a
+    single OTA process.
+-   `Process` is the public API used inside `OTAImageProcessorImpl` for data
+    processing. This is a wrapper over `ProcessInternal`, which can return
+    `CHIP_OTA_CHANGE_PROCESSOR` to notify a new processor should be selected for
+    the remaining data.
+-   `RegisterDescriptorCallback` can be used to register a callback for
+    processing the descriptor. It's optional.
+-   `ProcessInternal` should return: _ `CHIP_NO_ERROR` if block was processed
+    successfully. _ `CHIP_ERROR_BUFFER_TOO_SMALL` if current block doesn't
+    contain all necessary data. This can happen when a TLV value field has a
+    header, but it is split across two blocks. \*
+    `CHIP_OTA_FETCH_ALREADY_SCHEDULED` if block was processed successfully and
+    the fetching is already scheduled by the processor. This happens in the
+    default application processor, because the next data fetching is scheduled
+    through a callback (called when enough external flash was erased).
+
+Furthermore, a processor can use an instance of `OTADataAccumulator` to
+accumulate data until a given threshold. This is useful when a custom payload
+contains metadata that need parsing: accumulate data until the threshold is
+reached or return `CHIP_ERROR_BUFFER_TOO_SMALL` to signal
+`OTAImageProcessorImpl` more data is needed.
+
+```
+/**
+ * This class can be used to accumulate data until a given threshold.
+ * Should be used by OTATlvProcessor derived classes if they need
+ * metadata accumulation (e.g. for custom header decoding).
+ */
+class OTADataAccumulator
+{
+public:
+    void Init(uint32_t threshold);
+    void Clear();
+    CHIP_ERROR Accumulate(ByteSpan & block);
+
+    inline uint8_t* data() { return mBuffer.Get(); }
+
+private:
+    uint32_t mThreshold;
+    uint32_t mBufferOffset;
+    Platform::ScopedMemoryBuffer<uint8_t> mBuffer;
+};
+```
+
+## SSBL max entries example
+
+`CONFIG_CHIP_K32W0_MAX_ENTRIES_TEST` can be set to 1 to enable max entries test.
+There will be 8 additional processors registered in default `OtaHooks`
+implementation. The OTA image should be generated with the
+`create_ota_images.sh` script from `./scripts/tools/nxp/ota/examples`.
+
+## Factory data restore mechanism
+
+Prior to factory data update, the old factory data is backed up in external
+flash. If anything interrupts the update (e.g. power loss), there is a slight
+chance the internal flash factory data section is erased and has to be restored
+at next boot. The `FactoryDataProvider` offers a default restore mechanism and
+support for registering additional restore mechanisms or overwriting the default
+one.
+
+Prior to factory data update, the old factory data is backed up in external
+flash. If anything interrupts the update (e.g. power loss), there is a slight
+chance the internal flash factory data section is erased and has to be restored
+at next boot. The `FactoryDataProvider` offers a default restore mechanism and
+support for registering additional restore mechanisms or overwriting the default
+one.
+
+Restore mechanisms are just functions that have this signature:
+`CHIP_ERROR (*)(void)`. Any such function can be registered through
+`FactoryDataProvider::RegisterRestoreMechanism`.
+
+The default restore mechanism is implemented as a weak function:
+`FactoryDataDefaultRestoreMechanism`. It is registered in
+`FactoryDataProvider::Init`, before factory data validation, and it can be
+overwritten at application level. When doing the actual restore, the mechanisms
+are called in the order they were registered.
+
+Please note that the restore mechanisms registration order matters. Once a
+restore mechanism is successful (`CHIP_NO_ERROR` is returned), the restore
+process has finished and subsequent restore mechanisms will not be called.
diff --git a/src/platform/nxp/k32w/k32w0/DefaultTestEventTriggerDelegate.cpp b/src/platform/nxp/k32w/k32w0/DefaultTestEventTriggerDelegate.cpp
deleted file mode 100644
index 69935bb024559d..00000000000000
--- a/src/platform/nxp/k32w/k32w0/DefaultTestEventTriggerDelegate.cpp
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- *
- *    Copyright (c) 2022 Project CHIP Authors
- *    All rights reserved.
- *
- *    Licensed under the Apache License, Version 2.0 (the "License");
- *    you may not use this file except in compliance with the License.
- *    You may obtain a copy of the License at
- *
- *        http://www.apache.org/licenses/LICENSE-2.0
- *
- *    Unless required by applicable law or agreed to in writing, software
- *    distributed under the License is distributed on an "AS IS" BASIS,
- *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *    See the License for the specific language governing permissions and
- *    limitations under the License.
- */
-
-#include "DefaultTestEventTriggerDelegate.h"
-
-#include <lib/support/CodeUtils.h>
-#include <lib/support/logging/CHIPLogging.h>
-
-namespace chip {
-
-bool DefaultTestEventTriggerDelegate::DoesEnableKeyMatch(const ByteSpan & enableKey) const
-{
-    return !mEnableKey.empty() && mEnableKey.data_equal(enableKey);
-}
-
-} // namespace chip
diff --git a/src/platform/nxp/k32w/k32w0/DefaultTestEventTriggerDelegate.h b/src/platform/nxp/k32w/k32w0/DefaultTestEventTriggerDelegate.h
deleted file mode 100644
index 0bfd4c5b0fa725..00000000000000
--- a/src/platform/nxp/k32w/k32w0/DefaultTestEventTriggerDelegate.h
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- *
- *    Copyright (c) 2022 Project CHIP Authors
- *    All rights reserved.
- *
- *    Licensed under the Apache License, Version 2.0 (the "License");
- *    you may not use this file except in compliance with the License.
- *    You may obtain a copy of the License at
- *
- *        http://www.apache.org/licenses/LICENSE-2.0
- *
- *    Unless required by applicable law or agreed to in writing, software
- *    distributed under the License is distributed on an "AS IS" BASIS,
- *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *    See the License for the specific language governing permissions and
- *    limitations under the License.
- */
-
-#pragma once
-
-#include <app/TestEventTriggerDelegate.h>
-
-namespace chip {
-
-class DefaultTestEventTriggerDelegate : public TestEventTriggerDelegate
-{
-public:
-    explicit DefaultTestEventTriggerDelegate(const ByteSpan & enableKey) : mEnableKey(enableKey) {}
-
-    bool DoesEnableKeyMatch(const ByteSpan & enableKey) const override;
-
-private:
-    ByteSpan mEnableKey;
-};
-
-} // namespace chip
diff --git a/src/platform/nxp/k32w/k32w0/BLEManagerImpl.cpp b/src/platform/nxp/k32w0/BLEManagerImpl.cpp
similarity index 98%
rename from src/platform/nxp/k32w/k32w0/BLEManagerImpl.cpp
rename to src/platform/nxp/k32w0/BLEManagerImpl.cpp
index af56961cf23dc1..aa56e06a8d5598 100644
--- a/src/platform/nxp/k32w/k32w0/BLEManagerImpl.cpp
+++ b/src/platform/nxp/k32w0/BLEManagerImpl.cpp
@@ -37,7 +37,7 @@ osaEventId_t mControllerTaskEvent;
 extern msgQueue_t gApp2Host_TaskQueue;
 extern msgQueue_t gHci2Host_TaskQueue;
 
-#include <platform/nxp/k32w/k32w0/BLEManagerImpl.h>
+#include <platform/nxp/k32w0/BLEManagerImpl.h>
 
 extern "C" bool_t Ble_ConfigureHostStackConfig(void);
 
diff --git a/src/platform/nxp/k32w/k32w0/BLEManagerImpl.h b/src/platform/nxp/k32w0/BLEManagerImpl.h
similarity index 97%
rename from src/platform/nxp/k32w/k32w0/BLEManagerImpl.h
rename to src/platform/nxp/k32w0/BLEManagerImpl.h
index eb8a25804804d1..686eb1e3f703ee 100644
--- a/src/platform/nxp/k32w/k32w0/BLEManagerImpl.h
+++ b/src/platform/nxp/k32w0/BLEManagerImpl.h
@@ -25,7 +25,7 @@
 #include "ble_host_task_config.h"
 #include "controller_interface.h"
 
-#include <src/platform/nxp/k32w/common/BLEManagerCommon.h>
+#include <src/platform/nxp/common/legacy/BLEManagerCommon.h>
 
 /* host task configuration */
 #define HOST_TASK_PRIORITY (4U)
diff --git a/src/platform/nxp/k32w/k32w0/BUILD.gn b/src/platform/nxp/k32w0/BUILD.gn
similarity index 77%
rename from src/platform/nxp/k32w/k32w0/BUILD.gn
rename to src/platform/nxp/k32w0/BUILD.gn
index 76af2760bc9051..41a80a77a7aa53 100644
--- a/src/platform/nxp/k32w/k32w0/BUILD.gn
+++ b/src/platform/nxp/k32w0/BUILD.gn
@@ -19,17 +19,18 @@ import("${chip_root}/src/platform/device.gni")
 import("${nxp_sdk_build_root}/${nxp_sdk_name}/${nxp_sdk_name}.gni")
 
 assert(chip_device_platform == "nxp")
-assert(nxp_platform == "k32w/k32w0")
+assert(nxp_platform == "k32w0")
 
 if (chip_enable_openthread) {
   import("//build_overrides/openthread.gni")
 }
 
 static_library("nxp_platform") {
+  defines = []
   sources = [
-    "../../../SingletonConfigurationManager.cpp",
-    "../common/BLEManagerCommon.cpp",
-    "../common/BLEManagerCommon.h",
+    "../../SingletonConfigurationManager.cpp",
+    "../common/legacy/BLEManagerCommon.cpp",
+    "../common/legacy/BLEManagerCommon.h",
     "BLEManagerImpl.cpp",
     "BLEManagerImpl.h",
     "CHIPDevicePlatformConfig.h",
@@ -38,8 +39,6 @@ static_library("nxp_platform") {
     "ConfigurationManagerImpl.h",
     "ConnectivityManagerImpl.cpp",
     "ConnectivityManagerImpl.h",
-    "DefaultTestEventTriggerDelegate.cpp",
-    "DefaultTestEventTriggerDelegate.h",
     "DiagnosticDataProviderImpl.cpp",
     "DiagnosticDataProviderImpl.h",
     "K32W0Config.cpp",
@@ -60,12 +59,12 @@ static_library("nxp_platform") {
     "${chip_root}/src/credentials/examples/DeviceAttestationCredsExample.h",
     "${chip_root}/src/credentials/examples/ExampleDACs.h",
     "${chip_root}/src/credentials/examples/ExamplePAI.h",
-    "${chip_root}/src/platform/nxp/k32w/k32w0/BLEManagerImpl.h",
+    "${chip_root}/src/platform/nxp/k32w0/BLEManagerImpl.h",
   ]
 
   if (chip_with_factory_data == 1) {
     sources += [
-      "../common/FactoryDataProvider.cpp",
+      "FactoryDataProvider.cpp",
       "FactoryDataProviderImpl.cpp",
     ]
     public += [
@@ -79,13 +78,13 @@ static_library("nxp_platform") {
   }
 
   if (chip_enable_ota_requestor) {
-    public += [ "../common/OTAImageProcessorImpl.h" ]
+    public += [ "../common/legacy/OTAImageProcessorImpl.h" ]
 
     sources += [
-      "../common/OTAImageProcessorImpl.cpp",
-      "../common/OTAImageProcessorImpl.h",
-      "../common/OTATlvProcessor.cpp",
-      "../common/OTATlvProcessor.h",
+      "../common/legacy/OTAImageProcessorImpl.cpp",
+      "../common/legacy/OTAImageProcessorImpl.h",
+      "../common/legacy/OTATlvProcessor.cpp",
+      "../common/legacy/OTATlvProcessor.h",
     ]
 
     if (chip_enable_ota_firmware_processor == 1) {
@@ -107,10 +106,7 @@ static_library("nxp_platform") {
 
   deps = [ "${chip_root}/src/platform/logging:headers" ]
 
-  public_deps = [
-    "${chip_root}/src/app:test-event-trigger",
-    "${chip_root}/src/platform:platform_base",
-  ]
+  public_deps = [ "${chip_root}/src/platform:platform_base" ]
 
   if (chip_crypto == "platform") {
     if (chip_crypto_flavor == "tinycrypt") {
@@ -120,7 +116,7 @@ static_library("nxp_platform") {
     }
 
     if (chip_crypto_flavor == "NXP-Ultrafast-P256") {
-      sources += [ "${chip_root}/src/platform/nxp/k32w/k32w0/crypto/CHIPCryptoPALNXPUltrafastP256.cpp" ]
+      sources += [ "${chip_root}/src/platform/nxp/k32w0/crypto/CHIPCryptoPALNXPUltrafastP256.cpp" ]
 
       public_deps += [
         "${mbedtls_root}:mbedtls",
@@ -131,16 +127,16 @@ static_library("nxp_platform") {
 
   if (chip_enable_openthread) {
     sources += [
-      "../../../OpenThread/OpenThreadUtils.cpp",
+      "../../OpenThread/OpenThreadUtils.cpp",
       "ThreadStackManagerImpl.cpp",
       "ThreadStackManagerImpl.h",
     ]
 
     if (chip_mdns == "platform") {
       sources += [
-        "../../../OpenThread/DnssdImpl.cpp",
-        "../../../OpenThread/OpenThreadDnssdImpl.cpp",
-        "../../../OpenThread/OpenThreadDnssdImpl.h",
+        "../../OpenThread/DnssdImpl.cpp",
+        "../../OpenThread/OpenThreadDnssdImpl.cpp",
+        "../../OpenThread/OpenThreadDnssdImpl.h",
       ]
       deps += [ "${chip_root}/src/lib/dnssd:platform_header" ]
     }
diff --git a/src/platform/nxp/k32w/k32w0/BlePlatformConfig.h b/src/platform/nxp/k32w0/BlePlatformConfig.h
similarity index 100%
rename from src/platform/nxp/k32w/k32w0/BlePlatformConfig.h
rename to src/platform/nxp/k32w0/BlePlatformConfig.h
diff --git a/src/platform/nxp/k32w/k32w0/CHIPDevicePlatformConfig.h b/src/platform/nxp/k32w0/CHIPDevicePlatformConfig.h
similarity index 97%
rename from src/platform/nxp/k32w/k32w0/CHIPDevicePlatformConfig.h
rename to src/platform/nxp/k32w0/CHIPDevicePlatformConfig.h
index faa283ffbe41dc..523d6e8941232d 100644
--- a/src/platform/nxp/k32w/k32w0/CHIPDevicePlatformConfig.h
+++ b/src/platform/nxp/k32w0/CHIPDevicePlatformConfig.h
@@ -135,14 +135,14 @@
 #endif // CONFIG_CHIP_K32W0_KVS_MOVE_KEYS_TO_SPECIFIC_STORAGE
 
 /**
- * @def CONFIG_CHIP_K32W0_OTA_FACTORY_DATA_PROCESSOR
+ * @def CONFIG_CHIP_OTA_FACTORY_DATA_PROCESSOR
  *
  * Enables default OTA TLV factory data processor.
  * Disabled by default.
  */
-#ifndef CONFIG_CHIP_K32W0_OTA_FACTORY_DATA_PROCESSOR
-#define CONFIG_CHIP_K32W0_OTA_FACTORY_DATA_PROCESSOR 0
-#endif // CONFIG_CHIP_K32W0_OTA_FACTORY_DATA_PROCESSOR
+#ifndef CONFIG_CHIP_OTA_FACTORY_DATA_PROCESSOR
+#define CONFIG_CHIP_OTA_FACTORY_DATA_PROCESSOR 0
+#endif // CONFIG_CHIP_OTA_FACTORY_DATA_PROCESSOR
 
 /**
  * @def CHIP_DEVICE_LAYER_ENABLE_PDM_LOGS
@@ -211,4 +211,4 @@
 
 #define CHIP_DEVICE_CONFIG_ENABLE_TEST_SETUP_PARAMS 1
 
-#include <platform/nxp/k32w/common/CHIPDevicePlatformRamStorageConfig.h>
+#include <platform/nxp/k32w0/CHIPDevicePlatformRamStorageConfig.h>
diff --git a/src/platform/nxp/k32w/k32w0/CHIPDevicePlatformEvent.h b/src/platform/nxp/k32w0/CHIPDevicePlatformEvent.h
similarity index 100%
rename from src/platform/nxp/k32w/k32w0/CHIPDevicePlatformEvent.h
rename to src/platform/nxp/k32w0/CHIPDevicePlatformEvent.h
diff --git a/src/platform/nxp/k32w0/CHIPDevicePlatformRamStorageConfig.h b/src/platform/nxp/k32w0/CHIPDevicePlatformRamStorageConfig.h
new file mode 100644
index 00000000000000..51ee8c4d27ee79
--- /dev/null
+++ b/src/platform/nxp/k32w0/CHIPDevicePlatformRamStorageConfig.h
@@ -0,0 +1,185 @@
+/*
+ *
+ *    Copyright (c) 2022 Project CHIP Authors
+ *    All rights reserved.
+ *
+ *    Licensed under the Apache License, Version 2.0 (the "License");
+ *    you may not use this file except in compliance with the License.
+ *    You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *    Unless required by applicable law or agreed to in writing, software
+ *    distributed under the License is distributed on an "AS IS" BASIS,
+ *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *    See the License for the specific language governing permissions and
+ *    limitations under the License.
+ */
+
+/**
+ *    @file
+ *          Configuration of RAM storage metadata: key IDs and NVM IDs.
+ */
+
+#pragma once
+
+/* Base key IDs used when creating new keys for RAM storage instances. */
+/**
+ * @def kKeyId_Factory
+ *
+ * Base key id used for factory RAM storage.
+ */
+#ifndef kKeyId_Factory
+#define kKeyId_Factory (uint8_t) 0x01
+#endif
+
+/**
+ * @def kKeyId_Config
+ *
+ * Base key id used for config RAM storage.
+ */
+#ifndef kKeyId_Config
+#define kKeyId_Config (uint8_t) 0x02
+#endif
+
+/**
+ * @def kKeyId_Counter
+ *
+ * Base key id used for counter RAM storage.
+ */
+#ifndef kKeyId_Counter
+#define kKeyId_Counter (uint8_t) 0x03
+#endif
+
+/**
+ * @def kKeyId_KvsKeys
+ *
+ * Base key id used for KVS keys RAM storage.
+ */
+#ifndef kKeyId_KvsKeys
+#define kKeyId_KvsKeys (uint8_t) 0x04
+#endif
+
+/**
+ * @def kKeyId_KvsValues
+ *
+ * Base key id used for KVS values RAM storage.
+ */
+#ifndef kKeyId_KvsValues
+#define kKeyId_KvsValues (uint8_t) 0x05
+#endif
+
+/* PDM IDs used when defining RAM storage instances or RAM buffers (OT). */
+/**
+ * @def kNvmId_Factory
+ *
+ * PDM ID used for factory RAM storage.
+ */
+#ifndef kNvmId_Factory
+#define kNvmId_Factory (uint16_t) 0x5001
+#endif
+
+/**
+ * @def kNvmId_Config
+ *
+ * PDM ID used for config RAM storage.
+ */
+#ifndef kNvmId_Config
+#define kNvmId_Config (uint16_t) 0x5002
+#endif
+
+/**
+ * @def kNvmId_Counter
+ *
+ * PDM ID used for counter RAM storage.
+ */
+#ifndef kNvmId_Counter
+#define kNvmId_Counter (uint16_t) 0x5003
+#endif
+
+/**
+ * @def kNvmId_KvsKeys
+ *
+ * PDM ID used for KVS keys RAM storage.
+ */
+#ifndef kNvmId_KvsKeys
+#define kNvmId_KvsKeys (uint16_t) 0x6000
+#endif
+
+/**
+ * @def kNvmId_KvsValues
+ *
+ * PDM ID used for KVS values RAM storage.
+ * KVS buffer can become quite big, so this PDM
+ * id is used as base id for subsequent PDM ids
+ * used to store data in chunks of PDM page size.
+ * This will use the extended search feature, so
+ * subsequent PDM ids should not be used.
+ */
+#ifndef kNvmId_KvsValues
+#define kNvmId_KvsValues (uint16_t) 0x6001
+#endif
+
+/**
+ * @def kNvmId_KvsSubscription
+ *
+ * PDM ID used for KVS subscription RAM storage.
+ * It will store both keys and values for those keys.
+ */
+#ifndef kNvmId_KvsSubscription
+#define kNvmId_KvsSubscription (uint16_t) 0x6100
+#endif
+
+/**
+ * @def kNvmId_KvsGroups
+ *
+ * PDM ID used for KVS groups RAM storage.
+ * It will store both keys and values for those keys.
+ * This will use the extended search feature, so
+ * subsequent PDM ids should not be used.
+ */
+#ifndef kNvmId_KvsGroups
+#define kNvmId_KvsGroups (uint16_t) 0x6200
+#endif
+
+/**
+ * @def kNvmId_KvsAcl
+ *
+ * PDM ID used for KVS groups RAM storage.
+ * It will store both keys and values for those keys.
+ * This will use the extended search feature, so
+ * subsequent PDM ids should not be used.
+ */
+#ifndef kNvmId_KvsAcl
+#define kNvmId_KvsAcl (uint16_t) 0x6300
+#endif
+
+/**
+ * @def kNvmId_OTConfigData
+ *
+ * PDM ID used for OT RAM buffer.
+ */
+#ifndef kNvmId_OTConfigData
+#define kNvmId_OTConfigData (uint16_t) 0x4F00
+#endif
+
+/**
+ * @def kNvmId_ApplicationBase
+ *
+ * Base PDM ID to be used by applications to define their own
+ * PDM IDs by using an offset.
+ */
+#ifndef kNvmId_ApplicationBase
+#define kNvmId_ApplicationBase (uint16_t) 0xA000
+#endif
+
+#if CONFIG_CHIP_LOAD_REAL_FACTORY_DATA
+/**
+ * @def kNvmId_FactoryDataBackup
+ *
+ * PDM ID used for factory data backup in FactoryDataProvider.
+ */
+#ifndef kNvmId_FactoryDataBackup
+#define kNvmId_FactoryDataBackup (uint16_t) 0x7000
+#endif
+#endif // CONFIG_CHIP_LOAD_REAL_FACTORY_DATA
diff --git a/src/platform/nxp/k32w/k32w0/CHIPPlatformConfig.h b/src/platform/nxp/k32w0/CHIPPlatformConfig.h
similarity index 100%
rename from src/platform/nxp/k32w/k32w0/CHIPPlatformConfig.h
rename to src/platform/nxp/k32w0/CHIPPlatformConfig.h
diff --git a/src/platform/nxp/k32w/k32w0/ConfigurationManagerImpl.cpp b/src/platform/nxp/k32w0/ConfigurationManagerImpl.cpp
similarity index 98%
rename from src/platform/nxp/k32w/k32w0/ConfigurationManagerImpl.cpp
rename to src/platform/nxp/k32w0/ConfigurationManagerImpl.cpp
index b8477051faeade..7343c75b5d5865 100644
--- a/src/platform/nxp/k32w/k32w0/ConfigurationManagerImpl.cpp
+++ b/src/platform/nxp/k32w0/ConfigurationManagerImpl.cpp
@@ -29,8 +29,8 @@
 #include <platform/ConfigurationManager.h>
 #include <platform/DiagnosticDataProvider.h>
 #include <platform/internal/GenericConfigurationManagerImpl.ipp>
-#include <platform/nxp/k32w/k32w0/K32W0Config.h>
-#include <platform/nxp/k32w/k32w0/KeyValueStoreManagerImpl.h>
+#include <platform/nxp/k32w0/K32W0Config.h>
+#include <platform/nxp/k32w0/KeyValueStoreManagerImpl.h>
 
 #include "fsl_power.h"
 #include "fsl_reset.h"
diff --git a/src/platform/nxp/k32w/k32w0/ConfigurationManagerImpl.h b/src/platform/nxp/k32w0/ConfigurationManagerImpl.h
similarity index 98%
rename from src/platform/nxp/k32w/k32w0/ConfigurationManagerImpl.h
rename to src/platform/nxp/k32w0/ConfigurationManagerImpl.h
index 8fded100d00a87..c7cf2366ca97cb 100644
--- a/src/platform/nxp/k32w/k32w0/ConfigurationManagerImpl.h
+++ b/src/platform/nxp/k32w0/ConfigurationManagerImpl.h
@@ -26,7 +26,7 @@
 #pragma once
 
 #include <platform/internal/GenericConfigurationManagerImpl.h>
-#include <platform/nxp/k32w/k32w0/K32W0Config.h>
+#include <platform/nxp/k32w0/K32W0Config.h>
 
 namespace chip {
 namespace DeviceLayer {
diff --git a/src/platform/nxp/k32w/k32w0/ConnectivityManagerImpl.cpp b/src/platform/nxp/k32w0/ConnectivityManagerImpl.cpp
similarity index 100%
rename from src/platform/nxp/k32w/k32w0/ConnectivityManagerImpl.cpp
rename to src/platform/nxp/k32w0/ConnectivityManagerImpl.cpp
diff --git a/src/platform/nxp/k32w/k32w0/ConnectivityManagerImpl.h b/src/platform/nxp/k32w0/ConnectivityManagerImpl.h
similarity index 100%
rename from src/platform/nxp/k32w/k32w0/ConnectivityManagerImpl.h
rename to src/platform/nxp/k32w0/ConnectivityManagerImpl.h
diff --git a/src/platform/nxp/k32w/k32w0/DiagnosticDataProviderImpl.cpp b/src/platform/nxp/k32w0/DiagnosticDataProviderImpl.cpp
similarity index 99%
rename from src/platform/nxp/k32w/k32w0/DiagnosticDataProviderImpl.cpp
rename to src/platform/nxp/k32w0/DiagnosticDataProviderImpl.cpp
index b3e02f3f64cb71..8cf924d1a63424 100644
--- a/src/platform/nxp/k32w/k32w0/DiagnosticDataProviderImpl.cpp
+++ b/src/platform/nxp/k32w0/DiagnosticDataProviderImpl.cpp
@@ -25,7 +25,7 @@
 
 #include <crypto/CHIPCryptoPAL.h>
 #include <platform/DiagnosticDataProvider.h>
-#include <platform/nxp/k32w/k32w0/DiagnosticDataProviderImpl.h>
+#include <platform/nxp/k32w0/DiagnosticDataProviderImpl.h>
 
 #if CHIP_SYSTEM_CONFIG_USE_LWIP
 #include <lwip/tcpip.h>
diff --git a/src/platform/nxp/k32w/k32w0/DiagnosticDataProviderImpl.h b/src/platform/nxp/k32w0/DiagnosticDataProviderImpl.h
similarity index 100%
rename from src/platform/nxp/k32w/k32w0/DiagnosticDataProviderImpl.h
rename to src/platform/nxp/k32w0/DiagnosticDataProviderImpl.h
diff --git a/src/platform/nxp/k32w0/FactoryDataProvider.cpp b/src/platform/nxp/k32w0/FactoryDataProvider.cpp
new file mode 100644
index 00000000000000..23f8ffe7c0586b
--- /dev/null
+++ b/src/platform/nxp/k32w0/FactoryDataProvider.cpp
@@ -0,0 +1,368 @@
+/*
+ *
+ *    Copyright (c) 2022 Project CHIP Authors
+ *
+ *    Licensed under the Apache License, Version 2.0 (the "License");
+ *    you may not use this file except in compliance with the License.
+ *    You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *    Unless required by applicable law or agreed to in writing, software
+ *    distributed under the License is distributed on an "AS IS" BASIS,
+ *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *    See the License for the specific language governing permissions and
+ *    limitations under the License.
+ */
+
+#if (!CONFIG_CHIP_LOAD_REAL_FACTORY_DATA || !(defined CONFIG_CHIP_LOAD_REAL_FACTORY_DATA))
+#include <credentials/examples/DeviceAttestationCredsExample.h>
+#include <credentials/examples/ExampleDACs.h>
+#include <credentials/examples/ExamplePAI.h>
+#endif
+
+#include <credentials/CHIPCert.h>
+#include <credentials/CertificationDeclaration.h>
+#include <crypto/CHIPCryptoPAL.h>
+#include <lib/core/CHIPError.h>
+#include <lib/core/TLV.h>
+#include <lib/support/Base64.h>
+#include <lib/support/Span.h>
+#include <platform/ConfigurationManager.h>
+#include <platform/nxp/k32w0/FactoryDataProvider.h>
+
+#include <cctype>
+
+namespace chip {
+namespace DeviceLayer {
+
+static constexpr size_t kSpake2pSerializedVerifier_MaxBase64Len =
+    BASE64_ENCODED_LEN(chip::Crypto::kSpake2p_VerifierSerialized_Length) + 1;
+static constexpr size_t kSpake2pSalt_MaxBase64Len = BASE64_ENCODED_LEN(chip::Crypto::kSpake2p_Max_PBKDF_Salt_Length) + 1;
+/* Secure subsystem private key blob size is 32 + 24 = 56.
+ * DAC private key may be used to store an SSS exported blob instead of the private key.
+ */
+static constexpr size_t kDacPrivateKey_MaxLen = Crypto::kP256_PrivateKey_Length + 24;
+
+uint32_t FactoryDataProvider::kFactoryDataStart        = (uint32_t) __MATTER_FACTORY_DATA_START;
+uint32_t FactoryDataProvider::kFactoryDataSize         = (uint32_t) __MATTER_FACTORY_DATA_SIZE;
+uint32_t FactoryDataProvider::kFactoryDataPayloadStart = kFactoryDataStart + sizeof(FactoryDataProvider::Header);
+
+FactoryDataProvider::~FactoryDataProvider() {}
+
+CHIP_ERROR FactoryDataProvider::Validate()
+{
+    uint8_t output[Crypto::kSHA256_Hash_Length] = { 0 };
+
+    memcpy(&mHeader, (void *) kFactoryDataStart, sizeof(Header));
+    ReturnErrorCodeIf(mHeader.hashId != kHashId, CHIP_FACTORY_DATA_HASH_ID);
+
+    ReturnErrorOnFailure(Crypto::Hash_SHA256((uint8_t *) kFactoryDataPayloadStart, mHeader.size, output));
+    ReturnErrorCodeIf(memcmp(output, mHeader.hash, kHashLen) != 0, CHIP_FACTORY_DATA_SHA_CHECK);
+
+    return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR FactoryDataProvider::SearchForId(uint8_t searchedType, uint8_t * pBuf, size_t bufLength, uint16_t & length,
+                                            uint32_t * offset)
+{
+    uint32_t addr = kFactoryDataPayloadStart;
+    uint8_t type  = 0;
+
+    while (addr < (kFactoryDataPayloadStart + mHeader.size))
+    {
+        memcpy(&type, (void *) addr, sizeof(type));
+        memcpy(&length, (void *) (addr + 1), sizeof(length));
+
+        if (searchedType == type)
+        {
+            ReturnErrorCodeIf(bufLength < length, CHIP_ERROR_BUFFER_TOO_SMALL);
+            memcpy(pBuf, (void *) (addr + kValueOffset), length);
+
+            if (offset)
+                *offset = (addr - kFactoryDataPayloadStart);
+
+            return CHIP_NO_ERROR;
+        }
+        else
+        {
+            /* Jump past 3 bytes of length and then use length to jump to next data */
+            addr = addr + kValueOffset + length;
+        }
+    }
+
+    return CHIP_ERROR_NOT_FOUND;
+}
+
+CHIP_ERROR FactoryDataProvider::GetCertificationDeclaration(MutableByteSpan & outBuffer)
+{
+#if CHIP_USE_DEVICE_CONFIG_CERTIFICATION_DECLARATION
+    constexpr uint8_t kCdForAllExamples[] = CHIP_DEVICE_CONFIG_CERTIFICATION_DECLARATION;
+
+    return CopySpanToMutableSpan(ByteSpan{ kCdForAllExamples }, outBuffer);
+#else
+    uint16_t declarationSize = 0;
+    ReturnErrorOnFailure(SearchForId(FactoryDataId::kCertDeclarationId, outBuffer.data(), outBuffer.size(), declarationSize));
+    outBuffer.reduce_size(declarationSize);
+
+    return CHIP_NO_ERROR;
+#endif
+}
+
+CHIP_ERROR FactoryDataProvider::GetFirmwareInformation(MutableByteSpan & out_firmware_info_buffer)
+{
+    return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR FactoryDataProvider::GetDeviceAttestationCert(MutableByteSpan & outBuffer)
+{
+    uint16_t certificateSize = 0;
+    ReturnErrorOnFailure(SearchForId(FactoryDataId::kDacCertificateId, outBuffer.data(), outBuffer.size(), certificateSize));
+    outBuffer.reduce_size(certificateSize);
+    return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR FactoryDataProvider::GetProductAttestationIntermediateCert(MutableByteSpan & outBuffer)
+{
+    uint16_t certificateSize = 0;
+    ReturnErrorOnFailure(SearchForId(FactoryDataId::kPaiCertificateId, outBuffer.data(), outBuffer.size(), certificateSize));
+    outBuffer.reduce_size(certificateSize);
+    return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR FactoryDataProvider::SignWithDeviceAttestationKey(const ByteSpan & messageToSign, MutableByteSpan & outSignBuffer)
+{
+    return SignWithDacKey(messageToSign, outSignBuffer);
+}
+
+CHIP_ERROR FactoryDataProvider::GetSetupDiscriminator(uint16_t & setupDiscriminator)
+{
+    uint32_t discriminator = 0;
+    uint16_t temp          = 0;
+
+    ReturnErrorOnFailure(SearchForId(FactoryDataId::kDiscriminatorId, (uint8_t *) &discriminator, sizeof(discriminator), temp));
+    setupDiscriminator = (uint16_t) (discriminator & 0x0000FFFF);
+
+    return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR FactoryDataProvider::SetSetupDiscriminator(uint16_t setupDiscriminator)
+{
+    return CHIP_ERROR_NOT_IMPLEMENTED;
+}
+
+CHIP_ERROR FactoryDataProvider::GetSpake2pIterationCount(uint32_t & iterationCount)
+{
+    uint16_t temp = 0;
+    ReturnErrorOnFailure(SearchForId(FactoryDataId::kIcId, (uint8_t *) &iterationCount, sizeof(iterationCount), temp));
+
+    return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR FactoryDataProvider::GetSpake2pSalt(MutableByteSpan & saltBuf)
+{
+    char saltB64[kSpake2pSalt_MaxBase64Len] = { 0 };
+    uint16_t saltB64Len                     = 0;
+
+    ReturnErrorOnFailure(SearchForId(FactoryDataId::kSaltId, (uint8_t *) (&saltB64[0]), sizeof(saltB64), saltB64Len));
+    size_t saltLen = chip::Base64Decode32(saltB64, saltB64Len, reinterpret_cast<uint8_t *>(saltB64));
+
+    ReturnErrorCodeIf(saltLen > saltBuf.size(), CHIP_ERROR_BUFFER_TOO_SMALL);
+    memcpy(saltBuf.data(), saltB64, saltLen);
+    saltBuf.reduce_size(saltLen);
+
+    return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR FactoryDataProvider::GetSpake2pVerifier(MutableByteSpan & verifierBuf, size_t & verifierLen)
+{
+    char verifierB64[kSpake2pSerializedVerifier_MaxBase64Len] = { 0 };
+    uint16_t verifierB64Len                                   = 0;
+    ReturnErrorOnFailure(SearchForId(FactoryDataId::kVerifierId, (uint8_t *) &verifierB64[0], sizeof(verifierB64), verifierB64Len));
+
+    verifierLen = chip::Base64Decode32(verifierB64, verifierB64Len, reinterpret_cast<uint8_t *>(verifierB64));
+    ReturnErrorCodeIf(verifierLen > verifierBuf.size(), CHIP_ERROR_BUFFER_TOO_SMALL);
+    memcpy(verifierBuf.data(), verifierB64, verifierLen);
+    verifierBuf.reduce_size(verifierLen);
+
+    return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR FactoryDataProvider::GetSetupPasscode(uint32_t & setupPasscode)
+{
+    uint16_t length = 0;
+    ReturnErrorOnFailure(SearchForId(FactoryDataId::kSetupPasscodeId, (uint8_t *) &setupPasscode, sizeof(setupPasscode), length));
+
+    return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR FactoryDataProvider::SetSetupPasscode(uint32_t setupPasscode)
+{
+    return CHIP_ERROR_NOT_IMPLEMENTED;
+}
+
+CHIP_ERROR FactoryDataProvider::GetVendorName(char * buf, size_t bufSize)
+{
+    uint16_t length = 0;
+    ReturnErrorOnFailure(SearchForId(FactoryDataId::kVendorNameId, (uint8_t *) buf, bufSize, length));
+    buf[length] = '\0';
+
+    return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR FactoryDataProvider::GetVendorId(uint16_t & vendorId)
+{
+    uint16_t length = 0;
+    ReturnErrorOnFailure(SearchForId(FactoryDataId::kVidId, (uint8_t *) &vendorId, sizeof(vendorId), length));
+
+    return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR FactoryDataProvider::GetProductName(char * buf, size_t bufSize)
+{
+    uint16_t length = 0;
+    ReturnErrorOnFailure(SearchForId(FactoryDataId::kProductNameId, (uint8_t *) buf, bufSize, length));
+    buf[length] = '\0';
+
+    return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR FactoryDataProvider::GetProductId(uint16_t & productId)
+{
+    uint16_t length = 0;
+    ReturnErrorOnFailure(SearchForId(FactoryDataId::kPidId, (uint8_t *) &productId, sizeof(productId), length));
+
+    return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR FactoryDataProvider::GetPartNumber(char * buf, size_t bufSize)
+{
+    uint16_t length = 0;
+    ReturnErrorOnFailure(SearchForId(FactoryDataId::kPartNumber, (uint8_t *) buf, bufSize, length));
+    buf[length] = '\0';
+
+    return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR FactoryDataProvider::GetProductURL(char * buf, size_t bufSize)
+{
+    uint16_t length = 0;
+    ReturnErrorOnFailure(SearchForId(FactoryDataId::kProductURL, (uint8_t *) buf, bufSize, length));
+    buf[length] = '\0';
+
+    return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR FactoryDataProvider::GetProductLabel(char * buf, size_t bufSize)
+{
+    uint16_t length = 0;
+    ReturnErrorOnFailure(SearchForId(FactoryDataId::kProductLabel, (uint8_t *) buf, bufSize, length));
+    buf[length] = '\0';
+
+    return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR FactoryDataProvider::GetSerialNumber(char * buf, size_t bufSize)
+{
+    uint16_t length = 0;
+    ReturnErrorOnFailure(SearchForId(FactoryDataId::kSerialNumberId, (uint8_t *) buf, bufSize, length));
+    buf[length] = '\0';
+
+    return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR FactoryDataProvider::GetManufacturingDate(uint16_t & year, uint8_t & month, uint8_t & day)
+{
+    uint16_t length = 0;
+    uint8_t date[ConfigurationManager::kMaxManufacturingDateLength];
+
+    ReturnErrorOnFailure(
+        SearchForId(FactoryDataId::kManufacturingDateId, date, ConfigurationManager::kMaxManufacturingDateLength, length));
+    date[length] = '\0';
+
+    if (length == 10 && isdigit(date[0]) && isdigit(date[1]) && isdigit(date[2]) && isdigit(date[3]) && date[4] == '-' &&
+        isdigit(date[5]) && isdigit(date[6]) && date[7] == '-' && isdigit(date[8]) && isdigit(date[9]))
+    {
+        year  = 1000 * (date[0] - '0') + 100 * (date[1] - '0') + 10 * (date[2] - '0') + date[3] - '0';
+        month = 10 * (date[5] - '0') + date[6] - '0';
+        day   = 10 * (date[8] - '0') + date[9] - '0';
+    }
+    else
+    {
+        ChipLogError(DeviceLayer, "Manufacturing date is not formatted correctly: YYYY-MM-DD.");
+        return CHIP_ERROR_INVALID_ARGUMENT;
+    }
+
+    return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR FactoryDataProvider::GetHardwareVersion(uint16_t & hardwareVersion)
+{
+    uint16_t length = 0;
+    ReturnErrorOnFailure(
+        SearchForId(FactoryDataId::kHardwareVersionId, (uint8_t *) &hardwareVersion, sizeof(hardwareVersion), length));
+
+    return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR FactoryDataProvider::GetHardwareVersionString(char * buf, size_t bufSize)
+{
+    uint16_t length = 0;
+    ReturnErrorOnFailure(SearchForId(FactoryDataId::kHardwareVersionStrId, (uint8_t *) buf, bufSize, length));
+    buf[length] = '\0';
+
+    return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR FactoryDataProvider::GetRotatingDeviceIdUniqueId(MutableByteSpan & uniqueIdSpan)
+{
+    CHIP_ERROR err = CHIP_ERROR_NOT_IMPLEMENTED;
+#if CHIP_ENABLE_ROTATING_DEVICE_ID
+    static_assert(ConfigurationManager::kRotatingDeviceIDUniqueIDLength >= ConfigurationManager::kMinRotatingDeviceIDUniqueIDLength,
+                  "Length of unique ID for rotating device ID is smaller than minimum.");
+    uint16_t uniqueIdLen = 0;
+    err                  = SearchForId(FactoryDataId::kUniqueId, (uint8_t *) uniqueIdSpan.data(), uniqueIdSpan.size(), uniqueIdLen);
+#if defined(CHIP_DEVICE_CONFIG_ROTATING_DEVICE_ID_UNIQUE_ID)
+    if (err != CHIP_NO_ERROR)
+    {
+        constexpr uint8_t uniqueId[] = CHIP_DEVICE_CONFIG_ROTATING_DEVICE_ID_UNIQUE_ID;
+
+        ReturnErrorCodeIf(sizeof(uniqueId) > uniqueIdSpan.size(), CHIP_ERROR_BUFFER_TOO_SMALL);
+        memcpy(uniqueIdSpan.data(), uniqueId, sizeof(uniqueId));
+        uniqueIdLen = sizeof(uniqueId);
+        err         = CHIP_NO_ERROR;
+    }
+#endif // CHIP_DEVICE_CONFIG_ROTATING_DEVICE_ID_UNIQUE_ID
+    ReturnErrorOnFailure(err);
+    uniqueIdSpan.reduce_size(uniqueIdLen);
+#endif
+
+    return err;
+}
+
+CHIP_ERROR FactoryDataProvider::GetProductFinish(app::Clusters::BasicInformation::ProductFinishEnum * finish)
+{
+    uint8_t productFinish;
+    uint16_t length = 0;
+    auto err        = SearchForId(FactoryDataId::kProductFinish, &productFinish, sizeof(productFinish), length);
+    ReturnErrorCodeIf(err != CHIP_NO_ERROR, CHIP_ERROR_NOT_IMPLEMENTED);
+
+    *finish = static_cast<app::Clusters::BasicInformation::ProductFinishEnum>(productFinish);
+
+    return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR FactoryDataProvider::GetProductPrimaryColor(app::Clusters::BasicInformation::ColorEnum * primaryColor)
+{
+    uint8_t color;
+    uint16_t length = 0;
+    auto err        = SearchForId(FactoryDataId::kProductPrimaryColor, &color, sizeof(color), length);
+    ReturnErrorCodeIf(err != CHIP_NO_ERROR, CHIP_ERROR_NOT_IMPLEMENTED);
+
+    *primaryColor = static_cast<app::Clusters::BasicInformation::ColorEnum>(color);
+
+    return CHIP_NO_ERROR;
+}
+
+} // namespace DeviceLayer
+} // namespace chip
diff --git a/src/platform/nxp/k32w0/FactoryDataProvider.h b/src/platform/nxp/k32w0/FactoryDataProvider.h
new file mode 100644
index 00000000000000..8a76a84800baab
--- /dev/null
+++ b/src/platform/nxp/k32w0/FactoryDataProvider.h
@@ -0,0 +1,158 @@
+/*
+ *
+ *    Copyright (c) 2022 Project CHIP Authors
+ *
+ *    Licensed under the Apache License, Version 2.0 (the "License");
+ *    you may not use this file except in compliance with the License.
+ *    You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *    Unless required by applicable law or agreed to in writing, software
+ *    distributed under the License is distributed on an "AS IS" BASIS,
+ *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *    See the License for the specific language governing permissions and
+ *    limitations under the License.
+ */
+#pragma once
+
+#include <credentials/DeviceAttestationCredsProvider.h>
+#include <platform/CommissionableDataProvider.h>
+#include <platform/internal/GenericDeviceInstanceInfoProvider.h>
+#include <src/lib/core/CHIPError.h>
+
+#include <vector>
+
+#include "CHIPPlatformConfig.h"
+
+#include <vector>
+
+/* Grab symbol for the base address from the linker file. */
+extern uint32_t __MATTER_FACTORY_DATA_START[];
+extern uint32_t __MATTER_FACTORY_DATA_SIZE[];
+
+namespace chip {
+namespace DeviceLayer {
+
+#define CHIP_FACTORY_DATA_ERROR(e)                                                                                                 \
+    ChipError(ChipError::Range::kLastRange, ((uint8_t) ChipError::Range::kLastRange << 2) | e, __FILE__, __LINE__)
+
+#define CHIP_FACTORY_DATA_SHA_CHECK CHIP_FACTORY_DATA_ERROR(0x01)
+#define CHIP_FACTORY_DATA_HEADER_READ CHIP_FACTORY_DATA_ERROR(0x02)
+#define CHIP_FACTORY_DATA_HASH_ID CHIP_FACTORY_DATA_ERROR(0x03)
+#define CHIP_FACTORY_DATA_PDM_RESTORE CHIP_FACTORY_DATA_ERROR(0x04)
+#define CHIP_FACTORY_DATA_NULL CHIP_FACTORY_DATA_ERROR(0x05)
+#define CHIP_FACTORY_DATA_FLASH_ERASE CHIP_FACTORY_DATA_ERROR(0x06)
+#define CHIP_FACTORY_DATA_FLASH_PROGRAM CHIP_FACTORY_DATA_ERROR(0x07)
+#define CHIP_FACTORY_DATA_INTERNAL_FLASH_READ CHIP_FACTORY_DATA_ERROR(0x08)
+#define CHIP_FACTORY_DATA_PDM_SAVE_RECORD CHIP_FACTORY_DATA_ERROR(0x09)
+#define CHIP_FACTORY_DATA_PDM_READ_RECORD CHIP_FACTORY_DATA_ERROR(0x0A)
+#define CHIP_FACTORY_DATA_RESTORE_MECHANISM CHIP_FACTORY_DATA_ERROR(0x0B)
+
+// Forward declaration to define the getter for factory data provider impl instance
+class FactoryDataProviderImpl;
+
+/**
+ * @brief This class provides Commissionable data, Device Attestation Credentials,
+ *        and Device Instance Info.
+ */
+
+class FactoryDataProvider : public DeviceInstanceInfoProvider,
+                            public CommissionableDataProvider,
+                            public Credentials::DeviceAttestationCredentialsProvider
+{
+public:
+    struct Header
+    {
+        uint32_t hashId;
+        uint32_t size;
+        uint8_t hash[4];
+    };
+
+    // Default factory data IDs
+    enum FactoryDataId
+    {
+        kVerifierId = 1,
+        kSaltId,
+        kIcId,
+        kDacPrivateKeyId,
+        kDacCertificateId,
+        kPaiCertificateId,
+        kDiscriminatorId,
+        kSetupPasscodeId,
+        kVidId,
+        kPidId,
+        kCertDeclarationId,
+        kVendorNameId,
+        kProductNameId,
+        kSerialNumberId,
+        kManufacturingDateId,
+        kHardwareVersionId,
+        kHardwareVersionStrId,
+        kUniqueId,
+        kPartNumber,
+        kProductURL,
+        kProductLabel,
+        kProductFinish,
+        kProductPrimaryColor,
+        kMaxId
+    };
+
+    static uint32_t kFactoryDataStart;
+    static uint32_t kFactoryDataSize;
+    static uint32_t kFactoryDataPayloadStart;
+    static constexpr uint32_t kLengthOffset = 1;
+    static constexpr uint32_t kValueOffset  = 3;
+    static constexpr uint32_t kHashLen      = 4;
+    static constexpr size_t kHashId         = 0xCE47BA5E;
+
+    virtual ~FactoryDataProvider();
+
+    virtual CHIP_ERROR Init()                                                                          = 0;
+    virtual CHIP_ERROR SignWithDacKey(const ByteSpan & messageToSign, MutableByteSpan & outSignBuffer) = 0;
+    CHIP_ERROR Validate();
+
+    CHIP_ERROR SearchForId(uint8_t searchedType, uint8_t * pBuf, size_t bufLength, uint16_t & length, uint32_t * offset = nullptr);
+
+    // ===== Members functions that implement the CommissionableDataProvider
+    CHIP_ERROR GetSetupDiscriminator(uint16_t & setupDiscriminator) override;
+    CHIP_ERROR SetSetupDiscriminator(uint16_t setupDiscriminator) override;
+    CHIP_ERROR GetSpake2pIterationCount(uint32_t & iterationCount) override;
+    CHIP_ERROR GetSpake2pSalt(MutableByteSpan & saltBuf) override;
+    CHIP_ERROR GetSpake2pVerifier(MutableByteSpan & verifierBuf, size_t & verifierLen) override;
+    CHIP_ERROR GetSetupPasscode(uint32_t & setupPasscode) override;
+    CHIP_ERROR SetSetupPasscode(uint32_t setupPasscode) override;
+
+    // ===== Members functions that implement the DeviceAttestationCredentialsProvider
+    CHIP_ERROR GetCertificationDeclaration(MutableByteSpan & outBuffer) override;
+    CHIP_ERROR GetFirmwareInformation(MutableByteSpan & out_firmware_info_buffer) override;
+    CHIP_ERROR GetDeviceAttestationCert(MutableByteSpan & outBuffer) override;
+    CHIP_ERROR GetProductAttestationIntermediateCert(MutableByteSpan & outBuffer) override;
+    CHIP_ERROR SignWithDeviceAttestationKey(const ByteSpan & messageToSign, MutableByteSpan & outSignBuffer) override;
+
+    // ===== Members functions that implement the GenericDeviceInstanceInfoProvider
+    CHIP_ERROR GetVendorName(char * buf, size_t bufSize) override;
+    CHIP_ERROR GetVendorId(uint16_t & vendorId) override;
+    CHIP_ERROR GetProductName(char * buf, size_t bufSize) override;
+    CHIP_ERROR GetProductId(uint16_t & productId) override;
+    CHIP_ERROR GetPartNumber(char * buf, size_t bufSize) override;
+    CHIP_ERROR GetProductURL(char * buf, size_t bufSize) override;
+    CHIP_ERROR GetProductLabel(char * buf, size_t bufSize) override;
+    CHIP_ERROR GetHardwareVersionString(char * buf, size_t bufSize) override;
+    CHIP_ERROR GetSerialNumber(char * buf, size_t bufSize) override;
+    CHIP_ERROR GetManufacturingDate(uint16_t & year, uint8_t & month, uint8_t & day) override;
+    CHIP_ERROR GetHardwareVersion(uint16_t & hardwareVersion) override;
+    CHIP_ERROR GetRotatingDeviceIdUniqueId(MutableByteSpan & uniqueIdSpan) override;
+    CHIP_ERROR GetProductFinish(app::Clusters::BasicInformation::ProductFinishEnum * finish) override;
+    CHIP_ERROR GetProductPrimaryColor(app::Clusters::BasicInformation::ColorEnum * primaryColor) override;
+
+protected:
+    Header mHeader;
+};
+
+extern FactoryDataProvider & FactoryDataPrvd();
+
+extern FactoryDataProviderImpl & FactoryDataPrvdImpl();
+
+} // namespace DeviceLayer
+} // namespace chip
diff --git a/src/platform/nxp/k32w/k32w0/FactoryDataProviderImpl.cpp b/src/platform/nxp/k32w0/FactoryDataProviderImpl.cpp
similarity index 94%
rename from src/platform/nxp/k32w/k32w0/FactoryDataProviderImpl.cpp
rename to src/platform/nxp/k32w0/FactoryDataProviderImpl.cpp
index dc6acd3b619272..93c09adf5c749d 100644
--- a/src/platform/nxp/k32w/k32w0/FactoryDataProviderImpl.cpp
+++ b/src/platform/nxp/k32w0/FactoryDataProviderImpl.cpp
@@ -17,9 +17,9 @@
 
 #include <crypto/CHIPCryptoPAL.h>
 #include <lib/core/CHIPError.h>
-#include <platform/nxp/k32w/k32w0/FactoryDataProviderImpl.h>
+#include <platform/nxp/k32w0/FactoryDataProviderImpl.h>
 
-#if CONFIG_CHIP_K32W0_OTA_FACTORY_DATA_PROCESSOR
+#if CONFIG_CHIP_OTA_FACTORY_DATA_PROCESSOR
 extern "C" {
 #include "Flash_Adapter.h"
 }
@@ -31,7 +31,7 @@ namespace DeviceLayer {
 
 FactoryDataProviderImpl::FactoryDataProviderImpl()
 {
-#if CONFIG_CHIP_K32W0_OTA_FACTORY_DATA_PROCESSOR
+#if CONFIG_CHIP_OTA_FACTORY_DATA_PROCESSOR
     RegisterRestoreMechanism(FactoryDataDefaultRestoreMechanism);
 #endif
 }
@@ -40,7 +40,7 @@ CHIP_ERROR FactoryDataProviderImpl::Init()
 {
     CHIP_ERROR error = CHIP_NO_ERROR;
 
-#if CONFIG_CHIP_K32W0_OTA_FACTORY_DATA_PROCESSOR
+#if CONFIG_CHIP_OTA_FACTORY_DATA_PROCESSOR
     error = ValidateWithRestore();
 #else
     error = Validate();
@@ -91,7 +91,7 @@ CHIP_ERROR FactoryDataProviderImpl::SignWithDacKey(const ByteSpan & messageToSig
     return error;
 }
 
-#if CONFIG_CHIP_K32W0_OTA_FACTORY_DATA_PROCESSOR
+#if CONFIG_CHIP_OTA_FACTORY_DATA_PROCESSOR
 extern "C" WEAK CHIP_ERROR FactoryDataDefaultRestoreMechanism()
 {
     CHIP_ERROR error      = CHIP_NO_ERROR;
@@ -170,7 +170,7 @@ void FactoryDataProviderImpl::RegisterRestoreMechanism(RestoreMechanism restore)
 {
     mRestoreMechanisms.insert(mRestoreMechanisms.end(), restore);
 }
-#endif // CONFIG_CHIP_K32W0_OTA_FACTORY_DATA_PROCESSOR
+#endif // CONFIG_CHIP_OTA_FACTORY_DATA_PROCESSOR
 
 } // namespace DeviceLayer
 } // namespace chip
diff --git a/src/platform/nxp/k32w/k32w0/FactoryDataProviderImpl.h b/src/platform/nxp/k32w0/FactoryDataProviderImpl.h
similarity index 88%
rename from src/platform/nxp/k32w/k32w0/FactoryDataProviderImpl.h
rename to src/platform/nxp/k32w0/FactoryDataProviderImpl.h
index b359a6d3f196cd..afeb802352bc7b 100644
--- a/src/platform/nxp/k32w/k32w0/FactoryDataProviderImpl.h
+++ b/src/platform/nxp/k32w0/FactoryDataProviderImpl.h
@@ -16,7 +16,7 @@
  */
 #pragma once
 
-#include <platform/nxp/k32w/common/FactoryDataProvider.h>
+#include <platform/nxp/k32w0/FactoryDataProvider.h>
 #include <vector>
 
 namespace chip {
@@ -24,7 +24,7 @@ namespace DeviceLayer {
 
 /**
  * This class provides K32W0 specific factory data features.
- * CONFIG_CHIP_K32W0_OTA_FACTORY_DATA_PROCESSOR - enables factory data OTA
+ * CONFIG_CHIP_OTA_FACTORY_DATA_PROCESSOR - enables factory data OTA
  */
 
 class FactoryDataProviderImpl : public FactoryDataProvider
@@ -35,7 +35,7 @@ class FactoryDataProviderImpl : public FactoryDataProvider
     CHIP_ERROR Init() override;
     CHIP_ERROR SignWithDacKey(const ByteSpan & messageToSign, MutableByteSpan & outSignBuffer) override;
 
-#if CONFIG_CHIP_K32W0_OTA_FACTORY_DATA_PROCESSOR
+#if CONFIG_CHIP_OTA_FACTORY_DATA_PROCESSOR
     using RestoreMechanism = CHIP_ERROR (*)(void);
 
     static CHIP_ERROR UpdateData(uint8_t * pBuf);
diff --git a/src/platform/nxp/k32w/k32w0/InetPlatformConfig.h b/src/platform/nxp/k32w0/InetPlatformConfig.h
similarity index 100%
rename from src/platform/nxp/k32w/k32w0/InetPlatformConfig.h
rename to src/platform/nxp/k32w0/InetPlatformConfig.h
diff --git a/src/platform/nxp/k32w/k32w0/K32W0Config.cpp b/src/platform/nxp/k32w0/K32W0Config.cpp
similarity index 99%
rename from src/platform/nxp/k32w/k32w0/K32W0Config.cpp
rename to src/platform/nxp/k32w0/K32W0Config.cpp
index 850a1b7398ef06..2054ef5da619bf 100644
--- a/src/platform/nxp/k32w/k32w0/K32W0Config.cpp
+++ b/src/platform/nxp/k32w0/K32W0Config.cpp
@@ -25,7 +25,7 @@
 /* this file behaves like a config.h, comes first */
 #include <platform/internal/CHIPDeviceLayerInternal.h>
 
-#include <platform/nxp/k32w/k32w0/K32W0Config.h>
+#include <platform/nxp/k32w0/K32W0Config.h>
 
 #include <lib/core/CHIPEncoding.h>
 #include <platform/internal/testing/ConfigUnitTest.h>
diff --git a/src/platform/nxp/k32w/k32w0/K32W0Config.h b/src/platform/nxp/k32w0/K32W0Config.h
similarity index 98%
rename from src/platform/nxp/k32w/k32w0/K32W0Config.h
rename to src/platform/nxp/k32w0/K32W0Config.h
index e364c045c25b1c..7080e62e747bf1 100644
--- a/src/platform/nxp/k32w/k32w0/K32W0Config.h
+++ b/src/platform/nxp/k32w0/K32W0Config.h
@@ -20,7 +20,7 @@
 
 #include <functional>
 #include <platform/internal/CHIPDeviceLayerInternal.h>
-#include <platform/nxp/k32w/k32w0/RamStorage.h>
+#include <platform/nxp/k32w0/RamStorage.h>
 
 namespace chip {
 namespace DeviceLayer {
diff --git a/src/platform/nxp/k32w/k32w0/KeyValueStoreManagerImpl.cpp b/src/platform/nxp/k32w0/KeyValueStoreManagerImpl.cpp
similarity index 93%
rename from src/platform/nxp/k32w/k32w0/KeyValueStoreManagerImpl.cpp
rename to src/platform/nxp/k32w0/KeyValueStoreManagerImpl.cpp
index 8dbf3e5bd71903..50f900583769f7 100644
--- a/src/platform/nxp/k32w/k32w0/KeyValueStoreManagerImpl.cpp
+++ b/src/platform/nxp/k32w0/KeyValueStoreManagerImpl.cpp
@@ -25,9 +25,9 @@
 
 #include <lib/support/CHIPMem.h>
 #include <platform/KeyValueStoreManager.h>
-#include <platform/nxp/k32w/k32w0/K32W0Config.h>
-#include <platform/nxp/k32w/k32w0/KeyValueStoreManagerImpl.h>
-#include <platform/nxp/k32w/k32w0/RamStorage.h>
+#include <platform/nxp/k32w0/K32W0Config.h>
+#include <platform/nxp/k32w0/KeyValueStoreManagerImpl.h>
+#include <platform/nxp/k32w0/RamStorage.h>
 #include <string>
 
 namespace chip {
@@ -41,6 +41,7 @@ Internal::RamStorage KeyValueStoreManagerImpl::sKeysStorage         = { kNvmId_K
 Internal::RamStorage KeyValueStoreManagerImpl::sValuesStorage       = { kNvmId_KvsValues, "Values" };
 Internal::RamStorage KeyValueStoreManagerImpl::sSubscriptionStorage = { kNvmId_KvsSubscription, "Subscriptions" };
 Internal::RamStorage KeyValueStoreManagerImpl::sGroupsStorage       = { kNvmId_KvsGroups, "Groups" };
+Internal::RamStorage KeyValueStoreManagerImpl::sAclStorage          = { kNvmId_KvsAcl, "Acl" };
 
 KeyValueStoreManagerImpl KeyValueStoreManagerImpl::sInstance;
 
@@ -63,6 +64,12 @@ static inline bool IsKeyRelatedToSubscriptions(const char * key)
     return _key.find("g/su") == 0;
 }
 
+static inline bool IsKeyRelatedToAcl(const char * key)
+{
+    std::string _key(key);
+    return _key.find("/ac/") != std::string::npos;
+}
+
 static Internal::RamStorage * GetValStorage(const char * key)
 {
     Internal::RamStorage * storage = nullptr;
@@ -70,6 +77,7 @@ static Internal::RamStorage * GetValStorage(const char * key)
     storage = IsKeyRelatedToSubscriptions(key) ? &KeyValueStoreManagerImpl::sSubscriptionStorage
                                                : &KeyValueStoreManagerImpl::sValuesStorage;
     storage = IsKeyRelatedToGroups(key) ? &KeyValueStoreManagerImpl::sGroupsStorage : storage;
+    storage = IsKeyRelatedToAcl(key) ? &KeyValueStoreManagerImpl::sAclStorage : storage;
 
     return storage;
 }
@@ -81,6 +89,7 @@ static Internal::RamStorage * GetKeyStorage(const char * key)
     storage = IsKeyRelatedToSubscriptions(key) ? &KeyValueStoreManagerImpl::sSubscriptionStorage
                                                : &KeyValueStoreManagerImpl::sKeysStorage;
     storage = IsKeyRelatedToGroups(key) ? &KeyValueStoreManagerImpl::sGroupsStorage : storage;
+    storage = IsKeyRelatedToAcl(key) ? &KeyValueStoreManagerImpl::sAclStorage : storage;
 
     return storage;
 }
@@ -145,6 +154,12 @@ CHIP_ERROR KeyValueStoreManagerImpl::Init()
         ChipLogProgress(DeviceLayer, "Cannot init KVS groups storage with id: %d. Error: %s", kNvmId_KvsGroups, ErrorStr(err));
     }
 
+    err = sAclStorage.Init(Internal::RamStorage::kRamBufferInitialSize, true);
+    if (err != CHIP_NO_ERROR)
+    {
+        ChipLogProgress(DeviceLayer, "Cannot init KVS acl storage with id: %d. Error: %s", kNvmId_KvsAcl, ErrorStr(err));
+    }
+
 #if CONFIG_CHIP_K32W0_KVS_MOVE_KEYS_TO_SPECIFIC_STORAGE
     ChipLogProgress(DeviceLayer, "Moving some keys to dedicated storage");
     MoveKeysAndValues();
diff --git a/src/platform/nxp/k32w/k32w0/KeyValueStoreManagerImpl.h b/src/platform/nxp/k32w0/KeyValueStoreManagerImpl.h
similarity index 95%
rename from src/platform/nxp/k32w/k32w0/KeyValueStoreManagerImpl.h
rename to src/platform/nxp/k32w0/KeyValueStoreManagerImpl.h
index 718b92df6beb39..57d877beaeaaf9 100644
--- a/src/platform/nxp/k32w/k32w0/KeyValueStoreManagerImpl.h
+++ b/src/platform/nxp/k32w0/KeyValueStoreManagerImpl.h
@@ -24,7 +24,7 @@
 
 #pragma once
 
-#include <platform/nxp/k32w/k32w0/RamStorage.h>
+#include <platform/nxp/k32w0/RamStorage.h>
 
 namespace chip {
 namespace DeviceLayer {
@@ -41,6 +41,8 @@ class KeyValueStoreManagerImpl final : public KeyValueStoreManager
     static Internal::RamStorage sSubscriptionStorage;
     /* Storage for KVS groups keys and values. Cleared during factory reset. */
     static Internal::RamStorage sGroupsStorage;
+    /* Storage for KVS ACL keys and values. Cleared during factory reset. */
+    static Internal::RamStorage sAclStorage;
 
     // Allow the KeyValueStoreManager interface class to delegate method calls to
     // the implementation methods provided by this class.
diff --git a/src/platform/nxp/k32w/k32w0/Logging.cpp b/src/platform/nxp/k32w0/Logging.cpp
similarity index 100%
rename from src/platform/nxp/k32w/k32w0/Logging.cpp
rename to src/platform/nxp/k32w0/Logging.cpp
diff --git a/src/platform/nxp/k32w/k32w0/LowPowerHooks.cpp b/src/platform/nxp/k32w0/LowPowerHooks.cpp
similarity index 100%
rename from src/platform/nxp/k32w/k32w0/LowPowerHooks.cpp
rename to src/platform/nxp/k32w0/LowPowerHooks.cpp
diff --git a/src/platform/nxp/k32w/k32w0/NFCManagerImpl.cpp b/src/platform/nxp/k32w0/NFCManagerImpl.cpp
similarity index 100%
rename from src/platform/nxp/k32w/k32w0/NFCManagerImpl.cpp
rename to src/platform/nxp/k32w0/NFCManagerImpl.cpp
diff --git a/src/platform/nxp/k32w/k32w0/NFCManagerImpl.h b/src/platform/nxp/k32w0/NFCManagerImpl.h
similarity index 100%
rename from src/platform/nxp/k32w/k32w0/NFCManagerImpl.h
rename to src/platform/nxp/k32w0/NFCManagerImpl.h
diff --git a/src/platform/nxp/k32w/k32w0/OTAFactoryDataProcessor.cpp b/src/platform/nxp/k32w0/OTAFactoryDataProcessor.cpp
similarity index 97%
rename from src/platform/nxp/k32w/k32w0/OTAFactoryDataProcessor.cpp
rename to src/platform/nxp/k32w0/OTAFactoryDataProcessor.cpp
index d40d2ae3c17f5a..b6777c7dc32820 100644
--- a/src/platform/nxp/k32w/k32w0/OTAFactoryDataProcessor.cpp
+++ b/src/platform/nxp/k32w0/OTAFactoryDataProcessor.cpp
@@ -18,9 +18,10 @@
 
 #include <lib/core/TLV.h>
 #include <platform/internal/CHIPDeviceLayerInternal.h>
-#include <platform/nxp/k32w/common/CHIPDevicePlatformRamStorageConfig.h>
-#include <platform/nxp/k32w/k32w0/CHIPDevicePlatformConfig.h>
-#include <platform/nxp/k32w/k32w0/OTAFactoryDataProcessor.h>
+#include <platform/nxp/common/legacy/CHIPDevicePlatformRamStorageConfig.h>
+#include <platform/nxp/k32w0/CHIPDevicePlatformConfig.h>
+#include <platform/nxp/k32w0/FactoryDataProviderImpl.h>
+#include <platform/nxp/k32w0/OTAFactoryDataProcessor.h>
 
 #include "PDM.h"
 #include "fsl_flash.h"
diff --git a/src/platform/nxp/k32w/k32w0/OTAFactoryDataProcessor.h b/src/platform/nxp/k32w0/OTAFactoryDataProcessor.h
similarity index 93%
rename from src/platform/nxp/k32w/k32w0/OTAFactoryDataProcessor.h
rename to src/platform/nxp/k32w0/OTAFactoryDataProcessor.h
index 8682d0bcc1e9dc..3109e64a8d0ae3 100644
--- a/src/platform/nxp/k32w/k32w0/OTAFactoryDataProcessor.h
+++ b/src/platform/nxp/k32w0/OTAFactoryDataProcessor.h
@@ -21,9 +21,9 @@
 #include <lib/core/Optional.h>
 #include <lib/support/ScopedBuffer.h>
 #include <lib/support/Span.h>
-#include <platform/nxp/k32w/common/FactoryDataProvider.h>
-#include <platform/nxp/k32w/common/OTATlvProcessor.h>
-#include <platform/nxp/k32w/k32w0/FactoryDataProviderImpl.h>
+#include <platform/nxp/common/legacy/OTATlvProcessor.h>
+#include <platform/nxp/k32w0/FactoryDataProvider.h>
+#include <platform/nxp/k32w0/FactoryDataProviderImpl.h>
 
 namespace chip {
 
diff --git a/src/platform/nxp/k32w/k32w0/OTAFirmwareProcessor.cpp b/src/platform/nxp/k32w0/OTAFirmwareProcessor.cpp
similarity index 96%
rename from src/platform/nxp/k32w/k32w0/OTAFirmwareProcessor.cpp
rename to src/platform/nxp/k32w0/OTAFirmwareProcessor.cpp
index f63aa745378851..c7a1a2bbf435dd 100644
--- a/src/platform/nxp/k32w/k32w0/OTAFirmwareProcessor.cpp
+++ b/src/platform/nxp/k32w0/OTAFirmwareProcessor.cpp
@@ -17,9 +17,9 @@
  */
 
 #include <platform/internal/CHIPDeviceLayerInternal.h>
-#include <platform/nxp/k32w/common/OTAImageProcessorImpl.h>
-#include <platform/nxp/k32w/k32w0/CHIPDevicePlatformConfig.h>
-#include <platform/nxp/k32w/k32w0/OTAFirmwareProcessor.h>
+#include <platform/nxp/common/legacy/OTAImageProcessorImpl.h>
+#include <platform/nxp/k32w0/CHIPDevicePlatformConfig.h>
+#include <platform/nxp/k32w0/OTAFirmwareProcessor.h>
 
 #include "OtaSupport.h"
 #include "OtaUtils.h"
diff --git a/src/platform/nxp/k32w/k32w0/OTAFirmwareProcessor.h b/src/platform/nxp/k32w0/OTAFirmwareProcessor.h
similarity index 96%
rename from src/platform/nxp/k32w/k32w0/OTAFirmwareProcessor.h
rename to src/platform/nxp/k32w0/OTAFirmwareProcessor.h
index 5a1092ef5fbc46..444243f0c885d0 100644
--- a/src/platform/nxp/k32w/k32w0/OTAFirmwareProcessor.h
+++ b/src/platform/nxp/k32w0/OTAFirmwareProcessor.h
@@ -19,7 +19,7 @@
 #pragma once
 
 #include <lib/support/Span.h>
-#include <platform/nxp/k32w/common/OTATlvProcessor.h>
+#include <platform/nxp/common/legacy/OTATlvProcessor.h>
 
 namespace chip {
 
diff --git a/src/platform/nxp/k32w/k32w0/OTAHooks.cpp b/src/platform/nxp/k32w0/OTAHooks.cpp
similarity index 87%
rename from src/platform/nxp/k32w/k32w0/OTAHooks.cpp
rename to src/platform/nxp/k32w0/OTAHooks.cpp
index a00ae428a0f40d..30df88177ffdc6 100644
--- a/src/platform/nxp/k32w/k32w0/OTAHooks.cpp
+++ b/src/platform/nxp/k32w0/OTAHooks.cpp
@@ -16,16 +16,16 @@
  *    limitations under the License.
  */
 
-#include <platform/nxp/k32w/common/OTAImageProcessorImpl.h>
+#include <platform/nxp/common/legacy/OTAImageProcessorImpl.h>
 #include <src/include/platform/CHIPDeviceLayer.h>
 
 #include <src/app/clusters/ota-requestor/OTARequestorInterface.h>
 
-#include <platform/nxp/k32w/k32w0/CHIPDevicePlatformConfig.h>
-#include <platform/nxp/k32w/k32w0/OTAFirmwareProcessor.h>
-#if CONFIG_CHIP_K32W0_OTA_FACTORY_DATA_PROCESSOR
-#include <platform/nxp/k32w/k32w0/OTAFactoryDataProcessor.h>
-#endif // CONFIG_CHIP_K32W0_OTA_FACTORY_DATA_PROCESSOR
+#include <platform/nxp/k32w0/CHIPDevicePlatformConfig.h>
+#include <platform/nxp/k32w0/OTAFirmwareProcessor.h>
+#if CONFIG_CHIP_OTA_FACTORY_DATA_PROCESSOR
+#include <platform/nxp/k32w0/OTAFactoryDataProcessor.h>
+#endif // CONFIG_CHIP_OTA_FACTORY_DATA_PROCESSOR
 
 #include "OtaSupport.h"
 
@@ -51,9 +51,9 @@ extern "C" WEAK CHIP_ERROR OtaHookInit()
 {
     static chip::OTAFirmwareProcessor sApplicationProcessor;
     static chip::OTAFirmwareProcessor sBootloaderProcessor;
-#if CONFIG_CHIP_K32W0_OTA_FACTORY_DATA_PROCESSOR
+#if CONFIG_CHIP_OTA_FACTORY_DATA_PROCESSOR
     static chip::OTAFactoryDataProcessor sFactoryDataProcessor;
-#endif // CONFIG_CHIP_K32W0_OTA_FACTORY_DATA_PROCESSOR
+#endif // CONFIG_CHIP_OTA_FACTORY_DATA_PROCESSOR
 #if CONFIG_CHIP_K32W0_MAX_ENTRIES_TEST
     static chip::OTAFirmwareProcessor processors[8];
 #endif
@@ -64,9 +64,9 @@ extern "C" WEAK CHIP_ERROR OtaHookInit()
     auto & imageProcessor = chip::OTAImageProcessorImpl::GetDefaultInstance();
     ReturnErrorOnFailure(imageProcessor.RegisterProcessor(1, &sApplicationProcessor));
     ReturnErrorOnFailure(imageProcessor.RegisterProcessor(2, &sBootloaderProcessor));
-#if CONFIG_CHIP_K32W0_OTA_FACTORY_DATA_PROCESSOR
+#if CONFIG_CHIP_OTA_FACTORY_DATA_PROCESSOR
     ReturnErrorOnFailure(imageProcessor.RegisterProcessor(3, &sFactoryDataProcessor));
-#endif // CONFIG_CHIP_K32W0_OTA_FACTORY_DATA_PROCESSOR
+#endif // CONFIG_CHIP_OTA_FACTORY_DATA_PROCESSOR
 #if CONFIG_CHIP_K32W0_MAX_ENTRIES_TEST
     for (auto i = 0; i < 8; i++)
     {
diff --git a/src/platform/nxp/k32w/k32w0/PlatformManagerImpl.cpp b/src/platform/nxp/k32w0/PlatformManagerImpl.cpp
similarity index 98%
rename from src/platform/nxp/k32w/k32w0/PlatformManagerImpl.cpp
rename to src/platform/nxp/k32w0/PlatformManagerImpl.cpp
index 198f9318ba41fb..1a98552cb7e0d9 100644
--- a/src/platform/nxp/k32w/k32w0/PlatformManagerImpl.cpp
+++ b/src/platform/nxp/k32w0/PlatformManagerImpl.cpp
@@ -29,8 +29,8 @@
 #include <openthread-system.h>
 #include <platform/PlatformManager.h>
 #include <platform/internal/GenericPlatformManagerImpl_FreeRTOS.ipp>
-#include <platform/nxp/k32w/k32w0/DiagnosticDataProviderImpl.h>
-#include <platform/nxp/k32w/k32w0/KeyValueStoreManagerImpl.h>
+#include <platform/nxp/k32w0/DiagnosticDataProviderImpl.h>
+#include <platform/nxp/k32w0/KeyValueStoreManagerImpl.h>
 
 #if CHIP_SYSTEM_CONFIG_USE_LWIP
 #include <lwip/tcpip.h>
diff --git a/src/platform/nxp/k32w/k32w0/PlatformManagerImpl.h b/src/platform/nxp/k32w0/PlatformManagerImpl.h
similarity index 100%
rename from src/platform/nxp/k32w/k32w0/PlatformManagerImpl.h
rename to src/platform/nxp/k32w0/PlatformManagerImpl.h
diff --git a/src/platform/nxp/k32w/k32w0/RamStorage.cpp b/src/platform/nxp/k32w0/RamStorage.cpp
similarity index 99%
rename from src/platform/nxp/k32w/k32w0/RamStorage.cpp
rename to src/platform/nxp/k32w0/RamStorage.cpp
index ea32a7f9c525c8..a478a582b98fb1 100644
--- a/src/platform/nxp/k32w/k32w0/RamStorage.cpp
+++ b/src/platform/nxp/k32w0/RamStorage.cpp
@@ -18,7 +18,7 @@
 #include <openthread/platform/memory.h>
 #include <platform/internal/CHIPDeviceLayerInternal.h>
 
-#include <platform/nxp/k32w/k32w0/RamStorage.h>
+#include <platform/nxp/k32w0/RamStorage.h>
 
 #include "pdm_ram_storage_glue.h"
 
diff --git a/src/platform/nxp/k32w/k32w0/RamStorage.h b/src/platform/nxp/k32w0/RamStorage.h
similarity index 100%
rename from src/platform/nxp/k32w/k32w0/RamStorage.h
rename to src/platform/nxp/k32w0/RamStorage.h
diff --git a/src/platform/nxp/k32w/k32w0/SystemPlatformConfig.h b/src/platform/nxp/k32w0/SystemPlatformConfig.h
similarity index 100%
rename from src/platform/nxp/k32w/k32w0/SystemPlatformConfig.h
rename to src/platform/nxp/k32w0/SystemPlatformConfig.h
diff --git a/src/platform/nxp/k32w/k32w0/SystemTimeSupport.cpp b/src/platform/nxp/k32w0/SystemTimeSupport.cpp
similarity index 100%
rename from src/platform/nxp/k32w/k32w0/SystemTimeSupport.cpp
rename to src/platform/nxp/k32w0/SystemTimeSupport.cpp
diff --git a/src/platform/nxp/k32w/k32w0/ThreadStackManagerImpl.cpp b/src/platform/nxp/k32w0/ThreadStackManagerImpl.cpp
similarity index 100%
rename from src/platform/nxp/k32w/k32w0/ThreadStackManagerImpl.cpp
rename to src/platform/nxp/k32w0/ThreadStackManagerImpl.cpp
diff --git a/src/platform/nxp/k32w/k32w0/ThreadStackManagerImpl.h b/src/platform/nxp/k32w0/ThreadStackManagerImpl.h
similarity index 100%
rename from src/platform/nxp/k32w/k32w0/ThreadStackManagerImpl.h
rename to src/platform/nxp/k32w0/ThreadStackManagerImpl.h
diff --git a/src/platform/nxp/k32w/k32w0/args.gni b/src/platform/nxp/k32w0/args.gni
similarity index 89%
rename from src/platform/nxp/k32w/k32w0/args.gni
rename to src/platform/nxp/k32w0/args.gni
index 5f90c8248e207a..1076eea4f4cf7f 100644
--- a/src/platform/nxp/k32w/k32w0/args.gni
+++ b/src/platform/nxp/k32w0/args.gni
@@ -16,15 +16,14 @@ import("//build_overrides/chip.gni")
 import("//build_overrides/nxp_sdk.gni")
 import("//build_overrides/openthread.gni")
 
-nxp_platform = "k32w/k32w0"
+nxp_platform = "k32w0"
 nxp_sdk_name = "k32w0_sdk"
 nxp_device_layer = "nxp/${nxp_platform}"
 nxp_use_lwip = false
 nxp_use_mbedtls_port = false
 
 if (getenv("NXP_K32W0_SDK_ROOT") == "") {
-  k32w0_sdk_root =
-      "${nxp_sdk_matter_support_root}/github_sdk/k32w0_sdk/repo/core"
+  k32w0_sdk_root = "${nxp_sdk_matter_support_root}/github_sdk/k32w0/repo"
 } else {
   k32w0_sdk_root = getenv("NXP_K32W0_SDK_ROOT")
 }
@@ -72,6 +71,6 @@ openthread_external_mbedtls = mbedtls_target
 openthread_project_core_config_file = "OpenThreadConfig.h"
 openthread_core_config_platform_check_file =
     "openthread-core-k32w061-config-check.h"
-openthread_core_config_deps = [ "${chip_root}/examples/platform/nxp/k32w/k32w0:openthread_core_config_k32w0_chip_examples" ]
+openthread_core_config_deps = [ "${nxp_sdk_matter_support_root}/examples/platform/k32w0:openthread_core_config_k32w0_chip_examples" ]
 
-openthread_external_platform = "${chip_root}/third_party/openthread/platforms/nxp/k32w/k32w0:libopenthread-k32w0"
+openthread_external_platform = "${chip_root}/third_party/openthread/platforms/nxp/k32w0:libopenthread-k32w0"
diff --git a/src/platform/nxp/k32w/k32w0/ble_function_mux.c b/src/platform/nxp/k32w0/ble_function_mux.c
similarity index 100%
rename from src/platform/nxp/k32w/k32w0/ble_function_mux.c
rename to src/platform/nxp/k32w0/ble_function_mux.c
diff --git a/src/platform/nxp/k32w/k32w0/ble_function_mux.h b/src/platform/nxp/k32w0/ble_function_mux.h
similarity index 100%
rename from src/platform/nxp/k32w/k32w0/ble_function_mux.h
rename to src/platform/nxp/k32w0/ble_function_mux.h
diff --git a/src/platform/nxp/k32w/k32w0/crypto/CHIPCryptoPALNXPUltrafastP256.cpp b/src/platform/nxp/k32w0/crypto/CHIPCryptoPALNXPUltrafastP256.cpp
similarity index 100%
rename from src/platform/nxp/k32w/k32w0/crypto/CHIPCryptoPALNXPUltrafastP256.cpp
rename to src/platform/nxp/k32w0/crypto/CHIPCryptoPALNXPUltrafastP256.cpp
diff --git a/src/platform/nxp/k32w/k32w0/gatt_db.h b/src/platform/nxp/k32w0/gatt_db.h
similarity index 100%
rename from src/platform/nxp/k32w/k32w0/gatt_db.h
rename to src/platform/nxp/k32w0/gatt_db.h
diff --git a/src/platform/nxp/k32w/k32w0/gatt_uuid128.h b/src/platform/nxp/k32w0/gatt_uuid128.h
similarity index 100%
rename from src/platform/nxp/k32w/k32w0/gatt_uuid128.h
rename to src/platform/nxp/k32w0/gatt_uuid128.h
diff --git a/src/platform/nxp/k32w/k32w0/k32w0-chip-mbedtls-config.h b/src/platform/nxp/k32w0/k32w0-chip-mbedtls-config.h
similarity index 100%
rename from src/platform/nxp/k32w/k32w0/k32w0-chip-mbedtls-config.h
rename to src/platform/nxp/k32w0/k32w0-chip-mbedtls-config.h
diff --git a/third_party/nxp/nxp_matter_support b/third_party/nxp/nxp_matter_support
index ac504a0cc38963..e6deaf56001387 160000
--- a/third_party/nxp/nxp_matter_support
+++ b/third_party/nxp/nxp_matter_support
@@ -1 +1 @@
-Subproject commit ac504a0cc389632c0e26b4f04e65914d3a9ba8bd
+Subproject commit e6deaf5600138763ea68418e34bc62a02d1aef0d
diff --git a/third_party/openthread/platforms/nxp/k32w/k32w0/BUILD.gn b/third_party/openthread/platforms/nxp/k32w0/BUILD.gn
similarity index 92%
rename from third_party/openthread/platforms/nxp/k32w/k32w0/BUILD.gn
rename to third_party/openthread/platforms/nxp/k32w0/BUILD.gn
index 7ebd860e571371..bf9ed42e894965 100644
--- a/third_party/openthread/platforms/nxp/k32w/k32w0/BUILD.gn
+++ b/third_party/openthread/platforms/nxp/k32w0/BUILD.gn
@@ -30,7 +30,7 @@ config("openthread_k32w0_config") {
     "${openthread_nxp_root}/src/k32w0/platform",
     "${openthread_nxp_root}/src/common",
   ]
-  include_dirs += [ "${chip_root}/examples/platform/nxp/k32w/k32w0" ]
+  include_dirs += [ "${nxp_sdk_matter_support_root}/examples/platform/k32w0" ]
 
   if (is_clang) {
     cflags = [ "-Wno-format-nonliteral" ]
@@ -46,7 +46,7 @@ config("openthread_k32w0_config") {
 
 source_set("openthread_core_config_k32w0") {
   sources = [
-    "${chip_root}/examples/platform/nxp/k32w/k32w0/app/project_include/OpenThreadConfig.h",
+    "${nxp_sdk_matter_support_root}/examples/platform/k32w0/app/project_include/OpenThreadConfig.h",
     "${openthread_nxp_root}/src/k32w0/k32w061/openthread-core-k32w061-config-check.h",
   ]
 
@@ -95,7 +95,7 @@ source_set("libopenthread-k32w0") {
     "${nxp_sdk_build_root}:nxp_sdk",
     "${nxp_sdk_build_root}/${nxp_sdk_name}:mbedtls",
     "${openthread_root}/src/core:libopenthread_core_headers",
-    "../../..:libopenthread-platform",
-    "../../..:libopenthread-platform-utils",
+    "../..:libopenthread-platform",
+    "../..:libopenthread-platform-utils",
   ]
 }