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

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

commit adf0a2fc25a78fe22f9ee14cf44ccd8f41587856
Author: raiden00pl <[email protected]>
AuthorDate: Wed May 20 10:17:04 2026 +0200

    !arch/tlsr82: separate pulse count from PWM driver
    
    BREAKING CHANGE: separate pulse count from PWM driver
    
    Pulse count handling was removed from PWM driver and moved to a separate 
driver.
    For details about this change, look at previous commit.
    
    Signed-off-by: raiden00pl <[email protected]>
---
 arch/arm/src/tlsr82/Kconfig             |  11 +-
 arch/arm/src/tlsr82/Make.defs           |   4 +
 arch/arm/src/tlsr82/tlsr82_pulsecount.c | 739 ++++++++++++++++++++++++++++++++
 arch/arm/src/tlsr82/tlsr82_pulsecount.h |  38 ++
 arch/arm/src/tlsr82/tlsr82_pwm.c        | 135 ------
 arch/arm/src/tlsr82/tlsr82_pwm.h        |   2 +
 6 files changed, 791 insertions(+), 138 deletions(-)

diff --git a/arch/arm/src/tlsr82/Kconfig b/arch/arm/src/tlsr82/Kconfig
index dfb8d9ddf8f..4e517223907 100644
--- a/arch/arm/src/tlsr82/Kconfig
+++ b/arch/arm/src/tlsr82/Kconfig
@@ -258,7 +258,6 @@ menuconfig TLSR82_USB
 menuconfig TLSR82_PWM
        bool "PWM Configuration"
        default n
-       select PWM
 
 if TLSR82_PWM
 
@@ -267,42 +266,48 @@ if TLSR82_PWM
 config TLSR82_PWM0
        bool "TLSR82 PWM0 Enable"
        default n
+       select PWM
 
 config TLSR82_PWM0_PULSECOUNT
        bool "TLSR82 PWM0 PulseCount Enable"
        default n
-       depends on TLSR82_PWM0
-       select PWM_PULSECOUNT
+       select ARCH_HAVE_PULSECOUNT
+       select PULSECOUNT
 
 # PWM1 configuration
 
 config TLSR82_PWM1
        bool "TLSR82 PWM1 Enable"
        default n
+       select PWM
 
 # PWM2 configuration
 
 config TLSR82_PWM2
        bool "TLSR82 PWM2 Enable"
        default n
+       select PWM
 
 # PWM3 configuration
 
 config TLSR82_PWM3
        bool "TLSR82 PWM3 Enable"
        default n
+       select PWM
 
 # PWM4 configuration
 
 config TLSR82_PWM4
        bool "TLSR82 PWM4 Enable"
        default n
+       select PWM
 
 # PWM5 configuration
 
 config TLSR82_PWM5
        bool "TLSR82 PWM5 Enable"
        default n
+       select PWM
 
 endif
 
diff --git a/arch/arm/src/tlsr82/Make.defs b/arch/arm/src/tlsr82/Make.defs
index 704c733eb0e..cac170780ab 100644
--- a/arch/arm/src/tlsr82/Make.defs
+++ b/arch/arm/src/tlsr82/Make.defs
@@ -43,6 +43,10 @@ ifeq ($(CONFIG_TLSR82_PWM),y)
   CHIP_CSRCS += tlsr82_pwm.c
 endif
 
+ifeq ($(CONFIG_PULSECOUNT),y)
+  CHIP_CSRCS += tlsr82_pulsecount.c
+endif
+
 ifeq ($(CONFIG_TLSR82_ADC),y)
   CHIP_CSRCS += tlsr82_adc.c
 endif
diff --git a/arch/arm/src/tlsr82/tlsr82_pulsecount.c 
b/arch/arm/src/tlsr82/tlsr82_pulsecount.c
new file mode 100644
index 00000000000..1e13ddec51e
--- /dev/null
+++ b/arch/arm/src/tlsr82/tlsr82_pulsecount.c
@@ -0,0 +1,739 @@
+/****************************************************************************
+ * arch/arm/src/tlsr82/tlsr82_pulsecount.c
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * 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 <stdint.h>
+#include <stdio.h>
+#include <inttypes.h>
+#include <assert.h>
+#include <errno.h>
+#include <string.h>
+#include <nuttx/debug.h>
+
+#include <nuttx/arch.h>
+#include <nuttx/timers/pulsecount.h>
+#include <arch/board/board.h>
+
+#include "arm_internal.h"
+
+#include "chip.h"
+#include "tlsr82_pwm.h"
+#include "tlsr82_pulsecount.h"
+#include "tlsr82_gpio.h"
+#include "tlsr82_gpio_cfg.h"
+
+#include "hardware/tlsr82_pwm.h"
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+/* The PWM peripheral clock source is the system clock. */
+
+#define PWM_SRC_CLK_HZ        (CONFIG_TLSR82_CPU_CLK_MHZ * 1000000)
+
+/* The default clkdiv = 9, default PWM clock = PWM_SRC_CLK_HZ / 10. */
+
+#define PWM_INIT_CLKDIV       9
+
+/* Make sure the max frequency has at least 1% duty accuracy. */
+
+#define PWM_MAX_FREQ          (g_pulsecountclk / 100)
+#define PWM_MIN_FREQ          (g_pulsecountclk / UINT16_MAX + 1)
+
+/* PWM peripheral max pulse count number, bit 0 ~ 13. */
+
+#define PWM_MAX_COUNT         (0x3fff)
+
+/* PWM simple operation definition */
+
+#define PWM_INT_PEND(id)      BM_IS_SET(PWM_IRQ_STA_REG, 1 << ((id) + 2))
+#define PWM_INT_CLEAR(id)     BM_CLR(PWM_IRQ_STA_REG, 1 << ((id) + 2))
+#define PWM_INT_ENABLE(id)    BM_SET(PWM_IRQ_CTRL_REG, 1 << ((id) + 2))
+#define PWM_INT_DISABLE(id)   BM_CLR(PWM_IRQ_CTRL_REG, 1 << ((id) + 2))
+
+#define PWM0_PNUM_INT_PEND()      BM_IS_SET(PWM_IRQ_STA_REG, 1 << 0)
+#define PWM0_PNUM_INT_CLEAR()     BM_CLR(PWM_IRQ_STA_REG, 1 << 0)
+#define PWM0_PNUM_INT_ENABLE()    BM_SET(PWM_IRQ_CTRL_REG, 1 << 0)
+#define PWM0_PNUM_INT_ISENABLE()  BM_IS_SET(PWM_IRQ_CTRL_REG, 1 << 0)
+#define PWM0_PNUM_INT_DISABLE()   BM_CLR(PWM_IRQ_CTRL_REG, 1 << 0)
+
+/****************************************************************************
+ * Private Types
+ ****************************************************************************/
+
+/* This structure represents the state of one pulsecount timer */
+
+struct tlsr82_pulsecounttimer_s
+{
+  uint32_t pincfg;               /* PWM peripheral pin config */
+  uint8_t id;                    /* PWM peripheral channel id */
+  bool invert;                   /* Pulsecount output is inverted or not */
+  bool started;                  /* Pulsecount output has started or not */
+  uint8_t irq;                   /* Timer update IRQ */
+  uint32_t count;                /* Remaining pulse count */
+  uint32_t frequency;            /* Current frequency setting */
+  uint16_t max;
+  uint16_t cmp;
+  void *handle;                  /* Handle used for upper-half callback */
+};
+
+struct tlsr82_pulsecount_s
+{
+  const struct pulsecount_ops_s *ops;
+  struct tlsr82_pulsecounttimer_s *timer;
+};
+
+/****************************************************************************
+ * Static Function Prototypes
+ ****************************************************************************/
+
+/* Register access */
+
+#ifdef CONFIG_DEBUG_TIMER_INFO
+static void pulsecount_dumpregs(const char *msg);
+#else
+#  define pulsecount_dumpregs(msg)
+#endif
+
+/* Timer management */
+
+static void pulsecount_enable(struct tlsr82_pulsecounttimer_s *priv,
+                              bool enable);
+static int pulsecount_cfg_check(struct tlsr82_pulsecounttimer_s *priv);
+static int pulsecount_config(struct tlsr82_pulsecounttimer_s *priv,
+                             const struct pulsecount_info_s *info);
+
+static int pulsecount_interrupt(int irq, void *context, void *arg);
+
+/* Pulsecount timer methods */
+
+static int pulsecount_timer_setup(struct tlsr82_pulsecounttimer_s *priv);
+static int pulsecount_timer_shutdown(struct tlsr82_pulsecounttimer_s *priv);
+
+static int pulsecount_timer_stop(struct tlsr82_pulsecounttimer_s *priv);
+static int pulsecount_timer_ioctl(struct tlsr82_pulsecounttimer_s *priv,
+                                  int cmd, unsigned long arg);
+
+/* Pulsecount driver methods */
+
+static int pulsecount_setup(struct pulsecount_lowerhalf_s *dev);
+static int pulsecount_shutdown(struct pulsecount_lowerhalf_s *dev);
+static int pulsecount_start(struct pulsecount_lowerhalf_s *dev,
+                            const struct pulsecount_info_s *info,
+                            void *handle);
+static int pulsecount_stop(struct pulsecount_lowerhalf_s *dev);
+static int pulsecount_ioctl(struct pulsecount_lowerhalf_s *dev,
+                            int cmd, unsigned long arg);
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+static uint32_t g_pulsecountclk;
+
+static struct tlsr82_pulsecounttimer_s g_pulsecount0dev =
+{
+  .pincfg      = BOARD_PWM0_PIN,
+  .id          = 0,
+  .invert      = false,
+  .started     = false,
+  .irq         = NR_SW_PWM_IRQ,
+};
+
+static const struct pulsecount_ops_s g_pulsecountops =
+{
+  .setup       = pulsecount_setup,
+  .shutdown    = pulsecount_shutdown,
+  .start       = pulsecount_start,
+  .stop        = pulsecount_stop,
+  .ioctl       = pulsecount_ioctl,
+};
+
+static struct tlsr82_pulsecount_s g_pulsecount0lower =
+{
+  .ops = &g_pulsecountops,
+  .timer = &g_pulsecount0dev,
+};
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: pulsecount_dumpregs
+ *
+ * Description:
+ *   Dump all PWM peripheral registers.
+ *
+ * Input Parameters:
+ *   msg - message.
+ *
+ * Returned Value:
+ *   None
+ *
+ ****************************************************************************/
+
+#ifdef CONFIG_DEBUG_TIMER_INFO
+static void pulsecount_dumpregs(const char *msg)
+{
+  int i;
+  _info("%s:\n", msg);
+  _info("PWM_CLKDIV_REG   : 0x%x\n", PWM_CLKDIV_REG);
+  _info("PWM_ENABLE0_REG  : 0x%x\n", PWM_ENABLE0_REG);
+  _info("PWM_MODE0_REG    : 0x%x\n", PWM_MODE0_REG);
+  _info("PWM_ENABLE_REG   : 0x%x\n", PWM_ENABLE_REG);
+  _info("PWM_INVERT_REG   : 0x%x\n", PWM_INVERT_REG);
+  _info("PWM_N_INVERT_REG : 0x%x\n", PWM_N_INVERT_REG);
+  _info("PWM_POL_REG      : 0x%x\n", PWM_POL_REG);
+
+  for (i = 0; i < 5; i++)
+    {
+      _info("PWM_CYCLE_REG(%d): 0x%lx\n", i, PWM_CYCLE_REG(i));
+      _info("PWM_CMP_REG(%d)  : 0x%x\n", i, PWM_CMP_REG(i));
+      _info("PWM_MAX_REG(%d)  : 0x%x\n", i, PWM_MAX_REG(i));
+    }
+
+  _info("PWM_PLUSE_NUM_REG : 0x%x\n", PWM_PLUSE_NUM_REG);
+  _info("PWM_IRQ_CTRL_REG : 0x%x\n", PWM_IRQ_CTRL_REG);
+  _info("PWM_IRQ_STA_REG  : 0x%x\n", PWM_IRQ_STA_REG);
+}
+#endif
+
+/****************************************************************************
+ * Name: pulsecount_config
+ *
+ * Description:
+ *   (Re-)initialize the timer resources and start the pulsed output
+ *
+ * Input Parameters:
+ *   priv - A reference to the lower half pulsecount driver state structure
+ *   info - A reference to the characteristics of the pulsed output
+ *
+ * Returned Value:
+ *   Zero on success; a negated errno value on failure
+ *
+ ****************************************************************************/
+
+static int pulsecount_config(struct tlsr82_pulsecounttimer_s *priv,
+                             const struct pulsecount_info_s *info)
+{
+  /* Calculated values */
+
+  uint16_t max;
+  uint16_t cmp;
+
+  if (priv == NULL || info == NULL)
+    {
+      _err("priv or info is null, priv=%p info=%p\n", priv, info);
+      return -EINVAL;
+    }
+
+  _info("PWM%d invert: %d high: %" PRIu32 " ns low: %" PRIu32 " ns\n",
+          (int)priv->id, (int)priv->invert, info->high_ns,
+          info->low_ns);
+
+  if (pulsecount_frequency(info) == 0)
+    {
+      _err("ERROR: pulsecount period is too long, high: %" PRIu32
+           " ns low: %" PRIu32 " ns\n", info->high_ns, info->low_ns);
+      return -EINVAL;
+    }
+
+  if (pulsecount_frequency(info) > PWM_MAX_FREQ ||
+      pulsecount_frequency(info) < PWM_MIN_FREQ)
+    {
+      _err("ERROR: pulsecount frequency out of range, "
+           "freq: %ld, max: %ld, min: %ld\n",
+           pulsecount_frequency(info), PWM_MAX_FREQ, PWM_MIN_FREQ);
+      return -EINVAL;
+    }
+
+  /* Calculate the MAX and CMP register value
+   * period = max_reg / g_pulsecountclk
+   * freq   = g_pulsecountclk / max_reg
+   */
+
+  max = (uint16_t)((g_pulsecountclk / pulsecount_frequency(info)));
+
+  cmp = (uint16_t)(((uint64_t)max *
+                    (uint64_t)pulsecount_duty(info)) >> 16);
+
+  _info("PWM%d PCLK: %lu freq: %lu duty: %lu max: %u cmp: %u\n",
+        priv->id, g_pulsecountclk, pulsecount_frequency(info),
+        pulsecount_duty(info), max, cmp);
+
+  priv->max = max;
+  priv->cmp = cmp;
+
+  PWM_MAX_REG(priv->id) = priv->max;
+  PWM_CMP_REG(priv->id) = priv->cmp;
+
+  if (priv->count > 0)
+    {
+      PWM_MODE0_REG = PWM_MODE0_COUNT;
+      PWM_PLUSE_NUM_REG = priv->count;
+      PWM0_PNUM_INT_ENABLE();
+      up_enable_irq(priv->irq);
+    }
+  else
+    {
+      PWM_MODE0_REG = PWM_MODE0_NORMAL;
+    }
+
+  pulsecount_enable(priv, true);
+
+  return OK;
+}
+
+/****************************************************************************
+ * Name: pulsecount_interrupt
+ *
+ * Description:
+ *   Handle timer interrupts.
+ *
+ * Input Parameters:
+ *   priv - A reference to the lower half pulsecount driver state structure
+ *
+ * Returned Value:
+ *   Zero on success; a negated errno value on failure
+ *
+ ****************************************************************************/
+
+static int pulsecount_interrupt(int irq, void *context, void *arg)
+{
+  struct tlsr82_pulsecounttimer_s *priv =
+    (struct tlsr82_pulsecounttimer_s *)arg;
+
+  if (PWM0_PNUM_INT_PEND() && PWM0_PNUM_INT_ISENABLE())
+    {
+      /* Disable first interrupts, stop and reset the timer */
+
+      pulsecount_enable(priv, false);
+
+      /* Disable PWMn interrupt and clear interrupt flag */
+
+      PWM_INT_DISABLE(priv->id);
+      PWM_INT_CLEAR(priv->id);
+
+      /* Then perform the callback into the upper half driver */
+
+      pulsecount_expired(priv->handle);
+
+      priv->handle = NULL;
+    }
+
+  return OK;
+}
+
+/****************************************************************************
+ * Name: pulsecount_enable
+ *
+ * Description:
+ *   Enable or disable pulse output.
+ *
+ * Input Parameters:
+ *   dev - A reference to the lower half pulsecount driver state structure
+ *   en  - Enable clock if 'en' is 'true' and disable if 'false'
+ *
+ ****************************************************************************/
+
+static void pulsecount_enable(struct tlsr82_pulsecounttimer_s *priv, bool en)
+{
+  int id = (int)priv->id;
+
+  if (en)
+    {
+      if (priv->started)
+        {
+          return;
+        }
+
+      if (id == 0)
+        {
+          BM_SET(PWM_ENABLE0_REG, 1);
+        }
+      else
+        {
+          BM_SET(PWM_ENABLE_REG, 1 << id);
+        }
+
+      priv->started = true;
+    }
+  else
+    {
+      if (!priv->started)
+        {
+          return;
+        }
+
+      if (id == 0)
+        {
+          BM_CLR(PWM_ENABLE0_REG, 1);
+        }
+      else
+        {
+          BM_CLR(PWM_ENABLE_REG, 1 << id);
+        }
+
+      priv->started = false;
+    }
+}
+
+/****************************************************************************
+ * Name: pulsecount_cfg_check
+ *
+ * Description:
+ *   This method is called when the driver initialize. This function will
+ *   Check the pincfg.  If pincfg is not valid or the current pin can not be
+ *   used as a PWM peripheral output, this function will call PANIC().
+ *
+ * Input Parameters:
+ *   dev    - A reference to the lower half pulsecount driver state structure
+ *
+ * Returned Value:
+ *   Zero on success; a negated errno value on failure
+ *
+ *
+ ****************************************************************************/
+
+static int pulsecount_cfg_check(struct tlsr82_pulsecounttimer_s *priv)
+{
+  uint32_t pincfg = priv->pincfg;
+
+  if (pincfg == GPIO_INVLD_CFG)
+    {
+      _err("pulsecount pincfg is not valid, pincfg=0x%lx\n", pincfg);
+      PANIC();
+      return -EINVAL;
+    }
+
+  if (tlsr82_gpio_cfg_check(pincfg, TLSR82_MUX_PWM) != 0)
+    {
+      _err("pincfg=0x%lx does not support pulsecount mux\n", pincfg);
+      PANIC();
+      return -EINVAL;
+    }
+
+  return OK;
+}
+
+/****************************************************************************
+ * Name: pulsecount_timer_setup
+ *
+ * Description:
+ *   This method is called when the driver is opened.  The lower half driver
+ *   should configure and initialize the device so that it is ready for use.
+ *   It should not, however, output pulses until the start method is called.
+ *
+ * Input Parameters:
+ *   dev - A reference to the lower half pulsecount driver state structure
+ *
+ * Returned Value:
+ *   Zero on success; a negated errno value on failure
+ *
+ ****************************************************************************/
+
+static int pulsecount_timer_setup(struct tlsr82_pulsecounttimer_s *priv)
+{
+  uint32_t pincfg;
+  int ret = OK;
+
+  pulsecount_dumpregs("Initially");
+
+  /* Configure the pulsecount output pins, but do not start the timer yet */
+
+  pincfg = priv->pincfg;
+
+  _info("pincfg: %08lx\n", pincfg);
+
+  /* Set the complementary output inversion before GPIO configuration.  This
+   * keeps the output state stable while the GPIO is configured.
+   */
+
+  if (priv->invert)
+    {
+      BM_SET(PWM_N_INVERT_REG, 1 << priv->id);
+    }
+
+  if (priv->id == 0)
+    {
+      ret = irq_attach(priv->irq, pulsecount_interrupt, priv);
+      if (ret < 0)
+        {
+          _err("ERROR: PWM0 pulsecount interrupt attach failed, ret=%d\n",
+               ret);
+          return ret;
+        }
+    }
+
+  tlsr82_gpioconfig(pincfg);
+
+  return ret;
+}
+
+/****************************************************************************
+ * Name: pulsecount_timer_shutdown
+ *
+ * Description:
+ *   This method is called when the driver is closed.  The lower half driver
+ *   stop pulsed output, free any resources, disable the timer hardware, and
+ *   put the system into the lowest possible power usage state
+ *
+ * Input Parameters:
+ *   dev - A reference to the lower half pulsecount driver state structure
+ *
+ * Returned Value:
+ *   Zero on success; a negated errno value on failure
+ *
+ ****************************************************************************/
+
+static int pulsecount_timer_shutdown(struct tlsr82_pulsecounttimer_s *priv)
+{
+  /* Make sure that the output has been stopped */
+
+  pulsecount_timer_stop(priv);
+
+  /* Then put the GPIO pins back to the default state */
+
+  tlsr82_gpiounconfig(priv->pincfg);
+
+  return OK;
+}
+
+/****************************************************************************
+ * Name: pulsecount_timer_stop
+ *
+ * Description:
+ *   Stop the pulsed output and reset the timer resources
+ *
+ * Input Parameters:
+ *   dev - A reference to the lower half pulsecount driver state structure
+ *
+ * Returned Value:
+ *   Zero on success; a negated errno value on failure
+ *
+ * Assumptions:
+ *   This function is called to stop the pulsed output at anytime.  This
+ *   method is also called from the timer interrupt handler when a repetition
+ *   count expires... automatically stopping the timer.
+ *
+ ****************************************************************************/
+
+static int pulsecount_timer_stop(struct tlsr82_pulsecounttimer_s *priv)
+{
+  irqstate_t flags;
+
+  _info("PWM%u\n", priv->id);
+
+  /* Disable interrupts momentary to stop any ongoing timer processing and
+   * to prevent any concurrent access to the reset register.
+   */
+
+  flags = enter_critical_section();
+
+  /* Disable PWMn output */
+
+  pulsecount_enable(priv, false);
+
+  /* Disable PWMn interrupt and clear interrupt flag */
+
+  PWM_INT_DISABLE(priv->id);
+  PWM_INT_CLEAR(priv->id);
+
+  /* Disable and clear PWM0 count interrupt flag */
+
+  if (priv->count > 0)
+    {
+      priv->count = 0;
+      up_disable_irq(priv->irq);
+      PWM0_PNUM_INT_DISABLE();
+      PWM0_PNUM_INT_CLEAR();
+    }
+
+  leave_critical_section(flags);
+
+  pulsecount_dumpregs("After stop");
+
+  return OK;
+}
+
+/****************************************************************************
+ * Name: pulsecount_timer_ioctl
+ *
+ * Description:
+ *   Lower-half logic may support platform-specific ioctl commands
+ *
+ * Input Parameters:
+ *   dev - A reference to the lower half pulsecount driver state structure
+ *   cmd - The ioctl command
+ *   arg - The argument accompanying the ioctl command
+ *
+ * Returned Value:
+ *   Zero on success; a negated errno value on failure
+ *
+ ****************************************************************************/
+
+static int pulsecount_timer_ioctl(struct tlsr82_pulsecounttimer_s *priv,
+                                  int cmd, unsigned long arg)
+{
+#ifdef CONFIG_DEBUG_TIMER_INFO
+  /* There are no platform-specific ioctl commands */
+
+  _info("PWM%d\n", priv->id);
+#endif
+  return -ENOTTY;
+}
+
+static void tlsr82_pulsecount_hwinitialize(void)
+{
+  static bool pulsecount_initialized = false;
+
+  if (!pulsecount_initialized)
+    {
+      pulsecount_initialized = true;
+
+      /* Disable all the output */
+
+      BM_CLR(PWM_ENABLE0_REG, 0xff);
+      BM_CLR(PWM_ENABLE_REG, 0xff);
+
+      /* Configure the PWM peripheral clock. */
+
+      g_pulsecountclk = PWM_SRC_CLK_HZ / (PWM_INIT_CLKDIV + 1);
+      PWM_CLKDIV_REG = PWM_INIT_CLKDIV;
+
+      /* Disable and clear all PWM peripheral interrupts. */
+
+      BM_CLR(PWM_IRQ_CTRL_REG, 0xff);
+      BM_SET(PWM_IRQ_STA_REG, 0xff);
+
+      /* Enable the shared PWM peripheral interrupt. */
+
+      up_enable_irq(NR_SW_PWM_IRQ);
+    }
+}
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+static int pulsecount_setup(struct pulsecount_lowerhalf_s *dev)
+{
+  struct tlsr82_pulsecount_s *pulse = (struct tlsr82_pulsecount_s *)dev;
+  return pulsecount_timer_setup(pulse->timer);
+}
+
+static int pulsecount_shutdown(struct pulsecount_lowerhalf_s *dev)
+{
+  struct tlsr82_pulsecount_s *pulse = (struct tlsr82_pulsecount_s *)dev;
+  return pulsecount_timer_shutdown(pulse->timer);
+}
+
+static int pulsecount_start(struct pulsecount_lowerhalf_s *dev,
+                            const struct pulsecount_info_s *info,
+                            void *handle)
+{
+  struct tlsr82_pulsecount_s *pulse = (struct tlsr82_pulsecount_s *)dev;
+  struct tlsr82_pulsecounttimer_s *priv = pulse->timer;
+  int ret;
+
+  if (priv->id != 0)
+    {
+      _err("ERROR: PWM%d cannot support pulse count: %" PRIu32 "\n",
+           priv->id, info->count);
+      return -EPERM;
+    }
+
+  if (info->count == 0 || info->count > PWM_MAX_COUNT)
+    {
+      _err("ERROR: PWM0 count out of range, count: %" PRIu32
+           ", max: %d\n", info->count, PWM_MAX_COUNT);
+      return -EINVAL;
+    }
+
+  priv->count = info->count;
+  priv->handle = handle;
+
+  ret = pulsecount_config(priv, info);
+  if (ret == OK)
+    {
+      priv->frequency = pulsecount_frequency(info);
+    }
+
+  return ret;
+}
+
+static int pulsecount_stop(struct pulsecount_lowerhalf_s *dev)
+{
+  struct tlsr82_pulsecount_s *pulse = (struct tlsr82_pulsecount_s *)dev;
+  return pulsecount_timer_stop(pulse->timer);
+}
+
+static int pulsecount_ioctl(struct pulsecount_lowerhalf_s *dev,
+                            int cmd, unsigned long arg)
+{
+  struct tlsr82_pulsecount_s *pulse = (struct tlsr82_pulsecount_s *)dev;
+  return pulsecount_timer_ioctl(pulse->timer, cmd, arg);
+}
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+int tlsr82_pulsecountinitialize(const char *devpath, int minor)
+{
+  struct tlsr82_pulsecount_s *lower;
+  int ret;
+
+  tlsr82_pulsecount_hwinitialize();
+
+  if (minor != 0)
+    {
+      _err("ERROR: PWM%d cannot support pulse count\n", minor);
+      return -EINVAL;
+    }
+
+  lower = &g_pulsecount0lower;
+
+  ret = pulsecount_cfg_check(lower->timer);
+  if (ret < 0)
+    {
+      return ret;
+    }
+
+  ret = pulsecount_register(devpath,
+                            (struct pulsecount_lowerhalf_s *)lower);
+  if (ret < 0)
+    {
+      _err("%s has existed\n", devpath);
+      return ret;
+    }
+
+  pulsecount_dumpregs("tlsr82_pulsecountinitialize");
+  return ret;
+}
diff --git a/arch/arm/src/tlsr82/tlsr82_pulsecount.h 
b/arch/arm/src/tlsr82/tlsr82_pulsecount.h
new file mode 100644
index 00000000000..18588c899b9
--- /dev/null
+++ b/arch/arm/src/tlsr82/tlsr82_pulsecount.h
@@ -0,0 +1,38 @@
+/****************************************************************************
+ * arch/arm/src/tlsr82/tlsr82_pulsecount.h
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * 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_TLSR82_TLSR82_PULSECOUNT_H
+#define __ARCH_ARM_SRC_TLSR82_TLSR82_PULSECOUNT_H
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+/****************************************************************************
+ * Public Function Prototypes
+ ****************************************************************************/
+
+int tlsr82_pulsecountinitialize(const char *devpath, int minor);
+
+#endif /* __ARCH_ARM_SRC_TLSR82_TLSR82_PULSECOUNT_H */
diff --git a/arch/arm/src/tlsr82/tlsr82_pwm.c b/arch/arm/src/tlsr82/tlsr82_pwm.c
index f4d8f9fcb07..e5c8afb06f0 100644
--- a/arch/arm/src/tlsr82/tlsr82_pwm.c
+++ b/arch/arm/src/tlsr82/tlsr82_pwm.c
@@ -62,23 +62,11 @@
 #define PWM_MAX_FREQ          (g_pwmclk / 100)
 #define PWM_MIN_FREQ          (g_pwmclk / UINT16_MAX + 1)
 
-/* PWM max pulse count number, bit 0 ~ 13 */
-
-#define PWM_MAX_COUNT         (0x3fff)
-
-/* PWM simple operation definition */
-
 #define PWM_INT_PEND(id)      BM_IS_SET(PWM_IRQ_STA_REG, 1 << ((id) + 2))
 #define PWM_INT_CLEAR(id)     BM_CLR(PWM_IRQ_STA_REG, 1 << ((id) + 2))
 #define PWM_INT_ENABLE(id)    BM_SET(PWM_IRQ_CTRL_REG, 1 << ((id) + 2))
 #define PWM_INT_DISABLE(id)   BM_CLR(PWM_IRQ_CTRL_REG, 1 << ((id) + 2))
 
-#define PWM0_PNUM_INT_PEND()      BM_IS_SET(PWM_IRQ_STA_REG, 1 << 0)
-#define PWM0_PNUM_INT_CLEAR()     BM_CLR(PWM_IRQ_STA_REG, 1 << 0)
-#define PWM0_PNUM_INT_ENABLE()    BM_SET(PWM_IRQ_CTRL_REG, 1 << 0)
-#define PWM0_PNUM_INT_ISENABLE()  BM_IS_SET(PWM_IRQ_CTRL_REG, 1 << 0)
-#define PWM0_PNUM_INT_DISABLE()   BM_CLR(PWM_IRQ_CTRL_REG, 1 << 0)
-
 /****************************************************************************
  * Private Types
  ****************************************************************************/
@@ -92,16 +80,9 @@ struct tlsr82_pwmtimer_s
   uint8_t id;                    /* PWM hardware id */
   bool invert;                   /* PWM output is inverted or not */
   bool started;                  /* PWM output has started or not */
-#ifdef CONFIG_TLSR82_PWM0_PULSECOUNT
-  uint8_t irq;                   /* Timer update IRQ */
-  uint32_t count;                /* Remaining pulse count */
-#endif
   uint32_t frequency;            /* Current frequency setting */
   uint16_t max;
   uint16_t cmp;
-#ifdef CONFIG_TLSR82_PWM0_PULSECOUNT
-  void *handle;                  /* Handle used for upper-half callback */
-#endif
 };
 
 /****************************************************************************
@@ -123,23 +104,13 @@ static int pwm_cfg_check(struct tlsr82_pwmtimer_s *priv);
 static int pwm_config(struct tlsr82_pwmtimer_s *priv,
                       const struct pwm_info_s *info);
 
-#ifdef CONFIG_TLSR82_PWM0_PULSECOUNT
-static int pwm_interrupt(int irq, void *context, void *arg);
-#endif
-
 /* PWM driver methods */
 
 static int pwm_setup(struct pwm_lowerhalf_s *dev);
 static int pwm_shutdown(struct pwm_lowerhalf_s *dev);
 
-#ifdef CONFIG_TLSR82_PWM0_PULSECOUNT
-static int pwm_start(struct pwm_lowerhalf_s *dev,
-                     const struct pwm_info_s *info,
-                     void *handle);
-#else
 static int pwm_start(struct pwm_lowerhalf_s *dev,
                      const struct pwm_info_s *info);
-#endif
 
 static int pwm_stop(struct pwm_lowerhalf_s *dev);
 static int pwm_ioctl(struct pwm_lowerhalf_s *dev,
@@ -172,9 +143,6 @@ static struct tlsr82_pwmtimer_s g_pwm0dev =
   .id          = 0,
   .invert      = false,
   .started     = false,
-#ifdef CONFIG_TLSR82_PWM0_PULSECOUNT
-  .irq         = NR_SW_PWM_IRQ,
-#endif
 };
 #endif
 
@@ -343,20 +311,6 @@ static int pwm_config(struct tlsr82_pwmtimer_s *priv,
   PWM_MAX_REG(priv->id) = priv->max;
   PWM_CMP_REG(priv->id) = priv->cmp;
 
-#ifdef CONFIG_TLSR82_PWM0_PULSECOUNT
-  if (priv->count > 0)
-    {
-      PWM_MODE0_REG = PWM_MODE0_COUNT;
-      PWM_PLUSE_NUM_REG = priv->count;
-      PWM0_PNUM_INT_ENABLE();
-      up_enable_irq(priv->irq);
-    }
-  else
-    {
-      PWM_MODE0_REG = PWM_MODE0_NORMAL;
-    }
-#endif
-
   pwm_enable(priv, true);
 
   return OK;
@@ -376,33 +330,6 @@ static int pwm_config(struct tlsr82_pwmtimer_s *priv,
  *
  ****************************************************************************/
 
-#ifdef CONFIG_TLSR82_PWM0_PULSECOUNT
-static int pwm_interrupt(int irq, void *context, void *arg)
-{
-  struct tlsr82_pwmtimer_s *priv = (struct tlsr82_pwmtimer_s *)arg;
-
-  if (PWM0_PNUM_INT_PEND() && PWM0_PNUM_INT_ISENABLE())
-    {
-      /* Disable first interrupts, stop and reset the timer */
-
-      pwm_enable(priv, false);
-
-      /* Disable PWMn interrupt and clear interrupt flag */
-
-      PWM_INT_DISABLE(priv->id);
-      PWM_INT_CLEAR(priv->id);
-
-      /* Then perform the callback into the upper half driver */
-
-      pwm_expired(priv->handle);
-
-      priv->handle = NULL;
-    }
-
-  return OK;
-}
-#endif
-
 /****************************************************************************
  * Name: pwm_enable
  *
@@ -537,19 +464,6 @@ static int pwm_setup(struct pwm_lowerhalf_s *dev)
       BM_SET(PWM_N_INVERT_REG, 1 << priv->id);
     }
 
-#ifdef CONFIG_TLSR82_PWM0_PULSECOUNT
-  if (priv->id == 0)
-    {
-      ret = irq_attach(priv->irq, pwm_interrupt, dev);
-      if (ret < 0)
-        {
-          pwmerr("ERROR: PWM0 plusecount interrupt attach failed, ret=%d\n",
-                  ret);
-          return ret;
-        }
-    }
-#endif
-
   tlsr82_gpioconfig(pincfg);
 
   return ret;
@@ -601,49 +515,12 @@ static int pwm_shutdown(struct pwm_lowerhalf_s *dev)
  *
  ****************************************************************************/
 
-#ifdef CONFIG_PWM_PULSECOUNT
-static int pwm_start(struct pwm_lowerhalf_s *dev,
-                     const struct pwm_info_s *info,
-                     void *handle)
-#else
 static int pwm_start(struct pwm_lowerhalf_s *dev,
                      const struct pwm_info_s *info)
-#endif
 {
   int ret = OK;
   struct tlsr82_pwmtimer_s *priv = (struct tlsr82_pwmtimer_s *)dev;
 
-#ifdef CONFIG_PWM_PULSECOUNT
-
-  /* Check if a pulsecount has been selected */
-
-  if (info->channels[0].count > 0)
-    {
-      /* Only the PWM0 support the pulse counting */
-
-      if (priv->id != 0)
-        {
-          pwmerr("ERROR: PWM%d cannot support pulse count: %lu\n",
-                 priv->id, info->channels[0].count);
-          return -EPERM;
-        }
-
-      if (info->channels[0].count > PWM_MAX_COUNT)
-        {
-          pwmerr("ERROR: PWM0 count out of range, count: %lu, max: %d",
-                info->channels[0].count, PWM_MAX_COUNT);
-          return -EINVAL;
-        }
-
-      priv->count = info->channels[0].count;
-    }
-
-  /* Save the handle */
-
-  priv->handle = handle;
-
-#endif
-
   /* Config the PWM */
 
   ret = pwm_config(priv, info);
@@ -699,18 +576,6 @@ static int pwm_stop(struct pwm_lowerhalf_s *dev)
   PWM_INT_DISABLE(priv->id);
   PWM_INT_CLEAR(priv->id);
 
-#ifdef CONFIG_TLSR82_PWM0_PULSECOUNT
-  /* Disable and clear PWM0 count interrupt flag */
-
-  if (priv->count > 0)
-    {
-      priv->count = 0;
-      up_disable_irq(priv->irq);
-      PWM0_PNUM_INT_DISABLE();
-      PWM0_PNUM_INT_CLEAR();
-    }
-#endif
-
   leave_critical_section(flags);
 
   pwm_dumpregs("After stop");
diff --git a/arch/arm/src/tlsr82/tlsr82_pwm.h b/arch/arm/src/tlsr82/tlsr82_pwm.h
index 9544b71214b..f2d3525e3e6 100644
--- a/arch/arm/src/tlsr82/tlsr82_pwm.h
+++ b/arch/arm/src/tlsr82/tlsr82_pwm.h
@@ -75,7 +75,9 @@ extern "C"
  * Public Function Prototypes
  ****************************************************************************/
 
+#ifdef CONFIG_PWM
 int tlsr82_pwminitialize(const char *devpath, int minor);
+#endif
 
 #undef EXTERN
 #if defined(__cplusplus)

Reply via email to