diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2015-02-21 12:30:30 -0800 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2015-02-21 12:30:30 -0800 |
commit | 18a8d49973667aa016e68826eeb374788b7c63b0 (patch) | |
tree | d7f90fcf05087ce50ee931b596e60e4c3c082a29 /drivers/clk/qcom/clk-regmap-divider.c | |
parent | c189cb8ef62832f33b6cf757350a0270532a1ad8 (diff) | |
parent | ec02ace8ca0a50eef430d3676de5c5fa978b0e29 (diff) |
Merge tag 'clk-for-linus-3.20' of git://git.linaro.org/people/mike.turquette/linux
Pull clock framework updates from Mike Turquette:
"The clock framework changes contain the usual driver additions,
enhancements and fixes mostly for ARM32, ARM64, MIPS and Power-based
devices.
Additionally the framework core underwent a bit of surgery with two
major changes:
- The boundary between the clock core and clock providers (e.g clock
drivers) is now more well defined with dedicated provider helper
functions. struct clk no longer maps 1:1 with the hardware clock
but is a true per-user cookie which helps us tracker users of
hardware clocks and debug bad behavior.
- The addition of rate constraints for clocks. Rate ranges are now
supported which are analogous to the voltage ranges in the
regulator framework.
Unfortunately these changes to the core created some breakeage. We
think we fixed it all up but for this reason there are lots of last
minute commits trying to undo the damage"
* tag 'clk-for-linus-3.20' of git://git.linaro.org/people/mike.turquette/linux: (113 commits)
clk: Only recalculate the rate if needed
Revert "clk: mxs: Fix invalid 32-bit access to frac registers"
clk: qoriq: Add support for the platform PLL
powerpc/corenet: Enable CLK_QORIQ
clk: Replace explicit clk assignment with __clk_hw_set_clk
clk: Add __clk_hw_set_clk helper function
clk: Don't dereference parent clock if is NULL
MIPS: Alchemy: Remove bogus args from alchemy_clk_fgcs_detr
clkdev: Always allocate a struct clk and call __clk_get() w/ CCF
clk: shmobile: div6: Avoid division by zero in .round_rate()
clk: mxs: Fix invalid 32-bit access to frac registers
clk: omap: compile legacy omap3 clocks conditionally
clkdev: Export clk_register_clkdev
clk: Add rate constraints to clocks
clk: remove clk-private.h
pci: xgene: do not use clk-private.h
arm: omap2+ remove dead clock code
clk: Make clk API return per-user struct clk instances
clk: tegra: Define PLLD_DSI and remove dsia(b)_mux
clk: tegra: Add support for the Tegra132 CAR IP block
...
Diffstat (limited to 'drivers/clk/qcom/clk-regmap-divider.c')
-rw-r--r-- | drivers/clk/qcom/clk-regmap-divider.c | 70 |
1 files changed, 70 insertions, 0 deletions
diff --git a/drivers/clk/qcom/clk-regmap-divider.c b/drivers/clk/qcom/clk-regmap-divider.c new file mode 100644 index 000000000000..53484912301e --- /dev/null +++ b/drivers/clk/qcom/clk-regmap-divider.c @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2014, The Linux Foundation. All rights reserved. + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include <linux/kernel.h> +#include <linux/bitops.h> +#include <linux/regmap.h> +#include <linux/export.h> + +#include "clk-regmap-divider.h" + +static inline struct clk_regmap_div *to_clk_regmap_div(struct clk_hw *hw) +{ + return container_of(to_clk_regmap(hw), struct clk_regmap_div, clkr); +} + +static long div_round_rate(struct clk_hw *hw, unsigned long rate, + unsigned long *prate) +{ + struct clk_regmap_div *divider = to_clk_regmap_div(hw); + + return divider_round_rate(hw, rate, prate, NULL, divider->width, + CLK_DIVIDER_ROUND_CLOSEST); +} + +static int div_set_rate(struct clk_hw *hw, unsigned long rate, + unsigned long parent_rate) +{ + struct clk_regmap_div *divider = to_clk_regmap_div(hw); + struct clk_regmap *clkr = ÷r->clkr; + u32 div; + + div = divider_get_val(rate, parent_rate, NULL, divider->width, + CLK_DIVIDER_ROUND_CLOSEST); + + return regmap_update_bits(clkr->regmap, divider->reg, + (BIT(divider->width) - 1) << divider->shift, + div << divider->shift); +} + +static unsigned long div_recalc_rate(struct clk_hw *hw, + unsigned long parent_rate) +{ + struct clk_regmap_div *divider = to_clk_regmap_div(hw); + struct clk_regmap *clkr = ÷r->clkr; + u32 div; + + regmap_read(clkr->regmap, divider->reg, &div); + div >>= divider->shift; + div &= BIT(divider->width) - 1; + + return divider_recalc_rate(hw, parent_rate, div, NULL, + CLK_DIVIDER_ROUND_CLOSEST); +} + +const struct clk_ops clk_regmap_div_ops = { + .round_rate = div_round_rate, + .set_rate = div_set_rate, + .recalc_rate = div_recalc_rate, +}; +EXPORT_SYMBOL_GPL(clk_regmap_div_ops); |