1 /*
2 * Copyright 2024 NXP
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 #include <zephyr/drivers/firmware/scmi/clk.h>
8 #include <zephyr/drivers/clock_control.h>
9 #include <zephyr/logging/log.h>
10
11 LOG_MODULE_REGISTER(arm_scmi_clock);
12
13 #define DT_DRV_COMPAT arm_scmi_clock
14
15 struct scmi_clock_data {
16 uint32_t clk_num;
17 };
18
scmi_clock_on_off(const struct device * dev,clock_control_subsys_t clk,bool on)19 static int scmi_clock_on_off(const struct device *dev,
20 clock_control_subsys_t clk, bool on)
21 {
22 struct scmi_clock_data *data;
23 struct scmi_protocol *proto;
24 uint32_t clk_id;
25 struct scmi_clock_config cfg;
26
27 proto = dev->data;
28 data = proto->data;
29 clk_id = POINTER_TO_UINT(clk);
30
31 if (clk_id >= data->clk_num) {
32 return -EINVAL;
33 }
34
35 memset(&cfg, 0, sizeof(cfg));
36
37 cfg.attributes = SCMI_CLK_CONFIG_ENABLE_DISABLE(on);
38 cfg.clk_id = clk_id;
39
40 return scmi_clock_config_set(proto, &cfg);
41 }
42
scmi_clock_on(const struct device * dev,clock_control_subsys_t clk)43 static int scmi_clock_on(const struct device *dev, clock_control_subsys_t clk)
44 {
45 return scmi_clock_on_off(dev, clk, true);
46 }
47
scmi_clock_off(const struct device * dev,clock_control_subsys_t clk)48 static int scmi_clock_off(const struct device *dev, clock_control_subsys_t clk)
49 {
50 return scmi_clock_on_off(dev, clk, false);
51 }
52
scmi_clock_get_rate(const struct device * dev,clock_control_subsys_t clk,uint32_t * rate)53 static int scmi_clock_get_rate(const struct device *dev,
54 clock_control_subsys_t clk, uint32_t *rate)
55 {
56 struct scmi_clock_data *data;
57 struct scmi_protocol *proto;
58 uint32_t clk_id;
59
60 proto = dev->data;
61 data = proto->data;
62 clk_id = POINTER_TO_UINT(clk);
63
64 if (clk_id >= data->clk_num) {
65 return -EINVAL;
66 }
67
68 return scmi_clock_rate_get(proto, clk_id, rate);
69 }
70
71 static DEVICE_API(clock_control, scmi_clock_api) = {
72 .on = scmi_clock_on,
73 .off = scmi_clock_off,
74 .get_rate = scmi_clock_get_rate,
75 };
76
scmi_clock_init(const struct device * dev)77 static int scmi_clock_init(const struct device *dev)
78 {
79 struct scmi_protocol *proto;
80 struct scmi_clock_data *data;
81 int ret;
82 uint32_t attributes;
83
84 proto = dev->data;
85 data = proto->data;
86
87 ret = scmi_clock_protocol_attributes(proto, &attributes);
88 if (ret < 0) {
89 LOG_ERR("failed to fetch clock attributes: %d", ret);
90 return ret;
91 }
92
93 data->clk_num = SCMI_CLK_ATTRIBUTES_CLK_NUM(attributes);
94
95 return 0;
96 }
97
98 static struct scmi_clock_data data;
99
100 DT_INST_SCMI_PROTOCOL_DEFINE(0, &scmi_clock_init, NULL, &data, NULL,
101 PRE_KERNEL_1, CONFIG_CLOCK_CONTROL_INIT_PRIORITY,
102 &scmi_clock_api);
103