This is an automated email from the ASF dual-hosted git repository.

acassis pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/nuttx.git

commit 8d2451da0cc3f2ab1becc892443165dbbd0bc4b1
Author: raiden00pl <[email protected]>
AuthorDate: Mon Mar 13 12:41:29 2023 +0100

    arch/nrf53: add TIM support
---
 arch/arm/src/nrf53/Kconfig               |  20 +
 arch/arm/src/nrf53/Make.defs             |   7 +
 arch/arm/src/nrf53/nrf53_tim.c           | 857 +++++++++++++++++++++++++++++++
 arch/arm/src/nrf53/nrf53_tim.h           | 172 +++++++
 arch/arm/src/nrf53/nrf53_tim_lowerhalf.c | 538 +++++++++++++++++++
 arch/arm/src/nrf53/nrf53_tim_lowerhalf.h |  42 ++
 6 files changed, 1636 insertions(+)

diff --git a/arch/arm/src/nrf53/Kconfig b/arch/arm/src/nrf53/Kconfig
index d1bf7849c5..607848c9b7 100644
--- a/arch/arm/src/nrf53/Kconfig
+++ b/arch/arm/src/nrf53/Kconfig
@@ -76,6 +76,10 @@ config NRF53_UART
        bool
        default n
 
+config NRF53_TIMER
+       bool
+       default n
+
 menu "NRF53 Peripheral Selection"
 
 config NRF53_UART0
@@ -90,6 +94,22 @@ config NRF53_UART1
        select UART1_SERIALDRIVER
        select NRF53_UART
 
+config NRF53_TIMER0
+       bool "TIMER0"
+       select NRF53_TIMER
+       depends on !NRF53_SOFTDEVICE_CONTROLLER
+       default n
+
+config NRF53_TIMER1
+       bool "TIMER1"
+       select NRF53_TIMER
+       default n
+
+config NRF53_TIMER2
+       bool "TIMER2"
+       select NRF53_TIMER
+       default n
+
 endmenu # NRF53 Peripheral Selection
 
 menu "Clock Configuration"
diff --git a/arch/arm/src/nrf53/Make.defs b/arch/arm/src/nrf53/Make.defs
index 659da945dd..35d9159adf 100644
--- a/arch/arm/src/nrf53/Make.defs
+++ b/arch/arm/src/nrf53/Make.defs
@@ -51,6 +51,13 @@ ifeq ($(CONFIG_RPTUN),y)
 CHIP_CSRCS += nrf53_rptun.c
 endif
 
+ifeq ($(CONFIG_NRF53_TIMER),y)
+CHIP_CSRCS += nrf53_tim.c
+ifeq ($(CONFIG_TIMER),y)
+CHIP_CSRCS += nrf53_tim_lowerhalf.c
+endif
+endif
+
 ifeq ($(CONFIG_PM),y)
 CHIP_CSRCS += nrf53_pminitialize.c
 endif
diff --git a/arch/arm/src/nrf53/nrf53_tim.c b/arch/arm/src/nrf53/nrf53_tim.c
new file mode 100644
index 0000000000..c822f2e86f
--- /dev/null
+++ b/arch/arm/src/nrf53/nrf53_tim.c
@@ -0,0 +1,857 @@
+/****************************************************************************
+ * arch/arm/src/nrf53/nrf53_tim.c
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.  The
+ * ASF licenses this file to you 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.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+#include <assert.h>
+#include <debug.h>
+
+#include <nuttx/arch.h>
+#include <nuttx/irq.h>
+
+#include "arm_internal.h"
+#include "hardware/nrf53_tim.h"
+
+#include "nrf53_tim.h"
+
+/****************************************************************************
+ * Private Types
+ ****************************************************************************/
+
+struct nrf53_tim_priv_s
+{
+  struct nrf53_tim_ops_s *ops;
+  uint32_t                base;
+  uint32_t                irq;
+  uint8_t                 chan;
+  bool                    inuse;
+};
+
+/****************************************************************************
+ * Private Function Prototypes
+ ****************************************************************************/
+
+/* TIM registers access *****************************************************/
+
+static uint32_t nrf53_tim_getreg(struct nrf53_tim_dev_s *dev,
+                                 uint32_t offset);
+static void nrf53_tim_putreg(struct nrf53_tim_dev_s *dev,
+                             uint32_t offset,
+                             uint32_t value);
+
+/* TIM helpers **************************************************************/
+
+static uint32_t nrf53_tim_irq2reg(struct nrf53_tim_dev_s *dev,
+                                  uint8_t s);
+
+/* TIM operations ***********************************************************/
+
+static int nrf53_tim_start(struct nrf53_tim_dev_s *dev);
+static int nrf53_tim_stop(struct nrf53_tim_dev_s *dev);
+static int nrf53_tim_clear(struct nrf53_tim_dev_s *dev);
+static int nrf53_tim_configure(struct nrf53_tim_dev_s *dev, uint8_t mode,
+                               uint8_t width);
+static int nrf53_tim_shorts(struct nrf53_tim_dev_s *dev, uint8_t s,
+                            uint8_t i, bool en);
+static int nrf53_tim_count(struct nrf53_tim_dev_s *dev);
+static int nrf53_tim_setcc(struct nrf53_tim_dev_s *dev, uint8_t i,
+                           uint32_t cc);
+static int nrf53_tim_getcc(struct nrf53_tim_dev_s *dev, uint8_t i,
+                           uint32_t *cc);
+static int nrf53_tim_setpre(struct nrf53_tim_dev_s *dev, uint8_t pre);
+static int nrf53_tim_setisr(struct nrf53_tim_dev_s *dev, xcpt_t handler,
+                            void * arg);
+static int nrf53_tim_enableint(struct nrf53_tim_dev_s *dev, uint8_t s);
+static int nrf53_tim_disableint(struct nrf53_tim_dev_s *dev, uint8_t s);
+static int nrf53_tim_checkint(struct nrf53_tim_dev_s *dev, uint8_t s);
+static int nrf53_tim_ackint(struct nrf53_tim_dev_s *dev, uint8_t s);
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+/* NRF53 TIM ops */
+
+struct nrf53_tim_ops_s nrf53_tim_ops =
+{
+  .start      = nrf53_tim_start,
+  .stop       = nrf53_tim_stop,
+  .clear      = nrf53_tim_clear,
+  .configure  = nrf53_tim_configure,
+  .shorts     = nrf53_tim_shorts,
+  .count      = nrf53_tim_count,
+  .setcc      = nrf53_tim_setcc,
+  .getcc      = nrf53_tim_getcc,
+  .setpre     = nrf53_tim_setpre,
+  .setisr     = nrf53_tim_setisr,
+  .enableint  = nrf53_tim_enableint,
+  .disableint = nrf53_tim_disableint,
+  .checkint   = nrf53_tim_checkint,
+  .ackint     = nrf53_tim_ackint
+};
+
+#ifdef CONFIG_NRF53_TIMER0
+/* TIMER0 */
+
+struct nrf53_tim_priv_s g_nrf53_tim0_priv =
+{
+  .ops   = &nrf53_tim_ops,
+  .base  = NRF53_TIMER0_BASE,
+  .irq   = NRF53_IRQ_TIMER0,
+  .chan  = 4,
+  .inuse = false,
+};
+#endif
+
+#ifdef CONFIG_NRF53_TIMER1
+/* TIMER1 */
+
+struct nrf53_tim_priv_s g_nrf53_tim1_priv =
+{
+  .ops   = &nrf53_tim_ops,
+  .base  = NRF53_TIMER1_BASE,
+  .irq   = NRF53_IRQ_TIMER1,
+  .chan  = 4,
+  .inuse = false,
+};
+#endif
+
+#ifdef CONFIG_NRF53_TIMER2
+/* TIMER2 */
+
+struct nrf53_tim_priv_s g_nrf53_tim2_priv =
+{
+  .ops   = &nrf53_tim_ops,
+  .base  = NRF53_TIMER2_BASE,
+  .irq   = NRF53_IRQ_TIMER2,
+  .chan  = 4,
+  .inuse = false,
+};
+#endif
+
+#ifdef CONFIG_NRF53_TIMER3
+/* TIMER3 */
+
+struct nrf53_tim_priv_s g_nrf53_tim3_priv =
+{
+  .ops   = &nrf53_tim_ops,
+  .base  = NRF53_TIMER3_BASE,
+  .irq   = NRF53_IRQ_TIMER3,
+  .chan  = 6,
+  .inuse = false,
+};
+#endif
+
+#ifdef CONFIG_NRF53_TIMER4
+/* TIMER4 */
+
+struct nrf53_tim_priv_s g_nrf53_tim4_priv =
+{
+  .ops   = &nrf53_tim_ops,
+  .base  = NRF53_TIMER4_BASE,
+  .irq   = NRF53_IRQ_TIMER4,
+  .chan  = 6,
+  .inuse = false,
+};
+#endif
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: nrf53_tim_getreg
+ *
+ * Description:
+ *   Get a 32-bit register value by offset
+ *
+ ****************************************************************************/
+
+static uint32_t nrf53_tim_getreg(struct nrf53_tim_dev_s *dev,
+                                 uint32_t offset)
+{
+  DEBUGASSERT(dev);
+
+  return getreg32(((struct nrf53_tim_priv_s *)dev)->base + offset);
+}
+
+/****************************************************************************
+ * Name: nrf53_tim_putreg
+ *
+ * Description:
+ *   Put a 32-bit register value by offset
+ *
+ ****************************************************************************/
+
+static void nrf53_tim_putreg(struct nrf53_tim_dev_s *dev,
+                             uint32_t offset,
+                             uint32_t value)
+{
+  DEBUGASSERT(dev);
+
+  putreg32(value, ((struct nrf53_tim_priv_s *)dev)->base + offset);
+}
+
+/****************************************************************************
+ * Name: nrf53_tim_irq2reg
+ *
+ * Description:
+ *   Get the value of the interrupt register corresponding to the given
+ *   interrupt source
+ *
+ ****************************************************************************/
+
+static uint32_t nrf53_tim_irq2reg(struct nrf53_tim_dev_s *dev, uint8_t s)
+{
+  uint32_t regval = 0;
+
+  switch (s)
+    {
+      case NRF53_TIM_INT_COMPARE0:
+        {
+          regval = TIM_INT_COMPARE(0);
+          break;
+        }
+
+      case NRF53_TIM_INT_COMPARE1:
+        {
+          regval = TIM_INT_COMPARE(1);
+          break;
+        }
+
+      case NRF53_TIM_INT_COMPARE2:
+        {
+          regval = TIM_INT_COMPARE(2);
+          break;
+        }
+
+      case NRF53_TIM_INT_COMPARE3:
+        {
+          regval = TIM_INT_COMPARE(3);
+          break;
+        }
+
+      case NRF53_TIM_INT_COMPARE4:
+        {
+          regval = TIM_INT_COMPARE(4);
+          break;
+        }
+
+      case NRF53_TIM_INT_COMPARE5:
+        {
+          regval = TIM_INT_COMPARE(5);
+          break;
+        }
+
+      default:
+        {
+          tmrerr("ERROR: unsupported IRQ source %d\n", s);
+          regval = 0;
+          goto errout;
+        }
+    }
+
+errout:
+  return regval;
+}
+
+/****************************************************************************
+ * Name: nrf53_tim_start
+ ****************************************************************************/
+
+static int nrf53_tim_start(struct nrf53_tim_dev_s *dev)
+{
+  DEBUGASSERT(dev);
+
+  nrf53_tim_putreg(dev, NRF53_TIM_TASKS_START_OFFSET, TIM_TASKS_START);
+
+  return OK;
+}
+
+/****************************************************************************
+ * Name: nrf53_tim_stop
+ ****************************************************************************/
+
+static int nrf53_tim_stop(struct nrf53_tim_dev_s *dev)
+{
+  DEBUGASSERT(dev);
+
+  nrf53_tim_putreg(dev, NRF53_TIM_TASKS_STOP_OFFSET, TIM_TASKS_STOP);
+
+  return OK;
+}
+
+/****************************************************************************
+ * Name: nrf53_tim_clear
+ ****************************************************************************/
+
+static int nrf53_tim_clear(struct nrf53_tim_dev_s *dev)
+{
+  DEBUGASSERT(dev);
+
+  nrf53_tim_putreg(dev, NRF53_TIM_TASKS_CLEAR_OFFSET, TIM_TASKS_CLEAR);
+
+  return OK;
+}
+
+/****************************************************************************
+ * Name: nrf53_tim_configure
+ ****************************************************************************/
+
+static int nrf53_tim_configure(struct nrf53_tim_dev_s *dev, uint8_t mode,
+                               uint8_t width)
+{
+  uint32_t regval = 0;
+  int      ret    = OK;
+
+  DEBUGASSERT(dev);
+
+  /* Configure TIMER mode */
+
+  switch (mode)
+    {
+      case NRF53_TIM_MODE_UNUSED:
+        {
+          regval = 0;
+          break;
+        }
+
+      case NRF53_TIM_MODE_TIMER:
+        {
+          regval = TIM_MODE_TIMER;
+          break;
+        }
+
+      case NRF53_TIM_MODE_COUNTER:
+        {
+          regval = TIM_MODE_COUNTER;
+          break;
+        }
+
+      case NRF53_TIM_MODE_LOWPOWER:
+        {
+          regval = TIM_MODE_LPCOUNTER;
+          break;
+        }
+
+      default:
+        {
+          tmrerr("ERROR: unsupported TIMER mode %d\n", mode);
+          ret = -EINVAL;
+          goto errout;
+        }
+    }
+
+  nrf53_tim_putreg(dev, NRF53_TIM_MODE_OFFSET, regval);
+
+  /* Configure TIMER width */
+
+  switch (width)
+    {
+      case NRF53_TIM_WIDTH_16B:
+        {
+          regval = TIM_BITMODE_16B;
+          break;
+        }
+
+      case NRF53_TIM_WIDTH_8B:
+        {
+          regval = TIM_BITMODE_8B;
+          break;
+        }
+
+      case NRF53_TIM_WIDTH_24B:
+        {
+          regval = TIM_BITMODE_24B;
+          break;
+        }
+
+      case NRF53_TIM_WIDTH_32B:
+        {
+          regval = TIM_BITMODE_32B;
+          break;
+        }
+
+      default:
+        {
+          tmrerr("ERROR: unsupported TIMER width %d\n", width);
+          ret = -EINVAL;
+          goto errout;
+        }
+    }
+
+  nrf53_tim_putreg(dev, NRF53_TIM_BITMODE_OFFSET, regval);
+
+errout:
+  return ret;
+}
+
+/****************************************************************************
+ * Name: nrf53_tim_shorts
+ ****************************************************************************/
+
+static int nrf53_tim_shorts(struct nrf53_tim_dev_s *dev, uint8_t s,
+                            uint8_t i, bool en)
+{
+  uint32_t regval = 0;
+  uint32_t val    = 0;
+  int      ret    = OK;
+
+  regval = nrf53_tim_getreg(dev, NRF53_TIM_SHORTS_OFFSET);
+
+  switch (s)
+    {
+      case NRF53_TIM_SHORT_COMPARE_CLEAR:
+        {
+          val = TIM_SHORTS_COMPARE_CLEAR(i);
+          break;
+        }
+
+      case NRF53_TIM_SHORT_COMPARE_STOP:
+        {
+          val = TIM_SHORTS_COMPARE_STOP(i);
+          break;
+        }
+
+      default:
+        {
+          tmrerr("ERROR: unsupported SHORT %d\n", s);
+          ret = -EINVAL;
+          goto errout;
+        }
+    }
+
+  if (en == true)
+    {
+      regval |= val;
+    }
+  else
+    {
+      regval &= ~val;
+    }
+
+  nrf53_tim_putreg(dev, NRF53_TIM_SHORTS_OFFSET, regval);
+
+errout:
+  return ret;
+}
+
+/****************************************************************************
+ * Name: nrf53_tim_count
+ ****************************************************************************/
+
+static int nrf53_tim_count(struct nrf53_tim_dev_s *dev)
+{
+  DEBUGASSERT(dev);
+
+  nrf53_tim_putreg(dev, NRF53_TIM_TASKS_COUNT_OFFSET, TIM_TASKS_COUNT);
+
+  return OK;
+}
+
+/****************************************************************************
+ * Name: nrf53_tim_setcc
+ ****************************************************************************/
+
+static int nrf53_tim_setcc(struct nrf53_tim_dev_s *dev, uint8_t i,
+                           uint32_t cc)
+{
+  struct nrf53_tim_priv_s *tim = NULL;
+  int ret = OK;
+
+  DEBUGASSERT(dev);
+
+  tim = (struct nrf53_tim_priv_s *)dev;
+
+  /* Is the channel supported? */
+
+  if (i > tim->chan)
+    {
+      tmrerr("ERROR: unsupported TIMER channel %d\n", i);
+      ret = -EINVAL;
+      goto errout;
+    }
+
+  nrf53_tim_putreg(dev, NRF53_TIM_CC_OFFSET(i), cc);
+
+errout:
+  return ret;
+}
+
+/****************************************************************************
+ * Name: nrf53_tim_getcc
+ ****************************************************************************/
+
+static int nrf53_tim_getcc(struct nrf53_tim_dev_s *dev, uint8_t i,
+                           uint32_t *cc)
+{
+  struct nrf53_tim_priv_s *tim = NULL;
+  int ret = OK;
+
+  DEBUGASSERT(dev);
+  DEBUGASSERT(cc);
+
+  tim = (struct nrf53_tim_priv_s *)dev;
+
+  /* Is the channel supported? */
+
+  if (i > tim->chan)
+    {
+      tmrerr("ERROR: unsupported TIMER channel %d\n", i);
+      ret = -EINVAL;
+      goto errout;
+    }
+
+  *cc = nrf53_tim_getreg(dev, NRF53_TIM_CC_OFFSET(i));
+
+errout:
+  return ret;
+}
+
+/****************************************************************************
+ * Name: nrf53_tim_setpre
+ ****************************************************************************/
+
+static int nrf53_tim_setpre(struct nrf53_tim_dev_s *dev, uint8_t pre)
+{
+  int ret = OK;
+
+  DEBUGASSERT(dev);
+
+  if (pre < NRF53_TIM_PRE_16000000 || pre > NRF53_TIM_PRE_31250)
+    {
+      tmrerr("ERROR: unsupported TIMER prescaler %d\n", pre);
+      ret = -EINVAL;
+      goto errout;
+    }
+
+  nrf53_tim_putreg(dev, NRF53_TIM_PRESCALER_OFFSET, pre);
+
+errout:
+  return ret;
+}
+
+/****************************************************************************
+ * Name: nrf53_tim_setisr
+ ****************************************************************************/
+
+static int nrf53_tim_setisr(struct nrf53_tim_dev_s *dev, xcpt_t handler,
+                            void *arg)
+{
+  struct nrf53_tim_priv_s *tim = NULL;
+  int ret = OK;
+
+  DEBUGASSERT(dev);
+
+  tim = (struct nrf53_tim_priv_s *)dev;
+
+  /* Disable interrupt when callback is removed */
+
+  if (!handler)
+    {
+      up_disable_irq(tim->irq);
+      irq_detach(tim->irq);
+      ret = OK;
+      goto errout;
+    }
+
+  /* Otherwise set callback and enable interrupt */
+
+  irq_attach(tim->irq, handler, arg);
+  up_enable_irq(tim->irq);
+
+errout:
+  return ret;
+}
+
+/****************************************************************************
+ * Name: nrf53_tim_enableint
+ ****************************************************************************/
+
+static int nrf53_tim_enableint(struct nrf53_tim_dev_s *dev, uint8_t s)
+{
+  uint32_t regval = 0;
+  int      ret    = OK;
+
+  DEBUGASSERT(dev);
+
+  /* Get register value for given interrupt source */
+
+  regval = nrf53_tim_irq2reg(dev, s);
+  if (regval == 0)
+    {
+      ret = -EINVAL;
+      goto errout;
+    }
+
+  nrf53_tim_putreg(dev, NRF53_TIM_INTENSET_OFFSET, regval);
+
+errout:
+  return ret;
+}
+
+/****************************************************************************
+ * Name: nrf53_tim_disableint
+ ****************************************************************************/
+
+static int nrf53_tim_disableint(struct nrf53_tim_dev_s *dev, uint8_t s)
+{
+  uint32_t regval = 0;
+  int      ret    = OK;
+
+  DEBUGASSERT(dev);
+
+  /* Get register value for given interrupt source */
+
+  regval = nrf53_tim_irq2reg(dev, s);
+  if (regval == 0)
+    {
+      ret = -EINVAL;
+      goto errout;
+    }
+
+  nrf53_tim_putreg(dev, NRF53_TIM_INTCLR_OFFSET, regval);
+
+errout:
+  return ret;
+}
+
+/****************************************************************************
+ * Name: nrf53_tim_checkint
+ ****************************************************************************/
+
+static int nrf53_tim_checkint(struct nrf53_tim_dev_s *dev, uint8_t s)
+{
+  int ret = 0;
+
+  DEBUGASSERT(dev);
+
+  switch (s)
+    {
+      case NRF53_TIM_INT_COMPARE0:
+        {
+          ret = nrf53_tim_getreg(dev, NRF53_TIM_EVENTS_COMPARE_OFFSET(0));
+          break;
+        }
+
+      case NRF53_TIM_INT_COMPARE1:
+        {
+          ret = nrf53_tim_getreg(dev, NRF53_TIM_EVENTS_COMPARE_OFFSET(0));
+          break;
+        }
+
+      case NRF53_TIM_INT_COMPARE2:
+        {
+          ret = nrf53_tim_getreg(dev, NRF53_TIM_EVENTS_COMPARE_OFFSET(2));
+          break;
+        }
+
+      case NRF53_TIM_INT_COMPARE3:
+        {
+          ret = nrf53_tim_getreg(dev, NRF53_TIM_EVENTS_COMPARE_OFFSET(3));
+          break;
+        }
+
+      case NRF53_TIM_INT_COMPARE4:
+        {
+          ret = nrf53_tim_getreg(dev, NRF53_TIM_EVENTS_COMPARE_OFFSET(4));
+          break;
+        }
+
+      case NRF53_TIM_INT_COMPARE5:
+        {
+          ret = nrf53_tim_getreg(dev, NRF53_TIM_EVENTS_COMPARE_OFFSET(5));
+          break;
+        }
+
+      default:
+        {
+          tmrerr("ERROR: unsupported IRQ source %d\n", s);
+          ret = -EINVAL;
+          goto errout;
+        }
+    }
+
+errout:
+  return ret;
+}
+
+/****************************************************************************
+ * Name: nrf53_tim_ackint
+ ****************************************************************************/
+
+static int nrf53_tim_ackint(struct nrf53_tim_dev_s *dev, uint8_t s)
+{
+  int ret = 0;
+
+  DEBUGASSERT(dev);
+
+  switch (s)
+    {
+      case NRF53_TIM_INT_COMPARE0:
+        {
+          nrf53_tim_putreg(dev, NRF53_TIM_EVENTS_COMPARE_OFFSET(0), 0);
+          break;
+        }
+
+      case NRF53_TIM_INT_COMPARE1:
+        {
+          nrf53_tim_putreg(dev, NRF53_TIM_EVENTS_COMPARE_OFFSET(1), 0);
+          break;
+        }
+
+      case NRF53_TIM_INT_COMPARE2:
+        {
+          nrf53_tim_putreg(dev, NRF53_TIM_EVENTS_COMPARE_OFFSET(2), 0);
+          break;
+        }
+
+      case NRF53_TIM_INT_COMPARE3:
+        {
+          nrf53_tim_putreg(dev, NRF53_TIM_EVENTS_COMPARE_OFFSET(3), 0);
+          break;
+        }
+
+      case NRF53_TIM_INT_COMPARE4:
+        {
+          nrf53_tim_putreg(dev, NRF53_TIM_EVENTS_COMPARE_OFFSET(4), 0);
+          break;
+        }
+
+      case NRF53_TIM_INT_COMPARE5:
+        {
+          nrf53_tim_putreg(dev, NRF53_TIM_EVENTS_COMPARE_OFFSET(5), 0);
+          break;
+        }
+
+      default:
+        {
+          tmrerr("ERROR: unsupported IRQ source %d\n", s);
+          ret = -EINVAL;
+          goto errout;
+        }
+    }
+
+errout:
+  return ret;
+}
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: nrf53_tim_init
+ *
+ * Description:
+ *   Initialize TIMER device
+ *
+ ****************************************************************************/
+
+struct nrf53_tim_dev_s *nrf53_tim_init(int timer)
+{
+  struct nrf53_tim_priv_s *tim = NULL;
+
+  /* Get timer instance */
+
+  switch (timer)
+    {
+#ifdef CONFIG_NRF53_TIMER0
+      case 0:
+        {
+          tim = &g_nrf53_tim0_priv;
+          break;
+        }
+#endif
+
+#ifdef CONFIG_NRF53_TIMER1
+      case 1:
+        {
+          tim = &g_nrf53_tim1_priv;
+          break;
+        }
+#endif
+
+#ifdef CONFIG_NRF53_TIMER2
+      case 2:
+        {
+          tim = &g_nrf53_tim2_priv;
+          break;
+        }
+#endif
+
+#ifdef CONFIG_NRF53_TIMER3
+      case 3:
+        {
+          tim = &g_nrf53_tim3_priv;
+          break;
+        }
+#endif
+
+#ifdef CONFIG_NRF53_TIMER4
+      case 4:
+        {
+          tim = &g_nrf53_tim4_priv;
+          break;
+        }
+#endif
+
+      default:
+        {
+          tmrerr("ERROR: unsupported TIMER %d\n", timer);
+          goto errout;
+        }
+    }
+
+  if (tim->inuse != false)
+    {
+      /* Timer already in use */
+
+      tim = NULL;
+    }
+
+errout:
+  return (struct nrf53_tim_dev_s *)tim;
+}
+
+/****************************************************************************
+ * Name: nrf53_tim_deinit
+ *
+ * Description:
+ *   Deinit TIMER device
+ *
+ ****************************************************************************/
+
+int nrf53_tim_deinit(struct nrf53_tim_dev_s *dev)
+{
+  struct nrf53_tim_priv_s *tim = NULL;
+
+  DEBUGASSERT(dev);
+
+  tim = (struct nrf53_tim_priv_s *)dev;
+
+  tim->inuse = false;
+
+  return OK;
+}
diff --git a/arch/arm/src/nrf53/nrf53_tim.h b/arch/arm/src/nrf53/nrf53_tim.h
new file mode 100644
index 0000000000..1e0841922c
--- /dev/null
+++ b/arch/arm/src/nrf53/nrf53_tim.h
@@ -0,0 +1,172 @@
+/****************************************************************************
+ * arch/arm/src/nrf53/nrf53_tim.h
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.  The
+ * ASF licenses this file to you 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 __ARCH_ARM_SRC_NRF53_NRF53_TIM_H
+#define __ARCH_ARM_SRC_NRF53_NRF53_TIM_H
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+#include <stdint.h>
+
+#include <nuttx/irq.h>
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+/* Helpers ******************************************************************/
+
+#define NRF53_TIM_START(d)                ((d)->ops->start(d))
+#define NRF53_TIM_STOP(d)                 ((d)->ops->stop(d))
+#define NRF53_TIM_CLEAR(d)                ((d)->ops->clear(d))
+#define NRF53_TIM_CONFIGURE(d, m, w)      ((d)->ops->configure(d, m, w))
+#define NRF53_TIM_SHORTS(d, s, i, e)      ((d)->ops->shorts(d, s, i, e))
+#define NRF53_TIM_COUNT(d)                ((d)->ops->count(d))
+#define NRF53_TIM_SETCC(d, i, cc)         ((d)->ops->setcc(d, i, cc))
+#define NRF53_TIM_GETCC(d, i, cc)         ((d)->ops->getcc(d, i, cc))
+#define NRF53_TIM_SETPRE(d, pre)          ((d)->ops->setpre(d, pre))
+#define NRF53_TIM_SETISR(d, hnd, arg)     ((d)->ops->setisr(d, hnd, arg))
+#define NRF53_TIM_ENABLEINT(d, s)         ((d)->ops->enableint(d, s))
+#define NRF53_TIM_DISABLEINT(d, s)        ((d)->ops->disableint(d, s))
+#define NRF53_TIM_CHECKINT(d, s)          ((d)->ops->checkint(d, s))
+#define NRF53_TIM_ACKINT(d, s)            ((d)->ops->ackint(d, s))
+
+/****************************************************************************
+ * Public Types
+ ****************************************************************************/
+
+/* Timer mode */
+
+enum nrf53_tim_mode_e
+{
+  NRF53_TIM_MODE_UNUSED   = 0,
+  NRF53_TIM_MODE_TIMER    = 1,
+  NRF53_TIM_MODE_COUNTER  = 2,
+  NRF53_TIM_MODE_LOWPOWER = 3,
+};
+
+/* Timer bit width */
+
+enum nrf53_tim_width_e
+{
+  NRF53_TIM_WIDTH_16B    = 0,
+  NRF53_TIM_WIDTH_8B     = 1,
+  NRF53_TIM_WIDTH_24B    = 2,
+  NRF53_TIM_WIDTH_32B    = 3,
+};
+
+/* Timer CC index */
+
+enum nrf53_tim_cc_e
+{
+  NRF53_TIM_CC0 = 0,
+  NRF53_TIM_CC1 = 1,
+  NRF53_TIM_CC2 = 2,
+  NRF53_TIM_CC3 = 3,
+  NRF53_TIM_CC4 = 4,
+  NRF53_TIM_CC5 = 5
+};
+
+/* Timer IRQ source */
+
+enum nrf53_tim_irq_e
+{
+  NRF53_TIM_INT_COMPARE0 = 0,
+  NRF53_TIM_INT_COMPARE1 = 1,
+  NRF53_TIM_INT_COMPARE2 = 2,
+  NRF53_TIM_INT_COMPARE3 = 3,
+  NRF53_TIM_INT_COMPARE4 = 4,
+  NRF53_TIM_INT_COMPARE5 = 5,
+};
+
+/* Timer shorts type */
+
+enum nrf53_tim_shorts_e
+{
+  NRF53_TIM_SHORT_COMPARE_CLEAR = 1,
+  NRF53_TIM_SHORT_COMPARE_STOP  = 2
+};
+
+/* Timer frequency prescaler */
+
+enum nrf53_tim_pre_e
+{
+  NRF53_TIM_PRE_16000000 = 0,
+  NRF53_TIM_PRE_8000000  = 1,
+  NRF53_TIM_PRE_4000000  = 2,
+  NRF53_TIM_PRE_2000000  = 3,
+  NRF53_TIM_PRE_1000000  = 4,
+  NRF53_TIM_PRE_500000   = 5,
+  NRF53_TIM_PRE_250000   = 6,
+  NRF53_TIM_PRE_125000   = 7,
+  NRF53_TIM_PRE_62500    = 8,
+  NRF53_TIM_PRE_31250    = 9
+};
+
+/* NRF53 TIM device */
+
+struct nrf53_tim_dev_s
+{
+  struct nrf53_tim_ops_s *ops;
+};
+
+/* NRF53 TIM ops */
+
+struct nrf53_tim_ops_s
+{
+  /* Timer tasks */
+
+  int (*start)(struct nrf53_tim_dev_s *dev);
+  int (*stop)(struct nrf53_tim_dev_s *dev);
+  int (*clear)(struct nrf53_tim_dev_s *dev);
+
+  /* Timer configuration */
+
+  int (*configure)(struct nrf53_tim_dev_s *dev, uint8_t mode, uint8_t width);
+  int (*shorts)(struct nrf53_tim_dev_s *dev, uint8_t s, uint8_t i, bool en);
+
+  /* Timer operations */
+
+  int (*count)(struct nrf53_tim_dev_s *dev);
+  int (*setcc)(struct nrf53_tim_dev_s *dev, uint8_t i, uint32_t cc);
+  int (*getcc)(struct nrf53_tim_dev_s *dev, uint8_t i, uint32_t *cc);
+  int (*setpre)(struct nrf53_tim_dev_s *dev, uint8_t pre);
+
+  /* Timer interrupts */
+
+  int (*setisr)(struct nrf53_tim_dev_s *dev, xcpt_t handler, void *arg);
+  int (*enableint)(struct nrf53_tim_dev_s *dev, uint8_t source);
+  int (*disableint)(struct nrf53_tim_dev_s *dev, uint8_t source);
+  int (*checkint)(struct nrf53_tim_dev_s *dev, uint8_t source);
+  int (*ackint)(struct nrf53_tim_dev_s *dev, uint8_t source);
+};
+
+/****************************************************************************
+ * Public Function Prototypes
+ ****************************************************************************/
+
+struct nrf53_tim_dev_s *nrf53_tim_init(int timer);
+int nrf53_tim_deinit(struct nrf53_tim_dev_s *dev);
+
+#endif /* __ARCH_ARM_SRC_NRF53_NRF53_TIM_H */
diff --git a/arch/arm/src/nrf53/nrf53_tim_lowerhalf.c 
b/arch/arm/src/nrf53/nrf53_tim_lowerhalf.c
new file mode 100644
index 0000000000..6af5732b1c
--- /dev/null
+++ b/arch/arm/src/nrf53/nrf53_tim_lowerhalf.c
@@ -0,0 +1,538 @@
+/****************************************************************************
+ * arch/arm/src/nrf53/nrf53_tim_lowerhalf.c
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.  The
+ * ASF licenses this file to you 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.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+#include <sys/types.h>
+#include <stdbool.h>
+#include <string.h>
+#include <assert.h>
+#include <errno.h>
+#include <debug.h>
+
+#include <nuttx/arch.h>
+#include <nuttx/timers/timer.h>
+
+#include "arm_internal.h"
+#include "nrf53_tim.h"
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+/* TIMER configuration */
+
+#define NRF53_TIMER_CC  (NRF53_TIM_CC0)
+#define NRF53_TIMER_INT (NRF53_TIM_INT_COMPARE0)
+#define NRF53_TIMER_RES (NRF53_TIM_WIDTH_32B)
+#define NRF53_TIMER_MAX (0xffffffff)
+#define NRF53_TIMER_PRE (NRF53_TIM_PRE_1000000)
+#define NRF53_TIMER_PER (1000000)
+
+/****************************************************************************
+ * Private Types
+ ****************************************************************************/
+
+struct nrf53_timer_lowerhalf_s
+{
+  const struct timer_ops_s *ops;      /* Lower half operations */
+  struct nrf53_tim_dev_s   *tim;      /* nrf53 timer driver */
+  tccb_t                    callback; /* Current user interrupt callback */
+  void                     *arg;      /* Argument passed to upper half 
callback */
+  bool                      started;  /* True: Timer has been started */
+};
+
+/****************************************************************************
+ * Private Function Prototypes
+ ****************************************************************************/
+
+static int nrf53_timer_handler(int irq, void *context, void *arg);
+
+/* "Lower half" driver methods **********************************************/
+
+static int nrf53_timer_start(struct timer_lowerhalf_s *lower);
+static int nrf53_timer_stop(struct timer_lowerhalf_s *lower);
+static int nrf53_timer_getstatus(struct timer_lowerhalf_s *lower,
+                                 struct timer_status_s *status);
+static int nrf53_timer_settimeout(struct timer_lowerhalf_s *lower,
+                                  uint32_t timeout);
+static void nrf53_timer_setcallback(struct timer_lowerhalf_s *lower,
+                                    tccb_t callback, void *arg);
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+/* "Lower half" driver methods */
+
+static const struct timer_ops_s g_nrf53_timer_ops =
+{
+  .start       = nrf53_timer_start,
+  .stop        = nrf53_timer_stop,
+  .getstatus   = nrf53_timer_getstatus,
+  .settimeout  = nrf53_timer_settimeout,
+  .setcallback = nrf53_timer_setcallback,
+  .ioctl       = NULL,
+};
+
+#ifdef CONFIG_NRF53_TIMER0
+/* TIMER0 lower-half */
+
+static struct nrf53_timer_lowerhalf_s g_nrf53_timer0_lowerhalf =
+{
+  .ops = &g_nrf53_timer_ops,
+};
+#endif
+
+#ifdef CONFIG_NRF53_TIMER1
+/* TIMER1 lower-half */
+
+static struct nrf53_timer_lowerhalf_s g_nrf53_timer1_lowerhalf =
+{
+  .ops = &g_nrf53_timer_ops,
+};
+#endif
+
+#ifdef CONFIG_NRF53_TIMER2
+/* TIMER2 lower-half */
+
+static struct nrf53_timer_lowerhalf_s g_nrf53_timer2_lowerhalf =
+{
+  .ops = &g_nrf53_timer_ops,
+};
+#endif
+
+#ifdef CONFIG_NRF53_TIMER3
+/* TIMER3 lower-half */
+
+static struct nrf53_timer_lowerhalf_s g_nrf53_timer3_lowerhalf =
+{
+  .ops = &g_nrf53_timer_ops,
+};
+#endif
+
+#ifdef CONFIG_NRF53_TIMER4
+/* TIMER4 lower-half */
+
+static struct nrf53_timer_lowerhalf_s g_nrf53_timer4_lowerhalf =
+{
+  .ops = &g_nrf53_timer_ops,
+};
+#endif
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: nrf53_timer_handler
+ *
+ * Description:
+ *   Timer interrupt handler
+ *
+ * Input Parameters:
+ *
+ * Returned Value:
+ *
+ ****************************************************************************/
+
+static int nrf53_timer_handler(int irq, void *context, void *arg)
+{
+  struct nrf53_timer_lowerhalf_s *priv =
+    (struct nrf53_timer_lowerhalf_s *)arg;
+  uint32_t next_interval_us = 0;
+
+  NRF53_TIM_ACKINT(priv->tim, NRF53_TIMER_INT);
+
+  if (priv->callback(&next_interval_us, priv->arg))
+    {
+      if (next_interval_us > 0)
+        {
+          NRF53_TIM_SETCC(priv->tim, NRF53_TIMER_CC, next_interval_us);
+        }
+    }
+  else
+    {
+      nrf53_timer_stop((struct timer_lowerhalf_s *)priv);
+    }
+
+  return OK;
+}
+
+/****************************************************************************
+ * Name: nrf53_timer_start
+ *
+ * Description:
+ *   Start the timer, resetting the time to the current timeout,
+ *
+ * Input Parameters:
+ *   lower - A pointer the publicly visible representation of
+ *           the "lower-half" driver state structure.
+ *
+ * Returned Value:
+ *   Zero on success; a negated errno value on failure.
+ *
+ ****************************************************************************/
+
+static int nrf53_timer_start(struct timer_lowerhalf_s *lower)
+{
+  struct nrf53_timer_lowerhalf_s *priv =
+    (struct nrf53_timer_lowerhalf_s *)lower;
+  int ret = OK;
+
+  DEBUGASSERT(priv);
+
+  if (priv->started == true)
+    {
+      /* Return EBUSY to indicate that the timer was already running */
+
+      ret = -EBUSY;
+      goto errout;
+    }
+
+  /* Configure TIMER mode and resolution */
+
+  NRF53_TIM_CONFIGURE(priv->tim, NRF53_TIM_MODE_TIMER, NRF53_TIMER_RES);
+
+  /* Clear counter on COMPARE event */
+
+  NRF53_TIM_SHORTS(priv->tim, NRF53_TIM_SHORT_COMPARE_CLEAR,
+                   NRF53_TIMER_INT, true);
+
+  /* Configure prescaler */
+
+  NRF53_TIM_SETPRE(priv->tim, NRF53_TIMER_PRE);
+
+  /* Configure callback */
+
+  if (priv->callback != NULL)
+    {
+      NRF53_TIM_SETISR(priv->tim, nrf53_timer_handler, priv);
+      NRF53_TIM_ENABLEINT(priv->tim, NRF53_TIMER_INT);
+    }
+
+  NRF53_TIM_CLEAR(priv->tim);
+  NRF53_TIM_START(priv->tim);
+
+  priv->started = true;
+
+errout:
+  return ret;
+}
+
+/****************************************************************************
+ * Name: nrf53_timer_stop
+ *
+ * Description:
+ *   Stop the timer
+ *
+ * Input Parameters:
+ *   lower - A pointer the publicly visible representation of
+ *           the "lower-half" driver state structure.
+ *
+ * Returned Value:
+ *   Zero on success; a negated errno value on failure.
+ *
+ ****************************************************************************/
+
+static int nrf53_timer_stop(struct timer_lowerhalf_s *lower)
+{
+  struct nrf53_timer_lowerhalf_s *priv =
+    (struct nrf53_timer_lowerhalf_s *)lower;
+  int ret = OK;
+
+  DEBUGASSERT(priv);
+
+  if (priv->started == false)
+    {
+      /* Return ENODEV to indicate that the timer was not running */
+
+      ret = -ENODEV;
+      goto errout;
+    }
+
+  NRF53_TIM_DISABLEINT(priv->tim, NRF53_TIMER_INT);
+  NRF53_TIM_SETISR(priv->tim, NULL, NULL);
+  NRF53_TIM_STOP(priv->tim);
+
+  priv->started = false;
+
+errout:
+  return ret;
+}
+
+/****************************************************************************
+ * Name: nrf53_timer_getstatus
+ *
+ * Description:
+ *   get timer status
+ *
+ * Input Parameters:
+ *   lower  - A pointer the publicly visible representation of the "lower-
+ *            half" driver state structure.
+ *   status - The location to return the status information.
+ *
+ * Returned Value:
+ *   Zero on success; a negated errno value on failure.
+ *
+ ****************************************************************************/
+
+static int nrf53_timer_getstatus(struct timer_lowerhalf_s *lower,
+                                 struct timer_status_s *status)
+{
+  struct nrf53_timer_lowerhalf_s *priv =
+    (struct nrf53_timer_lowerhalf_s *)lower;
+
+  DEBUGASSERT(priv);
+  DEBUGASSERT(status);
+
+  /* Return the status bit */
+
+  status->flags = 0;
+
+  if (priv->started == true)
+    {
+      status->flags |= TCFLAGS_ACTIVE;
+    }
+
+  if (priv->callback)
+    {
+      status->flags |= TCFLAGS_HANDLER;
+    }
+
+  /* TODO: timeout and time left */
+
+  status->timeout  = 0;
+  status->timeleft = 0;
+
+  return OK;
+}
+
+/****************************************************************************
+ * Name: nrf53_timer_settimeout
+ *
+ * Description:
+ *   Set a new timeout value (and reset the timer)
+ *
+ * Input Parameters:
+ *   lower   - A pointer the publicly visible representation of
+ *             the "lower-half" driver state structure.
+ *   timeout - The new timeout value in microseconds.
+ *
+ * Returned Value:
+ *   Zero on success; a negated errno value on failure.
+ *
+ ****************************************************************************/
+
+static int nrf53_timer_settimeout(struct timer_lowerhalf_s *lower,
+                                  uint32_t timeout)
+{
+  struct nrf53_timer_lowerhalf_s *priv =
+    (struct nrf53_timer_lowerhalf_s *)lower;
+  uint64_t cc  = 0;
+  int      ret = OK;
+
+  DEBUGASSERT(priv);
+
+  if (priv->started == true)
+    {
+      ret = -EPERM;
+      goto errout;
+    }
+
+  if (timeout > NRF53_TIMER_MAX)
+    {
+      ret = -EINVAL;
+      goto errout;
+    }
+
+  cc = (timeout / 1000000) * NRF53_TIMER_PER;
+  NRF53_TIM_SETCC(priv->tim, NRF53_TIMER_CC, cc);
+
+errout:
+  return ret;
+}
+
+/****************************************************************************
+ * Name: nrf53_setcallback
+ *
+ * Description:
+ *   Call this user provided timeout handler.
+ *
+ * Input Parameters:
+ *   lower    - A pointer the publicly visible representation of
+ *              the "lower-half" driver state structure.
+ *   callback - The new timer expiration function pointer.  If this
+ *              function pointer is NULL, then the reset-on-expiration
+ *              behavior is restored,
+ *   arg      - Argument that will be provided in the callback
+ *
+ * Returned Value:
+ *   The previous timer expiration function pointer or NULL is there was
+ *   no previous function pointer.
+ *
+ ****************************************************************************/
+
+static void nrf53_timer_setcallback(struct timer_lowerhalf_s *lower,
+                                    tccb_t callback, void *arg)
+{
+  struct nrf53_timer_lowerhalf_s *priv =
+    (struct nrf53_timer_lowerhalf_s *)lower;
+  irqstate_t flags;
+
+  DEBUGASSERT(priv);
+
+  flags = enter_critical_section();
+
+  /* Save the new callback */
+
+  priv->callback = callback;
+  priv->arg      = arg;
+
+  if (callback != NULL && priv->started == true)
+    {
+      NRF53_TIM_SETISR(priv->tim, nrf53_timer_handler, priv);
+      NRF53_TIM_ENABLEINT(priv->tim, NRF53_TIMER_INT);
+    }
+  else
+    {
+      NRF53_TIM_DISABLEINT(priv->tim, NRF53_TIMER_INT);
+      NRF53_TIM_SETISR(priv->tim, NULL, NULL);
+    }
+
+  leave_critical_section(flags);
+}
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: nrf53_timer_initialize
+ *
+ * Description:
+ *   Bind the configuration timer to a timer lower half instance and
+ *   register the timer drivers at 'devpath'
+ *
+ * Input Parameters:
+ *   devpath - The full path to the timer device.  This should be of the
+ *     form /dev/timer0
+ *   timer - the timer's number.
+ *
+ * Returned Value:
+ *   Zero (OK) is returned on success; A negated errno value is returned
+ *   to indicate the nature of any failure.
+ *
+ ****************************************************************************/
+
+int nrf53_timer_initialize(const char *devpath, uint8_t timer)
+{
+  struct nrf53_timer_lowerhalf_s *lower = NULL;
+  void                           *drvr  = NULL;
+  int                             ret   = OK;
+
+  DEBUGASSERT(devpath);
+
+  switch (timer)
+    {
+#ifdef CONFIG_NRF53_TIMER0
+      case 0:
+        {
+          lower = &g_nrf53_timer0_lowerhalf;
+          break;
+        }
+#endif
+
+#ifdef CONFIG_NRF53_TIMER1
+      case 1:
+        {
+          lower = &g_nrf53_timer1_lowerhalf;
+          break;
+        }
+#endif
+
+#ifdef CONFIG_NRF53_TIMER2
+      case 2:
+        {
+          lower = &g_nrf53_timer2_lowerhalf;
+          break;
+        }
+#endif
+
+#ifdef CONFIG_NRF53_TIMER3
+      case 3:
+        {
+          lower = &g_nrf53_timer3_lowerhalf;
+          break;
+        }
+#endif
+
+#ifdef CONFIG_NRF53_TIMER4
+      case 4:
+        {
+          lower = &g_nrf53_timer4_lowerhalf;
+          break;
+        }
+#endif
+
+      default:
+        {
+          ret = -ENODEV;
+          goto errout;
+        }
+    }
+
+  /* Initialize the elements of lower half state structure */
+
+  lower->started  = false;
+  lower->callback = NULL;
+  lower->tim      = nrf53_tim_init(timer);
+
+  if (lower->tim == NULL)
+    {
+      ret = -EINVAL;
+      goto errout;
+    }
+
+  /* Register the timer driver as /dev/timerX.  The returned value from
+   * timer_register is a handle that could be used with timer_unregister().
+   * REVISIT: The returned handle is discard here.
+   */
+
+  drvr = timer_register(devpath, (struct timer_lowerhalf_s *)lower);
+  if (drvr == NULL)
+    {
+      /* The actual cause of the failure may have been a failure to allocate
+       * perhaps a failure to register the timer driver (such as if the
+       * 'depath' were not unique).  We know here but we return EEXIST to
+       * indicate the failure (implying the non-unique devpath).
+       */
+
+      ret = -EEXIST;
+      goto errout;
+    }
+
+errout:
+  return ret;
+}
diff --git a/arch/arm/src/nrf53/nrf53_tim_lowerhalf.h 
b/arch/arm/src/nrf53/nrf53_tim_lowerhalf.h
new file mode 100644
index 0000000000..02a98c4c6e
--- /dev/null
+++ b/arch/arm/src/nrf53/nrf53_tim_lowerhalf.h
@@ -0,0 +1,42 @@
+/****************************************************************************
+ * arch/arm/src/nrf53/nrf53_tim_lowerhalf.h
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.  The
+ * ASF licenses this file to you 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 __ARCH_ARM_SRC_NRF53_NRF53_TIM_LOWERHALF_H
+#define __ARCH_ARM_SRC_NRF53_NRF53_TIM_LOWERHALF_H
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+#include <nrf53_tim.h>
+
+/****************************************************************************
+ * Public Function Prototypes
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: nrf53_timer_initialize
+ ****************************************************************************/
+
+int nrf53_timer_initialize(const char *devpath, uint8_t timer);
+
+#endif /* __ARCH_ARM_SRC_NRF53_NRF53_TIM_LOWERHALF_H */


Reply via email to