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

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


The following commit(s) were added to refs/heads/master by this push:
     new 2bae5010b94 arm/nrf54l: add PWM support
2bae5010b94 is described below

commit 2bae5010b94e228ad4637615be5569940217b4bc
Author: raiden00pl <[email protected]>
AuthorDate: Sun Sep 20 16:19:29 2026 +0200

    arm/nrf54l: add PWM support
    
    arm/nrf54l: add PWM support
    
    Assisted-by: Codex:GPT-6
    Signed-off-by: raiden00pl <[email protected]>
---
 Documentation/platforms/arm/nrf54l/index.rst |   9 +-
 arch/arm/src/nrf54l/CMakeLists.txt           |   3 +
 arch/arm/src/nrf54l/Kconfig                  | 144 ++++++
 arch/arm/src/nrf54l/Make.defs                |   4 +
 arch/arm/src/nrf54l/hardware/nrf54l_pwm.h    | 223 +++++++++
 arch/arm/src/nrf54l/nrf54l_pwm.c             | 679 +++++++++++++++++++++++++++
 arch/arm/src/nrf54l/nrf54l_pwm.h             | 117 +++++
 7 files changed, 1178 insertions(+), 1 deletion(-)

diff --git a/Documentation/platforms/arm/nrf54l/index.rst 
b/Documentation/platforms/arm/nrf54l/index.rst
index b3293e5a51a..0dc99f96282 100644
--- a/Documentation/platforms/arm/nrf54l/index.rst
+++ b/Documentation/platforms/arm/nrf54l/index.rst
@@ -17,7 +17,7 @@ Peripheral  Support Notes
 GPIO        Yes
 GPIOTE      Yes
 GRTC        Yes     Counter and tickless scheduling
-PWM         No
+PWM         Yes
 QDEC        No
 RADIO       Yes     Bluetooth LE through SDC
 RRAMC       Yes     Progmem erase/write interface
@@ -49,6 +49,13 @@ by LFCLK, so the LFCLK source selected with 
``CONFIG_NRF54L_USE_LFCLK``
 determines the long-term accuracy of the system time.
 With SDC enabled, channels 7 through 11 are reserved for MPSL.
 
+PWM
+---
+
+PWM0 through PWM2 correspond to PWM20, PWM21 and PWM22. Each instance
+supports four output channels. The board must provide an
+``NRF54L_PWMn_CHm_PIN`` definition for each enabled channel.
+
 RADIO
 -----
 
diff --git a/arch/arm/src/nrf54l/CMakeLists.txt 
b/arch/arm/src/nrf54l/CMakeLists.txt
index e545c8db9e6..f3f1b86ccac 100644
--- a/arch/arm/src/nrf54l/CMakeLists.txt
+++ b/arch/arm/src/nrf54l/CMakeLists.txt
@@ -49,6 +49,9 @@ endif()
 if(CONFIG_NRF54L_GPIOTE)
   list(APPEND SRCS nrf54l_gpiote.c)
 endif()
+if(CONFIG_NRF54L_PWM)
+  list(APPEND SRCS nrf54l_pwm.c)
+endif()
 if(CONFIG_NRF54L_TIMER)
   list(APPEND SRCS nrf54l_tim.c)
   if(CONFIG_TIMER)
diff --git a/arch/arm/src/nrf54l/Kconfig b/arch/arm/src/nrf54l/Kconfig
index e0f9107e2f6..44539a84ee3 100644
--- a/arch/arm/src/nrf54l/Kconfig
+++ b/arch/arm/src/nrf54l/Kconfig
@@ -33,6 +33,10 @@ config NRF54L_TIMER
        bool
        default n
 
+config NRF54L_PWM
+       bool
+       default n
+
 menu "nRF54L Peripheral Selection"
 
 config NRF54L_GPIOTE
@@ -141,6 +145,24 @@ config NRF54L_TIMER6
        depends on !NRF54L_SOFTDEVICE_CONTROLLER
        default n
 
+config NRF54L_PWM0
+       bool "PWM0 (PWM20)"
+       select NRF54L_PWM
+       depends on PWM
+       default n
+
+config NRF54L_PWM1
+       bool "PWM1 (PWM21)"
+       select NRF54L_PWM
+       depends on PWM
+       default n
+
+config NRF54L_PWM2
+       bool "PWM2 (PWM22)"
+       select NRF54L_PWM
+       depends on PWM
+       default n
+
 config NRF54L_GRTC
        bool "GRTC"
        default n
@@ -225,6 +247,128 @@ config NRF54L_PER_PIN_INTERRUPTS
 
 endmenu # GPIO Interrupt Configuration
 
+menu "PWM configuration"
+
+if NRF54L_PWM
+
+config NRF54L_PWM_MULTICHAN
+       bool "PWM Multiple Output Channels"
+       default n
+
+if NRF54L_PWM_MULTICHAN
+
+if NRF54L_PWM0
+
+config NRF54L_PWM0_CH0
+       bool "PWM0 Channel 0 Output"
+       default n
+       ---help---
+               Enables channel 0 output.
+
+config NRF54L_PWM0_CH1
+       bool "PWM0 Channel 1 Output"
+       default n
+       ---help---
+               Enables channel 1 output.
+
+config NRF54L_PWM0_CH2
+       bool "PWM0 Channel 2 Output"
+       default n
+       ---help---
+               Enables channel 2 output.
+
+config NRF54L_PWM0_CH3
+       bool "PWM0 Channel 3 Output"
+       default n
+       ---help---
+               Enables channel 3 output.
+
+endif # NRF54L_PWM0
+
+if NRF54L_PWM1
+
+config NRF54L_PWM1_CH0
+       bool "PWM1 Channel 0 Output"
+       default n
+       ---help---
+               Enables channel 0 output.
+
+config NRF54L_PWM1_CH1
+       bool "PWM1 Channel 1 Output"
+       default n
+       ---help---
+               Enables channel 1 output.
+
+config NRF54L_PWM1_CH2
+       bool "PWM1 Channel 2 Output"
+       default n
+       ---help---
+               Enables channel 2 output.
+
+config NRF54L_PWM1_CH3
+       bool "PWM1 Channel 3 Output"
+       default n
+       ---help---
+               Enables channel 3 output.
+
+endif # NRF54L_PWM1
+
+if NRF54L_PWM2
+
+config NRF54L_PWM2_CH0
+       bool "PWM2 Channel 0 Output"
+       default n
+       ---help---
+               Enables channel 0 output.
+
+config NRF54L_PWM2_CH1
+       bool "PWM2 Channel 1 Output"
+       default n
+       ---help---
+               Enables channel 1 output.
+
+config NRF54L_PWM2_CH2
+       bool "PWM2 Channel 2 Output"
+       default n
+       ---help---
+               Enables channel 2 output.
+
+config NRF54L_PWM2_CH3
+       bool "PWM2 Channel 3 Output"
+       default n
+       ---help---
+               Enables channel 3 output.
+
+endif # NRF54L_PWM2
+
+endif # NRF54L_PWM_MULTICHAN
+
+if !NRF54L_PWM_MULTICHAN
+
+config NRF54L_PWM0_CHANNEL
+       int "PWM0 Output Channel"
+       depends on NRF54L_PWM0
+       default 0
+       range 0 3
+
+config NRF54L_PWM1_CHANNEL
+       int "PWM1 Output Channel"
+       depends on NRF54L_PWM1
+       default 0
+       range 0 3
+
+config NRF54L_PWM2_CHANNEL
+       int "PWM2 Output Channel"
+       depends on NRF54L_PWM2
+       default 0
+       range 0 3
+
+endif # !NRF54L_PWM_MULTICHAN
+
+endif # NRF54L_PWM
+
+endmenu # PWM configuration
+
 menuconfig NRF54L_SOFTDEVICE_CONTROLLER
        bool "SoftDevice Controller"
        depends on ALLOW_BSDNORDIC_COMPONENTS
diff --git a/arch/arm/src/nrf54l/Make.defs b/arch/arm/src/nrf54l/Make.defs
index fe9629b9e25..ded19109ce8 100644
--- a/arch/arm/src/nrf54l/Make.defs
+++ b/arch/arm/src/nrf54l/Make.defs
@@ -50,6 +50,10 @@ ifeq ($(CONFIG_NRF54L_GPIOTE),y)
 CHIP_CSRCS += nrf54l_gpiote.c
 endif
 
+ifeq ($(CONFIG_NRF54L_PWM),y)
+CHIP_CSRCS += nrf54l_pwm.c
+endif
+
 ifeq ($(CONFIG_NRF54L_TIMER),y)
 CHIP_CSRCS += nrf54l_tim.c
 ifeq ($(CONFIG_TIMER),y)
diff --git a/arch/arm/src/nrf54l/hardware/nrf54l_pwm.h 
b/arch/arm/src/nrf54l/hardware/nrf54l_pwm.h
new file mode 100644
index 00000000000..5d3a44a113b
--- /dev/null
+++ b/arch/arm/src/nrf54l/hardware/nrf54l_pwm.h
@@ -0,0 +1,223 @@
+/****************************************************************************
+ * arch/arm/src/nrf54l/hardware/nrf54l_pwm.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_NRF54L_HARDWARE_NRF54L_PWM_H
+#define __ARCH_ARM_SRC_NRF54L_HARDWARE_NRF54L_PWM_H
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+#include "hardware/nrf54l_memorymap.h"
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+/* Configuration ************************************************************/
+
+/* Register offsets *********************************************************/
+
+#define NRF54L_PWM_TASKS_STOP_OFFSET                  0x0004              /* 
Stop PWM */
+#define NRF54L_PWM_TASKS_NEXTSTEP_OFFSET              0x0008              /* 
Steps by one value in the current sequence */
+#define NRF54L_PWM_TASKS_DMA_SEQ_START_OFFSET(n)      (0x0010 + 8 * (n))  /* 
Start sequence n */
+#define NRF54L_PWM_SUBSCRIBE_STOP_OFFSET              0x0084              /* 
Subscribe to STOP */
+#define NRF54L_PWM_SUBSCRIBE_NEXTSTEP_OFFSET          0x0088              /* 
Subscribe to NEXTSTEP */
+#define NRF54L_PWM_SUBSCRIBE_DMA_SEQ_START_OFFSET(n)  (0x0090 + 8 * (n))  /* 
Subscribe to sequence n START */
+#define NRF54L_PWM_EVENTS_STOPPED_OFFSET              0x0104              /* 
STOP event */
+#define NRF54L_PWM_EVENTS_SEQSTARTED0_OFFSET          0x0108              /* 
Sequence 0 started event */
+#define NRF54L_PWM_EVENTS_SEQSTARTED1_OFFSET          0x010c              /* 
Sequence 1 started event */
+#define NRF54L_PWM_EVENTS_SEQEND0_OFFSET              0x0110              /* 
Sequence 0 end event */
+#define NRF54L_PWM_EVENTS_SEQEND1_OFFSET              0x0114              /* 
Sequence 1 end event */
+#define NRF54L_PWM_EVENTS_PWMPERIODEND_OFFSET         0x0118              /* 
PWM period end event */
+#define NRF54L_PWM_EVENTS_LOOPSDONE_OFFSET            0x011c              /* 
Loop done event */
+#define NRF54L_PWM_EVENTS_RAMUNDERFLOW_OFFSET         0x0120              /* 
RAM underflow */
+#define NRF54L_PWM_EVENTS_DMA_SEQ_END_OFFSET(n)       (0x0124 + 12 * (n)) /* 
Sequence n DMA buffer completed */
+#define NRF54L_PWM_EVENTS_DMA_SEQ_READY_OFFSET(n)     (0x0128 + 12 * (n)) /* 
Sequence n DMA buffer prepared */
+#define NRF54L_PWM_EVENTS_DMA_SEQ_BUSERROR_OFFSET(n)  (0x012c + 12 * (n)) /* 
Sequence n DMA bus error */
+#define NRF54L_PWM_EVENTS_COMPAREMATCH_OFFSET(n)      (0x013c + 4 * (n))  /* 
Compare match on PWM channel n */
+#define NRF54L_PWM_PUBLISH_STOPPED_OFFSET             0x0184              /* 
Publish STOPPED */
+#define NRF54L_PWM_PUBLISH_SEQSTARTED_OFFSET(n)       (0x0188 + 4 * (n))  /* 
Publish sequence n started event */
+#define NRF54L_PWM_PUBLISH_SEQEND_OFFSET(n)           (0x0190 + 4 * (n))  /* 
Publish sequence n end event */
+#define NRF54L_PWM_PUBLISH_PWMPERIODEND_OFFSET        0x0198              /* 
Publish PWMPERIODEND */
+#define NRF54L_PWM_PUBLISH_LOOPSDONE_OFFSET           0x019c              /* 
Publish LOOPSDONE */
+#define NRF54L_PWM_PUBLISH_RAMUNDERFLOW_OFFSET        0x01a0              /* 
Publish RAMUNDERFLOW */
+#define NRF54L_PWM_PUBLISH_DMA_SEQ_END_OFFSET(n)      (0x01a4 + 12 * (n)) /* 
Publish sequence n DMA END event */
+#define NRF54L_PWM_PUBLISH_DMA_SEQ_READY_OFFSET(n)    (0x01a8 + 12 * (n)) /* 
Publish sequence n DMA READY event */
+#define NRF54L_PWM_PUBLISH_DMA_SEQ_BUSERROR_OFFSET(n) (0x01ac + 12 * (n)) /* 
Publish sequence n DMA BUSERROR event */
+#define NRF54L_PWM_PUBLISH_COMPAREMATCH_OFFSET(n)     (0x01bc + 4 * (n))  /* 
Publish channel n COMPAREMATCH event */
+#define NRF54L_PWM_SHORTS_OFFSET                      0x0200              /* 
Shortcut register */
+#define NRF54L_PWM_INTEN_OFFSET                       0x0300              /* 
Enable or disable interrupt */
+#define NRF54L_PWM_INTENSET_OFFSET                    0x0304              /* 
Enable interrupt */
+#define NRF54L_PWM_INTENCLR_OFFSET                    0x0308              /* 
Disable interrupt */
+#define NRF54L_PWM_INTPEND_OFFSET                     0x030c              /* 
Pending interrupts */
+#define NRF54L_PWM_ENABLE_OFFSET                      0x0500              /* 
PWM enable */
+#define NRF54L_PWM_MODE_OFFSET                        0x0504              /* 
Wave counter mode */
+#define NRF54L_PWM_COUNTERTOP_OFFSET                  0x0508              /* 
Counter max value */
+#define NRF54L_PWM_PRESCALER_OFFSET                   0x050c              /* 
Prescaler configuration */
+#define NRF54L_PWM_DECODER_OFFSET                     0x0510              /* 
Configuration of the decoder */
+#define NRF54L_PWM_LOOP_OFFSET                        0x0514              /* 
Amount of playback of a loop */
+#define NRF54L_PWM_IDLEOUT_OFFSET                     0x0518              /* 
Idle output levels */
+#define NRF54L_PWM_SEQ0REFRESH_OFFSET                 0x0528              /* 
Sequence 0 additional periods */
+#define NRF54L_PWM_SEQ0ENDDELAY_OFFSET                0x052c              /* 
Time added after sequence 0 */
+#define NRF54L_PWM_SEQ1REFRESH_OFFSET                 0x0548              /* 
Sequence 1 additional periods */
+#define NRF54L_PWM_SEQ1ENDDELAY_OFFSET                0x054c              /* 
Time added after sequence 1 */
+#define NRF54L_PWM_PSEL0_OFFSET                       0x0560              /* 
Output pin select for PWM chan 0 */
+#define NRF54L_PWM_PSEL1_OFFSET                       0x0564              /* 
Output pin select for PWM chan 1 */
+#define NRF54L_PWM_PSEL2_OFFSET                       0x0568              /* 
Output pin select for PWM chan 2 */
+#define NRF54L_PWM_PSEL3_OFFSET                       0x056c              /* 
Output pin select for PWM chan 3 */
+
+#define NRF54L_PWM_DMA_SEQ_PTR_OFFSET(n)                 (0x0704 + 36 * (n)) 
/* Sequence n buffer address */
+#define NRF54L_PWM_DMA_SEQ_MAXCNT_OFFSET(n)              (0x0708 + 36 * (n)) 
/* Sequence n buffer size in bytes */
+#define NRF54L_PWM_DMA_SEQ_AMOUNT_OFFSET(n)              (0x070c + 36 * (n)) 
/* Sequence n completed transfer byte count */
+#define NRF54L_PWM_DMA_SEQ_CURRENTAMOUNT_OFFSET(n)       (0x0710 + 36 * (n)) 
/* Sequence n current transfer byte count */
+#define NRF54L_PWM_DMA_SEQ_TERMINATEONBUSERROR_OFFSET(n) (0x071c + 36 * (n)) 
/* Terminate sequence n DMA on bus error */
+#define NRF54L_PWM_DMA_SEQ_BUSERRORADDRESS_OFFSET(n)     (0x0720 + 36 * (n)) 
/* Address of last sequence n DMA bus error */
+
+/* Register Bitfield Definitions ********************************************/
+
+/* TASKS_STOP Register */
+
+#define PWM_TASKS_STOP                 (1 << 0) /* Bit 0: Stop PWM */
+
+/* TASKS_DMA.SEQ[n].START Register */
+
+#define PWM_TASKS_DMA_SEQ_START        (1 << 0) /* Bit 0: Start sequence */
+
+/* TASKS_NEXTSTEP Register */
+
+#define PWM_TASKS_NEXTSTEP             (1 << 0) /* Bit 0: Next step */
+
+/* SHORTS Register */
+
+#define PWM_SHORTS_SEQEND0_STOP             (1 << 0) /* Bit 0: Shortcut 
between event SEQEND[0] and task STOP */
+#define PWM_SHORTS_SEQEND1_STOP             (1 << 1) /* Bit 1: Shortcut 
between event SEQEND[1] and task STOP */
+#define PWM_SHORTS_LOOPSDONE_DMA_SEQ0_START (1 << 2) /* Bit 2: Shortcut 
between event LOOPSDONE and task DMA.SEQ[0].START */
+#define PWM_SHORTS_LOOPSDONE_DMA_SEQ1_START (1 << 3) /* Bit 3: Shortcut 
between event LOOPSDONE and task DMA.SEQ[1].START */
+#define PWM_SHORTS_LOOPSDONE_STOP           (1 << 4) /* Bit 4: Shortcut 
between event LOOPSDONE and task STOP */
+#define PWM_SHORTS_RAMUNDERFLOW_STOP        (1 << 5) /* Stop on RAM underflow 
*/
+#define PWM_SHORTS_DMA_SEQ0_BUSERROR_STOP   (1 << 6) /* Bit 6: Shortcut 
between event DMA.SEQ[0].BUSERROR and task STOP */
+#define PWM_SHORTS_DMA_SEQ1_BUSERROR_STOP   (1 << 7) /* Bit 7: Shortcut 
between event DMA.SEQ[1].BUSERROR and task STOP */
+
+/* INTEN/INTENSET/INTENCLR Register */
+
+#define PWM_INT_STOPPED                (1 << 1)              /* Interrupt for 
STOPPED */
+#define PWM_INT_SEQSTARTED0            (1 << 2)              /* Interrupt for 
SEQSTARTED0 */
+#define PWM_INT_SEQSTARTED1            (1 << 3)              /* Interrupt for 
SEQSTARTED1 */
+#define PWM_INT_SEQEND0                (1 << 4)              /* Interrupt for 
SEQEND0 */
+#define PWM_INT_SEQEND1                (1 << 5)              /* Interrupt for 
SEQEND1 */
+#define PWM_INT_PWMPERIODEND           (1 << 6)              /* Interrupt for 
PWMPERIODEND */
+#define PWM_INT_LOOPSDONE              (1 << 7)              /* Interrupt for 
LOOPSDONE */
+#define PWM_INT_RAMUNDERFLOW           (1 << 8)              /* Interrupt for 
RAMUNDERFLOW */
+#define PWM_INT_DMA_SEQ_END(n)         (1 << (9 + 3 * (n)))  /* Interrupt for 
sequence n DMA END */
+#define PWM_INT_DMA_SEQ_READY(n)       (1 << (10 + 3 * (n))) /* Interrupt for 
sequence n DMA READY */
+#define PWM_INT_DMA_SEQ_BUSERROR(n)    (1 << (11 + 3 * (n))) /* Interrupt for 
sequence n DMA BUSERROR */
+#define PWM_INT_COMPAREMATCH(n)        (1 << (15 + (n)))     /* Interrupt for 
channel n COMPAREMATCH */
+
+/* ENABLE Register */
+
+#define PWM_ENABLE_ENABLE              (1 << 0) /* Bit 0: Enable PWM module */
+#define PWM_ENABLE_DISABLE             (0 << 0) /* Bit 0: Disable PWM module */
+
+/* MODE Register */
+
+#define PWM_MODE_UP                    (0 << 0) /* Bit 0: Up counter, 
edge-aligned PWM */
+#define PWM_MODE_UPDOWN                (1 << 0) /* Bit 0: Up and down counter, 
center-aligned PWM */
+
+/* COUNTERTOP Register */
+
+#define PWM_COUNTERTOP_MASK            (0x7fff)
+
+/* PRESCALER Register */
+
+#define PWM_PRESCALER_SHIFT            (0)
+#define PWM_PRESCALER_MASK             (7 << PWM_PRESCALER_SHIFT)
+#  define PWM_PRESCALER_16MHZ          (0 << PWM_PRESCALER_SHIFT)
+#  define PWM_PRESCALER_8MHZ           (1 << PWM_PRESCALER_SHIFT)
+#  define PWM_PRESCALER_4MHZ           (2 << PWM_PRESCALER_SHIFT)
+#  define PWM_PRESCALER_2MHZ           (3 << PWM_PRESCALER_SHIFT)
+#  define PWM_PRESCALER_1MHZ           (4 << PWM_PRESCALER_SHIFT)
+#  define PWM_PRESCALER_500KHZ         (5 << PWM_PRESCALER_SHIFT)
+#  define PWM_PRESCALER_250KHZ         (6 << PWM_PRESCALER_SHIFT)
+#  define PWM_PRESCALER_125KHZ         (7 << PWM_PRESCALER_SHIFT)
+
+/* DECODER Register */
+
+#define PWM_DECODER_LOAD_SHIFT         (0) /* Bits 0-1: How a sequence is read 
from RAM */
+#define PWM_DECODER_LOAD_MASK          (3 << PWM_DECODER_LOAD_SHIFT)
+#  define PWM_DECODER_LOAD_COMMON      (0 << PWM_DECODER_LOAD_SHIFT)
+#  define PWM_DECODER_LOAD_GROUPED     (1 << PWM_DECODER_LOAD_SHIFT)
+#  define PWM_DECODER_LOAD_INDIVIDUAL  (2 << PWM_DECODER_LOAD_SHIFT)
+#  define PWM_DECODER_LOAD_WAVEFORM    (3 << PWM_DECODER_LOAD_SHIFT)
+
+#define PWM_DECODER_MODE_REFRESH       (0 << 8) /* Load using REFRESH */
+#define PWM_DECODER_MODE_NEXTSTEP      (1 << 8) /* Load using NEXTSTEP */
+
+/* LOOP Register */
+
+#define PWM_LOOP_MASK                  (0xffff)
+
+/* DMA.SEQ[n].MAXCNT Register */
+
+#define PWM_DMA_MAXCNT_MASK            (0x7fff)
+#define PWM_DMA_TERMINATEONBUSERROR    (1 << 0)
+
+/* IDLEOUT Register */
+
+#define PWM_IDLEOUT_VAL(n)             (1 << (n))
+
+/* SUBSCRIBE and PUBLISH Registers */
+
+#define PWM_SUBSCRIBE_CHIDX_SHIFT      (0)
+#define PWM_SUBSCRIBE_CHIDX_MASK       (0xff << PWM_SUBSCRIBE_CHIDX_SHIFT)
+#define PWM_SUBSCRIBE_EN               (1 << 31)
+#define PWM_PUBLISH_CHIDX_SHIFT        (0)
+#define PWM_PUBLISH_CHIDX_MASK         (0xff << PWM_PUBLISH_CHIDX_SHIFT)
+#define PWM_PUBLISH_EN                 (1 << 31)
+
+/* SEQ[n]REFRESH Register */
+
+#define PWM_SEQREFRESH_MASK            (0xffffff)
+
+/* SEQ[n]ENDDELAY Register */
+
+#define PWM_SEQENDDELAY_MASK           (0xffffff)
+
+/* PSEL[x] Register */
+
+#define PWM_PSEL_PIN_SHIFT             (0)        /* Bits 0-4: OUT pin number 
*/
+#define PWM_PSEL_PIN_MASK              (0x1f << PWM_PSEL_PIN_SHIFT)
+#define PWM_PSEL_PORT_SHIFT            (5)        /* Bits 5-7: OUT port number 
*/
+#define PWM_PSEL_PORT_MASK             (0x7 << PWM_PSEL_PORT_SHIFT)
+#define PWM_PSEL_CONNECTED             (0 << 31)  /* Bit 31: Connected */
+#define PWM_PSEL_DISCONNECTED          (1 << 31)  /* Bit 31: Disconnected */
+#define PWM_PSEL_RESET                 (0xffffffff)
+
+/* Decoder data */
+
+#define PWM_DECODER_COMPARE_SHIFT     (0)
+#define PWM_DECODER_COMPARE_MASK      (0x7fff)
+#define PWM_DECODER_POL_RISING        (0 << 15)
+#define PWM_DECODER_POL_FALLING       (1 << 15)
+
+#endif /* __ARCH_ARM_SRC_NRF54L_HARDWARE_NRF54L_PWM_H */
diff --git a/arch/arm/src/nrf54l/nrf54l_pwm.c b/arch/arm/src/nrf54l/nrf54l_pwm.c
new file mode 100644
index 00000000000..68867054daa
--- /dev/null
+++ b/arch/arm/src/nrf54l/nrf54l_pwm.c
@@ -0,0 +1,679 @@
+/****************************************************************************
+ * arch/arm/src/nrf54l/nrf54l_pwm.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 <assert.h>
+#include <nuttx/debug.h>
+#include <errno.h>
+#include <inttypes.h>
+#include <stdint.h>
+#include <stdio.h>
+
+#include <arch/board/board.h>
+
+#include "arm_internal.h"
+#include "nrf54l_gpio.h"
+#include "nrf54l_pwm.h"
+
+#include "hardware/nrf54l_pwm.h"
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+/* Default PWM polarity */
+
+#define PWM_POLARITY_DEFAULT (PWM_DECODER_POL_FALLING)
+
+/* Sequence 0 length */
+
+#define PWM_SEQ0_LEN         (4)
+
+/****************************************************************************
+ * Private Types
+ ****************************************************************************/
+
+struct nrf54l_pwm_s
+{
+  const struct pwm_ops_s *ops;       /* PWM operations */
+  uint32_t                base;      /* Base address of PWM register */
+  uint32_t                frequency; /* Current frequency setting */
+  uint32_t                cntrtop;   /* Counter top */
+  uint32_t                ch0_pin;   /* Channel 1 pin */
+  uint32_t                ch1_pin;   /* Channel 2 pin */
+  uint32_t                ch2_pin;   /* Channel 3 pin */
+  uint32_t                ch3_pin;   /* Channel 4 pin */
+
+  /* Sequence 0 */
+
+  uint16_t                    seq0[PWM_SEQ0_LEN];
+};
+
+/****************************************************************************
+ * Private Function Prototypes
+ ****************************************************************************/
+
+/* PWM Register access */
+
+static inline void nrf54l_pwm_putreg(struct nrf54l_pwm_s *priv,
+                                     uint32_t offset,
+                                     uint32_t value);
+static inline uint32_t nrf54l_pwm_getreg(struct nrf54l_pwm_s *priv,
+                                         uint32_t offset);
+
+/* PWM helpers */
+
+static int nrf54l_pwm_configure(struct nrf54l_pwm_s *priv);
+static int nrf54l_pwm_duty(struct nrf54l_pwm_s *priv, uint8_t chan,
+                           ub16_t duty);
+static int nrf54l_pwm_freq(struct nrf54l_pwm_s *priv, uint32_t freq);
+
+/* PWM driver methods */
+
+static int nrf54l_pwm_setup(struct pwm_lowerhalf_s *dev);
+static int nrf54l_pwm_shutdown(struct pwm_lowerhalf_s *dev);
+static int nrf54l_pwm_start(struct pwm_lowerhalf_s *dev,
+                            const struct pwm_info_s *info);
+static int nrf54l_pwm_stop(struct pwm_lowerhalf_s *dev);
+static int nrf54l_pwm_ioctl(struct pwm_lowerhalf_s *dev,
+                            int cmd, unsigned long arg);
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+/* This is the list of lower half PWM driver methods used by the upper half
+ * driver.
+ */
+
+static const struct pwm_ops_s g_nrf54l_pwmops =
+{
+  .setup       = nrf54l_pwm_setup,
+  .shutdown    = nrf54l_pwm_shutdown,
+  .start       = nrf54l_pwm_start,
+  .stop        = nrf54l_pwm_stop,
+  .ioctl       = nrf54l_pwm_ioctl,
+};
+
+#ifdef CONFIG_NRF54L_PWM0
+/* PWM 0 */
+
+struct nrf54l_pwm_s g_nrf54l_pwm0 =
+{
+  .ops     = &g_nrf54l_pwmops,
+  .base    = NRF54L_PWM20_BASE,
+#ifdef CONFIG_NRF54L_PWM0_CH0
+  .ch0_pin = NRF54L_PWM0_CH0_PIN,
+#endif
+#ifdef CONFIG_NRF54L_PWM0_CH1
+  .ch1_pin = NRF54L_PWM0_CH1_PIN,
+#endif
+#ifdef CONFIG_NRF54L_PWM0_CH2
+  .ch2_pin = NRF54L_PWM0_CH2_PIN,
+#endif
+#ifdef CONFIG_NRF54L_PWM0_CH3
+  .ch3_pin = NRF54L_PWM0_CH3_PIN,
+#endif
+};
+#endif
+
+#ifdef CONFIG_NRF54L_PWM1
+/* PWM 1 */
+
+struct nrf54l_pwm_s g_nrf54l_pwm1 =
+{
+  .ops     = &g_nrf54l_pwmops,
+  .base    = NRF54L_PWM21_BASE,
+#ifdef CONFIG_NRF54L_PWM1_CH0
+  .ch0_pin = NRF54L_PWM1_CH0_PIN,
+#endif
+#ifdef CONFIG_NRF54L_PWM1_CH1
+  .ch1_pin = NRF54L_PWM1_CH1_PIN,
+#endif
+#ifdef CONFIG_NRF54L_PWM1_CH2
+  .ch2_pin = NRF54L_PWM1_CH2_PIN,
+#endif
+#ifdef CONFIG_NRF54L_PWM1_CH3
+  .ch3_pin = NRF54L_PWM1_CH3_PIN,
+#endif
+};
+#endif
+
+#ifdef CONFIG_NRF54L_PWM2
+/* PWM 2 */
+
+struct nrf54l_pwm_s g_nrf54l_pwm2 =
+{
+  .ops     = &g_nrf54l_pwmops,
+  .base    = NRF54L_PWM22_BASE,
+#ifdef CONFIG_NRF54L_PWM2_CH0
+  .ch0_pin = NRF54L_PWM2_CH0_PIN,
+#endif
+#ifdef CONFIG_NRF54L_PWM2_CH1
+  .ch1_pin = NRF54L_PWM2_CH1_PIN,
+#endif
+#ifdef CONFIG_NRF54L_PWM2_CH2
+  .ch2_pin = NRF54L_PWM2_CH2_PIN,
+#endif
+#ifdef CONFIG_NRF54L_PWM2_CH3
+  .ch3_pin = NRF54L_PWM2_CH3_PIN,
+#endif
+};
+#endif
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: nrf54l_pwm_putreg
+ *
+ * Description:
+ *   Put a 32-bit register value by offset
+ *
+ ****************************************************************************/
+
+static inline void nrf54l_pwm_putreg(struct nrf54l_pwm_s *priv,
+                                     uint32_t offset,
+                                     uint32_t value)
+{
+  putreg32(value, priv->base + offset);
+}
+
+/****************************************************************************
+ * Name: nrf54l_pwm_getreg
+ *
+ * Description:
+ *   Get a 32-bit register value by offset
+ *
+ ****************************************************************************/
+
+static inline uint32_t nrf54l_pwm_getreg(struct nrf54l_pwm_s *priv,
+                                         uint32_t offset)
+{
+  return getreg32(priv->base + offset);
+}
+
+/****************************************************************************
+ * Name: nrf54l_pwm_configure
+ *
+ * Description:
+ *   Configure PWM
+ *
+ ****************************************************************************/
+
+static int nrf54l_pwm_configure(struct nrf54l_pwm_s *priv)
+{
+  uint32_t regval = 0;
+  int      ret    = OK;
+
+  DEBUGASSERT(priv);
+
+  /* Configure PWM mode */
+
+  nrf54l_pwm_putreg(priv, NRF54L_PWM_MODE_OFFSET, PWM_MODE_UP);
+
+  /* Configure decoder  */
+
+  regval = PWM_DECODER_LOAD_INDIVIDUAL | PWM_DECODER_MODE_REFRESH;
+  nrf54l_pwm_putreg(priv, NRF54L_PWM_DECODER_OFFSET, regval);
+
+  /* Configure sequence 0 */
+
+  regval = (uintptr_t)priv->seq0;
+  DEBUGASSERT((regval & 3) == 0);
+  nrf54l_pwm_putreg(priv, NRF54L_PWM_DMA_SEQ_PTR_OFFSET(0), regval);
+
+  /* Sequence length is in bytes */
+
+  regval = sizeof(priv->seq0);
+  nrf54l_pwm_putreg(priv, NRF54L_PWM_DMA_SEQ_MAXCNT_OFFSET(0), regval);
+
+  regval = 0;
+  nrf54l_pwm_putreg(priv, NRF54L_PWM_SEQ0REFRESH_OFFSET, regval);
+
+  return ret;
+}
+
+/****************************************************************************
+ * Name: nrf54l_pwm_duty
+ *
+ * Description:
+ *   Configure PWM duty
+ *
+ ****************************************************************************/
+
+static int nrf54l_pwm_duty(struct nrf54l_pwm_s *priv, uint8_t chan,
+                           ub16_t duty)
+{
+  uint16_t compare = 0;
+
+  DEBUGASSERT(priv);
+
+  pwminfo("PWM channel: %d duty: %" PRId32 "\n", chan, duty);
+
+  /* Get compare
+   *
+   * duty cycle = compare / reload (fractional value)
+   */
+
+  compare = b16toi(duty * priv->cntrtop + b16HALF);
+
+  /* Configure channel sequence */
+
+  priv->seq0[chan] = PWM_POLARITY_DEFAULT | compare;
+
+  pwminfo("seq0[%d]: %d %d\n", chan, compare, priv->seq0[chan]);
+
+  return OK;
+}
+
+/****************************************************************************
+ * Name: nrf54l_pwm_freq
+ *
+ * Description:
+ *   Configure PWM frequency
+ *
+ ****************************************************************************/
+
+static int nrf54l_pwm_freq(struct nrf54l_pwm_s *priv, uint32_t freq)
+{
+  uint32_t regval    = 0;
+  uint32_t pwm_clk   = 0;
+  uint32_t top       = 0;
+  uint32_t prescaler = 0;
+  uint64_t tmp       = 0;
+  int      ret       = OK;
+
+  DEBUGASSERT(priv);
+
+  /* Get best prescaler */
+
+  tmp = PWM_COUNTERTOP_MASK * freq;
+
+  if (tmp >= 16000000)
+    {
+      pwm_clk   = 16000000;
+      prescaler = PWM_PRESCALER_16MHZ;
+    }
+  else if (tmp >= 8000000)
+    {
+      pwm_clk   = 8000000;
+      prescaler = PWM_PRESCALER_8MHZ;
+    }
+  else if (tmp >= 4000000)
+    {
+      pwm_clk   = 4000000;
+      prescaler = PWM_PRESCALER_4MHZ;
+    }
+  else if (tmp >= 2000000)
+    {
+      pwm_clk   = 2000000;
+      prescaler = PWM_PRESCALER_2MHZ;
+    }
+  else if (tmp >= 1000000)
+    {
+      pwm_clk   = 1000000;
+      prescaler = PWM_PRESCALER_1MHZ;
+    }
+  else if (tmp >= 500000)
+    {
+      pwm_clk   = 500000;
+      prescaler = PWM_PRESCALER_500KHZ;
+    }
+  else if (tmp >= 250000)
+    {
+      pwm_clk   = 250000;
+      prescaler = PWM_PRESCALER_250KHZ;
+    }
+  else
+    {
+      pwm_clk   = 125000;
+      prescaler = PWM_PRESCALER_125KHZ;
+    }
+
+  /* Configure prescaler */
+
+  nrf54l_pwm_putreg(priv, NRF54L_PWM_PRESCALER_OFFSET, prescaler);
+
+  /* Get counter max */
+
+  top = pwm_clk / freq;
+  if (top < 2)
+    {
+      top = 1;
+    }
+  else if (top > PWM_COUNTERTOP_MASK)
+    {
+      top = PWM_COUNTERTOP_MASK;
+    }
+  else
+    {
+      top = top - 1;
+    }
+
+  /* Configure counter max */
+
+  regval = top;
+  nrf54l_pwm_putreg(priv, NRF54L_PWM_COUNTERTOP_OFFSET, regval);
+
+  priv->cntrtop = top;
+
+  pwminfo("PWM frequency: %" PRId32 " pwm_clk: %" PRId32
+          " pwm_prescaler: %" PRId32 " top: %" PRId32 "\n",
+          freq, pwm_clk, prescaler, top);
+
+  return ret;
+}
+
+/****************************************************************************
+ * Name: nrf54l_pwm_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.
+ *
+ ****************************************************************************/
+
+static int nrf54l_pwm_setup(struct pwm_lowerhalf_s *dev)
+{
+  struct nrf54l_pwm_s *priv = (struct nrf54l_pwm_s *)dev;
+  int                 ret  = OK;
+  uint32_t            regval = 0;
+  uint32_t            pin = 0;
+  uint32_t            port = 0;
+
+  DEBUGASSERT(dev);
+
+  /* Configure channels */
+
+  if (priv->ch0_pin != 0)
+    {
+      nrf54l_gpio_config(priv->ch0_pin);
+
+      pin  = GPIO_PIN_DECODE(priv->ch0_pin);
+      port = GPIO_PORT_DECODE(priv->ch0_pin);
+
+      regval = (port << PWM_PSEL_PORT_SHIFT);
+      regval |= (pin << PWM_PSEL_PIN_SHIFT);
+
+      nrf54l_pwm_putreg(priv, NRF54L_PWM_PSEL0_OFFSET, regval);
+    }
+
+  if (priv->ch1_pin != 0)
+    {
+      nrf54l_gpio_config(priv->ch1_pin);
+
+      pin  = GPIO_PIN_DECODE(priv->ch1_pin);
+      port = GPIO_PORT_DECODE(priv->ch1_pin);
+
+      regval = (port << PWM_PSEL_PORT_SHIFT);
+      regval |= (pin << PWM_PSEL_PIN_SHIFT);
+
+      nrf54l_pwm_putreg(priv, NRF54L_PWM_PSEL1_OFFSET, regval);
+    }
+
+  if (priv->ch2_pin != 0)
+    {
+      nrf54l_gpio_config(priv->ch2_pin);
+
+      pin  = GPIO_PIN_DECODE(priv->ch2_pin);
+      port = GPIO_PORT_DECODE(priv->ch2_pin);
+
+      regval = (port << PWM_PSEL_PORT_SHIFT);
+      regval |= (pin << PWM_PSEL_PIN_SHIFT);
+
+      nrf54l_pwm_putreg(priv, NRF54L_PWM_PSEL2_OFFSET, regval);
+    }
+
+  if (priv->ch3_pin != 0)
+    {
+      nrf54l_gpio_config(priv->ch3_pin);
+
+      pin  = GPIO_PIN_DECODE(priv->ch3_pin);
+      port = GPIO_PORT_DECODE(priv->ch3_pin);
+
+      regval = (port << PWM_PSEL_PORT_SHIFT);
+      regval |= (pin << PWM_PSEL_PIN_SHIFT);
+
+      nrf54l_pwm_putreg(priv, NRF54L_PWM_PSEL3_OFFSET, regval);
+    }
+
+  /* Configure PWM */
+
+  ret = nrf54l_pwm_configure(priv);
+  if (ret < 0)
+    {
+      pwmerr("ERROR: nrf54l_pwm_configure failed %d\n", ret);
+      goto errout;
+    }
+
+  /* Enable PWM */
+
+  nrf54l_pwm_putreg(priv, NRF54L_PWM_ENABLE_OFFSET, 1);
+
+errout:
+  return ret;
+}
+
+/****************************************************************************
+ * Name: nrf54l_pwm_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
+ *
+ ****************************************************************************/
+
+static int nrf54l_pwm_shutdown(struct pwm_lowerhalf_s *dev)
+{
+  struct nrf54l_pwm_s *priv = (struct nrf54l_pwm_s *)dev;
+  int                 ret  = OK;
+
+  DEBUGASSERT(dev);
+
+  /* Disable PWM */
+
+  nrf54l_pwm_putreg(priv, NRF54L_PWM_ENABLE_OFFSET, 0);
+
+  return ret;
+}
+
+/****************************************************************************
+ * Name: nrf54l_pwm_start
+ *
+ * Description:
+ *   (Re-)initialize the PWM and start the pulsed output
+ *
+ ****************************************************************************/
+
+static int nrf54l_pwm_start(struct pwm_lowerhalf_s *dev,
+                           const struct pwm_info_s *info)
+{
+  struct nrf54l_pwm_s *priv = (struct nrf54l_pwm_s *)dev;
+  int                 ret  = OK;
+  int                 i    = 0;
+
+  DEBUGASSERT(dev);
+
+  /* If frequency has not changed we just update duty */
+
+  if (info->frequency != priv->frequency)
+    {
+      /* Update frequency */
+
+      ret = nrf54l_pwm_freq(priv, info->frequency);
+
+      if (ret == OK)
+        {
+          priv->frequency = info->frequency;
+        }
+    }
+
+  for (i = 0; ret == OK && i < CONFIG_PWM_NCHANNELS; i++)
+    {
+      /* Break the loop if all following channels are not configured */
+
+      if (info->channels[i].channel == -1)
+        {
+          break;
+        }
+
+      /* Set output if channel configured */
+
+      if (info->channels[i].channel != 0)
+        {
+          ret = nrf54l_pwm_duty(priv,
+                               (info->channels[i].channel - 1),
+                               info->channels[i].duty);
+        }
+    }
+
+  /* Start sequence 0 */
+
+  nrf54l_pwm_putreg(priv, NRF54L_PWM_EVENTS_SEQSTARTED0_OFFSET, 0);
+  nrf54l_pwm_putreg(priv, NRF54L_PWM_TASKS_DMA_SEQ_START_OFFSET(0), 1);
+
+  /* Wait for sequence started */
+
+  while (nrf54l_pwm_getreg(priv, NRF54L_PWM_EVENTS_SEQSTARTED0_OFFSET) != 1);
+
+  return ret;
+}
+
+/****************************************************************************
+ * Name: nrf54l_pwm_stop
+ *
+ * Description:
+ *   Stop the PWM
+ *
+ ****************************************************************************/
+
+static int nrf54l_pwm_stop(struct pwm_lowerhalf_s *dev)
+{
+  struct nrf54l_pwm_s *priv = (struct nrf54l_pwm_s *)dev;
+
+  DEBUGASSERT(dev);
+
+  /* Stop PWM */
+
+  nrf54l_pwm_putreg(priv, NRF54L_PWM_EVENTS_STOPPED_OFFSET, 0);
+  nrf54l_pwm_putreg(priv, NRF54L_PWM_TASKS_STOP_OFFSET, 1);
+
+  /* Wait for PWM stopped */
+
+  while (nrf54l_pwm_getreg(priv, NRF54L_PWM_EVENTS_STOPPED_OFFSET) != 1);
+
+  return OK;
+}
+
+/****************************************************************************
+ * Name: nrf54l_pwm_ioctl
+ *
+ * Description:
+ *   Lower-half logic may support platform-specific ioctl commands
+ *
+ ****************************************************************************/
+
+static int nrf54l_pwm_ioctl(struct pwm_lowerhalf_s *dev,
+                           int cmd, unsigned long arg)
+{
+  struct nrf54l_pwm_s *priv = (struct nrf54l_pwm_s *)dev;
+
+  DEBUGASSERT(dev);
+
+  /* There are no platform-specific ioctl commands */
+
+  UNUSED(priv);
+
+  return -ENOTTY;
+}
+
+/****************************************************************************
+ * Public Function
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: nrf54l_pwminitialize
+ *
+ * Description:
+ *   Initialize one timer for use with the upper_level PWM driver.
+ *
+ * Input Parameters:
+ *   pwm - A number identifying the pwm instance.
+ *
+ * Returned Value:
+ *   On success, a pointer to the NRF54L lower half PWM driver is returned.
+ *   NULL is returned on any failure.
+ *
+ ****************************************************************************/
+
+struct pwm_lowerhalf_s *nrf54l_pwminitialize(int pwm)
+{
+  struct nrf54l_pwm_s *lower = NULL;
+
+  pwminfo("Initialize PWM%u\n", pwm);
+
+  switch (pwm)
+    {
+#ifdef CONFIG_NRF54L_PWM0
+      case 0:
+        {
+          lower = &g_nrf54l_pwm0;
+          break;
+        }
+#endif
+
+#ifdef CONFIG_NRF54L_PWM1
+      case 1:
+        {
+          lower = &g_nrf54l_pwm1;
+          break;
+        }
+#endif
+
+#ifdef CONFIG_NRF54L_PWM2
+      case 2:
+        {
+          lower = &g_nrf54l_pwm2;
+          break;
+        }
+#endif
+
+      default:
+        {
+          pwmerr("ERROR: No such PWM device %d\n", pwm);
+          lower = NULL;
+          goto errout;
+        }
+    }
+
+errout:
+  return (struct pwm_lowerhalf_s *)lower;
+}
diff --git a/arch/arm/src/nrf54l/nrf54l_pwm.h b/arch/arm/src/nrf54l/nrf54l_pwm.h
new file mode 100644
index 00000000000..ae1a1297850
--- /dev/null
+++ b/arch/arm/src/nrf54l/nrf54l_pwm.h
@@ -0,0 +1,117 @@
+/****************************************************************************
+ * arch/arm/src/nrf54l/nrf54l_pwm.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_NRF54L_NRF54L_PWM_H
+#define __ARCH_ARM_SRC_NRF54L_NRF54L_PWM_H
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+#include <nuttx/timers/pwm.h>
+
+#include "chip.h"
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+/* Configuration ************************************************************/
+
+/* Enable the specified PWM channel if multichannel PWM is disabled */
+
+#ifndef CONFIG_NRF54L_PWM_MULTICHAN
+
+#  ifdef CONFIG_NRF54L_PWM0
+#    if !defined(CONFIG_NRF54L_PWM0_CHANNEL)
+#      error "CONFIG_NRF54L_PWM0_CHANNEL must be provided"
+#    elif CONFIG_NRF54L_PWM0_CHANNEL == 0
+#      define CONFIG_NRF54L_PWM0_CH0 1
+#    elif CONFIG_NRF54L_PWM0_CHANNEL == 1
+#      define CONFIG_NRF54L_PWM0_CH1 1
+#    elif CONFIG_NRF54L_PWM0_CHANNEL == 2
+#      define CONFIG_NRF54L_PWM0_CH2 1
+#    elif CONFIG_NRF54L_PWM0_CHANNEL == 3
+#      define CONFIG_NRF54L_PWM0_CH3 1
+#    else
+#      error "Unsupported value of CONFIG_NRF54L_PWM0_CHANNEL"
+#    endif
+#  endif
+
+#  ifdef CONFIG_NRF54L_PWM1
+#    if !defined(CONFIG_NRF54L_PWM1_CHANNEL)
+#      error "CONFIG_NRF54L_PWM1_CHANNEL must be provided"
+#    elif CONFIG_NRF54L_PWM1_CHANNEL == 0
+#      define CONFIG_NRF54L_PWM1_CH0 1
+#    elif CONFIG_NRF54L_PWM1_CHANNEL == 1
+#      define CONFIG_NRF54L_PWM1_CH1 1
+#    elif CONFIG_NRF54L_PWM1_CHANNEL == 2
+#      define CONFIG_NRF54L_PWM1_CH2 1
+#    elif CONFIG_NRF54L_PWM1_CHANNEL == 3
+#      define CONFIG_NRF54L_PWM1_CH3 1
+#    else
+#      error "Unsupported value of CONFIG_NRF54L_PWM1_CHANNEL"
+#    endif
+#  endif
+
+#  ifdef CONFIG_NRF54L_PWM2
+#    if !defined(CONFIG_NRF54L_PWM2_CHANNEL)
+#      error "CONFIG_NRF54L_PWM2_CHANNEL must be provided"
+#    elif CONFIG_NRF54L_PWM2_CHANNEL == 0
+#      define CONFIG_NRF54L_PWM2_CH0 1
+#    elif CONFIG_NRF54L_PWM2_CHANNEL == 1
+#      define CONFIG_NRF54L_PWM2_CH1 1
+#    elif CONFIG_NRF54L_PWM2_CHANNEL == 2
+#      define CONFIG_NRF54L_PWM2_CH2 1
+#    elif CONFIG_NRF54L_PWM2_CHANNEL == 3
+#      define CONFIG_NRF54L_PWM2_CH3 1
+#    else
+#      error "Unsupported value of CONFIG_NRF54L_PWM2_CHANNEL"
+#    endif
+#  endif
+
+#endif
+
+/****************************************************************************
+ * Public Function Prototypes
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: nrf54l_pwminitialize
+ *
+ * Description:
+ *   Initialize one timer for use with the upper_level PWM driver.
+ *
+ * Input Parameters:
+ *   pwm - A number identifying the pwm instance.
+ *
+ * Returned Value:
+ *   On success, a pointer to the NRF54L lower half PWM driver is returned.
+ *   NULL is returned on any failure.
+ *
+ ****************************************************************************/
+
+struct pwm_lowerhalf_s *nrf54l_pwminitialize(int pwm);
+
+#endif /* __ARCH_ARM_SRC_NRF54L_NRF54L_PWM_H */

Reply via email to