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
commit c51105225135c1920ecec13ba64e21fbde2f7444 Author: Matteo Golin <[email protected]> AuthorDate: Wed Jul 8 16:04:06 2026 -0400 bcm2711/pwm: Implement PWM driver for the BCM2711 Implements the BCM2711 PWM driver. Works for PWM0 and PWM1. Signed-off-by: Matteo Golin <[email protected]> --- arch/arm64/src/bcm2711/CMakeLists.txt | 4 + arch/arm64/src/bcm2711/Kconfig | 45 ++ arch/arm64/src/bcm2711/Make.defs | 6 + arch/arm64/src/bcm2711/bcm2711_pwm.c | 528 +++++++++++++++++++++++ arch/arm64/src/bcm2711/bcm2711_pwm.h | 75 ++++ arch/arm64/src/bcm2711/hardware/bcm2711_gpclk.h | 2 +- arch/arm64/src/bcm2711/hardware/bcm2711_memmap.h | 6 +- arch/arm64/src/bcm2711/hardware/bcm2711_pwm.h | 32 +- 8 files changed, 676 insertions(+), 22 deletions(-) diff --git a/arch/arm64/src/bcm2711/CMakeLists.txt b/arch/arm64/src/bcm2711/CMakeLists.txt index 0dc93d00e3b..36235fff2a5 100644 --- a/arch/arm64/src/bcm2711/CMakeLists.txt +++ b/arch/arm64/src/bcm2711/CMakeLists.txt @@ -44,6 +44,10 @@ if(CONFIG_BCM2711_SPI) list(APPEND SRCS bcm2711_spi.c) endif() +if(CONFIG_BCM2711_PWM) + list(APPEND SRCS bcm2711_pwm.c) +endif() + # EMMC interfaces if(CONFIG_BCM2711_EMMC) diff --git a/arch/arm64/src/bcm2711/Kconfig b/arch/arm64/src/bcm2711/Kconfig index d4fd57fc985..4ce3c688c47 100644 --- a/arch/arm64/src/bcm2711/Kconfig +++ b/arch/arm64/src/bcm2711/Kconfig @@ -281,6 +281,51 @@ config BCM2711_SPI6 endif # BCM2711_SPI +##################################################################### +# PWM +##################################################################### + +config BCM2711_PWM + bool "PWM" + select PWM + default n + ---help--- + Enable PWM support on the BCM2711. + +if BCM2711_PWM + +config BCM2711_PWM0 + bool "PWM0" + default n + ---help--- + Enable support for the PWM0 interface. + +if BCM2711_PWM0 + +config BCM2711_PWM0_CHAN1_PIN + int "PWM0 Channel 1 GPIO pin" + default 12 + ---help--- + Configure PWM0_0 (channel 1) GPIO pin. Valid options are 12, 18. + +config BCM2711_PWM0_CHAN2_PIN + int "PWM0 Channel 2 GPIO pin" + default 13 + ---help--- + Configure PWM0_1 (channel 2) GPIO pin. Valid options are 13, 19, 45. + +endif # BCM2711_PWM0 + +config BCM2711_PWM1 + bool "PWM1" + default n + ---help--- + Enable support for the PWM1 interface. Note that PWM1 can only be mapped + to GPIO 40 for channel 1, and 41 for channel 2. This corresponds to the + audio jack on the RPi4B, where channel 1 is RIGHT and 2 is LEFT. + +endif # BCM2711_PWM + ##################################################################### # SDMMC Configuration ##################################################################### diff --git a/arch/arm64/src/bcm2711/Make.defs b/arch/arm64/src/bcm2711/Make.defs index a82aa277441..061a2a75a0a 100644 --- a/arch/arm64/src/bcm2711/Make.defs +++ b/arch/arm64/src/bcm2711/Make.defs @@ -49,6 +49,12 @@ ifeq ($(CONFIG_BCM2711_SPI),y) CHIP_CSRCS += bcm2711_spi.c endif +# PWM interfaces + +ifeq ($(CONFIG_BCM2711_PWM),y) +CHIP_CSRCS += bcm2711_pwm.c +endif + # EMMC interfaces ifeq ($(CONFIG_BCM2711_EMMC),y) diff --git a/arch/arm64/src/bcm2711/bcm2711_pwm.c b/arch/arm64/src/bcm2711/bcm2711_pwm.c new file mode 100644 index 00000000000..755bbf374e2 --- /dev/null +++ b/arch/arm64/src/bcm2711/bcm2711_pwm.c @@ -0,0 +1,528 @@ +/**************************************************************************** + * arch/arm64/src/bcm2711/bcm2711_pwm.c + * + * Contributed by: Matteo Golin <[email protected]> + * + * SPDX-License-Identifer: 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 <nuttx/mutex.h> +#include <nuttx/timers/pwm.h> + +#include "bcm2711_gpio.h" +#include "bcm2711_mailbox.h" +#include "bcm2711_pwm.h" + +#include "hardware/bcm2711_gpclk.h" +#include "hardware/bcm2711_pwm.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* PWM0 has several options for the channels. */ + +#if CONFIG_BCM2711_PWM0_CHAN1_PIN == 12 +#define BCM2711_PWM0_CHAN1_PIN_ALT BCM_GPIO_FUNC0 +#elif CONFIG_BCM2711_PWM0_CHAN1_PIN == 18 +#define BCM2711_PWM0_CHAN1_PIN_ALT BCM_GPIO_FUNC5 +#else +#error "Invalid pin selection for PWM0 channel 1!" +#endif + +#if CONFIG_BCM2711_PWM0_CHAN2_PIN == 13 +#define BCM2711_PWM0_CHAN2_PIN_ALT BCM_GPIO_FUNC0 +#elif CONFIG_BCM2711_PWM0_CHAN2_PIN == 19 +#define BCM2711_PWM0_CHAN2_PIN_ALT BCM_GPIO_FUNC5 +#elif CONFIG_BCM2711_PWM0_CHAN2_PIN == 45 +#define BCM2711_PWM0_CHAN2_PIN_ALT BCM_GPIO_FUNC0 +#else +#error "Invalid pin selection for PWM0 channel 2!" +#endif + +/* PWM1 only has one option for the channels */ + +#define BCM2711_PWM1_CHAN1_PIN (40) +#define BCM2711_PWM1_CHAN1_PIN_ALT BCM_GPIO_FUNC0 +#define BCM2711_PWM1_CHAN2_PIN (41) +#define BCM2711_PWM1_CHAN2_PIN_ALT BCM_GPIO_FUNC0 + +/* PWM clock runs at 54MHz */ + +#define PWM_CLKFREQ (54000000) + +/* GPCLK for PWM */ + +#define PWM_GPCLKCTL (BCM_GPCLK_BASEADDR + 0xa0) +#define PWM_GPCLKDIV (BCM_GPCLK_BASEADDR + 0xa4) + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +struct bcm2711_pwm_s +{ + struct pwm_lowerhalf_s dev; + mutex_t lock; /* We lock both channels at once, no granularity */ + uint32_t base; /* Interface base address */ + uint8_t port; /* Interface number */ + bool init; /* Initialized yet? */ +}; + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +static int bcm2711_pwm_setup(FAR struct pwm_lowerhalf_s *dev); +static int bcm2711_pwm_shutdown(FAR struct pwm_lowerhalf_s *dev); +static int bcm2711_pwm_start(FAR struct pwm_lowerhalf_s *dev, + FAR const struct pwm_info_s *info); +static int bcm2711_pwm_stop(FAR struct pwm_lowerhalf_s *dev); +static int bcm2711_pwm_ioctl(FAR struct pwm_lowerhalf_s *dev, int cmd, + unsigned long arg); + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +struct pwm_ops_s g_pwmops = +{ + .setup = bcm2711_pwm_setup, + .shutdown = bcm2711_pwm_shutdown, + .start = bcm2711_pwm_start, + .stop = bcm2711_pwm_stop, + .ioctl = bcm2711_pwm_ioctl, +}; + +#ifdef CONFIG_BCM2711_PWM0 +struct bcm2711_pwm_s g_pwm0 = +{ + .dev = + { + .ops = &g_pwmops, + }, + .lock = NXMUTEX_INITIALIZER, + .base = BCM_PWM0_BASEADDR, + .port = 0, + .init = false, +}; +#endif /* CONFIG_BCM2711_PWM0 */ + +#ifdef CONFIG_BCM2711_PWM1 +struct bcm2711_pwm_s g_pwm1 = +{ + .dev = + { + .ops = &g_pwmops, + }, + .lock = NXMUTEX_INITIALIZER, + .base = BCM_PWM1_BASEADDR, + .port = 1, + .init = false, +}; +#endif /* CONFIG_BCM2711_PWM1 */ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: bcm2711_channel_pol + * + * Description: + * Set the polarity of a PWM channel. NOTE: CPOL and DCPOL settings have + * the same values, so this function works for both. + * + * Input Parameters: + * priv - The PWM device reference + * mask - The mask for the channel's POLA register + * pol - The PWM upper-half driver polarity setting + * + ****************************************************************************/ + +static void bcm2711_channel_pol(struct bcm2711_pwm_s *priv, uint32_t mask, + uint8_t pol) +{ + uint32_t val = 0; /* Default: logical high */ + + if (pol == PWM_CPOL_LOW) + { + val = 0xffffffff; /* Logical low (this will be masked) */ + } + + modreg32(val, mask, BCM_PWM_CTL(priv->base)); +} + +/**************************************************************************** + * Name: bcm2711_setpulse + * + * Description: + * Set the duty cycle and frequency of the PWM interface + * + * Input Parameters: + * rangereg - The RNG register of the PWM channel in which to set the duty + * datreg - The DAT register of the PWM channel in which to set the duty + * duty - The duty value from the upper-half driver + * frequency - The frequency of the pulse in Hz + * + ****************************************************************************/ + +static void bcm2711_setpulse(uint32_t rangereg, uint32_t datreg, ub16_t duty, + uint32_t freq) +{ + uint32_t val = PWM_CLKFREQ / freq; + + putreg32(val, rangereg); + + /* Multiply the duty fractional amount by the frequency we set in our + * range. + */ + + val = ((uint64_t)val * (uint64_t)duty) / 0xffff; + pwminfo("Range: %08x\n", val); + putreg32(val, datreg); +} + +/**************************************************************************** + * Name: bcm2711_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. + * + * Input Parameters: + * dev - The device reference + * + * Returned Value: + * 0 on success, negated errno on failure. + * + ****************************************************************************/ + +static int bcm2711_pwm_setup(FAR struct pwm_lowerhalf_s *dev) +{ + struct bcm2711_pwm_s *priv = (struct bcm2711_pwm_s *)dev; + uint32_t errmask = BCM_PWM_STA_BERR | BCM_PWM_STA_GAPO2 | + BCM_PWM_STA_GAPO1 | BCM_PWM_STA_RERR1 | + BCM_PWM_STA_WERR1; + + nxmutex_lock(&priv->lock); + + /* Ensure channels are disabled so there is no output started */ + + modreg32(0, BCM_PWM_CTL_PWEN1, BCM_PWM_CTL(priv->base)); + modreg32(0, BCM_PWM_CTL_PWEN2, BCM_PWM_CTL(priv->base)); + + /* Clear all errors */ + + putreg32(errmask, BCM_PWM_STA(priv->base)); + + /* Put channels in PWM mode */ + + modreg32(0, BCM_PWM_CTL_MODE1, BCM_PWM_CTL(priv->base)); + modreg32(0, BCM_PWM_CTL_MODE2, BCM_PWM_CTL(priv->base)); + + /* Use marked-space mode */ + + modreg32(BCM_PWM_CTL_MSEN1, BCM_PWM_CTL_MSEN1, BCM_PWM_CTL(priv->base)); + modreg32(BCM_PWM_CTL_MSEN2, BCM_PWM_CTL_MSEN2, BCM_PWM_CTL(priv->base)); + + /* The way NuttX's PWM interface is set up, we should never have to use + * FIFO mode. This is because the PWM interface seems to be intended to + * just directly set a duty cycle that runs until stopped, not output a + * data stream. Hence, we disable FIFO usage. + */ + + modreg32(0, BCM_PWM_CTL_USEF1, BCM_PWM_CTL(priv->base)); + modreg32(0, BCM_PWM_CTL_USEF2, BCM_PWM_CTL(priv->base)); + nxmutex_unlock(&priv->lock); + return 0; +} + +/**************************************************************************** + * Name: bcm2711_pwm_shutdown + * + * Description: + * This method is called when the driver is closed. The lower half driver + * should stop pulsed output, free any resources, disable the timer + * hardware, and put the system into the lowest possible power usage state + * + * Input Parameters: + * dev - The device reference + * + * Returned Value: + * 0 on success, negated errno on failure. + * + ****************************************************************************/ + +static int bcm2711_pwm_shutdown(FAR struct pwm_lowerhalf_s *dev) +{ + struct bcm2711_pwm_s *priv = (struct bcm2711_pwm_s *)dev; + + nxmutex_lock(&priv->lock); + + /* Clear FIFOs */ + + modreg32(BCM_PWM_CTL_CLRF, BCM_PWM_CTL_CLRF, BCM_PWM_CTL(priv->base)); + + /* Ensure channels are disabled */ + + modreg32(0, BCM_PWM_CTL_PWEN1, BCM_PWM_CTL(priv->base)); + modreg32(0, BCM_PWM_CTL_PWEN2, BCM_PWM_CTL(priv->base)); + + nxmutex_unlock(&priv->lock); + return 0; +} + +/**************************************************************************** + * Name: bcm2711_pwm_start + * + * Description: + * (Re-)initialize the timer resources and start the pulsed output. The + * start method should return an error if it cannot start the timer with + * the given parameter (frequency or duty) + * + * Input Parameters: + * dev - The device reference + * info - Characteristics for the pulsed output + * + * Returned Value: + * 0 on success, negated errno on failure + * + ****************************************************************************/ + +static int bcm2711_pwm_start(FAR struct pwm_lowerhalf_s *dev, + FAR const struct pwm_info_s *info) +{ + struct bcm2711_pwm_s *priv = (struct bcm2711_pwm_s *)dev; + unsigned i = 0; + + pwminfo("Frequency %u Hz", info->frequency); + + for (i = 0; i < CONFIG_PWM_NCHANNELS; i++) + { + pwminfo("Channel %u duty %08x", info->channels[i].channel, + info->channels[i].duty); + pwminfo("Channel %u polarity %u", info->channels[i].channel, + info->channels[i].cpol); + + nxmutex_lock(&priv->lock); /* Lock for this iteration/channel */ + + switch (info->channels[i].channel) + { + case 1: + bcm2711_setpulse(BCM_PWM_RNG1(priv->base), + BCM_PWM_DAT1(priv->base), + info->channels[i].duty, info->frequency); + bcm2711_channel_pol(priv, BCM_PWM_CTL_POLA1, + info->channels[i].cpol); + + /* Enable channel output */ + + modreg32(BCM_PWM_CTL_PWEN1, BCM_PWM_CTL_PWEN1, + BCM_PWM_CTL(priv->base)); + break; + case 2: + bcm2711_setpulse(BCM_PWM_RNG2(priv->base), + BCM_PWM_DAT2(priv->base), + info->channels[i].duty, info->frequency); + bcm2711_channel_pol(priv, BCM_PWM_CTL_POLA2, + info->channels[i].cpol); + + /* Enable channel output */ + + modreg32(BCM_PWM_CTL_PWEN2, BCM_PWM_CTL_PWEN2, + BCM_PWM_CTL(priv->base)); + break; + default: + pwmerr("Invalid channel %d\n", info->channels[i].channel); + nxmutex_unlock(&priv->lock); /* Unlock before return */ + return -EINVAL; + } + + nxmutex_unlock(&priv->lock); /* Unlock for next iteration */ + } + + pwminfo("PWM%d status: %08x", priv->port, + getreg32(BCM_PWM_STA(priv->base))); + return 0; +} + +/**************************************************************************** + * Name: bcm2711_pwm_stop + * + * Description: + * Stop the pulsed output and reset the timer resources + * + * Input Parameters: + * dev - The device reference + * + * Returned Value: + * 0 on success, negated errno on failure + * + ****************************************************************************/ + +static int bcm2711_pwm_stop(FAR struct pwm_lowerhalf_s *dev) +{ + struct bcm2711_pwm_s *priv = (struct bcm2711_pwm_s *)dev; + + nxmutex_lock(&priv->lock); + + /* Ensure channels are disabled */ + + modreg32(0, BCM_PWM_CTL_PWEN1, BCM_PWM_CTL(priv->base)); + modreg32(0, BCM_PWM_CTL_PWEN2, BCM_PWM_CTL(priv->base)); + nxmutex_unlock(&priv->lock); + return 0; +} + +/**************************************************************************** + * Name: bcm2711_pwm_ioctl + * + * Description: + * Lower-half logic may support platform-specific ioctl commands + * + * Input Parameters: + * dev - The device reference + * cmd - IOCTL command + * arg - Opaque command argument + * + * Returned Value: + * 0 on success, negated errno on on failure + * + ****************************************************************************/ + +static int bcm2711_pwm_ioctl(FAR struct pwm_lowerhalf_s *dev, int cmd, + unsigned long arg) +{ + /* There are no lower-half specific commands needed here. */ + + return -ENOTTY; +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: bcm2711_pwminitialize + * + * Description: + * Initialize one PWM interface for use with the upper_level PWM driver. + * + * Input Parameters: + * timer - Which PWM interface to initialize (0 or 1) + * + * Returned Value: + * On success, a pointer to the lower half PWM driver is returned. + * NULL is returned on any failure. + * + ****************************************************************************/ + +struct pwm_lowerhalf_s *bcm2711_pwminitialize(int timer) +{ + int err; + uint8_t count; + struct bcm2711_pwm_s *priv; + + switch (timer) + { +#ifdef CONFIG_BCM2711_PWM0 + case 0: + priv = &g_pwm0; + bcm2711_gpio_set_func(CONFIG_BCM2711_PWM0_CHAN1_PIN, + BCM2711_PWM0_CHAN1_PIN_ALT); + bcm2711_gpio_set_pulls(CONFIG_BCM2711_PWM0_CHAN1_PIN, false, false); + bcm2711_gpio_set_func(CONFIG_BCM2711_PWM0_CHAN2_PIN, + BCM2711_PWM0_CHAN2_PIN_ALT); + bcm2711_gpio_set_pulls(CONFIG_BCM2711_PWM0_CHAN2_PIN, false, false); + break; +#endif +#ifdef CONFIG_BCM2711_PWM1 + case 1: + priv = &g_pwm1; + bcm2711_gpio_set_func(BCM2711_PWM1_CHAN1_PIN, + BCM2711_PWM1_CHAN1_PIN_ALT); + bcm2711_gpio_set_pulls(BCM2711_PWM1_CHAN1_PIN, false, false); + bcm2711_gpio_set_func(BCM2711_PWM1_CHAN2_PIN, + BCM2711_PWM1_CHAN2_PIN_ALT); + bcm2711_gpio_set_pulls(BCM2711_PWM1_CHAN2_PIN, false, false); + break; +#endif + default: + pwmerr("No PWM%d interface.", timer); + return NULL; + } + + /* Don't re-initialize */ + + if (priv->init) + { + pwmwarn("PWM%d already initialized, skipping...", priv->port); + return &priv->dev; + } + + /* Start PWM clock via mailbox domain */ + + count = 0; + do + { + err = bcm2711_mbox_setclken(MBOX_CLK_PWM, true); + count++; + } + while (err < 0 && count < 3); + + if (err < 0) + { + pwmerr("Couldn't enable PWM clock via mailbox: %d\n", err); + } + + /* NOTE: initialization sequence determined from rpi4-osdev project. + * They have CNTL and DIV offsets at 40, 41 from the GPCLK base. This + * offsets are in multiples of sizeof(unsigned) since they are added to an + * `unsigned *`. + */ + + /* Stops clock */ + + putreg32(BCM_GPCLK_PASSWD | BCM_GPCLK_CM_CTL_KILL, PWM_GPCLKCTL); + + /* Wait for clock to no longer be busy */ + + while (getreg32(PWM_GPCLKCTL) & BCM_GPCLK_CM_CTL_BUSY) + ; + + putreg32(BCM_GPCLK_PASSWD | BCM_PWMCLK_DIV_VAL, PWM_GPCLKDIV); + putreg32(BCM_GPCLK_PASSWD | BCM_GPCLK_CLKSRC_OSC, PWM_GPCLKCTL); + + /* Enable clock with the same settings. */ + + putreg32(BCM_GPCLK_PASSWD | BCM_GPCLK_CLKSRC_OSC | BCM_GPCLK_CM_CTL_ENAB, + PWM_GPCLKCTL); + + pwminfo("Initialized PWM%d", priv->port); + priv->init = true; + return &priv->dev; +} diff --git a/arch/arm64/src/bcm2711/bcm2711_pwm.h b/arch/arm64/src/bcm2711/bcm2711_pwm.h new file mode 100644 index 00000000000..c6edf1ad71d --- /dev/null +++ b/arch/arm64/src/bcm2711/bcm2711_pwm.h @@ -0,0 +1,75 @@ +/**************************************************************************** + * arch/arm64/src/bcm2711/bcm2711_pwm.h + * + * Contributed by: Matteo Golin <[email protected]> + * + * SPDX-License-Identifer: 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_ARM64_SRC_BCM2711_BCM2711_PWM_H +#define __ARCH_ARM64_SRC_BCM2711_BCM2711_PWM_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include <nuttx/config.h> + +#include <nuttx/timers/pwm.h> + +#ifndef __ASSEMBLY__ + +#undef EXTERN +#if defined(__cplusplus) +#define EXTERN extern "C" +extern "C" +{ +#else +#define EXTERN extern +#endif + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Name: bcm2711_pwminitialize + * + * Description: + * Initialize one PWM interface for use with the upper_level PWM driver. + * + * Input Parameters: + * timer - Which PWM interface to initialize (0 or 1) + * + * Returned Value: + * On success, a pointer to the lower half PWM driver is returned. + * NULL is returned on any failure. + * + ****************************************************************************/ + +struct pwm_lowerhalf_s *bcm2711_pwminitialize(int timer); + +#undef EXTERN +#if defined(__cplusplus) +} +#endif + +#endif /* __ASSEMBLY__ */ + +#endif /* __ARCH_ARM64_SRC_BCM2711_BCM2711_PWM_H */ diff --git a/arch/arm64/src/bcm2711/hardware/bcm2711_gpclk.h b/arch/arm64/src/bcm2711/hardware/bcm2711_gpclk.h index 7778ea99576..552a8b43a16 100644 --- a/arch/arm64/src/bcm2711/hardware/bcm2711_gpclk.h +++ b/arch/arm64/src/bcm2711/hardware/bcm2711_gpclk.h @@ -53,7 +53,7 @@ /* General purpose clock bit definitions */ -#define BCM_GPCLK_PASSWD 0x5a /* Clock manager password */ +#define BCM_GPCLK_PASSWD (0x5a << 24) /* Clock manager password */ #define BCM_GPCLK_CM_CTL_PASSWD (0xff << 24) /* CLK manager password mask */ #define BCM_GPCLK_CM_CTL_MASH (0x3 << 9) /* MASH control */ diff --git a/arch/arm64/src/bcm2711/hardware/bcm2711_memmap.h b/arch/arm64/src/bcm2711/hardware/bcm2711_memmap.h index 1ee99ff35bb..d0e536769d0 100644 --- a/arch/arm64/src/bcm2711/hardware/bcm2711_memmap.h +++ b/arch/arm64/src/bcm2711/hardware/bcm2711_memmap.h @@ -53,7 +53,7 @@ #define BCM_PERIPHERAL_BASEADDR 0x47e000000 -#endif // defined(CONFIG_BCM2711_LOW_PERIPHERAL) +#endif /* defined(CONFIG_BCM2711_LOW_PERIPHERAL) */ /* Base addresses for chip registers */ @@ -69,6 +69,10 @@ (BCM_PERIPHERAL_BASEADDR + 0x000203000) /* PCM */ #define BCM_SYST_BASEADDR \ (BCM_PERIPHERAL_BASEADDR + 0x000003000) /* System timer */ +#define BCM_PWM0_BASEADDR \ + (BCM_PERIPHERAL_BASEADDR + 0x00020c000) /* PWM0 */ +#define BCM_PWM1_BASEADDR \ + (BCM_PERIPHERAL_BASEADDR + 0x00020c800) /* PWM1 */ /* SPI interface register base addresses */ diff --git a/arch/arm64/src/bcm2711/hardware/bcm2711_pwm.h b/arch/arm64/src/bcm2711/hardware/bcm2711_pwm.h index 755f084635f..ca7e052b7ec 100644 --- a/arch/arm64/src/bcm2711/hardware/bcm2711_pwm.h +++ b/arch/arm64/src/bcm2711/hardware/bcm2711_pwm.h @@ -29,14 +29,15 @@ #include <nuttx/config.h> +#include "bcm2711_memmap.h" + /**************************************************************************** * Pre-processor Definitions ****************************************************************************/ -/* Base addresses */ +/* TODO: Explanation for PWM div val */ -#define BCM_PWM0_BASEADDR 0x7e20c000 -#define BCM_PWM1_BASEADDR 0x7e20c800 +#define BCM_PWMCLK_DIV_VAL (2 << 12) /* PWM register offsets */ @@ -51,23 +52,14 @@ /* PWM register addresses */ -#define BCM_PWM0_CTL (BCM_PWM0_BASEADDR + BCM_PWM_CTL_OFFSET) -#define BCM_PWM0_STA (BCM_PWM0_BASEADDR + BCM_PWM_STA_OFFSET) -#define BCM_PWM0_DMAC (BCM_PWM0_BASEADDR + BCM_PWM_DMAC_OFFSET) -#define BCM_PWM0_RNG1 (BCM_PWM0_BASEADDR + BCM_PWM_RNG1_OFFSET) -#define BCM_PWM0_DAT1 (BCM_PWM0_BASEADDR + BCM_PWM_DAT1_OFFSET) -#define BCM_PWM0_FIF1 (BCM_PWM0_BASEADDR + BCM_PWM_FIF1_OFFSET) -#define BCM_PWM0_RNG2 (BCM_PWM0_BASEADDR + BCM_PWM_RNG2_OFFSET) -#define BCM_PWM0_DAT2 (BCM_PWM0_BASEADDR + BCM_PWM_DAT2_OFFSET) - -#define BCM_PWM1_CTL (BCM_PWM0_BASEADDR + BCM_PWM_CTL_OFFSET) -#define BCM_PWM1_STA (BCM_PWM0_BASEADDR + BCM_PWM_STA_OFFSET) -#define BCM_PWM1_DMAC (BCM_PWM0_BASEADDR + BCM_PWM_DMAC_OFFSET) -#define BCM_PWM1_RNG1 (BCM_PWM0_BASEADDR + BCM_PWM_RNG1_OFFSET) -#define BCM_PWM1_DAT1 (BCM_PWM0_BASEADDR + BCM_PWM_DAT1_OFFSET) -#define BCM_PWM1_FIF1 (BCM_PWM0_BASEADDR + BCM_PWM_FIF1_OFFSET) -#define BCM_PWM1_RNG2 (BCM_PWM0_BASEADDR + BCM_PWM_RNG2_OFFSET) -#define BCM_PWM1_DAT2 (BCM_PWM0_BASEADDR + BCM_PWM_DAT2_OFFSET) +#define BCM_PWM_CTL(base) ((base) + BCM_PWM_CTL_OFFSET) +#define BCM_PWM_STA(base) ((base) + BCM_PWM_STA_OFFSET) +#define BCM_PWM_DMAC(base) ((base) + BCM_PWM_DMAC_OFFSET) +#define BCM_PWM_RNG1(base) ((base) + BCM_PWM_RNG1_OFFSET) +#define BCM_PWM_DAT1(base) ((base) + BCM_PWM_DAT1_OFFSET) +#define BCM_PWM_FIF1(base) ((base) + BCM_PWM_FIF1_OFFSET) +#define BCM_PWM_RNG2(base) ((base) + BCM_PWM_RNG2_OFFSET) +#define BCM_PWM_DAT2(base) ((base) + BCM_PWM_DAT2_OFFSET) /* PWM register bit definitions */
