diff options
author | Srikant Patnaik | 2015-01-11 12:28:04 +0530 |
---|---|---|
committer | Srikant Patnaik | 2015-01-11 12:28:04 +0530 |
commit | 871480933a1c28f8a9fed4c4d34d06c439a7a422 (patch) | |
tree | 8718f573808810c2a1e8cb8fb6ac469093ca2784 /ANDROID_3.4.5/drivers/clk | |
parent | 9d40ac5867b9aefe0722bc1f110b965ff294d30d (diff) | |
download | FOSSEE-netbook-kernel-source-871480933a1c28f8a9fed4c4d34d06c439a7a422.tar.gz FOSSEE-netbook-kernel-source-871480933a1c28f8a9fed4c4d34d06c439a7a422.tar.bz2 FOSSEE-netbook-kernel-source-871480933a1c28f8a9fed4c4d34d06c439a7a422.zip |
Moved, renamed, and deleted files
The original directory structure was scattered and unorganized.
Changes are basically to make it look like kernel structure.
Diffstat (limited to 'ANDROID_3.4.5/drivers/clk')
-rw-r--r-- | ANDROID_3.4.5/drivers/clk/Kconfig | 47 | ||||
-rw-r--r-- | ANDROID_3.4.5/drivers/clk/Makefile | 4 | ||||
-rw-r--r-- | ANDROID_3.4.5/drivers/clk/clk-divider.c | 200 | ||||
-rw-r--r-- | ANDROID_3.4.5/drivers/clk/clk-fixed-rate.c | 82 | ||||
-rw-r--r-- | ANDROID_3.4.5/drivers/clk/clk-gate.c | 150 | ||||
-rw-r--r-- | ANDROID_3.4.5/drivers/clk/clk-mux.c | 116 | ||||
-rw-r--r-- | ANDROID_3.4.5/drivers/clk/clk.c | 1464 | ||||
-rw-r--r-- | ANDROID_3.4.5/drivers/clk/clkdev.c | 175 |
8 files changed, 0 insertions, 2238 deletions
diff --git a/ANDROID_3.4.5/drivers/clk/Kconfig b/ANDROID_3.4.5/drivers/clk/Kconfig deleted file mode 100644 index 165e1feb..00000000 --- a/ANDROID_3.4.5/drivers/clk/Kconfig +++ /dev/null @@ -1,47 +0,0 @@ - -config CLKDEV_LOOKUP - bool - select HAVE_CLK - -config HAVE_CLK_PREPARE - bool - -config HAVE_MACH_CLKDEV - bool - -config COMMON_CLK - bool - select HAVE_CLK_PREPARE - ---help--- - The common clock framework is a single definition of struct - clk, useful across many platforms, as well as an - implementation of the clock API in include/linux/clk.h. - Architectures utilizing the common struct clk should select - this option. - -menu "Common Clock Framework" - depends on COMMON_CLK - -config COMMON_CLK_DISABLE_UNUSED - bool "Disabled unused clocks at boot" - depends on COMMON_CLK - ---help--- - Traverses the entire clock tree and disables any clocks that are - enabled in hardware but have not been enabled by any device drivers. - This saves power and keeps the software model of the clock in line - with reality. - - If in doubt, say "N". - -config COMMON_CLK_DEBUG - bool "DebugFS representation of clock tree" - depends on COMMON_CLK - select DEBUG_FS - ---help--- - Creates a directory hierchy in debugfs for visualizing the clk - tree structure. Each directory contains read-only members - that export information specific to that clk node: clk_rate, - clk_flags, clk_prepare_count, clk_enable_count & - clk_notifier_count. - -endmenu diff --git a/ANDROID_3.4.5/drivers/clk/Makefile b/ANDROID_3.4.5/drivers/clk/Makefile deleted file mode 100644 index 1f736bc1..00000000 --- a/ANDROID_3.4.5/drivers/clk/Makefile +++ /dev/null @@ -1,4 +0,0 @@ - -obj-$(CONFIG_CLKDEV_LOOKUP) += clkdev.o -obj-$(CONFIG_COMMON_CLK) += clk.o clk-fixed-rate.o clk-gate.o \ - clk-mux.o clk-divider.o diff --git a/ANDROID_3.4.5/drivers/clk/clk-divider.c b/ANDROID_3.4.5/drivers/clk/clk-divider.c deleted file mode 100644 index d5ac6a75..00000000 --- a/ANDROID_3.4.5/drivers/clk/clk-divider.c +++ /dev/null @@ -1,200 +0,0 @@ -/* - * Copyright (C) 2011 Sascha Hauer, Pengutronix <s.hauer@pengutronix.de> - * Copyright (C) 2011 Richard Zhao, Linaro <richard.zhao@linaro.org> - * Copyright (C) 2011-2012 Mike Turquette, Linaro Ltd <mturquette@linaro.org> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Adjustable divider clock implementation - */ - -#include <linux/clk-provider.h> -#include <linux/module.h> -#include <linux/slab.h> -#include <linux/io.h> -#include <linux/err.h> -#include <linux/string.h> - -/* - * DOC: basic adjustable divider clock that cannot gate - * - * Traits of this clock: - * prepare - clk_prepare only ensures that parents are prepared - * enable - clk_enable only ensures that parents are enabled - * rate - rate is adjustable. clk->rate = parent->rate / divisor - * parent - fixed parent. No clk_set_parent support - */ - -#define to_clk_divider(_hw) container_of(_hw, struct clk_divider, hw) - -#define div_mask(d) ((1 << (d->width)) - 1) - -static unsigned long clk_divider_recalc_rate(struct clk_hw *hw, - unsigned long parent_rate) -{ - struct clk_divider *divider = to_clk_divider(hw); - unsigned int div; - - div = readl(divider->reg) >> divider->shift; - div &= div_mask(divider); - - if (!(divider->flags & CLK_DIVIDER_ONE_BASED)) - div++; - - return parent_rate / div; -} -EXPORT_SYMBOL_GPL(clk_divider_recalc_rate); - -/* - * The reverse of DIV_ROUND_UP: The maximum number which - * divided by m is r - */ -#define MULT_ROUND_UP(r, m) ((r) * (m) + (m) - 1) - -static int clk_divider_bestdiv(struct clk_hw *hw, unsigned long rate, - unsigned long *best_parent_rate) -{ - struct clk_divider *divider = to_clk_divider(hw); - int i, bestdiv = 0; - unsigned long parent_rate, best = 0, now, maxdiv; - - if (!rate) - rate = 1; - - maxdiv = (1 << divider->width); - - if (divider->flags & CLK_DIVIDER_ONE_BASED) - maxdiv--; - - if (!best_parent_rate) { - parent_rate = __clk_get_rate(__clk_get_parent(hw->clk)); - bestdiv = DIV_ROUND_UP(parent_rate, rate); - bestdiv = bestdiv == 0 ? 1 : bestdiv; - bestdiv = bestdiv > maxdiv ? maxdiv : bestdiv; - return bestdiv; - } - - /* - * The maximum divider we can use without overflowing - * unsigned long in rate * i below - */ - maxdiv = min(ULONG_MAX / rate, maxdiv); - - for (i = 1; i <= maxdiv; i++) { - parent_rate = __clk_round_rate(__clk_get_parent(hw->clk), - MULT_ROUND_UP(rate, i)); - now = parent_rate / i; - if (now <= rate && now > best) { - bestdiv = i; - best = now; - *best_parent_rate = parent_rate; - } - } - - if (!bestdiv) { - bestdiv = (1 << divider->width); - if (divider->flags & CLK_DIVIDER_ONE_BASED) - bestdiv--; - *best_parent_rate = __clk_round_rate(__clk_get_parent(hw->clk), 1); - } - - return bestdiv; -} - -static long clk_divider_round_rate(struct clk_hw *hw, unsigned long rate, - unsigned long *prate) -{ - int div; - div = clk_divider_bestdiv(hw, rate, prate); - - if (prate) - return *prate / div; - else { - unsigned long r; - r = __clk_get_rate(__clk_get_parent(hw->clk)); - return r / div; - } -} -EXPORT_SYMBOL_GPL(clk_divider_round_rate); - -static int clk_divider_set_rate(struct clk_hw *hw, unsigned long rate) -{ - struct clk_divider *divider = to_clk_divider(hw); - unsigned int div; - unsigned long flags = 0; - u32 val; - - div = __clk_get_rate(__clk_get_parent(hw->clk)) / rate; - - if (!(divider->flags & CLK_DIVIDER_ONE_BASED)) - div--; - - if (div > div_mask(divider)) - div = div_mask(divider); - - if (divider->lock) - spin_lock_irqsave(divider->lock, flags); - - val = readl(divider->reg); - val &= ~(div_mask(divider) << divider->shift); - val |= div << divider->shift; - writel(val, divider->reg); - - if (divider->lock) - spin_unlock_irqrestore(divider->lock, flags); - - return 0; -} -EXPORT_SYMBOL_GPL(clk_divider_set_rate); - -struct clk_ops clk_divider_ops = { - .recalc_rate = clk_divider_recalc_rate, - .round_rate = clk_divider_round_rate, - .set_rate = clk_divider_set_rate, -}; -EXPORT_SYMBOL_GPL(clk_divider_ops); - -struct clk *clk_register_divider(struct device *dev, const char *name, - const char *parent_name, unsigned long flags, - void __iomem *reg, u8 shift, u8 width, - u8 clk_divider_flags, spinlock_t *lock) -{ - struct clk_divider *div; - struct clk *clk; - - div = kzalloc(sizeof(struct clk_divider), GFP_KERNEL); - - if (!div) { - pr_err("%s: could not allocate divider clk\n", __func__); - return NULL; - } - - /* struct clk_divider assignments */ - div->reg = reg; - div->shift = shift; - div->width = width; - div->flags = clk_divider_flags; - div->lock = lock; - - if (parent_name) { - div->parent[0] = kstrdup(parent_name, GFP_KERNEL); - if (!div->parent[0]) - goto out; - } - - clk = clk_register(dev, name, - &clk_divider_ops, &div->hw, - div->parent, - (parent_name ? 1 : 0), - flags); - if (clk) - return clk; - -out: - kfree(div->parent[0]); - kfree(div); - - return NULL; -} diff --git a/ANDROID_3.4.5/drivers/clk/clk-fixed-rate.c b/ANDROID_3.4.5/drivers/clk/clk-fixed-rate.c deleted file mode 100644 index 90c79fb5..00000000 --- a/ANDROID_3.4.5/drivers/clk/clk-fixed-rate.c +++ /dev/null @@ -1,82 +0,0 @@ -/* - * Copyright (C) 2010-2011 Canonical Ltd <jeremy.kerr@canonical.com> - * Copyright (C) 2011-2012 Mike Turquette, Linaro Ltd <mturquette@linaro.org> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Fixed rate clock implementation - */ - -#include <linux/clk-provider.h> -#include <linux/module.h> -#include <linux/slab.h> -#include <linux/io.h> -#include <linux/err.h> - -/* - * DOC: basic fixed-rate clock that cannot gate - * - * Traits of this clock: - * prepare - clk_(un)prepare only ensures parents are prepared - * enable - clk_enable only ensures parents are enabled - * rate - rate is always a fixed value. No clk_set_rate support - * parent - fixed parent. No clk_set_parent support - */ - -#define to_clk_fixed_rate(_hw) container_of(_hw, struct clk_fixed_rate, hw) - -static unsigned long clk_fixed_rate_recalc_rate(struct clk_hw *hw, - unsigned long parent_rate) -{ - return to_clk_fixed_rate(hw)->fixed_rate; -} -EXPORT_SYMBOL_GPL(clk_fixed_rate_recalc_rate); - -struct clk_ops clk_fixed_rate_ops = { - .recalc_rate = clk_fixed_rate_recalc_rate, -}; -EXPORT_SYMBOL_GPL(clk_fixed_rate_ops); - -struct clk *clk_register_fixed_rate(struct device *dev, const char *name, - const char *parent_name, unsigned long flags, - unsigned long fixed_rate) -{ - struct clk_fixed_rate *fixed; - char **parent_names = NULL; - u8 len; - - fixed = kzalloc(sizeof(struct clk_fixed_rate), GFP_KERNEL); - - if (!fixed) { - pr_err("%s: could not allocate fixed clk\n", __func__); - return ERR_PTR(-ENOMEM); - } - - /* struct clk_fixed_rate assignments */ - fixed->fixed_rate = fixed_rate; - - if (parent_name) { - parent_names = kmalloc(sizeof(char *), GFP_KERNEL); - - if (! parent_names) - goto out; - - len = sizeof(char) * strlen(parent_name); - - parent_names[0] = kmalloc(len, GFP_KERNEL); - - if (!parent_names[0]) - goto out; - - strncpy(parent_names[0], parent_name, len); - } - -out: - return clk_register(dev, name, - &clk_fixed_rate_ops, &fixed->hw, - parent_names, - (parent_name ? 1 : 0), - flags); -} diff --git a/ANDROID_3.4.5/drivers/clk/clk-gate.c b/ANDROID_3.4.5/drivers/clk/clk-gate.c deleted file mode 100644 index b5902e2e..00000000 --- a/ANDROID_3.4.5/drivers/clk/clk-gate.c +++ /dev/null @@ -1,150 +0,0 @@ -/* - * Copyright (C) 2010-2011 Canonical Ltd <jeremy.kerr@canonical.com> - * Copyright (C) 2011-2012 Mike Turquette, Linaro Ltd <mturquette@linaro.org> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Gated clock implementation - */ - -#include <linux/clk-provider.h> -#include <linux/module.h> -#include <linux/slab.h> -#include <linux/io.h> -#include <linux/err.h> -#include <linux/string.h> - -/** - * DOC: basic gatable clock which can gate and ungate it's ouput - * - * Traits of this clock: - * prepare - clk_(un)prepare only ensures parent is (un)prepared - * enable - clk_enable and clk_disable are functional & control gating - * rate - inherits rate from parent. No clk_set_rate support - * parent - fixed parent. No clk_set_parent support - */ - -#define to_clk_gate(_hw) container_of(_hw, struct clk_gate, hw) - -static void clk_gate_set_bit(struct clk_gate *gate) -{ - u32 reg; - unsigned long flags = 0; - - if (gate->lock) - spin_lock_irqsave(gate->lock, flags); - - reg = readl(gate->reg); - reg |= BIT(gate->bit_idx); - writel(reg, gate->reg); - - if (gate->lock) - spin_unlock_irqrestore(gate->lock, flags); -} - -static void clk_gate_clear_bit(struct clk_gate *gate) -{ - u32 reg; - unsigned long flags = 0; - - if (gate->lock) - spin_lock_irqsave(gate->lock, flags); - - reg = readl(gate->reg); - reg &= ~BIT(gate->bit_idx); - writel(reg, gate->reg); - - if (gate->lock) - spin_unlock_irqrestore(gate->lock, flags); -} - -static int clk_gate_enable(struct clk_hw *hw) -{ - struct clk_gate *gate = to_clk_gate(hw); - - if (gate->flags & CLK_GATE_SET_TO_DISABLE) - clk_gate_clear_bit(gate); - else - clk_gate_set_bit(gate); - - return 0; -} -EXPORT_SYMBOL_GPL(clk_gate_enable); - -static void clk_gate_disable(struct clk_hw *hw) -{ - struct clk_gate *gate = to_clk_gate(hw); - - if (gate->flags & CLK_GATE_SET_TO_DISABLE) - clk_gate_set_bit(gate); - else - clk_gate_clear_bit(gate); -} -EXPORT_SYMBOL_GPL(clk_gate_disable); - -static int clk_gate_is_enabled(struct clk_hw *hw) -{ - u32 reg; - struct clk_gate *gate = to_clk_gate(hw); - - reg = readl(gate->reg); - - /* if a set bit disables this clk, flip it before masking */ - if (gate->flags & CLK_GATE_SET_TO_DISABLE) - reg ^= BIT(gate->bit_idx); - - reg &= BIT(gate->bit_idx); - - return reg ? 1 : 0; -} -EXPORT_SYMBOL_GPL(clk_gate_is_enabled); - -struct clk_ops clk_gate_ops = { - .enable = clk_gate_enable, - .disable = clk_gate_disable, - .is_enabled = clk_gate_is_enabled, -}; -EXPORT_SYMBOL_GPL(clk_gate_ops); - -struct clk *clk_register_gate(struct device *dev, const char *name, - const char *parent_name, unsigned long flags, - void __iomem *reg, u8 bit_idx, - u8 clk_gate_flags, spinlock_t *lock) -{ - struct clk_gate *gate; - struct clk *clk; - - gate = kzalloc(sizeof(struct clk_gate), GFP_KERNEL); - - if (!gate) { - pr_err("%s: could not allocate gated clk\n", __func__); - return NULL; - } - - /* struct clk_gate assignments */ - gate->reg = reg; - gate->bit_idx = bit_idx; - gate->flags = clk_gate_flags; - gate->lock = lock; - - if (parent_name) { - gate->parent[0] = kstrdup(parent_name, GFP_KERNEL); - if (!gate->parent[0]) - goto out; - } - - clk = clk_register(dev, name, - &clk_gate_ops, &gate->hw, - gate->parent, - (parent_name ? 1 : 0), - flags); - if (clk) - return clk; -out: - kfree(gate->parent[0]); - kfree(gate); - - return NULL; -} diff --git a/ANDROID_3.4.5/drivers/clk/clk-mux.c b/ANDROID_3.4.5/drivers/clk/clk-mux.c deleted file mode 100644 index c71ad1f4..00000000 --- a/ANDROID_3.4.5/drivers/clk/clk-mux.c +++ /dev/null @@ -1,116 +0,0 @@ -/* - * Copyright (C) 2011 Sascha Hauer, Pengutronix <s.hauer@pengutronix.de> - * Copyright (C) 2011 Richard Zhao, Linaro <richard.zhao@linaro.org> - * Copyright (C) 2011-2012 Mike Turquette, Linaro Ltd <mturquette@linaro.org> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Simple multiplexer clock implementation - */ - -#include <linux/clk.h> -#include <linux/clk-provider.h> -#include <linux/module.h> -#include <linux/slab.h> -#include <linux/io.h> -#include <linux/err.h> - -/* - * DOC: basic adjustable multiplexer clock that cannot gate - * - * Traits of this clock: - * prepare - clk_prepare only ensures that parents are prepared - * enable - clk_enable only ensures that parents are enabled - * rate - rate is only affected by parent switching. No clk_set_rate support - * parent - parent is adjustable through clk_set_parent - */ - -#define to_clk_mux(_hw) container_of(_hw, struct clk_mux, hw) - -static u8 clk_mux_get_parent(struct clk_hw *hw) -{ - struct clk_mux *mux = to_clk_mux(hw); - u32 val; - - /* - * FIXME need a mux-specific flag to determine if val is bitwise or numeric - * e.g. sys_clkin_ck's clksel field is 3 bits wide, but ranges from 0x1 - * to 0x7 (index starts at one) - * OTOH, pmd_trace_clk_mux_ck uses a separate bit for each clock, so - * val = 0x4 really means "bit 2, index starts at bit 0" - */ - val = readl(mux->reg) >> mux->shift; - val &= (1 << mux->width) - 1; - - if (val && (mux->flags & CLK_MUX_INDEX_BIT)) - val = ffs(val) - 1; - - if (val && (mux->flags & CLK_MUX_INDEX_ONE)) - val--; - - if (val >= __clk_get_num_parents(hw->clk)) - return -EINVAL; - - return val; -} -EXPORT_SYMBOL_GPL(clk_mux_get_parent); - -static int clk_mux_set_parent(struct clk_hw *hw, u8 index) -{ - struct clk_mux *mux = to_clk_mux(hw); - u32 val; - unsigned long flags = 0; - - if (mux->flags & CLK_MUX_INDEX_BIT) - index = (1 << ffs(index)); - - if (mux->flags & CLK_MUX_INDEX_ONE) - index++; - - if (mux->lock) - spin_lock_irqsave(mux->lock, flags); - - val = readl(mux->reg); - val &= ~(((1 << mux->width) - 1) << mux->shift); - val |= index << mux->shift; - writel(val, mux->reg); - - if (mux->lock) - spin_unlock_irqrestore(mux->lock, flags); - - return 0; -} -EXPORT_SYMBOL_GPL(clk_mux_set_parent); - -struct clk_ops clk_mux_ops = { - .get_parent = clk_mux_get_parent, - .set_parent = clk_mux_set_parent, -}; -EXPORT_SYMBOL_GPL(clk_mux_ops); - -struct clk *clk_register_mux(struct device *dev, const char *name, - char **parent_names, u8 num_parents, unsigned long flags, - void __iomem *reg, u8 shift, u8 width, - u8 clk_mux_flags, spinlock_t *lock) -{ - struct clk_mux *mux; - - mux = kmalloc(sizeof(struct clk_mux), GFP_KERNEL); - - if (!mux) { - pr_err("%s: could not allocate mux clk\n", __func__); - return ERR_PTR(-ENOMEM); - } - - /* struct clk_mux assignments */ - mux->reg = reg; - mux->shift = shift; - mux->width = width; - mux->flags = clk_mux_flags; - mux->lock = lock; - - return clk_register(dev, name, &clk_mux_ops, &mux->hw, - parent_names, num_parents, flags); -} diff --git a/ANDROID_3.4.5/drivers/clk/clk.c b/ANDROID_3.4.5/drivers/clk/clk.c deleted file mode 100644 index 2da025ee..00000000 --- a/ANDROID_3.4.5/drivers/clk/clk.c +++ /dev/null @@ -1,1464 +0,0 @@ -/* - * Copyright (C) 2010-2011 Canonical Ltd <jeremy.kerr@canonical.com> - * Copyright (C) 2011-2012 Linaro Ltd <mturquette@linaro.org> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Standard functionality for the common clock API. See Documentation/clk.txt - */ - -#include <linux/clk-private.h> -#include <linux/module.h> -#include <linux/mutex.h> -#include <linux/spinlock.h> -#include <linux/err.h> -#include <linux/list.h> -#include <linux/slab.h> - -static DEFINE_SPINLOCK(enable_lock); -static DEFINE_MUTEX(prepare_lock); - -static HLIST_HEAD(clk_root_list); -static HLIST_HEAD(clk_orphan_list); -static LIST_HEAD(clk_notifier_list); - -/*** debugfs support ***/ - -#ifdef CONFIG_COMMON_CLK_DEBUG -#include <linux/debugfs.h> - -static struct dentry *rootdir; -static struct dentry *orphandir; -static int inited = 0; - -/* caller must hold prepare_lock */ -static int clk_debug_create_one(struct clk *clk, struct dentry *pdentry) -{ - struct dentry *d; - int ret = -ENOMEM; - - if (!clk || !pdentry) { - ret = -EINVAL; - goto out; - } - - d = debugfs_create_dir(clk->name, pdentry); - if (!d) - goto out; - - clk->dentry = d; - - d = debugfs_create_u32("clk_rate", S_IRUGO, clk->dentry, - (u32 *)&clk->rate); - if (!d) - goto err_out; - - d = debugfs_create_x32("clk_flags", S_IRUGO, clk->dentry, - (u32 *)&clk->flags); - if (!d) - goto err_out; - - d = debugfs_create_u32("clk_prepare_count", S_IRUGO, clk->dentry, - (u32 *)&clk->prepare_count); - if (!d) - goto err_out; - - d = debugfs_create_u32("clk_enable_count", S_IRUGO, clk->dentry, - (u32 *)&clk->enable_count); - if (!d) - goto err_out; - - d = debugfs_create_u32("clk_notifier_count", S_IRUGO, clk->dentry, - (u32 *)&clk->notifier_count); - if (!d) - goto err_out; - - ret = 0; - goto out; - -err_out: - debugfs_remove(clk->dentry); -out: - return ret; -} - -/* caller must hold prepare_lock */ -static int clk_debug_create_subtree(struct clk *clk, struct dentry *pdentry) -{ - struct clk *child; - struct hlist_node *tmp; - int ret = -EINVAL;; - - if (!clk || !pdentry) - goto out; - - ret = clk_debug_create_one(clk, pdentry); - - if (ret) - goto out; - - hlist_for_each_entry(child, tmp, &clk->children, child_node) - clk_debug_create_subtree(child, clk->dentry); - - ret = 0; -out: - return ret; -} - -/** - * clk_debug_register - add a clk node to the debugfs clk tree - * @clk: the clk being added to the debugfs clk tree - * - * Dynamically adds a clk to the debugfs clk tree if debugfs has been - * initialized. Otherwise it bails out early since the debugfs clk tree - * will be created lazily by clk_debug_init as part of a late_initcall. - * - * Caller must hold prepare_lock. Only clk_init calls this function (so - * far) so this is taken care. - */ -static int clk_debug_register(struct clk *clk) -{ - struct clk *parent; - struct dentry *pdentry; - int ret = 0; - - if (!inited) - goto out; - - parent = clk->parent; - - /* - * Check to see if a clk is a root clk. Also check that it is - * safe to add this clk to debugfs - */ - if (!parent) - if (clk->flags & CLK_IS_ROOT) - pdentry = rootdir; - else - pdentry = orphandir; - else - if (parent->dentry) - pdentry = parent->dentry; - else - goto out; - - ret = clk_debug_create_subtree(clk, pdentry); - -out: - return ret; -} - -/** - * clk_debug_init - lazily create the debugfs clk tree visualization - * - * clks are often initialized very early during boot before memory can - * be dynamically allocated and well before debugfs is setup. - * clk_debug_init walks the clk tree hierarchy while holding - * prepare_lock and creates the topology as part of a late_initcall, - * thus insuring that clks initialized very early will still be - * represented in the debugfs clk tree. This function should only be - * called once at boot-time, and all other clks added dynamically will - * be done so with clk_debug_register. - */ -static int __init clk_debug_init(void) -{ - struct clk *clk; - struct hlist_node *tmp; - - rootdir = debugfs_create_dir("clk", NULL); - - if (!rootdir) - return -ENOMEM; - - orphandir = debugfs_create_dir("orphans", rootdir); - - if (!orphandir) - return -ENOMEM; - - mutex_lock(&prepare_lock); - - hlist_for_each_entry(clk, tmp, &clk_root_list, child_node) - clk_debug_create_subtree(clk, rootdir); - - hlist_for_each_entry(clk, tmp, &clk_orphan_list, child_node) - clk_debug_create_subtree(clk, orphandir); - - inited = 1; - - mutex_unlock(&prepare_lock); - - return 0; -} -late_initcall(clk_debug_init); -#else -static inline int clk_debug_register(struct clk *clk) { return 0; } -#endif /* CONFIG_COMMON_CLK_DEBUG */ - -#ifdef CONFIG_COMMON_CLK_DISABLE_UNUSED -/* caller must hold prepare_lock */ -static void clk_disable_unused_subtree(struct clk *clk) -{ - struct clk *child; - struct hlist_node *tmp; - unsigned long flags; - - if (!clk) - goto out; - - hlist_for_each_entry(child, tmp, &clk->children, child_node) - clk_disable_unused_subtree(child); - - spin_lock_irqsave(&enable_lock, flags); - - if (clk->enable_count) - goto unlock_out; - - if (clk->flags & CLK_IGNORE_UNUSED) - goto unlock_out; - - if (__clk_is_enabled(clk) && clk->ops->disable) - clk->ops->disable(clk->hw); - -unlock_out: - spin_unlock_irqrestore(&enable_lock, flags); - -out: - return; -} - -static int clk_disable_unused(void) -{ - struct clk *clk; - struct hlist_node *tmp; - - mutex_lock(&prepare_lock); - - hlist_for_each_entry(clk, tmp, &clk_root_list, child_node) - clk_disable_unused_subtree(clk); - - hlist_for_each_entry(clk, tmp, &clk_orphan_list, child_node) - clk_disable_unused_subtree(clk); - - mutex_unlock(&prepare_lock); - - return 0; -} -late_initcall(clk_disable_unused); -#else -static inline int clk_disable_unused(struct clk *clk) { return 0; } -#endif /* CONFIG_COMMON_CLK_DISABLE_UNUSED */ - -/*** helper functions ***/ - -inline const char *__clk_get_name(struct clk *clk) -{ - return !clk ? NULL : clk->name; -} - -inline struct clk_hw *__clk_get_hw(struct clk *clk) -{ - return !clk ? NULL : clk->hw; -} - -inline u8 __clk_get_num_parents(struct clk *clk) -{ - return !clk ? -EINVAL : clk->num_parents; -} - -inline struct clk *__clk_get_parent(struct clk *clk) -{ - return !clk ? NULL : clk->parent; -} - -inline int __clk_get_enable_count(struct clk *clk) -{ - return !clk ? -EINVAL : clk->enable_count; -} - -inline int __clk_get_prepare_count(struct clk *clk) -{ - return !clk ? -EINVAL : clk->prepare_count; -} - -unsigned long __clk_get_rate(struct clk *clk) -{ - unsigned long ret; - - if (!clk) { - ret = -EINVAL; - goto out; - } - - ret = clk->rate; - - if (clk->flags & CLK_IS_ROOT) - goto out; - - if (!clk->parent) - ret = -ENODEV; - -out: - return ret; -} - -inline unsigned long __clk_get_flags(struct clk *clk) -{ - return !clk ? -EINVAL : clk->flags; -} - -int __clk_is_enabled(struct clk *clk) -{ - int ret; - - if (!clk) - return -EINVAL; - - /* - * .is_enabled is only mandatory for clocks that gate - * fall back to software usage counter if .is_enabled is missing - */ - if (!clk->ops->is_enabled) { - ret = clk->enable_count ? 1 : 0; - goto out; - } - - ret = clk->ops->is_enabled(clk->hw); -out: - return ret; -} - -static struct clk *__clk_lookup_subtree(const char *name, struct clk *clk) -{ - struct clk *child; - struct clk *ret; - struct hlist_node *tmp; - - if (!strcmp(clk->name, name)) - return clk; - - hlist_for_each_entry(child, tmp, &clk->children, child_node) { - ret = __clk_lookup_subtree(name, child); - if (ret) - return ret; - } - - return NULL; -} - -struct clk *__clk_lookup(const char *name) -{ - struct clk *root_clk; - struct clk *ret; - struct hlist_node *tmp; - - if (!name) - return NULL; - - /* search the 'proper' clk tree first */ - hlist_for_each_entry(root_clk, tmp, &clk_root_list, child_node) { - ret = __clk_lookup_subtree(name, root_clk); - if (ret) - return ret; - } - - /* if not found, then search the orphan tree */ - hlist_for_each_entry(root_clk, tmp, &clk_orphan_list, child_node) { - ret = __clk_lookup_subtree(name, root_clk); - if (ret) - return ret; - } - - return NULL; -} - -/*** clk api ***/ - -void __clk_unprepare(struct clk *clk) -{ - if (!clk) - return; - - if (WARN_ON(clk->prepare_count == 0)) - return; - - if (--clk->prepare_count > 0) - return; - - WARN_ON(clk->enable_count > 0); - - if (clk->ops->unprepare) - clk->ops->unprepare(clk->hw); - - __clk_unprepare(clk->parent); -} - -/** - * clk_unprepare - undo preparation of a clock source - * @clk: the clk being unprepare - * - * clk_unprepare may sleep, which differentiates it from clk_disable. In a - * simple case, clk_unprepare can be used instead of clk_disable to gate a clk - * if the operation may sleep. One example is a clk which is accessed over - * I2c. In the complex case a clk gate operation may require a fast and a slow - * part. It is this reason that clk_unprepare and clk_disable are not mutually - * exclusive. In fact clk_disable must be called before clk_unprepare. - */ -void clk_unprepare(struct clk *clk) -{ - mutex_lock(&prepare_lock); - __clk_unprepare(clk); - mutex_unlock(&prepare_lock); -} -EXPORT_SYMBOL_GPL(clk_unprepare); - -int __clk_prepare(struct clk *clk) -{ - int ret = 0; - - if (!clk) - return 0; - - if (clk->prepare_count == 0) { - ret = __clk_prepare(clk->parent); - if (ret) - return ret; - - if (clk->ops->prepare) { - ret = clk->ops->prepare(clk->hw); - if (ret) { - __clk_unprepare(clk->parent); - return ret; - } - } - } - - clk->prepare_count++; - - return 0; -} - -/** - * clk_prepare - prepare a clock source - * @clk: the clk being prepared - * - * clk_prepare may sleep, which differentiates it from clk_enable. In a simple - * case, clk_prepare can be used instead of clk_enable to ungate a clk if the - * operation may sleep. One example is a clk which is accessed over I2c. In - * the complex case a clk ungate operation may require a fast and a slow part. - * It is this reason that clk_prepare and clk_enable are not mutually - * exclusive. In fact clk_prepare must be called before clk_enable. - * Returns 0 on success, -EERROR otherwise. - */ -int clk_prepare(struct clk *clk) -{ - int ret; - - mutex_lock(&prepare_lock); - ret = __clk_prepare(clk); - mutex_unlock(&prepare_lock); - - return ret; -} -EXPORT_SYMBOL_GPL(clk_prepare); - -static void __clk_disable(struct clk *clk) -{ - if (!clk) - return; - - if (WARN_ON(clk->enable_count == 0)) - return; - - if (--clk->enable_count > 0) - return; - - if (clk->ops->disable) - clk->ops->disable(clk->hw); - - __clk_disable(clk->parent); -} - -/** - * clk_disable - gate a clock - * @clk: the clk being gated - * - * clk_disable must not sleep, which differentiates it from clk_unprepare. In - * a simple case, clk_disable can be used instead of clk_unprepare to gate a - * clk if the operation is fast and will never sleep. One example is a - * SoC-internal clk which is controlled via simple register writes. In the - * complex case a clk gate operation may require a fast and a slow part. It is - * this reason that clk_unprepare and clk_disable are not mutually exclusive. - * In fact clk_disable must be called before clk_unprepare. - */ -void clk_disable(struct clk *clk) -{ - unsigned long flags; - - spin_lock_irqsave(&enable_lock, flags); - __clk_disable(clk); - spin_unlock_irqrestore(&enable_lock, flags); -} -EXPORT_SYMBOL_GPL(clk_disable); - -static int __clk_enable(struct clk *clk) -{ - int ret = 0; - - if (!clk) - return 0; - - if (WARN_ON(clk->prepare_count == 0)) - return -ESHUTDOWN; - - if (clk->enable_count == 0) { - ret = __clk_enable(clk->parent); - - if (ret) - return ret; - - if (clk->ops->enable) { - ret = clk->ops->enable(clk->hw); - if (ret) { - __clk_disable(clk->parent); - return ret; - } - } - } - - clk->enable_count++; - return 0; -} - -/** - * clk_enable - ungate a clock - * @clk: the clk being ungated - * - * clk_enable must not sleep, which differentiates it from clk_prepare. In a - * simple case, clk_enable can be used instead of clk_prepare to ungate a clk - * if the operation will never sleep. One example is a SoC-internal clk which - * is controlled via simple register writes. In the complex case a clk ungate - * operation may require a fast and a slow part. It is this reason that - * clk_enable and clk_prepare are not mutually exclusive. In fact clk_prepare - * must be called before clk_enable. Returns 0 on success, -EERROR - * otherwise. - */ -int clk_enable(struct clk *clk) -{ - unsigned long flags; - int ret; - - spin_lock_irqsave(&enable_lock, flags); - ret = __clk_enable(clk); - spin_unlock_irqrestore(&enable_lock, flags); - - return ret; -} -EXPORT_SYMBOL_GPL(clk_enable); - -/** - * clk_get_rate - return the rate of clk - * @clk: the clk whose rate is being returned - * - * Simply returns the cached rate of the clk. Does not query the hardware. If - * clk is NULL then returns -EINVAL. - */ -unsigned long clk_get_rate(struct clk *clk) -{ - unsigned long rate; - - mutex_lock(&prepare_lock); - rate = __clk_get_rate(clk); - mutex_unlock(&prepare_lock); - - return rate; -} -EXPORT_SYMBOL_GPL(clk_get_rate); - -/** - * __clk_round_rate - round the given rate for a clk - * @clk: round the rate of this clock - * - * Caller must hold prepare_lock. Useful for clk_ops such as .set_rate - */ -unsigned long __clk_round_rate(struct clk *clk, unsigned long rate) -{ - unsigned long unused; - - if (!clk) - return -EINVAL; - - if (!clk->ops->round_rate) - return clk->rate; - - if (clk->flags & CLK_SET_RATE_PARENT) - return clk->ops->round_rate(clk->hw, rate, &unused); - else - return clk->ops->round_rate(clk->hw, rate, NULL); -} - -/** - * clk_round_rate - round the given rate for a clk - * @clk: the clk for which we are rounding a rate - * @rate: the rate which is to be rounded - * - * Takes in a rate as input and rounds it to a rate that the clk can actually - * use which is then returned. If clk doesn't support round_rate operation - * then the parent rate is returned. - */ -long clk_round_rate(struct clk *clk, unsigned long rate) -{ - unsigned long ret; - - mutex_lock(&prepare_lock); - ret = __clk_round_rate(clk, rate); - mutex_unlock(&prepare_lock); - - return ret; -} -EXPORT_SYMBOL_GPL(clk_round_rate); - -/** - * __clk_notify - call clk notifier chain - * @clk: struct clk * that is changing rate - * @msg: clk notifier type (see include/linux/clk.h) - * @old_rate: old clk rate - * @new_rate: new clk rate - * - * Triggers a notifier call chain on the clk rate-change notification - * for 'clk'. Passes a pointer to the struct clk and the previous - * and current rates to the notifier callback. Intended to be called by - * internal clock code only. Returns NOTIFY_DONE from the last driver - * called if all went well, or NOTIFY_STOP or NOTIFY_BAD immediately if - * a driver returns that. - */ -static int __clk_notify(struct clk *clk, unsigned long msg, - unsigned long old_rate, unsigned long new_rate) -{ - struct clk_notifier *cn; - struct clk_notifier_data cnd; - int ret = NOTIFY_DONE; - - cnd.clk = clk; - cnd.old_rate = old_rate; - cnd.new_rate = new_rate; - - list_for_each_entry(cn, &clk_notifier_list, node) { - if (cn->clk == clk) { - ret = srcu_notifier_call_chain(&cn->notifier_head, msg, - &cnd); - break; - } - } - - return ret; -} - -/** - * __clk_recalc_rates - * @clk: first clk in the subtree - * @msg: notification type (see include/linux/clk.h) - * - * Walks the subtree of clks starting with clk and recalculates rates as it - * goes. Note that if a clk does not implement the .recalc_rate callback then - * it is assumed that the clock will take on the rate of it's parent. - * - * clk_recalc_rates also propagates the POST_RATE_CHANGE notification, - * if necessary. - * - * Caller must hold prepare_lock. - */ -static void __clk_recalc_rates(struct clk *clk, unsigned long msg) -{ - unsigned long old_rate; - unsigned long parent_rate = 0; - struct hlist_node *tmp; - struct clk *child; - - old_rate = clk->rate; - - if (clk->parent) - parent_rate = clk->parent->rate; - - if (clk->ops->recalc_rate) - clk->rate = clk->ops->recalc_rate(clk->hw, parent_rate); - else - clk->rate = parent_rate; - - /* - * ignore NOTIFY_STOP and NOTIFY_BAD return values for POST_RATE_CHANGE - * & ABORT_RATE_CHANGE notifiers - */ - if (clk->notifier_count && msg) - __clk_notify(clk, msg, old_rate, clk->rate); - - hlist_for_each_entry(child, tmp, &clk->children, child_node) - __clk_recalc_rates(child, msg); -} - -/** - * __clk_speculate_rates - * @clk: first clk in the subtree - * @parent_rate: the "future" rate of clk's parent - * - * Walks the subtree of clks starting with clk, speculating rates as it - * goes and firing off PRE_RATE_CHANGE notifications as necessary. - * - * Unlike clk_recalc_rates, clk_speculate_rates exists only for sending - * pre-rate change notifications and returns early if no clks in the - * subtree have subscribed to the notifications. Note that if a clk does not - * implement the .recalc_rate callback then it is assumed that the clock will - * take on the rate of it's parent. - * - * Caller must hold prepare_lock. - */ -static int __clk_speculate_rates(struct clk *clk, unsigned long parent_rate) -{ - struct hlist_node *tmp; - struct clk *child; - unsigned long new_rate; - int ret = NOTIFY_DONE; - - if (clk->ops->recalc_rate) - new_rate = clk->ops->recalc_rate(clk->hw, parent_rate); - else - new_rate = parent_rate; - - /* abort the rate change if a driver returns NOTIFY_BAD */ - if (clk->notifier_count) - ret = __clk_notify(clk, PRE_RATE_CHANGE, clk->rate, new_rate); - - if (ret == NOTIFY_BAD) - goto out; - - hlist_for_each_entry(child, tmp, &clk->children, child_node) { - ret = __clk_speculate_rates(child, new_rate); - if (ret == NOTIFY_BAD) - break; - } - -out: - return ret; -} - -static void clk_calc_subtree(struct clk *clk, unsigned long new_rate) -{ - struct clk *child; - struct hlist_node *tmp; - - clk->new_rate = new_rate; - - hlist_for_each_entry(child, tmp, &clk->children, child_node) { - if (child->ops->recalc_rate) - child->new_rate = child->ops->recalc_rate(child->hw, new_rate); - else - child->new_rate = new_rate; - clk_calc_subtree(child, child->new_rate); - } -} - -/* - * calculate the new rates returning the topmost clock that has to be - * changed. - */ -static struct clk *clk_calc_new_rates(struct clk *clk, unsigned long rate) -{ - struct clk *top = clk; - unsigned long best_parent_rate = clk->parent->rate; - unsigned long new_rate; - - if (!clk->ops->round_rate && !(clk->flags & CLK_SET_RATE_PARENT)) { - clk->new_rate = clk->rate; - return NULL; - } - - if (!clk->ops->round_rate && (clk->flags & CLK_SET_RATE_PARENT)) { - top = clk_calc_new_rates(clk->parent, rate); - new_rate = clk->new_rate = clk->parent->new_rate; - - goto out; - } - - if (clk->flags & CLK_SET_RATE_PARENT) - new_rate = clk->ops->round_rate(clk->hw, rate, &best_parent_rate); - else - new_rate = clk->ops->round_rate(clk->hw, rate, NULL); - - if (best_parent_rate != clk->parent->rate) { - top = clk_calc_new_rates(clk->parent, best_parent_rate); - - goto out; - } - -out: - clk_calc_subtree(clk, new_rate); - - return top; -} - -/* - * Notify about rate changes in a subtree. Always walk down the whole tree - * so that in case of an error we can walk down the whole tree again and - * abort the change. - */ -static struct clk *clk_propagate_rate_change(struct clk *clk, unsigned long event) -{ - struct hlist_node *tmp; - struct clk *child, *fail_clk = NULL; - int ret = NOTIFY_DONE; - - if (clk->rate == clk->new_rate) - return 0; - - if (clk->notifier_count) { - ret = __clk_notify(clk, event, clk->rate, clk->new_rate); - if (ret == NOTIFY_BAD) - fail_clk = clk; - } - - hlist_for_each_entry(child, tmp, &clk->children, child_node) { - clk = clk_propagate_rate_change(child, event); - if (clk) - fail_clk = clk; - } - - return fail_clk; -} - -/* - * walk down a subtree and set the new rates notifying the rate - * change on the way - */ -static void clk_change_rate(struct clk *clk) -{ - struct clk *child; - unsigned long old_rate; - struct hlist_node *tmp; - - old_rate = clk->rate; - - if (clk->ops->set_rate) - clk->ops->set_rate(clk->hw, clk->new_rate); - - if (clk->ops->recalc_rate) - clk->rate = clk->ops->recalc_rate(clk->hw, - clk->parent->rate); - else - clk->rate = clk->parent->rate; - - if (clk->notifier_count && old_rate != clk->rate) - __clk_notify(clk, POST_RATE_CHANGE, old_rate, clk->rate); - - hlist_for_each_entry(child, tmp, &clk->children, child_node) - clk_change_rate(child); -} - -/** - * clk_set_rate - specify a new rate for clk - * @clk: the clk whose rate is being changed - * @rate: the new rate for clk - * - * In the simplest case clk_set_rate will only change the rate of clk. - * - * If clk has the CLK_SET_RATE_GATE flag set and it is enabled this call - * will fail; only when the clk is disabled will it be able to change - * its rate. - * - * Setting the CLK_SET_RATE_PARENT flag allows clk_set_rate to - * recursively propagate up to clk's parent; whether or not this happens - * depends on the outcome of clk's .round_rate implementation. If - * *parent_rate is 0 after calling .round_rate then upstream parent - * propagation is ignored. If *parent_rate comes back with a new rate - * for clk's parent then we propagate up to clk's parent and set it's - * rate. Upward propagation will continue until either a clk does not - * support the CLK_SET_RATE_PARENT flag or .round_rate stops requesting - * changes to clk's parent_rate. If there is a failure during upstream - * propagation then clk_set_rate will unwind and restore each clk's rate - * that had been successfully changed. Afterwards a rate change abort - * notification will be propagated downstream, starting from the clk - * that failed. - * - * At the end of all of the rate setting, clk_set_rate internally calls - * __clk_recalc_rates and propagates the rate changes downstream, - * starting from the highest clk whose rate was changed. This has the - * added benefit of propagating post-rate change notifiers. - * - * Note that while post-rate change and rate change abort notifications - * are guaranteed to be sent to a clk only once per call to - * clk_set_rate, pre-change notifications will be sent for every clk - * whose rate is changed. Stacking pre-change notifications is noisy - * for the drivers subscribed to them, but this allows drivers to react - * to intermediate clk rate changes up until the point where the final - * rate is achieved at the end of upstream propagation. - * - * Returns 0 on success, -EERROR otherwise. - */ -int clk_set_rate(struct clk *clk, unsigned long rate) -{ - struct clk *top, *fail_clk; - int ret = 0; - - /* prevent racing with updates to the clock topology */ - mutex_lock(&prepare_lock); - - /* bail early if nothing to do */ - if (rate == clk->rate) - goto out; - - /* calculate new rates and get the topmost changed clock */ - top = clk_calc_new_rates(clk, rate); - if (!top) { - ret = -EINVAL; - goto out; - } - - /* notify that we are about to change rates */ - fail_clk = clk_propagate_rate_change(top, PRE_RATE_CHANGE); - if (fail_clk) { - pr_warn("%s: failed to set %s rate\n", __func__, - fail_clk->name); - clk_propagate_rate_change(top, ABORT_RATE_CHANGE); - ret = -EBUSY; - goto out; - } - - /* change the rates */ - clk_change_rate(top); - - mutex_unlock(&prepare_lock); - - return 0; -out: - mutex_unlock(&prepare_lock); - - return ret; -} -EXPORT_SYMBOL_GPL(clk_set_rate); - -/** - * clk_get_parent - return the parent of a clk - * @clk: the clk whose parent gets returned - * - * Simply returns clk->parent. Returns NULL if clk is NULL. - */ -struct clk *clk_get_parent(struct clk *clk) -{ - struct clk *parent; - - mutex_lock(&prepare_lock); - parent = __clk_get_parent(clk); - mutex_unlock(&prepare_lock); - - return parent; -} -EXPORT_SYMBOL_GPL(clk_get_parent); - -/* - * .get_parent is mandatory for clocks with multiple possible parents. It is - * optional for single-parent clocks. Always call .get_parent if it is - * available and WARN if it is missing for multi-parent clocks. - * - * For single-parent clocks without .get_parent, first check to see if the - * .parents array exists, and if so use it to avoid an expensive tree - * traversal. If .parents does not exist then walk the tree with __clk_lookup. - */ -static struct clk *__clk_init_parent(struct clk *clk) -{ - struct clk *ret = NULL; - u8 index; - - /* handle the trivial cases */ - - if (!clk->num_parents) - goto out; - - if (clk->num_parents == 1) { - if (IS_ERR_OR_NULL(clk->parent)) - ret = clk->parent = __clk_lookup(clk->parent_names[0]); - ret = clk->parent; - goto out; - } - - if (!clk->ops->get_parent) { - WARN(!clk->ops->get_parent, - "%s: multi-parent clocks must implement .get_parent\n", - __func__); - goto out; - }; - - /* - * Do our best to cache parent clocks in clk->parents. This prevents - * unnecessary and expensive calls to __clk_lookup. We don't set - * clk->parent here; that is done by the calling function - */ - - index = clk->ops->get_parent(clk->hw); - - if (!clk->parents) - clk->parents = - kzalloc((sizeof(struct clk*) * clk->num_parents), - GFP_KERNEL); - - if (!clk->parents) - ret = __clk_lookup(clk->parent_names[index]); - else if (!clk->parents[index]) - ret = clk->parents[index] = - __clk_lookup(clk->parent_names[index]); - else - ret = clk->parents[index]; - -out: - return ret; -} - -void __clk_reparent(struct clk *clk, struct clk *new_parent) -{ -#ifdef CONFIG_COMMON_CLK_DEBUG - struct dentry *d; - struct dentry *new_parent_d; -#endif - - if (!clk || !new_parent) - return; - - hlist_del(&clk->child_node); - - if (new_parent) - hlist_add_head(&clk->child_node, &new_parent->children); - else - hlist_add_head(&clk->child_node, &clk_orphan_list); - -#ifdef CONFIG_COMMON_CLK_DEBUG - if (!inited) - goto out; - - if (new_parent) - new_parent_d = new_parent->dentry; - else - new_parent_d = orphandir; - - d = debugfs_rename(clk->dentry->d_parent, clk->dentry, - new_parent_d, clk->name); - if (d) - clk->dentry = d; - else - pr_debug("%s: failed to rename debugfs entry for %s\n", - __func__, clk->name); -out: -#endif - - clk->parent = new_parent; - - __clk_recalc_rates(clk, POST_RATE_CHANGE); -} - -static int __clk_set_parent(struct clk *clk, struct clk *parent) -{ - struct clk *old_parent; - unsigned long flags; - int ret = -EINVAL; - u8 i; - - old_parent = clk->parent; - - if (!clk->parents) - clk->parents = kzalloc((sizeof(struct clk*) * clk->num_parents), - GFP_KERNEL); - - /* - * find index of new parent clock using cached parent ptrs, - * or if not yet cached, use string name comparison and cache - * them now to avoid future calls to __clk_lookup. - */ - for (i = 0; i < clk->num_parents; i++) { - if (clk->parents && clk->parents[i] == parent) - break; - else if (!strcmp(clk->parent_names[i], parent->name)) { - if (clk->parents) - clk->parents[i] = __clk_lookup(parent->name); - break; - } - } - - if (i == clk->num_parents) { - pr_debug("%s: clock %s is not a possible parent of clock %s\n", - __func__, parent->name, clk->name); - goto out; - } - - /* migrate prepare and enable */ - if (clk->prepare_count) - __clk_prepare(parent); - - /* FIXME replace with clk_is_enabled(clk) someday */ - spin_lock_irqsave(&enable_lock, flags); - if (clk->enable_count) - __clk_enable(parent); - spin_unlock_irqrestore(&enable_lock, flags); - - /* change clock input source */ - ret = clk->ops->set_parent(clk->hw, i); - - /* clean up old prepare and enable */ - spin_lock_irqsave(&enable_lock, flags); - if (clk->enable_count) - __clk_disable(old_parent); - spin_unlock_irqrestore(&enable_lock, flags); - - if (clk->prepare_count) - __clk_unprepare(old_parent); - -out: - return ret; -} - -/** - * clk_set_parent - switch the parent of a mux clk - * @clk: the mux clk whose input we are switching - * @parent: the new input to clk - * - * Re-parent clk to use parent as it's new input source. If clk has the - * CLK_SET_PARENT_GATE flag set then clk must be gated for this - * operation to succeed. After successfully changing clk's parent - * clk_set_parent will update the clk topology, sysfs topology and - * propagate rate recalculation via __clk_recalc_rates. Returns 0 on - * success, -EERROR otherwise. - */ -int clk_set_parent(struct clk *clk, struct clk *parent) -{ - int ret = 0; - - if (!clk || !clk->ops) - return -EINVAL; - - if (!clk->ops->set_parent) - return -ENOSYS; - - /* prevent racing with updates to the clock topology */ - mutex_lock(&prepare_lock); - - if (clk->parent == parent) - goto out; - - /* propagate PRE_RATE_CHANGE notifications */ - if (clk->notifier_count) - ret = __clk_speculate_rates(clk, parent->rate); - - /* abort if a driver objects */ - if (ret == NOTIFY_STOP) - goto out; - - /* only re-parent if the clock is not in use */ - if ((clk->flags & CLK_SET_PARENT_GATE) && clk->prepare_count) - ret = -EBUSY; - else - ret = __clk_set_parent(clk, parent); - - /* propagate ABORT_RATE_CHANGE if .set_parent failed */ - if (ret) { - __clk_recalc_rates(clk, ABORT_RATE_CHANGE); - goto out; - } - - /* propagate rate recalculation downstream */ - __clk_reparent(clk, parent); - -out: - mutex_unlock(&prepare_lock); - - return ret; -} -EXPORT_SYMBOL_GPL(clk_set_parent); - -/** - * __clk_init - initialize the data structures in a struct clk - * @dev: device initializing this clk, placeholder for now - * @clk: clk being initialized - * - * Initializes the lists in struct clk, queries the hardware for the - * parent and rate and sets them both. - * - * Any struct clk passed into __clk_init must have the following members - * populated: - * .name - * .ops - * .hw - * .parent_names - * .num_parents - * .flags - * - * Essentially, everything that would normally be passed into clk_register is - * assumed to be initialized already in __clk_init. The other members may be - * populated, but are optional. - * - * __clk_init is only exposed via clk-private.h and is intended for use with - * very large numbers of clocks that need to be statically initialized. It is - * a layering violation to include clk-private.h from any code which implements - * a clock's .ops; as such any statically initialized clock data MUST be in a - * separate C file from the logic that implements it's operations. - */ -void __clk_init(struct device *dev, struct clk *clk) -{ - int i; - struct clk *orphan; - struct hlist_node *tmp, *tmp2; - - if (!clk) - return; - - mutex_lock(&prepare_lock); - - /* check to see if a clock with this name is already registered */ - if (__clk_lookup(clk->name)) - goto out; - - /* throw a WARN if any entries in parent_names are NULL */ - for (i = 0; i < clk->num_parents; i++) - WARN(!clk->parent_names[i], - "%s: invalid NULL in %s's .parent_names\n", - __func__, clk->name); - - /* - * Allocate an array of struct clk *'s to avoid unnecessary string - * look-ups of clk's possible parents. This can fail for clocks passed - * in to clk_init during early boot; thus any access to clk->parents[] - * must always check for a NULL pointer and try to populate it if - * necessary. - * - * If clk->parents is not NULL we skip this entire block. This allows - * for clock drivers to statically initialize clk->parents. - */ - if (clk->num_parents && !clk->parents) { - clk->parents = kmalloc((sizeof(struct clk*) * clk->num_parents), - GFP_KERNEL); - /* - * __clk_lookup returns NULL for parents that have not been - * clk_init'd; thus any access to clk->parents[] must check - * for a NULL pointer. We can always perform lazy lookups for - * missing parents later on. - */ - if (clk->parents) - for (i = 0; i < clk->num_parents; i++) - clk->parents[i] = - __clk_lookup(clk->parent_names[i]); - } - - clk->parent = __clk_init_parent(clk); - - /* - * Populate clk->parent if parent has already been __clk_init'd. If - * parent has not yet been __clk_init'd then place clk in the orphan - * list. If clk has set the CLK_IS_ROOT flag then place it in the root - * clk list. - * - * Every time a new clk is clk_init'd then we walk the list of orphan - * clocks and re-parent any that are children of the clock currently - * being clk_init'd. - */ - if (clk->parent) - hlist_add_head(&clk->child_node, - &clk->parent->children); - else if (clk->flags & CLK_IS_ROOT) - hlist_add_head(&clk->child_node, &clk_root_list); - else - hlist_add_head(&clk->child_node, &clk_orphan_list); - - /* - * Set clk's rate. The preferred method is to use .recalc_rate. For - * simple clocks and lazy developers the default fallback is to use the - * parent's rate. If a clock doesn't have a parent (or is orphaned) - * then rate is set to zero. - */ - if (clk->ops->recalc_rate) - clk->rate = clk->ops->recalc_rate(clk->hw, - __clk_get_rate(clk->parent)); - else if (clk->parent) - clk->rate = clk->parent->rate; - else - clk->rate = 0; - - /* - * walk the list of orphan clocks and reparent any that are children of - * this clock - */ - hlist_for_each_entry_safe(orphan, tmp, tmp2, &clk_orphan_list, child_node) - for (i = 0; i < orphan->num_parents; i++) - if (!strcmp(clk->name, orphan->parent_names[i])) { - __clk_reparent(orphan, clk); - break; - } - - /* - * optional platform-specific magic - * - * The .init callback is not used by any of the basic clock types, but - * exists for weird hardware that must perform initialization magic. - * Please consider other ways of solving initialization problems before - * using this callback, as it's use is discouraged. - */ - if (clk->ops->init) - clk->ops->init(clk->hw); - - clk_debug_register(clk); - -out: - mutex_unlock(&prepare_lock); - - return; -} - -/** - * clk_register - allocate a new clock, register it and return an opaque cookie - * @dev: device that is registering this clock - * @name: clock name - * @ops: operations this clock supports - * @hw: link to hardware-specific clock data - * @parent_names: array of string names for all possible parents - * @num_parents: number of possible parents - * @flags: framework-level hints and quirks - * - * clk_register is the primary interface for populating the clock tree with new - * clock nodes. It returns a pointer to the newly allocated struct clk which - * cannot be dereferenced by driver code but may be used in conjuction with the - * rest of the clock API. - */ -struct clk *clk_register(struct device *dev, const char *name, - const struct clk_ops *ops, struct clk_hw *hw, - char **parent_names, u8 num_parents, unsigned long flags) -{ - struct clk *clk; - - clk = kzalloc(sizeof(*clk), GFP_KERNEL); - if (!clk) - return NULL; - - clk->name = name; - clk->ops = ops; - clk->hw = hw; - clk->flags = flags; - clk->parent_names = parent_names; - clk->num_parents = num_parents; - hw->clk = clk; - - __clk_init(dev, clk); - - return clk; -} -EXPORT_SYMBOL_GPL(clk_register); - -/*** clk rate change notifiers ***/ - -/** - * clk_notifier_register - add a clk rate change notifier - * @clk: struct clk * to watch - * @nb: struct notifier_block * with callback info - * - * Request notification when clk's rate changes. This uses an SRCU - * notifier because we want it to block and notifier unregistrations are - * uncommon. The callbacks associated with the notifier must not - * re-enter into the clk framework by calling any top-level clk APIs; - * this will cause a nested prepare_lock mutex. - * - * Pre-change notifier callbacks will be passed the current, pre-change - * rate of the clk via struct clk_notifier_data.old_rate. The new, - * post-change rate of the clk is passed via struct - * clk_notifier_data.new_rate. - * - * Post-change notifiers will pass the now-current, post-change rate of - * the clk in both struct clk_notifier_data.old_rate and struct - * clk_notifier_data.new_rate. - * - * Abort-change notifiers are effectively the opposite of pre-change - * notifiers: the original pre-change clk rate is passed in via struct - * clk_notifier_data.new_rate and the failed post-change rate is passed - * in via struct clk_notifier_data.old_rate. - * - * clk_notifier_register() must be called from non-atomic context. - * Returns -EINVAL if called with null arguments, -ENOMEM upon - * allocation failure; otherwise, passes along the return value of - * srcu_notifier_chain_register(). - */ -int clk_notifier_register(struct clk *clk, struct notifier_block *nb) -{ - struct clk_notifier *cn; - int ret = -ENOMEM; - - if (!clk || !nb) - return -EINVAL; - - mutex_lock(&prepare_lock); - - /* search the list of notifiers for this clk */ - list_for_each_entry(cn, &clk_notifier_list, node) - if (cn->clk == clk) - break; - - /* if clk wasn't in the notifier list, allocate new clk_notifier */ - if (cn->clk != clk) { - cn = kzalloc(sizeof(struct clk_notifier), GFP_KERNEL); - if (!cn) - goto out; - - cn->clk = clk; - srcu_init_notifier_head(&cn->notifier_head); - - list_add(&cn->node, &clk_notifier_list); - } - - ret = srcu_notifier_chain_register(&cn->notifier_head, nb); - - clk->notifier_count++; - -out: - mutex_unlock(&prepare_lock); - - return ret; -} -EXPORT_SYMBOL_GPL(clk_notifier_register); - -/** - * clk_notifier_unregister - remove a clk rate change notifier - * @clk: struct clk * - * @nb: struct notifier_block * with callback info - * - * Request no further notification for changes to 'clk' and frees memory - * allocated in clk_notifier_register. - * - * Returns -EINVAL if called with null arguments; otherwise, passes - * along the return value of srcu_notifier_chain_unregister(). - */ -int clk_notifier_unregister(struct clk *clk, struct notifier_block *nb) -{ - struct clk_notifier *cn = NULL; - int ret = -EINVAL; - - if (!clk || !nb) - return -EINVAL; - - mutex_lock(&prepare_lock); - - list_for_each_entry(cn, &clk_notifier_list, node) - if (cn->clk == clk) - break; - - if (cn->clk == clk) { - ret = srcu_notifier_chain_unregister(&cn->notifier_head, nb); - - clk->notifier_count--; - - /* XXX the notifier code should handle this better */ - if (!cn->notifier_head.head) { - srcu_cleanup_notifier_head(&cn->notifier_head); - kfree(cn); - } - - } else { - ret = -ENOENT; - } - - mutex_unlock(&prepare_lock); - - return ret; -} -EXPORT_SYMBOL_GPL(clk_notifier_unregister); diff --git a/ANDROID_3.4.5/drivers/clk/clkdev.c b/ANDROID_3.4.5/drivers/clk/clkdev.c deleted file mode 100644 index 6db161f6..00000000 --- a/ANDROID_3.4.5/drivers/clk/clkdev.c +++ /dev/null @@ -1,175 +0,0 @@ -/* - * drivers/clk/clkdev.c - * - * Copyright (C) 2008 Russell King. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Helper for the clk API to assist looking up a struct clk. - */ -#include <linux/module.h> -#include <linux/kernel.h> -#include <linux/device.h> -#include <linux/list.h> -#include <linux/errno.h> -#include <linux/err.h> -#include <linux/string.h> -#include <linux/mutex.h> -#include <linux/clk.h> -#include <linux/clkdev.h> - -static LIST_HEAD(clocks); -static DEFINE_MUTEX(clocks_mutex); - -/* - * Find the correct struct clk for the device and connection ID. - * We do slightly fuzzy matching here: - * An entry with a NULL ID is assumed to be a wildcard. - * If an entry has a device ID, it must match - * If an entry has a connection ID, it must match - * Then we take the most specific entry - with the following - * order of precedence: dev+con > dev only > con only. - */ -static struct clk_lookup *clk_find(const char *dev_id, const char *con_id) -{ - struct clk_lookup *p, *cl = NULL; - int match, best = 0; - - list_for_each_entry(p, &clocks, node) { - match = 0; - if (p->dev_id) { - if (!dev_id || strcmp(p->dev_id, dev_id)) - continue; - match += 2; - } - if (p->con_id) { - if (!con_id || strcmp(p->con_id, con_id)) - continue; - match += 1; - } - - if (match > best) { - cl = p; - if (match != 3) - best = match; - else - break; - } - } - return cl; -} - -struct clk *clk_get_sys(const char *dev_id, const char *con_id) -{ - struct clk_lookup *cl; - - mutex_lock(&clocks_mutex); - cl = clk_find(dev_id, con_id); - if (cl && !__clk_get(cl->clk)) - cl = NULL; - mutex_unlock(&clocks_mutex); - - return cl ? cl->clk : ERR_PTR(-ENOENT); -} -EXPORT_SYMBOL(clk_get_sys); - -struct clk *clk_get(struct device *dev, const char *con_id) -{ - const char *dev_id = dev ? dev_name(dev) : NULL; - - return clk_get_sys(dev_id, con_id); -} -EXPORT_SYMBOL(clk_get); - -void clk_put(struct clk *clk) -{ - __clk_put(clk); -} -EXPORT_SYMBOL(clk_put); - -void clkdev_add(struct clk_lookup *cl) -{ - mutex_lock(&clocks_mutex); - list_add_tail(&cl->node, &clocks); - mutex_unlock(&clocks_mutex); -} -EXPORT_SYMBOL(clkdev_add); - -void __init clkdev_add_table(struct clk_lookup *cl, size_t num) -{ - mutex_lock(&clocks_mutex); - while (num--) { - list_add_tail(&cl->node, &clocks); - cl++; - } - mutex_unlock(&clocks_mutex); -} - -#define MAX_DEV_ID 20 -#define MAX_CON_ID 16 - -struct clk_lookup_alloc { - struct clk_lookup cl; - char dev_id[MAX_DEV_ID]; - char con_id[MAX_CON_ID]; -}; - -struct clk_lookup * __init_refok -clkdev_alloc(struct clk *clk, const char *con_id, const char *dev_fmt, ...) -{ - struct clk_lookup_alloc *cla; - - cla = __clkdev_alloc(sizeof(*cla)); - if (!cla) - return NULL; - - cla->cl.clk = clk; - if (con_id) { - strlcpy(cla->con_id, con_id, sizeof(cla->con_id)); - cla->cl.con_id = cla->con_id; - } - - if (dev_fmt) { - va_list ap; - - va_start(ap, dev_fmt); - vscnprintf(cla->dev_id, sizeof(cla->dev_id), dev_fmt, ap); - cla->cl.dev_id = cla->dev_id; - va_end(ap); - } - - return &cla->cl; -} -EXPORT_SYMBOL(clkdev_alloc); - -int clk_add_alias(const char *alias, const char *alias_dev_name, char *id, - struct device *dev) -{ - struct clk *r = clk_get(dev, id); - struct clk_lookup *l; - - if (IS_ERR(r)) - return PTR_ERR(r); - - l = clkdev_alloc(r, alias, alias_dev_name); - clk_put(r); - if (!l) - return -ENODEV; - clkdev_add(l); - return 0; -} -EXPORT_SYMBOL(clk_add_alias); - -/* - * clkdev_drop - remove a clock dynamically allocated - */ -void clkdev_drop(struct clk_lookup *cl) -{ - mutex_lock(&clocks_mutex); - list_del(&cl->node); - mutex_unlock(&clocks_mutex); - kfree(cl); -} -EXPORT_SYMBOL(clkdev_drop); |