[Silabs] SiWx917 folder structure skeleton in silabs folder (#23750)

* Copy of EFR32 in SiWx917 folder as the skeleton for platform changes

* restyling the PR

* Spelling corrections in the PR

* Spelling check recorrected
diff --git a/examples/lighting-app/silabs/SiWx917/.gn b/examples/lighting-app/silabs/SiWx917/.gn
new file mode 100644
index 0000000..4c078f6
--- /dev/null
+++ b/examples/lighting-app/silabs/SiWx917/.gn
@@ -0,0 +1,29 @@
+# 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/build.gni")
+
+# The location of the build configuration file.
+buildconfig = "${build_root}/config/BUILDCONFIG.gn"
+
+# CHIP uses angle bracket includes.
+check_system_includes = true
+
+default_args = {
+  target_cpu = "arm"
+  target_os = "freertos"
+  chip_openthread_ftd = true
+
+  import("//args.gni")
+}
diff --git a/examples/lighting-app/silabs/SiWx917/BUILD.gn b/examples/lighting-app/silabs/SiWx917/BUILD.gn
new file mode 100644
index 0000000..3a812b9
--- /dev/null
+++ b/examples/lighting-app/silabs/SiWx917/BUILD.gn
@@ -0,0 +1,385 @@
+# 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/build.gni")
+import("//build_overrides/chip.gni")
+import("//build_overrides/efr32_sdk.gni")
+import("//build_overrides/pigweed.gni")
+
+import("${build_root}/config/defaults.gni")
+import("${efr32_sdk_build_root}/efr32_executable.gni")
+import("${efr32_sdk_build_root}/efr32_sdk.gni")
+
+import("${chip_root}/examples/common/pigweed/pigweed_rpcs.gni")
+import("${chip_root}/src/platform/device.gni")
+
+if (chip_enable_pw_rpc) {
+  import("//build_overrides/pigweed.gni")
+  import("$dir_pw_build/target_types.gni")
+}
+
+assert(current_os == "freertos")
+
+efr32_project_dir = "${chip_root}/examples/lighting-app/silabs/efr32"
+examples_plat_dir = "${chip_root}/examples/platform/silabs/efr32"
+examples_common_plat_dir = "${chip_root}/examples/platform/silabs"
+
+declare_args() {
+  # Dump memory usage at link time.
+  chip_print_memory_usage = false
+
+  # Monitor & log memory usage at runtime.
+  enable_heap_monitoring = false
+
+  # Enable Sleepy end device
+  enable_sleepy_device = false
+
+  # OTA timeout in seconds
+  OTA_periodic_query_timeout = 86400
+
+  # Wifi related stuff - they are overridden by gn -args="use_wf200=true"
+  use_wf200 = false
+  use_rs911x = false
+  use_rs911x_sockets = false
+  sl_wfx_config_softap = false
+  sl_wfx_config_scan = true
+
+  # Disable LCD on supported devices
+  disable_lcd = false
+
+  # Argument to Disable IPv4 for wifi(rs911)
+  chip_enable_wifi_ipv4 = false
+
+  # Argument to force enable WPA3 security on rs91x
+  rs91x_wpa3_only = false
+}
+
+declare_args() {
+  # Enables LCD Qr Code on supported devices
+  show_qr_code = !disable_lcd
+}
+
+# qr code cannot be true if lcd is disabled
+assert(!(disable_lcd && show_qr_code))
+
+# Sanity check
+assert(!(chip_enable_wifi && chip_enable_openthread))
+assert(!(use_rs911x && chip_enable_openthread))
+assert(!(use_wf200 && chip_enable_openthread))
+if (chip_enable_wifi) {
+  assert(use_rs911x || use_wf200)
+  enable_openthread_cli = false
+  import("${chip_root}/src/platform/silabs/EFR32/wifi_args.gni")
+}
+
+# ThunderBoards, Explorer Kit and MGM240L do not support LCD (No LCD)
+if (silabs_board == "BRD4166A" || silabs_board == "BRD2601B" ||
+    silabs_board == "BRD2703A" || silabs_board == "BRD4319A") {
+  show_qr_code = false
+  disable_lcd = true
+}
+
+# WiFi settings
+if (chip_enable_wifi) {
+  # disabling LCD for MG24 for wifi
+  if (silabs_board == "BRD4186A" || silabs_board == "BRD4187A") {
+    show_qr_code = false
+    disable_lcd = true
+  }
+  wifi_sdk_dir = "${chip_root}/src/platform/silabs/EFR32/wifi"
+  efr32_lwip_defs = [ "LWIP_NETIF_API=1" ]
+  if (lwip_ipv4) {
+    efr32_lwip_defs += [
+      "LWIP_IPV4=1",
+
+      # adds following options to provide
+      # them to .cpp source files
+      # flags ported from lwipopts file
+      # TODO: move lwipopts to one location
+      "LWIP_ARP=1",
+      "LWIP_ICMP=1",
+      "LWIP_IGMP=1",
+      "LWIP_DHCP=1",
+      "LWIP_DNS=0",
+    ]
+  } else {
+    efr32_lwip_defs += [ "LWIP_IPV4=0" ]
+  }
+  if (lwip_ipv6) {
+    efr32_lwip_defs += [ "LWIP_IPV6=1" ]
+  } else {
+    efr32_lwip_defs += [ "LWIP_IPV6=0" ]
+  }
+
+  if (use_rs911x) {
+    wiseconnect_sdk_root =
+        "${chip_root}/third_party/silabs/wiseconnect-wifi-bt-sdk"
+    import("${examples_plat_dir}/rs911x/rs911x.gni")
+  } else {
+    import("${examples_plat_dir}/wf200/wf200.gni")
+  }
+}
+
+efr32_sdk("sdk") {
+  sources = [
+    "${efr32_project_dir}/include/CHIPProjectConfig.h",
+    "${examples_plat_dir}/FreeRTOSConfig.h",
+  ]
+
+  include_dirs = [
+    "${chip_root}/src/platform/silabs/EFR32",
+    "${efr32_project_dir}/include",
+    "${examples_plat_dir}",
+    "${chip_root}/src/lib",
+    "${examples_common_plat_dir}",
+  ]
+
+  defines = [
+    "BOARD_ID=${silabs_board}",
+    "OTA_PERIODIC_TIMEOUT=${OTA_periodic_query_timeout}",
+  ]
+
+  if (enable_heap_monitoring) {
+    defines += [ "HEAP_MONITORING" ]
+  }
+
+  if (chip_enable_pw_rpc) {
+    defines += [
+      "HAL_VCOM_ENABLE=1",
+      "PW_RPC_ENABLED",
+    ]
+  }
+
+  # WiFi Settings
+  if (chip_enable_wifi) {
+    if (use_rs911x) {
+      defines += rs911x_defs
+      include_dirs += rs911x_plat_incs
+    } else if (use_wf200) {
+      defines += wf200_defs
+      include_dirs += wf200_plat_incs
+    }
+
+    if (use_rs911x_sockets) {
+      include_dirs += [ "${examples_plat_dir}/wifi/rsi-sockets" ]
+      defines += rs911x_sock_defs
+    } else {
+      # Using LWIP instead of the native TCP/IP stack
+      defines += efr32_lwip_defs
+    }
+
+    if (sl_wfx_config_softap) {
+      defines += [ "SL_WFX_CONFIG_SOFTAP" ]
+    }
+    if (sl_wfx_config_scan) {
+      defines += [ "SL_WFX_CONFIG_SCAN" ]
+    }
+  }
+}
+
+efr32_executable("lighting_app") {
+  output_name = "chip-efr32-lighting-example.out"
+  include_dirs = [ "include" ]
+  defines = []
+
+  sources = [
+    "${examples_common_plat_dir}/heap_4_silabs.c",
+    "${examples_plat_dir}/BaseApplication.cpp",
+    "${examples_plat_dir}/efr32_utils.cpp",
+    "${examples_plat_dir}/init_efrPlatform.cpp",
+    "${examples_plat_dir}/matter_config.cpp",
+    "src/AppTask.cpp",
+    "src/LightingManager.cpp",
+    "src/ZclCallbacks.cpp",
+    "src/main.cpp",
+  ]
+
+  if (use_wstk_leds) {
+    sources += [ "${examples_plat_dir}/LEDWidget.cpp" ]
+  }
+
+  if (chip_enable_pw_rpc || chip_build_libshell || enable_openthread_cli ||
+      use_wf200 || use_rs911x) {
+    sources += [ "${examples_plat_dir}/uart.cpp" ]
+  }
+
+  deps = [
+    ":sdk",
+    "${chip_root}/examples/lighting-app/lighting-common",
+    "${chip_root}/examples/providers:device_info_provider",
+    "${chip_root}/src/lib",
+    "${chip_root}/src/setup_payload",
+  ]
+
+  # OpenThread Settings
+  if (chip_enable_openthread) {
+    deps += [
+      "${chip_root}/third_party/openthread:openthread",
+      "${chip_root}/third_party/openthread:openthread-platform",
+      "${examples_plat_dir}:efr-matter-shell",
+    ]
+  }
+
+  if (chip_enable_ota_requestor) {
+    defines += [ "EFR32_OTA_ENABLED" ]
+    sources += [ "${examples_plat_dir}/OTAConfig.cpp" ]
+  }
+
+  # WiFi Settings
+  if (chip_enable_wifi) {
+    if (use_rs911x) {
+      sources += rs911x_src_plat
+
+      # All the stuff from wiseconnect
+      sources += rs911x_src_sapi
+
+      # Apparently - the rsi library needs this (though we may not use use it)
+      sources += rs911x_src_sock
+      include_dirs += rs911x_inc_plat
+
+      if (use_rs911x_sockets) {
+        #
+        # Using native sockets inside RS911x
+        #
+        include_dirs += rs911x_sock_inc
+      } else {
+        #
+        # We use LWIP - not built-in sockets
+        #
+        sources += rs911x_src_lwip
+      }
+    } else if (use_wf200) {
+      sources += wf200_plat_src
+      include_dirs += wf200_plat_incs
+    }
+
+    if (chip_enable_wifi_ipv4) {
+      defines += [ "CHIP_DEVICE_CONFIG_ENABLE_IPV4" ]
+    }
+
+    if (rs91x_wpa3_only) {
+      # TODO: Change this macro once WF200 support is provided
+      defines += [ "WIFI_ENABLE_SECURITY_WPA3=1" ]
+    }
+  }
+
+  if (!disable_lcd) {
+    sources += [
+      "${examples_plat_dir}/display/demo-ui.c",
+      "${examples_plat_dir}/display/lcd.cpp",
+    ]
+
+    include_dirs += [ "${examples_plat_dir}/display" ]
+    defines += [
+      "DISPLAY_ENABLED",
+      "IS_DEMO_LIGHT=1",
+    ]
+    if (show_qr_code) {
+      defines += [ "QR_CODE_ENABLED" ]
+
+      deps += [ "${chip_root}/examples/common/QRCode" ]
+    }
+  }
+
+  if (chip_enable_pw_rpc) {
+    defines += [
+      "PW_RPC_ENABLED",
+      "PW_RPC_ATTRIBUTE_SERVICE=1",
+      "PW_RPC_BUTTON_SERVICE=1",
+      "PW_RPC_DESCRIPTOR_SERVICE=1",
+      "PW_RPC_DEVICE_SERVICE=1",
+      "PW_RPC_LIGHTING_SERVICE=1",
+      "PW_RPC_OTCLI_SERVICE=1",
+      "PW_RPC_THREAD_SERVICE=1",
+      "PW_RPC_TRACING_SERVICE=1",
+    ]
+
+    sources += [
+      "${chip_root}/examples/common/pigweed/RpcService.cpp",
+      "${chip_root}/examples/common/pigweed/efr32/PigweedLoggerMutex.cpp",
+      "${examples_common_plat_dir}/PigweedLogger.cpp",
+      "${examples_common_plat_dir}/Rpc.cpp",
+    ]
+
+    deps += [
+      "$dir_pw_hdlc:rpc_channel_output",
+      "$dir_pw_stream:sys_io_stream",
+      "$dir_pw_trace",
+      "$dir_pw_trace_tokenized",
+      "$dir_pw_trace_tokenized:trace_rpc_service",
+      "${chip_root}/config/efr32/lib/pw_rpc:pw_rpc",
+      "${chip_root}/examples/common/pigweed:attributes_service.nanopb_rpc",
+      "${chip_root}/examples/common/pigweed:button_service.nanopb_rpc",
+      "${chip_root}/examples/common/pigweed:descriptor_service.nanopb_rpc",
+      "${chip_root}/examples/common/pigweed:device_service.nanopb_rpc",
+      "${chip_root}/examples/common/pigweed:lighting_service.nanopb_rpc",
+      "${chip_root}/examples/common/pigweed:ot_cli_service.nanopb_rpc",
+      "${chip_root}/examples/common/pigweed:thread_service.nanopb_rpc",
+      "${examples_plat_dir}/pw_sys_io:pw_sys_io_efr32",
+    ]
+
+    deps += pw_build_LINK_DEPS
+
+    include_dirs += [
+      "${chip_root}/examples/common",
+      "${chip_root}/examples/common/pigweed/efr32",
+    ]
+  }
+
+  if (enable_heap_monitoring) {
+    sources += [ "${examples_common_plat_dir}/MemMonitoring.cpp" ]
+    defines += [ "HEAP_MONITORING" ]
+  }
+
+  ldscript = "${examples_plat_dir}/ldscripts/${silabs_family}.ld"
+
+  inputs = [ ldscript ]
+
+  ldflags = [ "-T" + rebase_path(ldscript, root_build_dir) ]
+
+  if (chip_print_memory_usage) {
+    ldflags += [
+      "-Wl,--print-memory-usage",
+      "-fstack-usage",
+    ]
+  }
+
+  # WiFi Settings
+  if (chip_enable_wifi) {
+    ldflags += [
+      "-Wl,--defsym",
+      "-Wl,SILABS_WIFI=1",
+    ]
+  }
+
+  # Attestation Credentials
+  if (chip_build_platform_attestation_credentials_provider) {
+    deps += [ "${examples_plat_dir}:efr32-attestation-credentials" ]
+  }
+
+  # Factory Data Provider
+  if (use_efr32_factory_data_provider) {
+    deps += [ "${examples_plat_dir}:efr32-factory-data-provider" ]
+  }
+
+  output_dir = root_out_dir
+}
+
+group("efr32") {
+  deps = [ ":lighting_app" ]
+}
+
+group("default") {
+  deps = [ ":efr32" ]
+}
diff --git a/examples/lighting-app/silabs/SiWx917/README.md b/examples/lighting-app/silabs/SiWx917/README.md
new file mode 100644
index 0000000..ae7565f
--- /dev/null
+++ b/examples/lighting-app/silabs/SiWx917/README.md
@@ -0,0 +1,424 @@
+# Matter EFR32 Lighting Example
+
+An example showing the use of CHIP on the Silicon Labs EFR32 MG12 and MG24.
+
+<hr>
+
+-   [Matter EFR32 Lighting Example](#matter-efr32-lighting-example)
+    -   [Introduction](#introduction)
+    -   [Building](#building)
+    -   [Flashing the Application](#flashing-the-application)
+    -   [Viewing Logging Output](#viewing-logging-output)
+    -   [Running the Complete Example](#running-the-complete-example)
+        -   [Notes](#notes)
+    -   [Running RPC console](#running-rpc-console)
+    -   [Device Tracing](#device-tracing)
+    -   [Memory settings](#memory-settings)
+    -   [OTA Software Update](#ota-software-update)
+    -   [Group Communication (Multicast)](#group-communication-multicast)
+    -   [Building options](#building-options)
+        -   [Disabling logging](#disabling-logging)
+        -   [Debug build / release build](#debug-build--release-build)
+        -   [Disabling LCD](#disabling-lcd)
+        -   [KVS maximum entry count](#kvs-maximum-entry-count)
+
+<hr>
+
+> **NOTE:** Silicon Laboratories now maintains a public matter GitHub repo with
+> frequent releases thoroughly tested and validated. Developers looking to
+> develop matter products with silabs hardware are encouraged to use our latest
+> release with added tools and documentation.
+> [Silabs Matter Github](https://github.com/SiliconLabs/matter/releases)
+
+<a name="intro"></a>
+
+## Introduction
+
+The EFR32 lighting example provides a baseline demonstration of a Light control
+device, built using Matter and the Silicon Labs gecko SDK. It can be controlled
+by a Chip controller over an Openthread or Wifi network..
+
+The EFR32 device can be commissioned over Bluetooth Low Energy where the device
+and the Chip controller will exchange security information with the Rendez-vous
+procedure. If using Thread, Thread Network credentials are then provided to the
+EFR32 device which will then join the Thread network.
+
+If the LCD is enabled, the LCD on the Silabs WSTK shows a QR Code containing the
+needed commissioning information for the BLE connection and starting the
+Rendez-vous procedure.
+
+The lighting example is intended to serve both as a means to explore the
+workings of Matter as well as a template for creating real products based on the
+Silicon Labs platform.
+
+<a name="building"></a>
+
+## Building
+
+-   Download the
+    [Simplicity Commander](https://www.silabs.com/mcu/programming-options)
+    command line tool, and ensure that `commander` is your shell search path.
+    (For Mac OS X, `commander` is located inside
+    `Commander.app/Contents/MacOS/`.)
+
+-   Download and install a suitable ARM gcc tool chain:
+    [GNU Arm Embedded Toolchain 9-2019-q4-major](https://developer.arm.com/tools-and-software/open-source-software/developer-tools/gnu-toolchain/gnu-rm/downloads)
+
+-   Install some additional tools (likely already present for CHIP developers):
+
+    -   Linux: `sudo apt-get install git ninja-build`
+
+    -   Mac OS X: `brew install ninja`
+
+-   Supported hardware:
+
+    -   > For the latest supported hardware please refer to the
+        > [Hardware Requirements](https://github.com/SiliconLabs/matter/blob/latest/docs/silabs/general/HARDWARE_REQUIREMENTS.md)
+        > in the Silicon Labs Matter Github Repo
+
+    MG12 boards:
+
+    -   BRD4161A / SLWSTK6000B / Wireless Starter Kit / 2.4GHz@19dBm
+    -   BRD4162A / SLWSTK6000B / Wireless Starter Kit / 2.4GHz@10dBm
+    -   BRD4163A / SLWSTK6000B / Wireless Starter Kit / 2.4GHz@10dBm,
+        868MHz@19dBm
+    -   BRD4164A / SLWSTK6000B / Wireless Starter Kit / 2.4GHz@19dBm
+    -   BRD4166A / SLTB004A / Thunderboard Sense 2 / 2.4GHz@10dBm
+    -   BRD4170A / SLWSTK6000B / Multiband Wireless Starter Kit / 2.4GHz@19dBm,
+        915MHz@19dBm
+    -   BRD4304A / SLWSTK6000B / MGM12P Module / 2.4GHz@19dBm
+
+    MG21 boards: Currently not supported due to RAM limitation.
+
+    -   BRD4180A / SLWSTK6006A / Wireless Starter Kit / 2.4GHz@20dBm
+
+    MG24 boards :
+
+    -   BRD2601B / SLWSTK6000B / Wireless Starter Kit / 2.4GHz@10dBm
+    -   BRD2703A / SLWSTK6000B / Wireless Starter Kit / 2.4GHz@10dBm
+    -   BRD4186A / SLWSTK6006A / Wireless Starter Kit / 2.4GHz@10dBm
+    -   BRD4186C / SLWSTK6006A / Wireless Starter Kit / 2.4GHz@10dBm
+    -   BRD4187A / SLWSTK6006A / Wireless Starter Kit / 2.4GHz@20dBm
+    -   BRD4187C / SLWSTK6006A / Wireless Starter Kit / 2.4GHz@20dBm
+
+    MG12 boards:
+
+    -   BRD4161A / SLWSTK6000B / Wireless Starter Kit / 2.4GHz@19dBm
+    -   BRD4162A / SLWSTK6000B / Wireless Starter Kit / 2.4GHz@10dBm
+    -   BRD4163A / SLWSTK6000B / Wireless Starter Kit / 2.4GHz@10dBm,
+        868MHz@19dBm
+    -   BRD4164A / SLWSTK6000B / Wireless Starter Kit / 2.4GHz@19dBm
+    -   BRD4166A / SLTB004A / Thunderboard Sense 2 / 2.4GHz@10dBm
+    -   BRD4170A / SLWSTK6000B / Multiband Wireless Starter Kit / 2.4GHz@19dBm,
+        915MHz@19dBm
+    -   BRD4304A / SLWSTK6000B / MGM12P Module / 2.4GHz@19dBm
+
+    MG21 boards: Currently not supported due to RAM limitation.
+
+    -   BRD4180A / SLWSTK6006A / Wireless Starter Kit / 2.4GHz@20dBm
+
+    MG24 boards :
+
+    -   BRD2601B / SLWSTK6000B / Wireless Starter Kit / 2.4GHz@10dBm
+    -   BRD2703A / SLWSTK6000B / Wireless Starter Kit / 2.4GHz@10dBm
+    -   BRD4186A / SLWSTK6006A / Wireless Starter Kit / 2.4GHz@10dBm
+    -   BRD4186C / SLWSTK6006A / Wireless Starter Kit / 2.4GHz@10dBm
+    -   BRD4187A / SLWSTK6006A / Wireless Starter Kit / 2.4GHz@20dBm
+    -   BRD4187C / SLWSTK6006A / Wireless Starter Kit / 2.4GHz@20dBm
+
+*   Build the example application:
+
+          cd ~/connectedhomeip
+          ./scripts/examples/gn_efr32_example.sh ./examples/lighting-app/efr32/ ./out/lighting-app BRD4161A
+
+-   To delete generated executable, libraries and object files use:
+
+          $ cd ~/connectedhomeip
+          $ rm -rf ./out/
+
+    OR use GN/Ninja directly
+
+          $ cd ~/connectedhomeip/examples/lighting-app/efr32
+          $ git submodule update --init
+          $ source third_party/connectedhomeip/scripts/activate.sh
+          $ export EFR32_BOARD=BRD4161A
+          $ gn gen out/debug
+          $ ninja -C out/debug
+
+-   To delete generated executable, libraries and object files use:
+
+          $ cd ~/connectedhomeip/examples/lighting-app/efr32
+          $ rm -rf out/
+
+*   Build the example as Sleepy End Device (SED)
+
+          $ ./scripts/examples/gn_efr32_example.sh ./examples/lighting-app/efr32/ ./out/lighting-app_SED BRD4161A --sed
+
+    or use gn as previously mentioned but adding the following arguments:
+
+          $ gn gen out/debug '--args=silabs_board="BRD4161A" enable_sleepy_device=true chip_openthread_ftd=false'
+
+*   Build the example with pigweed RPC
+
+          $ ./scripts/examples/gn_efr32_example.sh examples/lighting-app/efr32/ out/lighting_app_rpc BRD4161A 'import("//with_pw_rpc.gni")'
+
+    or use GN/Ninja Directly
+
+          $ cd ~/connectedhomeip/examples/lighting-app/efr32
+          $ git submodule update --init
+          $ source third_party/connectedhomeip/scripts/activate.sh
+          $ export EFR32_BOARD=BRD4161A
+          $ gn gen out/debug --args='import("//with_pw_rpc.gni")'
+          $ ninja -C out/debug
+
+    [Running Pigweed RPC console](#running-pigweed-rpc-console)
+
+For more build options, help is provided when running the build script without
+arguments
+
+         ./scripts/examples/gn_efr32_example.sh
+
+<a name="flashing"></a>
+
+## Flashing the Application
+
+-   On the command line:
+
+          $ cd ~/connectedhomeip/examples/lighting-app/efr32
+          $ python3 out/debug/chip-efr32-lighting-example.flash.py
+
+-   Or with the Ozone debugger, just load the .out file.
+
+<a name="view-logging"></a>
+
+## Viewing Logging Output
+
+The example application is built to use the SEGGER Real Time Transfer (RTT)
+facility for log output. RTT is a feature built-in to the J-Link Interface MCU
+on the WSTK development board. It allows bi-directional communication with an
+embedded application without the need for a dedicated UART.
+
+Using the RTT facility requires downloading and installing the _SEGGER J-Link
+Software and Documentation Pack_
+([web site](https://www.segger.com/downloads/jlink#J-LinkSoftwareAndDocumentationPack)).
+
+Alternatively, SEGGER Ozone J-Link debugger can be used to view RTT logs too
+after flashing the .out file.
+
+-   Download the J-Link installer by navigating to the appropriate URL and
+    agreeing to the license agreement.
+
+-   [JLink_Linux_x86_64.deb](https://www.segger.com/downloads/jlink/JLink_Linux_x86_64.deb)
+-   [JLink_MacOSX.pkg](https://www.segger.com/downloads/jlink/JLink_MacOSX.pkg)
+
+*   Install the J-Link software
+
+          $ cd ~/Downloads
+          $ sudo dpkg -i JLink_Linux_V*_x86_64.deb
+
+*   In Linux, grant the logged in user the ability to talk to the development
+    hardware via the linux tty device (/dev/ttyACMx) by adding them to the
+    dialout group.
+
+          $ sudo usermod -a -G dialout ${USER}
+
+Once the above is complete, log output can be viewed using the JLinkExe tool in
+combination with JLinkRTTClient as follows:
+
+-   Run the JLinkExe tool with arguments to autoconnect to the WSTK board:
+
+    For MG12 use:
+
+          $ JLinkExe -device EFR32MG12PXXXF1024 -if JTAG -speed 4000 -autoconnect 1
+
+    For MG21 use:
+
+          $ JLinkExe -device EFR32MG21AXXXF1024 -if SWD -speed 4000 -autoconnect 1
+
+-   In a second terminal, run the JLinkRTTClient to view logs:
+
+          $ JLinkRTTClient
+
+<a name="running-complete-example"></a>
+
+## Running the Complete Example
+
+-   It is assumed here that you already have an OpenThread border router
+    configured and running. If not see the following guide
+    [Openthread_border_router](https://github.com/project-chip/connectedhomeip/blob/master/docs/guides/openthread_border_router_pi.md)
+    for more information on how to setup a border router on a raspberryPi.
+
+    Take note that the RCP code is available directly through
+    [Simplicity Studio 5](https://www.silabs.com/products/development-tools/software/simplicity-studio/simplicity-studio-5)
+    under File->New->Project Wizard->Examples->Thread : ot-rcp
+
+-   User interface : **LCD** The LCD on Silabs WSTK shows a QR Code. This QR
+    Code is be scanned by the CHIP Tool app For the Rendez-vous procedure over
+    BLE
+
+        * On devices that do not have or support the LCD Display like the BRD4166A Thunderboard Sense 2,
+          a URL can be found in the RTT logs.
+
+          <info  > [SVR] Copy/paste the below URL in a browser to see the QR Code:
+          <info  > [SVR] https://project-chip.github.io/connectedhomeip/qrcode.html?data=CH%3AI34NM%20-00%200C9SS0
+
+    **LED 0** shows the overall state of the device and its connectivity. The
+    following states are possible:
+
+        -   _Short Flash On (50 ms on/950 ms off)_ ; The device is in the
+            unprovisioned (unpaired) state and is waiting for a commissioning
+            application to connect.
+
+        -   _Rapid Even Flashing_ ; (100 ms on/100 ms off)_ &mdash; The device is in the
+            unprovisioned state and a commissioning application is connected through
+            Bluetooth LE.
+
+        -   _Short Flash Off_ ; (950ms on/50ms off)_ &mdash; The device is fully
+            provisioned, but does not yet have full Thread network or service
+            connectivity.
+
+        -   _Solid On_ ; The device is fully provisioned and has full Thread
+            network and service connectivity.
+
+    **LED 1** Simulates the Light The following states are possible:
+
+        -   _Solid On_ ; Light is on
+        -   _Off_ ; Light is off
+
+    **Push Button 0**
+
+        -   _Press and Release_ : Start, or restart, BLE advertisement in fast mode. It will advertise in this mode
+            for 30 seconds. The device will then switch to a slower interval advertisement.
+            After 15 minutes, the advertisement stops.
+
+        -   _Pressed and hold for 6 s_ : Initiates the factory reset of the device.
+            Releasing the button within the 6-second window cancels the factory reset
+            procedure. **LEDs** blink in unison when the factory reset procedure is
+            initiated.
+
+    **Push Button 1** Toggles the light state On/Off
+
+*   You can provision and control the Chip device using the python controller,
+    Chip tool standalone, Android or iOS app
+
+*   You can provision and control the Chip device using the python controller,
+    Chip tool standalone, Android or iOS app
+
+    [CHIPTool](https://github.com/project-chip/connectedhomeip/blob/master/examples/chip-tool/README.md)
+
+    Here is an example with the CHIPTool:
+
+    chip-tool pairing ble-thread 1 hex:<operationalDataset> 20202021 3840
+
+    chip-tool onoff on 1 1
+
+### Notes
+
+-   Depending on your network settings your router might not provide native ipv6
+    addresses to your devices (Border router / PC). If this is the case, you
+    need to add a static ipv6 addresses on both device and then an ipv6 route to
+    the border router on your PC
+
+    -   On Border Router: `sudo ip addr add dev <Network interface> 2002::2/64`
+
+    -   On PC(Linux): `sudo ip addr add dev <Network interface> 2002::1/64`
+
+    -   Add Ipv6 route on PC(Linux)
+        `sudo ip route add <Thread global ipv6 prefix>/64 via 2002::2`
+
+<a name="running-pigweed-rpc-console"></a>
+
+## Running RPC console
+
+-   As part of building the example with RPCs enabled the chip_rpc python
+    interactive console is installed into your venv. The python wheel files are
+    also created in the output folder: out/debug/chip_rpc_console_wheels. To
+    install the wheel files without rebuilding:
+    `pip3 install out/debug/chip_rpc_console_wheels/*.whl`
+
+-   To use the chip-rpc console after it has been installed run:
+    `chip-console --device /dev/tty.<SERIALDEVICE> -b 115200 -o /<YourFolder>/pw_log.out`
+
+-   Then you can simulate a button press or release using the following command
+    where : idx = 0 or 1 for Button PB0 or PB1 action = 0 for PRESSED, 1 for
+    RELEASE Test toggling the LED with
+    `rpcs.chip.rpc.Button.Event(idx=1, pushed=True)`
+
+-   You can also Get and Set the light directly using the RPCs:
+    `rpcs.chip.rpc.Lighting.Get()`
+
+    `rpcs.chip.rpc.Lighting.Set(on=True, level=128, color=protos.chip.rpc.LightingColor(hue=5, saturation=5))`
+
+## Device Tracing
+
+Device tracing is available to analyze the device performance. To turn on
+tracing, build with RPC enabled. See Build the example with pigweed RPC.
+
+Obtain tracing json file.
+
+    $ ./{PIGWEED_REPO}/pw_trace_tokenized/py/pw_trace_tokenized/get_trace.py -d {PORT} -o {OUTPUT_FILE} \
+    -t {ELF_FILE} {PIGWEED_REPO}/pw_trace_tokenized/pw_trace_protos/trace_rpc.proto
+
+## Memory settings
+
+While most of the RAM usage in CHIP is static, allowing easier debugging and
+optimization with symbols analysis, we still need some HEAP for the crypto and
+OpenThread. Size of the HEAP can be modified by changing the value of the
+`configTOTAL_HEAP_SIZE` define inside of the FreeRTOSConfig.h file of this
+example. Please take note that a HEAP size smaller than 13k can and will cause a
+Mbedtls failure during the BLE rendez-vous or CASE session
+
+To track memory usage you can set `enable_heap_monitoring = true` either in the
+BUILD.gn file or pass it as a build argument to gn. This will print on the RTT
+console the RAM usage of each individual task and the number of Memory
+allocation and Free. While this is not extensive monitoring you're welcome to
+modify `examples/platform/efr32/MemMonitoring.cpp` to add your own memory
+tracking code inside the `trackAlloc` and `trackFree` function
+
+## OTA Software Update
+
+For the description of Software Update process with EFR32 example applications
+see
+[EFR32 OTA Software Update](../../../docs/guides/silabs_efr32_software_update.md)
+
+## Group Communication (Multicast)
+
+With this lighting example you can also use group communication to send Lighting
+commands to multiples devices at once. Please refer to the
+[chip-tool documentation](../../chip-tool/README.md) _Configuring the server
+side for Group Commands_ and _Using the Client to Send Group (Multicast) Matter
+Commands_
+
+## Building options
+
+All of Silabs's examples within the Matter repo have all the features enabled by
+default, as to provide the best end user experience. However some of those
+features can easily be toggled on or off. Here is a short list of options to be
+passed to the build scripts.
+
+### Disabling logging
+
+`chip_progress_logging, chip_detail_logging, chip_automation_logging`
+
+    $ ./scripts/examples/gn_efr32_example.sh ./examples/lighting-app/efr32 ./out/lighting-app BRD4164A "chip_detail_logging=false chip_automation_logging=false chip_progress_logging=false"
+
+### Debug build / release build
+
+`is_debug`
+
+    $ ./scripts/examples/gn_efr32_example.sh ./examples/lighting-app/efr32 ./out/lighting-app BRD4164A "is_debug=false"
+
+### Disabling LCD
+
+`show_qr_code`
+
+    $ ./scripts/examples/gn_efr32_example.sh ./examples/lighting-app/efr32 ./out/lighting-app BRD4164A "show_qr_code=false"
+
+### KVS maximum entry count
+
+`kvs_max_entries`
+
+    Set the maximum Kvs entries that can be stored in NVM (Default 75)
+    Thresholds: 30 <= kvs_max_entries <= 255
+
+    $ ./scripts/examples/gn_efr32_example.sh ./examples/lighting-app/efr32 ./out/lighting-app BRD4164A kvs_max_entries=50
diff --git a/examples/lighting-app/silabs/SiWx917/args.gni b/examples/lighting-app/silabs/SiWx917/args.gni
new file mode 100644
index 0000000..d216faa
--- /dev/null
+++ b/examples/lighting-app/silabs/SiWx917/args.gni
@@ -0,0 +1,30 @@
+# 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/pigweed.gni")
+import("${chip_root}/config/standalone/args.gni")
+import("${chip_root}/src/platform/silabs/EFR32/args.gni")
+
+efr32_sdk_target = get_label_info(":sdk", "label_no_toolchain")
+
+chip_enable_ota_requestor = true
+
+pw_log_BACKEND = "${chip_root}/src/lib/support/pw_log_chip"
+pw_assert_BACKEND = "$dir_pw_assert_log:check_backend"
+chip_enable_openthread = true
+pw_rpc_CONFIG = "$dir_pw_rpc:disable_global_mutex"
+
+openthread_external_platform =
+    "${chip_root}/third_party/openthread/platforms/efr32:libopenthread-efr32"
diff --git a/examples/lighting-app/silabs/SiWx917/build_for_wifi_args.gni b/examples/lighting-app/silabs/SiWx917/build_for_wifi_args.gni
new file mode 100644
index 0000000..363d2be
--- /dev/null
+++ b/examples/lighting-app/silabs/SiWx917/build_for_wifi_args.gni
@@ -0,0 +1,25 @@
+# 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/pigweed.gni")
+import("${chip_root}/config/standalone/args.gni")
+
+efr32_sdk_target = get_label_info(":sdk", "label_no_toolchain")
+chip_enable_openthread = false
+import("${chip_root}/src/platform/silabs/EFR32/wifi_args.gni")
+
+chip_enable_ota_requestor = true
+
+pw_log_BACKEND = "${chip_root}/src/lib/support/pw_log_chip"
+pw_assert_BACKEND = "$dir_pw_assert_log:check_backend"
diff --git a/examples/lighting-app/silabs/SiWx917/build_for_wifi_gnfile.gn b/examples/lighting-app/silabs/SiWx917/build_for_wifi_gnfile.gn
new file mode 100644
index 0000000..d391814
--- /dev/null
+++ b/examples/lighting-app/silabs/SiWx917/build_for_wifi_gnfile.gn
@@ -0,0 +1,28 @@
+# 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/build.gni")
+
+# The location of the build configuration file.
+buildconfig = "${build_root}/config/BUILDCONFIG.gn"
+
+# CHIP uses angle bracket includes.
+check_system_includes = true
+
+default_args = {
+  target_cpu = "arm"
+  target_os = "freertos"
+  chip_enable_wifi = true
+  import("//build_for_wifi_args.gni")
+}
diff --git a/examples/lighting-app/silabs/SiWx917/build_overrides b/examples/lighting-app/silabs/SiWx917/build_overrides
new file mode 120000
index 0000000..995884e
--- /dev/null
+++ b/examples/lighting-app/silabs/SiWx917/build_overrides
@@ -0,0 +1 @@
+../../../build_overrides
\ No newline at end of file
diff --git a/examples/lighting-app/silabs/SiWx917/include/AppConfig.h b/examples/lighting-app/silabs/SiWx917/include/AppConfig.h
new file mode 100644
index 0000000..ffadaf9
--- /dev/null
+++ b/examples/lighting-app/silabs/SiWx917/include/AppConfig.h
@@ -0,0 +1,30 @@
+/*
+ *
+ *    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.
+ */
+
+#pragma once
+
+#include "efr32_utils.h"
+
+// ---- Lighting Example App Config ----
+
+#define APP_TASK_NAME "Lit"
+
+// Time it takes in ms for the simulated actuator to move from one
+// state to another.
+#define ACTUATOR_MOVEMENT_PERIOS_MS 10
diff --git a/examples/lighting-app/silabs/SiWx917/include/AppEvent.h b/examples/lighting-app/silabs/SiWx917/include/AppEvent.h
new file mode 100644
index 0000000..7a19b71
--- /dev/null
+++ b/examples/lighting-app/silabs/SiWx917/include/AppEvent.h
@@ -0,0 +1,55 @@
+/*
+ *
+ *    Copyright (c) 2020 Project CHIP Authors
+ *    Copyright (c) 2018 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
+
+struct AppEvent;
+typedef void (*EventHandler)(AppEvent *);
+
+struct AppEvent
+{
+    enum AppEventTypes
+    {
+        kEventType_Button = 0,
+        kEventType_Timer,
+        kEventType_Light,
+        kEventType_Install,
+    };
+
+    uint16_t Type;
+
+    union
+    {
+        struct
+        {
+            uint8_t Action;
+        } ButtonEvent;
+        struct
+        {
+            void * Context;
+        } TimerEvent;
+        struct
+        {
+            uint8_t Action;
+            int32_t Actor;
+        } LightEvent;
+    };
+
+    EventHandler Handler;
+};
diff --git a/examples/lighting-app/silabs/SiWx917/include/AppTask.h b/examples/lighting-app/silabs/SiWx917/include/AppTask.h
new file mode 100644
index 0000000..df80995
--- /dev/null
+++ b/examples/lighting-app/silabs/SiWx917/include/AppTask.h
@@ -0,0 +1,131 @@
+/*
+ *
+ *    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.
+ */
+
+#pragma once
+
+/**********************************************************
+ * Includes
+ *********************************************************/
+
+#include <stdbool.h>
+#include <stdint.h>
+
+#include "AppEvent.h"
+#include "BaseApplication.h"
+#include "FreeRTOS.h"
+#include "LightingManager.h"
+#include "sl_simple_button_instances.h"
+#include "timers.h" // provides FreeRTOS timer support
+#include <app/clusters/identify-server/identify-server.h>
+#include <ble/BLEEndPoint.h>
+#include <lib/core/CHIPError.h>
+#include <platform/CHIPDeviceLayer.h>
+
+/**********************************************************
+ * Defines
+ *********************************************************/
+
+// Application-defined error codes in the CHIP_ERROR space.
+#define APP_ERROR_EVENT_QUEUE_FAILED CHIP_APPLICATION_ERROR(0x01)
+#define APP_ERROR_CREATE_TASK_FAILED CHIP_APPLICATION_ERROR(0x02)
+#define APP_ERROR_UNHANDLED_EVENT CHIP_APPLICATION_ERROR(0x03)
+#define APP_ERROR_CREATE_TIMER_FAILED CHIP_APPLICATION_ERROR(0x04)
+#define APP_ERROR_START_TIMER_FAILED CHIP_APPLICATION_ERROR(0x05)
+#define APP_ERROR_STOP_TIMER_FAILED CHIP_APPLICATION_ERROR(0x06)
+
+/**********************************************************
+ * AppTask Declaration
+ *********************************************************/
+
+class AppTask : public BaseApplication
+{
+
+public:
+    AppTask() = default;
+
+    static AppTask & GetAppTask() { return sAppTask; }
+
+    /**
+     * @brief AppTask task main loop function
+     *
+     * @param pvParameter FreeRTOS task parameter
+     */
+    static void AppTaskMain(void * pvParameter);
+
+    CHIP_ERROR StartAppTask();
+
+    /**
+     * @brief Event handler when a button is pressed
+     * Function posts an event for button processing
+     *
+     * @param buttonHandle APP_LIGHT_SWITCH or APP_FUNCTION_BUTTON
+     * @param btnAction button action - SL_SIMPLE_BUTTON_PRESSED,
+     *                  SL_SIMPLE_BUTTON_RELEASED or SL_SIMPLE_BUTTON_DISABLED
+     */
+    void ButtonEventHandler(const sl_button_t * buttonHandle, uint8_t btnAction) override;
+
+    /**
+     * @brief Callback called by the identify-server when an identify command is received
+     *
+     * @param identify identify structure the command applies on
+     */
+    static void OnIdentifyStart(Identify * identify);
+
+    /**
+     * @brief Callback called by the identify-server when an identify command is stopped or finished
+     *
+     * @param identify identify structure the command applies on
+     */
+    static void OnIdentifyStop(Identify * identify);
+
+    void PostLightActionRequest(int32_t aActor, LightingManager::Action_t aAction);
+
+private:
+    static AppTask sAppTask;
+
+    static void ActionInitiated(LightingManager::Action_t aAction, int32_t aActor);
+    static void ActionCompleted(LightingManager::Action_t aAction);
+    static void LightActionEventHandler(AppEvent * aEvent);
+
+    static void UpdateClusterState(intptr_t context);
+
+    /**
+     * @brief AppTask initialisation function
+     *
+     * @return CHIP_ERROR
+     */
+    CHIP_ERROR Init();
+
+    /**
+     * @brief PB0 Button event processing function
+     *        Press and hold will trigger a factory reset timer start
+     *        Press and release will restart BLEAdvertising if not commisionned
+     *
+     * @param aEvent button event being processed
+     */
+    static void ButtonHandler(AppEvent * aEvent);
+
+    /**
+     * @brief PB1 Button event processing function
+     *        Function triggers a switch action sent to the CHIP task
+     *
+     * @param aEvent button event being processed
+     */
+    static void SwitchActionEventHandler(AppEvent * aEvent);
+};
diff --git a/examples/lighting-app/silabs/SiWx917/include/CHIPProjectConfig.h b/examples/lighting-app/silabs/SiWx917/include/CHIPProjectConfig.h
new file mode 100644
index 0000000..4b3d8f5
--- /dev/null
+++ b/examples/lighting-app/silabs/SiWx917/include/CHIPProjectConfig.h
@@ -0,0 +1,135 @@
+/*
+ *
+ *    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.
+ */
+
+/**
+ *    @file
+ *          Example project configuration file for CHIP.
+ *
+ *          This is a place to put application or project-specific overrides
+ *          to the default configuration values for general CHIP features.
+ *
+ */
+
+#pragma once
+
+// Use a default pairing code if one hasn't been provisioned in flash.
+#ifndef CHIP_DEVICE_CONFIG_USE_TEST_SETUP_PIN_CODE
+#define CHIP_DEVICE_CONFIG_USE_TEST_SETUP_PIN_CODE 20202021
+#endif
+
+#ifndef CHIP_DEVICE_CONFIG_USE_TEST_SETUP_DISCRIMINATOR
+#define CHIP_DEVICE_CONFIG_USE_TEST_SETUP_DISCRIMINATOR 0xF00
+#endif
+
+// For convenience, Chip Security Test Mode can be enabled and the
+// requirement for authentication in various protocols can be disabled.
+//
+//    WARNING: These options make it possible to circumvent basic Chip security functionality,
+//    including message encryption. Because of this they MUST NEVER BE ENABLED IN PRODUCTION BUILDS.
+//
+#define CHIP_CONFIG_SECURITY_TEST_MODE 0
+
+/**
+ * CHIP_DEVICE_CONFIG_DEVICE_VENDOR_ID
+ *
+ * 0xFFF1: Test vendor
+ */
+#define CHIP_DEVICE_CONFIG_DEVICE_VENDOR_ID 0xFFF1
+
+/**
+ * CHIP_DEVICE_CONFIG_DEVICE_PRODUCT_ID
+ *
+ * 0x8005: example lighting app
+ */
+#define CHIP_DEVICE_CONFIG_DEVICE_PRODUCT_ID 0x8005
+
+/**
+ * CHIP_DEVICE_CONFIG_DEVICE_HARDWARE_VERSION
+ *
+ * The hardware version number assigned to device or product by the device vendor.  This
+ * number is scoped to the device product id, and typically corresponds to a revision of the
+ * physical device, a change to its packaging, and/or a change to its marketing presentation.
+ * This value is generally *not* incremented for device software versions.
+ */
+#define CHIP_DEVICE_CONFIG_DEVICE_HARDWARE_VERSION 1
+
+/**
+ * CHIP_DEVICE_CONFIG_DEVICE_SOFTWARE_VERSION_STRING
+ *
+ * A string identifying the software version running on the device.
+ * CHIP service currently expects the software version to be in the format
+ * {MAJOR_VERSION}.0d{MINOR_VERSION}
+ */
+#ifndef CHIP_DEVICE_CONFIG_DEVICE_SOFTWARE_VERSION_STRING
+#define CHIP_DEVICE_CONFIG_DEVICE_SOFTWARE_VERSION_STRING "0.1ALPHA"
+#endif
+
+/**
+ * CHIP_DEVICE_CONFIG_DEVICE_SOFTWARE_VERSION
+ *
+ * A uint32_t identifying the software version running on the device.
+ */
+/* The SoftwareVersion attribute of the Basic cluster. */
+#ifndef CHIP_DEVICE_CONFIG_DEVICE_SOFTWARE_VERSION
+#define CHIP_DEVICE_CONFIG_DEVICE_SOFTWARE_VERSION 0x0001
+#endif
+
+/**
+ * CHIP_DEVICE_CONFIG_ENABLE_CHIPOBLE
+ *
+ * Enable support for Chip-over-BLE (CHIPoBLE).
+ */
+#define CHIP_DEVICE_CONFIG_ENABLE_CHIPOBLE 1
+
+/**
+ * CHIP_DEVICE_CONFIG_TEST_SERIAL_NUMBER
+ *
+ * Enables the use of a hard-coded default serial number if none
+ * is found in Chip NV storage.
+ */
+#define CHIP_DEVICE_CONFIG_TEST_SERIAL_NUMBER "TEST_SN"
+
+/**
+ * CHIP_CONFIG_EVENT_LOGGING_UTC_TIMESTAMPS
+ *
+ * Enable recording UTC timestamps.
+ */
+#define CHIP_CONFIG_EVENT_LOGGING_UTC_TIMESTAMPS 1
+
+/**
+ * CHIP_DEVICE_CONFIG_EVENT_LOGGING_DEBUG_BUFFER_SIZE
+ *
+ * A size, in bytes, of the individual debug event logging buffer.
+ */
+#define CHIP_DEVICE_CONFIG_EVENT_LOGGING_DEBUG_BUFFER_SIZE (512)
+
+/**
+ *  @def CHIP_CONFIG_MRP_LOCAL_ACTIVE_RETRY_INTERVAL
+ *
+ *  @brief
+ *    Active retransmit interval, or time to wait before retransmission after
+ *    subsequent failures in milliseconds.
+ *
+ *  This is the default value, that might be adjusted by end device depending on its
+ *  needs (e.g. sleeping period) using Service Discovery TXT record CRA key.
+ *
+ */
+#define CHIP_CONFIG_MRP_LOCAL_ACTIVE_RETRY_INTERVAL (2000_ms32)
+
+#define CHIP_DEVICE_CONFIG_ENABLE_EXTENDED_DISCOVERY 1
diff --git a/examples/lighting-app/silabs/SiWx917/include/LightingManager.h b/examples/lighting-app/silabs/SiWx917/include/LightingManager.h
new file mode 100644
index 0000000..6d286fa
--- /dev/null
+++ b/examples/lighting-app/silabs/SiWx917/include/LightingManager.h
@@ -0,0 +1,90 @@
+/*
+ *
+ *    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.
+ */
+
+#pragma once
+
+#include <stdbool.h>
+#include <stdint.h>
+
+#include "AppEvent.h"
+
+#include "FreeRTOS.h"
+#include "timers.h" // provides FreeRTOS timer support
+#include <app/clusters/on-off-server/on-off-server.h>
+
+#include <lib/core/CHIPError.h>
+
+class LightingManager
+{
+public:
+    enum Action_t
+    {
+        ON_ACTION = 0,
+        OFF_ACTION,
+
+        INVALID_ACTION
+    } Action;
+
+    enum State_t
+    {
+        kState_OffInitiated = 0,
+        kState_OffCompleted,
+        kState_OnInitiated,
+        kState_OnCompleted,
+    } State;
+
+    CHIP_ERROR Init();
+    bool IsLightOn();
+    void EnableAutoTurnOff(bool aOn);
+    void SetAutoTurnOffDuration(uint32_t aDurationInSecs);
+    bool IsActionInProgress();
+    bool InitiateAction(int32_t aActor, Action_t aAction);
+
+    typedef void (*Callback_fn_initiated)(Action_t, int32_t aActor);
+    typedef void (*Callback_fn_completed)(Action_t);
+    void SetCallbacks(Callback_fn_initiated aActionInitiated_CB, Callback_fn_completed aActionCompleted_CB);
+
+    static void OnTriggerOffWithEffect(OnOffEffect * effect);
+
+private:
+    friend LightingManager & LightMgr(void);
+    State_t mState;
+
+    Callback_fn_initiated mActionInitiated_CB;
+    Callback_fn_completed mActionCompleted_CB;
+
+    bool mAutoTurnOff;
+    uint32_t mAutoTurnOffDuration;
+    bool mAutoTurnOffTimerArmed;
+    bool mOffEffectArmed;
+
+    void CancelTimer(void);
+    void StartTimer(uint32_t aTimeoutMs);
+
+    static void TimerEventHandler(TimerHandle_t xTimer);
+    static void AutoTurnOffTimerEventHandler(AppEvent * aEvent);
+    static void ActuatorMovementTimerEventHandler(AppEvent * aEvent);
+    static void OffEffectTimerEventHandler(AppEvent * aEvent);
+
+    static LightingManager sLight;
+};
+
+inline LightingManager & LightMgr(void)
+{
+    return LightingManager::sLight;
+}
diff --git a/examples/lighting-app/silabs/SiWx917/src/AppTask.cpp b/examples/lighting-app/silabs/SiWx917/src/AppTask.cpp
new file mode 100644
index 0000000..850649d
--- /dev/null
+++ b/examples/lighting-app/silabs/SiWx917/src/AppTask.cpp
@@ -0,0 +1,333 @@
+/*
+ *
+ *    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 "AppTask.h"
+#include "AppConfig.h"
+#include "AppEvent.h"
+
+#ifdef ENABLE_WSTK_LEDS
+#include "LEDWidget.h"
+#include "sl_simple_led_instances.h"
+#endif // ENABLE_WSTK_LEDS
+
+#include <app-common/zap-generated/attribute-id.h>
+#include <app-common/zap-generated/attribute-type.h>
+#include <app-common/zap-generated/cluster-id.h>
+#include <app/clusters/identify-server/identify-server.h>
+#include <app/clusters/on-off-server/on-off-server.h>
+#include <app/server/OnboardingCodesUtil.h>
+#include <app/server/Server.h>
+#include <app/util/attribute-storage.h>
+
+#include <assert.h>
+
+#include <setup_payload/QRCodeSetupPayloadGenerator.h>
+#include <setup_payload/SetupPayload.h>
+
+#include <lib/support/CodeUtils.h>
+
+#include <platform/CHIPDeviceLayer.h>
+
+#ifdef ENABLE_WSTK_LEDS
+#define SYSTEM_STATE_LED &sl_led_led0
+#define LIGHT_LED &sl_led_led1
+#endif // ENABLE_WSTK_LEDS
+
+#define APP_FUNCTION_BUTTON &sl_button_btn0
+#define APP_LIGHT_SWITCH &sl_button_btn1
+
+using namespace chip;
+using namespace ::chip::DeviceLayer;
+
+namespace {
+
+#ifdef ENABLE_WSTK_LEDS
+LEDWidget sLightLED;
+#endif // ENABLE_WSTK_LEDS
+
+EmberAfIdentifyEffectIdentifier sIdentifyEffect = EMBER_ZCL_IDENTIFY_EFFECT_IDENTIFIER_STOP_EFFECT;
+
+/**********************************************************
+ * Identify Callbacks
+ *********************************************************/
+
+namespace {
+void OnTriggerIdentifyEffectCompleted(chip::System::Layer * systemLayer, void * appState)
+{
+    ChipLogProgress(Zcl, "Trigger Identify Complete");
+    sIdentifyEffect = EMBER_ZCL_IDENTIFY_EFFECT_IDENTIFIER_STOP_EFFECT;
+
+#if CHIP_DEVICE_CONFIG_ENABLE_SED == 1
+    AppTask::GetAppTask().StopStatusLEDTimer();
+#endif
+}
+} // namespace
+
+void OnTriggerIdentifyEffect(Identify * identify)
+{
+    sIdentifyEffect = identify->mCurrentEffectIdentifier;
+
+    if (identify->mCurrentEffectIdentifier == EMBER_ZCL_IDENTIFY_EFFECT_IDENTIFIER_CHANNEL_CHANGE)
+    {
+        ChipLogProgress(Zcl, "IDENTIFY_EFFECT_IDENTIFIER_CHANNEL_CHANGE - Not supported, use effect varriant %d",
+                        identify->mEffectVariant);
+        sIdentifyEffect = static_cast<EmberAfIdentifyEffectIdentifier>(identify->mEffectVariant);
+    }
+
+#if CHIP_DEVICE_CONFIG_ENABLE_SED == 1
+    AppTask::GetAppTask().StartStatusLEDTimer();
+#endif
+
+    switch (sIdentifyEffect)
+    {
+    case EMBER_ZCL_IDENTIFY_EFFECT_IDENTIFIER_BLINK:
+    case EMBER_ZCL_IDENTIFY_EFFECT_IDENTIFIER_BREATHE:
+    case EMBER_ZCL_IDENTIFY_EFFECT_IDENTIFIER_OKAY:
+        (void) chip::DeviceLayer::SystemLayer().StartTimer(chip::System::Clock::Seconds16(5), OnTriggerIdentifyEffectCompleted,
+                                                           identify);
+        break;
+    case EMBER_ZCL_IDENTIFY_EFFECT_IDENTIFIER_FINISH_EFFECT:
+        (void) chip::DeviceLayer::SystemLayer().CancelTimer(OnTriggerIdentifyEffectCompleted, identify);
+        (void) chip::DeviceLayer::SystemLayer().StartTimer(chip::System::Clock::Seconds16(1), OnTriggerIdentifyEffectCompleted,
+                                                           identify);
+        break;
+    case EMBER_ZCL_IDENTIFY_EFFECT_IDENTIFIER_STOP_EFFECT:
+        (void) chip::DeviceLayer::SystemLayer().CancelTimer(OnTriggerIdentifyEffectCompleted, identify);
+        sIdentifyEffect = EMBER_ZCL_IDENTIFY_EFFECT_IDENTIFIER_STOP_EFFECT;
+        break;
+    default:
+        ChipLogProgress(Zcl, "No identifier effect");
+    }
+}
+
+Identify gIdentify = {
+    chip::EndpointId{ 1 },
+    AppTask::GetAppTask().OnIdentifyStart,
+    AppTask::GetAppTask().OnIdentifyStop,
+    EMBER_ZCL_IDENTIFY_IDENTIFY_TYPE_VISIBLE_LED,
+    OnTriggerIdentifyEffect,
+};
+
+} // namespace
+
+using namespace chip::TLV;
+using namespace ::chip::DeviceLayer;
+
+AppTask AppTask::sAppTask;
+
+CHIP_ERROR AppTask::Init()
+{
+    CHIP_ERROR err = CHIP_NO_ERROR;
+#ifdef DISPLAY_ENABLED
+    GetLCD().Init((uint8_t *) "Lighting-App");
+#endif
+
+    err = BaseApplication::Init(&gIdentify);
+    if (err != CHIP_NO_ERROR)
+    {
+        SILABS_LOG("BaseApplication::Init() failed");
+        appError(err);
+    }
+
+    err = LightMgr().Init();
+    if (err != CHIP_NO_ERROR)
+    {
+        SILABS_LOG("LightMgr::Init() failed");
+        appError(err);
+    }
+
+    LightMgr().SetCallbacks(ActionInitiated, ActionCompleted);
+
+#ifdef ENABLE_WSTK_LEDS
+    sLightLED.Init(LIGHT_LED);
+    sLightLED.Set(LightMgr().IsLightOn());
+#endif // ENABLE_WSTK_LEDS
+
+    return err;
+}
+
+CHIP_ERROR AppTask::StartAppTask()
+{
+    return BaseApplication::StartAppTask(AppTaskMain);
+}
+
+void AppTask::AppTaskMain(void * pvParameter)
+{
+    AppEvent event;
+    QueueHandle_t sAppEventQueue = *(static_cast<QueueHandle_t *>(pvParameter));
+
+    CHIP_ERROR err = sAppTask.Init();
+    if (err != CHIP_NO_ERROR)
+    {
+        SILABS_LOG("AppTask.Init() failed");
+        appError(err);
+    }
+
+#if !(defined(CHIP_DEVICE_CONFIG_ENABLE_SED) && CHIP_DEVICE_CONFIG_ENABLE_SED)
+    sAppTask.StartStatusLEDTimer();
+#endif
+
+    SILABS_LOG("App Task started");
+
+    while (true)
+    {
+        BaseType_t eventReceived = xQueueReceive(sAppEventQueue, &event, pdMS_TO_TICKS(10));
+        while (eventReceived == pdTRUE)
+        {
+            sAppTask.DispatchEvent(&event);
+            eventReceived = xQueueReceive(sAppEventQueue, &event, 0);
+        }
+    }
+}
+
+void AppTask::OnIdentifyStart(Identify * identify)
+{
+    ChipLogProgress(Zcl, "onIdentifyStart");
+
+#if CHIP_DEVICE_CONFIG_ENABLE_SED == 1
+    sAppTask.StartStatusLEDTimer();
+#endif
+}
+
+void AppTask::OnIdentifyStop(Identify * identify)
+{
+    ChipLogProgress(Zcl, "onIdentifyStop");
+
+#if CHIP_DEVICE_CONFIG_ENABLE_SED == 1
+    sAppTask.StopStatusLEDTimer();
+#endif
+}
+
+void AppTask::LightActionEventHandler(AppEvent * aEvent)
+{
+    bool initiated = false;
+    LightingManager::Action_t action;
+    int32_t actor;
+    CHIP_ERROR err = CHIP_NO_ERROR;
+
+    if (aEvent->Type == AppEvent::kEventType_Light)
+    {
+        action = static_cast<LightingManager::Action_t>(aEvent->LightEvent.Action);
+        actor  = aEvent->LightEvent.Actor;
+    }
+    else if (aEvent->Type == AppEvent::kEventType_Button)
+    {
+        action = (LightMgr().IsLightOn()) ? LightingManager::OFF_ACTION : LightingManager::ON_ACTION;
+        actor  = AppEvent::kEventType_Button;
+    }
+    else
+    {
+        err = APP_ERROR_UNHANDLED_EVENT;
+    }
+
+    if (err == CHIP_NO_ERROR)
+    {
+        initiated = LightMgr().InitiateAction(actor, action);
+
+        if (!initiated)
+        {
+            SILABS_LOG("Action is already in progress or active.");
+        }
+    }
+}
+
+void AppTask::ButtonEventHandler(const sl_button_t * buttonHandle, uint8_t btnAction)
+{
+    if (buttonHandle == NULL)
+    {
+        return;
+    }
+
+    AppEvent button_event           = {};
+    button_event.Type               = AppEvent::kEventType_Button;
+    button_event.ButtonEvent.Action = btnAction;
+
+    if (buttonHandle == APP_LIGHT_SWITCH && btnAction == SL_SIMPLE_BUTTON_PRESSED)
+    {
+        button_event.Handler = LightActionEventHandler;
+        sAppTask.PostEvent(&button_event);
+    }
+    else if (buttonHandle == APP_FUNCTION_BUTTON)
+    {
+        button_event.Handler = BaseApplication::ButtonHandler;
+        sAppTask.PostEvent(&button_event);
+    }
+}
+
+void AppTask::ActionInitiated(LightingManager::Action_t aAction, int32_t aActor)
+{
+    // Action initiated, update the light led
+    bool lightOn = aAction == LightingManager::ON_ACTION;
+    SILABS_LOG("Turning light %s", (lightOn) ? "On" : "Off")
+
+#ifdef ENABLE_WSTK_LEDS
+    sLightLED.Set(lightOn);
+#endif // ENABLE_WSTK_LEDS
+
+#ifdef DISPLAY_ENABLED
+    sAppTask.GetLCD().WriteDemoUI(lightOn);
+#endif
+
+    if (aActor == AppEvent::kEventType_Button)
+    {
+        sAppTask.mSyncClusterToButtonAction = true;
+    }
+}
+
+void AppTask::ActionCompleted(LightingManager::Action_t aAction)
+{
+    // action has been completed bon the light
+    if (aAction == LightingManager::ON_ACTION)
+    {
+        SILABS_LOG("Light ON")
+    }
+    else if (aAction == LightingManager::OFF_ACTION)
+    {
+        SILABS_LOG("Light OFF")
+    }
+
+    if (sAppTask.mSyncClusterToButtonAction)
+    {
+        chip::DeviceLayer::PlatformMgr().ScheduleWork(UpdateClusterState, reinterpret_cast<intptr_t>(nullptr));
+        sAppTask.mSyncClusterToButtonAction = false;
+    }
+}
+
+void AppTask::PostLightActionRequest(int32_t aActor, LightingManager::Action_t aAction)
+{
+    AppEvent event;
+    event.Type              = AppEvent::kEventType_Light;
+    event.LightEvent.Actor  = aActor;
+    event.LightEvent.Action = aAction;
+    event.Handler           = LightActionEventHandler;
+    PostEvent(&event);
+}
+
+void AppTask::UpdateClusterState(intptr_t context)
+{
+    uint8_t newValue = LightMgr().IsLightOn();
+
+    // write the new on/off value
+    EmberAfStatus status = OnOffServer::Instance().setOnOffValue(1, newValue, false);
+
+    if (status != EMBER_ZCL_STATUS_SUCCESS)
+    {
+        SILABS_LOG("ERR: updating on/off %x", status);
+    }
+}
diff --git a/examples/lighting-app/silabs/SiWx917/src/LightingManager.cpp b/examples/lighting-app/silabs/SiWx917/src/LightingManager.cpp
new file mode 100644
index 0000000..31a4ca0
--- /dev/null
+++ b/examples/lighting-app/silabs/SiWx917/src/LightingManager.cpp
@@ -0,0 +1,322 @@
+/*
+ *
+ *    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 "LightingManager.h"
+
+#include "AppConfig.h"
+#include "AppTask.h"
+#include <FreeRTOS.h>
+
+using namespace chip;
+using namespace ::chip::DeviceLayer;
+
+LightingManager LightingManager::sLight;
+
+TimerHandle_t sLightTimer;
+
+namespace {
+
+/**********************************************************
+ * OffWithEffect Callbacks
+ *********************************************************/
+
+OnOffEffect gEffect = {
+    chip::EndpointId{ 1 },
+    LightMgr().OnTriggerOffWithEffect,
+    EMBER_ZCL_ON_OFF_EFFECT_IDENTIFIER_DELAYED_ALL_OFF,
+    static_cast<uint8_t>(EMBER_ZCL_ON_OFF_DELAYED_ALL_OFF_EFFECT_VARIANT_FADE_TO_OFF_IN_0P8_SECONDS),
+};
+
+} // namespace
+
+CHIP_ERROR LightingManager::Init()
+{
+    // Create FreeRTOS sw timer for light timer.
+    sLightTimer = xTimerCreate("lightTmr",       // Just a text name, not used by the RTOS kernel
+                               1,                // == default timer period (mS)
+                               false,            // no timer reload (==one-shot)
+                               (void *) this,    // init timer id = light obj context
+                               TimerEventHandler // timer callback handler
+    );
+
+    if (sLightTimer == NULL)
+    {
+        SILABS_LOG("sLightTimer timer create failed");
+        return APP_ERROR_CREATE_TIMER_FAILED;
+    }
+
+    bool currentLedState;
+    // read current on/off value on endpoint one.
+    chip::DeviceLayer::PlatformMgr().LockChipStack();
+    OnOffServer::Instance().getOnOffValue(1, &currentLedState);
+    chip::DeviceLayer::PlatformMgr().UnlockChipStack();
+
+    mState                 = currentLedState ? kState_OnCompleted : kState_OffCompleted;
+    mAutoTurnOffTimerArmed = false;
+    mAutoTurnOff           = false;
+    mAutoTurnOffDuration   = 0;
+    mOffEffectArmed        = false;
+
+    return CHIP_NO_ERROR;
+}
+
+void LightingManager::SetCallbacks(Callback_fn_initiated aActionInitiated_CB, Callback_fn_completed aActionCompleted_CB)
+{
+    mActionInitiated_CB = aActionInitiated_CB;
+    mActionCompleted_CB = aActionCompleted_CB;
+}
+
+bool LightingManager::IsActionInProgress()
+{
+    return (mState == kState_OffInitiated || mState == kState_OnInitiated);
+}
+
+bool LightingManager::IsLightOn()
+{
+    return (mState == kState_OnCompleted);
+}
+
+void LightingManager::EnableAutoTurnOff(bool aOn)
+{
+    mAutoTurnOff = aOn;
+}
+
+void LightingManager::SetAutoTurnOffDuration(uint32_t aDurationInSecs)
+{
+    mAutoTurnOffDuration = aDurationInSecs;
+}
+
+bool LightingManager::InitiateAction(int32_t aActor, Action_t aAction)
+{
+    bool action_initiated = false;
+    State_t new_state;
+
+    // Initiate Turn On/Off Action only when the previous one is complete.
+    if (((mState == kState_OffCompleted) || mOffEffectArmed) && aAction == ON_ACTION)
+    {
+        action_initiated = true;
+
+        new_state = kState_OnInitiated;
+    }
+    else if (mState == kState_OnCompleted && aAction == OFF_ACTION && mOffEffectArmed == false)
+    {
+        action_initiated = true;
+
+        new_state = kState_OffInitiated;
+    }
+
+    if (action_initiated)
+    {
+        if (mAutoTurnOffTimerArmed && new_state == kState_OffInitiated)
+        {
+            // If auto turn off timer has been armed and someone initiates turning off,
+            // cancel the timer and continue as normal.
+            mAutoTurnOffTimerArmed = false;
+
+            CancelTimer();
+        }
+
+        if (mOffEffectArmed && new_state == kState_OnInitiated)
+        {
+            CancelTimer();
+            mOffEffectArmed = false;
+        }
+
+        StartTimer(ACTUATOR_MOVEMENT_PERIOS_MS);
+
+        // Since the timer started successfully, update the state and trigger callback
+        mState = new_state;
+
+        if (mActionInitiated_CB)
+        {
+            mActionInitiated_CB(aAction, aActor);
+        }
+    }
+
+    return action_initiated;
+}
+
+void LightingManager::StartTimer(uint32_t aTimeoutMs)
+{
+    if (xTimerIsTimerActive(sLightTimer))
+    {
+        SILABS_LOG("app timer already started!");
+        CancelTimer();
+    }
+
+    // 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(sLightTimer, (aTimeoutMs / portTICK_PERIOD_MS), 100) != pdPASS)
+    {
+        SILABS_LOG("sLightTimer timer start() failed");
+        appError(APP_ERROR_START_TIMER_FAILED);
+    }
+}
+
+void LightingManager::CancelTimer(void)
+{
+    if (xTimerStop(sLightTimer, 0) == pdFAIL)
+    {
+        SILABS_LOG("sLightTimer stop() failed");
+        appError(APP_ERROR_STOP_TIMER_FAILED);
+    }
+}
+
+void LightingManager::TimerEventHandler(TimerHandle_t xTimer)
+{
+    // Get light obj context from timer id.
+    LightingManager * light = static_cast<LightingManager *>(pvTimerGetTimerID(xTimer));
+
+    // The timer event handler will be called in the context of the timer task
+    // once sLightTimer expires. Post an event to apptask queue with the actual handler
+    // so that the event can be handled in the context of the apptask.
+    AppEvent event;
+    event.Type               = AppEvent::kEventType_Timer;
+    event.TimerEvent.Context = light;
+    if (light->mAutoTurnOffTimerArmed)
+    {
+        event.Handler = AutoTurnOffTimerEventHandler;
+    }
+    else if (light->mOffEffectArmed)
+    {
+        event.Handler = OffEffectTimerEventHandler;
+    }
+    else
+    {
+        event.Handler = ActuatorMovementTimerEventHandler;
+    }
+    AppTask::GetAppTask().PostEvent(&event);
+}
+
+void LightingManager::AutoTurnOffTimerEventHandler(AppEvent * aEvent)
+{
+    LightingManager * light = static_cast<LightingManager *>(aEvent->TimerEvent.Context);
+    int32_t actor           = AppEvent::kEventType_Timer;
+
+    // Make sure auto turn off timer is still armed.
+    if (!light->mAutoTurnOffTimerArmed)
+    {
+        return;
+    }
+
+    light->mAutoTurnOffTimerArmed = false;
+
+    SILABS_LOG("Auto Turn Off has been triggered!");
+
+    light->InitiateAction(actor, OFF_ACTION);
+}
+
+void LightingManager::OffEffectTimerEventHandler(AppEvent * aEvent)
+{
+    LightingManager * light = static_cast<LightingManager *>(aEvent->TimerEvent.Context);
+    int32_t actor           = AppEvent::kEventType_Timer;
+
+    // Make sure auto turn off timer is still armed.
+    if (!light->mOffEffectArmed)
+    {
+        return;
+    }
+
+    light->mOffEffectArmed = false;
+
+    SILABS_LOG("OffEffect completed");
+
+    light->InitiateAction(actor, OFF_ACTION);
+}
+
+void LightingManager::ActuatorMovementTimerEventHandler(AppEvent * aEvent)
+{
+    Action_t actionCompleted = INVALID_ACTION;
+
+    LightingManager * light = static_cast<LightingManager *>(aEvent->TimerEvent.Context);
+
+    if (light->mState == kState_OffInitiated)
+    {
+        light->mState   = kState_OffCompleted;
+        actionCompleted = OFF_ACTION;
+    }
+    else if (light->mState == kState_OnInitiated)
+    {
+        light->mState   = kState_OnCompleted;
+        actionCompleted = ON_ACTION;
+    }
+
+    if (actionCompleted != INVALID_ACTION)
+    {
+        if (light->mActionCompleted_CB)
+        {
+            light->mActionCompleted_CB(actionCompleted);
+        }
+
+        if (light->mAutoTurnOff && actionCompleted == ON_ACTION)
+        {
+            // Start the timer for auto turn off
+            light->StartTimer(light->mAutoTurnOffDuration * 1000);
+
+            light->mAutoTurnOffTimerArmed = true;
+
+            SILABS_LOG("Auto Turn off enabled. Will be triggered in %u seconds", light->mAutoTurnOffDuration);
+        }
+    }
+}
+
+void LightingManager::OnTriggerOffWithEffect(OnOffEffect * effect)
+{
+    chip::app::Clusters::OnOff::OnOffEffectIdentifier effectId = effect->mEffectIdentifier;
+    uint8_t effectVariant                                      = effect->mEffectVariant;
+    uint32_t offEffectDuration                                 = 0;
+
+    // Temporary print outs and delay to test OffEffect behaviour
+    // Until dimming is supported for dev boards.
+    if (effectId == EMBER_ZCL_ON_OFF_EFFECT_IDENTIFIER_DELAYED_ALL_OFF)
+    {
+        if (effectVariant == EMBER_ZCL_ON_OFF_DELAYED_ALL_OFF_EFFECT_VARIANT_FADE_TO_OFF_IN_0P8_SECONDS)
+        {
+            offEffectDuration = 800;
+            ChipLogProgress(Zcl, "EMBER_ZCL_ON_OFF_DELAYED_ALL_OFF_EFFECT_VARIANT_FADE_TO_OFF_IN_0P8_SECONDS");
+        }
+        else if (effectVariant == EMBER_ZCL_ON_OFF_DELAYED_ALL_OFF_EFFECT_VARIANT_NO_FADE)
+        {
+            offEffectDuration = 800;
+            ChipLogProgress(Zcl, "EMBER_ZCL_ON_OFF_DELAYED_ALL_OFF_EFFECT_VARIANT_NO_FADE");
+        }
+        else if (effectVariant ==
+                 EMBER_ZCL_ON_OFF_DELAYED_ALL_OFF_EFFECT_VARIANT_50_PERCENT_DIM_DOWN_IN_0P8_SECONDS_THEN_FADE_TO_OFF_IN_12_SECONDS)
+        {
+            offEffectDuration = 12800;
+            ChipLogProgress(Zcl,
+                            "EMBER_ZCL_ON_OFF_DELAYED_ALL_OFF_EFFECT_VARIANT_50_PERCENT_DIM_DOWN_IN_0P8_SECONDS_THEN_FADE_TO_OFF_"
+                            "IN_12_SECONDS");
+        }
+    }
+    else if (effectId == EMBER_ZCL_ON_OFF_EFFECT_IDENTIFIER_DYING_LIGHT)
+    {
+        if (effectVariant ==
+            EMBER_ZCL_ON_OFF_DYING_LIGHT_EFFECT_VARIANT_20_PERCENTER_DIM_UP_IN_0P5_SECONDS_THEN_FADE_TO_OFF_IN_1_SECOND)
+        {
+            offEffectDuration = 1500;
+            ChipLogProgress(
+                Zcl, "EMBER_ZCL_ON_OFF_DYING_LIGHT_EFFECT_VARIANT_20_PERCENTER_DIM_UP_IN_0P5_SECONDS_THEN_FADE_TO_OFF_IN_1_SECOND");
+        }
+    }
+
+    LightMgr().mOffEffectArmed = true;
+    LightMgr().StartTimer(offEffectDuration);
+}
diff --git a/examples/lighting-app/silabs/SiWx917/src/ZclCallbacks.cpp b/examples/lighting-app/silabs/SiWx917/src/ZclCallbacks.cpp
new file mode 100644
index 0000000..cfbcbc8
--- /dev/null
+++ b/examples/lighting-app/silabs/SiWx917/src/ZclCallbacks.cpp
@@ -0,0 +1,91 @@
+/*
+ *
+ *    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.
+ */
+
+/**
+ * @file
+ *   This file implements the handler for data model messages.
+ */
+
+#include "AppConfig.h"
+#include "LightingManager.h"
+
+#include <app-common/zap-generated/ids/Attributes.h>
+#include <app-common/zap-generated/ids/Clusters.h>
+#include <app/ConcreteAttributePath.h>
+#include <lib/support/logging/CHIPLogging.h>
+
+using namespace ::chip;
+using namespace ::chip::app::Clusters;
+
+void MatterPostAttributeChangeCallback(const chip::app::ConcreteAttributePath & attributePath, uint8_t type, uint16_t size,
+                                       uint8_t * value)
+{
+    ClusterId clusterId     = attributePath.mClusterId;
+    AttributeId attributeId = attributePath.mAttributeId;
+    ChipLogProgress(Zcl, "Cluster callback: " ChipLogFormatMEI, ChipLogValueMEI(clusterId));
+
+    if (clusterId == OnOff::Id && attributeId == OnOff::Attributes::OnOff::Id)
+    {
+        LightMgr().InitiateAction(AppEvent::kEventType_Light, *value ? LightingManager::ON_ACTION : LightingManager::OFF_ACTION);
+    }
+    else if (clusterId == LevelControl::Id)
+    {
+        ChipLogProgress(Zcl, "Level Control attribute ID: " ChipLogFormatMEI " Type: %u Value: %u, length %u",
+                        ChipLogValueMEI(attributeId), type, *value, size);
+
+        // WIP Apply attribute change to Light
+    }
+    else if (clusterId == ColorControl::Id)
+    {
+        ChipLogProgress(Zcl, "Color Control attribute ID: " ChipLogFormatMEI " Type: %u Value: %u, length %u",
+                        ChipLogValueMEI(attributeId), type, *value, size);
+
+        // WIP Apply attribute change to Light
+    }
+    else if (clusterId == OnOffSwitchConfiguration::Id)
+    {
+        ChipLogProgress(Zcl, "OnOff Switch Configuration attribute ID: " ChipLogFormatMEI " Type: %u Value: %u, length %u",
+                        ChipLogValueMEI(attributeId), type, *value, size);
+
+        // WIP Apply attribute change to Light
+    }
+    else if (clusterId == Identify::Id)
+    {
+        ChipLogProgress(Zcl, "Identify attribute ID: " ChipLogFormatMEI " Type: %u Value: %u, length %u",
+                        ChipLogValueMEI(attributeId), type, *value, size);
+    }
+}
+
+/** @brief OnOff Cluster Init
+ *
+ * This function is called when a specific cluster is initialized. It gives the
+ * application an opportunity to take care of cluster initialization procedures.
+ * It is called exactly once for each endpoint where cluster is present.
+ *
+ * @param endpoint   Ver.: always
+ *
+ * TODO Issue #3841
+ * emberAfOnOffClusterInitCallback happens before the stack initialize the cluster
+ * attributes to the default value.
+ * The logic here expects something similar to the deprecated Plugins callback
+ * emberAfPluginOnOffClusterServerPostInitCallback.
+ *
+ */
+void emberAfOnOffClusterInitCallback(EndpointId endpoint)
+{
+    // TODO: implement any additional Cluster Server init actions
+}
diff --git a/examples/lighting-app/silabs/SiWx917/src/main.cpp b/examples/lighting-app/silabs/SiWx917/src/main.cpp
new file mode 100644
index 0000000..2594f6f
--- /dev/null
+++ b/examples/lighting-app/silabs/SiWx917/src/main.cpp
@@ -0,0 +1,84 @@
+/*
+ *
+ *    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 <AppTask.h>
+
+#include "AppConfig.h"
+#include "init_efrPlatform.h"
+#include "sl_simple_button_instances.h"
+#include "sl_system_kernel.h"
+#include <DeviceInfoProviderImpl.h>
+#include <app/server/Server.h>
+#include <credentials/DeviceAttestationCredsProvider.h>
+#include <matter_config.h>
+#ifdef EFR32_ATTESTATION_CREDENTIALS
+#include <examples/platform/silabs/SilabsDeviceAttestationCreds.h>
+#else
+#include <credentials/examples/DeviceAttestationCredsExample.h>
+#endif
+
+#define BLE_DEV_NAME "SiLabs-Light"
+using namespace ::chip;
+using namespace ::chip::Inet;
+using namespace ::chip::DeviceLayer;
+using namespace ::chip::Credentials;
+
+#define UNUSED_PARAMETER(a) (a = a)
+
+volatile int apperror_cnt;
+static chip::DeviceLayer::DeviceInfoProviderImpl gExampleDeviceInfoProvider;
+
+// ================================================================================
+// Main Code
+// ================================================================================
+int main(void)
+{
+    init_efrPlatform();
+    if (EFR32MatterConfig::InitMatter(BLE_DEV_NAME) != CHIP_NO_ERROR)
+        appError(CHIP_ERROR_INTERNAL);
+
+    gExampleDeviceInfoProvider.SetStorageDelegate(&chip::Server::GetInstance().GetPersistentStorage());
+    chip::DeviceLayer::SetDeviceInfoProvider(&gExampleDeviceInfoProvider);
+
+    chip::DeviceLayer::PlatformMgr().LockChipStack();
+    // Initialize device attestation config
+#ifdef EFR32_ATTESTATION_CREDENTIALS
+    SetDeviceAttestationCredentialsProvider(Silabs::GetSilabsDacProvider());
+#else
+    SetDeviceAttestationCredentialsProvider(Examples::GetExampleDACProvider());
+#endif
+    chip::DeviceLayer::PlatformMgr().UnlockChipStack();
+
+    SILABS_LOG("Starting App Task");
+    if (AppTask::GetAppTask().StartAppTask() != CHIP_NO_ERROR)
+        appError(CHIP_ERROR_INTERNAL);
+
+    SILABS_LOG("Starting FreeRTOS scheduler");
+    sl_system_kernel_start();
+
+    // Should never get here.
+    chip::Platform::MemoryShutdown();
+    SILABS_LOG("vTaskStartScheduler() failed");
+    appError(CHIP_ERROR_INTERNAL);
+}
+
+void sl_button_on_change(const sl_button_t * handle)
+{
+    AppTask::GetAppTask().ButtonEventHandler(handle, sl_button_get_state(handle));
+}
diff --git a/examples/lighting-app/silabs/SiWx917/third_party/connectedhomeip b/examples/lighting-app/silabs/SiWx917/third_party/connectedhomeip
new file mode 120000
index 0000000..5930783
--- /dev/null
+++ b/examples/lighting-app/silabs/SiWx917/third_party/connectedhomeip
@@ -0,0 +1 @@
+../../../../..
\ No newline at end of file
diff --git a/examples/lighting-app/silabs/SiWx917/with_pw_rpc.gni b/examples/lighting-app/silabs/SiWx917/with_pw_rpc.gni
new file mode 100644
index 0000000..40a8bb7
--- /dev/null
+++ b/examples/lighting-app/silabs/SiWx917/with_pw_rpc.gni
@@ -0,0 +1,31 @@
+# Copyright (c) 2021 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.
+
+# add this gni as import in your build args to use pigweed in the example
+# 'import("//with_pw_rpc.gni")'
+
+import("//build_overrides/chip.gni")
+import("${chip_root}/config/efr32/lib/pw_rpc/pw_rpc.gni")
+import("${chip_root}/examples/platform/silabs/efr32/args.gni")
+
+efr32_sdk_target = get_label_info(":sdk", "label_no_toolchain")
+
+chip_enable_pw_rpc = true
+chip_enable_openthread = true
+chip_build_pw_trace_lib = true
+
+cpp_standard = "gnu++17"
+
+# Light app on EFR enables tracing server
+pw_trace_BACKEND = "$dir_pw_trace_tokenized"
diff --git a/examples/platform/silabs/SiWx917/BUILD.gn b/examples/platform/silabs/SiWx917/BUILD.gn
new file mode 100644
index 0000000..dbd8473
--- /dev/null
+++ b/examples/platform/silabs/SiWx917/BUILD.gn
@@ -0,0 +1,110 @@
+# 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/efr32_sdk.gni")
+import("${chip_root}/src/lib/lib.gni")
+import("${chip_root}/src/platform/device.gni")
+import("${efr32_sdk_build_root}/efr32_sdk.gni")
+
+config("chip_examples_project_config") {
+  include_dirs = [ "project_include" ]
+
+  # Link options that provide a replacement for 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("openthread_core_config_efr32_chip_examples") {
+  if (chip_enable_openthread) {
+    sources = [ "project_include/OpenThreadConfig.h" ]
+
+    public_deps = [ "${efr32_sdk_build_root}:efr32_sdk" ]
+
+    if (use_silabs_thread_lib) {
+      public_deps += [ "${efr32_sdk_build_root}:openthread_core_config_efr32" ]
+    } else {
+      public_deps += [ "${chip_root}/third_party/openthread/platforms/efr32:openthread_core_config_efr32" ]
+    }
+
+    public_configs = [ ":chip_examples_project_config" ]
+  }
+}
+
+source_set("efr-matter-shell") {
+  if (chip_build_libshell) {
+    defines = [ "ENABLE_CHIP_SHELL" ]
+
+    sources = [ "matter_shell.cpp" ]
+    include_dirs = [ "." ]
+
+    public_deps = [
+      "${chip_root}/examples/shell/shell_common:shell_common",
+      "${chip_root}/src/lib/shell:shell",
+      "${chip_root}/src/lib/shell:shell_core",
+    ]
+  }
+}
+
+config("attestation-credentials-config") {
+  include_dirs = [ "${chip_root}" ]
+
+  defines = [
+    # Set to 1 to enable EFR32 attestation credentials
+    "EFR32_ATTESTATION_CREDENTIALS",
+  ]
+}
+
+source_set("efr32-attestation-credentials") {
+  sources = [
+    "../SilabsDeviceAttestationCreds.cpp",
+    "../SilabsDeviceAttestationCreds.h",
+  ]
+
+  public_deps = [
+    "${chip_root}/src/credentials",
+    "${chip_root}/src/platform:platform_base",
+  ]
+
+  public_configs = [ ":attestation-credentials-config" ]
+}
+
+source_set("efr32-factory-data-provider") {
+  sources = [
+    "EFR32DeviceDataProvider.cpp",
+    "EFR32DeviceDataProvider.h",
+  ]
+
+  public_deps = [
+    "${chip_root}/src/credentials",
+    "${chip_root}/src/platform:platform_base",
+    "${chip_root}/src/setup_payload",
+  ]
+
+  #public_configs = [ "" ]
+}
diff --git a/examples/platform/silabs/SiWx917/BaseApplication.cpp b/examples/platform/silabs/SiWx917/BaseApplication.cpp
new file mode 100644
index 0000000..85748b3
--- /dev/null
+++ b/examples/platform/silabs/SiWx917/BaseApplication.cpp
@@ -0,0 +1,571 @@
+/*
+ *
+ *    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.
+ */
+
+/**********************************************************
+ * Includes
+ *********************************************************/
+
+#include "AppConfig.h"
+#include "AppEvent.h"
+#include "AppTask.h"
+
+#ifdef ENABLE_WSTK_LEDS
+#include "LEDWidget.h"
+#include "sl_simple_led_instances.h"
+#endif // ENABLE_WSTK_LEDS
+
+#ifdef DISPLAY_ENABLED
+#include "lcd.h"
+#ifdef QR_CODE_ENABLED
+#include "qrcodegen.h"
+#endif // QR_CODE_ENABLED
+#endif // DISPLAY_ENABLED
+
+#include "EFR32DeviceDataProvider.h"
+#include <app-common/zap-generated/attribute-id.h>
+#include <app-common/zap-generated/attribute-type.h>
+#include <app-common/zap-generated/cluster-id.h>
+#include <app/server/OnboardingCodesUtil.h>
+#include <app/server/Server.h>
+#include <app/util/attribute-storage.h>
+#include <assert.h>
+#include <lib/support/CodeUtils.h>
+#include <platform/CHIPDeviceLayer.h>
+#include <setup_payload/QRCodeSetupPayloadGenerator.h>
+#include <setup_payload/SetupPayload.h>
+
+#if CHIP_ENABLE_OPENTHREAD
+#include <platform/OpenThread/OpenThreadUtils.h>
+#include <platform/ThreadStackManager.h>
+#include <platform/silabs/ThreadStackManagerImpl.h>
+#endif // CHIP_ENABLE_OPENTHREAD
+
+#ifdef SL_WIFI
+#include "wfx_host_events.h"
+#include <app/clusters/network-commissioning/network-commissioning.h>
+#include <platform/silabs/NetworkCommissioningWiFiDriver.h>
+#endif // SL_WIFI
+
+/**********************************************************
+ * Defines and Constants
+ *********************************************************/
+
+#define FACTORY_RESET_TRIGGER_TIMEOUT 3000
+#define FACTORY_RESET_CANCEL_WINDOW_TIMEOUT 3000
+#ifndef APP_TASK_STACK_SIZE
+#define APP_TASK_STACK_SIZE (4096)
+#endif
+#define APP_TASK_PRIORITY 2
+#define APP_EVENT_QUEUE_SIZE 10
+#define EXAMPLE_VENDOR_ID 0xcafe
+
+#ifdef ENABLE_WSTK_LEDS
+#define SYSTEM_STATE_LED &sl_led_led0
+#endif // ENABLE_WSTK_LEDS
+
+#define APP_FUNCTION_BUTTON &sl_button_btn0
+
+using namespace chip;
+using namespace ::chip::DeviceLayer;
+
+namespace {
+
+/**********************************************************
+ * Variable declarations
+ *********************************************************/
+
+TimerHandle_t sFunctionTimer; // FreeRTOS app sw timer.
+TimerHandle_t sLightTimer;
+
+TaskHandle_t sAppTaskHandle;
+QueueHandle_t sAppEventQueue;
+
+#ifdef ENABLE_WSTK_LEDS
+LEDWidget sStatusLED;
+#endif // ENABLE_WSTK_LEDS
+
+#ifdef SL_WIFI
+app::Clusters::NetworkCommissioning::Instance
+    sWiFiNetworkCommissioningInstance(0 /* Endpoint Id */, &(NetworkCommissioning::SlWiFiDriver::GetInstance()));
+#endif /* SL_WIFI */
+
+#if !(defined(CHIP_DEVICE_CONFIG_ENABLE_SED) && CHIP_DEVICE_CONFIG_ENABLE_SED)
+
+bool sIsProvisioned      = false;
+bool sIsEnabled          = false;
+bool sIsAttached         = false;
+bool sHaveBLEConnections = false;
+
+#endif // CHIP_DEVICE_CONFIG_ENABLE_SED
+
+EmberAfIdentifyEffectIdentifier sIdentifyEffect = EMBER_ZCL_IDENTIFY_EFFECT_IDENTIFIER_STOP_EFFECT;
+
+uint8_t sAppEventQueueBuffer[APP_EVENT_QUEUE_SIZE * sizeof(AppEvent)];
+StaticQueue_t sAppEventQueueStruct;
+
+StackType_t appStack[APP_TASK_STACK_SIZE / sizeof(StackType_t)];
+StaticTask_t appTaskStruct;
+
+BaseApplication::Function_t mFunction;
+bool mFunctionTimerActive;
+
+Identify * gIdentifyptr = nullptr;
+
+#ifdef DISPLAY_ENABLED
+SilabsLCD slLCD;
+#endif
+
+} // namespace
+
+/**********************************************************
+ * AppTask Definitions
+ *********************************************************/
+
+CHIP_ERROR BaseApplication::StartAppTask(TaskFunction_t taskFunction)
+{
+    sAppEventQueue = xQueueCreateStatic(APP_EVENT_QUEUE_SIZE, sizeof(AppEvent), sAppEventQueueBuffer, &sAppEventQueueStruct);
+    if (sAppEventQueue == NULL)
+    {
+        SILABS_LOG("Failed to allocate app event queue");
+        appError(APP_ERROR_EVENT_QUEUE_FAILED);
+    }
+
+    // Start App task.
+    sAppTaskHandle =
+        xTaskCreateStatic(taskFunction, APP_TASK_NAME, ArraySize(appStack), &sAppEventQueue, 1, appStack, &appTaskStruct);
+    if (sAppTaskHandle == nullptr)
+    {
+        SILABS_LOG("Failed to create app task");
+        appError(APP_ERROR_CREATE_TASK_FAILED);
+    }
+    return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR BaseApplication::Init(Identify * identifyObj)
+{
+    CHIP_ERROR err = CHIP_NO_ERROR;
+
+    if (identifyObj == nullptr)
+    {
+        SILABS_LOG("Invalid Identify Object!");
+        appError(CHIP_ERROR_INVALID_ARGUMENT);
+    }
+
+    gIdentifyptr = identifyObj;
+
+#ifdef SL_WIFI
+    /*
+     * Wait for the WiFi to be initialized
+     */
+    SILABS_LOG("APP: Wait WiFi Init");
+    while (!wfx_hw_ready())
+    {
+        vTaskDelay(10);
+    }
+    SILABS_LOG("APP: Done WiFi Init");
+    /* We will init server when we get IP */
+
+    sWiFiNetworkCommissioningInstance.Init();
+#endif
+
+    // Create FreeRTOS sw timer for Function Selection.
+    sFunctionTimer = xTimerCreate("FnTmr",                  // Just a text name, not used by the RTOS kernel
+                                  1,                        // == default timer period (mS)
+                                  false,                    // no timer reload (==one-shot)
+                                  (void *) this,            // init timer id = app task obj context
+                                  FunctionTimerEventHandler // timer callback handler
+    );
+    if (sFunctionTimer == NULL)
+    {
+        SILABS_LOG("funct timer create failed");
+        appError(APP_ERROR_CREATE_TIMER_FAILED);
+    }
+
+    // Create FreeRTOS sw timer for LED Management.
+    sLightTimer = xTimerCreate("LightTmr",            // Text Name
+                               10,                    // Default timer period (mS)
+                               true,                  // reload timer
+                               (void *) this,         // Timer Id
+                               LightTimerEventHandler // Timer callback handler
+    );
+    if (sLightTimer == NULL)
+    {
+        SILABS_LOG("Light Timer create failed");
+        appError(APP_ERROR_CREATE_TIMER_FAILED);
+    }
+
+    SILABS_LOG("Current Software Version: %s", CHIP_DEVICE_CONFIG_DEVICE_SOFTWARE_VERSION_STRING);
+
+#ifdef ENABLE_WSTK_LEDS
+    LEDWidget::InitGpio();
+    sStatusLED.Init(SYSTEM_STATE_LED);
+#endif // ENABLE_WSTK_LEDS
+
+    ConfigurationMgr().LogDeviceConfig();
+
+    // Create buffer for QR code that can fit max size and null terminator.
+    char qrCodeBuffer[chip::QRCodeBasicSetupPayloadGenerator::kMaxQRCodeBase38RepresentationLength + 1];
+    chip::MutableCharSpan QRCode(qrCodeBuffer);
+
+    if (EFR32::EFR32DeviceDataProvider::GetDeviceDataProvider().GetSetupPayload(QRCode) == CHIP_NO_ERROR)
+    {
+        // Print setup info on LCD if available
+#ifdef QR_CODE_ENABLED
+        slLCD.SetQRCode((uint8_t *) QRCode.data(), QRCode.size());
+        slLCD.ShowQRCode(true, true);
+#else
+        PrintQrCodeURL(QRCode);
+#endif // QR_CODE_ENABLED
+    }
+    else
+    {
+        SILABS_LOG("Getting QR code failed!");
+    }
+
+    return err;
+}
+
+void BaseApplication::FunctionTimerEventHandler(TimerHandle_t xTimer)
+{
+    AppEvent event;
+    event.Type               = AppEvent::kEventType_Timer;
+    event.TimerEvent.Context = (void *) xTimer;
+    event.Handler            = FunctionEventHandler;
+    PostEvent(&event);
+}
+
+void BaseApplication::FunctionEventHandler(AppEvent * aEvent)
+{
+    if (aEvent->Type != AppEvent::kEventType_Timer)
+    {
+        return;
+    }
+
+    // If we reached here, the button was held past FACTORY_RESET_TRIGGER_TIMEOUT,
+    // initiate factory reset
+    if (mFunctionTimerActive && mFunction == kFunction_StartBleAdv)
+    {
+        SILABS_LOG("Factory Reset Triggered. Release button within %ums to cancel.", FACTORY_RESET_CANCEL_WINDOW_TIMEOUT);
+
+        // Start timer for FACTORY_RESET_CANCEL_WINDOW_TIMEOUT to allow user to
+        // cancel, if required.
+        StartFunctionTimer(FACTORY_RESET_CANCEL_WINDOW_TIMEOUT);
+
+#if CHIP_DEVICE_CONFIG_ENABLE_SED == 1
+        StartStatusLEDTimer();
+#endif // CHIP_DEVICE_CONFIG_ENABLE_SED
+
+        mFunction = kFunction_FactoryReset;
+
+#ifdef ENABLE_WSTK_LEDS
+        // Turn off all LEDs before starting blink to make sure blink is
+        // co-ordinated.
+        sStatusLED.Set(false);
+        sStatusLED.Blink(500);
+#endif // ENABLE_WSTK_LEDS
+    }
+    else if (mFunctionTimerActive && mFunction == kFunction_FactoryReset)
+    {
+        // Actually trigger Factory Reset
+        mFunction = kFunction_NoneSelected;
+
+#if CHIP_DEVICE_CONFIG_ENABLE_SED == 1
+        StopStatusLEDTimer();
+#endif // CHIP_DEVICE_CONFIG_ENABLE_SED
+
+        chip::Server::GetInstance().ScheduleFactoryReset();
+    }
+}
+
+void BaseApplication::LightEventHandler()
+{
+    // Collect connectivity and configuration state from the CHIP stack. Because
+    // the CHIP event loop is being run in a separate task, the stack must be
+    // locked while these values are queried.  However we use a non-blocking
+    // lock request (TryLockCHIPStack()) to avoid blocking other UI activities
+    // when the CHIP task is busy (e.g. with a long crypto operation).
+#if !(defined(CHIP_DEVICE_CONFIG_ENABLE_SED) && CHIP_DEVICE_CONFIG_ENABLE_SED)
+    if (PlatformMgr().TryLockChipStack())
+    {
+#ifdef SL_WIFI
+        sIsProvisioned = ConnectivityMgr().IsWiFiStationProvisioned();
+        sIsEnabled     = ConnectivityMgr().IsWiFiStationEnabled();
+        sIsAttached    = ConnectivityMgr().IsWiFiStationConnected();
+#endif /* SL_WIFI */
+#if CHIP_ENABLE_OPENTHREAD
+        sIsProvisioned = ConnectivityMgr().IsThreadProvisioned();
+        sIsEnabled     = ConnectivityMgr().IsThreadEnabled();
+        sIsAttached    = ConnectivityMgr().IsThreadAttached();
+#endif /* CHIP_ENABLE_OPENTHREAD */
+        sHaveBLEConnections = (ConnectivityMgr().NumBLEConnections() != 0);
+        PlatformMgr().UnlockChipStack();
+    }
+#endif // CHIP_DEVICE_CONFIG_ENABLE_SED
+
+    // Update the status LED if factory reset has not been initiated.
+    //
+    // If system has "full connectivity", keep the LED On constantly.
+    //
+    // If thread and service provisioned, but not attached to the thread network
+    // yet OR no connectivity to the service OR subscriptions are not fully
+    // established THEN blink the LED Off for a short period of time.
+    //
+    // If the system has ble connection(s) uptill the stage above, THEN blink
+    // the LEDs at an even rate of 100ms.
+    //
+    // Otherwise, blink the LED ON for a very short time.
+    if (mFunction != kFunction_FactoryReset)
+    {
+        if ((gIdentifyptr != nullptr) && (gIdentifyptr->mActive))
+        {
+#ifdef ENABLE_WSTK_LEDS
+            sStatusLED.Blink(250, 250);
+#endif // ENABLE_WSTK_LEDS
+        }
+        else if (sIdentifyEffect != EMBER_ZCL_IDENTIFY_EFFECT_IDENTIFIER_STOP_EFFECT)
+        {
+            if (sIdentifyEffect == EMBER_ZCL_IDENTIFY_EFFECT_IDENTIFIER_BLINK)
+            {
+#ifdef ENABLE_WSTK_LEDS
+                sStatusLED.Blink(50, 50);
+#endif // ENABLE_WSTK_LEDS
+            }
+            if (sIdentifyEffect == EMBER_ZCL_IDENTIFY_EFFECT_IDENTIFIER_BREATHE)
+            {
+#ifdef ENABLE_WSTK_LEDS
+                sStatusLED.Blink(1000, 1000);
+#endif // ENABLE_WSTK_LEDS
+            }
+            if (sIdentifyEffect == EMBER_ZCL_IDENTIFY_EFFECT_IDENTIFIER_OKAY)
+            {
+#ifdef ENABLE_WSTK_LEDS
+                sStatusLED.Blink(300, 700);
+#endif // ENABLE_WSTK_LEDS
+            }
+        }
+#if !(defined(CHIP_DEVICE_CONFIG_ENABLE_SED) && CHIP_DEVICE_CONFIG_ENABLE_SED)
+        else if (sIsProvisioned && sIsEnabled)
+        {
+            if (sIsAttached)
+            {
+#ifdef ENABLE_WSTK_LEDS
+                sStatusLED.Set(true);
+#endif // ENABLE_WSTK_LEDS
+            }
+            else
+            {
+#ifdef ENABLE_WSTK_LEDS
+                sStatusLED.Blink(950, 50);
+#endif
+            }
+        }
+        else if (sHaveBLEConnections)
+        {
+#ifdef ENABLE_WSTK_LEDS
+            sStatusLED.Blink(100, 100);
+#endif // ENABLE_WSTK_LEDS
+        }
+        else
+        {
+#ifdef ENABLE_WSTK_LEDS
+            sStatusLED.Blink(50, 950);
+#endif // ENABLE_WSTK_LEDS
+        }
+#endif // CHIP_DEVICE_CONFIG_ENABLE_SED
+    }
+
+#ifdef ENABLE_WSTK_LEDS
+    sStatusLED.Animate();
+#endif // ENABLE_WSTK_LEDS
+}
+
+void BaseApplication::ButtonHandler(AppEvent * aEvent)
+{
+    // To trigger software update: press the APP_FUNCTION_BUTTON button briefly (<
+    // FACTORY_RESET_TRIGGER_TIMEOUT) To initiate factory reset: press the
+    // APP_FUNCTION_BUTTON for FACTORY_RESET_TRIGGER_TIMEOUT +
+    // FACTORY_RESET_CANCEL_WINDOW_TIMEOUT All LEDs start blinking after
+    // FACTORY_RESET_TRIGGER_TIMEOUT to signal factory reset has been initiated.
+    // To cancel factory reset: release the APP_FUNCTION_BUTTON once all LEDs
+    // start blinking within the FACTORY_RESET_CANCEL_WINDOW_TIMEOUT
+    if (aEvent->ButtonEvent.Action == SL_SIMPLE_BUTTON_PRESSED)
+    {
+        if (!mFunctionTimerActive && mFunction == kFunction_NoneSelected)
+        {
+            StartFunctionTimer(FACTORY_RESET_TRIGGER_TIMEOUT);
+            mFunction = kFunction_StartBleAdv;
+        }
+    }
+    else
+    {
+        // If the button was released before factory reset got initiated, open the commissioning window and start BLE advertissement
+        // in fast mode
+        if (mFunctionTimerActive && mFunction == kFunction_StartBleAdv)
+        {
+            CancelFunctionTimer();
+            mFunction = kFunction_NoneSelected;
+
+#ifdef QR_CODE_ENABLED
+            // TOGGLE QRCode/LCD demo UI
+            slLCD.ToggleQRCode();
+#endif
+
+#ifdef SL_WIFI
+            if (!ConnectivityMgr().IsWiFiStationProvisioned())
+#else
+            if (!ConnectivityMgr().IsThreadProvisioned())
+#endif /* !SL_WIFI */
+            {
+                // Open Basic CommissioningWindow. Will start BLE advertisements
+                chip::DeviceLayer::PlatformMgr().LockChipStack();
+                CHIP_ERROR err = chip::Server::GetInstance().GetCommissioningWindowManager().OpenBasicCommissioningWindow();
+                chip::DeviceLayer::PlatformMgr().UnlockChipStack();
+                if (err != CHIP_NO_ERROR)
+                {
+                    SILABS_LOG("Failed to open the Basic Commissioning Window");
+                }
+            }
+            else { SILABS_LOG("Network is already provisioned, Ble advertissement not enabled"); }
+        }
+        else if (mFunctionTimerActive && mFunction == kFunction_FactoryReset)
+        {
+            CancelFunctionTimer();
+
+#if CHIP_DEVICE_CONFIG_ENABLE_SED == 1
+            StopStatusLEDTimer();
+#endif
+
+            // Change the function to none selected since factory reset has been
+            // canceled.
+            mFunction = kFunction_NoneSelected;
+            SILABS_LOG("Factory Reset has been Canceled");
+        }
+    }
+}
+
+void BaseApplication::CancelFunctionTimer()
+{
+    if (xTimerStop(sFunctionTimer, 0) == pdFAIL)
+    {
+        SILABS_LOG("app timer stop() failed");
+        appError(APP_ERROR_STOP_TIMER_FAILED);
+    }
+
+    mFunctionTimerActive = false;
+}
+
+void BaseApplication::StartFunctionTimer(uint32_t aTimeoutInMs)
+{
+    if (xTimerIsTimerActive(sFunctionTimer))
+    {
+        SILABS_LOG("app timer already started!");
+        CancelFunctionTimer();
+    }
+
+    // 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(sFunctionTimer, aTimeoutInMs / portTICK_PERIOD_MS, 100) != pdPASS)
+    {
+        SILABS_LOG("app timer start() failed");
+        appError(APP_ERROR_START_TIMER_FAILED);
+    }
+
+    mFunctionTimerActive = true;
+}
+
+void BaseApplication::StartStatusLEDTimer()
+{
+    if (pdPASS != xTimerStart(sLightTimer, 0))
+    {
+        SILABS_LOG("Light Time start failed");
+        appError(APP_ERROR_START_TIMER_FAILED);
+    }
+}
+
+void BaseApplication::StopStatusLEDTimer()
+{
+#ifdef ENABLE_WSTK_LEDS
+    sStatusLED.Set(false);
+#endif // ENABLE_WSTK_LEDS
+
+    if (xTimerStop(sLightTimer, 100) != pdPASS)
+    {
+        SILABS_LOG("Light Time start failed");
+        appError(APP_ERROR_START_TIMER_FAILED);
+    }
+}
+
+void BaseApplication::LightTimerEventHandler(TimerHandle_t xTimer)
+{
+    LightEventHandler();
+}
+
+#ifdef DISPLAY_ENABLED
+SilabsLCD & BaseApplication::GetLCD(void)
+{
+    return slLCD;
+}
+#endif
+
+void BaseApplication::PostEvent(const AppEvent * aEvent)
+{
+    if (sAppEventQueue != NULL)
+    {
+        BaseType_t status;
+        if (xPortIsInsideInterrupt())
+        {
+            BaseType_t higherPrioTaskWoken = pdFALSE;
+            status                         = xQueueSendFromISR(sAppEventQueue, aEvent, &higherPrioTaskWoken);
+
+#ifdef portYIELD_FROM_ISR
+            portYIELD_FROM_ISR(higherPrioTaskWoken);
+#elif portEND_SWITCHING_ISR // portYIELD_FROM_ISR or portEND_SWITCHING_ISR
+            portEND_SWITCHING_ISR(higherPrioTaskWoken);
+#else                       // portYIELD_FROM_ISR or portEND_SWITCHING_ISR
+#error "Must have portYIELD_FROM_ISR or portEND_SWITCHING_ISR"
+#endif // portYIELD_FROM_ISR or portEND_SWITCHING_ISR
+        }
+        else
+        {
+            status = xQueueSend(sAppEventQueue, aEvent, 1);
+        }
+
+        if (!status)
+        {
+            SILABS_LOG("Failed to post event to app task event queue");
+        }
+    }
+    else
+    {
+        SILABS_LOG("Event Queue is NULL should never happen");
+    }
+}
+
+void BaseApplication::DispatchEvent(AppEvent * aEvent)
+{
+    if (aEvent->Handler)
+    {
+        aEvent->Handler(aEvent);
+    }
+    else
+    {
+        SILABS_LOG("Event received with no handler. Dropping event.");
+    }
+}
diff --git a/examples/platform/silabs/SiWx917/BaseApplication.h b/examples/platform/silabs/SiWx917/BaseApplication.h
new file mode 100644
index 0000000..febd7aa
--- /dev/null
+++ b/examples/platform/silabs/SiWx917/BaseApplication.h
@@ -0,0 +1,186 @@
+/*
+ *
+ *    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.
+ */
+
+#pragma once
+
+/**********************************************************
+ * Includes
+ *********************************************************/
+
+#include <stdbool.h>
+#include <stdint.h>
+
+#include "AppEvent.h"
+#include "FreeRTOS.h"
+#include "sl_simple_button_instances.h"
+#include "timers.h" // provides FreeRTOS timer support
+#include <app/clusters/identify-server/identify-server.h>
+#include <ble/BLEEndPoint.h>
+#include <lib/core/CHIPError.h>
+#include <platform/CHIPDeviceLayer.h>
+
+#ifdef DISPLAY_ENABLED
+#include "demo-ui.h"
+#include "lcd.h"
+#ifdef QR_CODE_ENABLED
+#include "qrcodegen.h"
+#endif // QR_CODE_ENABLED
+#endif // DISPLAY_ENABLED
+
+/**********************************************************
+ * Defines
+ *********************************************************/
+
+// Application-defined error codes in the CHIP_ERROR space.
+#define APP_ERROR_EVENT_QUEUE_FAILED CHIP_APPLICATION_ERROR(0x01)
+#define APP_ERROR_CREATE_TASK_FAILED CHIP_APPLICATION_ERROR(0x02)
+#define APP_ERROR_UNHANDLED_EVENT CHIP_APPLICATION_ERROR(0x03)
+#define APP_ERROR_CREATE_TIMER_FAILED CHIP_APPLICATION_ERROR(0x04)
+#define APP_ERROR_START_TIMER_FAILED CHIP_APPLICATION_ERROR(0x05)
+#define APP_ERROR_STOP_TIMER_FAILED CHIP_APPLICATION_ERROR(0x06)
+
+/**********************************************************
+ * BaseApplication Declaration
+ *********************************************************/
+
+class BaseApplication
+{
+
+public:
+    BaseApplication() = default;
+    virtual ~BaseApplication(){};
+
+    /**
+     * @brief Create AppTask task and Event Queue
+     * If an error occurs during creation, application will hang after printing out error code
+     *
+     * @return CHIP_ERROR CHIP_NO_ERROR if no errors
+     */
+    CHIP_ERROR StartAppTask(TaskFunction_t taskFunction);
+
+    /**
+     * @brief PostEvent function that add event to AppTask queue for processing
+     *
+     * @param event AppEvent to post
+     */
+    static void PostEvent(const AppEvent * event);
+
+#ifdef DISPLAY_ENABLED
+    /**
+     * @brief Return LCD object
+     */
+    static SilabsLCD & GetLCD(void);
+#endif
+
+    /**
+     * @brief Event handler when a button is pressed
+     * Function posts an event for button processing
+     *
+     * @param buttonHandle APP_LIGHT_SWITCH or APP_FUNCTION_BUTTON
+     * @param btnAction button action - SL_SIMPLE_BUTTON_PRESSED,
+     *                  SL_SIMPLE_BUTTON_RELEASED or SL_SIMPLE_BUTTON_DISABLED
+     */
+    virtual void ButtonEventHandler(const sl_button_t * buttonHandle, uint8_t btnAction) = 0;
+
+    /**
+     * @brief Function called to start the LED light timer
+     */
+    static void StartStatusLEDTimer(void);
+
+    /**
+     * @brief Function to stop LED light timer
+     *        Turns off Status LED before stopping timer
+     */
+    static void StopStatusLEDTimer(void);
+
+    enum Function_t
+    {
+        kFunction_NoneSelected   = 0,
+        kFunction_SoftwareUpdate = 0,
+        kFunction_StartBleAdv    = 1,
+        kFunction_FactoryReset   = 2,
+
+        kFunction_Invalid
+    } Function;
+
+protected:
+    CHIP_ERROR Init(Identify * identifyObj);
+
+    /**
+     * @brief Function called to start the function timer
+     *
+     * @param aTimeoutMs timer duration in ms
+     */
+    static void StartFunctionTimer(uint32_t aTimeoutMs);
+
+    /**
+     * @brief Function to stop function timer
+     */
+    static void CancelFunctionTimer(void);
+
+    /**
+     * @brief Function call event callback function for processing
+     *
+     * @param event triggered event to be processed
+     */
+    void DispatchEvent(AppEvent * event);
+
+    /**
+     * @brief Function Timer finished callback function
+     *        Post an FunctionEventHandler event
+     *
+     * @param xTimer timer that finished
+     */
+    static void FunctionTimerEventHandler(TimerHandle_t xTimer);
+
+    /**
+     * @brief Timer Event processing function
+     *        Trigger factory if Press and Hold duration is respected
+     *
+     * @param aEvent post event being processed
+     */
+    static void FunctionEventHandler(AppEvent * aEvent);
+
+    /**
+     * @brief PB0 Button event processing function
+     *        Press and hold will trigger a factory reset timer start
+     *        Press and release will restart BLEAdvertising if not commisionned
+     *
+     * @param aEvent button event being processed
+     */
+    static void ButtonHandler(AppEvent * aEvent);
+
+    /**
+     * @brief Light Timer finished callback function
+     *        Calls LED processing function
+     *
+     * @param xTimer timer that finished
+     */
+    static void LightTimerEventHandler(TimerHandle_t xTimer);
+
+    /**
+     * @brief Updates device LEDs
+     */
+    static void LightEventHandler();
+
+    /**********************************************************
+     * Protected Attributes declaration
+     *********************************************************/
+    bool mSyncClusterToButtonAction;
+};
diff --git a/examples/platform/silabs/SiWx917/EFR32DeviceDataProvider.cpp b/examples/platform/silabs/SiWx917/EFR32DeviceDataProvider.cpp
new file mode 100644
index 0000000..6e097ff
--- /dev/null
+++ b/examples/platform/silabs/SiWx917/EFR32DeviceDataProvider.cpp
@@ -0,0 +1,335 @@
+/*
+ *
+ *    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 "EFR32DeviceDataProvider.h"
+#include <crypto/CHIPCryptoPAL.h>
+#include <lib/support/Base64.h>
+#include <platform/silabs/SilabsConfig.h>
+#include <setup_payload/Base38Encode.h>
+#include <setup_payload/SetupPayload.h>
+
+namespace chip {
+namespace DeviceLayer {
+namespace EFR32 {
+
+// using namespace chip::Credentials;
+using namespace chip::DeviceLayer::Internal;
+
+CHIP_ERROR EFR32DeviceDataProvider::GetSetupDiscriminator(uint16_t & setupDiscriminator)
+{
+    CHIP_ERROR err;
+    uint32_t setupDiscriminator32;
+
+    err = SILABSConfig::ReadConfigValue(SILABSConfig::kConfigKey_SetupDiscriminator, setupDiscriminator32);
+#if defined(CHIP_DEVICE_CONFIG_USE_TEST_SETUP_DISCRIMINATOR) && CHIP_DEVICE_CONFIG_USE_TEST_SETUP_DISCRIMINATOR
+    if (err == CHIP_DEVICE_ERROR_CONFIG_NOT_FOUND)
+    {
+        setupDiscriminator32 = CHIP_DEVICE_CONFIG_USE_TEST_SETUP_DISCRIMINATOR;
+        err                  = CHIP_NO_ERROR;
+    }
+#endif // defined(CHIP_DEVICE_CONFIG_USE_TEST_SETUP_DISCRIMINATOR) && CHIP_DEVICE_CONFIG_USE_TEST_SETUP_DISCRIMINATOR
+
+    VerifyOrReturnLogError(setupDiscriminator32 <= kMaxDiscriminatorValue, CHIP_ERROR_INVALID_ARGUMENT);
+    setupDiscriminator = static_cast<uint16_t>(setupDiscriminator32);
+    return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR EFR32DeviceDataProvider::GetSpake2pIterationCount(uint32_t & iterationCount)
+{
+    CHIP_ERROR err = SILABSConfig::ReadConfigValue(SILABSConfig::kConfigKey_Spake2pIterationCount, iterationCount);
+
+#if defined(CHIP_DEVICE_CONFIG_USE_TEST_SPAKE2P_ITERATION_COUNT) && CHIP_DEVICE_CONFIG_USE_TEST_SPAKE2P_ITERATION_COUNT
+    if (err == CHIP_DEVICE_ERROR_CONFIG_NOT_FOUND)
+    {
+        iterationCount = CHIP_DEVICE_CONFIG_USE_TEST_SPAKE2P_ITERATION_COUNT;
+        err            = CHIP_NO_ERROR;
+    }
+#endif // defined(CHIP_DEVICE_CONFIG_USE_TEST_SPAKE2P_ITERATION_COUNT) && CHIP_DEVICE_CONFIG_USE_TEST_SPAKE2P_ITERATION_COUNT
+    return err;
+}
+
+CHIP_ERROR EFR32DeviceDataProvider::GetSpake2pSalt(MutableByteSpan & saltBuf)
+{
+    static constexpr size_t kSpake2pSalt_MaxBase64Len = BASE64_ENCODED_LEN(chip::Crypto::kSpake2p_Max_PBKDF_Salt_Length) + 1;
+
+    CHIP_ERROR err                          = CHIP_NO_ERROR;
+    char saltB64[kSpake2pSalt_MaxBase64Len] = { 0 };
+    size_t saltB64Len                       = 0;
+
+    err = SILABSConfig::ReadConfigValueStr(SILABSConfig::kConfigKey_Spake2pSalt, saltB64, sizeof(saltB64), saltB64Len);
+
+#if defined(CHIP_DEVICE_CONFIG_USE_TEST_SPAKE2P_SALT)
+    if (err == CHIP_DEVICE_ERROR_CONFIG_NOT_FOUND)
+    {
+        saltB64Len = strlen(CHIP_DEVICE_CONFIG_USE_TEST_SPAKE2P_SALT);
+        ReturnErrorCodeIf(saltB64Len > sizeof(saltB64), CHIP_ERROR_BUFFER_TOO_SMALL);
+        memcpy(saltB64, CHIP_DEVICE_CONFIG_USE_TEST_SPAKE2P_SALT, saltB64Len);
+        err = CHIP_NO_ERROR;
+    }
+#endif // defined(CHIP_DEVICE_CONFIG_USE_TEST_SPAKE2P_SALT)
+
+    ReturnErrorOnFailure(err);
+
+    uint8_t saltByteArray[kSpake2pSalt_MaxBase64Len] = { 0 };
+    size_t saltLen                                   = chip::Base64Decode32(saltB64, saltB64Len, saltByteArray);
+    ReturnErrorCodeIf(saltLen > saltBuf.size(), CHIP_ERROR_BUFFER_TOO_SMALL);
+
+    memcpy(saltBuf.data(), saltByteArray, saltLen);
+    saltBuf.reduce_size(saltLen);
+
+    return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR EFR32DeviceDataProvider::GetSpake2pVerifier(MutableByteSpan & verifierBuf, size_t & verifierLen)
+{
+    static constexpr size_t kSpake2pSerializedVerifier_MaxBase64Len =
+        BASE64_ENCODED_LEN(chip::Crypto::kSpake2p_VerifierSerialized_Length) + 1;
+
+    CHIP_ERROR err                                            = CHIP_NO_ERROR;
+    char verifierB64[kSpake2pSerializedVerifier_MaxBase64Len] = { 0 };
+    size_t verifierB64Len                                     = 0;
+
+    err = SILABSConfig::ReadConfigValueStr(SILABSConfig::kConfigKey_Spake2pVerifier, verifierB64, sizeof(verifierB64),
+                                           verifierB64Len);
+
+#if defined(CHIP_DEVICE_CONFIG_USE_TEST_SPAKE2P_VERIFIER)
+    if (err == CHIP_DEVICE_ERROR_CONFIG_NOT_FOUND)
+    {
+        verifierB64Len = strlen(CHIP_DEVICE_CONFIG_USE_TEST_SPAKE2P_VERIFIER);
+        ReturnErrorCodeIf(verifierB64Len > sizeof(verifierB64), CHIP_ERROR_BUFFER_TOO_SMALL);
+        memcpy(verifierB64, CHIP_DEVICE_CONFIG_USE_TEST_SPAKE2P_VERIFIER, verifierB64Len);
+        err = CHIP_NO_ERROR;
+    }
+#endif // defined(CHIP_DEVICE_CONFIG_USE_TEST_SPAKE2P_VERIFIER)
+
+    ReturnErrorOnFailure(err);
+
+    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 EFR32DeviceDataProvider::GetSetupPayload(MutableCharSpan & payloadBuf)
+{
+    CHIP_ERROR err                                      = CHIP_NO_ERROR;
+    uint8_t payloadBitSet[kTotalPayloadDataSizeInBytes] = { 0 };
+    size_t bitSetLen                                    = 0;
+
+    err = SILABSConfig::ReadConfigValueBin(SILABSConfig::kConfigKey_SetupPayloadBitSet, payloadBitSet, kTotalPayloadDataSizeInBytes,
+                                           bitSetLen);
+
+#if defined(CHIP_DEVICE_CONFIG_USE_TEST_SETUP_PIN_CODE) && CHIP_DEVICE_CONFIG_USE_TEST_SETUP_PIN_CODE
+    if (err == CHIP_DEVICE_ERROR_CONFIG_NOT_FOUND)
+    {
+        static constexpr uint8_t kTestSetupPayloadBitset[] = { 0x88, 0xFF, 0x2F, 0x00, 0x44, 0x00, 0xE0, 0x4B, 0x84, 0x68, 0x02 };
+        bitSetLen                                          = sizeof(kTestSetupPayloadBitset);
+        ReturnErrorCodeIf(bitSetLen > kTotalPayloadDataSizeInBytes, CHIP_ERROR_BUFFER_TOO_SMALL);
+        memcpy(payloadBitSet, kTestSetupPayloadBitset, bitSetLen);
+        err = CHIP_NO_ERROR;
+    }
+#endif // defined(CHIP_DEVICE_CONFIG_USE_TEST_SPAKE2P_VERIFIER)
+
+    ReturnErrorOnFailure(err);
+
+    size_t prefixLen = strlen(kQRCodePrefix);
+
+    if (payloadBuf.size() < prefixLen + 1)
+    {
+        err = CHIP_ERROR_BUFFER_TOO_SMALL;
+    }
+    else
+    {
+        MutableCharSpan subSpan = payloadBuf.SubSpan(prefixLen, payloadBuf.size() - prefixLen);
+        memcpy(payloadBuf.data(), kQRCodePrefix, prefixLen);
+        err = base38Encode(MutableByteSpan(payloadBitSet), subSpan);
+        // Reduce output span size to be the size of written data
+        payloadBuf.reduce_size(subSpan.size() + prefixLen);
+    }
+
+    return err;
+}
+
+CHIP_ERROR EFR32DeviceDataProvider::GetVendorName(char * buf, size_t bufSize)
+{
+    size_t vendorNameLen = 0; // without counting null-terminator
+    return SILABSConfig::ReadConfigValueStr(SILABSConfig::kConfigKey_VendorName, buf, bufSize, vendorNameLen);
+}
+
+CHIP_ERROR EFR32DeviceDataProvider::GetVendorId(uint16_t & vendorId)
+{
+    ChipError err       = CHIP_NO_ERROR;
+    uint32_t vendorId32 = 0;
+
+    err = SILABSConfig::ReadConfigValue(SILABSConfig::kConfigKey_VendorId, vendorId32);
+
+#if defined(CHIP_DEVICE_CONFIG_DEVICE_VENDOR_ID) && CHIP_DEVICE_CONFIG_DEVICE_VENDOR_ID
+    if (err == CHIP_DEVICE_ERROR_CONFIG_NOT_FOUND)
+    {
+        vendorId32 = CHIP_DEVICE_CONFIG_DEVICE_VENDOR_ID;
+        err        = CHIP_NO_ERROR;
+    }
+#endif // defined(CHIP_DEVICE_CONFIG_DEVICE_VENDOR_ID) && CHIP_DEVICE_CONFIG_DEVICE_VENDOR_ID
+
+    ReturnErrorOnFailure(err);
+    vendorId = static_cast<uint16_t>(vendorId32);
+    return err;
+}
+
+CHIP_ERROR EFR32DeviceDataProvider::GetProductName(char * buf, size_t bufSize)
+{
+    size_t productNameLen = 0; // without counting null-terminator
+    return SILABSConfig::ReadConfigValueStr(SILABSConfig::kConfigKey_ProductName, buf, bufSize, productNameLen);
+}
+
+CHIP_ERROR EFR32DeviceDataProvider::GetProductId(uint16_t & productId)
+{
+    ChipError err        = CHIP_NO_ERROR;
+    uint32_t productId32 = 0;
+
+    err = SILABSConfig::ReadConfigValue(SILABSConfig::kConfigKey_ProductId, productId32);
+
+#if defined(CHIP_DEVICE_CONFIG_DEVICE_PRODUCT_ID) && CHIP_DEVICE_CONFIG_DEVICE_PRODUCT_ID
+    if (err == CHIP_DEVICE_ERROR_CONFIG_NOT_FOUND)
+    {
+        productId32 = CHIP_DEVICE_CONFIG_DEVICE_PRODUCT_ID;
+        err         = CHIP_NO_ERROR;
+    }
+#endif // defined(CHIP_DEVICE_CONFIG_DEVICE_PRODUCT_ID) && CHIP_DEVICE_CONFIG_DEVICE_PRODUCT_ID
+    ReturnErrorOnFailure(err);
+
+    productId = static_cast<uint16_t>(productId32);
+    return err;
+}
+
+CHIP_ERROR EFR32DeviceDataProvider::GetHardwareVersionString(char * buf, size_t bufSize)
+{
+    size_t hardwareVersionStringLen = 0; // without counting null-terminator
+    CHIP_ERROR err =
+        SILABSConfig::ReadConfigValueStr(SILABSConfig::kConfigKey_HardwareVersionString, buf, bufSize, hardwareVersionStringLen);
+#if defined(CHIP_DEVICE_CONFIG_DEVICE_SOFTWARE_VERSION_STRING)
+    if (err == CHIP_DEVICE_ERROR_CONFIG_NOT_FOUND)
+    {
+        memcpy(buf, CHIP_DEVICE_CONFIG_DEVICE_SOFTWARE_VERSION_STRING, sizeof(bufSize));
+        err = CHIP_NO_ERROR;
+    }
+#endif // CHIP_DEVICE_CONFIG_DEVICE_SOFTWARE_VERSION_STRING
+    return err;
+}
+
+CHIP_ERROR EFR32DeviceDataProvider::GetHardwareVersion(uint16_t & hardwareVersion)
+{
+    CHIP_ERROR err;
+    uint32_t hardwareVersion32;
+
+    err = SILABSConfig::ReadConfigValue(SILABSConfig::kConfigKey_HardwareVersion, hardwareVersion32);
+#if defined(CHIP_DEVICE_CONFIG_DEVICE_HARDWARE_VERSION)
+    if (err == CHIP_DEVICE_ERROR_CONFIG_NOT_FOUND)
+    {
+        hardwareVersion32 = CHIP_DEVICE_CONFIG_DEVICE_HARDWARE_VERSION;
+        err               = CHIP_NO_ERROR;
+    }
+#endif // defined(CHIP_DEVICE_CONFIG_DEVICE_HARDWARE_VERSION)
+
+    hardwareVersion = static_cast<uint16_t>(hardwareVersion32);
+    return err;
+}
+
+CHIP_ERROR EFR32DeviceDataProvider::GetRotatingDeviceIdUniqueId(MutableByteSpan & uniqueIdSpan)
+{
+    ChipError err = CHIP_ERROR_WRONG_KEY_TYPE;
+#if CHIP_ENABLE_ROTATING_DEVICE_ID
+    static_assert(ConfigurationManager::kRotatingDeviceIDUniqueIDLength >= ConfigurationManager::kMinRotatingDeviceIDUniqueIDLength,
+                  "Length of unique ID for rotating device ID is smaller than minimum.");
+
+    size_t uniqueIdLen = 0;
+    err =
+        SILABSConfig::ReadConfigValueBin(SILABSConfig::kConfigKey_UniqueId, uniqueIdSpan.data(), uniqueIdSpan.size(), uniqueIdLen);
+#ifdef CHIP_DEVICE_CONFIG_ROTATING_DEVICE_ID_UNIQUE_ID
+    if (err == CHIP_DEVICE_ERROR_CONFIG_NOT_FOUND)
+    {
+        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);
+    }
+#endif // CHIP_DEVICE_CONFIG_ROTATING_DEVICE_ID_UNIQUE_ID
+
+    ReturnErrorOnFailure(err);
+    uniqueIdSpan.reduce_size(uniqueIdLen);
+
+#endif // CHIP_ENABLE_ROTATING_DEVICE_ID
+    return err;
+}
+
+CHIP_ERROR EFR32DeviceDataProvider::GetSerialNumber(char * buf, size_t bufSize)
+{
+    size_t serialNumberLen = 0; // without counting null-terminator
+    return SILABSConfig::ReadConfigValueStr(SILABSConfig::kConfigKey_SerialNum, buf, bufSize, serialNumberLen);
+}
+
+CHIP_ERROR EFR32DeviceDataProvider::GetManufacturingDate(uint16_t & year, uint8_t & month, uint8_t & day)
+{
+    CHIP_ERROR err;
+    constexpr uint8_t kDateStringLength = 10; // YYYY-MM-DD
+    char dateStr[kDateStringLength + 1];
+    size_t dateLen;
+    char * parseEnd;
+
+    err = SILABSConfig::ReadConfigValueBin(SILABSConfig::kConfigKey_ManufacturingDate, reinterpret_cast<uint8_t *>(dateStr),
+                                           sizeof(dateStr), dateLen);
+    SuccessOrExit(err);
+
+    VerifyOrExit(dateLen == kDateStringLength, err = CHIP_ERROR_INVALID_ARGUMENT);
+
+    // Cast does not lose information, because we then check that we only parsed
+    // 4 digits, so our number can't be bigger than 9999.
+    year = static_cast<uint16_t>(strtoul(dateStr, &parseEnd, 10));
+    VerifyOrExit(parseEnd == dateStr + 4, err = CHIP_ERROR_INVALID_ARGUMENT);
+
+    // Cast does not lose information, because we then check that we only parsed
+    // 2 digits, so our number can't be bigger than 99.
+    month = static_cast<uint8_t>(strtoul(dateStr + 5, &parseEnd, 10));
+    VerifyOrExit(parseEnd == dateStr + 7, err = CHIP_ERROR_INVALID_ARGUMENT);
+
+    // Cast does not lose information, because we then check that we only parsed
+    // 2 digits, so our number can't be bigger than 99.
+    day = static_cast<uint8_t>(strtoul(dateStr + 8, &parseEnd, 10));
+    VerifyOrExit(parseEnd == dateStr + 10, err = CHIP_ERROR_INVALID_ARGUMENT);
+
+exit:
+    if (err != CHIP_NO_ERROR && err != CHIP_DEVICE_ERROR_CONFIG_NOT_FOUND)
+    {
+        ChipLogError(DeviceLayer, "Invalid manufacturing date: %s", dateStr);
+    }
+    return err;
+    return CHIP_ERROR_NOT_IMPLEMENTED;
+}
+
+EFR32DeviceDataProvider & EFR32DeviceDataProvider::GetDeviceDataProvider()
+{
+    static EFR32DeviceDataProvider sDataProvider;
+    return sDataProvider;
+}
+
+} // namespace EFR32
+} // namespace DeviceLayer
+} // namespace chip
diff --git a/examples/platform/silabs/SiWx917/EFR32DeviceDataProvider.h b/examples/platform/silabs/SiWx917/EFR32DeviceDataProvider.h
new file mode 100644
index 0000000..99d9049
--- /dev/null
+++ b/examples/platform/silabs/SiWx917/EFR32DeviceDataProvider.h
@@ -0,0 +1,67 @@
+/*
+ *
+ *    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/CommissionableDataProvider.h>
+#include <platform/internal/GenericDeviceInstanceInfoProvider.h>
+
+namespace chip {
+namespace DeviceLayer {
+namespace EFR32 {
+
+/**
+ * @brief This class provides Commissionable data, Device Attestation Credentials,
+ *        and Device Instance Info.
+ */
+
+class EFR32DeviceDataProvider : public CommissionableDataProvider,
+                                public Internal::GenericDeviceInstanceInfoProvider<Internal::SILABSConfig>
+{
+public:
+    EFR32DeviceDataProvider() :
+        CommissionableDataProvider(), Internal::GenericDeviceInstanceInfoProvider<Internal::SILABSConfig>(
+                                          ConfigurationManagerImpl::GetDefaultInstance())
+    {}
+
+    static EFR32DeviceDataProvider & GetDeviceDataProvider();
+    CHIP_ERROR GetSetupPayload(MutableCharSpan & payloadBuf);
+
+    // ===== Members functions that implement the CommissionableDataProvider
+    CHIP_ERROR GetSetupDiscriminator(uint16_t & setupDiscriminator) override;
+    CHIP_ERROR SetSetupDiscriminator(uint16_t setupDiscriminator) override { return CHIP_ERROR_NOT_IMPLEMENTED; }
+    CHIP_ERROR GetSpake2pIterationCount(uint32_t & iterationCount) override;
+    CHIP_ERROR GetSpake2pSalt(MutableByteSpan & saltBuf) override;
+    CHIP_ERROR GetSpake2pVerifier(MutableByteSpan & verifierBuf, size_t & verifierLen) override;
+    // Per spec 5.1.7. Passcode cannot be stored on the device
+    CHIP_ERROR GetSetupPasscode(uint32_t & setupPasscode) override { return CHIP_ERROR_NOT_IMPLEMENTED; };
+    CHIP_ERROR SetSetupPasscode(uint32_t setupPasscode) override { return CHIP_ERROR_NOT_IMPLEMENTED; }
+
+    // ===== 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 GetHardwareVersionString(char * buf, size_t bufSize) override;
+    CHIP_ERROR GetRotatingDeviceIdUniqueId(MutableByteSpan & uniqueIdSpan) 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;
+};
+
+} // namespace EFR32
+} // namespace DeviceLayer
+} // namespace chip
diff --git a/examples/platform/silabs/SiWx917/FreeRTOSConfig.h b/examples/platform/silabs/SiWx917/FreeRTOSConfig.h
new file mode 100644
index 0000000..50f4c24
--- /dev/null
+++ b/examples/platform/silabs/SiWx917/FreeRTOSConfig.h
@@ -0,0 +1,274 @@
+/*
+ *
+ *    Copyright (c) 2020 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.
+ */
+
+/***************************************************************************
+ * # License
+ *
+ * The licensor of this software is Silicon Laboratories Inc. Your use of this
+ * software is governed by the terms of Silicon Labs Master Software License
+ * Agreement (MSLA) available at
+ * www.silabs.com/about-us/legal/master-software-license-agreement. This
+ * software is Third Party Software licensed by Silicon Labs from a third party
+ * and is governed by the sections of the MSLA applicable to Third Party
+ * Software and the additional terms set forth below.
+ *
+ ******************************************************************************/
+/*
+    FreeRTOS V9.0.0 - Copyright (C) 2016 Real Time Engineers Ltd.
+    All rights reserved
+
+    VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
+
+    This file is part of the FreeRTOS distribution.
+
+    FreeRTOS is free software; you can redistribute it and/or modify it under
+    the terms of the GNU General Public License (version 2) as published by the
+    Free Software Foundation >>>> AND MODIFIED BY <<<< the FreeRTOS exception.
+
+    ***************************************************************************
+    >>!   NOTE: The modification to the GPL is included to allow you to     !<<
+    >>!   distribute a combined work that includes FreeRTOS without being   !<<
+    >>!   obliged to provide the source code for proprietary components     !<<
+    >>!   outside of the FreeRTOS kernel.                                   !<<
+    ***************************************************************************
+
+    FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY
+    WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+    FOR A PARTICULAR PURPOSE.  Full license text is available on the following
+    link: http://www.freertos.org/a00114.html
+
+    ***************************************************************************
+     *                                                                       *
+     *    FreeRTOS provides completely free yet professionally developed,    *
+     *    robust, strictly quality controlled, supported, and cross          *
+     *    platform software that is more than just the market leader, it     *
+     *    is the industry's de facto standard.                               *
+     *                                                                       *
+     *    Help yourself get started quickly while simultaneously helping     *
+     *    to support the FreeRTOS project by purchasing a FreeRTOS           *
+     *    tutorial book, reference manual, or both:                          *
+     *    http://www.FreeRTOS.org/Documentation                              *
+     *                                                                       *
+    ***************************************************************************
+
+    http://www.FreeRTOS.org/FAQHelp.html - Having a problem?  Start by reading
+    the FAQ page "My application does not run, what could be wrong?".  Have you
+    defined configASSERT()?
+
+    http://www.FreeRTOS.org/support - In return for receiving this top quality
+    embedded software for free we request you assist our global community by
+    participating in the support forum.
+
+    http://www.FreeRTOS.org/training - Investing in training allows your team to
+    be as productive as possible as early as possible.  Now you can receive
+    FreeRTOS training directly from Richard Barry, CEO of Real Time Engineers
+    Ltd, and the world's leading authority on the world's leading RTOS.
+
+    http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products,
+    including FreeRTOS+Trace - an indispensable productivity tool, a DOS
+    compatible FAT file system, and our tiny thread aware UDP/IP stack.
+
+    http://www.FreeRTOS.org/labs - Where new FreeRTOS products go to incubate.
+    Come and try FreeRTOS+TCP, our new open source TCP/IP stack for FreeRTOS.
+
+    http://www.OpenRTOS.com - Real Time Engineers ltd. license FreeRTOS to High
+    Integrity Systems ltd. to sell under the OpenRTOS brand.  Low cost OpenRTOS
+    licenses offer ticketed support, indemnification and commercial middleware.
+
+    http://www.SafeRTOS.com - High Integrity Systems also provide a safety
+    engineered and independently SIL3 certified version for use in safety and
+    mission critical applications that require provable dependability.
+
+    1 tab == 4 spaces!
+*/
+
+#pragma once
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <CHIPProjectConfig.h>
+
+#include <stdint.h>
+
+#include "RTE_Components.h"
+#include CMSIS_device_header
+
+#include "em_assert.h"
+#include "em_device.h"
+
+#if defined(SL_COMPONENT_CATALOG_PRESENT)
+#include "sl_component_catalog.h"
+#endif
+
+#if SL_SYSTEM_VIEW
+#include "SEGGER_SYSVIEW_FreeRTOS.h"
+#endif
+
+/*-----------------------------------------------------------
+ * Application specific definitions.
+ *
+ * These definitions should be adjusted for your particular hardware and
+ * application requirements.
+ *
+ * THESE PARAMETERS ARE DESCRIBED WITHIN THE 'CONFIGURATION' SECTION OF THE
+ * FreeRTOS API DOCUMENTATION AVAILABLE ON THE FreeRTOS.org WEB SITE.
+ *
+ * See http://www.freertos.org/a00110.html.
+ *----------------------------------------------------------*/
+
+/* Energy saving modes. */
+#if defined(SL_CATALOG_POWER_MANAGER_PRESENT)
+#define configUSE_TICKLESS_IDLE 1
+#else
+#define configUSE_TICKLESS_IDLE 0
+#endif // SL_CATALOG_POWER_MANAGER_PRESENT
+
+#define configTICK_RATE_HZ (1000)
+/* Definition used by Keil to replace default system clock source. */
+#define configOVERRIDE_DEFAULT_TICK_CONFIGURATION 1
+
+/* Hook function related definitions. */
+#define configUSE_TICK_HOOK (1)
+#define configCHECK_FOR_STACK_OVERFLOW (2)
+#define configUSE_MALLOC_FAILED_HOOK (1)
+#define configUSE_IDLE_HOOK (1)
+
+/* Main functions*/
+/* Run time stats gathering related definitions. */
+#define configGENERATE_RUN_TIME_STATS (0)
+
+/* Co-routine related definitions. */
+#define configUSE_CO_ROUTINES (0)
+#define configMAX_CO_ROUTINE_PRIORITIES (1)
+
+/* Software timer related definitions. */
+#define configUSE_TIMERS (1)
+#define configTIMER_TASK_PRIORITY (40) /* Highest priority */
+#define configTIMER_QUEUE_LENGTH (10)
+#define configTIMER_TASK_STACK_DEPTH (1024)
+
+/* Interrupt priorities used by the kernel port layer itself.  These are generic
+to all Cortex-M ports, and do not rely on any particular library functions. */
+#define configKERNEL_INTERRUPT_PRIORITY (255)
+/* !!!! configMAX_SYSCALL_INTERRUPT_PRIORITY must not be set to zero !!!!
+See http://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html. */
+#define configMAX_SYSCALL_INTERRUPT_PRIORITY 48
+#define configENABLE_FPU 0
+#define configENABLE_MPU 0
+/* FreeRTOS Secure Side Only and TrustZone Security Extension */
+#define configRUN_FREERTOS_SECURE_ONLY 1
+#define configENABLE_TRUSTZONE 0
+/* FreeRTOS MPU specific definitions. */
+#define configINCLUDE_APPLICATION_DEFINED_PRIVILEGED_FUNCTIONS (0)
+
+#define configCPU_CLOCK_HZ (SystemCoreClock)
+#define configUSE_PREEMPTION (1)
+#define configUSE_TIME_SLICING (1)
+#define configUSE_PORT_OPTIMISED_TASK_SELECTION (0)
+#define configUSE_TICKLESS_IDLE_SIMPLE_DEBUG (1) /* See into vPortSuppressTicksAndSleep source code for explanation */
+#define configMAX_PRIORITIES (56)
+#define configMINIMAL_STACK_SIZE (320) /* Number of words to use for Idle and Timer stacks */
+
+#ifdef HEAP_MONITORING
+#define configMAX_TASK_NAME_LEN (24)
+#else
+#define configMAX_TASK_NAME_LEN (10)
+#endif // HEAP_MONITORING
+
+#define configUSE_16_BIT_TICKS (0)
+#define configIDLE_SHOULD_YIELD (1)
+#define configUSE_MUTEXES (1)
+#define configUSE_RECURSIVE_MUTEXES (1)
+#define configUSE_COUNTING_SEMAPHORES (1)
+#define configUSE_TASK_NOTIFICATIONS 1
+#define configUSE_TRACE_FACILITY 1
+#define configQUEUE_REGISTRY_SIZE (10)
+#define configUSE_QUEUE_SETS (0)
+#define configUSE_NEWLIB_REENTRANT (1)
+#define configENABLE_BACKWARD_COMPATIBILITY (1)
+#define configSUPPORT_STATIC_ALLOCATION (1)
+#define configSUPPORT_DYNAMIC_ALLOCATION (1)
+
+#ifndef configTOTAL_HEAP_SIZE
+#ifdef SL_WIFI
+#define configTOTAL_HEAP_SIZE ((size_t)(34 * 1024))
+#else
+#define configTOTAL_HEAP_SIZE ((size_t)(20 * 1024))
+#endif
+#endif // configTOTAL_HEAP_SIZE
+
+/* Optional functions - most linkers will remove unused functions anyway. */
+#define INCLUDE_vTaskPrioritySet (1)
+#define INCLUDE_uxTaskPriorityGet (1)
+#define INCLUDE_vTaskDelete (1)
+#define INCLUDE_vTaskSuspend (1)
+#define INCLUDE_xResumeFromISR (1)
+#define INCLUDE_vTaskDelayUntil (1)
+#define INCLUDE_vTaskDelay (1)
+#define INCLUDE_xTaskGetSchedulerState (1)
+#define INCLUDE_xTaskGetCurrentTaskHandle (1)
+#define INCLUDE_uxTaskGetStackHighWaterMark (1)
+#define INCLUDE_xTaskGetIdleTaskHandle (1)
+#define INCLUDE_xTimerGetTimerDaemonTaskHandle (1)
+#define INCLUDE_pcTaskGetTaskName (1)
+#define INCLUDE_eTaskGetState (1)
+#define INCLUDE_xEventGroupSetBitFromISR (1)
+#define INCLUDE_xEventGroupSetBitsFromISR (1)
+#define INCLUDE_xSemaphoreGetMutexHolder (1)
+#define INCLUDE_xTimerPendFunctionCall (1)
+#define INCLUDE_xTaskGetHandle (1)
+
+/* Stop if an assertion fails. */
+#define configASSERT(x)                                                                                                            \
+    if ((x) == 0)                                                                                                                  \
+    {                                                                                                                              \
+        taskDISABLE_INTERRUPTS();                                                                                                  \
+        printf("\nFREERTOS ASSERT ( %s )\n", #x);                                                                                  \
+        for (;;)                                                                                                                   \
+            ;                                                                                                                      \
+    }
+#define configASSERTNULL(x)                                                                                                        \
+    if ((x) == NULL)                                                                                                               \
+    {                                                                                                                              \
+        taskDISABLE_INTERRUPTS();                                                                                                  \
+        for (;;)                                                                                                                   \
+            ;                                                                                                                      \
+    }
+
+/* Definitions that map the FreeRTOS port interrupt handlers to their CMSIS
+standard names. */
+#define vPortSVCHandler SVC_Handler
+#define xPortPendSVHandler PendSV_Handler
+/* Ensure Cortex-M port compatibility. */
+#define SysTick_Handler xPortSysTickHandler
+
+/* Thread local storage pointers used by the SDK */
+#ifndef configNUM_SDK_THREAD_LOCAL_STORAGE_POINTERS
+#define configNUM_SDK_THREAD_LOCAL_STORAGE_POINTERS 0
+#endif
+
+#if defined(__GNUC__)
+/* For the linker. */
+#define fabs __builtin_fabs
+#endif
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/examples/platform/silabs/SiWx917/LEDWidget.cpp b/examples/platform/silabs/SiWx917/LEDWidget.cpp
new file mode 100644
index 0000000..10ffcac
--- /dev/null
+++ b/examples/platform/silabs/SiWx917/LEDWidget.cpp
@@ -0,0 +1,89 @@
+/*
+ *
+ *    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"
+
+extern "C" {
+#include "sl_simple_led_instances.h"
+}
+
+#include <platform/CHIPDeviceLayer.h>
+
+using namespace ::chip::System;
+
+void LEDWidget::InitGpio(void)
+{
+    // Sets gpio pin mode for ALL board Leds.
+    sl_simple_led_init_instances();
+}
+
+void LEDWidget::Init(const sl_led_t * led)
+{
+    mLastChangeTimeMS = 0;
+    mBlinkOnTimeMS    = 0;
+    mBlinkOffTimeMS   = 0;
+    mLed              = led;
+
+    Set(false);
+}
+
+void LEDWidget::Invert(void)
+{
+    if (mLed)
+    {
+        sl_led_toggle(mLed);
+    }
+}
+
+void LEDWidget::Set(bool state)
+{
+    mLastChangeTimeMS = mBlinkOnTimeMS = mBlinkOffTimeMS = 0;
+    if (mLed)
+    {
+        state ? sl_led_turn_on(mLed) : sl_led_turn_off(mLed);
+    }
+}
+
+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       = sl_led_get_state(mLed) ? mBlinkOnTimeMS : mBlinkOffTimeMS;
+        uint64_t nextChangeTimeMS = mLastChangeTimeMS + stateDurMS;
+
+        if (nextChangeTimeMS < nowMS)
+        {
+            Invert();
+            mLastChangeTimeMS = nowMS;
+        }
+    }
+}
diff --git a/examples/platform/silabs/SiWx917/LEDWidget.h b/examples/platform/silabs/SiWx917/LEDWidget.h
new file mode 100644
index 0000000..d779cb9
--- /dev/null
+++ b/examples/platform/silabs/SiWx917/LEDWidget.h
@@ -0,0 +1,41 @@
+/*
+ *
+ *    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.
+ */
+
+#pragma once
+
+#include "sl_led.h"
+#include <stdint.h>
+
+class LEDWidget
+{
+public:
+    static void InitGpio(void);
+    void Init(const sl_led_t * led);
+    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;
+    const sl_led_t * mLed;
+};
diff --git a/examples/platform/silabs/SiWx917/MemMonitoring.cpp b/examples/platform/silabs/SiWx917/MemMonitoring.cpp
new file mode 100644
index 0000000..9da075e
--- /dev/null
+++ b/examples/platform/silabs/SiWx917/MemMonitoring.cpp
@@ -0,0 +1,111 @@
+/*
+ *
+ *    Copyright (c) 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.
+ */
+
+#include "MemMonitoring.h"
+
+#include "AppConfig.h"
+#include "FreeRTOS.h"
+#include <platform/CHIPDeviceLayer.h>
+
+#define BLE_STACK_TASK_NAME "Bluetooth stack"
+#define BLE_LINK_TASK_NAME "Bluetooth linklayer"
+
+static StackType_t monitoringStack[MONITORING_STACK_SIZE_byte / sizeof(StackType_t)];
+static StaticTask_t monitoringTaskStruct;
+
+size_t nbAllocSuccess        = 0;
+size_t nbFreeSuccess         = 0;
+size_t largestBlockAllocated = 0;
+
+void MemMonitoring::startHeapMonitoring()
+{
+    xTaskCreateStatic(HeapMonitoring, "Monitoring", MONITORING_STACK_SIZE_byte / sizeof(StackType_t), NULL, 1, monitoringStack,
+                      &monitoringTaskStruct);
+}
+
+void MemMonitoring::HeapMonitoring(void * pvParameter)
+{
+
+    UBaseType_t appTaskValue;
+    UBaseType_t bleEventTaskValue;
+    UBaseType_t bleTaskValue;
+    UBaseType_t linkLayerTaskValue;
+    UBaseType_t openThreadTaskValue;
+    UBaseType_t eventLoopTaskValue;
+
+    TaskHandle_t eventLoopHandleStruct = xTaskGetHandle(CHIP_DEVICE_CONFIG_CHIP_TASK_NAME);
+    TaskHandle_t otTaskHandle          = xTaskGetHandle(CHIP_DEVICE_CONFIG_THREAD_TASK_NAME);
+    TaskHandle_t appTaskHandle         = xTaskGetHandle(APP_TASK_NAME);
+    TaskHandle_t bleStackTaskHandle    = xTaskGetHandle(BLE_STACK_TASK_NAME);
+    TaskHandle_t bleLinkTaskHandle     = xTaskGetHandle(BLE_LINK_TASK_NAME);
+    TaskHandle_t bleEventTaskHandle    = xTaskGetHandle(CHIP_DEVICE_CONFIG_BLE_APP_TASK_NAME);
+
+#if CHIP_SYSTEM_CONFIG_USE_LWIP
+    UBaseType_t lwipTaskValue;
+    TaskHandle_t lwipHandle = xTaskGetHandle(TCPIP_THREAD_NAME);
+#endif // CHIP_SYSTEM_CONFIG_USE_LWIP
+
+    while (true)
+    {
+        appTaskValue        = uxTaskGetStackHighWaterMark(appTaskHandle);
+        bleEventTaskValue   = uxTaskGetStackHighWaterMark(bleEventTaskHandle);
+        bleTaskValue        = uxTaskGetStackHighWaterMark(bleStackTaskHandle);
+        linkLayerTaskValue  = uxTaskGetStackHighWaterMark(bleLinkTaskHandle);
+        openThreadTaskValue = uxTaskGetStackHighWaterMark(otTaskHandle);
+        eventLoopTaskValue  = uxTaskGetStackHighWaterMark(eventLoopHandleStruct);
+#if CHIP_SYSTEM_CONFIG_USE_LWIP
+        lwipTaskValue = uxTaskGetStackHighWaterMark(lwipHandle);
+#endif // CHIP_SYSTEM_CONFIG_USE_LWIP
+
+        SILABS_LOG("=============================");
+        SILABS_LOG("     ");
+        SILABS_LOG("Largest Block allocated              0x%x", largestBlockAllocated);
+        SILABS_LOG("Number Of Successful Alloc           0x%x", nbAllocSuccess);
+        SILABS_LOG("Number Of Successful Frees           0x%x", nbFreeSuccess);
+        SILABS_LOG("     ");
+        SILABS_LOG("App Task most bytes ever Free         0x%x", (appTaskValue * 4));
+        SILABS_LOG("BLE Event most bytes ever Free        0x%x", (bleEventTaskValue * 4));
+        SILABS_LOG("BLE Stack most bytes ever Free        0x%x", (bleTaskValue * 4));
+        SILABS_LOG("Link Layer Task most bytes ever Free  0x%x", (linkLayerTaskValue * 4));
+        SILABS_LOG("OpenThread Task most bytes ever Free  0x%x", (openThreadTaskValue * 4));
+        SILABS_LOG("Event Loop Task most bytes ever Free  0x%x", (eventLoopTaskValue * 4));
+#if CHIP_SYSTEM_CONFIG_USE_LWIP
+        SILABS_LOG("LWIP Task most bytes ever Free        0x%x", (lwipTaskValue * 4));
+#endif // CHIP_SYSTEM_CONFIG_USE_LWIP
+        SILABS_LOG("     ");
+        SILABS_LOG("=============================");
+        vTaskDelay(pdMS_TO_TICKS(5000));
+    }
+}
+
+extern "C" void memMonitoringTrackAlloc(void * ptr, size_t size)
+{
+    if (ptr != NULL)
+    {
+        nbAllocSuccess++;
+        if (largestBlockAllocated < size)
+        {
+            largestBlockAllocated = size;
+        }
+    }
+}
+
+extern "C" void memMonitoringTrackFree(void * ptr, size_t size)
+{
+    nbFreeSuccess++;
+}
diff --git a/examples/platform/silabs/SiWx917/OTAConfig.cpp b/examples/platform/silabs/SiWx917/OTAConfig.cpp
new file mode 100644
index 0000000..1056cf5
--- /dev/null
+++ b/examples/platform/silabs/SiWx917/OTAConfig.cpp
@@ -0,0 +1,101 @@
+/*
+ *
+ *    Copyright (c) 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.
+ */
+
+#include "OTAConfig.h"
+
+#include "application_properties.h"
+#include <app/server/Server.h>
+
+#if defined(SL_COMPONENT_CATALOG_PRESENT)
+#include "sl_component_catalog.h"
+#endif
+
+// Only include app properties if the Gecko SDK component that does it automatically isn't present
+#if !defined(SL_CATALOG_GECKO_BOOTLOADER_INTERFACE_PRESENT)
+// Header used for building the image GBL file
+#define APP_PROPERTIES_VERSION 1
+#define APP_PROPERTIES_ID                                                                                                          \
+    {                                                                                                                              \
+        0                                                                                                                          \
+    }
+
+__attribute__((used)) ApplicationProperties_t sl_app_properties = {
+    /// @brief Magic value indicating that this is an ApplicationProperties_t
+    /// Must equal @ref APPLICATION_PROPERTIES_MAGIC
+    .magic = APPLICATION_PROPERTIES_MAGIC,
+
+    /// Version number of this struct
+    .structVersion = APPLICATION_PROPERTIES_VERSION,
+
+    /// Type of signature this application is signed with
+    .signatureType = APPLICATION_SIGNATURE_NONE,
+
+    /// Location of the signature. Typically a pointer to the end of application
+    .signatureLocation = 0,
+
+    /// Information about the application
+    .app = {
+
+      /// Bitfield representing type of application
+      /// e.g. @ref APPLICATION_TYPE_BLUETOOTH_APP
+      .type = APPLICATION_TYPE_THREAD,
+
+      /// Version number for this application
+      .version = APP_PROPERTIES_VERSION,
+
+      /// Capabilities of this application
+      .capabilities = 0,
+
+      /// Unique ID (e.g. UUID/GUID) for the product this application is built for
+      .productId = APP_PROPERTIES_ID,
+    },
+
+    /// Pointer to information about the certificate
+    .cert = NULL,
+
+    /// Pointer to Long Token Data Section
+    .longTokenSectionAddress = NULL,
+};
+#endif // SL_CATALOG_GECKO_BOOTLOADER_INTERFACE_PRESENT
+
+// Global OTA objects
+chip::DefaultOTARequestor gRequestorCore;
+chip::DefaultOTARequestorStorage gRequestorStorage;
+chip::DeviceLayer::DefaultOTARequestorDriver gRequestorUser;
+chip::BDXDownloader gDownloader;
+chip::OTAImageProcessorImpl gImageProcessor;
+
+void OTAConfig::Init()
+{
+    // Initialize and interconnect the Requestor and Image Processor objects -- START
+    SetRequestorInstance(&gRequestorCore);
+
+    gRequestorStorage.Init(chip::Server::GetInstance().GetPersistentStorage());
+    gRequestorCore.Init(chip::Server::GetInstance(), gRequestorStorage, gRequestorUser, gDownloader);
+
+    // Periodic query timeout must be set prior to requestor being initialized
+    gRequestorUser.SetPeriodicQueryTimeout(OTA_PERIODIC_TIMEOUT);
+    gRequestorUser.Init(&gRequestorCore, &gImageProcessor);
+
+    gImageProcessor.SetOTAImageFile("test.txt");
+    gImageProcessor.SetOTADownloader(&gDownloader);
+
+    // Connect the Downloader and Image Processor objects
+    gDownloader.SetImageProcessorDelegate(&gImageProcessor);
+    // Initialize and interconnect the Requestor and Image Processor objects -- END
+}
diff --git a/examples/platform/silabs/SiWx917/OTAConfig.h b/examples/platform/silabs/SiWx917/OTAConfig.h
new file mode 100644
index 0000000..a4f8ac4
--- /dev/null
+++ b/examples/platform/silabs/SiWx917/OTAConfig.h
@@ -0,0 +1,34 @@
+/*
+ *
+ *    Copyright (c) 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.
+ */
+
+#pragma once
+
+#include <app/clusters/ota-requestor/BDXDownloader.h>
+#include <app/clusters/ota-requestor/DefaultOTARequestor.h>
+#include <app/clusters/ota-requestor/DefaultOTARequestorDriver.h>
+#include <app/clusters/ota-requestor/DefaultOTARequestorStorage.h>
+#include <platform/silabs/EFR32/OTAImageProcessorImpl.h>
+
+class OTAConfig
+{
+public:
+    OTAConfig(){};
+
+    static void Init();
+    static constexpr uint32_t kInitOTARequestorDelaySec = 3;
+};
diff --git a/examples/platform/silabs/SiWx917/TemperatureSensor.cpp b/examples/platform/silabs/SiWx917/TemperatureSensor.cpp
new file mode 100644
index 0000000..69ba106
--- /dev/null
+++ b/examples/platform/silabs/SiWx917/TemperatureSensor.cpp
@@ -0,0 +1,49 @@
+/*
+ *
+ *    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 "TemperatureSensor.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+// This is a C implementation. Need the ifdef __cplusplus else we get linking issues
+#include "sl_sensor_rht.h"
+
+#ifdef __cplusplus
+}
+#endif
+
+namespace TemperatureSensor {
+constexpr uint16_t kSensorTemperatureOffset = 800;
+
+sl_status_t Init()
+{
+    return sl_sensor_rht_init();
+}
+
+sl_status_t GetTemp(uint32_t * relativeHumidity, int16_t * temperature)
+{
+    // Sensor resolution 0.001 C
+    // DataModel resolution 0.01 C
+    int32_t temp;
+    sl_status_t status = sl_sensor_rht_get(relativeHumidity, &temp);
+    *temperature       = static_cast<int16_t>(temp / 10) - kSensorTemperatureOffset;
+    return status;
+}
+}; // namespace TemperatureSensor
diff --git a/examples/platform/silabs/SiWx917/TemperatureSensor.h b/examples/platform/silabs/SiWx917/TemperatureSensor.h
new file mode 100644
index 0000000..116287e
--- /dev/null
+++ b/examples/platform/silabs/SiWx917/TemperatureSensor.h
@@ -0,0 +1,28 @@
+/*
+ *
+ *    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.
+ */
+
+#pragma once
+
+#include "sl_status.h"
+#include <stdint.h>
+
+namespace TemperatureSensor {
+sl_status_t Init();
+sl_status_t GetTemp(uint32_t * relativeHumidity, int16_t * temperature);
+}; // namespace TemperatureSensor
diff --git a/examples/platform/silabs/SiWx917/args.gni b/examples/platform/silabs/SiWx917/args.gni
new file mode 100644
index 0000000..1726b62
--- /dev/null
+++ b/examples/platform/silabs/SiWx917/args.gni
@@ -0,0 +1,21 @@
+# 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")
+
+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>"
diff --git a/examples/platform/silabs/SiWx917/board_config.h b/examples/platform/silabs/SiWx917/board_config.h
new file mode 100644
index 0000000..8c495b4
--- /dev/null
+++ b/examples/platform/silabs/SiWx917/board_config.h
@@ -0,0 +1,54 @@
+/*
+ *  Copyright (c) 2018, 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
+ *   This file includes dev borad compile-time configuration constants for efr32.
+ *
+ */
+
+#pragma once
+
+/// Dev board suppports OQPSK modulation in 2.4GHz band.
+#define RADIO_CONFIG_2P4GHZ_OQPSK_SUPPORT 1
+#define RADIO_CONFIG_915MHZ_OQPSK_SUPPORT 0
+
+/// The PA(s) is(are) fed from the DCDC
+#if (BRD4166A)
+#define RADIO_CONFIG_PA_USES_DCDC 1
+#else
+#define RADIO_CONFIG_PA_USES_DCDC 0
+#endif
+
+#ifndef RADIO_CONFIG_DEBUG_COUNTERS_SUPPORT
+#define RADIO_CONFIG_DEBUG_COUNTERS_SUPPORT 0 /// Set to 1 to enable debug counters in radio.c
+#endif
+
+#ifndef RADIO_CONFIG_DMP_SUPPORT
+#define RADIO_CONFIG_DMP_SUPPORT 0 /// Set to 1 to enable Dynamic Multi-Protocol support in radio.c
+#endif
diff --git a/examples/platform/silabs/SiWx917/display/demo-ui-bitmaps.h b/examples/platform/silabs/SiWx917/display/demo-ui-bitmaps.h
new file mode 100644
index 0000000..4eca9c0
--- /dev/null
+++ b/examples/platform/silabs/SiWx917/display/demo-ui-bitmaps.h
@@ -0,0 +1,356 @@
+/***************************************************************************/ /**
+                                                                               * @file
+                                                                               * @brief User Interface bitmaps for demo.
+                                                                               *******************************************************************************
+                                                                               * # License
+                                                                               * <b>Copyright 2020 Silicon Laboratories Inc.
+                                                                               *www.silabs.com</b>
+                                                                               *******************************************************************************
+                                                                               *
+                                                                               * The licensor of this software is Silicon
+                                                                               *Laboratories Inc. Your use of this software is
+                                                                               *governed by the terms of Silicon Labs Master
+                                                                               *Software License Agreement (MSLA) available at
+                                                                               * www.silabs.com/about-us/legal/master-software-license-agreement.
+                                                                               *This software is distributed to you in Source Code
+                                                                               *format and is governed by the sections of the MSLA
+                                                                               *applicable to Source Code.
+                                                                               *
+                                                                               ******************************************************************************/
+
+#ifndef SILABS_DEMO_UI_BITMAPS_H
+#define SILABS_DEMO_UI_BITMAPS_H
+
+#define SILICONLABS_BITMAP_WIDTH 128
+#define SILICONLABS_BITMAP_HEIGHT 45
+
+#define ZIGBEE_BITMAP_WIDTH 16
+#define ZIGBEE_BITMAP_HEIGHT 16
+
+#define RAIL_BITMAP_WIDTH 16
+#define RAIL_BITMAP_HEIGHT 16
+
+#define CONNECT_BITMAP_WIDTH 16
+#define CONNECT_BITMAP_HEIGHT 16
+
+#define BLUETOOTH_BITMAP_WIDTH 16
+#define BLUETOOTH_BITMAP_HEIGHT 18
+
+#define SILABS_BITMAP                                                                                                              \
+    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,  \
+        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,    \
+        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,    \
+        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0f, 0xf0, 0xff, 0xff, 0xff, 0xf7, 0xff, 0xff,    \
+        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x1f, 0x00, 0x00, 0xf8, 0xff, 0xff, 0xcf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,    \
+        0xfd, 0xff, 0xff, 0x01, 0x00, 0x00, 0xc0, 0xff, 0xff, 0x1f, 0xff, 0xff, 0xff, 0xff, 0xff, 0x9f, 0xff, 0xff, 0x3f, 0x00,    \
+        0x00, 0x00, 0x00, 0xff, 0xff, 0x1f, 0xfc, 0xff, 0xff, 0xff, 0xff, 0xf3, 0xff, 0xff, 0x07, 0x00, 0x00, 0x00, 0x00, 0xfe,    \
+        0xff, 0x1f, 0xf8, 0xff, 0xff, 0xff, 0x7f, 0xfc, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0xfc, 0xff, 0x1f, 0xf0, 0xff,    \
+        0xff, 0xff, 0x1f, 0xff, 0xff, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0xff, 0x1f, 0xe0, 0xff, 0xff, 0xff, 0xc3, 0xff,    \
+        0xff, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0xff, 0x0f, 0xc0, 0xff, 0xff, 0xff, 0xf0, 0xff, 0xff, 0x07, 0x00, 0x00,    \
+        0x00, 0x00, 0x00, 0xff, 0xff, 0x07, 0xc0, 0xff, 0xff, 0x1f, 0xf8, 0xff, 0xff, 0x03, 0x00, 0x00, 0x00, 0x00, 0x80, 0xff,    \
+        0xff, 0x01, 0xc0, 0xff, 0xff, 0x07, 0xfc, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xff, 0x7f, 0x00, 0x80, 0xff,    \
+        0xff, 0x01, 0xfe, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x0f, 0x00, 0x80, 0xff, 0x7f, 0x00, 0xff, 0xff,    \
+        0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xff, 0x3f, 0x80, 0xff, 0xff, 0xff, 0x00, 0x00, 0xf0,    \
+        0xff, 0xff, 0x01, 0x00, 0x00, 0x00, 0xc0, 0xff, 0x0f, 0x80, 0xff, 0xff, 0xff, 0x00, 0xfc, 0xff, 0xff, 0xff, 0xff, 0x01,    \
+        0x00, 0x00, 0xc0, 0xff, 0x03, 0xc0, 0xff, 0xff, 0xff, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xff, 0x1f, 0x00, 0x00, 0xe0, 0xff,    \
+        0x01, 0xc0, 0xff, 0xff, 0xff, 0xf1, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xe0, 0xff, 0x00, 0xc0, 0xff, 0xff,    \
+        0xff, 0xc3, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x01, 0x00, 0xf0, 0x7f, 0x00, 0x80, 0xff, 0xff, 0xff, 0x0f, 0xfc, 0xff,    \
+        0xff, 0xff, 0xff, 0xff, 0x07, 0x00, 0xf8, 0x3f, 0x00, 0x80, 0xff, 0xff, 0xff, 0x3f, 0x00, 0x00, 0xfe, 0xff, 0xff, 0xff,    \
+        0x0f, 0x00, 0xfc, 0x1f, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0x07, 0xc0, 0xff, 0xff, 0xff, 0x0f, 0x00, 0xfe, 0x0f,    \
+        0x00, 0x00, 0xfc, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x1f, 0x00, 0xff, 0x07, 0x00, 0x00, 0xf0, 0xff,    \
+        0xff, 0xff, 0xff, 0xff, 0x3f, 0xfc, 0xff, 0xff, 0x1f, 0x80, 0xff, 0x07, 0x00, 0x00, 0xc0, 0xff, 0xff, 0xff, 0xff, 0xff,    \
+        0x3f, 0xf8, 0xff, 0xff, 0x1f, 0xc0, 0xff, 0x03, 0x00, 0x00, 0x00, 0xfc, 0xff, 0xff, 0xff, 0xff, 0x00, 0xf0, 0xff, 0xff,    \
+        0x0f, 0xf0, 0xff, 0x03, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xff, 0x3f, 0x00, 0x00, 0xf0, 0xff, 0xff, 0x0f, 0xfc, 0xff, 0x03,    \
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0xff, 0xff, 0x07, 0xfe, 0xff, 0x01, 0x00, 0x00, 0x3f, 0x00,    \
+        0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xff, 0xff, 0x83, 0xff, 0xff, 0x01, 0x00, 0xc0, 0xff, 0x07, 0x00, 0x00, 0x00, 0x00,    \
+        0x00, 0xfc, 0xff, 0xff, 0xe1, 0xff, 0xff, 0x03, 0x00, 0xf0, 0xff, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0xff, 0xff,    \
+        0xf8, 0xff, 0xff, 0x03, 0x00, 0xf8, 0xff, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x3f, 0xff, 0xff, 0xff, 0x03,    \
+        0x00, 0xfe, 0xff, 0x03, 0x00, 0x00, 0x00, 0x00, 0x80, 0xff, 0xff, 0xdf, 0xff, 0xff, 0xff, 0x07, 0x00, 0xff, 0xff, 0x01,    \
+        0x00, 0x00, 0x00, 0x00, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0f, 0x80, 0xff, 0xff, 0x03, 0x00, 0x00, 0x00, 0x00,    \
+        0xf8, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x1f, 0xc0, 0xff, 0xff, 0x07, 0x00, 0x00, 0x00, 0x80, 0xff, 0xff, 0xff, 0xff,    \
+        0xff, 0xff, 0xff, 0x3f, 0xc0, 0xff, 0xff, 0x1f, 0x00, 0x00, 0x00, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,    \
+        0xc0, 0xff, 0xff, 0xff, 0x00, 0x00, 0x80, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x81, 0xff, 0xff, 0xff,    \
+        0x1f, 0x00, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,    \
+        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,    \
+        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
+
+#define THREAD_BITMAP_WIDTH 16
+#define THREAD_BITMAP_HEIGHT 18
+
+#define THREAD_BITMAP                                                                                                              \
+    0x1F, 0xF8, 0x07, 0xE0, 0x03, 0xCE, 0x01, 0x9F, 0x01, 0xB3, 0x00, 0x33, 0xF0, 0x3F, 0xF8, 0x1F, 0x0C, 0x03, 0x0C, 0x03, 0x18,  \
+        0x03, 0x11, 0x83, 0x01, 0x83, 0x03, 0xC3, 0x07, 0xE3, 0x1F, 0xFB, 0x7f, 0xff, 0xff, 0xff
+
+#define WIFI_BITMAP_WIDTH 18
+#define WIFI_BITMAP_HEIGHT 18
+
+#define WIFI_BITMAP                                                                                                                \
+    0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x03, 0xFF, 0x01, 0xE0, 0x03, 0x00, 0xC7, 0xFF, 0xB8, 0xFF, 0xF7, 0x07, 0xF8, 0x0F, 0xC0, 0x3F,  \
+        0x3F, 0xFF, 0xFF, 0xFF, 0x3F, 0xFF, 0x7F, 0xF8, 0xFF, 0xE1, 0xFF, 0xCF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x0F
+
+#define MATTER_LOGO_WIDTH 18
+#define MATTER_LOGO_HEIGHT 17
+
+#define MATTER_LOGO_BITMAP                                                                                                         \
+    0xFF, 0xFF, 0xFF, 0xF3, 0xFF, 0xCF, 0xFF, 0x3F, 0xFF, 0xFF, 0xFC, 0x3F, 0x12, 0xFF, 0x01, 0xFE, 0xFF, 0xFF, 0xF3, 0x3F, 0x8F,  \
+        0x7F, 0xFC, 0xFC, 0xFC, 0xE3, 0xF1, 0x87, 0x87, 0xC7, 0xDE, 0x88, 0x33, 0xC7, 0xCF, 0xFC, 0xFF, 0xFF, 0x03
+
+// APP Logo, boolean only. must be 64x64
+#if IS_DEMO_SWITCH
+#define ON_DEMO_BITMAP                                                                                                             \
+    0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,  \
+        0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0x7F, 0x00, 0x00, 0x00, 0x00, 0xFE, 0xFF, 0xFF,    \
+        0x3F, 0x00, 0x00, 0x00, 0x00, 0xFC, 0xFF, 0xFF, 0x3F, 0x00, 0x00, 0x00, 0x00, 0xFC, 0xFF, 0xFF, 0x1F, 0x00, 0x00, 0x00,    \
+        0x00, 0xF8, 0xFF, 0xFF, 0x1F, 0x00, 0x00, 0x00, 0x00, 0xF8, 0xFF, 0xFF, 0x1F, 0x00, 0x00, 0x00, 0x00, 0xF8, 0xFF, 0xFF,    \
+        0x1F, 0x00, 0x00, 0x00, 0x00, 0xF8, 0xFF, 0xFF, 0x1F, 0xC0, 0xFF, 0xFF, 0x03, 0xF8, 0xFF, 0xFF, 0x1F, 0xE0, 0xFF, 0xFF,    \
+        0x07, 0xF8, 0xFF, 0xFF, 0x1F, 0xE0, 0xFF, 0xFF, 0x07, 0xF8, 0xFF, 0xFF, 0x1F, 0xE0, 0xFF, 0xFF, 0x07, 0xF8, 0xFF, 0xFF,    \
+        0x1F, 0xE0, 0xFF, 0xFF, 0x07, 0xF8, 0xFF, 0xFF, 0x1F, 0xE0, 0xFF, 0xFF, 0x07, 0xF8, 0xFF, 0xFF, 0x1F, 0xE0, 0xFF, 0xFF,    \
+        0x07, 0xF8, 0xFF, 0xFF, 0x1F, 0xE0, 0xFF, 0xFF, 0x07, 0xF8, 0xFF, 0xFF, 0x1F, 0xE0, 0xFF, 0xFF, 0x07, 0xF8, 0xFF, 0xFF,    \
+        0x1F, 0xC0, 0xFF, 0xFF, 0x03, 0xF8, 0xFF, 0xFF, 0x1F, 0x00, 0x00, 0x00, 0x00, 0xF8, 0xFF, 0xFF, 0x1F, 0x00, 0x00, 0x00,    \
+        0x00, 0xF8, 0xFF, 0xFF, 0x1F, 0x00, 0x00, 0x00, 0x00, 0xF8, 0xFF, 0xFF, 0x1F, 0x00, 0x00, 0x00, 0x00, 0xF8, 0xFF, 0xFF,    \
+        0x1F, 0x00, 0x00, 0x00, 0x00, 0xF8, 0xFF, 0xFF, 0x1F, 0x00, 0x00, 0x00, 0x00, 0xF8, 0xFF, 0xFF, 0x1F, 0x00, 0x00, 0x00,    \
+        0x00, 0xF8, 0xFF, 0xFF, 0x1F, 0x00, 0x00, 0x00, 0x00, 0xF8, 0xFF, 0xFF, 0x1F, 0x00, 0x00, 0x00, 0x00, 0xF8, 0xFF, 0xFF,    \
+        0x1F, 0x00, 0x00, 0x00, 0x00, 0xF8, 0xFF, 0xFF, 0x1F, 0x00, 0x00, 0x00, 0x00, 0xF8, 0xFF, 0xFF, 0x1F, 0x00, 0x00, 0x00,    \
+        0x00, 0xF8, 0xFF, 0xFF, 0x1F, 0x00, 0x00, 0x00, 0x00, 0xF8, 0xFF, 0xFF, 0x1F, 0x00, 0x00, 0x00, 0x00, 0xF8, 0xFF, 0xFF,    \
+        0x1F, 0x00, 0x00, 0x00, 0x00, 0xF8, 0xFF, 0xFF, 0x1F, 0x00, 0x00, 0x00, 0x00, 0xF8, 0xFF, 0xFF, 0x1F, 0x00, 0x00, 0x00,    \
+        0x00, 0xF8, 0xFF, 0xFF, 0x1F, 0x00, 0x00, 0x00, 0x00, 0xF8, 0xFF, 0xFF, 0x1F, 0x00, 0x00, 0x00, 0x00, 0xF8, 0xFF, 0xFF,    \
+        0x1F, 0x00, 0x00, 0x00, 0x00, 0xF8, 0xFF, 0xFF, 0x1F, 0x00, 0x00, 0x00, 0x00, 0xF8, 0xFF, 0xFF, 0x1F, 0x00, 0x00, 0x00,    \
+        0x00, 0xF8, 0xFF, 0xFF, 0x1F, 0x00, 0x00, 0x00, 0x00, 0xF8, 0xFF, 0xFF, 0x1F, 0x00, 0x00, 0x00, 0x00, 0xF8, 0xFF, 0xFF,    \
+        0x1F, 0x00, 0x00, 0x00, 0x00, 0xF8, 0xFF, 0xFF, 0x1F, 0x00, 0x00, 0x00, 0x00, 0xF8, 0xFF, 0xFF, 0x1F, 0x00, 0x00, 0x00,    \
+        0x00, 0xF8, 0xFF, 0xFF, 0x1F, 0x00, 0x00, 0x00, 0x00, 0xF8, 0xFF, 0xFF, 0x1F, 0x00, 0x00, 0x00, 0x00, 0xF8, 0xFF, 0xFF,    \
+        0x1F, 0x00, 0x00, 0x00, 0x00, 0xF8, 0xFF, 0xFF, 0x1F, 0x00, 0x00, 0x00, 0x00, 0xF8, 0xFF, 0xFF, 0x1F, 0x00, 0x00, 0x00,    \
+        0x00, 0xF8, 0xFF, 0xFF, 0x1F, 0x00, 0x00, 0x00, 0x00, 0xF8, 0xFF, 0xFF, 0x1F, 0x00, 0x00, 0x00, 0x00, 0xF8, 0xFF, 0xFF,    \
+        0x1F, 0x00, 0x00, 0x00, 0x00, 0xF8, 0xFF, 0xFF, 0x1F, 0x00, 0x00, 0x00, 0x00, 0xF8, 0xFF, 0xFF, 0x3F, 0x00, 0x00, 0x00,    \
+        0x00, 0xFC, 0xFF, 0xFF, 0x3F, 0x00, 0x00, 0x00, 0x00, 0xFC, 0xFF, 0xFF, 0x7F, 0x00, 0x00, 0x00, 0x00, 0xFE, 0xFF, 0xFF,    \
+        0xFF, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,    \
+        0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
+
+#define OFF_DEMO_BITMAP                                                                                                            \
+    0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,  \
+        0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x00, 0x00, 0x80, 0xFF, 0xFF, 0xFF, 0x7F, 0x00, 0x00, 0x00, 0x00, 0xFE, 0xFF, 0xFF,    \
+        0x3F, 0x00, 0x00, 0x00, 0x00, 0xFC, 0xFF, 0xFF, 0x3F, 0x00, 0x00, 0x00, 0x00, 0xFC, 0xFF, 0xFF, 0x3F, 0x00, 0x00, 0x00,    \
+        0x00, 0xFC, 0xFF, 0xFF, 0x3F, 0xF8, 0xFF, 0xFF, 0x1F, 0xFC, 0xFF, 0xFF, 0x3F, 0xF8, 0xFF, 0xFF, 0x1F, 0xFC, 0xFF, 0xFF,    \
+        0x3F, 0xFC, 0xFF, 0xFF, 0x3F, 0xFC, 0xFF, 0xFF, 0x3F, 0xFC, 0xFF, 0xFF, 0x3F, 0xFC, 0xFF, 0xFF, 0x3F, 0xFC, 0xFF, 0xFF,    \
+        0x3F, 0xFC, 0xFF, 0xFF, 0x3F, 0xFC, 0xFF, 0xFF, 0x3F, 0xFC, 0xFF, 0xFF, 0x3F, 0xFC, 0xFF, 0xFF, 0x3F, 0xFC, 0xFF, 0xFF,    \
+        0x3F, 0xFC, 0xFF, 0xFF, 0x3F, 0xFC, 0xFF, 0xFF, 0x3F, 0xFC, 0xFF, 0xFF, 0x3F, 0xFC, 0xFF, 0xFF, 0x3F, 0xFC, 0xFF, 0xFF,    \
+        0x3F, 0xFC, 0xFF, 0xFF, 0x3F, 0xFC, 0xFF, 0xFF, 0x3F, 0xFC, 0xFF, 0xFF, 0x3F, 0xFC, 0xFF, 0xFF, 0x3F, 0xFC, 0xFF, 0xFF,    \
+        0x3F, 0xFC, 0xFF, 0xFF, 0x3F, 0xFC, 0xFF, 0xFF, 0x3F, 0xFC, 0xFF, 0xFF, 0x3F, 0xFC, 0xFF, 0xFF, 0x3F, 0xFC, 0xFF, 0xFF,    \
+        0x3F, 0xFC, 0xFF, 0xFF, 0x3F, 0xFC, 0xFF, 0xFF, 0x3F, 0xFC, 0xFF, 0xFF, 0x3F, 0xFC, 0xFF, 0xFF, 0x3F, 0xFC, 0xFF, 0xFF,    \
+        0x3F, 0xFC, 0xFF, 0xFF, 0x3F, 0xFC, 0xFF, 0xFF, 0x3F, 0xFC, 0xFF, 0xFF, 0x3F, 0xFC, 0xFF, 0xFF, 0x3F, 0xFC, 0xFF, 0xFF,    \
+        0x3F, 0xFC, 0xFF, 0xFF, 0x3F, 0xFC, 0xFF, 0xFF, 0x3F, 0xFC, 0xFF, 0xFF, 0x3F, 0xFC, 0xFF, 0xFF, 0x3F, 0xFC, 0xFF, 0xFF,    \
+        0x3F, 0xFC, 0xFF, 0xFF, 0x3F, 0xFC, 0xFF, 0xFF, 0x3F, 0xFC, 0xFF, 0xFF, 0x3F, 0xFC, 0xFF, 0xFF, 0x3F, 0xFC, 0xFF, 0xFF,    \
+        0x3F, 0xFC, 0xFF, 0xFF, 0x3F, 0xFC, 0xFF, 0xFF, 0x3F, 0xFC, 0xFF, 0xFF, 0x3F, 0xFC, 0xFF, 0xFF, 0x3F, 0xFC, 0xFF, 0xFF,    \
+        0x3F, 0xFC, 0xFF, 0xFF, 0x3F, 0xFC, 0xFF, 0xFF, 0x3F, 0xFC, 0xFF, 0xFF, 0x3F, 0xFC, 0xFF, 0xFF, 0x3F, 0xFC, 0xFF, 0xFF,    \
+        0x3F, 0xFC, 0xFF, 0xFF, 0x3F, 0xFC, 0xFF, 0xFF, 0x3F, 0xFC, 0xFF, 0xFF, 0x3F, 0xFC, 0xFF, 0xFF, 0x3F, 0xFC, 0xFF, 0xFF,    \
+        0x3F, 0xFC, 0xFF, 0xFF, 0x3F, 0xFC, 0xFF, 0xFF, 0x3F, 0xFC, 0xFF, 0xFF, 0x3F, 0xFC, 0xFF, 0xFF, 0x3F, 0xFC, 0xFF, 0xFF,    \
+        0x3F, 0xFC, 0xFF, 0xFF, 0x3F, 0x3C, 0x00, 0x00, 0x3C, 0xFC, 0xFF, 0xFF, 0x3F, 0x3C, 0x00, 0x00, 0x3C, 0xFC, 0xFF, 0xFF,    \
+        0x3F, 0x3C, 0x00, 0x00, 0x3C, 0xFC, 0xFF, 0xFF, 0x3F, 0x3C, 0x00, 0x00, 0x3C, 0xFC, 0xFF, 0xFF, 0x3F, 0x3C, 0x00, 0x00,    \
+        0x3C, 0xFC, 0xFF, 0xFF, 0x3F, 0x3C, 0x00, 0x00, 0x3C, 0xFC, 0xFF, 0xFF, 0x3F, 0x3C, 0x00, 0x00, 0x3C, 0xFC, 0xFF, 0xFF,    \
+        0x3F, 0x3C, 0x00, 0x00, 0x3C, 0xFC, 0xFF, 0xFF, 0x3F, 0x3C, 0x00, 0x00, 0x3C, 0xFC, 0xFF, 0xFF, 0x3F, 0x3C, 0x00, 0x00,    \
+        0x3C, 0xFC, 0xFF, 0xFF, 0x3F, 0xFC, 0xFF, 0xFF, 0x3F, 0xFC, 0xFF, 0xFF, 0x3F, 0xF8, 0xFF, 0xFF, 0x1F, 0xFC, 0xFF, 0xFF,    \
+        0x3F, 0xF8, 0xFF, 0xFF, 0x1F, 0xFC, 0xFF, 0xFF, 0x3F, 0x00, 0x00, 0x00, 0x00, 0xFC, 0xFF, 0xFF, 0x3F, 0x00, 0x00, 0x00,    \
+        0x00, 0xFC, 0xFF, 0xFF, 0x3F, 0x00, 0x00, 0x00, 0x00, 0xFC, 0xFF, 0xFF, 0x7F, 0x00, 0x00, 0x00, 0x00, 0xFE, 0xFF, 0xFF,    \
+        0xFF, 0x01, 0x00, 0x00, 0x80, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,    \
+        0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
+#elif IS_DEMO_LIGHT
+#define ON_DEMO_BITMAP                                                                                                             \
+    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0xfc,  \
+        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0xfc, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0xfc, 0xff, 0xff, 0xff, 0xff,    \
+        0xff, 0xff, 0x7f, 0xfc, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0xfc, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0xfc,    \
+        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0xfc, 0xff, 0xff, 0xff, 0xff, 0xcf, 0xff, 0xff, 0xff, 0xff, 0xf3, 0xff, 0xff,    \
+        0x8f, 0xff, 0xff, 0xff, 0xff, 0xf1, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xf0, 0xff, 0xff, 0x1f, 0xfe, 0x07, 0xe0,    \
+        0x7f, 0xf8, 0xff, 0xff, 0x3f, 0xfc, 0x00, 0x00, 0x3f, 0xfc, 0xff, 0xff, 0x7f, 0x3c, 0xe0, 0x07, 0x3c, 0xfe, 0xff, 0xff,    \
+        0xff, 0x1f, 0xfe, 0x7f, 0xf8, 0xff, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xc7, 0xff, 0xff,    \
+        0xe3, 0xff, 0xff, 0xff, 0xff, 0xe3, 0xff, 0xff, 0xc7, 0xff, 0xff, 0xff, 0xff, 0xf1, 0xff, 0xff, 0x8f, 0xff, 0xff, 0xff,    \
+        0xff, 0xf1, 0xff, 0xff, 0x8f, 0xff, 0xff, 0xff, 0xff, 0xf8, 0xff, 0xff, 0x1f, 0xff, 0xff, 0xff, 0x7f, 0xfc, 0xff, 0xff,    \
+        0x3f, 0xfe, 0xff, 0xff, 0x7f, 0xfc, 0xff, 0xff, 0x3f, 0xfe, 0xff, 0xff, 0x7f, 0xfc, 0xff, 0xff, 0x3f, 0xfe, 0xff, 0xff,    \
+        0x7f, 0xfe, 0xff, 0xff, 0x7f, 0xfe, 0xff, 0xff, 0x3f, 0xfe, 0xff, 0xff, 0x7f, 0xfc, 0xff, 0xff, 0x3f, 0xfe, 0xff, 0xff,    \
+        0x7f, 0xfc, 0xff, 0x0f, 0x38, 0xfe, 0xff, 0xff, 0x7f, 0x1c, 0xf0, 0x0f, 0x38, 0xfe, 0x03, 0xc0, 0x7f, 0x1c, 0xf0, 0x0f,    \
+        0x38, 0xfe, 0x27, 0xe9, 0x7f, 0x1c, 0xf0, 0xff, 0x3f, 0xfe, 0xff, 0xff, 0x7f, 0xfc, 0xff, 0xff, 0x3f, 0xfe, 0xff, 0xff,    \
+        0x7f, 0xfc, 0xff, 0xff, 0x3f, 0xfe, 0xe7, 0xe7, 0x7f, 0xfc, 0xff, 0xff, 0x7f, 0xfe, 0xef, 0xf7, 0x7f, 0xfe, 0xff, 0xff,    \
+        0x7f, 0xfc, 0xef, 0xf7, 0x3f, 0xfe, 0xff, 0xff, 0xff, 0xfc, 0xef, 0xf3, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xf8, 0xcf, 0xf3,    \
+        0x1f, 0xff, 0xff, 0xff, 0xff, 0xf8, 0xdf, 0xfb, 0x1f, 0xff, 0xff, 0xff, 0xff, 0xf1, 0xdf, 0xfb, 0x8f, 0xff, 0xff, 0xff,    \
+        0xff, 0xe3, 0x9f, 0xf9, 0xc7, 0xff, 0xff, 0xff, 0xff, 0xc3, 0x9f, 0xf9, 0xc3, 0xff, 0xff, 0xff, 0xff, 0xc7, 0x9f, 0xfd,    \
+        0xe3, 0xff, 0xff, 0xff, 0xff, 0x8f, 0xbf, 0xfd, 0xf1, 0xff, 0xff, 0xff, 0xff, 0x1f, 0x3f, 0xfc, 0xf8, 0xff, 0xff, 0xff,    \
+        0xff, 0x3f, 0x3e, 0x7c, 0xfc, 0xff, 0xff, 0xff, 0xff, 0x7f, 0xfc, 0x3f, 0xfe, 0xff, 0xff, 0xff, 0xff, 0x7f, 0xfc, 0x3f,    \
+        0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x1f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,    \
+        0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x1f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x1f,    \
+        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x1f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,    \
+        0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x1f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf1, 0x8f,    \
+        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x01, 0x80, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x03, 0xc0, 0xff, 0xff, 0xff, 0xff,    \
+        0xff, 0xff, 0x3f, 0xfc, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,    \
+        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
+
+#define OFF_DEMO_BITMAP                                                                                                            \
+    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,  \
+        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,    \
+        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,    \
+        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,    \
+        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x07, 0xe0,    \
+        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, 0xe0, 0x07, 0xfc, 0xff, 0xff, 0xff,    \
+        0xff, 0x1f, 0xfe, 0x7f, 0xf8, 0xff, 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xc7, 0xff, 0xff,    \
+        0xe3, 0xff, 0xff, 0xff, 0xff, 0xe3, 0xff, 0xff, 0xc7, 0xff, 0xff, 0xff, 0xff, 0xf1, 0xff, 0xff, 0x8f, 0xff, 0xff, 0xff,    \
+        0xff, 0xf1, 0xff, 0xff, 0x8f, 0xff, 0xff, 0xff, 0xff, 0xf8, 0xff, 0xff, 0x1f, 0xff, 0xff, 0xff, 0x7f, 0xfc, 0xff, 0xff,    \
+        0x3f, 0xfe, 0xff, 0xff, 0x7f, 0xfc, 0xff, 0xff, 0x3f, 0xfe, 0xff, 0xff, 0x7f, 0xfc, 0xff, 0xff, 0x3f, 0xfe, 0xff, 0xff,    \
+        0x7f, 0xfe, 0xff, 0xff, 0x7f, 0xfe, 0xff, 0xff, 0x3f, 0xfe, 0xff, 0xff, 0x7f, 0xfc, 0xff, 0xff, 0x3f, 0xfe, 0xff, 0xff,    \
+        0x7f, 0xfc, 0xff, 0xff, 0x3f, 0xfe, 0xff, 0xff, 0x7f, 0xfc, 0xff, 0xff, 0x3f, 0xfe, 0xff, 0xff, 0x7f, 0xfc, 0xff, 0xff,    \
+        0x3f, 0xfe, 0xff, 0xff, 0x7f, 0xfc, 0xff, 0xff, 0x3f, 0xfe, 0xff, 0xff, 0x7f, 0xfc, 0xff, 0xff, 0x3f, 0xfe, 0xff, 0xff,    \
+        0x7f, 0xfc, 0xff, 0xff, 0x3f, 0xfe, 0xff, 0xff, 0x7f, 0xfc, 0xff, 0xff, 0x7f, 0xfe, 0xff, 0xff, 0x7f, 0xfe, 0xff, 0xff,    \
+        0x7f, 0xfc, 0xff, 0xff, 0x3f, 0xfe, 0xff, 0xff, 0xff, 0xfc, 0xff, 0xff, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xf8, 0xff, 0xff,    \
+        0x1f, 0xff, 0xff, 0xff, 0xff, 0xf8, 0xff, 0xff, 0x1f, 0xff, 0xff, 0xff, 0xff, 0xf1, 0xff, 0xff, 0x8f, 0xff, 0xff, 0xff,    \
+        0xff, 0xe3, 0xff, 0xff, 0xc7, 0xff, 0xff, 0xff, 0xff, 0xc3, 0xff, 0xff, 0xc3, 0xff, 0xff, 0xff, 0xff, 0xc7, 0xff, 0xff,    \
+        0xe3, 0xff, 0xff, 0xff, 0xff, 0x8f, 0xff, 0xff, 0xf1, 0xff, 0xff, 0xff, 0xff, 0x1f, 0xff, 0xff, 0xf8, 0xff, 0xff, 0xff,    \
+        0xff, 0x3f, 0xfe, 0x7f, 0xfc, 0xff, 0xff, 0xff, 0xff, 0x7f, 0xfc, 0x3f, 0xfe, 0xff, 0xff, 0xff, 0xff, 0x7f, 0xfc, 0x3f,    \
+        0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x1f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,    \
+        0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x1f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x1f,    \
+        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x1f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,    \
+        0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x1f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf1, 0x8f,    \
+        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x01, 0x80, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x03, 0xc0, 0xff, 0xff, 0xff, 0xff,    \
+        0xff, 0xff, 0x3f, 0xfc, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,    \
+        0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
+#elif IS_DEMO_LOCK
+#define ON_DEMO_BITMAP                                                                                                             \
+    0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,  \
+        0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x1F, 0xF8, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x03, 0xC0, 0xFF, 0xFF, 0xFF, 0xFF,    \
+        0xFF, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0x00, 0x00, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0x3F, 0x00, 0x00,    \
+        0xFC, 0xFF, 0xFF, 0xFF, 0xFF, 0x1F, 0xE0, 0x07, 0xF8, 0xFF, 0xFF, 0xFF, 0xFF, 0x1F, 0xF8, 0x1F, 0xF8, 0xFF, 0xFF, 0xFF,    \
+        0xFF, 0x0F, 0xFC, 0x3F, 0xF0, 0xFF, 0xFF, 0xFF, 0xFF, 0x0F, 0xFE, 0x7F, 0xF0, 0xFF, 0xFF, 0xFF, 0xFF, 0x0F, 0xFE, 0x7F,    \
+        0xF0, 0xFF, 0xFF, 0xFF, 0xFF, 0x07, 0xFF, 0xFF, 0xE0, 0xFF, 0xFF, 0xFF, 0xFF, 0x07, 0xFF, 0xFF, 0xE0, 0xFF, 0xFF, 0xFF,    \
+        0xFF, 0x07, 0xFF, 0xFF, 0xE0, 0xFF, 0xFF, 0xFF, 0xFF, 0x07, 0xFF, 0xFF, 0xE0, 0xFF, 0xFF, 0xFF, 0xFF, 0x07, 0xFF, 0xFF,    \
+        0xE0, 0xFF, 0xFF, 0xFF, 0xFF, 0x07, 0xFF, 0xFF, 0xE0, 0xFF, 0xFF, 0xFF, 0xFF, 0x07, 0xFF, 0xFF, 0xE0, 0xFF, 0xFF, 0xFF,    \
+        0xFF, 0x07, 0xFF, 0xFF, 0xE0, 0xFF, 0xFF, 0xFF, 0xFF, 0x07, 0xFF, 0xFF, 0xE0, 0xFF, 0xFF, 0xFF, 0x1F, 0x00, 0x00, 0x00,    \
+        0x00, 0xF8, 0xFF, 0xFF, 0x0F, 0x00, 0x00, 0x00, 0x00, 0xF0, 0xFF, 0xFF, 0x07, 0x00, 0x00, 0x00, 0x00, 0xE0, 0xFF, 0xFF,    \
+        0x07, 0x00, 0x00, 0x00, 0x00, 0xE0, 0xFF, 0xFF, 0x07, 0x00, 0x00, 0x00, 0x00, 0xE0, 0xFF, 0xFF, 0x07, 0x00, 0x00, 0x00,    \
+        0x00, 0xE0, 0xFF, 0xFF, 0x07, 0x00, 0x00, 0x00, 0x00, 0xE0, 0xFF, 0xFF, 0x07, 0x00, 0x00, 0x00, 0x00, 0xE0, 0xFF, 0xFF,    \
+        0x07, 0x00, 0x00, 0x00, 0x00, 0xE0, 0xFF, 0xFF, 0x07, 0x00, 0x00, 0x00, 0x00, 0xE0, 0xFF, 0xFF, 0x07, 0x00, 0x00, 0x00,    \
+        0x00, 0xE0, 0xFF, 0xFF, 0x07, 0x00, 0x00, 0x00, 0x00, 0xE0, 0xFF, 0xFF, 0x07, 0x00, 0x80, 0x01, 0x00, 0xE0, 0xFF, 0xFF,    \
+        0x07, 0x00, 0xE0, 0x07, 0x00, 0xE0, 0xFF, 0xFF, 0x07, 0x00, 0xF0, 0x0F, 0x00, 0xE0, 0xFF, 0xFF, 0x07, 0x00, 0xF8, 0x1F,    \
+        0x00, 0xE0, 0xFF, 0xFF, 0x07, 0x00, 0xF8, 0x1F, 0x00, 0xE0, 0xFF, 0xFF, 0x07, 0x00, 0xFC, 0x3F, 0x00, 0xE0, 0xFF, 0xFF,    \
+        0x07, 0x00, 0xFC, 0x3F, 0x00, 0xE0, 0xFF, 0xFF, 0x07, 0x00, 0xF8, 0x1F, 0x00, 0xE0, 0xFF, 0xFF, 0x07, 0x00, 0xF8, 0x1F,    \
+        0x00, 0xE0, 0xFF, 0xFF, 0x07, 0x00, 0xF0, 0x0F, 0x00, 0xE0, 0xFF, 0xFF, 0x07, 0x00, 0xE0, 0x07, 0x00, 0xE0, 0xFF, 0xFF,    \
+        0x07, 0x00, 0x80, 0x01, 0x00, 0xE0, 0xFF, 0xFF, 0x07, 0x00, 0x00, 0x00, 0x00, 0xE0, 0xFF, 0xFF, 0x07, 0x00, 0x00, 0x00,    \
+        0x00, 0xE0, 0xFF, 0xFF, 0x07, 0x00, 0x00, 0x00, 0x00, 0xE0, 0xFF, 0xFF, 0x07, 0x00, 0x00, 0x00, 0x00, 0xE0, 0xFF, 0xFF,    \
+        0x07, 0x00, 0x00, 0x00, 0x00, 0xE0, 0xFF, 0xFF, 0x07, 0x00, 0x00, 0x00, 0x00, 0xE0, 0xFF, 0xFF, 0x07, 0x00, 0x00, 0x00,    \
+        0x00, 0xE0, 0xFF, 0xFF, 0x07, 0x00, 0x00, 0x00, 0x00, 0xE0, 0xFF, 0xFF, 0x07, 0x00, 0x00, 0x00, 0x00, 0xE0, 0xFF, 0xFF,    \
+        0x07, 0x00, 0x00, 0x00, 0x00, 0xE0, 0xFF, 0xFF, 0x0F, 0x00, 0x00, 0x00, 0x00, 0xF0, 0xFF, 0xFF, 0x1F, 0x00, 0x00, 0x00,    \
+        0x00, 0xF8, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,    \
+        0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,    \
+        0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
+
+#define OFF_DEMO_BITMAP                                                                                                            \
+    0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,  \
+        0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x1F, 0xF8, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x03, 0xC0, 0xFF, 0xFF, 0xFF, 0xFF,    \
+        0xFF, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0x00, 0x00, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0x3F, 0x00, 0x00,    \
+        0xFC, 0xFF, 0xFF, 0xFF, 0xFF, 0x1F, 0xE0, 0x07, 0xF8, 0xFF, 0xFF, 0xFF, 0xFF, 0x1F, 0xF8, 0x1F, 0xF8, 0xFF, 0xFF, 0xFF,    \
+        0xFF, 0x0F, 0xFC, 0x3F, 0xF0, 0xFF, 0xFF, 0xFF, 0xFF, 0x0F, 0xFE, 0x7F, 0xF0, 0xFF, 0xFF, 0xFF, 0xFF, 0x0F, 0xFE, 0x7F,    \
+        0xF0, 0xFF, 0xFF, 0xFF, 0xFF, 0x07, 0xFF, 0xFF, 0xE0, 0xFF, 0xFF, 0xFF, 0xFF, 0x07, 0xFF, 0xFF, 0xE0, 0xFF, 0xFF, 0xFF,    \
+        0xFF, 0x07, 0xFF, 0xFF, 0xE0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xE0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,    \
+        0xE0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xE0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xE0, 0xFF, 0xFF, 0xFF,    \
+        0xFF, 0xFF, 0xFF, 0xFF, 0xE0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xE0, 0xFF, 0xFF, 0xFF, 0x1F, 0x00, 0x00, 0x00,    \
+        0x00, 0xF8, 0xFF, 0xFF, 0x0F, 0x00, 0x00, 0x00, 0x00, 0xF0, 0xFF, 0xFF, 0x07, 0x00, 0x00, 0x00, 0x00, 0xE0, 0xFF, 0xFF,    \
+        0x07, 0x00, 0x00, 0x00, 0x00, 0xE0, 0xFF, 0xFF, 0x07, 0x00, 0x00, 0x00, 0x00, 0xE0, 0xFF, 0xFF, 0x07, 0x00, 0x00, 0x00,    \
+        0x00, 0xE0, 0xFF, 0xFF, 0x07, 0x00, 0x00, 0x00, 0x00, 0xE0, 0xFF, 0xFF, 0x07, 0x00, 0x00, 0x00, 0x00, 0xE0, 0xFF, 0xFF,    \
+        0x07, 0x00, 0x00, 0x00, 0x00, 0xE0, 0xFF, 0xFF, 0x07, 0x00, 0x00, 0x00, 0x00, 0xE0, 0xFF, 0xFF, 0x07, 0x00, 0x00, 0x00,    \
+        0x00, 0xE0, 0xFF, 0xFF, 0x07, 0x00, 0x00, 0x00, 0x00, 0xE0, 0xFF, 0xFF, 0x07, 0x00, 0x80, 0x01, 0x00, 0xE0, 0xFF, 0xFF,    \
+        0x07, 0x00, 0xE0, 0x07, 0x00, 0xE0, 0xFF, 0xFF, 0x07, 0x00, 0xF0, 0x0F, 0x00, 0xE0, 0xFF, 0xFF, 0x07, 0x00, 0xF8, 0x1F,    \
+        0x00, 0xE0, 0xFF, 0xFF, 0x07, 0x00, 0xF8, 0x1F, 0x00, 0xE0, 0xFF, 0xFF, 0x07, 0x00, 0xFC, 0x3F, 0x00, 0xE0, 0xFF, 0xFF,    \
+        0x07, 0x00, 0xFC, 0x3F, 0x00, 0xE0, 0xFF, 0xFF, 0x07, 0x00, 0xF8, 0x1F, 0x00, 0xE0, 0xFF, 0xFF, 0x07, 0x00, 0xF8, 0x1F,    \
+        0x00, 0xE0, 0xFF, 0xFF, 0x07, 0x00, 0xF0, 0x0F, 0x00, 0xE0, 0xFF, 0xFF, 0x07, 0x00, 0xE0, 0x07, 0x00, 0xE0, 0xFF, 0xFF,    \
+        0x07, 0x00, 0x80, 0x01, 0x00, 0xE0, 0xFF, 0xFF, 0x07, 0x00, 0x00, 0x00, 0x00, 0xE0, 0xFF, 0xFF, 0x07, 0x00, 0x00, 0x00,    \
+        0x00, 0xE0, 0xFF, 0xFF, 0x07, 0x00, 0x00, 0x00, 0x00, 0xE0, 0xFF, 0xFF, 0x07, 0x00, 0x00, 0x00, 0x00, 0xE0, 0xFF, 0xFF,    \
+        0x07, 0x00, 0x00, 0x00, 0x00, 0xE0, 0xFF, 0xFF, 0x07, 0x00, 0x00, 0x00, 0x00, 0xE0, 0xFF, 0xFF, 0x07, 0x00, 0x00, 0x00,    \
+        0x00, 0xE0, 0xFF, 0xFF, 0x07, 0x00, 0x00, 0x00, 0x00, 0xE0, 0xFF, 0xFF, 0x07, 0x00, 0x00, 0x00, 0x00, 0xE0, 0xFF, 0xFF,    \
+        0x07, 0x00, 0x00, 0x00, 0x00, 0xE0, 0xFF, 0xFF, 0x0F, 0x00, 0x00, 0x00, 0x00, 0xF0, 0xFF, 0xFF, 0x1F, 0x00, 0x00, 0x00,    \
+        0x00, 0xF8, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,    \
+        0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,    \
+        0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
+#elif IS_DEMO_THERMOSTAT
+#define ON_DEMO_BITMAP                                                                                                             \
+    0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,  \
+        0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,    \
+        0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x0F, 0xF0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x07, 0xE0,    \
+        0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x03, 0xC0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x80, 0xFF, 0xFF, 0xFF, 0xFF,    \
+        0xFF, 0xFF, 0x81, 0x81, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC1, 0x83, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xE0, 0x07,    \
+        0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xE0, 0x07, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xE0, 0x07, 0xFF, 0xFF, 0xFF, 0xFF,    \
+        0xFF, 0xFF, 0xE0, 0x07, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xE0, 0x07, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xE0, 0x07,    \
+        0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xE0, 0x07, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xE0, 0x07, 0xFF, 0xFF, 0xFF, 0xFF,    \
+        0xFF, 0xFF, 0xE0, 0x07, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xE0, 0x07, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00,    \
+        0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF,    \
+        0xFF, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00,    \
+        0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF,    \
+        0xFF, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00,    \
+        0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF,    \
+        0xFF, 0xFF, 0x00, 0x00, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0x3F, 0x00, 0x00, 0xFC, 0xFF, 0xFF, 0xFF, 0xFF, 0x3F, 0x00, 0x00,    \
+        0xFC, 0xFF, 0xFF, 0xFF, 0xFF, 0x1F, 0x00, 0x00, 0xF8, 0xFF, 0xFF, 0xFF, 0xFF, 0x0F, 0x00, 0x00, 0xF0, 0xFF, 0xFF, 0xFF,    \
+        0xFF, 0x0F, 0x00, 0x00, 0xF0, 0xFF, 0xFF, 0xFF, 0xFF, 0x0F, 0x00, 0x00, 0xF0, 0xFF, 0xFF, 0xFF, 0xFF, 0x07, 0x00, 0x00,    \
+        0xE0, 0xFF, 0xFF, 0xFF, 0xFF, 0x07, 0x00, 0x00, 0xE0, 0xFF, 0xFF, 0xFF, 0xFF, 0x07, 0x00, 0x00, 0xE0, 0xFF, 0xFF, 0xFF,    \
+        0xFF, 0x07, 0x00, 0x00, 0xE0, 0xFF, 0xFF, 0xFF, 0xFF, 0x07, 0x00, 0x00, 0xE0, 0xFF, 0xFF, 0xFF, 0xFF, 0x07, 0x00, 0x00,    \
+        0xE0, 0xFF, 0xFF, 0xFF, 0xFF, 0x07, 0x00, 0x00, 0xE0, 0xFF, 0xFF, 0xFF, 0xFF, 0x0F, 0x00, 0x00, 0xF0, 0xFF, 0xFF, 0xFF,    \
+        0xFF, 0x0F, 0x00, 0x00, 0xF0, 0xFF, 0xFF, 0xFF, 0xFF, 0x1F, 0x00, 0x00, 0xF8, 0xFF, 0xFF, 0xFF, 0xFF, 0x1F, 0x00, 0x00,    \
+        0xF8, 0xFF, 0xFF, 0xFF, 0xFF, 0x3F, 0x00, 0x00, 0xFC, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0x00, 0x00, 0xFE, 0xFF, 0xFF, 0xFF,    \
+        0xFF, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x80, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x07, 0xE0,    \
+        0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,    \
+        0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,    \
+        0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
+#define OFF_DEMO_BITMAP ON_DEMO_BITMAP
+
+#else // Unknown demo....
+#define ON_DEMO_BITMAP                                                                                                             \
+    0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,  \
+        0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,    \
+        0xFF, 0xFF, 0x7F, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x0F, 0xF0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x03, 0xC0,    \
+        0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x80, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF,    \
+        0xFF, 0x7F, 0x00, 0x00, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0x3F, 0x00, 0x00, 0xFC, 0xFF, 0xFF, 0xFF, 0xFF, 0x1F, 0x00, 0x00,    \
+        0xF8, 0xFF, 0xFF, 0xFF, 0xFF, 0x0F, 0x00, 0x00, 0xF8, 0xFF, 0xFF, 0xFF, 0xFF, 0x0F, 0x00, 0x00, 0xF0, 0xFF, 0xFF, 0xFF,    \
+        0xFF, 0x07, 0x00, 0x00, 0xE0, 0xFF, 0xFF, 0xFF, 0xFF, 0x07, 0x00, 0x00, 0xE0, 0xFF, 0xFF, 0xFF, 0xFF, 0x0F, 0xF0, 0x0F,    \
+        0xF0, 0xFF, 0xFF, 0xFF, 0xFF, 0x3F, 0xFC, 0x3F, 0xFC, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0xFE, 0x7F, 0xFE, 0xFF, 0xFF, 0xFF,    \
+        0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF8, 0x1F, 0xF8, 0x1F, 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0x0F, 0xF0,    \
+        0x0F, 0xFF, 0xFF, 0xFF, 0x7F, 0xE0, 0x07, 0xE0, 0x07, 0xFE, 0xFF, 0xFF, 0x7F, 0xC0, 0x03, 0xC0, 0x03, 0xFE, 0xFF, 0xFF,    \
+        0x7F, 0xC0, 0x03, 0xC0, 0x03, 0xFE, 0xFF, 0xFF, 0x3F, 0xC0, 0x03, 0xC0, 0x03, 0xFC, 0xFF, 0xFF, 0x3F, 0x00, 0x00, 0x00,    \
+        0x00, 0xFC, 0xFF, 0xFF, 0x3F, 0x00, 0x00, 0x00, 0x00, 0xFC, 0xFF, 0xFF, 0x1F, 0x00, 0x00, 0x00, 0x00, 0xF8, 0xFF, 0xFF,    \
+        0x1F, 0x00, 0x00, 0x00, 0x00, 0xF8, 0xFF, 0xFF, 0x1F, 0x00, 0x00, 0x00, 0x00, 0xF8, 0xFF, 0xFF, 0x1F, 0x00, 0x00, 0x00,    \
+        0x00, 0xF8, 0xFF, 0xFF, 0x1F, 0x00, 0x00, 0x00, 0x00, 0xF8, 0xFF, 0xFF, 0x0F, 0x00, 0x00, 0x00, 0x00, 0xF0, 0xFF, 0xFF,    \
+        0x8F, 0x01, 0x80, 0x01, 0x80, 0xF1, 0xFF, 0xFF, 0xCF, 0x03, 0xC0, 0x03, 0xC0, 0xF3, 0xFF, 0xFF, 0xEF, 0x07, 0xE0, 0x07,    \
+        0xE0, 0xF7, 0xFF, 0xFF, 0xFF, 0x0F, 0xF0, 0x0F, 0xF0, 0xFF, 0xFF, 0xFF, 0xFF, 0x1F, 0xF8, 0x1F, 0xF8, 0xFF, 0xFF, 0xFF,    \
+        0xFF, 0x3F, 0xFC, 0x3F, 0xFC, 0xFF, 0xFF, 0xFF, 0x7F, 0x7E, 0x7E, 0x7E, 0x7E, 0xFE, 0xFF, 0xFF, 0x3F, 0xFC, 0x3F, 0xFC,    \
+        0x3F, 0xFC, 0xFF, 0xFF, 0x1F, 0xF8, 0x1F, 0xF8, 0x1F, 0xF8, 0xFF, 0xFF, 0x1F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF8, 0xFF, 0xFF,    \
+        0x1F, 0xE0, 0x07, 0xE0, 0x07, 0xF8, 0xFF, 0xFF, 0x3F, 0xC0, 0x03, 0xC0, 0x03, 0xFC, 0xFF, 0xFF, 0x3F, 0x80, 0x01, 0x80,    \
+        0x01, 0xFC, 0xFF, 0xFF, 0x7F, 0x00, 0x00, 0x00, 0x00, 0xFE, 0xFF, 0xFF, 0x7F, 0x00, 0x00, 0x00, 0x00, 0xFE, 0xFF, 0xFF,    \
+        0xFF, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x00, 0x00, 0x80, 0xFF, 0xFF, 0xFF, 0xFF, 0x03, 0x00, 0x00,    \
+        0xC0, 0xFF, 0xFF, 0xFF, 0xFF, 0x07, 0x00, 0x00, 0xE0, 0xFF, 0xFF, 0xFF, 0xFF, 0x0F, 0x00, 0x00, 0xF0, 0xFF, 0xFF, 0xFF,    \
+        0xFF, 0x1F, 0x00, 0x00, 0xF8, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0x00, 0x00, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x80,    \
+        0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x3F, 0xFC, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,    \
+        0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,    \
+        0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
+
+#define OFF_DEMO_BITMAP                                                                                                            \
+    0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,  \
+        0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,    \
+        0xFF, 0xFF, 0x7F, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x0F, 0xF0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x03, 0xC0,    \
+        0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x80, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF,    \
+        0xFF, 0x7F, 0x00, 0x00, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0x3F, 0x00, 0x00, 0xFC, 0xFF, 0xFF, 0xFF, 0xFF, 0x1F, 0x00, 0x00,    \
+        0xF8, 0xFF, 0xFF, 0xFF, 0xFF, 0x0F, 0x00, 0x00, 0xF0, 0xFF, 0xFF, 0xFF, 0xFF, 0x0F, 0x00, 0x00, 0xF0, 0xFF, 0xFF, 0xFF,    \
+        0xFF, 0x07, 0x00, 0x00, 0xE0, 0xFF, 0xFF, 0xFF, 0xFF, 0x07, 0x00, 0x00, 0xE0, 0xFF, 0xFF, 0xFF, 0xFF, 0x03, 0x00, 0x00,    \
+        0xC0, 0xFF, 0xFF, 0xFF, 0xFF, 0x03, 0x00, 0x00, 0xC0, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x00, 0x00, 0x80, 0xFF, 0xFF, 0xFF,    \
+        0xFF, 0x01, 0x00, 0x00, 0x80, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00,    \
+        0x00, 0xFF, 0xFF, 0xFF, 0x7F, 0x00, 0x00, 0x00, 0x00, 0xFE, 0xFF, 0xFF, 0x7F, 0x00, 0x00, 0x00, 0x00, 0xFE, 0xFF, 0xFF,    \
+        0x7F, 0x00, 0x00, 0x00, 0x00, 0xFE, 0xFF, 0xFF, 0x3F, 0x00, 0x00, 0x00, 0x00, 0xFC, 0xFF, 0xFF, 0x3F, 0x00, 0x00, 0x00,    \
+        0x00, 0xFC, 0xFF, 0xFF, 0x3F, 0x00, 0x00, 0x00, 0x00, 0xFC, 0xFF, 0xFF, 0x1F, 0x00, 0x00, 0x00, 0x00, 0xF8, 0xFF, 0xFF,    \
+        0x1F, 0x00, 0x00, 0x00, 0x00, 0xF8, 0xFF, 0xFF, 0x1F, 0x00, 0x00, 0x00, 0x00, 0xF8, 0xFF, 0xFF, 0x1F, 0x00, 0x00, 0x00,    \
+        0x00, 0xF8, 0xFF, 0xFF, 0x1F, 0x00, 0x00, 0x00, 0x00, 0xF8, 0xFF, 0xFF, 0x0F, 0x00, 0x00, 0x00, 0x00, 0xF0, 0xFF, 0xFF,    \
+        0x0F, 0x00, 0x00, 0x00, 0x00, 0xF0, 0xFF, 0xFF, 0x0F, 0x00, 0x00, 0x00, 0x00, 0xF0, 0xFF, 0xFF, 0x0F, 0x00, 0x00, 0x00,    \
+        0x00, 0xF0, 0xFF, 0xFF, 0x0F, 0x00, 0x00, 0x00, 0x00, 0xF0, 0xFF, 0xFF, 0x0F, 0x00, 0x00, 0x00, 0x00, 0xF0, 0xFF, 0xFF,    \
+        0x0F, 0x00, 0x00, 0x00, 0x00, 0xF0, 0xFF, 0xFF, 0x0F, 0x00, 0x00, 0x00, 0x00, 0xF0, 0xFF, 0xFF, 0x0F, 0x00, 0x00, 0x00,    \
+        0x00, 0xF0, 0xFF, 0xFF, 0x1F, 0x00, 0x00, 0x00, 0x00, 0xF8, 0xFF, 0xFF, 0x1F, 0x00, 0x00, 0x00, 0x00, 0xF8, 0xFF, 0xFF,    \
+        0x1F, 0x00, 0x00, 0x00, 0x00, 0xF8, 0xFF, 0xFF, 0x3F, 0x00, 0x00, 0x00, 0x00, 0xFC, 0xFF, 0xFF, 0x3F, 0x00, 0x00, 0x00,    \
+        0x00, 0xFC, 0xFF, 0xFF, 0x7F, 0x00, 0x00, 0x00, 0x00, 0xFE, 0xFF, 0xFF, 0x7F, 0x00, 0x00, 0x00, 0x00, 0xFE, 0xFF, 0xFF,    \
+        0xFF, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x00, 0x00, 0x80, 0xFF, 0xFF, 0xFF, 0xFF, 0x03, 0x00, 0x00,    \
+        0xC0, 0xFF, 0xFF, 0xFF, 0xFF, 0x07, 0x00, 0x00, 0xE0, 0xFF, 0xFF, 0xFF, 0xFF, 0x0F, 0x00, 0x00, 0xF0, 0xFF, 0xFF, 0xFF,    \
+        0xFF, 0x1F, 0x00, 0x00, 0xF8, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0x00, 0x00, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x80,    \
+        0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x3F, 0xFC, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,    \
+        0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,    \
+        0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
+
+#endif
+
+#endif // SILABS_DEMO_UI_BITMAPS_H
diff --git a/examples/platform/silabs/SiWx917/display/demo-ui.c b/examples/platform/silabs/SiWx917/display/demo-ui.c
new file mode 100644
index 0000000..73a8d52
--- /dev/null
+++ b/examples/platform/silabs/SiWx917/display/demo-ui.c
@@ -0,0 +1,136 @@
+/**
+ * @file
+ * @brief User Interface core logic for demo.
+ *******************************************************************************
+ * # License
+ * <b>Copyright 2020 Silicon Laboratories Inc.
+ *www.silabs.com</b>
+ *******************************************************************************
+ *
+ * The licensor of this software is Silicon
+ *Laboratories Inc. Your use of this software is
+ *governed by the terms of Silicon Labs Master
+ *Software License Agreement (MSLA) available at
+ * www.silabs.com/about-us/legal/master-software-license-agreement.
+ *This software is distributed to you in Source Code
+ *format and is governed by the sections of the MSLA
+ *applicable to Source Code.
+ *
+ ******************************************************************************/
+
+#include "demo-ui.h"
+#include "demo-ui-bitmaps.h"
+#include "dmd/dmd.h"
+#include "em_types.h"
+#include "glib.h"
+#include <stdio.h>
+#include <string.h>
+
+// Main Logo and App image
+#define SILICONLABS_X_POSITION ((glibContext.pDisplayGeometry->xSize - SILICONLABS_BITMAP_WIDTH) / 2)
+#define SILICONLABS_Y_POSITION 0
+#define APP_BITMAP_WIDTH 64
+#define APP_BITMAP_HEIGHT 64
+#define APP_X_POSITION ((glibContext.pDisplayGeometry->xSize - APP_BITMAP_WIDTH) / 2)
+#define APP_Y_POSITION (glibContext.pDisplayGeometry->ySize - APP_BITMAP_HEIGHT - 5)
+#define PROT1_ID_X_POSITION 1
+#define PROT2_ID_X_POSITION 79
+
+// Matter Logo
+#define PROT2_BITMAP_WIDTH MATTER_LOGO_WIDTH
+#define PROT2_BITMAP_HEIGHT MATTER_LOGO_HEIGHT
+#define PROT2_X_POSITION 104
+#define PROT2_Y_POSITION (APP_Y_POSITION + (APP_Y_POSITION / 2))
+#define PROT2_BITMAP (matterLogoBitmap)
+#define PROT2_BITMAP_CONN (matterLogoBitmap)
+
+// Networking Protocol Logo
+#ifdef SL_WIFI
+#define PROT1_BITMAP_WIDTH WIFI_BITMAP_WIDTH
+#define PROT1_BITMAP_HEIGHT WIFI_BITMAP_HEIGHT
+#define PROT1_X_POSITION 8
+#define PROT1_Y_POSITION (APP_Y_POSITION + (APP_Y_POSITION / 2))
+#define PROT1_BITMAP (networkBitMap)
+#define PROT1_BITMAP_CONN (networkBitMap)
+#else
+#define PROT1_BITMAP_WIDTH THREAD_BITMAP_WIDTH
+#define PROT1_BITMAP_HEIGHT THREAD_BITMAP_HEIGHT
+#define PROT1_X_POSITION 8
+#define PROT1_Y_POSITION (APP_Y_POSITION + (APP_Y_POSITION / 2))
+#define PROT1_BITMAP (networkBitMap)
+#define PROT1_BITMAP_CONN (networkBitMap)
+#endif
+
+/*******************************************************************************
+ ***************************  LOCAL VARIABLES   ********************************
+ ******************************************************************************/
+static GLIB_Context_t glibContext; /* Global glib context */
+
+static const uint8_t siliconlabsBitmap[] = { SILABS_BITMAP };
+static const uint8_t matterLogoBitmap[]  = { MATTER_LOGO_BITMAP };
+
+static const uint8_t OnStateBitMap[]  = { ON_DEMO_BITMAP };
+static const uint8_t OffStateBitMap[] = { OFF_DEMO_BITMAP };
+
+#ifdef SL_WIFI
+static const uint8_t networkBitMap[] = { WIFI_BITMAP };
+#else
+static const uint8_t networkBitMap[] = { THREAD_BITMAP };
+#endif
+
+// Future usage
+// static const uint8_t unconnectedBitMap[] = { QUESTION_MARK_BITMAP };
+
+/*******************************************************************************
+ **************************   LOCAL FUNCTIONS   ********************************
+ ******************************************************************************/
+static void demoUIDisplayLogo(void)
+{
+    GLIB_drawBitmap(&glibContext, SILICONLABS_X_POSITION, SILICONLABS_Y_POSITION, SILICONLABS_BITMAP_WIDTH,
+                    SILICONLABS_BITMAP_HEIGHT, siliconlabsBitmap);
+}
+
+/*******************************************************************************
+ **************************   GLOBAL FUNCTIONS   *******************************
+ ******************************************************************************/
+void demoUIInit(GLIB_Context_t * context)
+{
+    memcpy(&glibContext, context, sizeof(GLIB_Context_t));
+}
+
+void demoUIDisplayHeader(char * name)
+{
+    demoUIDisplayLogo();
+    if (APP_NAME_MAX_LENGTH >= strlen(name))
+    {
+        GLIB_drawStringOnLine(&glibContext, name, 5, GLIB_ALIGN_CENTER, 0, 0, true);
+    }
+    DMD_updateDisplay();
+}
+
+void demoUIDisplayApp(bool on)
+{
+    GLIB_drawBitmap(&glibContext, APP_X_POSITION, APP_Y_POSITION, APP_BITMAP_WIDTH, APP_BITMAP_HEIGHT,
+                    (on ? OnStateBitMap : OffStateBitMap));
+    DMD_updateDisplay();
+}
+
+void demoUIDisplayProtocol(demoUIProtocol protocol, bool isConnected)
+{
+    GLIB_drawBitmap(&glibContext, (protocol == DEMO_UI_PROTOCOL1 ? PROT1_X_POSITION : PROT2_X_POSITION),
+                    (protocol == DEMO_UI_PROTOCOL1 ? PROT1_Y_POSITION : PROT2_Y_POSITION),
+                    (protocol == DEMO_UI_PROTOCOL1 ? PROT1_BITMAP_WIDTH : PROT2_BITMAP_WIDTH),
+                    (protocol == DEMO_UI_PROTOCOL1 ? PROT1_BITMAP_HEIGHT : PROT2_BITMAP_HEIGHT),
+                    (protocol == DEMO_UI_PROTOCOL1 ? (isConnected ? PROT1_BITMAP_CONN : PROT1_BITMAP)
+                                                   : (isConnected ? PROT2_BITMAP_CONN : PROT2_BITMAP)));
+    DMD_updateDisplay();
+}
+
+void demoUIClearMainScreen(uint8_t * name)
+{
+    GLIB_clear(&glibContext);
+    demoUIDisplayHeader((char *) name);
+    demoUIDisplayApp(false);
+    demoUIDisplayProtocol(DEMO_UI_PROTOCOL1, false);
+    demoUIDisplayProtocol(DEMO_UI_PROTOCOL2, false);
+}
diff --git a/examples/platform/silabs/SiWx917/display/demo-ui.h b/examples/platform/silabs/SiWx917/display/demo-ui.h
new file mode 100644
index 0000000..6197a4e
--- /dev/null
+++ b/examples/platform/silabs/SiWx917/display/demo-ui.h
@@ -0,0 +1,139 @@
+/***************************************************************************/ /**
+                                                                               * @file
+                                                                               * @brief User Interface for demo.
+                                                                               *******************************************************************************
+                                                                               * # License
+                                                                               * <b>Copyright 2020 Silicon Laboratories Inc.
+                                                                               *www.silabs.com</b>
+                                                                               *******************************************************************************
+                                                                               *
+                                                                               * The licensor of this software is Silicon
+                                                                               *Laboratories Inc. Your use of this software is
+                                                                               *governed by the terms of Silicon Labs Master
+                                                                               *Software License Agreement (MSLA) available at
+                                                                               * www.silabs.com/about-us/legal/master-software-license-agreement.
+                                                                               *This software is distributed to you in Source Code
+                                                                               *format and is governed by the sections of the MSLA
+                                                                               *applicable to Source Code.
+                                                                               *
+                                                                               ******************************************************************************/
+
+#pragma once
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "glib.h"
+/**************************************************************************/ /**
+                                                                              * DEMO UI uses the underlying DMD interface and the
+                                                                              *GLIB and exposes several wrapper functions to
+                                                                              *application. These functions are used to display
+                                                                              * different bitmaps for the demo.
+                                                                              *
+                                                                              ******************************************************************************/
+
+#define APP_NAME_MAX_LENGTH 20
+
+/*******************************************************************************
+ ********************************   ENUMS   ************************************
+ ******************************************************************************/
+
+typedef enum
+{
+    DEMO_UI_PROTOCOL1,
+    DEMO_UI_PROTOCOL2
+} demoUIProtocol;
+
+typedef enum
+{
+    DEMO_UI_LIGHT_OFF,
+    DEMO_UI_LIGHT_ON
+} demoUILightState_t;
+
+typedef enum
+{
+    DEMO_UI_DIRECTION_PROT1,
+    DEMO_UI_DIRECTION_PROT2,
+    DEMO_UI_DIRECTION_SWITCH,
+    DEMO_UI_DIRECTION_INVALID
+} demoUILightDirection_t;
+
+typedef enum
+{
+    DEMO_UI_NO_NETWORK,
+    DEMO_UI_SCANNING,
+    DEMO_UI_JOINING,
+    DEMO_UI_FORMING,
+    DEMO_UI_NETWORK_UP,
+    DEMO_UI_STATE_UNKNOWN
+} demoUIZigBeeNetworkState_t;
+
+/*******************************************************************************
+ ******************************   PROTOTYPES   *********************************
+ ******************************************************************************/
+
+/**************************************************************************/ /**
+                                                                              * @brief
+                                                                              *   Initilize the GLIB and DMD interfaces.
+                                                                              *
+                                                                              * @param[in] void
+                                                                              *
+                                                                              * @return
+                                                                              *      void
+                                                                              *****************************************************************************/
+void demoUIInit(GLIB_Context_t * context);
+
+/**************************************************************************/ /**
+                                                                              * @brief
+                                                                              *   Update the display with Silicon Labs logo and
+                                                                              *application name.
+                                                                              *
+                                                                              * @param[in] name name of the current application.
+                                                                              *
+                                                                              * @return
+                                                                              *      void
+                                                                              *****************************************************************************/
+void demoUIDisplayHeader(char * name);
+
+/**************************************************************************/ /**
+                                                                              * @brief
+                                                                              *   Update the display with App image. Bool state only
+                                                                              *for now.
+                                                                              *
+                                                                              * @param[in] on status of App
+                                                                              *
+                                                                              * @return
+                                                                              *      void
+                                                                              *****************************************************************************/
+void demoUIDisplayApp(bool on);
+
+/**************************************************************************/ /**
+                                                                              * @brief
+                                                                              *   Update the display to show if the bluetooth is
+                                                                              *connected to the mobile device.
+                                                                              *
+                                                                              * @param[in] bool, true if the Light is connected to
+                                                                              *mobile device, false otherwise.
+                                                                              *
+                                                                              * @return
+                                                                              *      void
+                                                                              *****************************************************************************/
+void demoUIDisplayProtocol(demoUIProtocol protocol, bool isConnected);
+
+/**************************************************************************/ /**
+                                                                              * @brief
+                                                                              *   Clear the Lcd screen and display the main screen.
+                                                                              *
+                                                                              * @param[in] name - application name
+                                                                              * @param[in] showPROT1 - show protocol 1 related icon.
+                                                                              * @param[in] showPROT2 - show protocol 2 related icon.
+                                                                              *
+                                                                              * @return
+                                                                              *      void
+                                                                              *****************************************************************************/
+void demoUIClearMainScreen(uint8_t * name);
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/examples/platform/silabs/SiWx917/display/lcd.cpp b/examples/platform/silabs/SiWx917/display/lcd.cpp
new file mode 100644
index 0000000..6e1f2d2
--- /dev/null
+++ b/examples/platform/silabs/SiWx917/display/lcd.cpp
@@ -0,0 +1,220 @@
+/*
+ *
+ *    Copyright (c) 2020 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 <stdio.h>
+#include <string.h>
+
+#include "demo-ui.h"
+#include "lcd.h"
+
+#include "dmd.h"
+#include "glib.h"
+
+#ifdef QR_CODE_ENABLED
+#include "qrcodegen.h"
+#endif // QR_CODE_ENABLED
+
+#include "sl_board_control.h"
+
+#define LCD_SIZE 128
+#define QR_CODE_VERSION 4
+#define QR_CODE_MODULE_SIZE 3
+#define QR_CODE_BORDER_SIZE 0
+
+#ifdef QR_CODE_ENABLED
+static uint8_t qrCode[qrcodegen_BUFFER_LEN_FOR_VERSION(QR_CODE_VERSION)];
+static uint8_t workBuffer[qrcodegen_BUFFER_LEN_FOR_VERSION(QR_CODE_VERSION)];
+#endif // QR_CODE_ENABLED
+
+CHIP_ERROR SilabsLCD::Init(uint8_t * name, bool initialState)
+{
+    EMSTATUS status;
+    CHIP_ERROR err = CHIP_NO_ERROR;
+
+    // Check if Name is to long
+    if (name != nullptr)
+    {
+        if (APP_NAME_MAX_LENGTH < strlen((char *) name))
+        {
+            SILABS_LOG("App Name too long");
+            return CHIP_ERROR_INVALID_ARGUMENT;
+        }
+        else
+        {
+            strcpy((char *) mName, (char *) name);
+        }
+    }
+
+    /* Enable the memory lcd */
+    status = sl_board_enable_display();
+    if (status != SL_STATUS_OK)
+    {
+        SILABS_LOG("Board Display enable fail %d", status);
+        err = CHIP_ERROR_INTERNAL;
+    }
+
+    /* Initialize the DMD module for the DISPLAY device driver. */
+    status = DMD_init(0);
+    if (DMD_OK != status)
+    {
+        SILABS_LOG("DMD init failed %d", status);
+        err = CHIP_ERROR_INTERNAL;
+    }
+
+    /* Initialize the glib context */
+    status = GLIB_contextInit(&glibContext);
+    if (GLIB_OK != status)
+    {
+        SILABS_LOG("Glib context init failed %d", status);
+        err = CHIP_ERROR_INTERNAL;
+    }
+
+    glibContext.backgroundColor = White;
+    glibContext.foregroundColor = Black;
+    status                      = GLIB_clear(&glibContext);
+    if (GLIB_OK != status)
+    {
+        SILABS_LOG("Glib clear failed %d", status);
+        err = CHIP_ERROR_INTERNAL;
+    }
+    demoUIInit(&glibContext);
+
+    dState.mainState = initialState;
+
+    return err;
+}
+
+/* This function is necessary because currently glib.h cannot be used within a C++ context. */
+void * SilabsLCD::Context()
+{
+    return (void *) &glibContext;
+}
+
+int SilabsLCD::Clear()
+{
+    return GLIB_clear(&glibContext);
+}
+
+int SilabsLCD::DrawPixel(void * pContext, int32_t x, int32_t y)
+{
+    return GLIB_drawPixel((GLIB_Context_t *) pContext, x, y);
+}
+
+int SilabsLCD::Update(void)
+{
+    return DMD_updateDisplay();
+}
+
+void SilabsLCD::WriteDemoUI(bool state)
+{
+#ifdef QR_CODE_ENABLED
+    if (mShowQRCode)
+    {
+        mShowQRCode = false;
+    }
+#endif
+    dState.mainState = state;
+    WriteDemoUI();
+}
+
+void SilabsLCD::WriteDemoUI()
+{
+    Clear();
+    if (customUI != nullptr)
+    {
+        customUI(&glibContext);
+    }
+    else
+    {
+        demoUIClearMainScreen(mName);
+        demoUIDisplayApp(dState.mainState);
+    }
+}
+
+void SilabsLCD::SetCustomUI(customUICB cb)
+{
+    customUI = cb;
+}
+
+#ifdef QR_CODE_ENABLED
+void SilabsLCD::WriteQRCode()
+{
+    if (!qrcodegen_encodeText((const char *) mQRCodeBuffer, workBuffer, qrCode, qrcodegen_Ecc_LOW, QR_CODE_VERSION, QR_CODE_VERSION,
+                              qrcodegen_Mask_AUTO, true))
+    {
+        SILABS_LOG("qrcodegen_encodeText() failed");
+        return;
+    }
+
+    const int size = qrcodegen_getSize(qrCode);
+
+    GLIB_clear(&glibContext);
+
+    const int displaySize = (2 * QR_CODE_BORDER_SIZE + size) * QR_CODE_MODULE_SIZE;
+    const int displayX    = (LCD_SIZE - displaySize) / 2;
+    const int displayY    = displayX;
+
+    for (int y = 0; y < size; ++y)
+    {
+        for (int x = 0; x < size; ++x)
+        {
+            if (qrcodegen_getModule(qrCode, x, y))
+            {
+                LCDFillRect(displayX + (QR_CODE_BORDER_SIZE + x) * QR_CODE_MODULE_SIZE,
+                            displayY + (QR_CODE_BORDER_SIZE + y) * QR_CODE_MODULE_SIZE, QR_CODE_MODULE_SIZE, QR_CODE_MODULE_SIZE);
+            }
+        }
+    }
+
+    DMD_updateDisplay();
+}
+
+void SilabsLCD::SetQRCode(uint8_t * str, uint32_t size)
+{
+    if (size < chip::QRCodeBasicSetupPayloadGenerator::kMaxQRCodeBase38RepresentationLength + 1)
+    {
+        memcpy(mQRCodeBuffer, str, size);
+    }
+}
+
+void SilabsLCD::ShowQRCode(bool show, bool forceRefresh)
+{
+    if (show != mShowQRCode || forceRefresh)
+    {
+        (show) ? WriteQRCode() : WriteDemoUI();
+        mShowQRCode = show;
+    }
+}
+
+void SilabsLCD::ToggleQRCode(void)
+{
+    (mShowQRCode) ? WriteDemoUI() : WriteQRCode();
+    mShowQRCode = !mShowQRCode;
+}
+
+void SilabsLCD::LCDFillRect(uint8_t x, uint8_t y, uint8_t w, uint8_t h)
+{
+    for (int i = 0; i < h; i++)
+    {
+        for (int j = 0; j < w; j++)
+        {
+            GLIB_drawPixel(&glibContext, x + j, y + i);
+        }
+    }
+}
+#endif // QR_CODE_ENABLED
diff --git a/examples/platform/silabs/SiWx917/display/lcd.h b/examples/platform/silabs/SiWx917/display/lcd.h
new file mode 100644
index 0000000..d375b7a
--- /dev/null
+++ b/examples/platform/silabs/SiWx917/display/lcd.h
@@ -0,0 +1,74 @@
+/*
+ *
+ *    Copyright (c) 2020 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 "AppConfig.h"
+#include "glib.h"
+#ifdef QR_CODE_ENABLED
+#include "qrcodegen.h"
+#include <setup_payload/QRCodeSetupPayloadGenerator.h>
+#endif // QR_CODE_ENABLED
+
+#include "demo-ui.h"
+
+#define MAX_STR_LEN 48
+
+class SilabsLCD
+{
+
+public:
+    typedef void (*customUICB)(GLIB_Context_t * context);
+    CHIP_ERROR Init(uint8_t * name = nullptr, bool initialState = false);
+    void * Context();
+    int Clear(void);
+    int DrawPixel(void * pContext, int32_t x, int32_t y);
+    int Update(void);
+    void WriteDemoUI(bool state);
+    void SetCustomUI(customUICB cb);
+
+#ifdef QR_CODE_ENABLED
+    void SetQRCode(uint8_t * str, uint32_t size);
+    void ShowQRCode(bool show, bool forceRefresh = false);
+    void ToggleQRCode(void);
+#endif
+
+private:
+    typedef struct demoState
+    {
+        bool mainState = false;
+        bool protocol1 = false; /* data */
+    } DemoState_t;
+
+    void WriteQRCode();
+    void WriteDemoUI();
+#ifdef QR_CODE_ENABLED
+    void LCDFillRect(uint8_t x, uint8_t y, uint8_t w, uint8_t h);
+    char mQRCodeBuffer[chip::QRCodeBasicSetupPayloadGenerator::kMaxQRCodeBase38RepresentationLength + 1];
+    bool mShowQRCode = true;
+#endif
+    GLIB_Context_t glibContext;
+
+#ifdef SL_DEMO_NAME
+    uint8_t mName[] = SL_DEMO_NAME
+#else
+    uint8_t mName[APP_NAME_MAX_LENGTH + 1];
+#endif
+        customUICB customUI = nullptr;
+    DemoState_t dState;
+};
diff --git a/examples/platform/silabs/SiWx917/efr32_utils.cpp b/examples/platform/silabs/SiWx917/efr32_utils.cpp
new file mode 100644
index 0000000..bd2bf77
--- /dev/null
+++ b/examples/platform/silabs/SiWx917/efr32_utils.cpp
@@ -0,0 +1,37 @@
+/*
+ *
+ *    Copyright (c) 2020 Project CHIP Authors
+ *    Copyright (c) 2022 Silabs.
+ *    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 "efr32_utils.h"
+#include "init_efrPlatform.h"
+#include "sl_system_kernel.h"
+
+#include <matter_config.h>
+
+void appError(int err)
+{
+    SILABS_LOG("!!!!!!!!!!!! App Critical Error: %d !!!!!!!!!!!", err);
+    portDISABLE_INTERRUPTS();
+    while (true)
+        ;
+}
+
+void appError(CHIP_ERROR error)
+{
+    appError(static_cast<int>(error.AsInteger()));
+}
diff --git a/examples/platform/silabs/SiWx917/efr32_utils.h b/examples/platform/silabs/SiWx917/efr32_utils.h
new file mode 100644
index 0000000..b0d508d
--- /dev/null
+++ b/examples/platform/silabs/SiWx917/efr32_utils.h
@@ -0,0 +1,38 @@
+/*
+ *
+ *    Copyright (c) 2020 Project CHIP Authors
+ *    Copyright (c) 2022 Silabs.
+ *    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
+
+// EFR Logging
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+void silabsInitLog(void);
+
+void efr32Log(const char * aFormat, ...);
+#define SILABS_LOG(...) efr32Log(__VA_ARGS__);
+void appError(int err);
+
+#ifdef __cplusplus
+}
+
+#include <lib/core/CHIPError.h>
+void appError(CHIP_ERROR error);
+#endif
diff --git a/examples/platform/silabs/SiWx917/init_efrPlatform.cpp b/examples/platform/silabs/SiWx917/init_efrPlatform.cpp
new file mode 100644
index 0000000..993b4fe
--- /dev/null
+++ b/examples/platform/silabs/SiWx917/init_efrPlatform.cpp
@@ -0,0 +1,86 @@
+/*
+ *
+ *    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 "AppConfig.h"
+#include <lib/support/CHIPPlatformMemory.h>
+#include <platform/CHIPDeviceLayer.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+#include <assert.h>
+#include <string.h>
+
+#include <mbedtls/platform.h>
+
+#if CHIP_ENABLE_OPENTHREAD
+#include <openthread-core-config.h>
+#include <openthread/cli.h>
+#include <openthread/config.h>
+#include <openthread/dataset.h>
+#include <openthread/error.h>
+#include <openthread/heap.h>
+#include <openthread/icmp6.h>
+#include <openthread/instance.h>
+#include <openthread/link.h>
+#include <openthread/platform/openthread-system.h>
+#include <openthread/tasklet.h>
+#include <openthread/thread.h>
+#include <utils/uart.h>
+
+#include "platform-efr32.h"
+
+#if OPENTHREAD_CONFIG_HEAP_EXTERNAL_ENABLE
+#include "openthread/heap.h"
+#endif // OPENTHREAD_CONFIG_HEAP_EXTERNAL_ENABLE
+#endif // CHIP_ENABLE_OPENTHREAD
+
+#include "init_efrPlatform.h"
+#include "sl_component_catalog.h"
+#include "sl_mbedtls.h"
+#include "sl_system_init.h"
+
+#if SL_SYSTEM_VIEW
+#include "SEGGER_SYSVIEW.h"
+#endif
+
+void initAntenna(void);
+
+void init_efrPlatform(void)
+{
+    sl_system_init();
+    sl_mbedtls_init();
+#if SL_SYSTEM_VIEW
+    SEGGER_SYSVIEW_Conf();
+    SEGGER_SYSVIEW_Start();
+#endif
+
+#if SILABS_LOG_ENABLED
+    silabsInitLog();
+#endif
+
+#if CHIP_ENABLE_OPENTHREAD
+    efr32RadioInit();
+    efr32AlarmInit();
+#endif // CHIP_ENABLE_OPENTHREAD
+}
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/examples/platform/silabs/SiWx917/init_efrPlatform.h b/examples/platform/silabs/SiWx917/init_efrPlatform.h
new file mode 100644
index 0000000..aeb47b8
--- /dev/null
+++ b/examples/platform/silabs/SiWx917/init_efrPlatform.h
@@ -0,0 +1,29 @@
+/*
+ *
+ *    Copyright (c) 2020 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
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+void init_efrPlatform(void);
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/examples/platform/silabs/SiWx917/ldscripts/efr32mg12.ld b/examples/platform/silabs/SiWx917/ldscripts/efr32mg12.ld
new file mode 100644
index 0000000..f9f4f55
--- /dev/null
+++ b/examples/platform/silabs/SiWx917/ldscripts/efr32mg12.ld
@@ -0,0 +1,242 @@
+/*
+ *
+ *    Copyright (c) 2020 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.
+ */
+/***************************************************************************//**
+ * Linker script for Silicon Labs EFR32MG12P devices
+ *******************************************************************************
+ * # License
+ * <b>Copyright 2022 Silicon Laboratories Inc. www.silabs.com</b>
+ *******************************************************************************
+ *
+ * SPDX-License-Identifier: Zlib
+ *
+ * The licensor of this software is Silicon Laboratories Inc.
+ *
+ * This software is provided 'as-is', without any express or implied
+ * warranty. In no event will the authors be held liable for any damages
+ * arising from the use of this software.
+ *
+ * Permission is granted to anyone to use this software for any purpose,
+ * including commercial applications, and to alter it and redistribute it
+ * freely, subject to the following restrictions:
+ *
+ * 1. The origin of this software must not be misrepresented; you must not
+ *    claim that you wrote the original software. If you use this software
+ *    in a product, an acknowledgment in the product documentation would be
+ *    appreciated but is not required.
+ * 2. Altered source versions must be plainly marked as such, and must not be
+ *    misrepresented as being the original software.
+ * 3. This notice may not be removed or altered from any source distribution.
+ *
+ ******************************************************************************/
+
+
+MEMORY
+{
+  FLASH (rx) : ORIGIN = 0x00000000, LENGTH = 1048576
+  RAM (rwx)  : ORIGIN = 0x20000000, LENGTH = 262144
+}
+
+/* Linker script to place sections and symbol values. Should be used together
+ * with other linker script that defines memory regions FLASH and RAM.
+ * It references following symbols, which must be defined in code:
+ *   Reset_Handler : Entry of reset handler
+ *
+ * It defines following symbols, which code can use without definition:
+ *   __exidx_start
+ *   __exidx_end
+ *   __copy_table_start__
+ *   __copy_table_end__
+ *   __zero_table_start__
+ *   __zero_table_end__
+ *   __etext
+ *   __data_start__
+ *   __preinit_array_start
+ *   __preinit_array_end
+ *   __init_array_start
+ *   __init_array_end
+ *   __fini_array_start
+ *   __fini_array_end
+ *   __data_end__
+ *   __bss_start__
+ *   __bss_end__
+ *   __end__
+ *   end
+ *   __HeapBase
+ *   __HeapLimit
+ *   __StackLimit
+ *   __StackTop
+ *   __stack
+ */
+ENTRY(Reset_Handler)
+
+SECTIONS
+{
+  .text :
+  {
+    KEEP(*(.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*)
+
+    KEEP(*(.eh_frame*))
+  } > FLASH
+
+  .ARM.extab :
+  {
+    *(.ARM.extab* .gnu.linkonce.armextab.*)
+  } > FLASH
+
+  __exidx_start = .;
+  .ARM.exidx :
+  {
+    *(.ARM.exidx* .gnu.linkonce.armexidx.*)
+  } > FLASH
+  __exidx_end = .;
+
+  .copy.table :
+  {
+    . = ALIGN(4);
+    __copy_table_start__ = .;
+
+    LONG (__etext)
+    LONG (__data_start__)
+    LONG ((__data_end__ - __data_start__) / 4)
+
+    __copy_table_end__ = .;
+  } > FLASH
+
+  .zero.table :
+  {
+    . = ALIGN(4);
+    __zero_table_start__ = .;
+    __zero_table_end__ = .;
+  } > FLASH
+
+  __etext = ALIGN (4);
+
+  .data : AT (__etext)
+  {
+    __data_start__ = .;
+    *(vtable)
+    *(.data*)
+    . = ALIGN (4);
+    PROVIDE (__ram_func_section_start = .);
+    *(.ram)
+    PROVIDE (__ram_func_section_end = .);
+
+    . = ALIGN(4);
+    /* preinit data */
+    PROVIDE_HIDDEN (__preinit_array_start = .);
+    KEEP(*(.preinit_array))
+    PROVIDE_HIDDEN (__preinit_array_end = .);
+
+    . = ALIGN(4);
+    /* init data */
+    PROVIDE_HIDDEN (__init_array_start = .);
+    KEEP(*(SORT(.init_array.*)))
+    KEEP(*(.init_array))
+    PROVIDE_HIDDEN (__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);
+    /* All data end */
+    __data_end__ = .;
+
+  } > RAM
+
+  .bss :
+  {
+    . = ALIGN(4);
+    __bss_start__ = .;
+    *(.bss)
+    *(.bss.*)
+    *(COMMON)
+    . = ALIGN(4);
+    __bss_end__ = .;
+  } > RAM
+
+  .heap (COPY) :
+  {
+    __HeapBase = .;
+    __end__ = .;
+    end = __end__;
+    _end = __end__;
+    KEEP(*(.heap*))
+    __HeapLimit = .;
+  } > RAM
+ 
+  __main_flash_end__ = ORIGIN(FLASH) + LENGTH(FLASH);
+
+  /* .stack_dummy section doesn't contains any symbols. It is only
+   * used for linker to calculate size of stack sections, and assign
+   * values to stack symbols later */
+   .stack_dummy (COPY):
+  {
+    KEEP(*(.stack*))
+  } > RAM
+
+  /* Set stack top to end of RAM, and stack limit move down by
+   * size of stack_dummy section */
+  __StackTop = ORIGIN(RAM) + LENGTH(RAM);
+  __StackLimit = __StackTop - SIZEOF(.stack_dummy);
+  PROVIDE(__stack = __StackTop);
+
+  .nvm (DSECT) : {
+    KEEP(*(.simee*))
+  } > FLASH
+
+  /* Last page of flash is reserved for the manufacturing token space */
+  linker_nvm_end = __main_flash_end__ - 2048;
+  linker_nvm_begin = linker_nvm_end - SIZEOF(.nvm);
+  linker_nvm_size = SIZEOF(.nvm);
+  __nvm3Base = linker_nvm_begin;
+  __attestation_credentials_base = linker_nvm_end;
+
+  /* Check if data + heap + stack exceeds RAM limit */
+  /*ASSERT(__StackLimit >= __HeapLimit, "region RAM overflowed with stack")*/
+  ASSERT( (linker_nvm_begin + SIZEOF(.nvm)) <= __main_flash_end__, "NVM3 is excessing the flash size !")
+
+  /* Check if FLASH usage exceeds FLASH size */
+  ASSERT( LENGTH(FLASH) >= (__etext), "FLASH memory overflowed !")
+  ASSERT((__etext + SIZEOF(.data)) <= __nvm3Base, "FLASH memory overlapped with NVM section.")
+}
diff --git a/examples/platform/silabs/SiWx917/ldscripts/efr32mg21.ld b/examples/platform/silabs/SiWx917/ldscripts/efr32mg21.ld
new file mode 100644
index 0000000..2c9de0d
--- /dev/null
+++ b/examples/platform/silabs/SiWx917/ldscripts/efr32mg21.ld
@@ -0,0 +1,289 @@
+/*
+ *
+ *    Copyright (c) 2020 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.
+ */
+/***************************************************************************//**
+ * Linker script for Silicon Labs EFR32MG21 devices
+ * @version 5.7.2
+ *******************************************************************************
+ * # License
+ * <b>Copyright 2018 Silicon Laboratories Inc. www.silabs.com</b>
+ *******************************************************************************
+ *
+ * SPDX-License-Identifier: Zlib
+ *
+ * The licensor of this software is Silicon Laboratories Inc.
+ *
+ * This software is provided 'as-is', without any express or implied
+ * warranty. In no event will the authors be held liable for any damages
+ * arising from the use of this software.
+ *
+ * Permission is granted to anyone to use this software for any purpose,
+ * including commercial applications, and to alter it and redistribute it
+ * freely, subject to the following restrictions:
+ *
+ * 1. The origin of this software must not be misrepresented; you must not
+ *    claim that you wrote the original software. If you use this software
+ *    in a product, an acknowledgment in the product documentation would be
+ *    appreciated but is not required.
+ * 2. Altered source versions must be plainly marked as such, and must not be
+ *    misrepresented as being the original software.
+ * 3. This notice may not be removed or altered from any source distribution.
+ *
+ ******************************************************************************/
+
+MEMORY
+{
+  FLASH (rx) : ORIGIN = 0x00000000, LENGTH = 1048576 - 8192  /* 8K is reserved at top of flash on MG21 */
+  RAM (rwx)  : ORIGIN = 0x20000000, LENGTH = 98304
+}
+
+/* Linker script to place sections and symbol values. Should be used together
+ * with other linker script that defines memory regions FLASH and RAM.
+ * It references following symbols, which must be defined in code:
+ *   Reset_Handler : Entry of reset handler
+ *
+ * It defines following symbols, which code can use without definition:
+ *   __exidx_start
+ *   __exidx_end
+ *   __copy_table_start__
+ *   __copy_table_end__
+ *   __zero_table_start__
+ *   __zero_table_end__
+ *   __etext
+ *   __data_start__
+ *   __preinit_array_start
+ *   __preinit_array_end
+ *   __init_array_start
+ *   __init_array_end
+ *   __fini_array_start
+ *   __fini_array_end
+ *   __data_end__
+ *   __bss_start__
+ *   __bss_end__
+ *   __end__
+ *   end
+ *   __HeapBase
+ *   __HeapLimit
+ *   __StackLimit
+ *   __StackTop
+ *   __stack
+ *   __Vectors_End
+ *   __Vectors_Size
+ */
+ENTRY(Reset_Handler)
+
+SECTIONS
+{
+  .text :
+  {
+    KEEP(*(.vectors))
+    __Vectors_End = .;
+    __Vectors_Size = __Vectors_End - __Vectors;
+    __end__ = .;
+
+    *(.text*)
+
+    KEEP(*(.init))
+    KEEP(*(.fini))
+
+    KEEP(*(.application_properties))
+	KEEP(*(.gecko_configuration))
+	KEEP(*(.xo_configuration))
+    KEEP(*(.gatt_header))
+    KEEP(*(.gatt_data))
+
+    /* .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*)
+
+
+    KEEP(*(.eh_frame*))
+  } > FLASH
+
+
+  .ARM.extab :
+  {
+    *(.ARM.extab* .gnu.linkonce.armextab.*)
+  } > FLASH
+
+  __exidx_start = .;
+  .ARM.exidx :
+  {
+    *(.ARM.exidx* .gnu.linkonce.armexidx.*)
+  } > FLASH
+  __exidx_end = .;
+
+
+
+  /* To copy multiple ROM to RAM sections,
+   * uncomment .copy.table section and,
+   * define __STARTUP_COPY_MULTIPLE in startup_ARMCMx.S */
+  /*
+  .copy.table :
+  {
+    . = ALIGN(4);
+    __copy_table_start__ = .;
+    LONG (__etext)
+    LONG (__data_start__)
+    LONG (__data_end__ - __data_start__)
+    LONG (__etext2)
+    LONG (__data2_start__)
+    LONG (__data2_end__ - __data2_start__)
+    __copy_table_end__ = .;
+  } > FLASH
+  */
+
+  /* To clear multiple BSS sections,
+   * uncomment .zero.table section and,
+   * define __STARTUP_CLEAR_BSS_MULTIPLE in startup_ARMCMx.S */
+  /*
+  .zero.table :
+  {
+    . = ALIGN(4);
+    __zero_table_start__ = .;
+    LONG (__bss_start__)
+    LONG (__bss_end__ - __bss_start__)
+    LONG (__bss2_start__)
+    LONG (__bss2_end__ - __bss2_start__)
+    __zero_table_end__ = .;
+  } > FLASH
+  */
+
+  __etext = .;
+
+  /*******************************************************************/
+  /* Define flash block for BLE-simee & CHIP-nvm3                    */
+  /* simee: 9000H (36k) bytes for BLE nvm3                           */
+  /* chipNvm3_section: 4000H (16k) bytes for CHIP nvm3.              */
+  /* 8K is reserved for OpenThread's NVM which is mapped directly at */
+  /* the top of flash                                                */
+  /*******************************************************************/
+
+  OPENTHREAD_NVM_SIZE = 8192;
+
+  .nvm_dummy (DSECT):
+  {
+    __nvm3_dummy_begin = .;
+    . = ALIGN (8192);
+    __nvm3_dummy_simee = .;
+    KEEP(*(.simee));
+    . = ALIGN (8192);
+    __nvm3_dummy_chip = .;
+    KEEP(*(chipNvm3_section));
+    . = ALIGN (8192);
+    . += OPENTHREAD_NVM_SIZE;
+    . = ALIGN (8192);
+  } > FLASH
+
+  /* Set NVM to end of FLASH */
+  __nvm3Base = LENGTH(FLASH) - SIZEOF(.nvm_dummy) + (__nvm3_dummy_simee - __nvm3_dummy_begin);
+  __nvm3ChipBase = LENGTH(FLASH) - SIZEOF(.nvm_dummy) + (__nvm3_dummy_chip - __nvm3_dummy_begin);
+
+
+  /*******************************************************************/
+
+  .data : AT (__etext)
+  {
+    __data_start__ = .;
+    *(vtable)
+    *(.data*)
+    . = ALIGN (4);
+    PROVIDE (__ram_func_section_start = .);
+    *(.ram)
+    PROVIDE (__ram_func_section_end = .);
+
+    . = ALIGN(4);
+    /* preinit data */
+    PROVIDE_HIDDEN (__preinit_array_start = .);
+    KEEP(*(.preinit_array))
+    PROVIDE_HIDDEN (__preinit_array_end = .);
+
+    . = ALIGN(4);
+    /* init data */
+    PROVIDE_HIDDEN (__init_array_start = .);
+    KEEP(*(SORT(.init_array.*)))
+    KEEP(*(.init_array))
+    PROVIDE_HIDDEN (__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);
+    /* All data end */
+    __data_end__ = .;
+
+  } > RAM
+
+  .bss :
+  {
+    . = ALIGN(4);
+    __bss_start__ = .;
+    *(.bss*)
+    *(COMMON)
+    . = ALIGN(4);
+    __bss_end__ = .;
+  } > RAM
+
+  .heap (COPY):
+  {
+    __HeapBase = .;
+    __end__ = .;
+    end = __end__;
+    _end = __end__;
+    KEEP(*(.heap*))
+    __HeapLimit = .;
+  } > RAM
+
+  /* .stack_dummy section doesn't contains any symbols. It is only
+   * used for linker to calculate size of stack sections, and assign
+   * values to stack symbols later */
+  .stack_dummy (COPY):
+  {
+    KEEP(*(.stack*))
+  } > RAM
+
+  /* Set stack top to end of RAM, and stack limit move down by
+   * size of stack_dummy section */
+  __StackTop = ORIGIN(RAM) + LENGTH(RAM);
+  __StackLimit = __StackTop - SIZEOF(.stack_dummy);
+  PROVIDE(__stack = __StackTop);
+
+  /* Check if data + heap + stack exceeds RAM limit */
+  ASSERT(__StackLimit >= __HeapLimit, "region RAM overflowed with stack")
+
+
+  /* Check if FLASH usage exceeds FLASH size */
+  ASSERT( LENGTH(FLASH) >= (__etext + SIZEOF(.data)), "FLASH memory overflowed !")
+  ASSERT((__etext + SIZEOF(.data)) <= __nvm3Base, "FLASH memory overlapped with NVM section.")
+}
\ No newline at end of file
diff --git a/examples/platform/silabs/SiWx917/ldscripts/efr32mg24.ld b/examples/platform/silabs/SiWx917/ldscripts/efr32mg24.ld
new file mode 100644
index 0000000..b057a9a
--- /dev/null
+++ b/examples/platform/silabs/SiWx917/ldscripts/efr32mg24.ld
@@ -0,0 +1,243 @@
+/*
+ *
+ *    Copyright (c) 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     gcc_EFR32MG24.ld
+ * @brief    GNU Linker Script for Cortex-M based device
+ * @version  V2.2.0
+ * @date     16. December 2020
+ * Linker script for Silicon Labs EFR32MG24 devices
+ *******************************************************************************
+ * # License
+ * <b>Copyright 2022 Silicon Laboratories, Inc. www.silabs.com </b>
+ *******************************************************************************
+ *
+ * SPDX-License-Identifier: Zlib
+ * 
+ * The licensor of this software is Silicon Laboratories Inc.
+ * 
+ * This software is provided 'as-is', without any express or implied
+ * warranty. In no event will the authors be held liable for any damages
+ * arising from the use of this software.
+ * 
+ * Permission is granted to anyone to use this software for any purpose,
+ * including commercial applications, and to alter it and redistribute it
+ * freely, subject to the following restrictions:
+ * 
+ * 1. The origin of this software must not be misrepresented; you must not
+ *    claim that you wrote the original software. If you use this software
+ *    in a product, an acknowledgment in the product documentation would be
+ *    appreciated but is not required.
+ * 2. Altered source versions must be plainly marked as such, and must not be
+ *    misrepresented as being the original software.
+ * 3. This notice may not be removed or altered from any source distribution.
+ *
+ ******************************************************************************/
+
+MEMORY
+{
+  FLASH (rx) : ORIGIN = 0x08006000, LENGTH = 0x17A000
+  RAM (rwx)  : ORIGIN = 0x20000000, LENGTH = 0x40000
+}
+
+/* Linker script to place sections and symbol values. Should be used together
+ * with other linker script that defines memory regions FLASH and RAM.
+ * It references following symbols, which must be defined in code:
+ *   Reset_Handler : Entry of reset handler
+ *
+ * It defines following symbols, which code can use without definition:
+ *   __exidx_start
+ *   __exidx_end
+ *   __copy_table_start__
+ *   __copy_table_end__
+ *   __zero_table_start__
+ *   __zero_table_end__
+ *   __etext
+ *   __data_start__
+ *   __preinit_array_start
+ *   __preinit_array_end
+ *   __init_array_start
+ *   __init_array_end
+ *   __fini_array_start
+ *   __fini_array_end
+ *   __data_end__
+ *   __bss_start__
+ *   __bss_end__
+ *   __end__
+ *   end
+ *   __HeapLimit
+ *   __StackLimit
+ *   __StackTop
+ *   __stack
+ *   __StackSeal      (only if ARMv8-M stack sealing is used)
+ */
+
+ENTRY(Reset_Handler)
+
+SECTIONS
+{
+  .text :
+  {
+    KEEP(*(.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*)
+
+    KEEP(*(.eh_frame*))
+  } > FLASH
+  .ARM.extab :
+  {
+    *(.ARM.extab* .gnu.linkonce.armextab.*)
+  } > FLASH
+
+  __exidx_start = .;
+  .ARM.exidx :
+  {
+    *(.ARM.exidx* .gnu.linkonce.armexidx.*)
+  } > FLASH
+  __exidx_end = .;
+
+  .copy.table :
+  {
+    . = ALIGN(4);
+    __copy_table_start__ = .;
+
+    LONG (__etext)
+    LONG (__data_start__)
+    LONG ((__data_end__ - __data_start__) / 4)
+
+    __copy_table_end__ = .;
+  } > FLASH
+
+  .zero.table :
+  {
+    . = ALIGN(4);
+    __zero_table_start__ = .;
+    __zero_table_end__ = .;
+    __etext = ALIGN(4);
+  } > FLASH
+
+  .data : AT (__etext)
+  {
+    __data_start__ = .;
+    *(vtable)
+    *(.data*)
+    . = ALIGN (4);
+    PROVIDE (__ram_func_section_start = .);
+    *(.ram)
+    PROVIDE (__ram_func_section_end = .);
+
+    . = ALIGN(4);
+    /* preinit data */
+    PROVIDE_HIDDEN (__preinit_array_start = .);
+    KEEP(*(.preinit_array))
+    PROVIDE_HIDDEN (__preinit_array_end = .);
+
+    . = ALIGN(4);
+    /* init data */
+    PROVIDE_HIDDEN (__init_array_start = .);
+    KEEP(*(SORT(.init_array.*)))
+    KEEP(*(.init_array))
+    PROVIDE_HIDDEN (__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);
+    /* All data end */
+    __data_end__ = .;
+
+  } > RAM
+
+  .bss :
+  {
+    . = ALIGN(4);
+    __bss_start__ = .;
+    *(.bss)
+    *(.bss.*)
+    *(COMMON)
+    . = ALIGN(4);
+    __bss_end__ = .;
+  } > RAM AT > RAM
+
+  .heap (COPY):
+  {
+    __HeapBase = .;
+    __end__ = .;
+    end = __end__;
+    _end = __end__;
+    KEEP(*(.heap*))
+    __HeapLimit = .;
+  } > RAM
+
+  __main_flash_end__ = ORIGIN(FLASH) + LENGTH(FLASH);
+
+  /* .stack_dummy section doesn't contains any symbols. It is only
+   * used for linker to calculate size of stack sections, and assign
+   * values to stack symbols later */
+  .stack_dummy (COPY):
+  {
+    KEEP(*(.stack*))
+ /* KEEP(*(.stackseal*))*/
+  } > RAM
+
+  /* Set stack top to end of RAM, and stack limit move down by
+   * size of stack_dummy section */
+  __StackTop = ORIGIN(RAM) + LENGTH(RAM);
+  __StackLimit = __StackTop - SIZEOF(.stack_dummy);
+  PROVIDE(__stack = __StackTop);
+
+   .nvm (DSECT) : {
+    KEEP(*(.simee*))
+  } > FLASH
+
+  /* Last page of flash is reserved for the manufacturing token space */
+  linker_nvm_end = __main_flash_end__ - 8192;
+  linker_nvm_begin = linker_nvm_end - SIZEOF(.nvm);
+  linker_nvm_size = SIZEOF(.nvm);
+  __nvm3Base = linker_nvm_begin;
+  __attestation_credentials_base = linker_nvm_end;
+
+  /* Check if data + heap + stack exceeds RAM limit */
+  /*ASSERT(__StackLimit >= __HeapLimit, "region RAM overflowed with stack")*/
+  ASSERT( (linker_nvm_begin + SIZEOF(.nvm)) <= __main_flash_end__, "NVM3 is excessing the flash size !")
+
+  /* Check if FLASH usage exceeds FLASH size */
+  ASSERT( LENGTH(FLASH) >= (__etext + SIZEOF(.data)), "FLASH memory overflowed !")
+}
diff --git a/examples/platform/silabs/SiWx917/ldscripts/mgm24.ld b/examples/platform/silabs/SiWx917/ldscripts/mgm24.ld
new file mode 100644
index 0000000..b057a9a
--- /dev/null
+++ b/examples/platform/silabs/SiWx917/ldscripts/mgm24.ld
@@ -0,0 +1,243 @@
+/*
+ *
+ *    Copyright (c) 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     gcc_EFR32MG24.ld
+ * @brief    GNU Linker Script for Cortex-M based device
+ * @version  V2.2.0
+ * @date     16. December 2020
+ * Linker script for Silicon Labs EFR32MG24 devices
+ *******************************************************************************
+ * # License
+ * <b>Copyright 2022 Silicon Laboratories, Inc. www.silabs.com </b>
+ *******************************************************************************
+ *
+ * SPDX-License-Identifier: Zlib
+ * 
+ * The licensor of this software is Silicon Laboratories Inc.
+ * 
+ * This software is provided 'as-is', without any express or implied
+ * warranty. In no event will the authors be held liable for any damages
+ * arising from the use of this software.
+ * 
+ * Permission is granted to anyone to use this software for any purpose,
+ * including commercial applications, and to alter it and redistribute it
+ * freely, subject to the following restrictions:
+ * 
+ * 1. The origin of this software must not be misrepresented; you must not
+ *    claim that you wrote the original software. If you use this software
+ *    in a product, an acknowledgment in the product documentation would be
+ *    appreciated but is not required.
+ * 2. Altered source versions must be plainly marked as such, and must not be
+ *    misrepresented as being the original software.
+ * 3. This notice may not be removed or altered from any source distribution.
+ *
+ ******************************************************************************/
+
+MEMORY
+{
+  FLASH (rx) : ORIGIN = 0x08006000, LENGTH = 0x17A000
+  RAM (rwx)  : ORIGIN = 0x20000000, LENGTH = 0x40000
+}
+
+/* Linker script to place sections and symbol values. Should be used together
+ * with other linker script that defines memory regions FLASH and RAM.
+ * It references following symbols, which must be defined in code:
+ *   Reset_Handler : Entry of reset handler
+ *
+ * It defines following symbols, which code can use without definition:
+ *   __exidx_start
+ *   __exidx_end
+ *   __copy_table_start__
+ *   __copy_table_end__
+ *   __zero_table_start__
+ *   __zero_table_end__
+ *   __etext
+ *   __data_start__
+ *   __preinit_array_start
+ *   __preinit_array_end
+ *   __init_array_start
+ *   __init_array_end
+ *   __fini_array_start
+ *   __fini_array_end
+ *   __data_end__
+ *   __bss_start__
+ *   __bss_end__
+ *   __end__
+ *   end
+ *   __HeapLimit
+ *   __StackLimit
+ *   __StackTop
+ *   __stack
+ *   __StackSeal      (only if ARMv8-M stack sealing is used)
+ */
+
+ENTRY(Reset_Handler)
+
+SECTIONS
+{
+  .text :
+  {
+    KEEP(*(.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*)
+
+    KEEP(*(.eh_frame*))
+  } > FLASH
+  .ARM.extab :
+  {
+    *(.ARM.extab* .gnu.linkonce.armextab.*)
+  } > FLASH
+
+  __exidx_start = .;
+  .ARM.exidx :
+  {
+    *(.ARM.exidx* .gnu.linkonce.armexidx.*)
+  } > FLASH
+  __exidx_end = .;
+
+  .copy.table :
+  {
+    . = ALIGN(4);
+    __copy_table_start__ = .;
+
+    LONG (__etext)
+    LONG (__data_start__)
+    LONG ((__data_end__ - __data_start__) / 4)
+
+    __copy_table_end__ = .;
+  } > FLASH
+
+  .zero.table :
+  {
+    . = ALIGN(4);
+    __zero_table_start__ = .;
+    __zero_table_end__ = .;
+    __etext = ALIGN(4);
+  } > FLASH
+
+  .data : AT (__etext)
+  {
+    __data_start__ = .;
+    *(vtable)
+    *(.data*)
+    . = ALIGN (4);
+    PROVIDE (__ram_func_section_start = .);
+    *(.ram)
+    PROVIDE (__ram_func_section_end = .);
+
+    . = ALIGN(4);
+    /* preinit data */
+    PROVIDE_HIDDEN (__preinit_array_start = .);
+    KEEP(*(.preinit_array))
+    PROVIDE_HIDDEN (__preinit_array_end = .);
+
+    . = ALIGN(4);
+    /* init data */
+    PROVIDE_HIDDEN (__init_array_start = .);
+    KEEP(*(SORT(.init_array.*)))
+    KEEP(*(.init_array))
+    PROVIDE_HIDDEN (__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);
+    /* All data end */
+    __data_end__ = .;
+
+  } > RAM
+
+  .bss :
+  {
+    . = ALIGN(4);
+    __bss_start__ = .;
+    *(.bss)
+    *(.bss.*)
+    *(COMMON)
+    . = ALIGN(4);
+    __bss_end__ = .;
+  } > RAM AT > RAM
+
+  .heap (COPY):
+  {
+    __HeapBase = .;
+    __end__ = .;
+    end = __end__;
+    _end = __end__;
+    KEEP(*(.heap*))
+    __HeapLimit = .;
+  } > RAM
+
+  __main_flash_end__ = ORIGIN(FLASH) + LENGTH(FLASH);
+
+  /* .stack_dummy section doesn't contains any symbols. It is only
+   * used for linker to calculate size of stack sections, and assign
+   * values to stack symbols later */
+  .stack_dummy (COPY):
+  {
+    KEEP(*(.stack*))
+ /* KEEP(*(.stackseal*))*/
+  } > RAM
+
+  /* Set stack top to end of RAM, and stack limit move down by
+   * size of stack_dummy section */
+  __StackTop = ORIGIN(RAM) + LENGTH(RAM);
+  __StackLimit = __StackTop - SIZEOF(.stack_dummy);
+  PROVIDE(__stack = __StackTop);
+
+   .nvm (DSECT) : {
+    KEEP(*(.simee*))
+  } > FLASH
+
+  /* Last page of flash is reserved for the manufacturing token space */
+  linker_nvm_end = __main_flash_end__ - 8192;
+  linker_nvm_begin = linker_nvm_end - SIZEOF(.nvm);
+  linker_nvm_size = SIZEOF(.nvm);
+  __nvm3Base = linker_nvm_begin;
+  __attestation_credentials_base = linker_nvm_end;
+
+  /* Check if data + heap + stack exceeds RAM limit */
+  /*ASSERT(__StackLimit >= __HeapLimit, "region RAM overflowed with stack")*/
+  ASSERT( (linker_nvm_begin + SIZEOF(.nvm)) <= __main_flash_end__, "NVM3 is excessing the flash size !")
+
+  /* Check if FLASH usage exceeds FLASH size */
+  ASSERT( LENGTH(FLASH) >= (__etext + SIZEOF(.data)), "FLASH memory overflowed !")
+}
diff --git a/examples/platform/silabs/SiWx917/matter_config.cpp b/examples/platform/silabs/SiWx917/matter_config.cpp
new file mode 100644
index 0000000..83e9095
--- /dev/null
+++ b/examples/platform/silabs/SiWx917/matter_config.cpp
@@ -0,0 +1,243 @@
+/*
+ *
+ *    Copyright (c) 2020 Project CHIP Authors
+ *    Copyright (c) 2022 Silabs.
+ *    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 "AppConfig.h"
+#include "OTAConfig.h"
+#include <matter_config.h>
+
+#include <FreeRTOS.h>
+
+#include <mbedtls/platform.h>
+
+#ifdef SL_WIFI
+#include "wfx_host_events.h"
+#endif /* SL_WIFI */
+
+#if PW_RPC_ENABLED
+#include "Rpc.h"
+#endif
+
+#ifdef ENABLE_CHIP_SHELL
+#include "matter_shell.h"
+#endif
+
+#ifdef HEAP_MONITORING
+#include "MemMonitoring.h"
+#endif
+
+using namespace ::chip;
+using namespace ::chip::Inet;
+using namespace ::chip::DeviceLayer;
+
+#include <crypto/CHIPCryptoPAL.h>
+// If building with the EFR32-provided crypto backend, we can use the
+// opaque keystore
+#if CHIP_CRYPTO_PLATFORM
+#include <platform/silabs/EFR32/Efr32PsaOperationalKeystore.h>
+static chip::DeviceLayer::Internal::Efr32PsaOperationalKeystore gOperationalKeystore;
+#endif
+
+#include "EFR32DeviceDataProvider.h"
+
+#if CHIP_ENABLE_OPENTHREAD
+#include <inet/EndPointStateOpenThread.h>
+#include <openthread/cli.h>
+#include <openthread/dataset.h>
+#include <openthread/error.h>
+#include <openthread/heap.h>
+#include <openthread/icmp6.h>
+#include <openthread/instance.h>
+#include <openthread/link.h>
+#include <openthread/platform/openthread-system.h>
+#include <openthread/tasklet.h>
+#include <openthread/thread.h>
+
+// ================================================================================
+// Matter Networking Callbacks
+// ================================================================================
+void LockOpenThreadTask(void)
+{
+    chip::DeviceLayer::ThreadStackMgr().LockThreadStack();
+}
+
+void UnlockOpenThreadTask(void)
+{
+    chip::DeviceLayer::ThreadStackMgr().UnlockThreadStack();
+}
+
+// ================================================================================
+// EFR32MatterConfig Methods
+// ================================================================================
+
+CHIP_ERROR EFR32MatterConfig::InitOpenThread(void)
+{
+    SILABS_LOG("Initializing OpenThread stack");
+    ReturnErrorOnFailure(ThreadStackMgr().InitThreadStack());
+
+#if CHIP_DEVICE_CONFIG_THREAD_FTD
+    ReturnErrorOnFailure(ConnectivityMgr().SetThreadDeviceType(ConnectivityManager::kThreadDeviceType_Router));
+#else // CHIP_DEVICE_CONFIG_THREAD_FTD
+#if CHIP_DEVICE_CONFIG_ENABLE_SED
+    ReturnErrorOnFailure(ConnectivityMgr().SetThreadDeviceType(ConnectivityManager::kThreadDeviceType_SleepyEndDevice));
+#else  // CHIP_DEVICE_CONFIG_ENABLE_SED
+    ReturnErrorOnFailure(ConnectivityMgr().SetThreadDeviceType(ConnectivityManager::kThreadDeviceType_MinimalEndDevice));
+#endif // CHIP_DEVICE_CONFIG_ENABLE_SED
+#endif // CHIP_DEVICE_CONFIG_THREAD_FTD
+
+    SILABS_LOG("Starting OpenThread task");
+    return ThreadStackMgrImpl().StartThreadTask();
+}
+#endif // CHIP_ENABLE_OPENTHREAD
+
+#if EFR32_OTA_ENABLED
+void EFR32MatterConfig::InitOTARequestorHandler(System::Layer * systemLayer, void * appState)
+{
+    OTAConfig::Init();
+}
+#endif
+
+void EFR32MatterConfig::ConnectivityEventCallback(const ChipDeviceEvent * event, intptr_t arg)
+{
+    // Initialize OTA only when Thread or WiFi connectivity is established
+    if (((event->Type == DeviceEventType::kThreadConnectivityChange) &&
+         (event->ThreadConnectivityChange.Result == kConnectivity_Established)) ||
+        ((event->Type == DeviceEventType::kInternetConnectivityChange) &&
+         (event->InternetConnectivityChange.IPv6 == kConnectivity_Established)))
+    {
+#if EFR32_OTA_ENABLED
+        SILABS_LOG("Scheduling OTA Requestor initialization")
+        chip::DeviceLayer::SystemLayer().StartTimer(chip::System::Clock::Seconds32(OTAConfig::kInitOTARequestorDelaySec),
+                                                    InitOTARequestorHandler, nullptr);
+#endif
+    }
+}
+
+CHIP_ERROR EFR32MatterConfig::InitMatter(const char * appName)
+{
+    CHIP_ERROR err;
+
+    mbedtls_platform_set_calloc_free(CHIPPlatformMemoryCalloc, CHIPPlatformMemoryFree);
+
+    SILABS_LOG("==================================================");
+    SILABS_LOG("%s starting", appName);
+    SILABS_LOG("==================================================");
+
+#if PW_RPC_ENABLED
+    chip::rpc::Init();
+#endif
+
+#ifdef HEAP_MONITORING
+    MemMonitoring::startHeapMonitoring();
+#endif
+    SetDeviceInstanceInfoProvider(&EFR32::EFR32DeviceDataProvider::GetDeviceDataProvider());
+    SetCommissionableDataProvider(&EFR32::EFR32DeviceDataProvider::GetDeviceDataProvider());
+
+    //==============================================
+    // Init Matter Stack
+    //==============================================
+    SILABS_LOG("Init CHIP Stack");
+    // Init Chip memory management before the stack
+    ReturnErrorOnFailure(chip::Platform::MemoryInit());
+    ReturnErrorOnFailure(PlatformMgr().InitChipStack());
+
+    chip::DeviceLayer::ConnectivityMgr().SetBLEDeviceName(appName);
+
+#if CHIP_ENABLE_OPENTHREAD
+    ReturnErrorOnFailure(InitOpenThread());
+#endif
+
+    // Stop Matter event handling while setting up resources
+    chip::DeviceLayer::PlatformMgr().LockChipStack();
+
+    // Create initParams with SDK example defaults here
+    static chip::CommonCaseDeviceServerInitParams initParams;
+
+#if CHIP_CRYPTO_PLATFORM
+    // When building with EFR32 crypto, use the opaque key store
+    // instead of the default (insecure) one.
+    gOperationalKeystore.Init();
+    initParams.operationalKeystore = &gOperationalKeystore;
+#endif
+
+    // Initialize the remaining (not overridden) providers to the SDK example defaults
+    (void) initParams.InitializeStaticResourcesBeforeServerInit();
+
+#if CHIP_ENABLE_OPENTHREAD
+    // Set up OpenThread configuration when OpenThread is included
+    chip::Inet::EndPointStateOpenThread::OpenThreadEndpointInitParam nativeParams;
+    nativeParams.lockCb                = LockOpenThreadTask;
+    nativeParams.unlockCb              = UnlockOpenThreadTask;
+    nativeParams.openThreadInstancePtr = chip::DeviceLayer::ThreadStackMgrImpl().OTInstance();
+    initParams.endpointNativeParams    = static_cast<void *>(&nativeParams);
+#endif
+
+    // Init Matter Server and Start Event Loop
+    err = chip::Server::GetInstance().Init(initParams);
+    chip::DeviceLayer::PlatformMgr().UnlockChipStack();
+
+    ReturnErrorOnFailure(err);
+
+    // OTA Requestor initialization will be triggered by the connectivity events
+    PlatformMgr().AddEventHandler(ConnectivityEventCallback, reinterpret_cast<intptr_t>(nullptr));
+
+    SILABS_LOG("Starting Platform Manager Event Loop");
+    ReturnErrorOnFailure(PlatformMgr().StartEventLoopTask());
+
+#ifdef SL_WIFI
+    InitWiFi();
+#endif
+
+#ifdef ENABLE_CHIP_SHELL
+    chip::startShellTask();
+#endif
+
+    return CHIP_NO_ERROR;
+}
+
+#ifdef SL_WIFI
+void EFR32MatterConfig::InitWiFi(void)
+{
+#ifdef WF200_WIFI
+    // Start wfx bus communication task.
+    wfx_bus_start();
+#ifdef SL_WFX_USE_SECURE_LINK
+    wfx_securelink_task_start(); // start securelink key renegotiation task
+#endif                           // SL_WFX_USE_SECURE_LINK
+#endif                           /* WF200_WIFI */
+
+#ifdef RS911X_WIFI
+    /*
+     * Start up any RSI interface stuff
+     * (Not required) - Note that wfx_wifi_start will deal with
+     * starting up a rsi task - which will initialize the SPI interface.
+     */
+#endif
+}
+#endif // SL_WIFI
+
+// ================================================================================
+// FreeRTOS Callbacks
+// ================================================================================
+extern "C" void vApplicationIdleHook(void)
+{
+    // FreeRTOS Idle callback
+
+    // Check CHIP Config nvm3 and repack flash if necessary.
+    Internal::SILABSConfig::RepackNvm3Flash();
+}
diff --git a/examples/platform/silabs/SiWx917/matter_config.h b/examples/platform/silabs/SiWx917/matter_config.h
new file mode 100644
index 0000000..e0af603
--- /dev/null
+++ b/examples/platform/silabs/SiWx917/matter_config.h
@@ -0,0 +1,35 @@
+/*
+ *
+ *    Copyright (c) 2020 Project CHIP Authors
+ *    Copyright (c) 2022 Silabs.
+ *    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/CHIPMem.h>
+#include <lib/support/CHIPPlatformMemory.h>
+#include <platform/CHIPDeviceLayer.h>
+#include <platform/KeyValueStoreManager.h>
+
+class EFR32MatterConfig
+{
+public:
+    static CHIP_ERROR InitMatter(const char * appName);
+
+private:
+    static CHIP_ERROR InitOpenThread(void);
+    static void InitWiFi(void);
+    static void ConnectivityEventCallback(const chip::DeviceLayer::ChipDeviceEvent * event, intptr_t arg);
+    static void InitOTARequestorHandler(chip::System::Layer * systemLayer, void * appState);
+};
diff --git a/examples/platform/silabs/SiWx917/project_include/OpenThreadConfig.h b/examples/platform/silabs/SiWx917/project_include/OpenThreadConfig.h
new file mode 100644
index 0000000..dccf3c8
--- /dev/null
+++ b/examples/platform/silabs/SiWx917/project_include/OpenThreadConfig.h
@@ -0,0 +1,77 @@
+/*
+ *
+ *    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.
+ */
+
+/**
+ *    @file
+ *      Overrides to default OpenThread configuration.
+ *
+ */
+
+#pragma once
+
+#include <em_device.h>
+
+// Disable the SiLabs-supplied OpenThread logging facilities and use
+// the facilities provided by the Device Layer (see
+// src/platform/silabs/Logging.cpp).
+#define OPENTHREAD_CONFIG_LOG_OUTPUT OPENTHREAD_CONFIG_LOG_OUTPUT_APP
+
+// Turn on a moderate level of logging in OpenThread
+// Enable use of external heap allocator (calloc/free) for OpenThread.
+#define OPENTHREAD_CONFIG_HEAP_EXTERNAL_ENABLE 1
+
+// EFR32MG21A020F1024IM32 has 96k of RAM. Reduce the number of buffers to
+// conserve RAM for this Series 2 part.
+#if defined(EFR32MG21)
+#define OPENTHREAD_CONFIG_NUM_MESSAGE_BUFFERS 22
+#define OPENTHREAD_CONFIG_CLI_UART_TX_BUFFER_SIZE 512
+#define OPENTHREAD_CONFIG_CLI_UART_RX_BUFFER_SIZE 512
+#endif
+
+#define OPENTHREAD_CONFIG_NCP_HDLC_ENABLE 1
+#define OPENTHREAD_CONFIG_IP6_SLAAC_ENABLE 1
+
+#define OPENTHREAD_CONFIG_DNS_CLIENT_ENABLE 1
+#define OPENTHREAD_CONFIG_SRP_CLIENT_ENABLE 1
+#define OPENTHREAD_CONFIG_ECDSA_ENABLE 1
+
+// disable unused features
+#define OPENTHREAD_CONFIG_COAP_API_ENABLE 0
+#define OPENTHREAD_CONFIG_JOINER_ENABLE 0
+#define OPENTHREAD_CONFIG_COMMISSIONER_ENABLE 0
+#define OPENTHREAD_CONFIG_UDP_FORWARD_ENABLE 0
+#define OPENTHREAD_CONFIG_BORDER_ROUTER_ENABLE 0
+#define OPENTHREAD_CONFIG_DHCP6_CLIENT_ENABLE 0
+#define OPENTHREAD_CONFIG_DHCP6_SERVER_ENABLE 0
+#define OPENTHREAD_CONFIG_TCP_ENABLE 0
+
+// Support udp multicast by enabling Multicast Listener Registration (MLR)
+#define OPENTHREAD_CONFIG_MLR_ENABLE 1
+
+// Define as 1 to stay awake between fragments while transmitting a large packet,
+// and to stay awake after receiving a packet with frame pending set to true.
+#define OPENTHREAD_CONFIG_MAC_STAY_AWAKE_BETWEEN_FRAGMENTS 1
+
+// Use the SiLabs-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.
+//
+#include "openthread-core-efr32-config.h"
diff --git a/examples/platform/silabs/SiWx917/pw_sys_io/BUILD.gn b/examples/platform/silabs/SiWx917/pw_sys_io/BUILD.gn
new file mode 100644
index 0000000..722d2a7
--- /dev/null
+++ b/examples/platform/silabs/SiWx917/pw_sys_io/BUILD.gn
@@ -0,0 +1,39 @@
+# Copyright (c) 2021 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/pigweed.gni")
+
+import("$dir_pw_build/target_types.gni")
+
+examples_plat_dir = "${chip_root}/examples/platform/silabs/efr32"
+
+config("default_config") {
+  include_dirs = [ "public" ]
+}
+
+pw_source_set("pw_sys_io_efr32") {
+  sources = [ "sys_io_efr32.cc" ]
+
+  deps = [
+    "$dir_pw_sys_io:default_putget_bytes",
+    "$dir_pw_sys_io:facade",
+  ]
+
+  cflags = [ "-Wconversion" ]
+
+  public_configs = [ ":default_config" ]
+
+  include_dirs = [ "${examples_plat_dir}" ]
+}
diff --git a/examples/platform/silabs/SiWx917/pw_sys_io/public/pw_sys_io_efr32/init.h b/examples/platform/silabs/SiWx917/pw_sys_io/public/pw_sys_io_efr32/init.h
new file mode 100644
index 0000000..f11f5e9
--- /dev/null
+++ b/examples/platform/silabs/SiWx917/pw_sys_io/public/pw_sys_io_efr32/init.h
@@ -0,0 +1,27 @@
+/*
+ *
+ *    Copyright (c) 2021 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 "pw_preprocessor/util.h"
+
+PW_EXTERN_C_START
+
+// The actual implement of PreMainInit() in sys_io_BACKEND.
+void pw_sys_io_Init();
+
+PW_EXTERN_C_END
diff --git a/examples/platform/silabs/SiWx917/pw_sys_io/sys_io_efr32.cc b/examples/platform/silabs/SiWx917/pw_sys_io/sys_io_efr32.cc
new file mode 100644
index 0000000..4bc7d98
--- /dev/null
+++ b/examples/platform/silabs/SiWx917/pw_sys_io/sys_io_efr32.cc
@@ -0,0 +1,81 @@
+/*
+ *
+ *    Copyright (c) 2021 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 "pw_sys_io/sys_io.h"
+#include <cassert>
+#include <cinttypes>
+#include <stdio.h>
+#include <string.h>
+
+#include "uart.h"
+
+int16_t console_getchar(char * chr)
+{
+    int16_t retVal = 0;
+
+    // Busy wait for pw_rcp reads
+    while (retVal == 0)
+    {
+        retVal = uartConsoleRead(chr, 1);
+    }
+    return retVal;
+}
+
+int16_t console_putchar(const char * chr)
+{
+    return uartConsoleWrite(chr, 1);
+}
+
+extern "C" void pw_sys_io_Init()
+{
+    uartConsoleInit();
+}
+
+namespace pw::sys_io {
+
+Status ReadByte(std::byte * dest)
+{
+    if (!dest)
+        return Status::InvalidArgument();
+
+    int16_t ret = console_getchar(reinterpret_cast<char *>(dest));
+    return ret < 0 ? Status::FailedPrecondition() : OkStatus();
+}
+
+Status WriteByte(std::byte b)
+{
+    int16_t ret = console_putchar(reinterpret_cast<const char *>(&b));
+    return ret < 0 ? Status::FailedPrecondition() : OkStatus();
+}
+
+// Writes a string using pw::sys_io, and add newline characters at the end.
+StatusWithSize WriteLine(const std::string_view & s)
+{
+    size_t chars_written  = 0;
+    StatusWithSize result = WriteBytes(pw::as_bytes(pw::span(s)));
+    if (!result.ok())
+    {
+        return result;
+    }
+    chars_written += result.size();
+    result = WriteBytes(pw::as_bytes(pw::span("\r\n", 2)));
+    chars_written += result.size();
+
+    return StatusWithSize(result.status(), chars_written);
+}
+
+} // namespace pw::sys_io
diff --git a/examples/platform/silabs/SiWx917/rs911x/hal/efx_spi.c b/examples/platform/silabs/SiWx917/rs911x/hal/efx_spi.c
new file mode 100644
index 0000000..f01cac3
--- /dev/null
+++ b/examples/platform/silabs/SiWx917/rs911x/hal/efx_spi.c
@@ -0,0 +1,324 @@
+/*
+ *
+ *    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.
+ */
+
+/**
+ * Includes
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "dmadrv.h"
+#include "em_chip.h"
+#include "em_cmu.h"
+#include "em_core.h"
+#include "em_device.h"
+#include "em_gpio.h"
+#include "em_ldma.h"
+#if defined(EFR32MG12)
+#include "em_usart.h"
+#elif defined(EFR32MG24)
+#include "em_eusart.h"
+#endif
+#include "spidrv.h"
+
+#include "gpiointerrupt.h"
+#include "sl_device_init_clocks.h"
+#include "sl_status.h"
+
+#include "FreeRTOS.h"
+#include "event_groups.h"
+#include "task.h"
+
+#include "wfx_host_events.h"
+#include "wfx_rsi.h"
+
+#include "rsi_board_configuration.h"
+#include "rsi_driver.h"
+#include "sl_device_init_dpll.h"
+#include "sl_device_init_hfxo.h"
+
+StaticSemaphore_t xEfxSpiIntfSemaBuffer;
+static SemaphoreHandle_t spi_sem;
+
+#if defined(EFR32MG12)
+#include "sl_spidrv_exp_config.h"
+extern SPIDRV_Handle_t sl_spidrv_exp_handle;
+#endif
+
+#if defined(EFR32MG24)
+#include "sl_spidrv_eusart_exp_config.h"
+extern SPIDRV_Handle_t sl_spidrv_eusart_exp_handle;
+#endif
+
+static unsigned int tx_dma_channel;
+static unsigned int rx_dma_channel;
+
+static uint32_t dummy_data; /* Used for DMA - when results don't matter */
+extern void rsi_gpio_irq_cb(uint8_t irqnum);
+//#define RS911X_USE_LDMA
+
+/********************************************************
+ * @fn   sl_wfx_host_gpio_init(void)
+ * @brief
+ *        Deal with the PINS that are not associated with SPI -
+ *        Ie. RESET, Wakeup
+ * @return
+ *        None
+ **********************************************************/
+void sl_wfx_host_gpio_init(void)
+{
+    // Enable GPIO clock.
+    CMU_ClockEnable(cmuClock_GPIO, true);
+
+    GPIO_PinModeSet(WFX_RESET_PIN.port, WFX_RESET_PIN.pin, gpioModePushPull, PINOUT_SET);
+    GPIO_PinModeSet(WFX_SLEEP_CONFIRM_PIN.port, WFX_SLEEP_CONFIRM_PIN.pin, gpioModePushPull, PINOUT_CLEAR);
+
+    CMU_OscillatorEnable(cmuOsc_LFXO, true, true);
+
+    // Set up interrupt based callback function - trigger on both edges.
+    GPIOINT_Init();
+    GPIO_PinModeSet(WFX_INTERRUPT_PIN.port, WFX_INTERRUPT_PIN.pin, gpioModeInputPull, PINOUT_CLEAR);
+    GPIO_ExtIntConfig(WFX_INTERRUPT_PIN.port, WFX_INTERRUPT_PIN.pin, SL_WFX_HOST_PINOUT_SPI_IRQ, true, false, true);
+    GPIOINT_CallbackRegister(SL_WFX_HOST_PINOUT_SPI_IRQ, rsi_gpio_irq_cb);
+    GPIO_IntDisable(1 << SL_WFX_HOST_PINOUT_SPI_IRQ); /* Will be enabled by RSI */
+
+    // Change GPIO interrupt priority (FreeRTOS asserts unless this is done here!)
+    NVIC_SetPriority(GPIO_EVEN_IRQn, WFX_SPI_NVIC_PRIORITY);
+    NVIC_SetPriority(GPIO_ODD_IRQn, WFX_SPI_NVIC_PRIORITY);
+}
+
+/*****************************************************************
+ * @fn  void sl_wfx_host_reset_chip(void)
+ * @brief
+ *      To reset the WiFi CHIP
+ * @return
+ *      None
+ ****************************************************************/
+void sl_wfx_host_reset_chip(void)
+{
+    // Pull it low for at least 1 ms to issue a reset sequence
+    GPIO_PinOutClear(WFX_RESET_PIN.port, WFX_RESET_PIN.pin);
+
+    // Delay for 10ms
+    vTaskDelay(pdMS_TO_TICKS(10));
+
+    // Hold pin high to get chip out of reset
+    GPIO_PinOutSet(WFX_RESET_PIN.port, WFX_RESET_PIN.pin);
+
+    // Delay for 3ms
+    vTaskDelay(pdMS_TO_TICKS(3));
+}
+
+/*****************************************************************
+ * @fn   void rsi_hal_board_init(void)
+ * @brief
+ *       Initialize the board
+ * @return
+ *       None
+ ****************************************************************/
+void rsi_hal_board_init(void)
+{
+    spi_sem = xSemaphoreCreateBinaryStatic(&xEfxSpiIntfSemaBuffer);
+    xSemaphoreGive(spi_sem);
+
+    /* Assign DMA channel from Handle*/
+#if defined(EFR32MG12)
+    /* MG12 + rs9116 combination uses USART driver */
+    tx_dma_channel = sl_spidrv_exp_handle->txDMACh;
+    rx_dma_channel = sl_spidrv_exp_handle->rxDMACh;
+
+#elif defined(EFR32MG24)
+    /* MG24 + rs9116 combination uses EUSART driver */
+    tx_dma_channel = sl_spidrv_eusart_exp_handle->txDMACh;
+    rx_dma_channel = sl_spidrv_eusart_exp_handle->rxDMACh;
+#endif
+
+    /* GPIO INIT of MG12 & MG24 : Reset, Wakeup, Interrupt */
+    WFX_RSI_LOG("RSI_HAL: init GPIO");
+    sl_wfx_host_gpio_init();
+
+    /* Reset of Wifi chip */
+    WFX_RSI_LOG("RSI_HAL: Reset Wifi");
+    sl_wfx_host_reset_chip();
+    WFX_RSI_LOG("RSI_HAL: Init done");
+}
+
+/*****************************************************************************
+ *@fn static bool rx_dma_complete(unsigned int channel, unsigned int sequenceNo, void *userParam)
+ *
+ *@brief
+ *    complete dma
+ *
+ * @param[in] channel:
+ * @param[in] sequenceNO: sequence number
+ * @param[in] userParam :user parameter
+ *
+ * @return
+ *    None
+ ******************************************************************************/
+static bool rx_dma_complete(unsigned int channel, unsigned int sequenceNo, void * userParam)
+{
+    BaseType_t xHigherPriorityTaskWoken = pdFALSE;
+    // uint8_t *buf = (void *)userParam;
+
+    (void) channel;
+    (void) sequenceNo;
+    (void) userParam;
+
+    // WFX_RSI_LOG ("SPI: DMA done [%x,%x,%x,%x]", buf [0], buf [1], buf [2], buf [3]);
+    xSemaphoreGiveFromISR(spi_sem, &xHigherPriorityTaskWoken);
+    portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
+
+    return true;
+}
+
+/*************************************************************
+ * @fn   static void receiveDMA(uint8_t *rx_buf, uint16_t xlen)
+ * @brief
+ *       RX buf was specified
+ *       TX buf was not specified by caller - so we
+ *       transmit dummy data (typically 0)
+ * @param[in] rx_buf:
+ * @param[in] xlen:
+ * @return
+ *        None
+ *******************************************************************/
+static void receiveDMA(uint8_t * rx_buf, uint16_t xlen)
+{
+    /*
+     * The caller wants to receive data -
+     * The xmit can be dummy data (no src increment for tx)
+     */
+    dummy_data = 0;
+    DMADRV_PeripheralMemory(rx_dma_channel, MY_USART_RX_SIGNAL, (void *) rx_buf, (void *) &(MY_USART->RXDATA), true, xlen,
+                            dmadrvDataSize1, rx_dma_complete, NULL);
+
+    // Start transmit DMA.
+    DMADRV_MemoryPeripheral(tx_dma_channel, MY_USART_TX_SIGNAL, (void *) &(MY_USART->TXDATA), (void *) &(dummy_data), false, xlen,
+                            dmadrvDataSize1, NULL, NULL);
+}
+
+/*****************************************************************************
+ *@fn static void transmitDMA(void *rx_buf, void *tx_buf, uint8_t xlen)
+ *@brief
+ *    we have a tx_buf. There are some instances where
+ *    a rx_buf is not specified. If one is specified then
+ *    the caller wants results (auto increment src)
+ * @param[in] rx_buf:
+ * @param[in] tx_buf:
+ * @param[in] xlen:
+ * @return
+ *     None
+ ******************************************************************************/
+static void transmitDMA(uint8_t * rx_buf, uint8_t * tx_buf, uint16_t xlen)
+{
+    void * buf;
+    bool srcinc;
+    /*
+     * we have a tx_buf. There are some instances where
+     * a rx_buf is not specified. If one is specified then
+     * the caller wants results (auto increment src)
+     * TODO - the caller specified 8/32 bit - we should use this
+     * instead of dmadrvDataSize1 always
+     */
+    if (rx_buf == NULL)
+    {
+        buf    = &dummy_data;
+        srcinc = false;
+    }
+    else
+    {
+        buf                   = rx_buf;
+        srcinc                = true;
+        /* DEBUG */ rx_buf[0] = 0xAA;
+        rx_buf[1]             = 0x55;
+    }
+    DMADRV_PeripheralMemory(rx_dma_channel, MY_USART_RX_SIGNAL, buf, (void *) &(MY_USART->RXDATA), srcinc, xlen, dmadrvDataSize1,
+                            rx_dma_complete, buf);
+    // Start transmit DMA.
+    DMADRV_MemoryPeripheral(tx_dma_channel, MY_USART_TX_SIGNAL, (void *) &(MY_USART->TXDATA), (void *) tx_buf, true, xlen,
+                            dmadrvDataSize1, NULL, NULL);
+}
+
+/*********************************************************************
+ * @fn   int16_t rsi_spi_transfer(uint8_t *tx_buf, uint8_t *rx_buf, uint16_t xlen, uint8_t mode)
+ * @brief
+ *       Do a SPI transfer - Mode is 8/16 bit - But every 8 bit is aligned
+ * @param[in] tx_buf:
+ * @param[in] rx_buf:
+ * @param[in] xlen:
+ * @param[in] mode:
+ * @return
+ *        None
+ **************************************************************************/
+int16_t rsi_spi_transfer(uint8_t * tx_buf, uint8_t * rx_buf, uint16_t xlen, uint8_t mode)
+{
+    // WFX_RSI_LOG ("SPI: Xfer: tx=%x,rx=%x,len=%d",(uint32_t)tx_buf, (uint32_t)rx_buf, xlen);
+    if (xlen > MIN_XLEN)
+    {
+        MY_USART->CMD = USART_CMD_CLEARRX | USART_CMD_CLEARTX;
+        if (xSemaphoreTake(spi_sem, portMAX_DELAY) != pdTRUE)
+        {
+            return RSI_FALSE;
+        }
+        if (tx_buf == NULL)
+        {
+            receiveDMA(rx_buf, xlen);
+        }
+        else
+        {
+            transmitDMA(rx_buf, tx_buf, xlen);
+        }
+
+        /*
+         * receiveDMA() and transmitDMA() are asynchronous
+         * Our application design assumes that this function is synchronous
+         * To make it synchronous, we wait to re-acquire the semaphore before exiting this function
+         * rx_dma_complete() gives back the semaphore when the SPI transfer is done
+         */
+        if (xSemaphoreTake(spi_sem, pdMS_TO_TICKS(RSI_SEM_BLOCK_MIN_TIMER_VALUE_MS)) == pdTRUE)
+        {
+            // Transfer complete
+            // Give back the semaphore before exiting, so that it may be re-acquired
+            // in this function, just before the next transfer
+            xSemaphoreGive(spi_sem);
+        }
+        // Temporary patch
+        // Sometimes the xSemaphoreTake() above is getting stuck indefinitely
+        // As a workaround, if the transfer is not done within RSI_SEM_BLOCK_MIN_TIMER_VALUE_MS
+        // stop and start it again
+        // No need to re-acquire the semaphore since this is the function that acquired it
+        // TODO: Remove this after a permanent solution is found to the problem of the transfer getting stuck
+        else
+        {
+            uint32_t ldma_flags = 0;
+            uint32_t rem_len    = 0;
+            rem_len             = LDMA_TransferRemainingCount(RSI_LDMA_TRANSFER_CHANNEL_NUM);
+            LDMA_StopTransfer(RSI_LDMA_TRANSFER_CHANNEL_NUM);
+            ldma_flags = LDMA_IntGet();
+            LDMA_IntClear(ldma_flags);
+            receiveDMA(rx_buf, rem_len);
+            if (xSemaphoreTake(spi_sem, portMAX_DELAY) == pdTRUE)
+            {
+                xSemaphoreGive(spi_sem);
+            }
+        }
+    }
+
+    return RSI_ERROR_NONE;
+}
diff --git a/examples/platform/silabs/SiWx917/rs911x/hal/rsi_board_configuration.h b/examples/platform/silabs/SiWx917/rs911x/hal/rsi_board_configuration.h
new file mode 100644
index 0000000..204e751
--- /dev/null
+++ b/examples/platform/silabs/SiWx917/rs911x/hal/rsi_board_configuration.h
@@ -0,0 +1,43 @@
+/*
+ *
+ *    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.
+ */
+
+#ifndef _RSI_BOARD_CONFIGURATION_H_
+#define _RSI_BOARD_CONFIGURATION_H_
+
+typedef struct
+{
+    unsigned char port;
+    unsigned char pin;
+} rsi_pin_t;
+
+#define PIN(port_id, pin_id)                                                                                                       \
+    (rsi_pin_t) { .port = gpioPort##port_id, .pin = pin_id }
+
+#if defined(EFR32MG12_BRD4161A) || defined(BRD4161A) || defined(EFR32MG12_BRD4162A) || defined(BRD4162A) ||                        \
+    defined(EFR32MG12_BRD4163A) || defined(BRD4163A) || defined(EFR32MG12_BRD4164A) || defined(BRD4164A) ||                        \
+    defined(EFR32MG12_BRD4170A) || defined(BRD4170A)
+// BRD4161-63-64 are pin to pin compatible for SPI
+#include "brd4161a.h"
+#elif defined(EFR32MG24_BRD4186C) || defined(BRD4186C)
+#include "brd4186c.h"
+#elif defined(EFR32MG24_BRD4187C) || defined(BRD4187C)
+#include "brd4187c.h"
+#else
+#error "Need SPI Pins"
+#endif /* EFR32MG12_BRD4161A */
+
+#endif /* _RSI_BOARD_CONFIGURATION_H_ */
diff --git a/examples/platform/silabs/SiWx917/rs911x/hal/rsi_hal.h b/examples/platform/silabs/SiWx917/rs911x/hal/rsi_hal.h
new file mode 100644
index 0000000..4e19543
--- /dev/null
+++ b/examples/platform/silabs/SiWx917/rs911x/hal/rsi_hal.h
@@ -0,0 +1,111 @@
+/*
+ *
+ *    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.
+ */
+
+#ifndef _HAL_RSI_HAL_H_
+#define _HAL_RSI_HAL_H_
+#include "rsi_board_configuration.h"
+
+#define RSI_HAL_NO_COM_PORT /* This will be done by the project */
+
+/* Should be enums */
+#define RSI_HAL_RESET_PIN 0
+#define RSI_HAL_MODULE_INTERRUPT 1
+#define RSI_HAL_SLEEP_CONFIRM_PIN 2
+#define RSI_HAL_WAKEUP_INDICATION_PIN 3
+#define RSI_HAL_MODULE_INTERRUPT_PIN 4
+
+//! Timer related macros
+//! Macro to configure timer type in single shot
+#define RSI_HAL_TIMER_TYPE_SINGLE_SHOT 0
+
+// Macro to configure timer type in periodic
+#define RSI_HAL_TIMER_TYPE_PERIODIC 1
+
+// Macro to configure timer in micro seconds mode
+#define RSI_HAL_TIMER_MODE_MICRO 0
+
+// Macro to configure timer in milli seconds mode
+#define RSI_HAL_TIMER_MODE_MILLI 1
+
+//! GPIO Pins related Macros
+//! Macro to configure GPIO in output mode
+#define RSI_HAL_GPIO_OUTPUT_MODE 1
+
+// Macro to configure GPIO in input mode
+#define RSI_HAL_GPIO_INPUT_MODE 0
+
+// Macro to drive low value on GPIO
+#define RSI_HAL_GPIO_LOW 0
+
+// Macro to drive high value on GPIO
+#define RSI_HAL_GPIO_HIGH 1
+
+// Macro to drive LDMA channel number
+#define RSI_LDMA_TRANSFER_CHANNEL_NUM 3
+
+// Macro to drive semaphore block minimun timer in milli seconds
+#define RSI_SEM_BLOCK_MIN_TIMER_VALUE_MS 50
+
+/******************************************************
+ * *               Function Declarations
+ * ******************************************************/
+
+void rsi_hal_board_init(void);
+void rsi_switch_to_high_clk_freq(void);
+void rsi_hal_intr_config(void (*rsi_interrupt_handler)(void));
+void rsi_hal_intr_mask(void);
+void rsi_hal_intr_unmask(void);
+void rsi_hal_intr_clear(void);
+uint8_t rsi_hal_intr_pin_status(void);
+void rsi_hal_config_gpio(uint8_t gpio_number, uint8_t mode, uint8_t value);
+void rsi_hal_set_gpio(uint8_t gpio_number);
+uint8_t rsi_hal_get_gpio(uint8_t gpio_number);
+void rsi_hal_clear_gpio(uint8_t gpio_number);
+int16_t rsi_spi_transfer(uint8_t * tx_buff, uint8_t * rx_buff, uint16_t transfer_length, uint8_t mode);
+int16_t rsi_uart_send(uint8_t * ptrBuf, uint16_t bufLen);
+int16_t rsi_uart_recv(uint8_t * ptrBuf, uint16_t bufLen);
+int16_t rsi_com_port_send(uint8_t * ptrBuf, uint16_t bufLen);
+int16_t rsi_com_port_receive(uint8_t * ptrBuf, uint16_t bufLen);
+uint32_t rsi_get_random_number(void);
+int32_t rsi_timer_start(uint8_t timer_node, uint8_t mode, uint8_t type, uint32_t duration, void (*rsi_timer_expiry_handler)(void));
+int32_t rsi_timer_stop(uint8_t timer_node);
+uint32_t rsi_timer_read(uint8_t timer_node);
+void rsi_delay_us(uint32_t delay_us);
+void rsi_delay_ms(uint32_t delay_ms);
+uint32_t rsi_hal_gettickcount(void);
+void SysTick_Handler(void);
+
+void rsi_interrupt_handler(void);
+void ABRD(void);
+
+void Error_Handler(void);
+
+/* RTC Related API's */
+uint32_t rsi_rtc_get_time(void);
+int32_t rsi_rtc_set_time(uint32_t time);
+/* End - RTC Related API's */
+
+#ifdef LOGGING_STATS
+void rsi_hal_log_stats_intr_config(void (*rsi_give_wakeup_indication)());
+#endif /* LOGGING_STATS */
+#ifdef RSI_WITH_OS
+void rsi_os_delay_ms(uint32_t delay_ms);
+void PORTD_IRQHandler(void);
+
+#endif /* RSI_WITH_OS */
+
+#endif
diff --git a/examples/platform/silabs/SiWx917/rs911x/hal/rsi_hal_mcu_interrupt.c b/examples/platform/silabs/SiWx917/rs911x/hal/rsi_hal_mcu_interrupt.c
new file mode 100644
index 0000000..40e4189
--- /dev/null
+++ b/examples/platform/silabs/SiWx917/rs911x/hal/rsi_hal_mcu_interrupt.c
@@ -0,0 +1,161 @@
+/*
+ *
+ *    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 <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "dmadrv.h"
+#include "em_chip.h"
+#include "em_cmu.h"
+#include "em_core.h"
+#include "em_device.h"
+#include "em_gpio.h"
+#include "em_ldma.h"
+#include "em_usart.h"
+#include "gpiointerrupt.h"
+#include "sl_device_init_clocks.h"
+#include "sl_status.h"
+
+#include "FreeRTOS.h"
+#include "event_groups.h"
+#include "task.h"
+
+#include "wfx_host_events.h"
+#include "wfx_rsi.h"
+
+#include "rsi_board_configuration.h"
+#include "rsi_driver.h"
+
+typedef void (*UserIntCallBack_t)(void);
+UserIntCallBack_t call_back, gpio_callback;
+#ifdef LOGGING_STATS
+uint8_t current_pin_set, prev_pin_set;
+#endif /* LOGGING_STATS */
+
+/* ARGSUSED */
+void rsi_gpio_irq_cb(uint8_t irqnum)
+{
+
+    // WFX_RSI_LOG ("RSI: Got Int=%d", irqnum)
+    if (irqnum != SL_WFX_HOST_PINOUT_SPI_IRQ)
+        return;
+    GPIO_IntClear(1 << SL_WFX_HOST_PINOUT_SPI_IRQ);
+
+    // WFX_RSI_LOG ("Got SPI intr, cb=%x", (uint32_t)call_back);
+    if (call_back != NULL)
+        (*call_back)();
+}
+
+/*===================================================*/
+/**
+ * @fn           void rsi_hal_intr_config(void (* rsi_interrupt_handler)())
+ * @brief        Starts and enables the SPI interrupt
+ * @param[in]    rsi_interrupt_handler() ,call back function to handle interrupt
+ * @param[out]   none
+ * @return       none
+ * @description  This HAL API should contain the code to initialize the register/pins
+ *               related to interrupts and enable the interrupts.
+ */
+void rsi_hal_intr_config(void (*rsi_interrupt_handler)(void))
+{
+    call_back = rsi_interrupt_handler;
+    WFX_RSI_LOG("RSI:Set SPI intr CB to=%x", (uint32_t) call_back);
+}
+
+/*===================================================*/
+/**
+ * @fn           void rsi_hal_log_stats_intr_config(void (* rsi_give_wakeup_indication)())
+ * @brief        Checks the interrupt and map/set gpio callback function
+ * @param[in]    rsi_give_wakeup_indication() ,gpio call back function to handle interrupt
+ * @param[out]   none
+ * @return       none
+ * @description  This HAL API should contain the code
+ *               related to mapping of gpio callback function.
+ */
+#ifdef LOGGING_STATS
+void rsi_hal_log_stats_intr_config(void (*rsi_give_wakeup_indication)())
+{
+    gpio_callback = rsi_give_wakeup_indication;
+}
+#endif
+
+/*===================================================*/
+/**
+ * @fn           void rsi_hal_intr_mask(void)
+ * @brief        Disables the SPI Interrupt
+ * @param[in]    none
+ * @param[out]   none
+ * @return       none
+ * @description  This HAL API should contain the code to mask/disable interrupts.
+ */
+void rsi_hal_intr_mask(void)
+{
+    // WFX_RSI_LOG ("RSI:Disable IRQ");
+    // NVIC_DisableIRQ(GPIO_ODD_IRQn);
+    GPIO_IntDisable(1 << SL_WFX_HOST_PINOUT_SPI_IRQ);
+}
+
+/*===================================================*/
+/**
+ * @fn           void rsi_hal_intr_unmask(void)
+ * @brief        Enables the SPI interrupt
+ * @param[in]    none
+ * @param[out]   none
+ * @return       none
+ * @description  This HAL API should contain the code to enable interrupts.
+ */
+void rsi_hal_intr_unmask(void)
+{
+    // Unmask/Enable the interrupt
+    NVIC_EnableIRQ(GPIO_ODD_IRQn);
+    NVIC_EnableIRQ(GPIO_EVEN_IRQn);
+    GPIO_IntEnable(1 << SL_WFX_HOST_PINOUT_SPI_IRQ);
+    // WFX_RSI_LOG ("RSI:Enable IRQ (mask=%x)", GPIO_IntGetEnabled ());
+}
+
+/*===================================================*/
+/**
+ * @fn           void rsi_hal_intr_clear(void)
+ * @brief        Clears the pending interrupt
+ * @param[in]    none
+ * @param[out]   none
+ * @return       none
+ * @description  This HAL API should contain the code to clear the handled interrupts.
+ */
+void rsi_hal_intr_clear(void)
+{
+    GPIO_IntClear(1 << SL_WFX_HOST_PINOUT_SPI_IRQ);
+}
+
+/*===================================================*/
+/**
+ * @fn          void rsi_hal_intr_pin_status(void)
+ * @brief       Checks the SPI interrupt at pin level
+ * @param[in]   none
+ * @param[out]  uint8_t, interrupt status
+ * @return      none
+ * @description This API is used to check interrupt pin status(pin level whether it is high/low).
+ */
+uint8_t rsi_hal_intr_pin_status(void)
+{
+    uint32_t mask;
+    // Return interrupt pin  status(high(1) /low (0))
+    mask = GPIO_PinInGet(WFX_INTERRUPT_PIN.port, WFX_INTERRUPT_PIN.pin);
+
+    return !!mask;
+}
diff --git a/examples/platform/silabs/SiWx917/rs911x/hal/rsi_hal_mcu_ioports.c b/examples/platform/silabs/SiWx917/rs911x/hal/rsi_hal_mcu_ioports.c
new file mode 100644
index 0000000..1ff5bc5
--- /dev/null
+++ b/examples/platform/silabs/SiWx917/rs911x/hal/rsi_hal_mcu_ioports.c
@@ -0,0 +1,141 @@
+/*
+ *
+ *    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 <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "dmadrv.h"
+#include "em_chip.h"
+#include "em_cmu.h"
+#include "em_core.h"
+#include "em_device.h"
+#include "em_gpio.h"
+#include "em_ldma.h"
+#include "em_usart.h"
+#include "gpiointerrupt.h"
+#include "sl_device_init_clocks.h"
+#include "sl_status.h"
+
+#include "FreeRTOS.h"
+#include "event_groups.h"
+#include "task.h"
+
+#include "wfx_host_events.h"
+#include "wfx_rsi.h"
+
+#include "rsi_board_configuration.h"
+#include "rsi_driver.h"
+
+/*===========================================================*/
+/**
+ * @fn            void rsi_hal_config_gpio(uint8_t gpio_number,uint8_t mode,uint8_t value)
+ * @brief         Configures gpio pin in output mode,with a value
+ * @param[in]     uint8_t gpio_number, gpio pin number to be configured
+ * @param[in]     uint8_t mode , input/output mode of the gpio pin to configure
+ *                0 - input mode
+ *                1 - output mode
+ * @param[in]     uint8_t value, default value to be driven if gpio is configured in output mode
+ *                0 - low
+ *                1 - high
+ * @param[out]    none
+ * @return        none
+ * @description This API is used to configure host gpio pin in output mode.
+ */
+void rsi_hal_config_gpio(uint8_t gpio_number, uint8_t mode, uint8_t value)
+{
+
+    CMU_ClockEnable(cmuClock_GPIO, true);
+
+    // WFX_RSI_LOG ("RSI: CFG GPIO: 0x%x", gpio_number);
+    switch (gpio_number)
+    {
+    case RSI_HAL_RESET_PIN:
+        GPIO_PinModeSet(WFX_RESET_PIN.port, WFX_RESET_PIN.pin, gpioModePushPull, PINOUT_SET);
+        break;
+    default:
+        break;
+    }
+}
+
+/*===========================================================*/
+/**
+ * @fn            void rsi_hal_set_gpio(uint8_t gpio_number)
+ * @brief         Makes/drives the gpio  value high
+ * @param[in]     uint8_t gpio_number, gpio pin number
+ * @param[out]    none
+ * @return        none
+ * @description   This API is used to drives or makes the host gpio value high.
+ */
+void rsi_hal_set_gpio(uint8_t gpio_number)
+{
+    // WFX_RSI_LOG ("RSI: SET GPIO: 0x%x", gpio_number);
+    switch (gpio_number)
+    {
+    case RSI_HAL_RESET_PIN:
+        GPIO_PinModeSet(WFX_RESET_PIN.port, WFX_RESET_PIN.pin, gpioModeWiredOrPullDown, PINOUT_SET);
+        break;
+    default:
+        break;
+    }
+}
+
+/*===========================================================*/
+/**
+ * @fn          uint8_t rsi_hal_get_gpio(void)
+ * @brief       get the gpio pin value
+ * @param[in]   uint8_t gpio_number, gpio pin number
+ * @param[out]  none
+ * @return      gpio pin value
+ * @description This API is used to configure get the gpio pin value.
+ */
+uint8_t rsi_hal_get_gpio(uint8_t gpio_number)
+{
+    // WFX_RSI_LOG ("RSI: GET GPIO: 0x%x", gpio_number);
+    switch (gpio_number)
+    {
+    case RSI_HAL_RESET_PIN:
+        return GPIO_PinInGet(WFX_RESET_PIN.port, WFX_RESET_PIN.pin);
+    case RSI_HAL_MODULE_INTERRUPT_PIN:
+        return GPIO_PinInGet(WFX_INTERRUPT_PIN.port, WFX_INTERRUPT_PIN.pin);
+    default:
+        break;
+    }
+
+    return 0;
+}
+
+/*===========================================================*/
+/**
+ * @fn            void rsi_hal_set_gpio(uint8_t gpio_number)
+ * @brief         Makes/drives the gpio value to low
+ * @param[in]     uint8_t gpio_number, gpio pin number
+ * @param[out]    none
+ * @return        none
+ * @description   This API is used to drives or makes the host gpio value low.
+ */
+void rsi_hal_clear_gpio(uint8_t gpio_number)
+{
+    // WFX_RSI_LOG ("RSI: CLR GPIO: 0x%x", gpio_number);
+    switch (gpio_number)
+    {
+    case RSI_HAL_RESET_PIN:
+        return GPIO_PinOutClear(WFX_RESET_PIN.port, WFX_RESET_PIN.pin);
+    default:
+        break;
+    }
+}
diff --git a/examples/platform/silabs/SiWx917/rs911x/hal/rsi_hal_mcu_rtc.c b/examples/platform/silabs/SiWx917/rs911x/hal/rsi_hal_mcu_rtc.c
new file mode 100644
index 0000000..f57d47a
--- /dev/null
+++ b/examples/platform/silabs/SiWx917/rs911x/hal/rsi_hal_mcu_rtc.c
@@ -0,0 +1,326 @@
+/*
+ *
+ *    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.
+ */
+
+/**
+ * Includes
+ */
+#include "em_cmu.h"
+#include "em_core.h"
+#include "em_rtcc.h"
+#include "sl_sleeptimer_config.h"
+#include "sl_status.h"
+#include <stdlib.h>
+#include <time.h>
+
+#define ZONE0 0
+#define CH_SELECTOR 1u
+#define RTC_DEFAULT_COUNTER_VALUE 0u
+#define RSI_RTC_FREQ_VALUE 0
+#define TIME_ZONE_OFFSET 0u
+
+#define SLEEPTIMER_EVENT_OF (0x01)
+#define SLEEPTIMER_EVENT_COMP (0x02)
+#define SLEEPTIMER_ENUM(name)                                                                                                      \
+    typedef uint8_t name;                                                                                                          \
+    enum name##_enum
+#define TIME_UNIX_EPOCH (1970u)
+#define TIME_NTP_EPOCH (1900u)
+#define TIME_ZIGBEE_EPOCH (2000u)
+#define TIME_NTP_UNIX_EPOCH_DIFF (TIME_UNIX_EPOCH - TIME_NTP_EPOCH)
+#define TIME_ZIGBEE_UNIX_EPOCH_DIFF (TIME_ZIGBEE_EPOCH - TIME_UNIX_EPOCH)
+#define TIME_DAY_COUNT_NTP_TO_UNIX_EPOCH (TIME_NTP_UNIX_EPOCH_DIFF * 365u + 17u)      ///< 70 years and 17 leap days
+#define TIME_DAY_COUNT_ZIGBEE_TO_UNIX_EPOCH (TIME_ZIGBEE_UNIX_EPOCH_DIFF * 365u + 7u) ///< 30 years and 7 leap days
+#define TIME_SEC_PER_DAY (60u * 60u * 24u)
+#define TIME_NTP_EPOCH_OFFSET_SEC (TIME_DAY_COUNT_NTP_TO_UNIX_EPOCH * TIME_SEC_PER_DAY)
+#define TIME_ZIGBEE_EPOCH_OFFSET_SEC (TIME_DAY_COUNT_ZIGBEE_TO_UNIX_EPOCH * TIME_SEC_PER_DAY)
+#define TIME_DAY_PER_YEAR (365u)
+#define TIME_SEC_PER_YEAR (TIME_SEC_PER_DAY * TIME_DAY_PER_YEAR)
+#define TIME_UNIX_TIMESTAMP_MAX (0x7FFFFFFF)
+
+/// Time zone offset from UTC(second).
+typedef int32_t sl_sleeptimer_time_zone_offset_t;
+/// Timestamp, wall clock time in seconds.
+typedef uint32_t sl_sleeptimer_timestamp_t;
+/// @brief Time Format.
+SLEEPTIMER_ENUM(sl_sleeptimer_time_format_t){
+    TIME_FORMAT_UNIX = 0,           ///< Number of seconds since January 1, 1970, 00:00.
+                                    ///< Type is signed, so represented on 31 bit.
+    TIME_FORMAT_NTP = 1,            ///< Number of seconds since January 1, 1900, 00:00.
+                                    ///< Type is unsigned, so represented on 32 bit.
+    TIME_FORMAT_ZIGBEE_CLUSTER = 2, ///< Number of seconds since January 1, 2000, 00:00. Type is
+                                    ///< unsigned, so represented on 32 bit.
+};
+
+// Initialization flag.
+static bool is_sleeptimer_initialized = false;
+// Timer frequency in Hz.
+static uint32_t timer_frequency;
+#if SL_SLEEPTIMER_WALLCLOCK_CONFIG
+// Current time count.
+static sl_sleeptimer_timestamp_t second_count;
+// Tick rest when the frequency is not a divider of the timer width.
+static uint32_t overflow_tick_rest = 0;
+#endif
+
+/*******************************************************************************
+ * Checks if the time stamp, format and time zone are
+ *  within the supported range.
+ *
+ * @param time Time stamp to check.
+ * @param format Format of the time.
+ * @param time_zone Time zone offset in second.
+ *
+ * @return true if the time is valid. False otherwise.
+ ******************************************************************************/
+static bool is_valid_time(sl_sleeptimer_timestamp_t time, sl_sleeptimer_time_format_t format,
+                          sl_sleeptimer_time_zone_offset_t time_zone)
+{
+    bool valid_time = false;
+
+    // Check for overflow.
+    if ((time_zone < ZONE0 && time > (uint32_t) abs(time_zone)) || (time_zone >= ZONE0 && (time <= UINT32_MAX - time_zone)))
+    {
+        valid_time = true;
+    }
+    if (format == TIME_FORMAT_UNIX)
+    {
+        if (time > TIME_UNIX_TIMESTAMP_MAX)
+        { // Check if Unix time stamp is an
+          // unsigned 31 bits.
+            valid_time = false;
+        }
+    }
+    else
+    {
+        if ((format == TIME_FORMAT_NTP) && (time >= TIME_NTP_EPOCH_OFFSET_SEC))
+        {
+            valid_time &= true;
+        }
+        else if ((format == TIME_FORMAT_ZIGBEE_CLUSTER) && (time <= TIME_UNIX_TIMESTAMP_MAX - TIME_ZIGBEE_EPOCH_OFFSET_SEC))
+        {
+            valid_time &= true;
+        }
+        else
+        {
+            valid_time = false;
+        }
+    }
+    return valid_time;
+}
+
+/*******************************************************************************
+ * Gets RTCC timer frequency.
+ ******************************************************************************/
+uint32_t rsi_rtc_get_hal_timer_frequency(void)
+{
+    /* CMU_PrescToLog2 converts prescaler dividend to a logarithmic value. It only works for even
+     * numbers equal to 2^n.
+     * An unscaled dividend (dividend = argument + 1).
+     * So we need to send argument subtracted by 1
+     */
+    return (CMU_ClockFreqGet(cmuClock_RTCC) >> (CMU_PrescToLog2(SL_SLEEPTIMER_FREQ_DIVIDER - 1)));
+}
+
+/******************************************************************************
+ * Initializes RTCC sleep timer.
+ *****************************************************************************/
+void rsi_rtc_init_timer(void)
+{
+    RTCC_Init_TypeDef rtcc_init   = RTCC_INIT_DEFAULT;
+    RTCC_CCChConf_TypeDef channel = RTCC_CH_INIT_COMPARE_DEFAULT;
+
+    CMU_ClockEnable(cmuClock_RTCC, true);
+
+    rtcc_init.enable = false;
+
+    /* CMU_PrescToLog2 converts prescaler dividend to a logarithmic value. It only works for even
+     * numbers equal to 2^n.
+     * An unscaled dividend (dividend = argument + 1).
+     * So we need to send argument subtracted by 1
+     */
+    rtcc_init.presc = (RTCC_CntPresc_TypeDef)(CMU_PrescToLog2(SL_SLEEPTIMER_FREQ_DIVIDER - 1));
+
+    RTCC_Init(&rtcc_init);
+
+    // Compare channel starts disabled and is enabled only when compare match
+    // interrupt is enabled.
+    channel.chMode = rtccCapComChModeOff;
+    RTCC_ChannelInit(CH_SELECTOR, &channel);
+
+    RTCC_IntDisable(_RTCC_IEN_MASK);
+    RTCC_IntClear(_RTCC_IF_MASK);
+    RTCC_CounterSet(RTC_DEFAULT_COUNTER_VALUE);
+
+    RTCC_Enable(true);
+
+    NVIC_ClearPendingIRQ(RTCC_IRQn);
+    NVIC_EnableIRQ(RTCC_IRQn);
+}
+
+/******************************************************************************
+ * Enables RTCC interrupts.
+ *****************************************************************************/
+void rsi_rtc_enable_int(uint8_t local_flag)
+{
+    uint32_t rtcc_ien = 0u;
+
+    if (local_flag & SLEEPTIMER_EVENT_OF)
+    {
+        rtcc_ien |= RTCC_IEN_OF;
+    }
+
+    if (local_flag & SLEEPTIMER_EVENT_COMP)
+    {
+        rtcc_ien |= RTCC_IEN_CC1;
+    }
+
+    RTCC_IntEnable(rtcc_ien);
+}
+
+/*******************************************************************************
+ * Get timer frequency.
+ ******************************************************************************/
+uint32_t rsi_rtc_get_timer_frequency(void)
+{
+    return timer_frequency;
+}
+
+/******************************************************************************
+ * Gets RTCC counter value.
+ *****************************************************************************/
+uint32_t rsi_rtc_get_counter(void)
+{
+    return RTCC_CounterGet();
+}
+
+sl_status_t rsi_rtc_init(void)
+{
+    CORE_DECLARE_IRQ_STATE;
+    CORE_ENTER_ATOMIC();
+
+    if (!is_sleeptimer_initialized)
+    {
+        rsi_rtc_init_timer();
+        rsi_rtc_enable_int(SLEEPTIMER_EVENT_OF);
+        timer_frequency = rsi_rtc_get_hal_timer_frequency();
+        if (timer_frequency == RSI_RTC_FREQ_VALUE)
+        {
+            CORE_EXIT_ATOMIC();
+            return SL_STATUS_INVALID_PARAMETER;
+        }
+
+#if SL_SLEEPTIMER_WALLCLOCK_CONFIG
+        second_count = 0;
+#endif
+
+        is_sleeptimer_initialized = true;
+    }
+    CORE_EXIT_ATOMIC();
+
+    return SL_STATUS_OK;
+}
+
+#if SL_SLEEPTIMER_WALLCLOCK_CONFIG
+/*******************************************************************************
+ * Retrieves current time.
+ ******************************************************************************/
+uint32_t rsi_rtc_get_time(void)
+{
+    uint32_t cnt  = 0u;
+    uint32_t freq = 0u;
+    sl_sleeptimer_timestamp_t time;
+    CORE_DECLARE_IRQ_STATE;
+
+    cnt  = rsi_rtc_get_counter();
+    freq = rsi_rtc_get_timer_frequency();
+
+    CORE_ENTER_ATOMIC();
+    time = second_count + cnt / freq;
+    if (cnt % freq + overflow_tick_rest >= freq)
+    {
+        time++;
+    }
+    CORE_EXIT_ATOMIC();
+
+    return time;
+}
+
+/*******************************************************************************
+ * Sets current time.
+ ******************************************************************************/
+sl_status_t rsi_rtc_settime(sl_sleeptimer_timestamp_t time)
+{
+    uint32_t freq        = 0u;
+    uint32_t counter_sec = 0u;
+    uint32_t cnt         = 0;
+    CORE_DECLARE_IRQ_STATE;
+
+    if (!is_valid_time(time, TIME_FORMAT_UNIX, TIME_ZONE_OFFSET))
+    {
+        return SL_STATUS_INVALID_CONFIGURATION;
+    }
+
+    freq = rsi_rtc_get_timer_frequency();
+    cnt  = rsi_rtc_get_counter();
+
+    CORE_ENTER_ATOMIC();
+    second_count       = time;
+    overflow_tick_rest = 0;
+    counter_sec        = cnt / freq;
+
+    if (second_count >= counter_sec)
+    {
+        second_count -= counter_sec;
+    }
+    else
+    {
+        CORE_EXIT_ATOMIC();
+        return SL_STATUS_INVALID_CONFIGURATION;
+    }
+
+    CORE_EXIT_ATOMIC();
+
+    return SL_STATUS_OK;
+}
+
+/*******************************************************************************
+ * @fn  int32_t rsi_rtc_set_time(uint32_t time)
+ * @brief
+ *      Init Sleeptimer and Set current time.
+ * @param[in] time:
+ * @return
+ *      None
+ ******************************************************************************/
+int32_t rsi_rtc_set_time(uint32_t time)
+{
+    sl_status_t ret_val = SL_STATUS_OK;
+    ret_val             = rsi_rtc_init();
+    if (ret_val != SL_STATUS_OK)
+    {
+        return -1;
+    }
+    else
+    {
+        ret_val = rsi_rtc_settime(time);
+        if (ret_val != SL_STATUS_OK)
+        {
+            return -1;
+        }
+    }
+    return 0;
+}
+#endif // SL_SLEEPTIMER_WALLCLOCK_CONFIG
diff --git a/examples/platform/silabs/SiWx917/rs911x/hal/rsi_hal_mcu_timer.c b/examples/platform/silabs/SiWx917/rs911x/hal/rsi_hal_mcu_timer.c
new file mode 100644
index 0000000..c6d6381
--- /dev/null
+++ b/examples/platform/silabs/SiWx917/rs911x/hal/rsi_hal_mcu_timer.c
@@ -0,0 +1,322 @@
+/*
+ *
+ *    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.
+ */
+
+/**
+ * Includes
+ */
+
+#include "em_cmu.h"
+#ifdef RSI_WITH_OS
+/* FreeRTOS includes. */
+#include "FreeRTOS.h"
+#include "event_groups.h"
+#include "task.h"
+#include "timers.h"
+#if defined(SysTick)
+#undef SysTick_Handler
+/* FreeRTOS SysTick interrupt handler prototype */
+extern void SysTick_Handler(void);
+/* FreeRTOS tick timer interrupt handler prototype */
+extern void xPortSysTickHandler(void);
+#endif /* SysTick */
+#endif /* RSI_WITH_OS */
+#include "wfx_host_events.h"
+
+/* RSI Driver include file */
+#include "rsi_driver.h"
+/* RSI WLAN Config include file */
+#include "rsi_bootup_config.h"
+#include "rsi_common_apis.h"
+#include "rsi_data_types.h"
+#include "rsi_error.h"
+#include "rsi_nwk.h"
+#include "rsi_socket.h"
+#include "rsi_utils.h"
+#include "rsi_wlan.h"
+#include "rsi_wlan_apis.h"
+#include "rsi_wlan_config.h"
+#include "wfx_rsi.h"
+
+#ifndef _use_the_rsi_defined_functions
+
+StaticTimer_t sRsiTimerBuffer;
+
+/*
+ * We (Matter port) need a few functions out of this file
+ * They are at the top
+ */
+uint32_t rsi_hal_gettickcount(void)
+{
+    return xTaskGetTickCount();
+}
+void rsi_delay_ms(uint32_t delay_ms)
+{
+#ifndef RSI_WITH_OS
+    uint32_t start;
+#endif
+    if (delay_ms == 0) // Check if delay is 0msec
+        return;
+
+#ifdef RSI_WITH_OS
+    vTaskDelay(pdMS_TO_TICKS(delay_ms));
+#else
+    start = rsi_hal_gettickcount();
+    do
+    {
+    } while (rsi_hal_gettickcount() - start < delay_ms);
+#endif
+}
+static struct rsi_timer
+{
+    void (*func)(void);
+    TimerHandle_t handle;
+    uint8_t id;
+    uint8_t name[3];
+} rsi_timer[WFX_RSI_NUM_TIMERS];
+static void timer_cb(TimerHandle_t thandle)
+{
+    int x;
+    for (x = 0; x < WFX_RSI_NUM_TIMERS; x++)
+    {
+        if (rsi_timer[x].handle == thandle)
+        {
+            (*rsi_timer[x].func)();
+            break;
+        }
+    }
+}
+
+/*
+ * Run a one-shot/periodic timer
+ */
+int32_t rsi_timer_start(uint8_t timer_node, uint8_t mode, uint8_t type, uint32_t duration, void (*rsi_timer_cb)(void))
+{
+    int x;
+    struct rsi_timer * tp;
+
+    if (mode == RSI_HAL_TIMER_MODE_MILLI)
+        return RSI_ERROR_INVALID_OPTION; /* Not supported for now - Fix this later */
+    for (x = 0; x < WFX_RSI_NUM_TIMERS; x++)
+    {
+        tp = &rsi_timer[x];
+        if (tp->handle == NULL)
+        {
+            goto found;
+        }
+    }
+    /* No space */
+    return RSI_ERROR_INSUFFICIENT_BUFFER;
+found:
+    tp->name[0] = 'r';
+    tp->name[1] = timer_node;
+    tp->name[2] = 0;
+    tp->func    = rsi_timer_cb;
+    tp->handle =
+        xTimerCreateStatic((char *) &tp->name[0], pdMS_TO_TICKS(duration),
+                           ((mode == RSI_HAL_TIMER_TYPE_SINGLE_SHOT) ? pdFALSE : pdTRUE), NULL, timer_cb, &sRsiTimerBuffer);
+
+    if (tp->handle == NULL)
+    {
+        return RSI_ERROR_INSUFFICIENT_BUFFER;
+    }
+
+    (void) xTimerStart(tp->handle, TIMER_TICKS_TO_WAIT_0);
+
+    return RSI_ERROR_NONE;
+}
+#else /* _use_the_rsi_defined_functions */
+
+/* Counts 1ms timeTicks */
+volatile uint32_t msTicks = 0;
+
+/*===================================================*/
+/**
+ * @fn           int32_t rsi_timer_start(uint8_t timer_no, uint8_t mode,uint8_t type,uint32_t duration,void (*
+ * rsi_timer_expiry_handler)())
+ * @brief        Starts and configures timer
+ * @param[in]    timer_node, timer node to be configured.
+ * @param[in]    mode , mode of the timer
+ *               0 - Micro seconds mode
+ *               1 - Milli seconds mode
+ * @param[in]    type, type of  the timer
+ *               0 - single shot type
+ *               1 - periodic type
+ * @param[in]    duration, timer duration
+ * @param[in]    rsi_timer_expiry_handler() ,call back function to handle timer interrupt
+ * @param[out]   none
+ * @return       0 - success
+ *               !0 - Failure
+ * @description  This HAL API should contain the code to initialize the timer and start the timer
+ *
+ */
+
+int32_t rsi_timer_start(uint8_t timer_node, uint8_t mode, uint8_t type, uint32_t duration, void (*rsi_timer_expiry_handler)(void))
+{
+
+    // Initialise the timer
+
+    // register the call back
+
+    // Start timer
+
+    return 0;
+}
+
+/*===================================================*/
+/**
+ * @fn           int32_t rsi_timer_stop(uint8_t timer_no)
+ * @brief        Stops timer
+ * @param[in]    timer_node, timer node to stop
+ * @param[out]   none
+ * @return       0 - success
+ *               !0 - Failure
+ * @description  This HAL API should contain the code to stop the timer
+ *
+ */
+
+int32_t rsi_timer_stop(uint8_t timer_node)
+{
+
+    // Stop the timer
+
+    return 0;
+}
+
+/*===================================================*/
+/**
+ * @fn           uint32_t rsi_timer_read(uint8_t timer_node)
+ * @brief        read timer
+ * @param[in]    timer_node, timer node to read
+ * @param[out]   none
+ * @return       timer value
+ * @description  This HAL API should contain API to  read the timer
+ *
+ */
+uint32_t rsi_timer_read(uint8_t timer_node)
+{
+
+    volatile uint32_t timer_val = 0;
+
+    // read the timer and return timer value
+
+    return timer_val;
+}
+
+/*===================================================*/
+/**
+ * @fn           void rsi_delay_us(uint32_t delay)
+ * @brief        create delay in micro seconds
+ * @param[in]    delay_us, timer delay in micro seconds
+ * @param[out]   none
+ * @return       none
+ * @description  This HAL API should contain the code to create delay in micro seconds
+ *
+ */
+void rsi_delay_us(uint32_t delay_us)
+{
+
+    // call the API for delay in micro seconds
+
+    return;
+}
+
+#ifdef RSI_M4_INTERFACE
+
+extern void SysTick_Handler(void);
+
+void SysTick_Handler(void)
+{
+    _dwTickCount++;
+}
+
+uint32_t GetTickCount(void)
+{
+    return _dwTickCount; // gets the tick count from systic ISR
+}
+#endif
+
+/*===================================================*/
+/**
+ * @fn           void rsi_delay_ms(uint32_t delay)
+ * @brief        create delay in milli seconds
+ * @param[in]    delay, timer delay in milli seconds
+ * @param[out]   none
+ * @return       none
+ * @description  This HAL API should contain the code to create delay in milli seconds
+ */
+void rsi_delay_ms(uint32_t delay_ms)
+{
+#ifndef RSI_WITH_OS
+    uint32_t start;
+#endif
+    if (delay_ms == DELAY0)
+        return;
+
+#ifdef RSI_WITH_OS
+    vTaskDelay(delay_ms);
+#else
+    start = rsi_hal_gettickcount();
+    do
+    {
+    } while (rsi_hal_gettickcount() - start < delay_ms);
+#endif
+}
+
+/*===================================================*/
+/**
+ * @fn           uint32_t rsi_hal_gettickcount()
+ * @brief        provides a tick value in milliseconds
+ * @return       tick value
+ * @description  This HAL API should contain the code to read the timer tick count value in milliseconds
+ *
+ */
+
+#ifndef RSI_HAL_USE_RTOS_SYSTICK
+/*
+  SysTick handler implementation that also clears overflow flag.
+*/
+void SysTick_Handler(void)
+{
+    /* Increment counter necessary in Delay()*/
+    msTicks++;
+#ifdef RSI_WITH_OS
+    if (xTaskGetSchedulerState() != taskSCHEDULER_NOT_STARTED)
+    {
+        xPortSysTickHandler();
+    }
+#endif
+}
+
+uint32_t rsi_hal_gettickcount(void)
+{
+    return msTicks;
+
+#ifdef LINUX_PLATFORM
+    // Define your API to get the tick count delay in milli seconds from systic ISR and return the resultant value
+    struct rsi_timeval tv1;
+    gettimeofday(&tv1, NULL);
+    return (tv1.tv_sec * CONVERT_SEC_TO_MSEC + tv1.tv_usec * CONVERT_USEC_TO_MSEC);
+#endif
+}
+
+#else
+uint32_t rsi_hal_gettickcount(void)
+{
+    return xTaskGetTickCount();
+}
+#endif /* RSI_HAL_USE_RTOS_SYSTICK */
+#endif /* _use_the_rsi_defined_functions */
diff --git a/examples/platform/silabs/SiWx917/rs911x/rs911x.gni b/examples/platform/silabs/SiWx917/rs911x/rs911x.gni
new file mode 100644
index 0000000..f119810
--- /dev/null
+++ b/examples/platform/silabs/SiWx917/rs911x/rs911x.gni
@@ -0,0 +1,101 @@
+import("//build_overrides/chip.gni")
+import("//build_overrides/efr32_sdk.gni")
+import("//build_overrides/pigweed.gni")
+
+examples_plat_dir = "${chip_root}/examples/platform/silabs/efr32"
+wifi_sdk_dir = "${chip_root}/src/platform/silabs/EFR32/wifi"
+wiseconnect_sdk_root = "${chip_root}/third_party/silabs/wiseconnect-wifi-bt-sdk"
+rs911x_cflags = []
+
+rs911x_src_plat = [
+  "${examples_plat_dir}/rs911x/rsi_if.c",
+  "${examples_plat_dir}/rs911x/wfx_rsi_host.c",
+  "${wifi_sdk_dir}/wfx_notify.cpp",
+  "${examples_plat_dir}/rs911x/hal/rsi_hal_mcu_interrupt.c",
+  "${examples_plat_dir}/rs911x/hal/rsi_hal_mcu_ioports.c",
+  "${examples_plat_dir}/rs911x/hal/rsi_hal_mcu_timer.c",
+  "${examples_plat_dir}/rs911x/hal/efx_spi.c",
+]
+rs911x_plat_incs = [
+  "${wifi_sdk_dir}",
+  "${wifi_sdk_dir}/hal",
+  "${chip_root}/src/platform/EFR32",
+]
+
+#
+# All the stuff from wiseconnect
+#
+rs911x_src_sapi = [
+  "${wiseconnect_sdk_root}/sapi/wlan/rsi_wlan_apis.c",
+  "${wiseconnect_sdk_root}/sapi/common/rsi_apis_non_rom.c",
+  "${wiseconnect_sdk_root}/sapi/common/rsi_apis_rom.c",
+  "${wiseconnect_sdk_root}/sapi/common/rsi_common_apis.c",
+  "${wiseconnect_sdk_root}/sapi/common/rsi_device_init_apis.c",
+  "${wiseconnect_sdk_root}/sapi/driver/device_interface/spi/rsi_spi_frame_rd_wr.c",
+  "${wiseconnect_sdk_root}/sapi/driver/device_interface/spi/rsi_spi_functs.c",
+  "${wiseconnect_sdk_root}/sapi/driver/device_interface/spi/rsi_spi_iface_init.c",
+  "${wiseconnect_sdk_root}/sapi/driver/device_interface/spi/rsi_spi_mem_rd_wr.c",
+  "${wiseconnect_sdk_root}/sapi/driver/device_interface/spi/rsi_spi_reg_rd_wr.c",
+  "${wiseconnect_sdk_root}/sapi/driver/rsi_common.c",
+  "${wiseconnect_sdk_root}/sapi/driver/rsi_device_init.c",
+  "${wiseconnect_sdk_root}/sapi/driver/rsi_driver_event_handlers.c",
+  "${wiseconnect_sdk_root}/sapi/driver/rsi_driver.c",
+  "${wiseconnect_sdk_root}/sapi/driver/rsi_events_rom.c",
+  "${wiseconnect_sdk_root}/sapi/driver/rsi_events.c",
+  "${wiseconnect_sdk_root}/sapi/driver/rsi_iap.c",
+  "${wiseconnect_sdk_root}/sapi/driver/rsi_nwk_rom.c",
+  "${wiseconnect_sdk_root}/sapi/driver/rsi_nwk.c",
+  "${wiseconnect_sdk_root}/sapi/driver/rsi_pkt_mgmt_rom.c",
+  "${wiseconnect_sdk_root}/sapi/driver/rsi_pkt_mgmt.c",
+  "${wiseconnect_sdk_root}/sapi/driver/rsi_queue_rom.c",
+  "${wiseconnect_sdk_root}/sapi/driver/rsi_queue.c",
+  "${wiseconnect_sdk_root}/sapi/driver/rsi_scheduler_rom.c",
+  "${wiseconnect_sdk_root}/sapi/driver/rsi_scheduler.c",
+  "${wiseconnect_sdk_root}/sapi/driver/rsi_setregion_countryinfo.c",
+  "${wiseconnect_sdk_root}/sapi/driver/rsi_timer.c",
+  "${wiseconnect_sdk_root}/sapi/driver/rsi_utils_rom.c",
+  "${wiseconnect_sdk_root}/sapi/driver/rsi_utils.c",
+  "${wiseconnect_sdk_root}/sapi/driver/rsi_wlan.c",
+  "${wiseconnect_sdk_root}/sapi/rtos/freertos_wrapper/rsi_os_wrapper.c",
+]
+
+foreach(src_file, rs911x_src_sapi) {
+  rs911x_cflags += [ "-Wno-empty-body" ]
+}
+
+rs911x_inc_plat = [
+  "${wifi_sdk_dir}",
+  "${examples_plat_dir}/rs911x",
+  "${examples_plat_dir}/rs911x/hal",
+  "${wiseconnect_sdk_root}/sapi/include",
+]
+
+# Apparently - the rsi library needs this
+rs911x_src_sock = [
+  "${wiseconnect_sdk_root}/sapi/network/socket/rsi_socket.c",
+  "${wiseconnect_sdk_root}/sapi/network/socket/rsi_socket_rom.c",
+]
+rs911x_sock_inc = [ "${wifi_sdk_dir}/rsi-sockets" ]
+
+#
+# If we use LWIP - not built-in sockets
+#
+rs911x_src_lwip = [
+  "${wifi_sdk_dir}/ethernetif.cpp",
+  "${wifi_sdk_dir}/dhcp_client.cpp",
+  "${wifi_sdk_dir}/lwip_netif.cpp",
+]
+rs911x_defs = [
+  "SL_HEAP_SIZE=32768",
+  "SL_WIFI=1",
+  "SL_WFX_USE_SPI",
+  "EFX32_RS911X=1",
+  "RS911X_WIFI",
+  "RSI_WLAN_ENABLE",
+  "RSI_SPI_INTERFACE",
+  "RSI_WITH_OS",
+]
+rs911x_sock_defs = [
+  "RS911X_SOCKETS",
+  "RSI_IPV6_ENABLE",
+]
diff --git a/examples/platform/silabs/SiWx917/rs911x/rsi_if.c b/examples/platform/silabs/SiWx917/rs911x/rsi_if.c
new file mode 100644
index 0000000..7d3be40
--- /dev/null
+++ b/examples/platform/silabs/SiWx917/rs911x/rsi_if.c
@@ -0,0 +1,854 @@
+/*
+ *
+ *    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 <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "em_bus.h"
+#include "em_cmu.h"
+#include "em_gpio.h"
+#include "em_ldma.h"
+#include "em_usart.h"
+
+#include "sl_status.h"
+
+#include "FreeRTOS.h"
+#include "event_groups.h"
+#include "task.h"
+
+#include "wfx_host_events.h"
+
+#include "rsi_driver.h"
+#include "rsi_wlan_non_rom.h"
+
+#include "rsi_common_apis.h"
+#include "rsi_data_types.h"
+#include "rsi_nwk.h"
+#include "rsi_socket.h"
+#include "rsi_utils.h"
+#include "rsi_wlan.h"
+#include "rsi_wlan_apis.h"
+#include "rsi_wlan_config.h"
+//#include "rsi_wlan_non_rom.h"
+#include "rsi_bootup_config.h"
+#include "rsi_error.h"
+
+#include "dhcp_client.h"
+#include "wfx_host_events.h"
+#include "wfx_rsi.h"
+
+/* Rsi driver Task will use as its stack */
+StackType_t driverRsiTaskStack[WFX_RSI_WLAN_TASK_SZ] = { 0 };
+
+/* Structure that will hold the TCB of the wfxRsi Task being created. */
+StaticTask_t driverRsiTaskBuffer;
+
+/* Declare a variable to hold the data associated with the created event group. */
+StaticEventGroup_t rsiDriverEventGroup;
+
+bool hasNotifiedIPV6 = false;
+#if (CHIP_DEVICE_CONFIG_ENABLE_IPV4)
+bool hasNotifiedIPV4 = false;
+#endif /* CHIP_DEVICE_CONFIG_ENABLE_IPV4 */
+bool hasNotifiedWifiConnectivity = false;
+
+/*
+ * This file implements the interface to the RSI SAPIs
+ */
+static uint8_t wfx_rsi_drv_buf[WFX_RSI_BUF_SZ];
+wfx_wifi_scan_ext_t * temp_reset;
+uint8_t security;
+
+/******************************************************************
+ * @fn   int32_t wfx_rsi_get_ap_info(wfx_wifi_scan_result_t *ap)
+ * @brief
+ *       Getting the AP details
+ * @param[in] ap: access point
+ * @return
+ *        status
+ *********************************************************************/
+int32_t wfx_rsi_get_ap_info(wfx_wifi_scan_result_t * ap)
+{
+    int32_t status;
+    uint8_t rssi;
+    ap->security = security;
+    ap->chan     = wfx_rsi.ap_chan;
+    memcpy(&ap->bssid[0], &wfx_rsi.ap_mac.octet[0], BSSID_MAX_STR_LEN);
+    status = rsi_wlan_get(RSI_RSSI, &rssi, sizeof(rssi));
+    if (status == RSI_SUCCESS)
+    {
+        ap->rssi = (-1) * rssi;
+    }
+    return status;
+}
+
+/******************************************************************
+ * @fn   int32_t wfx_rsi_get_ap_ext(wfx_wifi_scan_ext_t *extra_info)
+ * @brief
+ *       Getting the AP extra details
+ * @param[in] extra info: access point extra information
+ * @return
+ *        status
+ *********************************************************************/
+int32_t wfx_rsi_get_ap_ext(wfx_wifi_scan_ext_t * extra_info)
+{
+    int32_t status;
+    uint8_t buff[RSI_RESPONSE_MAX_SIZE] = { 0 };
+    status                              = rsi_wlan_get(RSI_WLAN_EXT_STATS, buff, sizeof(buff));
+    if (status != RSI_SUCCESS)
+    {
+        WFX_RSI_LOG("\r\n Failed, Error Code : 0x%lX\r\n", status);
+    }
+    else
+    {
+        rsi_wlan_ext_stats_t * test   = (rsi_wlan_ext_stats_t *) buff;
+        extra_info->beacon_lost_count = test->beacon_lost_count - temp_reset->beacon_lost_count;
+        extra_info->beacon_rx_count   = test->beacon_rx_count - temp_reset->beacon_rx_count;
+        extra_info->mcast_rx_count    = test->mcast_rx_count - temp_reset->mcast_rx_count;
+        extra_info->mcast_tx_count    = test->mcast_tx_count - temp_reset->mcast_tx_count;
+        extra_info->ucast_rx_count    = test->ucast_rx_count - temp_reset->ucast_rx_count;
+        extra_info->ucast_tx_count    = test->ucast_tx_count - temp_reset->ucast_tx_count;
+        extra_info->overrun_count     = test->overrun_count - temp_reset->overrun_count;
+    }
+    return status;
+}
+
+/******************************************************************
+ * @fn   int32_t wfx_rsi_reset_count()
+ * @brief
+ *       Getting the driver reset count
+ * @param[in] None
+ * @return
+ *        status
+ *********************************************************************/
+int32_t wfx_rsi_reset_count()
+{
+    int32_t status;
+    uint8_t buff[RSI_RESPONSE_MAX_SIZE] = { 0 };
+    status                              = rsi_wlan_get(RSI_WLAN_EXT_STATS, buff, sizeof(buff));
+    if (status != RSI_SUCCESS)
+    {
+        WFX_RSI_LOG("\r\n Failed, Error Code : 0x%lX\r\n", status);
+    }
+    else
+    {
+        rsi_wlan_ext_stats_t * test   = (rsi_wlan_ext_stats_t *) buff;
+        temp_reset->beacon_lost_count = test->beacon_lost_count;
+        temp_reset->beacon_rx_count   = test->beacon_rx_count;
+        temp_reset->mcast_rx_count    = test->mcast_rx_count;
+        temp_reset->mcast_tx_count    = test->mcast_tx_count;
+        temp_reset->ucast_rx_count    = test->ucast_rx_count;
+        temp_reset->ucast_tx_count    = test->ucast_tx_count;
+        temp_reset->overrun_count     = test->overrun_count;
+    }
+    return status;
+}
+
+/******************************************************************
+ * @fn   wfx_rsi_disconnect()
+ * @brief
+ *       Getting the driver disconnect status
+ * @param[in] None
+ * @return
+ *        status
+ *********************************************************************/
+int32_t wfx_rsi_disconnect()
+{
+    int32_t status = rsi_wlan_disconnect();
+    return status;
+}
+
+/******************************************************************
+ * @fn   wfx_rsi_join_cb(uint16_t status, const uint8_t *buf, const uint16_t len)
+ * @brief
+ *       called when driver join with cb
+ * @param[in] status:
+ * @param[in] buf:
+ * @param[in] len:
+ * @return
+ *        None
+ *********************************************************************/
+static void wfx_rsi_join_cb(uint16_t status, const uint8_t * buf, const uint16_t len)
+{
+    WFX_RSI_LOG("%s: status: %02x", __func__, status);
+    wfx_rsi.dev_state &= ~WFX_RSI_ST_STA_CONNECTING;
+    temp_reset = (wfx_wifi_scan_ext_t *) malloc(sizeof(wfx_wifi_scan_ext_t));
+    memset(temp_reset, 0, sizeof(wfx_wifi_scan_ext_t));
+    if (status != RSI_SUCCESS)
+    {
+        /*
+         * We should enable retry.. (Need config variable for this)
+         */
+        WFX_RSI_LOG("%s: failed. retry: %d", __func__, wfx_rsi.join_retries);
+#if (WFX_RSI_CONFIG_MAX_JOIN != 0)
+        if (++wfx_rsi.join_retries < WFX_RSI_CONFIG_MAX_JOIN)
+#endif
+        {
+            xEventGroupSetBits(wfx_rsi.events, WFX_EVT_STA_START_JOIN);
+        }
+    }
+    else
+    {
+        /*
+         * Join was complete - Do the DHCP
+         */
+        WFX_RSI_LOG("%s: join completed.", __func__);
+#ifdef RS911X_SOCKETS
+        xEventGroupSetBits(wfx_rsi.events, WFX_EVT_STA_DO_DHCP);
+#else
+        xEventGroupSetBits(wfx_rsi.events, WFX_EVT_STA_CONN);
+#endif
+    }
+}
+
+/******************************************************************
+ * @fn  wfx_rsi_join_fail_cb(uint16_t status, uint8_t *buf, uint32_t len)
+ * @brief
+ *       called when driver fail to join with cb
+ * @param[in] status:
+ * @param[in] buf:
+ * @param[in] len:
+ * @return
+ *        None
+ *********************************************************************/
+static void wfx_rsi_join_fail_cb(uint16_t status, uint8_t * buf, uint32_t len)
+{
+    WFX_RSI_LOG("%s: error: failed status: %02x on try %d", __func__, status, wfx_rsi.join_retries);
+    wfx_rsi.join_retries += 1;
+    wfx_rsi.dev_state &= ~WFX_RSI_ST_STA_CONNECTING;
+    xEventGroupSetBits(wfx_rsi.events, WFX_EVT_STA_START_JOIN);
+}
+#ifdef RS911X_SOCKETS
+
+/******************************************************************
+ * @fn  wfx_rsi_ipchange_cb(uint16_t status, uint8_t *buf, uint32_t len)
+ * @brief
+ *       DHCP should end up here
+ * @param[in] status:
+ * @param[in] buf:
+ * @param[in] len:
+ * @return
+ *        None
+ *********************************************************************/
+static void wfx_rsi_ipchange_cb(uint16_t status, uint8_t * buf, uint32_t len)
+{
+    WFX_RSI_LOG("%s: status: %02x", __func__, status);
+    if (status != RSI_SUCCESS)
+    {
+        /* Restart DHCP? */
+        xEventGroupSetBits(wfx_rsi.events, WFX_EVT_STA_DO_DHCP);
+    }
+    else
+    {
+        wfx_rsi.dev_state |= WFX_RSI_ST_STA_DHCP_DONE;
+        xEventGroupSetBits(wfx_rsi.events, WFX_EVT_STA_DHCP_DONE);
+    }
+}
+
+#else
+/*************************************************************************************
+ * @fn  wfx_rsi_wlan_pkt_cb(uint16_t status, uint8_t *buf, uint32_t len)
+ * @brief
+ *      Got RAW WLAN data pkt
+ * @param[in]  status:
+ * @param[in]  buf:
+ * @param[in]  len:
+ * @return
+ *        None
+ *****************************************************************************************/
+static void wfx_rsi_wlan_pkt_cb(uint16_t status, uint8_t * buf, uint32_t len)
+{
+    // WFX_RSI_LOG("%s: status=%d, len=%d", __func__, status, len);
+    if (status != RSI_SUCCESS)
+    {
+        return;
+    }
+    wfx_host_received_sta_frame_cb(buf, len);
+}
+#endif /* !Socket support */
+
+/*************************************************************************************
+ * @fn  static int32_t wfx_rsi_init(void)
+ * @brief
+ *      driver initialization
+ * @param[in]  None
+ * @return
+ *        None
+ *****************************************************************************************/
+static int32_t wfx_rsi_init(void)
+{
+    int32_t status;
+    uint8_t buf[RSI_RESPONSE_HOLD_BUFF_SIZE];
+    extern void rsi_hal_board_init(void);
+
+    WFX_RSI_LOG("%s: starting(HEAP_SZ = %d)", __func__, SL_HEAP_SIZE);
+    //! Driver initialization
+    status = rsi_driver_init(wfx_rsi_drv_buf, WFX_RSI_BUF_SZ);
+    if ((status < RSI_DRIVER_STATUS) || (status > WFX_RSI_BUF_SZ))
+    {
+        WFX_RSI_LOG("%s: error: RSI drv init failed with status: %02x", __func__, status);
+        return status;
+    }
+
+    WFX_RSI_LOG("%s: rsi_device_init", __func__);
+    /* ! Redpine module intialisation */
+    if ((status = rsi_device_init(LOAD_NWP_FW)) != RSI_SUCCESS)
+    {
+        WFX_RSI_LOG("%s: error: rsi_device_init failed with status: %02x", __func__, status);
+        return status;
+    }
+    WFX_RSI_LOG("%s: start wireless drv task", __func__);
+    /*
+     * Create the driver task
+     */
+    wfx_rsi.drv_task = xTaskCreateStatic((TaskFunction_t) rsi_wireless_driver_task, "rsi_drv", WFX_RSI_WLAN_TASK_SZ, NULL,
+                                         WLAN_TASK_PRIORITY, driverRsiTaskStack, &driverRsiTaskBuffer);
+    if (NULL == wfx_rsi.drv_task)
+    {
+        WFX_RSI_LOG("%s: error: rsi_wireless_driver_task failed", __func__);
+        return RSI_ERROR_INVALID_PARAM;
+    }
+
+    /* Initialize WiSeConnect or Module features. */
+    WFX_RSI_LOG("%s: rsi_wireless_init", __func__);
+    if ((status = rsi_wireless_init(OPER_MODE_0, COEX_MODE_0)) != RSI_SUCCESS)
+    {
+        WFX_RSI_LOG("%s: error: rsi_wireless_init failed with status: %02x", __func__, status);
+        return status;
+    }
+
+    WFX_RSI_LOG("%s: get FW version..", __func__);
+    /*
+     * Get the MAC and other info to let the user know about it.
+     */
+    if (rsi_wlan_get(RSI_FW_VERSION, buf, sizeof(buf)) != RSI_SUCCESS)
+    {
+        WFX_RSI_LOG("%s: error: rsi_wlan_get(RSI_FW_VERSION) failed with status: %02x", __func__, status);
+        return status;
+    }
+
+    buf[sizeof(buf) - 1] = 0;
+    WFX_RSI_LOG("%s: RSI firmware version: %s", __func__, buf);
+    //! Send feature frame
+    if ((status = rsi_send_feature_frame()) != RSI_SUCCESS)
+    {
+        WFX_RSI_LOG("%s: error: rsi_send_feature_frame failed with status: %02x", __func__, status);
+        return status;
+    }
+
+    WFX_RSI_LOG("%s: sent rsi_send_feature_frame", __func__);
+    /* initializes wlan radio parameters and WLAN supplicant parameters.
+     */
+    (void) rsi_wlan_radio_init(); /* Required so we can get MAC address */
+    if ((status = rsi_wlan_get(RSI_MAC_ADDRESS, &wfx_rsi.sta_mac.octet[0], RESP_BUFF_SIZE)) != RSI_SUCCESS)
+    {
+        WFX_RSI_LOG("%s: error: rsi_wlan_get failed with status: %02x", __func__, status);
+        return status;
+    }
+
+    WFX_RSI_LOG("%s: WLAN: MAC %02x:%02x:%02x %02x:%02x:%02x", __func__, wfx_rsi.sta_mac.octet[0], wfx_rsi.sta_mac.octet[1],
+                wfx_rsi.sta_mac.octet[2], wfx_rsi.sta_mac.octet[3], wfx_rsi.sta_mac.octet[4], wfx_rsi.sta_mac.octet[5]);
+    wfx_rsi.events = xEventGroupCreateStatic(&rsiDriverEventGroup);
+    /*
+     * Register callbacks - We are only interested in the connectivity CBs
+     */
+    if ((status = rsi_wlan_register_callbacks(RSI_JOIN_FAIL_CB, wfx_rsi_join_fail_cb)) != RSI_SUCCESS)
+    {
+        WFX_RSI_LOG("%s: RSI callback register join failed with status: %02x", __func__, status);
+        return status;
+    }
+#ifdef RS911X_SOCKETS
+    (void) rsi_wlan_register_callbacks(RSI_IP_CHANGE_NOTIFY_CB, wfx_rsi_ipchange_cb);
+#else
+    if ((status = rsi_wlan_register_callbacks(RSI_WLAN_DATA_RECEIVE_NOTIFY_CB, wfx_rsi_wlan_pkt_cb)) != RSI_SUCCESS)
+    {
+        WFX_RSI_LOG("%s: RSI callback register data-notify failed with status: %02x", __func__, status);
+        return status;
+    }
+#endif
+    wfx_rsi.dev_state |= WFX_RSI_ST_DEV_READY;
+    WFX_RSI_LOG("%s: RSI: OK", __func__);
+    return RSI_SUCCESS;
+}
+
+/*************************************************************************************
+ * @fn  void wfx_show_err(char *msg)
+ * @brief
+ *      driver shows error message
+ * @param[in]  msg
+ * @return
+ *        None
+ *****************************************************************************************/
+void wfx_show_err(char * msg)
+{
+    WFX_RSI_LOG("%s: message: %d", __func__, msg);
+}
+
+/***************************************************************************************
+ * @fn   static void wfx_rsi_save_ap_info()
+ * @brief
+ *       Saving the details of the AP
+ * @param[in]  None
+ * @return
+ *       None
+ *******************************************************************************************/
+static void wfx_rsi_save_ap_info()
+{
+    int32_t status;
+    rsi_rsp_scan_t rsp;
+
+    status =
+        rsi_wlan_scan_with_bitmap_options((int8_t *) &wfx_rsi.sec.ssid[0], AP_CHANNEL_NO_0, &rsp, sizeof(rsp), SCAN_BITMAP_OPTN_1);
+    if (status)
+    {
+        /*
+         * Scan is done - failed
+         */
+    }
+    else
+    {
+        wfx_rsi.sec.security = rsp.scan_info->security_mode;
+        wfx_rsi.ap_chan      = rsp.scan_info->rf_channel;
+        memcpy(&wfx_rsi.ap_mac.octet[0], &rsp.scan_info->bssid[0], BSSID_MAX_STR_LEN);
+    }
+    if ((wfx_rsi.sec.security == RSI_WPA) || (wfx_rsi.sec.security == RSI_WPA2))
+    {
+        // saving the security before changing into mixed mode
+        security             = wfx_rsi.sec.security;
+        wfx_rsi.sec.security = RSI_WPA_WPA2_MIXED;
+    }
+    if (wfx_rsi.sec.security == SME_WPA3)
+    {
+        // returning 3 for WPA3 when DGWIFI read security-type is called
+        security             = WPA3_SECURITY;
+        wfx_rsi.sec.security = RSI_WPA3;
+    }
+    WFX_RSI_LOG("%s: WLAN: connecting to %s==%s, sec=%d, status=%02x", __func__, &wfx_rsi.sec.ssid[0], &wfx_rsi.sec.passkey[0],
+                wfx_rsi.sec.security, status);
+}
+
+/********************************************************************************************
+ * @fn   static void wfx_rsi_do_join(void)
+ * @brief
+ *        Start an async Join command
+ * @return
+ *        None
+ **********************************************************************************************/
+static void wfx_rsi_do_join(void)
+{
+    int32_t status;
+
+    if (wfx_rsi.dev_state & (WFX_RSI_ST_STA_CONNECTING | WFX_RSI_ST_STA_CONNECTED))
+    {
+        WFX_RSI_LOG("%s: not joining - already in progress", __func__);
+    }
+    else
+    {
+        WFX_RSI_LOG("%s: WLAN: connecting to %s==%s, sec=%d", __func__, &wfx_rsi.sec.ssid[0], &wfx_rsi.sec.passkey[0],
+                    wfx_rsi.sec.security);
+        /*
+         * Join the network
+         */
+        /* TODO - make the WFX_SECURITY_xxx - same as RSI_xxx
+         * Right now it's done by hand - we need something better
+         */
+        wfx_rsi.dev_state |= WFX_RSI_ST_STA_CONNECTING;
+
+        /* Try to connect Wifi with given Credentials
+         * until there is a success or maximum number of tries allowed
+         */
+        while (++wfx_rsi.join_retries < WFX_RSI_CONFIG_MAX_JOIN)
+        {
+
+            /* Call rsi connect call with given ssid and password
+             * And check there is a success
+             */
+            if ((status = rsi_wlan_connect_async((int8_t *) &wfx_rsi.sec.ssid[0], (rsi_security_mode_t) wfx_rsi.sec.security,
+                                                 &wfx_rsi.sec.passkey[0], wfx_rsi_join_cb)) != RSI_SUCCESS)
+            {
+
+                wfx_rsi.dev_state &= ~WFX_RSI_ST_STA_CONNECTING;
+                WFX_RSI_LOG("%s: rsi_wlan_connect_async failed with status: %02x on try %d", __func__, status,
+                            wfx_rsi.join_retries);
+                vTaskDelay(4000);
+                /* TODO - Start a timer.. to retry */
+            }
+            else
+            {
+                break; // exit while loop
+            }
+        }
+        if (wfx_rsi.join_retries == MAX_JOIN_RETRIES_COUNT)
+        {
+            WFX_RSI_LOG("Connect failed after %d tries", wfx_rsi.join_retries);
+        }
+        else
+        {
+            WFX_RSI_LOG("%s: starting JOIN to %s after %d tries\n", __func__, (char *) &wfx_rsi.sec.ssid[0], wfx_rsi.join_retries);
+        }
+    }
+}
+
+/*********************************************************************************
+ * @fn  void wfx_rsi_task(void *arg)
+ * @brief
+ * The main WLAN task - started by wfx_wifi_start () that interfaces with RSI.
+ * The rest of RSI stuff come in call-backs.
+ * The initialization has been already done.
+ * @param[in] arg:
+ * @return
+ *       None
+ **********************************************************************************/
+/* ARGSUSED */
+void wfx_rsi_task(void * arg)
+{
+    EventBits_t flags;
+#ifndef RS911X_SOCKETS
+    TickType_t last_dhcp_poll, now;
+    struct netif * sta_netif;
+#endif
+    (void) arg;
+    uint32_t rsi_status = wfx_rsi_init();
+    if (rsi_status != RSI_SUCCESS)
+    {
+        WFX_RSI_LOG("%s: error: wfx_rsi_init with status: %02x", __func__, rsi_status);
+        return;
+    }
+#ifndef RS911X_SOCKETS
+    wfx_lwip_start();
+    last_dhcp_poll = xTaskGetTickCount();
+    sta_netif      = wfx_get_netif(SL_WFX_STA_INTERFACE);
+#endif
+    wfx_started_notify();
+
+    WFX_RSI_LOG("%s: starting event wait", __func__);
+    for (;;)
+    {
+        /*
+         * This is the main job of this task.
+         * Wait for commands from the ConnectivityManager
+         * Make state changes (based on call backs)
+         */
+        flags = xEventGroupWaitBits(wfx_rsi.events,
+                                    WFX_EVT_STA_CONN | WFX_EVT_STA_DISCONN | WFX_EVT_STA_START_JOIN
+#ifdef RS911X_SOCKETS
+                                        | WFX_EVT_STA_DO_DHCP | WFX_EVT_STA_DHCP_DONE
+#endif /* RS911X_SOCKETS */
+#ifdef SL_WFX_CONFIG_SOFTAP
+                                        | WFX_EVT_AP_START | WFX_EVT_AP_STOP
+#endif /* SL_WFX_CONFIG_SOFTAP */
+#ifdef SL_WFX_CONFIG_SCAN
+                                        | WFX_EVT_SCAN
+#endif /* SL_WFX_CONFIG_SCAN */
+                                        | 0,
+                                    pdTRUE,              /* Clear the bits */
+                                    pdFALSE,             /* Wait for any bit */
+                                    pdMS_TO_TICKS(250)); /* 250 mSec */
+
+        if (flags)
+        {
+            WFX_RSI_LOG("%s: wait event encountered: %x", __func__, flags);
+        }
+#ifdef RS911X_SOCKETS
+        if (flags & WFX_EVT_STA_DO_DHCP)
+        {
+            /*
+             * Do DHCP -
+             */
+            if ((status = rsi_config_ipaddress(RSI_IP_VERSION_4, RSI_DHCP | RSI_DHCP_UNICAST_OFFER, NULL, NULL, NULL,
+                                               &wfx_rsi.ip4_addr[0], IP_CONF_RSP_BUFF_LENGTH_4, STATION)) != RSI_SUCCESS)
+            {
+                /* We should try this again.. (perhaps sleep) */
+                /* TODO - Figure out what to do here */
+            }
+        }
+#else /* !RS911X_SOCKET - using LWIP */
+        /*
+         * Let's handle DHCP polling here
+         */
+        if (wfx_rsi.dev_state & WFX_RSI_ST_STA_CONNECTED)
+        {
+            if ((now = xTaskGetTickCount()) > (last_dhcp_poll + pdMS_TO_TICKS(250)))
+            {
+#if (CHIP_DEVICE_CONFIG_ENABLE_IPV4)
+                uint8_t dhcp_state = dhcpclient_poll(sta_netif);
+                if (dhcp_state == DHCP_ADDRESS_ASSIGNED && !hasNotifiedIPV4)
+                {
+                    wfx_dhcp_got_ipv4((uint32_t) sta_netif->ip_addr.u_addr.ip4.addr);
+                    hasNotifiedIPV4 = true;
+                    if (!hasNotifiedWifiConnectivity)
+                    {
+                        wfx_connected_notify(CONNECTION_STATUS_SUCCESS, &wfx_rsi.ap_mac);
+                        hasNotifiedWifiConnectivity = true;
+                    }
+                }
+                else if (dhcp_state == DHCP_OFF)
+                {
+                    wfx_ip_changed_notify(IP_STATUS_FAIL);
+                    hasNotifiedIPV4 = false;
+                }
+#endif /* CHIP_DEVICE_CONFIG_ENABLE_IPV4 */
+                /* Checks if the assigned IPv6 address is preferred by evaluating
+                 * the first block of IPv6 address ( block 0)
+                 */
+                if ((ip6_addr_ispreferred(netif_ip6_addr_state(sta_netif, 0))) && !hasNotifiedIPV6)
+                {
+                    wfx_ipv6_notify(GET_IPV6_SUCCESS);
+                    hasNotifiedIPV6 = true;
+                    if (!hasNotifiedWifiConnectivity)
+                    {
+                        wfx_connected_notify(CONNECTION_STATUS_SUCCESS, &wfx_rsi.ap_mac);
+                        hasNotifiedWifiConnectivity = true;
+                    }
+                }
+                last_dhcp_poll = now;
+            }
+        }
+#endif /* RS911X_SOCKETS */
+        if (flags & WFX_EVT_STA_START_JOIN)
+        {
+            // saving the AP related info
+            wfx_rsi_save_ap_info();
+            // Joining to the network
+            wfx_rsi_do_join();
+        }
+        if (flags & WFX_EVT_STA_CONN)
+        {
+            /*
+             * Initiate the Join command (assuming we have been provisioned)
+             */
+            WFX_RSI_LOG("%s: starting LwIP STA", __func__);
+            wfx_rsi.dev_state |= WFX_RSI_ST_STA_CONNECTED;
+#ifndef RS911X_SOCKETS
+            hasNotifiedWifiConnectivity = false;
+#if (CHIP_DEVICE_CONFIG_ENABLE_IPV4)
+            hasNotifiedIPV4 = false;
+#endif // CHIP_DEVICE_CONFIG_ENABLE_IPV4
+            hasNotifiedIPV6 = false;
+            wfx_lwip_set_sta_link_up();
+#endif /* !RS911X_SOCKETS */
+            /* We need to get AP Mac - TODO */
+            // Uncomment once the hook into MATTER is moved to IP connectivity instead
+            // of AP connectivity. wfx_connected_notify(0, &wfx_rsi.ap_mac); // This
+            // is independent of IP connectivity.
+        }
+        if (flags & WFX_EVT_STA_DISCONN)
+        {
+            wfx_rsi.dev_state &=
+                ~(WFX_RSI_ST_STA_READY | WFX_RSI_ST_STA_CONNECTING | WFX_RSI_ST_STA_CONNECTED | WFX_RSI_ST_STA_DHCP_DONE);
+            WFX_RSI_LOG("%s: disconnect notify", __func__);
+            /* TODO: Implement disconnect notify */
+#ifndef RS911X_SOCKETS
+            wfx_lwip_set_sta_link_down(); // Internally dhcpclient_poll(netif) ->
+                                          // wfx_ip_changed_notify(0) for IPV4
+#if (CHIP_DEVICE_CONFIG_ENABLE_IPV4)
+            wfx_ip_changed_notify(IP_STATUS_FAIL);
+            hasNotifiedIPV4 = false;
+#endif /* CHIP_DEVICE_CONFIG_ENABLE_IPV4 */
+            wfx_ipv6_notify(GET_IPV6_FAIL);
+            hasNotifiedIPV6             = false;
+            hasNotifiedWifiConnectivity = false;
+#endif /* !RS911X_SOCKETS */
+        }
+#ifdef SL_WFX_CONFIG_SCAN
+        if (flags & WFX_EVT_SCAN)
+        {
+            if (!(wfx_rsi.dev_state & WFX_RSI_ST_SCANSTARTED))
+            {
+                WFX_RSI_LOG("%s: start SSID scan", __func__);
+                int x;
+                wfx_wifi_scan_result_t ap;
+                rsi_scan_info_t * scan;
+                int32_t status;
+                uint8_t bgscan_results[BG_SCAN_RES_SIZE] = { 0 };
+                status = rsi_wlan_bgscan_profile(1, (rsi_rsp_scan_t *) bgscan_results, BG_SCAN_RES_SIZE);
+
+                WFX_RSI_LOG("%s: status: %02x size = %d", __func__, status, BG_SCAN_RES_SIZE);
+                rsi_rsp_scan_t * rsp = (rsi_rsp_scan_t *) bgscan_results;
+                if (status)
+                {
+                    /*
+                     * Scan is done - failed
+                     */
+                }
+                else
+                    for (x = 0; x < rsp->scan_count[0]; x++)
+                    {
+                        scan = &rsp->scan_info[x];
+                        strcpy(&ap.ssid[0], (char *) &scan->ssid[0]);
+                        if (wfx_rsi.scan_ssid)
+                        {
+                            WFX_RSI_LOG("Inside scan_ssid");
+                            WFX_RSI_LOG("SCAN SSID: %s , ap scan: %s", wfx_rsi.scan_ssid, ap.ssid);
+                            if (strcmp(wfx_rsi.scan_ssid, ap.ssid) == CMP_SUCCESS)
+                            {
+                                WFX_RSI_LOG("Inside ap details");
+                                ap.security = scan->security_mode;
+                                ap.rssi     = (-1) * scan->rssi_val;
+                                memcpy(&ap.bssid[0], &scan->bssid[0], BSSID_MAX_STR_LEN);
+                                (*wfx_rsi.scan_cb)(&ap);
+                            }
+                        }
+                        else
+                        {
+                            WFX_RSI_LOG("Inside else");
+                            ap.security = scan->security_mode;
+                            ap.rssi     = (-1) * scan->rssi_val;
+                            memcpy(&ap.bssid[0], &scan->bssid[0], BSSID_MAX_STR_LEN);
+                            (*wfx_rsi.scan_cb)(&ap);
+                        }
+                    }
+                wfx_rsi.dev_state &= ~WFX_RSI_ST_SCANSTARTED;
+                /* Terminate with end of scan which is no ap sent back */
+                (*wfx_rsi.scan_cb)((wfx_wifi_scan_result_t *) 0);
+                wfx_rsi.scan_cb = (void (*)(wfx_wifi_scan_result_t *)) 0;
+
+                if (wfx_rsi.scan_ssid)
+                {
+                    vPortFree(wfx_rsi.scan_ssid);
+                    wfx_rsi.scan_ssid = (char *) 0;
+                }
+            }
+        }
+#endif /* SL_WFX_CONFIG_SCAN */
+#ifdef SL_WFX_CONFIG_SOFTAP
+        /* TODO */
+        if (flags & WFX_EVT_AP_START)
+        {
+        }
+        if (flags & WFX_EVT_AP_STOP)
+        {
+        }
+#endif /* SL_WFX_CONFIG_SOFTAP */
+    }
+}
+
+#if CHIP_DEVICE_CONFIG_ENABLE_IPV4
+/********************************************************************************************
+ * @fn   void wfx_dhcp_got_ipv4(uint32_t ip)
+ * @brief
+ *        Acquire the new ip address
+ * @param[in] ip: internet protocol
+ * @return
+ *        None
+ **********************************************************************************************/
+void wfx_dhcp_got_ipv4(uint32_t ip)
+{
+    /*
+     * Acquire the new IP address
+     */
+    wfx_rsi.ip4_addr[0] = (ip) &HEX_VALUE_FF;
+    wfx_rsi.ip4_addr[1] = (ip >> 8) & HEX_VALUE_FF;
+    wfx_rsi.ip4_addr[2] = (ip >> 16) & HEX_VALUE_FF;
+    wfx_rsi.ip4_addr[3] = (ip >> 24) & HEX_VALUE_FF;
+    WFX_RSI_LOG("%s: DHCP OK: IP=%d.%d.%d.%d", __func__, wfx_rsi.ip4_addr[0], wfx_rsi.ip4_addr[1], wfx_rsi.ip4_addr[2],
+                wfx_rsi.ip4_addr[3]);
+    /* Notify the Connectivity Manager - via the app */
+    wfx_ip_changed_notify(IP_STATUS_SUCCESS);
+    wfx_rsi.dev_state |= WFX_RSI_ST_STA_READY;
+}
+#endif /* CHIP_DEVICE_CONFIG_ENABLE_IPV4 */
+
+/*
+ * WARNING - Taken from RSI and broken up
+ * This is my own RSI stuff for not copying code and allocating an extra
+ * level of indirection - when using LWIP buffers
+ * see also: int32_t rsi_wlan_send_data_xx(uint8_t *buffer, uint32_t length)
+ */
+/********************************************************************************************
+ * @fn   void *wfx_rsi_alloc_pkt()
+ * @brief
+ *       Allocate packet to send data
+ * @param[in] None
+ * @return
+ *        None
+ **********************************************************************************************/
+void * wfx_rsi_alloc_pkt()
+{
+    rsi_pkt_t * pkt;
+
+    // Allocate packet to send data
+    if ((pkt = rsi_pkt_alloc(&rsi_driver_cb->wlan_cb->wlan_tx_pool)) == NULL)
+    {
+        return (void *) 0;
+    }
+
+    return (void *) pkt;
+}
+
+/********************************************************************************************
+ * @fn   void wfx_rsi_pkt_add_data(void *p, uint8_t *buf, uint16_t len, uint16_t off)
+ * @brief
+ *       add the data into packet
+ * @param[in]  p:
+ * @param[in]  buf:
+ * @param[in]  len:
+ * @param[in]  off:
+ * @return
+ *        None
+ **********************************************************************************************/
+void wfx_rsi_pkt_add_data(void * p, uint8_t * buf, uint16_t len, uint16_t off)
+{
+    rsi_pkt_t * pkt;
+
+    pkt = (rsi_pkt_t *) p;
+    memcpy(((char *) pkt->data) + off, buf, len);
+}
+
+/********************************************************************************************
+ * @fn   int32_t wfx_rsi_send_data(void *p, uint16_t len)
+ * @brief
+ *       Driver send a data
+ * @param[in]  p:
+ * @param[in]  len:
+ * @return
+ *        None
+ **********************************************************************************************/
+int32_t wfx_rsi_send_data(void * p, uint16_t len)
+{
+    int32_t status;
+    register uint8_t * host_desc;
+    rsi_pkt_t * pkt;
+
+    pkt       = (rsi_pkt_t *) p;
+    host_desc = pkt->desc;
+    memset(host_desc, 0, RSI_HOST_DESC_LENGTH);
+    rsi_uint16_to_2bytes(host_desc, (len & 0xFFF));
+
+    // Fill packet type
+    host_desc[1] |= (RSI_WLAN_DATA_Q << 4);
+    host_desc[2] |= 0x01;
+
+    rsi_enqueue_pkt(&rsi_driver_cb->wlan_tx_q, pkt);
+
+#ifndef RSI_SEND_SEM_BITMAP
+    rsi_driver_cb_non_rom->send_wait_bitmap |= BIT(0);
+#endif
+    // Set TX packet pending event
+    rsi_set_event(RSI_TX_EVENT);
+
+    if (rsi_wait_on_wlan_semaphore(&rsi_driver_cb_non_rom->send_data_sem, RSI_SEND_DATA_RESPONSE_WAIT_TIME) != RSI_ERROR_NONE)
+    {
+        return RSI_ERROR_RESPONSE_TIMEOUT;
+    }
+    status = rsi_wlan_get_status();
+
+    return status;
+}
+
+struct wfx_rsi wfx_rsi;
diff --git a/examples/platform/silabs/SiWx917/rs911x/rsi_wlan_config.h b/examples/platform/silabs/SiWx917/rs911x/rsi_wlan_config.h
new file mode 100644
index 0000000..f2a47b5
--- /dev/null
+++ b/examples/platform/silabs/SiWx917/rs911x/rsi_wlan_config.h
@@ -0,0 +1,606 @@
+/*
+ *
+ *    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.
+ */
+
+#ifndef RSI_CONFIG_H
+#define RSI_CONFIG_H
+
+#include "rsi_wlan_defines.h"
+
+//! Enable feature
+#define RSI_ENABLE 1
+//! Disable feature
+#define RSI_DISABLE 0
+
+//! To enable wlan opermode
+#define RSI_OPERMODE_WLAN 0
+
+//! To enable concurrent mode
+#define CONCURRENT_MODE RSI_DISABLE
+
+//! opermode command parameters
+/*=======================================================================*/
+//! To set wlan feature select bit map
+#define RSI_FEATURE_BIT_MAP (FEAT_SECURITY_OPEN)
+
+//! TCP IP BYPASS feature check
+#ifdef RS911X_SOCKETS
+#define RSI_TCP_IP_BYPASS RSI_DISABLE
+
+#define RSI_TCP_IP_FEATURE_BIT_MAP                                                                                                 \
+    (TCP_IP_FEAT_DHCPV4_CLIENT |                             /*TCP_IP_FEAT_HTTP_CLIENT | */                                        \
+     TCP_IP_FEAT_EXTENSION_VALID | /*TCP_IP_FEAT_SSL     |*/ /*TCP_IP_FEAT_DNS_CLIENT |*/                                          \
+     0)
+//! To set custom feature select bit map
+#define RSI_CUSTOM_FEATURE_BIT_MAP FEAT_CUSTOM_FEAT_EXTENSION_VALID
+
+#else /* Don't use RSI_SOCKETS */
+#define RSI_TCP_IP_BYPASS RSI_ENABLE
+#define RSI_TCP_IP_FEATURE_BIT_MAP (TCP_IP_FEAT_BYPASS /*| TCP_IP_FEAT_EXTENSION_VALID*/)
+#endif
+
+//! To set Extended custom feature select bit map
+#if WIFI_ENABLE_SECURITY_WPA3
+#ifdef RSI_M4_INTERFACE
+#define RSI_EXT_CUSTOM_FEATURE_BIT_MAP (EXT_FEAT_256K_MODE | EXT_FEAT_IEEE_80211W)
+#else
+#define RSI_EXT_CUSTOM_FEATURE_BIT_MAP (EXT_FEAT_384K_MODE | EXT_FEAT_IEEE_80211W)
+#endif
+#else
+#ifdef RSI_M4_INTERFACE
+#define RSI_EXT_CUSTOM_FEATURE_BIT_MAP EXT_FEAT_256K_MODE
+#else
+#define RSI_EXT_CUSTOM_FEATURE_BIT_MAP EXT_FEAT_384K_MODE
+#endif
+#endif
+
+//! To set Extended TCPIP feature select bit map
+#define RSI_EXT_TCPIP_FEATURE_BITMAP (/*EXT_FEAT_HTTP_OTAF_SUPPORT |*/ EXT_TCP_IP_SSL_16K_RECORD)
+//! Extended custom feature is selected internally
+//! CCP         -- EXT_FEAT_256K_MODE
+//! Wiseconnect -- EXT_FEAT_384K_MODE
+/*=======================================================================*/
+//! Feature frame parameters
+/*=======================================================================*/
+#define PLL_MODE 0
+#define RF_TYPE 1 //! 0 - External RF 1- Internal RF
+#define WIRELESS_MODE 0
+#define ENABLE_PPP 0
+#define AFE_TYPE 1
+#define FEATURE_ENABLES 0
+/*=======================================================================*/
+//! Band command parameters
+/*=======================================================================*/
+
+//! RSI_BAND_2P4GHZ(2.4GHz) or RSI_BAND_5GHZ(5GHz) or RSI_DUAL_BAND
+#define RSI_BAND RSI_BAND_2P4GHZ
+/*=======================================================================*/
+//! set region command parameters
+/*=======================================================================*/
+
+//! RSI_ENABLE or RSI_DISABLE Set region support
+#define RSI_SET_REGION_SUPPORT RSI_DISABLE //@ RSI_ENABLE or RSI_DISABLE set region
+
+//! If 1:region configurations taken from user ;0:region configurations taken from beacon
+#define RSI_SET_REGION_FROM_USER_OR_BEACON 1
+
+//! 0-Default Region domain ,1-US, 2-EUROPE, 3-JAPAN
+#define RSI_REGION_CODE 1
+
+//! 0- Without On Board Antenna , 1- With On Board Antenna
+#define RSI_MODULE_TYPE 1
+
+/*=======================================================================*/
+//! set region AP command parameters
+/*=======================================================================*/
+
+//! RSI_ENABLE or RSI_DISABLE Set region AP support
+#define RSI_SET_REGION_AP_SUPPORT RSI_DISABLE
+
+//! If 1:region configurations taken from user ;0:region configurations taken from firmware
+#define RSI_SET_REGION_AP_FROM_USER RSI_DISABLE
+
+//! "US" or "EU" or "JP" or other region codes
+#define RSI_COUNTRY_CODE "US"
+/*=======================================================================*/
+
+//! Rejoin parameters
+/*=======================================================================*/
+
+//! RSI_ENABLE or RSI_DISABLE rejoin params
+#define RSI_REJOIN_PARAMS_SUPPORT RSI_ENABLE
+
+//! Rejoin retry count. If 0 retries infinity times
+#define RSI_REJOIN_MAX_RETRY 5
+
+//! Periodicity of rejoin attempt
+#define RSI_REJOIN_SCAN_INTERVAL 1
+
+//! Beacon missed count
+#define RSI_REJOIN_BEACON_MISSED_COUNT 40
+
+//! RSI_ENABLE or RSI_DISABLE retry for first time join failure
+#define RSI_REJOIN_FIRST_TIME_RETRY RSI_DISABLE
+
+/*=======================================================================*/
+
+//! BG scan command parameters
+/*=======================================================================*/
+
+//! RSI_ENABLE or RSI_DISABLE BG Scan support
+#define RSI_BG_SCAN_SUPPORT RSI_ENABLE
+
+//! RSI_ENABLE or RSI_DISABLE BG scan
+#define RSI_BG_SCAN_ENABLE RSI_ENABLE
+
+//! RSI_ENABLE or RSI_DISABLE instant BG scan
+#define RSI_INSTANT_BG RSI_ENABLE
+
+//! BG scan threshold value
+#define RSI_BG_SCAN_THRESHOLD 63
+
+//! RSSI tolerance Threshold
+#define RSI_RSSI_TOLERANCE_THRESHOLD 4
+
+//! BG scan periodicity
+#define RSI_BG_SCAN_PERIODICITY 2
+
+//! Active scan duration
+#define RSI_ACTIVE_SCAN_DURATION 50
+
+//! Passive scan duration
+#define RSI_PASSIVE_SCAN_DURATION 50
+
+//! Multi probe
+#define RSI_MULTIPROBE RSI_ENABLE
+
+/*=======================================================================*/
+
+//! RSI_ENABLE or RSI_DISABLE to set RTS threshold config
+#define RSI_WLAN_CONFIG_ENABLE RSI_ENABLE
+
+#define CONFIG_RTSTHRESHOLD 1
+
+#define RSI_RTS_THRESHOLD 2346
+
+/*=======================================================================*/
+
+//! Roaming parameters
+/*=======================================================================*/
+
+//! RSI_ENABLE or RSI_DISABLE Roaming support
+#define RSI_ROAMING_SUPPORT RSI_DISABLE
+
+//! roaming threshold value
+#define RSI_ROAMING_THRESHOLD 67
+
+//! roaming hysterisis value
+#define RSI_ROAMING_HYSTERISIS 4
+
+/*=======================================================================*/
+//! High Throughput Capabilies related information
+/*=======================================================================*/
+
+//! RSI_ENABLE or RSI_DISABLE 11n mode in AP mode
+#define RSI_MODE_11N_ENABLE RSI_DISABLE
+
+//! HT caps supported
+#define RSI_HT_CAPS_NUM_RX_STBC (1 << 8)
+#define RSI_HT_CAPS_SHORT_GI_20MHZ BIT(5)
+#define RSI_HT_CAPS_GREENFIELD_EN BIT(4)
+#define RSI_HT_CAPS_SUPPORT_CH_WIDTH BIT(1)
+
+//! HT caps bit map.
+#define RSI_HT_CAPS_BIT_MAP                                                                                                        \
+    (RSI_HT_CAPS_NUM_RX_STBC | RSI_HT_CAPS_SHORT_GI_20MHZ | RSI_HT_CAPS_GREENFIELD_EN | RSI_HT_CAPS_SUPPORT_CH_WIDTH)
+
+/*=======================================================================*/
+//! Scan command parameters
+/*=======================================================================*/
+
+//! scan channel bit map in 2.4GHz band,valid if given channel to scan is 0
+#define RSI_SCAN_CHANNEL_BIT_MAP_2_4 0
+
+//! scan channle bit map in 5GHz band ,valid if given channel to scan is 0
+#define RSI_SCAN_CHANNEL_BIT_MAP_5 0
+
+//! scan_feature_bitmap ,valid only if specific channel to scan and ssid are given
+#define RSI_SCAN_FEAT_BITMAP 0
+
+/*=======================================================================*/
+//! Enterprise configuration command parameters
+/*=======================================================================*/
+
+//! Enterprise method ,should be one of among TLS, TTLS, FAST or PEAP
+#define RSI_EAP_METHOD "TTLS"
+//! This parameter is used to configure the module in Enterprise security mode
+#define RSI_EAP_INNER_METHOD "\"auth=MSCHAPV2\""
+//! Private Key Password is required for encrypted private key, format is like "\"12345678\""
+#define RSI_PRIVATE_KEY_PASSWORD ""
+/*=======================================================================*/
+//! AP configuration command parameters
+/*=======================================================================*/
+
+//! This Macro is used to enable AP keep alive functionality
+#define RSI_AP_KEEP_ALIVE_ENABLE RSI_ENABLE
+
+//! This parameter is used to configure keep alive type
+#define RSI_AP_KEEP_ALIVE_TYPE RSI_NULL_BASED_KEEP_ALIVE
+
+//! This parameter is used to configure keep alive period
+#define RSI_AP_KEEP_ALIVE_PERIOD 100
+
+//! This parameter is used to configure maximum stations supported
+#define RSI_MAX_STATIONS_SUPPORT 4
+/*=======================================================================*/
+//! Join command parameters
+/*=======================================================================*/
+
+//! Tx power level
+#define RSI_POWER_LEVEL RSI_POWER_LEVEL_HIGH
+
+//! RSI_JOIN_FEAT_STA_BG_ONLY_MODE_ENABLE or RSI_JOIN_FEAT_LISTEN_INTERVAL_VALID
+#if WIFI_ENABLE_SECURITY_WPA3
+#define RSI_JOIN_FEAT_BIT_MAP RSI_JOIN_FEAT_MFP_CAPABLE_REQUIRED
+#else
+#define RSI_JOIN_FEAT_BIT_MAP 0
+#endif
+
+#define RSI_LISTEN_INTERVAL 0
+
+//! Transmission data rate. Physical rate at which data has to be transmitted.
+#define RSI_DATA_RATE RSI_DATA_RATE_AUTO
+
+/*=======================================================================*/
+//! Ipconf command parameters
+/*=======================================================================*/
+
+//! DHCP client host name
+#define RSI_DHCP_HOST_NAME "efr_9116"
+
+//! Transmit test command parameters
+/*=======================================================================*/
+//! TX TEST rate flags
+#define RSI_TX_TEST_RATE_FLAGS 0
+
+//! TX TEST per channel bandwidth
+#define RSI_TX_TEST_PER_CH_BW 0
+
+//! TX TEST aggregation enable or disable
+#define RSI_TX_TEST_AGGR_ENABLE RSI_DISABLE
+
+//! TX TEST delay
+#define RSI_TX_TEST_DELAY 0
+
+/*======================================================================*/
+//! ssl parameters
+/*=======================================================================*/
+//! ssl version
+#define RSI_SSL_VERSION 0
+
+//! ssl ciphers
+#define RSI_SSL_CIPHERS SSL_ALL_CIPHERS
+
+//! Enable TCP over SSL with TLS version depends on remote side
+#define PROTOCOL_DFLT_VERSION BIT(0)
+
+//! Enable TCP over SSL with TLS version 1.0
+#define PROTOCOL_TLS_1_0 (BIT(0) | BIT(13))
+
+//! Enable TCP over SSL with TLS version 1.1
+#define PROTOCOL_TLS_1_1 (BIT(0) | BIT(14))
+
+//! Enable TCP over SSL with TLS version 1.2
+#define PROTOCOL_TLS_1_2 (BIT(0) | BIT(15))
+/*=======================================================================*/
+//! Power save command parameters
+/*=======================================================================*/
+//! set handshake type of power mode
+#define RSI_HAND_SHAKE_TYPE MSG_BASED
+
+//! 0 - LP, 1- ULP mode with RAM retention and 2 - ULP with Non RAM retention
+#define RSI_SELECT_LP_OR_ULP_MODE RSI_ULP_WITH_RAM_RET
+
+//! set DTIM aligment required
+//! 0 - module wakes up at beacon which is just before or equal to listen_interval
+//! 1 - module wakes up at DTIM beacon which is just before or equal to listen_interval
+#define RSI_DTIM_ALIGNED_TYPE 0
+
+//! Monitor interval for the FAST PSP mode
+//! default is 50 ms, and this parameter is valid for FAST PSP only
+#define RSI_MONITOR_INTERVAL 50
+
+//! Number of DTIMs to skip during powersave
+#define RSI_NUM_OF_DTIM_SKIP 0
+
+//! WMM PS parameters
+//! set wmm enable or disable
+#define RSI_WMM_PS_ENABLE RSI_DISABLE
+
+//! set wmm enable or disable
+//! 0- TX BASED 1 - PERIODIC
+#define RSI_WMM_PS_TYPE 0
+
+//! set wmm wake up interval
+#define RSI_WMM_PS_WAKE_INTERVAL 20
+
+//! set wmm UAPSD bitmap
+#define RSI_WMM_PS_UAPSD_BITMAP 15
+
+/*=======================================================================*/
+//! Socket configuration
+/*=======================================================================*/
+//! RSI_ENABLE or RSI_DISABLE High performance socket
+#define HIGH_PERFORMANCE_ENABLE RSI_ENABLE //@ RSI_ENABLE or RSI_DISABLE High performance socket
+#define TOTAL_SOCKETS 10                   //@ Total number of sockets. TCP TX + TCP RX + UDP TX + UDP RX
+#define TOTAL_TCP_SOCKETS 4                //@ Total TCP sockets. TCP TX + TCP RX
+#define TOTAL_UDP_SOCKETS 4                //@ Total UDP sockets. UDP TX + UDP RX
+#define TCP_TX_ONLY_SOCKETS 0              //@ Total TCP TX only sockets. TCP TX
+#define TCP_RX_ONLY_SOCKETS 0              //@ Total TCP RX only sockets. TCP RX
+#define UDP_TX_ONLY_SOCKETS 0              //@ Total UDP TX only sockets. UDP TX
+#define UDP_RX_ONLY_SOCKETS 0              //@ Total UDP RX only sockets. UDP RX
+#define TCP_RX_HIGH_PERFORMANCE_SOCKETS 1  //@ Total TCP RX High Performance sockets
+#define TCP_RX_WINDOW_SIZE_CAP 10          //@ TCP RX Window size
+#define TCP_RX_WINDOW_DIV_FACTOR 10        //@ TCP RX Window division factor
+/*=======================================================================*/
+
+//! Socket Create parameters
+/*=======================================================================*/
+
+//! Initial timeout for Socket
+#define RSI_SOCKET_KEEPALIVE_TIMEOUT 1200
+
+//! VAP ID for Concurrent mode
+#define RSI_VAP_ID 0
+
+//! Timeout for join or scan
+/*=======================================================================*/
+
+//! RSI_ENABLE or RSI_DISABLE Timeout support
+#define RSI_TIMEOUT_SUPPORT RSI_DISABLE
+
+//! roaming threshold value
+#define RSI_TIMEOUT_BIT_MAP 1
+
+//! roaming hysterisis value
+#define RSI_TIMEOUT_VALUE 1500
+
+//! Timeout for ping request
+/*=======================================================================*/
+
+//! Timeout for PING_REQUEST
+#define RSI_PING_REQ_TIMEOUT_MS 1000
+
+//! Provide HTTP/HTTPS response status code indication to application e.g 200, 404 etc
+/*=======================================================================*/
+//! Enable or Diable feature
+#define RSI_HTTP_STATUS_INDICATION_EN RSI_DISABLE
+/*=======================================================================*/
+
+//! Store Config Profile parameters
+/*=======================================================================*/
+
+//! Client profile
+#define RSI_WLAN_PROFILE_CLIENT 0
+//! P2P profile
+#define RSI_WLAN_PROFILE_P2P 1
+//! EAP profile
+#define RSI_WLAN_PROFILE_EAP 2
+//! AP profile
+#define RSI_WLAN_PROFILE_AP 6
+//! All profiles
+#define RSI_WLAN_PROFILE_ALL 0xFF
+
+//! AP Config Profile Parameters
+/*==============================================================================*/
+
+//! Transmission data rate. Physical rate at which data has to be transmitted.
+#define RSI_CONFIG_AP_DATA_RATE RSI_DATA_RATE_AUTO
+//! To set wlan feature select bit map
+#define RSI_CONFIG_AP_WLAN_FEAT_BIT_MAP (FEAT_SECURITY_PSK)
+//! TCP/IP feature select bitmap for selecting TCP/IP features
+#define RSI_CONFIG_AP_TCP_IP_FEAT_BIT_MAP (TCP_IP_FEAT_DHCPV4_SERVER)
+//! To set custom feature select bit map
+#define RSI_CONFIG_AP_CUSTOM_FEAT_BIT_MAP 0
+//! Tx power level
+#define RSI_CONFIG_AP_TX_POWER RSI_POWER_LEVEL_HIGH
+//! AP SSID
+#define RSI_CONFIG_AP_SSID "SILABS_AP"
+//! RSI_BAND_2P4GHZ(2.4GHz) or RSI_BAND_5GHZ(5GHz) or RSI_DUAL_BAND
+#define RSI_CONFIG_AP_BAND RSI_BAND_2P4GHZ
+//! To configure AP channle number
+#define RSI_CONFIG_AP_CHANNEL 6
+//! To configure security type
+#define RSI_CONFIG_AP_SECURITY_TYPE RSI_WPA
+//! To configure encryption type
+#define RSI_CONFIG_AP_ENCRYPTION_TYPE 1
+//! To configure PSK
+#define RSI_CONFIG_AP_PSK "1234567890"
+//! To configure beacon interval
+#define RSI_CONFIG_AP_BEACON_INTERVAL 100
+//! To configure DTIM period
+#define RSI_CONFIG_AP_DTIM 2
+//! This parameter is used to configure keep alive type
+#define RSI_CONFIG_AP_KEEP_ALIVE_TYPE 0 //! RSI_NULL_BASED_KEEP_ALIVE
+
+#define RSI_CONFIG_AP_KEEP_ALIVE_COUNTER 0 //! 100
+//! This parameter is used to configure keep alive period
+#define RSI_CONFIG_AP_KEEP_ALIVE_PERIOD 100
+//! This parameter is used to configure maximum stations supported
+#define RSI_CONFIG_AP_MAX_STATIONS_COUNT 4
+//! P2P Network parameters
+//! TCP_STACK_USED BIT(0) - IPv4, BIT(1) -IPv6, (BIT(0) | BIT(1)) - Both IPv4 and IPv6
+#define RSI_CONFIG_AP_TCP_STACK_USED BIT(0)
+//! IP address of the module
+//! E.g: 0x0A0AA8C0 == 192.168.10.10
+#define RSI_CONFIG_AP_IP_ADDRESS 0x0A0AA8C0
+//! IP address of netmask
+//! E.g: 0x00FFFFFF == 255.255.255.0
+#define RSI_CONFIG_AP_SN_MASK_ADDRESS 0x00FFFFFF
+//! IP address of Gateway
+//! E.g: 0x0A0AA8C0 == 192.168.10.10
+#define RSI_CONFIG_AP_GATEWAY_ADDRESS 0x0A0AA8C0
+
+//! Client Profile Parameters
+/* ===================================================================================== */
+
+//! To configure data rate
+#define RSI_CONFIG_CLIENT_DATA_RATE RSI_DATA_RATE_AUTO
+//! To configure wlan feature bitmap
+#define RSI_CONFIG_CLIENT_WLAN_FEAT_BIT_MAP 0
+//! To configure tcp/ip feature bitmap
+#define RSI_CONFIG_CLIENT_TCP_IP_FEAT_BIT_MAP BIT(2)
+//! To configure custom feature bit map
+#define RSI_CONFIG_CLIENT_CUSTOM_FEAT_BIT_MAP 0
+//! To configure TX power
+#define RSI_CONFIG_CLIENT_TX_POWER RSI_POWER_LEVEL_HIGH
+//! To configure listen interval
+#define RSI_CONFIG_CLIENT_LISTEN_INTERVAL 0
+//! To configure SSID
+#define RSI_CONFIG_CLIENT_SSID "Matter_9116"
+//! RSI_BAND_2P4GHZ(2.4GHz) or RSI_BAND_5GHZ(5GHz) or RSI_DUAL_BAND
+#define RSI_CONFIG_CLIENT_BAND RSI_BAND_2P4GHZ
+//! To configure channel number
+#define RSI_CONFIG_CLIENT_CHANNEL 0
+//! To configure security type
+#define RSI_CONFIG_CLIENT_SECURITY_TYPE 0 // RSI_WPA
+//! To configure encryption type
+#define RSI_CONFIG_CLIENT_ENCRYPTION_TYPE 0
+//! To configure PSK
+#define RSI_CONFIG_CLIENT_PSK "1234567890"
+//! To configure PMK
+#define RSI_CONFIG_CLIENT_PMK ""
+//! Client Network parameters
+//! TCP_STACK_USED BIT(0) - IPv4, BIT(1) -IPv6, (BIT(0) | BIT(1)) - Both IPv4 and IPv6
+#define RSI_CONFIG_CLIENT_TCP_STACK_USED BIT(0)
+//! DHCP mode 1- Enable 0- Disable
+//! If DHCP mode is disabled given IP statically
+#define RSI_CONFIG_CLIENT_DHCP_MODE RSI_DHCP
+//! IP address of the module
+//! E.g: 0x0A0AA8C0 == 192.168.10.10
+#define RSI_CONFIG_CLIENT_IP_ADDRESS 0x0A0AA8C0
+//! IP address of netmask
+//! E.g: 0x00FFFFFF == 255.255.255.0
+#define RSI_CONFIG_CLIENT_SN_MASK_ADDRESS 0x00FFFFFF
+//! IP address of Gateway
+//! E.g: 0x010AA8C0 == 192.168.10.1
+#define RSI_CONFIG_CLIENT_GATEWAY_ADDRESS 0x010AA8C0
+//! scan channel bit map in 2.4GHz band,valid if given channel to scan is 0
+#define RSI_CONFIG_CLIENT_SCAN_FEAT_BITMAP 0
+//! Scan channel magic code
+#define RSI_CONFIG_CLIENT_MAGIC_CODE 0x4321
+//! scan channel bit map in 2.4GHz band,valid if given channel to scan is 0
+#define RSI_CONFIG_CLIENT_SCAN_CHAN_BITMAP_2_4_GHZ 0
+//! scan channle bit map in 5GHz band ,valid if given channel to scan is 0
+#define RSI_CONFIG_CLIENT_SCAN_CHAN_BITMAP_5_0_GHZ 0
+
+//! EAP Client Profile Parameters
+/* =========================================================================== */
+
+//! To configure data rate
+#define RSI_CONFIG_EAP_DATA_RATE RSI_DATA_RATE_AUTO
+//! To configure wlan feature bitmap
+#define RSI_CONFIG_EAP_WLAN_FEAT_BIT_MAP 0
+//! To configure tcp/ip feature bitmap
+#define RSI_CONFIG_EAP_TCP_IP_FEAT_BIT_MAP BIT(2)
+//! To configure custom feature bit map
+#define RSI_CONFIG_EAP_CUSTOM_FEAT_BIT_MAP 0
+//! To configure EAP TX power
+#define RSI_CONFIG_EAP_TX_POWER RSI_POWER_LEVEL_HIGH
+//! To Configure scan channel feature bitmap
+#define RSI_CONFIG_EAP_SCAN_FEAT_BITMAP 0
+//! scan channel bit map in 2.4GHz band,valid if given channel to scan is 0
+#define RSI_CONFIG_EAP_CHAN_MAGIC_CODE 0 // 0x4321
+//! scan channel bit map in 2.4GHz band,valid if given channel to scan is 0
+#define RSI_CONFIG_EAP_SCAN_CHAN_BITMAP_2_4_GHZ 0
+//! scan channle bit map in 5GHz band ,valid if given channel to scan is 0
+#define RSI_CONFIG_EAP_SCAN_CHAN_BITMAP_5_0_GHZ 0
+//! To configure SSID
+#define RSI_CONFIG_EAP_SSID "SILABS_AP"
+//! RSI_BAND_2P4GHZ(2.4GHz) or RSI_BAND_5GHZ(5GHz) or RSI_DUAL_BAND
+#define RSI_CONFIG_EAP_BAND RSI_BAND_2P4GHZ
+//! To set security type
+#define RSI_CONFIG_EAP_SECURITY_TYPE RSI_WPA2_EAP
+//! To set encryption type
+#define RSI_CONFIG_EAP_ENCRYPTION_TYPE 0
+//! To set channel number
+#define RSI_CONFIG_EAP_CHANNEL 0
+//! Enterprise method ,should be one of among TLS, TTLS, FAST or PEAP
+#define RSI_CONFIG_EAP_METHOD "TLS"
+//! This parameter is used to configure the module in Enterprise security mode
+#define RSI_CONFIG_EAP_INNER_METHOD "\"auth=MSCHAPV2\""
+//! To configure EAP user identity
+#define RSI_CONFIG_EAP_USER_IDENTITY "\"user1\""
+//! TO configure EAP password
+#define RSI_CONFIG_EAP_PASSWORD "\"test123\""
+//! EAP Network parameters
+//! TCP_STACK_USED BIT(0) - IPv4, BIT(1) -IPv6, (BIT(0) | BIT(1)) - Both IPv4 and IPv6
+#define RSI_CONFIG_EAP_TCP_STACK_USED BIT(0)
+//! DHCP mode 1- Enable 0- Disable
+//! If DHCP mode is disabled given IP statically
+#define RSI_CONFIG_EAP_DHCP_MODE RSI_DHCP
+//! IP address of the module
+//! E.g: 0x0A0AA8C0 == 192.168.10.10
+#define RSI_CONFIG_EAP_IP_ADDRESS 0x0A0AA8C0
+//! IP address of netmask
+//! E.g: 0x00FFFFFF == 255.255.255.0
+#define RSI_CONFIG_EAP_SN_MASK_ADDRESS 0x00FFFFFF
+//! IP address of Gateway
+//! E.g: 0x010AA8C0 == 192.168.10.1
+#define RSI_CONFIG_EAP_GATEWAY_ADDRESS 0x010AA8C0
+
+//! P2P Profile parameters
+/* ================================================================================= */
+
+//! To configure data rate
+#define RSI_CONFIG_P2P_DATA_RATE RSI_DATA_RATE_AUTO
+//! To configure wlan feature bitmap
+#define RSI_CONFIG_P2P_WLAN_FEAT_BIT_MAP 0
+//! To configure P2P tcp/ip feature  bitmap
+#define RSI_CONFIG_P2P_TCP_IP_FEAT_BIT_MAP BIT(2)
+//! To configure P2P custom feature bitmap
+#define RSI_CONFIG_P2P_CUSTOM_FEAT_BIT_MAP 0
+//! TO configure P2P tx power level
+#define RSI_CONFIG_P2P_TX_POWER RSI_POWER_LEVEL_HIGH
+//! Set P2P go intent
+#define RSI_CONFIG_P2P_GO_INTNET 16 //! Support only Autonomous GO mode
+//! Set device name
+#define RSI_CONFIG_P2P_DEVICE_NAME "WSC1.1"
+//! Set device operating channel
+#define RSI_CONFIG_P2P_OPERATING_CHANNEL 11
+//! Set SSID postfix
+#define RSI_CONFIG_P2P_SSID_POSTFIX "WSC_1_0_0"
+//! Set P2P join SSID
+#define RSI_CONFIG_P2P_JOIN_SSID "SILABS_AP"
+//! Set psk key
+#define RSI_CONFIG_P2P_PSK_KEY "12345678"
+//! P2P Network parameters
+//! TCP_STACK_USED BIT(0) - IPv4, BIT(1) -IPv6, (BIT(0) | BIT(1)) - Both IPv4 and IPv6
+#define RSI_CONFIG_P2P_TCP_STACK_USED BIT(0)
+//! DHCP mode 1- Enable 0- Disable
+//! If DHCP mode is disabled given IP statically
+#define RSI_CONFIG_P2P_DHCP_MODE 1
+//! IP address of the module
+//! E.g: 0x0A0AA8C0 == 192.168.10.10
+#define RSI_CONFIG_P2P_IP_ADDRESS 0x0A0AA8C0
+//! IP address of netmask
+//! E.g: 0x00FFFFFF == 255.255.255.0
+#define RSI_CONFIG_P2P_SN_MASK_ADDRESS 0x00FFFFFF
+//! IP address of Gateway
+//! E.g: 0x010AA8C0 == 192.168.10.1
+#define RSI_CONFIG_P2P_GATEWAY_ADDRESS 0x010AA8C0
+
+#endif
diff --git a/examples/platform/silabs/SiWx917/rs911x/wfx_rsi.h b/examples/platform/silabs/SiWx917/rs911x/wfx_rsi.h
new file mode 100644
index 0000000..380fc8f
--- /dev/null
+++ b/examples/platform/silabs/SiWx917/rs911x/wfx_rsi.h
@@ -0,0 +1,98 @@
+/*
+ *
+ *    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.
+ */
+
+#ifndef _WFX_RSI_H_
+#define _WFX_RSI_H_
+/*
+ * Interface to RSI Sapis
+ */
+
+#define WFX_RSI_WLAN_TASK_SZ (1024 + 512 + 256) /* Unknown how big this should be 	*/
+#define WFX_RSI_TASK_SZ (1024 + 1024)           /* Stack for the WFX/RSI task		*/
+#define WFX_RSI_BUF_SZ (1024 * 10)              /* May need tweak 			*/
+#define WFX_RSI_CONFIG_MAX_JOIN 5               /* Max join retries			*/
+#define WFX_RSI_NUM_TIMERS 2                    /* Number of RSI timers to alloc	*/
+
+/*
+ * Various events fielded by the wfx_rsi task
+ * Make sure that we only use 8 bits (otherwise freeRTOS - may need some changes)
+ */
+#define WFX_EVT_STA_CONN 0x01
+#define WFX_EVT_STA_DISCONN 0x02
+#define WFX_EVT_AP_START 0x04
+#define WFX_EVT_AP_STOP 0x08
+#define WFX_EVT_SCAN 0x10 /* This is used as scan result and start */
+#define WFX_EVT_STA_START_JOIN 0x20
+#define WFX_EVT_STA_DO_DHCP 0x40
+#define WFX_EVT_STA_DHCP_DONE 0x80
+
+#define WFX_RSI_ST_DEV_READY 0x01
+#define WFX_RSI_ST_AP_READY 0x02
+#define WFX_RSI_ST_STA_PROVISIONED 0x04
+#define WFX_RSI_ST_STA_CONNECTING 0x08
+#define WFX_RSI_ST_STA_CONNECTED 0x10
+#define WFX_RSI_ST_STA_DHCP_DONE 0x40 /* Requested to do DHCP after conn	*/
+#define WFX_RSI_ST_STA_MODE 0x80      /* Enable Station Mode			*/
+#define WFX_RSI_ST_AP_MODE 0x100      /* Enable AP Mode			*/
+#define WFX_RSI_ST_STA_READY (WFX_RSI_ST_STA_CONNECTED | WFX_RSI_ST_STA_DHCP_DONE)
+#define WFX_RSI_ST_STARTED 0x200     /* RSI task started			*/
+#define WFX_RSI_ST_SCANSTARTED 0x400 /* Scan Started				*/
+
+struct wfx_rsi
+{
+    EventGroupHandle_t events;
+    TaskHandle_t drv_task;
+    TaskHandle_t wlan_task;
+    uint16_t dev_state;
+    uint16_t ap_chan; /* The chan our STA is using	*/
+    wfx_wifi_provision_t sec;
+#ifdef SL_WFX_CONFIG_SCAN
+    void (*scan_cb)(wfx_wifi_scan_result_t *);
+    char * scan_ssid; /* Which one are we scanning for */
+#endif
+#ifdef SL_WFX_CONFIG_SOFTAP
+    sl_wfx_mac_address_t softap_mac;
+#endif
+    sl_wfx_mac_address_t sta_mac;
+    sl_wfx_mac_address_t ap_mac;   /* To which our STA is connected */
+    sl_wfx_mac_address_t ap_bssid; /* To which our STA is connected */
+    uint16_t join_retries;
+    uint8_t ip4_addr[4]; /* Not sure if this is enough */
+};
+#define RSI_SCAN_RESP_SZ 54
+
+extern struct wfx_rsi wfx_rsi;
+#ifdef __cplusplus
+extern "C" {
+#endif
+void wfx_rsidev_init(void);
+void wfx_rsi_task(void * arg);
+void efr32Log(const char * aFormat, ...);
+#if CHIP_DEVICE_CONFIG_ENABLE_IPV4
+void wfx_ip_changed_notify(int got_ip);
+#endif /* CHIP_DEVICE_CONFIG_ENABLE_IPV4 */
+int32_t wfx_rsi_get_ap_info(wfx_wifi_scan_result_t * ap);
+int32_t wfx_rsi_get_ap_ext(wfx_wifi_scan_ext_t * extra_info);
+int32_t wfx_rsi_reset_count();
+int32_t wfx_rsi_disconnect();
+#define WFX_RSI_LOG(...) efr32Log(__VA_ARGS__);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _WFX_RSI_H_ */
diff --git a/examples/platform/silabs/SiWx917/rs911x/wfx_rsi_host.c b/examples/platform/silabs/SiWx917/rs911x/wfx_rsi_host.c
new file mode 100644
index 0000000..a55e0ae
--- /dev/null
+++ b/examples/platform/silabs/SiWx917/rs911x/wfx_rsi_host.c
@@ -0,0 +1,440 @@
+/*
+ *
+ *    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 <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "em_bus.h"
+#include "em_cmu.h"
+#include "em_gpio.h"
+#include "em_ldma.h"
+#include "em_usart.h"
+#include "sl_status.h"
+
+#include "FreeRTOS.h"
+#include "event_groups.h"
+#include "task.h"
+
+#include "wfx_host_events.h"
+#include "wfx_rsi.h"
+
+/* wfxRsi Task will use as its stack */
+StackType_t wfxRsiTaskStack[WFX_RSI_TASK_SZ] = { 0 };
+
+/* Structure that will hold the TCB of the wfxRsi Task being created. */
+StaticTask_t wfxRsiTaskBuffer;
+
+/*********************************************************************
+ * @fn  sl_status_t wfx_wifi_start(void)
+ * @brief
+ * Called from ConnectivityManagerImpl.cpp - to enable the device
+ * Create the RSI task and let it deal with life.
+ * @param[in]  None
+ * @return  Returns SL_STATUS_OK if successful,
+ *          SL_STATUS_FAIL otherwise
+ ***********************************************************************/
+sl_status_t wfx_wifi_start(void)
+{
+    if (wfx_rsi.dev_state & WFX_RSI_ST_STARTED)
+    {
+        WFX_RSI_LOG("%s: already started.", __func__);
+        return SL_STATUS_OK;
+    }
+    wfx_rsi.dev_state |= WFX_RSI_ST_STARTED;
+    WFX_RSI_LOG("%s: starting..", __func__);
+    /*
+     * Create the Wifi driver task
+     */
+    wfx_rsi.wlan_task = xTaskCreateStatic(wfx_rsi_task, "wfx_rsi", WFX_RSI_TASK_SZ, NULL, WLAN_DRIVER_TASK_PRIORITY,
+                                          wfxRsiTaskStack, &wfxRsiTaskBuffer);
+
+    if (NULL == wfx_rsi.wlan_task)
+    {
+        WFX_RSI_LOG("%s: error: failed to create task.", __func__);
+        return SL_STATUS_FAIL;
+    }
+    return SL_STATUS_OK;
+}
+
+/*********************************************************************
+ * @fn  void wfx_enable_sta_mode(void)
+ * @brief
+ *      driver enable the STA mode
+ * @param[in]  None
+ * @return   None
+ ***********************************************************************/
+void wfx_enable_sta_mode(void)
+{
+    wfx_rsi.dev_state |= WFX_RSI_ST_STA_MODE;
+}
+
+/*********************************************************************
+ * @fn  bool wfx_is_sta_mode_enabled(void)
+ * @brief
+ *      driver enabled the STA mode
+ * @param[in]  None
+ * @return   mode
+ ***********************************************************************/
+bool wfx_is_sta_mode_enabled(void)
+{
+    bool mode;
+    mode = !!(wfx_rsi.dev_state & WFX_RSI_ST_STA_MODE);
+    // WFX_RSI_LOG("%s: %d", __func__, (mode ? "yes" : "no"));
+    return mode;
+}
+
+/*********************************************************************
+ * @fn  sl_wfx_state_t wfx_get_wifi_state(void)
+ * @brief
+ *      get the wifi state
+ * @param[in]  None
+ * @return   return SL_WFX_NOT_INIT if successful,
+ *         SL_WFX_started otherwise
+ ***********************************************************************/
+sl_wfx_state_t wfx_get_wifi_state(void)
+{
+    if (wfx_rsi.dev_state & WFX_RSI_ST_STA_DHCP_DONE)
+    {
+        return SL_WFX_STA_INTERFACE_CONNECTED;
+    }
+    if (wfx_rsi.dev_state & WFX_RSI_ST_DEV_READY)
+    {
+        return SL_WFX_STARTED;
+    }
+    return SL_WFX_NOT_INIT;
+}
+
+/*********************************************************************
+ * @fn  sl_wfx_state_t wfx_get_wifi_state(void)
+ * @brief
+ *      get the wifi mac address
+ * @param[in]  Interface:
+ * @param[in]  addr : address
+ * @return
+ *       None
+ ***********************************************************************/
+void wfx_get_wifi_mac_addr(sl_wfx_interface_t interface, sl_wfx_mac_address_t * addr)
+{
+    sl_wfx_mac_address_t * mac;
+
+#ifdef SL_WFX_CONFIG_SOFTAP
+    mac = (interface == SL_WFX_SOFTAP_INTERFACE) ? &wfx_rsi.softap_mac : &wfx_rsi.sta_mac;
+#else
+    mac = &wfx_rsi.sta_mac;
+#endif
+    *addr = *mac;
+    WFX_RSI_LOG("%s: %02x:%02x:%02x:%02x:%02x:%02x", __func__, mac->octet[0], mac->octet[1], mac->octet[2], mac->octet[3],
+                mac->octet[4], mac->octet[5]);
+}
+
+/*********************************************************************
+ * @fn  void wfx_set_wifi_provision(wfx_wifi_provision_t *cfg)
+ * @brief
+ *      Driver set the wifi provision
+ * @param[in]  cfg:  wifi configuration
+ * @return
+ *       None
+ ***********************************************************************/
+void wfx_set_wifi_provision(wfx_wifi_provision_t * cfg)
+{
+    WFX_RSI_LOG("%s: SSID: %s", __func__, &wfx_rsi.sec.ssid[0]);
+
+    wfx_rsi.sec = *cfg;
+    wfx_rsi.dev_state |= WFX_RSI_ST_STA_PROVISIONED;
+}
+
+/*********************************************************************
+ * @fn  bool wfx_get_wifi_provision(wfx_wifi_provision_t *wifiConfig)
+ * @brief
+ *      Driver get the wifi provision
+ * @param[in]  wifiConfig:  wifi configuration
+ * @return  return false if successful,
+ *        true otherwise
+ ***********************************************************************/
+bool wfx_get_wifi_provision(wfx_wifi_provision_t * wifiConfig)
+{
+    if (wifiConfig != NULL)
+    {
+        if (wfx_rsi.dev_state & WFX_RSI_ST_STA_PROVISIONED)
+        {
+            *wifiConfig = wfx_rsi.sec;
+            return true;
+        }
+    }
+    return false;
+}
+
+/*********************************************************************
+ * @fn  bool wfx_is_sta_provisioned(void)
+ * @brief
+ *      Driver is STA provisioned
+ * @param[in]  None
+ * @return  None
+ ***********************************************************************/
+bool wfx_is_sta_provisioned(void)
+{
+    bool status = (wfx_rsi.dev_state & WFX_RSI_ST_STA_PROVISIONED) ? true : false;
+    WFX_RSI_LOG("%s: status: SSID -> %s: %s", __func__, &wfx_rsi.sec.ssid[0], (status ? "provisioned" : "not provisioned"));
+    return status;
+}
+
+/*********************************************************************
+ * @fn  void wfx_clear_wifi_provision(void)
+ * @brief
+ *      Driver is clear the wifi provision
+ * @param[in]  None
+ * @return  None
+ ***********************************************************************/
+void wfx_clear_wifi_provision(void)
+{
+    memset(&wfx_rsi.sec, 0, sizeof(wfx_rsi.sec));
+    wfx_rsi.dev_state &= ~WFX_RSI_ST_STA_PROVISIONED;
+    WFX_RSI_LOG("%s: completed.", __func__);
+}
+
+/*************************************************************************
+ * @fn sl_status_t wfx_connect_to_ap(void)
+ * @brief
+ * Start a JOIN command to the AP - Done by the wfx_rsi task
+ * @param[in]   None
+ * @return  returns SL_STATUS_OK if successful,
+ *         SL_STATUS_INVALID_CONFIGURATION otherwise
+ ****************************************************************************/
+sl_status_t wfx_connect_to_ap(void)
+{
+    if (wfx_rsi.dev_state & WFX_RSI_ST_STA_PROVISIONED)
+    {
+        WFX_RSI_LOG("%s: connecting to access point -> SSID: %s, PSK:%s", __func__, &wfx_rsi.sec.ssid[0], &wfx_rsi.sec.passkey[0]);
+        xEventGroupSetBits(wfx_rsi.events, WFX_EVT_STA_START_JOIN);
+    }
+    else
+    {
+        WFX_RSI_LOG("%s: error: access point not provisioned", __func__);
+        return SL_STATUS_INVALID_CONFIGURATION;
+    }
+    return SL_STATUS_OK;
+}
+
+/*********************************************************************
+ * @fn  void wfx_setup_ip6_link_local(sl_wfx_interface_t whichif)
+ * @brief
+ *      Implement the ipv6 setup
+ * @param[in]  whichif:
+ * @return  None
+ ***********************************************************************/
+void wfx_setup_ip6_link_local(sl_wfx_interface_t whichif)
+{
+    /*
+     * TODO: Implement IPV6 setup, currently in wfx_rsi_task()
+     * This is hooked with MATTER code.
+     */
+    WFX_RSI_LOG("%s: warning: not implemented.", __func__);
+}
+
+/*********************************************************************
+ * @fn  bool wfx_is_sta_connected(void)
+ * @brief
+ *      called fuction when driver is connected to STA
+ * @param[in]  None
+ * @return  returns ture if successful,
+ *          false otherwise
+ ***********************************************************************/
+bool wfx_is_sta_connected(void)
+{
+    bool status;
+    status = (wfx_rsi.dev_state & WFX_RSI_ST_STA_CONNECTED) ? true : false;
+    WFX_RSI_LOG("%s: status: %s", __func__, (status ? "connected" : "not connected"));
+    return status;
+}
+
+/*********************************************************************
+ * @fn  wifi_mode_t wfx_get_wifi_mode()
+ * @brief
+ *      get the wifi mode
+ * @param[in]  None
+ * @return  return WIFI_MODE_NULL if successful,
+ *          WIFI_MODE_STA otherwise
+ ***********************************************************************/
+wifi_mode_t wfx_get_wifi_mode()
+{
+    if (wfx_rsi.dev_state & WFX_RSI_ST_DEV_READY)
+        return WIFI_MODE_STA;
+    return WIFI_MODE_NULL;
+}
+
+/*********************************************************************
+ * @fn  sl_status_t wfx_sta_discon(void)
+ * @brief
+ *      called fuction when STA disconnected
+ * @param[in]  None
+ * @return  return SL_STATUS_OK if successful,
+ *          SL_STATUS_FAIL otherwise
+ ***********************************************************************/
+sl_status_t wfx_sta_discon(void)
+{
+    WFX_RSI_LOG("%s: started.", __func__);
+    int32_t status;
+    status = wfx_rsi_disconnect();
+    wfx_rsi.dev_state &= ~WFX_RSI_ST_STA_CONNECTED;
+    WFX_RSI_LOG("%s: completed.", __func__);
+    return status;
+}
+#if CHIP_DEVICE_CONFIG_ENABLE_IPV4
+/*********************************************************************
+ * @fn  bool wfx_have_ipv4_addr(sl_wfx_interface_t which_if)
+ * @brief
+ *      called fuction when driver have ipv4 address
+ * @param[in]  which_if:
+ * @return  returns ture if successful,
+ *          false otherwise
+ ***********************************************************************/
+bool wfx_have_ipv4_addr(sl_wfx_interface_t which_if)
+{
+    bool status = false;
+    if (which_if == SL_WFX_STA_INTERFACE)
+    {
+        status = (wfx_rsi.dev_state & WFX_RSI_ST_STA_DHCP_DONE) ? true : false;
+    }
+    else
+    {
+        status = false; /* TODO */
+    }
+    WFX_RSI_LOG("%s: status: %d", __func__, status);
+    return status;
+}
+#endif /* CHIP_DEVICE_CONFIG_ENABLE_IPV4 */
+
+/*********************************************************************
+ * @fn  bool wfx_have_ipv6_addr(sl_wfx_interface_t which_if)
+ * @brief
+ *      called fuction when driver have ipv6 address
+ * @param[in]  which_if:
+ * @return  returns ture if successful,
+ *          false otherwise
+ ***********************************************************************/
+bool wfx_have_ipv6_addr(sl_wfx_interface_t which_if)
+{
+    bool status = false;
+    if (which_if == SL_WFX_STA_INTERFACE)
+    {
+        status = (wfx_rsi.dev_state & WFX_RSI_ST_STA_CONNECTED) ? true : false;
+    }
+    else
+    {
+        status = false; /* TODO */
+    }
+    WFX_RSI_LOG("%s: status: %d", __func__, status);
+    return status;
+}
+
+/*********************************************************************
+ * @fn  bool wfx_hw_ready(void)
+ * @brief
+ *      called fuction when driver ready
+ * @param[in]  None
+ * @return  returns ture if successful,
+ *          false otherwise
+ ***********************************************************************/
+bool wfx_hw_ready(void)
+{
+    return (wfx_rsi.dev_state & WFX_RSI_ST_DEV_READY) ? true : false;
+}
+
+/*********************************************************************
+ * @fn  int32_t wfx_get_ap_info(wfx_wifi_scan_result_t *ap)
+ * @brief
+ *      get the access point information
+ * @param[in]  ap: access point
+ * @return
+ *      access point information
+ ***********************************************************************/
+int32_t wfx_get_ap_info(wfx_wifi_scan_result_t * ap)
+{
+    return wfx_rsi_get_ap_info(ap);
+}
+
+/*********************************************************************
+ * @fn   int32_t wfx_get_ap_ext(wfx_wifi_scan_ext_t *extra_info)
+ * @brief
+ *      get the access point extra information
+ * @param[in]  extra_info:access point extra information
+ * @return
+ *      access point extra information
+ ***********************************************************************/
+int32_t wfx_get_ap_ext(wfx_wifi_scan_ext_t * extra_info)
+{
+    return wfx_rsi_get_ap_ext(extra_info);
+}
+
+/***************************************************************************
+ * @fn   int32_t wfx_reset_counts(){
+ * @brief
+ *      get the driver reset count
+ * @param[in]  None
+ * @return
+ *      reset count
+ *****************************************************************************/
+int32_t wfx_reset_counts()
+{
+    return wfx_rsi_reset_count();
+}
+
+#ifdef SL_WFX_CONFIG_SCAN
+/*******************************************************************************
+ * @fn   bool wfx_start_scan(char *ssid, void (*callback)(wfx_wifi_scan_result_t *))
+ * @brief
+ *       called fuction when driver start scaning
+ * @param[in]  ssid:
+ * @return returns ture if successful,
+ *          false otherwise
+ *******************************************************************************/
+bool wfx_start_scan(char * ssid, void (*callback)(wfx_wifi_scan_result_t *))
+{
+    int sz;
+
+    if (wfx_rsi.scan_cb)
+        return false; /* Already in progress */
+    if (ssid)
+    {
+        sz = strlen(ssid);
+        if ((wfx_rsi.scan_ssid = (char *) pvPortMalloc(sz + 1)) == (char *) 0)
+        {
+            return false;
+        }
+        strcpy(wfx_rsi.scan_ssid, ssid);
+    }
+    wfx_rsi.scan_cb = callback;
+    xEventGroupSetBits(wfx_rsi.events, WFX_EVT_SCAN);
+
+    return true;
+}
+
+/***************************************************************************
+ * @fn   void wfx_cancel_scan(void)
+ * @brief
+ *      called function when driver cancel scaning
+ * @param[in]  None
+ * @return
+ *      None
+ *****************************************************************************/
+void wfx_cancel_scan(void)
+{
+    /* Not possible */
+    WFX_RSI_LOG("%s: cannot cancel scan", __func__);
+}
+#endif /* SL_WFX_CONFIG_SCAN */
diff --git a/examples/platform/silabs/SiWx917/rs911x/wfx_rsidev.c b/examples/platform/silabs/SiWx917/rs911x/wfx_rsidev.c
new file mode 100644
index 0000000..8d8a3c1
--- /dev/null
+++ b/examples/platform/silabs/SiWx917/rs911x/wfx_rsidev.c
@@ -0,0 +1,272 @@
+/*
+ *
+ *    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.
+ */
+
+#ifdef _WFX_NOT_USED_USING_HAL_INSTEAD_
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "em_bus.h"
+#include "em_cmu.h"
+#include "em_gpio.h"
+#include "em_ldma.h"
+#include "em_usart.h"
+#include "gpiointerrupt.h"
+
+/* Need Lwip stuff before rsi is included */
+#include "wfx_host_events.h"
+
+#include "FreeRTOS.h"
+#include "event_groups.h"
+#include "rsi_common_apis.h"
+#include "rsi_data_types.h"
+#include "rsi_error.h"
+#include "rsi_nwk.h"
+#include "rsi_socket.h"
+#include "rsi_utils.h"
+#include "rsi_wlan.h"
+#include "rsi_wlan_apis.h"
+#include "rsi_wlan_config.h"
+#include "task.h"
+
+#include "wfx_host_pinout.h"
+#include "wfx_rsi.h"
+
+/* The following stuff comes from hal/rsi_hal_mcu_interrupt.c */
+static void (*rsi_intr_cb)(void);
+/*********************************************************************
+ * @fn  void rsi_hal_intr_config(void (*rsi_interrupt_handler)(void))
+ * @brief
+ *      get the hal intr configuration
+ * @param[in]  rsi_interrupt_handler:
+ * @return
+ *      None
+ ***********************************************************************/
+void rsi_hal_intr_config(void (*rsi_interrupt_handler)(void))
+{
+    rsi_intr_cb = rsi_interrupt_handler;
+}
+
+/***********************************************************************
+ * @fn  static void wfx_spi_wakeup_irq_callback(uint8_t irqNumber)
+ * @brief
+ *       end of stuff from hal/rsi_hal_mcu_interrupt.c
+ * @param[in]  irqNumber:
+ * @return  None
+ * **********************************************************************/
+static void wfx_spi_wakeup_irq_callback(uint8_t irqNumber)
+{
+    BaseType_t bus_task_woken;
+    uint32_t interrupt_mask;
+
+    if (irqNumber != SL_WFX_HOST_PINOUT_SPI_IRQ)
+        return;
+    // Get and clear all pending GPIO interrupts
+    interrupt_mask = GPIO_IntGet();
+    GPIO_IntClear(interrupt_mask);
+    if (rsi_intr_cb)
+        (*rsi_intr_cb)();
+}
+
+/***********************************************************************
+ * @fn   static void wfx_host_gpio_init(void)
+ * @brief
+ *       function called when host gpio intialization
+ * @param[in]  None
+ * @return  None
+ * **********************************************************************/
+static void wfx_host_gpio_init(void)
+{
+    // Enable GPIO clock.
+    CMU_ClockEnable(cmuClock_GPIO, true);
+
+    // Configure WF200 reset pin.
+    GPIO_PinModeSet(SL_WFX_HOST_PINOUT_RESET_PORT, SL_WFX_HOST_PINOUT_RESET_PIN, gpioModePushPull, PINOUT_CLEAR);
+    // Configure WF200 WUP pin.
+    GPIO_PinModeSet(SL_WFX_HOST_PINOUT_WUP_PORT, SL_WFX_HOST_PINOUT_WUP_PIN, gpioModePushPull, PINOUT_CLEAR);
+
+    // GPIO used as IRQ.
+    GPIO_PinModeSet(SL_WFX_HOST_PINOUT_SPI_WIRQ_PORT, SL_WFX_HOST_PINOUT_SPI_WIRQ_PIN, gpioModeInputPull, PINOUT_CLEAR);
+    CMU_OscillatorEnable(cmuOsc_LFXO, true, true);
+
+    // Set up interrupt based callback function - trigger on both edges.
+    GPIOINT_Init();
+    GPIO_ExtIntConfig(SL_WFX_HOST_PINOUT_SPI_WIRQ_PORT, SL_WFX_HOST_PINOUT_SPI_WIRQ_PIN, SL_WFX_HOST_PINOUT_SPI_IRQ, true, false,
+                      true);
+    GPIOINT_CallbackRegister(SL_WFX_HOST_PINOUT_SPI_IRQ, wfx_spi_wakeup_irq_callback);
+
+    // Change GPIO interrupt priority (FreeRTOS asserts unless this is done here!)
+    NVIC_SetPriority(GPIO_EVEN_IRQn, WFX_GPIO_NVIC_PRIORITY);
+    NVIC_SetPriority(GPIO_ODD_IRQn, WFX_GPIO_NVIC_PRIORITY);
+}
+
+#define USART SL_WFX_HOST_PINOUT_SPI_PERIPHERAL
+
+/***********************************************************************
+ * @fn   static int sl_wfx_host_spi_set_config(void *usart)
+ * @brief
+ *       set the configuration of spi
+ * @param[in]  usart:
+ * @return  returns 0 if successful,
+ *         -1 otherwise
+ * **********************************************************************/
+static int sl_wfx_host_spi_set_config(void * usart)
+{
+    int ret = -1;
+
+    if (0)
+    {
+#if defined(USART0)
+    }
+    else if (usart == USART0)
+    {
+        usart_clock     = cmuClock_USART0;
+        usart_tx_signal = dmadrvPeripheralSignal_USART0_TXBL;
+        usart_rx_signal = dmadrvPeripheralSignal_USART0_RXDATAV;
+        ret             = 0;
+#endif
+#if defined(USART1)
+    }
+    else if (usart == USART1)
+    {
+        usart_clock     = cmuClock_USART1;
+        usart_tx_signal = dmadrvPeripheralSignal_USART1_TXBL;
+        usart_rx_signal = dmadrvPeripheralSignal_USART1_RXDATAV;
+        ret             = 0;
+#endif
+#if defined(USART2)
+    }
+    else if (usart == USART2)
+    {
+        usart_clock     = cmuClock_USART2;
+        usart_tx_signal = dmadrvPeripheralSignal_USART2_TXBL;
+        usart_rx_signal = dmadrvPeripheralSignal_USART2_RXDATAV;
+        ret             = 0;
+#endif
+#if defined(USART3)
+    }
+    else if (usart == USART3)
+    {
+        usart_clock     = cmuClock_USART3;
+        usart_tx_signal = dmadrvPeripheralSignal_USART3_TXBL;
+        usart_rx_signal = dmadrvPeripheralSignal_USART3_RXDATAV;
+        ret             = 0;
+#endif
+#if defined(USART4)
+    }
+    else if (usart == USART4)
+    {
+        usart_clock     = cmuClock_USART4;
+        usart_tx_signal = dmadrvPeripheralSignal_USART4_TXBL;
+        usart_rx_signal = dmadrvPeripheralSignal_USART4_RXDATAV;
+        ret             = 0;
+#endif
+#if defined(USART5)
+    }
+    else if (usart == USART5)
+    {
+        usart_clock     = cmuClock_USART5;
+        usart_tx_signal = dmadrvPeripheralSignal_USART5_TXBL;
+        usart_rx_signal = dmadrvPeripheralSignal_USART5_RXDATAV;
+        ret             = 0;
+#endif
+#if defined(USARTRF0)
+    }
+    else if (usart == USARTRF0)
+    {
+        usart_clock     = cmuClock_USARTRF0;
+        usart_tx_signal = dmadrvPeripheralSignal_USARTRF0_TXBL;
+        usart_rx_signal = dmadrvPeripheralSignal_USARTRF0_RXDATAV;
+        ret             = 0;
+#endif
+#if defined(USARTRF1)
+    }
+    else if (usart == USARTRF1)
+    {
+        usart_clock     = cmuClock_USARTRF1;
+        usart_tx_signal = dmadrvPeripheralSignal_USARTRF1_TXBL;
+        usart_rx_signal = dmadrvPeripheralSignal_USARTRF1_RXDATAV;
+        ret             = 0;
+#endif
+    }
+
+    return ret;
+}
+
+/****************************************************************************
+ * @fn  sl_status_t sl_wfx_host_init_bus(void)
+ * @brief
+ * Initialize SPI peripheral
+ * @param[in] None
+ * @return  returns SL_STATUS_OK if successful,
+ *        SL_STATUS_FAIL otherwise
+ *****************************************************************************/
+sl_status_t sl_wfx_host_init_bus(void)
+{
+    int res;
+
+    // Initialize and enable the USART
+    USART_InitSync_TypeDef usartInit = USART_INITSYNC_DEFAULT;
+
+    res = sl_wfx_host_spi_set_config(USART);
+    if (res != SPI_CONFIG_SUCCESS)
+    {
+        return SL_STATUS_FAIL;
+    }
+
+    spi_enabled        = true;
+    dummy_tx_data      = 0;
+    usartInit.baudrate = 36000000u;
+    usartInit.msbf     = true;
+    CMU_ClockEnable(cmuClock_HFPER, true);
+    CMU_ClockEnable(cmuClock_GPIO, true);
+    CMU_ClockEnable(usart_clock, true);
+    USART_InitSync(USART, &usartInit);
+    USART->CTRL |= (1u << _USART_CTRL_SMSDELAY_SHIFT);
+    USART->ROUTELOC0 =
+        (USART->ROUTELOC0 & ~(_USART_ROUTELOC0_TXLOC_MASK | _USART_ROUTELOC0_RXLOC_MASK | _USART_ROUTELOC0_CLKLOC_MASK)) |
+        (SL_WFX_HOST_PINOUT_SPI_TX_LOC << _USART_ROUTELOC0_TXLOC_SHIFT) |
+        (SL_WFX_HOST_PINOUT_SPI_RX_LOC << _USART_ROUTELOC0_RXLOC_SHIFT) |
+        (SL_WFX_HOST_PINOUT_SPI_CLK_LOC << _USART_ROUTELOC0_CLKLOC_SHIFT);
+
+    USART->ROUTEPEN = USART_ROUTEPEN_TXPEN | USART_ROUTEPEN_RXPEN | USART_ROUTEPEN_CLKPEN;
+    GPIO_DriveStrengthSet(SL_WFX_HOST_PINOUT_SPI_CLK_PORT, gpioDriveStrengthStrongAlternateStrong);
+    GPIO_PinModeSet(SL_WFX_HOST_PINOUT_SPI_TX_PORT, SL_WFX_HOST_PINOUT_SPI_TX_PIN, gpioModePushPull, PINOUT_CLEAR);
+    GPIO_PinModeSet(SL_WFX_HOST_PINOUT_SPI_RX_PORT, SL_WFX_HOST_PINOUT_SPI_RX_PIN, gpioModeInput, PINOUT_CLEAR);
+    GPIO_PinModeSet(SL_WFX_HOST_PINOUT_SPI_CLK_PORT, SL_WFX_HOST_PINOUT_SPI_CLK_PIN, gpioModePushPull, PINOUT_CLEAR);
+
+    DMADRV_Init();
+    DMADRV_AllocateChannel(&tx_dma_channel, NULL);
+    DMADRV_AllocateChannel(&rx_dma_channel, NULL);
+    GPIO_PinModeSet(SL_WFX_HOST_PINOUT_SPI_CS_PORT, SL_WFX_HOST_PINOUT_SPI_CS_PIN, gpioModePushPull, PINOUT_SET);
+    USART->CMD = USART_CMD_CLEARRX | USART_CMD_CLEARTX;
+
+    return SL_STATUS_OK;
+}
+
+/***********************************************************************
+ * @fn   void wfx_rsidev_init(void)
+ * @brief
+ *       function called when driver rsidev intialization
+ * @param[in]  None
+ * @return  None
+ * **********************************************************************/
+void wfx_rsidev_init(void)
+{
+    wfx_host_gpio_init();
+}
+#endif /* _NOT_USED */
diff --git a/examples/platform/silabs/SiWx917/uart.cpp b/examples/platform/silabs/SiWx917/uart.cpp
new file mode 100644
index 0000000..76dbca2
--- /dev/null
+++ b/examples/platform/silabs/SiWx917/uart.cpp
@@ -0,0 +1,343 @@
+/*
+ *
+ *    Copyright (c) 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.
+ */
+#include "AppConfig.h"
+#include "matter_shell.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+#include "assert.h"
+#include "em_core.h"
+#include "em_usart.h"
+#include "sl_board_control.h"
+#include "sl_uartdrv_instances.h"
+#if (defined(EFR32MG24) || defined(MGM24))
+#include "sl_uartdrv_eusart_vcom_config.h"
+#else
+#include "sl_uartdrv_usart_vcom_config.h"
+#endif // EFR32MG24
+#include "uart.h"
+#include "uartdrv.h"
+#include <stddef.h>
+#include <string.h>
+
+#if defined(SL_CATALOG_POWER_MANAGER_PRESENT)
+#include "sl_power_manager.h"
+#endif
+
+#if !defined(MIN)
+#define MIN(A, B) ((A) < (B) ? (A) : (B))
+#endif
+
+#if (defined(EFR32MG24) || defined(MGM24))
+#define HELPER1(x) EUSART##x##_RX_IRQn
+#else
+#define HELPER1(x) USART##x##_RX_IRQn
+#endif
+
+#define HELPER2(x) HELPER1(x)
+
+#if (defined(EFR32MG24) || defined(MGM24))
+#define HELPER3(x) EUSART##x##_RX_IRQHandler
+#else
+#define HELPER3(x) USART##x##_RX_IRQHandler
+#endif
+
+#define HELPER4(x) HELPER3(x)
+
+// On MG24 boards VCOM runs on the EUSART device, MG12 uses the UART device
+#if (defined(EFR32MG24) || defined(MGM24))
+#define USART_IRQ HELPER2(SL_UARTDRV_EUSART_VCOM_PERIPHERAL_NO)
+#define USART_IRQHandler HELPER4(SL_UARTDRV_EUSART_VCOM_PERIPHERAL_NO)
+#define vcom_handle sl_uartdrv_eusart_vcom_handle
+#else
+#define USART_IRQ HELPER2(SL_UARTDRV_USART_VCOM_PERIPHERAL_NO)
+#define USART_IRQHandler HELPER4(SL_UARTDRV_USART_VCOM_PERIPHERAL_NO)
+#define vcom_handle sl_uartdrv_usart_vcom_handle
+#endif // EFR32MG24
+
+typedef struct
+{
+    // The data buffer
+    uint8_t * pBuffer;
+    // The offset of the first item written to the list.
+    volatile uint16_t Head;
+    // The offset of the next item to be written to the list.
+    volatile uint16_t Tail;
+    // Maxium size of data that can be hold in buffer before overwriting
+    uint16_t MaxSize;
+} Fifo_t;
+
+#define UART_CONSOLE_ERR -1 // Negative value in case of UART Console action failed. Triggers a failure for PW_RPC
+#define MAX_BUFFER_SIZE 256
+#define MAX_DMA_BUFFER_SIZE (MAX_BUFFER_SIZE / 2)
+// In order to reduce the probability of data loss during the dmaFull callback handler we use
+// two duplicate receive buffers so we can always have one "active" receive queue.
+static uint8_t sRxDmaBuffer[MAX_DMA_BUFFER_SIZE];
+static uint8_t sRxDmaBuffer2[MAX_DMA_BUFFER_SIZE];
+static uint16_t lastCount; // Nb of bytes already processed from the active dmaBuffer
+
+// Rx buffer for the receive Fifo
+static uint8_t sRxFifoBuffer[MAX_BUFFER_SIZE];
+static Fifo_t sReceiveFifo;
+
+static void UART_rx_callback(UARTDRV_Handle_t handle, Ecode_t transferStatus, uint8_t * data, UARTDRV_Count_t transferCount);
+
+static bool InitFifo(Fifo_t * fifo, uint8_t * pDataBuffer, uint16_t bufferSize)
+{
+    if (fifo == NULL || pDataBuffer == NULL)
+    {
+        return false;
+    }
+
+    fifo->pBuffer = pDataBuffer;
+    fifo->MaxSize = bufferSize;
+    fifo->Tail = fifo->Head = 0;
+
+    return true;
+}
+
+/*
+ *   @brief Get the amount of unprocessed bytes in the fifo buffer
+ *   @param Ptr to the fifo
+ *   @return Nb of "unread" bytes available in the fifo
+ */
+static uint16_t AvailableDataCount(Fifo_t * fifo)
+{
+    uint16_t size = 0;
+
+    // if equal there is no data return 0 directly
+    if (fifo->Tail != fifo->Head)
+    {
+        // determine if a wrap around occurred to get the right data size available.
+        size = (fifo->Tail < fifo->Head) ? (fifo->MaxSize - fifo->Head + fifo->Tail) : (fifo->Tail - fifo->Head);
+    }
+
+    return size;
+}
+
+/*
+ *   @brief Get the available space in the fifo buffer to insert new data
+ *   @param Ptr to the fifo
+ *   @return Nb of free bytes left in te buffer
+ */
+static uint16_t RemainingSpace(Fifo_t * fifo)
+{
+    return fifo->MaxSize - AvailableDataCount(fifo);
+}
+
+/*
+ *   @brief Write data in the fifo as a circular buffer
+ *   @param Ptr to the fifo, ptr of the data to write, nb of bytes to write
+ */
+static void WriteToFifo(Fifo_t * fifo, uint8_t * pDataToWrite, uint16_t SizeToWrite)
+{
+    assert(fifo);
+    assert(pDataToWrite);
+    assert(SizeToWrite <= fifo->MaxSize);
+
+    // Overwrite is not allowed
+    if (RemainingSpace(fifo) >= SizeToWrite)
+    {
+        uint16_t nBytesBeforWrap = (fifo->MaxSize - fifo->Tail);
+        if (SizeToWrite > nBytesBeforWrap)
+        {
+            // The number of bytes to write is bigger than the remaining bytes
+            // in the buffer, we have to wrap around
+            memcpy(fifo->pBuffer + fifo->Tail, pDataToWrite, nBytesBeforWrap);
+            memcpy(fifo->pBuffer, pDataToWrite + nBytesBeforWrap, SizeToWrite - nBytesBeforWrap);
+        }
+        else
+        {
+            memcpy(fifo->pBuffer + fifo->Tail, pDataToWrite, SizeToWrite);
+        }
+
+        fifo->Tail = (fifo->Tail + SizeToWrite) % fifo->MaxSize; // increment tail with wraparound
+    }
+}
+
+/*
+ *   @brief Write data in the fifo as a circular buffer
+ *   @param Ptr to the fifo, ptr to contain the data to process, nb of bytes to pull from the fifo
+ *   @return Nb of bytes that were retrieved.
+ */
+static uint8_t RetrieveFromFifo(Fifo_t * fifo, uint8_t * pData, uint16_t SizeToRead)
+{
+    assert(fifo);
+    assert(pData);
+    assert(SizeToRead <= fifo->MaxSize);
+
+    uint16_t ReadSize        = MIN(SizeToRead, AvailableDataCount(fifo));
+    uint16_t nBytesBeforWrap = (fifo->MaxSize - fifo->Head);
+
+    if (ReadSize > nBytesBeforWrap)
+    {
+        memcpy(pData, fifo->pBuffer + fifo->Head, nBytesBeforWrap);
+        memcpy(pData + nBytesBeforWrap, fifo->pBuffer, ReadSize - nBytesBeforWrap);
+    }
+    else
+    {
+        memcpy(pData, (fifo->pBuffer + fifo->Head), ReadSize);
+    }
+
+    fifo->Head = (fifo->Head + ReadSize) % fifo->MaxSize; // increment tail with wraparound
+
+    return ReadSize;
+}
+
+/*
+ *   @brief Init the the UART for serial communication, Start DMA reception
+ *          and init Fifo to handle the received data from this uart
+ *
+ *   @Note This UART is used for pigweed rpc
+ */
+void uartConsoleInit(void)
+{
+    sl_board_enable_vcom();
+    // Init a fifo for the data received on the uart
+    InitFifo(&sReceiveFifo, sRxFifoBuffer, MAX_BUFFER_SIZE);
+
+    // Activate 2 dma queues to always have one active
+
+    UARTDRV_Receive(vcom_handle, sRxDmaBuffer, MAX_DMA_BUFFER_SIZE, UART_rx_callback);
+    UARTDRV_Receive(vcom_handle, sRxDmaBuffer2, MAX_DMA_BUFFER_SIZE, UART_rx_callback);
+
+    // Enable USART0/EUSART0 interrupt to wake OT task when data arrives
+    NVIC_ClearPendingIRQ(USART_IRQ);
+    NVIC_EnableIRQ(USART_IRQ);
+
+#if (defined(EFR32MG24) || defined(MGM24))
+    // Clear previous RX interrupts
+    EUSART_IntClear(SL_UARTDRV_EUSART_VCOM_PERIPHERAL, EUSART_IF_RXFL);
+
+    // Enable RX interrupts
+    EUSART_IntEnable(SL_UARTDRV_EUSART_VCOM_PERIPHERAL, EUSART_IF_RXFL);
+
+    // Enable EUSART
+    EUSART_Enable(SL_UARTDRV_EUSART_VCOM_PERIPHERAL, eusartEnable);
+#else
+    USART_IntEnable(SL_UARTDRV_USART_VCOM_PERIPHERAL, USART_IF_RXDATAV);
+#endif // EFR32MG24
+}
+
+void USART_IRQHandler(void)
+{
+#ifdef ENABLE_CHIP_SHELL
+    chip::NotifyShellProcessFromISR();
+#endif
+#if defined(SL_WIFI)
+    /* TODO */
+#elif !defined(PW_RPC_ENABLED)
+    otSysEventSignalPending();
+#endif
+
+#if (defined(EFR32MG24) || defined(MGM24))
+    EUSART_IntClear(SL_UARTDRV_EUSART_VCOM_PERIPHERAL, EUSART_IF_RXFL);
+#endif
+}
+
+/*
+ *   @brief Callback triggered when a UARTDRV DMA buffer is full
+ */
+static void UART_rx_callback(UARTDRV_Handle_t handle, Ecode_t transferStatus, uint8_t * data, UARTDRV_Count_t transferCount)
+{
+    (void) transferStatus;
+
+    uint8_t writeSize = (transferCount - lastCount);
+    if (RemainingSpace(&sReceiveFifo) >= writeSize)
+    {
+        WriteToFifo(&sReceiveFifo, data + lastCount, writeSize);
+        lastCount = 0;
+    }
+
+    UARTDRV_Receive(vcom_handle, data, transferCount, UART_rx_callback);
+
+#ifdef ENABLE_CHIP_SHELL
+    chip::NotifyShellProcessFromISR();
+#endif
+#if defined(SL_WIFI)
+    /* TODO */
+#elif !defined(PW_RPC_ENABLED)
+    otSysEventSignalPending();
+#endif
+}
+
+/*
+ *   @brief Read the data available from the console Uart
+ *   @param Buffer that contains the data to write, number bytes to write.
+ *   @return Amount of bytes written or ERROR (-1)
+ */
+int16_t uartConsoleWrite(const char * Buf, uint16_t BufLength)
+{
+    if (Buf == NULL || BufLength < 1)
+    {
+        return UART_CONSOLE_ERR;
+    }
+
+#if defined(SL_CATALOG_POWER_MANAGER_PRESENT)
+    sl_power_manager_add_em_requirement(SL_POWER_MANAGER_EM1);
+#endif
+
+    // Use of ForceTransmit here. Transmit with DMA was causing errors with PW_RPC
+    // TODO Use DMA and find/fix what causes the issue with PW
+    if (UARTDRV_ForceTransmit(vcom_handle, (uint8_t *) Buf, BufLength) == ECODE_EMDRV_UARTDRV_OK)
+    {
+#if defined(SL_CATALOG_POWER_MANAGER_PRESENT)
+        sl_power_manager_remove_em_requirement(SL_POWER_MANAGER_EM1);
+#endif
+        return BufLength;
+    }
+
+#if defined(SL_CATALOG_POWER_MANAGER_PRESENT)
+    sl_power_manager_remove_em_requirement(SL_POWER_MANAGER_EM1);
+#endif
+
+    return UART_CONSOLE_ERR;
+}
+
+/*
+ *   @brief Read the data available from the console Uart
+ *   @param Buffer for the data to be read, number bytes to read.
+ *   @return Amount of bytes that was read from the rx fifo or ERROR (-1)
+ */
+int16_t uartConsoleRead(char * Buf, uint16_t NbBytesToRead)
+{
+    uint8_t * data;
+    UARTDRV_Count_t count, remaining;
+
+    if (Buf == NULL || NbBytesToRead < 1)
+    {
+        return UART_CONSOLE_ERR;
+    }
+
+    if (NbBytesToRead > AvailableDataCount(&sReceiveFifo))
+    {
+        // Not enough data available in the fifo for the read size request
+        // If there is data available in dma buffer, get it now.
+        CORE_ATOMIC_SECTION(UARTDRV_GetReceiveStatus(vcom_handle, &data, &count, &remaining); if (count > lastCount) {
+            WriteToFifo(&sReceiveFifo, data + lastCount, count - lastCount);
+            lastCount = count;
+        })
+    }
+
+    return (int16_t) RetrieveFromFifo(&sReceiveFifo, (uint8_t *) Buf, NbBytesToRead);
+}
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/examples/platform/silabs/SiWx917/uart.h b/examples/platform/silabs/SiWx917/uart.h
new file mode 100644
index 0000000..f708030
--- /dev/null
+++ b/examples/platform/silabs/SiWx917/uart.h
@@ -0,0 +1,40 @@
+/*
+ *
+ *    Copyright (c) 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.
+ */
+
+#pragma once
+
+#include <stdint.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+void uartConsoleInit(void);
+int16_t uartConsoleWrite(const char * Buf, uint16_t BufLength);
+int16_t uartConsoleRead(char * Buf, uint16_t NbBytesToRead);
+
+// Implemented by in openthread code
+#ifndef PW_RPC_ENABLED
+extern void otPlatUartReceived(const uint8_t * aBuf, uint16_t aBufLength);
+extern void otPlatUartSendDone(void);
+extern void otSysEventSignalPending(void);
+#endif
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
diff --git a/examples/platform/silabs/SiWx917/wf200/efr_spi.c b/examples/platform/silabs/SiWx917/wf200/efr_spi.c
new file mode 100644
index 0000000..fb35093
--- /dev/null
+++ b/examples/platform/silabs/SiWx917/wf200/efr_spi.c
@@ -0,0 +1,426 @@
+/*
+ *
+ *    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 "sl_wfx_configuration_defaults.h"
+
+#include "sl_wfx.h"
+#include "sl_wfx_board.h"
+#include "sl_wfx_host_api.h"
+
+#include "dmadrv.h"
+#include "em_bus.h"
+#include "em_cmu.h"
+#include "em_gpio.h"
+#include "em_ldma.h"
+#include "em_usart.h"
+#include "spidrv.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "FreeRTOS.h"
+#include "semphr.h"
+#ifdef SLEEP_ENABLED
+#include "sl_power_manager.h"
+#endif
+#include "AppConfig.h"
+
+#include "gpiointerrupt.h"
+
+#include "sl_spidrv_exp_config.h"
+#include "sl_wfx_board.h"
+#include "sl_wfx_host.h"
+#include "sl_wfx_task.h"
+#include "wfx_host_events.h"
+
+extern SPIDRV_Handle_t sl_spidrv_exp_handle;
+
+#define USART SL_WFX_HOST_PINOUT_SPI_PERIPHERAL
+
+StaticSemaphore_t xEfrSpiSemaBuffer;
+static SemaphoreHandle_t spi_sem;
+
+static unsigned int tx_dma_channel;
+static unsigned int rx_dma_channel;
+
+static uint32_t dummy_rx_data;
+static uint32_t dummy_tx_data;
+static bool spi_enabled = false;
+
+#if defined(EFR32MG12)
+uint8_t wirq_irq_nb = SL_WFX_HOST_PINOUT_SPI_IRQ;
+#elif defined(EFR32MG24)
+uint8_t wirq_irq_nb = SL_WFX_HOST_PINOUT_SPI_WIRQ_PIN; // SL_WFX_HOST_PINOUT_SPI_WIRQ_PIN;
+#endif
+
+#define PIN_OUT_SET 1
+#define PIN_OUT_CLEAR 0
+
+/****************************************************************************
+ * @fn  sl_status_t sl_wfx_host_init_bus(void)
+ * @brief
+ *  Initialize SPI peripheral
+ * @param[in] None
+ * @return returns SL_STATUS_OK
+ *****************************************************************************/
+sl_status_t sl_wfx_host_init_bus(void)
+{
+    spi_enabled = true;
+
+    /* Assign allocated DMA channel */
+    tx_dma_channel = sl_spidrv_exp_handle->txDMACh;
+    rx_dma_channel = sl_spidrv_exp_handle->rxDMACh;
+
+    /*
+     * Route EUSART1 MOSI, MISO, and SCLK to the specified pins.  CS is
+     * not controlled by EUSART so there is no write to the corresponding
+     * EUSARTROUTE register to do this.
+     */
+    MY_USART->CTRL |= (1u << _USART_CTRL_SMSDELAY_SHIFT);
+
+#if defined(EFR32MG12)
+    MY_USART->ROUTEPEN = USART_ROUTEPEN_TXPEN | USART_ROUTEPEN_RXPEN | USART_ROUTEPEN_CLKPEN;
+#endif
+
+#if defined(EFR32MG24)
+    GPIO->USARTROUTE[0].ROUTEEN = GPIO_USART_ROUTEEN_RXPEN | // MISO
+        GPIO_USART_ROUTEEN_TXPEN |                           // MOSI
+        GPIO_USART_ROUTEEN_CLKPEN;
+#endif
+
+    spi_sem = xSemaphoreCreateBinaryStatic(&xEfrSpiSemaBuffer);
+    xSemaphoreGive(spi_sem);
+
+    return SL_STATUS_OK;
+}
+
+/****************************************************************************
+ * @fn  sl_status_t sl_wfx_host_deinit_bus(void)
+ * @brief
+ *     De-initialize SPI peripheral and DMAs
+ * @param[in] None
+ * @return returns SL_STATUS_OK
+ *****************************************************************************/
+sl_status_t sl_wfx_host_deinit_bus(void)
+{
+    vSemaphoreDelete(spi_sem);
+    // Stop DMAs.
+    DMADRV_StopTransfer(rx_dma_channel);
+    DMADRV_StopTransfer(tx_dma_channel);
+    DMADRV_FreeChannel(tx_dma_channel);
+    DMADRV_FreeChannel(rx_dma_channel);
+    DMADRV_DeInit();
+    USART_Reset(MY_USART);
+    return SL_STATUS_OK;
+}
+
+/****************************************************************************
+ * @fn  sl_status_t sl_wfx_host_spi_cs_assert()
+ * @brief
+ *     Assert chip select.
+ * @param[in] None
+ * @return returns SL_STATUS_OK
+ *****************************************************************************/
+sl_status_t sl_wfx_host_spi_cs_assert()
+{
+    GPIO_PinOutClear(SL_SPIDRV_EXP_CS_PORT, SL_SPIDRV_EXP_CS_PIN);
+    return SL_STATUS_OK;
+}
+
+/****************************************************************************
+ * @fn  sl_status_t sl_wfx_host_spi_cs_deassert()
+ * @brief
+ *     De-Assert chip select.
+ * @param[in] None
+ * @return returns SL_STATUS_OK
+ *****************************************************************************/
+sl_status_t sl_wfx_host_spi_cs_deassert()
+{
+    GPIO_PinOutSet(SL_SPIDRV_EXP_CS_PORT, SL_SPIDRV_EXP_CS_PIN);
+    return SL_STATUS_OK;
+}
+
+/****************************************************************************
+ * @fn  static bool rx_dma_complete(unsigned int channel, unsigned int sequenceNo, void *userParam)
+ * @brief
+ *     function called when the DMA complete
+ * @param[in] channel:
+ * @param[in]  sequenceNo: sequence number
+ * @param[in]  userParam: user parameter
+ * @return returns true if suucessful,
+ *          false otherwise
+ *****************************************************************************/
+static bool rx_dma_complete(unsigned int channel, unsigned int sequenceNo, void * userParam)
+{
+    (void) channel;
+    (void) sequenceNo;
+    (void) userParam;
+
+    BaseType_t xHigherPriorityTaskWoken = pdFALSE;
+    xSemaphoreGiveFromISR(spi_sem, &xHigherPriorityTaskWoken);
+    portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
+
+    return true;
+}
+
+/****************************************************************************
+ * @fn   void receiveDMA(uint8_t *buffer, uint16_t buffer_length)
+ * @brief
+ *     start receive DMA
+ * @param[in]  buffer:
+ * @param[in]  buffer_length:
+ * @return  None
+ *****************************************************************************/
+void receiveDMA(uint8_t * buffer, uint16_t buffer_length)
+{
+    // Start receive DMA.
+    DMADRV_PeripheralMemory(rx_dma_channel, MY_USART_RX_SIGNAL, (void *) buffer, (void *) &(MY_USART->RXDATA), true, buffer_length,
+                            dmadrvDataSize1, rx_dma_complete, NULL);
+
+    // Start transmit DMA.
+    DMADRV_MemoryPeripheral(tx_dma_channel, MY_USART_TX_SIGNAL, (void *) &(MY_USART->TXDATA), (void *) &(dummy_tx_data), false,
+                            buffer_length, dmadrvDataSize1, NULL, NULL);
+}
+
+/****************************************************************************
+ * @fn   void transmitDMA(uint8_t *buffer, uint16_t buffer_length)
+ * @brief
+ *     start  transmit DMA
+ * @param[in]  buffer:
+ * @param[in]  buffer_length:
+ * @return  None
+ *****************************************************************************/
+void transmitDMA(uint8_t * buffer, uint16_t buffer_length)
+{
+    // Receive DMA runs only to initiate callback
+    // Start receive DMA.
+    DMADRV_PeripheralMemory(rx_dma_channel, MY_USART_RX_SIGNAL, &dummy_rx_data, (void *) &(MY_USART->RXDATA), false, buffer_length,
+                            dmadrvDataSize1, rx_dma_complete, NULL);
+    // Start transmit DMA.
+    DMADRV_MemoryPeripheral(tx_dma_channel, MY_USART_TX_SIGNAL, (void *) &(MY_USART->TXDATA), (void *) buffer, true, buffer_length,
+                            dmadrvDataSize1, NULL, NULL);
+}
+
+/****************************************************************************
+ * @fn  sl_status_t sl_wfx_host_spi_transfer_no_cs_assert(sl_wfx_host_bus_transfer_type_t type,
+                                                  uint8_t *header,
+                                                  uint16_t header_length,
+                                                  uint8_t *buffer,
+                                                  uint16_t buffer_length)
+ * @brief
+ * WFX SPI transfer implementation
+ * @param[in] type:
+ * @param[in] header:
+ * @param[in] header_length:
+ * @param[in] buffer:
+ * @param[in] buffer_length:
+ * @return  returns SL_STATUS_OK if successful,
+ *          SL_STATUS_FAIL otherwise
+ *****************************************************************************/
+sl_status_t sl_wfx_host_spi_transfer_no_cs_assert(sl_wfx_host_bus_transfer_type_t type, uint8_t * header, uint16_t header_length,
+                                                  uint8_t * buffer, uint16_t buffer_length)
+{
+    sl_status_t result = SL_STATUS_FAIL;
+    const bool is_read = (type == SL_WFX_BUS_READ);
+
+    while (!(MY_USART->STATUS & USART_STATUS_TXBL))
+    {
+    }
+    MY_USART->CMD = USART_CMD_CLEARRX | USART_CMD_CLEARTX;
+
+    /* header length should be greater than 0 */
+    if (header_length > 0)
+    {
+        for (uint8_t * buffer_ptr = header; header_length > 0; --header_length, ++buffer_ptr)
+        {
+            MY_USART->TXDATA = (uint32_t)(*buffer_ptr);
+
+            while (!(MY_USART->STATUS & USART_STATUS_TXC))
+            {
+            }
+        }
+        while (!(MY_USART->STATUS & USART_STATUS_TXBL))
+        {
+        }
+    }
+
+    /* buffer length should be greater than 0 */
+    if (buffer_length > 0)
+    {
+        MY_USART->CMD = USART_CMD_CLEARRX | USART_CMD_CLEARTX;
+        if (xSemaphoreTake(spi_sem, portMAX_DELAY) == pdTRUE)
+        {
+            if (is_read)
+            {
+                receiveDMA(buffer, buffer_length);
+                result = SL_STATUS_OK;
+            }
+            else
+            {
+                transmitDMA(buffer, buffer_length);
+                result = SL_STATUS_OK;
+            }
+
+            if (xSemaphoreTake(spi_sem, portMAX_DELAY) == pdTRUE)
+            {
+                xSemaphoreGive(spi_sem);
+            }
+        }
+        else
+        {
+            result = SL_STATUS_TIMEOUT;
+        }
+    }
+
+    return result;
+}
+
+/****************************************************************************
+ * @fn   void sl_wfx_host_start_platform_interrupt(void)
+ * @brief
+ * Enable WFX interrupt
+ * @param[in]  none
+ * @return None
+ *****************************************************************************/
+void sl_wfx_host_start_platform_interrupt(void)
+{
+    // Enable (and clear) the bus interrupt
+    GPIO_ExtIntConfig(SL_WFX_HOST_PINOUT_SPI_WIRQ_PORT, SL_WFX_HOST_PINOUT_SPI_WIRQ_PIN, wirq_irq_nb, true, false, true);
+}
+
+/****************************************************************************
+ * @fn   sl_status_t sl_wfx_host_disable_platform_interrupt(void)
+ * @brief
+ * Disable WFX interrupt
+ * @param[in]  None
+ * @return  returns SL_STATUS_OK if successful,
+ *          SL_STATUS_FAIL otherwise
+ *****************************************************************************/
+sl_status_t sl_wfx_host_disable_platform_interrupt(void)
+{
+    GPIO_IntDisable(1 << wirq_irq_nb);
+    return SL_STATUS_OK;
+}
+
+/****************************************************************************
+ * @fn   sl_status_t sl_wfx_host_enable_platform_interrupt(void)
+ * @brief
+ *      enable the platform interrupt
+ * @param[in]  None
+ * @return  returns SL_STATUS_OK if successful,
+ *          SL_STATUS_FAIL otherwise
+ *****************************************************************************/
+sl_status_t sl_wfx_host_enable_platform_interrupt(void)
+{
+    GPIO_IntEnable(1 << wirq_irq_nb);
+    return SL_STATUS_OK;
+}
+
+/****************************************************************************
+ * @fn   sl_status_t sl_wfx_host_enable_spi(void)
+ * @brief
+ *       enable spi
+ * @param[in]  None
+ * @return  returns SL_STATUS_OK if successful,
+ *          SL_STATUS_FAIL otherwise
+ *****************************************************************************/
+sl_status_t sl_wfx_host_enable_spi(void)
+{
+    if (spi_enabled == false)
+    {
+#ifdef SLEEP_ENABLED
+        // Prevent the host to use lower EM than EM1
+        sl_power_manager_add_em_requirement(SL_POWER_MANAGER_EM1);
+#endif
+        spi_enabled = true;
+    }
+    return SL_STATUS_OK;
+}
+
+/****************************************************************************
+ * @fn   sl_status_t sl_wfx_host_disable_spi(void)
+ * @brief
+ *       disable spi
+ * @param[in]  None
+ * @return  returns SL_STATUS_OK if successful,
+ *          SL_STATUS_FAIL otherwise
+ *****************************************************************************/
+sl_status_t sl_wfx_host_disable_spi(void)
+{
+    if (spi_enabled == true)
+    {
+        spi_enabled = false;
+#ifdef SLEEP_ENABLED
+        // Allow the host to use the lowest allowed EM
+        sl_power_manager_remove_em_requirement(SL_POWER_MANAGER_EM1);
+#endif
+    }
+    return SL_STATUS_OK;
+}
+
+/*
+ * IRQ for SPI callback
+ * Clear the Interrupt and wake up the task that
+ * handles the actions of the interrupt (typically - wfx_bus_task ())
+ */
+static void sl_wfx_spi_wakeup_irq_callback(uint8_t irqNumber)
+{
+    BaseType_t bus_task_woken;
+    uint32_t interrupt_mask;
+
+    if (irqNumber != wirq_irq_nb)
+        return;
+    // Get and clear all pending GPIO interrupts
+    interrupt_mask = GPIO_IntGet();
+    GPIO_IntClear(interrupt_mask);
+    bus_task_woken = pdFALSE;
+    xSemaphoreGiveFromISR(wfx_wakeup_sem, &bus_task_woken);
+    vTaskNotifyGiveFromISR(wfx_bus_task_handle, &bus_task_woken);
+    portYIELD_FROM_ISR(bus_task_woken);
+}
+
+/****************************************************************************
+ * Init some actions pins to the WF-200 expansion board
+ *****************************************************************************/
+void sl_wfx_host_gpio_init(void)
+{
+    SILABS_LOG("WIFI: GPIO Init:IRQ=%d", wirq_irq_nb);
+    // Enable GPIO clock.
+    CMU_ClockEnable(cmuClock_GPIO, true);
+
+    // Configure WF200 reset pin.
+    GPIO_PinModeSet(SL_WFX_HOST_PINOUT_RESET_PORT, SL_WFX_HOST_PINOUT_RESET_PIN, gpioModePushPull, 0);
+    // Configure WF200 WUP pin.
+    GPIO_PinModeSet(SL_WFX_HOST_PINOUT_WUP_PORT, SL_WFX_HOST_PINOUT_WUP_PIN, gpioModePushPull, 0);
+
+    // GPIO used as IRQ.
+    GPIO_PinModeSet(SL_WFX_HOST_PINOUT_SPI_WIRQ_PORT, SL_WFX_HOST_PINOUT_SPI_WIRQ_PIN, gpioModeInputPull, 0);
+    CMU_OscillatorEnable(cmuOsc_LFXO, true, true);
+
+    // Set up interrupt based callback function - trigger on both edges.
+    GPIOINT_Init();
+    GPIO_ExtIntConfig(SL_WFX_HOST_PINOUT_SPI_WIRQ_PORT, SL_WFX_HOST_PINOUT_SPI_WIRQ_PIN, wirq_irq_nb, true, false,
+                      false); /* Don't enable it */
+
+    GPIOINT_CallbackRegister(wirq_irq_nb, sl_wfx_spi_wakeup_irq_callback);
+
+    // Change GPIO interrupt priority (FreeRTOS asserts unless this is done here!)
+    NVIC_ClearPendingIRQ(1 << wirq_irq_nb);
+    NVIC_SetPriority(GPIO_EVEN_IRQn, 5);
+    NVIC_SetPriority(GPIO_ODD_IRQn, 5);
+}
diff --git a/examples/platform/silabs/SiWx917/wf200/host_if.cpp b/examples/platform/silabs/SiWx917/wf200/host_if.cpp
new file mode 100644
index 0000000..26bd788
--- /dev/null
+++ b/examples/platform/silabs/SiWx917/wf200/host_if.cpp
@@ -0,0 +1,1270 @@
+/*
+ *
+ *    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.
+ */
+
+/* Includes */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "em_bus.h"
+#include "em_cmu.h"
+#include "em_gpio.h"
+#include "em_ldma.h"
+#include "em_usart.h"
+#include "gpiointerrupt.h"
+
+#include "wifi_config.h"
+
+#include "AppConfig.h"
+#include "sl_wfx_board.h"
+#include "sl_wfx_host.h"
+#include "sl_wfx_task.h"
+#include "wfx_host_events.h"
+
+#include "FreeRTOS.h"
+#include "event_groups.h"
+#include "task.h"
+
+#include "dhcp_client.h"
+#include "ethernetif.h"
+#include <platform/CHIPDeviceLayer.h>
+
+using namespace ::chip;
+using namespace ::chip::DeviceLayer;
+
+/* wfxRsi Task will use as its stack */
+StackType_t wfxEventTaskStack[1024] = { 0 };
+
+/* Structure that will hold the TCB of the wfxRsi Task being created. */
+StaticTask_t wfxEventTaskBuffer;
+
+/* Declare a variable to hold the data associated with the created event group. */
+StaticEventGroup_t wfxEventGroup;
+
+EventGroupHandle_t sl_wfx_event_group;
+TaskHandle_t wfx_events_task_handle;
+static sl_wfx_mac_address_t ap_mac;
+static uint32_t sta_ip;
+static wfx_wifi_scan_result_t ap_info;
+
+// Set Scan Parameters
+#define ACTIVE_CHANNEL_TIME 110
+#define PASSIVE_CHANNEL_TIME 0
+#define NUM_PROBE_REQUEST 2
+
+// wfx_fmac_driver context
+sl_wfx_context_t wifiContext;
+static uint8_t wifi_extra;
+
+/*****************************************************************************
+ * macros
+ ******************************************************************************/
+#define WE_ST_STARTED 1
+#define WE_ST_STA_CONN 2
+#define WE_ST_HW_STARTED 4
+
+#ifdef SL_WFX_CONFIG_SOFTAP
+// Connection parameters
+char softap_ssid[32]                   = SOFTAP_SSID_DEFAULT;
+char softap_passkey[64]                = SOFTAP_PASSKEY_DEFAULT;
+sl_wfx_security_mode_t softap_security = SOFTAP_SECURITY_DEFAULT;
+uint8_t softap_channel                 = SOFTAP_CHANNEL_DEFAULT;
+#endif
+
+/* station network interface structures */
+struct netif * sta_netif;
+wfx_wifi_provision_t wifi_provision;
+sl_wfx_get_counters_cnf_t * counters;
+sl_wfx_get_counters_cnf_t * Tempcounters;
+#define PUT_COUNTER(name) SILABS_LOG("%-24s %lu\r\n", #name, (unsigned long) counters->body.count_##name);
+
+bool hasNotifiedIPV6             = false;
+bool hasNotifiedIPV4             = false;
+bool hasNotifiedWifiConnectivity = false;
+static uint8_t retryJoin         = 0;
+bool retryInProgress             = false;
+
+#ifdef SL_WFX_CONFIG_SCAN
+static struct scan_result_holder
+{
+    struct scan_result_holder * next;
+    wfx_wifi_scan_result scan;
+} * scan_save;
+static uint8_t scan_count = 0;
+static void (*scan_cb)(wfx_wifi_scan_result_t *); /* user-callback - when scan is done */
+static char * scan_ssid;                          /* Which one are we scanning for */
+static void sl_wfx_scan_result_callback(sl_wfx_scan_result_ind_body_t * scan_result);
+static void sl_wfx_scan_complete_callback(uint32_t status);
+#endif /* SL_WFX_CONFIG_SCAN */
+
+static void wfx_events_task(void * p_arg);
+
+/* WF200 host callbacks */
+static void sl_wfx_connect_callback(sl_wfx_connect_ind_body_t connect_indication_body);
+static void sl_wfx_disconnect_callback(uint8_t * mac, uint16_t reason);
+static void sl_wfx_generic_status_callback(sl_wfx_generic_ind_t * frame);
+
+#ifdef SL_WFX_CONFIG_SOFTAP
+static void sl_wfx_start_ap_callback(uint32_t status);
+static void sl_wfx_stop_ap_callback(void);
+static void sl_wfx_client_connected_callback(uint8_t * mac);
+static void sl_wfx_ap_client_disconnected_callback(uint32_t status, uint8_t * mac);
+static void sl_wfx_ap_client_rejected_callback(uint32_t status, uint8_t * mac);
+#endif
+
+extern uint32_t gOverrunCount;
+
+/***************************************************************************
+ * @brief
+ * Creates WFX events processing task.
+ ******************************************************************************/
+static void wfx_events_task_start()
+{
+    /* create an event group to track Wi-Fi events */
+    sl_wfx_event_group = xEventGroupCreateStatic(&wfxEventGroup);
+
+    wfx_events_task_handle = xTaskCreateStatic(wfx_events_task, "wfx_events", WLAN_TASK_STACK_SIZE, NULL, WLAN_TASK_PRIORITY,
+                                               wfxEventTaskStack, &wfxEventTaskBuffer);
+    if (NULL == wfx_events_task_handle)
+    {
+        SILABS_LOG("Failed to create WFX wfx_events");
+    }
+}
+
+/****************************************************************************
+ * @brief
+ * Called when the driver needs to post an event
+ * @param[in]  event_payload:
+ * @returns Returns SL_STATUS_OK if successful,
+ *SL_STATUS_FAIL otherwise
+ *****************************************************************************/
+sl_status_t sl_wfx_host_process_event(sl_wfx_generic_message_t * event_payload)
+{
+    switch (event_payload->header.id)
+    {
+    /******** INDICATION ********/
+    case SL_WFX_STARTUP_IND_ID: {
+        SILABS_LOG("WFX Startup Completed\r\n");
+        PlatformMgrImpl().HandleWFXSystemEvent(WIFI_EVENT, event_payload);
+        break;
+    }
+    case SL_WFX_CONNECT_IND_ID: {
+        sl_wfx_connect_ind_t * connect_indication = (sl_wfx_connect_ind_t *) event_payload;
+        sl_wfx_connect_callback(connect_indication->body);
+        break;
+    }
+    case SL_WFX_DISCONNECT_IND_ID: {
+        sl_wfx_disconnect_ind_t * disconnect_indication = (sl_wfx_disconnect_ind_t *) event_payload;
+        sl_wfx_disconnect_callback(disconnect_indication->body.mac, disconnect_indication->body.reason);
+        break;
+    }
+    case SL_WFX_RECEIVED_IND_ID: {
+        sl_wfx_received_ind_t * ethernet_frame = (sl_wfx_received_ind_t *) event_payload;
+        if (ethernet_frame->body.frame_type == ETH_FRAME)
+        {
+            sl_wfx_host_received_frame_callback(ethernet_frame);
+        }
+        break;
+    }
+#ifdef SL_WFX_CONFIG_SCAN
+    case SL_WFX_SCAN_RESULT_IND_ID: {
+        sl_wfx_scan_result_ind_t * scan_result = (sl_wfx_scan_result_ind_t *) event_payload;
+        sl_wfx_scan_result_callback(&scan_result->body);
+        break;
+    }
+    case SL_WFX_SCAN_COMPLETE_IND_ID: {
+        sl_wfx_scan_complete_ind_t * scan_complete = (sl_wfx_scan_complete_ind_t *) event_payload;
+        sl_wfx_scan_complete_callback(scan_complete->body.status);
+        break;
+    }
+#endif /* SL_WFX_CONFIG_SCAN */
+#ifdef SL_WFX_CONFIG_SOFTAP
+    case SL_WFX_START_AP_IND_ID: {
+        sl_wfx_start_ap_ind_t * start_ap_indication = (sl_wfx_start_ap_ind_t *) event_payload;
+        sl_wfx_start_ap_callback(start_ap_indication->body.status);
+        break;
+    }
+    case SL_WFX_STOP_AP_IND_ID: {
+        sl_wfx_stop_ap_callback();
+        break;
+    }
+    case SL_WFX_AP_CLIENT_CONNECTED_IND_ID: {
+        sl_wfx_ap_client_connected_ind_t * client_connected_indication = (sl_wfx_ap_client_connected_ind_t *) event_payload;
+        sl_wfx_client_connected_callback(client_connected_indication->body.mac);
+        break;
+    }
+    case SL_WFX_AP_CLIENT_REJECTED_IND_ID: {
+        sl_wfx_ap_client_rejected_ind_t * ap_client_rejected_indication = (sl_wfx_ap_client_rejected_ind_t *) event_payload;
+        sl_wfx_ap_client_rejected_callback(ap_client_rejected_indication->body.reason, ap_client_rejected_indication->body.mac);
+        break;
+    }
+    case SL_WFX_AP_CLIENT_DISCONNECTED_IND_ID: {
+        sl_wfx_ap_client_disconnected_ind_t * ap_client_disconnected_indication =
+            (sl_wfx_ap_client_disconnected_ind_t *) event_payload;
+        sl_wfx_ap_client_disconnected_callback(ap_client_disconnected_indication->body.reason,
+                                               ap_client_disconnected_indication->body.mac);
+        break;
+    }
+#endif /* SL_WFX_CONFIG_SOFTAP */
+#ifdef SL_WFX_USE_SECURE_LINK
+    case SL_WFX_SECURELINK_EXCHANGE_PUB_KEYS_IND_ID: {
+        if (host_context.waited_event_id != SL_WFX_SECURELINK_EXCHANGE_PUB_KEYS_IND_ID)
+        {
+            memcpy((void *) &sl_wfx_context->secure_link_exchange_ind, (void *) event_payload, event_payload->header.length);
+        }
+        break;
+    }
+#endif
+    case SL_WFX_GENERIC_IND_ID: {
+        sl_wfx_generic_ind_t * generic_status = (sl_wfx_generic_ind_t *) event_payload;
+        sl_wfx_generic_status_callback(generic_status);
+        break;
+    }
+    case SL_WFX_EXCEPTION_IND_ID: {
+        sl_wfx_exception_ind_t * firmware_exception = (sl_wfx_exception_ind_t *) event_payload;
+        uint8_t * exception_tmp                     = (uint8_t *) firmware_exception;
+        SILABS_LOG("firmware exception\r\n");
+        for (uint16_t i = 0; i < firmware_exception->header.length; i += 16)
+        {
+            SILABS_LOG("hif: %.8x:", i);
+            for (uint8_t j = 0; (j < 16) && ((i + j) < firmware_exception->header.length); j++)
+            {
+                SILABS_LOG(" %.2x", *exception_tmp);
+                exception_tmp++;
+            }
+            SILABS_LOG("\r\n");
+        }
+        break;
+    }
+    case SL_WFX_ERROR_IND_ID: {
+        sl_wfx_error_ind_t * firmware_error = (sl_wfx_error_ind_t *) event_payload;
+        uint8_t * error_tmp                 = (uint8_t *) firmware_error;
+        SILABS_LOG("firmware error %lu\r\n", firmware_error->body.type);
+        for (uint16_t i = 0; i < firmware_error->header.length; i += 16)
+        {
+            SILABS_LOG("hif: %.8x:", i);
+            for (uint8_t j = 0; (j < 16) && ((i + j) < firmware_error->header.length); j++)
+            {
+                SILABS_LOG(" %.2x", *error_tmp);
+                error_tmp++;
+            }
+            SILABS_LOG("\r\n");
+        }
+        break;
+    }
+    }
+
+    return SL_STATUS_OK;
+}
+
+#ifdef SL_WFX_CONFIG_SCAN
+/****************************************************************************
+ * @brief
+ * Callback for individual scan result
+ * @param[in] scan_result: Scan result of all SSID's
+ *****************************************************************************/
+static void sl_wfx_scan_result_callback(sl_wfx_scan_result_ind_body_t * scan_result)
+{
+    struct scan_result_holder * ap;
+
+    SILABS_LOG("# %2d %2d  %03d %02X:%02X:%02X:%02X:%02X:%02X  %s", scan_count, scan_result->channel,
+               ((int16_t)(scan_result->rcpi - 220) / 2), scan_result->mac[0], scan_result->mac[1], scan_result->mac[2],
+               scan_result->mac[3], scan_result->mac[4], scan_result->mac[5], scan_result->ssid_def.ssid);
+    /*Report one AP information*/
+    SILABS_LOG("\r\n");
+    /* don't save if filter only wants specific ssid */
+    if (scan_ssid != (char *) 0)
+    {
+        if (strcmp(scan_ssid, (char *) &scan_result->ssid_def.ssid[0]) != CMP_SUCCESS)
+            return;
+    }
+    if ((ap = (struct scan_result_holder *) pvPortMalloc(sizeof(*ap))) == (struct scan_result_holder *) 0)
+    {
+        SILABS_LOG("*ERR*Scan: No Mem");
+    }
+    else
+    {
+        ap->next  = scan_save;
+        scan_save = ap;
+        /* Not checking if scan_result->ssid_length is < 33 */
+        memcpy(ap->scan.ssid, scan_result->ssid_def.ssid, scan_result->ssid_def.ssid_length);
+        ap->scan.ssid[scan_result->ssid_def.ssid_length] = 0; /* make sure about null terminate */
+        /* We do it in this order WPA3 first */
+        /* No EAP supported - Is this required */
+        if (scan_result->security_mode.wpa3)
+        {
+            ap->scan.security = WFX_SEC_WPA3;
+        }
+        else if (scan_result->security_mode.wpa2)
+        {
+            ap->scan.security = WFX_SEC_WPA2;
+        }
+        else if (scan_result->security_mode.wpa)
+        {
+            ap->scan.security = WFX_SEC_WPA;
+        }
+        else if (scan_result->security_mode.wep)
+        {
+            ap->scan.security = WFX_SEC_WEP;
+        }
+        else
+        {
+            ap->scan.security = WFX_SEC_NONE;
+        }
+        ap->scan.chan = scan_result->channel;
+        ap->scan.rssi = scan_result->rcpi;
+        memcpy(&ap->scan.bssid[0], &scan_result->mac[0], BSSID_MAX_STR_LEN);
+        scan_count++;
+    }
+}
+
+/****************************************************************************
+ * @brief
+ * Callback for scan complete
+ * @param[in] status:Status of WLAN scan api
+ *****************************************************************************/
+/* ARGSUSED */
+static void sl_wfx_scan_complete_callback(uint32_t status)
+{
+    (void) (status);
+    /* Use scan_count value and reset it */
+    xEventGroupSetBits(sl_wfx_event_group, SL_WFX_SCAN_COMPLETE);
+}
+#endif /* SL_WFX_CONFIG_SCAN */
+
+/****************************************************************************
+ * @brief
+ * Callback when station connects
+ * @param[in]  mac: MAC address of device
+ * @param[in]  status: Status of connect call
+ *****************************************************************************/
+static void sl_wfx_connect_callback(sl_wfx_connect_ind_body_t connect_indication_body)
+{
+    uint8_t * mac   = connect_indication_body.mac;
+    uint32_t status = connect_indication_body.status;
+    switch (status)
+    {
+    case WFM_STATUS_SUCCESS: {
+        SILABS_LOG("STA-Connected\r\n");
+        memcpy(&ap_mac.octet[0], mac, MAC_ADDRESS_FIRST_OCTET);
+        sl_wfx_context->state =
+            static_cast<sl_wfx_state_t>(static_cast<int>(sl_wfx_context->state) | static_cast<int>(SL_WFX_STA_INTERFACE_CONNECTED));
+        xEventGroupSetBits(sl_wfx_event_group, SL_WFX_CONNECT);
+        break;
+    }
+    case WFM_STATUS_NO_MATCHING_AP: {
+        SILABS_LOG("WFX Connection failed, access point not found\r\n");
+        break;
+    }
+    case WFM_STATUS_CONNECTION_ABORTED: {
+        SILABS_LOG("WFX Connection aborted\r\n");
+        break;
+    }
+    case WFM_STATUS_CONNECTION_TIMEOUT: {
+        SILABS_LOG("WFX Connection timeout\r\n");
+        break;
+    }
+    case WFM_STATUS_CONNECTION_REJECTED_BY_AP: {
+        SILABS_LOG("WFX Connection rejected by the access point\r\n");
+        break;
+    }
+    case WFM_STATUS_CONNECTION_AUTH_FAILURE: {
+        SILABS_LOG("WFX Connection authentication failure\r\n");
+        break;
+    }
+    default: {
+        SILABS_LOG("WF Connection attempt error\r\n");
+    }
+    }
+
+    if ((status != WFM_STATUS_SUCCESS) && retryJoin < MAX_JOIN_RETRIES_COUNT)
+    {
+        retryJoin += 1;
+        retryInProgress = false;
+        SILABS_LOG("WFX Retry to connect to network count: %d", retryJoin);
+        sl_wfx_context->state =
+            static_cast<sl_wfx_state_t>(static_cast<int>(sl_wfx_context->state) & ~static_cast<int>(SL_WFX_STARTED));
+        xEventGroupSetBits(sl_wfx_event_group, SL_WFX_RETRY_CONNECT);
+    }
+}
+
+/****************************************************************************
+ * @brief
+ * Callback for station disconnect
+ * @param[in]  mac: MAC address of device
+ * @param[in]  reason: Reason code of disconnection
+ *****************************************************************************/
+static void sl_wfx_disconnect_callback(uint8_t * mac, uint16_t reason)
+{
+    (void) (mac);
+    SILABS_LOG("WFX Disconnected %d\r\n", reason);
+    sl_wfx_context->state =
+        static_cast<sl_wfx_state_t>(static_cast<int>(sl_wfx_context->state) & ~static_cast<int>(SL_WFX_STA_INTERFACE_CONNECTED));
+    xEventGroupSetBits(sl_wfx_event_group, SL_WFX_DISCONNECT);
+}
+
+#ifdef SL_WFX_CONFIG_SOFTAP
+/****************************************************************************
+ * @brief
+ * Callback for AP started
+ * @param[in]  status: Status of wfx start ap api
+ *****************************************************************************/
+static void sl_wfx_start_ap_callback(uint32_t status)
+{
+    if (status == AP_START_SUCCESS)
+    {
+        SILABS_LOG("AP started\r\n");
+        sl_wfx_context->state =
+            static_cast<sl_wfx_state_t>(static_cast<int>(sl_wfx_context->state) | static_cast<int>(SL_WFX_AP_INTERFACE_UP));
+        xEventGroupSetBits(sl_wfx_event_group, SL_WFX_START_AP);
+    }
+    else
+    {
+        SILABS_LOG("AP start failed\r\n");
+        strcpy(event_log, "AP start failed");
+    }
+}
+
+/****************************************************************************
+ * @brief
+ * Callback for AP stopped
+ *****************************************************************************/
+static void sl_wfx_stop_ap_callback(void)
+{
+    // TODO
+    // dhcpserver_clear_stored_mac();
+    SILABS_LOG("SoftAP stopped\r\n");
+    sl_wfx_context->state =
+        static_cast<sl_wfx_state_t>(static_cast<int>(sl_wfx_context->state) & ~static_cast<int>(SL_WFX_AP_INTERFACE_UP));
+    xEventGroupSetBits(sl_wfx_event_group, SL_WFX_STOP_AP);
+}
+
+/****************************************************************************
+ * @brief
+ * Callback for client connect to AP
+ * @param[in]  mac: MAC address of device
+ *****************************************************************************/
+static void sl_wfx_client_connected_callback(uint8_t * mac)
+{
+    SILABS_LOG("Client connected, MAC: %02X:%02X:%02X:%02X:%02X:%02X\r\n", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
+    // TODO
+    SILABS_LOG("Open a web browser and go to http://%d.%d.%d.%d\r\n", ap_ip_addr0, ap_ip_addr1, ap_ip_addr2, ap_ip_addr3);
+}
+
+/****************************************************************************
+ * @brief
+ * Callback for client rejected from AP
+ * @param[in] status: Status of ap rejected
+ * @param[in] mac: MAC address of device
+ *****************************************************************************/
+static void sl_wfx_ap_client_rejected_callback(uint32_t status, uint8_t * mac)
+{
+    SILABS_LOG("Client rejected, reason: %d, MAC: %02X:%02X:%02X:%02X:%02X:%02X\r\n", (int) status, mac[0], mac[1], mac[2], mac[3],
+               mac[4], mac[5]);
+}
+
+/****************************************************************************
+ * @brief
+ * Callback for AP client disconnect
+ * @param[in] status: Status of ap dissconnect
+ * @param[in]  mac:
+ *****************************************************************************/
+static void sl_wfx_ap_client_disconnected_callback(uint32_t status, uint8_t * mac)
+{
+    // TODO
+    SILABS_LOG("Client disconnected, reason: %d, MAC: %02X:%02X:%02X:%02X:%02X:%02X\r\n", (int) status, mac[0], mac[1], mac[2],
+               mac[3], mac[4], mac[5]);
+}
+#endif /* SL_WFX_CONFIG_SOFTAP */
+
+/****************************************************************************
+ * @brief
+ * Callback for generic status received
+ * @param[in] farme:
+ *****************************************************************************/
+static void sl_wfx_generic_status_callback(sl_wfx_generic_ind_t * frame)
+{
+    (void) (frame);
+    SILABS_LOG("WFX Generic status received\r\n");
+}
+
+/***************************************************************************
+ * @brief
+ * WFX events processing task.
+ * @param[in] p_arg:
+ *  ******************************************************************************/
+static void wfx_events_task(void * p_arg)
+{
+    TickType_t last_dhcp_poll, now;
+    EventBits_t flags;
+    (void) p_arg;
+
+    sta_netif      = wfx_get_netif(SL_WFX_STA_INTERFACE);
+    last_dhcp_poll = xTaskGetTickCount();
+    while (true)
+    {
+        flags = xEventGroupWaitBits(sl_wfx_event_group,
+                                    SL_WFX_CONNECT | SL_WFX_DISCONNECT
+#ifdef SL_WFX_CONFIG_SOFTAP
+                                        | SL_WFX_START_AP | SL_WFX_STOP_AP
+#endif /* SL_WFX_CONFIG_SOFTAP */
+#ifdef SL_WFX_CONFIG_SCAN
+                                        | SL_WFX_SCAN_START | SL_WFX_SCAN_COMPLETE
+#endif /* SL_WFX_CONFIG_SCAN */
+                                        | BITS_TO_WAIT,
+                                    pdTRUE, pdFALSE, pdMS_TO_TICKS(250)); /* 250 msec delay converted to ticks */
+        if (flags & SL_WFX_RETRY_CONNECT)
+        {
+            if (!retryInProgress)
+            {
+                SILABS_LOG("WFX sending the connect command");
+                wfx_connect_to_ap();
+                retryInProgress = true;
+            }
+        }
+
+        if (wifi_extra & WE_ST_STA_CONN)
+        {
+            if ((now = xTaskGetTickCount()) > (last_dhcp_poll + pdMS_TO_TICKS(250)))
+            {
+#if (CHIP_DEVICE_CONFIG_ENABLE_IPV4)
+                uint8_t dhcp_state = dhcpclient_poll(&sta_netif);
+
+                if ((dhcp_state == DHCP_ADDRESS_ASSIGNED) && !hasNotifiedIPV4)
+                {
+                    wfx_dhcp_got_ipv4((uint32_t) sta_netif->ip_addr.u_addr.ip4.addr);
+                    hasNotifiedIPV4 = true;
+                    if (!hasNotifiedWifiConnectivity)
+                    {
+                        SILABS_LOG("WIFI: Has Notified Wifi Connectivity");
+                        wfx_connected_notify(CONNECTION_STATUS_SUCCESS, &ap_mac);
+                        hasNotifiedWifiConnectivity = true;
+                    }
+                }
+                else if (dhcp_state == DHCP_OFF)
+                {
+                    wfx_ip_changed_notify(IP_STATUS_FAIL);
+                    hasNotifiedIPV4 = false;
+                }
+#endif // CHIP_DEVICE_CONFIG_ENABLE_IPV4
+                if ((ip6_addr_ispreferred(netif_ip6_addr_state(sta_netif, 0))) && !hasNotifiedIPV6)
+                {
+                    wfx_ipv6_notify(1);
+                    hasNotifiedIPV6 = true;
+                    if (!hasNotifiedWifiConnectivity)
+                    {
+                        wfx_connected_notify(CONNECTION_STATUS_SUCCESS, &ap_mac);
+                        hasNotifiedWifiConnectivity = true;
+                    }
+                }
+                last_dhcp_poll = now;
+            }
+        }
+
+        if (flags & SL_WFX_CONNECT)
+        {
+#if (CHIP_DEVICE_CONFIG_ENABLE_IPV4)
+            wfx_ip_changed_notify(IP_STATUS_FAIL);
+            hasNotifiedIPV4 = false;
+#endif // CHIP_DEVICE_CONFIG_ENABLE_IPV4
+            wfx_ipv6_notify(GET_IPV6_FAIL);
+            hasNotifiedIPV6             = false;
+            hasNotifiedWifiConnectivity = false;
+            SILABS_LOG("WIFI: Connected to AP");
+            wifi_extra |= WE_ST_STA_CONN;
+            wfx_lwip_set_sta_link_up();
+#ifdef SLEEP_ENABLED
+            if (!(wfx_get_wifi_state() & SL_WFX_AP_INTERFACE_UP))
+            {
+                // Enable the power save
+                sl_wfx_set_power_mode(WFM_PM_MODE_PS, WFM_PM_POLL_UAPSD, BEACON_1);
+                sl_wfx_enable_device_power_save();
+            }
+#endif // SLEEP_ENABLED
+        }
+
+        if (flags & SL_WFX_DISCONNECT)
+        {
+
+#if (CHIP_DEVICE_CONFIG_ENABLE_IPV4)
+            wfx_ip_changed_notify(IP_STATUS_FAIL);
+            hasNotifiedIPV4 = false;
+#endif // CHIP_DEVICE_CONFIG_ENABLE_IPV4
+            wfx_ipv6_notify(GET_IPV6_FAIL);
+            hasNotifiedIPV6             = false;
+            hasNotifiedWifiConnectivity = false;
+            wifi_extra &= ~WE_ST_STA_CONN;
+            wfx_lwip_set_sta_link_down();
+        }
+
+#ifdef SL_WFX_CONFIG_SCAN
+        if (flags & SL_WFX_SCAN_START)
+        {
+            /*
+             * Start the Scan
+             */
+            sl_wfx_ssid_def_t ssid, *sp;
+            uint16_t num_ssid, slen;
+            if (scan_ssid)
+            {
+                memset(&ssid, 0, sizeof(ssid));
+                slen = strlen(scan_ssid);
+                memcpy(&ssid.ssid[0], scan_ssid, slen);
+                ssid.ssid_length = slen;
+                num_ssid         = 1;
+                sp               = &ssid;
+            }
+            else
+            {
+                num_ssid = 0;
+                sp       = (sl_wfx_ssid_def_t *) 0;
+            }
+
+            SILABS_LOG("WIFI Scan Parameter set to Active channel time %d, Passive "
+                       "Channel Time: %d, Number of prob: %d",
+                       ACTIVE_CHANNEL_TIME, PASSIVE_CHANNEL_TIME, NUM_PROBE_REQUEST);
+            (void) sl_wfx_set_scan_parameters(ACTIVE_CHANNEL_TIME, PASSIVE_CHANNEL_TIME, NUM_PROBE_REQUEST);
+            (void) sl_wfx_send_scan_command(WFM_SCAN_MODE_ACTIVE, CHANNEL_LIST, /* Channel list */
+                                            CHANNEL_COUNT,                      /* Scan all chans */
+                                            sp, num_ssid, IE_DATA,              /* IE we're looking for */
+                                            IE_DATA_LENGTH, BSSID_SCAN);
+        }
+        if (flags & SL_WFX_SCAN_COMPLETE)
+        {
+            struct scan_result_holder *hp, *next;
+
+            SILABS_LOG("WIFI: Return %d scan results", scan_count);
+            for (hp = scan_save; hp; hp = next)
+            {
+                next = hp->next;
+                (*scan_cb)(&hp->scan);
+                vPortFree(hp);
+            }
+            (*scan_cb)((wfx_wifi_scan_result *) 0);
+            scan_save  = (struct scan_result_holder *) 0;
+            scan_count = 0;
+            if (scan_ssid)
+            {
+                vPortFree(scan_ssid);
+                scan_ssid = (char *) 0;
+            }
+            /* Terminate scan */
+            scan_cb = 0;
+        }
+#endif /* SL_WFX_CONFIG_SCAN */
+    }
+}
+
+/****************************************************************************
+ * @brief
+ * Initialize the WF200 used by the two interfaces
+ *****************************************************************************/
+static sl_status_t wfx_init(void)
+{
+    /* Initialize the WF200 used by the two interfaces */
+    wfx_events_task_start();
+    sl_status_t status = sl_wfx_init(&wifiContext);
+    SILABS_LOG("FMAC Driver version    %s", FMAC_DRIVER_VERSION_STRING);
+    switch (status)
+    {
+    case SL_STATUS_OK:
+        SILABS_LOG("WF200 FW ver:%d.%d.%d [MAC %02x:%02x:%02x-%02x:%02x:%02x]", wifiContext.firmware_major,
+                   wifiContext.firmware_minor, wifiContext.firmware_build, wifiContext.mac_addr_0.octet[0],
+                   wifiContext.mac_addr_0.octet[1], wifiContext.mac_addr_0.octet[2], wifiContext.mac_addr_0.octet[3],
+                   wifiContext.mac_addr_0.octet[4], wifiContext.mac_addr_0.octet[5]);
+        SILABS_LOG("WF200 Init OK");
+
+        if (wifiContext.state == SL_WFX_STA_INTERFACE_CONNECTED)
+        {
+            sl_wfx_send_disconnect_command();
+        }
+
+        break;
+    case SL_STATUS_WIFI_INVALID_KEY:
+        SILABS_LOG("*ERR*WF200: F/W keyset invalid");
+        break;
+    case SL_STATUS_WIFI_FIRMWARE_DOWNLOAD_TIMEOUT:
+        SILABS_LOG("*ERR*WF200: F/W download timo");
+        break;
+    case SL_STATUS_TIMEOUT:
+        SILABS_LOG("*ERR*WF200: Poll for value timo");
+        break;
+    case SL_STATUS_FAIL:
+        SILABS_LOG("*ERR*WF200: Error");
+        break;
+    default:
+        SILABS_LOG("*ERR*WF200: Unknown");
+    }
+
+    return status;
+}
+
+/*****************************************************************************
+ * @brief
+ *   tcp ip, wfx and lwip stack and start dhcp client.
+ * @return
+ *    sl_status_t Shows init succes or error.
+ ******************************************************************************/
+static void wfx_wifi_hw_start(void)
+{
+    sl_status_t status;
+
+    if (wifi_extra & WE_ST_HW_STARTED)
+        return;
+    SILABS_LOG("STARTING WF200\n");
+    wifi_extra |= WE_ST_HW_STARTED;
+
+    sl_wfx_host_gpio_init();
+    if ((status = wfx_init()) == SL_STATUS_OK)
+    {
+        /* Initialize the LwIP stack */
+        SILABS_LOG("WF200:Start LWIP");
+        wfx_lwip_start();
+        wifiContext.state = SL_WFX_STARTED; /* Really this is a bit mask */
+        SILABS_LOG("WF200:ready..");
+    }
+    else
+    {
+        SILABS_LOG("*ERR*WF200:init failed");
+    }
+}
+
+/***********************************************************************
+ * @brief
+ * Get AP info
+ * @param[in]  ap: access point information
+ * @return returns -1
+ **************************************************************************/
+int32_t wfx_get_ap_info(wfx_wifi_scan_result_t * ap)
+{
+    int32_t signal_strength;
+    SILABS_LOG("WIFI:SSID:: %s", &ap_info.ssid[0]);
+    memcpy(ap->ssid, ap_info.ssid, sizeof(ap_info.ssid));
+    SILABS_LOG("WIFI:Mac addr:: %02x:%02x:%02x:%02x:%02x:%02x", ap_info.bssid[0], ap_info.bssid[1], ap_info.bssid[2],
+               ap_info.bssid[3], ap_info.bssid[4], ap_info.bssid[5]);
+    memcpy(ap->bssid, ap_info.bssid, sizeof(ap_info.bssid));
+    ap->security = ap_info.security;
+    SILABS_LOG("WIFI:security:: %d", ap->security);
+    ap->chan = ap_info.chan;
+    SILABS_LOG("WIFI:Channel:: to %d", ap->chan);
+
+    sl_status_t status = sl_wfx_get_signal_strength((uint32_t *) &signal_strength);
+
+    if (status == SL_STATUS_OK)
+    {
+        SILABS_LOG("status SL_STATUS_OK & signal_strength:: %d", signal_strength);
+        ap->rssi = (signal_strength - 220) / 2;
+    }
+    return status;
+}
+
+/************************************************************************
+ * @brief
+ * Get AP extra info
+ * @param[in]  extra_info: access point extra information
+ * @return returns -1
+ **************************************************************************/
+int32_t wfx_get_ap_ext(wfx_wifi_scan_ext_t * extra_info)
+{
+    int32_t status;
+    status = get_all_counters();
+    if (status != SL_STATUS_OK)
+    {
+        SILABS_LOG("Failed to get the couters");
+    }
+    else
+    {
+        extra_info->beacon_lost_count = counters->body.count_miss_beacon;
+        extra_info->beacon_rx_count   = counters->body.count_rx_beacon;
+        extra_info->mcast_rx_count    = counters->body.count_rx_multicast_frames;
+        extra_info->mcast_tx_count    = counters->body.count_tx_multicast_frames;
+        extra_info->ucast_rx_count    = counters->body.count_rx_packets;
+        extra_info->ucast_tx_count    = counters->body.count_tx_packets;
+        extra_info->overrun_count     = gOverrunCount;
+    }
+    return status;
+}
+
+sl_status_t get_all_counters(void)
+{
+    sl_status_t result;
+    uint8_t command_id         = 0x05;
+    uint16_t mib_id            = 0x2035;
+    sl_wfx_mib_req_t * request = NULL;
+    uint32_t request_length    = SL_WFX_ROUND_UP_EVEN(sizeof(sl_wfx_header_mib_t) + sizeof(sl_wfx_mib_req_body_t));
+
+    result =
+        sl_wfx_allocate_command_buffer((sl_wfx_generic_message_t **) &request, command_id, SL_WFX_CONTROL_BUFFER, request_length);
+
+    if (request == NULL)
+    {
+    }
+
+    request->body.mib_id      = mib_id;
+    request->header.interface = 0x2;
+    request->header.encrypted = 0x0;
+
+    result = sl_wfx_send_request(command_id, (sl_wfx_generic_message_t *) request, request_length);
+    SL_WFX_ERROR_CHECK(result);
+
+    result = sl_wfx_host_wait_for_confirmation(command_id, SL_WFX_DEFAULT_REQUEST_TIMEOUT_MS, (void **) &counters);
+    SL_WFX_ERROR_CHECK(result);
+
+    SILABS_LOG("%-24s %12s \r\n", "", "Debug Counters Content");
+    SILABS_LOG("%-24s %lu\r\n", "rcpi", (unsigned long) counters->body.rcpi);
+    PUT_COUNTER(plcp_errors);
+    PUT_COUNTER(fcs_errors);
+    PUT_COUNTER(tx_packets);
+    PUT_COUNTER(rx_packets);
+    PUT_COUNTER(rx_packet_errors);
+    PUT_COUNTER(rx_decryption_failures);
+    PUT_COUNTER(rx_mic_failures);
+    PUT_COUNTER(rx_no_key_failures);
+    PUT_COUNTER(tx_multicast_frames);
+    PUT_COUNTER(tx_frames_success);
+    PUT_COUNTER(tx_frame_failures);
+    PUT_COUNTER(tx_frames_retried);
+    PUT_COUNTER(tx_frames_multi_retried);
+    PUT_COUNTER(rx_frame_duplicates);
+    PUT_COUNTER(rts_success);
+    PUT_COUNTER(rts_failures);
+    PUT_COUNTER(ack_failures);
+    PUT_COUNTER(rx_multicast_frames);
+    PUT_COUNTER(rx_frames_success);
+    PUT_COUNTER(rx_cmacicv_errors);
+    PUT_COUNTER(rx_cmac_replays);
+    PUT_COUNTER(rx_mgmt_ccmp_replays);
+    PUT_COUNTER(rx_bipmic_errors);
+    PUT_COUNTER(rx_beacon);
+    PUT_COUNTER(miss_beacon);
+
+error_handler:
+
+    if (result == SL_STATUS_TIMEOUT)
+    {
+        if (sl_wfx_context->used_buffers > 0)
+        {
+            sl_wfx_context->used_buffers--;
+        }
+    }
+    if (request != NULL)
+    {
+        sl_wfx_free_command_buffer((sl_wfx_generic_message_t *) request, command_id, SL_WFX_CONTROL_BUFFER);
+    }
+
+    return result;
+}
+
+/************************************************************************
+ * @brief
+ *    reset the count
+ * @return returns -1
+ **************************************************************************/
+int32_t wfx_reset_counts()
+{
+    /* TODO */
+    return -1;
+}
+
+/*************************************************************************
+ * @brief
+ * I think that this is getting called before FreeRTOS threads are ready
+ * @return  returns SL_STATUS_OK
+ **************************************************************************/
+sl_status_t wfx_wifi_start(void)
+{
+    if (wifi_extra & WE_ST_STARTED)
+    {
+        SILABS_LOG("WIFI: Already started");
+        return SL_STATUS_OK;
+    }
+    wifi_extra |= WE_ST_STARTED;
+    wfx_soft_init();
+    wfx_wifi_hw_start();
+
+    return SL_STATUS_OK;
+}
+
+/****************************************************************************
+ * @brief
+ *      get the wifi state
+ * @return returns wificonetext state
+ *****************************************************************************/
+sl_wfx_state_t wfx_get_wifi_state(void)
+{
+    return wifiContext.state;
+}
+
+/****************************************************************************
+ * @brief
+ *      getnetif using interface
+ * @param[in]  interface:
+ * @return returns selectedNetif
+ *****************************************************************************/
+struct netif * wfx_GetNetif(sl_wfx_interface_t interface)
+{
+    struct netif * SelectedNetif = NULL;
+    if (interface == SL_WFX_STA_INTERFACE)
+    {
+        SelectedNetif = sta_netif;
+    }
+#ifdef SL_WFX_CONFIG_SOFTAP
+    else if (interface == SL_WFX_SOFTAP_INTERFACE)
+    {
+        // no ap currently
+    }
+#endif
+    return SelectedNetif;
+}
+
+/****************************************************************************
+ * @brief
+ * get the wifi mac address using interface
+ * @param[in] interface:
+ * @return  returns wificontext.mac_addr_o if successful,
+ *          wificontext.mac_addr_1 otherwise
+ *****************************************************************************/
+sl_wfx_mac_address_t wfx_get_wifi_mac_addr(sl_wfx_interface_t interface)
+{
+    // return Mac address used by WFX SL_WFX_STA_INTERFACE or SL_WFX_SOFTAP_INTERFACE,
+    return (interface == SL_WFX_STA_INTERFACE) ? wifiContext.mac_addr_0 : wifiContext.mac_addr_1;
+}
+
+/****************************************************************************
+ * @brief
+ * set the wifi provision
+ * @param[in] wifiConfig: configuration of wifi
+ *****************************************************************************/
+void wfx_set_wifi_provision(wfx_wifi_provision_t * wifiConfig)
+{
+    memcpy(wifi_provision.ssid, wifiConfig->ssid, sizeof(wifiConfig->ssid));
+    memcpy(wifi_provision.passkey, wifiConfig->passkey, sizeof(wifiConfig->passkey));
+    SILABS_LOG("WIFI: Provision SSID=%s", &wifi_provision.ssid[0]);
+
+    /* Not very good - To be improved */
+    switch (wifiConfig->security)
+    {
+    case WFX_SEC_WPA:
+        wifi_provision.security = static_cast<uint8_t>(sl_wfx_security_mode_e::WFM_SECURITY_MODE_WPA2_WPA1_PSK);
+        break;
+    case WFX_SEC_WPA3:
+        wifi_provision.security = WFM_SECURITY_MODE_WPA3_SAE;
+        break;
+    case WFX_SEC_WPA2:
+        wifi_provision.security = static_cast<uint8_t>(sl_wfx_security_mode_e::WFM_SECURITY_MODE_WPA2_WPA1_PSK);
+        break;
+    case WFX_SEC_WPA_WPA2_MIXED:
+        wifi_provision.security = static_cast<uint8_t>(sl_wfx_security_mode_e::WFM_SECURITY_MODE_WPA2_WPA1_PSK);
+        break;
+    default:
+        wifi_provision.security = WFM_SECURITY_MODE_WPA2_PSK;
+        break;
+    }
+}
+
+/****************************************************************************
+ * @brief
+ * get the wifi provision
+ * @param[in] wifiConfig: configuration of wifi
+ * @return returns true if successful,
+ *         false otherwise
+ *****************************************************************************/
+bool wfx_get_wifi_provision(wfx_wifi_provision_t * wifiConfig)
+{
+    if (wifiConfig == NULL)
+    {
+        return false;
+    }
+    memcpy(wifiConfig, &wifi_provision, sizeof(wfx_wifi_provision_t));
+
+    return true;
+}
+
+/****************************************************************************
+ * @brief
+ * clear the wifi provision
+ * @return returns true if successful,
+ *         false otherwise
+ *****************************************************************************/
+void wfx_clear_wifi_provision(void)
+{
+    memset(&wifi_provision, 0, sizeof(wifi_provision));
+}
+
+/****************************************************************************
+ * @brief
+ *      driver STA provisioned
+ * @return returns true if successful,
+ *         false otherwise
+ *****************************************************************************/
+bool wfx_is_sta_provisioned(void)
+{
+    return (wifi_provision.ssid[0]) ? true : false;
+}
+
+/****************************************************************************
+ * @fn  sl_status_t wfx_connect_to_ap(void)
+ * @brief
+ *  driver connect to ap
+ * @return returns SL_STATUS_NOT_AVAILABLE
+ *****************************************************************************/
+sl_status_t wfx_connect_to_ap(void)
+{
+    sl_status_t result;
+
+    if (wifi_provision.ssid[0] == 0)
+    {
+        return SL_STATUS_NOT_AVAILABLE;
+    }
+    SILABS_LOG("WIFI:JOIN to %s", &wifi_provision.ssid[0]);
+
+    SILABS_LOG("WIFI Scan Parameter set to Active channel time %d, Passive Channel "
+               "Time: %d, Number of prob: %d",
+               ACTIVE_CHANNEL_TIME, PASSIVE_CHANNEL_TIME, NUM_PROBE_REQUEST);
+    (void) sl_wfx_set_scan_parameters(ACTIVE_CHANNEL_TIME, PASSIVE_CHANNEL_TIME, NUM_PROBE_REQUEST);
+    result =
+        sl_wfx_send_join_command((uint8_t *) wifi_provision.ssid, strlen(wifi_provision.ssid), NULL, CHANNEL_0,
+                                 static_cast<sl_wfx_security_mode_t>(wifi_provision.security), PREVENT_ROAMING, DISABLE_PMF_MODE,
+                                 (uint8_t *) wifi_provision.passkey, strlen(wifi_provision.passkey), NULL, IE_DATA_LENGTH);
+
+    return result;
+}
+
+/****************************************************************************
+ * @brief
+ * get the wifi mac addresss
+ * @param[in] interface:
+ * @param[in] addr : address
+ *****************************************************************************/
+void wfx_get_wifi_mac_addr(sl_wfx_interface_t interface, sl_wfx_mac_address_t * addr)
+{
+    sl_wfx_mac_address_t * mac;
+
+#ifdef SL_WFX_CONFIG_SOFTAP
+    mac = (interface == SL_WFX_SOFTAP_INTERFACE) ? &wifiContext.mac_addr_1 : &wifiContext.mac_addr_0;
+#else
+    mac = &wifiContext.mac_addr_0;
+#endif
+    *addr = *mac;
+    SILABS_LOG("WLAN:Get WiFi Mac addr %02x:%02x:%02x:%02x:%02x:%02x", mac->octet[0], mac->octet[1], mac->octet[2], mac->octet[3],
+               mac->octet[4], mac->octet[5]);
+    memcpy(&ap_info.bssid[0], &mac->octet[0], 6);
+}
+
+/****************************************************************************
+ * @brief
+ *     function called when driver have ipv4 address
+ * @param[in]  which_if:
+ * @return returns false if successful,
+ *         true otherwise
+ *****************************************************************************/
+bool wfx_have_ipv4_addr(sl_wfx_interface_t which_if)
+{
+    if (which_if == SL_WFX_STA_INTERFACE)
+    {
+        return (sta_ip == STA_IP_FAIL) ? false : true;
+    }
+    else
+    {
+        return false; /* TODO */
+    }
+}
+
+/****************************************************************************
+ * @brief
+ *     function called when driver have ipv6 address
+ * @param[in]  which_if:
+ * @return returns false if successful,
+ *         true otherwise
+ *****************************************************************************/
+bool wfx_have_ipv6_addr(sl_wfx_interface_t which_if)
+{
+    SILABS_LOG("%s: started.", __func__);
+    bool status = false;
+    if (which_if == SL_WFX_STA_INTERFACE)
+    {
+        status = wfx_is_sta_connected();
+    }
+    else
+    {
+        status = false; /* TODO */
+    }
+    SILABS_LOG("%s: status: %d", __func__, status);
+    return status;
+}
+
+/****************************************************************************
+ * @brief
+ * Disconnect station mode from connected AP
+ * @returns Returns SL_STATUS_OK if successful,
+ *             SL_STATUS_FAIL otherwise
+ *****************************************************************************/
+sl_status_t wfx_sta_discon(void)
+{
+    SILABS_LOG("STA-Disconnecting");
+    int32_t status = sl_wfx_send_disconnect_command();
+    wifi_extra &= ~WE_ST_STA_CONN;
+    xEventGroupSetBits(sl_wfx_event_group, SL_WFX_RETRY_CONNECT);
+    return status;
+}
+
+/****************************************************************************
+ * @brief
+ *     enable the STA mode
+ * @return returns true
+ *****************************************************************************/
+bool wfx_is_sta_mode_enabled(void)
+{
+    return true; /* It always is */
+}
+
+/****************************************************************************
+ * @brief
+ *     fuction called when driver is STA connected
+ * @return returns true if successful,
+ *         false otherwise
+ *****************************************************************************/
+bool wfx_is_sta_connected(void)
+{
+    bool val;
+
+    val = (wifi_extra & WE_ST_STA_CONN) ? true : false;
+
+    SILABS_LOG("WLAN: STA %s connected", (val ? "IS" : "NOT"));
+
+    return val;
+}
+
+/****************************************************************************
+ * @brief
+ *      It is automatically done when lwip link up
+ * @return returns true if successful,
+ *         false otherwise
+ *****************************************************************************/
+void wfx_setup_ip6_link_local(sl_wfx_interface_t whichif)
+{
+    SILABS_LOG("Setup-IP6: TODO"); /* It is automatically done when lwip link up */
+}
+
+/****************************************************************************
+ * @brief
+ *      get the wifi mode
+ * @return returns WIFI_MODE_NULL if successful,
+ *         WIFI_MODE_STA otherwise
+ *****************************************************************************/
+wifi_mode_t wfx_get_wifi_mode()
+{
+    if (wifiContext.state & SL_WFX_STARTED)
+        return WIFI_MODE_STA;
+    return WIFI_MODE_NULL;
+}
+
+/*****************************************************************************
+ * @brief
+ * This is called from the context of AppTask
+ * For WF200 - Start WIFI here
+ * @return returns true if successful,
+ *         false otherwise
+ ******************************************************************************/
+bool wfx_hw_ready(void)
+{
+    return (wifiContext.state & SL_WFX_STARTED) ? true : false;
+}
+
+#if CHIP_DEVICE_CONFIG_ENABLE_IPV4
+/*****************************************************************************
+ * @brief
+ *    function called when dhcp got ipv4
+ * @param[in]  ip : internet protocol
+ ******************************************************************************/
+void wfx_dhcp_got_ipv4(uint32_t ip)
+{
+    /* Acquire the new IP address
+     */
+    sta_ip = ip;
+    wfx_ip_changed_notify(IP_STATUS_SUCCESS);
+}
+#endif /* CHIP_DEVICE_CONFIG_ENABLE_IPV4 */
+
+/*****************************************************************************
+ * @brief
+ *    function called from connectivityManager
+ ******************************************************************************/
+void wfx_enable_sta_mode(void)
+{
+    /* Nothing to do - default is that it is
+       place holder */
+}
+
+/****************************************************************************
+ * @brief
+ * driver scan start
+ * @param[in]  callback: Callback from the wifi scan  results
+ * @return returns true if successful,
+ *         false otherwise
+ *****************************************************************************/
+#ifdef SL_WFX_CONFIG_SCAN
+bool wfx_start_scan(char * ssid, void (*callback)(wfx_wifi_scan_result_t *))
+{
+    int sz;
+
+    if (scan_cb)
+        return false; /* Already in progress */
+    if (ssid)
+    {
+        sz = strlen(ssid);
+        if ((scan_ssid = (char *) pvPortMalloc(sz + 1)) == (char *) 0)
+        {
+            return false;
+        }
+        strcpy(scan_ssid, ssid);
+    }
+    scan_cb = callback;
+    xEventGroupSetBits(sl_wfx_event_group, SL_WFX_SCAN_START);
+
+    return true;
+}
+
+/****************************************************************************
+ * @brief
+ * driver scan cancelation
+ *****************************************************************************/
+void wfx_cancel_scan(void)
+{
+    struct scan_result_holder *hp, *next;
+    /* Not possible */
+    if (!scan_cb)
+    {
+        return;
+    }
+    sl_wfx_send_stop_scan_command();
+    for (hp = scan_save; hp; hp = next)
+    {
+        next = hp->next;
+        vPortFree(hp);
+    }
+    scan_save  = (struct scan_result_holder *) 0;
+    scan_count = 0;
+    if (scan_ssid)
+    {
+        vPortFree(scan_ssid);
+        scan_ssid = (char *) 0;
+    }
+    scan_cb = 0;
+}
+#endif /* SL_WFX_CONFIG_SCAN */
diff --git a/examples/platform/silabs/SiWx917/wf200/sl_wfx_board.h b/examples/platform/silabs/SiWx917/wf200/sl_wfx_board.h
new file mode 100644
index 0000000..96ab968
--- /dev/null
+++ b/examples/platform/silabs/SiWx917/wf200/sl_wfx_board.h
@@ -0,0 +1,34 @@
+/*
+ *
+ *    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.
+ */
+
+#ifndef _SL_WFX_BOARD_H_
+#define _SL_WFX_BOARD_H_
+/*
+ * Pull in the right board PINS
+ */
+#if defined(EFR32MG12_BRD4161A) || defined(BRD4161A) || defined(EFR32MG12_BRD4162A) || defined(BRD4162A) ||                        \
+    defined(EFR32MG12_BRD4163A) || defined(BRD4163A) || defined(EFR32MG12_BRD4164A) || defined(BRD4164A) ||                        \
+    defined(EFR32MG12_BRD4170A) || defined(BRD4170A)
+#include "brd4161a.h"
+#elif defined(EFR32MG24_BRD4186C) || defined(BRD4186C) || defined(EFR32MG24_BRD4186A) || defined(BRD4186A)
+#include "brd4186c.h"
+#elif defined(EFR32MG24_BRD4187C) || defined(BRD4187C) || defined(EFR32MG24_BRD4187A) || defined(BRD4187A)
+#include "brd4187c.h"
+#else
+#error "Need SPI Pins"
+#endif /* EFR32MG12_BRD4161A */
+#endif /* _SL_WFX_BOARD_H_ */
diff --git a/examples/platform/silabs/SiWx917/wf200/sl_wfx_configuration.h b/examples/platform/silabs/SiWx917/wf200/sl_wfx_configuration.h
new file mode 100644
index 0000000..deb468d
--- /dev/null
+++ b/examples/platform/silabs/SiWx917/wf200/sl_wfx_configuration.h
@@ -0,0 +1,30 @@
+/*
+ *
+ *    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
+
+// SL_WFX_DEFAULT_REQUEST_TIMEOUT_MS> Timeout period in milliseconds<250-10000>
+// Default: 5000
+// Timeout period in milliseconds for requests.
+#define SL_WFX_DEFAULT_REQUEST_TIMEOUT_MS (5000)
+
+// <h>WFx Secure Link configuration
+
+// SL_WFX_SLK_CURVE25519> Use crypto curves
+// Default: 1
+// If this option is enabled ECDH crypto is used, KDF otherwise.
+#define SL_WFX_SLK_CURVE25519 (1)
diff --git a/examples/platform/silabs/SiWx917/wf200/sl_wfx_crypto.c b/examples/platform/silabs/SiWx917/wf200/sl_wfx_crypto.c
new file mode 100644
index 0000000..ddad3ec
--- /dev/null
+++ b/examples/platform/silabs/SiWx917/wf200/sl_wfx_crypto.c
@@ -0,0 +1,409 @@
+/*
+ *
+ *    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.
+ */
+
+#ifdef SL_WFX_USE_SECURE_LINK
+
+/* Includes */
+
+#include "sl_wfx.h"
+#include <stdio.h>
+
+#include "mbedtls/ccm.h"
+#include "mbedtls/ctr_drbg.h"
+#include "mbedtls/ecdh.h"
+#include "mbedtls/entropy.h"
+#include "mbedtls/md.h"
+#include "mbedtls/sha256.h"
+
+#include "FreeRTOS.h"
+#include "queue.h"
+#include "semphr.h"
+#include "task.h"
+
+// Secure link MAC key location for WGM160P (in DI page in flash)
+#ifdef EFM32GG11B820F2048GM64 // WGM160PX22KGA2
+#define SL_WFX_FCCC_BASE_ADDR ((void *) 0x0fe08000ul)
+#define SL_WFX_FCCC_DI_OFFSET 0x1B0ul
+#define SL_WFX_FCCC_DI_ADDR ((void *) (SL_WFX_FCCC_BASE_ADDR + SL_WFX_FCCC_DI_OFFSET))
+#define SL_WFX_SECURE_LINK_MAC_KEY_LOCATION ((void *) (SL_WFX_FCCC_BASE_ADDR + 0x3D0))
+#endif
+/******************************************************
+ *                      Macros
+ ******************************************************/
+#define MAC_KEY_FAIL_BYTE 0XFF
+#define KEY_DIGEST_SIZE 92
+#define MEMCMP_FAIL 0
+#define MPI_SET 1
+#define SUCCESS_STATUS_WIFI_SECURE_LINK_EXCHANGE 0
+#define SHA224_0 0
+#define HMAC_SIZE 92
+#define MEMSET_LEN 1
+#define LABLE_LEN 24
+#define ADDRESS_LENGTH 0
+#define CCM_STATUS_SUCCESS 0
+/******************************************************
+ *                    Constants
+ ******************************************************/
+
+/* Semaphore to signal wfx driver available */
+extern TaskHandle_t wfx_securelink_task;
+extern SemaphoreHandle_t wfx_securelink_rx_mutex;
+
+/******************************************************
+ *                   Enumerations
+ ******************************************************/
+
+/******************************************************
+ *                 Type Definitions
+ ******************************************************/
+
+/******************************************************
+ *                    Structures
+ ******************************************************/
+
+/******************************************************
+ *               Function Declarations
+ ******************************************************/
+
+static inline void reverse_bytes(uint8_t * src, uint8_t length);
+
+/******************************************************
+ *               Variable Definitions
+ ******************************************************/
+
+#if SL_WFX_SLK_CURVE25519
+static mbedtls_ecdh_context mbedtls_host_context;
+static mbedtls_ctr_drbg_context host_drbg_context;
+#endif
+static mbedtls_entropy_context entropy;
+uint8_t temp_key_location[SL_WFX_HOST_PUB_KEY_MAC_SIZE];
+#ifdef EFM32GG11B820F2048GM64 // WGM160PX22KGA2
+static const uint8_t * const secure_link_mac_key = (uint8_t *) SL_WFX_SECURE_LINK_MAC_KEY_LOCATION;
+#else
+static const uint8_t secure_link_mac_key[SL_WFX_SECURE_LINK_MAC_KEY_LENGTH] = { 0x2B, 0x49, 0xFD, 0x66, 0xCB, 0x74, 0x6D, 0x6B,
+                                                                                0x4F, 0xDC, 0xC3, 0x79, 0x4E, 0xC5, 0x9A, 0x86,
+                                                                                0xE5, 0x48, 0x2A, 0x41, 0x22, 0x87, 0x8B, 0x12,
+                                                                                0x1A, 0x7C, 0x3E, 0xEF, 0xB7, 0x04, 0x9E, 0xB3 };
+#endif
+/******************************************************
+ *               Function Definitions
+ ******************************************************/
+/****************************************************************************
+ * @fn  sl_status_t sl_wfx_host_get_secure_link_mac_key(uint8_t *sl_mac_key)
+ * @brief
+ * Get secure link mac key
+ * @param[in]  sl_mac_key:
+ * @return  returns SL_STATUS_OK
+ *****************************************************************************/
+sl_status_t sl_wfx_host_get_secure_link_mac_key(uint8_t * sl_mac_key)
+{
+    sl_status_t result = SL_STATUS_WIFI_SECURE_LINK_MAC_KEY_ERROR;
+
+    memcpy(sl_mac_key, secure_link_mac_key, SL_WFX_SECURE_LINK_MAC_KEY_LENGTH);
+
+    for (uint8_t index = 0; index < SL_WFX_SECURE_LINK_MAC_KEY_LENGTH; ++index)
+    {
+        // Assuming 0xFF... when not written
+        if (sl_mac_key[index] != MAC_KEY_FAIL_BYTE)
+        {
+            result = SL_STATUS_OK;
+            break;
+        }
+    }
+
+    return result;
+}
+
+/****************************************************************************
+ * @fn  sl_status_t sl_wfx_host_compute_pub_key(sl_wfx_securelink_exchange_pub_keys_req_body_t *request,
+                                        const uint8_t *sl_mac_key)
+ * @brief
+ * compute host public key
+ * @param[in] request :
+ * @param[in] sl_mac_key :
+ * @return  returns SL_STATUS_OK
+ *****************************************************************************/
+sl_status_t sl_wfx_host_compute_pub_key(sl_wfx_securelink_exchange_pub_keys_req_body_t * request, const uint8_t * sl_mac_key)
+{
+    sl_status_t status = SL_STATUS_OK;
+
+#if SL_WFX_SLK_CURVE25519
+    const char identifier[] = "ecdh";
+
+    mbedtls_ecdh_init(&mbedtls_host_context);
+    mbedtls_ctr_drbg_init(&host_drbg_context);
+    mbedtls_entropy_init(&entropy);
+    status = mbedtls_ctr_drbg_seed(&host_drbg_context, mbedtls_entropy_func, &entropy, (const unsigned char *) identifier,
+                                   sizeof(identifier));
+    status += mbedtls_ecp_group_load(&mbedtls_host_context.grp, MBEDTLS_ECP_DP_CURVE25519);
+    status += mbedtls_ecdh_gen_public(&mbedtls_host_context.grp, &mbedtls_host_context.d, &mbedtls_host_context.Q,
+                                      mbedtls_ctr_drbg_random, &host_drbg_context);
+    status += mbedtls_mpi_write_binary(&mbedtls_host_context.Q.X, request->host_pub_key, SL_WFX_HOST_PUB_KEY_SIZE);
+#else
+    mbedtls_entropy_init(&entropy);
+    status                        = mbedtls_entropy_func(&entropy, request->host_pub_key, SL_WFX_HOST_PUB_KEY_SIZE);
+#endif
+    reverse_bytes(request->host_pub_key, SL_WFX_HOST_PUB_KEY_SIZE);
+    SL_WFX_ERROR_CHECK(status);
+
+    // Generate SHA512 digest of public key
+    status = mbedtls_md_hmac(mbedtls_md_info_from_type(MBEDTLS_MD_SHA512), sl_mac_key, SL_WFX_HOST_PUB_KEY_SIZE,
+                             request->host_pub_key, SL_WFX_HOST_PUB_KEY_SIZE, request->host_pub_key_mac);
+    SL_WFX_ERROR_CHECK(status);
+
+error_handler:
+    if (status != SL_STATUS_OK)
+    {
+        return SL_STATUS_WIFI_SECURE_LINK_EXCHANGE_FAILED;
+    }
+    return status;
+}
+
+/****************************************************************************
+ * @fn  sl_status_t sl_wfx_host_verify_pub_key(sl_wfx_securelink_exchange_pub_keys_ind_t *response_packet,
+                                       const uint8_t *sl_mac_key,
+                                       uint8_t *sl_host_pub_key)
+ * @brief
+ * verify host public key
+ * @param[in]  response_packet:
+ * @param[in]  sl_mac_key:
+ * @param[in]  sl_host_pub_key:
+ * @return returns SL_STATUS_OK if successful,
+ *         SL_STATUS_FAIL otherwise
+ *****************************************************************************/
+sl_status_t sl_wfx_host_verify_pub_key(sl_wfx_securelink_exchange_pub_keys_ind_t * response_packet, const uint8_t * sl_mac_key,
+                                       uint8_t * sl_host_pub_key)
+{
+    sl_status_t status = SL_STATUS_OK;
+    uint8_t shared_key_digest[KEY_DIGEST_SIZE];
+
+    if (xSemaphoreTake(wfx_securelink_rx_mutex, portMAX_DELAY) != pdTRUE)
+    {
+        return SL_STATUS_WIFI_SECURE_LINK_EXCHANGE_FAILED;
+    }
+
+    // Compute the Hash and verify the public key/hashing
+    status = mbedtls_md_hmac(mbedtls_md_info_from_type(MBEDTLS_MD_SHA512), sl_mac_key, SL_WFX_NCP_PUB_KEY_SIZE,
+                             response_packet->body.ncp_pub_key, SL_WFX_NCP_PUB_KEY_SIZE, temp_key_location);
+    SL_WFX_ERROR_CHECK(status);
+
+    // Calculate session key if public key/SHA512 digest matches
+    if (memcmp(temp_key_location, response_packet->body.ncp_pub_key_mac, SL_WFX_HOST_PUB_KEY_MAC_SIZE) != MEMCMP_FAIL)
+    {
+        status = SL_STATUS_WIFI_SECURE_LINK_EXCHANGE_FAILED;
+        goto error_handler;
+    }
+
+#if SL_WFX_SLK_CURVE25519
+    SL_WFX_UNUSED_PARAMETER(sl_host_pub_key);
+
+    mbedtls_mpi_lset(&mbedtls_host_context.Qp.Z, MPI_SET);
+
+    // Read Ineo public key
+    reverse_bytes(response_packet->body.ncp_pub_key, SL_WFX_NCP_PUB_KEY_SIZE);
+    mbedtls_mpi_read_binary(&mbedtls_host_context.Qp.X, response_packet->body.ncp_pub_key, SL_WFX_NCP_PUB_KEY_SIZE);
+
+    // Calculate shared secret
+    if (mbedtls_ecdh_compute_shared(&mbedtls_host_context.grp, &mbedtls_host_context.z, &mbedtls_host_context.Qp,
+                                    &mbedtls_host_context.d, mbedtls_ctr_drbg_random,
+                                    &host_drbg_context) != SUCCESS_STATUS_WIFI_SECURE_LINK_EXCHANGE)
+    {
+        status = SL_STATUS_WIFI_SECURE_LINK_EXCHANGE_FAILED;
+        goto error_handler;
+    }
+
+    // Generate session key
+    mbedtls_mpi_write_binary(&mbedtls_host_context.z, temp_key_location, SL_WFX_HOST_PUB_KEY_SIZE);
+    reverse_bytes(temp_key_location, SL_WFX_HOST_PUB_KEY_SIZE);
+    mbedtls_sha256(temp_key_location, SL_WFX_HOST_PUB_KEY_SIZE, shared_key_digest, SHA224_0);
+#else
+    uint8_t hmac_input[HMAC_SIZE] = { 0 };
+    char label[LABLE_LEN]         = "SecureLink!KeyDerivation";
+
+    memset((uint16_t *) &hmac_input[0], (uint16_t) sl_wfx_htole16(1), MEMSET_LEN);
+    memcpy((uint8_t *) &hmac_input[2], (uint8_t *) label, LABLE_LEN);
+    memcpy((uint8_t *) &hmac_input[26], sl_host_pub_key, SL_WFX_NCP_PUB_KEY_SIZE);
+    memcpy((uint8_t *) &hmac_input[58], (uint8_t *) response_packet->body.ncp_pub_key, SL_WFX_NCP_PUB_KEY_SIZE);
+    memset((uint16_t *) &hmac_input[90], (uint16_t) sl_wfx_htole16(128), 1);
+
+    // Generate SHA256 digest of hmac_input
+    status = mbedtls_md_hmac(mbedtls_md_info_from_type(MBEDTLS_MD_SHA256), sl_mac_key, SL_WFX_HOST_PUB_KEY_SIZE,
+                             (uint8_t *) hmac_input, HMAC_SIZE, shared_key_digest);
+#endif
+
+    memcpy(sl_wfx_context->secure_link_session_key, shared_key_digest,
+           SL_WFX_SECURE_LINK_SESSION_KEY_LENGTH); // Use the lower 16 bytes of the sha256
+    sl_wfx_context->secure_link_nonce.hp_packet_count = 0;
+    sl_wfx_context->secure_link_nonce.rx_packet_count = 0;
+    sl_wfx_context->secure_link_nonce.tx_packet_count = 0;
+
+error_handler:
+    if (xSemaphoreGive(wfx_securelink_rx_mutex) != pdTRUE)
+    {
+        printf("ERROR: sl_wfx_securelink_rx_mutex. unable to post.\n");
+    }
+    return status;
+}
+
+/****************************************************************************
+ * @fn  sl_status_t sl_wfx_host_free_crypto_context(void)
+ * @brief
+ * Free host crypto context
+ * @param[in] None
+ * @return returns SL_STATUS_OK
+ *****************************************************************************/
+sl_status_t sl_wfx_host_free_crypto_context(void)
+{
+#if SL_WFX_SLK_CURVE25519
+    mbedtls_ecdh_free(&mbedtls_host_context);
+    mbedtls_ctr_drbg_free(&host_drbg_context);
+#endif
+    mbedtls_entropy_free(&entropy);
+
+    return SL_STATUS_OK;
+}
+
+/********************************************************************************
+ * @fn   sl_status_t sl_wfx_host_decode_secure_link_data(uint8_t *buffer, uint32_t length, uint8_t *session_key)
+ * @brief
+ * Decode receive data
+ * Length excludes size of CCM tag and secure link header
+ * @param[in] buffer:
+ * @param[in] length:
+ * @param[in] session_key:
+ * @return returns SL_STATUS_OK if successful,
+ *         SL_STATUS_FAIL otherwise
+ ********************************************************************************/
+sl_status_t sl_wfx_host_decode_secure_link_data(uint8_t * buffer, uint32_t length, uint8_t * session_key)
+{
+    mbedtls_ccm_context ccm_context;
+    sl_status_t status = SL_STATUS_SECURITY_DECRYPT_ERROR;
+    int crypto_status;
+    sl_wfx_nonce_t nonce = { 0, 0, 0 };
+
+    if (xSemaphoreTake(wfx_securelink_rx_mutex, portMAX_DELAY) != pdTRUE)
+    {
+        return SL_STATUS_FAIL;
+    }
+
+    // Nonce for decryption should have TX and HP counters 0, only use RX counter
+    nonce.rx_packet_count = sl_wfx_context->secure_link_nonce.rx_packet_count;
+
+    // Init context
+    mbedtls_ccm_init(&ccm_context);
+
+    // Set the crypto key
+    crypto_status = mbedtls_ccm_setkey(&ccm_context, MBEDTLS_CIPHER_ID_AES, session_key, SL_WFX_SECURE_LINK_SESSION_KEY_BIT_COUNT);
+    SL_WFX_ERROR_CHECK(crypto_status);
+
+    // Decrypt the data
+    if (!mbedtls_ccm_auth_decrypt(&ccm_context, length, (uint8_t *) &nonce, SL_WFX_SECURE_LINK_NONCE_SIZE_BYTES, NULL,
+                                  ADDRESS_LENGTH, (uint8_t *) buffer, (uint8_t *) buffer, (uint8_t *) buffer + length,
+                                  SL_WFX_SECURE_LINK_CCM_TAG_SIZE))
+    {
+        status = SL_STATUS_OK;
+    }
+
+error_handler:
+    mbedtls_ccm_free(&ccm_context);
+    if (xSemaphoreGive(wfx_securelink_rx_mutex) != pdTRUE)
+    {
+        printf("ERROR: sl_wfx_securelink_rx_mutex. unable to post.\n");
+    }
+    return status;
+}
+
+/*********************************************************************
+ * @fn  sl_status_t sl_wfx_host_encode_secure_link_data(sl_wfx_generic_message_t *buffer,
+                                                uint32_t data_length,
+                                                uint8_t *session_key,
+                                                uint8_t *nonce)
+ * @brief
+ * Encode transmit data
+ * Length excludes size of CCM tag and secure link header
+ * @param[in]  buffer:
+ * @param[in]  data_length:
+ * @param[in]  session_key:
+ * @param[in]  nonce:
+ * @return  returns SL_STATUS_OK if successful,
+ *         SL_STATUS_FAIL otherwise
+*************************************************************************/
+sl_status_t sl_wfx_host_encode_secure_link_data(sl_wfx_generic_message_t * buffer, uint32_t data_length, uint8_t * session_key,
+                                                uint8_t * nonce)
+{
+    mbedtls_ccm_context ccm_context;
+    sl_status_t status = SL_STATUS_FAIL;
+
+    mbedtls_ccm_init(&ccm_context);
+    if (mbedtls_ccm_setkey(&ccm_context, MBEDTLS_CIPHER_ID_AES, session_key, SL_WFX_SECURE_LINK_SESSION_KEY_BIT_COUNT) ==
+        CCM_STATUS_SUCCESS)
+    {
+        mbedtls_ccm_encrypt_and_tag(&ccm_context, data_length, nonce, SL_WFX_SECURE_LINK_NONCE_SIZE_BYTES, NULL, ADDRESS_LENGTH,
+                                    (uint8_t *) &buffer->header.id, (uint8_t *) &buffer->header.id,
+                                    (uint8_t *) &buffer->header.id + data_length, SL_WFX_SECURE_LINK_CCM_TAG_SIZE);
+        status = SL_STATUS_OK;
+    }
+
+    mbedtls_ccm_free(&ccm_context);
+
+    return status;
+}
+
+/****************************************************************************
+ * @fn  sl_status_t sl_wfx_host_schedule_secure_link_renegotiation(void)
+ * @brief
+ * Called when the driver needs to schedule secure link renegotiation
+ * @param[in] None
+ * @returns Returns SL_STATUS_OK if successful,
+ *          SL_STATUS_FAIL otherwise
+ *****************************************************************************/
+sl_status_t sl_wfx_host_schedule_secure_link_renegotiation(void)
+{
+    // call sl_wfx_secure_link_renegotiate_session_key() as soon as it makes sense for the host to do so
+    xTaskNotifyGive(wfx_securelink_task);
+    return SL_STATUS_OK;
+}
+
+/****************************************************************************
+ * @fn  static inline void reverse_bytes(uint8_t *src, uint8_t length)
+ * @brief
+ *         reverse the bytes
+ * @param[in] src: source
+ * @param[in] length:
+ * @returns None
+ *****************************************************************************/
+static inline void reverse_bytes(uint8_t * src, uint8_t length)
+{
+    uint8_t * lo = src;
+    uint8_t * hi = src + length - 1;
+    uint8_t swap;
+
+    while (lo < hi)
+    {
+        swap  = *lo;
+        *lo++ = *hi;
+        *hi-- = swap;
+    }
+}
+
+/********************************************************************************************************
+ ********************************************************************************************************
+ *                                       DEPENDENCIES & AVAIL CHECK(S)
+ ********************************************************************************************************
+ *******************************************************************************************************/
+
+#endif // SL_WFX_USE_SECURE_LINK
diff --git a/examples/platform/silabs/SiWx917/wf200/sl_wfx_host.h b/examples/platform/silabs/SiWx917/wf200/sl_wfx_host.h
new file mode 100644
index 0000000..dc9bcd2
--- /dev/null
+++ b/examples/platform/silabs/SiWx917/wf200/sl_wfx_host.h
@@ -0,0 +1,52 @@
+/*
+ *
+ *    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 "FreeRTOS.h"
+#include "queue.h"
+#include "semphr.h"
+#include "sl_wfx.h"
+#include "task.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+uint8_t sl_wfx_host_get_waited_event(void);
+sl_status_t wfx_soft_init(void);
+
+#ifdef SLEEP_ENABLED
+sl_status_t sl_wfx_host_switch_to_wirq(void);
+#endif
+#ifdef __cplusplus
+}
+#endif
+
+#define SL_WFX_MAX_STATIONS 8
+#define SL_WFX_MAX_SCAN_RESULTS 50
+
+typedef struct __attribute__((__packed__)) scan_result_list_s
+{
+    sl_wfx_ssid_def_t ssid_def;
+    uint8_t mac[SL_WFX_MAC_ADDR_SIZE];
+    uint16_t channel;
+    sl_wfx_security_mode_bitmask_t security_mode;
+    uint16_t rcpi;
+} scan_result_list_t;
+
+void sl_wfx_host_start_platform_interrupt(void);
+extern SemaphoreHandle_t wfx_wakeup_sem;
diff --git a/examples/platform/silabs/SiWx917/wf200/sl_wfx_securelink_task.c b/examples/platform/silabs/SiWx917/wf200/sl_wfx_securelink_task.c
new file mode 100644
index 0000000..28ffdda
--- /dev/null
+++ b/examples/platform/silabs/SiWx917/wf200/sl_wfx_securelink_task.c
@@ -0,0 +1,85 @@
+/*
+ *
+ *    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.
+ */
+
+#ifdef SL_WFX_USE_SECURE_LINK
+#include "secure_link/sl_wfx_secure_link.h"
+
+#include "FreeRTOS.h"
+#include "queue.h"
+#include "semphr.h"
+#include "task.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+// Securelink Task Configurations
+#define WFX_SECURELINK_TASK_PRIO 1u
+#define WFX_SECURELINK_TASK_STK_SIZE 512u
+
+TaskHandle_t secureLinkTaskHandle;
+SemaphoreHandle_t s_xSLSemaphore;
+StackType_t secureLinkStack[WFX_SECURELINK_TASK_STK_SIZE];
+StaticTask_t secureLinkTaskStruct;
+
+StaticSemaphore_t xSlMutexBuffer;
+
+/*********************************************************************
+ * @fn  static void prvSecureLinkTask(void *p_arg)
+ * @brief
+ * The task that implements the Secure Link renegotiation with WFX.
+ * @param[in] p_arg:
+ * @return None
+ *************************************************************************/
+static void prvSecureLinkTask(void * p_arg)
+{
+    sl_status_t result;
+    (void) p_arg;
+
+    /* Create a mutex used for making Secure Link renegotiations atomic */
+    s_xSLSemaphore = xSemaphoreCreateMutexStatic(&xSlMutexBuffer);
+
+    for (;;)
+    {
+        /* Wait for a key renegotiation request */
+        ulTaskNotifyTake(pdTRUE, portMAX_DELAY);
+
+        result = sl_wfx_secure_link_renegotiate_session_key();
+        if (result != SL_STATUS_OK)
+        {
+            printf("session key negotiation error %lu\n", result);
+        }
+    }
+}
+
+/****************************************************************************
+ * @fn  void wfx_securelink_task_start(void)
+ * @brief
+ * Creates WFX securelink key renegotiation task.
+ * @param[in] None
+ * @return None
+ ******************************************************************************/
+void wfx_securelink_task_start(void)
+{
+    secureLinkTaskHandle = xTaskCreateStatic(prvSecureLinkTask, "secureLinkTask", WFX_SECURELINK_TASK_STK_SIZE, NULL,
+                                             WFX_SECURELINK_TASK_PRIO, secureLinkStack, &secureLinkTaskStruct);
+    if (secureLinkTaskHandle == NULL)
+    {
+        printf("Failed to create WFX secureLinkTask");
+    }
+}
+
+#endif
diff --git a/examples/platform/silabs/SiWx917/wf200/sl_wfx_task.c b/examples/platform/silabs/SiWx917/wf200/sl_wfx_task.c
new file mode 100644
index 0000000..8a00e45
--- /dev/null
+++ b/examples/platform/silabs/SiWx917/wf200/sl_wfx_task.c
@@ -0,0 +1,128 @@
+/*
+ *
+ *    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 <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "em_gpio.h"
+
+#include "sl_wfx.h"
+#include "sl_wfx_board.h"
+#include "sl_wfx_host.h"
+#include "sl_wfx_task.h"
+
+#include "FreeRTOS.h"
+#include "event_groups.h"
+#include "task.h"
+
+#include "AppConfig.h"
+
+#define CHECK_VAL 0
+#define WFX_BUS_TASK_PRIORITY 2
+#define BUS_TASK_STACK_SIZE 1024
+static StackType_t busStack[BUS_TASK_STACK_SIZE];
+StaticTask_t busTaskStruct;
+TaskHandle_t wfx_bus_task_handle;
+
+wfx_frame_q_item wfx_bus_tx_frame;
+SemaphoreHandle_t wfxtask_tx_complete;
+SemaphoreHandle_t wfxtask_mutex;
+
+// Flag to indicate receive frames is currently running.
+static bool wfx_bus_rx_in_process = false;
+
+/***************************************************************************
+ * @fn  bool wfx_bus_is_receive_processing(void)
+ * @brief
+ * Check receive frame status
+ * @param[in]  None
+ * @return returns wfx_bus_rx_in_process
+ ******************************************************************************/
+bool wfx_bus_is_receive_processing(void)
+{
+    return wfx_bus_rx_in_process;
+}
+
+/*****************************************************************************
+ * @fn  static sl_status_t receive_frames()
+ * @brief
+ * Receives frames from the WFX.
+ * @param[in] None
+ * @return returns result
+ ******************************************************************************/
+static sl_status_t receive_frames()
+{
+    sl_status_t result;
+    uint16_t control_register = 0;
+    wfx_bus_rx_in_process     = true;
+    do
+    {
+        result = sl_wfx_receive_frame(&control_register);
+        SL_WFX_ERROR_CHECK(result);
+    } while ((control_register & SL_WFX_CONT_NEXT_LEN_MASK) != CHECK_VAL);
+
+error_handler:
+    wfx_bus_rx_in_process = false;
+    return result;
+}
+
+/********************************************************************************
+ * @fn  static void wfx_bus_task(void *p_arg)
+ * @brief
+ * WFX bus communication task.
+ * receives frames from the Bus interface
+ * @param[in] p_arg:
+ * @return None
+ */
+static void wfx_bus_task(void * p_arg)
+{
+    SILABS_LOG("SPI: Bus Task started");
+    sl_wfx_host_start_platform_interrupt();
+    for (;;)
+    {
+        /*Wait for an interrupt from WFX*/
+        ulTaskNotifyTake(pdTRUE, portMAX_DELAY);
+
+        /*Disable the interrupt while treating frames received to avoid
+         *the case where the interrupt is set but there is no frame left to treat.*/
+        sl_wfx_host_disable_platform_interrupt();
+
+        /*Receive the frame(s) pending in WFX*/
+        receive_frames();
+
+        /*Re-enable the interrupt*/
+        sl_wfx_host_enable_platform_interrupt();
+    }
+}
+
+/***************************************************************************
+ * @fn  void wfx_bus_start()
+ * @brief
+ * Creates WFX bus communication task.
+ * @param[in] None
+ * @return None
+ ******************************************************************************/
+void wfx_bus_start()
+{
+    wfx_bus_task_handle =
+        xTaskCreateStatic(wfx_bus_task, "wfxbus", BUS_TASK_STACK_SIZE, NULL, WFX_BUS_TASK_PRIORITY, busStack, &busTaskStruct);
+    if (wfx_bus_task_handle == NULL)
+    {
+        SILABS_LOG("*ERR*WFX BusTask");
+    }
+}
diff --git a/examples/platform/silabs/SiWx917/wf200/sl_wfx_task.h b/examples/platform/silabs/SiWx917/wf200/sl_wfx_task.h
new file mode 100644
index 0000000..6838b9b
--- /dev/null
+++ b/examples/platform/silabs/SiWx917/wf200/sl_wfx_task.h
@@ -0,0 +1,57 @@
+/*
+ *
+ *    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 <stdbool.h>
+
+#include "FreeRTOS.h"
+#include "sl_wfx_constants.h"
+#include "task.h"
+
+typedef struct
+{
+    sl_wfx_send_frame_req_t * frame;
+    uint32_t data_length;
+    sl_wfx_interface_t interface;
+    uint8_t priority;
+} wfx_frame_q_item;
+
+extern wfx_frame_q_item wfxtask_tx_frame;
+extern TaskHandle_t wfx_bus_task_handle;
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/****************************************************************************
+ * @fn void wfx_bus_start(void)
+ * @brief
+ * Start wfx bus communication task.
+ *****************************************************************************/
+void wfx_bus_start(void);
+
+/****************************************************************************
+ * @fn  bool wfx_bus_is_receive_processing(void)
+ * @brief
+ * Returns status of wfx receive frames.
+ *****************************************************************************/
+bool wfx_bus_is_receive_processing(void);
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/examples/platform/silabs/SiWx917/wf200/wf200.gni b/examples/platform/silabs/SiWx917/wf200/wf200.gni
new file mode 100644
index 0000000..358384a
--- /dev/null
+++ b/examples/platform/silabs/SiWx917/wf200/wf200.gni
@@ -0,0 +1,30 @@
+import("//build_overrides/chip.gni")
+import("//build_overrides/efr32_sdk.gni")
+import("//build_overrides/pigweed.gni")
+
+examples_plat_dir = "${chip_root}/examples/platform/silabs/efr32"
+wifi_sdk_dir = "${chip_root}/src/platform/silabs/EFR32/wifi"
+
+wf200_defs = [
+  "SL_HEAP_SIZE=24576",
+  "WF200_WIFI=1",
+  "SL_WIFI=1",
+  "SL_WFX_USE_SPI",
+  "SL_WFX_DEBUG_MASK=0x0003",
+]
+softap_defs = "SL_WFX_CONFIG_SOFTAP"
+wifi_scan_defs = "SL_WFX_CONFIG_SCAN"
+wf200_plat_incs = [
+  "${wifi_sdk_dir}/",
+  "${examples_plat_dir}/wf200",
+]
+wf200_plat_src = [
+  "${wifi_sdk_dir}/dhcp_client.cpp",
+  "${wifi_sdk_dir}/ethernetif.cpp",
+  "${wifi_sdk_dir}/lwip_netif.cpp",
+  "${wifi_sdk_dir}/wfx_notify.cpp",
+  "${examples_plat_dir}/wf200/sl_wfx_task.c",
+  "${examples_plat_dir}/wf200/wf200_init.c",
+  "${examples_plat_dir}/wf200/efr_spi.c",
+  "${examples_plat_dir}/wf200/host_if.cpp",
+]
diff --git a/examples/platform/silabs/SiWx917/wf200/wf200_init.c b/examples/platform/silabs/SiWx917/wf200/wf200_init.c
new file mode 100644
index 0000000..12973d3
--- /dev/null
+++ b/examples/platform/silabs/SiWx917/wf200/wf200_init.c
@@ -0,0 +1,543 @@
+/*
+ *
+ *    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.
+ */
+
+/* Includes */
+
+#include "em_gpio.h"
+
+#include "sl_wfx.h"
+#include "sl_wfx_board.h"
+
+// File specific to each platform, it must be created for custom boards
+#include "sl_wfx_pds.h"
+
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+/* Firmware include */
+#include "sl_wfx_wf200_C0.h"
+
+#include "FreeRTOS.h"
+#include "event_groups.h"
+#include "task.h"
+
+#include "AppConfig.h"
+#include "sl_wfx_host.h"
+#include "sl_wfx_task.h"
+#include "wfx_host_events.h"
+
+#include "sl_spidrv_instances.h"
+#include "spidrv.h"
+
+#define SL_WFX_EVENT_MAX_SIZE 512
+#define SL_WFX_EVENT_LIST_SIZE 1
+
+StaticSemaphore_t xWfxWakeupSemaBuffer;
+uint8_t sWfxEventQueueBuffer[SL_WFX_EVENT_LIST_SIZE * sizeof(uint8_t)];
+StaticQueue_t sWfxEventQueueStruct;
+QueueHandle_t wfx_event_Q        = NULL;
+SemaphoreHandle_t wfx_wakeup_sem = NULL;
+SemaphoreHandle_t wfx_mutex      = NULL;
+
+StaticSemaphore_t xWfxMutexBuffer;
+
+struct
+{
+    uint32_t wf200_firmware_download_progress;
+    int wf200_initialized;
+    uint8_t waited_event_id;
+    uint8_t posted_event_id;
+} host_context;
+
+#ifdef SL_WFX_USE_SDIO
+#ifdef SLEEP_ENABLED
+sl_status_t sl_wfx_host_enable_sdio(void);
+sl_status_t sl_wfx_host_disable_sdio(void);
+#endif
+#endif
+
+#ifdef SL_WFX_USE_SPI
+#ifdef SLEEP_ENABLED
+sl_status_t sl_wfx_host_enable_spi(void);
+sl_status_t sl_wfx_host_disable_spi(void);
+#endif
+#endif
+
+/****************************************************************************
+ * @fn  sl_status_t wfx_soft_init(void)
+ * @brief
+ * WFX FMAC driver host interface initialization
+ * @param[in] None
+ * @returns Returns SL_STATUS_OK if successful,
+ *          SL_STATUS_FAIL otherwise
+ *****************************************************************************/
+sl_status_t wfx_soft_init(void)
+{
+    SILABS_LOG("WF200:Soft Init");
+    if ((wfx_event_Q = xQueueCreateStatic(SL_WFX_EVENT_LIST_SIZE, sizeof(uint8_t), sWfxEventQueueBuffer, &sWfxEventQueueStruct)) ==
+        NULL)
+    {
+        return SL_STATUS_FAIL;
+    }
+
+    if ((wfx_wakeup_sem = xSemaphoreCreateBinaryStatic(&xWfxWakeupSemaBuffer)) == NULL)
+    {
+        return SL_STATUS_FAIL;
+    }
+
+    if ((wfx_mutex = xSemaphoreCreateMutexStatic(&xWfxMutexBuffer)) == NULL)
+    {
+        return SL_STATUS_FAIL;
+    }
+
+    return SL_STATUS_OK;
+}
+/****************************************************************************
+ * @fn  sl_status_t sl_wfx_host_init(void)
+ * @brief
+ * Notify driver init function
+ * @param[in] None
+ * @returns Returns SL_STATUS_OK if successful,
+ *          SL_STATUS_FAIL otherwise
+ *****************************************************************************/
+sl_status_t sl_wfx_host_init(void)
+{
+    SILABS_LOG("WFX: Host Init");
+    host_context.wf200_firmware_download_progress = 0;
+    host_context.wf200_initialized                = 0;
+    return SL_STATUS_OK;
+}
+
+/****************************************************************************
+ * @fn   sl_status_t sl_wfx_host_get_firmware_data(const uint8_t **data, uint32_t data_size)
+ * @brief
+ * Get firmware data
+ * @param[in] data:
+ * @param[in] data_size:
+ * @returns Returns SL_STATUS_OK if successful,
+ *          SL_STATUS_FAIL otherwise
+ *****************************************************************************/
+sl_status_t sl_wfx_host_get_firmware_data(const uint8_t ** data, uint32_t data_size)
+{
+    *data = &sl_wfx_firmware[host_context.wf200_firmware_download_progress];
+    host_context.wf200_firmware_download_progress += data_size;
+    return SL_STATUS_OK;
+}
+
+/****************************************************************************
+ * @fn   sl_status_t sl_wfx_host_get_firmware_size(uint32_t *firmware_size)
+ * @brief
+ * Get firmware size
+ * @param[in] firmware_size:
+ * @returns Returns SL_STATUS_OK if successful,
+ *         SL_STATUS_FAIL otherwise
+ *****************************************************************************/
+sl_status_t sl_wfx_host_get_firmware_size(uint32_t * firmware_size)
+{
+    *firmware_size = sizeof(sl_wfx_firmware);
+    return SL_STATUS_OK;
+}
+
+/****************************************************************************
+ * @fn   sl_status_t sl_wfx_host_get_pds_data(const char **pds_data, uint16_t index)
+ * @brief
+ * Get PDS data
+ * @param[in] pds_data:
+ * @param[in] index:
+ * @returns Returns SL_STATUS_OK if successful,
+ *SL_STATUS_FAIL otherwise
+ *****************************************************************************/
+sl_status_t sl_wfx_host_get_pds_data(const char ** pds_data, uint16_t index)
+{
+    *pds_data = sl_wfx_pds[index];
+    return SL_STATUS_OK;
+}
+
+/****************************************************************************
+ * @fn  sl_status_t sl_wfx_host_get_pds_size(uint16_t *pds_size)
+ * @brief
+ * Get PDS size
+ * @param[in] pds_size:
+ * @returns Returns SL_STATUS_OK if successful,
+ *SL_STATUS_FAIL otherwise
+ *****************************************************************************/
+sl_status_t sl_wfx_host_get_pds_size(uint16_t * pds_size)
+{
+    *pds_size = SL_WFX_ARRAY_COUNT(sl_wfx_pds);
+    return SL_STATUS_OK;
+}
+
+/****************************************************************************
+ * @fn  sl_status_t sl_wfx_host_deinit(void)
+ * @brief
+ * Deinit host interface
+ * @param[in] None
+ * @returns Returns SL_STATUS_OK if successful,
+ *SL_STATUS_FAIL otherwise
+ *****************************************************************************/
+sl_status_t sl_wfx_host_deinit(void)
+{
+    return SL_STATUS_OK;
+}
+
+/****************************************************************************
+ * @fn  sl_status_t sl_wfx_host_allocate_buffer(void **buffer, sl_wfx_buffer_type_t type, uint32_t buffer_size)
+ * @brief
+ * Allocate buffer (Should allocate either Ethernet - from LWIP or Control) - TODO
+ * @param[in] buffer:
+ * @param[in] type:
+ * @param[in] buffer_size:
+ * @returns Returns SL_STATUS_OK if successful,
+ *SL_STATUS_FAIL otherwise
+ *****************************************************************************/
+sl_status_t sl_wfx_host_allocate_buffer(void ** buffer, sl_wfx_buffer_type_t type, uint32_t buffer_size)
+{
+    if ((*buffer = pvPortMalloc(buffer_size)) == (void *) 0)
+    {
+        return SL_STATUS_FAIL;
+    }
+    return SL_STATUS_OK;
+}
+
+/****************************************************************************
+ * @fn  sl_status_t sl_wfx_host_free_buffer(void *buffer, sl_wfx_buffer_type_t type)
+ * @brief
+ * Free host buffer (CHECK LWIP buffer)
+ * @param[in] buffer:
+ * @param[in] type:
+ * @returns Returns SL_STATUS_OK if successful,
+ *SL_STATUS_FAIL otherwise
+ *****************************************************************************/
+sl_status_t sl_wfx_host_free_buffer(void * buffer, sl_wfx_buffer_type_t type)
+{
+    vPortFree(buffer);
+    return SL_STATUS_OK;
+}
+
+/****************************************************************************
+ * @fn  sl_status_t sl_wfx_host_hold_in_reset(void)
+ * @brief
+ * Set reset pin low
+ * @param[in] None
+ * @returns Returns SL_STATUS_OK if successful,
+ *SL_STATUS_FAIL otherwise
+ *****************************************************************************/
+sl_status_t sl_wfx_host_hold_in_reset(void)
+{
+    GPIO_PinOutClear(SL_WFX_HOST_PINOUT_RESET_PORT, SL_WFX_HOST_PINOUT_RESET_PIN);
+    host_context.wf200_initialized = 0;
+    return SL_STATUS_OK;
+}
+
+/****************************************************************************
+ * @fn  sl_status_t sl_wfx_host_set_wake_up_pin(uint8_t state)
+ * @brief
+ * Set wakeup pin status
+ * @param[in] state:
+ * @returns Returns SL_STATUS_OK if successful,
+ *SL_STATUS_FAIL otherwise
+ *****************************************************************************/
+sl_status_t sl_wfx_host_set_wake_up_pin(uint8_t state)
+{
+    CORE_DECLARE_IRQ_STATE;
+
+    CORE_ENTER_ATOMIC();
+    if (state > PINOUT_CLEAR_STATUS)
+    {
+#ifdef SLEEP_ENABLED
+#ifdef SL_WFX_USE_SDIO
+        sl_wfx_host_enable_sdio();
+#endif
+#ifdef SL_WFX_USE_SPI
+        sl_wfx_host_enable_spi();
+#endif
+#endif
+        GPIO_PinOutSet(SL_WFX_HOST_PINOUT_WUP_PORT, SL_WFX_HOST_PINOUT_WUP_PIN);
+    }
+    else
+    {
+        GPIO_PinOutClear(SL_WFX_HOST_PINOUT_WUP_PORT, SL_WFX_HOST_PINOUT_WUP_PIN);
+#ifdef SLEEP_ENABLED
+#ifdef SL_WFX_USE_SDIO
+        sl_wfx_host_disable_sdio();
+#endif
+#ifdef SL_WFX_USE_SPI
+        sl_wfx_host_disable_spi();
+#endif
+#endif
+    }
+    CORE_EXIT_ATOMIC();
+    return SL_STATUS_OK;
+}
+
+/****************************************************************************
+ * @fn  sl_status_t sl_wfx_host_reset_chip(void)
+ * @brief
+ * reset the host chip
+ * @returns Returns SL_STATUS_OK if successful,
+ *SL_STATUS_FAIL otherwise
+ *****************************************************************************/
+sl_status_t sl_wfx_host_reset_chip(void)
+{
+    // Pull it low for at least 1 ms to issue a reset sequence
+    GPIO_PinOutClear(SL_WFX_HOST_PINOUT_RESET_PORT, SL_WFX_HOST_PINOUT_RESET_PIN);
+
+    // Delay for 10ms
+    vTaskDelay(pdMS_TO_TICKS(10));
+
+    // Hold pin high to get chip out of reset
+    GPIO_PinOutSet(SL_WFX_HOST_PINOUT_RESET_PORT, SL_WFX_HOST_PINOUT_RESET_PIN);
+
+    // Delay for 3ms
+    vTaskDelay(pdMS_TO_TICKS(3));
+
+    host_context.wf200_initialized = 0;
+    return SL_STATUS_OK;
+}
+
+/****************************************************************************
+ * @fn  sl_status_t sl_wfx_host_wait_for_wake_up(void)
+ * @brief
+ * wait for the host wake up
+ * @returns Returns SL_STATUS_OK if successful,
+ *SL_STATUS_FAIL otherwise
+ *****************************************************************************/
+sl_status_t sl_wfx_host_wait_for_wake_up(void)
+{
+    xSemaphoreTake(wfx_wakeup_sem, TICKS_TO_WAIT_0);
+    xSemaphoreTake(wfx_wakeup_sem, TICKS_TO_WAIT_3 / portTICK_PERIOD_MS);
+
+    return SL_STATUS_OK;
+}
+
+/****************************************************************************
+ * @fn  sl_status_t sl_wfx_host_wait(uint32_t wait_time)
+ * @brief
+ * wait for the host
+ * @param[in]  wait_time:
+ * @returns Returns SL_STATUS_OK if successful,
+ *SL_STATUS_FAIL otherwise
+ *****************************************************************************/
+
+sl_status_t sl_wfx_host_wait(uint32_t wait_time)
+{
+    uint32_t ticks = pdMS_TO_TICKS(wait_time);
+    vTaskDelay(ticks ? ticks : 10);
+    return SL_STATUS_OK;
+}
+
+/****************************************************************************
+ * @fn   sl_status_t sl_wfx_host_setup_waited_event(uint8_t event_id)
+ * @brief
+ * Called when the driver needs to setup the waited event
+ * @param[in] event_id:
+ * @returns Returns SL_STATUS_OK if successful,
+ *SL_STATUS_FAIL otherwise
+ *****************************************************************************/
+
+sl_status_t sl_wfx_host_setup_waited_event(uint8_t event_id)
+{
+    host_context.waited_event_id = event_id;
+    host_context.posted_event_id = 0;
+
+    return SL_STATUS_OK;
+}
+
+/****************************************************************************
+ * @fn  uint8_t sl_wfx_host_get_waited_event(void)
+ * @brief
+ * Called when the driver get waited event
+ * @returns returns host_context.waited_event_id
+ *****************************************************************************/
+
+uint8_t sl_wfx_host_get_waited_event(void)
+{
+    return host_context.waited_event_id;
+}
+
+/******************************************************************************
+ * @fn  sl_status_t sl_wfx_host_wait_for_confirmation(uint8_t confirmation_id, uint32_t timeout, void **event_payload_out)
+ * @brief
+ * wait for the host confirmation
+ * @param[in] confirmation_id:
+ * @param[in] timeout:
+ * @param[in] event_payload_out:
+ * @returns Returns SL_STATUS_OK if successful,
+ * Timeout, SL_STATUS_TIMEOUT otherwise
+ *****************************************************************************/
+
+sl_status_t sl_wfx_host_wait_for_confirmation(uint8_t confirmation_id, uint32_t timeout, void ** event_payload_out)
+{
+    uint8_t posted_event_id;
+    for (uint32_t i = 0; i < timeout; i++)
+    {
+        /* Wait for an event posted by the function sl_wfx_host_post_event() */
+        if (xQueueReceive(wfx_event_Q, &posted_event_id, TICKS_TO_WAIT_1) == pdTRUE)
+        {
+            /* Once a message is received, check if it is the expected ID */
+            if (confirmation_id == posted_event_id)
+            {
+                /* Pass the confirmation reply and return*/
+                if (event_payload_out != NULL)
+                {
+                    *event_payload_out = sl_wfx_context->event_payload_buffer;
+                }
+                return SL_STATUS_OK;
+            }
+        }
+    }
+    /* The wait for the confirmation timed out, return */
+    return SL_STATUS_TIMEOUT;
+}
+
+/****************************************************************************
+ * @fn  sl_status_t sl_wfx_host_lock(void)
+ * @brief
+ * Called when the driver needs to lock its access
+ * @returns Returns SL_STATUS_OK if successful,
+ *SL_STATUS_TIMEOUT otherwise
+ *****************************************************************************/
+sl_status_t sl_wfx_host_lock(void)
+{
+
+    sl_status_t status = SL_STATUS_OK;
+
+    if (xSemaphoreTake(wfx_mutex, TICKS_TO_WAIT_500) != pdTRUE)
+    {
+        SILABS_LOG("*ERR*Wi-Fi driver mutex timo");
+        status = SL_STATUS_TIMEOUT;
+    }
+
+    return status;
+}
+
+/****************************************************************************
+ * @fn  sl_status_t sl_wfx_host_unlock(void)
+ * @brief
+ * Called when the driver needs to unlock its access
+ * @returns Returns SL_STATUS_OK
+ *****************************************************************************/
+sl_status_t sl_wfx_host_unlock(void)
+{
+    xSemaphoreGive(wfx_mutex);
+
+    return SL_STATUS_OK;
+}
+
+/******************************************************************************
+ * @fn  sl_status_t sl_wfx_host_post_event(sl_wfx_generic_message_t *event_payload)
+ * @brief
+ * Called when the driver needs to post an event
+ * @param[in]  event_payload:
+ * @returns Returns status
+ *****************************************************************************/
+sl_status_t sl_wfx_host_post_event(sl_wfx_generic_message_t * event_payload)
+{
+    sl_status_t status;
+
+    /* Forward the message to the application */
+    status = sl_wfx_host_process_event(event_payload);
+
+    if (host_context.waited_event_id == event_payload->header.id)
+    {
+        if (event_payload->header.length < SL_WFX_EVENT_MAX_SIZE)
+        {
+            /* Post the event in the queue */
+            memcpy(sl_wfx_context->event_payload_buffer, (void *) event_payload, event_payload->header.length);
+            host_context.posted_event_id = event_payload->header.id;
+            xQueueOverwrite(wfx_event_Q, (void *) &event_payload->header.id);
+        }
+    }
+
+    return status;
+}
+
+/****************************************************************************
+ * @fn  sl_status_t sl_wfx_host_transmit_frame(void *frame, uint32_t frame_len)
+ * @brief
+ * Called when the driver needs to transmit a frame
+ * @param[in] frame:
+ * @param[in] frame_len:
+ * @returns returns sl_wfx_data_write(frame, frame_len)
+ *****************************************************************************/
+sl_status_t sl_wfx_host_transmit_frame(void * frame, uint32_t frame_len)
+{
+    return sl_wfx_data_write(frame, frame_len);
+}
+
+/****************************************************************************
+ * @fn  sl_status_t sl_wfx_host_sleep_grant(sl_wfx_host_bus_transfer_type_t type,
+                                    sl_wfx_register_address_t address,
+                                    uint32_t length)
+ * @brief
+ * Called when the driver is considering putting the
+ * WFx in sleep mode
+ * @param[in] type:
+ * @param[in] address:
+ * @param[in] length:
+ * @returns SL_WIFI_SLEEP_GRANTED to let the WFx go to
+ *sleep, SL_WIFI_SLEEP_NOT_GRANTED otherwise
+ *****************************************************************************/
+sl_status_t sl_wfx_host_sleep_grant(sl_wfx_host_bus_transfer_type_t type, sl_wfx_register_address_t address, uint32_t length)
+{
+    (void) (type);
+    (void) (address);
+    (void) (length);
+
+    return SL_STATUS_WIFI_SLEEP_GRANTED;
+}
+
+#if SL_WFX_DEBUG_MASK
+/****************************************************************************
+ * @fn  void sl_wfx_host_log(const char *str, ...)
+ * @brief
+ * Host debug output
+ * @param[in] str: string
+ * @return None
+ *****************************************************************************/
+void sl_wfx_host_log(const char * str, ...)
+{
+    va_list args;
+    va_start(args, str);
+    vprintf(str, args);
+    va_end(args);
+}
+#endif
+#ifndef PW_RPC_ENABLED
+/* Place holder - This is just to handle UART interrupts
+ * The "otThread tasks handles it. WiFi does not need it yet
+ * I don't care for it. I should really have the thread
+ * shut it off
+ */
+#if !CHIP_ENABLE_OPENTHREAD
+/****************************************************************************
+ * @fn  void otSysEventSignalPending(void)
+ * @brief
+ * system event signal pending
+ * @param[in] None
+ * @return None
+ *****************************************************************************/
+void otSysEventSignalPending(void)
+{
+    // BaseType_t yieldRequired = ThreadStackMgrImpl().SignalThreadActivityPendingFromISR();
+    SILABS_LOG("*ERR*UART intr - NOT Handled");
+    portYIELD_FROM_ISR(pdFALSE);
+}
+#endif /* !CHIP_ENABLE_OPENTHREAD */
+#endif /* PW_RPC_ENABLED */
diff --git a/src/platform/silabs/SiWx917/BLEManagerImpl.cpp b/src/platform/silabs/SiWx917/BLEManagerImpl.cpp
new file mode 100644
index 0000000..a76f26c
--- /dev/null
+++ b/src/platform/silabs/SiWx917/BLEManagerImpl.cpp
@@ -0,0 +1,1093 @@
+/*
+ *
+ *    Copyright (c) 2020-2021 Project CHIP Authors
+ *    Copyright (c) 2019 Nest Labs, Inc.
+ *
+ *    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 Silicon Labs EFR32 platforms.
+ */
+
+/* this file behaves like a config.h, comes first */
+#include <platform/internal/CHIPDeviceLayerInternal.h>
+#if CHIP_DEVICE_CONFIG_ENABLE_CHIPOBLE
+
+#include "sl_component_catalog.h"
+
+#include <platform/internal/BLEManager.h>
+
+#include "FreeRTOS.h"
+#include "rail.h"
+extern "C" {
+#include "sl_bluetooth.h"
+}
+#include "sl_bt_api.h"
+#include "sl_bt_stack_config.h"
+#include "sl_bt_stack_init.h"
+#include "timers.h"
+#include <ble/CHIPBleServiceData.h>
+#include <lib/support/CodeUtils.h>
+#include <lib/support/logging/CHIPLogging.h>
+#include <platform/CommissionableDataProvider.h>
+#include <platform/DeviceInstanceInfoProvider.h>
+#include <sl_bt_rtos_adaptation.h>
+
+#if CHIP_ENABLE_ADDITIONAL_DATA_ADVERTISING
+#include <setup_payload/AdditionalDataPayloadGenerator.h>
+#endif
+
+using namespace ::chip;
+using namespace ::chip::Ble;
+
+namespace chip {
+namespace DeviceLayer {
+namespace Internal {
+
+namespace {
+
+#define CHIP_ADV_DATA_TYPE_FLAGS 0x01
+#define CHIP_ADV_DATA_TYPE_UUID 0x03
+#define CHIP_ADV_DATA_TYPE_NAME 0x09
+#define CHIP_ADV_DATA_TYPE_SERVICE_DATA 0x16
+
+#define CHIP_ADV_DATA_FLAGS 0x06
+
+#define CHIP_ADV_DATA 0
+#define CHIP_ADV_SCAN_RESPONSE_DATA 1
+#define CHIP_ADV_SHORT_UUID_LEN 2
+
+#define MAX_RESPONSE_DATA_LEN 31
+#define MAX_ADV_DATA_LEN 31
+
+// Timer Frequency used.
+#define TIMER_CLK_FREQ ((uint32_t) 32768)
+// Convert msec to timer ticks.
+#define TIMER_MS_2_TIMERTICK(ms) ((TIMER_CLK_FREQ * ms) / 1000)
+#define TIMER_S_2_TIMERTICK(s) (TIMER_CLK_FREQ * s)
+
+#define BLE_MAX_BUFFER_SIZE (3076)
+#define BLE_MAX_ADVERTISERS (1)
+#define BLE_CONFIG_MAX_PERIODIC_ADVERTISING_SYNC (0)
+#define BLE_CONFIG_MAX_SOFTWARE_TIMERS (4)
+#define BLE_CONFIG_MIN_TX_POWER (-30)
+#define BLE_CONFIG_MAX_TX_POWER (80)
+#define BLE_CONFIG_RF_PATH_GAIN_TX (0)
+#define BLE_CONFIG_RF_PATH_GAIN_RX (0)
+
+// Default Connection  parameters
+#define BLE_CONFIG_MIN_INTERVAL (16) // Time = Value x 1.25 ms = 30ms
+#define BLE_CONFIG_MAX_INTERVAL (80) // Time = Value x 1.25 ms = 100ms
+#define BLE_CONFIG_LATENCY (0)
+#define BLE_CONFIG_TIMEOUT (100)          // Time = Value x 10 ms = 1s
+#define BLE_CONFIG_MIN_CE_LENGTH (0)      // Leave to min value
+#define BLE_CONFIG_MAX_CE_LENGTH (0xFFFF) // Leave to max value
+
+TimerHandle_t sbleAdvTimeoutTimer; // FreeRTOS sw timer.
+
+const uint8_t UUID_CHIPoBLEService[]       = { 0xFB, 0x34, 0x9B, 0x5F, 0x80, 0x00, 0x00, 0x80,
+                                         0x00, 0x10, 0x00, 0x00, 0xF6, 0xFF, 0x00, 0x00 };
+const uint8_t ShortUUID_CHIPoBLEService[]  = { 0xF6, 0xFF };
+const ChipBleUUID ChipUUID_CHIPoBLEChar_RX = { { 0x18, 0xEE, 0x2E, 0xF5, 0x26, 0x3D, 0x45, 0x59, 0x95, 0x9F, 0x4F, 0x9C, 0x42, 0x9F,
+                                                 0x9D, 0x11 } };
+const ChipBleUUID ChipUUID_CHIPoBLEChar_TX = { { 0x18, 0xEE, 0x2E, 0xF5, 0x26, 0x3D, 0x45, 0x59, 0x95, 0x9F, 0x4F, 0x9C, 0x42, 0x9F,
+                                                 0x9D, 0x12 } };
+
+} // namespace
+
+BLEManagerImpl BLEManagerImpl::sInstance;
+
+CHIP_ERROR BLEManagerImpl::_Init()
+{
+    CHIP_ERROR err;
+
+    // Initialize the CHIP BleLayer.
+    err = BleLayer::Init(this, this, &DeviceLayer::SystemLayer());
+    SuccessOrExit(err);
+
+    memset(mBleConnections, 0, sizeof(mBleConnections));
+    memset(mIndConfId, kUnusedIndex, sizeof(mIndConfId));
+    mServiceMode = ConnectivityManager::kCHIPoBLEServiceMode_Enabled;
+
+    // Create FreeRTOS sw timer for BLE timeouts and interval change.
+    sbleAdvTimeoutTimer = xTimerCreate("BleAdvTimer",       // Just a text name, not used by the RTOS kernel
+                                       1,                   // == default timer period (mS)
+                                       false,               // no timer reload (==one-shot)
+                                       (void *) this,       // init timer id = ble obj context
+                                       BleAdvTimeoutHandler // timer callback handler
+    );
+
+    mFlags.ClearAll().Set(Flags::kAdvertisingEnabled, CHIP_DEVICE_CONFIG_CHIPOBLE_ENABLE_ADVERTISING_AUTOSTART);
+    mFlags.Set(Flags::kFastAdvertisingEnabled, true);
+    PlatformMgr().ScheduleWork(DriveBLEState, 0);
+
+exit:
+    return err;
+}
+
+uint16_t BLEManagerImpl::_NumConnections(void)
+{
+    uint16_t numCons = 0;
+    for (uint16_t i = 0; i < kMaxConnections; i++)
+    {
+        if (mBleConnections[i].allocated)
+        {
+            numCons++;
+        }
+    }
+
+    return numCons;
+}
+
+CHIP_ERROR BLEManagerImpl::_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 BLEManagerImpl::_SetAdvertisingMode(BLEAdvertisingMode mode)
+{
+    switch (mode)
+    {
+    case BLEAdvertisingMode::kFastAdvertising:
+        mFlags.Set(Flags::kFastAdvertisingEnabled, true);
+        break;
+    case BLEAdvertisingMode::kSlowAdvertising:
+        mFlags.Set(Flags::kFastAdvertisingEnabled, false);
+        break;
+    default:
+        return CHIP_ERROR_INVALID_ARGUMENT;
+    }
+    mFlags.Set(Flags::kRestartAdvertising);
+    PlatformMgr().ScheduleWork(DriveBLEState, 0);
+    return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR BLEManagerImpl::_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 BLEManagerImpl::_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;
+        }
+        strcpy(mDeviceName, deviceName);
+        mFlags.Set(Flags::kDeviceNameSet);
+        mFlags.Set(Flags::kRestartAdvertising);
+        ChipLogProgress(DeviceLayer, "Setting device name to : \"%s\"", mDeviceName);
+    }
+    else
+    {
+        mDeviceName[0] = 0;
+    }
+    PlatformMgr().ScheduleWork(DriveBLEState, 0);
+    return CHIP_NO_ERROR;
+}
+
+void BLEManagerImpl::_OnPlatformEvent(const ChipDeviceEvent * event)
+{
+    switch (event->Type)
+    {
+    case DeviceEventType::kCHIPoBLESubscribe: {
+        ChipDeviceEvent connEstEvent;
+
+        ChipLogProgress(DeviceLayer, "_OnPlatformEvent kCHIPoBLESubscribe");
+        HandleSubscribeReceived(event->CHIPoBLESubscribe.ConId, &CHIP_BLE_SVC_ID, &ChipUUID_CHIPoBLEChar_TX);
+        connEstEvent.Type = DeviceEventType::kCHIPoBLEConnectionEstablished;
+        PlatformMgr().PostEventOrDie(&connEstEvent);
+    }
+    break;
+
+    case DeviceEventType::kCHIPoBLEUnsubscribe: {
+        ChipLogProgress(DeviceLayer, "_OnPlatformEvent kCHIPoBLEUnsubscribe");
+        HandleUnsubscribeReceived(event->CHIPoBLEUnsubscribe.ConId, &CHIP_BLE_SVC_ID, &ChipUUID_CHIPoBLEChar_TX);
+    }
+    break;
+
+    case DeviceEventType::kCHIPoBLEWriteReceived: {
+        ChipLogProgress(DeviceLayer, "_OnPlatformEvent kCHIPoBLEWriteReceived");
+        HandleWriteReceived(event->CHIPoBLEWriteReceived.ConId, &CHIP_BLE_SVC_ID, &ChipUUID_CHIPoBLEChar_RX,
+                            PacketBufferHandle::Adopt(event->CHIPoBLEWriteReceived.Data));
+    }
+    break;
+
+    case DeviceEventType::kCHIPoBLEConnectionError: {
+        ChipLogProgress(DeviceLayer, "_OnPlatformEvent kCHIPoBLEConnectionError");
+        HandleConnectionError(event->CHIPoBLEConnectionError.ConId, event->CHIPoBLEConnectionError.Reason);
+    }
+    break;
+
+    case DeviceEventType::kCHIPoBLEIndicateConfirm: {
+        ChipLogProgress(DeviceLayer, "_OnPlatformEvent kCHIPoBLEIndicateConfirm");
+        HandleIndicationConfirmation(event->CHIPoBLEIndicateConfirm.ConId, &CHIP_BLE_SVC_ID, &ChipUUID_CHIPoBLEChar_TX);
+    }
+    break;
+
+    default:
+        ChipLogProgress(DeviceLayer, "_OnPlatformEvent default:  event->Type = %d", event->Type);
+        break;
+    }
+}
+
+bool BLEManagerImpl::SubscribeCharacteristic(BLE_CONNECTION_OBJECT conId, const ChipBleUUID * svcId, const ChipBleUUID * charId)
+{
+    ChipLogProgress(DeviceLayer, "BLEManagerImpl::SubscribeCharacteristic() not supported");
+    return false;
+}
+
+bool BLEManagerImpl::UnsubscribeCharacteristic(BLE_CONNECTION_OBJECT conId, const ChipBleUUID * svcId, const ChipBleUUID * charId)
+{
+    ChipLogProgress(DeviceLayer, "BLEManagerImpl::UnsubscribeCharacteristic() not supported");
+    return false;
+}
+
+bool BLEManagerImpl::CloseConnection(BLE_CONNECTION_OBJECT conId)
+{
+    CHIP_ERROR err = CHIP_NO_ERROR;
+    sl_status_t ret;
+
+    ChipLogProgress(DeviceLayer, "Closing BLE GATT connection (con %u)", conId);
+
+    ret = sl_bt_connection_close(conId);
+    err = MapBLEError(ret);
+
+    if (err != CHIP_NO_ERROR)
+    {
+        ChipLogError(DeviceLayer, "sl_bt_connection_close() failed: %s", ErrorStr(err));
+    }
+
+    return (err == CHIP_NO_ERROR);
+}
+
+uint16_t BLEManagerImpl::GetMTU(BLE_CONNECTION_OBJECT conId) const
+{
+    CHIPoBLEConState * conState = const_cast<BLEManagerImpl *>(this)->GetConnectionState(conId);
+    return (conState != NULL) ? conState->mtu : 0;
+}
+
+bool BLEManagerImpl::SendIndication(BLE_CONNECTION_OBJECT conId, const ChipBleUUID * svcId, const ChipBleUUID * charId,
+                                    PacketBufferHandle data)
+{
+    CHIP_ERROR err              = CHIP_NO_ERROR;
+    CHIPoBLEConState * conState = GetConnectionState(conId);
+    sl_status_t ret;
+    uint16_t cId        = (UUIDsMatch(&ChipUUID_CHIPoBLEChar_RX, charId) ? gattdb_CHIPoBLEChar_Rx : gattdb_CHIPoBLEChar_Tx);
+    uint8_t timerHandle = GetTimerHandle(conId, true);
+
+    VerifyOrExit(((conState != NULL) && (conState->subscribed != 0)), err = CHIP_ERROR_INVALID_ARGUMENT);
+    VerifyOrExit(timerHandle != kMaxConnections, err = CHIP_ERROR_NO_MEMORY);
+
+    // start timer for light indication confirmation. Long delay for spake2 indication
+    sl_bt_system_set_lazy_soft_timer(TIMER_S_2_TIMERTICK(6), 0, timerHandle, true);
+
+    ret = sl_bt_gatt_server_send_indication(conId, cId, (data->DataLength()), data->Start());
+    err = MapBLEError(ret);
+
+exit:
+    if (err != CHIP_NO_ERROR)
+    {
+        ChipLogError(DeviceLayer, "BLEManagerImpl::SendIndication() failed: %s", ErrorStr(err));
+        return false;
+    }
+
+    return true;
+}
+
+bool BLEManagerImpl::SendWriteRequest(BLE_CONNECTION_OBJECT conId, const ChipBleUUID * svcId, const ChipBleUUID * charId,
+                                      PacketBufferHandle pBuf)
+{
+    ChipLogProgress(DeviceLayer, "BLEManagerImpl::SendWriteRequest() not supported");
+    return false;
+}
+
+bool BLEManagerImpl::SendReadRequest(BLE_CONNECTION_OBJECT conId, const ChipBleUUID * svcId, const ChipBleUUID * charId,
+                                     PacketBufferHandle pBuf)
+{
+    ChipLogProgress(DeviceLayer, "BLEManagerImpl::SendReadRequest() not supported");
+    return false;
+}
+
+bool BLEManagerImpl::SendReadResponse(BLE_CONNECTION_OBJECT conId, BLE_READ_REQUEST_CONTEXT requestContext,
+                                      const ChipBleUUID * svcId, const ChipBleUUID * charId)
+{
+    ChipLogProgress(DeviceLayer, "BLEManagerImpl::SendReadResponse() not supported");
+    return false;
+}
+
+void BLEManagerImpl::NotifyChipConnectionClosed(BLE_CONNECTION_OBJECT conId)
+{
+    // Nothing to do
+}
+
+CHIP_ERROR BLEManagerImpl::MapBLEError(int bleErr)
+{
+    switch (bleErr)
+    {
+    case SL_STATUS_OK:
+        return CHIP_NO_ERROR;
+    case SL_STATUS_BT_ATT_INVALID_ATT_LENGTH:
+        return CHIP_ERROR_INVALID_STRING_LENGTH;
+    case SL_STATUS_INVALID_PARAMETER:
+        return CHIP_ERROR_INVALID_ARGUMENT;
+    case SL_STATUS_INVALID_STATE:
+        return CHIP_ERROR_INCORRECT_STATE;
+    case SL_STATUS_NOT_SUPPORTED:
+        return CHIP_ERROR_UNSUPPORTED_CHIP_FEATURE;
+    default:
+        return CHIP_ERROR(ChipError::Range::kPlatform, bleErr + CHIP_DEVICE_CONFIG_SILABS_BLE_ERROR_MIN);
+    }
+}
+
+void BLEManagerImpl::DriveBLEState(void)
+{
+    CHIP_ERROR err = CHIP_NO_ERROR;
+
+    // Check if BLE stack is initialized
+    VerifyOrExit(mFlags.Has(Flags::kEFRBLEStackInitialized), /* */);
+
+    // Start advertising if needed...
+    if (mServiceMode == ConnectivityManager::kCHIPoBLEServiceMode_Enabled && mFlags.Has(Flags::kAdvertisingEnabled) &&
+        NumConnections() < kMaxConnections)
+    {
+        // 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);
+    }
+
+exit:
+    if (err != CHIP_NO_ERROR)
+    {
+        ChipLogError(DeviceLayer, "Disabling CHIPoBLE service due to error: %s", ErrorStr(err));
+        mServiceMode = ConnectivityManager::kCHIPoBLEServiceMode_Disabled;
+    }
+}
+
+CHIP_ERROR BLEManagerImpl::ConfigureAdvertisingData(void)
+{
+    sl_status_t ret;
+    ChipBLEDeviceIdentificationInfo mDeviceIdInfo;
+    CHIP_ERROR err;
+    uint8_t responseData[MAX_RESPONSE_DATA_LEN];
+    uint8_t advData[MAX_ADV_DATA_LEN];
+    uint32_t index              = 0;
+    uint32_t mDeviceNameLength  = 0;
+    uint8_t mDeviceIdInfoLength = 0;
+
+    VerifyOrExit((kMaxDeviceNameLength + 1) < UINT8_MAX, err = CHIP_ERROR_INVALID_ARGUMENT);
+
+    memset(responseData, 0, MAX_RESPONSE_DATA_LEN);
+    memset(advData, 0, MAX_ADV_DATA_LEN);
+
+    err = ConfigurationMgr().GetBLEDeviceIdentificationInfo(mDeviceIdInfo);
+    SuccessOrExit(err);
+
+    if (!mFlags.Has(Flags::kDeviceNameSet))
+    {
+        uint16_t discriminator;
+        SuccessOrExit(err = GetCommissionableDataProvider()->GetSetupDiscriminator(discriminator));
+
+        snprintf(mDeviceName, sizeof(mDeviceName), "%s%04u", CHIP_DEVICE_CONFIG_BLE_DEVICE_NAME_PREFIX, discriminator);
+
+        mDeviceName[kMaxDeviceNameLength] = 0;
+        mDeviceNameLength                 = strlen(mDeviceName);
+
+        VerifyOrExit(mDeviceNameLength < kMaxDeviceNameLength, err = CHIP_ERROR_INVALID_ARGUMENT);
+    }
+
+    mDeviceNameLength = strlen(mDeviceName); // Device Name length + length field
+    VerifyOrExit(mDeviceNameLength < kMaxDeviceNameLength, err = CHIP_ERROR_INVALID_ARGUMENT);
+
+    mDeviceIdInfoLength = sizeof(mDeviceIdInfo); // Servicedatalen + length+ UUID (Short)
+    static_assert(sizeof(mDeviceIdInfo) + CHIP_ADV_SHORT_UUID_LEN + 1 <= UINT8_MAX, "Our length won't fit in a uint8_t");
+    static_assert(2 + CHIP_ADV_SHORT_UUID_LEN + sizeof(mDeviceIdInfo) + 1 <= MAX_ADV_DATA_LEN, "Our buffer is not big enough");
+
+    index            = 0;
+    advData[index++] = 0x02;                                                                    // length
+    advData[index++] = CHIP_ADV_DATA_TYPE_FLAGS;                                                // AD type : flags
+    advData[index++] = CHIP_ADV_DATA_FLAGS;                                                     // AD value
+    advData[index++] = static_cast<uint8_t>(mDeviceIdInfoLength + CHIP_ADV_SHORT_UUID_LEN + 1); // AD length
+    advData[index++] = CHIP_ADV_DATA_TYPE_SERVICE_DATA;                                         // AD type : Service Data
+    advData[index++] = ShortUUID_CHIPoBLEService[0];                                            // AD value
+    advData[index++] = ShortUUID_CHIPoBLEService[1];
+    memcpy(&advData[index], (void *) &mDeviceIdInfo, mDeviceIdInfoLength); // AD value
+    index += mDeviceIdInfoLength;
+
+#if CHIP_ENABLE_ADDITIONAL_DATA_ADVERTISING
+    ReturnErrorOnFailure(EncodeAdditionalDataTlv());
+#endif
+
+    if (0xff != advertising_set_handle)
+    {
+        sl_bt_advertiser_delete_set(advertising_set_handle);
+        advertising_set_handle = 0xff;
+    }
+
+    ret = sl_bt_advertiser_create_set(&advertising_set_handle);
+    if (ret != SL_STATUS_OK)
+    {
+        err = MapBLEError(ret);
+        ChipLogError(DeviceLayer, "sl_bt_advertiser_create_set() failed: %s", ErrorStr(err));
+        ExitNow();
+    }
+
+    ret = sl_bt_legacy_advertiser_set_data(advertising_set_handle, sl_bt_advertiser_advertising_data_packet, index,
+                                           (uint8_t *) advData);
+
+    if (ret != SL_STATUS_OK)
+    {
+        err = MapBLEError(ret);
+        ChipLogError(DeviceLayer, "sl_bt_legacy_advertiser_set_data() - Advertising Data failed: %s", ErrorStr(err));
+        ExitNow();
+    }
+
+    index = 0;
+
+    responseData[index++] = CHIP_ADV_SHORT_UUID_LEN + 1;  // AD length
+    responseData[index++] = CHIP_ADV_DATA_TYPE_UUID;      // AD type : uuid
+    responseData[index++] = ShortUUID_CHIPoBLEService[0]; // AD value
+    responseData[index++] = ShortUUID_CHIPoBLEService[1];
+
+    responseData[index++] = static_cast<uint8_t>(mDeviceNameLength + 1); // length
+    responseData[index++] = CHIP_ADV_DATA_TYPE_NAME;                     // AD type : name
+    memcpy(&responseData[index], mDeviceName, mDeviceNameLength);        // AD value
+    index += mDeviceNameLength;
+
+    ret = sl_bt_legacy_advertiser_set_data(advertising_set_handle, sl_bt_advertiser_scan_response_packet, index,
+                                           (uint8_t *) responseData);
+
+    if (ret != SL_STATUS_OK)
+    {
+        err = MapBLEError(ret);
+        ChipLogError(DeviceLayer, "sl_bt_legacy_advertiser_set_data() - Scan Response failed: %s", ErrorStr(err));
+        ExitNow();
+    }
+
+    err = MapBLEError(ret);
+
+exit:
+    return err;
+}
+
+CHIP_ERROR BLEManagerImpl::StartAdvertising(void)
+{
+    CHIP_ERROR err;
+    sl_status_t ret;
+    uint32_t interval_min;
+    uint32_t interval_max;
+    uint16_t numConnectionss = NumConnections();
+    uint8_t connectableAdv =
+        (numConnectionss < kMaxConnections) ? sl_bt_advertiser_connectable_scannable : sl_bt_advertiser_scannable_non_connectable;
+
+    // If already advertising, stop it, before changing values
+    if (mFlags.Has(Flags::kAdvertising))
+    {
+        sl_bt_advertiser_stop(advertising_set_handle);
+    }
+    else
+    {
+        ChipLogDetail(DeviceLayer, "Start BLE advertissement");
+    }
+
+    const uint8_t kResolvableRandomAddrType = 2; // Private resolvable random address type
+    bd_addr unusedBdAddr;                        // We can ignore this field when setting random address.
+    sl_bt_advertiser_set_random_address(advertising_set_handle, kResolvableRandomAddrType, unusedBdAddr, &unusedBdAddr);
+    (void) unusedBdAddr;
+
+    err = ConfigureAdvertisingData();
+    SuccessOrExit(err);
+
+    mFlags.Clear(Flags::kRestartAdvertising);
+
+    if (mFlags.Has(Flags::kFastAdvertisingEnabled))
+    {
+        interval_min = CHIP_DEVICE_CONFIG_BLE_FAST_ADVERTISING_INTERVAL_MIN;
+        interval_max = CHIP_DEVICE_CONFIG_BLE_FAST_ADVERTISING_INTERVAL_MAX;
+    }
+    else
+    {
+        interval_min = CHIP_DEVICE_CONFIG_BLE_SLOW_ADVERTISING_INTERVAL_MIN;
+        interval_max = CHIP_DEVICE_CONFIG_BLE_SLOW_ADVERTISING_INTERVAL_MAX;
+    }
+
+    ret = sl_bt_advertiser_set_timing(advertising_set_handle, interval_min, interval_max, 0, 0);
+    err = MapBLEError(ret);
+    SuccessOrExit(err);
+
+    sl_bt_advertiser_configure(advertising_set_handle, 1);
+    ret = sl_bt_legacy_advertiser_start(advertising_set_handle, connectableAdv);
+
+    if (SL_STATUS_OK == ret)
+    {
+        if (mFlags.Has(Flags::kFastAdvertisingEnabled))
+        {
+            StartBleAdvTimeoutTimer(CHIP_DEVICE_CONFIG_BLE_ADVERTISING_INTERVAL_CHANGE_TIME);
+        }
+        mFlags.Set(Flags::kAdvertising);
+    }
+
+    err = MapBLEError(ret);
+
+exit:
+    return err;
+}
+
+CHIP_ERROR BLEManagerImpl::StopAdvertising(void)
+{
+    CHIP_ERROR err = CHIP_NO_ERROR;
+    sl_status_t ret;
+
+    if (mFlags.Has(Flags::kAdvertising))
+    {
+        mFlags.Clear(Flags::kAdvertising).Clear(Flags::kRestartAdvertising);
+        mFlags.Set(Flags::kFastAdvertisingEnabled, true);
+
+        ret = sl_bt_advertiser_stop(advertising_set_handle);
+        sl_bt_advertiser_delete_set(advertising_set_handle);
+        advertising_set_handle = 0xff;
+        err                    = MapBLEError(ret);
+        SuccessOrExit(err);
+
+        CancelBleAdvTimeoutTimer();
+    }
+
+exit:
+    return err;
+}
+
+void BLEManagerImpl::UpdateMtu(volatile sl_bt_msg_t * evt)
+{
+    CHIPoBLEConState * bleConnState = GetConnectionState(evt->data.evt_gatt_mtu_exchanged.connection);
+    if (bleConnState != NULL)
+    {
+        // bleConnState->MTU is a 10-bit field inside a uint16_t.  We're
+        // assigning to it from a uint16_t, and compilers warn about
+        // possibly not fitting.  There's no way to suppress that warning
+        // via explicit cast; we have to disable the warning around the
+        // assignment.
+        //
+        // TODO: https://github.com/project-chip/connectedhomeip/issues/2569
+        // tracks making this safe with a check or explaining why no check
+        // is needed.
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wconversion"
+        bleConnState->mtu = evt->data.evt_gatt_mtu_exchanged.mtu;
+#pragma GCC diagnostic pop
+        ;
+    }
+}
+
+void BLEManagerImpl::HandleBootEvent(void)
+{
+    mFlags.Set(Flags::kEFRBLEStackInitialized);
+    PlatformMgr().ScheduleWork(DriveBLEState, 0);
+}
+
+void BLEManagerImpl::HandleConnectEvent(volatile sl_bt_msg_t * evt)
+{
+    sl_bt_evt_connection_opened_t * conn_evt = (sl_bt_evt_connection_opened_t *) &(evt->data);
+    uint8_t connHandle                       = conn_evt->connection;
+    uint8_t bondingHandle                    = conn_evt->bonding;
+
+    ChipLogProgress(DeviceLayer, "Connect Event for handle : %d", connHandle);
+
+    AddConnection(connHandle, bondingHandle);
+
+    PlatformMgr().ScheduleWork(DriveBLEState, 0);
+}
+
+void BLEManagerImpl::HandleConnectionCloseEvent(volatile sl_bt_msg_t * evt)
+{
+    sl_bt_evt_connection_closed_t * conn_evt = (sl_bt_evt_connection_closed_t *) &(evt->data);
+    uint8_t connHandle                       = conn_evt->connection;
+
+    ChipLogProgress(DeviceLayer, "Disconnect Event for handle : %d", connHandle);
+
+    if (RemoveConnection(connHandle))
+    {
+        ChipDeviceEvent event;
+        event.Type                          = DeviceEventType::kCHIPoBLEConnectionError;
+        event.CHIPoBLEConnectionError.ConId = connHandle;
+
+        switch (conn_evt->reason)
+        {
+        case SL_STATUS_BT_CTRL_REMOTE_USER_TERMINATED:
+        case SL_STATUS_BT_CTRL_REMOTE_DEVICE_TERMINATED_CONNECTION_DUE_TO_LOW_RESOURCES:
+        case SL_STATUS_BT_CTRL_REMOTE_POWERING_OFF:
+            event.CHIPoBLEConnectionError.Reason = BLE_ERROR_REMOTE_DEVICE_DISCONNECTED;
+            break;
+
+        case SL_STATUS_BT_CTRL_CONNECTION_TERMINATED_BY_LOCAL_HOST:
+            event.CHIPoBLEConnectionError.Reason = BLE_ERROR_APP_CLOSED_CONNECTION;
+            break;
+
+        default:
+            event.CHIPoBLEConnectionError.Reason = BLE_ERROR_CHIPOBLE_PROTOCOL_ABORT;
+            break;
+        }
+
+        ChipLogProgress(DeviceLayer, "BLE GATT connection closed (con %u, reason %u)", connHandle, conn_evt->reason);
+
+        PlatformMgr().PostEventOrDie(&event);
+
+        // Arrange to re-enable connectable advertising in case it was disabled due to the
+        // maximum connection limit being reached.
+        mFlags.Set(Flags::kRestartAdvertising);
+        mFlags.Set(Flags::kFastAdvertisingEnabled);
+        PlatformMgr().ScheduleWork(DriveBLEState, 0);
+    }
+}
+
+void BLEManagerImpl::HandleWriteEvent(volatile sl_bt_msg_t * evt)
+{
+    uint16_t attribute = evt->data.evt_gatt_server_user_write_request.characteristic;
+
+    ChipLogProgress(DeviceLayer, "Char Write Req, char : %d", attribute);
+
+    if (gattdb_CHIPoBLEChar_Rx == attribute)
+    {
+        HandleRXCharWrite(evt);
+    }
+}
+
+void BLEManagerImpl::HandleTXCharCCCDWrite(volatile sl_bt_msg_t * evt)
+{
+    CHIP_ERROR err = CHIP_NO_ERROR;
+    CHIPoBLEConState * bleConnState;
+    bool isIndicationEnabled = false;
+    ChipDeviceEvent event;
+
+    bleConnState = GetConnectionState(evt->data.evt_gatt_server_user_write_request.connection);
+    VerifyOrExit(bleConnState != NULL, err = CHIP_ERROR_NO_MEMORY);
+
+    // Determine if the client is enabling or disabling notification/indication.
+    isIndicationEnabled = (evt->data.evt_gatt_server_characteristic_status.client_config_flags == sl_bt_gatt_indication);
+
+    ChipLogProgress(DeviceLayer, "HandleTXcharCCCDWrite - Config Flags value : %d",
+                    evt->data.evt_gatt_server_characteristic_status.client_config_flags);
+    ChipLogProgress(DeviceLayer, "CHIPoBLE %s received", isIndicationEnabled ? "subscribe" : "unsubscribe");
+
+    if (isIndicationEnabled)
+    {
+        // If indications are not already enabled for the connection...
+        if (!bleConnState->subscribed)
+        {
+            bleConnState->subscribed = 1;
+            // Post an event to the CHIP queue to process either a CHIPoBLE Subscribe or Unsubscribe based on
+            // whether the client is enabling or disabling indications.
+            {
+                event.Type                    = DeviceEventType::kCHIPoBLESubscribe;
+                event.CHIPoBLESubscribe.ConId = evt->data.evt_gatt_server_user_write_request.connection;
+                err                           = PlatformMgr().PostEvent(&event);
+            }
+        }
+    }
+    else
+    {
+        bleConnState->subscribed      = 0;
+        event.Type                    = DeviceEventType::kCHIPoBLEUnsubscribe;
+        event.CHIPoBLESubscribe.ConId = evt->data.evt_gatt_server_user_write_request.connection;
+        err                           = PlatformMgr().PostEvent(&event);
+    }
+
+exit:
+    if (err != CHIP_NO_ERROR)
+    {
+        ChipLogError(DeviceLayer, "HandleTXCharCCCDWrite() failed: %s", ErrorStr(err));
+    }
+}
+
+void BLEManagerImpl::HandleRXCharWrite(volatile sl_bt_msg_t * evt)
+{
+    CHIP_ERROR err = CHIP_NO_ERROR;
+    System::PacketBufferHandle buf;
+    uint16_t writeLen = evt->data.evt_gatt_server_user_write_request.value.len;
+    uint8_t * data    = (uint8_t *) evt->data.evt_gatt_server_user_write_request.value.data;
+
+    // Copy the data to a packet buffer.
+    buf = System::PacketBufferHandle::NewWithData(data, writeLen, 0, 0);
+    VerifyOrExit(!buf.IsNull(), err = CHIP_ERROR_NO_MEMORY);
+
+    ChipLogDetail(DeviceLayer, "Write request/command received for CHIPoBLE RX characteristic (con %u, len %u)",
+                  evt->data.evt_gatt_server_user_write_request.connection, buf->DataLength());
+
+    // Post an event to the CHIP queue to deliver the data into the CHIP stack.
+    {
+        ChipDeviceEvent event;
+        event.Type                        = DeviceEventType::kCHIPoBLEWriteReceived;
+        event.CHIPoBLEWriteReceived.ConId = evt->data.evt_gatt_server_user_write_request.connection;
+        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 BLEManagerImpl::HandleTxConfirmationEvent(BLE_CONNECTION_OBJECT conId)
+{
+    ChipDeviceEvent event;
+    uint8_t timerHandle = sInstance.GetTimerHandle(conId, false);
+
+    ChipLogProgress(DeviceLayer, "Tx Confirmation received");
+
+    // stop indication confirmation timer
+    if (timerHandle < kMaxConnections)
+    {
+        ChipLogProgress(DeviceLayer, " stop soft timer");
+        sl_bt_system_set_lazy_soft_timer(0, 0, timerHandle, false);
+    }
+
+    event.Type                          = DeviceEventType::kCHIPoBLEIndicateConfirm;
+    event.CHIPoBLEIndicateConfirm.ConId = conId;
+    PlatformMgr().PostEventOrDie(&event);
+}
+
+void BLEManagerImpl::HandleSoftTimerEvent(volatile sl_bt_msg_t * evt)
+{
+    // BLE Manager starts soft timers with timer handles less than kMaxConnections
+    // If we receive a callback for unknown timer handle ignore this.
+    if (evt->data.evt_system_soft_timer.handle < kMaxConnections)
+    {
+        ChipLogProgress(DeviceLayer, "BLEManagerImpl::HandleSoftTimerEvent CHIPOBLE_PROTOCOL_ABORT");
+        ChipDeviceEvent event;
+        event.Type                                                   = DeviceEventType::kCHIPoBLEConnectionError;
+        event.CHIPoBLEConnectionError.ConId                          = mIndConfId[evt->data.evt_system_soft_timer.handle];
+        sInstance.mIndConfId[evt->data.evt_system_soft_timer.handle] = kUnusedIndex;
+        event.CHIPoBLEConnectionError.Reason                         = BLE_ERROR_CHIPOBLE_PROTOCOL_ABORT;
+        PlatformMgr().PostEventOrDie(&event);
+    }
+}
+
+bool BLEManagerImpl::RemoveConnection(uint8_t connectionHandle)
+{
+    CHIPoBLEConState * bleConnState = GetConnectionState(connectionHandle, true);
+    bool status                     = false;
+
+    if (bleConnState != NULL)
+    {
+        memset(bleConnState, 0, sizeof(CHIPoBLEConState));
+        status = true;
+    }
+
+    return status;
+}
+
+void BLEManagerImpl::AddConnection(uint8_t connectionHandle, uint8_t bondingHandle)
+{
+    CHIPoBLEConState * bleConnState = GetConnectionState(connectionHandle, true);
+
+    if (bleConnState != NULL)
+    {
+        memset(bleConnState, 0, sizeof(CHIPoBLEConState));
+        bleConnState->allocated        = 1;
+        bleConnState->connectionHandle = connectionHandle;
+        bleConnState->bondingHandle    = bondingHandle;
+    }
+}
+
+BLEManagerImpl::CHIPoBLEConState * BLEManagerImpl::GetConnectionState(uint8_t connectionHandle, bool allocate)
+{
+    uint8_t freeIndex = kMaxConnections;
+
+    for (uint8_t i = 0; i < kMaxConnections; i++)
+    {
+        if (mBleConnections[i].allocated == 1)
+        {
+            if (mBleConnections[i].connectionHandle == connectionHandle)
+            {
+                return &mBleConnections[i];
+            }
+        }
+
+        else if (i < freeIndex)
+        {
+            freeIndex = i;
+        }
+    }
+
+    if (allocate)
+    {
+        if (freeIndex < kMaxConnections)
+        {
+            return &mBleConnections[freeIndex];
+        }
+
+        ChipLogError(DeviceLayer, "Failed to allocate CHIPoBLEConState");
+    }
+
+    return NULL;
+}
+
+#if CHIP_ENABLE_ADDITIONAL_DATA_ADVERTISING
+CHIP_ERROR BLEManagerImpl::EncodeAdditionalDataTlv()
+{
+    CHIP_ERROR err = CHIP_NO_ERROR;
+    BitFlags<AdditionalDataFields> additionalDataFields;
+    AdditionalDataPayloadGeneratorParams additionalDataPayloadParams;
+
+#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(additionalDataPayloadParams.rotatingDeviceIdLifetimeCounter);
+    SuccessOrExit(err);
+    additionalDataPayloadParams.rotatingDeviceIdUniqueId = rotatingDeviceIdUniqueIdSpan;
+    additionalDataFields.Set(AdditionalDataFields::RotatingDeviceId);
+#endif /* CHIP_ENABLE_ROTATING_DEVICE_ID && defined(CHIP_DEVICE_CONFIG_ROTATING_DEVICE_ID_UNIQUE_ID) */
+
+    err = AdditionalDataPayloadGenerator().generateAdditionalDataPayload(additionalDataPayloadParams, c3AdditionalDataBufferHandle,
+                                                                         additionalDataFields);
+
+exit:
+    if (err != CHIP_NO_ERROR)
+    {
+        ChipLogError(DeviceLayer, "Failed to generate TLV encoded Additional Data (%s)", __func__);
+    }
+
+    return err;
+}
+
+void BLEManagerImpl::HandleC3ReadRequest(volatile sl_bt_msg_t * evt)
+{
+    sl_bt_evt_gatt_server_user_read_request_t * readReq =
+        (sl_bt_evt_gatt_server_user_read_request_t *) &(evt->data.evt_gatt_server_user_read_request);
+    ChipLogDetail(DeviceLayer, "Read request received for CHIPoBLEChar_C3 - opcode:%d", readReq->att_opcode);
+    sl_status_t ret = sl_bt_gatt_server_send_user_read_response(readReq->connection, readReq->characteristic, 0,
+                                                                sInstance.c3AdditionalDataBufferHandle->DataLength(),
+                                                                sInstance.c3AdditionalDataBufferHandle->Start(), nullptr);
+
+    if (ret != SL_STATUS_OK)
+    {
+        ChipLogDetail(DeviceLayer, "Failed to send read response, err:%ld", ret);
+    }
+}
+#endif // CHIP_ENABLE_ADDITIONAL_DATA_ADVERTISING
+
+uint8_t BLEManagerImpl::GetTimerHandle(uint8_t connectionHandle, bool allocate)
+{
+    uint8_t freeIndex = kMaxConnections;
+
+    for (uint8_t i = 0; i < kMaxConnections; i++)
+    {
+        if (mIndConfId[i] == connectionHandle)
+        {
+            return i;
+        }
+        else if (allocate)
+        {
+            if (i < freeIndex)
+            {
+                freeIndex = i;
+            }
+        }
+    }
+
+    if (freeIndex < kMaxConnections)
+    {
+        mIndConfId[freeIndex] = connectionHandle;
+    }
+    else
+    {
+        ChipLogError(DeviceLayer, "Failed to Save Conn Handle for indication");
+    }
+
+    return freeIndex;
+}
+
+void BLEManagerImpl::BleAdvTimeoutHandler(TimerHandle_t xTimer)
+{
+    if (BLEMgrImpl().mFlags.Has(Flags::kFastAdvertisingEnabled))
+    {
+        ChipLogDetail(DeviceLayer, "bleAdv Timeout : Start slow advertissment");
+        BLEMgr().SetAdvertisingMode(BLEAdvertisingMode::kSlowAdvertising);
+    }
+}
+
+void BLEManagerImpl::CancelBleAdvTimeoutTimer(void)
+{
+    if (xTimerStop(sbleAdvTimeoutTimer, 0) == pdFAIL)
+    {
+        ChipLogError(DeviceLayer, "Failed to stop BledAdv timeout timer");
+    }
+}
+
+void BLEManagerImpl::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");
+    }
+}
+
+void BLEManagerImpl::DriveBLEState(intptr_t arg)
+{
+    sInstance.DriveBLEState();
+}
+
+} // namespace Internal
+} // namespace DeviceLayer
+} // namespace chip
+
+extern "C" void sl_bt_on_event(sl_bt_msg_t * evt)
+{
+    // As this is running in a separate thread, we need to block CHIP from operating,
+    // until the events are handled.
+    chip::DeviceLayer::PlatformMgr().LockChipStack();
+
+    // handle bluetooth events
+    switch (SL_BT_MSG_ID(evt->header))
+    {
+    case sl_bt_evt_system_boot_id: {
+        ChipLogProgress(DeviceLayer, "Bluetooth stack booted: v%d.%d.%d-b%d", evt->data.evt_system_boot.major,
+                        evt->data.evt_system_boot.minor, evt->data.evt_system_boot.patch, evt->data.evt_system_boot.build);
+        chip::DeviceLayer::Internal::BLEMgrImpl().HandleBootEvent();
+
+        RAIL_Version_t railVer;
+        RAIL_GetVersion(&railVer, true);
+        ChipLogProgress(DeviceLayer, "RAIL version:, v%d.%d.%d-b%d", railVer.major, railVer.minor, railVer.rev, railVer.build);
+        sl_bt_connection_set_default_parameters(BLE_CONFIG_MIN_INTERVAL, BLE_CONFIG_MAX_INTERVAL, BLE_CONFIG_LATENCY,
+                                                BLE_CONFIG_TIMEOUT, BLE_CONFIG_MIN_CE_LENGTH, BLE_CONFIG_MAX_CE_LENGTH);
+    }
+    break;
+
+    case sl_bt_evt_connection_opened_id: {
+        chip::DeviceLayer::Internal::BLEMgrImpl().HandleConnectEvent(evt);
+    }
+    break;
+    case sl_bt_evt_connection_parameters_id: {
+        // ChipLogProgress(DeviceLayer, "Connection parameter ID received");
+    }
+    break;
+    case sl_bt_evt_connection_phy_status_id: {
+        // ChipLogProgress(DeviceLayer, "PHY update procedure is completed");
+    }
+    break;
+    case sl_bt_evt_connection_closed_id: {
+        chip::DeviceLayer::Internal::BLEMgrImpl().HandleConnectionCloseEvent(evt);
+    }
+    break;
+
+    /* This event indicates that a remote GATT client is attempting to write a value of an
+     * attribute in to the local GATT database, where the attribute was defined in the GATT
+     * XML firmware configuration file to have type="user".  */
+    case sl_bt_evt_gatt_server_attribute_value_id: {
+        chip::DeviceLayer::Internal::BLEMgrImpl().HandleWriteEvent(evt);
+    }
+    break;
+
+    case sl_bt_evt_gatt_mtu_exchanged_id: {
+        chip::DeviceLayer::Internal::BLEMgrImpl().UpdateMtu(evt);
+    }
+    break;
+
+    // confirmation of indication received from remote GATT client
+    case sl_bt_evt_gatt_server_characteristic_status_id: {
+        sl_bt_gatt_server_characteristic_status_flag_t StatusFlags;
+
+        StatusFlags = (sl_bt_gatt_server_characteristic_status_flag_t) evt->data.evt_gatt_server_characteristic_status.status_flags;
+
+        if (sl_bt_gatt_server_confirmation == StatusFlags)
+        {
+            chip::DeviceLayer::Internal::BLEMgrImpl().HandleTxConfirmationEvent(
+                evt->data.evt_gatt_server_characteristic_status.connection);
+        }
+        else if ((evt->data.evt_gatt_server_characteristic_status.characteristic == gattdb_CHIPoBLEChar_Tx) &&
+                 (evt->data.evt_gatt_server_characteristic_status.status_flags == gatt_server_client_config))
+        {
+            chip::DeviceLayer::Internal::BLEMgrImpl().HandleTXCharCCCDWrite(evt);
+        }
+    }
+    break;
+
+    /* Software Timer event */
+    case sl_bt_evt_system_soft_timer_id: {
+        chip::DeviceLayer::Internal::BLEMgrImpl().HandleSoftTimerEvent(evt);
+    }
+    break;
+
+    case sl_bt_evt_gatt_server_user_read_request_id: {
+        ChipLogProgress(DeviceLayer, "GATT server user_read_request");
+#if CHIP_ENABLE_ADDITIONAL_DATA_ADVERTISING
+        if (evt->data.evt_gatt_server_user_read_request.characteristic == gattdb_CHIPoBLEChar_C3)
+        {
+            chip::DeviceLayer::Internal::BLEMgrImpl().HandleC3ReadRequest(evt);
+        }
+#endif // CHIP_ENABLE_ADDITIONAL_DATA_ADVERTISING
+    }
+    break;
+
+    case sl_bt_evt_connection_remote_used_features_id: {
+        // ChipLogProgress(DeviceLayer, "link layer features supported by the remote device");
+    }
+    break;
+
+    default:
+        ChipLogProgress(DeviceLayer, "evt_UNKNOWN id = %08" PRIx32, SL_BT_MSG_ID(evt->header));
+        break;
+    }
+
+    chip::DeviceLayer::PlatformMgr().UnlockChipStack();
+}
+
+#endif // CHIP_DEVICE_CONFIG_ENABLE_CHIPOBLE
diff --git a/src/platform/silabs/SiWx917/BUILD.gn b/src/platform/silabs/SiWx917/BUILD.gn
new file mode 100644
index 0000000..b67c63c
--- /dev/null
+++ b/src/platform/silabs/SiWx917/BUILD.gn
@@ -0,0 +1,125 @@
+# Copyright (c) 2021 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/pigweed.gni")
+
+import("${chip_root}/src/platform/device.gni")
+
+import("${chip_root}/build/chip/buildconfig_header.gni")
+import("${chip_root}/src/crypto/crypto.gni")
+
+silabs_platform_dir = "${chip_root}/src/platform/silabs"
+
+assert(chip_device_platform == "efr32")
+
+if (chip_enable_openthread) {
+  import("//build_overrides/openthread.gni")
+}
+
+if (chip_crypto == "platform") {
+  import("//build_overrides/mbedtls.gni")
+}
+
+static_library("EFR32") {
+  sources = [
+    "${silabs_platform_dir}/BLEManagerImpl.h",
+    "${silabs_platform_dir}/BlePlatformConfig.h",
+    "${silabs_platform_dir}/CHIPDevicePlatformConfig.h",
+    "${silabs_platform_dir}/CHIPDevicePlatformEvent.h",
+    "${silabs_platform_dir}/CHIPMem-Platform.cpp",
+    "${silabs_platform_dir}/CHIPPlatformConfig.h",
+    "${silabs_platform_dir}/ConfigurationManagerImpl.h",
+    "${silabs_platform_dir}/ConnectivityManagerImpl.h",
+    "${silabs_platform_dir}/DiagnosticDataProviderImpl.cpp",
+    "${silabs_platform_dir}/DiagnosticDataProviderImpl.h",
+    "${silabs_platform_dir}/InetPlatformConfig.h",
+    "${silabs_platform_dir}/KeyValueStoreManagerImpl.h",
+    "${silabs_platform_dir}/Logging.cpp",
+    "${silabs_platform_dir}/PlatformManagerImpl.h",
+    "${silabs_platform_dir}/SilabsConfig.cpp",
+    "${silabs_platform_dir}/SilabsConfig.h",
+    "${silabs_platform_dir}/SystemPlatformConfig.h",
+    "../../FreeRTOS/SystemTimeSupport.cpp",
+    "../../SingletonConfigurationManager.cpp",
+    "BLEManagerImpl.cpp",
+    "ConfigurationManagerImpl.cpp",
+    "KeyValueStoreManagerImpl.cpp",
+    "PlatformManagerImpl.cpp",
+  ]
+
+  if (chip_enable_ota_requestor) {
+    sources += [
+      "OTAImageProcessorImpl.cpp",
+      "OTAImageProcessorImpl.h",
+    ]
+  }
+
+  public_deps = [ "${chip_root}/src/platform:platform_base" ]
+
+  # Add platform crypto implementation
+  if (chip_crypto == "platform") {
+    sources += [
+      "CHIPCryptoPALPsaEfr32.cpp",
+      "Efr32OpaqueKeypair.h",
+      "Efr32PsaOpaqueKeypair.cpp",
+      "Efr32PsaOperationalKeystore.cpp",
+      "Efr32PsaOperationalKeystore.h",
+    ]
+
+    public_deps += [
+      "${chip_root}/src/crypto",
+      "${mbedtls_root}:mbedtls",
+    ]
+  }
+
+  # Add pigweed KVS
+  deps = [
+    "$dir_pw_kvs:crc16",
+    "$dir_pw_log",
+  ]
+  public_deps += [
+    "$dir_pw_checksum",
+    "$dir_pw_kvs",
+  ]
+  if (chip_enable_openthread) {
+    public_deps += [ "${chip_root}/third_party/openthread:openthread" ]
+
+    deps += [ "${chip_root}/third_party/openthread:openthread_cli" ]
+
+    sources += [
+      "${silabs_platform_dir}/ThreadStackManagerImpl.h",
+      "../../OpenThread/OpenThreadUtils.cpp",
+      "ConnectivityManagerImpl.cpp",
+      "ThreadStackManagerImpl.cpp",
+    ]
+
+    if (chip_mdns == "platform") {
+      sources += [ "../../OpenThread/DnssdImpl.cpp" ]
+      deps += [ "${chip_root}/src/lib/dnssd:platform_header" ]
+    }
+
+    public_configs = [
+      "${chip_root}/src/lib/address_resolve:default_address_resolve_config",
+    ]
+  }
+
+  if (chip_enable_wifi) {
+    sources += [
+      "${silabs_platform_dir}/ConnectivityManagerImpl_WIFI.cpp",
+      "${silabs_platform_dir}/NetworkCommissioningWiFiDriver.cpp",
+      "${silabs_platform_dir}/NetworkCommissioningWiFiDriver.h",
+    ]
+  }
+}
diff --git a/src/platform/silabs/SiWx917/CHIPCryptoPALPsaEfr32.cpp b/src/platform/silabs/SiWx917/CHIPCryptoPALPsaEfr32.cpp
new file mode 100644
index 0000000..13af1ae
--- /dev/null
+++ b/src/platform/silabs/SiWx917/CHIPCryptoPALPsaEfr32.cpp
@@ -0,0 +1,1879 @@
+/*
+ *
+ *    Copyright (c) 2020-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.
+ */
+
+/**
+ *    @file
+ *      PSA Crypto API based implementation of CHIP crypto primitives
+ *      with Silicon Labs SDK modifications
+ */
+
+#include <crypto/CHIPCryptoPAL.h>
+
+#include <type_traits>
+
+// Include version header to get configuration information
+#include <mbedtls/version.h>
+
+#if !defined(MBEDTLS_PSA_CRYPTO_C)
+#error "This implementation needs PSA Crypto"
+#endif
+
+#if !defined(MBEDTLS_USE_PSA_CRYPTO)
+#error "This implementation requires that PSA Crypto keys can be used for CSR generation"
+#endif
+
+#include "psa/crypto.h"
+
+// Go straight for the driver wrappers for speed on plaintext keys
+extern "C" {
+#include "psa_crypto_core.h"
+#include "psa_crypto_driver_wrappers.h"
+}
+
+// Includes needed for SPAKE2+ ECP operations
+#include <mbedtls/bignum.h>
+#include <mbedtls/ecp.h>
+
+// Includes needed for certificate parsing
+#if defined(MBEDTLS_X509_CRT_PARSE_C)
+#include <mbedtls/x509_crt.h>
+#endif // defined(MBEDTLS_X509_CRT_PARSE_C)
+#include <mbedtls/md.h>
+#include <mbedtls/x509.h>
+#include <mbedtls/x509_csr.h>
+
+#if defined(MBEDTLS_ERROR_C)
+#include <mbedtls/error.h>
+#endif // defined(MBEDTLS_ERROR_C)
+
+#include <lib/core/CHIPSafeCasts.h>
+#include <lib/support/BufferWriter.h>
+#include <lib/support/BytesToHex.h>
+#include <lib/support/CHIPArgParser.hpp>
+#include <lib/support/CHIPMem.h>
+#include <lib/support/CodeUtils.h>
+#include <lib/support/SafeInt.h>
+#include <lib/support/SafePointerCast.h>
+#include <lib/support/logging/CHIPLogging.h>
+
+#include <string.h>
+
+namespace chip {
+namespace Crypto {
+
+using chip::Platform::MemoryCalloc;
+using chip::Platform::MemoryFree;
+
+#define MAX_ERROR_STR_LEN 128
+#define NUM_BYTES_IN_SHA256_HASH 32
+
+// In mbedTLS 3.0.0 direct access to structure fields was replaced with using MBEDTLS_PRIVATE macro.
+#if (MBEDTLS_VERSION_NUMBER >= 0x03000000)
+#define CHIP_CRYPTO_PAL_PRIVATE(x) MBEDTLS_PRIVATE(x)
+#else
+#define CHIP_CRYPTO_PAL_PRIVATE(x) x
+#endif
+
+#if (MBEDTLS_VERSION_NUMBER >= 0x03000000 && MBEDTLS_VERSION_NUMBER < 0x03010000)
+#define CHIP_CRYPTO_PAL_PRIVATE_X509(x) MBEDTLS_PRIVATE(x)
+#else
+#define CHIP_CRYPTO_PAL_PRIVATE_X509(x) x
+#endif
+
+static void _log_mbedTLS_error(int error_code)
+{
+    if (error_code != 0)
+    {
+#if defined(MBEDTLS_ERROR_C)
+        char error_str[MAX_ERROR_STR_LEN];
+        mbedtls_strerror(error_code, error_str, sizeof(error_str));
+        ChipLogError(Crypto, "mbedTLS error: %s", error_str);
+#else
+        // Error codes defined in 16-bit negative hex numbers. Ease lookup by printing likewise
+        ChipLogError(Crypto, "mbedTLS error: -0x%04X", -static_cast<uint16_t>(error_code));
+#endif
+    }
+}
+
+static void _log_PSA_error(psa_status_t status)
+{
+    if (status != 0)
+    {
+        // Error codes defined in 16-bit negative hex numbers. Ease lookup by printing likewise
+        ChipLogError(Crypto, "PSA error: %ld", status);
+    }
+}
+
+static bool _isValidTagLength(size_t tag_length)
+{
+    if (tag_length == 8 || tag_length == 12 || tag_length == 16)
+    {
+        return true;
+    }
+    return false;
+}
+
+/**
+ * @brief Compare two times
+ *
+ * @param t1 First time to compare
+ * @param t2 Second time to compare
+ * @return int  0 If both times are idential to the second, -1 if t1 < t2, 1 if t1 > t2.
+ */
+static int timeCompare(mbedtls_x509_time * t1, mbedtls_x509_time * t2)
+{
+    VerifyOrReturnValue(t1->year >= t2->year, -1);
+    VerifyOrReturnValue(t1->year <= t2->year, 1);
+    // Same year
+    VerifyOrReturnValue(t1->mon >= t2->mon, -1);
+    VerifyOrReturnValue(t1->mon <= t2->mon, 1);
+    // Same month
+    VerifyOrReturnValue(t1->day >= t2->day, -1);
+    VerifyOrReturnValue(t1->day <= t2->day, 1);
+    // Same day
+    VerifyOrReturnValue(t1->hour >= t2->hour, -1);
+    VerifyOrReturnValue(t1->hour <= t2->hour, 1);
+    // Same hour
+    VerifyOrReturnValue(t1->min >= t2->min, -1);
+    VerifyOrReturnValue(t1->min <= t2->min, 1);
+    // Same minute
+    VerifyOrReturnValue(t1->sec >= t2->sec, -1);
+    VerifyOrReturnValue(t1->sec <= t2->sec, 1);
+    // Same second
+    return 0;
+}
+
+CHIP_ERROR AES_CCM_encrypt(const uint8_t * plaintext, size_t plaintext_length, const uint8_t * aad, size_t aad_length,
+                           const uint8_t * key, size_t key_length, const uint8_t * nonce, size_t nonce_length, uint8_t * ciphertext,
+                           uint8_t * tag, size_t tag_length)
+{
+    CHIP_ERROR error          = CHIP_NO_ERROR;
+    psa_status_t status       = PSA_ERROR_BAD_STATE;
+    psa_key_attributes_t attr = PSA_KEY_ATTRIBUTES_INIT;
+    size_t output_length      = 0;
+    uint8_t * buffer          = nullptr;
+    bool allocated_buffer     = false;
+
+    VerifyOrExit(_isValidTagLength(tag_length), error = CHIP_ERROR_INVALID_ARGUMENT);
+    VerifyOrExit(key_length == kAES_CCM128_Key_Length, error = CHIP_ERROR_INVALID_ARGUMENT);
+    VerifyOrExit(key != nullptr, error = CHIP_ERROR_INVALID_ARGUMENT);
+    VerifyOrExit(key_length == kAES_CCM128_Key_Length, error = CHIP_ERROR_INVALID_ARGUMENT);
+    VerifyOrExit(nonce != nullptr, error = CHIP_ERROR_INVALID_ARGUMENT);
+    VerifyOrExit(nonce_length > 0, error = CHIP_ERROR_INVALID_ARGUMENT);
+    VerifyOrExit(CanCastTo<int>(nonce_length), error = CHIP_ERROR_INVALID_ARGUMENT);
+    VerifyOrExit(tag != nullptr, error = CHIP_ERROR_INVALID_ARGUMENT);
+
+    // If the ciphertext and tag outputs aren't a contiguous buffer, the PSA API requires buffer copying
+    if (Uint8::to_uchar(ciphertext) + plaintext_length != Uint8::to_uchar(tag))
+    {
+        buffer           = (uint8_t *) MemoryCalloc(1, plaintext_length + tag_length);
+        allocated_buffer = true;
+        VerifyOrExit(buffer != nullptr, error = CHIP_ERROR_NO_MEMORY);
+    }
+
+    psa_crypto_init();
+
+    psa_set_key_type(&attr, PSA_KEY_TYPE_AES);
+    psa_set_key_bits(&attr, key_length * 8);
+    psa_set_key_algorithm(&attr, PSA_ALG_AEAD_WITH_AT_LEAST_THIS_LENGTH_TAG(PSA_ALG_CCM, 8));
+    psa_set_key_usage_flags(&attr, PSA_KEY_USAGE_ENCRYPT);
+
+    status = psa_driver_wrapper_aead_encrypt(
+        &attr, Uint8::to_const_uchar(key), key_length, PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_CCM, tag_length),
+        Uint8::to_const_uchar(nonce), nonce_length, Uint8::to_const_uchar(aad), aad_length, Uint8::to_const_uchar(plaintext),
+        plaintext_length, allocated_buffer ? buffer : ciphertext, plaintext_length + tag_length, &output_length);
+
+    VerifyOrExit(status == PSA_SUCCESS, error = CHIP_ERROR_INTERNAL);
+    VerifyOrExit(output_length == plaintext_length + tag_length, error = CHIP_ERROR_INTERNAL);
+
+    if (allocated_buffer)
+    {
+        memcpy(Uint8::to_uchar(ciphertext), buffer, plaintext_length);
+        memcpy(Uint8::to_uchar(tag), buffer + plaintext_length, tag_length);
+        memset(buffer, 0, plaintext_length + tag_length);
+    }
+
+exit:
+    if (allocated_buffer)
+    {
+        MemoryFree(buffer);
+    }
+    psa_reset_key_attributes(&attr);
+    return error;
+}
+
+CHIP_ERROR AES_CCM_decrypt(const uint8_t * ciphertext, size_t ciphertext_len, const uint8_t * aad, size_t aad_len,
+                           const uint8_t * tag, size_t tag_length, const uint8_t * key, size_t key_length, const uint8_t * nonce,
+                           size_t nonce_length, uint8_t * plaintext)
+{
+    CHIP_ERROR error          = CHIP_NO_ERROR;
+    psa_status_t status       = PSA_ERROR_BAD_STATE;
+    psa_key_attributes_t attr = PSA_KEY_ATTRIBUTES_INIT;
+    size_t output_length      = 0;
+    uint8_t * buffer          = nullptr;
+    bool allocated_buffer     = false;
+
+    VerifyOrExit(_isValidTagLength(tag_length), error = CHIP_ERROR_INVALID_ARGUMENT);
+    VerifyOrExit(tag != nullptr, error = CHIP_ERROR_INVALID_ARGUMENT);
+    VerifyOrExit(key != nullptr, error = CHIP_ERROR_INVALID_ARGUMENT);
+    VerifyOrExit(key_length == kAES_CCM128_Key_Length, error = CHIP_ERROR_INVALID_ARGUMENT);
+    VerifyOrExit(nonce != nullptr, error = CHIP_ERROR_INVALID_ARGUMENT);
+    VerifyOrExit(nonce_length > 0, error = CHIP_ERROR_INVALID_ARGUMENT);
+
+    // If the ciphertext and tag outputs aren't a contiguous buffer, the PSA API requires buffer copying
+    if (Uint8::to_const_uchar(ciphertext) + ciphertext_len != Uint8::to_const_uchar(tag))
+    {
+        buffer           = (uint8_t *) MemoryCalloc(1, ciphertext_len + tag_length);
+        allocated_buffer = true;
+        VerifyOrExit(buffer != nullptr, error = CHIP_ERROR_NO_MEMORY);
+    }
+
+    psa_crypto_init();
+
+    psa_set_key_type(&attr, PSA_KEY_TYPE_AES);
+    psa_set_key_bits(&attr, key_length * 8);
+    psa_set_key_algorithm(&attr, PSA_ALG_AEAD_WITH_AT_LEAST_THIS_LENGTH_TAG(PSA_ALG_CCM, 8));
+    psa_set_key_usage_flags(&attr, PSA_KEY_USAGE_DECRYPT);
+
+    if (allocated_buffer)
+    {
+        memcpy(buffer, ciphertext, ciphertext_len);
+        memcpy(buffer + ciphertext_len, tag, tag_length);
+    }
+
+    status = psa_driver_wrapper_aead_decrypt(
+        &attr, Uint8::to_const_uchar(key), key_length, PSA_ALG_AEAD_WITH_SHORTENED_TAG(PSA_ALG_CCM, tag_length),
+        Uint8::to_const_uchar(nonce), nonce_length, Uint8::to_const_uchar(aad), aad_len, allocated_buffer ? buffer : ciphertext,
+        ciphertext_len + tag_length, plaintext, ciphertext_len, &output_length);
+
+    if (allocated_buffer)
+    {
+        memset(buffer, 0, ciphertext_len + tag_length);
+    }
+
+    VerifyOrExit(status == PSA_SUCCESS, error = CHIP_ERROR_INTERNAL);
+    VerifyOrExit(output_length == ciphertext_len, error = CHIP_ERROR_INTERNAL);
+exit:
+    if (allocated_buffer)
+    {
+        MemoryFree(buffer);
+    }
+
+    psa_reset_key_attributes(&attr);
+    return error;
+}
+
+CHIP_ERROR Hash_SHA256(const uint8_t * data, const size_t data_length, uint8_t * out_buffer)
+{
+    size_t output_length = 0;
+
+    psa_crypto_init();
+
+    const psa_status_t result =
+        psa_hash_compute(PSA_ALG_SHA_256, data, data_length, out_buffer, PSA_HASH_LENGTH(PSA_ALG_SHA_256), &output_length);
+
+    VerifyOrReturnError(result == PSA_SUCCESS, CHIP_ERROR_INTERNAL);
+    VerifyOrReturnError(output_length == PSA_HASH_LENGTH(PSA_ALG_SHA_256), CHIP_ERROR_INTERNAL);
+
+    return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR Hash_SHA1(const uint8_t * data, const size_t data_length, uint8_t * out_buffer)
+{
+    size_t output_length = 0;
+
+    psa_crypto_init();
+
+    const psa_status_t result =
+        psa_hash_compute(PSA_ALG_SHA_1, data, data_length, out_buffer, PSA_HASH_LENGTH(PSA_ALG_SHA_1), &output_length);
+
+    VerifyOrReturnError(result == PSA_SUCCESS, CHIP_ERROR_INTERNAL);
+    VerifyOrReturnError(output_length == PSA_HASH_LENGTH(PSA_ALG_SHA_1), CHIP_ERROR_INTERNAL);
+
+    return CHIP_NO_ERROR;
+}
+
+static_assert(kMAX_Hash_SHA256_Context_Size >= sizeof(psa_hash_operation_t),
+              "kMAX_Hash_SHA256_Context_Size is too small for the size of underlying psa_hash_operation_t");
+
+static inline psa_hash_operation_t * to_inner_hash_sha256_context(HashSHA256OpaqueContext * context)
+{
+    return SafePointerCast<psa_hash_operation_t *>(context);
+}
+
+Hash_SHA256_stream::Hash_SHA256_stream(void)
+{
+    psa_hash_operation_t * context             = to_inner_hash_sha256_context(&mContext);
+    const psa_hash_operation_t initial_context = PSA_HASH_OPERATION_INIT;
+    memcpy(context, &initial_context, sizeof(psa_hash_operation_t));
+}
+
+Hash_SHA256_stream::~Hash_SHA256_stream(void)
+{
+    psa_hash_operation_t * context = to_inner_hash_sha256_context(&mContext);
+    psa_hash_abort(context);
+    Clear();
+}
+
+CHIP_ERROR Hash_SHA256_stream::Begin(void)
+{
+    psa_crypto_init();
+
+    psa_hash_operation_t * context = to_inner_hash_sha256_context(&mContext);
+    *context                       = PSA_HASH_OPERATION_INIT;
+    const psa_status_t result      = psa_hash_setup(context, PSA_ALG_SHA_256);
+
+    VerifyOrReturnError(result == PSA_SUCCESS, CHIP_ERROR_INTERNAL);
+
+    return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR Hash_SHA256_stream::AddData(const ByteSpan data)
+{
+    psa_hash_operation_t * context = to_inner_hash_sha256_context(&mContext);
+    const psa_status_t result      = psa_hash_update(context, Uint8::to_const_uchar(data.data()), data.size());
+
+    VerifyOrReturnError(result == PSA_SUCCESS, CHIP_ERROR_INTERNAL);
+
+    return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR Hash_SHA256_stream::GetDigest(MutableByteSpan & out_buffer)
+{
+    CHIP_ERROR result              = CHIP_NO_ERROR;
+    psa_status_t status            = PSA_ERROR_BAD_STATE;
+    size_t output_length           = 0;
+    psa_hash_operation_t * context = to_inner_hash_sha256_context(&mContext);
+
+    VerifyOrReturnError(out_buffer.size() >= kSHA256_Hash_Length, CHIP_ERROR_BUFFER_TOO_SMALL);
+
+    // Clone the context first since calculating the digest finishes the operation
+    psa_hash_operation_t digest_context = PSA_HASH_OPERATION_INIT;
+    status                              = psa_hash_clone(context, &digest_context);
+
+    VerifyOrReturnError(status == PSA_SUCCESS, CHIP_ERROR_INTERNAL);
+
+    // Calculate digest on the cloned context
+    status = psa_hash_finish(&digest_context, Uint8::to_uchar(out_buffer.data()), out_buffer.size(), &output_length);
+
+    VerifyOrExit(status == PSA_SUCCESS, result = CHIP_ERROR_INTERNAL);
+    VerifyOrExit(output_length == PSA_HASH_LENGTH(PSA_ALG_SHA_256), result = CHIP_ERROR_INTERNAL);
+exit:
+    psa_hash_abort(&digest_context);
+    return result;
+}
+
+CHIP_ERROR Hash_SHA256_stream::Finish(MutableByteSpan & out_buffer)
+{
+    psa_hash_operation_t * context = to_inner_hash_sha256_context(&mContext);
+    size_t output_length           = 0;
+
+    VerifyOrReturnError(out_buffer.size() >= kSHA256_Hash_Length, CHIP_ERROR_BUFFER_TOO_SMALL);
+    const psa_status_t status = psa_hash_finish(context, Uint8::to_uchar(out_buffer.data()), out_buffer.size(), &output_length);
+
+    VerifyOrReturnError(status == PSA_SUCCESS, CHIP_ERROR_INTERNAL);
+    VerifyOrReturnError(output_length == PSA_HASH_LENGTH(PSA_ALG_SHA_256), CHIP_ERROR_INTERNAL);
+
+    return CHIP_NO_ERROR;
+}
+
+void Hash_SHA256_stream::Clear(void)
+{
+    psa_hash_operation_t * context = to_inner_hash_sha256_context(&mContext);
+    psa_hash_abort(context);
+}
+
+CHIP_ERROR HKDF_sha::HKDF_SHA256(const uint8_t * secret, const size_t secret_length, const uint8_t * salt, const size_t salt_length,
+                                 const uint8_t * info, const size_t info_length, uint8_t * out_buffer, size_t out_length)
+{
+    VerifyOrReturnError(secret != nullptr, CHIP_ERROR_INVALID_ARGUMENT);
+    VerifyOrReturnError(secret_length > 0, CHIP_ERROR_INVALID_ARGUMENT);
+
+    // Salt is optional
+    if (salt_length > 0)
+    {
+        VerifyOrReturnError(salt != nullptr, CHIP_ERROR_INVALID_ARGUMENT);
+    }
+
+    VerifyOrReturnError(info_length > 0, CHIP_ERROR_INVALID_ARGUMENT);
+    VerifyOrReturnError(info != nullptr, CHIP_ERROR_INVALID_ARGUMENT);
+    VerifyOrReturnError(out_length > 0, CHIP_ERROR_INVALID_ARGUMENT);
+    VerifyOrReturnError(out_buffer != nullptr, CHIP_ERROR_INVALID_ARGUMENT);
+
+    CHIP_ERROR error                         = CHIP_NO_ERROR;
+    psa_status_t status                      = PSA_ERROR_BAD_STATE;
+    psa_key_derivation_operation_t operation = PSA_KEY_DERIVATION_OPERATION_INIT;
+
+    psa_crypto_init();
+
+    status = psa_key_derivation_setup(&operation, PSA_ALG_HKDF(PSA_ALG_SHA_256));
+    VerifyOrExit(status == PSA_SUCCESS, error = CHIP_ERROR_INTERNAL);
+
+    if (salt_length > 0)
+    {
+        status =
+            psa_key_derivation_input_bytes(&operation, PSA_KEY_DERIVATION_INPUT_SALT, Uint8::to_const_uchar(salt), salt_length);
+        VerifyOrExit(status == PSA_SUCCESS, error = CHIP_ERROR_INTERNAL);
+    }
+
+    status =
+        psa_key_derivation_input_bytes(&operation, PSA_KEY_DERIVATION_INPUT_SECRET, Uint8::to_const_uchar(secret), secret_length);
+    VerifyOrExit(status == PSA_SUCCESS, error = CHIP_ERROR_INTERNAL);
+
+    status = psa_key_derivation_input_bytes(&operation, PSA_KEY_DERIVATION_INPUT_INFO, Uint8::to_const_uchar(info), info_length);
+    VerifyOrExit(status == PSA_SUCCESS, error = CHIP_ERROR_INTERNAL);
+
+    status = psa_key_derivation_output_bytes(&operation, out_buffer, out_length);
+    VerifyOrExit(status == PSA_SUCCESS, error = CHIP_ERROR_INTERNAL);
+exit:
+    psa_key_derivation_abort(&operation);
+
+    return error;
+}
+
+CHIP_ERROR HMAC_sha::HMAC_SHA256(const uint8_t * key, size_t key_length, const uint8_t * message, size_t message_length,
+                                 uint8_t * out_buffer, size_t out_length)
+{
+    VerifyOrReturnError(key != nullptr, CHIP_ERROR_INVALID_ARGUMENT);
+    VerifyOrReturnError(key_length > 0, CHIP_ERROR_INVALID_ARGUMENT);
+    VerifyOrReturnError(message != nullptr, CHIP_ERROR_INVALID_ARGUMENT);
+    VerifyOrReturnError(message_length > 0, CHIP_ERROR_INVALID_ARGUMENT);
+    VerifyOrReturnError(out_length >= kSHA256_Hash_Length, CHIP_ERROR_INVALID_ARGUMENT);
+    VerifyOrReturnError(out_buffer != nullptr, CHIP_ERROR_INVALID_ARGUMENT);
+
+    CHIP_ERROR error              = CHIP_NO_ERROR;
+    psa_status_t status           = PSA_ERROR_BAD_STATE;
+    psa_key_attributes_t attr     = PSA_KEY_ATTRIBUTES_INIT;
+    psa_mac_operation_t operation = PSA_MAC_OPERATION_INIT;
+    size_t output_length          = 0;
+
+    psa_crypto_init();
+
+    psa_set_key_type(&attr, PSA_KEY_TYPE_HMAC);
+    psa_set_key_bits(&attr, key_length * 8);
+    psa_set_key_usage_flags(&attr, PSA_KEY_USAGE_SIGN_HASH);
+    psa_set_key_algorithm(&attr, PSA_ALG_HMAC(PSA_ALG_SHA_256));
+
+    status = psa_driver_wrapper_mac_compute(&attr, Uint8::to_const_uchar(key), key_length, PSA_ALG_HMAC(PSA_ALG_SHA_256),
+                                            Uint8::to_const_uchar(message), message_length, out_buffer, out_length, &output_length);
+
+    VerifyOrExit(status == PSA_SUCCESS, error = CHIP_ERROR_INTERNAL);
+    VerifyOrExit(output_length == PSA_HASH_LENGTH(PSA_ALG_SHA_256), error = CHIP_ERROR_INTERNAL);
+exit:
+    psa_mac_abort(&operation);
+    psa_reset_key_attributes(&attr);
+    return error;
+}
+
+CHIP_ERROR PBKDF2_sha256::pbkdf2_sha256(const uint8_t * password, size_t plen, const uint8_t * salt, size_t slen,
+                                        unsigned int iteration_count, uint32_t key_length, uint8_t * output)
+{
+    // TODO: replace inlined algorithm with usage of the PSA key derivation API once implemented
+    CHIP_ERROR error          = CHIP_NO_ERROR;
+    psa_status_t status       = PSA_ERROR_BAD_STATE;
+    psa_key_attributes_t attr = PSA_KEY_ATTRIBUTES_INIT;
+    size_t output_length      = 0;
+
+    // Align these buffers on the native data size to speed up the XOR
+    static const size_t hash_size_in_native =
+        ((PSA_HASH_LENGTH(PSA_ALG_SHA_256) + sizeof(unsigned int) - 1) / sizeof(unsigned int));
+    static_assert(hash_size_in_native * sizeof(unsigned int) >= PSA_HASH_LENGTH(PSA_ALG_SHA_256));
+
+    unsigned int md1_buffer[hash_size_in_native];
+    unsigned int work_buffer[hash_size_in_native];
+    uint8_t * md1  = (uint8_t *) md1_buffer;
+    uint8_t * work = (uint8_t *) work_buffer;
+
+    size_t use_len;
+    unsigned char * out_p = output;
+    uint8_t * U1          = (uint8_t *) MemoryCalloc(1, slen + 4);
+
+    VerifyOrExit(U1 != nullptr, error = CHIP_ERROR_NO_MEMORY);
+    VerifyOrExit(password != nullptr, error = CHIP_ERROR_INVALID_ARGUMENT);
+    VerifyOrExit(plen > 0, error = CHIP_ERROR_INVALID_ARGUMENT);
+    VerifyOrExit(salt != nullptr, error = CHIP_ERROR_INVALID_ARGUMENT);
+    VerifyOrExit(slen >= kSpake2p_Min_PBKDF_Salt_Length, error = CHIP_ERROR_INVALID_ARGUMENT);
+    VerifyOrExit(slen <= kSpake2p_Max_PBKDF_Salt_Length, error = CHIP_ERROR_INVALID_ARGUMENT);
+    VerifyOrExit(key_length > 0, error = CHIP_ERROR_INVALID_ARGUMENT);
+    VerifyOrExit(output != nullptr, error = CHIP_ERROR_INVALID_ARGUMENT);
+
+    psa_crypto_init();
+
+    psa_set_key_type(&attr, PSA_KEY_TYPE_HMAC);
+    psa_set_key_bits(&attr, plen * 8);
+    psa_set_key_usage_flags(&attr, PSA_KEY_USAGE_SIGN_HASH);
+    psa_set_key_algorithm(&attr, PSA_ALG_HMAC(PSA_ALG_SHA_256));
+
+    // Start with initializing the salt + counter
+    memcpy(U1, salt, slen);
+    U1[slen]     = 0;
+    U1[slen + 1] = 0;
+    U1[slen + 2] = 0;
+    U1[slen + 3] = 1;
+
+    // Loop until we have generated the requested key length
+    while (key_length)
+    {
+        // U1 ends up in work
+        status = psa_driver_wrapper_mac_compute(&attr, password, plen, PSA_ALG_HMAC(PSA_ALG_SHA_256), U1, slen + 4, work,
+                                                PSA_HASH_LENGTH(PSA_ALG_SHA_256), &output_length);
+
+        VerifyOrExit(status == PSA_SUCCESS, error = CHIP_ERROR_INTERNAL);
+        VerifyOrExit(output_length == PSA_HASH_LENGTH(PSA_ALG_SHA_256), error = CHIP_ERROR_INTERNAL);
+
+        memcpy(md1, work, PSA_HASH_LENGTH(PSA_ALG_SHA_256));
+
+        for (size_t i = 1; i < iteration_count; i++)
+        {
+            // U2 ends up in md1
+            //
+
+            status = psa_driver_wrapper_mac_compute(&attr, password, plen, PSA_ALG_HMAC(PSA_ALG_SHA_256), md1, sizeof(md1_buffer),
+                                                    md1, sizeof(md1_buffer), &output_length);
+
+            VerifyOrExit(status == PSA_SUCCESS, error = CHIP_ERROR_INTERNAL);
+            VerifyOrExit(output_length == PSA_HASH_LENGTH(PSA_ALG_SHA_256), error = CHIP_ERROR_INTERNAL);
+
+            // U1 xor U2
+            //
+            for (size_t j = 0; j < hash_size_in_native; j++)
+            {
+                work_buffer[j] ^= md1_buffer[j];
+            }
+        }
+
+        use_len = (key_length < PSA_HASH_LENGTH(PSA_ALG_SHA_256)) ? key_length : PSA_HASH_LENGTH(PSA_ALG_SHA_256);
+        memcpy(out_p, work, use_len);
+
+        key_length -= (uint32_t) use_len;
+        out_p += use_len;
+
+        for (size_t i = 4; i > 0; i--)
+        {
+            if (++U1[slen + i - 1] != 0)
+            {
+                break;
+            }
+        }
+    }
+
+exit:
+    MemoryFree(U1);
+    psa_reset_key_attributes(&attr);
+    return error;
+}
+
+CHIP_ERROR add_entropy_source(entropy_source fn_source, void * p_source, size_t threshold)
+{
+    // PSA Crypto has its own entropy and doesn't support an override mechanism
+    (void) fn_source;
+    (void) p_source;
+    (void) threshold;
+
+    return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR DRBG_get_bytes(uint8_t * out_buffer, const size_t out_length)
+{
+    VerifyOrReturnError(out_buffer != nullptr, CHIP_ERROR_INVALID_ARGUMENT);
+    VerifyOrReturnError(out_length > 0, CHIP_ERROR_INVALID_ARGUMENT);
+
+    psa_crypto_init();
+    const psa_status_t result = psa_generate_random(Uint8::to_uchar(out_buffer), out_length);
+    VerifyOrReturnError(result == PSA_SUCCESS, CHIP_ERROR_INTERNAL);
+
+    return CHIP_NO_ERROR;
+}
+
+// CryptoRNG's definition is needed to use the mbedTLS-backed SPAKE2+ and certificate operations
+static int CryptoRNG(void * ctxt, uint8_t * out_buffer, size_t out_length)
+{
+    return (chip::Crypto::DRBG_get_bytes(out_buffer, out_length) == CHIP_NO_ERROR) ? 0 : 1;
+}
+
+// Mapping function is used as part of the certificate operations
+mbedtls_ecp_group_id MapECPGroupId(SupportedECPKeyTypes keyType)
+{
+    switch (keyType)
+    {
+    case SupportedECPKeyTypes::ECP256R1:
+        return MBEDTLS_ECP_DP_SECP256R1;
+    default:
+        return MBEDTLS_ECP_DP_NONE;
+    }
+}
+
+/*******************************************************************************
+ *
+ * WARNING: The default (base) implementation of P256Keypair is UNSAFE!
+ *
+ * Because of the way CHIPCryptoPAL has evolved, it is dictating how a base
+ * P256Keypair should behave. This includes:
+ *      * Allowing using a P256 key for both ECDSA and ECDH operations
+ *      * Needing to support copying a key through Serialize()/Deserialize()
+ *        operations. This can't easily be done opaquely on an opaque backend
+ *        without convoluted forms of reference tracking.
+ *      * Not including a way to figure out whether the created key is supposed
+ *        to be ephemeral or long-lived.
+ *      * Needing to support ingestion of specific-format keys through
+ *        Deserialize() (to support e.g. the example DAC provider).
+ *
+ * These conditions have lead to the base implementation of this class in this
+ * crypto backend being backed by a plaintext key buffer instead of opaque key
+ * references. Usage of the base class is strongly discouraged, and is only
+ * implemented to support the in-tree examples which instantiate keys of this
+ * base class.
+ *
+ ******************************************************************************/
+
+typedef struct
+{
+    uint8_t privkey[32];
+    size_t bitlen;
+} psa_plaintext_ecp_keypair;
+
+static inline psa_plaintext_ecp_keypair * to_keypair(P256KeypairContext * context)
+{
+    return SafePointerCast<psa_plaintext_ecp_keypair *>(context);
+}
+
+static inline const psa_plaintext_ecp_keypair * to_const_keypair(const P256KeypairContext * context)
+{
+    return SafePointerCast<const psa_plaintext_ecp_keypair *>(context);
+}
+
+CHIP_ERROR P256Keypair::ECDSA_sign_msg(const uint8_t * msg, const size_t msg_length, P256ECDSASignature & out_signature) const
+{
+    CHIP_ERROR error                          = CHIP_NO_ERROR;
+    psa_status_t status                       = PSA_ERROR_BAD_STATE;
+    psa_key_attributes_t attr                 = PSA_KEY_ATTRIBUTES_INIT;
+    size_t output_length                      = 0;
+    const psa_plaintext_ecp_keypair * keypair = to_const_keypair(&mKeypair);
+
+    VerifyOrExit(mInitialized, error = CHIP_ERROR_WELL_UNINITIALIZED);
+    VerifyOrExit((msg != nullptr) && (msg_length > 0), error = CHIP_ERROR_INVALID_ARGUMENT);
+
+    psa_crypto_init();
+
+    psa_set_key_type(&attr, PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1));
+    psa_set_key_bits(&attr, keypair->bitlen);
+    psa_set_key_algorithm(&attr, PSA_ALG_ECDSA(PSA_ALG_SHA_256));
+    psa_set_key_usage_flags(&attr, PSA_KEY_USAGE_SIGN_MESSAGE);
+
+    // use imported key to sign a message
+    status =
+        psa_driver_wrapper_sign_message(&attr, keypair->privkey, PSA_BITS_TO_BYTES(keypair->bitlen), PSA_ALG_ECDSA(PSA_ALG_SHA_256),
+                                        msg, msg_length, out_signature.Bytes(), out_signature.Capacity(), &output_length);
+
+    VerifyOrReturnError(status == PSA_SUCCESS, CHIP_ERROR_INTERNAL);
+    VerifyOrReturnError(output_length == kP256_ECDSA_Signature_Length_Raw, CHIP_ERROR_INTERNAL);
+    VerifyOrReturnError(out_signature.SetLength(output_length) == CHIP_NO_ERROR, CHIP_ERROR_INTERNAL);
+
+exit:
+    _log_PSA_error(status);
+    psa_reset_key_attributes(&attr);
+
+    return error;
+}
+
+CHIP_ERROR P256PublicKey::ECDSA_validate_msg_signature(const uint8_t * msg, const size_t msg_length,
+                                                       const P256ECDSASignature & signature) const
+{
+    CHIP_ERROR error          = CHIP_NO_ERROR;
+    psa_status_t status       = PSA_ERROR_BAD_STATE;
+    psa_key_attributes_t attr = PSA_KEY_ATTRIBUTES_INIT;
+
+    VerifyOrExit((msg != nullptr) && (msg_length > 0), error = CHIP_ERROR_INVALID_ARGUMENT);
+
+    psa_crypto_init();
+
+    psa_set_key_type(&attr, PSA_KEY_TYPE_ECC_PUBLIC_KEY(PSA_ECC_FAMILY_SECP_R1));
+    psa_set_key_bits(&attr, 256);
+    psa_set_key_usage_flags(&attr, PSA_KEY_USAGE_VERIFY_MESSAGE);
+    psa_set_key_algorithm(&attr, PSA_ALG_ECDSA(PSA_ALG_SHA_256));
+
+    // use imported key to verify a message
+    status = psa_driver_wrapper_verify_message(&attr, Uint8::to_const_uchar(*this), Length(), PSA_ALG_ECDSA(PSA_ALG_SHA_256), msg,
+                                               msg_length, signature.ConstBytes(), signature.Length());
+
+    VerifyOrExit(status == PSA_SUCCESS, error = CHIP_ERROR_INVALID_SIGNATURE);
+exit:
+    _log_PSA_error(status);
+    psa_reset_key_attributes(&attr);
+
+    return error;
+}
+
+CHIP_ERROR P256PublicKey::ECDSA_validate_hash_signature(const uint8_t * hash, const size_t hash_length,
+                                                        const P256ECDSASignature & signature) const
+{
+    VerifyOrReturnError(hash != nullptr, CHIP_ERROR_INVALID_ARGUMENT);
+    VerifyOrReturnError(hash_length == kSHA256_Hash_Length, CHIP_ERROR_INVALID_ARGUMENT);
+    VerifyOrReturnError(signature.Length() == kP256_ECDSA_Signature_Length_Raw, CHIP_ERROR_INVALID_ARGUMENT);
+
+    CHIP_ERROR error          = CHIP_NO_ERROR;
+    psa_status_t status       = PSA_ERROR_BAD_STATE;
+    psa_key_attributes_t attr = PSA_KEY_ATTRIBUTES_INIT;
+
+    // Step 1: import public key as volatile
+    psa_crypto_init();
+
+    psa_set_key_type(&attr, PSA_KEY_TYPE_ECC_PUBLIC_KEY(PSA_ECC_FAMILY_SECP_R1));
+    psa_set_key_bits(&attr, 256);
+    psa_set_key_usage_flags(&attr, PSA_KEY_USAGE_VERIFY_HASH);
+    psa_set_key_algorithm(&attr, PSA_ALG_ECDSA(PSA_ALG_SHA_256));
+
+    // use imported key to verify a hash
+    status = psa_driver_wrapper_verify_hash(&attr, Uint8::to_const_uchar(*this), Length(), PSA_ALG_ECDSA(PSA_ALG_SHA_256), hash,
+                                            hash_length, signature.ConstBytes(), signature.Length());
+
+    VerifyOrExit(status == PSA_SUCCESS, error = CHIP_ERROR_INVALID_SIGNATURE);
+exit:
+    _log_PSA_error(status);
+    psa_reset_key_attributes(&attr);
+    return error;
+}
+
+CHIP_ERROR P256Keypair::ECDH_derive_secret(const P256PublicKey & remote_public_key, P256ECDHDerivedSecret & out_secret) const
+{
+    // Todo: replace with driver call once key derivation through the driver wrapper has been figured out
+    CHIP_ERROR error                          = CHIP_NO_ERROR;
+    psa_status_t status                       = PSA_ERROR_BAD_STATE;
+    mbedtls_svc_key_id_t key_id               = 0;
+    psa_key_attributes_t attr                 = PSA_KEY_ATTRIBUTES_INIT;
+    size_t output_length                      = 0;
+    const psa_plaintext_ecp_keypair * keypair = to_const_keypair(&mKeypair);
+
+    VerifyOrExit(mInitialized, error = CHIP_ERROR_WELL_UNINITIALIZED);
+
+    // Step 1: import plaintext key as volatile for ECDH
+    psa_crypto_init();
+
+    psa_set_key_type(&attr, PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1));
+    psa_set_key_bits(&attr, keypair->bitlen);
+    psa_set_key_algorithm(&attr, PSA_ALG_ECDH);
+    psa_set_key_usage_flags(&attr, PSA_KEY_USAGE_DERIVE);
+
+    status = psa_import_key(&attr, keypair->privkey, PSA_BITS_TO_BYTES(keypair->bitlen), &key_id);
+
+    VerifyOrExit(status == PSA_SUCCESS, error = CHIP_ERROR_INTERNAL);
+
+    // Step 2: do key derivation
+    status = psa_raw_key_agreement(PSA_ALG_ECDH, key_id, Uint8::to_const_uchar(remote_public_key), remote_public_key.Length(),
+                                   Uint8::to_uchar(out_secret),
+                                   (out_secret.Length() == 0) ? out_secret.Capacity() : out_secret.Length(), &output_length);
+
+    VerifyOrExit(status == PSA_SUCCESS, error = CHIP_ERROR_INTERNAL);
+    SuccessOrExit(out_secret.SetLength(output_length));
+
+exit:
+    _log_PSA_error(status);
+    // Step 3: destroy imported key
+    psa_reset_key_attributes(&attr);
+    if (key_id != 0)
+    {
+        psa_destroy_key(key_id);
+    }
+    return error;
+}
+
+void ClearSecretData(uint8_t * buf, size_t len)
+{
+    mbedtls_platform_zeroize(buf, len);
+}
+
+// THE BELOW IS FROM `third_party/openthread/repo/third_party/mbedtls/repo/library/constant_time.c` since
+// mbedtls_ct_memcmp is not available on Linux somehow :(
+int mbedtls_ct_memcmp_copy(const void * a, const void * b, size_t n)
+{
+    size_t i;
+    volatile const unsigned char * A = (volatile const unsigned char *) a;
+    volatile const unsigned char * B = (volatile const unsigned char *) b;
+    volatile unsigned char diff      = 0;
+
+    for (i = 0; i < n; i++)
+    {
+        /* Read volatile data in order before computing diff.
+         * This avoids IAR compiler warning:
+         * 'the order of volatile accesses is undefined ..' */
+        unsigned char x = A[i], y = B[i];
+        diff |= x ^ y;
+    }
+
+    return ((int) diff);
+}
+
+bool IsBufferContentEqualConstantTime(const void * a, const void * b, size_t n)
+{
+    return mbedtls_ct_memcmp_copy(a, b, n) == 0;
+}
+
+CHIP_ERROR P256Keypair::Initialize()
+{
+    CHIP_ERROR error                    = CHIP_NO_ERROR;
+    psa_status_t status                 = PSA_ERROR_BAD_STATE;
+    psa_plaintext_ecp_keypair * keypair = to_keypair(&mKeypair);
+    size_t output_length;
+
+    if (mInitialized)
+    {
+        return CHIP_ERROR_INCORRECT_STATE;
+    }
+
+    // Step 1: Generate a volatile new key
+    psa_key_attributes_t attr = PSA_KEY_ATTRIBUTES_INIT;
+    psa_crypto_init();
+
+    psa_set_key_type(&attr, PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1));
+    psa_set_key_bits(&attr, 256);
+    psa_set_key_algorithm(&attr, PSA_ALG_ECDH);
+    psa_set_key_usage_flags(&attr, PSA_KEY_USAGE_DERIVE | PSA_KEY_USAGE_EXPORT);
+
+    status = psa_driver_wrapper_generate_key(&attr, keypair->privkey, sizeof(keypair->privkey), &output_length);
+
+    VerifyOrExit(status == PSA_SUCCESS, error = CHIP_ERROR_INTERNAL);
+    VerifyOrExit(output_length == kP256_PrivateKey_Length, error = CHIP_ERROR_INTERNAL);
+
+    keypair->bitlen = 256;
+
+    // Step 2: Export the public key into the pubkey member
+    status = psa_driver_wrapper_export_public_key(&attr, keypair->privkey, sizeof(keypair->privkey), Uint8::to_uchar(mPublicKey),
+                                                  mPublicKey.Length(), &output_length);
+
+    VerifyOrExit(status == PSA_SUCCESS, error = CHIP_ERROR_INTERNAL);
+    VerifyOrExit(output_length == kP256_PublicKey_Length, error = CHIP_ERROR_INTERNAL);
+
+exit:
+    _log_PSA_error(status);
+    if (error == CHIP_NO_ERROR)
+    {
+        mInitialized = true;
+    }
+    psa_reset_key_attributes(&attr);
+
+    return error;
+}
+
+CHIP_ERROR P256Keypair::Serialize(P256SerializedKeypair & output) const
+{
+    CHIP_ERROR error                          = CHIP_NO_ERROR;
+    const psa_plaintext_ecp_keypair * keypair = to_const_keypair(&mKeypair);
+    size_t len                                = output.Length() == 0 ? output.Capacity() : output.Length();
+    Encoding::BufferWriter bbuf(output, len);
+
+    VerifyOrExit(mInitialized, error = CHIP_ERROR_WELL_UNINITIALIZED);
+
+    bbuf.Put(mPublicKey, mPublicKey.Length());
+
+    VerifyOrExit(bbuf.Available() == sizeof(keypair->privkey), error = CHIP_ERROR_INTERNAL);
+
+    bbuf.Put(keypair->privkey, PSA_BITS_TO_BYTES(keypair->bitlen));
+    VerifyOrExit(bbuf.Fit(), error = CHIP_ERROR_BUFFER_TOO_SMALL);
+
+    output.SetLength(bbuf.Needed());
+
+exit:
+    return error;
+}
+
+CHIP_ERROR P256Keypair::Deserialize(P256SerializedKeypair & input)
+{
+    CHIP_ERROR error                    = CHIP_NO_ERROR;
+    psa_plaintext_ecp_keypair * keypair = to_keypair(&mKeypair);
+    Encoding::BufferWriter bbuf(mPublicKey, mPublicKey.Length());
+
+    VerifyOrExit(input.Length() == mPublicKey.Length() + kP256_PrivateKey_Length, error = CHIP_ERROR_INVALID_ARGUMENT);
+
+    Clear();
+
+    memcpy(keypair->privkey, Uint8::to_uchar(input) + mPublicKey.Length(), kP256_PrivateKey_Length);
+    keypair->bitlen = 256;
+
+    bbuf.Put((const uint8_t *) input, mPublicKey.Length());
+    VerifyOrExit(bbuf.Fit(), error = CHIP_ERROR_NO_MEMORY);
+
+    mInitialized = true;
+
+exit:
+    return error;
+}
+
+void P256Keypair::Clear()
+{
+    if (mInitialized)
+    {
+        psa_plaintext_ecp_keypair * keypair = to_keypair(&mKeypair);
+        memset(keypair, 0, sizeof(psa_plaintext_ecp_keypair));
+        mInitialized = false;
+    }
+}
+
+P256Keypair::~P256Keypair()
+{
+    Clear();
+}
+
+CHIP_ERROR P256Keypair::NewCertificateSigningRequest(uint8_t * out_csr, size_t & csr_length) const
+{
+    MutableByteSpan csr(out_csr, csr_length);
+    CHIP_ERROR err = GenerateCertificateSigningRequest(this, csr);
+    csr_length     = (CHIP_NO_ERROR == err) ? csr.size() : 0;
+    return err;
+}
+
+CHIP_ERROR VerifyCertificateSigningRequest(const uint8_t * csr_buf, size_t csr_length, P256PublicKey & pubkey)
+{
+#if defined(MBEDTLS_X509_CSR_PARSE_C)
+    ReturnErrorOnFailure(VerifyCertificateSigningRequestFormat(csr_buf, csr_length));
+
+    // TODO: For some embedded targets, mbedTLS library doesn't have mbedtls_x509_csr_parse_der, and mbedtls_x509_csr_parse_free.
+    //       Taking a step back, embedded targets likely will not process CSR requests. Adding this action item to reevaluate
+    //       this if there's a need for this processing for embedded targets.
+    CHIP_ERROR error   = CHIP_NO_ERROR;
+    size_t pubkey_size = 0;
+
+    mbedtls_ecp_keypair * keypair = nullptr;
+
+    P256ECDSASignature signature;
+    MutableByteSpan out_raw_sig_span(signature.Bytes(), signature.Capacity());
+
+    mbedtls_x509_csr csr;
+    mbedtls_x509_csr_init(&csr);
+
+    int result = mbedtls_x509_csr_parse_der(&csr, csr_buf, csr_length);
+    VerifyOrExit(result == 0, error = CHIP_ERROR_INTERNAL);
+
+    // Verify the signature algorithm and public key type
+    VerifyOrExit(csr.CHIP_CRYPTO_PAL_PRIVATE(sig_md) == MBEDTLS_MD_SHA256, error = CHIP_ERROR_UNSUPPORTED_SIGNATURE_TYPE);
+    VerifyOrExit(csr.CHIP_CRYPTO_PAL_PRIVATE(sig_pk) == MBEDTLS_PK_ECDSA, error = CHIP_ERROR_WRONG_KEY_TYPE);
+
+    keypair = mbedtls_pk_ec(csr.CHIP_CRYPTO_PAL_PRIVATE_X509(pk));
+
+    // Copy the public key from the CSR
+    result = mbedtls_ecp_point_write_binary(&keypair->CHIP_CRYPTO_PAL_PRIVATE(grp), &keypair->CHIP_CRYPTO_PAL_PRIVATE(Q),
+                                            MBEDTLS_ECP_PF_UNCOMPRESSED, &pubkey_size, Uint8::to_uchar(pubkey), pubkey.Length());
+
+    VerifyOrExit(result == 0, error = CHIP_ERROR_INTERNAL);
+    VerifyOrExit(pubkey_size == pubkey.Length(), error = CHIP_ERROR_INTERNAL);
+
+    // Convert DER signature to raw signature
+    error = EcdsaAsn1SignatureToRaw(kP256_FE_Length,
+                                    ByteSpan{ csr.CHIP_CRYPTO_PAL_PRIVATE(sig).CHIP_CRYPTO_PAL_PRIVATE_X509(p),
+                                              csr.CHIP_CRYPTO_PAL_PRIVATE(sig).CHIP_CRYPTO_PAL_PRIVATE_X509(len) },
+                                    out_raw_sig_span);
+
+    VerifyOrExit(error == CHIP_NO_ERROR, error = CHIP_ERROR_INVALID_ARGUMENT);
+    VerifyOrExit(out_raw_sig_span.size() == (kP256_FE_Length * 2), error = CHIP_ERROR_INTERNAL);
+    signature.SetLength(out_raw_sig_span.size());
+
+    // Verify the signature using the public key
+    error = pubkey.ECDSA_validate_msg_signature(csr.CHIP_CRYPTO_PAL_PRIVATE_X509(cri).CHIP_CRYPTO_PAL_PRIVATE_X509(p),
+                                                csr.CHIP_CRYPTO_PAL_PRIVATE_X509(cri).CHIP_CRYPTO_PAL_PRIVATE_X509(len), signature);
+
+    SuccessOrExit(error);
+
+exit:
+    mbedtls_x509_csr_free(&csr);
+    _log_mbedTLS_error(result);
+    return error;
+#else
+    ChipLogError(Crypto, "MBEDTLS_X509_CSR_PARSE_C is not enabled. CSR cannot be parsed");
+    return CHIP_ERROR_UNSUPPORTED_CHIP_FEATURE;
+#endif
+}
+
+typedef struct Spake2p_Context
+{
+    mbedtls_ecp_group curve;
+    mbedtls_ecp_point M;
+    mbedtls_ecp_point N;
+    mbedtls_ecp_point X;
+    mbedtls_ecp_point Y;
+    mbedtls_ecp_point L;
+    mbedtls_ecp_point Z;
+    mbedtls_ecp_point V;
+
+    mbedtls_mpi w0;
+    mbedtls_mpi w1;
+    mbedtls_mpi xy;
+    mbedtls_mpi tempbn;
+} Spake2p_Context;
+
+static inline Spake2p_Context * to_inner_spake2p_context(Spake2pOpaqueContext * context)
+{
+    return SafePointerCast<Spake2p_Context *>(context);
+}
+
+CHIP_ERROR Spake2p_P256_SHA256_HKDF_HMAC::InitInternal(void)
+{
+    CHIP_ERROR error = CHIP_NO_ERROR;
+    int result       = 0;
+
+    Spake2p_Context * context = to_inner_spake2p_context(&mSpake2pContext);
+
+    memset(context, 0, sizeof(Spake2p_Context));
+
+    mbedtls_ecp_group_init(&context->curve);
+    result = mbedtls_ecp_group_load(&context->curve, MBEDTLS_ECP_DP_SECP256R1);
+    VerifyOrExit(result == 0, error = CHIP_ERROR_INTERNAL);
+
+    VerifyOrExit(mbedtls_md_info_from_type(MBEDTLS_MD_SHA256) != nullptr, error = CHIP_ERROR_INTERNAL);
+
+    mbedtls_ecp_point_init(&context->M);
+    mbedtls_ecp_point_init(&context->N);
+    mbedtls_ecp_point_init(&context->X);
+    mbedtls_ecp_point_init(&context->Y);
+    mbedtls_ecp_point_init(&context->L);
+    mbedtls_ecp_point_init(&context->V);
+    mbedtls_ecp_point_init(&context->Z);
+    M = &context->M;
+    N = &context->N;
+    X = &context->X;
+    Y = &context->Y;
+    L = &context->L;
+    V = &context->V;
+    Z = &context->Z;
+
+    mbedtls_mpi_init(&context->w0);
+    mbedtls_mpi_init(&context->w1);
+    mbedtls_mpi_init(&context->xy);
+    mbedtls_mpi_init(&context->tempbn);
+    w0     = &context->w0;
+    w1     = &context->w1;
+    xy     = &context->xy;
+    tempbn = &context->tempbn;
+
+    G     = &context->curve.G;
+    order = &context->curve.N;
+
+    return error;
+
+exit:
+    _log_mbedTLS_error(result);
+    Clear();
+    return error;
+}
+
+void Spake2p_P256_SHA256_HKDF_HMAC::Clear()
+{
+    VerifyOrReturn(state != CHIP_SPAKE2P_STATE::PREINIT);
+
+    Spake2p_Context * context = to_inner_spake2p_context(&mSpake2pContext);
+
+    mbedtls_ecp_point_free(&context->M);
+    mbedtls_ecp_point_free(&context->N);
+    mbedtls_ecp_point_free(&context->X);
+    mbedtls_ecp_point_free(&context->Y);
+    mbedtls_ecp_point_free(&context->L);
+    mbedtls_ecp_point_free(&context->Z);
+    mbedtls_ecp_point_free(&context->V);
+
+    mbedtls_mpi_free(&context->w0);
+    mbedtls_mpi_free(&context->w1);
+    mbedtls_mpi_free(&context->xy);
+    mbedtls_mpi_free(&context->tempbn);
+
+    mbedtls_ecp_group_free(&context->curve);
+
+    state = CHIP_SPAKE2P_STATE::PREINIT;
+}
+
+CHIP_ERROR Spake2p_P256_SHA256_HKDF_HMAC::Mac(const uint8_t * key, size_t key_len, const uint8_t * in, size_t in_len,
+                                              MutableByteSpan & out_span)
+{
+    HMAC_sha hmac;
+    VerifyOrReturnError(out_span.size() >= kSHA256_Hash_Length, CHIP_ERROR_BUFFER_TOO_SMALL);
+    ReturnErrorOnFailure(hmac.HMAC_SHA256(key, key_len, in, in_len, out_span.data(), kSHA256_Hash_Length));
+    out_span = out_span.SubSpan(0, kSHA256_Hash_Length);
+    return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR Spake2p_P256_SHA256_HKDF_HMAC::MacVerify(const uint8_t * key, size_t key_len, const uint8_t * mac, size_t mac_len,
+                                                    const uint8_t * in, size_t in_len)
+{
+    CHIP_ERROR error = CHIP_NO_ERROR;
+    int result       = 0;
+
+    uint8_t computed_mac[kSHA256_Hash_Length];
+    MutableByteSpan computed_mac_span{ computed_mac };
+    VerifyOrExit(mac_len == kSHA256_Hash_Length, error = CHIP_ERROR_INVALID_ARGUMENT);
+
+    SuccessOrExit(error = Mac(key, key_len, in, in_len, computed_mac_span));
+    VerifyOrExit(computed_mac_span.size() == mac_len, error = CHIP_ERROR_INTERNAL);
+
+    VerifyOrExit(IsBufferContentEqualConstantTime(mac, computed_mac, kSHA256_Hash_Length), error = CHIP_ERROR_INTERNAL);
+
+exit:
+    _log_mbedTLS_error(result);
+    return error;
+}
+
+CHIP_ERROR Spake2p_P256_SHA256_HKDF_HMAC::FELoad(const uint8_t * in, size_t in_len, void * fe)
+{
+    CHIP_ERROR error = CHIP_NO_ERROR;
+    int result       = 0;
+
+    result = mbedtls_mpi_read_binary((mbedtls_mpi *) fe, Uint8::to_const_uchar(in), in_len);
+    VerifyOrExit(result == 0, error = CHIP_ERROR_INTERNAL);
+
+    result = mbedtls_mpi_mod_mpi((mbedtls_mpi *) fe, (mbedtls_mpi *) fe, (const mbedtls_mpi *) order);
+    VerifyOrExit(result == 0, error = CHIP_ERROR_INTERNAL);
+
+exit:
+    _log_mbedTLS_error(result);
+    return error;
+}
+
+CHIP_ERROR Spake2p_P256_SHA256_HKDF_HMAC::FEWrite(const void * fe, uint8_t * out, size_t out_len)
+{
+    if (mbedtls_mpi_write_binary((const mbedtls_mpi *) fe, Uint8::to_uchar(out), out_len) != 0)
+    {
+        return CHIP_ERROR_INTERNAL;
+    }
+    return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR Spake2p_P256_SHA256_HKDF_HMAC::FEGenerate(void * fe)
+{
+    CHIP_ERROR error = CHIP_NO_ERROR;
+    int result       = 0;
+
+    Spake2p_Context * context = to_inner_spake2p_context(&mSpake2pContext);
+
+    result = mbedtls_ecp_gen_privkey(&context->curve, (mbedtls_mpi *) fe, CryptoRNG, nullptr);
+    VerifyOrExit(result == 0, error = CHIP_ERROR_INTERNAL);
+
+exit:
+    _log_mbedTLS_error(result);
+    return error;
+}
+
+CHIP_ERROR Spake2p_P256_SHA256_HKDF_HMAC::FEMul(void * fer, const void * fe1, const void * fe2)
+{
+    CHIP_ERROR error = CHIP_NO_ERROR;
+    int result       = 0;
+
+    result = mbedtls_mpi_mul_mpi((mbedtls_mpi *) fer, (const mbedtls_mpi *) fe1, (const mbedtls_mpi *) fe2);
+    VerifyOrExit(result == 0, error = CHIP_ERROR_INTERNAL);
+
+    result = mbedtls_mpi_mod_mpi((mbedtls_mpi *) fer, (mbedtls_mpi *) fer, (const mbedtls_mpi *) order);
+    VerifyOrExit(result == 0, error = CHIP_ERROR_INTERNAL);
+
+exit:
+    _log_mbedTLS_error(result);
+    return error;
+}
+
+CHIP_ERROR Spake2p_P256_SHA256_HKDF_HMAC::PointLoad(const uint8_t * in, size_t in_len, void * R)
+{
+    Spake2p_Context * context = to_inner_spake2p_context(&mSpake2pContext);
+
+    if (mbedtls_ecp_point_read_binary(&context->curve, (mbedtls_ecp_point *) R, Uint8::to_const_uchar(in), in_len) != 0)
+    {
+        return CHIP_ERROR_INTERNAL;
+    }
+
+    return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR Spake2p_P256_SHA256_HKDF_HMAC::PointWrite(const void * R, uint8_t * out, size_t out_len)
+{
+    memset(out, 0, out_len);
+
+    size_t mbedtls_out_len = out_len;
+
+    Spake2p_Context * context = to_inner_spake2p_context(&mSpake2pContext);
+
+    if (mbedtls_ecp_point_write_binary(&context->curve, (const mbedtls_ecp_point *) R, MBEDTLS_ECP_PF_UNCOMPRESSED,
+                                       &mbedtls_out_len, Uint8::to_uchar(out), out_len) != 0)
+    {
+        return CHIP_ERROR_INTERNAL;
+    }
+
+    return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR Spake2p_P256_SHA256_HKDF_HMAC::PointMul(void * R, const void * P1, const void * fe1)
+{
+    Spake2p_Context * context = to_inner_spake2p_context(&mSpake2pContext);
+
+    if (mbedtls_ecp_mul(&context->curve, (mbedtls_ecp_point *) R, (const mbedtls_mpi *) fe1, (const mbedtls_ecp_point *) P1,
+                        CryptoRNG, nullptr) != 0)
+    {
+        return CHIP_ERROR_INTERNAL;
+    }
+
+    return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR Spake2p_P256_SHA256_HKDF_HMAC::PointAddMul(void * R, const void * P1, const void * fe1, const void * P2,
+                                                      const void * fe2)
+{
+    Spake2p_Context * context = to_inner_spake2p_context(&mSpake2pContext);
+
+    if (mbedtls_ecp_muladd(&context->curve, (mbedtls_ecp_point *) R, (const mbedtls_mpi *) fe1, (const mbedtls_ecp_point *) P1,
+                           (const mbedtls_mpi *) fe2, (const mbedtls_ecp_point *) P2) != 0)
+    {
+        return CHIP_ERROR_INTERNAL;
+    }
+
+    return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR Spake2p_P256_SHA256_HKDF_HMAC::PointInvert(void * R)
+{
+    mbedtls_ecp_point * Rp    = (mbedtls_ecp_point *) R;
+    Spake2p_Context * context = to_inner_spake2p_context(&mSpake2pContext);
+
+    if (mbedtls_mpi_sub_mpi(&Rp->CHIP_CRYPTO_PAL_PRIVATE(Y), &context->curve.P, &Rp->CHIP_CRYPTO_PAL_PRIVATE(Y)) != 0)
+    {
+        return CHIP_ERROR_INTERNAL;
+    }
+
+    return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR Spake2p_P256_SHA256_HKDF_HMAC::PointCofactorMul(void * R)
+{
+    return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR Spake2p_P256_SHA256_HKDF_HMAC::ComputeL(uint8_t * Lout, size_t * L_len, const uint8_t * w1in, size_t w1in_len)
+{
+    CHIP_ERROR error = CHIP_NO_ERROR;
+    int result       = 0;
+
+    mbedtls_ecp_group curve;
+    mbedtls_mpi w1_bn;
+    mbedtls_ecp_point Ltemp;
+
+    mbedtls_ecp_group_init(&curve);
+    mbedtls_mpi_init(&w1_bn);
+    mbedtls_ecp_point_init(&Ltemp);
+
+    result = mbedtls_ecp_group_load(&curve, MBEDTLS_ECP_DP_SECP256R1);
+    VerifyOrExit(result == 0, error = CHIP_ERROR_INTERNAL);
+
+    result = mbedtls_mpi_read_binary(&w1_bn, Uint8::to_const_uchar(w1in), w1in_len);
+    VerifyOrExit(result == 0, error = CHIP_ERROR_INTERNAL);
+
+    result = mbedtls_mpi_mod_mpi(&w1_bn, &w1_bn, &curve.N);
+    VerifyOrExit(result == 0, error = CHIP_ERROR_INTERNAL);
+
+    result = mbedtls_ecp_mul(&curve, &Ltemp, &w1_bn, &curve.G, CryptoRNG, nullptr);
+    VerifyOrExit(result == 0, error = CHIP_ERROR_INTERNAL);
+
+    memset(Lout, 0, *L_len);
+
+    result = mbedtls_ecp_point_write_binary(&curve, &Ltemp, MBEDTLS_ECP_PF_UNCOMPRESSED, L_len, Uint8::to_uchar(Lout), *L_len);
+    VerifyOrExit(result == 0, error = CHIP_ERROR_INTERNAL);
+
+exit:
+    _log_mbedTLS_error(result);
+    mbedtls_ecp_point_free(&Ltemp);
+    mbedtls_mpi_free(&w1_bn);
+    mbedtls_ecp_group_free(&curve);
+
+    return error;
+}
+
+CHIP_ERROR Spake2p_P256_SHA256_HKDF_HMAC::PointIsValid(void * R)
+{
+    Spake2p_Context * context = to_inner_spake2p_context(&mSpake2pContext);
+
+    if (mbedtls_ecp_check_pubkey(&context->curve, (mbedtls_ecp_point *) R) != 0)
+    {
+        return CHIP_ERROR_INTERNAL;
+    }
+
+    return CHIP_NO_ERROR;
+}
+
+constexpr uint8_t sOID_AttributeType_CommonName[]         = { 0x55, 0x04, 0x03 };
+constexpr uint8_t sOID_AttributeType_MatterVendorId[]     = { 0x2B, 0x06, 0x01, 0x04, 0x01, 0x82, 0xA2, 0x7C, 0x02, 0x01 };
+constexpr uint8_t sOID_AttributeType_MatterProductId[]    = { 0x2B, 0x06, 0x01, 0x04, 0x01, 0x82, 0xA2, 0x7C, 0x02, 0x02 };
+constexpr uint8_t sOID_SigAlgo_ECDSAWithSHA256[]          = { 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x04, 0x03, 0x02 };
+constexpr uint8_t sOID_Extension_BasicConstraints[]       = { 0x55, 0x1D, 0x13 };
+constexpr uint8_t sOID_Extension_KeyUsage[]               = { 0x55, 0x1D, 0x0F };
+constexpr uint8_t sOID_Extension_SubjectKeyIdentifier[]   = { 0x55, 0x1D, 0x0E };
+constexpr uint8_t sOID_Extension_AuthorityKeyIdentifier[] = { 0x55, 0x1D, 0x23 };
+
+/**
+ * Compares an mbedtls_asn1_buf structure (oidBuf) to a reference OID represented as uint8_t array (oid).
+ */
+#define OID_CMP(oid, oidBuf)                                                                                                       \
+    ((MBEDTLS_ASN1_OID == (oidBuf).CHIP_CRYPTO_PAL_PRIVATE_X509(tag)) &&                                                           \
+     (sizeof(oid) == (oidBuf).CHIP_CRYPTO_PAL_PRIVATE_X509(len)) &&                                                                \
+     (memcmp((oid), (oidBuf).CHIP_CRYPTO_PAL_PRIVATE_X509(p), (oidBuf).CHIP_CRYPTO_PAL_PRIVATE_X509(len)) == 0))
+
+CHIP_ERROR VerifyAttestationCertificateFormat(const ByteSpan & cert, AttestationCertType certType)
+{
+#if defined(MBEDTLS_X509_CRT_PARSE_C)
+    CHIP_ERROR error = CHIP_NO_ERROR;
+    int result       = 0;
+    mbedtls_x509_crt mbed_cert;
+    unsigned char * p         = nullptr;
+    const unsigned char * end = nullptr;
+    size_t len                = 0;
+    bool extBasicPresent      = false;
+    bool extKeyUsagePresent   = false;
+
+    VerifyOrReturnError(!cert.empty(), CHIP_ERROR_INVALID_ARGUMENT);
+
+    mbedtls_x509_crt_init(&mbed_cert);
+
+    result = mbedtls_x509_crt_parse(&mbed_cert, Uint8::to_const_uchar(cert.data()), cert.size());
+    VerifyOrExit(result == 0, error = CHIP_ERROR_INTERNAL);
+
+    // "version" value is 1 higher than the actual encoded value.
+    VerifyOrExit(mbed_cert.CHIP_CRYPTO_PAL_PRIVATE_X509(version) - 1 == 2, error = CHIP_ERROR_INTERNAL);
+
+    // Verify signature algorithms is ECDSA with SHA256.
+    VerifyOrExit(OID_CMP(sOID_SigAlgo_ECDSAWithSHA256, mbed_cert.CHIP_CRYPTO_PAL_PRIVATE_X509(sig_oid)),
+                 error = CHIP_ERROR_INTERNAL);
+
+    // Verify public key presence and format.
+    {
+        Crypto::P256PublicKey pubkey;
+        SuccessOrExit(error = ExtractPubkeyFromX509Cert(cert, pubkey));
+    }
+
+    p      = mbed_cert.CHIP_CRYPTO_PAL_PRIVATE_X509(v3_ext).CHIP_CRYPTO_PAL_PRIVATE_X509(p);
+    end    = p + mbed_cert.CHIP_CRYPTO_PAL_PRIVATE_X509(v3_ext).CHIP_CRYPTO_PAL_PRIVATE_X509(len);
+    result = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE);
+    VerifyOrExit(result == 0, error = CHIP_ERROR_INTERNAL);
+
+    while (p < end)
+    {
+        mbedtls_x509_buf extOID = { 0, 0, nullptr };
+        int extCritical         = 0;
+
+        result = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE);
+        VerifyOrExit(result == 0, error = CHIP_ERROR_INTERNAL);
+
+        /* Get extension ID */
+        result = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_OID);
+        VerifyOrExit(result == 0, error = CHIP_ERROR_INTERNAL);
+
+        extOID.CHIP_CRYPTO_PAL_PRIVATE_X509(tag) = MBEDTLS_ASN1_OID;
+        extOID.CHIP_CRYPTO_PAL_PRIVATE_X509(len) = len;
+        extOID.CHIP_CRYPTO_PAL_PRIVATE_X509(p)   = p;
+        p += len;
+
+        /* Get optional critical */
+        result = mbedtls_asn1_get_bool(&p, end, &extCritical);
+        VerifyOrExit(result == 0 || result == MBEDTLS_ERR_ASN1_UNEXPECTED_TAG, error = CHIP_ERROR_INTERNAL);
+
+        /* Data should be octet string type */
+        result = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_OCTET_STRING);
+        VerifyOrExit(result == 0, error = CHIP_ERROR_INTERNAL);
+
+        if (OID_CMP(sOID_Extension_BasicConstraints, extOID))
+        {
+            int isCA                 = 0;
+            int pathLen              = -1;
+            unsigned char * seqStart = p;
+
+            VerifyOrExit(extCritical, error = CHIP_ERROR_INTERNAL);
+            extBasicPresent = true;
+
+            result = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE);
+            VerifyOrExit(result == 0, error = CHIP_ERROR_INTERNAL);
+            if (len > 0)
+            {
+                result = mbedtls_asn1_get_bool(&p, end, &isCA);
+                VerifyOrExit(result == 0 || result == MBEDTLS_ERR_ASN1_UNEXPECTED_TAG, error = CHIP_ERROR_INTERNAL);
+
+                if (p != seqStart + len)
+                {
+                    result = mbedtls_asn1_get_int(&p, end, &pathLen);
+                    VerifyOrExit(result == 0, error = CHIP_ERROR_INTERNAL);
+                }
+            }
+
+            if (certType == AttestationCertType::kDAC)
+            {
+                VerifyOrExit(!isCA && pathLen == -1, error = CHIP_ERROR_INTERNAL);
+            }
+            else if (certType == AttestationCertType::kPAI)
+            {
+                VerifyOrExit(isCA && pathLen == 0, error = CHIP_ERROR_INTERNAL);
+            }
+            else
+            {
+                VerifyOrExit(isCA && (pathLen == -1 || pathLen == 0 || pathLen == 1), error = CHIP_ERROR_INTERNAL);
+            }
+        }
+        else if (OID_CMP(sOID_Extension_KeyUsage, extOID))
+        {
+            mbedtls_x509_bitstring bs = { 0, 0, nullptr };
+            unsigned int keyUsage     = 0;
+
+            VerifyOrExit(extCritical, error = CHIP_ERROR_INTERNAL);
+            extKeyUsagePresent = true;
+
+            result = mbedtls_asn1_get_bitstring(&p, p + len, &bs);
+            VerifyOrExit(result == 0, error = CHIP_ERROR_INTERNAL);
+
+            for (size_t i = 0; i < bs.CHIP_CRYPTO_PAL_PRIVATE_X509(len) && i < sizeof(unsigned int); i++)
+            {
+                keyUsage |= static_cast<unsigned int>(bs.CHIP_CRYPTO_PAL_PRIVATE_X509(p)[i]) << (8 * i);
+            }
+
+            if (certType == AttestationCertType::kDAC)
+            {
+                // SHALL only have the digitalSignature bit set.
+                VerifyOrExit(keyUsage == MBEDTLS_X509_KU_DIGITAL_SIGNATURE, error = CHIP_ERROR_INTERNAL);
+            }
+            else
+            {
+                bool keyCertSignFlag = keyUsage & MBEDTLS_X509_KU_KEY_CERT_SIGN;
+                bool crlSignFlag     = keyUsage & MBEDTLS_X509_KU_CRL_SIGN;
+                bool otherFlags =
+                    keyUsage & ~(MBEDTLS_X509_KU_CRL_SIGN | MBEDTLS_X509_KU_KEY_CERT_SIGN | MBEDTLS_X509_KU_DIGITAL_SIGNATURE);
+                VerifyOrExit(keyCertSignFlag && crlSignFlag && !otherFlags, error = CHIP_ERROR_INTERNAL);
+            }
+        }
+        else
+        {
+            p += len;
+        }
+    }
+
+    // Verify basic and key usage extensions are present.
+    VerifyOrExit(extBasicPresent && extKeyUsagePresent, error = CHIP_ERROR_INTERNAL);
+
+    // Verify that SKID and AKID extensions are present.
+    {
+        uint8_t kidBuf[kSubjectKeyIdentifierLength];
+        MutableByteSpan kid(kidBuf);
+        SuccessOrExit(error = ExtractSKIDFromX509Cert(cert, kid));
+        if (certType == AttestationCertType::kDAC || certType == AttestationCertType::kPAI)
+        {
+            // Mandatory extension for DAC and PAI certs.
+            SuccessOrExit(error = ExtractAKIDFromX509Cert(cert, kid));
+        }
+    }
+
+exit:
+    _log_mbedTLS_error(result);
+    mbedtls_x509_crt_free(&mbed_cert);
+
+#else
+    (void) cert;
+    (void) certType;
+    CHIP_ERROR error = CHIP_ERROR_NOT_IMPLEMENTED;
+#endif // defined(MBEDTLS_X509_CRT_PARSE_C)
+
+    return error;
+}
+
+CHIP_ERROR ValidateCertificateChain(const uint8_t * rootCertificate, size_t rootCertificateLen, const uint8_t * caCertificate,
+                                    size_t caCertificateLen, const uint8_t * leafCertificate, size_t leafCertificateLen,
+                                    CertificateChainValidationResult & result)
+{
+#if defined(MBEDTLS_X509_CRT_PARSE_C)
+    CHIP_ERROR error = CHIP_NO_ERROR;
+    mbedtls_x509_crt certChain;
+    mbedtls_x509_crt rootCert;
+    mbedtls_x509_time leaf_valid_from;
+    mbedtls_x509_crt * cert = NULL;
+    int mbedResult;
+    uint32_t flags;
+    int compare_from  = 0;
+    int compare_until = 0;
+
+    result = CertificateChainValidationResult::kInternalFrameworkError;
+
+    VerifyOrReturnError(rootCertificate != nullptr && rootCertificateLen != 0,
+                        (result = CertificateChainValidationResult::kRootArgumentInvalid, CHIP_ERROR_INVALID_ARGUMENT));
+    VerifyOrReturnError(leafCertificate != nullptr && leafCertificateLen != 0,
+                        (result = CertificateChainValidationResult::kLeafArgumentInvalid, CHIP_ERROR_INVALID_ARGUMENT));
+
+    mbedtls_x509_crt_init(&certChain);
+    mbedtls_x509_crt_init(&rootCert);
+
+    /* Start of chain  */
+    mbedResult = mbedtls_x509_crt_parse(&certChain, Uint8::to_const_uchar(leafCertificate), leafCertificateLen);
+    VerifyOrExit(mbedResult == 0, (result = CertificateChainValidationResult::kLeafFormatInvalid, error = CHIP_ERROR_INTERNAL));
+    leaf_valid_from = certChain.valid_from;
+
+    /* Add the intermediate to the chain, if present */
+    if (caCertificate != nullptr && caCertificateLen > 0)
+    {
+        mbedResult = mbedtls_x509_crt_parse(&certChain, Uint8::to_const_uchar(caCertificate), caCertificateLen);
+        VerifyOrExit(mbedResult == 0, (result = CertificateChainValidationResult::kICAFormatInvalid, error = CHIP_ERROR_INTERNAL));
+    }
+
+    /* Parse the root cert */
+    mbedResult = mbedtls_x509_crt_parse(&rootCert, Uint8::to_const_uchar(rootCertificate), rootCertificateLen);
+    VerifyOrExit(mbedResult == 0, (result = CertificateChainValidationResult::kRootFormatInvalid, error = CHIP_ERROR_INTERNAL));
+
+    /* Validates that intermediate and root certificates are valid at the time of the leaf certificate's start time.  */
+    compare_from  = timeCompare(&leaf_valid_from, &rootCert.valid_from);
+    compare_until = timeCompare(&leaf_valid_from, &rootCert.valid_to);
+    VerifyOrExit((compare_from >= 0) && (compare_until <= 0),
+                 (result = CertificateChainValidationResult::kChainInvalid, error = CHIP_ERROR_CERT_NOT_TRUSTED));
+    cert = certChain.next;
+    while (cert)
+    {
+        compare_from  = timeCompare(&leaf_valid_from, &cert->valid_from);
+        compare_until = timeCompare(&leaf_valid_from, &cert->valid_to);
+        VerifyOrExit((compare_from >= 0) && (compare_until <= 0),
+                     (result = CertificateChainValidationResult::kChainInvalid, error = CHIP_ERROR_CERT_NOT_TRUSTED));
+        cert = cert->next;
+    }
+
+    /* Verify the chain against the root */
+    mbedResult = mbedtls_x509_crt_verify(&certChain, &rootCert, NULL, NULL, &flags, NULL, NULL);
+
+    switch (mbedResult)
+    {
+    case 0:
+        VerifyOrExit(flags == 0, (result = CertificateChainValidationResult::kInternalFrameworkError, error = CHIP_ERROR_INTERNAL));
+        result = CertificateChainValidationResult::kSuccess;
+        break;
+    case MBEDTLS_ERR_X509_CERT_VERIFY_FAILED:
+        result = CertificateChainValidationResult::kChainInvalid;
+        error  = CHIP_ERROR_CERT_NOT_TRUSTED;
+        break;
+    default:
+        SuccessOrExit((result = CertificateChainValidationResult::kInternalFrameworkError, error = CHIP_ERROR_INTERNAL));
+    }
+
+exit:
+    _log_mbedTLS_error(mbedResult);
+    mbedtls_x509_crt_free(&certChain);
+    mbedtls_x509_crt_free(&rootCert);
+
+#else
+    (void) rootCertificate;
+    (void) rootCertificateLen;
+    (void) caCertificate;
+    (void) caCertificateLen;
+    (void) leafCertificate;
+    (void) leafCertificateLen;
+    (void) result;
+    CHIP_ERROR error = CHIP_ERROR_NOT_IMPLEMENTED;
+#endif // defined(MBEDTLS_X509_CRT_PARSE_C)
+
+    return error;
+}
+
+inline bool IsTimeGreaterThanEqual(const mbedtls_x509_time * const timeA, const mbedtls_x509_time * const timeB)
+{
+
+    // checks if two values are different and if yes, then returns first > second.
+#define RETURN_STRICTLY_GREATER_IF_DIFFERENT(component)                                                                            \
+    {                                                                                                                              \
+        auto valueA = timeA->CHIP_CRYPTO_PAL_PRIVATE_X509(component);                                                              \
+        auto valueB = timeB->CHIP_CRYPTO_PAL_PRIVATE_X509(component);                                                              \
+                                                                                                                                   \
+        if (valueA != valueB)                                                                                                      \
+        {                                                                                                                          \
+            return valueA > valueB;                                                                                                \
+        }                                                                                                                          \
+    }
+
+    RETURN_STRICTLY_GREATER_IF_DIFFERENT(year);
+    RETURN_STRICTLY_GREATER_IF_DIFFERENT(mon);
+    RETURN_STRICTLY_GREATER_IF_DIFFERENT(day);
+    RETURN_STRICTLY_GREATER_IF_DIFFERENT(hour);
+    RETURN_STRICTLY_GREATER_IF_DIFFERENT(min);
+    RETURN_STRICTLY_GREATER_IF_DIFFERENT(sec);
+
+    // all above are equal
+    return true;
+}
+
+CHIP_ERROR IsCertificateValidAtIssuance(const ByteSpan & referenceCertificate, const ByteSpan & toBeEvaluatedCertificate)
+{
+#if defined(MBEDTLS_X509_CRT_PARSE_C)
+    CHIP_ERROR error = CHIP_NO_ERROR;
+    mbedtls_x509_crt mbedReferenceCertificate;
+    mbedtls_x509_crt mbedToBeEvaluatedCertificate;
+    mbedtls_x509_time refNotBeforeTime;
+    mbedtls_x509_time tbeNotBeforeTime;
+    mbedtls_x509_time tbeNotAfterTime;
+    int result;
+
+    VerifyOrReturnError(!referenceCertificate.empty() && !toBeEvaluatedCertificate.empty(), CHIP_ERROR_INVALID_ARGUMENT);
+
+    mbedtls_x509_crt_init(&mbedReferenceCertificate);
+    mbedtls_x509_crt_init(&mbedToBeEvaluatedCertificate);
+
+    result = mbedtls_x509_crt_parse(&mbedReferenceCertificate, Uint8::to_const_uchar(referenceCertificate.data()),
+                                    referenceCertificate.size());
+    VerifyOrExit(result == 0, error = CHIP_ERROR_INTERNAL);
+
+    result = mbedtls_x509_crt_parse(&mbedToBeEvaluatedCertificate, Uint8::to_const_uchar(toBeEvaluatedCertificate.data()),
+                                    toBeEvaluatedCertificate.size());
+    VerifyOrExit(result == 0, error = CHIP_ERROR_INTERNAL);
+
+    refNotBeforeTime = mbedReferenceCertificate.CHIP_CRYPTO_PAL_PRIVATE_X509(valid_from);
+    tbeNotBeforeTime = mbedToBeEvaluatedCertificate.CHIP_CRYPTO_PAL_PRIVATE_X509(valid_from);
+    tbeNotAfterTime  = mbedToBeEvaluatedCertificate.CHIP_CRYPTO_PAL_PRIVATE_X509(valid_to);
+
+    // check if referenceCertificate is issued at or after tbeCertificate's notBefore timestamp
+    VerifyOrExit(IsTimeGreaterThanEqual(&refNotBeforeTime, &tbeNotBeforeTime), error = CHIP_ERROR_CERT_EXPIRED);
+
+    // check if referenceCertificate is issued at or before tbeCertificate's notAfter timestamp
+    VerifyOrExit(IsTimeGreaterThanEqual(&tbeNotAfterTime, &refNotBeforeTime), error = CHIP_ERROR_CERT_EXPIRED);
+
+exit:
+    _log_mbedTLS_error(result);
+    mbedtls_x509_crt_free(&mbedReferenceCertificate);
+    mbedtls_x509_crt_free(&mbedToBeEvaluatedCertificate);
+
+#else
+    (void) referenceCertificate;
+    (void) toBeEvaluatedCertificate;
+    CHIP_ERROR error = CHIP_ERROR_NOT_IMPLEMENTED;
+#endif // defined(MBEDTLS_X509_CRT_PARSE_C)
+
+    return error;
+}
+
+CHIP_ERROR IsCertificateValidAtCurrentTime(const ByteSpan & certificate)
+{
+#if defined(MBEDTLS_X509_CRT_PARSE_C)
+    CHIP_ERROR error = CHIP_NO_ERROR;
+    mbedtls_x509_crt mbedCertificate;
+    int result;
+
+    VerifyOrReturnError(!certificate.empty(), CHIP_ERROR_INVALID_ARGUMENT);
+
+    mbedtls_x509_crt_init(&mbedCertificate);
+
+    result = mbedtls_x509_crt_parse(&mbedCertificate, Uint8::to_const_uchar(certificate.data()), certificate.size());
+    VerifyOrExit(result == 0, error = CHIP_ERROR_INTERNAL);
+
+    // check if certificate's notBefore timestamp is earlier than or equal to current time.
+    result = mbedtls_x509_time_is_past(&mbedCertificate.CHIP_CRYPTO_PAL_PRIVATE_X509(valid_from));
+    VerifyOrExit(result == 1, error = CHIP_ERROR_CERT_EXPIRED);
+
+    // check if certificate's notAfter timestamp is later than current time.
+    result = mbedtls_x509_time_is_future(&mbedCertificate.CHIP_CRYPTO_PAL_PRIVATE_X509(valid_to));
+    VerifyOrExit(result == 1, error = CHIP_ERROR_CERT_EXPIRED);
+
+exit:
+    _log_mbedTLS_error(result);
+    mbedtls_x509_crt_free(&mbedCertificate);
+
+#else
+    (void) certificate;
+    CHIP_ERROR error = CHIP_ERROR_NOT_IMPLEMENTED;
+#endif // defined(MBEDTLS_X509_CRT_PARSE_C)
+
+    return error;
+}
+
+CHIP_ERROR ExtractPubkeyFromX509Cert(const ByteSpan & certificate, Crypto::P256PublicKey & pubkey)
+{
+#if defined(MBEDTLS_X509_CRT_PARSE_C)
+    CHIP_ERROR error = CHIP_NO_ERROR;
+    mbedtls_x509_crt mbed_cert;
+    mbedtls_ecp_keypair * keypair = nullptr;
+    size_t pubkey_size            = 0;
+
+    mbedtls_x509_crt_init(&mbed_cert);
+
+    int result = mbedtls_x509_crt_parse(&mbed_cert, Uint8::to_const_uchar(certificate.data()), certificate.size());
+    VerifyOrExit(result == 0, error = CHIP_ERROR_INTERNAL);
+
+    VerifyOrExit(mbedtls_pk_get_type(&(mbed_cert.CHIP_CRYPTO_PAL_PRIVATE_X509(pk))) == MBEDTLS_PK_ECKEY,
+                 error = CHIP_ERROR_INVALID_ARGUMENT);
+
+    keypair = mbedtls_pk_ec(mbed_cert.CHIP_CRYPTO_PAL_PRIVATE_X509(pk));
+    VerifyOrExit(keypair->CHIP_CRYPTO_PAL_PRIVATE(grp).id == MapECPGroupId(pubkey.Type()), error = CHIP_ERROR_INVALID_ARGUMENT);
+    // Copy the public key from the cert in raw point format
+    result =
+        mbedtls_ecp_point_write_binary(&keypair->CHIP_CRYPTO_PAL_PRIVATE(grp), &keypair->CHIP_CRYPTO_PAL_PRIVATE(Q),
+                                       MBEDTLS_ECP_PF_UNCOMPRESSED, &pubkey_size, Uint8::to_uchar(pubkey.Bytes()), pubkey.Length());
+
+    VerifyOrExit(result == 0, error = CHIP_ERROR_INTERNAL);
+    VerifyOrExit(pubkey_size == pubkey.Length(), error = CHIP_ERROR_INTERNAL);
+
+exit:
+    _log_mbedTLS_error(result);
+    mbedtls_x509_crt_free(&mbed_cert);
+
+#else
+    (void) certificate;
+    (void) pubkey;
+    CHIP_ERROR error = CHIP_ERROR_NOT_IMPLEMENTED;
+#endif // defined(MBEDTLS_X509_CRT_PARSE_C)
+
+    return error;
+}
+
+namespace {
+
+CHIP_ERROR ExtractKIDFromX509Cert(bool extractSKID, const ByteSpan & certificate, MutableByteSpan & kid)
+{
+#if defined(MBEDTLS_X509_CRT_PARSE_C)
+    CHIP_ERROR error = CHIP_ERROR_NOT_FOUND;
+    mbedtls_x509_crt mbed_cert;
+    unsigned char * p         = nullptr;
+    const unsigned char * end = nullptr;
+    size_t len                = 0;
+
+    mbedtls_x509_crt_init(&mbed_cert);
+
+    int result = mbedtls_x509_crt_parse(&mbed_cert, Uint8::to_const_uchar(certificate.data()), certificate.size());
+    VerifyOrExit(result == 0, error = CHIP_ERROR_INTERNAL);
+
+    // TODO: The mbedTLS team is working on supporting SKID and AKID extensions processing.
+    // Once it is supported, this code should be updated.
+
+    p   = mbed_cert.CHIP_CRYPTO_PAL_PRIVATE_X509(v3_ext).CHIP_CRYPTO_PAL_PRIVATE_X509(p);
+    end = mbed_cert.CHIP_CRYPTO_PAL_PRIVATE_X509(v3_ext).CHIP_CRYPTO_PAL_PRIVATE_X509(p) +
+        mbed_cert.CHIP_CRYPTO_PAL_PRIVATE_X509(v3_ext).CHIP_CRYPTO_PAL_PRIVATE_X509(len);
+    result = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE);
+    VerifyOrExit(result == 0, error = CHIP_ERROR_WRONG_CERT_TYPE);
+
+    while (p < end)
+    {
+        result = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE);
+        VerifyOrExit(result == 0, error = CHIP_ERROR_WRONG_CERT_TYPE);
+        result = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_OID);
+        VerifyOrExit(result == 0, error = CHIP_ERROR_WRONG_CERT_TYPE);
+
+        mbedtls_x509_buf extOID    = { MBEDTLS_ASN1_OID, len, p };
+        bool extractCurrentExtSKID = extractSKID && OID_CMP(sOID_Extension_SubjectKeyIdentifier, extOID);
+        bool extractCurrentExtAKID = !extractSKID && OID_CMP(sOID_Extension_AuthorityKeyIdentifier, extOID);
+        p += len;
+
+        int is_critical = 0;
+        result          = mbedtls_asn1_get_bool(&p, end, &is_critical);
+        VerifyOrExit(result == 0 || result == MBEDTLS_ERR_ASN1_UNEXPECTED_TAG, error = CHIP_ERROR_WRONG_CERT_TYPE);
+
+        result = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_OCTET_STRING);
+        VerifyOrExit(result == 0, error = CHIP_ERROR_WRONG_CERT_TYPE);
+
+        if (extractCurrentExtSKID || extractCurrentExtAKID)
+        {
+            if (extractCurrentExtSKID)
+            {
+                result = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_OCTET_STRING);
+                VerifyOrExit(result == 0, error = CHIP_ERROR_WRONG_CERT_TYPE);
+            }
+            else
+            {
+                result = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE);
+                VerifyOrExit(result == 0, error = CHIP_ERROR_WRONG_CERT_TYPE);
+                result = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_CONTEXT_SPECIFIC);
+                VerifyOrExit(result == 0, error = CHIP_ERROR_WRONG_CERT_TYPE);
+                // Other optional fields, authorityCertIssuer and authorityCertSerialNumber,
+                // will be skipped if present.
+            }
+            VerifyOrExit(len == kSubjectKeyIdentifierLength, error = CHIP_ERROR_WRONG_CERT_TYPE);
+            VerifyOrExit(len <= kid.size(), error = CHIP_ERROR_BUFFER_TOO_SMALL);
+            memcpy(kid.data(), p, len);
+            if (kid.size() > len)
+            {
+                kid.reduce_size(len);
+            }
+            ExitNow(error = CHIP_NO_ERROR);
+            break;
+        }
+        p += len;
+    }
+
+exit:
+    _log_mbedTLS_error(result);
+    mbedtls_x509_crt_free(&mbed_cert);
+
+#else
+    (void) certificate;
+    (void) kid;
+    CHIP_ERROR error = CHIP_ERROR_NOT_IMPLEMENTED;
+#endif // defined(MBEDTLS_X509_CRT_PARSE_C)
+
+    return error;
+}
+
+} // namespace
+
+CHIP_ERROR ExtractSKIDFromX509Cert(const ByteSpan & certificate, MutableByteSpan & skid)
+{
+    return ExtractKIDFromX509Cert(true, certificate, skid);
+}
+
+CHIP_ERROR ExtractAKIDFromX509Cert(const ByteSpan & certificate, MutableByteSpan & akid)
+{
+    return ExtractKIDFromX509Cert(false, certificate, akid);
+}
+
+CHIP_ERROR ExtractVIDPIDFromX509Cert(const ByteSpan & certificate, AttestationCertVidPid & vidpid)
+{
+#if defined(MBEDTLS_X509_CRT_PARSE_C)
+    CHIP_ERROR error = CHIP_NO_ERROR;
+    mbedtls_x509_crt mbed_cert;
+    mbedtls_asn1_named_data * dnIterator = nullptr;
+    AttestationCertVidPid vidpidFromCN;
+
+    mbedtls_x509_crt_init(&mbed_cert);
+
+    int result = mbedtls_x509_crt_parse(&mbed_cert, Uint8::to_const_uchar(certificate.data()), certificate.size());
+    VerifyOrExit(result == 0, error = CHIP_ERROR_INTERNAL);
+
+    for (dnIterator = &mbed_cert.CHIP_CRYPTO_PAL_PRIVATE_X509(subject); dnIterator != nullptr;
+         dnIterator = dnIterator->CHIP_CRYPTO_PAL_PRIVATE_X509(next))
+    {
+        DNAttrType attrType = DNAttrType::kUnspecified;
+        if (OID_CMP(sOID_AttributeType_CommonName, dnIterator->CHIP_CRYPTO_PAL_PRIVATE_X509(oid)))
+        {
+            attrType = DNAttrType::kCommonName;
+        }
+        else if (OID_CMP(sOID_AttributeType_MatterVendorId, dnIterator->CHIP_CRYPTO_PAL_PRIVATE_X509(oid)))
+        {
+            attrType = DNAttrType::kMatterVID;
+        }
+        else if (OID_CMP(sOID_AttributeType_MatterProductId, dnIterator->CHIP_CRYPTO_PAL_PRIVATE_X509(oid)))
+        {
+            attrType = DNAttrType::kMatterPID;
+        }
+
+        size_t val_len  = dnIterator->CHIP_CRYPTO_PAL_PRIVATE_X509(val).CHIP_CRYPTO_PAL_PRIVATE_X509(len);
+        uint8_t * val_p = dnIterator->CHIP_CRYPTO_PAL_PRIVATE_X509(val).CHIP_CRYPTO_PAL_PRIVATE_X509(p);
+        error           = ExtractVIDPIDFromAttributeString(attrType, ByteSpan(val_p, val_len), vidpid, vidpidFromCN);
+        SuccessOrExit(error);
+    }
+
+    // If Matter Attributes were not found use values extracted from the CN Attribute,
+    // which might be uninitialized as well.
+    if (!vidpid.Initialized())
+    {
+        vidpid = vidpidFromCN;
+    }
+
+exit:
+    _log_mbedTLS_error(result);
+    mbedtls_x509_crt_free(&mbed_cert);
+
+#else
+    (void) certificate;
+    (void) vidpid;
+    CHIP_ERROR error = CHIP_ERROR_NOT_IMPLEMENTED;
+#endif // defined(MBEDTLS_X509_CRT_PARSE_C)
+
+    return error;
+}
+
+} // namespace Crypto
+} // namespace chip
diff --git a/src/platform/silabs/SiWx917/ConfigurationManagerImpl.cpp b/src/platform/silabs/SiWx917/ConfigurationManagerImpl.cpp
new file mode 100644
index 0000000..aad7493
--- /dev/null
+++ b/src/platform/silabs/SiWx917/ConfigurationManagerImpl.cpp
@@ -0,0 +1,317 @@
+/*
+ *
+ *    Copyright (c) 2020 Project CHIP Authors
+ *    Copyright (c) 2019 Nest Labs, Inc.
+ *
+ *    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 the implementation of the Device Layer ConfigurationManager object
+ *          for EFR32 platforms using the Silicon Labs SDK.
+ */
+/* this file behaves like a config.h, comes first */
+#include <platform/internal/CHIPDeviceLayerInternal.h>
+
+#include <platform/internal/GenericConfigurationManagerImpl.ipp>
+
+#include <platform/ConfigurationManager.h>
+#include <platform/DiagnosticDataProvider.h>
+#include <platform/silabs/SilabsConfig.h>
+
+#include "em_rmu.h"
+
+#if CHIP_DEVICE_CONFIG_ENABLE_WIFI_STATION
+#include "wfx_host_events.h"
+#endif
+
+namespace chip {
+namespace DeviceLayer {
+
+using namespace ::chip::DeviceLayer::Internal;
+
+ConfigurationManagerImpl & ConfigurationManagerImpl::GetDefaultInstance()
+{
+    static ConfigurationManagerImpl sInstance;
+    return sInstance;
+}
+
+CHIP_ERROR ConfigurationManagerImpl::Init()
+{
+    CHIP_ERROR err;
+
+    // Initialize the generic implementation base class.
+    err = Internal::GenericConfigurationManagerImpl<SILABSConfig>::Init();
+    SuccessOrExit(err);
+
+    // TODO: Initialize the global GroupKeyStore object here (#1626)
+
+    IncreaseBootCount();
+    // It is possible to configure the possible reset sources with RMU_ResetControl
+    // In this case, we keep Reset control at default setting
+    rebootCause = RMU_ResetCauseGet();
+    RMU_ResetCauseClear();
+
+    err = CHIP_NO_ERROR;
+
+exit:
+    return err;
+}
+
+bool ConfigurationManagerImpl::CanFactoryReset()
+{
+    // TODO: query the application to determine if factory reset is allowed.
+    return true;
+}
+
+void ConfigurationManagerImpl::InitiateFactoryReset()
+{
+    PlatformMgr().ScheduleWork(DoFactoryReset);
+}
+
+CHIP_ERROR ConfigurationManagerImpl::GetRebootCount(uint32_t & rebootCount)
+{
+    return SILABSConfig::ReadConfigValue(SILABSConfig::kConfigKey_BootCount, rebootCount);
+}
+
+CHIP_ERROR ConfigurationManagerImpl::IncreaseBootCount(void)
+{
+    uint32_t bootCount = 0;
+
+    if (SILABSConfig::ConfigValueExists(SILABSConfig::kConfigKey_BootCount))
+    {
+        GetRebootCount(bootCount);
+    }
+
+    return SILABSConfig::WriteConfigValue(SILABSConfig::kConfigKey_BootCount, bootCount + 1);
+}
+
+CHIP_ERROR ConfigurationManagerImpl::GetBootReason(uint32_t & bootReason)
+{
+    // rebootCause is obtained at bootup.
+    BootReasonType matterBootCause;
+#if defined(_SILICON_LABS_32B_SERIES_1)
+    if (rebootCause & RMU_RSTCAUSE_PORST || rebootCause & RMU_RSTCAUSE_EXTRST) // PowerOn or External pin reset
+    {
+        matterBootCause = BootReasonType::kPowerOnReboot;
+    }
+    else if (rebootCause & RMU_RSTCAUSE_AVDDBOD || rebootCause & RMU_RSTCAUSE_DVDDBOD || rebootCause & RMU_RSTCAUSE_DECBOD)
+    {
+        matterBootCause = BootReasonType::kBrownOutReset;
+    }
+    else if (rebootCause & RMU_RSTCAUSE_SYSREQRST)
+    {
+        matterBootCause = BootReasonType::kSoftwareReset;
+    }
+    else if (rebootCause & RMU_RSTCAUSE_WDOGRST)
+    {
+        matterBootCause = BootReasonType::kSoftwareWatchdogReset;
+    }
+    else
+    {
+        matterBootCause = BootReasonType::kUnspecified;
+    }
+    // Not tracked HARDWARE_WATCHDOG_RESET && SOFTWARE_UPDATE_COMPLETED
+#elif defined(_SILICON_LABS_32B_SERIES_2)
+    if (rebootCause & EMU_RSTCAUSE_POR || rebootCause & EMU_RSTCAUSE_PIN) // PowerOn or External pin reset
+    {
+        matterBootCause = BootReasonType::kPowerOnReboot;
+    }
+    else if (rebootCause & EMU_RSTCAUSE_AVDDBOD || rebootCause & EMU_RSTCAUSE_DVDDBOD || rebootCause & EMU_RSTCAUSE_DECBOD ||
+             rebootCause & EMU_RSTCAUSE_VREGIN || rebootCause & EMU_RSTCAUSE_IOVDD0BOD || rebootCause & EMU_RSTCAUSE_DVDDLEBOD)
+    {
+        matterBootCause = BootReasonType::kBrownOutReset;
+    }
+    else if (rebootCause & EMU_RSTCAUSE_SYSREQ)
+    {
+        matterBootCause = BootReasonType::kSoftwareReset;
+    }
+    else if (rebootCause & EMU_RSTCAUSE_WDOG0 || rebootCause & EMU_RSTCAUSE_WDOG1)
+    {
+        matterBootCause = BootReasonType::kSoftwareWatchdogReset;
+    }
+    else
+    {
+        matterBootCause = BootReasonType::kUnspecified;
+    }
+    // Not tracked HARDWARE_WATCHDOG_RESET && SOFTWARE_UPDATE_COMPLETED
+#else
+    matterBootCause = BootReasonType::kUnspecified;
+#endif
+
+    bootReason = to_underlying(matterBootCause);
+    return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR ConfigurationManagerImpl::GetTotalOperationalHours(uint32_t & totalOperationalHours)
+{
+    if (!SILABSConfig::ConfigValueExists(SILABSConfig::kConfigKey_TotalOperationalHours))
+    {
+        totalOperationalHours = 0;
+        return CHIP_NO_ERROR;
+    }
+
+    return SILABSConfig::ReadConfigValue(SILABSConfig::kConfigKey_TotalOperationalHours, totalOperationalHours);
+}
+
+CHIP_ERROR ConfigurationManagerImpl::StoreTotalOperationalHours(uint32_t totalOperationalHours)
+{
+    return SILABSConfig::WriteConfigValue(SILABSConfig::kConfigKey_TotalOperationalHours, totalOperationalHours);
+}
+
+CHIP_ERROR ConfigurationManagerImpl::ReadPersistedStorageValue(::chip::Platform::PersistedStorage::Key persistedStorageKey,
+                                                               uint32_t & value)
+{
+    // This method reads CHIP Persisted Counter type nvm3 objects.
+    // (where persistedStorageKey represents an index to the counter).
+    CHIP_ERROR err;
+
+    err = SILABSConfig::ReadConfigValueCounter(persistedStorageKey, value);
+    if (err == CHIP_DEVICE_ERROR_CONFIG_NOT_FOUND)
+    {
+        err = CHIP_ERROR_PERSISTED_STORAGE_VALUE_NOT_FOUND;
+    }
+    SuccessOrExit(err);
+
+exit:
+    return err;
+}
+
+CHIP_ERROR ConfigurationManagerImpl::WritePersistedStorageValue(::chip::Platform::PersistedStorage::Key persistedStorageKey,
+                                                                uint32_t value)
+{
+    // This method reads CHIP Persisted Counter type nvm3 objects.
+    // (where persistedStorageKey represents an index to the counter).
+    CHIP_ERROR err;
+
+    err = SILABSConfig::WriteConfigValueCounter(persistedStorageKey, value);
+    if (err == CHIP_DEVICE_ERROR_CONFIG_NOT_FOUND)
+    {
+        err = CHIP_ERROR_PERSISTED_STORAGE_VALUE_NOT_FOUND;
+    }
+    SuccessOrExit(err);
+
+exit:
+    return err;
+}
+
+CHIP_ERROR ConfigurationManagerImpl::ReadConfigValue(Key key, bool & val)
+{
+    return SILABSConfig::ReadConfigValue(key, val);
+}
+
+CHIP_ERROR ConfigurationManagerImpl::ReadConfigValue(Key key, uint32_t & val)
+{
+    return SILABSConfig::ReadConfigValue(key, val);
+}
+
+CHIP_ERROR ConfigurationManagerImpl::ReadConfigValue(Key key, uint64_t & val)
+{
+    return SILABSConfig::ReadConfigValue(key, val);
+}
+
+CHIP_ERROR ConfigurationManagerImpl::ReadConfigValueStr(Key key, char * buf, size_t bufSize, size_t & outLen)
+{
+    return SILABSConfig::ReadConfigValueStr(key, buf, bufSize, outLen);
+}
+
+CHIP_ERROR ConfigurationManagerImpl::ReadConfigValueBin(Key key, uint8_t * buf, size_t bufSize, size_t & outLen)
+{
+    return SILABSConfig::ReadConfigValueBin(key, buf, bufSize, outLen);
+}
+
+CHIP_ERROR ConfigurationManagerImpl::WriteConfigValue(Key key, bool val)
+{
+    return SILABSConfig::WriteConfigValue(key, val);
+}
+
+CHIP_ERROR ConfigurationManagerImpl::WriteConfigValue(Key key, uint32_t val)
+{
+    return SILABSConfig::WriteConfigValue(key, val);
+}
+
+CHIP_ERROR ConfigurationManagerImpl::WriteConfigValue(Key key, uint64_t val)
+{
+    return SILABSConfig::WriteConfigValue(key, val);
+}
+
+CHIP_ERROR ConfigurationManagerImpl::WriteConfigValueStr(Key key, const char * str)
+{
+    return SILABSConfig::WriteConfigValueStr(key, str);
+}
+
+CHIP_ERROR ConfigurationManagerImpl::WriteConfigValueStr(Key key, const char * str, size_t strLen)
+{
+    return SILABSConfig::WriteConfigValueStr(key, str, strLen);
+}
+
+CHIP_ERROR ConfigurationManagerImpl::WriteConfigValueBin(Key key, const uint8_t * data, size_t dataLen)
+{
+    return SILABSConfig::WriteConfigValueBin(key, data, dataLen);
+}
+
+void ConfigurationManagerImpl::RunConfigUnitTest(void)
+{
+    SILABSConfig::RunConfigUnitTest();
+}
+
+void ConfigurationManagerImpl::DoFactoryReset(intptr_t arg)
+{
+    CHIP_ERROR err;
+
+    ChipLogProgress(DeviceLayer, "Performing factory reset");
+
+    err = SILABSConfig::FactoryResetConfig();
+    if (err != CHIP_NO_ERROR)
+    {
+        ChipLogError(DeviceLayer, "FactoryResetConfig() failed: %s", chip::ErrorStr(err));
+    }
+
+#if CHIP_DEVICE_CONFIG_ENABLE_THREAD
+
+    ChipLogProgress(DeviceLayer, "Clearing Thread provision");
+    ThreadStackMgr().ErasePersistentInfo();
+
+#endif // CHIP_DEVICE_CONFIG_ENABLE_THREAD
+
+    PersistedStorage::KeyValueStoreMgrImpl().ErasePartition();
+
+#if CHIP_DEVICE_CONFIG_ENABLE_WIFI_STATION
+    ChipLogProgress(DeviceLayer, "Clearing WiFi provision");
+    wfx_clear_wifi_provision();
+#endif // CHIP_DEVICE_CONFIG_ENABLE_WIFI_STATION
+
+    // Restart the system.
+    ChipLogProgress(DeviceLayer, "System restarting");
+    NVIC_SystemReset();
+}
+
+#ifdef SL_WIFI
+CHIP_ERROR ConfigurationManagerImpl::GetPrimaryWiFiMACAddress(uint8_t * buf)
+{
+    sl_wfx_mac_address_t macaddr;
+    wfx_get_wifi_mac_addr(SL_WFX_STA_INTERFACE, &macaddr);
+    memcpy(buf, &macaddr.octet[0], sizeof(macaddr.octet));
+
+    return CHIP_NO_ERROR;
+}
+#endif
+
+ConfigurationManager & ConfigurationMgrImpl()
+{
+    return ConfigurationManagerImpl::GetDefaultInstance();
+}
+
+} // namespace DeviceLayer
+} // namespace chip
diff --git a/src/platform/silabs/SiWx917/ConnectivityManagerImpl.cpp b/src/platform/silabs/SiWx917/ConnectivityManagerImpl.cpp
new file mode 100644
index 0000000..c38a5e5
--- /dev/null
+++ b/src/platform/silabs/SiWx917/ConnectivityManagerImpl.cpp
@@ -0,0 +1,74 @@
+/*
+ *
+ *    Copyright (c) 2020 Project CHIP Authors
+ *    Copyright (c) 2019 Nest Labs, Inc.
+ *
+ *    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.
+ */
+/* this file behaves like a config.h, comes first */
+#include <platform/internal/CHIPDeviceLayerInternal.h>
+
+#include <lib/support/CodeUtils.h>
+#include <lib/support/logging/CHIPLogging.h>
+#include <platform/ConnectivityManager.h>
+#include <platform/internal/BLEManager.h>
+
+#include <platform/internal/GenericConnectivityManagerImpl_UDP.ipp>
+
+#if INET_CONFIG_ENABLE_TCP_ENDPOINT
+#include <platform/internal/GenericConnectivityManagerImpl_TCP.ipp>
+#endif
+
+#if CHIP_DEVICE_CONFIG_ENABLE_CHIPOBLE
+#include <platform/internal/GenericConnectivityManagerImpl_BLE.ipp>
+#endif
+
+#if CHIP_DEVICE_CONFIG_ENABLE_THREAD
+#include <platform/internal/GenericConnectivityManagerImpl_Thread.ipp>
+#endif
+
+using namespace ::chip;
+using namespace ::chip::Inet;
+using namespace ::chip::System;
+using namespace ::chip::TLV;
+using namespace ::chip::DeviceLayer::Internal;
+
+namespace chip {
+namespace DeviceLayer {
+
+ConnectivityManagerImpl ConnectivityManagerImpl::sInstance;
+
+CHIP_ERROR ConnectivityManagerImpl::_Init()
+{
+    CHIP_ERROR err = CHIP_NO_ERROR;
+
+    // Initialize the generic base classes that require it.
+#if CHIP_DEVICE_CONFIG_ENABLE_THREAD
+    GenericConnectivityManagerImpl_Thread<ConnectivityManagerImpl>::_Init();
+#endif
+    SuccessOrExit(err);
+
+exit:
+    return err;
+}
+
+void ConnectivityManagerImpl::_OnPlatformEvent(const ChipDeviceEvent * event)
+{
+    // Forward the event to the generic base classes as needed.
+#if CHIP_DEVICE_CONFIG_ENABLE_THREAD
+    GenericConnectivityManagerImpl_Thread<ConnectivityManagerImpl>::_OnPlatformEvent(event);
+#endif
+}
+
+} // namespace DeviceLayer
+} // namespace chip
diff --git a/src/platform/silabs/SiWx917/Efr32OpaqueKeypair.h b/src/platform/silabs/SiWx917/Efr32OpaqueKeypair.h
new file mode 100644
index 0000000..58123c1
--- /dev/null
+++ b/src/platform/silabs/SiWx917/Efr32OpaqueKeypair.h
@@ -0,0 +1,224 @@
+/*
+ *    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 <crypto/CHIPCryptoPAL.h>
+#include <platform/CHIPDeviceError.h>
+
+namespace chip {
+namespace DeviceLayer {
+namespace Internal {
+
+typedef uint16_t EFR32OpaqueKeyId;
+constexpr EFR32OpaqueKeyId kEFR32OpaqueKeyIdUnknown       = 0xFFFFU; // Do not modify, will impact existing deployments
+constexpr EFR32OpaqueKeyId kEFR32OpaqueKeyIdVolatile      = 0xFFFEU; // Do not modify, will impact existing deployments
+constexpr EFR32OpaqueKeyId kEFR32OpaqueKeyIdPersistentMin = 0x0U;    // Do not modify, will impact existing deployments
+constexpr EFR32OpaqueKeyId kEFR32OpaqueKeyIdPersistentMax = 0x1FFU;  // Do not decrease, will impact existing deployments
+
+enum class EFR32OpaqueKeyUsages : uint8_t
+{
+    ECDSA_P256_SHA256 = 0,
+    ECDH_P256         = 1,
+};
+
+/**
+ * @brief Base class for opaque keys
+ *
+ * Deriving from this class allows using it as a base class for operations
+ * which don't expose the private key independent of key size.
+ **/
+class EFR32OpaqueKeypair
+{
+public:
+    EFR32OpaqueKeypair();
+    virtual ~EFR32OpaqueKeypair();
+
+    /**
+     * @brief Load a keypair with given key ID
+     *
+     * If no key exists under the given ID, an error is returned
+     * and the object is unusable for operations.
+     *
+     * @param key_id    key ID under which this key was created
+     *
+     * @return Returns a CHIP_ERROR on error, CHIP_NO_ERROR otherwise
+     **/
+    CHIP_ERROR Load(EFR32OpaqueKeyId key_id);
+
+    /**
+     * @brief Create a new keypair with given ID and usage
+     *
+     * If a key already exists under the given ID, an error is returned
+     * and no new key is created.
+     *
+     * @param key_id    key ID under which to store this key. Set to 0
+     *                  for a non-persistent key which gets destructed
+     *                  when the lifetime of this object ends, or set
+     *                  to any other value to store the key under that
+     *                  ID.
+     *
+     * @return Returns a CHIP_ERROR on error, CHIP_NO_ERROR otherwise
+     **/
+    CHIP_ERROR Create(EFR32OpaqueKeyId key_id, EFR32OpaqueKeyUsages usage);
+
+    /**
+     * @brief Get the public key for this keypair
+     *
+     * @param output        Output buffer to put public key (in 0x04 || X || Y format)
+     * @param output_size   Size of \p output
+     * @param output_length Amount of bytes put in \p output on success
+     *
+     * @return Returns a CHIP_ERROR on error, CHIP_NO_ERROR otherwise
+     **/
+    CHIP_ERROR GetPublicKey(uint8_t * output, size_t output_size, size_t * output_length) const;
+
+    /**
+     * @brief Get the key ID for this keypair
+     *
+     * @return Returns kEFR32OpaqueKeyIdUnknown for an uninitialised/invalid
+     *         key, kEFR32OpaqueKeyIdVolatile for a volatile key, and a key
+     *         ID in the range [kEFR32OpaqueKeyIdPersistentMin, kEFR32OpaqueKeyIdPersistentMax]
+     *         for valid persistent keys.
+     **/
+    EFR32OpaqueKeyId GetKeyId() const;
+
+    /**
+     * @brief Use this keypair to sign a message using the ECDSA-SHA256 algorithm
+     *
+     * @param msg           Message buffer to sign
+     * @param msg_len       Size of \p msg in bytes
+     * @param output        Output buffer to write signature to. Signature
+     *                      is in raw format (i.e. binary concatenation of
+     *                      r and s)
+     * @param output_size   Size of output buffer
+     * @param output_length Amount of bytes written into output buffer
+     *
+     * @return Returns a CHIP_ERROR on error, CHIP_NO_ERROR otherwise
+     **/
+    CHIP_ERROR Sign(const uint8_t * msg, size_t msg_len, uint8_t * output, size_t output_size, size_t * output_length) const;
+
+    /**
+     * @brief Use this keypair to derive a key using the raw ECDH algorithm
+     *
+     * @param their_key     Buffer containing raw uncompressed public key
+     *                      of party to derive with
+     * @param their_key_len Size of \p their_key in bytes
+     * @param output        Output buffer to write derived bytes to
+     * @param output_size   Size of output buffer
+     * @param output_length Amount of bytes written into output buffer
+     *
+     * @return Returns a CHIP_ERROR on error, CHIP_NO_ERROR otherwise
+     **/
+    CHIP_ERROR Derive(const uint8_t * their_key, size_t their_key_len, uint8_t * output, size_t output_size,
+                      size_t * output_length) const;
+
+    /**
+     * @brief Delete the keypair from storage
+     *
+     * @return Returns a CHIP_ERROR on error, CHIP_NO_ERROR otherwise
+     **/
+    CHIP_ERROR Delete();
+
+protected:
+    void * mContext      = nullptr;
+    bool mHasKey         = false;
+    bool mIsPersistent   = false;
+    uint8_t * mPubkeyRef = nullptr;
+    size_t mPubkeySize   = 0;
+    size_t mPubkeyLength = 0;
+};
+
+/**
+ * @brief Derived class of P256Keypair for using opaque keys
+ *
+ * The signature and compiled form of this class is suboptimal due to how
+ * the P256Keypair isn't really an abstract interface, but rather partly
+ * interface / partly implementation. Future optimisation should look at
+ * converting P256Keypair to a fully abstract interface.
+ **/
+class EFR32OpaqueP256Keypair : public chip::Crypto::P256Keypair, public EFR32OpaqueKeypair
+{
+public:
+    EFR32OpaqueP256Keypair();
+    ~EFR32OpaqueP256Keypair() override;
+
+    /**
+     * @brief Initialize the keypair.
+     * @return Returns a CHIP_ERROR on error, CHIP_NO_ERROR otherwise
+     **/
+    CHIP_ERROR Initialize() override;
+
+    /**
+     * @brief Serialize the keypair (unsupported on opaque keys)
+     * @return Returns a CHIP_ERROR on error, CHIP_NO_ERROR otherwise
+     **/
+    CHIP_ERROR Serialize(chip::Crypto::P256SerializedKeypair & output) const override;
+
+    /**
+     * @brief Deserialize the keypair (unsupported on opaque keys)
+     * @return Returns a CHIP_ERROR on error, CHIP_NO_ERROR otherwise
+     **/
+    CHIP_ERROR Deserialize(chip::Crypto::P256SerializedKeypair & input) override;
+
+    /**
+     * @brief Generate a new Certificate Signing Request (CSR).
+     * @param csr Newly generated CSR in DER format
+     * @param csr_length The caller provides the length of input buffer (csr). The function returns the actual length of generated
+     *CSR.
+     * @return Returns a CHIP_ERROR on error, CHIP_NO_ERROR otherwise
+     **/
+    CHIP_ERROR NewCertificateSigningRequest(uint8_t * csr, size_t & csr_length) const override;
+
+    /**
+     * @brief A function to sign a msg using ECDSA
+     * @param msg Message that needs to be signed
+     * @param msg_length Length of message
+     * @param out_signature Buffer that will hold the output signature. The signature consists of: 2 EC elements (r and s),
+     * in raw <r,s> point form (see SEC1).
+     * @return Returns a CHIP_ERROR on error, CHIP_NO_ERROR otherwise
+     **/
+    CHIP_ERROR ECDSA_sign_msg(const uint8_t * msg, size_t msg_length,
+                              chip::Crypto::P256ECDSASignature & out_signature) const override;
+
+    /**
+     * @brief A function to derive a shared secret using ECDH
+     *
+     * This implements the CHIP_Crypto_ECDH(PrivateKey myPrivateKey, PublicKey theirPublicKey) cryptographic primitive
+     * from the specification, using this class's private key from `mKeypair` as `myPrivateKey` and the remote
+     * public key from `remote_public_key` as `theirPublicKey`.
+     *
+     * @param remote_public_key Public key of remote peer with which we are trying to establish secure channel. remote_public_key is
+     * ASN.1 DER encoded as padded big-endian field elements as described in SEC 1: Elliptic Curve Cryptography
+     * [https://www.secg.org/sec1-v2.pdf]
+     * @param out_secret Buffer to write out secret into. This is a byte array representing the x coordinate of the shared secret.
+     * @return Returns a CHIP_ERROR on error, CHIP_NO_ERROR otherwise
+     **/
+    CHIP_ERROR ECDH_derive_secret(const chip::Crypto::P256PublicKey & remote_public_key,
+                                  chip::Crypto::P256ECDHDerivedSecret & out_secret) const override;
+
+    /** @brief Return public key for the keypair.
+     **/
+    const chip::Crypto::P256PublicKey & Pubkey() const override;
+
+private:
+    chip::Crypto::P256PublicKey mPubKey;
+};
+
+} // namespace Internal
+} // namespace DeviceLayer
+} // namespace chip
diff --git a/src/platform/silabs/SiWx917/Efr32PsaOpaqueKeypair.cpp b/src/platform/silabs/SiWx917/Efr32PsaOpaqueKeypair.cpp
new file mode 100644
index 0000000..ae9a0f6
--- /dev/null
+++ b/src/platform/silabs/SiWx917/Efr32PsaOpaqueKeypair.cpp
@@ -0,0 +1,452 @@
+/*
+ *    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 "Efr32OpaqueKeypair.h"
+#include "em_device.h"
+#include <psa/crypto.h>
+
+#include <lib/core/CHIPSafeCasts.h>
+#include <lib/support/CHIPMem.h>
+#include <lib/support/SafeInt.h>
+using chip::Platform::MemoryCalloc;
+using chip::Platform::MemoryFree;
+
+using chip::Crypto::P256ECDHDerivedSecret;
+using chip::Crypto::P256ECDSASignature;
+using chip::Crypto::P256Keypair;
+using chip::Crypto::P256PublicKey;
+using chip::Crypto::P256SerializedKeypair;
+
+namespace chip {
+namespace DeviceLayer {
+namespace Internal {
+
+/*******************************************************************************
+ *
+ * PSA key ID range for storing Matter Opaque keys
+ *
+ ******************************************************************************/
+#define PSA_KEY_ID_FOR_MATTER_MIN (0x00004400)
+#define PSA_KEY_ID_FOR_MATTER_MAX (0x000045FF)
+#define PSA_KEY_ID_FOR_MATTER_SIZE (PSA_KEY_ID_FOR_MATTER_MAX - PSA_KEY_ID_FOR_MATTER_MIN + 1)
+
+static_assert((kEFR32OpaqueKeyIdPersistentMax - kEFR32OpaqueKeyIdPersistentMin) < PSA_KEY_ID_FOR_MATTER_SIZE,
+              "Not enough PSA range to store all allowed opaque key IDs");
+
+#if defined(SEMAILBOX_PRESENT) && (_SILICON_LABS_SECURITY_FEATURE == _SILICON_LABS_SECURITY_FEATURE_VAULT)
+#define PSA_CRYPTO_LOCATION_FOR_DEVICE PSA_KEY_LOCATION_SL_SE_OPAQUE
+#elif defined(CRYPTOACC_PRESENT) && defined(SEPUF_PRESENT) && defined(SL_TRUSTZONE_NONSECURE)
+#define PSA_CRYPTO_LOCATION_FOR_DEVICE PSA_KEY_LOCATION_SL_CRYPTOACC_OPAQUE
+#else
+#define PSA_CRYPTO_LOCATION_FOR_DEVICE PSA_KEY_LOCATION_LOCAL_STORAGE
+#endif
+
+static void _log_PSA_error(psa_status_t status)
+{
+    if (status != PSA_SUCCESS)
+    {
+        ChipLogError(Crypto, "PSA error: %ld", status);
+    }
+}
+
+/*******************************************************************************
+ *
+ * PSA Crypto backed implementation of EFR32OpaqueKeypair
+ *
+ ******************************************************************************/
+
+static bool is_opaque_key_valid(EFR32OpaqueKeyId id)
+{
+    if (id == kEFR32OpaqueKeyIdVolatile)
+    {
+        return true;
+    }
+    else if (id >= kEFR32OpaqueKeyIdPersistentMin && id <= (kEFR32OpaqueKeyIdPersistentMin + PSA_KEY_ID_FOR_MATTER_SIZE))
+    {
+        return true;
+    }
+
+    return false;
+}
+
+static mbedtls_svc_key_id_t psa_key_id_from_opaque(EFR32OpaqueKeyId id)
+{
+    if (id == kEFR32OpaqueKeyIdVolatile || !is_opaque_key_valid(id))
+    {
+        return 0;
+    }
+
+    return PSA_KEY_ID_FOR_MATTER_MIN + (id - kEFR32OpaqueKeyIdPersistentMin);
+}
+
+static EFR32OpaqueKeyId opaque_key_id_from_psa(mbedtls_svc_key_id_t id)
+{
+    if (id == 0)
+    {
+        return kEFR32OpaqueKeyIdVolatile;
+    }
+    else if (id >= PSA_KEY_ID_FOR_MATTER_MIN && id <= PSA_KEY_ID_FOR_MATTER_MAX)
+    {
+        return (id + kEFR32OpaqueKeyIdPersistentMin) - PSA_KEY_ID_FOR_MATTER_MIN;
+    }
+    else
+    {
+        return kEFR32OpaqueKeyIdUnknown;
+    }
+}
+
+EFR32OpaqueKeypair::EFR32OpaqueKeypair()
+{
+    psa_crypto_init();
+    // Avoid having a reference to PSA datatypes in the signature of this class
+    mContext = MemoryCalloc(1, sizeof(mbedtls_svc_key_id_t));
+}
+
+EFR32OpaqueKeypair::~EFR32OpaqueKeypair()
+{
+    // Free key resources
+    if (mContext != nullptr)
+    {
+        // Delete volatile keys, since nobody else can after we drop the key ID.
+        if (!mIsPersistent)
+        {
+            Delete();
+        }
+
+        MemoryFree(mContext);
+        mContext = nullptr;
+    }
+}
+
+CHIP_ERROR EFR32OpaqueKeypair::Load(EFR32OpaqueKeyId opaque_id)
+{
+    CHIP_ERROR error            = CHIP_NO_ERROR;
+    psa_status_t status         = PSA_ERROR_BAD_STATE;
+    mbedtls_svc_key_id_t key_id = 0;
+
+    VerifyOrExit(opaque_id != kEFR32OpaqueKeyIdVolatile, error = CHIP_ERROR_INVALID_ARGUMENT);
+    VerifyOrExit(is_opaque_key_valid(opaque_id), error = CHIP_ERROR_INVALID_ARGUMENT);
+    VerifyOrExit(mContext, error = CHIP_ERROR_INCORRECT_STATE);
+
+    // If the object contains a volatile key, clean it up before reusing the object storage
+    if (mHasKey && !mIsPersistent)
+    {
+        Delete();
+    }
+
+    key_id = psa_key_id_from_opaque(opaque_id);
+
+    status = psa_export_public_key(key_id, mPubkeyRef, mPubkeySize, &mPubkeyLength);
+
+    if (status == PSA_ERROR_DOES_NOT_EXIST)
+    {
+        error = CHIP_DEVICE_ERROR_CONFIG_NOT_FOUND;
+        goto exit;
+    }
+
+    VerifyOrExit(status == PSA_SUCCESS, {
+        _log_PSA_error(status);
+        error = CHIP_ERROR_INTERNAL;
+    });
+
+    // Store the key ID and mark the key as valid
+    *(mbedtls_svc_key_id_t *) mContext = key_id;
+    mHasKey                            = true;
+    mIsPersistent                      = true;
+
+exit:
+    if (error != CHIP_NO_ERROR)
+    {
+        memset(mPubkeyRef, 0, mPubkeySize);
+    }
+
+    return error;
+}
+
+CHIP_ERROR EFR32OpaqueKeypair::Create(EFR32OpaqueKeyId opaque_id, EFR32OpaqueKeyUsages usage)
+{
+    CHIP_ERROR error            = CHIP_NO_ERROR;
+    psa_status_t status         = PSA_ERROR_BAD_STATE;
+    psa_key_attributes_t attr   = PSA_KEY_ATTRIBUTES_INIT;
+    mbedtls_svc_key_id_t key_id = 0;
+
+    VerifyOrExit(is_opaque_key_valid(opaque_id), error = CHIP_ERROR_INVALID_ARGUMENT);
+    VerifyOrExit(mContext, error = CHIP_ERROR_INCORRECT_STATE);
+
+    if (opaque_id == kEFR32OpaqueKeyIdVolatile)
+    {
+        psa_set_key_lifetime(
+            &attr, PSA_KEY_LIFETIME_FROM_PERSISTENCE_AND_LOCATION(PSA_KEY_LIFETIME_VOLATILE, PSA_CRYPTO_LOCATION_FOR_DEVICE));
+    }
+    else
+    {
+        psa_key_handle_t key_handle;
+
+        key_id = psa_key_id_from_opaque(opaque_id);
+
+        // Check if the key already exists
+        int ret = psa_open_key(key_id, &key_handle);
+        if (PSA_SUCCESS == ret)
+        {
+            // WARNING: Existing key! This is caused by a problem in the key store.
+            // The key must be destroyed, otherwhise the device won't recover.
+            ChipLogError(Crypto, "WARNING: PSA key recycled: %d / %ld", opaque_id, key_id);
+            psa_destroy_key(key_id);
+        }
+
+        psa_set_key_id(&attr, key_id);
+        psa_set_key_lifetime(
+            &attr, PSA_KEY_LIFETIME_FROM_PERSISTENCE_AND_LOCATION(PSA_KEY_LIFETIME_PERSISTENT, PSA_CRYPTO_LOCATION_FOR_DEVICE));
+    }
+
+    switch (usage)
+    {
+    case EFR32OpaqueKeyUsages::ECDSA_P256_SHA256:
+        psa_set_key_type(&attr, PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1));
+        psa_set_key_bits(&attr, 256);
+        psa_set_key_algorithm(&attr, PSA_ALG_ECDSA(PSA_ALG_SHA_256));
+        // Need hash signing permissions because the CSR generation uses sign_hash internally
+        psa_set_key_usage_flags(&attr, PSA_KEY_USAGE_SIGN_MESSAGE | PSA_KEY_USAGE_SIGN_HASH);
+        break;
+    case EFR32OpaqueKeyUsages::ECDH_P256:
+        psa_set_key_type(&attr, PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1));
+        psa_set_key_bits(&attr, 256);
+        psa_set_key_algorithm(&attr, PSA_ALG_ECDH);
+        psa_set_key_usage_flags(&attr, PSA_KEY_USAGE_DERIVE);
+        break;
+    }
+
+    status = psa_generate_key(&attr, &key_id);
+    VerifyOrExit(status == PSA_SUCCESS, {
+        _log_PSA_error(status);
+        error = CHIP_ERROR_INTERNAL;
+    });
+
+    // Export the public key
+    status = psa_export_public_key(key_id, mPubkeyRef, mPubkeySize, &mPubkeyLength);
+    if (PSA_SUCCESS != status)
+    {
+        _log_PSA_error(status);
+        // Key generation succeeded, but pubkey export did not. To avoid
+        // memory leaks, delete the generated key before returning the error
+        psa_destroy_key(key_id);
+        error = CHIP_ERROR_INTERNAL;
+        goto exit;
+    }
+
+    // Store the key ID and mark the key as valid
+    mHasKey       = true;
+    mIsPersistent = opaque_id != kEFR32OpaqueKeyIdVolatile;
+
+exit:
+    psa_reset_key_attributes(&attr);
+    if (mContext)
+    {
+        if (CHIP_NO_ERROR == error)
+        {
+            *(mbedtls_svc_key_id_t *) mContext = key_id;
+        }
+        else
+        {
+            *(mbedtls_svc_key_id_t *) mContext = 0;
+        }
+    }
+    return error;
+}
+
+CHIP_ERROR EFR32OpaqueKeypair::GetPublicKey(uint8_t * output, size_t output_size, size_t * output_length) const
+{
+    CHIP_ERROR error = CHIP_NO_ERROR;
+    VerifyOrExit(mHasKey, error = CHIP_ERROR_INCORRECT_STATE);
+
+    if (output_size >= mPubkeyLength)
+    {
+        memcpy(output, mPubkeyRef, mPubkeyLength);
+        *output_length = mPubkeyLength;
+    }
+    else
+    {
+        error = CHIP_ERROR_BUFFER_TOO_SMALL;
+    }
+exit:
+    return error;
+}
+
+EFR32OpaqueKeyId EFR32OpaqueKeypair::GetKeyId() const
+{
+    if (!mHasKey)
+    {
+        return kEFR32OpaqueKeyIdUnknown;
+    }
+
+    if (!mIsPersistent)
+    {
+        return kEFR32OpaqueKeyIdVolatile;
+    }
+
+    return opaque_key_id_from_psa(*(mbedtls_svc_key_id_t *) mContext);
+}
+
+CHIP_ERROR EFR32OpaqueKeypair::Sign(const uint8_t * msg, size_t msg_len, uint8_t * output, size_t output_size,
+                                    size_t * output_length) const
+{
+    CHIP_ERROR error    = CHIP_NO_ERROR;
+    psa_status_t status = PSA_ERROR_BAD_STATE;
+
+    VerifyOrExit(mContext, error = CHIP_ERROR_INCORRECT_STATE);
+    VerifyOrExit(mHasKey, error = CHIP_ERROR_INCORRECT_STATE);
+
+    status = psa_sign_message(*(mbedtls_svc_key_id_t *) mContext, PSA_ALG_ECDSA(PSA_ALG_SHA_256), msg, msg_len, output, output_size,
+                              output_length);
+
+    VerifyOrExit(status == PSA_SUCCESS, {
+        _log_PSA_error(status);
+        error = CHIP_ERROR_INTERNAL;
+    });
+
+exit:
+    return error;
+}
+
+CHIP_ERROR EFR32OpaqueKeypair::Derive(const uint8_t * their_key, size_t their_key_len, uint8_t * output, size_t output_size,
+                                      size_t * output_length) const
+{
+    CHIP_ERROR error    = CHIP_NO_ERROR;
+    psa_status_t status = PSA_ERROR_BAD_STATE;
+
+    VerifyOrExit(mHasKey, error = CHIP_ERROR_INCORRECT_STATE);
+
+    status = psa_raw_key_agreement(PSA_ALG_ECDH, *(mbedtls_svc_key_id_t *) mContext, their_key, their_key_len, output, output_size,
+                                   output_length);
+
+    VerifyOrExit(status == PSA_SUCCESS, {
+        _log_PSA_error(status);
+        error = CHIP_ERROR_INTERNAL;
+    });
+
+exit:
+    return error;
+}
+
+CHIP_ERROR EFR32OpaqueKeypair::Delete()
+{
+    CHIP_ERROR error    = CHIP_NO_ERROR;
+    psa_status_t status = PSA_ERROR_BAD_STATE;
+
+    VerifyOrExit(mHasKey, error = CHIP_ERROR_INCORRECT_STATE);
+
+    status = psa_destroy_key(*(mbedtls_svc_key_id_t *) mContext);
+    VerifyOrExit(status == PSA_SUCCESS, {
+        _log_PSA_error(status);
+        error = CHIP_ERROR_INTERNAL;
+    });
+
+exit:
+    mHasKey       = false;
+    mIsPersistent = false;
+    memset(mPubkeyRef, 0, mPubkeySize);
+    if (mContext)
+    {
+        *(mbedtls_svc_key_id_t *) mContext = 0;
+    }
+    return error;
+}
+
+/*******************************************************************************
+ *
+ * PSA Crypto backed implementation of EFR32OpaqueP256Keypair
+ *
+ ******************************************************************************/
+EFR32OpaqueP256Keypair::EFR32OpaqueP256Keypair()
+{
+    mPubkeyRef    = mPubKey.Bytes();
+    mPubkeySize   = mPubKey.Length();
+    mPubkeyLength = 0;
+}
+
+EFR32OpaqueP256Keypair::~EFR32OpaqueP256Keypair() {}
+
+CHIP_ERROR EFR32OpaqueP256Keypair::Initialize()
+{
+    if (mPubkeyLength > 0)
+    {
+        // already have a key - ECDH use case where CASESession is calling Initialize()
+        return CHIP_NO_ERROR;
+    }
+
+    ChipLogError(Crypto, "Initialize() is invalid on opaque keys, use Create() instead");
+    return CHIP_ERROR_NOT_IMPLEMENTED;
+}
+
+CHIP_ERROR EFR32OpaqueP256Keypair::Serialize(P256SerializedKeypair & output) const
+{
+    ChipLogError(Crypto, "Serialisation is invalid on opaque keys, share the object instead");
+    return CHIP_ERROR_NOT_IMPLEMENTED;
+}
+
+CHIP_ERROR EFR32OpaqueP256Keypair::Deserialize(P256SerializedKeypair & input)
+{
+    ChipLogError(Crypto, "Serialisation is invalid on opaque keys");
+    return CHIP_ERROR_NOT_IMPLEMENTED;
+}
+
+CHIP_ERROR EFR32OpaqueP256Keypair::NewCertificateSigningRequest(uint8_t * out_csr, size_t & csr_length) const
+{
+    MutableByteSpan csr(out_csr, csr_length);
+    CHIP_ERROR err = GenerateCertificateSigningRequest(this, csr);
+    csr_length     = (CHIP_NO_ERROR == err) ? csr.size() : 0;
+    return err;
+}
+
+CHIP_ERROR EFR32OpaqueP256Keypair::ECDSA_sign_msg(const uint8_t * msg, size_t msg_length, P256ECDSASignature & out_signature) const
+{
+    CHIP_ERROR error     = CHIP_NO_ERROR;
+    size_t output_length = 0;
+
+    VerifyOrExit((msg != nullptr) && (msg_length > 0), error = CHIP_ERROR_INVALID_ARGUMENT);
+
+    error = Sign(msg, msg_length, out_signature.Bytes(), out_signature.Capacity(), &output_length);
+
+    SuccessOrExit(error);
+    SuccessOrExit(out_signature.SetLength(output_length));
+exit:
+    return error;
+}
+
+CHIP_ERROR EFR32OpaqueP256Keypair::ECDH_derive_secret(const P256PublicKey & remote_public_key,
+                                                      P256ECDHDerivedSecret & out_secret) const
+{
+    CHIP_ERROR error     = CHIP_NO_ERROR;
+    size_t output_length = 0;
+
+    error = Derive(Uint8::to_const_uchar(remote_public_key), remote_public_key.Length(), Uint8::to_uchar(out_secret),
+                   (out_secret.Length() == 0) ? out_secret.Capacity() : out_secret.Length(), &output_length);
+
+    SuccessOrExit(error);
+    SuccessOrExit(out_secret.SetLength(output_length));
+exit:
+    return error;
+}
+
+const P256PublicKey & EFR32OpaqueP256Keypair::Pubkey() const
+{
+    return mPubKey;
+}
+
+} // namespace Internal
+} // namespace DeviceLayer
+} // namespace chip
diff --git a/src/platform/silabs/SiWx917/Efr32PsaOperationalKeystore.cpp b/src/platform/silabs/SiWx917/Efr32PsaOperationalKeystore.cpp
new file mode 100644
index 0000000..e8fdf61
--- /dev/null
+++ b/src/platform/silabs/SiWx917/Efr32PsaOperationalKeystore.cpp
@@ -0,0 +1,455 @@
+/*
+ *    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 "Efr32PsaOperationalKeystore.h"
+
+#include <crypto/OperationalKeystore.h>
+#include <lib/core/CHIPError.h>
+#include <lib/core/CHIPTLV.h>
+#include <lib/core/DataModelTypes.h>
+#include <lib/support/CHIPMem.h>
+#include <lib/support/CodeUtils.h>
+#include <lib/support/SafeInt.h>
+
+#include "Efr32OpaqueKeypair.h"
+#include <platform/silabs/SilabsConfig.h>
+
+namespace chip {
+namespace DeviceLayer {
+namespace Internal {
+
+static_assert((sizeof(FabricIndex) == 1), "Implementation is not prepared for large fabric indices");
+static_assert(SL_MATTER_MAX_STORED_OP_KEYS <= (kEFR32OpaqueKeyIdPersistentMax - kEFR32OpaqueKeyIdPersistentMin),
+              "Not enough opaque keys available to cover all requested operational keys");
+static_assert((CHIP_CONFIG_MAX_FABRICS + 1) <= SL_MATTER_MAX_STORED_OP_KEYS,
+              "Not enough operational keys requested to cover all potential fabrics (+1 staging for fabric update)");
+static_assert(SL_MATTER_MAX_STORED_OP_KEYS >= 1, "Minimum supported amount of operational keys is 1");
+
+using namespace chip::Crypto;
+
+using chip::Platform::MemoryCalloc;
+using chip::Platform::MemoryFree;
+
+Efr32PsaOperationalKeystore::~Efr32PsaOperationalKeystore()
+{
+    Deinit();
+}
+
+CHIP_ERROR Efr32PsaOperationalKeystore::Init()
+{
+    // Detect existing keymap size
+    CHIP_ERROR error   = CHIP_NO_ERROR;
+    size_t wantedLen   = SL_MATTER_MAX_STORED_OP_KEYS * sizeof(FabricIndex);
+    size_t existingLen = 0;
+    bool update_cache  = false;
+
+    if (SILABSConfig::ConfigValueExists(SILABSConfig::kConfigKey_OpKeyMap, existingLen))
+    {
+        // There's a pre-existing key map on disk. Size the map to read it fully.
+        size_t outLen = 0;
+
+        if (existingLen > (kEFR32OpaqueKeyIdPersistentMax - kEFR32OpaqueKeyIdPersistentMin) * sizeof(FabricIndex))
+        {
+            return CHIP_ERROR_INTERNAL;
+        }
+
+        // Upsize the map if the config was changed
+        if (existingLen < wantedLen)
+        {
+            existingLen = wantedLen;
+        }
+
+        mKeyMap = (FabricIndex *) MemoryCalloc(1, existingLen);
+        VerifyOrExit(mKeyMap, error = CHIP_ERROR_NO_MEMORY);
+
+        // Read the existing key map
+        error = SILABSConfig::ReadConfigValueBin(SILABSConfig::kConfigKey_OpKeyMap, (uint8_t *) mKeyMap, existingLen, outLen);
+        SuccessOrExit(error);
+
+        // If upsizing, extend the map with undefined indices
+        for (size_t i = (outLen / sizeof(FabricIndex)); i < (existingLen / sizeof(FabricIndex)); i++)
+        {
+            mKeyMap[i] = kUndefinedFabricIndex;
+        }
+
+        // If the config has changed, check whether it can be downsized fully or partially
+        if (existingLen > wantedLen)
+        {
+            size_t highest_found_index = 0;
+            for (size_t i = (wantedLen / sizeof(FabricIndex)); i < (existingLen / sizeof(FabricIndex)); i++)
+            {
+                if (mKeyMap[i] != kUndefinedFabricIndex)
+                {
+                    highest_found_index = i;
+                }
+            }
+
+            // set size to the smallest that will fit the upper opaque key ID in use
+            if (highest_found_index > 0)
+            {
+                existingLen  = (highest_found_index + 1) * sizeof(FabricIndex);
+                update_cache = true;
+            }
+        }
+
+        // Set the key map size
+        mKeyMapSize = existingLen;
+    }
+    else
+    {
+        // No key map on disk. Create and initialize a new one.
+        mKeyMap = (FabricIndex *) MemoryCalloc(1, wantedLen);
+        VerifyOrExit(mKeyMap, error = CHIP_ERROR_NO_MEMORY);
+
+        for (size_t i = 0; i < (wantedLen / sizeof(FabricIndex)); i++)
+        {
+            mKeyMap[i] = kUndefinedFabricIndex;
+        }
+
+        mKeyMapSize = wantedLen;
+
+        update_cache = true;
+    }
+
+    // Write-out keymap if needed
+    if (update_cache)
+    {
+        error = SILABSConfig::WriteConfigValueBin(SILABSConfig::kConfigKey_OpKeyMap, mKeyMap, mKeyMapSize);
+        SuccessOrExit(error);
+    }
+
+    // Initialize cache key
+    mCachedKey = Platform::New<EFR32OpaqueP256Keypair>();
+    VerifyOrExit(mCachedKey, error = CHIP_ERROR_NO_MEMORY);
+
+exit:
+    if (error != CHIP_NO_ERROR)
+    {
+        Deinit();
+        return error;
+    }
+
+    mIsInitialized = true;
+    return CHIP_NO_ERROR;
+}
+
+EFR32OpaqueKeyId Efr32PsaOperationalKeystore::FindKeyIdForFabric(FabricIndex fabricIndex) const
+{
+    // Search the map linearly to find a matching index slot
+    for (size_t i = 0; i < (mKeyMapSize / sizeof(FabricIndex)); i++)
+    {
+        if (mKeyMap[i] == fabricIndex)
+        {
+            // Found a match
+            return i + kEFR32OpaqueKeyIdPersistentMin;
+        }
+    }
+
+    return kEFR32OpaqueKeyIdUnknown;
+}
+
+bool Efr32PsaOperationalKeystore::HasOpKeypairForFabric(FabricIndex fabricIndex) const
+{
+    VerifyOrReturnError(mIsInitialized, false);
+    VerifyOrReturnError(IsValidFabricIndex(fabricIndex), false);
+
+    // If there was a pending keypair, then there's really a usable key
+    if (mIsPendingKeypairActive && (fabricIndex == mPendingFabricIndex) && (mPendingKeypair != nullptr))
+    {
+        return true;
+    }
+
+    // Check whether we have a match in the map
+    if (FindKeyIdForFabric(fabricIndex) != kEFR32OpaqueKeyIdUnknown)
+    {
+        return true;
+    }
+
+    return false;
+}
+
+CHIP_ERROR Efr32PsaOperationalKeystore::NewOpKeypairForFabric(FabricIndex fabricIndex,
+                                                              MutableByteSpan & outCertificateSigningRequest)
+{
+    CHIP_ERROR error = CHIP_NO_ERROR;
+    VerifyOrReturnError(mIsInitialized, CHIP_ERROR_WELL_UNINITIALIZED);
+    VerifyOrReturnError(IsValidFabricIndex(fabricIndex), CHIP_ERROR_INVALID_FABRIC_INDEX);
+
+    // If a key is pending, we cannot generate for a different fabric index until we commit or revert.
+    if ((mPendingFabricIndex != kUndefinedFabricIndex) && (fabricIndex != mPendingFabricIndex))
+    {
+        return CHIP_ERROR_INVALID_FABRIC_INDEX;
+    }
+
+    VerifyOrReturnError(outCertificateSigningRequest.size() >= Crypto::kMAX_CSR_Length, CHIP_ERROR_BUFFER_TOO_SMALL);
+
+    // Generate new key
+    EFR32OpaqueKeyId id = kEFR32OpaqueKeyIdUnknown;
+
+    if (mPendingFabricIndex != kUndefinedFabricIndex)
+    {
+        // If we already have a pending key, delete it and put a new one in its place
+        id = mPendingKeypair->GetKeyId();
+        if (id == kEFR32OpaqueKeyIdUnknown)
+        {
+            ResetPendingKey();
+        }
+        else
+        {
+            mPendingKeypair->Delete();
+            if (id == kEFR32OpaqueKeyIdVolatile)
+            {
+                id = kEFR32OpaqueKeyIdUnknown;
+            }
+        }
+    }
+
+    if (id == kEFR32OpaqueKeyIdUnknown)
+    {
+        // Try to find an available opaque ID in the map
+        id = FindKeyIdForFabric(kUndefinedFabricIndex);
+
+        if (!mPendingKeypair)
+        {
+            mPendingKeypair = Platform::New<EFR32OpaqueP256Keypair>();
+        }
+    }
+
+    if (id == kEFR32OpaqueKeyIdUnknown)
+    {
+        // Could not find a free spot in the map
+        return CHIP_ERROR_NO_MEMORY;
+    }
+
+    // Create new key on the old or found key ID
+    error = mPendingKeypair->Create(id, EFR32OpaqueKeyUsages::ECDSA_P256_SHA256);
+    if (error != CHIP_NO_ERROR)
+    {
+        ResetPendingKey();
+        return error;
+    }
+
+    // Set CSR and state
+    size_t csrLength = outCertificateSigningRequest.size();
+    error            = mPendingKeypair->NewCertificateSigningRequest(outCertificateSigningRequest.data(), csrLength);
+    if (error != CHIP_NO_ERROR)
+    {
+        ResetPendingKey();
+        return error;
+    }
+
+    outCertificateSigningRequest.reduce_size(csrLength);
+    mPendingFabricIndex = fabricIndex;
+
+    return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR Efr32PsaOperationalKeystore::ActivateOpKeypairForFabric(FabricIndex fabricIndex,
+                                                                   const Crypto::P256PublicKey & nocPublicKey)
+{
+    VerifyOrReturnError(mIsInitialized, CHIP_ERROR_WELL_UNINITIALIZED);
+    VerifyOrReturnError(mPendingKeypair != nullptr, CHIP_ERROR_INVALID_FABRIC_INDEX);
+    VerifyOrReturnError(IsValidFabricIndex(fabricIndex) && (fabricIndex == mPendingFabricIndex), CHIP_ERROR_INVALID_FABRIC_INDEX);
+
+    // Validate public key being activated matches last generated pending keypair
+    VerifyOrReturnError(mPendingKeypair->Pubkey().Matches(nocPublicKey), CHIP_ERROR_INVALID_PUBLIC_KEY);
+
+    mIsPendingKeypairActive = true;
+
+    return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR Efr32PsaOperationalKeystore::CommitOpKeypairForFabric(FabricIndex fabricIndex)
+{
+    VerifyOrReturnError(mIsInitialized, CHIP_ERROR_WELL_UNINITIALIZED);
+    VerifyOrReturnError(mPendingKeypair != nullptr, CHIP_ERROR_INVALID_FABRIC_INDEX);
+    VerifyOrReturnError(IsValidFabricIndex(fabricIndex) && (fabricIndex == mPendingFabricIndex), CHIP_ERROR_INVALID_FABRIC_INDEX);
+    VerifyOrReturnError(mIsPendingKeypairActive == true, CHIP_ERROR_INCORRECT_STATE);
+
+    // Add key association to key map
+    EFR32OpaqueKeyId id = mPendingKeypair->GetKeyId();
+
+    if (id == kEFR32OpaqueKeyIdUnknown || id == kEFR32OpaqueKeyIdVolatile)
+    {
+        ResetPendingKey();
+        return CHIP_ERROR_INTERNAL;
+    }
+
+    // Guard against array out-of-bounds (should not happen with correctly initialised keys)
+    size_t keymap_index = id - kEFR32OpaqueKeyIdPersistentMin;
+    if (keymap_index >= (mKeyMapSize / sizeof(FabricIndex)))
+    {
+        return CHIP_ERROR_INTERNAL;
+    }
+
+    if (mKeyMap[keymap_index] != kUndefinedFabricIndex)
+    {
+        ResetPendingKey();
+        return CHIP_ERROR_INTERNAL;
+    }
+
+    mKeyMap[keymap_index] = fabricIndex;
+
+    // Persist key map
+    CHIP_ERROR error = SILABSConfig::WriteConfigValueBin(SILABSConfig::kConfigKey_OpKeyMap, mKeyMap, mKeyMapSize);
+    if (error != CHIP_NO_ERROR)
+    {
+        return error;
+    }
+
+    // There's a good chance we'll need the key again soon
+    mCachedKey->Load(id);
+
+    mPendingKeypair         = nullptr;
+    mIsPendingKeypairActive = false;
+    mPendingFabricIndex     = kUndefinedFabricIndex;
+
+    return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR Efr32PsaOperationalKeystore::RemoveOpKeypairForFabric(FabricIndex fabricIndex)
+{
+    VerifyOrReturnError(mIsInitialized, CHIP_ERROR_WELL_UNINITIALIZED);
+    VerifyOrReturnError(IsValidFabricIndex(fabricIndex), CHIP_ERROR_INVALID_FABRIC_INDEX);
+
+    // Remove pending keypair if we have it and the fabric ID matches
+    if ((mPendingKeypair != nullptr) && (fabricIndex == mPendingFabricIndex))
+    {
+        RevertPendingKeypair();
+    }
+
+    EFR32OpaqueKeyId id = FindKeyIdForFabric(fabricIndex);
+    if (id == kEFR32OpaqueKeyIdUnknown)
+    {
+        // Fabric is not in the map, so assume it's gone already
+        return CHIP_NO_ERROR;
+    }
+
+    // Guard against array out-of-bounds (should not happen with correctly initialised keys)
+    size_t keymap_index = id - kEFR32OpaqueKeyIdPersistentMin;
+    if (keymap_index >= (mKeyMapSize / sizeof(FabricIndex)))
+    {
+        return CHIP_ERROR_INTERNAL;
+    }
+
+    // Reset the key mapping since we'll be deleting this key
+    mKeyMap[keymap_index] = kUndefinedFabricIndex;
+
+    // Persist key map
+    CHIP_ERROR error = SILABSConfig::WriteConfigValueBin(SILABSConfig::kConfigKey_OpKeyMap, mKeyMap, mKeyMapSize);
+    if (error != CHIP_NO_ERROR)
+    {
+        return error;
+    }
+
+    // Check if key is cached
+    EFR32OpaqueKeyId cachedId = mCachedKey->GetKeyId();
+
+    if (id == cachedId)
+    {
+        // Delete from persistent storage and unload
+        mCachedKey->Delete();
+        return CHIP_NO_ERROR;
+    }
+
+    // Load it for purposes of deletion
+    error = mCachedKey->Load(id);
+    if (error != CHIP_NO_ERROR && error != CHIP_DEVICE_ERROR_CONFIG_NOT_FOUND)
+    {
+        return CHIP_ERROR_INTERNAL;
+    }
+
+    mCachedKey->Delete();
+
+    return CHIP_NO_ERROR;
+}
+
+void Efr32PsaOperationalKeystore::RevertPendingKeypair()
+{
+    if (mIsInitialized)
+    {
+        // Just delete the pending key from storage
+        ResetPendingKey();
+    }
+}
+
+CHIP_ERROR Efr32PsaOperationalKeystore::SignWithOpKeypair(FabricIndex fabricIndex, const ByteSpan & message,
+                                                          Crypto::P256ECDSASignature & outSignature) const
+{
+    VerifyOrReturnError(mIsInitialized, CHIP_ERROR_WELL_UNINITIALIZED);
+    VerifyOrReturnError(IsValidFabricIndex(fabricIndex), CHIP_ERROR_INVALID_FABRIC_INDEX);
+
+    // Check to see whether the key is an activated pending key
+    if (mIsPendingKeypairActive && (fabricIndex == mPendingFabricIndex))
+    {
+        VerifyOrReturnError(mPendingKeypair != nullptr, CHIP_ERROR_INTERNAL);
+        return mPendingKeypair->ECDSA_sign_msg(message.data(), message.size(), outSignature);
+    }
+
+    // Figure out which key ID we're looking for
+    EFR32OpaqueKeyId id = FindKeyIdForFabric(fabricIndex);
+
+    if (id == kEFR32OpaqueKeyIdUnknown)
+    {
+        // Fabric is not in the map, but the caller thinks it's there?
+        return CHIP_ERROR_INTERNAL;
+    }
+
+    // Check whether we have the key in cache
+    EFR32OpaqueKeyId cachedId = mCachedKey->GetKeyId();
+
+    if (id == cachedId)
+    {
+        return mCachedKey->ECDSA_sign_msg(message.data(), message.size(), outSignature);
+    }
+
+    // If not, we need to recreate from the backend
+    CHIP_ERROR error = mCachedKey->Load(id);
+    if (error != CHIP_NO_ERROR)
+    {
+        return CHIP_ERROR_INTERNAL;
+    }
+
+    // Sign with retrieved key
+    error = mCachedKey->ECDSA_sign_msg(message.data(), message.size(), outSignature);
+    if (error != CHIP_NO_ERROR)
+    {
+        return CHIP_ERROR_INTERNAL;
+    }
+
+    return CHIP_NO_ERROR;
+}
+
+Crypto::P256Keypair * Efr32PsaOperationalKeystore::AllocateEphemeralKeypairForCASE()
+{
+    EFR32OpaqueP256Keypair * new_key = Platform::New<EFR32OpaqueP256Keypair>();
+
+    if (new_key != nullptr)
+    {
+        new_key->Create(kEFR32OpaqueKeyIdVolatile, EFR32OpaqueKeyUsages::ECDH_P256);
+    }
+
+    return new_key;
+}
+
+void Efr32PsaOperationalKeystore::ReleaseEphemeralKeypair(Crypto::P256Keypair * keypair)
+{
+    Platform::Delete<EFR32OpaqueP256Keypair>((EFR32OpaqueP256Keypair *) keypair);
+}
+
+} // namespace Internal
+} // namespace DeviceLayer
+} // namespace chip
diff --git a/src/platform/silabs/SiWx917/Efr32PsaOperationalKeystore.h b/src/platform/silabs/SiWx917/Efr32PsaOperationalKeystore.h
new file mode 100644
index 0000000..4203724
--- /dev/null
+++ b/src/platform/silabs/SiWx917/Efr32PsaOperationalKeystore.h
@@ -0,0 +1,145 @@
+/*
+ *    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 <crypto/OperationalKeystore.h>
+#include <lib/core/CHIPConfig.h>
+
+#include <psa/crypto.h>
+
+#include "Efr32OpaqueKeypair.h"
+#include <platform/CHIPDeviceLayer.h>
+
+// Set SL_MATTER_MAX_STORED_OP_KEYS to the preferred size of the mapping table
+// between fabric IDs and opaque key indices. It can not be less than
+// CHIP_CONFIG_MAX_FABRICS + 1 (since there would be too few map elements to
+// support all fabrics the application wants to support in addition to an extra
+// pending key), but can be larger in case a consistent on-disk size of the map
+// is required.
+#ifndef SL_MATTER_MAX_STORED_OP_KEYS
+#define SL_MATTER_MAX_STORED_OP_KEYS (CHIP_CONFIG_MAX_FABRICS + 1)
+#endif
+
+namespace chip {
+namespace DeviceLayer {
+namespace Internal {
+
+/**
+ * @brief OperationalKeystore implementation making use of the EFR32 SDK-provided
+ *        storage mechanisms to load/store keypairs.
+ *
+ * WARNING: Ensure that any implementation that uses this one as a starting point
+ *          DOES NOT have the raw key material (in usable form) passed up/down to
+ *          direct storage APIs that may make copies on heap/stack without sanitization.
+ */
+class Efr32PsaOperationalKeystore : public chip::Crypto::OperationalKeystore
+{
+public:
+    Efr32PsaOperationalKeystore(){};
+    virtual ~Efr32PsaOperationalKeystore() override;
+
+    // Non-copyable
+    Efr32PsaOperationalKeystore(Efr32PsaOperationalKeystore const &) = delete;
+    void operator=(Efr32PsaOperationalKeystore const &) = delete;
+
+    /**
+     * @brief Initialize the Operational Keystore
+     */
+    CHIP_ERROR Init();
+
+    bool HasPendingOpKeypair() const override { return (mPendingKeypair != nullptr); }
+
+    bool HasOpKeypairForFabric(FabricIndex fabricIndex) const override;
+    CHIP_ERROR NewOpKeypairForFabric(FabricIndex fabricIndex, MutableByteSpan & outCertificateSigningRequest) override;
+    CHIP_ERROR ActivateOpKeypairForFabric(FabricIndex fabricIndex, const chip::Crypto::P256PublicKey & nocPublicKey) override;
+    CHIP_ERROR CommitOpKeypairForFabric(FabricIndex fabricIndex) override;
+    CHIP_ERROR RemoveOpKeypairForFabric(FabricIndex fabricIndex) override;
+    void RevertPendingKeypair() override;
+    CHIP_ERROR SignWithOpKeypair(FabricIndex fabricIndex, const ByteSpan & message,
+                                 chip::Crypto::P256ECDSASignature & outSignature) const override;
+    Crypto::P256Keypair * AllocateEphemeralKeypairForCASE() override;
+    void ReleaseEphemeralKeypair(chip::Crypto::P256Keypair * keypair) override;
+
+protected:
+    // The keymap maps PSA Crypto persistent key ID offsets against fabric IDs.
+    // The keymap is persisted in NVM3, and the keys are stored through the PSA
+    // API.
+    FabricIndex * mKeyMap = nullptr;
+    size_t mKeyMapSize    = 0;
+
+    // The key cache is to avoid having to reconstruct keys from the storage
+    // backend all the time (since it is rather slow).
+    EFR32OpaqueP256Keypair * mCachedKey = nullptr;
+
+    // This pending fabric index is `kUndefinedFabricIndex` if there isn't a
+    // pending keypair override for a given fabric.
+    FabricIndex mPendingFabricIndex          = kUndefinedFabricIndex;
+    EFR32OpaqueP256Keypair * mPendingKeypair = nullptr;
+    bool mIsPendingKeypairActive             = false;
+    bool mIsInitialized                      = false;
+
+private:
+    void ResetPendingKey()
+    {
+        if (mPendingKeypair != nullptr)
+        {
+            mPendingKeypair->Delete();
+            Platform::Delete(mPendingKeypair);
+        }
+        mPendingKeypair         = nullptr;
+        mIsPendingKeypairActive = false;
+        mPendingFabricIndex     = kUndefinedFabricIndex;
+    }
+
+    void Deinit()
+    {
+        ResetPendingKey();
+
+        if (mCachedKey != nullptr)
+        {
+            Platform::Delete<EFR32OpaqueP256Keypair>(mCachedKey);
+            mCachedKey = nullptr;
+        }
+
+        if (mKeyMap != nullptr)
+        {
+            Platform::MemoryFree(mKeyMap);
+            mKeyMap     = nullptr;
+            mKeyMapSize = 0;
+        }
+
+        mIsInitialized = false;
+    }
+
+    /**
+     * @brief Find the opaque key ID stored in the map for a given
+     *        fabric ID.
+     *
+     * @param fabricIndex The fabric index to find the opaque key ID for.
+     *                    Can also be kUndefinedFabricIndex to find the first
+     *                    unoccupied key ID.
+     *
+     * @return a valid key ID on match, or kEFR32OpaqueKeyIdUnknown if no
+     *         match is found.
+     */
+    EFR32OpaqueKeyId FindKeyIdForFabric(FabricIndex fabricIndex) const;
+};
+
+} // namespace Internal
+} // namespace DeviceLayer
+} // namespace chip
diff --git a/src/platform/silabs/SiWx917/KeyValueStoreManagerImpl.cpp b/src/platform/silabs/SiWx917/KeyValueStoreManagerImpl.cpp
new file mode 100644
index 0000000..c752c75
--- /dev/null
+++ b/src/platform/silabs/SiWx917/KeyValueStoreManagerImpl.cpp
@@ -0,0 +1,213 @@
+/*
+ *
+ *    Copyright (c) 2021-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
+ *          Platform-specific key value storage implementation for SILABS
+ */
+
+#include <lib/support/CHIPMemString.h>
+#include <lib/support/CodeUtils.h>
+#include <platform/CHIPDeviceLayer.h>
+#include <platform/KeyValueStoreManager.h>
+#include <platform/silabs/SilabsConfig.h>
+#include <stdio.h>
+#include <string.h>
+
+using namespace ::chip;
+using namespace ::chip::DeviceLayer::Internal;
+
+#define CONVERT_KEYMAP_INDEX_TO_NVM3KEY(index) (SILABSConfig::kConfigKey_KvsFirstKeySlot + index)
+#define CONVERT_NVM3KEY_TO_KEYMAP_INDEX(nvm3Key) (nvm3Key - SILABSConfig::kConfigKey_KvsFirstKeySlot)
+
+namespace chip {
+namespace DeviceLayer {
+namespace PersistedStorage {
+
+KeyValueStoreManagerImpl KeyValueStoreManagerImpl::sInstance;
+char mKvsStoredKeyString[KeyValueStoreManagerImpl::kMaxEntries][PersistentStorageDelegate::kKeyLengthMax + 1];
+
+CHIP_ERROR KeyValueStoreManagerImpl::Init(void)
+{
+    CHIP_ERROR err;
+    err = SILABSConfig::Init();
+    SuccessOrExit(err);
+
+    memset(mKvsStoredKeyString, 0, sizeof(mKvsStoredKeyString));
+    size_t outLen;
+    err = SILABSConfig::ReadConfigValueBin(SILABSConfig::kConfigKey_KvsStringKeyMap,
+                                           reinterpret_cast<uint8_t *>(mKvsStoredKeyString), sizeof(mKvsStoredKeyString), outLen);
+
+    if (err == CHIP_DEVICE_ERROR_CONFIG_NOT_FOUND) // Initial boot
+    {
+        err = CHIP_NO_ERROR;
+    }
+
+exit:
+    return err;
+}
+
+bool KeyValueStoreManagerImpl::IsValidKvsNvm3Key(uint32_t nvm3Key) const
+{
+    return ((SILABSConfig::kConfigKey_KvsFirstKeySlot <= nvm3Key) && (nvm3Key <= SILABSConfig::kConfigKey_KvsLastKeySlot));
+}
+
+CHIP_ERROR KeyValueStoreManagerImpl::MapKvsKeyToNvm3(const char * key, uint32_t & nvm3Key, bool isSlotNeeded) const
+{
+    CHIP_ERROR err;
+    uint8_t firstEmptyKeySlot = kMaxEntries;
+    for (uint8_t keyIndex = 0; keyIndex < kMaxEntries; keyIndex++)
+    {
+        if (strcmp(key, mKvsStoredKeyString[keyIndex]) == 0)
+        {
+            nvm3Key = CONVERT_KEYMAP_INDEX_TO_NVM3KEY(keyIndex);
+            VerifyOrDie(IsValidKvsNvm3Key(nvm3Key) == true);
+            return CHIP_NO_ERROR;
+        }
+
+        if (isSlotNeeded && (firstEmptyKeySlot == kMaxEntries) && (mKvsStoredKeyString[keyIndex][0] == 0))
+        {
+            firstEmptyKeySlot = keyIndex;
+        }
+    }
+
+    if (isSlotNeeded)
+    {
+        if (firstEmptyKeySlot != kMaxEntries)
+        {
+            nvm3Key = CONVERT_KEYMAP_INDEX_TO_NVM3KEY(firstEmptyKeySlot);
+            VerifyOrDie(IsValidKvsNvm3Key(nvm3Key) == true);
+            err = CHIP_NO_ERROR;
+        }
+        else
+        {
+            err = CHIP_ERROR_PERSISTED_STORAGE_FAILED;
+        }
+    }
+    else
+    {
+        err = CHIP_ERROR_PERSISTED_STORAGE_VALUE_NOT_FOUND;
+    }
+    return err;
+}
+
+void KeyValueStoreManagerImpl::ForceKeyMapSave()
+{
+    OnScheduledKeyMapSave(nullptr, nullptr);
+}
+
+void KeyValueStoreManagerImpl::OnScheduledKeyMapSave(System::Layer * systemLayer, void * appState)
+{
+    SILABSConfig::WriteConfigValueBin(SILABSConfig::kConfigKey_KvsStringKeyMap,
+                                      reinterpret_cast<const uint8_t *>(mKvsStoredKeyString), sizeof(mKvsStoredKeyString));
+}
+
+void KeyValueStoreManagerImpl::ScheduleKeyMapSave(void)
+{
+    /*
+        During commissioning, the key map will be modified multiples times subsequently.
+        Commit the key map in nvm once it as stabilized.
+    */
+    SystemLayer().StartTimer(
+        std::chrono::duration_cast<System::Clock::Timeout>(System::Clock::Seconds32(SILABS_KVS_SAVE_DELAY_SECONDS)),
+        KeyValueStoreManagerImpl::OnScheduledKeyMapSave, NULL);
+}
+
+CHIP_ERROR KeyValueStoreManagerImpl::_Get(const char * key, void * value, size_t value_size, size_t * read_bytes_size,
+                                          size_t offset_bytes) const
+{
+    VerifyOrReturnError(key != nullptr, CHIP_ERROR_INVALID_ARGUMENT);
+
+    uint32_t nvm3Key;
+    CHIP_ERROR err = MapKvsKeyToNvm3(key, nvm3Key);
+    VerifyOrReturnError(err == CHIP_NO_ERROR, err);
+
+    size_t outLen;
+    err = SILABSConfig::ReadConfigValueBin(nvm3Key, reinterpret_cast<uint8_t *>(value), value_size, outLen, offset_bytes);
+    if (read_bytes_size)
+    {
+        *read_bytes_size = outLen;
+    }
+
+    if (err == CHIP_DEVICE_ERROR_CONFIG_NOT_FOUND)
+    {
+        return CHIP_ERROR_PERSISTED_STORAGE_VALUE_NOT_FOUND;
+    }
+
+    return err;
+}
+
+CHIP_ERROR KeyValueStoreManagerImpl::_Put(const char * key, const void * value, size_t value_size)
+{
+    VerifyOrReturnError(key != nullptr, CHIP_ERROR_INVALID_ARGUMENT);
+
+    uint32_t nvm3Key;
+    CHIP_ERROR err = MapKvsKeyToNvm3(key, nvm3Key, /* isSlotNeeded */ true);
+    VerifyOrReturnError(err == CHIP_NO_ERROR, err);
+
+    err = SILABSConfig::WriteConfigValueBin(nvm3Key, reinterpret_cast<const uint8_t *>(value), value_size);
+    if (err == CHIP_NO_ERROR)
+    {
+        uint32_t keyIndex = nvm3Key - SILABSConfig::kConfigKey_KvsFirstKeySlot;
+        Platform::CopyString(mKvsStoredKeyString[keyIndex], key);
+        ScheduleKeyMapSave();
+    }
+
+    return err;
+}
+
+CHIP_ERROR KeyValueStoreManagerImpl::_Delete(const char * key)
+{
+    VerifyOrReturnError(key != nullptr, CHIP_ERROR_INVALID_ARGUMENT);
+
+    uint32_t nvm3Key;
+    CHIP_ERROR err = MapKvsKeyToNvm3(key, nvm3Key);
+    VerifyOrReturnError(err == CHIP_NO_ERROR, err);
+
+    err = SILABSConfig::ClearConfigValue(nvm3Key);
+    if (err == CHIP_NO_ERROR)
+    {
+        uint32_t keyIndex = CONVERT_NVM3KEY_TO_KEYMAP_INDEX(nvm3Key);
+        memset(mKvsStoredKeyString[keyIndex], 0, sizeof(mKvsStoredKeyString[keyIndex]));
+        ScheduleKeyMapSave();
+    }
+
+    return err;
+}
+
+CHIP_ERROR KeyValueStoreManagerImpl::ErasePartition(void)
+{
+    // Iterate over all the Matter Kvs nvm3 records and delete each one...
+    CHIP_ERROR err = CHIP_NO_ERROR;
+    for (uint32_t nvm3Key = SILABSConfig::kMinConfigKey_MatterKvs; nvm3Key < SILABSConfig::kMaxConfigKey_MatterKvs; nvm3Key++)
+    {
+        err = SILABSConfig::ClearConfigValue(nvm3Key);
+
+        if (err != CHIP_NO_ERROR)
+        {
+            break;
+        }
+    }
+
+    memset(mKvsStoredKeyString, 0, sizeof(mKvsStoredKeyString));
+    return err;
+}
+
+} // namespace PersistedStorage
+} // namespace DeviceLayer
+} // namespace chip
diff --git a/src/platform/silabs/SiWx917/OTAImageProcessorImpl.cpp b/src/platform/silabs/SiWx917/OTAImageProcessorImpl.cpp
new file mode 100644
index 0000000..f07fd94
--- /dev/null
+++ b/src/platform/silabs/SiWx917/OTAImageProcessorImpl.cpp
@@ -0,0 +1,335 @@
+/*
+ *
+ *    Copyright (c) 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.
+ */
+
+#include "OTAImageProcessorImpl.h"
+#include <app/clusters/ota-requestor/OTADownloader.h>
+#include <app/clusters/ota-requestor/OTARequestorInterface.h>
+
+extern "C" {
+#include "btl_interface.h"
+#include "em_bus.h" // For CORE_CRITICAL_SECTION
+}
+
+#include <platform/silabs/SilabsConfig.h>
+
+/// No error, operation OK
+#define SL_BOOTLOADER_OK 0L
+
+namespace chip {
+
+// Define static memebers
+uint8_t OTAImageProcessorImpl::mSlotId                                                  = 0;
+uint32_t OTAImageProcessorImpl::mWriteOffset                                            = 0;
+uint16_t OTAImageProcessorImpl::writeBufOffset                                          = 0;
+uint8_t OTAImageProcessorImpl::writeBuffer[kAlignmentBytes] __attribute__((aligned(4))) = { 0 };
+
+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;
+}
+
+bool OTAImageProcessorImpl::IsFirstImageRun()
+{
+    OTARequestorInterface * requestor = chip::GetRequestorInstance();
+    if (requestor == nullptr)
+    {
+        return false;
+    }
+
+    return requestor->GetCurrentUpdateState() == OTARequestorInterface::OTAUpdateStateEnum::kApplying;
+}
+
+CHIP_ERROR OTAImageProcessorImpl::ConfirmCurrentImage()
+{
+    OTARequestorInterface * requestor = chip::GetRequestorInstance();
+    if (requestor == nullptr)
+    {
+        return CHIP_ERROR_INTERNAL;
+    }
+
+    uint32_t currentVersion;
+    uint32_t targetVersion = requestor->GetTargetVersion();
+    ReturnErrorOnFailure(DeviceLayer::ConfigurationMgr().GetSoftwareVersion(currentVersion));
+    if (currentVersion != targetVersion)
+    {
+        ChipLogError(SoftwareUpdate, "Current software version = %" PRIu32 ", expected software version = %" PRIu32, currentVersion,
+                     targetVersion);
+        return CHIP_ERROR_INCORRECT_STATE;
+    }
+
+    return CHIP_NO_ERROR;
+}
+
+void OTAImageProcessorImpl::HandlePrepareDownload(intptr_t context)
+{
+    int32_t err           = SL_BOOTLOADER_OK;
+    auto * imageProcessor = reinterpret_cast<OTAImageProcessorImpl *>(context);
+
+    if (imageProcessor == nullptr)
+    {
+        ChipLogError(SoftwareUpdate, "ImageProcessor context is null");
+        return;
+    }
+    else if (imageProcessor->mDownloader == nullptr)
+    {
+        ChipLogError(SoftwareUpdate, "mDownloader is null");
+        return;
+    }
+
+    ChipLogProgress(SoftwareUpdate, "HandlePrepareDownload");
+
+    CORE_CRITICAL_SECTION(bootloader_init();)
+    mSlotId                                 = 0; // Single slot until we support multiple images
+    writeBufOffset                          = 0;
+    mWriteOffset                            = 0;
+    imageProcessor->mParams.downloadedBytes = 0;
+
+    imageProcessor->mHeaderParser.Init();
+
+    // Not calling bootloader_eraseStorageSlot(mSlotId) here because we erase during each write
+
+    imageProcessor->mDownloader->OnPreparedForDownload(err == SL_BOOTLOADER_OK ? CHIP_NO_ERROR : CHIP_ERROR_INTERNAL);
+}
+
+void OTAImageProcessorImpl::HandleFinalize(intptr_t context)
+{
+    uint32_t err          = SL_BOOTLOADER_OK;
+    auto * imageProcessor = reinterpret_cast<OTAImageProcessorImpl *>(context);
+    if (imageProcessor == nullptr)
+    {
+        return;
+    }
+
+    // Pad the remainder of the write buffer with zeros and write it to bootloader storage
+    if (writeBufOffset != 0)
+    {
+        // Account for last bytes of the image not yet written to storage
+        imageProcessor->mParams.downloadedBytes += writeBufOffset;
+
+        while (writeBufOffset != kAlignmentBytes)
+        {
+            writeBuffer[writeBufOffset] = 0;
+            writeBufOffset++;
+        }
+
+        CORE_CRITICAL_SECTION(err = bootloader_eraseWriteStorage(mSlotId, mWriteOffset, writeBuffer, kAlignmentBytes);)
+        if (err)
+        {
+            ChipLogError(SoftwareUpdate, "ERROR: In HandleFinalize bootloader_eraseWriteStorage() error %ld", err);
+            imageProcessor->mDownloader->EndDownload(CHIP_ERROR_WRITE_FAILED);
+            return;
+        }
+    }
+
+    imageProcessor->ReleaseBlock();
+
+    ChipLogProgress(SoftwareUpdate, "OTA image downloaded successfully");
+}
+
+void OTAImageProcessorImpl::HandleApply(intptr_t context)
+{
+    uint32_t err = SL_BOOTLOADER_OK;
+
+    ChipLogProgress(SoftwareUpdate, "OTAImageProcessorImpl::HandleApply()");
+
+    // Force KVS to store pending keys such as data from StoreCurrentUpdateInfo()
+    chip::DeviceLayer::PersistedStorage::KeyValueStoreMgrImpl().ForceKeyMapSave();
+
+    CORE_CRITICAL_SECTION(err = bootloader_verifyImage(mSlotId, NULL);)
+    if (err != SL_BOOTLOADER_OK)
+    {
+        ChipLogError(SoftwareUpdate, "ERROR: bootloader_verifyImage() error %ld", err);
+
+        return;
+    }
+
+    CORE_CRITICAL_SECTION(err = bootloader_setImageToBootload(mSlotId);)
+    if (err != SL_BOOTLOADER_OK)
+    {
+        ChipLogError(SoftwareUpdate, "ERROR: bootloader_setImageToBootload() error %ld", err);
+
+        return;
+    }
+
+    // This reboots the device
+    CORE_CRITICAL_SECTION(bootloader_rebootAndInstall();)
+}
+
+void OTAImageProcessorImpl::HandleAbort(intptr_t context)
+{
+    auto * imageProcessor = reinterpret_cast<OTAImageProcessorImpl *>(context);
+    if (imageProcessor == nullptr)
+    {
+        return;
+    }
+
+    // Not clearing the image storage area as it is done during each write
+    imageProcessor->ReleaseBlock();
+}
+
+void OTAImageProcessorImpl::HandleProcessBlock(intptr_t context)
+{
+    uint32_t err          = SL_BOOTLOADER_OK;
+    auto * imageProcessor = reinterpret_cast<OTAImageProcessorImpl *>(context);
+    if (imageProcessor == nullptr)
+    {
+        ChipLogError(SoftwareUpdate, "ImageProcessor context is null");
+        return;
+    }
+    else if (imageProcessor->mDownloader == nullptr)
+    {
+        ChipLogError(SoftwareUpdate, "mDownloader is null");
+        return;
+    }
+
+    ByteSpan block        = imageProcessor->mBlock;
+    CHIP_ERROR chip_error = imageProcessor->ProcessHeader(block);
+
+    if (chip_error != CHIP_NO_ERROR)
+    {
+        ChipLogError(SoftwareUpdate, "Matter image header parser error %s", chip::ErrorStr(chip_error));
+        imageProcessor->mDownloader->EndDownload(CHIP_ERROR_INVALID_FILE_IDENTIFIER);
+        return;
+    }
+
+    // Copy data into the word-aligned writeBuffer, once it fills write its contents to the bootloader storage
+    // Final data block is handled in HandleFinalize().
+    uint32_t blockReadOffset = 0;
+    while (blockReadOffset < block.size())
+    {
+        writeBuffer[writeBufOffset] = *((block.data()) + blockReadOffset);
+        writeBufOffset++;
+        blockReadOffset++;
+        if (writeBufOffset == kAlignmentBytes)
+        {
+            writeBufOffset = 0;
+
+            CORE_CRITICAL_SECTION(err = bootloader_eraseWriteStorage(mSlotId, mWriteOffset, writeBuffer, kAlignmentBytes);)
+            if (err)
+            {
+                ChipLogError(SoftwareUpdate, "ERROR: In HandleProcessBlock bootloader_eraseWriteStorage() error %ld", err);
+                imageProcessor->mDownloader->EndDownload(CHIP_ERROR_WRITE_FAILED);
+                return;
+            }
+            mWriteOffset += kAlignmentBytes;
+            imageProcessor->mParams.downloadedBytes += kAlignmentBytes;
+        }
+    }
+
+    imageProcessor->mDownloader->FetchNextData();
+}
+
+CHIP_ERROR OTAImageProcessorImpl::ProcessHeader(ByteSpan & block)
+{
+    if (mHeaderParser.IsInitialized())
+    {
+        OTAImageHeader header;
+        CHIP_ERROR error = mHeaderParser.AccumulateAndDecode(block, header);
+
+        // Needs more data to decode the header
+        ReturnErrorCodeIf(error == CHIP_ERROR_BUFFER_TOO_SMALL, CHIP_NO_ERROR);
+        ReturnErrorOnFailure(error);
+
+        // SL TODO -- store version somewhere
+        ChipLogProgress(SoftwareUpdate, "Image Header software version: %ld payload size: %lu", header.mSoftwareVersion,
+                        (long unsigned int) header.mPayloadSize);
+        mParams.totalFileBytes = header.mPayloadSize;
+        mHeaderParser.Clear();
+    }
+    return CHIP_NO_ERROR;
+}
+
+// Store block data for HandleProcessBlock to access
+CHIP_ERROR OTAImageProcessorImpl::SetBlock(ByteSpan & block)
+{
+    if ((block.data() == nullptr) || block.empty())
+    {
+        return CHIP_NO_ERROR;
+    }
+
+    // Allocate memory for block data if we don't have enough already
+    if (mBlock.size() < block.size())
+    {
+        ReleaseBlock();
+
+        mBlock = MutableByteSpan(static_cast<uint8_t *>(chip::Platform::MemoryAlloc(block.size())), block.size());
+        if (mBlock.data() == nullptr)
+        {
+            return CHIP_ERROR_NO_MEMORY;
+        }
+    }
+
+    // Store the actual block data
+    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;
+}
+
+CHIP_ERROR OTAImageProcessorImpl::ReleaseBlock()
+{
+    if (mBlock.data() != nullptr)
+    {
+        chip::Platform::MemoryFree(mBlock.data());
+    }
+
+    mBlock = MutableByteSpan();
+    return CHIP_NO_ERROR;
+}
+
+} // namespace chip
diff --git a/src/platform/silabs/SiWx917/OTAImageProcessorImpl.h b/src/platform/silabs/SiWx917/OTAImageProcessorImpl.h
new file mode 100644
index 0000000..30709bd
--- /dev/null
+++ b/src/platform/silabs/SiWx917/OTAImageProcessorImpl.h
@@ -0,0 +1,80 @@
+/*
+ *
+ *    Copyright (c) 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.
+ */
+
+#pragma once
+
+#include <app/clusters/ota-requestor/OTADownloader.h>
+#include <lib/core/OTAImageHeader.h>
+#include <platform/CHIPDeviceLayer.h>
+#include <platform/OTAImageProcessor.h>
+
+#include <fstream>
+
+namespace chip {
+
+class OTAImageProcessorImpl : public OTAImageProcessorInterface
+{
+public:
+    //////////// 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;
+
+    void SetOTADownloader(OTADownloader * downloader) { mDownloader = downloader; }
+    void SetOTAImageFile(const char * imageFile) { mImageFile = imageFile; }
+
+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);
+    CHIP_ERROR ProcessHeader(ByteSpan & block);
+
+    /**
+     * 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();
+
+    // EFR32 platform creates a single instance of OTAImageProcessorImpl class.
+    // If that changes then the use of static members and functions must be revisited
+    static uint32_t mWriteOffset; // End of last written block
+    static uint8_t mSlotId;       // Bootloader storage slot
+    MutableByteSpan mBlock;
+    OTADownloader * mDownloader;
+    OTAImageHeaderParser mHeaderParser;
+    const char * mImageFile                 = nullptr;
+    static constexpr size_t kAlignmentBytes = 64;
+    // Intermediate, word-aligned buffer for writing to the bootloader storage.
+    // Bootloader storage API requires the buffer size to be a multiple of 4.
+    static uint8_t writeBuffer[kAlignmentBytes] __attribute__((aligned(4)));
+    // Offset indicates how far the write buffer has been filled
+    static uint16_t writeBufOffset;
+};
+
+} // namespace chip
diff --git a/src/platform/silabs/SiWx917/PlatformManagerImpl.cpp b/src/platform/silabs/SiWx917/PlatformManagerImpl.cpp
new file mode 100644
index 0000000..25de6d5
--- /dev/null
+++ b/src/platform/silabs/SiWx917/PlatformManagerImpl.cpp
@@ -0,0 +1,163 @@
+/*
+ *
+ *    Copyright (c) 2020 Project CHIP Authors
+ *    Copyright (c) 2019 Nest Labs, Inc.
+ *
+ *    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 PlatformManager object
+ *          for Silabs platforms using the Silicon Labs SDK.
+ */
+/* this file behaves like a config.h, comes first */
+#include <platform/internal/CHIPDeviceLayerInternal.h>
+
+#include <platform/FreeRTOS/SystemTimeSupport.h>
+#include <platform/KeyValueStoreManager.h>
+#include <platform/PlatformManager.h>
+#include <platform/internal/GenericPlatformManagerImpl_FreeRTOS.ipp>
+#include <platform/silabs/DiagnosticDataProviderImpl.h>
+
+#if CHIP_SYSTEM_CONFIG_USE_LWIP
+#include <lwip/tcpip.h>
+#endif // CHIP_SYSTEM_CONFIG_USE_LWIP
+
+#include "AppConfig.h"
+#include "FreeRTOS.h"
+
+namespace chip {
+namespace DeviceLayer {
+
+PlatformManagerImpl PlatformManagerImpl::sInstance;
+
+CHIP_ERROR PlatformManagerImpl::_InitChipStack(void)
+{
+    CHIP_ERROR err;
+
+    // Initialize the configuration system.
+    err = chip::DeviceLayer::PersistedStorage::KeyValueStoreMgrImpl().Init();
+    SuccessOrExit(err);
+
+#if CHIP_SYSTEM_CONFIG_USE_LWIP
+    // Initialize LwIP.
+    tcpip_init(NULL, NULL);
+#endif // CHIP_SYSTEM_CONFIG_USE_LWIP
+
+    ReturnErrorOnFailure(System::Clock::InitClock_RealTime());
+
+    // Call _InitChipStack() on the generic implementation base class
+    // to finish the initialization process.
+    err = Internal::GenericPlatformManagerImpl_FreeRTOS<PlatformManagerImpl>::_InitChipStack();
+    SuccessOrExit(err);
+
+exit:
+    return err;
+}
+
+void PlatformManagerImpl::_Shutdown()
+{
+    uint64_t upTime = 0;
+
+    if (GetDiagnosticDataProvider().GetUpTime(upTime) == CHIP_NO_ERROR)
+    {
+        uint32_t totalOperationalHours = 0;
+
+        if (ConfigurationMgr().GetTotalOperationalHours(totalOperationalHours) == CHIP_NO_ERROR)
+        {
+            ConfigurationMgr().StoreTotalOperationalHours(totalOperationalHours + static_cast<uint32_t>(upTime / 3600));
+        }
+        else
+        {
+            ChipLogError(DeviceLayer, "Failed to get total operational hours of the Node");
+        }
+    }
+    else
+    {
+        ChipLogError(DeviceLayer, "Failed to get current uptime since the Node’s last reboot");
+    }
+
+    Internal::GenericPlatformManagerImpl_FreeRTOS<PlatformManagerImpl>::_Shutdown();
+}
+#if CHIP_DEVICE_CONFIG_ENABLE_WIFI_STATION
+void PlatformManagerImpl::HandleWFXSystemEvent(wfx_event_base_t eventBase, sl_wfx_generic_message_t * eventData)
+{
+    ChipDeviceEvent event;
+    memset(&event, 0, sizeof(event));
+    event.Type                              = DeviceEventType::kWFXSystemEvent;
+    event.Platform.WFXSystemEvent.eventBase = eventBase;
+
+    if (eventBase == WIFI_EVENT)
+    {
+        switch (eventData->header.id)
+        {
+        case SL_WFX_STARTUP_IND_ID:
+            memcpy(&event.Platform.WFXSystemEvent.data.startupEvent, eventData,
+                   sizeof(event.Platform.WFXSystemEvent.data.startupEvent));
+            break;
+        case SL_WFX_CONNECT_IND_ID:
+            memcpy(&event.Platform.WFXSystemEvent.data.connectEvent, eventData,
+                   sizeof(event.Platform.WFXSystemEvent.data.connectEvent));
+            break;
+        case SL_WFX_DISCONNECT_IND_ID:
+            memcpy(&event.Platform.WFXSystemEvent.data.disconnectEvent, eventData,
+                   sizeof(event.Platform.WFXSystemEvent.data.disconnectEvent));
+            break;
+        // case SL_WFX_RECEIVED_IND_ID:
+        //     memcpy(&event.Platform.WFXSystemEvent.data.receivedEvent, eventData,
+        //            sizeof(event.Platform.WFXSystemEvent.data.receivedEvent));
+        //     break;
+        // case SL_WFX_GENERIC_IND_ID:
+        //     memcpy(&event.Platform.WFXSystemEvent.data.genericEvent, eventData,
+        //            sizeof(event.Platform.WFXSystemEvent.data.genericEvent));
+        //     break;
+        // case SL_WFX_EXCEPTION_IND_ID:
+        //     memcpy(&event.Platform.WFXSystemEvent.data.exceptionEvent, eventData,
+        //            sizeof(event.Platform.WFXSystemEvent.data.exceptionEvent));
+        //     break;
+        // case SL_WFX_ERROR_IND_ID:
+        //     memcpy(&event.Platform.WFXSystemEvent.data.errorEvent, eventData,
+        //            sizeof(event.Platform.WFXSystemEvent.data.errorEvent));
+        //     break;
+        default:
+            break;
+        }
+    }
+    else if (eventBase == IP_EVENT)
+    {
+        switch (eventData->header.id)
+        {
+        case IP_EVENT_STA_GOT_IP:
+            memcpy(&event.Platform.WFXSystemEvent.data.genericMsgEvent, eventData,
+                   sizeof(event.Platform.WFXSystemEvent.data.genericMsgEvent));
+            break;
+        case IP_EVENT_GOT_IP6:
+            memcpy(&event.Platform.WFXSystemEvent.data.genericMsgEvent, eventData,
+                   sizeof(event.Platform.WFXSystemEvent.data.genericMsgEvent));
+            break;
+        case IP_EVENT_STA_LOST_IP:
+            memcpy(&event.Platform.WFXSystemEvent.data.genericMsgEvent, eventData,
+                   sizeof(event.Platform.WFXSystemEvent.data.genericMsgEvent));
+            break;
+        default:
+            break;
+        }
+    }
+
+    (void) sInstance.PostEvent(&event);
+}
+#endif
+
+} // namespace DeviceLayer
+} // namespace chip
diff --git a/src/platform/silabs/SiWx917/ThreadStackManagerImpl.cpp b/src/platform/silabs/SiWx917/ThreadStackManagerImpl.cpp
new file mode 100644
index 0000000..16d7922
--- /dev/null
+++ b/src/platform/silabs/SiWx917/ThreadStackManagerImpl.cpp
@@ -0,0 +1,173 @@
+/*
+ *
+ *    Copyright (c) 2020 Project CHIP Authors
+ *    Copyright (c) 2019 Nest Labs, Inc.
+ *
+ *    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 ThreadStackManager object for
+ *          EFR32 platforms using the Silicon Labs SDK and the OpenThread
+ *          stack.
+ *
+ */
+/* this file behaves like a config.h, comes first */
+#include <platform/internal/CHIPDeviceLayerInternal.h>
+
+#include <platform/FreeRTOS/GenericThreadStackManagerImpl_FreeRTOS.cpp>
+#include <platform/OpenThread/GenericThreadStackManagerImpl_OpenThread.cpp>
+#include <platform/OpenThread/OpenThreadUtils.h>
+#include <platform/ThreadStackManager.h>
+
+#include <openthread/platform/entropy.h>
+
+#include <lib/support/CHIPPlatformMemory.h>
+
+namespace chip {
+namespace DeviceLayer {
+
+using namespace ::chip::DeviceLayer::Internal;
+
+ThreadStackManagerImpl ThreadStackManagerImpl::sInstance;
+
+CHIP_ERROR ThreadStackManagerImpl::_InitThreadStack(void)
+{
+    return InitThreadStack(NULL);
+}
+
+CHIP_ERROR ThreadStackManagerImpl::InitThreadStack(otInstance * otInst)
+{
+    CHIP_ERROR err = CHIP_NO_ERROR;
+
+    // Initialize the generic implementation base classes.
+    err = GenericThreadStackManagerImpl_FreeRTOS<ThreadStackManagerImpl>::DoInit();
+    SuccessOrExit(err);
+    err = GenericThreadStackManagerImpl_OpenThread<ThreadStackManagerImpl>::DoInit(otInst);
+    SuccessOrExit(err);
+
+exit:
+    return err;
+}
+
+bool ThreadStackManagerImpl::IsInitialized()
+{
+    return sInstance.mThreadStackLock != NULL;
+}
+
+} // namespace DeviceLayer
+} // namespace chip
+
+using namespace ::chip::DeviceLayer;
+
+/**
+ * Glue function called directly by the OpenThread stack when tasklet processing work
+ * is pending.
+ */
+extern "C" void otTaskletsSignalPending(otInstance * p_instance)
+{
+    ThreadStackMgrImpl().SignalThreadActivityPending();
+}
+
+/**
+ * Glue function called directly by the OpenThread stack when system event processing work
+ * is pending.
+ */
+extern "C" void otSysEventSignalPending(void)
+{
+    BaseType_t yieldRequired = ThreadStackMgrImpl().SignalThreadActivityPendingFromISR();
+    portYIELD_FROM_ISR(yieldRequired);
+}
+
+extern "C" void * otPlatCAlloc(size_t aNum, size_t aSize)
+{
+    return CHIPPlatformMemoryCalloc(aNum, aSize);
+}
+
+extern "C" void otPlatFree(void * aPtr)
+{
+    CHIPPlatformMemoryFree(aPtr);
+}
+
+extern "C" __WEAK void sl_openthread_init(void)
+{
+    // Place holder for enabling Silabs specific features available only through Simplicity Studio
+}
+
+/**
+ * @brief Openthread UART implementation for the CLI is conflicting
+ *        with the UART implemented for Pigweed RPC as they use the same UART port
+ *
+ *        We now only build the uart as implemented in
+ *        connectedhomeip/examples/platform/efr32/uart.c
+ *        and remap OT functions to use our uart api.
+ *
+ *        For now OT CLI isn't usable when the examples are built with pw_rpc
+ */
+
+#ifndef PW_RPC_ENABLED
+#include "uart.h"
+#endif
+
+extern "C" otError otPlatUartEnable(void)
+{
+#ifdef PW_RPC_ENABLED
+    return OT_ERROR_NOT_IMPLEMENTED;
+#else
+    uartConsoleInit();
+    return OT_ERROR_NONE;
+#endif
+}
+
+#if CHIP_DEVICE_CONFIG_THREAD_ENABLE_CLI
+
+extern "C" otError otPlatUartSend(const uint8_t * aBuf, uint16_t aBufLength)
+{
+#ifdef PW_RPC_ENABLED
+    return OT_ERROR_NOT_IMPLEMENTED;
+#else
+    if (uartConsoleWrite((const char *) aBuf, aBufLength) > 0)
+    {
+        otPlatUartSendDone();
+        return OT_ERROR_NONE;
+    }
+    return OT_ERROR_FAILED;
+#endif
+}
+
+extern "C" void efr32UartProcess(void)
+{
+#if !defined(PW_RPC_ENABLED) && !defined(ENABLE_CHIP_SHELL)
+    uint8_t tempBuf[128] = { 0 };
+    // will read the data available up to 128bytes
+    uint16_t count = uartConsoleRead((char *) tempBuf, 128);
+    if (count > 0)
+    {
+        // ot process Received data for CLI cmds
+        otPlatUartReceived(tempBuf, count);
+    }
+#endif
+}
+
+extern "C" __WEAK otError otPlatUartFlush(void)
+{
+    return OT_ERROR_NOT_IMPLEMENTED;
+}
+
+extern "C" __WEAK otError otPlatUartDisable(void)
+{
+    return OT_ERROR_NOT_IMPLEMENTED;
+}
+
+#endif // CHIP_DEVICE_CONFIG_THREAD_ENABLE_CLI
diff --git a/src/platform/silabs/SiWx917/args.gni b/src/platform/silabs/SiWx917/args.gni
new file mode 100644
index 0000000..6e7ac8d
--- /dev/null
+++ b/src/platform/silabs/SiWx917/args.gni
@@ -0,0 +1,61 @@
+# 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/efr32_sdk.gni")
+import("//build_overrides/pigweed.gni")
+
+import("${chip_root}/examples/platform/silabs/efr32/args.gni")
+import("${chip_root}/src/crypto/crypto.gni")
+
+# ARM architecture flags will be set based on silabs_family.
+arm_platform_config = "${efr32_sdk_build_root}/efr32_arm.gni"
+
+mbedtls_target = "${efr32_sdk_build_root}:efr32_sdk"
+
+openthread_external_mbedtls = mbedtls_target
+
+# default to platform crypto implementation but allow commandline override
+if (chip_crypto == "") {
+  chip_crypto = "platform"
+}
+
+chip_device_platform = "efr32"
+
+#Net work configuration OpenThread
+lwip_platform = "efr32"
+chip_mdns = "platform"
+chip_inet_config_enable_ipv4 = false
+chip_inet_config_enable_tcp_endpoint = false
+chip_system_config_use_open_thread_inet_endpoints = true
+chip_with_lwip = false
+
+chip_build_tests = false
+
+# Transitional CommissionableDataProvider not used anymore
+# examples/platform/silabs/efr32/EFR32DeviceDataProvider is now used.
+chip_use_transitional_commissionable_data_provider = false
+
+openthread_root = "${chip_root}/third_party/openthread/ot-efr32/openthread"
+openthread_core_config_platform_check_file =
+    "openthread-core-efr32-config-check.h"
+openthread_project_core_config_file = "OpenThreadConfig.h"
+openthread_core_config_deps = [ "${chip_root}/examples/platform/silabs/efr32:openthread_core_config_efr32_chip_examples" ]
+
+chip_config_memory_management = "platform"
+
+pw_build_LINK_DEPS = [
+  "$dir_pw_assert:impl",
+  "$dir_pw_log:impl",
+]
diff --git a/src/platform/silabs/SiWx917/efr32-chip-mbedtls-config.h b/src/platform/silabs/SiWx917/efr32-chip-mbedtls-config.h
new file mode 100644
index 0000000..049c12c
--- /dev/null
+++ b/src/platform/silabs/SiWx917/efr32-chip-mbedtls-config.h
@@ -0,0 +1,141 @@
+/*
+ *  Copyright (c) 2020, 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.
+ */
+
+#pragma once
+
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "em_device.h"
+#include "em_se.h"
+
+#if CHIP_HAVE_CONFIG_H
+#include <crypto/CryptoBuildConfig.h>
+#endif // CHIP_HAVE_CONFIG_H
+
+/**
+ * Enable H Crypto and Entropy modules
+ */
+#define MBEDTLS_AES_C
+#define MBEDTLS_ECP_C
+#define MBEDTLS_ECDH_C
+#define MBEDTLS_ENTROPY_C
+#define MBEDTLS_SHA224_C
+#define MBEDTLS_SHA256_C
+
+#define MBEDTLS_PLATFORM_SNPRINTF_MACRO snprintf
+
+#define MBEDTLS_AES_ROM_TABLES
+#define MBEDTLS_ASN1_PARSE_C
+#define MBEDTLS_ASN1_WRITE_C
+#define MBEDTLS_BASE64_C
+#define MBEDTLS_BIGNUM_C
+#define MBEDTLS_CCM_C
+#define MBEDTLS_CIPHER_C
+#define MBEDTLS_CMAC_C
+#define MBEDTLS_CTR_DRBG_C
+#define MBEDTLS_ECDH_LEGACY_CONTEXT
+#define MBEDTLS_ECDSA_C
+#define MBEDTLS_ECDSA_DETERMINISTIC
+#define MBEDTLS_ECJPAKE_C
+#define MBEDTLS_ECP_DP_SECP256R1_ENABLED
+#define MBEDTLS_ECP_NIST_OPTIM
+#define MBEDTLS_ENTROPY_FORCE_SHA256
+#define MBEDTLS_ENTROPY_HARDWARE_ALT
+#define MBEDTLS_ERROR_STRERROR_DUMMY
+#define MBEDTLS_HAVE_ASM
+#define MBEDTLS_HKDF_C
+#define MBEDTLS_HMAC_DRBG_C
+#define MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED
+#define MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED
+#define MBEDTLS_KEY_EXCHANGE_PSK_ENABLED
+#define MBEDTLS_MD_C
+#define MBEDTLS_NO_PLATFORM_ENTROPY
+#define MBEDTLS_OID_C
+#define MBEDTLS_PEM_PARSE_C
+#define MBEDTLS_PEM_WRITE_C
+#define MBEDTLS_PK_C
+#define MBEDTLS_PK_PARSE_C
+#define MBEDTLS_PK_WRITE_C
+#if CHIP_CRYPTO_MBEDTLS
+#define MBEDTLS_PKCS5_C
+#endif
+#define MBEDTLS_PLATFORM_C
+#define MBEDTLS_PLATFORM_MEMORY
+#define MBEDTLS_PLATFORM_NO_STD_FUNCTIONS
+#define MBEDTLS_PSA_CRYPTO_C
+#define MBEDTLS_PSA_CRYPTO_CONFIG
+#define MBEDTLS_PSA_CRYPTO_DRIVERS
+#define MBEDTLS_PSA_CRYPTO_STORAGE_C
+#define MBEDTLS_SHA256_SMALLER
+#define MBEDTLS_SHA512_C
+#define MBEDTLS_SSL_CLI_C
+#define MBEDTLS_SSL_COOKIE_C
+#define MBEDTLS_SSL_DTLS_ANTI_REPLAY
+#define MBEDTLS_SSL_DTLS_HELLO_VERIFY
+#define MBEDTLS_SSL_EXPORT_KEYS
+#define MBEDTLS_SSL_KEEP_PEER_CERTIFICATE
+#define MBEDTLS_SSL_MAX_FRAGMENT_LENGTH
+#define MBEDTLS_SSL_PROTO_TLS1_2
+#define MBEDTLS_SSL_PROTO_DTLS
+#define MBEDTLS_SSL_SRV_C
+#define MBEDTLS_SSL_TLS_C
+
+#if CHIP_CRYPTO_PLATFORM
+#define MBEDTLS_USE_PSA_CRYPTO
+#endif
+
+#define MBEDTLS_X509_CREATE_C
+#define MBEDTLS_X509_CSR_WRITE_C
+#define MBEDTLS_X509_CRL_PARSE_C
+#define MBEDTLS_X509_CRT_PARSE_C
+#define MBEDTLS_X509_CSR_PARSE_C
+#define MBEDTLS_X509_USE_C
+
+#define MBEDTLS_MPI_WINDOW_SIZE 1       /**< Maximum windows size used. */
+#define MBEDTLS_MPI_MAX_SIZE 32         /**< Maximum number of bytes for usable MPIs. */
+#define MBEDTLS_ECP_MAX_BITS 256        /**< Maximum bit size of groups */
+#define MBEDTLS_ECP_WINDOW_SIZE 2       /**< Maximum window size used */
+#define MBEDTLS_ECP_FIXED_POINT_OPTIM 0 /**< Enable fixed-point speed-up */
+#define MBEDTLS_ENTROPY_MAX_SOURCES 2   /**< Maximum number of sources supported */
+
+#if OPENTHREAD_CONFIG_COAP_SECURE_API_ENABLE
+#define MBEDTLS_SSL_MAX_CONTENT_LEN 900 /**< Maxium fragment length in bytes */
+#else
+#define MBEDTLS_SSL_MAX_CONTENT_LEN 768 /**< Maxium fragment length in bytes */
+#endif
+
+#define MBEDTLS_SSL_CIPHERSUITES MBEDTLS_TLS_ECJPAKE_WITH_AES_128_CCM_8
+
+#define MBEDTLS_CIPHER_MODE_WITH_PADDING
+
+#include "check_crypto_config.h"
+#include "config-device-acceleration.h"
+#include "mbedtls/check_config.h"
+#include "mbedtls/config_psa.h"
diff --git a/src/platform/silabs/SiWx917/efr32-mbedtls-psa-crypto-config.h b/src/platform/silabs/SiWx917/efr32-mbedtls-psa-crypto-config.h
new file mode 100644
index 0000000..6df9724
--- /dev/null
+++ b/src/platform/silabs/SiWx917/efr32-mbedtls-psa-crypto-config.h
@@ -0,0 +1,78 @@
+/*
+ *
+ *    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.
+ */
+
+#pragma once
+
+// ADD USER PSA CRYPTO CONFIG HERE
+#define SL_PSA_KEY_USER_SLOT_COUNT (4)
+
+#define SL_PSA_ITS_USER_MAX_FILES (128)
+
+#include "em_device.h"
+#if defined(SEMAILBOX_PRESENT) || defined(CRYPTOACC_PRESENT)
+// Use accelerated HMAC when we have it
+#define MBEDTLS_PSA_ACCEL_ALG_HMAC
+// Use accelerated ECDSA/ECDH when we have it
+#define MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_KEY_PAIR
+#define MBEDTLS_PSA_ACCEL_KEY_TYPE_ECC_PUBLIC_KEY
+#define MBEDTLS_PSA_ACCEL_ECC_SECP_R1_256
+#define MBEDTLS_PSA_ACCEL_ALG_ECDH
+#define MBEDTLS_PSA_ACCEL_ALG_ECDSA
+#else
+// Devices without SEMAILBOX or CRYPTOACC don't have HMAC top-level accelerated
+#define MBEDTLS_PSA_BUILTIN_ALG_HMAC 1
+// Devices without SEMAILBOX or CRYPTOACC don't have fully implemented ECDSA/ECDH
+#define MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_PUBLIC_KEY 1
+#define MBEDTLS_PSA_BUILTIN_KEY_TYPE_ECC_KEY_PAIR 1
+#define MBEDTLS_PSA_BUILTIN_ECC_SECP_R1_256 1
+#define MBEDTLS_PSA_BUILTIN_ALG_ECDH 1
+#define MBEDTLS_PSA_BUILTIN_ALG_ECDSA 1
+#endif
+// end of user configuration section >>>
+
+// AUTO GENERATED PSA CONFIG SECTION BELOW. **KEEP AS IS FUTURE GSDK UPDATE**
+#define PSA_WANT_KEY_TYPE_AES
+#define PSA_WANT_ALG_CMAC
+#define PSA_WANT_ALG_SHA_256
+#define PSA_WANT_ALG_CCM
+#define PSA_WANT_ALG_ECB_NO_PADDING
+#define PSA_WANT_ALG_ECDSA
+#define PSA_WANT_ALG_ECDH
+#define PSA_WANT_KEY_TYPE_ECC_KEY_PAIR
+#define PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY
+#define PSA_WANT_ECC_SECP_R1_256
+#define PSA_WANT_ALG_HKDF
+#define PSA_WANT_ALG_HMAC
+#define PSA_WANT_KEY_TYPE_HMAC
+#define MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG
+#define MBEDTLS_PSA_ACCEL_ALG_SHA_1
+#define MBEDTLS_PSA_ACCEL_ALG_SHA_224
+#define MBEDTLS_PSA_ACCEL_ALG_SHA_256
+#define MBEDTLS_PSA_ACCEL_KEY_TYPE_AES
+#define MBEDTLS_PSA_ACCEL_ALG_ECB_NO_PADDING
+#define MBEDTLS_PSA_ACCEL_ALG_CBC_NO_PADDING
+#define MBEDTLS_PSA_ACCEL_ALG_CBC_PKCS7
+#define MBEDTLS_PSA_ACCEL_ALG_CTR
+#define MBEDTLS_PSA_ACCEL_ALG_CFB
+#define MBEDTLS_PSA_ACCEL_ALG_OFB
+#define MBEDTLS_PSA_ACCEL_ALG_GCM
+#define MBEDTLS_PSA_ACCEL_ALG_CCM
+#define MBEDTLS_PSA_ACCEL_ALG_CMAC
+
+#define MBEDTLS_PSA_KEY_SLOT_COUNT (15 + 1 + SL_PSA_KEY_USER_SLOT_COUNT)
+#define SL_PSA_ITS_MAX_FILES (1 + SL_PSA_ITS_USER_MAX_FILES)
diff --git a/src/platform/silabs/SiWx917/wifi/dhcp_client.cpp b/src/platform/silabs/SiWx917/wifi/dhcp_client.cpp
new file mode 100644
index 0000000..15c6785
--- /dev/null
+++ b/src/platform/silabs/SiWx917/wifi/dhcp_client.cpp
@@ -0,0 +1,149 @@
+/*
+ *
+ *    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 LWIP_IPV4 && LWIP_DHCP
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "em_bus.h"
+#include "em_cmu.h"
+#include "em_gpio.h"
+#include "em_ldma.h"
+#include "em_usart.h"
+
+#include "dhcp_client.h"
+#include "lwip/dhcp.h"
+#include "wfx_host_events.h"
+#include "wifi_config.h"
+
+#include "AppConfig.h"
+#include "FreeRTOS.h"
+#include "event_groups.h"
+
+#define MAX_DHCP_TRIES 4
+#define NETIF_IPV4_ADDRESS(X, Y) (((X) >> (8 * Y)) & 0xFF)
+
+/* Station IP address */
+uint8_t sta_ip_addr0      = STA_IP_ADDR0_DEFAULT;
+uint8_t sta_ip_addr1      = STA_IP_ADDR1_DEFAULT;
+uint8_t sta_ip_addr2      = STA_IP_ADDR2_DEFAULT;
+uint8_t sta_ip_addr3      = STA_IP_ADDR3_DEFAULT;
+uint8_t sta_netmask_addr0 = STA_NETMASK_ADDR0_DEFAULT;
+uint8_t sta_netmask_addr1 = STA_NETMASK_ADDR1_DEFAULT;
+uint8_t sta_netmask_addr2 = STA_NETMASK_ADDR2_DEFAULT;
+uint8_t sta_netmask_addr3 = STA_NETMASK_ADDR3_DEFAULT;
+uint8_t sta_gw_addr0      = STA_GW_ADDR0_DEFAULT;
+uint8_t sta_gw_addr1      = STA_GW_ADDR1_DEFAULT;
+uint8_t sta_gw_addr2      = STA_GW_ADDR2_DEFAULT;
+uint8_t sta_gw_addr3      = STA_GW_ADDR3_DEFAULT;
+
+/// Current DHCP state machine state.
+static volatile uint8_t dhcp_state = DHCP_OFF;
+
+/*****************************************************************************
+ * @fn  void dhcpclient_set_link_state(int link_up)
+ * @brief
+ * Notify DHCP client task about the wifi status
+ * @param link_up link status
+ * @return None
+ ******************************************************************************/
+void dhcpclient_set_link_state(int link_up)
+{
+    if (link_up)
+    {
+        dhcp_state = DHCP_START;
+        SILABS_LOG("DHCP: Starting");
+    }
+    else
+    {
+        /* Update DHCP state machine */
+        dhcp_state = DHCP_LINK_DOWN;
+    }
+}
+
+/**********************************************************************************
+ * @fn  uint8_t dhcpclient_poll(void *arg)
+ * @brief
+ * Don't need a task here. We get polled every 250ms
+ * @return  None
+ ************************************************************************************/
+uint8_t dhcpclient_poll(void * arg)
+{
+    struct netif * netif = (struct netif *) arg;
+    ip_addr_t ipaddr;
+    ip_addr_t netmask;
+    ip_addr_t gw;
+    struct dhcp * dhcp;
+
+    switch (dhcp_state)
+    {
+    case DHCP_START:
+        SILABS_LOG("DHCP: Wait addr");
+        ip_addr_set_zero_ip4(&netif->ip_addr);
+        ip_addr_set_zero_ip4(&netif->netmask);
+        ip_addr_set_zero_ip4(&netif->gw);
+        dhcp_start(netif);
+        dhcp_state = DHCP_WAIT_ADDRESS;
+        break;
+
+    case DHCP_WAIT_ADDRESS:
+        if (dhcp_supplied_address(netif))
+        {
+            dhcp_state = DHCP_ADDRESS_ASSIGNED;
+
+            uint64_t addr = netif->ip_addr.u_addr.ip4.addr;
+            SILABS_LOG("DHCP IP: %d.%d.%d.%d", NETIF_IPV4_ADDRESS(addr, 0), NETIF_IPV4_ADDRESS(addr, 1),
+                       NETIF_IPV4_ADDRESS(addr, 2), NETIF_IPV4_ADDRESS(addr, 3));
+        }
+        else
+        {
+            dhcp = (struct dhcp *) netif_get_client_data(netif, LWIP_NETIF_CLIENT_DATA_INDEX_DHCP);
+
+            /* DHCP timeout */
+            if (dhcp->tries > MAX_DHCP_TRIES)
+            {
+                dhcp_state = DHCP_TIMEOUT;
+
+                SILABS_LOG("*ERR*DHCP: Failed");
+                /* Stop DHCP */
+                dhcp_stop(netif);
+
+                /* TODO - I am not sure that this is best */
+                /* Static address used */
+                IP_ADDR4(&ipaddr, sta_ip_addr0, sta_ip_addr1, sta_ip_addr2, sta_ip_addr3);
+                IP_ADDR4(&netmask, sta_netmask_addr0, sta_netmask_addr1, sta_netmask_addr2, sta_netmask_addr3);
+                IP_ADDR4(&gw, sta_gw_addr0, sta_gw_addr1, sta_gw_addr2, sta_gw_addr3);
+                netif_set_addr(netif, ip_2_ip4(&ipaddr), ip_2_ip4(&netmask), ip_2_ip4(&gw));
+            }
+        }
+        break;
+
+    case DHCP_LINK_DOWN:
+        /* Stop DHCP */
+        SILABS_LOG("*ERR*DHCP Link down");
+        dhcp_stop(netif);
+        dhcp_state = DHCP_OFF;
+        break;
+    default:
+        break;
+    }
+    return dhcp_state;
+}
+
+#endif /* LWIP_IPV4 && LWIP_DHCP */
diff --git a/src/platform/silabs/SiWx917/wifi/dhcp_client.h b/src/platform/silabs/SiWx917/wifi/dhcp_client.h
new file mode 100644
index 0000000..3040f71
--- /dev/null
+++ b/src/platform/silabs/SiWx917/wifi/dhcp_client.h
@@ -0,0 +1,45 @@
+/*
+ *
+ *    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 LWIP_IPV4 && LWIP_DHCP
+
+#pragma once
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+// DHCP client states
+#define DHCP_OFF (uint8_t) 0
+#define DHCP_START (uint8_t) 1
+#define DHCP_WAIT_ADDRESS (uint8_t) 2
+#define DHCP_ADDRESS_ASSIGNED (uint8_t) 3
+#define DHCP_TIMEOUT (uint8_t) 4
+#define DHCP_LINK_DOWN (uint8_t) 5
+
+/*****************************************************************************
+ * @fn  void dhcpclient_set_link_state(int link_up)
+ * @brief
+ * Notify DHCP client task about the wifi status
+ * @param link_up link status
+ ******************************************************************************/
+void dhcpclient_set_link_state(int link_up);
+uint8_t dhcpclient_poll(void * arg);
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* LWIP_IPV4 && LWIP_DHCP */
diff --git a/src/platform/silabs/SiWx917/wifi/ethernetif.cpp b/src/platform/silabs/SiWx917/wifi/ethernetif.cpp
new file mode 100644
index 0000000..d1fcc01
--- /dev/null
+++ b/src/platform/silabs/SiWx917/wifi/ethernetif.cpp
@@ -0,0 +1,461 @@
+/*
+ *
+ *    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.
+ */
+
+/* Includes */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "em_bus.h"
+#include "em_cmu.h"
+#include "em_gpio.h"
+#include "em_ldma.h"
+#include "em_usart.h"
+
+#ifndef WF200_WIFI
+#include "FreeRTOS.h"
+#include "event_groups.h"
+#include "task.h"
+#endif
+
+#include "wfx_host_events.h"
+#include "wifi_config.h"
+#ifdef WF200_WIFI
+#include "sl_wfx.h"
+#endif
+/* LwIP includes. */
+#include "ethernetif.h"
+#include "lwip/ethip6.h"
+#include "lwip/timeouts.h"
+#include "netif/etharp.h"
+
+#ifndef SILABS_LOG
+extern "C" {
+void efr32Log(const char * aFormat, ...);
+#define SILABS_LOG(...) efr32Log(__VA_ARGS__);
+}
+#endif
+
+StaticSemaphore_t xEthernetIfSemaBuffer;
+
+/*****************************************************************************
+ * Defines
+ ******************************************************************************/
+#define STATION_NETIF0 's'
+#define STATION_NETIF1 't'
+
+#define LWIP_FRAME_ALIGNMENT 60
+
+uint32_t gOverrunCount = 0;
+
+/*****************************************************************************
+ * Variables
+ ******************************************************************************/
+
+/*****************************************************************************
+ * @fn static void low_level_init(struct netif *netif)
+ * @brief
+ *    Initializes the hardware parameters. Called from ethernetif_init().
+ *
+ * @param[in] netif: the already initialized lwip network interface structure
+ *
+ * @return
+ *    None
+ ******************************************************************************/
+static void low_level_init(struct netif * netif)
+{
+    /* set netif MAC hardware address length */
+    netif->hwaddr_len = ETH_HWADDR_LEN;
+
+    /* Set netif MAC hardware address */
+    sl_wfx_mac_address_t mac_addr;
+
+    wfx_get_wifi_mac_addr(SL_WFX_STA_INTERFACE, &mac_addr);
+
+    netif->hwaddr[0] = mac_addr.octet[0];
+    netif->hwaddr[1] = mac_addr.octet[1];
+    netif->hwaddr[2] = mac_addr.octet[2];
+    netif->hwaddr[3] = mac_addr.octet[3];
+    netif->hwaddr[4] = mac_addr.octet[4];
+    netif->hwaddr[5] = mac_addr.octet[5];
+
+    /* Set netif maximum transfer unit */
+    netif->mtu = 1500;
+
+    /* Accept broadcast address and ARP traffic */
+    netif->flags |= NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP | NETIF_FLAG_IGMP;
+
+#if LWIP_IPV6_MLD
+    netif->flags |= NETIF_FLAG_MLD6;
+#endif /* LWIP_IPV6_MLD */
+}
+
+/********************************************************************************
+ * @fn  static void low_level_input(struct netif *netif, uint8_t *b, uint16_t len)
+ * @brief
+ * Make PBUF out of a linear buffer - that can be fed into lwip
+ * @param[in]  netif: the already initialized lwip network interface structure
+ * @param[in]  len: length
+ * @return
+ *     None
+ ************************************************************************************/
+static void low_level_input(struct netif * netif, uint8_t * b, uint16_t len)
+{
+    struct pbuf *p, *q;
+    uint32_t bufferoffset;
+
+    if (len <= 0)
+    {
+        return;
+    }
+    if (len < LWIP_FRAME_ALIGNMENT)
+    { /* 60 : LWIP frame alignment */
+        len = LWIP_FRAME_ALIGNMENT;
+    }
+
+    /* Drop packets originated from the same interface and is not destined for the said interface */
+    const uint8_t * src_mac = b + netif->hwaddr_len;
+    const uint8_t * dst_mac = b;
+
+    if (!(ip6_addr_ispreferred(netif_ip6_addr_state(netif, 0))) && (memcmp(netif->hwaddr, src_mac, netif->hwaddr_len) == 0) &&
+        (memcmp(netif->hwaddr, dst_mac, netif->hwaddr_len) != 0))
+    {
+#ifdef WIFI_DEBUG_ENABLED
+        SILABS_LOG("%s: DROP, [%02x:%02x:%02x:%02x:%02x:%02x]<-[%02x:%02x:%02x:%02x:%02x:%02x] type=%02x%02x", __func__,
+
+                   dst_mac[0], dst_mac[1], dst_mac[2], dst_mac[3], dst_mac[4], dst_mac[5],
+
+                   src_mac[0], src_mac[1], src_mac[2], src_mac[3], src_mac[4], src_mac[5],
+
+                   b[12], b[13]);
+#endif
+        return;
+    }
+
+    /* We allocate a pbuf chain of pbufs from the Lwip buffer pool
+     * and copy the data to the pbuf chain
+     */
+    if ((p = pbuf_alloc(PBUF_RAW, len, PBUF_POOL)) != STRUCT_PBUF)
+    {
+        for (q = p, bufferoffset = 0; q != NULL; q = q->next)
+        {
+            memcpy((uint8_t *) q->payload, (uint8_t *) b + bufferoffset, q->len);
+            bufferoffset += q->len;
+        }
+#ifdef WIFI_DEBUG_ENABLED
+        SILABS_LOG("%s: ACCEPT %d, [%02x:%02x:%02x:%02x:%02x:%02x]<-[%02x:%02x:%02x:%02x:%02x:%02x] type=%02x%02x", __func__,
+                   bufferoffset,
+
+                   dst_mac[0], dst_mac[1], dst_mac[2], dst_mac[3], dst_mac[4], dst_mac[5],
+
+                   src_mac[0], src_mac[1], src_mac[2], src_mac[3], src_mac[4], src_mac[5],
+
+                   b[12], b[13]);
+#endif
+
+        if (netif->input(p, netif) != ERR_OK)
+        {
+            gOverrunCount++;
+            SILABS_LOG("overrun count entering when fail to alloc value %d", gOverrunCount);
+            pbuf_free(p);
+        }
+    }
+    else
+    {
+        gOverrunCount++;
+        SILABS_LOG("overrun count entering when fail to alloc value %d", gOverrunCount);
+    }
+}
+
+/*****************************************************************************
+ *  @fn  static err_t low_level_output(struct netif *netif, struct pbuf *p)
+ *  @brief
+ *    This function should does the actual transmission of the packet(s).
+ *    The packet is contained in the pbuf that is passed to the function.
+ *    This pbuf might be chained.
+ *
+ * @param[in] netif: the lwip network interface structure
+ *
+ * @param[in] p: the packet to send
+ *
+ * @return
+ *    ERR_OK if successful
+ ******************************************************************************/
+#ifdef WF200_WIFI
+static err_t low_level_output(struct netif * netif, struct pbuf * p)
+{
+    struct pbuf * q;
+    sl_wfx_send_frame_req_t * tx_buffer;
+    uint8_t * buffer;
+    uint32_t framelength, asize;
+    uint32_t bufferoffset;
+    uint32_t padding;
+    sl_status_t result;
+
+    for (q = p, framelength = 0; q != NULL; q = q->next)
+    {
+        framelength += q->len;
+    }
+    if (framelength < LWIP_FRAME_ALIGNMENT)
+    { /* 60 : Frame alignment for LWIP */
+        padding = LWIP_FRAME_ALIGNMENT - framelength;
+    }
+    else
+    {
+        padding = 0;
+    }
+
+    /* choose padding of 64 */
+    asize = SL_WFX_ROUND_UP(framelength + padding, 64) + sizeof(sl_wfx_send_frame_req_t);
+    // 12 is size of other data in buffer struct, user shouldn't have to care about this?
+    if (sl_wfx_host_allocate_buffer((void **) &tx_buffer, SL_WFX_TX_FRAME_BUFFER, asize) != SL_STATUS_OK)
+    {
+        SILABS_LOG("*ERR*EN-Out: No mem frame len=%d", framelength);
+        gOverrunCount++;
+        SILABS_LOG("overrun count exiting when faied to alloc value %d", gOverrunCount);
+        return ERR_MEM;
+    }
+    buffer = tx_buffer->body.packet_data;
+    /* copy frame from pbufs to driver buffers */
+    for (q = p, bufferoffset = 0; q != NULL; q = q->next)
+    {
+        /* Get bytes in current lwIP buffer */
+        memcpy((uint8_t *) ((uint8_t *) buffer + bufferoffset), (uint8_t *) ((uint8_t *) q->payload), q->len);
+        bufferoffset += q->len;
+    }
+    /* No requirement to do this - but we should for security */
+    if (padding)
+    {
+        memset(buffer + bufferoffset, 0, padding);
+        framelength += padding;
+    }
+    /* transmit */
+    int i  = 0;
+    result = SL_STATUS_FAIL;
+
+#ifdef WIFI_DEBUG_ENABLED
+    SILABS_LOG("WF200: Out %d", (int) framelength);
+#endif
+
+    /* send the generated frame over Wifi network */
+    while ((result != SL_STATUS_OK) && (i++ < 10))
+    {
+        result = sl_wfx_send_ethernet_frame(tx_buffer, framelength, SL_WFX_STA_INTERFACE, PRIORITY_0);
+    }
+    sl_wfx_host_free_buffer(tx_buffer, SL_WFX_TX_FRAME_BUFFER);
+
+    if (result != SL_STATUS_OK)
+    {
+        SILABS_LOG("*ERR*Send enet %d", (int) framelength);
+        return ERR_IF;
+    }
+    return ERR_OK;
+}
+
+/*****************************************************************************
+ * @fn   void sl_wfx_host_received_frame_callback(sl_wfx_received_ind_t *rx_buffer)
+ * @brief
+ *    This function implements the wf200 received frame callback.
+ *    Called from the context of the bus_task (not ISR)
+ *
+ * @param[in] rx_buffer: the ethernet frame received by the wf200
+ *
+ * @return
+ *    None
+ ******************************************************************************/
+void sl_wfx_host_received_frame_callback(sl_wfx_received_ind_t * rx_buffer)
+{
+    struct netif * netif;
+
+    /* Check packet interface to send to AP or STA interface */
+    if ((rx_buffer->header.info & SL_WFX_MSG_INFO_INTERFACE_MASK) == (SL_WFX_STA_INTERFACE << SL_WFX_MSG_INFO_INTERFACE_OFFSET))
+    {
+
+        /* Send received frame to station interface */
+        if ((netif = wfx_get_netif(SL_WFX_STA_INTERFACE)) != NULL)
+        {
+            uint8_t * buffer;
+            uint16_t len;
+
+            len    = rx_buffer->body.frame_length;
+            buffer = (uint8_t *) &(rx_buffer->body.frame[rx_buffer->body.frame_padding]);
+
+#ifdef WIFI_DEBUG_ENABLED
+            SILABS_LOG("WF200: In %d", (int) len);
+#endif
+
+            low_level_input(netif, buffer, len);
+        }
+        else
+        {
+#ifdef WIFI_DEBUG_ENABLED
+            SILABS_LOG("WF200: NO-INTF");
+#endif
+        }
+    }
+    else
+    {
+#ifdef WIFI_DEBUG_ENABLED
+        SILABS_LOG("WF200: Invalid frame IN");
+#endif
+    }
+}
+
+#else /* For RS911x - using LWIP */
+static SemaphoreHandle_t ethout_sem;
+/*****************************************************************************
+ *  @fn  static err_t low_level_output(struct netif *netif, struct pbuf *p)
+ *  @brief
+ *    This function is called from LWIP task when LWIP stack
+ *    has some data to be forwarded over WiFi Network
+ *
+ * @param[in] netif: lwip network interface
+ *
+ * @param[in] p: the packet to send
+ *
+ * @return
+ *    ERR_OK if successful
+ ******************************************************************************/
+static err_t low_level_output(struct netif * netif, struct pbuf * p)
+{
+    void * rsipkt;
+    struct pbuf * q;
+    uint16_t framelength;
+
+    if (xSemaphoreTake(ethout_sem, portMAX_DELAY) != pdTRUE)
+    {
+        return ERR_IF;
+    }
+#ifdef WIFI_DEBUG_ENABLED
+    SILABS_LOG("EN-RSI: Output");
+#endif
+    if ((netif->flags & (NETIF_FLAG_LINK_UP | NETIF_FLAG_UP)) != (NETIF_FLAG_LINK_UP | NETIF_FLAG_UP))
+    {
+        SILABS_LOG("EN-RSI:NOT UP");
+        xSemaphoreGive(ethout_sem);
+        return ERR_IF;
+    }
+    /* Confirm if packet is allocated */
+    rsipkt = wfx_rsi_alloc_pkt();
+    if (!rsipkt)
+    {
+        SILABS_LOG("EN-RSI:No buf");
+        xSemaphoreGive(ethout_sem);
+        return ERR_IF;
+    }
+
+#ifdef WIFI_DEBUG_ENABLED
+    uint8_t * b = (uint8_t *) p->payload;
+    SILABS_LOG("EN-RSI: Out [%02x:%02x:%02x:%02x:%02x:%02x][%02x:%02x:%02x:%02x:%02x:%02x]type=%02x%02x", b[0], b[1], b[2], b[3],
+               b[4], b[5], b[6], b[7], b[8], b[9], b[10], b[11], b[12], b[13]);
+#endif
+    /* Generate the packet */
+    for (q = p, framelength = 0; q != NULL; q = q->next)
+    {
+        wfx_rsi_pkt_add_data(rsipkt, (uint8_t *) (q->payload), (uint16_t) q->len, framelength);
+        framelength += q->len;
+    }
+    if (framelength < LWIP_FRAME_ALIGNMENT)
+    {
+        /* Add junk data to the end for frame alignment if framelength is less than 60 */
+        wfx_rsi_pkt_add_data(rsipkt, (uint8_t *) (p->payload), LWIP_FRAME_ALIGNMENT - framelength, framelength);
+    }
+#ifdef WIFI_DEBUG_ENABLED
+    SILABS_LOG("EN-RSI: Sending %d", framelength);
+#endif
+
+    /* forward the generated packet to RSI to
+     * send the data over wifi network
+     */
+    if (wfx_rsi_send_data(rsipkt, framelength))
+    {
+        SILABS_LOG("*ERR*EN-RSI:Send fail");
+        xSemaphoreGive(ethout_sem);
+        return ERR_IF;
+    }
+
+#ifdef WIFI_DEBUG_ENABLED
+    SILABS_LOG("EN-RSI:Xmit %d", framelength);
+#endif
+    xSemaphoreGive(ethout_sem);
+
+    return ERR_OK;
+}
+
+/*****************************************************************************
+ *  @fn  void wfx_host_received_sta_frame_cb(uint8_t *buf, int len)
+ *  @brief
+ *    host received frame cb
+ *
+ * @param[in] buf: buffer
+ *
+ * @param[in] len: length
+ *
+ * @return
+ *    None
+ ******************************************************************************/
+void wfx_host_received_sta_frame_cb(uint8_t * buf, int len)
+{
+    struct netif * ifp;
+
+    /* get the network interface for STATION interface,
+     * and forward the received frame buffer to LWIP
+     */
+    if ((ifp = wfx_get_netif(SL_WFX_STA_INTERFACE)) != (struct netif *) 0)
+    {
+        low_level_input(ifp, buf, len);
+    }
+}
+
+#endif /* RS911x - with LWIP */
+
+/*****************************************************************************
+ *  @fn  err_t sta_ethernetif_init(struct netif *netif)
+ *  @brief
+ *    sta ethernet if initialization
+ *
+ * @param[in] netif: the lwip network interface structure
+ *
+ * @return
+ *    ERR_OK if successful
+ ******************************************************************************/
+err_t sta_ethernetif_init(struct netif * netif)
+{
+    LWIP_ASSERT("netif != NULL", (netif != NULL));
+
+    /* Set the netif name to identify the interface */
+    netif->name[0] = STATION_NETIF0;
+    netif->name[1] = STATION_NETIF1;
+
+#if LWIP_IPV4 && LWIP_ARP
+    netif->output = etharp_output;
+#endif /* #if LWIP_IPV4 && LWIP_ARP */
+#if LWIP_IPV6 && LWIP_ETHERNET
+    netif->output_ip6 = ethip6_output;
+#endif /* LWIP_IPV6 && LWIP_ETHERNET */
+    netif->linkoutput = low_level_output;
+
+    /* initialize the hardware */
+    low_level_init(netif);
+#ifndef WF200_WIFI
+    /* Need single output only */
+    ethout_sem = xSemaphoreCreateBinaryStatic(&xEthernetIfSemaBuffer);
+    xSemaphoreGive(ethout_sem);
+#endif
+    return ERR_OK;
+}
diff --git a/src/platform/silabs/SiWx917/wifi/ethernetif.h b/src/platform/silabs/SiWx917/wifi/ethernetif.h
new file mode 100644
index 0000000..dfea1ea
--- /dev/null
+++ b/src/platform/silabs/SiWx917/wifi/ethernetif.h
@@ -0,0 +1,52 @@
+/*
+ *
+ *    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 "lwip/err.h"
+#include "lwip/netif.h"
+#ifdef __cplusplus
+extern "C" {
+#endif
+/***************************************************************************
+ * @fn  err_t sta_ethernetif_init(struct netif *netif)
+ * @brief
+ * Sets up the station network interface.
+ *
+ * @param netif the lwip network interface structure
+ * @returns ERR_OK if successful
+ ******************************************************************************/
+err_t sta_ethernetif_init(struct netif * netif);
+
+/***************************************************************************
+ * @fn err_t ap_ethernetif_init(struct netif *netif
+ * @brief
+ * Sets up the AP network interface.
+ *
+ * @param netif the lwip network interface structure
+ * @returns ERR_OK if successful
+ ******************************************************************************/
+err_t ap_ethernetif_init(struct netif * netif);
+
+#ifdef WF200_WIFI
+void sl_wfx_host_received_frame_callback(sl_wfx_received_ind_t * rx_buffer);
+#else
+void wfx_host_received_sta_frame_cb(uint8_t * buf, int len);
+#endif /* WF200_WIFI */
+#ifdef __cplusplus
+}
+#endif
diff --git a/src/platform/silabs/SiWx917/wifi/lwip_netif.cpp b/src/platform/silabs/SiWx917/wifi/lwip_netif.cpp
new file mode 100644
index 0000000..e19cf97
--- /dev/null
+++ b/src/platform/silabs/SiWx917/wifi/lwip_netif.cpp
@@ -0,0 +1,159 @@
+/*
+ *
+ *    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.
+ */
+
+#ifndef RS911X_SOCKETS
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "em_bus.h"
+#include "em_cmu.h"
+#include "em_gpio.h"
+#include "em_ldma.h"
+#include "em_usart.h"
+
+#include "wfx_host_events.h"
+#include "wifi_config.h"
+
+#include "AppConfig.h"
+#include "dhcp_client.h"
+#include "ethernetif.h"
+
+#include "FreeRTOS.h"
+#include "event_groups.h"
+#include "task.h"
+
+#include <platform/CHIPDeviceLayer.h>
+using namespace ::chip;
+using namespace ::chip::DeviceLayer;
+static struct netif sta_netif;
+
+#ifdef SL_WFX_CONFIG_SOFTAP
+static struct netif ap_netif;
+#endif
+
+/****************************************************************************
+ * @fn   static void netif_config(struct netif *sta_if, struct netif *ap_if)
+ * @brief
+ *      netif configuration
+ * @param[in]  sta_if:
+ * @param[in]  ap_if:
+ * @return None
+ *****************************************************************************/
+static void netif_config(struct netif * sta_if, struct netif * ap_if)
+{
+    if (sta_if != NULL)
+    {
+#if LWIP_IPV4
+        ip_addr_t sta_ipaddr;
+        ip_addr_t sta_netmask;
+        ip_addr_t sta_gw;
+
+        /* Initialize the Station information */
+        ip_addr_set_zero_ip4(&sta_ipaddr);
+        ip_addr_set_zero_ip4(&sta_netmask);
+        ip_addr_set_zero_ip4(&sta_gw);
+#endif /* LWIP_IPV4 */
+
+        /* Add station interfaces */
+        netif_add(sta_if,
+#if LWIP_IPV4
+                  (const ip4_addr_t *) &sta_ipaddr, (const ip4_addr_t *) &sta_netmask, (const ip4_addr_t *) &sta_gw,
+#endif /* LWIP_IPV4 */
+                  NULL, &sta_ethernetif_init, &tcpip_input);
+
+        /* Registers the default network interface */
+        netif_set_default(sta_if);
+    }
+}
+
+/****************************************************************************
+ * @fn  void wfx_lwip_set_sta_link_up(void)
+ * @brief
+ * Set station link status to up.
+ * @param[in]  None
+ * @return None
+ *****************************************************************************/
+void wfx_lwip_set_sta_link_up(void)
+{
+    netifapi_netif_set_up(&sta_netif);
+    netifapi_netif_set_link_up(&sta_netif);
+#if LWIP_IPV4 && LWIP_DHCP
+    dhcpclient_set_link_state(LINK_UP);
+#endif /* LWIP_IPV4 && LWIP_DHCP */
+    /*
+     * Enable IPV6
+     */
+
+#if LWIP_IPV6_AUTOCONFIG
+    sta_netif.ip6_autoconfig_enabled = 1;
+#endif /* LWIP_IPV6_AUTOCONFIG */
+    netif_create_ip6_linklocal_address(&sta_netif, MAC_48_BIT_SET);
+}
+
+/***************************************************************************
+ * @fn  void wfx_lwip_set_sta_link_down(void)
+ * @brief
+ * Set station link status to down.
+ * @param[in] None
+ * @return None
+ *****************************************************************************/
+void wfx_lwip_set_sta_link_down(void)
+{
+#if LWIP_IPV4 && LWIP_DHCP
+    dhcpclient_set_link_state(LINK_DOWN);
+#endif /* LWIP_IPV4 && LWIP_DHCP */
+    netifapi_netif_set_link_down(&sta_netif);
+    netifapi_netif_set_down(&sta_netif);
+}
+
+/***************************************************************************
+ * @fn  void wfx_lwip_start(void)
+ * @brief
+ * Initialize the LwIP stack
+ * @param[in] None
+ * @return None
+ *****************************************************************************/
+void wfx_lwip_start(void)
+{
+    /* Initialize the LwIP stack */
+    netif_config(&sta_netif, NULL);
+}
+
+/***************************************************************************
+ * @fn   struct netif *wfx_get_netif(sl_wfx_interface_t interface)
+ * @brief
+ * get the netif
+ * @param[in] interface:
+ * @return None
+ *****************************************************************************/
+struct netif * wfx_get_netif(sl_wfx_interface_t interface)
+{
+    if (interface == SL_WFX_STA_INTERFACE)
+    {
+        return &sta_netif;
+    }
+#ifdef SL_WFX_CONFIG_SOFTAP
+    else if (interface == SL_WFX_SOFTAP_INTERFACE)
+    {
+        return &ap_netif;
+    }
+#endif
+    return (struct netif *) 0;
+}
+
+#endif /* RS911X_SOCKETS */
diff --git a/src/platform/silabs/SiWx917/wifi/wfx_host_events.h b/src/platform/silabs/SiWx917/wifi/wfx_host_events.h
new file mode 100644
index 0000000..5a7e861
--- /dev/null
+++ b/src/platform/silabs/SiWx917/wifi/wfx_host_events.h
@@ -0,0 +1,375 @@
+/*
+ *
+ *    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
+
+#ifdef WF200_WIFI
+#include "FreeRTOS.h"
+#include "event_groups.h"
+#include "semphr.h"
+#include "task.h"
+#include "timers.h"
+
+#include "sl_wfx_cmd_api.h"
+#include "sl_wfx_constants.h"
+
+typedef struct __attribute__((__packed__)) sl_wfx_get_counters_cnf_body_s
+{
+    uint32_t status;
+    uint16_t mib_id;
+    uint16_t length;
+    uint32_t rcpi;
+    uint32_t count_plcp_errors;
+    uint32_t count_fcs_errors;
+    uint32_t count_tx_packets;
+    uint32_t count_rx_packets;
+    uint32_t count_rx_packet_errors;
+    uint32_t count_rx_decryption_failures;
+    uint32_t count_rx_mic_failures;
+    uint32_t count_rx_no_key_failures;
+    uint32_t count_tx_multicast_frames;
+    uint32_t count_tx_frames_success;
+    uint32_t count_tx_frame_failures;
+    uint32_t count_tx_frames_retried;
+    uint32_t count_tx_frames_multi_retried;
+    uint32_t count_rx_frame_duplicates;
+    uint32_t count_rts_success;
+    uint32_t count_rts_failures;
+    uint32_t count_ack_failures;
+    uint32_t count_rx_multicast_frames;
+    uint32_t count_rx_frames_success;
+    uint32_t count_rx_cmacicv_errors;
+    uint32_t count_rx_cmac_replays;
+    uint32_t count_rx_mgmt_ccmp_replays;
+    uint32_t count_rx_bipmic_errors;
+    uint32_t count_rx_beacon;
+    uint32_t count_miss_beacon;
+    uint32_t reserved[15];
+} sl_wfx_get_counters_cnf_body_t;
+
+typedef struct __attribute__((__packed__)) sl_wfx_get_counters_cnf_s
+{
+    /** Common message header. */
+    sl_wfx_header_t header;
+    /** Confirmation message body. */
+    sl_wfx_get_counters_cnf_body_t body;
+} sl_wfx_get_counters_cnf_t;
+
+typedef struct __attribute__((__packed__)) sl_wfx_mib_req_body_s
+{
+    uint16_t mib_id; ///< ID of the MIB to be read.
+    uint16_t reserved;
+} sl_wfx_mib_req_body_t;
+
+typedef struct __attribute__((__packed__)) sl_wfx_header_mib_s
+{
+    uint16_t length; ///< Message length in bytes including this uint16_t.
+                     ///< Maximum value is 8188 but maximum Request size is FW dependent and reported in the
+                     ///< ::sl_wfx_startup_ind_body_t::size_inp_ch_buf.
+    uint8_t id;      ///< Contains the message Id indexed by sl_wfx_general_commands_ids_t or sl_wfx_message_ids_t.
+    uint8_t reserved : 1;
+    uint8_t interface : 2;
+    uint8_t seqnum : 3;
+    uint8_t encrypted : 2;
+} sl_wfx_header_mib_t;
+
+typedef struct __attribute__((__packed__)) sl_wfx_mib_req_s
+{
+    /** Common message header. */
+    sl_wfx_header_mib_t header;
+    /** Request message body. */
+    sl_wfx_mib_req_body_t body;
+} sl_wfx_mib_req_t;
+
+#else /* End WF200 else RS911x */
+
+#include "wfx_msgs.h"
+
+/* Wi-Fi events*/
+#define SL_WFX_STARTUP_IND_ID 1
+#define SL_WFX_CONNECT_IND_ID 2
+#define SL_WFX_DISCONNECT_IND_ID 3
+#define SL_WFX_SCAN_COMPLETE_ID 4
+#define WFX_RSI_SSID_SIZE 64
+
+#endif /* WF200 */
+
+#ifndef RS911X_SOCKETS
+/* LwIP includes. */
+#include "lwip/apps/httpd.h"
+#include "lwip/ip_addr.h"
+#include "lwip/netif.h"
+#include "lwip/netifapi.h"
+#include "lwip/tcpip.h"
+
+/* Wi-Fi bitmask events - for the task */
+#define SL_WFX_CONNECT (1 << 1)
+#define SL_WFX_DISCONNECT (1 << 2)
+#define SL_WFX_START_AP (1 << 3)
+#define SL_WFX_STOP_AP (1 << 4)
+#define SL_WFX_SCAN_START (1 << 5)
+#define SL_WFX_SCAN_COMPLETE (1 << 6)
+#define SL_WFX_RETRY_CONNECT (1 << 7)
+
+#endif /* RS911X_SOCKETS */
+
+#include "sl_status.h"
+
+#ifdef RS911X_WIFI
+#define WLAN_TASK_STACK_SIZE 1024
+#define WLAN_TASK_PRIORITY 1
+#define WLAN_DRIVER_TASK_PRIORITY 1
+#define MAX_JOIN_RETRIES_COUNT 5
+
+#else /* WF200 */
+#define WLAN_TASK_STACK_SIZE 1024
+#define WLAN_TASK_PRIORITY 1
+#define MAX_JOIN_RETRIES_COUNT 5
+#endif
+
+// WLAN related Macros
+#define ETH_FRAME 0
+#define CMP_SUCCESS 0
+#define BSSID_MAX_STR_LEN 6
+#define MAC_ADDRESS_FIRST_OCTET 6
+#define AP_START_SUCCESS 0
+#define BITS_TO_WAIT 0
+#define CONNECTION_STATUS_SUCCESS 1
+#define IP_STATUS_FAIL 0
+#define GET_IPV6_SUCCESS 1
+#define GET_IPV6_FAIL 0
+#define BEACON_1 0
+#define CHANNEL_LIST (const uint8_t *) 0
+#define CHANNEL_COUNT 0
+#define IE_DATA (const uint8_t *) 0
+#define IE_DATA_LENGTH 0
+#define BSSID_SCAN (const uint8_t *) 0
+#define CHANNEL_0 0
+#define PREVENT_ROAMING 1
+#define DISABLE_PMF_MODE 0
+#define STA_IP_FAIL 0
+#define IP_STATUS_SUCCESS 1
+#define ACTIVE_CHANNEL_TIME_100 100
+#define PASSIVE_CHANNEL_TIME_0 0
+#define PROBE_NUM_REQ_1 1
+
+#define PINOUT_CLEAR_STATUS 0
+#define TICKS_TO_WAIT_0 0
+#define TICKS_TO_WAIT_3 3
+#define TICKS_TO_WAIT_1 1
+#define TICKS_TO_WAIT_500 500
+
+// TASK and Interrupt Macros
+#define SUCCESS_STATUS 1
+#define LINK_UP 1
+#define LINK_DOWN 0
+#define MAC_48_BIT_SET 1
+#define STRUCT_PBUF (struct pbuf *) 0
+#define PRIORITY_0 0
+#define HEX_VALUE_FF 0XFF
+
+// Timer Delay
+#define MAX_XLEN 16
+#define MIN_XLEN 0
+#define PINOUT_CLEAR 0
+#define PINOUT_SET 1
+#define WFX_SPI_NVIC_PRIORITY 5
+#define WFX_GPIO_NVIC_PRIORITY 5
+#define CB_VALUE (DMADRV_Callback_t) 0
+
+/* TIMER_TICKS_TO_WAIT Specifies the time, in ticks, that the calling task should
+ * be held in the Blocked state to wait for the start command to be successfully
+ * sent to the timer command queue.
+ */
+#define TIMER_TICKS_TO_WAIT_0 0
+
+#define CONVERT_SEC_TO_MSEC 1000
+#define CONVERT_USEC_TO_MSEC (1 / 1000)
+
+#define RSI_RESPONSE_MAX_SIZE 28
+#define RSI_RESPONSE_HOLD_BUFF_SIZE 128
+#define RSI_DRIVER_STATUS 0
+#define OPER_MODE_0 0
+#define COEX_MODE_0 0
+#define RESP_BUFF_SIZE 6
+#define AP_CHANNEL_NO_0 0
+#define SCAN_BITMAP_OPTN_1 1
+#define IP_CONF_RSP_BUFF_LENGTH_4 4
+#define STATION 0
+#define BG_SCAN_RES_SIZE 500
+
+#define SPI_CONFIG_SUCCESS 0
+#define WPA3_SECURITY 3
+
+typedef enum
+{
+    WIFI_EVENT,
+    IP_EVENT,
+} wfx_event_base_t;
+
+typedef enum
+{
+    IP_EVENT_STA_GOT_IP,
+    IP_EVENT_GOT_IP6,
+    IP_EVENT_STA_LOST_IP,
+} ip_event_id_t;
+
+/* Note that these are same as RSI_security */
+typedef enum
+{
+    WFX_SEC_NONE           = 0,
+    WFX_SEC_WPA            = 1,
+    WFX_SEC_WPA2           = 2,
+    WFX_SEC_WEP            = 3,
+    WFX_SEC_WPA_EAP        = 4,
+    WFX_SEC_WPA2_EAP       = 5,
+    WFX_SEC_WPA_WPA2_MIXED = 6,
+    WFX_SEC_WPA_PMK        = 7,
+    WFX_SEC_WPA2_PMK       = 8,
+    WFX_SEC_WPS_PIN        = 9,
+    WFX_SEC_GEN_WPS_PIN    = 10,
+    WFX_SEC_PUSH_BTN       = 11,
+    WFX_SEC_WPA3           = 11,
+} wfx_sec_t;
+
+#define WPA3_SECURITY 3
+
+typedef struct
+{
+    char ssid[32 + 1];
+    char passkey[64 + 1];
+    uint8_t security;
+} wfx_wifi_provision_t;
+
+typedef enum
+{
+    WIFI_MODE_NULL = 0,
+    WIFI_MODE_STA,
+    WIFI_MODE_AP,
+    WIFI_MODE_APSTA,
+    WIFI_MODE_MAX,
+} wifi_mode_t;
+
+typedef struct wfx_wifi_scan_result
+{
+    char ssid[32 + 1];
+    uint8_t security;
+    uint8_t bssid[6];
+    uint8_t chan;
+    int16_t rssi; /* I suspect this is in dBm - so signed */
+} wfx_wifi_scan_result_t;
+
+typedef struct wfx_wifi_scan_ext
+{
+    uint32_t beacon_lost_count;
+    uint32_t beacon_rx_count;
+    uint32_t mcast_rx_count;
+    uint32_t mcast_tx_count;
+    uint32_t ucast_rx_count;
+    uint32_t ucast_tx_count;
+    uint32_t overrun_count;
+} wfx_wifi_scan_ext_t;
+
+#ifdef RS911X_WIFI
+/*
+ * This Sh%t is here to support WFXUtils - and the Matter stuff that uses it
+ * We took it from the SDK (for WF200)
+ */
+typedef enum
+{
+    SL_WFX_NOT_INIT                = 0,
+    SL_WFX_STARTED                 = 1,
+    SL_WFX_STA_INTERFACE_CONNECTED = 2,
+    SL_WFX_AP_INTERFACE_UP         = 3,
+    SL_WFX_SLEEPING                = 4,
+    SL_WFX_POWER_SAVE_ACTIVE       = 5,
+} sl_wfx_state_t;
+
+typedef enum
+{
+    SL_WFX_STA_INTERFACE    = 0, ///< Interface 0, linked to the station
+    SL_WFX_SOFTAP_INTERFACE = 1, ///< Interface 1, linked to the softap
+} sl_wfx_interface_t;
+
+#endif /* RS911X_WIFI */
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+void sl_wfx_host_gpio_init(void);
+sl_status_t wfx_wifi_start(void);
+void wfx_enable_sta_mode(void);
+sl_wfx_state_t wfx_get_wifi_state(void);
+void wfx_get_wifi_mac_addr(sl_wfx_interface_t interface, sl_wfx_mac_address_t * addr);
+void wfx_set_wifi_provision(wfx_wifi_provision_t * wifiConfig);
+bool wfx_get_wifi_provision(wfx_wifi_provision_t * wifiConfig);
+bool wfx_is_sta_provisioned(void);
+bool wfx_is_sta_mode_enabled(void);
+int32_t wfx_get_ap_info(wfx_wifi_scan_result_t * ap);
+int32_t wfx_get_ap_ext(wfx_wifi_scan_ext_t * extra_info);
+int32_t wfx_reset_counts();
+
+void wfx_clear_wifi_provision(void);
+sl_status_t wfx_connect_to_ap(void);
+void wfx_setup_ip6_link_local(sl_wfx_interface_t);
+bool wfx_is_sta_connected(void);
+sl_status_t wfx_sta_discon(void);
+#if CHIP_DEVICE_CONFIG_ENABLE_IPV4
+bool wfx_have_ipv4_addr(sl_wfx_interface_t);
+#endif /* CHIP_DEVICE_CONFIG_ENABLE_IPV4 */
+bool wfx_have_ipv6_addr(sl_wfx_interface_t);
+wifi_mode_t wfx_get_wifi_mode(void);
+bool wfx_start_scan(char * ssid, void (*scan_cb)(wfx_wifi_scan_result_t *)); /* true returned if successfully started */
+void wfx_cancel_scan(void);
+
+/*
+ * Call backs into the Matter Platform code
+ */
+void wfx_started_notify(void);
+void wfx_connected_notify(int32_t status, sl_wfx_mac_address_t * ap);
+void wfx_disconnected_notify(int32_t status);
+/* Implemented for LWIP */
+void wfx_host_received_sta_frame_cb(uint8_t * buf, int len);
+void wfx_lwip_set_sta_link_up(void);
+void wfx_lwip_set_sta_link_down(void);
+void wfx_lwip_start(void);
+struct netif * wfx_get_netif(sl_wfx_interface_t interface);
+#if CHIP_DEVICE_CONFIG_ENABLE_IPV4
+void wfx_dhcp_got_ipv4(uint32_t);
+#endif /* CHIP_DEVICE_CONFIG_ENABLE_IPV4 */
+bool wfx_hw_ready(void);
+#if CHIP_DEVICE_CONFIG_ENABLE_IPV4
+void wfx_ip_changed_notify(int got_ip);
+#endif /* CHIP_DEVICE_CONFIG_ENABLE_IPV4 */
+void wfx_ipv6_notify(int got_ip);
+
+#ifdef RS911X_WIFI
+/* RSI for LWIP */
+void * wfx_rsi_alloc_pkt(void);
+void wfx_rsi_pkt_add_data(void * p, uint8_t * buf, uint16_t len, uint16_t off);
+int32_t wfx_rsi_send_data(void * p, uint16_t len);
+#endif /* RS911X_WIFI */
+
+#ifdef WF200_WIFI
+void wfx_bus_start(void);
+sl_status_t get_all_counters(void);
+void sl_wfx_host_gpio_init(void);
+sl_status_t sl_wfx_host_process_event(sl_wfx_generic_message_t * event_payload);
+#endif
+#ifdef __cplusplus
+}
+#endif
diff --git a/src/platform/silabs/SiWx917/wifi/wfx_msgs.h b/src/platform/silabs/SiWx917/wifi/wfx_msgs.h
new file mode 100644
index 0000000..edf0aec
--- /dev/null
+++ b/src/platform/silabs/SiWx917/wifi/wfx_msgs.h
@@ -0,0 +1,182 @@
+/*
+ *
+ *    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.
+ */
+
+#ifndef _WFX_MSGS_H_
+#define _WFX_MSGS_H_
+/*
+ * Taken from sl_wfx firmware - so I can re-use.
+ * I need to do a better job than to use this stuff
+ * in the CPP files of Matter
+ */
+typedef struct
+{
+    uint8_t octet[6]; ///< Table to store a MAC address
+} sl_wfx_mac_address_t;
+/**
+ * @brief General Message header structure
+ *
+ */
+typedef struct __attribute__((__packed__)) sl_wfx_header_s
+{
+    uint16_t length; ///< Message length in bytes including this uint16_t.
+                     ///< Maximum value is 8188 but maximum Request size is FW dependent and reported in the
+                     ///< ::sl_wfx_startup_ind_body_t::size_inp_ch_buf.
+    uint8_t id;      ///< Contains the message Id indexed by sl_wfx_general_commands_ids_t or sl_wfx_message_ids_t.
+    uint8_t info;    ///< TODO comment missing
+} sl_wfx_header_t;
+
+/**
+ * @brief Generic message structure for all requests, confirmations and indications
+ *
+ */
+typedef struct __attribute__((__packed__)) sl_wfx_generic_message_s
+{
+    sl_wfx_header_t header; ///< 4 bytes header
+    uint8_t body[];         ///< variable size payload of the message
+} sl_wfx_generic_message_t;
+#define SL_WFX_OPN_SIZE 14
+#define SL_WFX_UID_SIZE 8
+#define SL_WFX_DISABLED_CHANNEL_LIST_SIZE 2
+#define SL_WFX_FIRMWARE_LABEL_SIZE 128
+/**
+ * @brief Startup Indication message.
+ * This is the first message sent to the host to confirm boot success.
+ * It gives detailed information on the HW and FW versions and capabilities
+ */
+typedef struct __attribute__((__packed__)) sl_wfx_startup_ind_body_s
+{
+    uint32_t
+        status; ///< Initialization status. A value of zero indicates the boot is completed successfully  (see enum sl_wfx_status_t)
+    uint16_t hardware_id; ///<=RO misc_read_reg7 register value
+#if 0                     /* Not used in RS911x for now - use stuff here for the port */
+  uint8_t  opn[SL_WFX_OPN_SIZE];                           ///<=OTP part_OPN
+  uint8_t  uid[SL_WFX_UID_SIZE];                           ///<=OTP UID
+  uint16_t num_inp_ch_bufs;                                ///<Number of buffers available for request messages.
+  uint16_t size_inp_ch_buf;                                ///<TX Buffer size in bytes=request message max size.
+  uint8_t  num_links_aP;                                   ///<number of STA that are supported in AP mode
+  uint8_t  num_interfaces;                                 ///<number of interfaces (WIFI link : STA or AP) that can be created by the user
+  uint8_t  mac_addr[2][SL_WFX_MAC_ADDR_SIZE];              ///<MAC addresses derived from OTP
+  uint8_t  api_version_minor;
+  uint8_t  api_version_major;
+  sl_wfx_capabilities_t capabilities;                      ///<List some FW options
+  uint8_t  firmware_build;
+  uint8_t  firmware_minor;
+  uint8_t  firmware_major;
+  uint8_t  firmware_type;                                  ///<See enum sl_wfx_fw_type_t
+  uint8_t  disabled_channel_list[SL_WFX_DISABLED_CHANNEL_LIST_SIZE]; ///<=OTP Disabled channel list info
+  sl_wfx_otp_regul_sel_mode_info_t regul_sel_mode_info;    ///<OTP region selection mode info
+  sl_wfx_otp_phy_info_t otp_phy_info;                      ///<info on OTP backoff tables used to enforce the different DFS regulations.
+  uint32_t supported_rate_mask;                            ///<A bit mask that indicates which rates are supported by the Physical layer. See enum api_rate_index.
+  uint8_t  firmware_label[SL_WFX_FIRMWARE_LABEL_SIZE];     ///<Null terminated text string describing the loaded FW.
+#else
+    uint8_t mac_addr[6];
+#endif
+} sl_wfx_startup_ind_body_t;
+
+typedef struct __attribute__((__packed__)) sl_wfx_startup_ind_s
+{
+    sl_wfx_header_t header;
+    sl_wfx_startup_ind_body_t body;
+} sl_wfx_startup_ind_t;
+/**
+ * @brief Indication message body for sl_wfx_connect_ind_t.
+ */
+typedef struct __attribute__((__packed__)) sl_wfx_connect_ind_body_s
+{
+    /**
+     * @brief Status of the connection request.
+     * @details <B>WFM_STATUS_SUCCESS</B>: the connection request was completed successfully.
+     *          <BR><B>any other value</B>: the connection request failed.
+     *          <BR>See sl_wfx_fmac_status_t for enumeration values.
+     */
+    uint32_t status;
+    /**
+     * @brief MAC address of the connected access point.
+     */
+    uint8_t mac[6];
+    /**
+     * @brief Channel of the connected access point.
+     * @details <B>1 - 13</B>: Channel number.
+     */
+    uint16_t channel;
+    /**
+     * @brief Beacon Interval of the connected access point.
+     */
+    uint8_t beacon_interval;
+    /**
+     * @brief DTIM period of the connected access point.
+     * @details <B>1 - 255</B>: DTIM period.
+     */
+    uint8_t dtim_period;
+    /**
+     * @brief Maximum PHY data rate supported by the connection.
+     * @details See sl_wfx_rate_index_t for enumeration values.
+     */
+    uint16_t max_phy_rate;
+} sl_wfx_connect_ind_body_t;
+
+/**
+ * @brief Indication message used to signal the completion of a connection operation.
+ * @details The device will send this indication to signal the connection request initiated
+ *          with sl_wfx_connect_req_t has been completed. The indication is also sent when
+ *          the device autonomously roams to another access point.
+ * @ingroup WFM_GROUP_MODE_IDLE
+ */
+typedef struct __attribute__((__packed__)) sl_wfx_connect_ind_s
+{
+    /** Common message header. */
+    sl_wfx_header_t header;
+    /** Indication message body. */
+    sl_wfx_connect_ind_body_t body;
+} sl_wfx_connect_ind_t;
+/**
+ * @brief Indication message body for sl_wfx_disconnect_ind_t.
+ */
+typedef struct __attribute__((__packed__)) sl_wfx_disconnect_ind_body_s
+{
+    /**
+     * @brief MAC address of the access point.
+     */
+    uint8_t mac[6];
+    /**
+     * @brief Reason for disconnection.
+     * @details <B>WFM_DISCONNECTED_REASON_UNSPECIFIED</B>: The device disconnected because of an internal error.
+     *          <BR><B>WFM_DISCONNECTED_REASON_AP_LOST</B>: The device lost the AP beacons for too long.
+     *          <BR><B>WFM_DISCONNECTED_REASON_REJECTED</B>: The device was disconnected by the AP.
+     *          <BR><B>WFM_DISCONNECTED_REASON_LEAVING_BSS</B>: Disconnection was requested through the device API.
+     *          <BR><B>WFM_DISCONNECTED_REASON_WPA_COUNTERMEASURES</B>: WPA countermeasures triggered a disconnection
+     *          <BR>See sl_wfx_disconnected_reason_t for enumeration values.
+     */
+    uint16_t reason;
+} sl_wfx_disconnect_ind_body_t;
+
+/**
+ * @brief Indication message used to signal the completion of a disconnection operation.
+ * @details The device will send this indication to signal the disconnection request initiated
+ *          with sl_wfx_disconnect_req_t has been completed. The indication is also sent when
+ *          the device has lost the connection to an access point and has been unable to regain it.
+ * @ingroup WFM_GROUP_MODE_STA
+ */
+typedef struct __attribute__((__packed__)) sl_wfx_disconnect_ind_s
+{
+    /** Common message header. */
+    sl_wfx_header_t header;
+    /** Indication message body. */
+    sl_wfx_disconnect_ind_body_t body;
+} sl_wfx_disconnect_ind_t;
+
+#endif /* _WFX_MSGS_H_ */
diff --git a/src/platform/silabs/SiWx917/wifi/wfx_notify.cpp b/src/platform/silabs/SiWx917/wifi/wfx_notify.cpp
new file mode 100644
index 0000000..9f681e7
--- /dev/null
+++ b/src/platform/silabs/SiWx917/wifi/wfx_notify.cpp
@@ -0,0 +1,189 @@
+/*
+ *
+ *    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 <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "em_bus.h"
+#include "em_cmu.h"
+#include "em_gpio.h"
+#include "em_ldma.h"
+#include "em_usart.h"
+#include "gpiointerrupt.h"
+
+#include "AppConfig.h"
+
+#include "FreeRTOS.h"
+#include "event_groups.h"
+#include "task.h"
+
+#include "wfx_host_events.h"
+
+#ifdef RS911X_WIFI
+#include "wfx_rsi.h"
+#endif
+
+#include <platform/CHIPDeviceLayer.h>
+//#include <app/server/Mdns.h>
+#include <app/server/Dnssd.h>
+#include <app/server/Server.h>
+
+using namespace ::chip;
+using namespace ::chip::DeviceLayer;
+
+/*
+ * Notifications to the upper-layer
+ * All done in the context of the RSI/WiFi task (rsi_if.c)
+ */
+
+/***********************************************************************************
+ * @fn  wfx_started_notify()
+ * @brief
+ *       Wifi device started notification
+ * @param[in]: None
+ * @return None
+ *************************************************************************************/
+void wfx_started_notify()
+{
+    sl_wfx_startup_ind_t evt;
+    sl_wfx_mac_address_t mac;
+
+    SILABS_LOG("%s: started.", __func__);
+
+    memset(&evt, 0, sizeof(evt));
+    evt.header.id     = SL_WFX_STARTUP_IND_ID;
+    evt.header.length = sizeof evt;
+    evt.body.status   = 0;
+    wfx_get_wifi_mac_addr(SL_WFX_STA_INTERFACE, &mac);
+    memcpy(&evt.body.mac_addr[0], &mac.octet[0], MAC_ADDRESS_FIRST_OCTET);
+
+    PlatformMgrImpl().HandleWFXSystemEvent(WIFI_EVENT, (sl_wfx_generic_message_t *) &evt);
+}
+
+/***********************************************************************************
+ * @fn  void wfx_connected_notify(int32_t status, sl_wfx_mac_address_t *ap)
+ * @brief
+ * For now we are not notifying anything other than AP Mac -
+ * Other stuff such as DTIM etc. may be required for later
+ * @param[in] status:
+ * @param[in] ap: access point
+ * @return None
+ *************************************************************************************/
+void wfx_connected_notify(int32_t status, sl_wfx_mac_address_t * ap)
+{
+    sl_wfx_connect_ind_t evt;
+
+    SILABS_LOG("%s: started.", __func__);
+
+    if (status != SUCCESS_STATUS)
+    {
+        SILABS_LOG("%s: error: failed status: %d.", __func__, status);
+        return;
+    }
+
+    SILABS_LOG("%s: connected.", __func__);
+
+    memset(&evt, 0, sizeof(evt));
+    evt.header.id     = SL_WFX_CONNECT_IND_ID;
+    evt.header.length = sizeof evt;
+
+#ifdef RS911X_WIFI
+    evt.body.channel = wfx_rsi.ap_chan;
+#endif
+    memcpy(&evt.body.mac[0], &ap->octet[0], MAC_ADDRESS_FIRST_OCTET);
+
+    PlatformMgrImpl().HandleWFXSystemEvent(WIFI_EVENT, (sl_wfx_generic_message_t *) &evt);
+}
+
+/**************************************************************************************
+ * @fn  void wfx_disconnected_notify(int32_t status)
+ * @brief
+ *    notification of disconnection
+ * @param[in] status:
+ * @return None
+ ********************************************************************************************/
+void wfx_disconnected_notify(int32_t status)
+{
+    sl_wfx_disconnect_ind_t evt;
+
+    SILABS_LOG("%s: started.", __func__);
+
+    memset(&evt, 0, sizeof(evt));
+    evt.header.id     = SL_WFX_DISCONNECT_IND_ID;
+    evt.header.length = sizeof evt;
+    evt.body.reason   = status;
+    PlatformMgrImpl().HandleWFXSystemEvent(WIFI_EVENT, (sl_wfx_generic_message_t *) &evt);
+}
+
+/**************************************************************************************
+ * @fn  void wfx_ipv6_notify(int got_ip)
+ * @brief
+ *      notification of ipv6
+ * @param[in]  got_ip:
+ * @return None
+ ********************************************************************************************/
+void wfx_ipv6_notify(int got_ip)
+{
+    sl_wfx_generic_message_t eventData;
+
+    SILABS_LOG("%s: started.", __func__);
+
+    memset(&eventData, 0, sizeof(eventData));
+    eventData.header.id     = got_ip ? IP_EVENT_GOT_IP6 : IP_EVENT_STA_LOST_IP;
+    eventData.header.length = sizeof(eventData.header);
+    PlatformMgrImpl().HandleWFXSystemEvent(IP_EVENT, &eventData);
+
+    /* So the other threads can run and have the connectivity OK */
+    if (got_ip)
+    {
+        /* Should remember this */
+        vTaskDelay(1);
+        chip::DeviceLayer::PlatformMgr().LockChipStack();
+        chip::app::DnssdServer::Instance().StartServer(/*Dnssd::CommissioningMode::kEnabledBasic*/);
+        chip::DeviceLayer::PlatformMgr().UnlockChipStack();
+    }
+}
+
+/**************************************************************************************
+ * @fn   void wfx_ip_changed_notify(int got_ip)
+ * @brief
+ *      notification of ip change
+ * @param[in]  got_ip:
+ * @return None
+ ********************************************************************************************/
+void wfx_ip_changed_notify(int got_ip)
+{
+    sl_wfx_generic_message_t eventData;
+
+    SILABS_LOG("%s: started.", __func__);
+
+    memset(&eventData, 0, sizeof(eventData));
+    eventData.header.id     = got_ip ? IP_EVENT_STA_GOT_IP : IP_EVENT_STA_LOST_IP;
+    eventData.header.length = sizeof(eventData.header);
+    PlatformMgrImpl().HandleWFXSystemEvent(IP_EVENT, &eventData);
+
+    /* So the other threads can run and have the connectivity OK */
+    if (got_ip)
+    {
+        /* Should remember this */
+        vTaskDelay(1);
+        chip::DeviceLayer::PlatformMgr().LockChipStack();
+        chip::app::DnssdServer::Instance().StartServer(/*Dnssd::CommissioningMode::kEnabledBasic*/);
+        chip::DeviceLayer::PlatformMgr().UnlockChipStack();
+    }
+}
diff --git a/src/platform/silabs/SiWx917/wifi/wifi_config.h b/src/platform/silabs/SiWx917/wifi/wifi_config.h
new file mode 100644
index 0000000..88ad34b
--- /dev/null
+++ b/src/platform/silabs/SiWx917/wifi/wifi_config.h
@@ -0,0 +1,71 @@
+/*
+ *
+ *    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.
+ */
+
+#ifndef DEMO_CONFIG_H
+#define DEMO_CONFIG_H
+
+#define USE_DHCP_CLIENT_DEFAULT 1 ///< If defined, DHCP is enabled, otherwise static address below is used
+
+/************************** Station Static Default ****************************/
+#define STA_IP_ADDR0_DEFAULT (uint8_t) 192 ///< Static IP: IP address value 0
+#define STA_IP_ADDR1_DEFAULT (uint8_t) 168 ///< Static IP: IP address value 1
+#define STA_IP_ADDR2_DEFAULT (uint8_t) 0   ///< Static IP: IP address value 2
+#define STA_IP_ADDR3_DEFAULT (uint8_t) 1   ///< Static IP: IP address value 3
+
+/*NETMASK*/
+#define STA_NETMASK_ADDR0_DEFAULT (uint8_t) 255 ///< Static IP: Netmask value 0
+#define STA_NETMASK_ADDR1_DEFAULT (uint8_t) 255 ///< Static IP: Netmask value 1
+#define STA_NETMASK_ADDR2_DEFAULT (uint8_t) 255 ///< Static IP: Netmask value 2
+#define STA_NETMASK_ADDR3_DEFAULT (uint8_t) 0   ///< Static IP: Netmask value 3
+
+/*Gateway Address*/
+#define STA_GW_ADDR0_DEFAULT (uint8_t) 0 ///< Static IP: Gateway value 0
+#define STA_GW_ADDR1_DEFAULT (uint8_t) 0 ///< Static IP: Gateway value 1
+#define STA_GW_ADDR2_DEFAULT (uint8_t) 0 ///< Static IP: Gateway value 2
+#define STA_GW_ADDR3_DEFAULT (uint8_t) 0 ///< Static IP: Gateway value 3
+
+/************************** Access Point Static Default ****************************/
+// #define AP_IP_ADDR0_DEFAULT (uint8_t) 10 ///< Static IP: IP address value 0
+// #define AP_IP_ADDR1_DEFAULT (uint8_t) 10 ///< Static IP: IP address value 1
+// #define AP_IP_ADDR2_DEFAULT (uint8_t) 0  ///< Static IP: IP address value 2
+// #define AP_IP_ADDR3_DEFAULT (uint8_t) 1  ///< Static IP: IP address value 3
+
+/*NETMASK*/
+// #define AP_NETMASK_ADDR0_DEFAULT (uint8_t) 255 ///< Static IP: Netmask value 0
+// #define AP_NETMASK_ADDR1_DEFAULT (uint8_t) 255 ///< Static IP: Netmask value 1
+// #define AP_NETMASK_ADDR2_DEFAULT (uint8_t) 255 ///< Static IP: Netmask value 2
+// #define AP_NETMASK_ADDR3_DEFAULT (uint8_t) 0   ///< Static IP: Netmask value 3
+
+/*Gateway Address*/
+// #define AP_GW_ADDR0_DEFAULT (uint8_t) 0 ///< Static IP: Gateway value 0
+// #define AP_GW_ADDR1_DEFAULT (uint8_t) 0 ///< Static IP: Gateway value 1
+// #define AP_GW_ADDR2_DEFAULT (uint8_t) 0 ///< Static IP: Gateway value 2
+// #define AP_GW_ADDR3_DEFAULT (uint8_t) 0 ///< Static IP: Gateway value 3
+
+#define WLAN_SSID_DEFAULT "AP_name"                      ///< wifi ssid for client mode
+#define WLAN_PASSKEY_DEFAULT "passkey"                   ///< wifi password for client mode
+#define WLAN_SECURITY_DEFAULT WFM_SECURITY_MODE_WPA2_PSK ///< wifi security mode for client mode:
+///< WFM_SECURITY_MODE_OPEN/WFM_SECURITY_MODE_WEP/WFM_SECURITY_MODE_WPA2_WPA1_PSK
+
+#define SOFTAP_SSID_DEFAULT "silabs_softap"                ///< wifi ssid for soft ap mode
+#define SOFTAP_PASSKEY_DEFAULT "changeme"                  ///< wifi password for soft ap mode
+#define SOFTAP_SECURITY_DEFAULT WFM_SECURITY_MODE_WPA2_PSK ///< wifi security for soft ap mode:
+///< WFM_SECURITY_MODE_OPEN/WFM_SECURITY_MODE_WEP/WFM_SECURITY_MODE_WPA2_WPA1_PSK
+
+#define SOFTAP_CHANNEL_DEFAULT 6 ///< wifi channel for soft ap
+
+#endif // DEMO_CONFIG_H
diff --git a/src/platform/silabs/SiWx917/wifi_args.gni b/src/platform/silabs/SiWx917/wifi_args.gni
new file mode 100644
index 0000000..73a6613
--- /dev/null
+++ b/src/platform/silabs/SiWx917/wifi_args.gni
@@ -0,0 +1,58 @@
+# Copyright (c) 2021 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/build.gni")
+import("//build_overrides/chip.gni")
+import("//build_overrides/efr32_sdk.gni")
+import("//build_overrides/pigweed.gni")
+
+import("${chip_root}/examples/platform/silabs/efr32/args.gni")
+import("${chip_root}/src/crypto/crypto.gni")
+
+# ARM architecture flags will be set based on silabs_family.
+arm_platform_config = "${efr32_sdk_build_root}/efr32_arm.gni"
+
+mbedtls_target = "${efr32_sdk_build_root}:efr32_sdk"
+
+# default to platform crypto implementation but allow commandline override
+if (chip_crypto == "") {
+  chip_crypto = "platform"
+}
+
+# Transitional CommissionableDataProvider not used anymore
+# examples/platform/efr32/EFR32DeviceDataProvider is now used.
+chip_use_transitional_commissionable_data_provider = false
+
+#lwip_platform = "external"
+lwip_platform = "efr32"
+lwip_ipv6 = true
+lwip_ipv4 = true
+lwip_api = true
+lwip_ethernet = true
+
+chip_device_platform = "efr32"
+chip_enable_openthread = false
+chip_inet_config_enable_ipv4 = true
+chip_inet_config_enable_dns_resolver = false
+chip_inet_config_enable_tcp_endpoint = true
+
+chip_build_tests = false
+chip_config_memory_management = "platform"
+chip_mdns = "minimal"
+chip_enable_pw_rpc = false
+
+pw_build_LINK_DEPS = [
+  "$dir_pw_assert:impl",
+  "$dir_pw_log:impl",
+]
diff --git a/third_party/silabs/SiWx917_sdk.gni b/third_party/silabs/SiWx917_sdk.gni
new file mode 100644
index 0000000..38359a7
--- /dev/null
+++ b/third_party/silabs/SiWx917_sdk.gni
@@ -0,0 +1,825 @@
+# 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/efr32_sdk.gni")
+import("//build_overrides/jlink.gni")
+import("//build_overrides/mbedtls.gni")
+
+import("${chip_root}/src/lib/lib.gni")
+import("silabs_board.gni")
+
+declare_args() {
+  # Location of the efr32 SDK.
+  efr32_sdk_root = "${chip_root}/third_party/silabs/gecko_sdk"
+  sdk_support_root = "${chip_root}/third_party/silabs/matter_support"
+
+  # Build openthread with prebuilt silabs lib
+  use_silabs_thread_lib = false
+  enable_openthread_cli = true
+
+  kvs_max_entries = 75
+  use_external_flash = true
+
+  # Use Silabs factory data provider example.
+  # Users can implement their own.
+  use_efr32_factory_data_provider = true
+
+  # Enable Segger System View
+  use_system_view = false
+}
+
+# Explorer Kit and MGM240L do not have external flash
+if (silabs_board == "BRD2703A" || silabs_board == "BRD4319A") {
+  use_external_flash = false
+}
+
+# Enable LEDs by default
+use_wstk_leds = true
+
+# Board does not support LEDs and Buttons at the same time
+if (silabs_board == "BRD4317A" || silabs_board == "BRD4316A" ||
+    silabs_board == "BRD4319A") {
+  use_wstk_leds = false
+}
+
+assert(efr32_sdk_root != "", "efr32_sdk_root must be specified")
+
+# Defines an efr32 SDK build target.
+#
+# Parameters:
+#   efr32_sdk_root - The location of the erf32 SDK.
+#   sources - The sources files to build.
+template("efr32_sdk") {
+  if (defined(invoker.efr32_sdk_root)) {
+    efr32_sdk_root = invoker.efr32_sdk_root
+  }
+
+  assert(efr32_sdk_root != "", "efr32_sdk_root must be specified")
+  use_wf200 = false
+  if (defined(invoker.use_wf200)) {
+    if (invoker.use_wf200) {
+      use_wf200 = true
+    }
+  }
+
+  sdk_target_name = target_name
+
+  config("${sdk_target_name}_config") {
+    include_dirs = []
+    libs = []
+    if (defined(invoker.include_dirs)) {
+      include_dirs += invoker.include_dirs
+    }
+
+    # Treat these includes as system includes, so warnings in them are not fatal.
+    _include_dirs = [
+      "${efr32_sdk_root}",
+      "${efr32_sdk_root}/hardware/kit/common/bsp",
+      "${efr32_sdk_root}/app/common/util/app_assert/",
+      "${efr32_sdk_root}/hardware/board/inc",
+      "${efr32_sdk_root}/hardware/driver/memlcd/inc",
+      "${efr32_sdk_root}/hardware/driver/memlcd/src/ls013b7dh03",
+      "${efr32_sdk_root}/platform/bootloader",
+      "${efr32_sdk_root}/platform/bootloader/config",
+      "${efr32_sdk_root}/platform/bootloader/config/s2/btl_interface",
+      "${efr32_sdk_root}/platform/bootloader/api",
+      "${efr32_sdk_root}/platform/CMSIS/Core/Include",
+      "${efr32_sdk_root}/platform/CMSIS/RTOS2/Include",
+      "${efr32_sdk_root}/platform/common/inc",
+      "${efr32_sdk_root}/platform/driver/button/inc",
+      "${efr32_sdk_root}/platform/emdrv/common/inc",
+      "${efr32_sdk_root}/platform/emdrv/gpiointerrupt/inc",
+      "${efr32_sdk_root}/platform/emdrv/dmadrv/config",
+      "${efr32_sdk_root}/platform/emdrv/dmadrv/inc",
+      "${efr32_sdk_root}/platform/emdrv/nvm3/inc",
+      "${efr32_sdk_root}/platform/emdrv/rtcdrv/inc",
+      "${efr32_sdk_root}/platform/emlib/inc",
+      "${efr32_sdk_root}/platform/halconfig/inc/hal-config",
+      "${efr32_sdk_root}/platform/peripheral/inc",
+      "${efr32_sdk_root}/platform/radio/rail_lib/common",
+      "${efr32_sdk_root}/platform/radio/rail_lib/chip/efr32",
+      "${efr32_sdk_root}/platform/radio/rail_lib/chip/efr32/rf/common/cortex",
+      "${efr32_sdk_root}/platform/radio/rail_lib/hal",
+      "${efr32_sdk_root}/platform/radio/rail_lib/hal/efr32",
+      "${efr32_sdk_root}/platform/radio/rail_lib/protocol/ieee802154",
+      "${efr32_sdk_root}/platform/radio/rail_lib/plugin/pa-conversions",
+      "${efr32_sdk_root}/platform/radio/rail_lib/plugin/rail_util_pti",
+      "${efr32_sdk_root}/platform/radio/rail_lib/plugin/rail_util_rf_path",
+      "${efr32_sdk_root}/platform/service/device_init/inc",
+      "${efr32_sdk_root}/platform/service/hfxo_manager/config/",
+      "${efr32_sdk_root}/platform/service/hfxo_manager/inc",
+      "${efr32_sdk_root}/platform/service/hfxo_manager/src",
+      "${efr32_sdk_root}/platform/service/mpu/inc",
+      "${efr32_sdk_root}/platform/service/power_manager/config/",
+      "${efr32_sdk_root}/platform/service/power_manager/inc/",
+      "${efr32_sdk_root}/platform/service/power_manager/src/",
+      "${efr32_sdk_root}/platform/service/sleeptimer/inc",
+      "${efr32_sdk_root}/platform/service/sleeptimer/config",
+      "${efr32_sdk_root}/platform/service/system/inc",
+      "${efr32_sdk_root}/platform/service/udelay/inc",
+      "${efr32_sdk_root}/platform/service/legacy_hal/inc",
+      "${efr32_sdk_root}/platform/service/token_manager/config",
+      "${efr32_sdk_root}/platform/service/token_manager/inc",
+      "${efr32_sdk_root}/platform/service/token_manager/test",
+      "${efr32_sdk_root}/platform/service/token_manager/test/include",
+      "${efr32_sdk_root}/platform/service/token_manager/test/stack/config",
+      "${efr32_sdk_root}/platform/service/token_manager/test/stack/include",
+      "${efr32_sdk_root}/platform/middleware/glib",
+      "${efr32_sdk_root}/platform/middleware/glib/glib",
+      "${efr32_sdk_root}/platform/middleware/glib/dmd",
+      "${efr32_sdk_root}/platform/base/hal/plugin/psstore",
+      "${efr32_sdk_root}/platform/base/hal/plugin/antenna",
+      "${efr32_sdk_root}/protocol/bluetooth/inc/",
+      "${efr32_sdk_root}/app/bluetooth/common/in_place_ota_dfu/",
+      "${efr32_sdk_root}/util/plugin/plugin-common/fem-control",
+      "${efr32_sdk_root}/util/silicon_labs/silabs_core/graphics",
+      "${efr32_sdk_root}/util/silicon_labs/silabs_core/memory_manager",
+      "${efr32_sdk_root}/util/third_party/crypto/mbedtls/include",
+      "${efr32_sdk_root}/util/third_party/crypto/mbedtls/include/psa",
+      "${efr32_sdk_root}/util/third_party/crypto/mbedtls/library",
+      "${efr32_sdk_root}/util/third_party/crypto/sl_component/sl_alt/include",
+      "${efr32_sdk_root}/util/third_party/crypto/sl_component/sl_protocol_crypto/src",
+      "${efr32_sdk_root}/util/third_party/crypto/sl_component/sl_mbedtls_support/inc",
+      "${efr32_sdk_root}/util/third_party/crypto/sl_component/sl_mbedtls_support/config/",
+      "${efr32_sdk_root}/util/third_party/crypto/sl_component/sl_psa_driver/inc",
+      "${efr32_sdk_root}/util/third_party/crypto/sl_component/sl_psa_driver/inc/public",
+      "${efr32_sdk_root}/util/third_party/crypto/sl_component/se_manager/inc",
+      "${efr32_sdk_root}/util/third_party/crypto/sl_component/se_manager/src/",
+      "${efr32_sdk_root}/util/third_party/freertos/cmsis/Include",
+      "${efr32_sdk_root}/util/third_party/freertos/kernel/include",
+      "${sdk_support_root}/matter/efr32/${silabs_family}/${silabs_board}/config",
+      "${sdk_support_root}/matter/efr32/${silabs_family}/${silabs_board}/autogen",
+    ]
+
+    # Note that we're setting the mbedTLS and PSA configuration files through a
+    # define. This means the build system by default does not pick up changes in
+    # the content of these, only when changing the filename itself.
+    # To fix this, these files are also manually depended upon in the source set
+    # declared in efr32_mbedtls_config further down this file.
+    defines = [
+      "MBEDTLS_CONFIG_FILE=\"efr32-chip-mbedtls-config.h\"",
+      "MBEDTLS_PSA_CRYPTO_CONFIG_FILE=\"efr32-mbedtls-psa-crypto-config.h\"",
+      "__STARTUP_CLEAR_BSS",
+      "HARD_FAULT_LOG_ENABLE",
+      "CORTEXM3_EFM32_MICRO",
+      "EFR32_LOG_ENABLED=1",
+      "NVM3_DEFAULT_NVM_SIZE=40960",
+      "NVM3_DEFAULT_MAX_OBJECT_SIZE=4092",
+      "KVS_MAX_ENTRIES=${kvs_max_entries}",
+      "EFR32_OPENTHREAD_API",
+      "PHY=EMBER_PHY_RAIL",
+      "CORTEXM3",
+      "MICRO=EMBER_MICRO_CORTEXM3_EFR32",
+      "PLAT=EMBER_PLATFORM_CORTEXM3",
+      "${silabs_mcu}=1",
+      "${silabs_board}=1",
+      "__HEAP_SIZE=0",
+      "SL_CATALOG_FREERTOS_KERNEL_PRESENT=1",
+      "MBEDTLS_THREADING_C=1",
+      "MBEDTLS_THREADING_ALT=1",
+      "SL_THREADING_ALT=1",
+      "SL_COMPONENT_CATALOG_PRESENT",
+      "PLATFORM_HEADER=\"platform-header.h\"",
+      "USE_NVM3=1",
+
+      #"__STACK_SIZE=0",
+    ]
+
+    if (use_system_view) {
+      _include_dirs += [
+        "${efr32_sdk_root}/util/third_party/segger/systemview/SEGGER",
+        "${efr32_sdk_root}/util/third_party/segger/systemview/Sample/FreeRTOSV10/Config/Cortex-M",
+        "${efr32_sdk_root}/util/third_party/segger/systemview/Sample/FreeRTOSV10",
+        "${efr32_sdk_root}/util/third_party/segger/systemview/Config/",
+      ]
+
+      defines += [ "SL_SYSTEM_VIEW=1" ]
+    }
+
+    defines += board_defines
+
+    if (use_wstk_leds) {
+      _include_dirs += [ "${efr32_sdk_root}/platform/driver/leddrv/inc" ]
+
+      defines += [ "ENABLE_WSTK_LEDS" ]
+    }
+
+    if (defined(invoker.enable_sleepy_device)) {
+      if (invoker.enable_sleepy_device) {
+        defines += [
+          "CHIP_DEVICE_CONFIG_ENABLE_SED=1",
+          "SL_CATALOG_POWER_MANAGER_PRESENT",
+          "SL_CATALOG_SLEEPTIMER_PRESENT",
+        ]
+      }
+    }
+
+    if (chip_build_libshell) {  # matter shell
+      defines += [
+        "ENABLE_CHIP_SHELL",
+        "OPENTHREAD_CONFIG_CLI_TRANSPORT=OT_CLI_TRANSPORT_CONSOLE",
+        "CHIP_DEVICE_CONFIG_THREAD_ENABLE_CLI=1",
+      ]
+    } else {
+      if (enable_openthread_cli) {  # ot-cli only
+        defines += [ "CHIP_DEVICE_CONFIG_THREAD_ENABLE_CLI=1" ]
+      }
+    }
+
+    # USART include files
+    if ((defined(invoker.chip_enable_pw_rpc) && invoker.chip_enable_pw_rpc) ||
+        chip_build_libshell || enable_openthread_cli ||
+        (defined(invoker.chip_enable_wifi) && invoker.chip_enable_wifi) ||
+        (defined(invoker.show_qr_code) && invoker.show_qr_code) ||
+        (defined(invoker.disable_lcd) && !invoker.disable_lcd) ||
+        (defined(invoker.use_external_flash) && use_external_flash)) {
+      defines += [ "CONFIG_ENABLE_UART" ]
+
+      if (defined(invoker.use_external_flash) && use_external_flash) {
+        defines += [ "CONFIG_USE_EXTERNAL_FLASH" ]
+
+        _include_dirs += [ "${efr32_sdk_root}/hardware/driver/mx25_flash_shutdown/inc/sl_mx25_flash_shutdown_usart" ]
+      }
+
+      _include_dirs += [
+        "${efr32_sdk_root}/platform/emdrv/uartdrv/inc",
+        "${efr32_sdk_root}/platform/emdrv/uartdrv/config",
+        "${efr32_sdk_root}/hardware/driver/memlcd/inc/memlcd_usart",
+      ]
+    }
+
+    if (silabs_family == "efr32mg12") {
+      _include_dirs += [
+        "${efr32_sdk_root}/platform/Device/SiliconLabs/EFR32MG12P/Include",
+        "${efr32_sdk_root}/platform/radio/rail_lib/chip/efr32/efr32xg1x",
+        "${efr32_sdk_root}/util/third_party/freertos/kernel/portable/GCC/ARM_CM4F",
+        "${efr32_sdk_root}/platform/radio/rail_lib/plugin/pa-conversions/efr32xg1x/config",
+        "${efr32_sdk_root}/platform/service/device_init/config/s1/",
+        "${efr32_sdk_root}/platform/emdrv/spidrv/inc",
+      ]
+
+      libs += [
+        "${sdk_support_root}/protocol/bluetooth/lib/EFR32MG12P/GCC/binapploader.o",
+        "${sdk_support_root}/protocol/bluetooth/lib/EFR32MG12P/GCC/libbluetooth.a",
+        "${sdk_support_root}/platform/radio/rail_lib/autogen/librail_release/librail_multiprotocol_efr32xg12_gcc_release.a",
+        "${sdk_support_root}/platform/emdrv/nvm3/lib/libnvm3_CM4_gcc.a",
+      ]
+
+      defines += [ "EFR32MG12" ]
+    } else if (silabs_family == "efr32mg21") {
+      _include_dirs += [
+        "${efr32_sdk_root}/platform/Device/SiliconLabs/EFR32MG21/Include",
+        "${efr32_sdk_root}/platform/radio/rail_lib/chip/efr32/efr32xg2x",
+        "${efr32_sdk_root}/util/third_party/freertos/kernel/portable/GCC/ARM_CM33_NTZ/non_secure",
+        "${efr32_sdk_root}/platform/radio/rail_lib/plugin/pa-conversions/efr32xg21",
+        "${efr32_sdk_root}/platform/radio/rail_lib/plugin/pa-conversions/efr32xg21/config",
+        "${efr32_sdk_root}/platform/service/device_init/config/s2/",
+      ]
+
+      libs += [
+        "${sdk_support_root}/protocol/bluetooth/lib/EFR32MG21/GCC/binapploader.o",
+        "${sdk_support_root}/protocol/bluetooth/lib/EFR32MG21/GCC/libbluetooth.a",
+        "${sdk_support_root}/platform/radio/rail_lib/autogen/librail_release/librail_multiprotocol_efr32xg21_gcc_release.a",
+        "${sdk_support_root}/platform/emdrv/nvm3/lib/libnvm3_CM33_gcc.a",
+      ]
+
+      defines += [
+        "EFR32MG21",
+        "EFR32_SERIES2_CONFIG1_MICRO",
+      ]
+    } else if (silabs_family == "efr32mg24") {
+      _include_dirs += [
+        "${efr32_sdk_root}/platform/Device/SiliconLabs/EFR32MG24/Include",
+        "${efr32_sdk_root}/platform/radio/rail_lib/chip/efr32/efr32xg2x",
+        "${efr32_sdk_root}/util/third_party/freertos/kernel/portable/GCC/ARM_CM33_NTZ/non_secure",
+        "${efr32_sdk_root}/platform/radio/rail_lib/plugin/pa-conversions/efr32xg24",
+        "${efr32_sdk_root}/platform/radio/rail_lib/plugin/pa-conversions/efr32xg24/config",
+        "${efr32_sdk_root}/platform/service/device_init/config/s2/",
+        "${efr32_sdk_root}/platform/emdrv/spidrv/inc",
+      ]
+
+      libs += [
+        "${sdk_support_root}/protocol/bluetooth/lib/EFR32MG24/GCC/libapploader.a",
+        "${sdk_support_root}/protocol/bluetooth/lib/EFR32MG24/GCC/libbluetooth.a",
+        "${sdk_support_root}/platform/radio/rail_lib/autogen/librail_release/librail_multiprotocol_efr32xg24_gcc_release.a",
+        "${sdk_support_root}/platform/emdrv/nvm3/lib/libnvm3_CM33_gcc.a",
+      ]
+
+      defines += [
+        "EFR32MG24",
+        "EFR32_SERIES2_CONFIG4_MICRO",
+      ]
+    } else if (silabs_family == "mgm24") {
+      _include_dirs += [
+        "${efr32_sdk_root}/platform/Device/SiliconLabs/MGM24/Include",
+        "${efr32_sdk_root}/platform/radio/rail_lib/chip/efr32/efr32xg2x",
+        "${efr32_sdk_root}/platform/radio/rail_lib/protocol/ble",
+        "${efr32_sdk_root}/platform/radio/rail_lib/protocol/ieee802154",
+        "${efr32_sdk_root}/util/third_party/freertos/kernel/portable/GCC/ARM_CM33_NTZ/non_secure",
+        "${efr32_sdk_root}/platform/radio/rail_lib/plugin/pa-conversions/efr32xg24",
+        "${efr32_sdk_root}/platform/radio/rail_lib/plugin/pa-conversions/efr32xg24/config",
+        "${efr32_sdk_root}/platform/service/device_init/config/s2/",
+      ]
+
+      libs += [
+        "${sdk_support_root}/protocol/bluetooth/lib/EFR32MG24/GCC/libapploader.a",
+        "${sdk_support_root}/protocol/bluetooth/lib/EFR32MG24/GCC/libbluetooth.a",
+        "${sdk_support_root}/platform/radio/rail_lib/autogen/librail_release/librail_multiprotocol_module_efr32xg24_gcc_release.a",
+        "${sdk_support_root}/platform/emdrv/nvm3/lib/libnvm3_CM33_gcc.a",
+      ]
+
+      if (silabs_mcu == "MGM240PB32VNA") {
+        libs += [ "${sdk_support_root}/platform/radio/rail_lib/autogen/librail_release/librail_config_mgm240pb32vna_gcc.a" ]
+      } else if (silabs_mcu == "MGM240PB22VNA") {
+        libs += [ "${sdk_support_root}/platform/radio/rail_lib/autogen/librail_release/librail_config_mgm240pb22vna_gcc.a" ]
+      } else if (silabs_mcu == "MGM240L022RNF") {
+        libs += [ "${sdk_support_root}/platform/radio/rail_lib/autogen/librail_release/librail_config_mgm240l022rnf_gcc.a" ]
+      }
+
+      defines += [
+        "MGM24",
+        "EFR32_SERIES2_CONFIG4_MICRO",
+      ]
+    }
+
+    if (use_wf200) {
+      _include_dirs += [
+        "${efr32_sdk_root}/platform/radio/wifi/wfx_fmac_driver",
+        "${efr32_sdk_root}/platform/radio/wifi/wfx_fmac_driver/bus",
+        "${efr32_sdk_root}/platform/radio/wifi/wfx_fmac_driver/firmware",
+        "${efr32_sdk_root}/platform/radio/wifi/wfx_fmac_driver/pds/brd8022a",
+        "${efr32_sdk_root}/platform/radio/wifi/wfx_fmac_driver/secure_link",
+      ]
+    }
+
+    cflags = []
+    foreach(include_dir, _include_dirs) {
+      cflags += [ "-isystem" + rebase_path(include_dir, root_build_dir) ]
+    }
+
+    cflags += [
+      "-Wno-maybe-uninitialized",
+      "-Wno-shadow",
+    ]
+
+    if (silabs_family == "efr32mg24" || silabs_family == "mgm24") {
+      cflags += [ "-mcmse" ]
+    }
+
+    if (defined(invoker.use_rs911x)) {
+      if (invoker.use_rs911x == true) {
+        #add compilation flags for rs991x build. This will be addressed directly in wiseconnect sdk in the next version release of that sdk
+        cflags += invoker.rs911x_cflags
+      }
+    }
+
+    if (defined(invoker.defines)) {
+      defines += invoker.defines
+    }
+  }
+
+  source_set("efr32_mbedtls_config") {
+    # We're setting the mbedTLS config flags here as the efr32_sdk target
+    # acts as the mbedTLS target for EFR32 builds. We need this for the build
+    # system to recompile mbedTLS (= the SDK) when the mbedTLS config gets
+    # edited.
+    sources = [
+      "${chip_root}/src/platform/silabs/EFR32/efr32-chip-mbedtls-config.h",
+      "${chip_root}/src/platform/silabs/EFR32/efr32-mbedtls-psa-crypto-config.h",
+    ]
+
+    public_deps = [ "${chip_root}/src/crypto:crypto_buildconfig" ]
+  }
+
+  source_set(sdk_target_name) {
+    sources = [
+      "${chip_root}/third_party/mbedtls/repo/include/mbedtls/platform.h",
+      "${efr32_sdk_root}/app/bluetooth/common/in_place_ota_dfu/sl_bt_in_place_ota_dfu.c",
+      "${efr32_sdk_root}/hardware/board/src/sl_board_control_gpio.c",
+      "${efr32_sdk_root}/hardware/board/src/sl_board_init.c",
+      "${efr32_sdk_root}/platform/CMSIS/RTOS2/Source/os_systick.c",
+      "${efr32_sdk_root}/platform/bootloader/api/btl_interface.c",
+      "${efr32_sdk_root}/platform/bootloader/api/btl_interface_storage.c",
+      "${efr32_sdk_root}/platform/bootloader/security/sha/crypto_sha.c",
+      "${efr32_sdk_root}/platform/common/src/sl_slist.c",
+      "${efr32_sdk_root}/platform/driver/button/src/sl_button.c",
+      "${efr32_sdk_root}/platform/driver/button/src/sl_simple_button.c",
+      "${efr32_sdk_root}/platform/emdrv/dmadrv/src/dmadrv.c",
+      "${efr32_sdk_root}/platform/emdrv/gpiointerrupt/src/gpiointerrupt.c",
+      "${efr32_sdk_root}/platform/emdrv/nvm3/src/nvm3_default.c",
+      "${efr32_sdk_root}/platform/emdrv/nvm3/src/nvm3_hal_flash.c",
+      "${efr32_sdk_root}/platform/emdrv/nvm3/src/nvm3_lock.c",
+      "${efr32_sdk_root}/platform/emlib/src/em_adc.c",
+      "${efr32_sdk_root}/platform/emlib/src/em_cmu.c",
+      "${efr32_sdk_root}/platform/emlib/src/em_core.c",
+      "${efr32_sdk_root}/platform/emlib/src/em_crypto.c",
+      "${efr32_sdk_root}/platform/emlib/src/em_emu.c",
+      "${efr32_sdk_root}/platform/emlib/src/em_gpio.c",
+      "${efr32_sdk_root}/platform/emlib/src/em_ldma.c",
+      "${efr32_sdk_root}/platform/emlib/src/em_msc.c",
+      "${efr32_sdk_root}/platform/emlib/src/em_prs.c",
+      "${efr32_sdk_root}/platform/emlib/src/em_rmu.c",
+      "${efr32_sdk_root}/platform/emlib/src/em_rtcc.c",
+      "${efr32_sdk_root}/platform/emlib/src/em_se.c",
+      "${efr32_sdk_root}/platform/emlib/src/em_system.c",
+      "${efr32_sdk_root}/platform/emlib/src/em_timer.c",
+      "${efr32_sdk_root}/platform/peripheral/src/peripheral_sysrtc.c",
+      "${efr32_sdk_root}/platform/radio/rail_lib/hal/efr32/hal_efr.c",
+      "${efr32_sdk_root}/platform/radio/rail_lib/plugin/pa-conversions/pa_conversions_efr32.c",
+      "${efr32_sdk_root}/platform/radio/rail_lib/plugin/rail_util_pti/sl_rail_util_pti.c",
+      "${efr32_sdk_root}/platform/service/device_init/src/sl_device_init_lfrco.c",
+      "${efr32_sdk_root}/platform/service/device_init/src/sl_device_init_nvic.c",
+      "${efr32_sdk_root}/platform/service/hfxo_manager/src/sl_hfxo_manager.c",
+      "${efr32_sdk_root}/platform/service/legacy_hal/src/token_legacy.c",
+      "${efr32_sdk_root}/platform/service/mpu/src/sl_mpu.c",
+      "${efr32_sdk_root}/platform/service/power_manager/src/sl_power_manager.c",
+      "${efr32_sdk_root}/platform/service/power_manager/src/sl_power_manager_debug.c",
+      "${efr32_sdk_root}/platform/service/power_manager/src/sl_power_manager_hal_s0_s1.c",
+      "${efr32_sdk_root}/platform/service/power_manager/src/sl_power_manager_hal_s2.c",
+      "${efr32_sdk_root}/platform/service/sleeptimer/src/sl_sleeptimer.c",
+      "${efr32_sdk_root}/platform/service/sleeptimer/src/sl_sleeptimer_hal_rtcc.c",
+      "${efr32_sdk_root}/platform/service/sleeptimer/src/sl_sleeptimer_hal_sysrtc.c",
+      "${efr32_sdk_root}/platform/service/system/src/sl_system_init.c",
+      "${efr32_sdk_root}/platform/service/system/src/sl_system_kernel.c",
+      "${efr32_sdk_root}/platform/service/system/src/sl_system_process_action.c",
+      "${efr32_sdk_root}/platform/service/token_manager/src/sl_token_def.c",
+      "${efr32_sdk_root}/platform/service/token_manager/src/sl_token_manager.c",
+      "${efr32_sdk_root}/platform/service/token_manager/src/sl_token_manufacturing.c",
+      "${efr32_sdk_root}/platform/service/udelay/src/sl_udelay.c",
+      "${efr32_sdk_root}/platform/service/udelay/src/sl_udelay_armv6m_gcc.S",
+      "${efr32_sdk_root}/protocol/bluetooth/src/sl_bt_mbedtls_context.c",
+      "${efr32_sdk_root}/protocol/bluetooth/src/sl_bt_rtos_adaptation.c",
+      "${efr32_sdk_root}/protocol/bluetooth/src/sl_bt_stack_init.c",
+      "${efr32_sdk_root}/protocol/bluetooth/src/sli_bt_advertiser_config.c",
+      "${efr32_sdk_root}/protocol/bluetooth/src/sli_bt_connection_config.c",
+      "${efr32_sdk_root}/util/silicon_labs/silabs_core/memory_manager/sl_malloc.c",
+      "${efr32_sdk_root}/util/third_party/crypto/mbedtls/library/aes.c",
+      "${efr32_sdk_root}/util/third_party/crypto/mbedtls/library/aesni.c",
+      "${efr32_sdk_root}/util/third_party/crypto/mbedtls/library/asn1parse.c",
+      "${efr32_sdk_root}/util/third_party/crypto/mbedtls/library/asn1write.c",
+      "${efr32_sdk_root}/util/third_party/crypto/mbedtls/library/base64.c",
+      "${efr32_sdk_root}/util/third_party/crypto/mbedtls/library/bignum.c",
+      "${efr32_sdk_root}/util/third_party/crypto/mbedtls/library/camellia.c",
+      "${efr32_sdk_root}/util/third_party/crypto/mbedtls/library/ccm.c",
+      "${efr32_sdk_root}/util/third_party/crypto/mbedtls/library/chacha20.c",
+      "${efr32_sdk_root}/util/third_party/crypto/mbedtls/library/chachapoly.c",
+      "${efr32_sdk_root}/util/third_party/crypto/mbedtls/library/cipher.c",
+      "${efr32_sdk_root}/util/third_party/crypto/mbedtls/library/cipher_wrap.c",
+      "${efr32_sdk_root}/util/third_party/crypto/mbedtls/library/cmac.c",
+      "${efr32_sdk_root}/util/third_party/crypto/mbedtls/library/constant_time.c",
+      "${efr32_sdk_root}/util/third_party/crypto/mbedtls/library/ctr_drbg.c",
+      "${efr32_sdk_root}/util/third_party/crypto/mbedtls/library/debug.c",
+      "${efr32_sdk_root}/util/third_party/crypto/mbedtls/library/des.c",
+      "${efr32_sdk_root}/util/third_party/crypto/mbedtls/library/dhm.c",
+      "${efr32_sdk_root}/util/third_party/crypto/mbedtls/library/ecdh.c",
+      "${efr32_sdk_root}/util/third_party/crypto/mbedtls/library/ecdsa.c",
+      "${efr32_sdk_root}/util/third_party/crypto/mbedtls/library/ecjpake.c",
+      "${efr32_sdk_root}/util/third_party/crypto/mbedtls/library/ecp.c",
+      "${efr32_sdk_root}/util/third_party/crypto/mbedtls/library/ecp_curves.c",
+      "${efr32_sdk_root}/util/third_party/crypto/mbedtls/library/entropy.c",
+      "${efr32_sdk_root}/util/third_party/crypto/mbedtls/library/entropy_poll.c",
+      "${efr32_sdk_root}/util/third_party/crypto/mbedtls/library/gcm.c",
+      "${efr32_sdk_root}/util/third_party/crypto/mbedtls/library/hkdf.c",
+      "${efr32_sdk_root}/util/third_party/crypto/mbedtls/library/hmac_drbg.c",
+      "${efr32_sdk_root}/util/third_party/crypto/mbedtls/library/md.c",
+      "${efr32_sdk_root}/util/third_party/crypto/mbedtls/library/md5.c",
+      "${efr32_sdk_root}/util/third_party/crypto/mbedtls/library/oid.c",
+      "${efr32_sdk_root}/util/third_party/crypto/mbedtls/library/pem.c",
+      "${efr32_sdk_root}/util/third_party/crypto/mbedtls/library/pk.c",
+      "${efr32_sdk_root}/util/third_party/crypto/mbedtls/library/pk_wrap.c",
+      "${efr32_sdk_root}/util/third_party/crypto/mbedtls/library/pkcs12.c",
+      "${efr32_sdk_root}/util/third_party/crypto/mbedtls/library/pkcs5.c",
+      "${efr32_sdk_root}/util/third_party/crypto/mbedtls/library/pkparse.c",
+      "${efr32_sdk_root}/util/third_party/crypto/mbedtls/library/pkwrite.c",
+      "${efr32_sdk_root}/util/third_party/crypto/mbedtls/library/platform.c",
+      "${efr32_sdk_root}/util/third_party/crypto/mbedtls/library/platform_util.c",
+      "${efr32_sdk_root}/util/third_party/crypto/mbedtls/library/poly1305.c",
+      "${efr32_sdk_root}/util/third_party/crypto/mbedtls/library/psa_crypto.c",
+      "${efr32_sdk_root}/util/third_party/crypto/mbedtls/library/psa_crypto_aead.c",
+      "${efr32_sdk_root}/util/third_party/crypto/mbedtls/library/psa_crypto_cipher.c",
+      "${efr32_sdk_root}/util/third_party/crypto/mbedtls/library/psa_crypto_client.c",
+      "${efr32_sdk_root}/util/third_party/crypto/mbedtls/library/psa_crypto_driver_wrappers.c",
+      "${efr32_sdk_root}/util/third_party/crypto/mbedtls/library/psa_crypto_ecp.c",
+      "${efr32_sdk_root}/util/third_party/crypto/mbedtls/library/psa_crypto_hash.c",
+      "${efr32_sdk_root}/util/third_party/crypto/mbedtls/library/psa_crypto_mac.c",
+      "${efr32_sdk_root}/util/third_party/crypto/mbedtls/library/psa_crypto_rsa.c",
+      "${efr32_sdk_root}/util/third_party/crypto/mbedtls/library/psa_crypto_se.c",
+      "${efr32_sdk_root}/util/third_party/crypto/mbedtls/library/psa_crypto_slot_management.c",
+      "${efr32_sdk_root}/util/third_party/crypto/mbedtls/library/psa_crypto_storage.c",
+      "${efr32_sdk_root}/util/third_party/crypto/mbedtls/library/psa_its_file.c",
+      "${efr32_sdk_root}/util/third_party/crypto/mbedtls/library/ripemd160.c",
+      "${efr32_sdk_root}/util/third_party/crypto/mbedtls/library/rsa.c",
+      "${efr32_sdk_root}/util/third_party/crypto/mbedtls/library/sha1.c",
+      "${efr32_sdk_root}/util/third_party/crypto/mbedtls/library/sha256.c",
+      "${efr32_sdk_root}/util/third_party/crypto/mbedtls/library/sha512.c",
+      "${efr32_sdk_root}/util/third_party/crypto/mbedtls/library/ssl_cache.c",
+      "${efr32_sdk_root}/util/third_party/crypto/mbedtls/library/ssl_ciphersuites.c",
+      "${efr32_sdk_root}/util/third_party/crypto/mbedtls/library/ssl_cli.c",
+      "${efr32_sdk_root}/util/third_party/crypto/mbedtls/library/ssl_cookie.c",
+      "${efr32_sdk_root}/util/third_party/crypto/mbedtls/library/ssl_msg.c",
+      "${efr32_sdk_root}/util/third_party/crypto/mbedtls/library/ssl_srv.c",
+      "${efr32_sdk_root}/util/third_party/crypto/mbedtls/library/ssl_ticket.c",
+      "${efr32_sdk_root}/util/third_party/crypto/mbedtls/library/ssl_tls.c",
+      "${efr32_sdk_root}/util/third_party/crypto/mbedtls/library/ssl_tls13_keys.c",
+      "${efr32_sdk_root}/util/third_party/crypto/mbedtls/library/threading.c",
+      "${efr32_sdk_root}/util/third_party/crypto/mbedtls/library/timing.c",
+      "${efr32_sdk_root}/util/third_party/crypto/mbedtls/library/version.c",
+      "${efr32_sdk_root}/util/third_party/crypto/mbedtls/library/x509.c",
+      "${efr32_sdk_root}/util/third_party/crypto/mbedtls/library/x509_create.c",
+      "${efr32_sdk_root}/util/third_party/crypto/mbedtls/library/x509_crl.c",
+      "${efr32_sdk_root}/util/third_party/crypto/mbedtls/library/x509_crt.c",
+      "${efr32_sdk_root}/util/third_party/crypto/mbedtls/library/x509_csr.c",
+      "${efr32_sdk_root}/util/third_party/crypto/mbedtls/library/x509write_crt.c",
+      "${efr32_sdk_root}/util/third_party/crypto/mbedtls/library/x509write_csr.c",
+      "${efr32_sdk_root}/util/third_party/crypto/sl_component/sl_mbedtls_support/src/aes_aes.c",
+      "${efr32_sdk_root}/util/third_party/crypto/sl_component/sl_mbedtls_support/src/crypto_aes.c",
+      "${efr32_sdk_root}/util/third_party/crypto/sl_component/sl_mbedtls_support/src/crypto_ecp.c",
+      "${efr32_sdk_root}/util/third_party/crypto/sl_component/sl_mbedtls_support/src/error.c",
+      "${efr32_sdk_root}/util/third_party/crypto/sl_component/sl_mbedtls_support/src/mbedtls_ccm.c",
+      "${efr32_sdk_root}/util/third_party/crypto/sl_component/sl_mbedtls_support/src/mbedtls_cmac.c",
+      "${efr32_sdk_root}/util/third_party/crypto/sl_component/sl_mbedtls_support/src/mbedtls_ecdsa_ecdh.c",
+      "${efr32_sdk_root}/util/third_party/crypto/sl_component/sl_mbedtls_support/src/mbedtls_sha.c",
+      "${efr32_sdk_root}/util/third_party/crypto/sl_component/sl_mbedtls_support/src/sl_entropy_hardware.c",
+      "${efr32_sdk_root}/util/third_party/crypto/sl_component/sl_mbedtls_support/src/sl_mbedtls.c",
+      "${efr32_sdk_root}/util/third_party/crypto/sl_component/sl_mbedtls_support/src/version_features.c",
+      "${efr32_sdk_root}/util/third_party/crypto/sl_component/sl_protocol_crypto/src/sli_protocol_crypto_crypto.c",
+      "${efr32_sdk_root}/util/third_party/crypto/sl_component/sl_protocol_crypto/src/sli_protocol_crypto_radioaes.c",
+      "${efr32_sdk_root}/util/third_party/crypto/sl_component/sl_psa_driver/src/crypto_management.c",
+      "${efr32_sdk_root}/util/third_party/crypto/sl_component/sl_psa_driver/src/sl_psa_its_nvm3.c",
+      "${efr32_sdk_root}/util/third_party/crypto/sl_component/sl_psa_driver/src/sli_crypto_transparent_driver_aead.c",
+      "${efr32_sdk_root}/util/third_party/crypto/sl_component/sl_psa_driver/src/sli_crypto_transparent_driver_cipher.c",
+      "${efr32_sdk_root}/util/third_party/crypto/sl_component/sl_psa_driver/src/sli_crypto_transparent_driver_hash.c",
+      "${efr32_sdk_root}/util/third_party/crypto/sl_component/sl_psa_driver/src/sli_crypto_transparent_driver_mac.c",
+      "${efr32_sdk_root}/util/third_party/crypto/sl_component/sl_psa_driver/src/sli_crypto_trng_driver.c",
+      "${efr32_sdk_root}/util/third_party/crypto/sl_component/sl_psa_driver/src/sli_psa_driver_common.c",
+      "${efr32_sdk_root}/util/third_party/crypto/sl_component/sl_psa_driver/src/sli_psa_driver_init.c",
+      "${efr32_sdk_root}/util/third_party/crypto/sl_component/sl_psa_driver/src/sli_psa_trng.c",
+      "${efr32_sdk_root}/util/third_party/crypto/sl_component/sl_psa_driver/src/sli_se_driver_builtin_keys.c",
+      "${efr32_sdk_root}/util/third_party/crypto/sl_component/sl_psa_driver/src/sli_se_driver_signature.c",
+      "${efr32_sdk_root}/util/third_party/freertos/cmsis/Source/cmsis_os2.c",
+      "${efr32_sdk_root}/util/third_party/freertos/kernel/croutine.c",
+      "${efr32_sdk_root}/util/third_party/freertos/kernel/event_groups.c",
+      "${efr32_sdk_root}/util/third_party/freertos/kernel/list.c",
+      "${efr32_sdk_root}/util/third_party/freertos/kernel/queue.c",
+      "${efr32_sdk_root}/util/third_party/freertos/kernel/stream_buffer.c",
+      "${efr32_sdk_root}/util/third_party/freertos/kernel/tasks.c",
+      "${efr32_sdk_root}/util/third_party/freertos/kernel/timers.c",
+      "${sdk_support_root}/matter/efr32/${silabs_family}/${silabs_board}/autogen/gatt_db.c",
+      "${sdk_support_root}/matter/efr32/${silabs_family}/${silabs_board}/autogen/sl_bluetooth.c",
+      "${sdk_support_root}/matter/efr32/${silabs_family}/${silabs_board}/autogen/sl_board_default_init.c",
+      "${sdk_support_root}/matter/efr32/${silabs_family}/${silabs_board}/autogen/sl_device_init_clocks.c",
+      "${sdk_support_root}/matter/efr32/${silabs_family}/${silabs_board}/autogen/sl_event_handler.c",
+      "${sdk_support_root}/matter/efr32/${silabs_family}/${silabs_board}/autogen/sl_simple_button_instances.c",
+    ]
+
+    if (use_system_view) {
+      sources += [
+        "${efr32_sdk_root}/util/third_party/segger/systemview/SEGGER/SEGGER_SYSVIEW.c",
+        "${efr32_sdk_root}/util/third_party/segger/systemview/Sample/FreeRTOSV10/Config/Cortex-M/SEGGER_SYSVIEW_Config_FreeRTOS.c",
+        "${efr32_sdk_root}/util/third_party/segger/systemview/Sample/FreeRTOSV10/SEGGER_SYSVIEW_FreeRTOS.c",
+      ]
+    }
+
+    if (use_wstk_leds) {
+      sources += [
+        "${efr32_sdk_root}/platform/driver/leddrv/src/sl_led.c",
+        "${efr32_sdk_root}/platform/driver/leddrv/src/sl_pwm_led.c",
+        "${efr32_sdk_root}/platform/driver/leddrv/src/sl_simple_led.c",
+        "${efr32_sdk_root}/platform/driver/leddrv/src/sl_simple_rgb_pwm_led.c",
+        "${sdk_support_root}/matter/efr32/${silabs_family}/${silabs_board}/autogen/sl_simple_led_instances.c",
+      ]
+    }
+
+    # SPI is only used for Wifi
+    if (defined(invoker.chip_enable_wifi) && invoker.chip_enable_wifi) {
+      sources += [
+        "${efr32_sdk_root}/platform/emdrv/spidrv/src/spidrv.c",
+        "${sdk_support_root}/matter/efr32/${silabs_family}/${silabs_board}/autogen/sl_spidrv_init.c",
+      ]
+    }
+
+    if (defined(invoker.enable_sleepy_device)) {
+      if (invoker.enable_sleepy_device) {
+        sources += [ "${efr32_sdk_root}/util/third_party/freertos/kernel/portable/SiliconLabs/tick_power_manager.c" ]
+      }
+    }
+
+    if (defined(enable_fem)) {
+      sources += [
+        "${efr32_sdk_root}/util/plugin/plugin-common/fem-control/fem-control.c",
+      ]
+    }
+
+    # USART sources files
+    if ((defined(invoker.chip_enable_pw_rpc) && invoker.chip_enable_pw_rpc) ||
+        chip_build_libshell || enable_openthread_cli ||
+        (defined(invoker.chip_enable_wifi) && invoker.chip_enable_wifi) ||
+        (defined(invoker.show_qr_code) && invoker.show_qr_code) ||
+        (defined(invoker.disable_lcd) && !invoker.disable_lcd) ||
+        (defined(invoker.use_external_flash) && use_external_flash)) {
+      sources += [
+        "${efr32_sdk_root}/hardware/driver/memlcd/src/memlcd_usart/sl_memlcd_spi.c",
+        "${efr32_sdk_root}/platform/emdrv/uartdrv/src/uartdrv.c",
+        "${efr32_sdk_root}/platform/emlib/src/em_eusart.c",
+        "${efr32_sdk_root}/platform/emlib/src/em_leuart.c",
+        "${efr32_sdk_root}/platform/emlib/src/em_usart.c",
+        "${sdk_support_root}/matter/efr32/${silabs_family}/${silabs_board}/autogen/sl_uartdrv_init.c",
+      ]
+
+      if (defined(invoker.use_external_flash) && use_external_flash) {
+        sources += [ "${efr32_sdk_root}/hardware/driver/mx25_flash_shutdown/src/sl_mx25_flash_shutdown_usart/sl_mx25_flash_shutdown.c" ]
+      }
+    }
+
+    if ((defined(invoker.show_qr_code) && invoker.show_qr_code) ||
+        (defined(invoker.disable_lcd) && !invoker.disable_lcd)) {
+      sources += [
+        "${efr32_sdk_root}/hardware/driver/memlcd/src/sl_memlcd.c",
+        "${efr32_sdk_root}/hardware/driver/memlcd/src/sl_memlcd_display.c",
+        "${efr32_sdk_root}/platform/middleware/glib/dmd/display/dmd_memlcd.c",
+        "${efr32_sdk_root}/platform/middleware/glib/glib/bmp.c",
+        "${efr32_sdk_root}/platform/middleware/glib/glib/glib.c",
+        "${efr32_sdk_root}/platform/middleware/glib/glib/glib_bitmap.c",
+        "${efr32_sdk_root}/platform/middleware/glib/glib/glib_circle.c",
+        "${efr32_sdk_root}/platform/middleware/glib/glib/glib_font_narrow_6x8.c",
+        "${efr32_sdk_root}/platform/middleware/glib/glib/glib_font_normal_8x8.c",
+        "${efr32_sdk_root}/platform/middleware/glib/glib/glib_font_number_16x20.c",
+        "${efr32_sdk_root}/platform/middleware/glib/glib/glib_line.c",
+        "${efr32_sdk_root}/platform/middleware/glib/glib/glib_polygon.c",
+        "${efr32_sdk_root}/platform/middleware/glib/glib/glib_rectangle.c",
+        "${efr32_sdk_root}/platform/middleware/glib/glib/glib_string.c",
+      ]
+    }
+
+    if (use_wf200) {
+      sources += [
+        "${efr32_sdk_root}/platform/radio/wifi/wfx_fmac_driver/bus/sl_wfx_bus.c",
+        "${efr32_sdk_root}/platform/radio/wifi/wfx_fmac_driver/bus/sl_wfx_bus_spi.c",
+        "${efr32_sdk_root}/platform/radio/wifi/wfx_fmac_driver/secure_link/sl_wfx_secure_link.c",
+        "${efr32_sdk_root}/platform/radio/wifi/wfx_fmac_driver/sl_wfx.c",
+      ]
+    }
+
+    if (silabs_family == "efr32mg12") {
+      sources += [
+        "${efr32_sdk_root}/platform/Device/SiliconLabs/EFR32MG12P/Source/startup_efr32mg12p.c",
+        "${efr32_sdk_root}/platform/Device/SiliconLabs/EFR32MG12P/Source/system_efr32mg12p.c",
+        "${efr32_sdk_root}/platform/service/device_init/src/sl_device_init_dcdc_s1.c",
+        "${efr32_sdk_root}/platform/service/device_init/src/sl_device_init_emu_s1.c",
+        "${efr32_sdk_root}/platform/service/device_init/src/sl_device_init_hfxo_s1.c",
+        "${efr32_sdk_root}/platform/service/device_init/src/sl_device_init_lfxo_s1.c",
+        "${efr32_sdk_root}/protocol/bluetooth/src/sl_apploader_util_s1.c",
+        "${efr32_sdk_root}/util/third_party/freertos/kernel/portable/GCC/ARM_CM4F/port.c",
+      ]
+    } else if (silabs_family == "efr32mg21") {
+      sources += [
+        "${efr32_sdk_root}/platform/Device/SiliconLabs/EFR32MG21/Source/startup_efr32mg21.c",
+        "${efr32_sdk_root}/platform/Device/SiliconLabs/EFR32MG21/Source/system_efr32mg21.c",
+        "${efr32_sdk_root}/platform/radio/rail_lib/plugin/rail_util_rf_path/sl_rail_util_rf_path.c",
+        "${efr32_sdk_root}/platform/service/device_init/src/sl_device_init_emu_s2.c",
+        "${efr32_sdk_root}/platform/service/device_init/src/sl_device_init_hfrco.c",
+        "${efr32_sdk_root}/platform/service/device_init/src/sl_device_init_hfxo_s2.c",
+        "${efr32_sdk_root}/platform/service/device_init/src/sl_device_init_lfxo_s2.c",
+        "${efr32_sdk_root}/platform/service/hfxo_manager/src/sl_hfxo_manager_hal_s2.c",
+        "${efr32_sdk_root}/util/third_party/crypto/sl_component/se_manager/src/sl_se_manager.c",
+        "${efr32_sdk_root}/util/third_party/crypto/sl_component/se_manager/src/sl_se_manager_cipher.c",
+        "${efr32_sdk_root}/util/third_party/crypto/sl_component/se_manager/src/sl_se_manager_entropy.c",
+        "${efr32_sdk_root}/util/third_party/crypto/sl_component/se_manager/src/sl_se_manager_hash.c",
+        "${efr32_sdk_root}/util/third_party/crypto/sl_component/se_manager/src/sl_se_manager_key_derivation.c",
+        "${efr32_sdk_root}/util/third_party/crypto/sl_component/se_manager/src/sl_se_manager_key_handling.c",
+        "${efr32_sdk_root}/util/third_party/crypto/sl_component/se_manager/src/sl_se_manager_signature.c",
+        "${efr32_sdk_root}/util/third_party/crypto/sl_component/se_manager/src/sl_se_manager_util.c",
+        "${efr32_sdk_root}/util/third_party/crypto/sl_component/sl_alt/source/sl_se_management.c",
+        "${efr32_sdk_root}/util/third_party/crypto/sl_component/sl_mbedtls_support/src/se_aes.c",
+        "${efr32_sdk_root}/util/third_party/crypto/sl_component/sl_mbedtls_support/src/se_gcm.c",
+        "${efr32_sdk_root}/util/third_party/crypto/sl_component/sl_mbedtls_support/src/se_jpake.c",
+        "${efr32_sdk_root}/util/third_party/crypto/sl_component/sl_protocol_crypto/src/sli_radioaes_management.c",
+        "${efr32_sdk_root}/util/third_party/crypto/sl_component/sl_psa_driver/src/sli_se_driver_aead.c",
+        "${efr32_sdk_root}/util/third_party/crypto/sl_component/sl_psa_driver/src/sli_se_driver_cipher.c",
+        "${efr32_sdk_root}/util/third_party/crypto/sl_component/sl_psa_driver/src/sli_se_driver_key_derivation.c",
+        "${efr32_sdk_root}/util/third_party/crypto/sl_component/sl_psa_driver/src/sli_se_driver_key_management.c",
+        "${efr32_sdk_root}/util/third_party/crypto/sl_component/sl_psa_driver/src/sli_se_driver_mac.c",
+        "${efr32_sdk_root}/util/third_party/crypto/sl_component/sl_psa_driver/src/sli_se_opaque_driver_aead.c",
+        "${efr32_sdk_root}/util/third_party/crypto/sl_component/sl_psa_driver/src/sli_se_opaque_driver_cipher.c",
+        "${efr32_sdk_root}/util/third_party/crypto/sl_component/sl_psa_driver/src/sli_se_opaque_driver_mac.c",
+        "${efr32_sdk_root}/util/third_party/crypto/sl_component/sl_psa_driver/src/sli_se_opaque_key_derivation.c",
+        "${efr32_sdk_root}/util/third_party/crypto/sl_component/sl_psa_driver/src/sli_se_transparent_driver_cipher.c",
+        "${efr32_sdk_root}/util/third_party/crypto/sl_component/sl_psa_driver/src/sli_se_transparent_driver_hash.c",
+        "${efr32_sdk_root}/util/third_party/crypto/sl_component/sl_psa_driver/src/sli_se_transparent_driver_mac.c",
+        "${efr32_sdk_root}/util/third_party/crypto/sl_component/sl_psa_driver/src/sli_se_transparent_key_derivation.c",
+        "${efr32_sdk_root}/util/third_party/freertos/kernel/portable/GCC/ARM_CM33_NTZ/non_secure/port.c",
+        "${efr32_sdk_root}/util/third_party/freertos/kernel/portable/GCC/ARM_CM33_NTZ/non_secure/portasm.c",
+      ]
+    } else if (silabs_family == "efr32mg24") {
+      sources += [
+        "${efr32_sdk_root}/platform/Device/SiliconLabs/EFR32MG24/Source/startup_efr32mg24.c",
+        "${efr32_sdk_root}/platform/Device/SiliconLabs/EFR32MG24/Source/system_efr32mg24.c",
+        "${efr32_sdk_root}/platform/radio/rail_lib/plugin/pa-conversions/pa_curves_efr32.c",
+        "${efr32_sdk_root}/platform/service/device_init/src/sl_device_init_dcdc_s2.c",
+        "${efr32_sdk_root}/platform/service/device_init/src/sl_device_init_emu_s2.c",
+        "${efr32_sdk_root}/platform/service/device_init/src/sl_device_init_hfxo_s2.c",
+        "${efr32_sdk_root}/platform/service/device_init/src/sl_device_init_lfxo_s2.c",
+        "${efr32_sdk_root}/platform/service/hfxo_manager/src/sl_hfxo_manager_hal_s2.c",
+        "${efr32_sdk_root}/protocol/bluetooth/src/sl_apploader_util_s2.c",
+        "${efr32_sdk_root}/util/third_party/crypto/sl_component/se_manager/src/sl_se_manager.c",
+        "${efr32_sdk_root}/util/third_party/crypto/sl_component/se_manager/src/sl_se_manager_attestation.c",
+        "${efr32_sdk_root}/util/third_party/crypto/sl_component/se_manager/src/sl_se_manager_cipher.c",
+        "${efr32_sdk_root}/util/third_party/crypto/sl_component/se_manager/src/sl_se_manager_entropy.c",
+        "${efr32_sdk_root}/util/third_party/crypto/sl_component/se_manager/src/sl_se_manager_hash.c",
+        "${efr32_sdk_root}/util/third_party/crypto/sl_component/se_manager/src/sl_se_manager_key_derivation.c",
+        "${efr32_sdk_root}/util/third_party/crypto/sl_component/se_manager/src/sl_se_manager_key_handling.c",
+        "${efr32_sdk_root}/util/third_party/crypto/sl_component/se_manager/src/sl_se_manager_signature.c",
+        "${efr32_sdk_root}/util/third_party/crypto/sl_component/se_manager/src/sl_se_manager_util.c",
+        "${efr32_sdk_root}/util/third_party/crypto/sl_component/sl_mbedtls_support/src/se_aes.c",
+        "${efr32_sdk_root}/util/third_party/crypto/sl_component/sl_mbedtls_support/src/se_jpake.c",
+        "${efr32_sdk_root}/util/third_party/crypto/sl_component/sl_protocol_crypto/src/sli_radioaes_management.c",
+        "${efr32_sdk_root}/util/third_party/crypto/sl_component/sl_psa_driver/src/sli_se_driver_aead.c",
+        "${efr32_sdk_root}/util/third_party/crypto/sl_component/sl_psa_driver/src/sli_se_driver_cipher.c",
+        "${efr32_sdk_root}/util/third_party/crypto/sl_component/sl_psa_driver/src/sli_se_driver_key_derivation.c",
+        "${efr32_sdk_root}/util/third_party/crypto/sl_component/sl_psa_driver/src/sli_se_driver_key_management.c",
+        "${efr32_sdk_root}/util/third_party/crypto/sl_component/sl_psa_driver/src/sli_se_driver_mac.c",
+        "${efr32_sdk_root}/util/third_party/crypto/sl_component/sl_psa_driver/src/sli_se_opaque_driver_aead.c",
+        "${efr32_sdk_root}/util/third_party/crypto/sl_component/sl_psa_driver/src/sli_se_opaque_driver_cipher.c",
+        "${efr32_sdk_root}/util/third_party/crypto/sl_component/sl_psa_driver/src/sli_se_opaque_driver_mac.c",
+        "${efr32_sdk_root}/util/third_party/crypto/sl_component/sl_psa_driver/src/sli_se_opaque_key_derivation.c",
+        "${efr32_sdk_root}/util/third_party/crypto/sl_component/sl_psa_driver/src/sli_se_transparent_driver_aead.c",
+        "${efr32_sdk_root}/util/third_party/crypto/sl_component/sl_psa_driver/src/sli_se_transparent_driver_cipher.c",
+        "${efr32_sdk_root}/util/third_party/crypto/sl_component/sl_psa_driver/src/sli_se_transparent_driver_hash.c",
+        "${efr32_sdk_root}/util/third_party/crypto/sl_component/sl_psa_driver/src/sli_se_transparent_driver_mac.c",
+        "${efr32_sdk_root}/util/third_party/crypto/sl_component/sl_psa_driver/src/sli_se_transparent_key_derivation.c",
+        "${efr32_sdk_root}/util/third_party/freertos/kernel/portable/GCC/ARM_CM33_NTZ/non_secure/port.c",
+        "${efr32_sdk_root}/util/third_party/freertos/kernel/portable/GCC/ARM_CM33_NTZ/non_secure/portasm.c",
+      ]
+    } else if (silabs_family == "mgm24") {
+      sources += [
+        "${efr32_sdk_root}/platform/Device/SiliconLabs/MGM24/Source/startup_mgm24.c",
+        "${efr32_sdk_root}/platform/Device/SiliconLabs/MGM24/Source/system_mgm24.c",
+        "${efr32_sdk_root}/platform/radio/rail_lib/plugin/pa-conversions/pa_curves_efr32.c",
+        "${efr32_sdk_root}/platform/service/device_init/src/sl_device_init_dcdc_s2.c",
+        "${efr32_sdk_root}/platform/service/device_init/src/sl_device_init_emu_s2.c",
+        "${efr32_sdk_root}/platform/service/device_init/src/sl_device_init_hfxo_mgm24.c",
+        "${efr32_sdk_root}/platform/service/device_init/src/sl_device_init_lfxo_s2.c",
+        "${efr32_sdk_root}/platform/service/hfxo_manager/src/sl_hfxo_manager_hal_s2.c",
+        "${efr32_sdk_root}/protocol/bluetooth/src/sl_apploader_util_s2.c",
+        "${efr32_sdk_root}/util/third_party/crypto/sl_component/se_manager/src/sl_se_manager.c",
+        "${efr32_sdk_root}/util/third_party/crypto/sl_component/se_manager/src/sl_se_manager_attestation.c",
+        "${efr32_sdk_root}/util/third_party/crypto/sl_component/se_manager/src/sl_se_manager_cipher.c",
+        "${efr32_sdk_root}/util/third_party/crypto/sl_component/se_manager/src/sl_se_manager_entropy.c",
+        "${efr32_sdk_root}/util/third_party/crypto/sl_component/se_manager/src/sl_se_manager_hash.c",
+        "${efr32_sdk_root}/util/third_party/crypto/sl_component/se_manager/src/sl_se_manager_key_derivation.c",
+        "${efr32_sdk_root}/util/third_party/crypto/sl_component/se_manager/src/sl_se_manager_key_handling.c",
+        "${efr32_sdk_root}/util/third_party/crypto/sl_component/se_manager/src/sl_se_manager_signature.c",
+        "${efr32_sdk_root}/util/third_party/crypto/sl_component/se_manager/src/sl_se_manager_util.c",
+        "${efr32_sdk_root}/util/third_party/crypto/sl_component/sl_mbedtls_support/src/se_aes.c",
+        "${efr32_sdk_root}/util/third_party/crypto/sl_component/sl_mbedtls_support/src/se_jpake.c",
+        "${efr32_sdk_root}/util/third_party/crypto/sl_component/sl_protocol_crypto/src/sli_radioaes_management.c",
+        "${efr32_sdk_root}/util/third_party/crypto/sl_component/sl_psa_driver/src/sli_se_driver_aead.c",
+        "${efr32_sdk_root}/util/third_party/crypto/sl_component/sl_psa_driver/src/sli_se_driver_cipher.c",
+        "${efr32_sdk_root}/util/third_party/crypto/sl_component/sl_psa_driver/src/sli_se_driver_key_derivation.c",
+        "${efr32_sdk_root}/util/third_party/crypto/sl_component/sl_psa_driver/src/sli_se_driver_key_management.c",
+        "${efr32_sdk_root}/util/third_party/crypto/sl_component/sl_psa_driver/src/sli_se_driver_mac.c",
+        "${efr32_sdk_root}/util/third_party/crypto/sl_component/sl_psa_driver/src/sli_se_opaque_driver_aead.c",
+        "${efr32_sdk_root}/util/third_party/crypto/sl_component/sl_psa_driver/src/sli_se_opaque_driver_cipher.c",
+        "${efr32_sdk_root}/util/third_party/crypto/sl_component/sl_psa_driver/src/sli_se_opaque_driver_mac.c",
+        "${efr32_sdk_root}/util/third_party/crypto/sl_component/sl_psa_driver/src/sli_se_opaque_key_derivation.c",
+        "${efr32_sdk_root}/util/third_party/crypto/sl_component/sl_psa_driver/src/sli_se_transparent_driver_aead.c",
+        "${efr32_sdk_root}/util/third_party/crypto/sl_component/sl_psa_driver/src/sli_se_transparent_driver_cipher.c",
+        "${efr32_sdk_root}/util/third_party/crypto/sl_component/sl_psa_driver/src/sli_se_transparent_driver_hash.c",
+        "${efr32_sdk_root}/util/third_party/crypto/sl_component/sl_psa_driver/src/sli_se_transparent_driver_mac.c",
+        "${efr32_sdk_root}/util/third_party/crypto/sl_component/sl_psa_driver/src/sli_se_transparent_key_derivation.c",
+        "${efr32_sdk_root}/util/third_party/freertos/kernel/portable/GCC/ARM_CM33_NTZ/non_secure/port.c",
+        "${efr32_sdk_root}/util/third_party/freertos/kernel/portable/GCC/ARM_CM33_NTZ/non_secure/portasm.c",
+      ]
+    }
+
+    if (silabs_board == "BRD4186A" || silabs_board == "BRD4186C" ||
+        silabs_board == "BRD4187A" || silabs_board == "BRD4187C") {
+      sources += [ "${efr32_sdk_root}/platform/service/device_init/src/sl_device_init_dpll_s2.c" ]
+    }
+
+    public_deps = [
+      ":efr32_mbedtls_config",
+      "${segger_rtt_root}:segger_rtt",
+      "${segger_rtt_root}:segger_rtt_printf",
+      "${segger_rtt_root}:segger_rtt_syscalls",
+    ]
+
+    if (defined(invoker.sources)) {
+      sources += invoker.sources
+    }
+
+    public_configs = [ ":${sdk_target_name}_config" ]
+  }
+}