1 /* 2 * TI 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/clkdev.h> 20 #include <linux/clk/ti.h> 21 #include <linux/of.h> 22 #include <linux/of_address.h> 23 #include <linux/list.h> 24 25 #include "clock.h" 26 27 #undef pr_fmt 28 #define pr_fmt(fmt) "%s: " fmt, __func__ 29 30 struct ti_clk_ll_ops *ti_clk_ll_ops; 31 static struct device_node *clocks_node_ptr[CLK_MAX_MEMMAPS]; 32 33 /** 34 * ti_dt_clocks_register - register DT alias clocks during boot 35 * @oclks: list of clocks to register 36 * 37 * Register alias or non-standard DT clock entries during boot. By 38 * default, DT clocks are found based on their node name. If any 39 * additional con-id / dev-id -> clock mapping is required, use this 40 * function to list these. 41 */ 42 void __init ti_dt_clocks_register(struct ti_dt_clk oclks[]) 43 { 44 struct ti_dt_clk *c; 45 struct device_node *node; 46 struct clk *clk; 47 struct of_phandle_args clkspec; 48 49 for (c = oclks; c->node_name != NULL; c++) { 50 node = of_find_node_by_name(NULL, c->node_name); 51 clkspec.np = node; 52 clk = of_clk_get_from_provider(&clkspec); 53 54 if (!IS_ERR(clk)) { 55 c->lk.clk = clk; 56 clkdev_add(&c->lk); 57 } else { 58 pr_warn("failed to lookup clock node %s\n", 59 c->node_name); 60 } 61 } 62 } 63 64 struct clk_init_item { 65 struct device_node *node; 66 struct clk_hw *hw; 67 ti_of_clk_init_cb_t func; 68 struct list_head link; 69 }; 70 71 static LIST_HEAD(retry_list); 72 73 /** 74 * ti_clk_retry_init - retries a failed clock init at later phase 75 * @node: device not for the clock 76 * @hw: partially initialized clk_hw struct for the clock 77 * @func: init function to be called for the clock 78 * 79 * Adds a failed clock init to the retry list. The retry list is parsed 80 * once all the other clocks have been initialized. 81 */ 82 int __init ti_clk_retry_init(struct device_node *node, struct clk_hw *hw, 83 ti_of_clk_init_cb_t func) 84 { 85 struct clk_init_item *retry; 86 87 pr_debug("%s: adding to retry list...\n", node->name); 88 retry = kzalloc(sizeof(*retry), GFP_KERNEL); 89 if (!retry) 90 return -ENOMEM; 91 92 retry->node = node; 93 retry->func = func; 94 retry->hw = hw; 95 list_add(&retry->link, &retry_list); 96 97 return 0; 98 } 99 100 /** 101 * ti_clk_get_reg_addr - get register address for a clock register 102 * @node: device node for the clock 103 * @index: register index from the clock node 104 * 105 * Builds clock register address from device tree information. This 106 * is a struct of type clk_omap_reg. Returns a pointer to the register 107 * address, or a pointer error value in failure. 108 */ 109 void __iomem *ti_clk_get_reg_addr(struct device_node *node, int index) 110 { 111 struct clk_omap_reg *reg; 112 u32 val; 113 u32 tmp; 114 int i; 115 116 reg = (struct clk_omap_reg *)&tmp; 117 118 for (i = 0; i < CLK_MAX_MEMMAPS; i++) { 119 if (clocks_node_ptr[i] == node->parent) 120 break; 121 } 122 123 if (i == CLK_MAX_MEMMAPS) { 124 pr_err("clk-provider not found for %s!\n", node->name); 125 return IOMEM_ERR_PTR(-ENOENT); 126 } 127 128 reg->index = i; 129 130 if (of_property_read_u32_index(node, "reg", index, &val)) { 131 pr_err("%s must have reg[%d]!\n", node->name, index); 132 return IOMEM_ERR_PTR(-EINVAL); 133 } 134 135 reg->offset = val; 136 137 return (void __iomem *)tmp; 138 } 139 140 /** 141 * ti_dt_clk_init_provider - init master clock provider 142 * @parent: master node 143 * @index: internal index for clk_reg_ops 144 * 145 * Initializes a master clock IP block. This basically sets up the 146 * mapping from clocks node to the memory map index. All the clocks 147 * are then initialized through the common of_clk_init call, and the 148 * clocks will access their memory maps based on the node layout. 149 */ 150 void ti_dt_clk_init_provider(struct device_node *parent, int index) 151 { 152 struct device_node *clocks; 153 154 /* get clocks for this parent */ 155 clocks = of_get_child_by_name(parent, "clocks"); 156 if (!clocks) { 157 pr_err("%s missing 'clocks' child node.\n", parent->name); 158 return; 159 } 160 161 /* add clocks node info */ 162 clocks_node_ptr[index] = clocks; 163 } 164 165 /** 166 * ti_dt_clk_init_retry_clks - init clocks from the retry list 167 * 168 * Initializes any clocks that have failed to initialize before, 169 * reasons being missing parent node(s) during earlier init. This 170 * typically happens only for DPLLs which need to have both of their 171 * parent clocks ready during init. 172 */ 173 void ti_dt_clk_init_retry_clks(void) 174 { 175 struct clk_init_item *retry; 176 struct clk_init_item *tmp; 177 int retries = 5; 178 179 while (!list_empty(&retry_list) && retries) { 180 list_for_each_entry_safe(retry, tmp, &retry_list, link) { 181 pr_debug("retry-init: %s\n", retry->node->name); 182 retry->func(retry->hw, retry->node); 183 list_del(&retry->link); 184 kfree(retry); 185 } 186 retries--; 187 } 188 } 189 190 #if defined(CONFIG_ARCH_OMAP3) && defined(CONFIG_ATAGS) 191 void __init ti_clk_patch_legacy_clks(struct ti_clk **patch) 192 { 193 while (*patch) { 194 memcpy((*patch)->patch, *patch, sizeof(**patch)); 195 patch++; 196 } 197 } 198 199 struct clk __init *ti_clk_register_clk(struct ti_clk *setup) 200 { 201 struct clk *clk; 202 struct ti_clk_fixed *fixed; 203 struct ti_clk_fixed_factor *fixed_factor; 204 struct clk_hw *clk_hw; 205 206 if (setup->clk) 207 return setup->clk; 208 209 switch (setup->type) { 210 case TI_CLK_FIXED: 211 fixed = setup->data; 212 213 clk = clk_register_fixed_rate(NULL, setup->name, NULL, 214 CLK_IS_ROOT, fixed->frequency); 215 break; 216 case TI_CLK_MUX: 217 clk = ti_clk_register_mux(setup); 218 break; 219 case TI_CLK_DIVIDER: 220 clk = ti_clk_register_divider(setup); 221 break; 222 case TI_CLK_COMPOSITE: 223 clk = ti_clk_register_composite(setup); 224 break; 225 case TI_CLK_FIXED_FACTOR: 226 fixed_factor = setup->data; 227 228 clk = clk_register_fixed_factor(NULL, setup->name, 229 fixed_factor->parent, 230 0, fixed_factor->mult, 231 fixed_factor->div); 232 break; 233 case TI_CLK_GATE: 234 clk = ti_clk_register_gate(setup); 235 break; 236 case TI_CLK_DPLL: 237 clk = ti_clk_register_dpll(setup); 238 break; 239 default: 240 pr_err("bad type for %s!\n", setup->name); 241 clk = ERR_PTR(-EINVAL); 242 } 243 244 if (!IS_ERR(clk)) { 245 setup->clk = clk; 246 if (setup->clkdm_name) { 247 if (__clk_get_flags(clk) & CLK_IS_BASIC) { 248 pr_warn("can't setup clkdm for basic clk %s\n", 249 setup->name); 250 } else { 251 clk_hw = __clk_get_hw(clk); 252 to_clk_hw_omap(clk_hw)->clkdm_name = 253 setup->clkdm_name; 254 omap2_init_clk_clkdm(clk_hw); 255 } 256 } 257 } 258 259 return clk; 260 } 261 262 int __init ti_clk_register_legacy_clks(struct ti_clk_alias *clks) 263 { 264 struct clk *clk; 265 bool retry; 266 struct ti_clk_alias *retry_clk; 267 struct ti_clk_alias *tmp; 268 269 while (clks->clk) { 270 clk = ti_clk_register_clk(clks->clk); 271 if (IS_ERR(clk)) { 272 if (PTR_ERR(clk) == -EAGAIN) { 273 list_add(&clks->link, &retry_list); 274 } else { 275 pr_err("register for %s failed: %ld\n", 276 clks->clk->name, PTR_ERR(clk)); 277 return PTR_ERR(clk); 278 } 279 } else { 280 clks->lk.clk = clk; 281 clkdev_add(&clks->lk); 282 } 283 clks++; 284 } 285 286 retry = true; 287 288 while (!list_empty(&retry_list) && retry) { 289 retry = false; 290 list_for_each_entry_safe(retry_clk, tmp, &retry_list, link) { 291 pr_debug("retry-init: %s\n", retry_clk->clk->name); 292 clk = ti_clk_register_clk(retry_clk->clk); 293 if (IS_ERR(clk)) { 294 if (PTR_ERR(clk) == -EAGAIN) { 295 continue; 296 } else { 297 pr_err("register for %s failed: %ld\n", 298 retry_clk->clk->name, 299 PTR_ERR(clk)); 300 return PTR_ERR(clk); 301 } 302 } else { 303 retry = true; 304 retry_clk->lk.clk = clk; 305 clkdev_add(&retry_clk->lk); 306 list_del(&retry_clk->link); 307 } 308 } 309 } 310 311 return 0; 312 } 313 #endif 314