aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorOlof Johansson <olof@lixom.net>2015-10-26 01:42:37 -0400
committerOlof Johansson <olof@lixom.net>2015-10-26 01:42:37 -0400
commitedd2a06d9c06a28f6f636929d586d17de835cd6b (patch)
tree97c8d63dd247494999bda213da1b845de853cf69
parent64ebda3acd6ea592e6f97dcd0682e87aa7cf8d61 (diff)
parent9b038bc58ad2658c76fd8b50bb333dfd4454573c (diff)
Merge tag 'sunxi-clocks-for-4.4' of https://git.kernel.org/pub/scm/linux/kernel/git/mripard/linux into next/dt
Bringing in the sunxi clock branch since it introduces header file contents that is needed by the DT branch. This is a stable tag shared with the clk tree. Allwinner clock additions for 4.4 - Support for the Audio PLL and child clocks - Support for the A33 AHB gates - New clk-multiplier generic driver * tag 'sunxi-clocks-for-4.4' of https://git.kernel.org/pub/scm/linux/kernel/git/mripard/linux: clk: sunxi: mod1 clock support clk: sunxi: codec clock support clk: sunxi: pll2: Add A13 support clk: sunxi: Add a driver for the PLL2 clk: Add a basic multiplier clock clk: sunxi: Add A33 gates support Signed-off-by: Olof Johansson <olof@lixom.net>
-rw-r--r--drivers/clk/Makefile1
-rw-r--r--drivers/clk/clk-multiplier.c181
-rw-r--r--drivers/clk/sunxi/Makefile3
-rw-r--r--drivers/clk/sunxi/clk-a10-codec.c44
-rw-r--r--drivers/clk/sunxi/clk-a10-mod1.c81
-rw-r--r--drivers/clk/sunxi/clk-a10-pll2.c216
-rw-r--r--drivers/clk/sunxi/clk-simple-gates.c2
-rw-r--r--include/dt-bindings/clock/sun4i-a10-pll2.h53
-rw-r--r--include/linux/clk-provider.h42
9 files changed, 623 insertions, 0 deletions
diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile
index 9f7155855391..0066a06abbf3 100644
--- a/drivers/clk/Makefile
+++ b/drivers/clk/Makefile
@@ -6,6 +6,7 @@ obj-$(CONFIG_COMMON_CLK) += clk-divider.o
6obj-$(CONFIG_COMMON_CLK) += clk-fixed-factor.o 6obj-$(CONFIG_COMMON_CLK) += clk-fixed-factor.o
7obj-$(CONFIG_COMMON_CLK) += clk-fixed-rate.o 7obj-$(CONFIG_COMMON_CLK) += clk-fixed-rate.o
8obj-$(CONFIG_COMMON_CLK) += clk-gate.o 8obj-$(CONFIG_COMMON_CLK) += clk-gate.o
9obj-$(CONFIG_COMMON_CLK) += clk-multiplier.o
9obj-$(CONFIG_COMMON_CLK) += clk-mux.o 10obj-$(CONFIG_COMMON_CLK) += clk-mux.o
10obj-$(CONFIG_COMMON_CLK) += clk-composite.o 11obj-$(CONFIG_COMMON_CLK) += clk-composite.o
11obj-$(CONFIG_COMMON_CLK) += clk-fractional-divider.o 12obj-$(CONFIG_COMMON_CLK) += clk-fractional-divider.o
diff --git a/drivers/clk/clk-multiplier.c b/drivers/clk/clk-multiplier.c
new file mode 100644
index 000000000000..43ec269fcbff
--- /dev/null
+++ b/drivers/clk/clk-multiplier.c
@@ -0,0 +1,181 @@
1/*
2 * Copyright (C) 2015 Maxime Ripard <maxime.ripard@free-electrons.com>
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation.
7 */
8
9#include <linux/bitops.h>
10#include <linux/clk-provider.h>
11#include <linux/err.h>
12#include <linux/export.h>
13#include <linux/kernel.h>
14#include <linux/of.h>
15#include <linux/slab.h>
16
17#define to_clk_multiplier(_hw) container_of(_hw, struct clk_multiplier, hw)
18
19static unsigned long __get_mult(struct clk_multiplier *mult,
20 unsigned long rate,
21 unsigned long parent_rate)
22{
23 if (mult->flags & CLK_MULTIPLIER_ROUND_CLOSEST)
24 return DIV_ROUND_CLOSEST(rate, parent_rate);
25
26 return rate / parent_rate;
27}
28
29static unsigned long clk_multiplier_recalc_rate(struct clk_hw *hw,
30 unsigned long parent_rate)
31{
32 struct clk_multiplier *mult = to_clk_multiplier(hw);
33 unsigned long val;
34
35 val = clk_readl(mult->reg) >> mult->shift;
36 val &= GENMASK(mult->width - 1, 0);
37
38 if (!val && mult->flags & CLK_MULTIPLIER_ZERO_BYPASS)
39 val = 1;
40
41 return parent_rate * val;
42}
43
44static bool __is_best_rate(unsigned long rate, unsigned long new,
45 unsigned long best, unsigned long flags)
46{
47 if (flags & CLK_MULTIPLIER_ROUND_CLOSEST)
48 return abs(rate - new) < abs(rate - best);
49
50 return new >= rate && new < best;
51}
52
53static unsigned long __bestmult(struct clk_hw *hw, unsigned long rate,
54 unsigned long *best_parent_rate,
55 u8 width, unsigned long flags)
56{
57 unsigned long orig_parent_rate = *best_parent_rate;
58 unsigned long parent_rate, current_rate, best_rate = ~0;
59 unsigned int i, bestmult = 0;
60
61 if (!(clk_hw_get_flags(hw) & CLK_SET_RATE_PARENT))
62 return rate / *best_parent_rate;
63
64 for (i = 1; i < ((1 << width) - 1); i++) {
65 if (rate == orig_parent_rate * i) {
66 /*
67 * This is the best case for us if we have a
68 * perfect match without changing the parent
69 * rate.
70 */
71 *best_parent_rate = orig_parent_rate;
72 return i;
73 }
74
75 parent_rate = clk_hw_round_rate(clk_hw_get_parent(hw),
76 rate / i);
77 current_rate = parent_rate * i;
78
79 if (__is_best_rate(rate, current_rate, best_rate, flags)) {
80 bestmult = i;
81 best_rate = current_rate;
82 *best_parent_rate = parent_rate;
83 }
84 }
85
86 return bestmult;
87}
88
89static long clk_multiplier_round_rate(struct clk_hw *hw, unsigned long rate,
90 unsigned long *parent_rate)
91{
92 struct clk_multiplier *mult = to_clk_multiplier(hw);
93 unsigned long factor = __bestmult(hw, rate, parent_rate,
94 mult->width, mult->flags);
95
96 return *parent_rate * factor;
97}
98
99static int clk_multiplier_set_rate(struct clk_hw *hw, unsigned long rate,
100 unsigned long parent_rate)
101{
102 struct clk_multiplier *mult = to_clk_multiplier(hw);
103 unsigned long factor = __get_mult(mult, rate, parent_rate);
104 unsigned long flags = 0;
105 unsigned long val;
106
107 if (mult->lock)
108 spin_lock_irqsave(mult->lock, flags);
109 else
110 __acquire(mult->lock);
111
112 val = clk_readl(mult->reg);
113 val &= ~GENMASK(mult->width + mult->shift - 1, mult->shift);
114 val |= factor << mult->shift;
115 clk_writel(val, mult->reg);
116
117 if (mult->lock)
118 spin_unlock_irqrestore(mult->lock, flags);
119 else
120 __release(mult->lock);
121
122 return 0;
123}
124
125const struct clk_ops clk_multiplier_ops = {
126 .recalc_rate = clk_multiplier_recalc_rate,
127 .round_rate = clk_multiplier_round_rate,
128 .set_rate = clk_multiplier_set_rate,
129};
130EXPORT_SYMBOL_GPL(clk_multiplier_ops);
131
132struct clk *clk_register_multiplier(struct device *dev, const char *name,
133 const char *parent_name,
134 unsigned long flags,
135 void __iomem *reg, u8 shift, u8 width,
136 u8 clk_mult_flags, spinlock_t *lock)
137{
138 struct clk_init_data init;
139 struct clk_multiplier *mult;
140 struct clk *clk;
141
142 mult = kmalloc(sizeof(*mult), GFP_KERNEL);
143 if (!mult)
144 return ERR_PTR(-ENOMEM);
145
146 init.name = name;
147 init.ops = &clk_multiplier_ops;
148 init.flags = flags | CLK_IS_BASIC;
149 init.parent_names = &parent_name;
150 init.num_parents = 1;
151
152 mult->reg = reg;
153 mult->shift = shift;
154 mult->width = width;
155 mult->flags = clk_mult_flags;
156 mult->lock = lock;
157 mult->hw.init = &init;
158
159 clk = clk_register(dev, &mult->hw);
160 if (IS_ERR(clk))
161 kfree(mult);
162
163 return clk;
164}
165EXPORT_SYMBOL_GPL(clk_register_multiplier);
166
167void clk_unregister_multiplier(struct clk *clk)
168{
169 struct clk_multiplier *mult;
170 struct clk_hw *hw;
171
172 hw = __clk_get_hw(clk);
173 if (!hw)
174 return;
175
176 mult = to_clk_multiplier(hw);
177
178 clk_unregister(clk);
179 kfree(mult);
180}
181EXPORT_SYMBOL_GPL(clk_unregister_multiplier);
diff --git a/drivers/clk/sunxi/Makefile b/drivers/clk/sunxi/Makefile
index f5a35b82cc1a..cb4c299214ce 100644
--- a/drivers/clk/sunxi/Makefile
+++ b/drivers/clk/sunxi/Makefile
@@ -3,7 +3,10 @@
3# 3#
4 4
5obj-y += clk-sunxi.o clk-factors.o 5obj-y += clk-sunxi.o clk-factors.o
6obj-y += clk-a10-codec.o
6obj-y += clk-a10-hosc.o 7obj-y += clk-a10-hosc.o
8obj-y += clk-a10-mod1.o
9obj-y += clk-a10-pll2.o
7obj-y += clk-a20-gmac.o 10obj-y += clk-a20-gmac.o
8obj-y += clk-mod0.o 11obj-y += clk-mod0.o
9obj-y += clk-simple-gates.o 12obj-y += clk-simple-gates.o
diff --git a/drivers/clk/sunxi/clk-a10-codec.c b/drivers/clk/sunxi/clk-a10-codec.c
new file mode 100644
index 000000000000..ac321d6a0df5
--- /dev/null
+++ b/drivers/clk/sunxi/clk-a10-codec.c
@@ -0,0 +1,44 @@
1/*
2 * Copyright 2013 Emilio López
3 *
4 * Emilio López <emilio@elopez.com.ar>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 */
16
17#include <linux/clk-provider.h>
18#include <linux/of.h>
19#include <linux/of_address.h>
20
21#define SUN4I_CODEC_GATE 31
22
23static void __init sun4i_codec_clk_setup(struct device_node *node)
24{
25 struct clk *clk;
26 const char *clk_name = node->name, *parent_name;
27 void __iomem *reg;
28
29 reg = of_io_request_and_map(node, 0, of_node_full_name(node));
30 if (IS_ERR(reg))
31 return;
32
33 of_property_read_string(node, "clock-output-names", &clk_name);
34 parent_name = of_clk_get_parent_name(node, 0);
35
36 clk = clk_register_gate(NULL, clk_name, parent_name,
37 CLK_SET_RATE_PARENT, reg,
38 SUN4I_CODEC_GATE, 0, NULL);
39
40 if (!IS_ERR(clk))
41 of_clk_add_provider(node, of_clk_src_simple_get, clk);
42}
43CLK_OF_DECLARE(sun4i_codec, "allwinner,sun4i-a10-codec-clk",
44 sun4i_codec_clk_setup);
diff --git a/drivers/clk/sunxi/clk-a10-mod1.c b/drivers/clk/sunxi/clk-a10-mod1.c
new file mode 100644
index 000000000000..e9d870de165c
--- /dev/null
+++ b/drivers/clk/sunxi/clk-a10-mod1.c
@@ -0,0 +1,81 @@
1/*
2 * Copyright 2013 Emilio López
3 *
4 * Emilio López <emilio@elopez.com.ar>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 */
16
17#include <linux/clk-provider.h>
18#include <linux/of.h>
19#include <linux/of_address.h>
20#include <linux/slab.h>
21
22static DEFINE_SPINLOCK(mod1_lock);
23
24#define SUN4I_MOD1_ENABLE 31
25#define SUN4I_MOD1_MUX 16
26#define SUN4I_MOD1_MUX_WIDTH 2
27#define SUN4I_MOD1_MAX_PARENTS 4
28
29static void __init sun4i_mod1_clk_setup(struct device_node *node)
30{
31 struct clk *clk;
32 struct clk_mux *mux;
33 struct clk_gate *gate;
34 const char *parents[4];
35 const char *clk_name = node->name;
36 void __iomem *reg;
37 int i;
38
39 reg = of_io_request_and_map(node, 0, of_node_full_name(node));
40 if (IS_ERR(reg))
41 return;
42
43 mux = kzalloc(sizeof(*mux), GFP_KERNEL);
44 if (!mux)
45 goto err_unmap;
46
47 gate = kzalloc(sizeof(*gate), GFP_KERNEL);
48 if (!gate)
49 goto err_free_mux;
50
51 of_property_read_string(node, "clock-output-names", &clk_name);
52 i = of_clk_parent_fill(node, parents, SUN4I_MOD1_MAX_PARENTS);
53
54 gate->reg = reg;
55 gate->bit_idx = SUN4I_MOD1_ENABLE;
56 gate->lock = &mod1_lock;
57 mux->reg = reg;
58 mux->shift = SUN4I_MOD1_MUX;
59 mux->mask = BIT(SUN4I_MOD1_MUX_WIDTH) - 1;
60 mux->lock = &mod1_lock;
61
62 clk = clk_register_composite(NULL, clk_name, parents, i,
63 &mux->hw, &clk_mux_ops,
64 NULL, NULL,
65 &gate->hw, &clk_gate_ops, 0);
66 if (IS_ERR(clk))
67 goto err_free_gate;
68
69 of_clk_add_provider(node, of_clk_src_simple_get, clk);
70
71 return;
72
73err_free_gate:
74 kfree(gate);
75err_free_mux:
76 kfree(mux);
77err_unmap:
78 iounmap(reg);
79}
80CLK_OF_DECLARE(sun4i_mod1, "allwinner,sun4i-a10-mod1-clk",
81 sun4i_mod1_clk_setup);
diff --git a/drivers/clk/sunxi/clk-a10-pll2.c b/drivers/clk/sunxi/clk-a10-pll2.c
new file mode 100644
index 000000000000..5484c31ec568
--- /dev/null
+++ b/drivers/clk/sunxi/clk-a10-pll2.c
@@ -0,0 +1,216 @@
1/*
2 * Copyright 2013 Emilio López
3 * Emilio López <emilio@elopez.com.ar>
4 *
5 * Copyright 2015 Maxime Ripard
6 * Maxime Ripard <maxime.ripard@free-electrons.com>
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 */
18
19#include <linux/clk-provider.h>
20#include <linux/of.h>
21#include <linux/of_address.h>
22#include <linux/slab.h>
23
24#include <dt-bindings/clock/sun4i-a10-pll2.h>
25
26#define SUN4I_PLL2_ENABLE 31
27
28#define SUN4I_PLL2_PRE_DIV_SHIFT 0
29#define SUN4I_PLL2_PRE_DIV_WIDTH 5
30#define SUN4I_PLL2_PRE_DIV_MASK GENMASK(SUN4I_PLL2_PRE_DIV_WIDTH - 1, 0)
31
32#define SUN4I_PLL2_N_SHIFT 8
33#define SUN4I_PLL2_N_WIDTH 7
34#define SUN4I_PLL2_N_MASK GENMASK(SUN4I_PLL2_N_WIDTH - 1, 0)
35
36#define SUN4I_PLL2_POST_DIV_SHIFT 26
37#define SUN4I_PLL2_POST_DIV_WIDTH 4
38#define SUN4I_PLL2_POST_DIV_MASK GENMASK(SUN4I_PLL2_POST_DIV_WIDTH - 1, 0)
39
40#define SUN4I_PLL2_POST_DIV_VALUE 4
41
42#define SUN4I_PLL2_OUTPUTS 4
43
44struct sun4i_pll2_data {
45 u32 post_div_offset;
46 u32 pre_div_flags;
47};
48
49static DEFINE_SPINLOCK(sun4i_a10_pll2_lock);
50
51static void __init sun4i_pll2_setup(struct device_node *node,
52 struct sun4i_pll2_data *data)
53{
54 const char *clk_name = node->name, *parent;
55 struct clk **clks, *base_clk, *prediv_clk;
56 struct clk_onecell_data *clk_data;
57 struct clk_multiplier *mult;
58 struct clk_gate *gate;
59 void __iomem *reg;
60 u32 val;
61
62 reg = of_io_request_and_map(node, 0, of_node_full_name(node));
63 if (IS_ERR(reg))
64 return;
65
66 clk_data = kzalloc(sizeof(*clk_data), GFP_KERNEL);
67 if (!clk_data)
68 goto err_unmap;
69
70 clks = kcalloc(SUN4I_PLL2_OUTPUTS, sizeof(struct clk *), GFP_KERNEL);
71 if (!clks)
72 goto err_free_data;
73
74 parent = of_clk_get_parent_name(node, 0);
75 prediv_clk = clk_register_divider(NULL, "pll2-prediv",
76 parent, 0, reg,
77 SUN4I_PLL2_PRE_DIV_SHIFT,
78 SUN4I_PLL2_PRE_DIV_WIDTH,
79 data->pre_div_flags,
80 &sun4i_a10_pll2_lock);
81 if (!prediv_clk) {
82 pr_err("Couldn't register the prediv clock\n");
83 goto err_free_array;
84 }
85
86 /* Setup the gate part of the PLL2 */
87 gate = kzalloc(sizeof(struct clk_gate), GFP_KERNEL);
88 if (!gate)
89 goto err_unregister_prediv;
90
91 gate->reg = reg;
92 gate->bit_idx = SUN4I_PLL2_ENABLE;
93 gate->lock = &sun4i_a10_pll2_lock;
94
95 /* Setup the multiplier part of the PLL2 */
96 mult = kzalloc(sizeof(struct clk_multiplier), GFP_KERNEL);
97 if (!mult)
98 goto err_free_gate;
99
100 mult->reg = reg;
101 mult->shift = SUN4I_PLL2_N_SHIFT;
102 mult->width = 7;
103 mult->flags = CLK_MULTIPLIER_ZERO_BYPASS |
104 CLK_MULTIPLIER_ROUND_CLOSEST;
105 mult->lock = &sun4i_a10_pll2_lock;
106
107 parent = __clk_get_name(prediv_clk);
108 base_clk = clk_register_composite(NULL, "pll2-base",
109 &parent, 1,
110 NULL, NULL,
111 &mult->hw, &clk_multiplier_ops,
112 &gate->hw, &clk_gate_ops,
113 CLK_SET_RATE_PARENT);
114 if (!base_clk) {
115 pr_err("Couldn't register the base multiplier clock\n");
116 goto err_free_multiplier;
117 }
118
119 parent = __clk_get_name(base_clk);
120
121 /*
122 * PLL2-1x
123 *
124 * This is supposed to have a post divider, but we won't need
125 * to use it, we just need to initialise it to 4, and use a
126 * fixed divider.
127 */
128 val = readl(reg);
129 val &= ~(SUN4I_PLL2_POST_DIV_MASK << SUN4I_PLL2_POST_DIV_SHIFT);
130 val |= (SUN4I_PLL2_POST_DIV_VALUE - data->post_div_offset) << SUN4I_PLL2_POST_DIV_SHIFT;
131 writel(val, reg);
132
133 of_property_read_string_index(node, "clock-output-names",
134 SUN4I_A10_PLL2_1X, &clk_name);
135 clks[SUN4I_A10_PLL2_1X] = clk_register_fixed_factor(NULL, clk_name,
136 parent,
137 CLK_SET_RATE_PARENT,
138 1,
139 SUN4I_PLL2_POST_DIV_VALUE);
140 WARN_ON(IS_ERR(clks[SUN4I_A10_PLL2_1X]));
141
142 /*
143 * PLL2-2x
144 *
145 * This clock doesn't use the post divider, and really is just
146 * a fixed divider from the PLL2 base clock.
147 */
148 of_property_read_string_index(node, "clock-output-names",
149 SUN4I_A10_PLL2_2X, &clk_name);
150 clks[SUN4I_A10_PLL2_2X] = clk_register_fixed_factor(NULL, clk_name,
151 parent,
152 CLK_SET_RATE_PARENT,
153 1, 2);
154 WARN_ON(IS_ERR(clks[SUN4I_A10_PLL2_2X]));
155
156 /* PLL2-4x */
157 of_property_read_string_index(node, "clock-output-names",
158 SUN4I_A10_PLL2_4X, &clk_name);
159 clks[SUN4I_A10_PLL2_4X] = clk_register_fixed_factor(NULL, clk_name,
160 parent,
161 CLK_SET_RATE_PARENT,
162 1, 1);
163 WARN_ON(IS_ERR(clks[SUN4I_A10_PLL2_4X]));
164
165 /* PLL2-8x */
166 of_property_read_string_index(node, "clock-output-names",
167 SUN4I_A10_PLL2_8X, &clk_name);
168 clks[SUN4I_A10_PLL2_8X] = clk_register_fixed_factor(NULL, clk_name,
169 parent,
170 CLK_SET_RATE_PARENT,
171 2, 1);
172 WARN_ON(IS_ERR(clks[SUN4I_A10_PLL2_8X]));
173
174 clk_data->clks = clks;
175 clk_data->clk_num = SUN4I_PLL2_OUTPUTS;
176 of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
177
178 return;
179
180err_free_multiplier:
181 kfree(mult);
182err_free_gate:
183 kfree(gate);
184err_unregister_prediv:
185 clk_unregister_divider(prediv_clk);
186err_free_array:
187 kfree(clks);
188err_free_data:
189 kfree(clk_data);
190err_unmap:
191 iounmap(reg);
192}
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);
diff --git a/drivers/clk/sunxi/clk-simple-gates.c b/drivers/clk/sunxi/clk-simple-gates.c
index 6ce91180da1b..0214c6548afd 100644
--- a/drivers/clk/sunxi/clk-simple-gates.c
+++ b/drivers/clk/sunxi/clk-simple-gates.c
@@ -128,6 +128,8 @@ CLK_OF_DECLARE(sun8i_a23_apb1, "allwinner,sun8i-a23-apb1-gates-clk",
128 sunxi_simple_gates_init); 128 sunxi_simple_gates_init);
129CLK_OF_DECLARE(sun8i_a23_apb2, "allwinner,sun8i-a23-apb2-gates-clk", 129CLK_OF_DECLARE(sun8i_a23_apb2, "allwinner,sun8i-a23-apb2-gates-clk",
130 sunxi_simple_gates_init); 130 sunxi_simple_gates_init);
131CLK_OF_DECLARE(sun8i_a33_ahb1, "allwinner,sun8i-a33-ahb1-gates-clk",
132 sunxi_simple_gates_init);
131CLK_OF_DECLARE(sun9i_a80_ahb0, "allwinner,sun9i-a80-ahb0-gates-clk", 133CLK_OF_DECLARE(sun9i_a80_ahb0, "allwinner,sun9i-a80-ahb0-gates-clk",
132 sunxi_simple_gates_init); 134 sunxi_simple_gates_init);
133CLK_OF_DECLARE(sun9i_a80_ahb1, "allwinner,sun9i-a80-ahb1-gates-clk", 135CLK_OF_DECLARE(sun9i_a80_ahb1, "allwinner,sun9i-a80-ahb1-gates-clk",
diff --git a/include/dt-bindings/clock/sun4i-a10-pll2.h b/include/dt-bindings/clock/sun4i-a10-pll2.h
new file mode 100644
index 000000000000..071c8112d531
--- /dev/null
+++ b/include/dt-bindings/clock/sun4i-a10-pll2.h
@@ -0,0 +1,53 @@
1/*
2 * Copyright 2015 Maxime Ripard
3 *
4 * Maxime Ripard <maxime.ripard@free-electrons.com>
5 *
6 * This file is dual-licensed: you can use it either under the terms
7 * of the GPL or the X11 license, at your option. Note that this dual
8 * licensing only applies to this file, and not this project as a
9 * whole.
10 *
11 * a) This file is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU General Public License as
13 * published by the Free Software Foundation; either version 2 of the
14 * License, or (at your option) any later version.
15 *
16 * This file is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
20 *
21 * Or, alternatively,
22 *
23 * b) Permission is hereby granted, free of charge, to any person
24 * obtaining a copy of this software and associated documentation
25 * files (the "Software"), to deal in the Software without
26 * restriction, including without limitation the rights to use,
27 * copy, modify, merge, publish, distribute, sublicense, and/or
28 * sell copies of the Software, and to permit persons to whom the
29 * Software is furnished to do so, subject to the following
30 * conditions:
31 *
32 * The above copyright notice and this permission notice shall be
33 * included in all copies or substantial portions of the Software.
34 *
35 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
36 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
37 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
38 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
39 * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
40 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
41 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
42 * OTHER DEALINGS IN THE SOFTWARE.
43 */
44
45#ifndef __DT_BINDINGS_CLOCK_SUN4I_A10_PLL2_H_
46#define __DT_BINDINGS_CLOCK_SUN4I_A10_PLL2_H_
47
48#define SUN4I_A10_PLL2_1X 0
49#define SUN4I_A10_PLL2_2X 1
50#define SUN4I_A10_PLL2_4X 2
51#define SUN4I_A10_PLL2_8X 3
52
53#endif /* __DT_BINDINGS_CLOCK_SUN4I_A10_PLL2_H_ */
diff --git a/include/linux/clk-provider.h b/include/linux/clk-provider.h
index 3ecc07d0da77..6a7dfe33a317 100644
--- a/include/linux/clk-provider.h
+++ b/include/linux/clk-provider.h
@@ -518,6 +518,48 @@ struct clk *clk_register_fractional_divider(struct device *dev,
518 void __iomem *reg, u8 mshift, u8 mwidth, u8 nshift, u8 nwidth, 518 void __iomem *reg, u8 mshift, u8 mwidth, u8 nshift, u8 nwidth,
519 u8 clk_divider_flags, spinlock_t *lock); 519 u8 clk_divider_flags, spinlock_t *lock);
520 520
521/**
522 * struct clk_multiplier - adjustable multiplier clock
523 *
524 * @hw: handle between common and hardware-specific interfaces
525 * @reg: register containing the multiplier
526 * @shift: shift to the multiplier bit field
527 * @width: width of the multiplier bit field
528 * @lock: register lock
529 *
530 * Clock with an adjustable multiplier affecting its output frequency.
531 * Implements .recalc_rate, .set_rate and .round_rate
532 *
533 * Flags:
534 * CLK_MULTIPLIER_ZERO_BYPASS - By default, the multiplier is the value read
535 * from the register, with 0 being a valid value effectively
536 * zeroing the output clock rate. If CLK_MULTIPLIER_ZERO_BYPASS is
537 * set, then a null multiplier will be considered as a bypass,
538 * leaving the parent rate unmodified.
539 * CLK_MULTIPLIER_ROUND_CLOSEST - Makes the best calculated divider to be
540 * rounded to the closest integer instead of the down one.
541 */
542struct clk_multiplier {
543 struct clk_hw hw;
544 void __iomem *reg;
545 u8 shift;
546 u8 width;
547 u8 flags;
548 spinlock_t *lock;
549};
550
551#define CLK_MULTIPLIER_ZERO_BYPASS BIT(0)
552#define CLK_MULTIPLIER_ROUND_CLOSEST BIT(1)
553
554extern const struct clk_ops clk_multiplier_ops;
555
556struct clk *clk_register_multiplier(struct device *dev, const char *name,
557 const char *parent_name,
558 unsigned long flags,
559 void __iomem *reg, u8 shift, u8 width,
560 u8 clk_mult_flags, spinlock_t *lock);
561void clk_unregister_multiplier(struct clk *clk);
562
521/*** 563/***
522 * struct clk_composite - aggregate clock of mux, divider and gate clocks 564 * struct clk_composite - aggregate clock of mux, divider and gate clocks
523 * 565 *