1d861196163e30c07add471562b45dce38517c9b2Colin Cross/* 2d861196163e30c07add471562b45dce38517c9b2Colin Cross * 3d861196163e30c07add471562b45dce38517c9b2Colin Cross * Copyright (C) 2010 Google, Inc. 4d861196163e30c07add471562b45dce38517c9b2Colin Cross * 5d861196163e30c07add471562b45dce38517c9b2Colin Cross * Author: 6d861196163e30c07add471562b45dce38517c9b2Colin Cross * Colin Cross <ccross@google.com> 7d861196163e30c07add471562b45dce38517c9b2Colin Cross * 8d861196163e30c07add471562b45dce38517c9b2Colin Cross * This software is licensed under the terms of the GNU General Public 9d861196163e30c07add471562b45dce38517c9b2Colin Cross * License version 2, as published by the Free Software Foundation, and 10d861196163e30c07add471562b45dce38517c9b2Colin Cross * may be copied, distributed, and modified under those terms. 11d861196163e30c07add471562b45dce38517c9b2Colin Cross * 12d861196163e30c07add471562b45dce38517c9b2Colin Cross * This program is distributed in the hope that it will be useful, 13d861196163e30c07add471562b45dce38517c9b2Colin Cross * but WITHOUT ANY WARRANTY; without even the implied warranty of 14d861196163e30c07add471562b45dce38517c9b2Colin Cross * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15d861196163e30c07add471562b45dce38517c9b2Colin Cross * GNU General Public License for more details. 16d861196163e30c07add471562b45dce38517c9b2Colin Cross * 17d861196163e30c07add471562b45dce38517c9b2Colin Cross */ 18d861196163e30c07add471562b45dce38517c9b2Colin Cross 19d861196163e30c07add471562b45dce38517c9b2Colin Cross#include <linux/kernel.h> 20d861196163e30c07add471562b45dce38517c9b2Colin Cross#include <linux/clk.h> 214729fd7a7dfe7847b4870801ad12222adaeb016cColin Cross#include <linux/clkdev.h> 224729fd7a7dfe7847b4870801ad12222adaeb016cColin Cross#include <linux/debugfs.h> 234729fd7a7dfe7847b4870801ad12222adaeb016cColin Cross#include <linux/delay.h> 24d861196163e30c07add471562b45dce38517c9b2Colin Cross#include <linux/init.h> 254729fd7a7dfe7847b4870801ad12222adaeb016cColin Cross#include <linux/list.h> 26d861196163e30c07add471562b45dce38517c9b2Colin Cross#include <linux/module.h> 274729fd7a7dfe7847b4870801ad12222adaeb016cColin Cross#include <linux/sched.h> 28d861196163e30c07add471562b45dce38517c9b2Colin Cross#include <linux/seq_file.h> 294729fd7a7dfe7847b4870801ad12222adaeb016cColin Cross#include <linux/slab.h> 304729fd7a7dfe7847b4870801ad12222adaeb016cColin Cross 314729fd7a7dfe7847b4870801ad12222adaeb016cColin Cross#include <mach/clk.h> 32d861196163e30c07add471562b45dce38517c9b2Colin Cross 3371fc84cc35ee05913306bfe6e2454cdfc5bf7081Colin Cross#include "board.h" 3441cfe3676d0f4f07ba79d4f64a21450ab02d22cdColin Cross#include "clock.h" 35d861196163e30c07add471562b45dce38517c9b2Colin Cross 364729fd7a7dfe7847b4870801ad12222adaeb016cColin Cross/* 374729fd7a7dfe7847b4870801ad12222adaeb016cColin Cross * Locking: 384729fd7a7dfe7847b4870801ad12222adaeb016cColin Cross * 394729fd7a7dfe7847b4870801ad12222adaeb016cColin Cross * Each struct clk has a spinlock. 404729fd7a7dfe7847b4870801ad12222adaeb016cColin Cross * 414729fd7a7dfe7847b4870801ad12222adaeb016cColin Cross * To avoid AB-BA locking problems, locks must always be traversed from child 424729fd7a7dfe7847b4870801ad12222adaeb016cColin Cross * clock to parent clock. For example, when enabling a clock, the clock's lock 434729fd7a7dfe7847b4870801ad12222adaeb016cColin Cross * is taken, and then clk_enable is called on the parent, which take's the 444729fd7a7dfe7847b4870801ad12222adaeb016cColin Cross * parent clock's lock. There is one exceptions to this ordering: When dumping 454729fd7a7dfe7847b4870801ad12222adaeb016cColin Cross * the clock tree through debugfs. In this case, clk_lock_all is called, 464729fd7a7dfe7847b4870801ad12222adaeb016cColin Cross * which attemps to iterate through the entire list of clocks and take every 474729fd7a7dfe7847b4870801ad12222adaeb016cColin Cross * clock lock. If any call to spin_trylock fails, all locked clocks are 484729fd7a7dfe7847b4870801ad12222adaeb016cColin Cross * unlocked, and the process is retried. When all the locks are held, 494729fd7a7dfe7847b4870801ad12222adaeb016cColin Cross * the only clock operation that can be called is clk_get_rate_all_locked. 504729fd7a7dfe7847b4870801ad12222adaeb016cColin Cross * 514729fd7a7dfe7847b4870801ad12222adaeb016cColin Cross * Within a single clock, no clock operation can call another clock operation 524729fd7a7dfe7847b4870801ad12222adaeb016cColin Cross * on itself, except for clk_get_rate_locked and clk_set_rate_locked. Any 534729fd7a7dfe7847b4870801ad12222adaeb016cColin Cross * clock operation can call any other clock operation on any of it's possible 544729fd7a7dfe7847b4870801ad12222adaeb016cColin Cross * parents. 554729fd7a7dfe7847b4870801ad12222adaeb016cColin Cross * 564729fd7a7dfe7847b4870801ad12222adaeb016cColin Cross * An additional mutex, clock_list_lock, is used to protect the list of all 574729fd7a7dfe7847b4870801ad12222adaeb016cColin Cross * clocks. 584729fd7a7dfe7847b4870801ad12222adaeb016cColin Cross * 594729fd7a7dfe7847b4870801ad12222adaeb016cColin Cross * The clock operations must lock internally to protect against 604729fd7a7dfe7847b4870801ad12222adaeb016cColin Cross * read-modify-write on registers that are shared by multiple clocks 614729fd7a7dfe7847b4870801ad12222adaeb016cColin Cross */ 624729fd7a7dfe7847b4870801ad12222adaeb016cColin Crossstatic DEFINE_MUTEX(clock_list_lock); 63d861196163e30c07add471562b45dce38517c9b2Colin Crossstatic LIST_HEAD(clocks); 64d861196163e30c07add471562b45dce38517c9b2Colin Cross 65d861196163e30c07add471562b45dce38517c9b2Colin Crossstruct clk *tegra_get_clock_by_name(const char *name) 66d861196163e30c07add471562b45dce38517c9b2Colin Cross{ 67d861196163e30c07add471562b45dce38517c9b2Colin Cross struct clk *c; 68d861196163e30c07add471562b45dce38517c9b2Colin Cross struct clk *ret = NULL; 694729fd7a7dfe7847b4870801ad12222adaeb016cColin Cross mutex_lock(&clock_list_lock); 70d861196163e30c07add471562b45dce38517c9b2Colin Cross list_for_each_entry(c, &clocks, node) { 71d861196163e30c07add471562b45dce38517c9b2Colin Cross if (strcmp(c->name, name) == 0) { 72d861196163e30c07add471562b45dce38517c9b2Colin Cross ret = c; 73d861196163e30c07add471562b45dce38517c9b2Colin Cross break; 74d861196163e30c07add471562b45dce38517c9b2Colin Cross } 75d861196163e30c07add471562b45dce38517c9b2Colin Cross } 764729fd7a7dfe7847b4870801ad12222adaeb016cColin Cross mutex_unlock(&clock_list_lock); 77d861196163e30c07add471562b45dce38517c9b2Colin Cross return ret; 78d861196163e30c07add471562b45dce38517c9b2Colin Cross} 79d861196163e30c07add471562b45dce38517c9b2Colin Cross 804729fd7a7dfe7847b4870801ad12222adaeb016cColin Cross/* Must be called with c->spinlock held */ 814729fd7a7dfe7847b4870801ad12222adaeb016cColin Crossstatic unsigned long clk_predict_rate_from_parent(struct clk *c, struct clk *p) 8271fc84cc35ee05913306bfe6e2454cdfc5bf7081Colin Cross{ 8371fc84cc35ee05913306bfe6e2454cdfc5bf7081Colin Cross u64 rate; 8471fc84cc35ee05913306bfe6e2454cdfc5bf7081Colin Cross 854729fd7a7dfe7847b4870801ad12222adaeb016cColin Cross rate = clk_get_rate(p); 8671fc84cc35ee05913306bfe6e2454cdfc5bf7081Colin Cross 8771fc84cc35ee05913306bfe6e2454cdfc5bf7081Colin Cross if (c->mul != 0 && c->div != 0) { 884729fd7a7dfe7847b4870801ad12222adaeb016cColin Cross rate *= c->mul; 89421186e71000c067c2687baeffde62954a80cdccColin Cross rate += c->div - 1; /* round up */ 9071fc84cc35ee05913306bfe6e2454cdfc5bf7081Colin Cross do_div(rate, c->div); 9171fc84cc35ee05913306bfe6e2454cdfc5bf7081Colin Cross } 9271fc84cc35ee05913306bfe6e2454cdfc5bf7081Colin Cross 934729fd7a7dfe7847b4870801ad12222adaeb016cColin Cross return rate; 9471fc84cc35ee05913306bfe6e2454cdfc5bf7081Colin Cross} 9571fc84cc35ee05913306bfe6e2454cdfc5bf7081Colin Cross 964729fd7a7dfe7847b4870801ad12222adaeb016cColin Cross/* Must be called with c->spinlock held */ 974729fd7a7dfe7847b4870801ad12222adaeb016cColin Crossunsigned long clk_get_rate_locked(struct clk *c) 98d861196163e30c07add471562b45dce38517c9b2Colin Cross{ 994729fd7a7dfe7847b4870801ad12222adaeb016cColin Cross unsigned long rate; 100d861196163e30c07add471562b45dce38517c9b2Colin Cross 1014729fd7a7dfe7847b4870801ad12222adaeb016cColin Cross if (c->parent) 1024729fd7a7dfe7847b4870801ad12222adaeb016cColin Cross rate = clk_predict_rate_from_parent(c, c->parent); 1034729fd7a7dfe7847b4870801ad12222adaeb016cColin Cross else 1044729fd7a7dfe7847b4870801ad12222adaeb016cColin Cross rate = c->rate; 105bd41ef55e88ae03381569e51ad6ff3bab35e7b0eColin Cross 1064729fd7a7dfe7847b4870801ad12222adaeb016cColin Cross return rate; 107d861196163e30c07add471562b45dce38517c9b2Colin Cross} 108d861196163e30c07add471562b45dce38517c9b2Colin Cross 1094729fd7a7dfe7847b4870801ad12222adaeb016cColin Crossunsigned long clk_get_rate(struct clk *c) 110d861196163e30c07add471562b45dce38517c9b2Colin Cross{ 111d861196163e30c07add471562b45dce38517c9b2Colin Cross unsigned long flags; 1124729fd7a7dfe7847b4870801ad12222adaeb016cColin Cross unsigned long rate; 113d861196163e30c07add471562b45dce38517c9b2Colin Cross 1144729fd7a7dfe7847b4870801ad12222adaeb016cColin Cross spin_lock_irqsave(&c->spinlock, flags); 115d861196163e30c07add471562b45dce38517c9b2Colin Cross 1164729fd7a7dfe7847b4870801ad12222adaeb016cColin Cross rate = clk_get_rate_locked(c); 1174729fd7a7dfe7847b4870801ad12222adaeb016cColin Cross 1184729fd7a7dfe7847b4870801ad12222adaeb016cColin Cross spin_unlock_irqrestore(&c->spinlock, flags); 1194729fd7a7dfe7847b4870801ad12222adaeb016cColin Cross 1204729fd7a7dfe7847b4870801ad12222adaeb016cColin Cross return rate; 1214729fd7a7dfe7847b4870801ad12222adaeb016cColin Cross} 1224729fd7a7dfe7847b4870801ad12222adaeb016cColin CrossEXPORT_SYMBOL(clk_get_rate); 1234729fd7a7dfe7847b4870801ad12222adaeb016cColin Cross 1244729fd7a7dfe7847b4870801ad12222adaeb016cColin Crossint clk_reparent(struct clk *c, struct clk *parent) 1254729fd7a7dfe7847b4870801ad12222adaeb016cColin Cross{ 1264729fd7a7dfe7847b4870801ad12222adaeb016cColin Cross c->parent = parent; 1274729fd7a7dfe7847b4870801ad12222adaeb016cColin Cross return 0; 1284729fd7a7dfe7847b4870801ad12222adaeb016cColin Cross} 1294729fd7a7dfe7847b4870801ad12222adaeb016cColin Cross 1304729fd7a7dfe7847b4870801ad12222adaeb016cColin Crossvoid clk_init(struct clk *c) 1314729fd7a7dfe7847b4870801ad12222adaeb016cColin Cross{ 1324729fd7a7dfe7847b4870801ad12222adaeb016cColin Cross spin_lock_init(&c->spinlock); 133d861196163e30c07add471562b45dce38517c9b2Colin Cross 134d861196163e30c07add471562b45dce38517c9b2Colin Cross if (c->ops && c->ops->init) 135d861196163e30c07add471562b45dce38517c9b2Colin Cross c->ops->init(c); 136d861196163e30c07add471562b45dce38517c9b2Colin Cross 137f035530b799a9c945415ad2139bb6494b542639aColin Cross if (!c->ops || !c->ops->enable) { 138f035530b799a9c945415ad2139bb6494b542639aColin Cross c->refcnt++; 1394db4afb4df93425708ca19417921bcc6a6306476Colin Cross c->set = true; 140f035530b799a9c945415ad2139bb6494b542639aColin Cross if (c->parent) 141f035530b799a9c945415ad2139bb6494b542639aColin Cross c->state = c->parent->state; 142f035530b799a9c945415ad2139bb6494b542639aColin Cross else 143f035530b799a9c945415ad2139bb6494b542639aColin Cross c->state = ON; 144f035530b799a9c945415ad2139bb6494b542639aColin Cross } 145f035530b799a9c945415ad2139bb6494b542639aColin Cross 1464729fd7a7dfe7847b4870801ad12222adaeb016cColin Cross mutex_lock(&clock_list_lock); 147d861196163e30c07add471562b45dce38517c9b2Colin Cross list_add(&c->node, &clocks); 1484729fd7a7dfe7847b4870801ad12222adaeb016cColin Cross mutex_unlock(&clock_list_lock); 149d861196163e30c07add471562b45dce38517c9b2Colin Cross} 150d861196163e30c07add471562b45dce38517c9b2Colin Cross 1514729fd7a7dfe7847b4870801ad12222adaeb016cColin Crossint clk_enable(struct clk *c) 152d861196163e30c07add471562b45dce38517c9b2Colin Cross{ 1534729fd7a7dfe7847b4870801ad12222adaeb016cColin Cross int ret = 0; 1544729fd7a7dfe7847b4870801ad12222adaeb016cColin Cross unsigned long flags; 1554729fd7a7dfe7847b4870801ad12222adaeb016cColin Cross 1564729fd7a7dfe7847b4870801ad12222adaeb016cColin Cross spin_lock_irqsave(&c->spinlock, flags); 157bd41ef55e88ae03381569e51ad6ff3bab35e7b0eColin Cross 158d861196163e30c07add471562b45dce38517c9b2Colin Cross if (c->refcnt == 0) { 159d861196163e30c07add471562b45dce38517c9b2Colin Cross if (c->parent) { 1604729fd7a7dfe7847b4870801ad12222adaeb016cColin Cross ret = clk_enable(c->parent); 161d861196163e30c07add471562b45dce38517c9b2Colin Cross if (ret) 1624729fd7a7dfe7847b4870801ad12222adaeb016cColin Cross goto out; 163d861196163e30c07add471562b45dce38517c9b2Colin Cross } 164d861196163e30c07add471562b45dce38517c9b2Colin Cross 165d861196163e30c07add471562b45dce38517c9b2Colin Cross if (c->ops && c->ops->enable) { 166d861196163e30c07add471562b45dce38517c9b2Colin Cross ret = c->ops->enable(c); 167d861196163e30c07add471562b45dce38517c9b2Colin Cross if (ret) { 168d861196163e30c07add471562b45dce38517c9b2Colin Cross if (c->parent) 1694729fd7a7dfe7847b4870801ad12222adaeb016cColin Cross clk_disable(c->parent); 1704729fd7a7dfe7847b4870801ad12222adaeb016cColin Cross goto out; 171d861196163e30c07add471562b45dce38517c9b2Colin Cross } 172d861196163e30c07add471562b45dce38517c9b2Colin Cross c->state = ON; 1734db4afb4df93425708ca19417921bcc6a6306476Colin Cross c->set = true; 174d861196163e30c07add471562b45dce38517c9b2Colin Cross } 175d861196163e30c07add471562b45dce38517c9b2Colin Cross } 176d861196163e30c07add471562b45dce38517c9b2Colin Cross c->refcnt++; 1774729fd7a7dfe7847b4870801ad12222adaeb016cColin Crossout: 1784729fd7a7dfe7847b4870801ad12222adaeb016cColin Cross spin_unlock_irqrestore(&c->spinlock, flags); 1794729fd7a7dfe7847b4870801ad12222adaeb016cColin Cross return ret; 180d861196163e30c07add471562b45dce38517c9b2Colin Cross} 1814729fd7a7dfe7847b4870801ad12222adaeb016cColin CrossEXPORT_SYMBOL(clk_enable); 182d861196163e30c07add471562b45dce38517c9b2Colin Cross 1834729fd7a7dfe7847b4870801ad12222adaeb016cColin Crossvoid clk_disable(struct clk *c) 184d861196163e30c07add471562b45dce38517c9b2Colin Cross{ 185d861196163e30c07add471562b45dce38517c9b2Colin Cross unsigned long flags; 18671fc84cc35ee05913306bfe6e2454cdfc5bf7081Colin Cross 1874729fd7a7dfe7847b4870801ad12222adaeb016cColin Cross spin_lock_irqsave(&c->spinlock, flags); 18871fc84cc35ee05913306bfe6e2454cdfc5bf7081Colin Cross 189d861196163e30c07add471562b45dce38517c9b2Colin Cross if (c->refcnt == 0) { 190d861196163e30c07add471562b45dce38517c9b2Colin Cross WARN(1, "Attempting to disable clock %s with refcnt 0", c->name); 1914729fd7a7dfe7847b4870801ad12222adaeb016cColin Cross spin_unlock_irqrestore(&c->spinlock, flags); 192d861196163e30c07add471562b45dce38517c9b2Colin Cross return; 193d861196163e30c07add471562b45dce38517c9b2Colin Cross } 194d861196163e30c07add471562b45dce38517c9b2Colin Cross if (c->refcnt == 1) { 195d861196163e30c07add471562b45dce38517c9b2Colin Cross if (c->ops && c->ops->disable) 196d861196163e30c07add471562b45dce38517c9b2Colin Cross c->ops->disable(c); 197d861196163e30c07add471562b45dce38517c9b2Colin Cross 198d861196163e30c07add471562b45dce38517c9b2Colin Cross if (c->parent) 1994729fd7a7dfe7847b4870801ad12222adaeb016cColin Cross clk_disable(c->parent); 200d861196163e30c07add471562b45dce38517c9b2Colin Cross 201d861196163e30c07add471562b45dce38517c9b2Colin Cross c->state = OFF; 202d861196163e30c07add471562b45dce38517c9b2Colin Cross } 203d861196163e30c07add471562b45dce38517c9b2Colin Cross c->refcnt--; 204d861196163e30c07add471562b45dce38517c9b2Colin Cross 2054729fd7a7dfe7847b4870801ad12222adaeb016cColin Cross spin_unlock_irqrestore(&c->spinlock, flags); 206d861196163e30c07add471562b45dce38517c9b2Colin Cross} 207d861196163e30c07add471562b45dce38517c9b2Colin CrossEXPORT_SYMBOL(clk_disable); 208d861196163e30c07add471562b45dce38517c9b2Colin Cross 2094729fd7a7dfe7847b4870801ad12222adaeb016cColin Crossint clk_set_parent(struct clk *c, struct clk *parent) 210d861196163e30c07add471562b45dce38517c9b2Colin Cross{ 211d861196163e30c07add471562b45dce38517c9b2Colin Cross int ret; 2124729fd7a7dfe7847b4870801ad12222adaeb016cColin Cross unsigned long flags; 2134729fd7a7dfe7847b4870801ad12222adaeb016cColin Cross unsigned long new_rate; 2144729fd7a7dfe7847b4870801ad12222adaeb016cColin Cross unsigned long old_rate; 215d861196163e30c07add471562b45dce38517c9b2Colin Cross 2164729fd7a7dfe7847b4870801ad12222adaeb016cColin Cross spin_lock_irqsave(&c->spinlock, flags); 217d861196163e30c07add471562b45dce38517c9b2Colin Cross 2184729fd7a7dfe7847b4870801ad12222adaeb016cColin Cross if (!c->ops || !c->ops->set_parent) { 2194729fd7a7dfe7847b4870801ad12222adaeb016cColin Cross ret = -ENOSYS; 2204729fd7a7dfe7847b4870801ad12222adaeb016cColin Cross goto out; 2214729fd7a7dfe7847b4870801ad12222adaeb016cColin Cross } 22271fc84cc35ee05913306bfe6e2454cdfc5bf7081Colin Cross 2234729fd7a7dfe7847b4870801ad12222adaeb016cColin Cross new_rate = clk_predict_rate_from_parent(c, parent); 2244729fd7a7dfe7847b4870801ad12222adaeb016cColin Cross old_rate = clk_get_rate_locked(c); 225d861196163e30c07add471562b45dce38517c9b2Colin Cross 2264729fd7a7dfe7847b4870801ad12222adaeb016cColin Cross ret = c->ops->set_parent(c, parent); 2274729fd7a7dfe7847b4870801ad12222adaeb016cColin Cross if (ret) 2284729fd7a7dfe7847b4870801ad12222adaeb016cColin Cross goto out; 229d861196163e30c07add471562b45dce38517c9b2Colin Cross 2304729fd7a7dfe7847b4870801ad12222adaeb016cColin Crossout: 2314729fd7a7dfe7847b4870801ad12222adaeb016cColin Cross spin_unlock_irqrestore(&c->spinlock, flags); 232d861196163e30c07add471562b45dce38517c9b2Colin Cross return ret; 233d861196163e30c07add471562b45dce38517c9b2Colin Cross} 234d861196163e30c07add471562b45dce38517c9b2Colin CrossEXPORT_SYMBOL(clk_set_parent); 235d861196163e30c07add471562b45dce38517c9b2Colin Cross 236d861196163e30c07add471562b45dce38517c9b2Colin Crossstruct clk *clk_get_parent(struct clk *c) 237d861196163e30c07add471562b45dce38517c9b2Colin Cross{ 238d861196163e30c07add471562b45dce38517c9b2Colin Cross return c->parent; 239d861196163e30c07add471562b45dce38517c9b2Colin Cross} 240d861196163e30c07add471562b45dce38517c9b2Colin CrossEXPORT_SYMBOL(clk_get_parent); 241d861196163e30c07add471562b45dce38517c9b2Colin Cross 24271fc84cc35ee05913306bfe6e2454cdfc5bf7081Colin Crossint clk_set_rate_locked(struct clk *c, unsigned long rate) 24371fc84cc35ee05913306bfe6e2454cdfc5bf7081Colin Cross{ 244421186e71000c067c2687baeffde62954a80cdccColin Cross long new_rate; 245421186e71000c067c2687baeffde62954a80cdccColin Cross 24671fc84cc35ee05913306bfe6e2454cdfc5bf7081Colin Cross if (!c->ops || !c->ops->set_rate) 24771fc84cc35ee05913306bfe6e2454cdfc5bf7081Colin Cross return -ENOSYS; 24871fc84cc35ee05913306bfe6e2454cdfc5bf7081Colin Cross 2494729fd7a7dfe7847b4870801ad12222adaeb016cColin Cross if (rate > c->max_rate) 2504729fd7a7dfe7847b4870801ad12222adaeb016cColin Cross rate = c->max_rate; 25171fc84cc35ee05913306bfe6e2454cdfc5bf7081Colin Cross 252421186e71000c067c2687baeffde62954a80cdccColin Cross if (c->ops && c->ops->round_rate) { 253421186e71000c067c2687baeffde62954a80cdccColin Cross new_rate = c->ops->round_rate(c, rate); 254421186e71000c067c2687baeffde62954a80cdccColin Cross 255421186e71000c067c2687baeffde62954a80cdccColin Cross if (new_rate < 0) 256421186e71000c067c2687baeffde62954a80cdccColin Cross return new_rate; 257421186e71000c067c2687baeffde62954a80cdccColin Cross 258421186e71000c067c2687baeffde62954a80cdccColin Cross rate = new_rate; 259421186e71000c067c2687baeffde62954a80cdccColin Cross } 260421186e71000c067c2687baeffde62954a80cdccColin Cross 2614729fd7a7dfe7847b4870801ad12222adaeb016cColin Cross return c->ops->set_rate(c, rate); 26271fc84cc35ee05913306bfe6e2454cdfc5bf7081Colin Cross} 26371fc84cc35ee05913306bfe6e2454cdfc5bf7081Colin Cross 26471fc84cc35ee05913306bfe6e2454cdfc5bf7081Colin Crossint clk_set_rate(struct clk *c, unsigned long rate) 26571fc84cc35ee05913306bfe6e2454cdfc5bf7081Colin Cross{ 2664729fd7a7dfe7847b4870801ad12222adaeb016cColin Cross int ret; 26771fc84cc35ee05913306bfe6e2454cdfc5bf7081Colin Cross unsigned long flags; 26871fc84cc35ee05913306bfe6e2454cdfc5bf7081Colin Cross 2694729fd7a7dfe7847b4870801ad12222adaeb016cColin Cross spin_lock_irqsave(&c->spinlock, flags); 2704729fd7a7dfe7847b4870801ad12222adaeb016cColin Cross 27171fc84cc35ee05913306bfe6e2454cdfc5bf7081Colin Cross ret = clk_set_rate_locked(c, rate); 2724729fd7a7dfe7847b4870801ad12222adaeb016cColin Cross 2734729fd7a7dfe7847b4870801ad12222adaeb016cColin Cross spin_unlock_irqrestore(&c->spinlock, flags); 274d861196163e30c07add471562b45dce38517c9b2Colin Cross 275d861196163e30c07add471562b45dce38517c9b2Colin Cross return ret; 276d861196163e30c07add471562b45dce38517c9b2Colin Cross} 277d861196163e30c07add471562b45dce38517c9b2Colin CrossEXPORT_SYMBOL(clk_set_rate); 278d861196163e30c07add471562b45dce38517c9b2Colin Cross 279d861196163e30c07add471562b45dce38517c9b2Colin Cross 2804729fd7a7dfe7847b4870801ad12222adaeb016cColin Cross/* Must be called with clocks lock and all indvidual clock locks held */ 2814729fd7a7dfe7847b4870801ad12222adaeb016cColin Crossunsigned long clk_get_rate_all_locked(struct clk *c) 2824729fd7a7dfe7847b4870801ad12222adaeb016cColin Cross{ 2834729fd7a7dfe7847b4870801ad12222adaeb016cColin Cross u64 rate; 2844729fd7a7dfe7847b4870801ad12222adaeb016cColin Cross int mul = 1; 2854729fd7a7dfe7847b4870801ad12222adaeb016cColin Cross int div = 1; 2864729fd7a7dfe7847b4870801ad12222adaeb016cColin Cross struct clk *p = c; 2874729fd7a7dfe7847b4870801ad12222adaeb016cColin Cross 2884729fd7a7dfe7847b4870801ad12222adaeb016cColin Cross while (p) { 2894729fd7a7dfe7847b4870801ad12222adaeb016cColin Cross c = p; 2904729fd7a7dfe7847b4870801ad12222adaeb016cColin Cross if (c->mul != 0 && c->div != 0) { 2914729fd7a7dfe7847b4870801ad12222adaeb016cColin Cross mul *= c->mul; 2924729fd7a7dfe7847b4870801ad12222adaeb016cColin Cross div *= c->div; 2934729fd7a7dfe7847b4870801ad12222adaeb016cColin Cross } 2944729fd7a7dfe7847b4870801ad12222adaeb016cColin Cross p = c->parent; 2954729fd7a7dfe7847b4870801ad12222adaeb016cColin Cross } 296d861196163e30c07add471562b45dce38517c9b2Colin Cross 2974729fd7a7dfe7847b4870801ad12222adaeb016cColin Cross rate = c->rate; 2984729fd7a7dfe7847b4870801ad12222adaeb016cColin Cross rate *= mul; 2994729fd7a7dfe7847b4870801ad12222adaeb016cColin Cross do_div(rate, div); 300d861196163e30c07add471562b45dce38517c9b2Colin Cross 3014729fd7a7dfe7847b4870801ad12222adaeb016cColin Cross return rate; 302d861196163e30c07add471562b45dce38517c9b2Colin Cross} 303d861196163e30c07add471562b45dce38517c9b2Colin Cross 30471fc84cc35ee05913306bfe6e2454cdfc5bf7081Colin Crosslong clk_round_rate(struct clk *c, unsigned long rate) 30571fc84cc35ee05913306bfe6e2454cdfc5bf7081Colin Cross{ 3064729fd7a7dfe7847b4870801ad12222adaeb016cColin Cross unsigned long flags; 3074729fd7a7dfe7847b4870801ad12222adaeb016cColin Cross long ret; 3084729fd7a7dfe7847b4870801ad12222adaeb016cColin Cross 3094729fd7a7dfe7847b4870801ad12222adaeb016cColin Cross spin_lock_irqsave(&c->spinlock, flags); 3104729fd7a7dfe7847b4870801ad12222adaeb016cColin Cross 3114729fd7a7dfe7847b4870801ad12222adaeb016cColin Cross if (!c->ops || !c->ops->round_rate) { 3124729fd7a7dfe7847b4870801ad12222adaeb016cColin Cross ret = -ENOSYS; 3134729fd7a7dfe7847b4870801ad12222adaeb016cColin Cross goto out; 3144729fd7a7dfe7847b4870801ad12222adaeb016cColin Cross } 31571fc84cc35ee05913306bfe6e2454cdfc5bf7081Colin Cross 31671fc84cc35ee05913306bfe6e2454cdfc5bf7081Colin Cross if (rate > c->max_rate) 31771fc84cc35ee05913306bfe6e2454cdfc5bf7081Colin Cross rate = c->max_rate; 31871fc84cc35ee05913306bfe6e2454cdfc5bf7081Colin Cross 3194729fd7a7dfe7847b4870801ad12222adaeb016cColin Cross ret = c->ops->round_rate(c, rate); 3204729fd7a7dfe7847b4870801ad12222adaeb016cColin Cross 3214729fd7a7dfe7847b4870801ad12222adaeb016cColin Crossout: 3224729fd7a7dfe7847b4870801ad12222adaeb016cColin Cross spin_unlock_irqrestore(&c->spinlock, flags); 3234729fd7a7dfe7847b4870801ad12222adaeb016cColin Cross return ret; 32471fc84cc35ee05913306bfe6e2454cdfc5bf7081Colin Cross} 32571fc84cc35ee05913306bfe6e2454cdfc5bf7081Colin CrossEXPORT_SYMBOL(clk_round_rate); 32671fc84cc35ee05913306bfe6e2454cdfc5bf7081Colin Cross 327d861196163e30c07add471562b45dce38517c9b2Colin Crossstatic int tegra_clk_init_one_from_table(struct tegra_clk_init_table *table) 328d861196163e30c07add471562b45dce38517c9b2Colin Cross{ 329d861196163e30c07add471562b45dce38517c9b2Colin Cross struct clk *c; 330d861196163e30c07add471562b45dce38517c9b2Colin Cross struct clk *p; 331d861196163e30c07add471562b45dce38517c9b2Colin Cross 332d861196163e30c07add471562b45dce38517c9b2Colin Cross int ret = 0; 333d861196163e30c07add471562b45dce38517c9b2Colin Cross 334d861196163e30c07add471562b45dce38517c9b2Colin Cross c = tegra_get_clock_by_name(table->name); 335d861196163e30c07add471562b45dce38517c9b2Colin Cross 336d861196163e30c07add471562b45dce38517c9b2Colin Cross if (!c) { 337d861196163e30c07add471562b45dce38517c9b2Colin Cross pr_warning("Unable to initialize clock %s\n", 338d861196163e30c07add471562b45dce38517c9b2Colin Cross table->name); 339d861196163e30c07add471562b45dce38517c9b2Colin Cross return -ENODEV; 340d861196163e30c07add471562b45dce38517c9b2Colin Cross } 341d861196163e30c07add471562b45dce38517c9b2Colin Cross 342d861196163e30c07add471562b45dce38517c9b2Colin Cross if (table->parent) { 343d861196163e30c07add471562b45dce38517c9b2Colin Cross p = tegra_get_clock_by_name(table->parent); 344d861196163e30c07add471562b45dce38517c9b2Colin Cross if (!p) { 345d861196163e30c07add471562b45dce38517c9b2Colin Cross pr_warning("Unable to find parent %s of clock %s\n", 346d861196163e30c07add471562b45dce38517c9b2Colin Cross table->parent, table->name); 347d861196163e30c07add471562b45dce38517c9b2Colin Cross return -ENODEV; 348d861196163e30c07add471562b45dce38517c9b2Colin Cross } 349d861196163e30c07add471562b45dce38517c9b2Colin Cross 350d861196163e30c07add471562b45dce38517c9b2Colin Cross if (c->parent != p) { 351d861196163e30c07add471562b45dce38517c9b2Colin Cross ret = clk_set_parent(c, p); 352d861196163e30c07add471562b45dce38517c9b2Colin Cross if (ret) { 353d861196163e30c07add471562b45dce38517c9b2Colin Cross pr_warning("Unable to set parent %s of clock %s: %d\n", 354d861196163e30c07add471562b45dce38517c9b2Colin Cross table->parent, table->name, ret); 355d861196163e30c07add471562b45dce38517c9b2Colin Cross return -EINVAL; 356d861196163e30c07add471562b45dce38517c9b2Colin Cross } 357d861196163e30c07add471562b45dce38517c9b2Colin Cross } 358d861196163e30c07add471562b45dce38517c9b2Colin Cross } 359d861196163e30c07add471562b45dce38517c9b2Colin Cross 360d861196163e30c07add471562b45dce38517c9b2Colin Cross if (table->rate && table->rate != clk_get_rate(c)) { 361d861196163e30c07add471562b45dce38517c9b2Colin Cross ret = clk_set_rate(c, table->rate); 362d861196163e30c07add471562b45dce38517c9b2Colin Cross if (ret) { 363d861196163e30c07add471562b45dce38517c9b2Colin Cross pr_warning("Unable to set clock %s to rate %lu: %d\n", 364d861196163e30c07add471562b45dce38517c9b2Colin Cross table->name, table->rate, ret); 365d861196163e30c07add471562b45dce38517c9b2Colin Cross return -EINVAL; 366d861196163e30c07add471562b45dce38517c9b2Colin Cross } 367d861196163e30c07add471562b45dce38517c9b2Colin Cross } 368d861196163e30c07add471562b45dce38517c9b2Colin Cross 369d861196163e30c07add471562b45dce38517c9b2Colin Cross if (table->enabled) { 370d861196163e30c07add471562b45dce38517c9b2Colin Cross ret = clk_enable(c); 371d861196163e30c07add471562b45dce38517c9b2Colin Cross if (ret) { 372d861196163e30c07add471562b45dce38517c9b2Colin Cross pr_warning("Unable to enable clock %s: %d\n", 373d861196163e30c07add471562b45dce38517c9b2Colin Cross table->name, ret); 374d861196163e30c07add471562b45dce38517c9b2Colin Cross return -EINVAL; 375d861196163e30c07add471562b45dce38517c9b2Colin Cross } 376d861196163e30c07add471562b45dce38517c9b2Colin Cross } 377d861196163e30c07add471562b45dce38517c9b2Colin Cross 378d861196163e30c07add471562b45dce38517c9b2Colin Cross return 0; 379d861196163e30c07add471562b45dce38517c9b2Colin Cross} 380d861196163e30c07add471562b45dce38517c9b2Colin Cross 381d861196163e30c07add471562b45dce38517c9b2Colin Crossvoid tegra_clk_init_from_table(struct tegra_clk_init_table *table) 382d861196163e30c07add471562b45dce38517c9b2Colin Cross{ 383d861196163e30c07add471562b45dce38517c9b2Colin Cross for (; table->name; table++) 384d861196163e30c07add471562b45dce38517c9b2Colin Cross tegra_clk_init_one_from_table(table); 385d861196163e30c07add471562b45dce38517c9b2Colin Cross} 386d861196163e30c07add471562b45dce38517c9b2Colin CrossEXPORT_SYMBOL(tegra_clk_init_from_table); 387d861196163e30c07add471562b45dce38517c9b2Colin Cross 388d861196163e30c07add471562b45dce38517c9b2Colin Crossvoid tegra_periph_reset_deassert(struct clk *c) 389d861196163e30c07add471562b45dce38517c9b2Colin Cross{ 390742face03f57727b5a86d0df631e47a1ef0498d2Peter De Schrijver BUG_ON(!c->ops->reset); 391742face03f57727b5a86d0df631e47a1ef0498d2Peter De Schrijver c->ops->reset(c, false); 392d861196163e30c07add471562b45dce38517c9b2Colin Cross} 393d861196163e30c07add471562b45dce38517c9b2Colin CrossEXPORT_SYMBOL(tegra_periph_reset_deassert); 394d861196163e30c07add471562b45dce38517c9b2Colin Cross 395d861196163e30c07add471562b45dce38517c9b2Colin Crossvoid tegra_periph_reset_assert(struct clk *c) 396d861196163e30c07add471562b45dce38517c9b2Colin Cross{ 397742face03f57727b5a86d0df631e47a1ef0498d2Peter De Schrijver BUG_ON(!c->ops->reset); 398742face03f57727b5a86d0df631e47a1ef0498d2Peter De Schrijver c->ops->reset(c, true); 399d861196163e30c07add471562b45dce38517c9b2Colin Cross} 400d861196163e30c07add471562b45dce38517c9b2Colin CrossEXPORT_SYMBOL(tegra_periph_reset_assert); 401d861196163e30c07add471562b45dce38517c9b2Colin Cross 4024fccf75ba3bee0bb3be7828caa03625d4ac100a2Peter De Schrijver/* Several extended clock configuration bits (e.g., clock routing, clock 4034fccf75ba3bee0bb3be7828caa03625d4ac100a2Peter De Schrijver * phase control) are included in PLL and peripheral clock source 4044fccf75ba3bee0bb3be7828caa03625d4ac100a2Peter De Schrijver * registers. */ 4054fccf75ba3bee0bb3be7828caa03625d4ac100a2Peter De Schrijverint tegra_clk_cfg_ex(struct clk *c, enum tegra_clk_ex_param p, u32 setting) 4064fccf75ba3bee0bb3be7828caa03625d4ac100a2Peter De Schrijver{ 4074fccf75ba3bee0bb3be7828caa03625d4ac100a2Peter De Schrijver int ret = 0; 4084fccf75ba3bee0bb3be7828caa03625d4ac100a2Peter De Schrijver unsigned long flags; 4094fccf75ba3bee0bb3be7828caa03625d4ac100a2Peter De Schrijver 4104fccf75ba3bee0bb3be7828caa03625d4ac100a2Peter De Schrijver spin_lock_irqsave(&c->spinlock, flags); 4114fccf75ba3bee0bb3be7828caa03625d4ac100a2Peter De Schrijver 4124fccf75ba3bee0bb3be7828caa03625d4ac100a2Peter De Schrijver if (!c->ops || !c->ops->clk_cfg_ex) { 4134fccf75ba3bee0bb3be7828caa03625d4ac100a2Peter De Schrijver ret = -ENOSYS; 4144fccf75ba3bee0bb3be7828caa03625d4ac100a2Peter De Schrijver goto out; 4154fccf75ba3bee0bb3be7828caa03625d4ac100a2Peter De Schrijver } 4164fccf75ba3bee0bb3be7828caa03625d4ac100a2Peter De Schrijver ret = c->ops->clk_cfg_ex(c, p, setting); 4174fccf75ba3bee0bb3be7828caa03625d4ac100a2Peter De Schrijver 4184fccf75ba3bee0bb3be7828caa03625d4ac100a2Peter De Schrijverout: 4194fccf75ba3bee0bb3be7828caa03625d4ac100a2Peter De Schrijver spin_unlock_irqrestore(&c->spinlock, flags); 4204fccf75ba3bee0bb3be7828caa03625d4ac100a2Peter De Schrijver 4214fccf75ba3bee0bb3be7828caa03625d4ac100a2Peter De Schrijver return ret; 4224fccf75ba3bee0bb3be7828caa03625d4ac100a2Peter De Schrijver} 4234fccf75ba3bee0bb3be7828caa03625d4ac100a2Peter De Schrijver 424d861196163e30c07add471562b45dce38517c9b2Colin Cross#ifdef CONFIG_DEBUG_FS 4254729fd7a7dfe7847b4870801ad12222adaeb016cColin Cross 4264729fd7a7dfe7847b4870801ad12222adaeb016cColin Crossstatic int __clk_lock_all_spinlocks(void) 4274729fd7a7dfe7847b4870801ad12222adaeb016cColin Cross{ 4284729fd7a7dfe7847b4870801ad12222adaeb016cColin Cross struct clk *c; 4294729fd7a7dfe7847b4870801ad12222adaeb016cColin Cross 4304729fd7a7dfe7847b4870801ad12222adaeb016cColin Cross list_for_each_entry(c, &clocks, node) 4314729fd7a7dfe7847b4870801ad12222adaeb016cColin Cross if (!spin_trylock(&c->spinlock)) 4324729fd7a7dfe7847b4870801ad12222adaeb016cColin Cross goto unlock_spinlocks; 4334729fd7a7dfe7847b4870801ad12222adaeb016cColin Cross 4344729fd7a7dfe7847b4870801ad12222adaeb016cColin Cross return 0; 4354729fd7a7dfe7847b4870801ad12222adaeb016cColin Cross 4364729fd7a7dfe7847b4870801ad12222adaeb016cColin Crossunlock_spinlocks: 4374729fd7a7dfe7847b4870801ad12222adaeb016cColin Cross list_for_each_entry_continue_reverse(c, &clocks, node) 4384729fd7a7dfe7847b4870801ad12222adaeb016cColin Cross spin_unlock(&c->spinlock); 4394729fd7a7dfe7847b4870801ad12222adaeb016cColin Cross 4404729fd7a7dfe7847b4870801ad12222adaeb016cColin Cross return -EAGAIN; 4414729fd7a7dfe7847b4870801ad12222adaeb016cColin Cross} 4424729fd7a7dfe7847b4870801ad12222adaeb016cColin Cross 4434729fd7a7dfe7847b4870801ad12222adaeb016cColin Crossstatic void __clk_unlock_all_spinlocks(void) 4444729fd7a7dfe7847b4870801ad12222adaeb016cColin Cross{ 4454729fd7a7dfe7847b4870801ad12222adaeb016cColin Cross struct clk *c; 4464729fd7a7dfe7847b4870801ad12222adaeb016cColin Cross 4474729fd7a7dfe7847b4870801ad12222adaeb016cColin Cross list_for_each_entry_reverse(c, &clocks, node) 4484729fd7a7dfe7847b4870801ad12222adaeb016cColin Cross spin_unlock(&c->spinlock); 4494729fd7a7dfe7847b4870801ad12222adaeb016cColin Cross} 4504729fd7a7dfe7847b4870801ad12222adaeb016cColin Cross 4514729fd7a7dfe7847b4870801ad12222adaeb016cColin Cross/* 4524729fd7a7dfe7847b4870801ad12222adaeb016cColin Cross * This function retries until it can take all locks, and may take 4534729fd7a7dfe7847b4870801ad12222adaeb016cColin Cross * an arbitrarily long time to complete. 4544729fd7a7dfe7847b4870801ad12222adaeb016cColin Cross * Must be called with irqs enabled, returns with irqs disabled 4554729fd7a7dfe7847b4870801ad12222adaeb016cColin Cross * Must be called with clock_list_lock held 4564729fd7a7dfe7847b4870801ad12222adaeb016cColin Cross */ 4574729fd7a7dfe7847b4870801ad12222adaeb016cColin Crossstatic void clk_lock_all(void) 4584729fd7a7dfe7847b4870801ad12222adaeb016cColin Cross{ 4594729fd7a7dfe7847b4870801ad12222adaeb016cColin Cross int ret; 4604729fd7a7dfe7847b4870801ad12222adaeb016cColin Crossretry: 4614729fd7a7dfe7847b4870801ad12222adaeb016cColin Cross local_irq_disable(); 4624729fd7a7dfe7847b4870801ad12222adaeb016cColin Cross 4634729fd7a7dfe7847b4870801ad12222adaeb016cColin Cross ret = __clk_lock_all_spinlocks(); 4644729fd7a7dfe7847b4870801ad12222adaeb016cColin Cross if (ret) 4654729fd7a7dfe7847b4870801ad12222adaeb016cColin Cross goto failed_spinlocks; 4664729fd7a7dfe7847b4870801ad12222adaeb016cColin Cross 4674729fd7a7dfe7847b4870801ad12222adaeb016cColin Cross /* All locks taken successfully, return */ 4684729fd7a7dfe7847b4870801ad12222adaeb016cColin Cross return; 4694729fd7a7dfe7847b4870801ad12222adaeb016cColin Cross 4704729fd7a7dfe7847b4870801ad12222adaeb016cColin Crossfailed_spinlocks: 4714729fd7a7dfe7847b4870801ad12222adaeb016cColin Cross local_irq_enable(); 4724729fd7a7dfe7847b4870801ad12222adaeb016cColin Cross yield(); 4734729fd7a7dfe7847b4870801ad12222adaeb016cColin Cross goto retry; 4744729fd7a7dfe7847b4870801ad12222adaeb016cColin Cross} 4754729fd7a7dfe7847b4870801ad12222adaeb016cColin Cross 4764729fd7a7dfe7847b4870801ad12222adaeb016cColin Cross/* 4774729fd7a7dfe7847b4870801ad12222adaeb016cColin Cross * Unlocks all clocks after a clk_lock_all 4784729fd7a7dfe7847b4870801ad12222adaeb016cColin Cross * Must be called with irqs disabled, returns with irqs enabled 4794729fd7a7dfe7847b4870801ad12222adaeb016cColin Cross * Must be called with clock_list_lock held 4804729fd7a7dfe7847b4870801ad12222adaeb016cColin Cross */ 4814729fd7a7dfe7847b4870801ad12222adaeb016cColin Crossstatic void clk_unlock_all(void) 4824729fd7a7dfe7847b4870801ad12222adaeb016cColin Cross{ 4834729fd7a7dfe7847b4870801ad12222adaeb016cColin Cross __clk_unlock_all_spinlocks(); 4844729fd7a7dfe7847b4870801ad12222adaeb016cColin Cross 4854729fd7a7dfe7847b4870801ad12222adaeb016cColin Cross local_irq_enable(); 4864729fd7a7dfe7847b4870801ad12222adaeb016cColin Cross} 4874729fd7a7dfe7847b4870801ad12222adaeb016cColin Cross 488d861196163e30c07add471562b45dce38517c9b2Colin Crossstatic struct dentry *clk_debugfs_root; 489d861196163e30c07add471562b45dce38517c9b2Colin Cross 490d861196163e30c07add471562b45dce38517c9b2Colin Cross 491d861196163e30c07add471562b45dce38517c9b2Colin Crossstatic void clock_tree_show_one(struct seq_file *s, struct clk *c, int level) 492d861196163e30c07add471562b45dce38517c9b2Colin Cross{ 493d861196163e30c07add471562b45dce38517c9b2Colin Cross struct clk *child; 494d861196163e30c07add471562b45dce38517c9b2Colin Cross const char *state = "uninit"; 49571fc84cc35ee05913306bfe6e2454cdfc5bf7081Colin Cross char div[8] = {0}; 496d861196163e30c07add471562b45dce38517c9b2Colin Cross 497d861196163e30c07add471562b45dce38517c9b2Colin Cross if (c->state == ON) 498d861196163e30c07add471562b45dce38517c9b2Colin Cross state = "on"; 499d861196163e30c07add471562b45dce38517c9b2Colin Cross else if (c->state == OFF) 500d861196163e30c07add471562b45dce38517c9b2Colin Cross state = "off"; 501d861196163e30c07add471562b45dce38517c9b2Colin Cross 502d861196163e30c07add471562b45dce38517c9b2Colin Cross if (c->mul != 0 && c->div != 0) { 50371fc84cc35ee05913306bfe6e2454cdfc5bf7081Colin Cross if (c->mul > c->div) { 50471fc84cc35ee05913306bfe6e2454cdfc5bf7081Colin Cross int mul = c->mul / c->div; 50571fc84cc35ee05913306bfe6e2454cdfc5bf7081Colin Cross int mul2 = (c->mul * 10 / c->div) % 10; 50671fc84cc35ee05913306bfe6e2454cdfc5bf7081Colin Cross int mul3 = (c->mul * 10) % c->div; 50771fc84cc35ee05913306bfe6e2454cdfc5bf7081Colin Cross if (mul2 == 0 && mul3 == 0) 50871fc84cc35ee05913306bfe6e2454cdfc5bf7081Colin Cross snprintf(div, sizeof(div), "x%d", mul); 50971fc84cc35ee05913306bfe6e2454cdfc5bf7081Colin Cross else if (mul3 == 0) 51071fc84cc35ee05913306bfe6e2454cdfc5bf7081Colin Cross snprintf(div, sizeof(div), "x%d.%d", mul, mul2); 51171fc84cc35ee05913306bfe6e2454cdfc5bf7081Colin Cross else 51271fc84cc35ee05913306bfe6e2454cdfc5bf7081Colin Cross snprintf(div, sizeof(div), "x%d.%d..", mul, mul2); 51371fc84cc35ee05913306bfe6e2454cdfc5bf7081Colin Cross } else { 514d861196163e30c07add471562b45dce38517c9b2Colin Cross snprintf(div, sizeof(div), "%d%s", c->div / c->mul, 515d861196163e30c07add471562b45dce38517c9b2Colin Cross (c->div % c->mul) ? ".5" : ""); 51671fc84cc35ee05913306bfe6e2454cdfc5bf7081Colin Cross } 517d861196163e30c07add471562b45dce38517c9b2Colin Cross } 518d861196163e30c07add471562b45dce38517c9b2Colin Cross 51971fc84cc35ee05913306bfe6e2454cdfc5bf7081Colin Cross seq_printf(s, "%*s%c%c%-*s %-6s %-3d %-8s %-10lu\n", 52071fc84cc35ee05913306bfe6e2454cdfc5bf7081Colin Cross level * 3 + 1, "", 52171fc84cc35ee05913306bfe6e2454cdfc5bf7081Colin Cross c->rate > c->max_rate ? '!' : ' ', 52271fc84cc35ee05913306bfe6e2454cdfc5bf7081Colin Cross !c->set ? '*' : ' ', 523d861196163e30c07add471562b45dce38517c9b2Colin Cross 30 - level * 3, c->name, 5244729fd7a7dfe7847b4870801ad12222adaeb016cColin Cross state, c->refcnt, div, clk_get_rate_all_locked(c)); 5254729fd7a7dfe7847b4870801ad12222adaeb016cColin Cross 5264729fd7a7dfe7847b4870801ad12222adaeb016cColin Cross list_for_each_entry(child, &clocks, node) { 5274729fd7a7dfe7847b4870801ad12222adaeb016cColin Cross if (child->parent != c) 5284729fd7a7dfe7847b4870801ad12222adaeb016cColin Cross continue; 5294729fd7a7dfe7847b4870801ad12222adaeb016cColin Cross 530d861196163e30c07add471562b45dce38517c9b2Colin Cross clock_tree_show_one(s, child, level + 1); 531d861196163e30c07add471562b45dce38517c9b2Colin Cross } 532d861196163e30c07add471562b45dce38517c9b2Colin Cross} 533d861196163e30c07add471562b45dce38517c9b2Colin Cross 534d861196163e30c07add471562b45dce38517c9b2Colin Crossstatic int clock_tree_show(struct seq_file *s, void *data) 535d861196163e30c07add471562b45dce38517c9b2Colin Cross{ 536d861196163e30c07add471562b45dce38517c9b2Colin Cross struct clk *c; 53771fc84cc35ee05913306bfe6e2454cdfc5bf7081Colin Cross seq_printf(s, " clock state ref div rate\n"); 53871fc84cc35ee05913306bfe6e2454cdfc5bf7081Colin Cross seq_printf(s, "--------------------------------------------------------------\n"); 5394729fd7a7dfe7847b4870801ad12222adaeb016cColin Cross 5404729fd7a7dfe7847b4870801ad12222adaeb016cColin Cross mutex_lock(&clock_list_lock); 5414729fd7a7dfe7847b4870801ad12222adaeb016cColin Cross 5424729fd7a7dfe7847b4870801ad12222adaeb016cColin Cross clk_lock_all(); 5434729fd7a7dfe7847b4870801ad12222adaeb016cColin Cross 544d861196163e30c07add471562b45dce38517c9b2Colin Cross list_for_each_entry(c, &clocks, node) 545d861196163e30c07add471562b45dce38517c9b2Colin Cross if (c->parent == NULL) 546d861196163e30c07add471562b45dce38517c9b2Colin Cross clock_tree_show_one(s, c, 0); 5474729fd7a7dfe7847b4870801ad12222adaeb016cColin Cross 5484729fd7a7dfe7847b4870801ad12222adaeb016cColin Cross clk_unlock_all(); 5494729fd7a7dfe7847b4870801ad12222adaeb016cColin Cross 5504729fd7a7dfe7847b4870801ad12222adaeb016cColin Cross mutex_unlock(&clock_list_lock); 551d861196163e30c07add471562b45dce38517c9b2Colin Cross return 0; 552d861196163e30c07add471562b45dce38517c9b2Colin Cross} 553d861196163e30c07add471562b45dce38517c9b2Colin Cross 554d861196163e30c07add471562b45dce38517c9b2Colin Crossstatic int clock_tree_open(struct inode *inode, struct file *file) 555d861196163e30c07add471562b45dce38517c9b2Colin Cross{ 556d861196163e30c07add471562b45dce38517c9b2Colin Cross return single_open(file, clock_tree_show, inode->i_private); 557d861196163e30c07add471562b45dce38517c9b2Colin Cross} 558d861196163e30c07add471562b45dce38517c9b2Colin Cross 559d861196163e30c07add471562b45dce38517c9b2Colin Crossstatic const struct file_operations clock_tree_fops = { 560d861196163e30c07add471562b45dce38517c9b2Colin Cross .open = clock_tree_open, 561d861196163e30c07add471562b45dce38517c9b2Colin Cross .read = seq_read, 562d861196163e30c07add471562b45dce38517c9b2Colin Cross .llseek = seq_lseek, 563d861196163e30c07add471562b45dce38517c9b2Colin Cross .release = single_release, 564d861196163e30c07add471562b45dce38517c9b2Colin Cross}; 565d861196163e30c07add471562b45dce38517c9b2Colin Cross 566d861196163e30c07add471562b45dce38517c9b2Colin Crossstatic int possible_parents_show(struct seq_file *s, void *data) 567d861196163e30c07add471562b45dce38517c9b2Colin Cross{ 568d861196163e30c07add471562b45dce38517c9b2Colin Cross struct clk *c = s->private; 569d861196163e30c07add471562b45dce38517c9b2Colin Cross int i; 570d861196163e30c07add471562b45dce38517c9b2Colin Cross 571d861196163e30c07add471562b45dce38517c9b2Colin Cross for (i = 0; c->inputs[i].input; i++) { 572d861196163e30c07add471562b45dce38517c9b2Colin Cross char *first = (i == 0) ? "" : " "; 573d861196163e30c07add471562b45dce38517c9b2Colin Cross seq_printf(s, "%s%s", first, c->inputs[i].input->name); 574d861196163e30c07add471562b45dce38517c9b2Colin Cross } 575d861196163e30c07add471562b45dce38517c9b2Colin Cross seq_printf(s, "\n"); 576d861196163e30c07add471562b45dce38517c9b2Colin Cross return 0; 577d861196163e30c07add471562b45dce38517c9b2Colin Cross} 578d861196163e30c07add471562b45dce38517c9b2Colin Cross 579d861196163e30c07add471562b45dce38517c9b2Colin Crossstatic int possible_parents_open(struct inode *inode, struct file *file) 580d861196163e30c07add471562b45dce38517c9b2Colin Cross{ 581d861196163e30c07add471562b45dce38517c9b2Colin Cross return single_open(file, possible_parents_show, inode->i_private); 582d861196163e30c07add471562b45dce38517c9b2Colin Cross} 583d861196163e30c07add471562b45dce38517c9b2Colin Cross 584d861196163e30c07add471562b45dce38517c9b2Colin Crossstatic const struct file_operations possible_parents_fops = { 585d861196163e30c07add471562b45dce38517c9b2Colin Cross .open = possible_parents_open, 586d861196163e30c07add471562b45dce38517c9b2Colin Cross .read = seq_read, 587d861196163e30c07add471562b45dce38517c9b2Colin Cross .llseek = seq_lseek, 588d861196163e30c07add471562b45dce38517c9b2Colin Cross .release = single_release, 589d861196163e30c07add471562b45dce38517c9b2Colin Cross}; 590d861196163e30c07add471562b45dce38517c9b2Colin Cross 591d861196163e30c07add471562b45dce38517c9b2Colin Crossstatic int clk_debugfs_register_one(struct clk *c) 592d861196163e30c07add471562b45dce38517c9b2Colin Cross{ 59312520c438f48113593130d210eba821a532c893bAl Viro struct dentry *d; 594d861196163e30c07add471562b45dce38517c9b2Colin Cross 595d861196163e30c07add471562b45dce38517c9b2Colin Cross d = debugfs_create_dir(c->name, clk_debugfs_root); 596d861196163e30c07add471562b45dce38517c9b2Colin Cross if (!d) 597d861196163e30c07add471562b45dce38517c9b2Colin Cross return -ENOMEM; 598d861196163e30c07add471562b45dce38517c9b2Colin Cross c->dent = d; 599d861196163e30c07add471562b45dce38517c9b2Colin Cross 600d861196163e30c07add471562b45dce38517c9b2Colin Cross d = debugfs_create_u8("refcnt", S_IRUGO, c->dent, (u8 *)&c->refcnt); 601d861196163e30c07add471562b45dce38517c9b2Colin Cross if (!d) 602d861196163e30c07add471562b45dce38517c9b2Colin Cross goto err_out; 603d861196163e30c07add471562b45dce38517c9b2Colin Cross 604d861196163e30c07add471562b45dce38517c9b2Colin Cross d = debugfs_create_u32("rate", S_IRUGO, c->dent, (u32 *)&c->rate); 605d861196163e30c07add471562b45dce38517c9b2Colin Cross if (!d) 606d861196163e30c07add471562b45dce38517c9b2Colin Cross goto err_out; 607d861196163e30c07add471562b45dce38517c9b2Colin Cross 608d861196163e30c07add471562b45dce38517c9b2Colin Cross d = debugfs_create_x32("flags", S_IRUGO, c->dent, (u32 *)&c->flags); 609d861196163e30c07add471562b45dce38517c9b2Colin Cross if (!d) 610d861196163e30c07add471562b45dce38517c9b2Colin Cross goto err_out; 611d861196163e30c07add471562b45dce38517c9b2Colin Cross 612d861196163e30c07add471562b45dce38517c9b2Colin Cross if (c->inputs) { 613d861196163e30c07add471562b45dce38517c9b2Colin Cross d = debugfs_create_file("possible_parents", S_IRUGO, c->dent, 614d861196163e30c07add471562b45dce38517c9b2Colin Cross c, &possible_parents_fops); 615d861196163e30c07add471562b45dce38517c9b2Colin Cross if (!d) 616d861196163e30c07add471562b45dce38517c9b2Colin Cross goto err_out; 617d861196163e30c07add471562b45dce38517c9b2Colin Cross } 618d861196163e30c07add471562b45dce38517c9b2Colin Cross 619d861196163e30c07add471562b45dce38517c9b2Colin Cross return 0; 620d861196163e30c07add471562b45dce38517c9b2Colin Cross 621d861196163e30c07add471562b45dce38517c9b2Colin Crosserr_out: 62212520c438f48113593130d210eba821a532c893bAl Viro debugfs_remove_recursive(c->dent); 623d861196163e30c07add471562b45dce38517c9b2Colin Cross return -ENOMEM; 624d861196163e30c07add471562b45dce38517c9b2Colin Cross} 625d861196163e30c07add471562b45dce38517c9b2Colin Cross 626d861196163e30c07add471562b45dce38517c9b2Colin Crossstatic int clk_debugfs_register(struct clk *c) 627d861196163e30c07add471562b45dce38517c9b2Colin Cross{ 628d861196163e30c07add471562b45dce38517c9b2Colin Cross int err; 629d861196163e30c07add471562b45dce38517c9b2Colin Cross struct clk *pa = c->parent; 630d861196163e30c07add471562b45dce38517c9b2Colin Cross 631d861196163e30c07add471562b45dce38517c9b2Colin Cross if (pa && !pa->dent) { 632d861196163e30c07add471562b45dce38517c9b2Colin Cross err = clk_debugfs_register(pa); 633d861196163e30c07add471562b45dce38517c9b2Colin Cross if (err) 634d861196163e30c07add471562b45dce38517c9b2Colin Cross return err; 635d861196163e30c07add471562b45dce38517c9b2Colin Cross } 636d861196163e30c07add471562b45dce38517c9b2Colin Cross 637d861196163e30c07add471562b45dce38517c9b2Colin Cross if (!c->dent) { 638d861196163e30c07add471562b45dce38517c9b2Colin Cross err = clk_debugfs_register_one(c); 639d861196163e30c07add471562b45dce38517c9b2Colin Cross if (err) 640d861196163e30c07add471562b45dce38517c9b2Colin Cross return err; 641d861196163e30c07add471562b45dce38517c9b2Colin Cross } 642d861196163e30c07add471562b45dce38517c9b2Colin Cross return 0; 643d861196163e30c07add471562b45dce38517c9b2Colin Cross} 644d861196163e30c07add471562b45dce38517c9b2Colin Cross 645d861196163e30c07add471562b45dce38517c9b2Colin Crossstatic int __init clk_debugfs_init(void) 646d861196163e30c07add471562b45dce38517c9b2Colin Cross{ 647d861196163e30c07add471562b45dce38517c9b2Colin Cross struct clk *c; 648d861196163e30c07add471562b45dce38517c9b2Colin Cross struct dentry *d; 649d861196163e30c07add471562b45dce38517c9b2Colin Cross int err = -ENOMEM; 650d861196163e30c07add471562b45dce38517c9b2Colin Cross 651d861196163e30c07add471562b45dce38517c9b2Colin Cross d = debugfs_create_dir("clock", NULL); 652d861196163e30c07add471562b45dce38517c9b2Colin Cross if (!d) 653d861196163e30c07add471562b45dce38517c9b2Colin Cross return -ENOMEM; 654d861196163e30c07add471562b45dce38517c9b2Colin Cross clk_debugfs_root = d; 655d861196163e30c07add471562b45dce38517c9b2Colin Cross 656d861196163e30c07add471562b45dce38517c9b2Colin Cross d = debugfs_create_file("clock_tree", S_IRUGO, clk_debugfs_root, NULL, 657d861196163e30c07add471562b45dce38517c9b2Colin Cross &clock_tree_fops); 658d861196163e30c07add471562b45dce38517c9b2Colin Cross if (!d) 659d861196163e30c07add471562b45dce38517c9b2Colin Cross goto err_out; 660d861196163e30c07add471562b45dce38517c9b2Colin Cross 661d861196163e30c07add471562b45dce38517c9b2Colin Cross list_for_each_entry(c, &clocks, node) { 662d861196163e30c07add471562b45dce38517c9b2Colin Cross err = clk_debugfs_register(c); 663d861196163e30c07add471562b45dce38517c9b2Colin Cross if (err) 664d861196163e30c07add471562b45dce38517c9b2Colin Cross goto err_out; 665d861196163e30c07add471562b45dce38517c9b2Colin Cross } 666d861196163e30c07add471562b45dce38517c9b2Colin Cross return 0; 667d861196163e30c07add471562b45dce38517c9b2Colin Crosserr_out: 668d861196163e30c07add471562b45dce38517c9b2Colin Cross debugfs_remove_recursive(clk_debugfs_root); 669d861196163e30c07add471562b45dce38517c9b2Colin Cross return err; 670d861196163e30c07add471562b45dce38517c9b2Colin Cross} 671d861196163e30c07add471562b45dce38517c9b2Colin Cross 672d861196163e30c07add471562b45dce38517c9b2Colin Crosslate_initcall(clk_debugfs_init); 673d861196163e30c07add471562b45dce38517c9b2Colin Cross#endif 674