Allwinner sunXi SoCs clock changes

Those are mostly random fixes, except for one patch to the composite
 clock that adds support for automatic reparenting.
 -----BEGIN PGP SIGNATURE-----
 Version: GnuPG v1.4.12 (GNU/Linux)
 
 iQIcBAABAgAGBQJSf2QbAAoJEBx+YmzsjxAg1FMP/0iMDhjaqpeKfoZdfS+eYOPZ
 tE3AJq3JiCIeWWojYvHKCc+4JhYb5w0rW95Z6XOtV0zRLMhyj97bObSRGXv+uL0K
 1xyGtGDCqfIP3TIPlMt6sKzBZi6DVHyjkyVjQ1BvGFHKYgsnbMaOgODzANMUf4kE
 L/Z7JQGpFKNJgcJq6H8RuCT6FQYpD+2nLNbqFTcM52XFB39I1ztLiKXDB9wju738
 +M+oiXGYrg9iorzK3t26VfgqyYDDkJe7fn+66SPhTGhiWLpOpas/8hNyU8+wUs7h
 q1ACiAfOW2VFrQMbAbH6Az7wydXPZ7ruYxvcO7Ihbua60w382czOpeZOABoQ+ikg
 Ogby1mRU0cydAYne0/B/Ege+e60PivZQQ+1/6F8vIGZ1e8s+9DJZETNQV14wQ7gx
 3uB9AsmdDCfW7ky5kIXk9WbdCYrmcagtbpkbCnf701O8bayJHiLCw96DIwz3/EMm
 p682Su4L1/w06uUjdRJgjkhZqYgCQgD7ZKfXUEw8QIrTSTh9qQyXmWY0lpgW3c72
 WCLGp9TGeonuH4LxUAllFHNNQpsaZzeYSoz4q5+qkuqo3p12S7vzAQU4T/7LKL6y
 BMfVYPYB5HZof0vG/Cyngvjq9pq7dq+4eFwcwOJ4F6/UsNdBtmUcTEMbBnjfre4E
 V0U5CWDWhGI1s3n9Ibx3
 =sWyX
 -----END PGP SIGNATURE-----

Merge tag 'sunxi-clk-for-3.13' of https://github.com/mripard/linux into clk-next-sunxi-rebase

Allwinner sunXi SoCs clock changes

Those are mostly random fixes, except for one patch to the composite
clock that adds support for automatic reparenting.

Conflicts:
	drivers/clk/sunxi/clk-sunxi.c
This commit is contained in:
Mike Turquette 2013-12-01 12:42:45 -08:00
commit 1d9438f7b5
3 changed files with 76 additions and 14 deletions

View File

@ -55,6 +55,30 @@ static unsigned long clk_composite_recalc_rate(struct clk_hw *hw,
return rate_ops->recalc_rate(rate_hw, parent_rate); return rate_ops->recalc_rate(rate_hw, parent_rate);
} }
static long clk_composite_determine_rate(struct clk_hw *hw, unsigned long rate,
unsigned long *best_parent_rate,
struct clk **best_parent_p)
{
struct clk_composite *composite = to_clk_composite(hw);
const struct clk_ops *rate_ops = composite->rate_ops;
const struct clk_ops *mux_ops = composite->mux_ops;
struct clk_hw *rate_hw = composite->rate_hw;
struct clk_hw *mux_hw = composite->mux_hw;
if (rate_hw && rate_ops && rate_ops->determine_rate) {
rate_hw->clk = hw->clk;
return rate_ops->determine_rate(rate_hw, rate, best_parent_rate,
best_parent_p);
} else if (mux_hw && mux_ops && mux_ops->determine_rate) {
mux_hw->clk = hw->clk;
return mux_ops->determine_rate(rate_hw, rate, best_parent_rate,
best_parent_p);
} else {
pr_err("clk: clk_composite_determine_rate function called, but no mux or rate callback set!\n");
return 0;
}
}
static long clk_composite_round_rate(struct clk_hw *hw, unsigned long rate, static long clk_composite_round_rate(struct clk_hw *hw, unsigned long rate,
unsigned long *prate) unsigned long *prate)
{ {
@ -147,6 +171,8 @@ struct clk *clk_register_composite(struct device *dev, const char *name,
composite->mux_ops = mux_ops; composite->mux_ops = mux_ops;
clk_composite_ops->get_parent = clk_composite_get_parent; clk_composite_ops->get_parent = clk_composite_get_parent;
clk_composite_ops->set_parent = clk_composite_set_parent; clk_composite_ops->set_parent = clk_composite_set_parent;
if (mux_ops->determine_rate)
clk_composite_ops->determine_rate = clk_composite_determine_rate;
} }
if (rate_hw && rate_ops) { if (rate_hw && rate_ops) {
@ -170,6 +196,8 @@ struct clk *clk_register_composite(struct device *dev, const char *name,
composite->rate_hw = rate_hw; composite->rate_hw = rate_hw;
composite->rate_ops = rate_ops; composite->rate_ops = rate_ops;
clk_composite_ops->recalc_rate = clk_composite_recalc_rate; clk_composite_ops->recalc_rate = clk_composite_recalc_rate;
if (rate_ops->determine_rate)
clk_composite_ops->determine_rate = clk_composite_determine_rate;
} }
if (gate_hw && gate_ops) { if (gate_hw && gate_ops) {

View File

@ -40,7 +40,7 @@ struct clk_factors {
#define to_clk_factors(_hw) container_of(_hw, struct clk_factors, hw) #define to_clk_factors(_hw) container_of(_hw, struct clk_factors, hw)
#define SETMASK(len, pos) (((-1U) >> (31-len)) << (pos)) #define SETMASK(len, pos) (((1U << (len)) - 1) << (pos))
#define CLRMASK(len, pos) (~(SETMASK(len, pos))) #define CLRMASK(len, pos) (~(SETMASK(len, pos)))
#define FACTOR_GET(bit, len, reg) (((reg) & SETMASK(len, bit)) >> (bit)) #define FACTOR_GET(bit, len, reg) (((reg) & SETMASK(len, bit)) >> (bit))
@ -88,7 +88,7 @@ static long clk_factors_round_rate(struct clk_hw *hw, unsigned long rate,
static int clk_factors_set_rate(struct clk_hw *hw, unsigned long rate, static int clk_factors_set_rate(struct clk_hw *hw, unsigned long rate,
unsigned long parent_rate) unsigned long parent_rate)
{ {
u8 n, k, m, p; u8 n = 0, k = 0, m = 0, p = 0;
u32 reg; u32 reg;
struct clk_factors *factors = to_clk_factors(hw); struct clk_factors *factors = to_clk_factors(hw);
struct clk_factors_config *config = factors->config; struct clk_factors_config *config = factors->config;

View File

@ -37,18 +37,16 @@ static void __init sun4i_osc_clk_setup(struct device_node *node)
const char *clk_name = node->name; const char *clk_name = node->name;
u32 rate; u32 rate;
if (of_property_read_u32(node, "clock-frequency", &rate))
return;
/* allocate fixed-rate and gate clock structs */ /* allocate fixed-rate and gate clock structs */
fixed = kzalloc(sizeof(struct clk_fixed_rate), GFP_KERNEL); fixed = kzalloc(sizeof(struct clk_fixed_rate), GFP_KERNEL);
if (!fixed) if (!fixed)
return; return;
gate = kzalloc(sizeof(struct clk_gate), GFP_KERNEL); gate = kzalloc(sizeof(struct clk_gate), GFP_KERNEL);
if (!gate) { if (!gate)
kfree(fixed); goto err_free_fixed;
return;
}
if (of_property_read_u32(node, "clock-frequency", &rate))
return;
/* set up gate and fixed rate properties */ /* set up gate and fixed rate properties */
gate->reg = of_iomap(node, 0); gate->reg = of_iomap(node, 0);
@ -63,10 +61,18 @@ static void __init sun4i_osc_clk_setup(struct device_node *node)
&gate->hw, &clk_gate_ops, &gate->hw, &clk_gate_ops,
CLK_IS_ROOT); CLK_IS_ROOT);
if (!IS_ERR(clk)) { if (IS_ERR(clk))
of_clk_add_provider(node, of_clk_src_simple_get, clk); goto err_free_gate;
clk_register_clkdev(clk, clk_name, NULL);
} of_clk_add_provider(node, of_clk_src_simple_get, clk);
clk_register_clkdev(clk, clk_name, NULL);
return;
err_free_gate:
kfree(gate);
err_free_fixed:
kfree(fixed);
} }
CLK_OF_DECLARE(sun4i_osc, "allwinner,sun4i-osc-clk", sun4i_osc_clk_setup); CLK_OF_DECLARE(sun4i_osc, "allwinner,sun4i-osc-clk", sun4i_osc_clk_setup);
@ -616,7 +622,32 @@ static void __init of_sunxi_table_clock_setup(const struct of_device_id *clk_mat
} }
} }
static void __init sunxi_init_clocks(struct device_node *np) /**
* System clock protection
*
* By enabling these critical clocks, we prevent their accidental gating
* by the framework
*/
static void __init sunxi_clock_protect(void)
{
struct clk *clk;
/* memory bus clock - sun5i+ */
clk = clk_get(NULL, "mbus");
if (!IS_ERR(clk)) {
clk_prepare_enable(clk);
clk_put(clk);
}
/* DDR clock - sun4i+ */
clk = clk_get(NULL, "pll5_ddr");
if (!IS_ERR(clk)) {
clk_prepare_enable(clk);
clk_put(clk);
}
}
static void __init sunxi_init_clocks(void)
{ {
/* Register factor clocks */ /* Register factor clocks */
of_sunxi_table_clock_setup(clk_factors_match, sunxi_factors_clk_setup); of_sunxi_table_clock_setup(clk_factors_match, sunxi_factors_clk_setup);
@ -629,6 +660,9 @@ static void __init sunxi_init_clocks(struct device_node *np)
/* Register gate clocks */ /* Register gate clocks */
of_sunxi_table_clock_setup(clk_gates_match, sunxi_gates_clk_setup); of_sunxi_table_clock_setup(clk_gates_match, sunxi_gates_clk_setup);
/* Enable core system clocks */
sunxi_clock_protect();
} }
CLK_OF_DECLARE(sun4i_a10_clk_init, "allwinner,sun4i-a10", sunxi_init_clocks); CLK_OF_DECLARE(sun4i_a10_clk_init, "allwinner,sun4i-a10", sunxi_init_clocks);
CLK_OF_DECLARE(sun5i_a10s_clk_init, "allwinner,sun5i-a10s", sunxi_init_clocks); CLK_OF_DECLARE(sun5i_a10s_clk_init, "allwinner,sun5i-a10s", sunxi_init_clocks);