Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions drivers/clock_control/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -109,3 +109,4 @@ zephyr_library_sources_ifdef(CONFIG_CLOCK_CONTROL_AST10X0 clock_control_ast10x0.
zephyr_library_sources_ifdef(CONFIG_CLOCK_CONTROL_MAX32 clock_control_max32.c)
zephyr_library_sources_ifdef(CONFIG_CLOCK_CONTROL_NRF_AUXPLL clock_control_nrf_auxpll.c)
zephyr_library_sources_ifdef(CONFIG_CLOCK_CONTROL_WCH_RCC clock_control_wch_rcc.c)
zephyr_library_sources_ifdef(CONFIG_CLOCK_CONTROL_TI_SYSCON clock_control_ti_syscon.c)
2 changes: 2 additions & 0 deletions drivers/clock_control/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -110,4 +110,6 @@ source "drivers/clock_control/Kconfig.wch_rcc"

source "drivers/clock_control/Kconfig.it51xxx"

source "drivers/clock_control/Kconfig.ti_syscon"

endif # CLOCK_CONTROL
10 changes: 10 additions & 0 deletions drivers/clock_control/Kconfig.ti_syscon
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
# Copyright (c) 2025 Texas Instruments
# SPDX-License-Identifier: Apache-2.0

config CLOCK_CONTROL_TI_SYSCON
bool "TI Syscon backed gate-clock driver"
default y
depends on DT_HAS_TI_AM654_EHRPWM_TBCLK_ENABLED || DT_HAS_TI_AM64_EPWM_TBCLK_ENABLED || DT_HAS_TI_AM62_EPWM_TBCLK_ENABLED
select SYSCON
help
Enable driver for TI Syscon backed gate-clock controller.
132 changes: 132 additions & 0 deletions drivers/clock_control/clock_control_ti_syscon.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
/*
* Copyright 2025 Texas Instruments
*
* SPDX-License-Identifier: Apache-2.0
*/

#define DT_AM654_COMPAT ti_am654_ehrpwm_tbclk
#define DT_AM64_COMPAT ti_am64_epwm_tbclk
#define DT_AM62_COMPAT ti_am62_epwm_tbclk

#include <zephyr/drivers/clock_control.h>
#include <zephyr/drivers/syscon.h>
#include <zephyr/logging/log.h>

LOG_MODULE_REGISTER(ti_syscon_gate_clk, CONFIG_CLOCK_CONTROL_LOG_LEVEL);

#define DEV_CFG(dev) ((struct ti_syscon_gate_clk_cfg *)(dev)->config)

struct ti_syscon_gate_clk_id_data {
uint32_t offset;
uint32_t bit;
};

#if DT_HAS_COMPAT_STATUS_OKAY(DT_AM64_COMPAT)
static const struct ti_syscon_gate_clk_id_data am64_clk_ids[] = {
{0, 0}, {0, 1}, {0, 2}, {0, 3}, {0, 4}, {0, 5}, {0, 6}, {0, 7}, {0, 8},
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Any good way to encode this data into DT so that we don't need to keep device specific data here in the driver?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually, I replicated this behavior from Linux where several compat strings can stay in the same driver code.
To answer your question, this can be added to the DT, provided noone has a problem with this big array of register indices in the node.

};
#endif

#if DT_HAS_COMPAT_STATUS_OKAY(DT_AM654_COMPAT)
static const struct ti_syscon_gate_clk_id_data am654_clk_ids[] = {
{0x0, 0}, {0x4, 0}, {0x8, 0}, {0xc, 0}, {0x10, 0}, {0x14, 0},
};
#endif

#if DT_HAS_COMPAT_STATUS_OKAY(DT_AM62_COMPAT)
static const struct ti_syscon_gate_clk_id_data am62_clk_ids[] = {
{0, 0},
{0, 1},
{0, 2},
};
#endif

struct ti_syscon_gate_clk_cfg {
mm_reg_t reg;
const struct device *syscon;
const struct ti_syscon_gate_clk_id_data *clk_ids;
const uint32_t num_clk_ids;
};

static int ti_syscon_gate_clk_enable(const struct device *dev, clock_control_subsys_t sub_system,
bool enable)
{
const struct ti_syscon_gate_clk_cfg *cfg = DEV_CFG(dev);
uint32_t clk_id = (sub_system ? (uint32_t)sub_system : 0);
uint32_t reg;
uint32_t bit;
uint32_t val;
uint32_t rb;
int err;

if (clk_id >= cfg->num_clk_ids) {
LOG_ERR("invalid clk id");
return -EINVAL;
}

reg = cfg->reg + cfg->clk_ids[clk_id].offset;
bit = cfg->clk_ids[clk_id].bit;

err = syscon_read_reg(cfg->syscon, reg, &val);
if (err < 0) {
LOG_ERR("failed to read syscon register");
return err;
}

if (enable) {
val |= BIT(bit);
} else {
val &= ~BIT(bit);
}

err = syscon_write_reg(cfg->syscon, reg, val);
if (err < 0) {
LOG_ERR("failed to write syscon register");
return err;
}

err = syscon_read_reg(cfg->syscon, reg, &rb);
if (err < 0) {
LOG_ERR("failed to read syscon register");
return err;
}

if (rb != val) {
LOG_ERR("readback does not match written value");
return -EIO;
}

return 0;
}

static int ti_syscon_gate_clk_on(const struct device *dev, clock_control_subsys_t sub_system)
{
return ti_syscon_gate_clk_enable(dev, sub_system, true);
}

static int ti_syscon_gate_clk_off(const struct device *dev, clock_control_subsys_t sub_system)
{
return ti_syscon_gate_clk_enable(dev, sub_system, false);
}

static DEVICE_API(clock_control, ti_syscon_gate_clk_driver_api) = {
.on = ti_syscon_gate_clk_on,
.off = ti_syscon_gate_clk_off,
};

#define TI_SYSCON_GATE_CLK_INIT(node, clks) \
static const struct ti_syscon_gate_clk_cfg ti_syscon_gate_clk_config_##node = { \
.reg = DT_REG_ADDR(node), \
.syscon = DEVICE_DT_GET(DT_PARENT(node)), \
.clk_ids = clks, \
.num_clk_ids = ARRAY_SIZE(clks), \
}; \
\
DEVICE_DT_DEFINE(node, NULL, NULL, NULL, &ti_syscon_gate_clk_config_##node, POST_KERNEL, \
CONFIG_CLOCK_CONTROL_INIT_PRIORITY, &ti_syscon_gate_clk_driver_api);

/* add more compats as required */

DT_FOREACH_STATUS_OKAY_VARGS(DT_AM654_COMPAT, TI_SYSCON_GATE_CLK_INIT, am654_clk_ids)
DT_FOREACH_STATUS_OKAY_VARGS(DT_AM64_COMPAT, TI_SYSCON_GATE_CLK_INIT, am64_clk_ids)
DT_FOREACH_STATUS_OKAY_VARGS(DT_AM62_COMPAT, TI_SYSCON_GATE_CLK_INIT, am62_clk_ids)
1 change: 1 addition & 0 deletions drivers/pwm/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -54,3 +54,4 @@ zephyr_library_sources_ifdef(CONFIG_PWM_RENESAS_RZ_GPT pwm_renesas_rz_gpt.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_SHELL pwm_shell.c)
zephyr_library_sources_ifdef(CONFIG_PWM_TI_AM3352_EHRPWM pwm_ti_am3352_ehrpwm.c)
2 changes: 2 additions & 0 deletions drivers/pwm/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -122,4 +122,6 @@ source "drivers/pwm/Kconfig.fake"

source "drivers/pwm/Kconfig.renesas_rz"

source "drivers/pwm/Kconfig.ti_am3352_ehrpwm"

endif # PWM
9 changes: 9 additions & 0 deletions drivers/pwm/Kconfig.ti_am3352_ehrpwm
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# Copyright (c) 2025 Texas Instruments
# SPDX-License-Identifier: Apache-2.0

config PWM_TI_AM3352_EHRPWM
bool "TI EHRPWM based PWM controller"
default y
depends on DT_HAS_TI_AM3352_EHRPWM_ENABLED
help
Enable EHRPWM controller for TI SoCs
Loading