mirror of
https://gitlab.rtems.org/rtems/rtos/rtems.git
synced 2025-12-05 15:15:44 +00:00
bsp/aarch64/raspberrypi4: Add PWM peripheral support
This commit adds support for the PWM peripheral on the aarch64/raspberrypi BSP.
This commit is contained in:
110
bsps/aarch64/raspberrypi/include/bsp/raspberrypi-pwm.h
Normal file
110
bsps/aarch64/raspberrypi/include/bsp/raspberrypi-pwm.h
Normal file
@@ -0,0 +1,110 @@
|
||||
/* SPDX-License-Identifier: BSD-2-Clause */
|
||||
|
||||
/**
|
||||
* @file
|
||||
*
|
||||
* @ingroup RTEMSBSPsAArch64Raspberrypi4
|
||||
*
|
||||
* @brief Raspberry Pi specific PWM definitions.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2025 Shaunak Datar
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef LIBBSP_AARCH64_RASPBERRYPI_4_PWM_H
|
||||
#define LIBBSP_AARCH64_RASPBERRYPI_4_PWM_H
|
||||
|
||||
#include "bsp/raspberrypi.h"
|
||||
#include "bsp/rpi-gpio.h"
|
||||
#include "bsp/utility.h"
|
||||
|
||||
typedef enum { raspberrypi_pwm0, raspberrypi_pwm1 } raspberrypi_pwm_channel;
|
||||
|
||||
typedef enum {
|
||||
raspberrypi_pwm_master0,
|
||||
raspberrypi_pwm_master1
|
||||
} raspberrypi_pwm_master;
|
||||
|
||||
/**
|
||||
* @name PWM_CONTROL register bits
|
||||
* @{
|
||||
*/
|
||||
#define C_MSEN2 BSP_BIT32( 15 ) /**< Channel 2 Mark-Space enable */
|
||||
#define C_USEF2 BSP_BIT32( 13 ) /**< Channel 2 use FIFO */
|
||||
#define C_POLA2 BSP_BIT32( 12 ) /**< Channel 2 invert polarity */
|
||||
#define C_SBIT2 BSP_BIT32( 11 ) /**< Channel 2 silence bit high */
|
||||
#define C_RPTL2 BSP_BIT32( 10 ) /**< Channel 2 repeat on underrun */
|
||||
#define C_MODE2 BSP_BIT32( 9 ) /**< Channel 2 serializer mode */
|
||||
#define C_PWEN2 BSP_BIT32( 8 ) /**< Channel 2 enable output */
|
||||
#define C_MSEN1 BSP_BIT32( 7 ) /**< Channel 1 Mark-Space enable */
|
||||
#define C_CLRF BSP_BIT32( 6 ) /**< Clear FIFO */
|
||||
#define C_USEF1 BSP_BIT32( 5 ) /**< Channel 1 use FIFO */
|
||||
#define C_POLA1 BSP_BIT32( 4 ) /**< Channel 1 invert polarity */
|
||||
#define C_SBIT1 BSP_BIT32( 3 ) /**< Channel 1 silence bit high */
|
||||
#define C_RPTL1 BSP_BIT32( 2 ) /**< Channel 1 repeat underrun */
|
||||
#define C_MODE1 BSP_BIT32( 1 ) /**< Channel 1 serializer mode */
|
||||
#define C_PWEN1 BSP_BIT32( 0 ) /**< Channel 1 enable output */
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
* @brief Set PWM clock divider.
|
||||
* @param divisor 1 – 4095; PWMCLK = 19.2 MHz / @p divisor.
|
||||
* @retval RTEMS_SUCCESSFUL OK
|
||||
* @retval RTEMS_INVALID_NUMBER 0 or >4095
|
||||
*/
|
||||
rtems_status_code rpi_pwm_set_clock( uint32_t divisor );
|
||||
|
||||
/**
|
||||
* @brief Update duty-cycle register.
|
||||
* @param master Selects the hardware instance to be used
|
||||
* (raspberrypi_pwm_master0 = PWM0, raspberrypi_pwm_master1 = PWM1)
|
||||
* @param channel Selects the channel for @p master (raspberrypi_pwm0 = PWMx_0,
|
||||
* raspberrypi_pwm1 = PWMx_1)
|
||||
* @param data Initial duty count, 1 – current range value.(0 rejected)
|
||||
*/
|
||||
rtems_status_code rpi_pwm_set_data(
|
||||
raspberrypi_pwm_master master,
|
||||
raspberrypi_pwm_channel channel,
|
||||
uint32_t data
|
||||
);
|
||||
|
||||
/**
|
||||
* @brief Main PWM initialization function. This functions sets up the PWM
|
||||
* master, channel, duty cycle and GPIO pin.
|
||||
* @param master Selects the hardware instance to be used
|
||||
* (raspberrypi_pwm_master0 = PWM0, raspberrypi_pwm_master1 = PWM1)
|
||||
* @param channel Selects the channel for @p master (raspberrypi_pwm0 = PWMx_0,
|
||||
* raspberrypi_pwm1 = PWMx_1)
|
||||
* @param range Period register value (> 0)
|
||||
* @param data Initial duty count, 1 – @p range (0 rejected)
|
||||
*/
|
||||
rtems_status_code rpi_pwm_init(
|
||||
raspberrypi_pwm_master master,
|
||||
raspberrypi_pwm_channel channel,
|
||||
uint32_t range,
|
||||
uint32_t data
|
||||
);
|
||||
|
||||
#endif /* LIBBSP_AARCH64_RASPBERRYPI_4_PWM_H */
|
||||
@@ -11,6 +11,7 @@
|
||||
/*
|
||||
* Copyright (c) 2022 Mohd Noor Aman
|
||||
* Copyright (c) 2024 Ning Yang
|
||||
* Copyright (c) 2025 Shaunak Datar
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
@@ -284,6 +285,42 @@
|
||||
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
* @name PWM Clock Manager Register and Offsets
|
||||
*
|
||||
* @{
|
||||
*/
|
||||
|
||||
#define BCM2711_CM_PWM_BASE ( RPI_PERIPHERAL_BASE + 0x00101000 )
|
||||
#define BCM2711_CM_PWM_CTL 0xA0
|
||||
#define BCM2711_CM_PWM_DIV 0xA4
|
||||
#define CM_PWM_PASSWD ( 0x5A << 24 )
|
||||
#define CM_PWM_CTL_SRC_OSC BSP_BIT32( 0 )
|
||||
#define CM_PWM_CTL_BUSY BSP_BIT32( 7 )
|
||||
#define CM_PWM_CTL_ENAB BSP_BIT32( 4 )
|
||||
#define CM_PWM_DIV_MASK 0xFFF
|
||||
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
* @name PWM Registers and offsets
|
||||
*
|
||||
* @{
|
||||
*/
|
||||
|
||||
#define BCM2711_PWM0_BASE ( RPI_PERIPHERAL_BASE + 0x0020C000 )
|
||||
#define BCM2711_PWM1_BASE ( RPI_PERIPHERAL_BASE + 0x0020C800 )
|
||||
#define BCM2711_PWM_CONTROL 0x00
|
||||
#define BCM2711_PWM_STATUS 0x04
|
||||
#define BCM2711_PWM_DMAC 0x08
|
||||
#define BCM2711_PWM_RNG1 0x10
|
||||
#define BCM2711_PWM_DAT1 0x14
|
||||
#define BCM2711_PWM_FIFO 0x18
|
||||
#define BCM2711_PWM_RNG2 0x20
|
||||
#define BCM2711_PWM_DAT2 0x24
|
||||
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
* @name Mailbox Registers
|
||||
*
|
||||
|
||||
198
bsps/aarch64/raspberrypi/pwm/raspberrypi-pwm.c
Normal file
198
bsps/aarch64/raspberrypi/pwm/raspberrypi-pwm.c
Normal file
@@ -0,0 +1,198 @@
|
||||
/* SPDX-License-Identifier: BSD-2-Clause */
|
||||
|
||||
/**
|
||||
* @file
|
||||
*
|
||||
* @ingroup RTEMSBSPsAArch64Raspberrypi4
|
||||
*
|
||||
* @brief PWM Support
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2025 Shaunak Datar
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "bsp/raspberrypi-pwm.h"
|
||||
|
||||
// Clock manager macros
|
||||
#define BCM2711_CM_PWM( x ) BCM2835_REG( BCM2711_CM_PWM_BASE + ( x ) )
|
||||
#define CM_PWM_CTL_ENABLE_OSC \
|
||||
( CM_PWM_PASSWD | CM_PWM_CTL_ENAB | CM_PWM_CTL_SRC_OSC )
|
||||
#define CM_PWM_CTL_DISABLE ( CM_PWM_PASSWD | CM_PWM_CTL_SRC_OSC )
|
||||
|
||||
static inline bool rpi_pwm_validate(
|
||||
raspberrypi_pwm_master master,
|
||||
raspberrypi_pwm_channel channel
|
||||
)
|
||||
{
|
||||
return ( ( master == raspberrypi_pwm_master0 ) ||
|
||||
( master == raspberrypi_pwm_master1 ) ) &&
|
||||
( ( channel == raspberrypi_pwm0 ) || ( channel == raspberrypi_pwm1 ) );
|
||||
}
|
||||
|
||||
rtems_status_code rpi_pwm_set_clock( uint32_t divisor )
|
||||
{
|
||||
if ( !( divisor > 0 && divisor < 4096 ) ) {
|
||||
return RTEMS_INVALID_NUMBER;
|
||||
}
|
||||
|
||||
/* Stop Clock */
|
||||
BCM2711_CM_PWM( BCM2711_CM_PWM_CTL ) = CM_PWM_CTL_DISABLE;
|
||||
while ( BCM2711_CM_PWM( BCM2711_CM_PWM_CTL ) & CM_PWM_CTL_BUSY );
|
||||
|
||||
/* Set divisor */
|
||||
divisor &= CM_PWM_DIV_MASK;
|
||||
BCM2711_CM_PWM( BCM2711_CM_PWM_DIV ) = CM_PWM_PASSWD | ( divisor << 12 );
|
||||
|
||||
/* Select src = osc(1) and enable */
|
||||
BCM2711_CM_PWM( BCM2711_CM_PWM_CTL ) = CM_PWM_CTL_ENABLE_OSC;
|
||||
while ( !( BCM2711_CM_PWM( BCM2711_CM_PWM_CTL ) & CM_PWM_CTL_BUSY ) );
|
||||
|
||||
return RTEMS_SUCCESSFUL;
|
||||
}
|
||||
|
||||
static rtems_status_code rpi_pwm_set_control(
|
||||
raspberrypi_pwm_master master,
|
||||
raspberrypi_pwm_channel channel
|
||||
)
|
||||
{
|
||||
uint32_t pwm_base = ( master == raspberrypi_pwm_master0 ) ?
|
||||
BCM2711_PWM0_BASE :
|
||||
BCM2711_PWM1_BASE;
|
||||
uint32_t control_reg = pwm_base + BCM2711_PWM_CONTROL;
|
||||
uint32_t control = BCM2835_REG( control_reg );
|
||||
|
||||
if ( channel == raspberrypi_pwm0 ) {
|
||||
control &= ~( C_MODE1 | C_POLA1 | C_SBIT1 | C_RPTL1 | C_USEF1 );
|
||||
control |= ( C_PWEN1 | C_CLRF | C_MSEN1 );
|
||||
} else {
|
||||
control &= ~( C_MODE2 | C_POLA2 | C_SBIT2 | C_RPTL2 | C_USEF2 );
|
||||
control |= ( C_PWEN2 | C_CLRF | C_MSEN2 );
|
||||
}
|
||||
BCM2835_REG( control_reg ) = control;
|
||||
return RTEMS_SUCCESSFUL;
|
||||
}
|
||||
|
||||
static rtems_status_code rpi_pwm_set_range(
|
||||
raspberrypi_pwm_master master,
|
||||
raspberrypi_pwm_channel channel,
|
||||
uint32_t range
|
||||
)
|
||||
{
|
||||
uint32_t pwm_base = ( master == raspberrypi_pwm_master0 ) ?
|
||||
BCM2711_PWM0_BASE :
|
||||
BCM2711_PWM1_BASE;
|
||||
uint32_t range_offset = ( channel == raspberrypi_pwm0 ) ? BCM2711_PWM_RNG1 :
|
||||
BCM2711_PWM_RNG2;
|
||||
|
||||
BCM2835_REG( pwm_base + range_offset ) = range;
|
||||
return RTEMS_SUCCESSFUL;
|
||||
}
|
||||
|
||||
rtems_status_code rpi_pwm_set_data(
|
||||
raspberrypi_pwm_master master,
|
||||
raspberrypi_pwm_channel channel,
|
||||
uint32_t data
|
||||
)
|
||||
{
|
||||
if ( !( rpi_pwm_validate( master, channel ) ) || data == 0 ) {
|
||||
return RTEMS_INVALID_NUMBER;
|
||||
}
|
||||
|
||||
uint32_t pwm_base = ( master == raspberrypi_pwm_master0 ) ?
|
||||
BCM2711_PWM0_BASE :
|
||||
BCM2711_PWM1_BASE;
|
||||
uint32_t range_offset = ( channel == raspberrypi_pwm0 ) ? BCM2711_PWM_RNG1 :
|
||||
BCM2711_PWM_RNG2;
|
||||
|
||||
if ( data > BCM2835_REG( pwm_base + range_offset ) ) {
|
||||
return RTEMS_INVALID_NUMBER;
|
||||
}
|
||||
|
||||
uint32_t data_offset = ( channel == raspberrypi_pwm0 ) ? BCM2711_PWM_DAT1 :
|
||||
BCM2711_PWM_DAT2;
|
||||
|
||||
BCM2835_REG( pwm_base + data_offset ) = data;
|
||||
return RTEMS_SUCCESSFUL;
|
||||
}
|
||||
|
||||
static rtems_status_code rpi_pwm_set_gpio(
|
||||
raspberrypi_pwm_master master,
|
||||
raspberrypi_pwm_channel channel
|
||||
)
|
||||
{
|
||||
rtems_status_code sc;
|
||||
|
||||
if ( master == raspberrypi_pwm_master0 ) {
|
||||
if ( channel == raspberrypi_pwm0 ) {
|
||||
sc = raspberrypi_gpio_set_function( 18, GPIO_AF5 );
|
||||
} else {
|
||||
sc = raspberrypi_gpio_set_function( 19, GPIO_AF5 );
|
||||
}
|
||||
} else {
|
||||
if ( channel == raspberrypi_pwm0 ) {
|
||||
sc = raspberrypi_gpio_set_function( 40, GPIO_AF0 );
|
||||
} else {
|
||||
sc = raspberrypi_gpio_set_function( 41, GPIO_AF0 );
|
||||
}
|
||||
}
|
||||
|
||||
return sc;
|
||||
}
|
||||
|
||||
rtems_status_code rpi_pwm_init(
|
||||
raspberrypi_pwm_master master,
|
||||
raspberrypi_pwm_channel channel,
|
||||
uint32_t range,
|
||||
uint32_t data
|
||||
)
|
||||
{
|
||||
rtems_status_code sc;
|
||||
|
||||
if ( !( rpi_pwm_validate( master, channel ) ) || range == 0 ) {
|
||||
return RTEMS_INVALID_NUMBER;
|
||||
}
|
||||
|
||||
sc = rpi_pwm_set_gpio( master, channel );
|
||||
if ( sc != RTEMS_SUCCESSFUL ) {
|
||||
return sc;
|
||||
}
|
||||
|
||||
sc = rpi_pwm_set_range( master, channel, range );
|
||||
if ( sc != RTEMS_SUCCESSFUL ) {
|
||||
return sc;
|
||||
}
|
||||
|
||||
sc = rpi_pwm_set_data( master, channel, data );
|
||||
if ( sc != RTEMS_SUCCESSFUL ) {
|
||||
return sc;
|
||||
}
|
||||
|
||||
sc = rpi_pwm_set_control( master, channel );
|
||||
if ( sc != RTEMS_SUCCESSFUL ) {
|
||||
return sc;
|
||||
}
|
||||
|
||||
return RTEMS_SUCCESSFUL;
|
||||
}
|
||||
@@ -65,6 +65,8 @@ links:
|
||||
uid: objspi
|
||||
- role: build-dependency
|
||||
uid: objwatchdog
|
||||
- role: build-dependency
|
||||
uid: objpwm
|
||||
source:
|
||||
- bsps/aarch64/raspberrypi/fdt/bsp_fdt.c
|
||||
- bsps/aarch64/raspberrypi/fdt/rpi4b_dtb.c
|
||||
|
||||
17
spec/build/bsps/aarch64/raspberrypi/objpwm.yml
Normal file
17
spec/build/bsps/aarch64/raspberrypi/objpwm.yml
Normal file
@@ -0,0 +1,17 @@
|
||||
SPDX-License-Identifier: CC-BY-SA-4.0 OR BSD-2-Clause
|
||||
build-type: objects
|
||||
cflags: []
|
||||
copyrights:
|
||||
- Copyright (C) 2025 Shaunak Datar
|
||||
cppflags: []
|
||||
cxxflags: []
|
||||
enabled-by: true
|
||||
includes: []
|
||||
install:
|
||||
- destination: ${BSP_INCLUDEDIR}/bsp
|
||||
source:
|
||||
- bsps/aarch64/raspberrypi/include/bsp/raspberrypi-pwm.h
|
||||
links: []
|
||||
source:
|
||||
- bsps/aarch64/raspberrypi/pwm/raspberrypi-pwm.c
|
||||
type: build
|
||||
Reference in New Issue
Block a user