From a5248750e6f1cdc2f007affa0fdcbfcc8a25d896 Mon Sep 17 00:00:00 2001 From: Dave Joseph Date: Tue, 20 May 2025 14:19:28 +0530 Subject: [PATCH] drivers: firmware: Clock control TISCI driver support Support added for clock control using TISCI for devices using the binding ti,k2g-sci-clk. This driver relies on the TISCI layer to make calls to the DMSC core to set and get the clock rate and retrieve clock status. Signed-off-by: Dave Joseph --- drivers/clock_control/CMakeLists.txt | 15 ++-- drivers/clock_control/Kconfig | 2 + drivers/clock_control/Kconfig.tisci | 9 ++ drivers/clock_control/clock_control_tisci.c | 90 +++++++++++++++++++ dts/bindings/clock/ti,k2g-sci-clk.yaml | 22 +++++ .../clock_control/tisci_clock_control.h | 39 ++++++++ 6 files changed, 171 insertions(+), 6 deletions(-) create mode 100644 drivers/clock_control/Kconfig.tisci create mode 100644 drivers/clock_control/clock_control_tisci.c create mode 100644 dts/bindings/clock/ti,k2g-sci-clk.yaml create mode 100644 include/zephyr/drivers/clock_control/tisci_clock_control.h diff --git a/drivers/clock_control/CMakeLists.txt b/drivers/clock_control/CMakeLists.txt index bec53ab1ba5c7..43c5af321a1b0 100644 --- a/drivers/clock_control/CMakeLists.txt +++ b/drivers/clock_control/CMakeLists.txt @@ -49,12 +49,15 @@ zephyr_library_sources_ifdef(CONFIG_CLOCK_CONTROL_NRF_HSFLL_GLOBAL clock_cont zephyr_library_sources_ifdef(CONFIG_CLOCK_CONTROL_RTS5912_SCCON clock_control_rts5912_sccon.c) zephyr_library_sources_ifdef(CONFIG_CLOCK_CONTROL_NRFS_AUDIOPLL clock_control_nrfs_audiopll.c) zephyr_library_sources_ifdef(CONFIG_CLOCK_CONTROL_IT51XXX clock_control_it51xxx.c) -zephyr_library_sources_ifdef(CONFIG_CLOCK_CONTROL_NRF2_COMMON clock_control_nrf2_common.c) -zephyr_library_sources_ifdef(CONFIG_CLOCK_CONTROL_NRF_FLL16M clock_control_nrf_fll16m.c) -zephyr_library_sources_ifdef(CONFIG_CLOCK_CONTROL_NRF54H_HFXO clock_control_nrf54h_hfxo.c) -zephyr_library_sources_ifdef(CONFIG_CLOCK_CONTROL_NRF_HSFLL_LOCAL clock_control_nrf_hsfll_local.c) -zephyr_library_sources_ifdef(CONFIG_CLOCK_CONTROL_NRF_LFCLK clock_control_nrf_lfclk.c) -zephyr_library_sources_ifdef(CONFIG_CLOCK_CONTROL_BOUFFALOLAB_BL60X clock_control_bl60x.c) +zephyr_library_sources_ifdef(CONFIG_CLOCK_CONTROL_TISCI clock_control_tisci.c) + +if(CONFIG_CLOCK_CONTROL_NRF2) + zephyr_library_sources(clock_control_nrf2_common.c) + zephyr_library_sources(clock_control_nrf2_fll16m.c) + zephyr_library_sources(clock_control_nrf2_hfxo.c) + zephyr_library_sources(clock_control_nrf2_hsfll.c) + zephyr_library_sources(clock_control_nrf2_lfclk.c) +endif() 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 82fa462ee717f..e0e5b85674cac 100644 --- a/drivers/clock_control/Kconfig +++ b/drivers/clock_control/Kconfig @@ -116,4 +116,6 @@ source "drivers/clock_control/Kconfig.wch_rcc" source "drivers/clock_control/Kconfig.it51xxx" +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..c271ba96afe63 --- /dev/null +++ b/drivers/clock_control/clock_control_tisci.c @@ -0,0 +1,90 @@ +/* + * 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); + +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 = 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 = 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 inline enum clock_control_status tisci_get_status(const struct device *dev, + clock_control_subsys_t sys) +{ + enum clock_control_status state = CLOCK_CONTROL_STATUS_UNKNOWN; + 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 state; +} + +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..400ea735f4307 --- /dev/null +++ b/include/zephyr/drivers/clock_control/tisci_clock_control.h @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2025 Texas Instruments + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef ZEPHYR_DRIVERS_CLOCK_CONTROL_TISCI_CLOCK_CONTROL_H_ +#define ZEPHYR_DRIVERS_CLOCK_CONTROL_TISCI_CLOCK_CONTROL_H_ + +/** + * @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. + */ +#include +struct tisci_clock_config { + uint32_t dev_id; + uint32_t clk_id; +}; + +#define TISCI_GET_CLOCK(_dev) DEVICE_DT_GET(DT_PHANDLE(DT_NODELABEL(_dev), clocks)) + +#define TISCI_GET_CLOCK_DETAILS(_dev) \ + {.dev_id = DT_CLOCKS_CELL(DT_NODELABEL(_dev), devid), \ + .clk_id = DT_CLOCKS_CELL(DT_NODELABEL(_dev), clkid)} + +#define TISCI_GET_CLOCK_BY_INST(inst) DEVICE_DT_INST_GET(inst) + +#define TISCI_GET_CLOCK_DETAILS_BY_INST(inst) \ + {.dev_id = DT_INST_CLOCKS_CELL(inst, devid), .clk_id = DT_INST_CLOCKS_CELL(inst, clkid)} +#endif