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
  ...
This commit is contained in:
Linus Torvalds
2015-02-21 12:30:30 -08:00
132개의 변경된 파일13048개의 추가작업 그리고 5705개의 파일을 삭제

파일 보기

@@ -20,11 +20,221 @@
#include <linux/of_address.h>
#include <linux/reset-controller.h>
#include <linux/spinlock.h>
#include <linux/log2.h>
#include "clk-factors.h"
static DEFINE_SPINLOCK(clk_lock);
/**
* sun6i_a31_ahb1_clk_setup() - Setup function for a31 ahb1 composite clk
*/
#define SUN6I_AHB1_MAX_PARENTS 4
#define SUN6I_AHB1_MUX_PARENT_PLL6 3
#define SUN6I_AHB1_MUX_SHIFT 12
/* un-shifted mask is what mux_clk expects */
#define SUN6I_AHB1_MUX_MASK 0x3
#define SUN6I_AHB1_MUX_GET_PARENT(reg) ((reg >> SUN6I_AHB1_MUX_SHIFT) & \
SUN6I_AHB1_MUX_MASK)
#define SUN6I_AHB1_DIV_SHIFT 4
#define SUN6I_AHB1_DIV_MASK (0x3 << SUN6I_AHB1_DIV_SHIFT)
#define SUN6I_AHB1_DIV_GET(reg) ((reg & SUN6I_AHB1_DIV_MASK) >> \
SUN6I_AHB1_DIV_SHIFT)
#define SUN6I_AHB1_DIV_SET(reg, div) ((reg & ~SUN6I_AHB1_DIV_MASK) | \
(div << SUN6I_AHB1_DIV_SHIFT))
#define SUN6I_AHB1_PLL6_DIV_SHIFT 6
#define SUN6I_AHB1_PLL6_DIV_MASK (0x3 << SUN6I_AHB1_PLL6_DIV_SHIFT)
#define SUN6I_AHB1_PLL6_DIV_GET(reg) ((reg & SUN6I_AHB1_PLL6_DIV_MASK) >> \
SUN6I_AHB1_PLL6_DIV_SHIFT)
#define SUN6I_AHB1_PLL6_DIV_SET(reg, div) ((reg & ~SUN6I_AHB1_PLL6_DIV_MASK) | \
(div << SUN6I_AHB1_PLL6_DIV_SHIFT))
struct sun6i_ahb1_clk {
struct clk_hw hw;
void __iomem *reg;
};
#define to_sun6i_ahb1_clk(_hw) container_of(_hw, struct sun6i_ahb1_clk, hw)
static unsigned long sun6i_ahb1_clk_recalc_rate(struct clk_hw *hw,
unsigned long parent_rate)
{
struct sun6i_ahb1_clk *ahb1 = to_sun6i_ahb1_clk(hw);
unsigned long rate;
u32 reg;
/* Fetch the register value */
reg = readl(ahb1->reg);
/* apply pre-divider first if parent is pll6 */
if (SUN6I_AHB1_MUX_GET_PARENT(reg) == SUN6I_AHB1_MUX_PARENT_PLL6)
parent_rate /= SUN6I_AHB1_PLL6_DIV_GET(reg) + 1;
/* clk divider */
rate = parent_rate >> SUN6I_AHB1_DIV_GET(reg);
return rate;
}
static long sun6i_ahb1_clk_round(unsigned long rate, u8 *divp, u8 *pre_divp,
u8 parent, unsigned long parent_rate)
{
u8 div, calcp, calcm = 1;
/*
* clock can only divide, so we will never be able to achieve
* frequencies higher than the parent frequency
*/
if (parent_rate && rate > parent_rate)
rate = parent_rate;
div = DIV_ROUND_UP(parent_rate, rate);
/* calculate pre-divider if parent is pll6 */
if (parent == SUN6I_AHB1_MUX_PARENT_PLL6) {
if (div < 4)
calcp = 0;
else if (div / 2 < 4)
calcp = 1;
else if (div / 4 < 4)
calcp = 2;
else
calcp = 3;
calcm = DIV_ROUND_UP(div, 1 << calcp);
} else {
calcp = __roundup_pow_of_two(div);
calcp = calcp > 3 ? 3 : calcp;
}
/* we were asked to pass back divider values */
if (divp) {
*divp = calcp;
*pre_divp = calcm - 1;
}
return (parent_rate / calcm) >> calcp;
}
static long sun6i_ahb1_clk_determine_rate(struct clk_hw *hw, unsigned long rate,
unsigned long min_rate,
unsigned long max_rate,
unsigned long *best_parent_rate,
struct clk_hw **best_parent_clk)
{
struct clk *clk = hw->clk, *parent, *best_parent = NULL;
int i, num_parents;
unsigned long parent_rate, best = 0, child_rate, best_child_rate = 0;
/* find the parent that can help provide the fastest rate <= rate */
num_parents = __clk_get_num_parents(clk);
for (i = 0; i < num_parents; i++) {
parent = clk_get_parent_by_index(clk, i);
if (!parent)
continue;
if (__clk_get_flags(clk) & CLK_SET_RATE_PARENT)
parent_rate = __clk_round_rate(parent, rate);
else
parent_rate = __clk_get_rate(parent);
child_rate = sun6i_ahb1_clk_round(rate, NULL, NULL, i,
parent_rate);
if (child_rate <= rate && child_rate > best_child_rate) {
best_parent = parent;
best = parent_rate;
best_child_rate = child_rate;
}
}
if (best_parent)
*best_parent_clk = __clk_get_hw(best_parent);
*best_parent_rate = best;
return best_child_rate;
}
static int sun6i_ahb1_clk_set_rate(struct clk_hw *hw, unsigned long rate,
unsigned long parent_rate)
{
struct sun6i_ahb1_clk *ahb1 = to_sun6i_ahb1_clk(hw);
unsigned long flags;
u8 div, pre_div, parent;
u32 reg;
spin_lock_irqsave(&clk_lock, flags);
reg = readl(ahb1->reg);
/* need to know which parent is used to apply pre-divider */
parent = SUN6I_AHB1_MUX_GET_PARENT(reg);
sun6i_ahb1_clk_round(rate, &div, &pre_div, parent, parent_rate);
reg = SUN6I_AHB1_DIV_SET(reg, div);
reg = SUN6I_AHB1_PLL6_DIV_SET(reg, pre_div);
writel(reg, ahb1->reg);
spin_unlock_irqrestore(&clk_lock, flags);
return 0;
}
static const struct clk_ops sun6i_ahb1_clk_ops = {
.determine_rate = sun6i_ahb1_clk_determine_rate,
.recalc_rate = sun6i_ahb1_clk_recalc_rate,
.set_rate = sun6i_ahb1_clk_set_rate,
};
static void __init sun6i_ahb1_clk_setup(struct device_node *node)
{
struct clk *clk;
struct sun6i_ahb1_clk *ahb1;
struct clk_mux *mux;
const char *clk_name = node->name;
const char *parents[SUN6I_AHB1_MAX_PARENTS];
void __iomem *reg;
int i = 0;
reg = of_io_request_and_map(node, 0, of_node_full_name(node));
/* we have a mux, we will have >1 parents */
while (i < SUN6I_AHB1_MAX_PARENTS &&
(parents[i] = of_clk_get_parent_name(node, i)) != NULL)
i++;
of_property_read_string(node, "clock-output-names", &clk_name);
ahb1 = kzalloc(sizeof(struct sun6i_ahb1_clk), GFP_KERNEL);
if (!ahb1)
return;
mux = kzalloc(sizeof(struct clk_mux), GFP_KERNEL);
if (!mux) {
kfree(ahb1);
return;
}
/* set up clock properties */
mux->reg = reg;
mux->shift = SUN6I_AHB1_MUX_SHIFT;
mux->mask = SUN6I_AHB1_MUX_MASK;
mux->lock = &clk_lock;
ahb1->reg = reg;
clk = clk_register_composite(NULL, clk_name, parents, i,
&mux->hw, &clk_mux_ops,
&ahb1->hw, &sun6i_ahb1_clk_ops,
NULL, NULL, 0);
if (!IS_ERR(clk)) {
of_clk_add_provider(node, of_clk_src_simple_get, clk);
clk_register_clkdev(clk, clk_name, NULL);
}
}
CLK_OF_DECLARE(sun6i_a31_ahb1, "allwinner,sun6i-a31-ahb1-clk", sun6i_ahb1_clk_setup);
/* Maximum number of parents our clocks have */
#define SUNXI_MAX_PARENTS 5
@@ -354,43 +564,6 @@ static void sun7i_a20_get_out_factors(u32 *freq, u32 parent_rate,
*p = calcp;
}
/**
* clk_sunxi_mmc_phase_control() - configures MMC clock phase control
*/
void clk_sunxi_mmc_phase_control(struct clk *clk, u8 sample, u8 output)
{
#define to_clk_composite(_hw) container_of(_hw, struct clk_composite, hw)
#define to_clk_factors(_hw) container_of(_hw, struct clk_factors, hw)
struct clk_hw *hw = __clk_get_hw(clk);
struct clk_composite *composite = to_clk_composite(hw);
struct clk_hw *rate_hw = composite->rate_hw;
struct clk_factors *factors = to_clk_factors(rate_hw);
unsigned long flags = 0;
u32 reg;
if (factors->lock)
spin_lock_irqsave(factors->lock, flags);
reg = readl(factors->reg);
/* set sample clock phase control */
reg &= ~(0x7 << 20);
reg |= ((sample & 0x7) << 20);
/* set output clock phase control */
reg &= ~(0x7 << 8);
reg |= ((output & 0x7) << 8);
writel(reg, factors->reg);
if (factors->lock)
spin_unlock_irqrestore(factors->lock, flags);
}
EXPORT_SYMBOL(clk_sunxi_mmc_phase_control);
/**
* sunxi_factors_clk_setup() - Setup function for factor clocks
*/
@@ -413,6 +586,7 @@ static struct clk_factors_config sun6i_a31_pll1_config = {
.kwidth = 2,
.mshift = 0,
.mwidth = 2,
.n_start = 1,
};
static struct clk_factors_config sun8i_a23_pll1_config = {
@@ -520,7 +694,16 @@ static const struct factors_data sun7i_a20_out_data __initconst = {
static struct clk * __init sunxi_factors_clk_setup(struct device_node *node,
const struct factors_data *data)
{
return sunxi_factors_register(node, data, &clk_lock);
void __iomem *reg;
reg = of_iomap(node, 0);
if (!reg) {
pr_err("Could not get registers for factors-clk: %s\n",
node->name);
return NULL;
}
return sunxi_factors_register(node, data, &clk_lock, reg);
}
@@ -561,7 +744,7 @@ static void __init sunxi_mux_clk_setup(struct device_node *node,
of_property_read_string(node, "clock-output-names", &clk_name);
clk = clk_register_mux(NULL, clk_name, parents, i,
CLK_SET_RATE_NO_REPARENT, reg,
CLK_SET_RATE_PARENT, reg,
data->shift, SUNXI_MUX_GATE_WIDTH,
0, &clk_lock);
@@ -1217,7 +1400,6 @@ CLK_OF_DECLARE(sun7i_a20_clk_init, "allwinner,sun7i-a20", sun5i_init_clocks);
static const char *sun6i_critical_clocks[] __initdata = {
"cpu",
"ahb1_sdram",
};
static void __init sun6i_init_clocks(struct device_node *node)