xref: /rk3399_ARM-atf/drivers/nxp/clk/s32cc/s32cc_clk_drv.c (revision d9373519873b11cf7d9cad57742272c80d8967e7)
1 /*
2  * Copyright 2024 NXP
3  *
4  * SPDX-License-Identifier: BSD-3-Clause
5  */
6 #include <errno.h>
7 
8 #include <common/debug.h>
9 #include <drivers/clk.h>
10 #include <s32cc-clk-modules.h>
11 #include <s32cc-clk-utils.h>
12 
13 #define MAX_STACK_DEPTH		(15U)
14 
15 static int update_stack_depth(unsigned int *depth)
16 {
17 	if (*depth == 0U) {
18 		return -ENOMEM;
19 	}
20 
21 	(*depth)--;
22 	return 0;
23 }
24 
25 static int s32cc_clk_enable(unsigned long id)
26 {
27 	return -ENOTSUP;
28 }
29 
30 static void s32cc_clk_disable(unsigned long id)
31 {
32 }
33 
34 static bool s32cc_clk_is_enabled(unsigned long id)
35 {
36 	return false;
37 }
38 
39 static unsigned long s32cc_clk_get_rate(unsigned long id)
40 {
41 	return 0;
42 }
43 
44 static int set_module_rate(const struct s32cc_clk_obj *module,
45 			   unsigned long rate, unsigned long *orate,
46 			   unsigned int *depth);
47 
48 static int set_osc_freq(const struct s32cc_clk_obj *module, unsigned long rate,
49 			unsigned long *orate, unsigned int *depth)
50 {
51 	struct s32cc_osc *osc = s32cc_obj2osc(module);
52 	int ret;
53 
54 	ret = update_stack_depth(depth);
55 	if (ret != 0) {
56 		return ret;
57 	}
58 
59 	if ((osc->freq != 0UL) && (rate != osc->freq)) {
60 		ERROR("Already initialized oscillator. freq = %lu\n",
61 		      osc->freq);
62 		return -EINVAL;
63 	}
64 
65 	osc->freq = rate;
66 	*orate = osc->freq;
67 
68 	return 0;
69 }
70 
71 static int set_clk_freq(const struct s32cc_clk_obj *module, unsigned long rate,
72 			unsigned long *orate, unsigned int *depth)
73 {
74 	const struct s32cc_clk *clk = s32cc_obj2clk(module);
75 	int ret;
76 
77 	ret = update_stack_depth(depth);
78 	if (ret != 0) {
79 		return ret;
80 	}
81 
82 	if ((clk->min_freq != 0UL) && (clk->max_freq != 0UL) &&
83 	    ((rate < clk->min_freq) || (rate > clk->max_freq))) {
84 		ERROR("%lu frequency is out of the allowed range: [%lu:%lu]\n",
85 		      rate, clk->min_freq, clk->max_freq);
86 		return -EINVAL;
87 	}
88 
89 	if (clk->module != NULL) {
90 		return set_module_rate(clk->module, rate, orate, depth);
91 	}
92 
93 	if (clk->pclock != NULL) {
94 		return set_clk_freq(&clk->pclock->desc, rate, orate, depth);
95 	}
96 
97 	return -EINVAL;
98 }
99 
100 static int set_module_rate(const struct s32cc_clk_obj *module,
101 			   unsigned long rate, unsigned long *orate,
102 			   unsigned int *depth)
103 {
104 	int ret = 0;
105 
106 	ret = update_stack_depth(depth);
107 	if (ret != 0) {
108 		return ret;
109 	}
110 
111 	switch (module->type) {
112 	case s32cc_clk_t:
113 		ret = set_clk_freq(module, rate, orate, depth);
114 		break;
115 	case s32cc_osc_t:
116 		ret = set_osc_freq(module, rate, orate, depth);
117 		break;
118 	default:
119 		ret = -EINVAL;
120 		break;
121 	}
122 
123 	return ret;
124 }
125 
126 static int s32cc_clk_set_rate(unsigned long id, unsigned long rate,
127 			      unsigned long *orate)
128 {
129 	unsigned int depth = MAX_STACK_DEPTH;
130 	const struct s32cc_clk *clk;
131 	int ret;
132 
133 	clk = s32cc_get_arch_clk(id);
134 	if (clk == NULL) {
135 		return -EINVAL;
136 	}
137 
138 	ret = set_module_rate(&clk->desc, rate, orate, &depth);
139 	if (ret != 0) {
140 		ERROR("Failed to set frequency (%lu MHz) for clock %lu\n",
141 		      rate, id);
142 	}
143 
144 	return ret;
145 }
146 
147 static int s32cc_clk_get_parent(unsigned long id)
148 {
149 	return -ENOTSUP;
150 }
151 
152 static int s32cc_clk_set_parent(unsigned long id, unsigned long parent_id)
153 {
154 	return -ENOTSUP;
155 }
156 
157 void s32cc_clk_register_drv(void)
158 {
159 	static const struct clk_ops s32cc_clk_ops = {
160 		.enable		= s32cc_clk_enable,
161 		.disable	= s32cc_clk_disable,
162 		.is_enabled	= s32cc_clk_is_enabled,
163 		.get_rate	= s32cc_clk_get_rate,
164 		.set_rate	= s32cc_clk_set_rate,
165 		.get_parent	= s32cc_clk_get_parent,
166 		.set_parent	= s32cc_clk_set_parent,
167 	};
168 
169 	clk_register(&s32cc_clk_ops);
170 }
171 
172