diff --git a/drivers/clock_control/CMakeLists.txt b/drivers/clock_control/CMakeLists.txt index c5e9c9e5bd09d..1c708193642c3 100644 --- a/drivers/clock_control/CMakeLists.txt +++ b/drivers/clock_control/CMakeLists.txt @@ -66,6 +66,7 @@ zephyr_library_sources_ifdef(CONFIG_CLOCK_CONTROL_BOUFFALOLAB_BL61X clock_cont zephyr_library_sources_ifdef(CONFIG_CLOCK_CONTROL_BOUFFALOLAB_BL70X clock_control_bl70x.c) zephyr_library_sources_ifdef(CONFIG_CLOCK_CONTROL_SF32LB_HXT48 clock_control_sf32lb_hxt48.c) zephyr_library_sources_ifdef(CONFIG_CLOCK_CONTROL_SF32LB_RCC clock_control_sf32lb_rcc.c) +zephyr_library_sources_ifdef(CONFIG_CLOCK_CONTROL_TISCI clock_control_tisci.c) if(CONFIG_CLOCK_CONTROL_RENESAS_RZA2M_CPG) zephyr_library_sources(clock_control_renesas_rza2m_cpg.c) diff --git a/drivers/clock_control/Kconfig b/drivers/clock_control/Kconfig index e2c4a071ab09a..7d33019c7c4f3 100644 --- a/drivers/clock_control/Kconfig +++ b/drivers/clock_control/Kconfig @@ -122,4 +122,6 @@ source "drivers/clock_control/Kconfig.sf32lb_hxt48" source "drivers/clock_control/Kconfig.sf32lb_rcc" +source "drivers/clock_control/Kconfig.tisci" + endif # CLOCK_CONTROL diff --git a/drivers/clock_control/Kconfig.tisci b/drivers/clock_control/Kconfig.tisci new file mode 100644 index 0000000000000..e56d5023b2ab5 --- /dev/null +++ b/drivers/clock_control/Kconfig.tisci @@ -0,0 +1,9 @@ +# Copyright 2024 Texas Instruments Incorporated. +# SPDX-License-Identifier: Apache-2.0 + +config CLOCK_CONTROL_TISCI + bool "TI SCI Clock Control driver" + default y + depends on DT_HAS_TI_K2G_SCI_CLK_ENABLED + help + Driver for TISCI based clock control. diff --git a/drivers/clock_control/clock_control_tisci.c b/drivers/clock_control/clock_control_tisci.c new file mode 100644 index 0000000000000..7032c7b380d76 --- /dev/null +++ b/drivers/clock_control/clock_control_tisci.c @@ -0,0 +1,100 @@ +/* + * Copyright (c) 2025, Texas Instruments + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#define DT_DRV_COMPAT ti_k2g_sci_clk + +#include +#include +#include +#include +#include +#include + +LOG_MODULE_REGISTER(ti_k2g_sci_clk, CONFIG_CLOCK_CONTROL_LOG_LEVEL); + +static const struct device *dmsc = DEVICE_DT_GET(DT_NODELABEL(dmsc)); + +static int tisci_get_rate(const struct device *dev, clock_control_subsys_t sys, uint32_t *rate) +{ + struct tisci_clock_config *req = (struct tisci_clock_config *)sys; + uint64_t temp_rate; + int ret; + + ret = tisci_cmd_clk_get_freq(dmsc, req->dev_id, req->clk_id, &temp_rate); + if (ret) { + LOG_ERR("Failed to get clock freq: dev_id=%u clk_id=%u err=%d", req->dev_id, + req->clk_id, ret); + return ret; + } + + *rate = (uint32_t)temp_rate; + + return 0; +} + +static int tisci_set_rate(const struct device *dev, void *sys, void *rate) +{ + struct tisci_clock_config *req = (struct tisci_clock_config *)sys; + uint64_t freq = *((uint64_t *)rate); + int ret; + + ret = tisci_cmd_clk_set_freq(dmsc, req->dev_id, req->clk_id, freq, freq, freq); + if (ret) { + LOG_ERR("Failed to set clock freq: dev_id=%u clk_id=%u freq=%llu err=%d", + req->dev_id, req->clk_id, freq, ret); + } + + return ret; +} + +static enum clock_control_status tisci_get_status(const struct device *dev, + clock_control_subsys_t sys) +{ + struct tisci_clock_config *req = (struct tisci_clock_config *)sys; + bool req_state = true; + bool curr_state = true; + int ret; + + ret = tisci_cmd_clk_is_on(dmsc, req->clk_id, req->dev_id, &req_state, &curr_state); + if (ret) { + LOG_ERR("Failed to get clock ON status: dev_id=%u clk_id=%u err=%d", req->dev_id, + req->clk_id, ret); + return CLOCK_CONTROL_STATUS_UNKNOWN; + } + if (curr_state) { + return CLOCK_CONTROL_STATUS_ON; + } + if (req_state && !curr_state) { + return CLOCK_CONTROL_STATUS_STARTING; + } + + curr_state = true; + + ret = tisci_cmd_clk_is_off(dmsc, req->clk_id, req->dev_id, NULL, &curr_state); + if (ret) { + LOG_ERR("Failed to get clock OFF status: dev_id=%u clk_id=%u err=%d", req->dev_id, + req->clk_id, ret); + return CLOCK_CONTROL_STATUS_UNKNOWN; + } + + if (curr_state) { + return CLOCK_CONTROL_STATUS_OFF; + } + + return CLOCK_CONTROL_STATUS_UNKNOWN; +} + +static DEVICE_API(clock_control, tisci_clock_driver_api) = { + .get_rate = tisci_get_rate, + .set_rate = tisci_set_rate, + .get_status = tisci_get_status +}; + +#define TI_K2G_SCI_CLK_INIT(_n) \ + DEVICE_DT_INST_DEFINE(_n, NULL, NULL, NULL, NULL, PRE_KERNEL_1, \ + CONFIG_CLOCK_CONTROL_INIT_PRIORITY, &tisci_clock_driver_api); + +DT_INST_FOREACH_STATUS_OKAY(TI_K2G_SCI_CLK_INIT) diff --git a/dts/bindings/clock/ti,k2g-sci-clk.yaml b/dts/bindings/clock/ti,k2g-sci-clk.yaml new file mode 100644 index 0000000000000..e7042d63a6fee --- /dev/null +++ b/dts/bindings/clock/ti,k2g-sci-clk.yaml @@ -0,0 +1,22 @@ +# Copyright 2025 Texas Instruments Incorporated. +# SPDX-License-Identifier: Apache-2.0 + +description: TI-SCI clock controller + +compatible: "ti,k2g-sci-clk" + +include: + - clock-controller.yaml + - base.yaml + +properties: + "#clock-cells": + type: int + required: true + description: > + Number of cells required to specify a clock provided by this controller. + const: 2 + +clock-cells: + - devid + - clkid diff --git a/include/zephyr/drivers/clock_control/tisci_clock_control.h b/include/zephyr/drivers/clock_control/tisci_clock_control.h new file mode 100644 index 0000000000000..f9457c25875bc --- /dev/null +++ b/include/zephyr/drivers/clock_control/tisci_clock_control.h @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2025 Texas Instruments + * + * SPDX-License-Identifier: Apache-2.0 + */ +#ifndef ZEPHYR_INCLUDE_DRIVERS_CLOCK_CONTROL_TISCI_CLOCK_CONTROL_H_ +#define ZEPHYR_INCLUDE_DRIVERS_CLOCK_CONTROL_TISCI_CLOCK_CONTROL_H_ + +#include + +/** + * @struct tisci_clock_config + * @brief Clock configuration structure + * + * This structure is used to define the configuration for a clock, including + * the device ID and clock ID. + * + * @param tisci_clock_config::dev_id + * Device ID associated with the clock. + * + * @param tisci_clock_config::clk_id + * Clock ID within the device. + */ +struct tisci_clock_config { + uint32_t dev_id; + uint32_t clk_id; +}; + +#define TISCI_GET_CLOCK(node_id) DEVICE_DT_GET(DT_PHANDLE(node_id, clocks)) + +#define TISCI_GET_CLOCK_DETAILS(node_id) \ + { \ + .dev_id = DT_CLOCKS_CELL(node_id, devid), \ + .clk_id = DT_CLOCKS_CELL(node_id, clkid) \ + } + +#define TISCI_GET_CLOCK_BY_INST(inst) TISCI_GET_CLOCK(DT_DRV_INST(inst)) + +#define TISCI_GET_CLOCK_DETAILS_BY_INST(DT_DRV_INST) TISCI_GET_CLOCK_DETAILS(DT_DRV_INST(inst)) + +#endif