Skip to content

drivers: firmware: Clock control TISCI driver support #90216

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
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
15 changes: 9 additions & 6 deletions drivers/clock_control/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Copy link
Contributor

Choose a reason for hiding this comment

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

The above look unrelated, seems like you had some rebase issue going on here.

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)
Expand Down
2 changes: 2 additions & 0 deletions drivers/clock_control/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -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
9 changes: 9 additions & 0 deletions drivers/clock_control/Kconfig.tisci
Original file line number Diff line number Diff line change
@@ -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.
90 changes: 90 additions & 0 deletions drivers/clock_control/clock_control_tisci.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
/*
* Copyright (c) 2025, Texas Instruments
*
* SPDX-License-Identifier: Apache-2.0
*/

#define DT_DRV_COMPAT ti_k2g_sci_clk

#include <zephyr/device.h>
#include <zephyr/drivers/firmware/tisci/tisci.h>
#include <zephyr/drivers/clock_control.h>
#include <zephyr/drivers/clock_control/tisci_clock_control.h>
#include <zephyr/devicetree.h>
#include <zephyr/logging/log.h>

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);
Copy link
Contributor

Choose a reason for hiding this comment

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

Declare ret, then a newline, then assign to it, then no newline after between the assignment and the checking of ret. Same for tisci_set_rate(), make them look like you did in tisci_get_status().


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,
Copy link
Contributor

Choose a reason for hiding this comment

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

inline?

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;
Copy link
Contributor

Choose a reason for hiding this comment

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

return CLOCK_CONTROL_STATUS_UNKNOWN; here, then just drop the state variable.

}

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)
22 changes: 22 additions & 0 deletions dts/bindings/clock/ti,k2g-sci-clk.yaml
Original file line number Diff line number Diff line change
@@ -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
39 changes: 39 additions & 0 deletions include/zephyr/drivers/clock_control/tisci_clock_control.h
Original file line number Diff line number Diff line change
@@ -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 <stdint.h>
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))
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
#define TISCI_GET_CLOCK(_dev) DEVICE_DT_GET(DT_PHANDLE(DT_NODELABEL(_dev), clocks))
#define TISCI_GET_CLOCK(node_id) DEVICE_DT_GET(DT_PHANDLE(node_id, clocks))

I feel we should follow the devicetree.h convention and use node_id instead of manually using DT_NODELABEL here


#define TISCI_GET_CLOCK_DETAILS(_dev) \
{.dev_id = DT_CLOCKS_CELL(DT_NODELABEL(_dev), devid), \
.clk_id = DT_CLOCKS_CELL(DT_NODELABEL(_dev), clkid)}

Comment on lines +31 to +34
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
#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_DETAILS(node_id) \
{ \
.dev_id = DT_CLOCKS_CELL(node_id, devid), \
.clk_id = DT_CLOCKS_CELL(node_id, clkid), \
}

Copy link
Contributor

Choose a reason for hiding this comment

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

same here

#define TISCI_GET_CLOCK_BY_INST(inst) DEVICE_DT_INST_GET(inst)
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
#define TISCI_GET_CLOCK_BY_INST(inst) DEVICE_DT_INST_GET(inst)
#define TISCI_GET_CLOCK_BY_INST(inst) TISCI_GET_CLOCK(DT_DRV_INST(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)}
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
{.dev_id = DT_INST_CLOCKS_CELL(inst, devid), .clk_id = DT_INST_CLOCKS_CELL(inst, clkid)}
TISCI_GET_CLOCK_DETAILS(DT_DRV_INST(inst))

#endif
Loading