1 /* 2 * TI composite clock support 3 * 4 * Copyright (C) 2013 Texas Instruments, Inc. 5 * 6 * Tero Kristo <t-kristo@ti.com> 7 * 8 * This program is free software; you can redistribute it and/or modify 9 * it under the terms of the GNU General Public License version 2 as 10 * published by the Free Software Foundation. 11 * 12 * This program is distributed "as is" WITHOUT ANY WARRANTY of any 13 * kind, whether express or implied; without even the implied warranty 14 * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 * GNU General Public License for more details. 16 */ 17 18 #include <linux/clk-provider.h> 19 #include <linux/slab.h> 20 #include <linux/io.h> 21 #include <linux/of.h> 22 #include <linux/of_address.h> 23 #include <linux/clk/ti.h> 24 #include <linux/list.h> 25 26 #include "clock.h" 27 28 #undef pr_fmt 29 #define pr_fmt(fmt) "%s: " fmt, __func__ 30 31 static unsigned long ti_composite_recalc_rate(struct clk_hw *hw, 32 unsigned long parent_rate) 33 { 34 return ti_clk_divider_ops.recalc_rate(hw, parent_rate); 35 } 36 37 static long ti_composite_round_rate(struct clk_hw *hw, unsigned long rate, 38 unsigned long *prate) 39 { 40 return -EINVAL; 41 } 42 43 static int ti_composite_set_rate(struct clk_hw *hw, unsigned long rate, 44 unsigned long parent_rate) 45 { 46 return -EINVAL; 47 } 48 49 static const struct clk_ops ti_composite_divider_ops = { 50 .recalc_rate = &ti_composite_recalc_rate, 51 .round_rate = &ti_composite_round_rate, 52 .set_rate = &ti_composite_set_rate, 53 }; 54 55 static const struct clk_ops ti_composite_gate_ops = { 56 .enable = &omap2_dflt_clk_enable, 57 .disable = &omap2_dflt_clk_disable, 58 .is_enabled = &omap2_dflt_clk_is_enabled, 59 }; 60 61 struct component_clk { 62 int num_parents; 63 const char **parent_names; 64 struct device_node *node; 65 int type; 66 struct clk_hw *hw; 67 struct list_head link; 68 }; 69 70 static const char * const component_clk_types[] __initconst = { 71 "gate", "divider", "mux" 72 }; 73 74 static LIST_HEAD(component_clks); 75 76 static struct device_node *_get_component_node(struct device_node *node, int i) 77 { 78 int rc; 79 struct of_phandle_args clkspec; 80 81 rc = of_parse_phandle_with_args(node, "clocks", "#clock-cells", i, 82 &clkspec); 83 if (rc) 84 return NULL; 85 86 return clkspec.np; 87 } 88 89 static struct component_clk *_lookup_component(struct device_node *node) 90 { 91 struct component_clk *comp; 92 93 list_for_each_entry(comp, &component_clks, link) { 94 if (comp->node == node) 95 return comp; 96 } 97 return NULL; 98 } 99 100 struct clk_hw_omap_comp { 101 struct clk_hw hw; 102 struct device_node *comp_nodes[CLK_COMPONENT_TYPE_MAX]; 103 struct component_clk *comp_clks[CLK_COMPONENT_TYPE_MAX]; 104 }; 105 106 static inline struct clk_hw *_get_hw(struct clk_hw_omap_comp *clk, int idx) 107 { 108 if (!clk) 109 return NULL; 110 111 if (!clk->comp_clks[idx]) 112 return NULL; 113 114 return clk->comp_clks[idx]->hw; 115 } 116 117 #define to_clk_hw_comp(_hw) container_of(_hw, struct clk_hw_omap_comp, hw) 118 119 #if defined(CONFIG_ARCH_OMAP3) && defined(CONFIG_ATAGS) 120 struct clk *ti_clk_register_composite(struct ti_clk *setup) 121 { 122 struct ti_clk_composite *comp; 123 struct clk_hw *gate; 124 struct clk_hw *mux; 125 struct clk_hw *div; 126 int num_parents = 1; 127 const char * const *parent_names = NULL; 128 struct clk *clk; 129 int ret; 130 131 comp = setup->data; 132 133 div = ti_clk_build_component_div(comp->divider); 134 gate = ti_clk_build_component_gate(comp->gate); 135 mux = ti_clk_build_component_mux(comp->mux); 136 137 if (div) 138 parent_names = &comp->divider->parent; 139 140 if (gate) 141 parent_names = &comp->gate->parent; 142 143 if (mux) { 144 num_parents = comp->mux->num_parents; 145 parent_names = comp->mux->parents; 146 } 147 148 clk = clk_register_composite(NULL, setup->name, 149 parent_names, num_parents, mux, 150 &ti_clk_mux_ops, div, 151 &ti_composite_divider_ops, gate, 152 &ti_composite_gate_ops, 0); 153 154 ret = ti_clk_add_alias(NULL, clk, setup->name); 155 if (ret) { 156 clk_unregister(clk); 157 return ERR_PTR(ret); 158 } 159 160 return clk; 161 } 162 #endif 163 164 static void __init _register_composite(struct clk_hw *hw, 165 struct device_node *node) 166 { 167 struct clk *clk; 168 struct clk_hw_omap_comp *cclk = to_clk_hw_comp(hw); 169 struct component_clk *comp; 170 int num_parents = 0; 171 const char **parent_names = NULL; 172 int i; 173 int ret; 174 175 /* Check for presence of each component clock */ 176 for (i = 0; i < CLK_COMPONENT_TYPE_MAX; i++) { 177 if (!cclk->comp_nodes[i]) 178 continue; 179 180 comp = _lookup_component(cclk->comp_nodes[i]); 181 if (!comp) { 182 pr_debug("component %s not ready for %s, retry\n", 183 cclk->comp_nodes[i]->name, node->name); 184 if (!ti_clk_retry_init(node, hw, 185 _register_composite)) 186 return; 187 188 goto cleanup; 189 } 190 if (cclk->comp_clks[comp->type] != NULL) { 191 pr_err("duplicate component types for %s (%s)!\n", 192 node->name, component_clk_types[comp->type]); 193 goto cleanup; 194 } 195 196 cclk->comp_clks[comp->type] = comp; 197 198 /* Mark this node as found */ 199 cclk->comp_nodes[i] = NULL; 200 } 201 202 /* All components exists, proceed with registration */ 203 for (i = CLK_COMPONENT_TYPE_MAX - 1; i >= 0; i--) { 204 comp = cclk->comp_clks[i]; 205 if (!comp) 206 continue; 207 if (comp->num_parents) { 208 num_parents = comp->num_parents; 209 parent_names = comp->parent_names; 210 break; 211 } 212 } 213 214 if (!num_parents) { 215 pr_err("%s: no parents found for %s!\n", __func__, node->name); 216 goto cleanup; 217 } 218 219 clk = clk_register_composite(NULL, node->name, 220 parent_names, num_parents, 221 _get_hw(cclk, CLK_COMPONENT_TYPE_MUX), 222 &ti_clk_mux_ops, 223 _get_hw(cclk, CLK_COMPONENT_TYPE_DIVIDER), 224 &ti_composite_divider_ops, 225 _get_hw(cclk, CLK_COMPONENT_TYPE_GATE), 226 &ti_composite_gate_ops, 0); 227 228 if (!IS_ERR(clk)) { 229 ret = ti_clk_add_alias(NULL, clk, node->name); 230 if (ret) { 231 clk_unregister(clk); 232 goto cleanup; 233 } 234 of_clk_add_provider(node, of_clk_src_simple_get, clk); 235 } 236 237 cleanup: 238 /* Free component clock list entries */ 239 for (i = 0; i < CLK_COMPONENT_TYPE_MAX; i++) { 240 if (!cclk->comp_clks[i]) 241 continue; 242 list_del(&cclk->comp_clks[i]->link); 243 kfree(cclk->comp_clks[i]); 244 } 245 246 kfree(cclk); 247 } 248 249 static void __init of_ti_composite_clk_setup(struct device_node *node) 250 { 251 unsigned int num_clks; 252 int i; 253 struct clk_hw_omap_comp *cclk; 254 255 /* Number of component clocks to be put inside this clock */ 256 num_clks = of_clk_get_parent_count(node); 257 258 if (!num_clks) { 259 pr_err("composite clk %s must have component(s)\n", node->name); 260 return; 261 } 262 263 cclk = kzalloc(sizeof(*cclk), GFP_KERNEL); 264 if (!cclk) 265 return; 266 267 /* Get device node pointers for each component clock */ 268 for (i = 0; i < num_clks; i++) 269 cclk->comp_nodes[i] = _get_component_node(node, i); 270 271 _register_composite(&cclk->hw, node); 272 } 273 CLK_OF_DECLARE(ti_composite_clock, "ti,composite-clock", 274 of_ti_composite_clk_setup); 275 276 /** 277 * ti_clk_add_component - add a component clock to the pool 278 * @node: device node of the component clock 279 * @hw: hardware clock definition for the component clock 280 * @type: type of the component clock 281 * 282 * Adds a component clock to the list of available components, so that 283 * it can be registered by a composite clock. 284 */ 285 int __init ti_clk_add_component(struct device_node *node, struct clk_hw *hw, 286 int type) 287 { 288 unsigned int num_parents; 289 const char **parent_names; 290 struct component_clk *clk; 291 292 num_parents = of_clk_get_parent_count(node); 293 294 if (!num_parents) { 295 pr_err("component-clock %s must have parent(s)\n", node->name); 296 return -EINVAL; 297 } 298 299 parent_names = kzalloc((sizeof(char *) * num_parents), GFP_KERNEL); 300 if (!parent_names) 301 return -ENOMEM; 302 303 of_clk_parent_fill(node, parent_names, num_parents); 304 305 clk = kzalloc(sizeof(*clk), GFP_KERNEL); 306 if (!clk) { 307 kfree(parent_names); 308 return -ENOMEM; 309 } 310 311 clk->num_parents = num_parents; 312 clk->parent_names = parent_names; 313 clk->hw = hw; 314 clk->node = node; 315 clk->type = type; 316 list_add(&clk->link, &component_clks); 317 318 return 0; 319 } 320