drivers: pwm: Add driver for xmc4xxx using ccu4 module
Adds driver for pwm on xmc4xxx using Capture Compare Unit 4 (CCU4) module. There are four CCU4 with each one having four channels Thus it's possible to have up to 16 pwm output signals. The output of each channel can only be connected to a specific port/pin. The possible connection and gpio configurations are defined using pinctrl. The CCU4 module also has a capture mode. Capture support will be added in the future. Signed-off-by: Andriy Gelman <andriy.gelman@gmail.com>
This commit is contained in:
parent
2cfd831209
commit
23b6e4f507
16 changed files with 436 additions and 1 deletions
|
@ -53,6 +53,8 @@ The Relax Kit development board configuration supports the following hardware fe
|
||||||
+-----------+------------+-----------------------+
|
+-----------+------------+-----------------------+
|
||||||
| DMA | on-chip | dma |
|
| DMA | on-chip | dma |
|
||||||
+-----------+------------+-----------------------+
|
+-----------+------------+-----------------------+
|
||||||
|
| PWM | on-chip | pwm |
|
||||||
|
+-----------+------------+-----------------------+
|
||||||
|
|
||||||
More details about the supported peripherals are available in `XMC4500 TRM`_
|
More details about the supported peripherals are available in `XMC4500 TRM`_
|
||||||
Other hardware features are not currently supported by the Zephyr kernel.
|
Other hardware features are not currently supported by the Zephyr kernel.
|
||||||
|
|
|
@ -15,3 +15,15 @@
|
||||||
drive-strength = "strong-soft-edge";
|
drive-strength = "strong-soft-edge";
|
||||||
hwctrl = "disabled";
|
hwctrl = "disabled";
|
||||||
};
|
};
|
||||||
|
|
||||||
|
&pwm_out_p1_0_ccu40_ch3 {
|
||||||
|
drive-strength = "strong-medium-edge";
|
||||||
|
drive-push-pull;
|
||||||
|
hwctrl = "disabled";
|
||||||
|
};
|
||||||
|
|
||||||
|
&pwm_out_p1_1_ccu40_ch2 {
|
||||||
|
drive-strength = "strong-medium-edge";
|
||||||
|
drive-push-pull;
|
||||||
|
hwctrl = "disabled";
|
||||||
|
};
|
||||||
|
|
|
@ -10,6 +10,7 @@
|
||||||
|
|
||||||
#include <infineon/xmc4500_F100x1024.dtsi>
|
#include <infineon/xmc4500_F100x1024.dtsi>
|
||||||
#include <infineon/xmc4500_F100x1024-intc.dtsi>
|
#include <infineon/xmc4500_F100x1024-intc.dtsi>
|
||||||
|
#include <zephyr/dt-bindings/pwm/pwm.h>
|
||||||
#include "xmc45_relax_kit-pinctrl.dtsi"
|
#include "xmc45_relax_kit-pinctrl.dtsi"
|
||||||
|
|
||||||
/ {
|
/ {
|
||||||
|
@ -20,6 +21,7 @@
|
||||||
aliases {
|
aliases {
|
||||||
led0 = &led1;
|
led0 = &led1;
|
||||||
die-temp0 = &die_temp;
|
die-temp0 = &die_temp;
|
||||||
|
pwm-led0 = &pwm_led1;
|
||||||
};
|
};
|
||||||
|
|
||||||
leds {
|
leds {
|
||||||
|
@ -33,6 +35,18 @@
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
pwmleds {
|
||||||
|
compatible = "pwm-leds";
|
||||||
|
pwm_led1: pwm_led1 {
|
||||||
|
pwms = <&pwm_ccu40 2 PWM_SEC(1) PWM_POLARITY_NORMAL>;
|
||||||
|
label = "PWM LED1";
|
||||||
|
};
|
||||||
|
pwm_led2: pwm_led2 {
|
||||||
|
pwms = <&pwm_ccu40 3 PWM_SEC(1) PWM_POLARITY_NORMAL>;
|
||||||
|
label = "PWM LED2";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
chosen {
|
chosen {
|
||||||
zephyr,sram = &dsram1;
|
zephyr,sram = &dsram1;
|
||||||
zephyr,flash = &flash0;
|
zephyr,flash = &flash0;
|
||||||
|
@ -102,3 +116,9 @@
|
||||||
&gpio1 {
|
&gpio1 {
|
||||||
status = "okay";
|
status = "okay";
|
||||||
};
|
};
|
||||||
|
|
||||||
|
&pwm_ccu40 {
|
||||||
|
slice-prescaler = <15 15 15 15>;
|
||||||
|
pinctrl-0 = <&pwm_out_p1_0_ccu40_ch3 &pwm_out_p1_1_ccu40_ch2>;
|
||||||
|
pinctrl-names = "default";
|
||||||
|
};
|
||||||
|
|
|
@ -56,6 +56,8 @@ The Relax Kit development board configuration supports the following hardware fe
|
||||||
+-----------+------------+-----------------------+
|
+-----------+------------+-----------------------+
|
||||||
| DMA | on-chip | dma |
|
| DMA | on-chip | dma |
|
||||||
+-----------+------------+-----------------------+
|
+-----------+------------+-----------------------+
|
||||||
|
| PWM | on-chip | pwm |
|
||||||
|
+-----------+------------+-----------------------+
|
||||||
|
|
||||||
More details about the supported peripherals are available in `XMC4700 TRM`_
|
More details about the supported peripherals are available in `XMC4700 TRM`_
|
||||||
Other hardware features are not currently supported by the Zephyr kernel.
|
Other hardware features are not currently supported by the Zephyr kernel.
|
||||||
|
|
|
@ -34,6 +34,7 @@ zephyr_library_sources_ifdef(CONFIG_PWM_TEST pwm_test.c)
|
||||||
zephyr_library_sources_ifdef(CONFIG_PWM_RPI_PICO pwm_rpi_pico.c)
|
zephyr_library_sources_ifdef(CONFIG_PWM_RPI_PICO pwm_rpi_pico.c)
|
||||||
zephyr_library_sources_ifdef(CONFIG_PWM_BBLED_XEC pwm_mchp_xec_bbled.c)
|
zephyr_library_sources_ifdef(CONFIG_PWM_BBLED_XEC pwm_mchp_xec_bbled.c)
|
||||||
zephyr_library_sources_ifdef(CONFIG_PWM_INTEL_BLINKY pwm_intel_blinky.c)
|
zephyr_library_sources_ifdef(CONFIG_PWM_INTEL_BLINKY pwm_intel_blinky.c)
|
||||||
|
zephyr_library_sources_ifdef(CONFIG_PWM_XMC4XXX_CCU4 pwm_xmc4xxx_ccu4.c)
|
||||||
|
|
||||||
zephyr_library_sources_ifdef(CONFIG_USERSPACE pwm_handlers.c)
|
zephyr_library_sources_ifdef(CONFIG_USERSPACE pwm_handlers.c)
|
||||||
zephyr_library_sources_ifdef(CONFIG_PWM_CAPTURE pwm_capture.c)
|
zephyr_library_sources_ifdef(CONFIG_PWM_CAPTURE pwm_capture.c)
|
||||||
|
|
|
@ -89,4 +89,6 @@ source "drivers/pwm/Kconfig.rpi_pico"
|
||||||
|
|
||||||
source "drivers/pwm/Kconfig.intel_blinky"
|
source "drivers/pwm/Kconfig.intel_blinky"
|
||||||
|
|
||||||
|
source "drivers/pwm/Kconfig.xmc4xxx_ccu4"
|
||||||
|
|
||||||
endif # PWM
|
endif # PWM
|
||||||
|
|
9
drivers/pwm/Kconfig.xmc4xxx_ccu4
Normal file
9
drivers/pwm/Kconfig.xmc4xxx_ccu4
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
# Copyright (c) 2023 SLB
|
||||||
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
|
config PWM_XMC4XXX_CCU4
|
||||||
|
bool "Infineon XMC4XXX CCU4 driver"
|
||||||
|
default y
|
||||||
|
depends on DT_HAS_INFINEON_XMC4XXX_CCU4_PWM_ENABLED
|
||||||
|
help
|
||||||
|
Enables Infineon XMC4XXX CCU4 PWM driver.
|
112
drivers/pwm/pwm_xmc4xxx_ccu4.c
Normal file
112
drivers/pwm/pwm_xmc4xxx_ccu4.c
Normal file
|
@ -0,0 +1,112 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2023 SLB
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define DT_DRV_COMPAT infineon_xmc4xxx_ccu4_pwm
|
||||||
|
|
||||||
|
#include <soc.h>
|
||||||
|
#include <zephyr/dt-bindings/pwm/pwm.h>
|
||||||
|
#include <zephyr/drivers/pwm.h>
|
||||||
|
#include <zephyr/drivers/pinctrl.h>
|
||||||
|
|
||||||
|
#include <xmc_ccu4.h>
|
||||||
|
#include <xmc_scu.h>
|
||||||
|
|
||||||
|
#include <zephyr/logging/log.h>
|
||||||
|
LOG_MODULE_REGISTER(pwm_xmc4xxx_ccu4, CONFIG_PWM_LOG_LEVEL);
|
||||||
|
|
||||||
|
#define NUM_SLICES 4
|
||||||
|
#define NUM_CHANNELS NUM_SLICES
|
||||||
|
#define SLICE_ADDR_FROM_MODULE(module_ptr, idx) ((uint32_t)(module_ptr) + ((idx) + 1) * 0x100)
|
||||||
|
|
||||||
|
struct pwm_xmc4xxx_ccu4_config {
|
||||||
|
XMC_CCU4_MODULE_t *ccu4;
|
||||||
|
const struct pinctrl_dev_config *pcfg;
|
||||||
|
const uint8_t slice_prescaler[NUM_SLICES];
|
||||||
|
};
|
||||||
|
|
||||||
|
static int pwm_xmc4xxx_ccu4_init(const struct device *dev)
|
||||||
|
{
|
||||||
|
const struct pwm_xmc4xxx_ccu4_config *config = dev->config;
|
||||||
|
|
||||||
|
/* enables the CCU4 clock and ungates clock to CCU4x */
|
||||||
|
XMC_CCU4_EnableModule(config->ccu4);
|
||||||
|
XMC_CCU4_StartPrescaler(config->ccu4);
|
||||||
|
|
||||||
|
for (int i = 0; i < NUM_SLICES; i++) {
|
||||||
|
XMC_CCU4_SLICE_t *slice;
|
||||||
|
XMC_CCU4_SLICE_COMPARE_CONFIG_t slice_conf = {
|
||||||
|
.prescaler_initval = config->slice_prescaler[i]
|
||||||
|
};
|
||||||
|
|
||||||
|
slice = (XMC_CCU4_SLICE_t *)SLICE_ADDR_FROM_MODULE(config->ccu4, i);
|
||||||
|
XMC_CCU4_SLICE_CompareInit(slice, &slice_conf);
|
||||||
|
}
|
||||||
|
|
||||||
|
return pinctrl_apply_state(config->pcfg, PINCTRL_STATE_DEFAULT);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int pwm_xmc4xxx_ccu4_set_cycles(const struct device *dev, uint32_t channel,
|
||||||
|
uint32_t period_cycles, uint32_t pulse_cycles,
|
||||||
|
pwm_flags_t flags)
|
||||||
|
{
|
||||||
|
const struct pwm_xmc4xxx_ccu4_config *config = dev->config;
|
||||||
|
XMC_CCU4_SLICE_t *slice;
|
||||||
|
int slice_idx = channel;
|
||||||
|
|
||||||
|
if (channel >= NUM_CHANNELS) {
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (period_cycles == 0 || period_cycles > UINT16_MAX + 1 || pulse_cycles > UINT16_MAX) {
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
slice = (XMC_CCU4_SLICE_t *)SLICE_ADDR_FROM_MODULE(config->ccu4, slice_idx);
|
||||||
|
slice->PRS = period_cycles - 1;
|
||||||
|
slice->CRS = period_cycles - pulse_cycles;
|
||||||
|
slice->PSL = flags & PWM_POLARITY_INVERTED;
|
||||||
|
|
||||||
|
XMC_CCU4_EnableShadowTransfer(config->ccu4, BIT(slice_idx * 4));
|
||||||
|
|
||||||
|
/* start if not already running */
|
||||||
|
XMC_CCU4_EnableClock(config->ccu4, slice_idx);
|
||||||
|
XMC_CCU4_SLICE_StartTimer(slice);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int pwm_xmc4xxx_ccu4_get_cycles_per_sec(const struct device *dev, uint32_t channel,
|
||||||
|
uint64_t *cycles)
|
||||||
|
{
|
||||||
|
const struct pwm_xmc4xxx_ccu4_config *config = dev->config;
|
||||||
|
int slice_idx = channel;
|
||||||
|
|
||||||
|
if (channel >= NUM_SLICES) {
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
*cycles = XMC_SCU_CLOCK_GetCcuClockFrequency() >> config->slice_prescaler[slice_idx];
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct pwm_driver_api pwm_xmc4xxx_ccu4_driver_api = {
|
||||||
|
.set_cycles = pwm_xmc4xxx_ccu4_set_cycles,
|
||||||
|
.get_cycles_per_sec = pwm_xmc4xxx_ccu4_get_cycles_per_sec,
|
||||||
|
};
|
||||||
|
|
||||||
|
#define PWM_XMC4XXX_CCU4_INIT(n) \
|
||||||
|
PINCTRL_DT_INST_DEFINE(n); \
|
||||||
|
\
|
||||||
|
static const struct pwm_xmc4xxx_ccu4_config config##n = { \
|
||||||
|
.ccu4 = (CCU4_GLOBAL_TypeDef *)DT_INST_REG_ADDR(n), \
|
||||||
|
.pcfg = PINCTRL_DT_INST_DEV_CONFIG_GET(n), \
|
||||||
|
.slice_prescaler = DT_INST_PROP(n, slice_prescaler)}; \
|
||||||
|
\
|
||||||
|
DEVICE_DT_INST_DEFINE(n, pwm_xmc4xxx_ccu4_init, NULL, NULL, &config##n, POST_KERNEL, \
|
||||||
|
CONFIG_PWM_INIT_PRIORITY, &pwm_xmc4xxx_ccu4_driver_api);
|
||||||
|
|
||||||
|
DT_INST_FOREACH_STATUS_OKAY(PWM_XMC4XXX_CCU4_INIT)
|
|
@ -199,4 +199,47 @@
|
||||||
/omit-if-no-ref/ spi_sclk_p5_2_u2c0: spi_sclk_p5_2_u2c0 {
|
/omit-if-no-ref/ spi_sclk_p5_2_u2c0: spi_sclk_p5_2_u2c0 {
|
||||||
pinmux = <XMC4XXX_PINMUX_SET(5, 2, 1)>;
|
pinmux = <XMC4XXX_PINMUX_SET(5, 2, 1)>;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/omit-if-no-ref/ pwm_out_p0_12_ccu40_ch3: pwm_out_p0_12_ccu40_ch3 {
|
||||||
|
pinmux = <XMC4XXX_PINMUX_SET(0, 12, 3)>;
|
||||||
|
};
|
||||||
|
/omit-if-no-ref/ pwm_out_p1_0_ccu40_ch3: pwm_out_p1_0_ccu40_ch3 {
|
||||||
|
pinmux = <XMC4XXX_PINMUX_SET(1, 0, 3)>;
|
||||||
|
};
|
||||||
|
/omit-if-no-ref/ pwm_out_p1_1_ccu40_ch2: pwm_out_p1_1_ccu40_ch2 {
|
||||||
|
pinmux = <XMC4XXX_PINMUX_SET(1, 1, 3)>;
|
||||||
|
};
|
||||||
|
/omit-if-no-ref/ pwm_out_p1_2_ccu40_ch1: pwm_out_p1_2_ccu40_ch1 {
|
||||||
|
pinmux = <XMC4XXX_PINMUX_SET(1, 2, 3)>;
|
||||||
|
};
|
||||||
|
/omit-if-no-ref/ pwm_out_p1_3_ccu40_ch0: pwm_out_p1_3_ccu40_ch0 {
|
||||||
|
pinmux = <XMC4XXX_PINMUX_SET(1, 3, 3)>;
|
||||||
|
};
|
||||||
|
/omit-if-no-ref/ pwm_out_p2_2_ccu41_ch3: pwm_out_p2_2_ccu41_ch3 {
|
||||||
|
pinmux = <XMC4XXX_PINMUX_SET(2, 2, 3)>;
|
||||||
|
};
|
||||||
|
/omit-if-no-ref/ pwm_out_p2_3_ccu41_ch2: pwm_out_p2_3_ccu41_ch2 {
|
||||||
|
pinmux = <XMC4XXX_PINMUX_SET(2, 3, 3)>;
|
||||||
|
};
|
||||||
|
/omit-if-no-ref/ pwm_out_p2_4_ccu41_ch1: pwm_out_p2_4_ccu41_ch1 {
|
||||||
|
pinmux = <XMC4XXX_PINMUX_SET(2, 4, 3)>;
|
||||||
|
};
|
||||||
|
/omit-if-no-ref/ pwm_out_p2_5_ccu41_ch0: pwm_out_p2_5_ccu41_ch0 {
|
||||||
|
pinmux = <XMC4XXX_PINMUX_SET(2, 5, 3)>;
|
||||||
|
};
|
||||||
|
/omit-if-no-ref/ pwm_out_p3_0_ccu42_ch0: pwm_out_p3_0_ccu42_ch0 {
|
||||||
|
pinmux = <XMC4XXX_PINMUX_SET(3, 0, 3)>;
|
||||||
|
};
|
||||||
|
/omit-if-no-ref/ pwm_out_p3_3_ccu42_ch3: pwm_out_p3_3_ccu42_ch3 {
|
||||||
|
pinmux = <XMC4XXX_PINMUX_SET(3, 3, 3)>;
|
||||||
|
};
|
||||||
|
/omit-if-no-ref/ pwm_out_p3_4_ccu42_ch2: pwm_out_p3_4_ccu42_ch2 {
|
||||||
|
pinmux = <XMC4XXX_PINMUX_SET(3, 4, 3)>;
|
||||||
|
};
|
||||||
|
/omit-if-no-ref/ pwm_out_p3_5_ccu42_ch1: pwm_out_p3_5_ccu42_ch1 {
|
||||||
|
pinmux = <XMC4XXX_PINMUX_SET(3, 5, 3)>;
|
||||||
|
};
|
||||||
|
/omit-if-no-ref/ pwm_out_p3_6_ccu42_ch0: pwm_out_p3_6_ccu42_ch0 {
|
||||||
|
pinmux = <XMC4XXX_PINMUX_SET(3, 6, 3)>;
|
||||||
|
};
|
||||||
};
|
};
|
||||||
|
|
|
@ -714,4 +714,101 @@
|
||||||
/omit-if-no-ref/ i2c_target_sda_p3_5_u2c1: i2c_target_sda_p3_5_u2c1 {
|
/omit-if-no-ref/ i2c_target_sda_p3_5_u2c1: i2c_target_sda_p3_5_u2c1 {
|
||||||
pinmux = <XMC4XXX_PINMUX_SET(3, 5, 0x19)>;
|
pinmux = <XMC4XXX_PINMUX_SET(3, 5, 0x19)>;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/omit-if-no-ref/ pwm_out_p0_12_ccu40_ch3: pwm_out_p0_12_ccu40_ch3 {
|
||||||
|
pinmux = <XMC4XXX_PINMUX_SET(0, 12, 3)>;
|
||||||
|
};
|
||||||
|
/omit-if-no-ref/ pwm_out_p0_13_ccu40_ch2: pwm_out_p0_13_ccu40_ch2 {
|
||||||
|
pinmux = <XMC4XXX_PINMUX_SET(0, 13, 3)>;
|
||||||
|
};
|
||||||
|
/omit-if-no-ref/ pwm_out_p0_14_ccu40_ch1: pwm_out_p0_14_ccu40_ch1 {
|
||||||
|
pinmux = <XMC4XXX_PINMUX_SET(0, 14, 3)>;
|
||||||
|
};
|
||||||
|
/omit-if-no-ref/ pwm_out_p0_15_ccu40_ch0: pwm_out_p0_15_ccu40_ch0 {
|
||||||
|
pinmux = <XMC4XXX_PINMUX_SET(0, 15, 3)>;
|
||||||
|
};
|
||||||
|
/omit-if-no-ref/ pwm_out_p1_0_ccu40_ch3: pwm_out_p1_0_ccu40_ch3 {
|
||||||
|
pinmux = <XMC4XXX_PINMUX_SET(1, 0, 3)>;
|
||||||
|
};
|
||||||
|
/omit-if-no-ref/ pwm_out_p1_1_ccu40_ch2: pwm_out_p1_1_ccu40_ch2 {
|
||||||
|
pinmux = <XMC4XXX_PINMUX_SET(1, 1, 3)>;
|
||||||
|
};
|
||||||
|
/omit-if-no-ref/ pwm_out_p1_2_ccu40_ch1: pwm_out_p1_2_ccu40_ch1 {
|
||||||
|
pinmux = <XMC4XXX_PINMUX_SET(1, 2, 3)>;
|
||||||
|
};
|
||||||
|
/omit-if-no-ref/ pwm_out_p1_3_ccu40_ch0: pwm_out_p1_3_ccu40_ch0 {
|
||||||
|
pinmux = <XMC4XXX_PINMUX_SET(1, 3, 3)>;
|
||||||
|
};
|
||||||
|
/omit-if-no-ref/ pwm_out_p2_2_ccu41_ch3: pwm_out_p2_2_ccu41_ch3 {
|
||||||
|
pinmux = <XMC4XXX_PINMUX_SET(2, 2, 3)>;
|
||||||
|
};
|
||||||
|
/omit-if-no-ref/ pwm_out_p2_3_ccu41_ch2: pwm_out_p2_3_ccu41_ch2 {
|
||||||
|
pinmux = <XMC4XXX_PINMUX_SET(2, 3, 3)>;
|
||||||
|
};
|
||||||
|
/omit-if-no-ref/ pwm_out_p2_4_ccu41_ch1: pwm_out_p2_4_ccu41_ch1 {
|
||||||
|
pinmux = <XMC4XXX_PINMUX_SET(2, 4, 3)>;
|
||||||
|
};
|
||||||
|
/omit-if-no-ref/ pwm_out_p2_5_ccu41_ch0: pwm_out_p2_5_ccu41_ch0 {
|
||||||
|
pinmux = <XMC4XXX_PINMUX_SET(2, 5, 3)>;
|
||||||
|
};
|
||||||
|
/omit-if-no-ref/ pwm_out_p3_0_ccu42_ch0: pwm_out_p3_0_ccu42_ch0 {
|
||||||
|
pinmux = <XMC4XXX_PINMUX_SET(3, 0, 3)>;
|
||||||
|
};
|
||||||
|
/omit-if-no-ref/ pwm_out_p3_3_ccu42_ch3: pwm_out_p3_3_ccu42_ch3 {
|
||||||
|
pinmux = <XMC4XXX_PINMUX_SET(3, 3, 3)>;
|
||||||
|
};
|
||||||
|
/omit-if-no-ref/ pwm_out_p3_4_ccu42_ch2: pwm_out_p3_4_ccu42_ch2 {
|
||||||
|
pinmux = <XMC4XXX_PINMUX_SET(3, 4, 3)>;
|
||||||
|
};
|
||||||
|
/omit-if-no-ref/ pwm_out_p3_5_ccu42_ch1: pwm_out_p3_5_ccu42_ch1 {
|
||||||
|
pinmux = <XMC4XXX_PINMUX_SET(3, 5, 3)>;
|
||||||
|
};
|
||||||
|
/omit-if-no-ref/ pwm_out_p3_6_ccu42_ch0: pwm_out_p3_6_ccu42_ch0 {
|
||||||
|
pinmux = <XMC4XXX_PINMUX_SET(3, 6, 3)>;
|
||||||
|
};
|
||||||
|
/omit-if-no-ref/ pwm_out_p3_7_ccu41_ch3: pwm_out_p3_7_ccu41_ch3 {
|
||||||
|
pinmux = <XMC4XXX_PINMUX_SET(3, 7, 3)>;
|
||||||
|
};
|
||||||
|
/omit-if-no-ref/ pwm_out_p3_8_ccu41_ch2: pwm_out_p3_8_ccu41_ch2 {
|
||||||
|
pinmux = <XMC4XXX_PINMUX_SET(3, 8, 3)>;
|
||||||
|
};
|
||||||
|
/omit-if-no-ref/ pwm_out_p3_9_ccu41_ch1: pwm_out_p3_9_ccu41_ch1 {
|
||||||
|
pinmux = <XMC4XXX_PINMUX_SET(3, 9, 3)>;
|
||||||
|
};
|
||||||
|
/omit-if-no-ref/ pwm_out_p3_10_ccu41_ch0: pwm_out_p3_10_ccu41_ch0 {
|
||||||
|
pinmux = <XMC4XXX_PINMUX_SET(3, 10, 3)>;
|
||||||
|
};
|
||||||
|
/omit-if-no-ref/ pwm_out_p3_11_ccu42_ch3: pwm_out_p3_11_ccu42_ch3 {
|
||||||
|
pinmux = <XMC4XXX_PINMUX_SET(3, 11, 3)>;
|
||||||
|
};
|
||||||
|
/omit-if-no-ref/ pwm_out_p3_12_ccu42_ch2: pwm_out_p3_12_ccu42_ch2 {
|
||||||
|
pinmux = <XMC4XXX_PINMUX_SET(3, 12, 3)>;
|
||||||
|
};
|
||||||
|
/omit-if-no-ref/ pwm_out_p3_13_ccu42_ch1: pwm_out_p3_13_ccu42_ch1 {
|
||||||
|
pinmux = <XMC4XXX_PINMUX_SET(3, 13, 3)>;
|
||||||
|
};
|
||||||
|
/omit-if-no-ref/ pwm_out_p4_3_ccu43_ch3: pwm_out_p4_3_ccu43_ch3 {
|
||||||
|
pinmux = <XMC4XXX_PINMUX_SET(4, 3, 3)>;
|
||||||
|
};
|
||||||
|
/omit-if-no-ref/ pwm_out_p4_4_ccu43_ch2: pwm_out_p4_4_ccu43_ch2 {
|
||||||
|
pinmux = <XMC4XXX_PINMUX_SET(4, 4, 3)>;
|
||||||
|
};
|
||||||
|
/omit-if-no-ref/ pwm_out_p4_5_ccu43_ch1: pwm_out_p4_5_ccu43_ch1 {
|
||||||
|
pinmux = <XMC4XXX_PINMUX_SET(4, 5, 3)>;
|
||||||
|
};
|
||||||
|
/omit-if-no-ref/ pwm_out_p4_6_ccu43_ch0: pwm_out_p4_6_ccu43_ch0 {
|
||||||
|
pinmux = <XMC4XXX_PINMUX_SET(4, 6, 3)>;
|
||||||
|
};
|
||||||
|
/omit-if-no-ref/ pwm_out_p6_2_ccu43_ch3: pwm_out_p6_2_ccu43_ch3 {
|
||||||
|
pinmux = <XMC4XXX_PINMUX_SET(6, 2, 3)>;
|
||||||
|
};
|
||||||
|
/omit-if-no-ref/ pwm_out_p6_3_ccu43_ch2: pwm_out_p6_3_ccu43_ch2 {
|
||||||
|
pinmux = <XMC4XXX_PINMUX_SET(6, 3, 3)>;
|
||||||
|
};
|
||||||
|
/omit-if-no-ref/ pwm_out_p6_4_ccu43_ch1: pwm_out_p6_4_ccu43_ch1 {
|
||||||
|
pinmux = <XMC4XXX_PINMUX_SET(6, 4, 3)>;
|
||||||
|
};
|
||||||
|
/omit-if-no-ref/ pwm_out_p6_5_ccu43_ch0: pwm_out_p6_5_ccu43_ch0 {
|
||||||
|
pinmux = <XMC4XXX_PINMUX_SET(6, 5, 3)>;
|
||||||
|
};
|
||||||
};
|
};
|
||||||
|
|
|
@ -187,6 +187,34 @@
|
||||||
compatible = "infineon,xmc4xxx-temp";
|
compatible = "infineon,xmc4xxx-temp";
|
||||||
status = "disabled";
|
status = "disabled";
|
||||||
};
|
};
|
||||||
|
|
||||||
|
pwm_ccu40: ccu40@4000c000 {
|
||||||
|
compatible = "infineon,xmc4xxx-ccu4-pwm";
|
||||||
|
reg = <0x4000c000 0x4000>;
|
||||||
|
#pwm-cells = <3>;
|
||||||
|
status = "disabled";
|
||||||
|
};
|
||||||
|
|
||||||
|
pwm_ccu41: ccu41@40010000 {
|
||||||
|
compatible = "infineon,xmc4xxx-ccu4-pwm";
|
||||||
|
reg = <0x40010000 0x4000>;
|
||||||
|
#pwm-cells = <3>;
|
||||||
|
status = "disabled";
|
||||||
|
};
|
||||||
|
|
||||||
|
pwm_ccu42: ccu42@40014000 {
|
||||||
|
compatible = "infineon,xmc4xxx-ccu4-pwm";
|
||||||
|
reg = <0x40014000 0x4000>;
|
||||||
|
#pwm-cells = <3>;
|
||||||
|
status = "disabled";
|
||||||
|
};
|
||||||
|
|
||||||
|
pwm_ccu43: ccu43@48004000 {
|
||||||
|
compatible = "infineon,xmc4xxx-ccu4-pwm";
|
||||||
|
reg = <0x48004000 0x4000>;
|
||||||
|
#pwm-cells = <3>;
|
||||||
|
status = "disabled";
|
||||||
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
84
dts/bindings/pwm/infineon,xmc4xxx-ccu4-pwm.yaml
Normal file
84
dts/bindings/pwm/infineon,xmc4xxx-ccu4-pwm.yaml
Normal file
|
@ -0,0 +1,84 @@
|
||||||
|
# Copyright (c) 2023 SLB
|
||||||
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
|
description: |
|
||||||
|
Infineon XMC4XXX PWM Capture Compare Unit 4 (CCU4) module
|
||||||
|
|
||||||
|
The are four CCU4 modules with dts node labels:
|
||||||
|
pwm_ccu40, pwm_ccu41, pwm_ccu42, pwm_ccu43.
|
||||||
|
Each module has four slices and each slice has one channel.
|
||||||
|
A channel is connected to a particular gpio pin, which are defined
|
||||||
|
using pinctrl in:
|
||||||
|
dts/arm/infineon/xmc4xxx_xxx-pinctrl.dtsi
|
||||||
|
|
||||||
|
The CCU4 modules uses the CCU clock source. Each slice applies a separate
|
||||||
|
prescalar which divides the clock.
|
||||||
|
|
||||||
|
Device tree example:
|
||||||
|
A node can define a 'pwm' field, usually referenced in a 'pwms'
|
||||||
|
property, where the entries include the PWM module phandle,
|
||||||
|
channel number, pulse period (in nanoseconds or set using
|
||||||
|
PWM_XX() macros), and a channela
|
||||||
|
flag (PWM_POLARITY_NORMAL/PWM_POLARITY_INVERTED).
|
||||||
|
|
||||||
|
The pwm ccu4 node must define the slice-prescaler values and the pinctrl nodes:
|
||||||
|
&pwm_ccu40 {
|
||||||
|
slice-prescaler = <15 15 15 15>;
|
||||||
|
pinctrl-0 = <&pwm_out_p1_1_ccu40_ch2>;
|
||||||
|
pinctrl-names = "default";
|
||||||
|
};
|
||||||
|
|
||||||
|
Another node can reference the PWM as follows:
|
||||||
|
&test_node {
|
||||||
|
...
|
||||||
|
pwms = <&pwm_ccu40 0 PWM_SEC(1) PWM_POLARITY_NORMAL>;
|
||||||
|
...
|
||||||
|
};
|
||||||
|
|
||||||
|
The user must also explicitly set pinctrl properties.
|
||||||
|
The pin should be configured with drive-push-pull bool option and hwctrl should be set
|
||||||
|
to disabled. The drive-strength field can be set to any of the supported values:
|
||||||
|
&pwm_out_p1_1_ccu40_ch2 {
|
||||||
|
drive-strength = "strong-medium-edge";
|
||||||
|
drive-push-pull;
|
||||||
|
hwctrl = "disabled";
|
||||||
|
};
|
||||||
|
|
||||||
|
The CCU4 pinctrl nodes have a node labels in the format
|
||||||
|
pwm_out_p{PORT}_{PIN}_ccu4{MODULE_IDX}_ch{CHANNEL_IDX}, where MODULE_IDX and
|
||||||
|
CHANNEL_IDX refers to specific pwm_ccu4x module and channel, respectively.
|
||||||
|
PORT/PIN pair defines what gpio the channel connects to.
|
||||||
|
|
||||||
|
compatible: "infineon,xmc4xxx-ccu4-pwm"
|
||||||
|
|
||||||
|
include:
|
||||||
|
- name: base.yaml
|
||||||
|
- name: pwm-controller.yaml
|
||||||
|
- name: pinctrl-device.yaml
|
||||||
|
|
||||||
|
properties:
|
||||||
|
reg:
|
||||||
|
required: true
|
||||||
|
|
||||||
|
pinctrl-0:
|
||||||
|
required: true
|
||||||
|
|
||||||
|
pinctrl-names:
|
||||||
|
required: true
|
||||||
|
|
||||||
|
slice-prescaler:
|
||||||
|
type: array
|
||||||
|
required: true
|
||||||
|
description: |
|
||||||
|
Defines the clock divider for each channel.
|
||||||
|
The entry in the array will divide CCU clock by (2 << value).
|
||||||
|
The range for the prescaler values is [0, 15].
|
||||||
|
Reducing prescaler value will improve resolution but decrease the maximum period.
|
||||||
|
|
||||||
|
"#pwm-cells":
|
||||||
|
const: 3
|
||||||
|
|
||||||
|
pwm-cells:
|
||||||
|
- channel
|
||||||
|
- period
|
||||||
|
- flags
|
|
@ -45,4 +45,9 @@ config HAS_XMCLIB_I2C
|
||||||
help
|
help
|
||||||
Enable XMCLIB I2C
|
Enable XMCLIB I2C
|
||||||
|
|
||||||
|
config HAS_XMCLIB_CCU
|
||||||
|
bool
|
||||||
|
help
|
||||||
|
Enable XMCLIB CCU4/CCU8
|
||||||
|
|
||||||
endif # HAS_XMCLIB
|
endif # HAS_XMCLIB
|
||||||
|
|
13
samples/basic/blinky_pwm/boards/xmc45_relax_kit.overlay
Normal file
13
samples/basic/blinky_pwm/boards/xmc45_relax_kit.overlay
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2023 SLB
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
&pwm_led1 {
|
||||||
|
status = "okay";
|
||||||
|
};
|
||||||
|
|
||||||
|
&pwm_ccu40 {
|
||||||
|
status = "okay";
|
||||||
|
};
|
|
@ -19,5 +19,6 @@ config SOC_SERIES_XMC_4XXX
|
||||||
select HAS_XMCLIB_DMA
|
select HAS_XMCLIB_DMA
|
||||||
select HAS_XMCLIB_SPI
|
select HAS_XMCLIB_SPI
|
||||||
select HAS_XMCLIB_I2C
|
select HAS_XMCLIB_I2C
|
||||||
|
select HAS_XMCLIB_CCU
|
||||||
help
|
help
|
||||||
Enable support for XMC 4xxx MCU series
|
Enable support for XMC 4xxx MCU series
|
||||||
|
|
|
@ -31,7 +31,11 @@ void z_arm_platform_init(void)
|
||||||
temp |= PMU_FLASH_WS;
|
temp |= PMU_FLASH_WS;
|
||||||
FLASH0->FCON = temp;
|
FLASH0->FCON = temp;
|
||||||
|
|
||||||
XMC_SCU_CLOCK_SetSleepConfig(XMC_SCU_CLOCK_SLEEP_MODE_CONFIG_SYSCLK_FPLL);
|
XMC_SCU_CLOCK_SetSleepConfig(XMC_SCU_CLOCK_SLEEP_MODE_CONFIG_SYSCLK_FPLL
|
||||||
|
#ifdef CONFIG_PWM_XMC4XXX_CCU4
|
||||||
|
| XMC_SCU_CLOCK_SLEEP_MODE_CONFIG_ENABLE_CCU
|
||||||
|
#endif
|
||||||
|
);
|
||||||
|
|
||||||
/* configure PLL & system clock */
|
/* configure PLL & system clock */
|
||||||
SystemCoreClockSetup();
|
SystemCoreClockSetup();
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue