blob: 7032c7b380d767e8834d0aff2a127772ad71ea74 [file]
/*
* 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);
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)