SyterKit 0.4.0.x
SyterKit is a bare-metal framework
Loading...
Searching...
No Matches
Macros | Functions | Variables
sys-pwm.c File Reference

System PWM (Pulse Width Modulation) driver for Allwinner (sunxi) platforms. More...

#include <io.h>
#include <stdarg.h>
#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
#include <types.h>
#include <timer.h>
#include <common.h>
#include <log.h>
#include <sys-clk.h>
#include <sys-pwm.h>
Include dependency graph for sys-pwm.c:

Macros

#define PRESCALE_MAX   256
 
#define sunxi_pwm_do_div(n, base)
 Perform division with rounding for PWM calculations.
 

Functions

static void sunxi_pwm_reg_set (uint32_t reg, uint32_t reg_shift, uint32_t reg_width, uint32_t data)
 Set the value of a specific field in a PWM register.
 
static void sunxi_pwm_gpio_init (sunxi_pwm_t *pwm, int channel)
 Initialize the GPIO for a specific PWM channel.
 
static void sunxi_pwm_clk_init (sunxi_pwm_t *pwm)
 Initialize the PWM clock by configuring the bus and peripheral clocks.
 
static void sunxi_pwm_clk_deinit (sunxi_pwm_t *pwm)
 Deinitialize the PWM clock and gate/reset control.
 
static void sunxi_pwm_enable_controller (sunxi_pwm_t *pwm, int channel)
 Enable the PWM controller for a specific channel.
 
static void sunxi_pwm_disable_controller (sunxi_pwm_t *pwm, int channel)
 Disable the PWM controller for a specific channel.
 
static void sunxi_pwm_set_porality (sunxi_pwm_t *pwm, int channel, sunxi_pwm_polarity_t polarity)
 Set the polarity of a specific PWM channel.
 
static uint32_t sunxi_pwm_get_pccr_reg_offset (uint32_t channel)
 Get the PCC register offset for a given PWM channel.
 
static uint32_t sunxi_pwm_get_pdzcr_reg_offset (uint32_t channel)
 Get the register offset for the PWM dead zone control register (PDZCR) for a specific channel.
 
static int sunxi_pwm_set_config_single (sunxi_pwm_t *pwm, int channel, sunxi_pwm_config_t *config)
 Configures a single PWM channel with the given configuration parameters.
 
static int sunxi_pwm_set_config_bind (sunxi_pwm_t *pwm, int channel, sunxi_pwm_config_t *config)
 Configure and bind a PWM channel with specific settings.
 
static int sunxi_pwm_release_single (sunxi_pwm_t *pwm, int channel)
 Release a single PWM channel.
 
static int sunxi_pwm_release_bind (sunxi_pwm_t *pwm, int channel)
 Release a bound PWM channel.
 
void sunxi_pwm_init (sunxi_pwm_t *pwm)
 Initialize the PWM instance.
 
void sunxi_pwm_deinit (sunxi_pwm_t *pwm)
 Deinitialize the PWM instance.
 
int sunxi_pwm_set_config (sunxi_pwm_t *pwm, int channel, sunxi_pwm_config_t *config)
 Set configuration for a PWM channel.
 
int sunxi_pwm_release (sunxi_pwm_t *pwm, int channel)
 Release the PWM channel.
 

Variables

static const uint32_t pre_scal [][2]
 Pre-scaler values for clock division.
 

Detailed Description

System PWM (Pulse Width Modulation) driver for Allwinner (sunxi) platforms.

This file implements PWM functionality for Allwinner SoCs, supporting multiple channels with configurable frequency, duty cycle, polarity, and dead zone timing. It provides both single-channel and dual-channel binding modes, with support for pulse mode operations. The driver handles various clock sources including APB and oscillator clocks, and provides fine-grained control over PWM output parameters.

Macro Definition Documentation

◆ PRESCALE_MAX

#define PRESCALE_MAX   256

◆ sunxi_pwm_do_div

#define sunxi_pwm_do_div (   n,
  base 
)
Value:
do { \
uint32_t __base = (base); \
uint32_t __rem; \
__rem = ((uint64_t) (n)) % __base; \
(n) = ((uint64_t) (n)) / __base; \
if (__rem > __base / 2) \
++(n); \
} while (0)
u64_t uint64_t
Definition stdint.h:16
u32_t uint32_t
Definition stdint.h:13

Perform division with rounding for PWM calculations.

This macro performs a division operation on a given number n by base, and applies rounding to the result. The division is done by casting both operands to uint64_t to avoid overflow for large values. If the remainder is greater than half of base, the quotient is incremented by 1, implementing rounding to the nearest integer.

Parameters
nThe numerator, which will be updated with the quotient.
baseThe divisor.
Returns
The remainder of the division.

Function Documentation

◆ sunxi_pwm_clk_deinit()

static void sunxi_pwm_clk_deinit ( sunxi_pwm_t pwm)
inlinestatic

Deinitialize the PWM clock and gate/reset control.

This function disables the clock and resets the PWM controller by clearing the appropriate bits in the clock gate and reset registers. It handles both bus and standalone clocks, depending on the configuration of the PWM structure.

Parameters
pwmPointer to the PWM controller structure.
Note
This function will only affect the clock if the corresponding clock base addresses are properly initialized in the PWM structure.

◆ sunxi_pwm_clk_init()

static void sunxi_pwm_clk_init ( sunxi_pwm_t pwm)
inlinestatic

Initialize the PWM clock by configuring the bus and peripheral clocks.

This function initializes the PWM clock by enabling the necessary bus and peripheral clocks. It handles the clock reset and gate control for both the bus and peripheral clocks. If the PWM uses a bus clock, it will configure the bus clock by setting the reset bit and opening the clock gate. Similarly, if the PWM uses a separate clock, the function will configure it in the same manner.

Parameters
pwmPointer to the PWM controller structure.
Note
This function checks for both bus and peripheral clock configuration, and applies clock reset and gate operations accordingly. It also introduces a small delay (udelay(10)) to ensure proper clock stabilization after gating the clock.

◆ sunxi_pwm_deinit()

void sunxi_pwm_deinit ( sunxi_pwm_t pwm)

Deinitialize the PWM instance.

This function deinitializes the PWM instance by deactivating the clocks and re-initializing the GPIOs for each channel. It also marks the PWM as uninitialized (status set to false).

Parameters
pwmPointer to the PWM instance structure.

◆ sunxi_pwm_disable_controller()

static void sunxi_pwm_disable_controller ( sunxi_pwm_t pwm,
int  channel 
)
inlinestatic

Disable the PWM controller for a specific channel.

This function disables the PWM controller for the given channel by clearing the corresponding bit in the PWM controller's "PWM_PER" register.

Parameters
pwmPointer to the PWM controller structure.
channelThe PWM channel number (0-15) to disable.

◆ sunxi_pwm_enable_controller()

static void sunxi_pwm_enable_controller ( sunxi_pwm_t pwm,
int  channel 
)
inlinestatic

Enable the PWM controller for a specific channel.

This function enables the PWM controller for the given channel by setting the corresponding bit in the PWM controller's "PWM_PER" register.

Parameters
pwmPointer to the PWM controller structure.
channelThe PWM channel number (0-15) to enable.

◆ sunxi_pwm_get_pccr_reg_offset()

static uint32_t sunxi_pwm_get_pccr_reg_offset ( uint32_t  channel)
inlinestatic

Get the PCC register offset for a given PWM channel.

This function returns the corresponding PWM PCCR register offset based on the input channel. The channels are mapped to the register offsets in a predefined array. If the provided channel is out of the valid range, the function returns the offset for channel 0.

Parameters
channelThe PWM channel number (0-15).
Returns
uint32_t The corresponding PCC register offset for the given channel.
Note
This function assumes that the channel is within a valid range (0-15). If the channel is outside this range, the default value of PWM_PCCR01 is returned.

◆ sunxi_pwm_get_pdzcr_reg_offset()

static uint32_t sunxi_pwm_get_pdzcr_reg_offset ( uint32_t  channel)
inlinestatic

Get the register offset for the PWM dead zone control register (PDZCR) for a specific channel.

This function maps each PWM channel to its corresponding PDZCR register offset. The function returns the register offset based on the given channel number. The mapping for channels is as follows:

  • Channel 0 and 1 -> PWM_PDZCR01
  • Channel 2 and 3 -> PWM_PDZCR23
  • Channel 4 and 5 -> PWM_PDZCR45
  • Channel 6 and 7 -> PWM_PDZCR67
  • Channel 8 and 9 -> PWM_PDZCR89
  • Channel a and b -> PWM_PDZCRab
  • Channel c and d -> PWM_PDZCRcd
  • Channel e and f -> PWM_PDZCRef
Parameters
channelThe PWM channel number (0-15).
Returns
uint32_t The register offset corresponding to the given PWM channel. Returns PWM_PDZCR01 for invalid channel numbers.

◆ sunxi_pwm_gpio_init()

static void sunxi_pwm_gpio_init ( sunxi_pwm_t pwm,
int  channel 
)
inlinestatic

Initialize the GPIO for a specific PWM channel.

This function initializes the GPIO pins associated with a given PWM channel. If the channel is bound to another channel (via a binding mode), the GPIO for the bound channel is also initialized. The initialization process involves configuring the pin and its multiplexing function as defined in the PWM controller structure.

Parameters
pwmPointer to the PWM controller structure.
channelThe PWM channel number (0-15) whose GPIO needs to be initialized.
Note
If the specified channel is in the "PWM_CHANNEL_BIND" mode, the GPIO for the bound channel will also be initialized first before initializing the specified channel's GPIO.

◆ sunxi_pwm_init()

void sunxi_pwm_init ( sunxi_pwm_t pwm)

Initialize the PWM instance.

This function initializes the PWM instance by setting up the necessary clocks and marking the PWM as initialized (status set to true).

Parameters
pwmPointer to the PWM instance structure.

◆ sunxi_pwm_reg_set()

static void sunxi_pwm_reg_set ( uint32_t  reg,
uint32_t  reg_shift,
uint32_t  reg_width,
uint32_t  data 
)
inlinestatic

Set the value of a specific field in a PWM register.

This function modifies a specific field in the PWM register by shifting and masking the data. It reads the current register value, applies the mask and shift to set the field value, and writes the modified value back to the register.

Parameters
regThe base address of the register.
reg_shiftThe bit position to shift the data for the specific field.
reg_widthThe width (size) of the field to be modified (in bits).
dataThe data to be written to the register field.

◆ sunxi_pwm_release()

int sunxi_pwm_release ( sunxi_pwm_t pwm,
int  channel 
)

Release the PWM channel.

This function releases the specified PWM channel. It checks if the PWM is initialized, validates the channel index, and then either releases a bound channel or a single channel based on the current channel mode.

Parameters
pwmPointer to the PWM instance structure.
channelThe PWM channel to release (0-based index).
Returns
0 on success, -1 if an error occurs (e.g., PWM not initialized, invalid channel index).

◆ sunxi_pwm_release_bind()

static int sunxi_pwm_release_bind ( sunxi_pwm_t pwm,
int  channel 
)
static

Release a bound PWM channel.

This function handles the release of a bound PWM channel. It disables the clock for both the primary and bound channels, resets the clock source to the oscillator, and clears the corresponding dead zone control register for the first channel in the binding.

Parameters
pwmPointer to the PWM instance structure.
channelThe primary PWM channel to release (0-based index).
Returns
0 on success.

◆ sunxi_pwm_release_single()

static int sunxi_pwm_release_single ( sunxi_pwm_t pwm,
int  channel 
)
static

Release a single PWM channel.

This function handles the release of a single PWM channel. It disables the PWM controller for the specified channel, closes the clock gate, and resets the clock source to the oscillator.

Parameters
pwmPointer to the PWM instance structure.
channelThe PWM channel to release (0-based index).
Returns
0 on success.

◆ sunxi_pwm_set_config()

int sunxi_pwm_set_config ( sunxi_pwm_t pwm,
int  channel,
sunxi_pwm_config_t config 
)

Set configuration for a PWM channel.

This function sets the configuration for the specified PWM channel. It checks if the PWM is initialized, validates the channel index, and then applies the configuration either for a bound channel or a single channel based on the current channel mode.

Parameters
pwmPointer to the PWM instance structure.
channelThe PWM channel to configure (0-based index).
configPointer to the PWM configuration structure containing the settings.
Returns
0 on success, -1 if an error occurs (e.g., PWM not initialized, invalid channel index).

◆ sunxi_pwm_set_config_bind()

static int sunxi_pwm_set_config_bind ( sunxi_pwm_t pwm,
int  channel,
sunxi_pwm_config_t config 
)
static

Configure and bind a PWM channel with specific settings.

This function configures the PWM settings for the specified channel, binds it with another channel, and sets up various parameters such as clock source, duty cycle, dead time, active cycles, and period cycles. It also handles the configuration for pulse mode and GPIO initialization for the PWM output.

Parameters
pwmPointer to the PWM instance structure.
channelThe PWM channel to configure (0-based index).
configPointer to the PWM configuration structure.
Returns
0 on success, -1 on error (e.g., invalid duty time or dead zone).

◆ sunxi_pwm_set_config_single()

static int sunxi_pwm_set_config_single ( sunxi_pwm_t pwm,
int  channel,
sunxi_pwm_config_t config 
)
static

Configures a single PWM channel with the given configuration parameters.

This function sets up the PWM configuration for a specific channel. It configures the clock source, the period, duty cycle, polarity, and other related settings based on the provided configuration. It also adjusts the frequency and duty cycle to ensure they are within valid ranges and applies the necessary register settings.

Parameters
pwmPointer to the sunxi_pwm_t structure representing the PWM controller.
channelThe PWM channel number to configure.
configPointer to a sunxi_pwm_config_t structure containing the PWM configuration parameters.
Returns
0 on success, -1 if there is an error in the configuration.
Note
The function configures the PWM clock source based on the period (frequency) provided in the configuration. It can select between APB or OSC clock sources, and sets the prescaler and divider values to achieve the desired frequency and duty cycle.
Warning
The period_ns in the configuration should not be zero and must be greater than duty_ns.

◆ sunxi_pwm_set_porality()

static void sunxi_pwm_set_porality ( sunxi_pwm_t pwm,
int  channel,
sunxi_pwm_polarity_t  polarity 
)
inlinestatic

Set the polarity of a specific PWM channel.

This function sets the polarity for the specified PWM channel. The polarity determines the active state of the PWM signal (high or low). If the polarity is set to 1, the PWM signal is active high; if set to 0, the PWM signal is active low.

Parameters
pwmPointer to the PWM controller structure.
channelThe PWM channel number (0-15) to configure.
polarityThe desired polarity: 1 for active high, 0 for active low.

Variable Documentation

◆ pre_scal

const uint32_t pre_scal[][2]
static
Initial value:
= {
{0, 1},
{1, 2},
{2, 4},
{3, 8},
{4, 16},
{5, 32},
{6, 64},
{7, 128},
{8, 256},
}

Pre-scaler values for clock division.

This constant array maps register values (reg_val) to corresponding clock pre-divider values (clk_pre_div). The array is used to configure the pre-scaler for clock division in PWM or similar hardware modules.

The first element in each pair is the register value, and the second element is the associated clock division factor.