1 /* 2 * This program is free software; you can redistribute it and/or modify 3 * it under the terms of the GNU General Public License version 2 as 4 * published by the Free Software Foundation. 5 * 6 * This program is distributed in the hope that it will be useful, 7 * but WITHOUT ANY WARRANTY; without even the implied warranty of 8 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 9 * GNU General Public License for more details. 10 * 11 * Copyright (C) 2012 ARM Limited 12 */ 13 14 #define pr_fmt(fmt) "vexpress-osc: " fmt 15 16 #include <linux/clkdev.h> 17 #include <linux/clk-provider.h> 18 #include <linux/err.h> 19 #include <linux/of.h> 20 #include <linux/platform_device.h> 21 #include <linux/slab.h> 22 #include <linux/vexpress.h> 23 24 struct vexpress_osc { 25 struct vexpress_config_func *func; 26 struct clk_hw hw; 27 unsigned long rate_min; 28 unsigned long rate_max; 29 }; 30 31 #define to_vexpress_osc(osc) container_of(osc, struct vexpress_osc, hw) 32 33 static unsigned long vexpress_osc_recalc_rate(struct clk_hw *hw, 34 unsigned long parent_rate) 35 { 36 struct vexpress_osc *osc = to_vexpress_osc(hw); 37 u32 rate; 38 39 vexpress_config_read(osc->func, 0, &rate); 40 41 return rate; 42 } 43 44 static long vexpress_osc_round_rate(struct clk_hw *hw, unsigned long rate, 45 unsigned long *parent_rate) 46 { 47 struct vexpress_osc *osc = to_vexpress_osc(hw); 48 49 if (WARN_ON(osc->rate_min && rate < osc->rate_min)) 50 rate = osc->rate_min; 51 52 if (WARN_ON(osc->rate_max && rate > osc->rate_max)) 53 rate = osc->rate_max; 54 55 return rate; 56 } 57 58 static int vexpress_osc_set_rate(struct clk_hw *hw, unsigned long rate, 59 unsigned long parent_rate) 60 { 61 struct vexpress_osc *osc = to_vexpress_osc(hw); 62 63 return vexpress_config_write(osc->func, 0, rate); 64 } 65 66 static struct clk_ops vexpress_osc_ops = { 67 .recalc_rate = vexpress_osc_recalc_rate, 68 .round_rate = vexpress_osc_round_rate, 69 .set_rate = vexpress_osc_set_rate, 70 }; 71 72 73 struct clk * __init vexpress_osc_setup(struct device *dev) 74 { 75 struct clk_init_data init; 76 struct vexpress_osc *osc = kzalloc(sizeof(*osc), GFP_KERNEL); 77 78 if (!osc) 79 return NULL; 80 81 osc->func = vexpress_config_func_get_by_dev(dev); 82 if (!osc->func) { 83 kfree(osc); 84 return NULL; 85 } 86 87 init.name = dev_name(dev); 88 init.ops = &vexpress_osc_ops; 89 init.flags = CLK_IS_ROOT; 90 init.num_parents = 0; 91 osc->hw.init = &init; 92 93 return clk_register(NULL, &osc->hw); 94 } 95 96 void __init vexpress_osc_of_setup(struct device_node *node) 97 { 98 struct clk_init_data init; 99 struct vexpress_osc *osc; 100 struct clk *clk; 101 u32 range[2]; 102 103 osc = kzalloc(sizeof(*osc), GFP_KERNEL); 104 if (!osc) 105 goto error; 106 107 osc->func = vexpress_config_func_get_by_node(node); 108 if (!osc->func) { 109 pr_err("Failed to obtain config func for node '%s'!\n", 110 node->name); 111 goto error; 112 } 113 114 if (of_property_read_u32_array(node, "freq-range", range, 115 ARRAY_SIZE(range)) == 0) { 116 osc->rate_min = range[0]; 117 osc->rate_max = range[1]; 118 } 119 120 of_property_read_string(node, "clock-output-names", &init.name); 121 if (!init.name) 122 init.name = node->name; 123 124 init.ops = &vexpress_osc_ops; 125 init.flags = CLK_IS_ROOT; 126 init.num_parents = 0; 127 128 osc->hw.init = &init; 129 130 clk = clk_register(NULL, &osc->hw); 131 if (IS_ERR(clk)) { 132 pr_err("Failed to register clock '%s'!\n", init.name); 133 goto error; 134 } 135 136 of_clk_add_provider(node, of_clk_src_simple_get, clk); 137 138 pr_debug("Registered clock '%s'\n", init.name); 139 140 return; 141 142 error: 143 if (osc->func) 144 vexpress_config_func_put(osc->func); 145 kfree(osc); 146 } 147 CLK_OF_DECLARE(vexpress_soc, "arm,vexpress-osc", vexpress_osc_of_setup); 148