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