1/* 2 * 3 * Copyright (C) 2010 Google, Inc. 4 * 5 * Author: 6 * Colin Cross <ccross@google.com> 7 * 8 * This software is licensed under the terms of the GNU General Public 9 * License version 2, as published by the Free Software Foundation, and 10 * may be copied, distributed, and modified under those terms. 11 * 12 * This program is distributed in the hope that it will be useful, 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 * GNU General Public License for more details. 16 * 17 */ 18 19#include <linux/kernel.h> 20#include <linux/clk.h> 21#include <linux/list.h> 22#include <linux/init.h> 23#include <linux/module.h> 24#include <linux/debugfs.h> 25#include <linux/slab.h> 26#include <linux/seq_file.h> 27#include <asm/clkdev.h> 28 29#include "clock.h" 30 31static LIST_HEAD(clocks); 32 33static DEFINE_SPINLOCK(clock_lock); 34 35struct clk *tegra_get_clock_by_name(const char *name) 36{ 37 struct clk *c; 38 struct clk *ret = NULL; 39 unsigned long flags; 40 spin_lock_irqsave(&clock_lock, flags); 41 list_for_each_entry(c, &clocks, node) { 42 if (strcmp(c->name, name) == 0) { 43 ret = c; 44 break; 45 } 46 } 47 spin_unlock_irqrestore(&clock_lock, flags); 48 return ret; 49} 50 51int clk_reparent(struct clk *c, struct clk *parent) 52{ 53 pr_debug("%s: %s\n", __func__, c->name); 54 if (c->refcnt && c->parent) 55 clk_disable_locked(c->parent); 56 c->parent = parent; 57 if (c->refcnt && c->parent) 58 clk_enable_locked(c->parent); 59 list_del(&c->sibling); 60 list_add_tail(&c->sibling, &parent->children); 61 return 0; 62} 63 64static void propagate_rate(struct clk *c) 65{ 66 struct clk *clkp; 67 pr_debug("%s: %s\n", __func__, c->name); 68 list_for_each_entry(clkp, &c->children, sibling) { 69 pr_debug(" %s\n", clkp->name); 70 if (clkp->ops->recalculate_rate) 71 clkp->ops->recalculate_rate(clkp); 72 propagate_rate(clkp); 73 } 74} 75 76void clk_init(struct clk *c) 77{ 78 unsigned long flags; 79 80 spin_lock_irqsave(&clock_lock, flags); 81 82 INIT_LIST_HEAD(&c->children); 83 INIT_LIST_HEAD(&c->sibling); 84 85 if (c->ops && c->ops->init) 86 c->ops->init(c); 87 88 list_add(&c->node, &clocks); 89 90 if (c->parent) 91 list_add_tail(&c->sibling, &c->parent->children); 92 93 spin_unlock_irqrestore(&clock_lock, flags); 94} 95 96int clk_enable_locked(struct clk *c) 97{ 98 int ret; 99 pr_debug("%s: %s\n", __func__, c->name); 100 if (c->refcnt == 0) { 101 if (c->parent) { 102 ret = clk_enable_locked(c->parent); 103 if (ret) 104 return ret; 105 } 106 107 if (c->ops && c->ops->enable) { 108 ret = c->ops->enable(c); 109 if (ret) { 110 if (c->parent) 111 clk_disable_locked(c->parent); 112 return ret; 113 } 114 c->state = ON; 115#ifdef CONFIG_DEBUG_FS 116 c->set = 1; 117#endif 118 } 119 } 120 c->refcnt++; 121 122 return 0; 123} 124 125int clk_enable(struct clk *c) 126{ 127 int ret; 128 unsigned long flags; 129 spin_lock_irqsave(&clock_lock, flags); 130 ret = clk_enable_locked(c); 131 spin_unlock_irqrestore(&clock_lock, flags); 132 return ret; 133} 134EXPORT_SYMBOL(clk_enable); 135 136void clk_disable_locked(struct clk *c) 137{ 138 pr_debug("%s: %s\n", __func__, c->name); 139 if (c->refcnt == 0) { 140 WARN(1, "Attempting to disable clock %s with refcnt 0", c->name); 141 return; 142 } 143 if (c->refcnt == 1) { 144 if (c->ops && c->ops->disable) 145 c->ops->disable(c); 146 147 if (c->parent) 148 clk_disable_locked(c->parent); 149 150 c->state = OFF; 151 } 152 c->refcnt--; 153} 154 155void clk_disable(struct clk *c) 156{ 157 unsigned long flags; 158 spin_lock_irqsave(&clock_lock, flags); 159 clk_disable_locked(c); 160 spin_unlock_irqrestore(&clock_lock, flags); 161} 162EXPORT_SYMBOL(clk_disable); 163 164int clk_set_parent_locked(struct clk *c, struct clk *parent) 165{ 166 int ret; 167 168 pr_debug("%s: %s\n", __func__, c->name); 169 170 if (!c->ops || !c->ops->set_parent) 171 return -ENOSYS; 172 173 ret = c->ops->set_parent(c, parent); 174 175 if (ret) 176 return ret; 177 178 propagate_rate(c); 179 180 return 0; 181} 182 183int clk_set_parent(struct clk *c, struct clk *parent) 184{ 185 int ret; 186 unsigned long flags; 187 spin_lock_irqsave(&clock_lock, flags); 188 ret = clk_set_parent_locked(c, parent); 189 spin_unlock_irqrestore(&clock_lock, flags); 190 return ret; 191} 192EXPORT_SYMBOL(clk_set_parent); 193 194struct clk *clk_get_parent(struct clk *c) 195{ 196 return c->parent; 197} 198EXPORT_SYMBOL(clk_get_parent); 199 200int clk_set_rate(struct clk *c, unsigned long rate) 201{ 202 int ret = 0; 203 unsigned long flags; 204 205 spin_lock_irqsave(&clock_lock, flags); 206 207 pr_debug("%s: %s\n", __func__, c->name); 208 209 if (c->ops && c->ops->set_rate) 210 ret = c->ops->set_rate(c, rate); 211 else 212 ret = -ENOSYS; 213 214 propagate_rate(c); 215 216 spin_unlock_irqrestore(&clock_lock, flags); 217 218 return ret; 219} 220EXPORT_SYMBOL(clk_set_rate); 221 222unsigned long clk_get_rate(struct clk *c) 223{ 224 unsigned long flags; 225 unsigned long ret; 226 227 spin_lock_irqsave(&clock_lock, flags); 228 229 pr_debug("%s: %s\n", __func__, c->name); 230 231 ret = c->rate; 232 233 spin_unlock_irqrestore(&clock_lock, flags); 234 return ret; 235} 236EXPORT_SYMBOL(clk_get_rate); 237 238static int tegra_clk_init_one_from_table(struct tegra_clk_init_table *table) 239{ 240 struct clk *c; 241 struct clk *p; 242 243 int ret = 0; 244 245 c = tegra_get_clock_by_name(table->name); 246 247 if (!c) { 248 pr_warning("Unable to initialize clock %s\n", 249 table->name); 250 return -ENODEV; 251 } 252 253 if (table->parent) { 254 p = tegra_get_clock_by_name(table->parent); 255 if (!p) { 256 pr_warning("Unable to find parent %s of clock %s\n", 257 table->parent, table->name); 258 return -ENODEV; 259 } 260 261 if (c->parent != p) { 262 ret = clk_set_parent(c, p); 263 if (ret) { 264 pr_warning("Unable to set parent %s of clock %s: %d\n", 265 table->parent, table->name, ret); 266 return -EINVAL; 267 } 268 } 269 } 270 271 if (table->rate && table->rate != clk_get_rate(c)) { 272 ret = clk_set_rate(c, table->rate); 273 if (ret) { 274 pr_warning("Unable to set clock %s to rate %lu: %d\n", 275 table->name, table->rate, ret); 276 return -EINVAL; 277 } 278 } 279 280 if (table->enabled) { 281 ret = clk_enable(c); 282 if (ret) { 283 pr_warning("Unable to enable clock %s: %d\n", 284 table->name, ret); 285 return -EINVAL; 286 } 287 } 288 289 return 0; 290} 291 292void tegra_clk_init_from_table(struct tegra_clk_init_table *table) 293{ 294 for (; table->name; table++) 295 tegra_clk_init_one_from_table(table); 296} 297EXPORT_SYMBOL(tegra_clk_init_from_table); 298 299void tegra_periph_reset_deassert(struct clk *c) 300{ 301 tegra2_periph_reset_deassert(c); 302} 303EXPORT_SYMBOL(tegra_periph_reset_deassert); 304 305void tegra_periph_reset_assert(struct clk *c) 306{ 307 tegra2_periph_reset_assert(c); 308} 309EXPORT_SYMBOL(tegra_periph_reset_assert); 310 311int __init tegra_init_clock(void) 312{ 313 tegra2_init_clocks(); 314 315 return 0; 316} 317 318#ifdef CONFIG_DEBUG_FS 319static struct dentry *clk_debugfs_root; 320 321 322static void clock_tree_show_one(struct seq_file *s, struct clk *c, int level) 323{ 324 struct clk *child; 325 struct clk *safe; 326 const char *state = "uninit"; 327 char div[5] = {0}; 328 329 if (c->state == ON) 330 state = "on"; 331 else if (c->state == OFF) 332 state = "off"; 333 334 if (c->mul != 0 && c->div != 0) { 335 BUG_ON(c->mul > 2); 336 if (c->mul > c->div) 337 snprintf(div, sizeof(div), "x%d", c->mul / c->div); 338 else 339 snprintf(div, sizeof(div), "%d%s", c->div / c->mul, 340 (c->div % c->mul) ? ".5" : ""); 341 } 342 343 seq_printf(s, "%*s%-*s %-6s %-3d %-5s %-10lu\n", 344 level * 3 + 1, c->set ? "" : "*", 345 30 - level * 3, c->name, 346 state, c->refcnt, div, c->rate); 347 list_for_each_entry_safe(child, safe, &c->children, sibling) { 348 clock_tree_show_one(s, child, level + 1); 349 } 350} 351 352static int clock_tree_show(struct seq_file *s, void *data) 353{ 354 struct clk *c; 355 unsigned long flags; 356 seq_printf(s, " clock state ref div rate \n"); 357 seq_printf(s, "-----------------------------------------------------------\n"); 358 spin_lock_irqsave(&clock_lock, flags); 359 list_for_each_entry(c, &clocks, node) 360 if (c->parent == NULL) 361 clock_tree_show_one(s, c, 0); 362 spin_unlock_irqrestore(&clock_lock, flags); 363 return 0; 364} 365 366static int clock_tree_open(struct inode *inode, struct file *file) 367{ 368 return single_open(file, clock_tree_show, inode->i_private); 369} 370 371static const struct file_operations clock_tree_fops = { 372 .open = clock_tree_open, 373 .read = seq_read, 374 .llseek = seq_lseek, 375 .release = single_release, 376}; 377 378static int possible_parents_show(struct seq_file *s, void *data) 379{ 380 struct clk *c = s->private; 381 int i; 382 383 for (i = 0; c->inputs[i].input; i++) { 384 char *first = (i == 0) ? "" : " "; 385 seq_printf(s, "%s%s", first, c->inputs[i].input->name); 386 } 387 seq_printf(s, "\n"); 388 return 0; 389} 390 391static int possible_parents_open(struct inode *inode, struct file *file) 392{ 393 return single_open(file, possible_parents_show, inode->i_private); 394} 395 396static const struct file_operations possible_parents_fops = { 397 .open = possible_parents_open, 398 .read = seq_read, 399 .llseek = seq_lseek, 400 .release = single_release, 401}; 402 403static int clk_debugfs_register_one(struct clk *c) 404{ 405 struct dentry *d, *child, *child_tmp; 406 407 d = debugfs_create_dir(c->name, clk_debugfs_root); 408 if (!d) 409 return -ENOMEM; 410 c->dent = d; 411 412 d = debugfs_create_u8("refcnt", S_IRUGO, c->dent, (u8 *)&c->refcnt); 413 if (!d) 414 goto err_out; 415 416 d = debugfs_create_u32("rate", S_IRUGO, c->dent, (u32 *)&c->rate); 417 if (!d) 418 goto err_out; 419 420 d = debugfs_create_x32("flags", S_IRUGO, c->dent, (u32 *)&c->flags); 421 if (!d) 422 goto err_out; 423 424 if (c->inputs) { 425 d = debugfs_create_file("possible_parents", S_IRUGO, c->dent, 426 c, &possible_parents_fops); 427 if (!d) 428 goto err_out; 429 } 430 431 return 0; 432 433err_out: 434 d = c->dent; 435 list_for_each_entry_safe(child, child_tmp, &d->d_subdirs, d_u.d_child) 436 debugfs_remove(child); 437 debugfs_remove(c->dent); 438 return -ENOMEM; 439} 440 441static int clk_debugfs_register(struct clk *c) 442{ 443 int err; 444 struct clk *pa = c->parent; 445 446 if (pa && !pa->dent) { 447 err = clk_debugfs_register(pa); 448 if (err) 449 return err; 450 } 451 452 if (!c->dent) { 453 err = clk_debugfs_register_one(c); 454 if (err) 455 return err; 456 } 457 return 0; 458} 459 460static int __init clk_debugfs_init(void) 461{ 462 struct clk *c; 463 struct dentry *d; 464 int err = -ENOMEM; 465 466 d = debugfs_create_dir("clock", NULL); 467 if (!d) 468 return -ENOMEM; 469 clk_debugfs_root = d; 470 471 d = debugfs_create_file("clock_tree", S_IRUGO, clk_debugfs_root, NULL, 472 &clock_tree_fops); 473 if (!d) 474 goto err_out; 475 476 list_for_each_entry(c, &clocks, node) { 477 err = clk_debugfs_register(c); 478 if (err) 479 goto err_out; 480 } 481 return 0; 482err_out: 483 debugfs_remove_recursive(clk_debugfs_root); 484 return err; 485} 486 487late_initcall(clk_debugfs_init); 488#endif 489