1// SPDX-License-Identifier: GPL-2.0+ 2/* 3 * Copyright (C) 2016 Masahiro Yamada <yamada.masahiro@socionext.com> 4 */ 5 6#define LOG_CATEGORY UCLASS_CLK 7 8#include <clk-uclass.h> 9#include <dm.h> 10#include <log.h> 11#include <dm/device-internal.h> 12#include <linux/clk-provider.h> 13 14#define UBOOT_DM_CLK_FIXED_RATE "fixed_rate_clock" 15#define UBOOT_DM_CLK_FIXED_RATE_RAW "fixed_rate_raw_clock" 16 17static ulong clk_fixed_rate_get_rate(struct clk *clk) 18{ 19 return to_clk_fixed_rate(clk->dev)->fixed_rate; 20} 21 22/* avoid clk_enable() return -ENOSYS */ 23static int dummy_enable(struct clk *clk) 24{ 25 return 0; 26} 27 28const struct clk_ops clk_fixed_rate_ops = { 29 .get_rate = clk_fixed_rate_get_rate, 30 .enable = dummy_enable, 31 .disable = dummy_enable, 32}; 33 34void clk_fixed_rate_ofdata_to_plat_(struct udevice *dev, 35 struct clk_fixed_rate *plat) 36{ 37 struct clk *clk = &plat->clk; 38 if (CONFIG_IS_ENABLED(OF_REAL)) 39 plat->fixed_rate = dev_read_u32_default(dev, "clock-frequency", 40 0); 41 42 /* Make fixed rate clock accessible from higher level struct clk */ 43 /* FIXME: This is not allowed */ 44 dev_set_uclass_priv(dev, clk); 45 46 clk->dev = dev; 47 clk->enable_count = 0; 48} 49 50static ulong clk_fixed_rate_raw_get_rate(struct clk *clk) 51{ 52 return container_of(clk, struct clk_fixed_rate, clk)->fixed_rate; 53} 54 55const struct clk_ops clk_fixed_rate_raw_ops = { 56 .get_rate = clk_fixed_rate_raw_get_rate, 57}; 58 59static int clk_fixed_rate_of_to_plat(struct udevice *dev) 60{ 61 clk_fixed_rate_ofdata_to_plat_(dev, to_clk_fixed_rate(dev)); 62 63 return 0; 64} 65 66#if CONFIG_IS_ENABLED(CLK_CCF) 67struct clk *clk_register_fixed_rate(struct device *dev, const char *name, 68 ulong rate) 69{ 70 struct clk *clk; 71 struct clk_fixed_rate *fixed; 72 int ret; 73 74 fixed = kzalloc(sizeof(*fixed), GFP_KERNEL); 75 if (!fixed) 76 return ERR_PTR(-ENOMEM); 77 78 fixed->fixed_rate = rate; 79 80 clk = &fixed->clk; 81 82 ret = clk_register(clk, UBOOT_DM_CLK_FIXED_RATE_RAW, name, NULL); 83 if (ret) { 84 kfree(fixed); 85 return ERR_PTR(ret); 86 } 87 88 return clk; 89} 90#endif 91 92static const struct udevice_id clk_fixed_rate_match[] = { 93 { 94 .compatible = "fixed-clock", 95 }, 96 { /* sentinel */ } 97}; 98 99U_BOOT_DRIVER(fixed_clock) = { 100 .name = "fixed_clock", 101 .id = UCLASS_CLK, 102 .of_match = clk_fixed_rate_match, 103 .of_to_plat = clk_fixed_rate_of_to_plat, 104 .plat_auto = sizeof(struct clk_fixed_rate), 105 .ops = &clk_fixed_rate_ops, 106 .flags = DM_FLAG_PRE_RELOC, 107}; 108 109U_BOOT_DRIVER(clk_fixed_rate_raw) = { 110 .name = UBOOT_DM_CLK_FIXED_RATE_RAW, 111 .id = UCLASS_CLK, 112 .ops = &clk_fixed_rate_raw_ops, 113 .flags = DM_FLAG_PRE_RELOC, 114}; 115