1 /*
2 * Copyright 2023 NXP
3 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 */
6
7 #include <stdio.h>
8 #include "sm_platform.h"
9 #include "sm_clock.h"
10 #include "scmi_clock.h"
11
12 /*******************************************************************************
13 * Definitions
14 ******************************************************************************/
15
16 /*******************************************************************************
17 * Variables
18 ******************************************************************************/
19
20 /*!
21 * @brief Configure Root Clock
22 *
23 * @param sm_clk
24 */
SM_CLOCK_SetRootClock(sm_clock_t * sm_clk)25 void SM_CLOCK_SetRootClock(sm_clock_t *sm_clk)
26 {
27 scmi_clock_rate_t rate = {0, 0};
28 uint32_t channel = sm_clk->channel;
29 uint32_t clockId = sm_clk->clk_id;
30 uint32_t pclkId = sm_clk->pclk_id;
31 uint32_t div = sm_clk->div;
32 uint32_t attributes = sm_clk->attributes;
33 uint32_t oemConfigVal = sm_clk->oem_config_val;
34 uint32_t flags = sm_clk->flags;
35 uint32_t oldPclkId = 0; /* parent clock id */
36 uint64_t srcRate, rootRate;
37 int32_t status = -1;
38
39 if (div == 0)
40 return;
41
42 status = SCMI_ClockParentGet(channel, clockId, &oldPclkId);
43 if (status != 0)
44 return;
45
46 if (oldPclkId != pclkId)
47 {
48 status = SCMI_ClockParentSet(channel, clockId, pclkId);
49 if (status != 0)
50 return;
51 }
52 status = SCMI_ClockRateGet(channel, pclkId, &rate);
53 if (status != 0)
54 return;
55
56 srcRate = rate.upper;
57 srcRate = (srcRate << 32);
58 srcRate |= rate.lower;
59
60 rootRate = srcRate / div;
61
62 rate.lower = rootRate & SM_CLOCK_RATE_MASK;
63 rate.upper = (rootRate >> 32) & SM_CLOCK_RATE_MASK;
64
65 status = SCMI_ClockRateSet(channel, clockId, flags, rate);
66 if (status != 0)
67 return;
68 status = SCMI_ClockConfigSet(channel, clockId, attributes, oemConfigVal);
69 if (status != 0)
70 return;
71
72 return;
73 }
74
75 /*!
76 * @brief Enable/Disable Root Clock
77 *
78 * @param sm_clk
79 */
SM_CLOCK_EnableRootClock(sm_clock_t * sm_clk)80 void SM_CLOCK_EnableRootClock(sm_clock_t *sm_clk)
81 {
82 uint32_t channel = sm_clk->channel;
83 uint32_t clockId = sm_clk->clk_id;
84 uint32_t attributes = sm_clk->attributes;
85 uint32_t oemConfigVal = sm_clk->oem_config_val;
86 int32_t status = -1;
87
88 status = SCMI_ClockConfigSet(channel, clockId, attributes, oemConfigVal);
89 if (status != 0)
90 return;
91
92 return;
93 }
94
SM_CLOCK_GetIpFreq(sm_clock_t * sm_clk)95 uint64_t SM_CLOCK_GetIpFreq(sm_clock_t *sm_clk)
96 {
97 scmi_clock_rate_t rate = {0, 0};
98 uint32_t channel = sm_clk->channel;
99 uint32_t clockId = sm_clk->clk_id;
100 uint32_t pclkId = sm_clk->pclk_id;
101 int32_t status = 0;
102
103 status = SCMI_ClockParentGet(channel, clockId, &pclkId);
104 if (status != 0)
105 return 0;
106
107 status = SCMI_ClockRateGet(channel, clockId, &rate);
108 if (status != 0)
109 return 0;
110
111 return rate.lower | ((uint64_t)(rate.upper) << 32U);
112 }
113
114 /*!
115 * @brief Configure PLL Clock
116 *
117 * @param sm_clk
118 */
SM_CLOCK_SetPllClock(sm_clock_t * sm_clk)119 void SM_CLOCK_SetPllClock(sm_clock_t *sm_clk)
120 {
121 scmi_clock_rate_t rate = {0, 0};
122 uint32_t channel = sm_clk->channel;
123 uint32_t clockId = sm_clk->clk_id;
124 uint32_t flags = sm_clk->flags;
125 int32_t status = -1;
126
127 rate.lower = sm_clk->ratel;
128 rate.upper = sm_clk->rateu;
129
130 status = SCMI_ClockRateSet(channel, clockId, flags, rate);
131 if (status != 0)
132 return;
133
134 return;
135 }
136
SM_CLOCK_GetSourceFreq(sm_clock_t * sm_clk)137 uint64_t SM_CLOCK_GetSourceFreq(sm_clock_t *sm_clk)
138 {
139 scmi_clock_rate_t rate = {0, 0};
140 uint32_t channel = sm_clk->channel;
141 uint32_t clockId = sm_clk->clk_id;
142 int32_t status = -1;
143
144 status = SCMI_ClockRateGet(channel, clockId, &rate);
145 if (status != 0)
146 return 0ULL;
147
148 return rate.lower | ((uint64_t)(rate.upper) << 32U);
149 }
150