xref: /rk3399_ARM-atf/drivers/nxp/clk/s32cc/s32cc_clk_drv.c (revision d9373519873b11cf7d9cad57742272c80d8967e7)
13a580e9eSGhennadi Procopciuc /*
23a580e9eSGhennadi Procopciuc  * Copyright 2024 NXP
33a580e9eSGhennadi Procopciuc  *
43a580e9eSGhennadi Procopciuc  * SPDX-License-Identifier: BSD-3-Clause
53a580e9eSGhennadi Procopciuc  */
63a580e9eSGhennadi Procopciuc #include <errno.h>
73a580e9eSGhennadi Procopciuc 
8*d9373519SGhennadi Procopciuc #include <common/debug.h>
93a580e9eSGhennadi Procopciuc #include <drivers/clk.h>
10*d9373519SGhennadi Procopciuc #include <s32cc-clk-modules.h>
11*d9373519SGhennadi Procopciuc #include <s32cc-clk-utils.h>
12*d9373519SGhennadi Procopciuc 
13*d9373519SGhennadi Procopciuc #define MAX_STACK_DEPTH		(15U)
14*d9373519SGhennadi Procopciuc 
15*d9373519SGhennadi Procopciuc static int update_stack_depth(unsigned int *depth)
16*d9373519SGhennadi Procopciuc {
17*d9373519SGhennadi Procopciuc 	if (*depth == 0U) {
18*d9373519SGhennadi Procopciuc 		return -ENOMEM;
19*d9373519SGhennadi Procopciuc 	}
20*d9373519SGhennadi Procopciuc 
21*d9373519SGhennadi Procopciuc 	(*depth)--;
22*d9373519SGhennadi Procopciuc 	return 0;
23*d9373519SGhennadi Procopciuc }
243a580e9eSGhennadi Procopciuc 
253a580e9eSGhennadi Procopciuc static int s32cc_clk_enable(unsigned long id)
263a580e9eSGhennadi Procopciuc {
273a580e9eSGhennadi Procopciuc 	return -ENOTSUP;
283a580e9eSGhennadi Procopciuc }
293a580e9eSGhennadi Procopciuc 
303a580e9eSGhennadi Procopciuc static void s32cc_clk_disable(unsigned long id)
313a580e9eSGhennadi Procopciuc {
323a580e9eSGhennadi Procopciuc }
333a580e9eSGhennadi Procopciuc 
343a580e9eSGhennadi Procopciuc static bool s32cc_clk_is_enabled(unsigned long id)
353a580e9eSGhennadi Procopciuc {
363a580e9eSGhennadi Procopciuc 	return false;
373a580e9eSGhennadi Procopciuc }
383a580e9eSGhennadi Procopciuc 
393a580e9eSGhennadi Procopciuc static unsigned long s32cc_clk_get_rate(unsigned long id)
403a580e9eSGhennadi Procopciuc {
413a580e9eSGhennadi Procopciuc 	return 0;
423a580e9eSGhennadi Procopciuc }
433a580e9eSGhennadi Procopciuc 
44*d9373519SGhennadi Procopciuc static int set_module_rate(const struct s32cc_clk_obj *module,
45*d9373519SGhennadi Procopciuc 			   unsigned long rate, unsigned long *orate,
46*d9373519SGhennadi Procopciuc 			   unsigned int *depth);
47*d9373519SGhennadi Procopciuc 
48*d9373519SGhennadi Procopciuc static int set_osc_freq(const struct s32cc_clk_obj *module, unsigned long rate,
49*d9373519SGhennadi Procopciuc 			unsigned long *orate, unsigned int *depth)
50*d9373519SGhennadi Procopciuc {
51*d9373519SGhennadi Procopciuc 	struct s32cc_osc *osc = s32cc_obj2osc(module);
52*d9373519SGhennadi Procopciuc 	int ret;
53*d9373519SGhennadi Procopciuc 
54*d9373519SGhennadi Procopciuc 	ret = update_stack_depth(depth);
55*d9373519SGhennadi Procopciuc 	if (ret != 0) {
56*d9373519SGhennadi Procopciuc 		return ret;
57*d9373519SGhennadi Procopciuc 	}
58*d9373519SGhennadi Procopciuc 
59*d9373519SGhennadi Procopciuc 	if ((osc->freq != 0UL) && (rate != osc->freq)) {
60*d9373519SGhennadi Procopciuc 		ERROR("Already initialized oscillator. freq = %lu\n",
61*d9373519SGhennadi Procopciuc 		      osc->freq);
62*d9373519SGhennadi Procopciuc 		return -EINVAL;
63*d9373519SGhennadi Procopciuc 	}
64*d9373519SGhennadi Procopciuc 
65*d9373519SGhennadi Procopciuc 	osc->freq = rate;
66*d9373519SGhennadi Procopciuc 	*orate = osc->freq;
67*d9373519SGhennadi Procopciuc 
68*d9373519SGhennadi Procopciuc 	return 0;
69*d9373519SGhennadi Procopciuc }
70*d9373519SGhennadi Procopciuc 
71*d9373519SGhennadi Procopciuc static int set_clk_freq(const struct s32cc_clk_obj *module, unsigned long rate,
72*d9373519SGhennadi Procopciuc 			unsigned long *orate, unsigned int *depth)
73*d9373519SGhennadi Procopciuc {
74*d9373519SGhennadi Procopciuc 	const struct s32cc_clk *clk = s32cc_obj2clk(module);
75*d9373519SGhennadi Procopciuc 	int ret;
76*d9373519SGhennadi Procopciuc 
77*d9373519SGhennadi Procopciuc 	ret = update_stack_depth(depth);
78*d9373519SGhennadi Procopciuc 	if (ret != 0) {
79*d9373519SGhennadi Procopciuc 		return ret;
80*d9373519SGhennadi Procopciuc 	}
81*d9373519SGhennadi Procopciuc 
82*d9373519SGhennadi Procopciuc 	if ((clk->min_freq != 0UL) && (clk->max_freq != 0UL) &&
83*d9373519SGhennadi Procopciuc 	    ((rate < clk->min_freq) || (rate > clk->max_freq))) {
84*d9373519SGhennadi Procopciuc 		ERROR("%lu frequency is out of the allowed range: [%lu:%lu]\n",
85*d9373519SGhennadi Procopciuc 		      rate, clk->min_freq, clk->max_freq);
86*d9373519SGhennadi Procopciuc 		return -EINVAL;
87*d9373519SGhennadi Procopciuc 	}
88*d9373519SGhennadi Procopciuc 
89*d9373519SGhennadi Procopciuc 	if (clk->module != NULL) {
90*d9373519SGhennadi Procopciuc 		return set_module_rate(clk->module, rate, orate, depth);
91*d9373519SGhennadi Procopciuc 	}
92*d9373519SGhennadi Procopciuc 
93*d9373519SGhennadi Procopciuc 	if (clk->pclock != NULL) {
94*d9373519SGhennadi Procopciuc 		return set_clk_freq(&clk->pclock->desc, rate, orate, depth);
95*d9373519SGhennadi Procopciuc 	}
96*d9373519SGhennadi Procopciuc 
97*d9373519SGhennadi Procopciuc 	return -EINVAL;
98*d9373519SGhennadi Procopciuc }
99*d9373519SGhennadi Procopciuc 
100*d9373519SGhennadi Procopciuc static int set_module_rate(const struct s32cc_clk_obj *module,
101*d9373519SGhennadi Procopciuc 			   unsigned long rate, unsigned long *orate,
102*d9373519SGhennadi Procopciuc 			   unsigned int *depth)
103*d9373519SGhennadi Procopciuc {
104*d9373519SGhennadi Procopciuc 	int ret = 0;
105*d9373519SGhennadi Procopciuc 
106*d9373519SGhennadi Procopciuc 	ret = update_stack_depth(depth);
107*d9373519SGhennadi Procopciuc 	if (ret != 0) {
108*d9373519SGhennadi Procopciuc 		return ret;
109*d9373519SGhennadi Procopciuc 	}
110*d9373519SGhennadi Procopciuc 
111*d9373519SGhennadi Procopciuc 	switch (module->type) {
112*d9373519SGhennadi Procopciuc 	case s32cc_clk_t:
113*d9373519SGhennadi Procopciuc 		ret = set_clk_freq(module, rate, orate, depth);
114*d9373519SGhennadi Procopciuc 		break;
115*d9373519SGhennadi Procopciuc 	case s32cc_osc_t:
116*d9373519SGhennadi Procopciuc 		ret = set_osc_freq(module, rate, orate, depth);
117*d9373519SGhennadi Procopciuc 		break;
118*d9373519SGhennadi Procopciuc 	default:
119*d9373519SGhennadi Procopciuc 		ret = -EINVAL;
120*d9373519SGhennadi Procopciuc 		break;
121*d9373519SGhennadi Procopciuc 	}
122*d9373519SGhennadi Procopciuc 
123*d9373519SGhennadi Procopciuc 	return ret;
124*d9373519SGhennadi Procopciuc }
125*d9373519SGhennadi Procopciuc 
1263a580e9eSGhennadi Procopciuc static int s32cc_clk_set_rate(unsigned long id, unsigned long rate,
1273a580e9eSGhennadi Procopciuc 			      unsigned long *orate)
1283a580e9eSGhennadi Procopciuc {
129*d9373519SGhennadi Procopciuc 	unsigned int depth = MAX_STACK_DEPTH;
130*d9373519SGhennadi Procopciuc 	const struct s32cc_clk *clk;
131*d9373519SGhennadi Procopciuc 	int ret;
132*d9373519SGhennadi Procopciuc 
133*d9373519SGhennadi Procopciuc 	clk = s32cc_get_arch_clk(id);
134*d9373519SGhennadi Procopciuc 	if (clk == NULL) {
135*d9373519SGhennadi Procopciuc 		return -EINVAL;
136*d9373519SGhennadi Procopciuc 	}
137*d9373519SGhennadi Procopciuc 
138*d9373519SGhennadi Procopciuc 	ret = set_module_rate(&clk->desc, rate, orate, &depth);
139*d9373519SGhennadi Procopciuc 	if (ret != 0) {
140*d9373519SGhennadi Procopciuc 		ERROR("Failed to set frequency (%lu MHz) for clock %lu\n",
141*d9373519SGhennadi Procopciuc 		      rate, id);
142*d9373519SGhennadi Procopciuc 	}
143*d9373519SGhennadi Procopciuc 
144*d9373519SGhennadi Procopciuc 	return ret;
1453a580e9eSGhennadi Procopciuc }
1463a580e9eSGhennadi Procopciuc 
1473a580e9eSGhennadi Procopciuc static int s32cc_clk_get_parent(unsigned long id)
1483a580e9eSGhennadi Procopciuc {
1493a580e9eSGhennadi Procopciuc 	return -ENOTSUP;
1503a580e9eSGhennadi Procopciuc }
1513a580e9eSGhennadi Procopciuc 
1523a580e9eSGhennadi Procopciuc static int s32cc_clk_set_parent(unsigned long id, unsigned long parent_id)
1533a580e9eSGhennadi Procopciuc {
1543a580e9eSGhennadi Procopciuc 	return -ENOTSUP;
1553a580e9eSGhennadi Procopciuc }
1563a580e9eSGhennadi Procopciuc 
1573a580e9eSGhennadi Procopciuc void s32cc_clk_register_drv(void)
1583a580e9eSGhennadi Procopciuc {
1593a580e9eSGhennadi Procopciuc 	static const struct clk_ops s32cc_clk_ops = {
1603a580e9eSGhennadi Procopciuc 		.enable		= s32cc_clk_enable,
1613a580e9eSGhennadi Procopciuc 		.disable	= s32cc_clk_disable,
1623a580e9eSGhennadi Procopciuc 		.is_enabled	= s32cc_clk_is_enabled,
1633a580e9eSGhennadi Procopciuc 		.get_rate	= s32cc_clk_get_rate,
1643a580e9eSGhennadi Procopciuc 		.set_rate	= s32cc_clk_set_rate,
1653a580e9eSGhennadi Procopciuc 		.get_parent	= s32cc_clk_get_parent,
1663a580e9eSGhennadi Procopciuc 		.set_parent	= s32cc_clk_set_parent,
1673a580e9eSGhennadi Procopciuc 	};
1683a580e9eSGhennadi Procopciuc 
1693a580e9eSGhennadi Procopciuc 	clk_register(&s32cc_clk_ops);
1703a580e9eSGhennadi Procopciuc }
1713a580e9eSGhennadi Procopciuc 
172