xref: /optee_os/core/drivers/clk/fixed_clk.c (revision 804e32d7cfeac9a625473215d03158720b8e57fc)
1 // SPDX-License-Identifier: BSD-2-Clause
2 /*
3  * Copyright (c) 2021, Bootlin
4  */
5 
6 #include <drivers/clk.h>
7 #include <drivers/clk_dt.h>
8 #include <libfdt.h>
9 #include <malloc.h>
10 #include <stdint.h>
11 
12 struct fixed_clock_data {
13 	unsigned long rate;
14 };
15 
16 static unsigned long fixed_clk_get_rate(struct clk *clk,
17 					unsigned long parent_rate __unused)
18 {
19 	struct fixed_clock_data *d = clk->priv;
20 
21 	return d->rate;
22 }
23 
24 static const struct clk_ops fixed_clk_clk_ops = {
25 	.get_rate = fixed_clk_get_rate,
26 };
27 
28 static TEE_Result fixed_clock_setup(const void *fdt, int offs)
29 {
30 	const uint32_t *freq = NULL;
31 	const char *name = NULL;
32 	struct clk *clk = NULL;
33 	TEE_Result res = TEE_ERROR_GENERIC;
34 	struct fixed_clock_data *fcd = NULL;
35 
36 	name = fdt_get_name(fdt, offs, NULL);
37 	if (!name)
38 		name = "fixed-clock";
39 
40 	clk = clk_alloc(name, &fixed_clk_clk_ops, NULL, 0);
41 	if (!clk)
42 		return TEE_ERROR_OUT_OF_MEMORY;
43 
44 	fcd = calloc(1, sizeof(struct fixed_clock_data));
45 	if (!fcd) {
46 		res = TEE_ERROR_OUT_OF_MEMORY;
47 		goto free_clk;
48 	}
49 
50 	freq = fdt_getprop(fdt, offs, "clock-frequency", NULL);
51 	if (!freq) {
52 		res = TEE_ERROR_BAD_FORMAT;
53 		goto free_fcd;
54 	}
55 
56 	fcd->rate = fdt32_to_cpu(*freq);
57 	clk->priv = fcd;
58 
59 	res = clk_register(clk);
60 	if (res)
61 		goto free_fcd;
62 
63 	res = clk_dt_register_clk_provider(fdt, offs, clk_dt_get_simple_clk,
64 					   clk);
65 	if (!res)
66 		return TEE_SUCCESS;
67 
68 free_fcd:
69 	free(fcd);
70 free_clk:
71 	clk_free(clk);
72 
73 	return res;
74 }
75 
76 CLK_DT_DECLARE(fixed_clock, "fixed-clock", fixed_clock_setup);
77