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:
Andriy Gelman 2023-06-04 21:36:17 -04:00 committed by Carles Cufí
commit 23b6e4f507
16 changed files with 436 additions and 1 deletions

View file

@ -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.

View file

@ -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";
};

View file

@ -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";
};

View file

@ -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.

View file

@ -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)

View file

@ -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

View 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.

View 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)

View file

@ -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)>;
};
}; };

View file

@ -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)>;
};
}; };

View file

@ -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";
};
}; };
}; };

View 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

View file

@ -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

View file

@ -0,0 +1,13 @@
/*
* Copyright (c) 2023 SLB
*
* SPDX-License-Identifier: Apache-2.0
*/
&pwm_led1 {
status = "okay";
};
&pwm_ccu40 {
status = "okay";
};

View file

@ -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

View file

@ -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();