diff --git a/doc/site/en/guides/porting/_toc.yaml b/doc/site/en/guides/porting/_toc.yaml
new file mode 100644
index 000000000..82553d136
--- /dev/null
+++ b/doc/site/en/guides/porting/_toc.yaml
@@ -0,0 +1,20 @@
+toc:
+- title: Overview
+ path: /guides/porting/
+ step_group: porting_guide
+- title: Set up the Build Environment
+ path: /guides/porting/set-up-the-build-environment
+ step_group: porting_guide
+- title: Implement Platform Abstraction Layer APIs
+ path: /guides/porting/implement-platform-abstraction-layer-apis
+ step_group: porting_guide
+- title: Implement Advanced Features
+ path: /guides/porting/implement-advanced-features
+ step_group: porting_guide
+- title: Validate the Port
+ path: /guides/porting/validate-the-port
+ step_group: porting_guide
+- title: Certification and README
+ path: /guides/porting/certification-and-readme
+ step_group: porting_guide
+
diff --git a/doc/site/en/guides/porting/certification-and-readme.md b/doc/site/en/guides/porting/certification-and-readme.md
new file mode 100644
index 000000000..7ecb8c5a7
--- /dev/null
+++ b/doc/site/en/guides/porting/certification-and-readme.md
@@ -0,0 +1,27 @@
+# Certification and README
+
+## Thread Certification
+
+To achieve Thread Certification, the port must be tested against the official
+[Thread Harness](http://graniteriverlabs.com/thread/) and pass all scenarios
+listed in the Thread Certification Test Plan.
+
+For more information, see
+[Certification](https://openthread.io/certification).
+
+## README
+
+A detailed README is necessary to demonstrate how to build and run OpenThread on
+a new hardware platform.
+
+At a minimum, the README should include:
+
+- Information about the hardware platform
+- Links to the required toolchain
+- How to configure platform-specific vendor software
+- How to build and flash binaries onto the platform
+- Versions of libraries and toolchains used for validation of the port
+
+See the
+[EFR32MG12 README](https://github.com/openthread/openthread/blob/master/examples/platforms/efr32/efr32mg12/README.md)
+for an example.
diff --git a/doc/site/en/guides/porting/implement-advanced-features.md b/doc/site/en/guides/porting/implement-advanced-features.md
new file mode 100644
index 000000000..1880539b6
--- /dev/null
+++ b/doc/site/en/guides/porting/implement-advanced-features.md
@@ -0,0 +1,135 @@
+# Implement Advanced Features
+
+Some advanced features are optional, depending on whether or not they are
+supported on the target hardware platform.
+
+
+
+## Step 1: Auto frame pending
+
+IEEE 802.15.4 defines two kinds of data transmission methods between parent and
+child: direct transmission and indirect transmission. The latter is designed
+primarily for sleepy end devices (SEDs) which sleep most of the time,
+periodically waking to poll the parent for queued data.
+
+- **Direct Transmission** — parent sends a data frame directly to the end device
+
+
+- **Indirect Transmission** — parent holds data until requested by its intended end device
+
+
+In the Indirect case, a child end device must first poll the parent to determine
+whether any data is available for it. To do this, the child sends a data
+request, which the parent acknowledges. The parent then determines whether it
+has any data for the child device; if so, it sends a data packet to the child
+device, which acknowledges receipt of the data.
+
+If the radio supports dynamically setting the Frame Pending bit in outgoing
+acknowledgments to SEDs, the drivers must implement the
+[source address match](https://github.com/openthread/openthread/blob/master/include/openthread/platform/radio.h#L288)
+API to enable this capability. OpenThread uses this API to tell the radio which
+SEDs to set the Frame Pending bit for.
+
+If the radio does not support dynamically setting the Frame Pending bit, the
+radio might stub out the source address match API to return
+`OT_ERROR_NOT_IMPLEMENTED`.
+
+## Step 2: Energy Scan/Detect with radio
+
+> Note: This feature is optional.
+
+The Energy Scan/Detect feature requires the radio chip to sample energy
+presenting on selected channels and return the detected energy value to the
+upper layer.
+
+If this feature is not implemented, the IEEE 802.15.4 MAC layer
+sends/receives a Beacon Request/Response packet to evaluate the current
+energy value on the channel.
+
+If the radio chip supports Energy Scan/Detect, make sure to disable software
+energy scanning logic by setting the macro
+`OPENTHREAD_CONFIG_ENABLE_SOFTWARE_ENERGY_SCAN = 0`.
+
+## Step 3: Hardware acceleration for mbedTLS
+
+> Note: This feature is optional.
+
+mbedTLS defines several macros in the main configuration header file,
+[`mbedtls-config.h`](https://github.com/openthread/openthread/blob/master/third_party/mbedtls/mbedtls-config.h),
+to allow users to enable alternative implementations of AES, SHA1, SHA2, and
+other modules, as well as individual functions for the Elliptic curve
+cryptography (ECC) over GF(p) module. See
+[mbedTLS hardware acceleration](https://docs.mbed.com/docs/mbed-os-handbook/en/latest/advanced/tls_hardware_acceleration/)
+for more information.
+
+OpenThread does not enable those macros, therefore the symmetric crypto
+algorithms, hash algorithms and ECC functions all utilize software
+implementations by default. These implementations require considerable memory
+and computational resources. For optimal performance and a better user
+experience, we recommend enabling hardware acceleration instead of software to
+implement the above operations.
+
+To enable hardware acceleration within OpenThread, the following mbedTLS
+configuration header files should be added to the compile option flags in the
+platform example's Makefile:
+
+- Main configuration, which defines all necessary macros used in OpenThread:
+ `/openthread/third-party/mbedtls/mbedtls-config.h`
+- User-specific configuration, which defines alternate implementations of
+ modules and functions: `/openthread/examples/platforms/{platform-name}/crypto/{platform-name}-mbedtls-config.h`
+
+Example:
+
+```
+EFR32_MBEDTLS_CPPFLAGS = -DMBEDTLS_CONFIG_FILE='\"mbedtls-config.h\"'
+EFR32_MBEDTLS_CPPFLAGS += -DMBEDTLS_USER_CONFIG_FILE='\"efr32-mbedtls-config.h\"'
+```
+
+Commented macros in `mbedtls-config.h` are not mandatory, and can be enabled in
+the user-specific configuration header file for hardware acceleration.
+
+For a complete example user-specific configuration, see the
+[`mbedtls_config_autogen.h`](https://github.com/openthread/openthread/blob/master/examples/platforms/efr32/efr32mg12/crypto/mbedtls_config_autogen.h)
+file.
+
+### AES module
+
+OpenThread Security applies AES CCM (Counter with CBC-MAC) crypto to
+encrypt/decrypt the IEEE 802.15.4 or MLE messages and validates the message
+integration code. Hardware acceleration should at least support basic AES ECB
+(Electronic Codebook Book) mode for AES CCM basic functional call.
+
+To utilize an alternative AES module implementation:
+
+1. Define the `MBEDTLS_AES_ALT` macro in the user-specific mbedTLS
+ configuration header file
+1. Indicate the path of the `aes_alt.h` file using the `MBEDTLS_CPPFLAGS`
+ variable
+
+### SHA256 module
+
+OpenThread Security applies HMAC and SHA256 hash algorithms to calculate the
+hash value for master key management and PSKc generation according to the Thread
+Specification.
+
+To utilize an alternative basic SHA256 module implementation:
+
+1. Define the `MBEDTLS_SHA256_ALT` macro in the user-specific mbedTLS
+ configuration header file
+1. Indicate the path of the `sha256_alt.h` file using the `MBEDTLS_CPPFLAGS`
+ variable
+
+### ECC functions
+
+Since mbedTLS currently only supports hardware acceleration for parts of ECC
+functions, rather than the entire module, you can choose to implement some
+functions defined in
+`{path-to-mbedtls}/library/ecp.c` to accelerate ECC
+point multiplication.
+
+Curve secp256r1 is used in the key exchange algorithm of the
+[ECJPAKE](https://tools.ietf.org/html/draft-cragie-tls-ecjpake-00) draft. Hence,
+hardware acceleration should at least support the secp256r1 short weierstrass
+curve operation. See [SiLabs CRYPTO Hardware Acceleration for
+mbedTLS](https://siliconlabs.github.io/Gecko_SDK_Doc/mbedtls/html/group__sl__crypto.html)
+for an example.
diff --git a/doc/site/en/guides/porting/implement-platform-abstraction-layer-apis.md b/doc/site/en/guides/porting/implement-platform-abstraction-layer-apis.md
new file mode 100644
index 000000000..a224bc7f3
--- /dev/null
+++ b/doc/site/en/guides/porting/implement-platform-abstraction-layer-apis.md
@@ -0,0 +1,204 @@
+# Implement Platform Abstraction Layer APIs
+
+OpenThread is OS and platform agnostic, with a narrow Platform Abstraction Layer
+(PAL). This PAL defines:
+
+
+
+
+
+- Alarm interface for free-running timer with alarm
+- Bus interfaces (UART, SPI) for communicating CLI and Spinel messages
+- Radio interface for IEEE 802.15.4-2006 communication
+- GCC-specific initialization routines
+- Entropy for true random number generation
+- Settings service for non-volatile configuration storage
+- Logging interface for delivering OpenThread log messages
+- System-specific initialization routines
+
+All APIs should be implemented based on the underlying Hardware Abstraction
+Layer (HAL) Build Support Package (BSP).
+
+> Key Point: Unless noted as optional, **Platform Abstraction Layer APIs are
+mandatory** and must be implemented according to the definitions in each API
+header file.
+
+API files should be placed in the following directories:
+
+Type | Directory
+------|------
+Platform-specific PAL implementation | `/openthread/examples/platforms/{platform-name}`
+Header files — Non-volatile storage API | `/openthread/examples/platforms/utils`
+All other header files | `/openthread/include/openthread/platform`
+HAL BSP | `/openthread/third_party/{platform-name}`
+
+## Step 1: Alarm
+
+API declaration:
+
+[`/openthread/include/openthread/platform/alarm-milli.h`](https://github.com/openthread/openthread/blob/master/include/openthread/platform/alarm-milli.h)
+
+The Alarm API provides fundamental timing and alarm services for the upper layer
+timer implementation.
+
+There are two alarm service types,
+[millisecond](https://github.com/openthread/openthread/blob/master/include/openthread/platform/alarm-milli.h)
+and [microsecond](https://github.com/openthread/openthread/blob/master/include/openthread/platform/alarm-micro.h).
+Millisecond is required for a new hardware platform. Microsecond is optional.
+
+## Step 2: UART
+
+> Note: This API is optional.
+
+API declaration:
+
+[`/openthread/include/openthread/platform/uart.h`](https://github.com/openthread/openthread/blob/master/include/openthread/platform/uart.h)
+
+The UART API implements fundamental serial port communication via the UART
+interface.
+
+While the OpenThread
+[CLI](https://github.com/openthread/openthread/tree/master/examples/apps/cli)
+and [NCP](https://github.com/openthread/openthread/tree/master/examples/apps/ncp)
+add-ons depend on the UART interface to interact with the host side, UART API
+support is optional. However, even if you do not plan to use these add-ons on
+your new hardware platform example, we highly recommend you add support for a
+few reasons:
+
+- The CLI is useful for validating that the port works correctly
+- The Harness Automation Tool uses the UART interface to control OpenThread for testing and certification purposes
+
+If the target hardware platform supports a USB CDC module rather than UART, make
+sure to:
+
+- Install the correct USB CDC driver on the host side
+- Replace the UART API implementation with the USB CDC driver (along with BSP)
+ on the OpenThread side, using the same function prototypes
+
+## Step 3: Radio
+
+API declaration:
+
+[`/openthread/include/openthread/platform/radio.h`](https://github.com/openthread/openthread/blob/master/include/openthread/platform/radio.h)
+
+The Radio API defines all necessary functions called by the upper IEEE 802.15.4
+MAC layer. The Radio chip must be fully compliant with the 2.4GHz IEEE
+802.15.4-2006 specification.
+
+Due to its enhanced low power feature, OpenThread requires all platforms to
+implement auto frame pending (indirect transmission) by default, and the source
+address match table should also be implemented in the `radio.h` source file.
+
+However, if your new hardware platform example is resource limited, the source
+address table can be defined as zero length. See
+[Auto Frame Pending](#auto-frame-pending) for more information.
+
+> Note: The `otPlatRadioGetIeeeEui64` Radio API **MUST** return a unique
+administered factory-assigned IEEE EUI-64 that includes the manufacturer's OUI.
+The EUI-64 is used to match to steering data during the Joiner Discovery phase.
+
+## Step 4: Misc/Reset
+
+API declaration:
+
+[`/openthread/include/openthread/platform/misc.h`](https://github.com/openthread/openthread/blob/master/include/openthread/platform/misc.h)
+
+The Misc/Reset API provides a method to reset the software on the chip, and
+query the reason for last reset.
+
+## Step 5: Entropy
+
+> Note: **Implementation of this API is required in every port of OpenThread.**
+
+API declaration:
+
+[`/openthread/include/openthread/platform/entropy.h`](https://github.com/openthread/openthread/blob/master/include/openthread/platform/entropy.h)
+
+The Entropy API provides a true random number generator (TRNG) for the upper
+layer, which is used to maintain security assets for the entire OpenThread
+network. The API should guarantee that a new random number is generated for
+each function call. Security assets affected by the TRNG include:
+
+- AES CCM nonce
+- Random delayed jitter
+- Devices' extended address
+- The initial random period in the trickle timer
+- CoAP token/message IDs
+
+Note that many platforms have already integrated a random number generator,
+exposing the API in its BSP package. In the event that the target hardware
+platform does not support TRNG, consider leveraging ADC module sampling to
+generate a fixed-length random number. Sample over multiple iterations if
+necessary to meet the TRNG requirements (uint32_t).
+
+When the macro `MBEDTLS_ENTROPY_HARDWARE_ALT` is set to `1`, this API should
+also provide a method to generate the hardware entropy used in the mbedTLS
+library.
+
+## Step 6: Non-volatile storage
+
+> Note: **Only _one_ of these APIs is required to be implemented in every port
+of OpenThread.**
+
+API declarations:
+
+[`/openthread/include/openthread/platform/flash.h`](https://github.com/openthread/openthread/blob/master/include/openthread/platform/flash.h)
+
+**or**
+
+[`/openthread/include/openthread/platform/settings.h`](https://github.com/openthread/openthread/blob/master/include/openthread/platform/settings.h)
+
+The Non-volatile storage requirement can be satisfied by implementing one of the
+two APIs listed above. The Flash API implements a flash storage driver, while
+the Settings API provides functions for an underlying flash operation
+implementation to the upper layer.
+
+These APIs expose to the upper layer:
+
+- The available non-volatile storage size used to store application data (for
+ example, active/pending operational dataset, current network parameters and
+ thread devices' credentials for reattachment after reset)
+- Read, write, erase, and query flash status operations
+
+Use `OPENTHREAD_CONFIG_PLATFORM_FLASH_API_ENABLE` in your platform example's
+core config file to indicate which API the platform should use. If set to `1`,
+the Flash API must be implemented. Otherwise, the Settings API must be
+implemented.
+
+This flag must be set in your
+`/openthread/examples/platforms/{platform-name}/openthread-core-{platform-name}-config.h`
+file.
+
+## Step 7: Logging
+
+> Note: This API is optional.
+
+API declaration:
+
+[`/openthread/include/openthread/platform/logging.h`](https://github.com/openthread/openthread/blob/master/include/openthread/platform/logging.h)
+
+The Logging API implements OpenThread's logging and debug functionality, with
+multiple levels of debug output available. This API is optional if you do not
+plan to utilize OpenThread's logging on your new hardware platform example.
+
+The highest and most detailed level is `OPENTHREAD_LOG_LEVEL_DEBG`, which
+prints all raw packet information and logs lines through the serial port or on
+the terminal. Choose a debug level that best meets your needs.
+
+## Step 8: System-specific
+
+API declaration:
+
+[`/openthread/examples/platforms/openthread-system.h`](https://github.com/openthread/openthread/blob/master/examples/platforms/openthread-system.h)
+
+The System-specific API primarily provides initialization and deinitialization
+operations for the selected hardware platform. This API is not called by the
+OpenThread library itself, but may be useful for your system/RTOS. You can also
+implement the initialization of other modules (for example, UART, Radio, Random,
+Misc/Reset) in this source file.
+
+Implementation of this API depends on your use case. If you wish to use the
+generated [CLI and NCP applications](https://openthread.io/guides/build#binaries) for an [example
+platform](https://github.com/openthread/openthread/tree/master/examples/platforms),
+you must implement this API. Otherwise, any API can be implemented to integrate
+the example platform drivers into your system/RTOS.
diff --git a/doc/site/en/guides/porting/index.md b/doc/site/en/guides/porting/index.md
new file mode 100644
index 000000000..d721d757c
--- /dev/null
+++ b/doc/site/en/guides/porting/index.md
@@ -0,0 +1,33 @@
+# Porting OpenThread to New Hardware Platforms
+
+Porting the OpenThread stack to a new hardware platform consists of five steps:
+
+1. [Set up the build environment](https://github.com/openthread/openthread/blob/master/doc/site/en/guides/porting/set-up-the-build-environment.md)
+1. [Implement Platform Abstraction Layer APIs](https://github.com/openthread/openthread/blob/master/doc/site/en/guides/porting/implement-platform-abstraction-layer-apis.md)
+1. [Implement advanced features (Hardware Abstraction Layer)](https://github.com/openthread/openthread/blob/master/doc/site/en/guides/porting/implement-advanced-features.md)
+1. [Validate the port](https://github.com/openthread/openthread/blob/master/doc/site/en/guides/porting/validate-the-port.md)
+1. [Certification and README](https://github.com/openthread/openthread/blob/master/doc/site/en/guides/porting/certification-and-readme.md)
+
+## Hardware platform requirements
+
+OpenThread requires the following platform services:
+
+- [IEEE 802.15.4-2006](https://standards.ieee.org/findstds/standard/802.15.4-2006.html)
+ 2.4 GHz radio
+ - Send and receive IEEE 802.15.4 frames
+ - Generate IEEE 802.15.4 Acknowledgment frames
+ - Provide Received Signal Strength Indicator (RSSI) measurements on
+ received frames
+- A millisecond-resolution free-running timer with alarm
+- Non-volatile storage for storing network configuration settings
+- A true random number generator (TRNG)
+
+## Example builds
+
+Several example builds are provided in the OpenThread repository. For more
+information, see [Platforms](https://openthread.io/platforms).
+
+For a complete end-to-end example of how to port OpenThread from scratch, see
+the [Add support for EFR32](https://github.com/openthread/openthread/pull/1592)
+pull request.
+
diff --git a/doc/site/en/guides/porting/set-up-the-build-environment.md b/doc/site/en/guides/porting/set-up-the-build-environment.md
new file mode 100644
index 000000000..73cc4939c
--- /dev/null
+++ b/doc/site/en/guides/porting/set-up-the-build-environment.md
@@ -0,0 +1,217 @@
+# Set Up the Build Environment
+
+To promote free and open development, OpenThread uses GNU Autotools in the build
+toolchain. Currently, this toolchain is required for porting OpenThread to a new
+hardware platform.
+
+Other build toolchains might be supported in the future, but they are not within
+the scope of this porting guide.
+
+> Note: For all path and code examples in this porting
+guide, always replace {platform-name} with the name of
+your new platform example. Most of the examples in the guide use a `efr32` platform
+name.
+
+## Step 1: GNU Autoconf
+
+The [Autoconf](https://www.gnu.org/software/autoconf/autoconf.html) script
+contains the basic system configuration options, including specific
+platform-relative macro definitions. These macros can be exposed for
+conditional compilation in other Makefiles during the pre-compiling phase.
+
+The OpenThread Autoconf script is located at:
+[`/openthread/configure.ac`](https://github.com/openthread/openthread/blob/master/configure.ac)
+
+### Platform example name
+
+In the `AC_ARG_WITH(examples ...)` macro, add the new hardware platform example name. The name
+should be added in alphabetical order.
+
+Example:
+
+```
+AC_ARG_WITH(examples,
+ [AS_HELP_STRING([--with-examples=TARGET],
+ [Specify the examples from one of: none, simulation, cc2538, cc2650, efr32, nrf52840 @<:@default=none@:>@.])],
+ [
+ case "${with_examples}" in
+ none)
+ ;;
+ simulation|cc2538|cc2650|efr32|nrf52840)
+ if test ${enable_posix_app} = "yes"; then
+ AC_MSG_ERROR([--with-examples must be none when POSIX apps are enabled by --enable-posix-app])
+ fi
+ ;;
+ *)
+ AC_MSG_ERROR([Invalid value ${with_examples} for --with-examples])
+ ;;
+ esac
+ ],
+ [with_examples=none])
+```
+
+### Platform-specific C preprocessor symbol
+
+Define a platform-specific C preprocessor symbol for the platform example and
+expose it.
+
+The platform-specific C preprocessor symbol is exposed at
+`include/openthread-config.h`. By including the symbol in this header file, we
+can leverage it in our source code for preprocessor conditional compilation
+cases.
+
+Example:
+
+```
+case ${with_examples} in
+
+ ...
+
+ efr32)
+ OPENTHREAD_EXAMPLES_EFR32=1
+ AC_DEFINE_UNQUOTED([OPENTHREAD_EXAMPLES_EFR32],[${OPENTHREAD_EXAMPLES_EFR32}],[Define to 1 if you want to use efr32 examples])
+ ;;
+
+...
+
+esac
+
+...
+
+AC_SUBST(OPENTHREAD_EXAMPLES_EFR32)
+AM_CONDITIONAL([OPENTHREAD_EXAMPLES_EFR32], [test "${OPENTHREAD_EXAMPLES}" = "efr32"])
+```
+
+### Makefile output directory
+
+In the `AC_CONFIG_FILES` macro, add a Makefile output directory for the
+platform example.
+
+Example:
+
+```
+AC_CONFIG_FILES ([
+ examples/platforms/efr32/Makefile
+])
+```
+
+## Step 2: GNU Automake
+
+Create and modify [Automake](https://www.gnu.org/software/automake/) files to
+support the new platform example.
+
+The following platform-specific Automake files need to be created:
+
+- `/openthread/examples/Makefile-{platform-name}`
+- `/openthread/examples/platforms/{platform-name}/Makefile.am`
+- `/openthread/examples/platforms/{platform-name}/Makefile.platform.am`
+
+See [`/examples`](https://github.com/openthread/openthread/tree/master/examples/) for sample implementations of
+these files.
+
+The following Automake files also need to be updated with your platform
+information:
+
+- [`/openthread/examples/platforms/Makefile.am`](https://github.com/openthread/openthread/blob/master/examples/platforms/Makefile.am)
+- [`/openthread/examples/platforms/Makefile.platform.am`](https://github.com/openthread/openthread/blob/master/examples/platforms/Makefile.platform.am)
+
+### Linker script configuration
+
+The [GNU Linker](http://www.ece.ufrgs.br/~fetter/eng04476/manuals/ld.pdf) script
+describes how to map all sections in the input files (`.o` "object" files
+generated by the GNU Compiler Collection (GCC)) to the final output file (for
+example, `.elf`). It also determines the storage location of each segment of an
+executable program, as well as the entry address. The platform-specific linker
+script is often provided with the platform's BSP.
+
+Configure the `ld` tool to point to the platform-specific linker script using
+the `-T` option of the `LDADD_COMMON` variable.
+
+Create
+`/openthread/examples/platforms/{platform-name}/Makefile.platform.am`
+and point the new platform to its linker script:
+
+```
+if OPENTHREAD_EXAMPLES_EFR32
+ LDADD_COMMON += \
+ $(top_builddir)/examples/platforms/efr32/libopenthread-efr32.a \
+ $(top_srcdir)/third_party/silabs/gecko_sdk_suite/v1.0/platform/radio/rail_lib/autogen/librail_release/librail_efr32xg12_gcc_release.a \
+ $(NULL)
+
+LDFLAGS_COMMON += \
+ -T $(top_srcdir)/third_party/silabs/gecko_sdk_suite/v1.0/platform/Device/SiliconLabs/EFR32MG12P/Source/GCC/efr32mg12p.ld \
+ $(NULL)
+endif # OPENTHREAD_EXAMPLES_EFR32
+```
+
+Add the platform's linker script configuration to the
+[`/openthread/examples/platforms/Makefile.platform.am`](https://github.com/openthread/openthread/blob/master/examples/platforms/Makefile.platform.am)
+utility Makefile:
+
+```
+if OPENTHREAD_EXAMPLES_EFR32
+include $(top_srcdir)/examples/platforms/efr32/Makefile.platform.am
+endif
+```
+
+### Subdirectory configuration
+
+Modify [`/openthread/examples/platforms/Makefile.am`](https://github.com/openthread/openthread/blob/master/examples/platforms/Makefile.platform.am)
+to configure the package subdirectories for the new platform example.
+
+Add the platform subdirectory name in the list for `make dist`, in alphabetical
+order:
+
+```
+# Always package (e.g. for 'make dist') these subdirectories.
+
+DIST_SUBDIRS = \
+ cc2538 \
+ cc2650 \
+ efr32 \
+ nrf52840 \
+ simulation \
+ utils \
+ $(NULL)
+```
+
+Append platform subdirectory name to the `SUBDIRS` variable:
+
+```
+# Always build (e.g. for 'make all') these subdirectories.
+
+if OPENTHREAD_EXAMPLES_EFR32
+ SUBDIRS += efr32
+endif
+```
+
+### Toolchain startup code
+
+Toolchain startup code is often provided along with the platform's BSP. This
+code typically:
+
+1. Implements the entry function (`Reset_Handler`) of the executable program
+1. Defines the interrupt vector table
+1. Initializes the Heap and Stack
+1. Copies the `.data` section from non-volatile memory to RAM
+1. Jumps to the application main function to execute the application logic
+
+The startup code (C or assembly source code) must be added to the
+platform-specific `Makefile.am`, otherwise some key variables used in the linker
+script cannot be quoted correctly:
+
+- `/openthread/examples/platforms/{platform-name}/Makefile.am`
+
+Example:
+
+```
+libopenthread_efr32_a_SOURCES = \
+@top_builddir@/third_party/silabs/gecko_sdk_suite/v1.0/hardware/kit/common/bsp/bsp_bcc.c \
+@top_builddir@/third_party/silabs/gecko_sdk_suite/v1.0/hardware/kit/common/bsp/bsp_stk.c \
+@top_builddir@/third_party/silabs/gecko_sdk_suite/v1.0/platform/Device/SiliconLabs/EFR32MG12P/Source/system_efr32mg12p.c \
+@top_builddir@/third_party/silabs/gecko_sdk_suite/v1.0/platform/Device/SiliconLabs/EFR32MG12P/Source/GCC/startup_efr32mg12p.c \
+```
+
+> Note: Any non-original derivative code (for example, linker script or
+toolchain startup code) must be contained in
+[`/openthread/third_party`](https://github.com/openthread/openthread/tree/master/third_party).
diff --git a/doc/site/en/guides/porting/validate-the-port.md b/doc/site/en/guides/porting/validate-the-port.md
new file mode 100644
index 000000000..99216b05a
--- /dev/null
+++ b/doc/site/en/guides/porting/validate-the-port.md
@@ -0,0 +1,214 @@
+# Validate the Port
+
+Basic validation is necessary to verify a successful port of OpenThread to a new
+hardware platform example.
+
+## Step 1: Compile for the target platform
+
+Demonstrate a successful build by compiling the example OpenThread application
+for the target platform.
+
+```
+$ ./bootstrap
+$ make -f examples/Makefile-efr32 COMMISSIONER=1 JOINER=1
+```
+
+## Step 2: Interact with the CLI
+
+Demonstrate successful OpenThread execution and UART capability by interacting
+with the CLI.
+
+Open a terminal to `/dev/ttyACM0` (serial port settings: 115200 8-N-1). Type
+`help` for a list of commands.
+
+> Note: The set of CLI commands will vary based on the features enabled in a
+particular build. The majority of them have been elided in the example output
+below.
+
+```
+> help
+help
+autostart
+bufferinfo
+...
+version
+whitelist
+```
+
+## Step 3: Form a Thread network
+
+Demonstrate successful protocol timers by forming a Thread network and verifying
+the node has transitioned to the Leader state.
+
+```
+> dataset init new
+Done
+> dataset
+Active Timestamp: 1
+Channel: 13
+Channel Mask: 07fff800
+Ext PAN ID: d63e8e3e495ebbc3
+Mesh Local Prefix: fd3d:b50b:f96d:722d/64
+Master Key: dfd34f0f05cad978ec4e32b0413038ff
+Network Name: OpenThread-8f28
+PAN ID: 0x8f28
+PSKc: c23a76e98f1a6483639b1ac1271e2e27
+Security Policy: 0, onrcb
+Done
+> dataset commit active
+Done
+> ifconfig up
+Done
+> thread start
+Done
+```
+
+Wait a couple of seconds...
+
+```
+> state
+leader
+Done
+```
+
+## Step 4: Attach a second node
+
+Demonstrate successful radio communication by attaching a second node to the
+newly formed Thread network, using the same Thread Master Key and PAN ID from
+the first node:
+
+```
+> dataset masterkey dfd34f0f05cad978ec4e32b0413038ff
+Done
+> dataset panid 0x8f28
+Done
+> dataset commit active
+Done
+> routerselectionjitter 1
+Done
+> ifconfig up
+Done
+> thread start
+Done
+```
+
+Wait a couple of seconds...
+
+```
+> state
+router
+Done
+```
+
+## Step 5: Ping between devices
+
+Demonstrate successful data path communication by sending/receiving ICMPv6 Echo
+request/response messages.
+
+List all IPv6 addresses of Leader:
+
+```
+> ipaddr
+fdde:ad00:beef:0:0:ff:fe00:fc00
+fdde:ad00:beef:0:0:ff:fe00:800
+fdde:ad00:beef:0:5b:3bcd:deff:7786
+fe80:0:0:0:6447:6e10:cf7:ee29
+Done
+```
+
+Send an ICMPv6 ping from Router to Leader's Mesh-Local EID IPv6 address:
+
+```
+> ping fdde:ad00:beef:0:5b:3bcd:deff:7786
+16 bytes from fdde:ad00:beef:0:5b:3bcd:deff:7786: icmp_seq=1 hlim=64 time=24ms
+```
+
+## Step 6: Reset a device and validate reattachment
+
+Demonstrate non-volatile functionality by resetting the device and validating
+its reattachment to the same network without user intervention.
+
+Start a Thread network:
+
+```
+> dataset init new
+Done
+> dataset
+Active Timestamp: 1
+Channel: 13
+Channel Mask: 07fff800
+Ext PAN ID: d63e8e3e495ebbc3
+Mesh Local Prefix: fd3d:b50b:f96d:722d/64
+Master Key: dfd34f0f05cad978ec4e32b0413038ff
+Network Name: OpenThread-8f28
+PAN ID: 0x8f28
+PSKc: c23a76e98f1a6483639b1ac1271e2e27
+Security Policy: 0, onrcb
+Done
+> dataset commit active
+Done
+> ifconfig up
+Done
+> thread start
+Done
+```
+
+Wait a couple of seconds and verify that the active dataset has been stored in
+non-volatile storage:
+
+```
+> dataset active
+Active Timestamp: 1
+Channel: 13
+Channel Mask: 07fff800
+Ext PAN ID: d63e8e3e495ebbc3
+Mesh Local Prefix: fd3d:b50b:f96d:722d/64
+Master Key: dfd34f0f05cad978ec4e32b0413038ff
+Network Name: OpenThread-8f28
+PAN ID: 0x8f28
+PSKc: c23a76e98f1a6483639b1ac1271e2e27
+Security Policy: 0, onrcb
+Done
+```
+
+Reset the device:
+
+```
+> reset
+> ifconfig up
+Done
+> thread start
+Done
+```
+
+Wait a couple of seconds and verify that the device has successfully reattached
+to the network:
+
+```
+> panid
+0x8f28
+Done
+> state
+router
+Done
+```
+
+## Step 7: Verify random number generation
+
+Demonstrate random number generation by executing the `factoryreset` command and
+verifying a new random extended address.
+
+```
+> extaddr
+a660421703f3fdc3
+Done
+> factoryreset
+```
+
+Wait a couple of seconds...
+
+```
+> extaddr
+9a8ed90715a5f7b6
+Done
+```