aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMaxime Ripard <maxime.ripard@free-electrons.com>2015-09-21 07:32:43 -0400
committerMaxime Ripard <maxime.ripard@free-electrons.com>2015-10-21 15:51:28 -0400
commiteb662f854710e6a438789a4b0d1d0cce8c12379d (patch)
tree1550ceffb453194a49357c0321b0c6dd56b279ba
parent460d0d444822e9032a2573fc051b45c68b89a97a (diff)
clk: sunxi: pll2: Add A13 support
The A13, unlike the A10 and A20, doesn't use a pass-through exception for the 0 value in the pre and post dividers, but increments all the values written in the register by one. Add an exception for both these cases to handle them nicely. Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com> Reviewed-by: Chen-Yu Tsai <wens@csie.org>
-rw-r--r--drivers/clk/sunxi/clk-a10-pll2.c38
1 files changed, 33 insertions, 5 deletions
diff --git a/drivers/clk/sunxi/clk-a10-pll2.c b/drivers/clk/sunxi/clk-a10-pll2.c
index a57742a8576d..5484c31ec568 100644
--- a/drivers/clk/sunxi/clk-a10-pll2.c
+++ b/drivers/clk/sunxi/clk-a10-pll2.c
@@ -41,9 +41,15 @@
41 41
42#define SUN4I_PLL2_OUTPUTS 4 42#define SUN4I_PLL2_OUTPUTS 4
43 43
44struct sun4i_pll2_data {
45 u32 post_div_offset;
46 u32 pre_div_flags;
47};
48
44static DEFINE_SPINLOCK(sun4i_a10_pll2_lock); 49static DEFINE_SPINLOCK(sun4i_a10_pll2_lock);
45 50
46static void __init sun4i_pll2_setup(struct device_node *node) 51static void __init sun4i_pll2_setup(struct device_node *node,
52 struct sun4i_pll2_data *data)
47{ 53{
48 const char *clk_name = node->name, *parent; 54 const char *clk_name = node->name, *parent;
49 struct clk **clks, *base_clk, *prediv_clk; 55 struct clk **clks, *base_clk, *prediv_clk;
@@ -70,8 +76,7 @@ static void __init sun4i_pll2_setup(struct device_node *node)
70 parent, 0, reg, 76 parent, 0, reg,
71 SUN4I_PLL2_PRE_DIV_SHIFT, 77 SUN4I_PLL2_PRE_DIV_SHIFT,
72 SUN4I_PLL2_PRE_DIV_WIDTH, 78 SUN4I_PLL2_PRE_DIV_WIDTH,
73 CLK_DIVIDER_ONE_BASED | 79 data->pre_div_flags,
74 CLK_DIVIDER_ALLOW_ZERO,
75 &sun4i_a10_pll2_lock); 80 &sun4i_a10_pll2_lock);
76 if (!prediv_clk) { 81 if (!prediv_clk) {
77 pr_err("Couldn't register the prediv clock\n"); 82 pr_err("Couldn't register the prediv clock\n");
@@ -122,7 +127,7 @@ static void __init sun4i_pll2_setup(struct device_node *node)
122 */ 127 */
123 val = readl(reg); 128 val = readl(reg);
124 val &= ~(SUN4I_PLL2_POST_DIV_MASK << SUN4I_PLL2_POST_DIV_SHIFT); 129 val &= ~(SUN4I_PLL2_POST_DIV_MASK << SUN4I_PLL2_POST_DIV_SHIFT);
125 val |= SUN4I_PLL2_POST_DIV_VALUE << SUN4I_PLL2_POST_DIV_SHIFT; 130 val |= (SUN4I_PLL2_POST_DIV_VALUE - data->post_div_offset) << SUN4I_PLL2_POST_DIV_SHIFT;
126 writel(val, reg); 131 writel(val, reg);
127 132
128 of_property_read_string_index(node, "clock-output-names", 133 of_property_read_string_index(node, "clock-output-names",
@@ -185,4 +190,27 @@ err_free_data:
185err_unmap: 190err_unmap:
186 iounmap(reg); 191 iounmap(reg);
187} 192}
188CLK_OF_DECLARE(sun4i_pll2, "allwinner,sun4i-a10-pll2-clk", sun4i_pll2_setup); 193
194static struct sun4i_pll2_data sun4i_a10_pll2_data = {
195 .pre_div_flags = CLK_DIVIDER_ONE_BASED | CLK_DIVIDER_ALLOW_ZERO,
196};
197
198static void __init sun4i_a10_pll2_setup(struct device_node *node)
199{
200 sun4i_pll2_setup(node, &sun4i_a10_pll2_data);
201}
202
203CLK_OF_DECLARE(sun4i_a10_pll2, "allwinner,sun4i-a10-pll2-clk",
204 sun4i_a10_pll2_setup);
205
206static struct sun4i_pll2_data sun5i_a13_pll2_data = {
207 .post_div_offset = 1,
208};
209
210static void __init sun5i_a13_pll2_setup(struct device_node *node)
211{
212 sun4i_pll2_setup(node, &sun5i_a13_pll2_data);
213}
214
215CLK_OF_DECLARE(sun5i_a13_pll2, "allwinner,sun5i-a13-pll2-clk",
216 sun5i_a13_pll2_setup);