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_probe(const void *fdt, int offs, 29 const void *compat_data __unused) 30 { 31 const uint32_t *freq = NULL; 32 const char *name = NULL; 33 struct clk *clk = NULL; 34 TEE_Result res = TEE_ERROR_GENERIC; 35 struct fixed_clock_data *fcd = NULL; 36 37 name = fdt_get_name(fdt, offs, NULL); 38 if (!name) 39 name = "fixed-clock"; 40 41 clk = clk_alloc(name, &fixed_clk_clk_ops, NULL, 0); 42 if (!clk) 43 return TEE_ERROR_OUT_OF_MEMORY; 44 45 fcd = calloc(1, sizeof(struct fixed_clock_data)); 46 if (!fcd) { 47 res = TEE_ERROR_OUT_OF_MEMORY; 48 goto free_clk; 49 } 50 51 freq = fdt_getprop(fdt, offs, "clock-frequency", NULL); 52 if (!freq) { 53 res = TEE_ERROR_BAD_FORMAT; 54 goto free_fcd; 55 } 56 57 fcd->rate = fdt32_to_cpu(*freq); 58 clk->priv = fcd; 59 60 res = clk_register(clk); 61 if (res) 62 goto free_fcd; 63 64 res = clk_dt_register_clk_provider(fdt, offs, clk_dt_get_simple_clk, 65 clk); 66 if (!res) 67 return TEE_SUCCESS; 68 69 free_fcd: 70 free(fcd); 71 free_clk: 72 clk_free(clk); 73 74 return res; 75 } 76 77 CLK_DT_DECLARE(fixed_clock, "fixed-clock", fixed_clock_probe); 78