Primary Git Repository for the Zephyr Project. Zephyr is a new generation, scalable, optimized, secure RTOS for multiple hardware architectures.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

124 lines
2.7 KiB

/*
* Copyright 2024-2025 NXP
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <zephyr/drivers/firmware/scmi/clk.h>
#include <zephyr/drivers/clock_control.h>
#include <zephyr/logging/log.h>
LOG_MODULE_REGISTER(arm_scmi_clock);
#define DT_DRV_COMPAT arm_scmi_clock
struct scmi_clock_data {
uint32_t clk_num;
};
static int scmi_clock_on_off(const struct device *dev,
clock_control_subsys_t clk, bool on)
{
struct scmi_clock_data *data;
struct scmi_protocol *proto;
uint32_t clk_id;
struct scmi_clock_config cfg;
proto = dev->data;
data = proto->data;
clk_id = POINTER_TO_UINT(clk);
if (clk_id >= data->clk_num) {
return -EINVAL;
}
memset(&cfg, 0, sizeof(cfg));
cfg.attributes = SCMI_CLK_CONFIG_ENABLE_DISABLE(on);
cfg.clk_id = clk_id;
return scmi_clock_config_set(proto, &cfg);
}
static int scmi_clock_on(const struct device *dev, clock_control_subsys_t clk)
{
return scmi_clock_on_off(dev, clk, true);
}
static int scmi_clock_off(const struct device *dev, clock_control_subsys_t clk)
{
return scmi_clock_on_off(dev, clk, false);
}
static int scmi_clock_get_rate(const struct device *dev,
clock_control_subsys_t clk, uint32_t *rate)
{
struct scmi_clock_data *data;
struct scmi_protocol *proto;
uint32_t clk_id;
proto = dev->data;
data = proto->data;
clk_id = POINTER_TO_UINT(clk);
if (clk_id >= data->clk_num) {
return -EINVAL;
}
return scmi_clock_rate_get(proto, clk_id, rate);
}
static int scmi_clock_set_rate(const struct device *dev,
clock_control_subsys_t clk,
clock_control_subsys_rate_t rate)
{
struct scmi_clock_data *data;
struct scmi_protocol *proto;
struct scmi_clock_rate_config cfg = {0};
proto = dev->data;
data = proto->data;
cfg.flags = SCMI_CLK_RATE_SET_FLAGS_ROUNDS_AUTO;
cfg.clk_id = POINTER_TO_UINT(clk);
cfg.rate[0] = (uintptr_t)rate;
if (cfg.clk_id >= data->clk_num) {
return -EINVAL;
}
return scmi_clock_rate_set(proto, &cfg);
}
static DEVICE_API(clock_control, scmi_clock_api) = {
.on = scmi_clock_on,
.off = scmi_clock_off,
.get_rate = scmi_clock_get_rate,
.set_rate = scmi_clock_set_rate,
};
static int scmi_clock_init(const struct device *dev)
{
struct scmi_protocol *proto;
struct scmi_clock_data *data;
int ret;
uint32_t attributes;
proto = dev->data;
data = proto->data;
ret = scmi_clock_protocol_attributes(proto, &attributes);
if (ret < 0) {
LOG_ERR("failed to fetch clock attributes: %d", ret);
return ret;
}
data->clk_num = SCMI_CLK_ATTRIBUTES_CLK_NUM(attributes);
return 0;
}
static struct scmi_clock_data data;
DT_INST_SCMI_PROTOCOL_DEFINE(0, &scmi_clock_init, NULL, &data, NULL,
PRE_KERNEL_1, CONFIG_CLOCK_CONTROL_INIT_PRIORITY,
&scmi_clock_api);