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