ff: nordic: Add WDT driver for nRF91

Add implementation for WDT driver for nRF9160

Signed-off-by: Andreas Vibeto <andreas.vibeto@nordicsemi.no>
diff --git a/api-tests/platform/drivers/watchdog/nrf/nrf9160_wdt.c b/api-tests/platform/drivers/watchdog/nrf/nrf9160_wdt.c
new file mode 100644
index 0000000..f48318f
--- /dev/null
+++ b/api-tests/platform/drivers/watchdog/nrf/nrf9160_wdt.c
@@ -0,0 +1,157 @@
+ /** @file
+  * Copyright (c) 2021 Nordic Semiconductor ASA.
+  * SPDX-License-Identifier : Apache-2.0
+  *
+  * 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 "nrf_wdt.h"
+
+/* Following defines should be used for structure members */
+#define     __IM     volatile const      /*! Defines 'read only' structure member permissions */
+#define     __OM     volatile            /*! Defines 'write only' structure member permissions */
+#define     __IOM    volatile            /*! Defines 'read / write' structure member permissions */
+
+/**
+  * @brief Watchdog Timer
+  */
+struct NRF_WDT_Type {                           /*!< (@ 0x40018000) WDT_NS Structure                                           */
+  __OM  uint32_t  TASKS_START;                  /*!< (@ 0x00000000) Start the watchdog                                         */
+  __IM  uint32_t  RESERVED[31];
+  __IOM uint32_t  SUBSCRIBE_START;              /*!< (@ 0x00000080) Subscribe configuration for task START                     */
+  __IM  uint32_t  RESERVED1[31];
+  __IOM uint32_t  EVENTS_TIMEOUT;               /*!< (@ 0x00000100) Watchdog timeout                                           */
+  __IM  uint32_t  RESERVED2[31];
+  __IOM uint32_t  PUBLISH_TIMEOUT;              /*!< (@ 0x00000180) Publish configuration for event TIMEOUT                    */
+  __IM  uint32_t  RESERVED3[96];
+  __IOM uint32_t  INTENSET;                     /*!< (@ 0x00000304) Enable interrupt                                           */
+  __IOM uint32_t  INTENCLR;                     /*!< (@ 0x00000308) Disable interrupt                                          */
+  __IM  uint32_t  RESERVED4[61];
+  __IM  uint32_t  RUNSTATUS;                    /*!< (@ 0x00000400) Run status                                                 */
+  __IM  uint32_t  REQSTATUS;                    /*!< (@ 0x00000404) Request status                                             */
+  __IM  uint32_t  RESERVED5[63];
+  __IOM uint32_t  CRV;                          /*!< (@ 0x00000504) Counter reload value                                       */
+  __IOM uint32_t  RREN;                         /*!< (@ 0x00000508) Enable register for reload request registers               */
+  __IOM uint32_t  CONFIG;                       /*!< (@ 0x0000050C) Configuration register                                     */
+  __IM  uint32_t  RESERVED6[60];
+  __OM  uint32_t  RR[8];                        /*!< (@ 0x00000600) Description collection: Reload request n                   */
+};          
+
+/* Register: WDT_CONFIG */
+/* Description: Configuration register */
+#define WDT_CONFIG_SLEEP_Pos (0UL) /*!< Position of SLEEP field. */
+#define WDT_CONFIG_SLEEP_Pause (0UL) /*!< Pause WDT while the CPU is sleeping */
+#define WDT_CONFIG_SLEEP_Run (1UL) /*!< Keep WDT running while the CPU is sleeping */
+
+/* Register: WDT_RUNSTATUS */
+/* Description: Run status */
+#define WDT_RUNSTATUS_RUNSTATUSWDT_Pos (0UL) /*!< Position of RUNSTATUSWDT field. */
+#define WDT_RUNSTATUS_RUNSTATUSWDT_Msk (0x1UL << WDT_RUNSTATUS_RUNSTATUSWDT_Pos) /*!< Bit mask of RUNSTATUSWDT field. */
+#define WDT_RUNSTATUS_RUNSTATUSWDT_NotRunning (0UL) /*!< Watchdog is not running */
+#define WDT_RUNSTATUS_RUNSTATUSWDT_Running (1UL) /*!< Watchdog is running */
+
+/**
+    @brief           - Initializes an hardware watchdog timer
+    @param           - base_addr       : Base address of the watchdog module
+                     - time_us         : Time in micro seconds
+    @return          - SUCCESS, FAILURE
+**/
+int nrf_wdt_init(addr_t base_addr, uint32_t time_us)
+{
+    struct NRF_WDT_Type *nrf_wdt = (struct NRF_WDT_Type*)base_addr;
+
+    /* The FF framework is written with the assumption that the watchdog timer
+     * can be stopped and reconfigured, but this is not possible on the nRF91.
+     * Therefore, the timeout value will only be written to the timer before
+     * the timer is enabled. It is recommended to only use the highest duration
+     * needed for the timeout value for all tests, as using a shorter duration
+     * might result in an unexpected timeout.
+     */
+    if (!nrf_wdt_is_enabled(base_addr)) {
+        /* From nRF91 documentation, the timeout in seconds is
+        *       timeout [s] = (CRV + 1) / 32768
+        */
+        uint32_t ticks = ((time_us / 1000000) * 32768) - 1;
+
+        if ((ticks >= 0xFFFFFFFFUL) || (ticks < 0xFUL))
+        {
+            // Maximum and minimum values defined in nRF91 documentation
+            return PAL_STATUS_ERROR;
+        }
+
+        nrf_wdt->CRV = ticks;
+
+        // Enable Stop and keep the watchdog running while CPU is sleeping
+        nrf_wdt->CONFIG = (WDT_CONFIG_SLEEP_Run << WDT_CONFIG_SLEEP_Pos);
+
+        // Enable the reload request register to allow reloading the timer
+        nrf_wdt->RREN = 0x01UL;
+    }
+
+    return PAL_STATUS_SUCCESS;
+}
+
+/**
+    @brief           - Enables a hardware watchdog timer
+    @param           - base_addr       : Base address of the watchdog module
+    @return          - SUCCESS, FAILURE
+**/
+int nrf_wdt_enable(addr_t base_addr)
+{
+    struct NRF_WDT_Type *nrf_wdt = (struct NRF_WDT_Type*)base_addr;
+    
+    if (!nrf_wdt_is_enabled(base_addr)) {
+        nrf_wdt->TASKS_START = 0x01UL; // Trigger start task
+    } else {
+        /* If the timer has already been started reload the timer instead of
+         * triggering the start task, as the start task will not do anything
+         * once the timer has already been started.
+         */
+        nrf_wdt->RR[0] = 0x6E524635UL; // Reload WDT
+    }
+
+    return PAL_STATUS_SUCCESS;
+}
+
+/**
+    @brief           - Disables a hardware watchdog timer
+    @param           - base_addr       : Base address of the watchdog module
+    @return          - SUCCESS, FAILURE
+**/
+int nrf_wdt_disable(addr_t base_addr)
+{
+    struct NRF_WDT_Type *nrf_wdt = (struct NRF_WDT_Type*)base_addr;
+
+    /* As the nRF91 WDT cannot be stopped, the timer will be reloaded to the
+     * value in the CRV register. This should work in all cases, as the timer
+     * will be reloaded at the beginning of each test case, and the time it
+     * takes to tear down and set up a new test case should never exceed the
+     * timeout duration.
+     */
+    if (nrf_wdt_is_enabled(base_addr)) {
+        nrf_wdt->RR[0] = 0x6E524635UL;
+    }
+
+    return PAL_STATUS_SUCCESS;
+}
+
+/**
+    @brief           - Checks whether hardware watchdog timer is enabled
+    @param           - base_addr       : Base address of the watchdog module
+    @return          - Enabled : 1, Disabled : 0
+**/
+int nrf_wdt_is_enabled(addr_t base_addr)
+{
+    struct NRF_WDT_Type *nrf_wdt = (struct NRF_WDT_Type*)base_addr;
+    return (nrf_wdt->RUNSTATUS & WDT_RUNSTATUS_RUNSTATUSWDT_Msk);
+}
diff --git a/api-tests/platform/drivers/watchdog/nrf/nrf5340/nrf_wdt.c b/api-tests/platform/drivers/watchdog/nrf/nrf_wdt.c
similarity index 100%
rename from api-tests/platform/drivers/watchdog/nrf/nrf5340/nrf_wdt.c
rename to api-tests/platform/drivers/watchdog/nrf/nrf_wdt.c
diff --git a/api-tests/platform/targets/tgt_ff_tfm_nrf9160/target.cfg b/api-tests/platform/targets/tgt_ff_tfm_nrf9160/target.cfg
index a52f3c0..c7c3ca5 100644
--- a/api-tests/platform/targets/tgt_ff_tfm_nrf9160/target.cfg
+++ b/api-tests/platform/targets/tgt_ff_tfm_nrf9160/target.cfg
@@ -24,12 +24,14 @@
 
 // Watchdog device info
 watchdog.num = 1;
-watchdog.0.base = 0; // Unused value
+watchdog.0.base = 0x50018000;
 watchdog.0.num_of_tick_per_micro_sec = 1;
-watchdog.0.timeout_in_micro_sec_low = 60000000; // 60 secs
-watchdog.0.timeout_in_micro_sec_medium = 60000000;  // 60 secs
-watchdog.0.timeout_in_micro_sec_high = 60000000; // 60 secs
-watchdog.0.timeout_in_micro_sec_crypto = 60000000; // 60 secs
+// The same value should be used for all timeout durations, as the nRF91
+// WDT cannot be reconfigured once it has been started.
+watchdog.0.timeout_in_micro_sec_low = 18000000; // 18 secs
+watchdog.0.timeout_in_micro_sec_medium = 18000000;  // 18 secs
+watchdog.0.timeout_in_micro_sec_high = 18000000; // 18 secs
+watchdog.0.timeout_in_micro_sec_crypto = 18000000; // 18 secs
 
 // Range of 1KB Non-volatile memory to preserve data over reset. Ex, NVRAM and FLASH
 nvmem.num =1;
diff --git a/api-tests/platform/targets/tgt_ff_tfm_nrf9160/target.cmake b/api-tests/platform/targets/tgt_ff_tfm_nrf9160/target.cmake
index 960c0db..a008c46 100644
--- a/api-tests/platform/targets/tgt_ff_tfm_nrf9160/target.cmake
+++ b/api-tests/platform/targets/tgt_ff_tfm_nrf9160/target.cmake
@@ -18,6 +18,4 @@
 # * limitations under the License.
 #**/
 
-set(WATCHDOG_AVAILABLE 0)
-
 include(${PSA_ROOT_DIR}/platform/targets/tgt_ff_tfm_nrf_common/target.cmake)
diff --git a/api-tests/platform/targets/tgt_ff_tfm_nrf_common/target.cmake b/api-tests/platform/targets/tgt_ff_tfm_nrf_common/target.cmake
index adeb37e..99d68a1 100644
--- a/api-tests/platform/targets/tgt_ff_tfm_nrf_common/target.cmake
+++ b/api-tests/platform/targets/tgt_ff_tfm_nrf_common/target.cmake
@@ -43,8 +43,18 @@
 		# Driver files will be compiled as part of driver partition
 		${PSA_ROOT_DIR}/platform/targets/tgt_ff_tfm_nrf_common/spe/pal_driver_intf.c
 		${PSA_ROOT_DIR}/platform/drivers/nvmem/pal_nvmem.c
-		${PSA_ROOT_DIR}/platform/drivers/watchdog/nrf/${PSA_API_TEST_TARGET}/nrf_wdt.c
 	)
+
+	if(${PSA_API_TEST_TARGET} STREQUAL nrf9160)
+		list(APPEND PAL_SRC_C_DRIVER_SP
+			${PSA_ROOT_DIR}/platform/drivers/watchdog/nrf/nrf9160_wdt.c
+		)
+	else()
+		list(APPEND PAL_SRC_C_DRIVER_SP
+			${PSA_ROOT_DIR}/platform/drivers/watchdog/nrf/nrf_wdt.c
+		)
+	endif()
+
 endif()
 
 if((${SUITE} STREQUAL "CRYPTO") OR