1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
|
// SPDX-License-Identifier: GPL-2.0+
/*
* Copyright 2025 NXP
*
* Peng Fan <peng.fan@nxp.com>
*/
#include <dm/uclass.h>
#include <scmi_agent.h>
int imx_clk_scmi_enable(u32 clock_id, bool enable)
{
struct scmi_clk_state_in in = {
.clock_id = clock_id,
.attributes = (enable) ? 1 : 0,
};
struct scmi_clk_state_out out;
struct scmi_msg msg = SCMI_MSG_IN(SCMI_PROTOCOL_ID_CLOCK,
SCMI_CLOCK_CONFIG_SET,
in, out);
int ret;
struct udevice *dev;
ret = uclass_get_device_by_name(UCLASS_CLK, "protocol@14", &dev);
if (ret)
return ret;
ret = devm_scmi_process_msg(dev, &msg);
if (ret)
return ret;
return scmi_to_linux_errno(out.status);
}
ulong imx_clk_scmi_set_rate(u32 clock_id, ulong rate)
{
struct scmi_clk_rate_set_in in = {
.clock_id = clock_id,
.flags = SCMI_CLK_RATE_ROUND_CLOSEST,
.rate_lsb = (u32)rate,
.rate_msb = (u32)((u64)rate >> 32),
};
struct scmi_clk_rate_set_out out;
struct scmi_msg msg = SCMI_MSG_IN(SCMI_PROTOCOL_ID_CLOCK,
SCMI_CLOCK_RATE_SET,
in, out);
int ret;
struct udevice *dev;
ret = uclass_get_device_by_name(UCLASS_CLK, "protocol@14", &dev);
if (ret)
return ret;
ret = devm_scmi_process_msg(dev, &msg);
if (ret < 0)
return ret;
ret = scmi_to_linux_errno(out.status);
if (ret < 0)
return ret;
struct scmi_clk_rate_get_in in_rate = {
.clock_id = clock_id,
};
struct scmi_clk_rate_get_out out_rate;
msg = SCMI_MSG_IN(SCMI_PROTOCOL_ID_CLOCK, SCMI_CLOCK_RATE_GET, in_rate, out_rate);
ret = devm_scmi_process_msg(dev, &msg);
if (ret < 0)
return ret;
ret = scmi_to_linux_errno(out_rate.status);
if (ret < 0)
return ret;
return (ulong)(((u64)out_rate.rate_msb << 32) | out_rate.rate_lsb);
}
ulong imx_clk_scmi_get_rate(u32 clock_id)
{
struct scmi_clk_rate_get_in in = {
.clock_id = clock_id,
};
struct scmi_clk_rate_get_out out;
struct scmi_msg msg = SCMI_MSG_IN(SCMI_PROTOCOL_ID_CLOCK,
SCMI_CLOCK_RATE_GET,
in, out);
int ret;
struct udevice *dev;
ret = uclass_get_device_by_name(UCLASS_CLK, "protocol@14", &dev);
if (ret)
return ret;
ret = devm_scmi_process_msg(dev, &msg);
if (ret < 0)
return ret;
ret = scmi_to_linux_errno(out.status);
if (ret < 0)
return ret;
return (ulong)(((u64)out.rate_msb << 32) | out.rate_lsb);
}
int imx_clk_scmi_set_parent(u32 clock_id, u32 parent_id)
{
struct scmi_clk_parent_set_in in = {
.clock_id = clock_id,
.parent_clk = parent_id,
};
struct scmi_clk_parent_set_out out;
struct scmi_msg msg = SCMI_MSG_IN(SCMI_PROTOCOL_ID_CLOCK,
SCMI_CLOCK_PARENT_SET,
in, out);
int ret;
struct udevice *dev;
ret = uclass_get_device_by_name(UCLASS_CLK, "protocol@14", &dev);
if (ret)
return ret;
ret = devm_scmi_process_msg(dev, &msg);
if (ret < 0)
return ret;
ret = scmi_to_linux_errno(out.status);
if (ret < 0 && ret != -EACCES)
printf("%s: %d, clock_id %u\n", __func__, ret, clock_id);
return ret;
}
|