aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/clk/mmp/Makefile2
-rw-r--r--drivers/clk/mmp/clk.c192
-rw-r--r--drivers/clk/mmp/clk.h106
3 files changed, 298 insertions, 2 deletions
diff --git a/drivers/clk/mmp/Makefile b/drivers/clk/mmp/Makefile
index 2855f7b686ed..32b5b90c9fa9 100644
--- a/drivers/clk/mmp/Makefile
+++ b/drivers/clk/mmp/Makefile
@@ -2,7 +2,7 @@
2# Makefile for mmp specific clk 2# Makefile for mmp specific clk
3# 3#
4 4
5obj-y += clk-apbc.o clk-apmu.o clk-frac.o clk-mix.o clk-gate.o 5obj-y += clk-apbc.o clk-apmu.o clk-frac.o clk-mix.o clk-gate.o clk.o
6 6
7obj-$(CONFIG_CPU_PXA168) += clk-pxa168.o 7obj-$(CONFIG_CPU_PXA168) += clk-pxa168.o
8obj-$(CONFIG_CPU_PXA910) += clk-pxa910.o 8obj-$(CONFIG_CPU_PXA910) += clk-pxa910.o
diff --git a/drivers/clk/mmp/clk.c b/drivers/clk/mmp/clk.c
new file mode 100644
index 000000000000..cf038ef54c59
--- /dev/null
+++ b/drivers/clk/mmp/clk.c
@@ -0,0 +1,192 @@
1#include <linux/io.h>
2#include <linux/clk.h>
3#include <linux/clk-provider.h>
4#include <linux/clkdev.h>
5#include <linux/of.h>
6#include <linux/of_address.h>
7
8#include "clk.h"
9
10void mmp_clk_init(struct device_node *np, struct mmp_clk_unit *unit,
11 int nr_clks)
12{
13 static struct clk **clk_table;
14
15 clk_table = kcalloc(nr_clks, sizeof(struct clk *), GFP_KERNEL);
16 if (!clk_table)
17 return;
18
19 unit->clk_table = clk_table;
20 unit->nr_clks = nr_clks;
21 unit->clk_data.clks = clk_table;
22 unit->clk_data.clk_num = nr_clks;
23 of_clk_add_provider(np, of_clk_src_onecell_get, &unit->clk_data);
24}
25
26void mmp_register_fixed_rate_clks(struct mmp_clk_unit *unit,
27 struct mmp_param_fixed_rate_clk *clks,
28 int size)
29{
30 int i;
31 struct clk *clk;
32
33 for (i = 0; i < size; i++) {
34 clk = clk_register_fixed_rate(NULL, clks[i].name,
35 clks[i].parent_name,
36 clks[i].flags,
37 clks[i].fixed_rate);
38 if (IS_ERR(clk)) {
39 pr_err("%s: failed to register clock %s\n",
40 __func__, clks[i].name);
41 continue;
42 }
43 if (clks[i].id)
44 unit->clk_table[clks[i].id] = clk;
45 }
46}
47
48void mmp_register_fixed_factor_clks(struct mmp_clk_unit *unit,
49 struct mmp_param_fixed_factor_clk *clks,
50 int size)
51{
52 struct clk *clk;
53 int i;
54
55 for (i = 0; i < size; i++) {
56 clk = clk_register_fixed_factor(NULL, clks[i].name,
57 clks[i].parent_name,
58 clks[i].flags, clks[i].mult,
59 clks[i].div);
60 if (IS_ERR(clk)) {
61 pr_err("%s: failed to register clock %s\n",
62 __func__, clks[i].name);
63 continue;
64 }
65 if (clks[i].id)
66 unit->clk_table[clks[i].id] = clk;
67 }
68}
69
70void mmp_register_general_gate_clks(struct mmp_clk_unit *unit,
71 struct mmp_param_general_gate_clk *clks,
72 void __iomem *base, int size)
73{
74 struct clk *clk;
75 int i;
76
77 for (i = 0; i < size; i++) {
78 clk = clk_register_gate(NULL, clks[i].name,
79 clks[i].parent_name,
80 clks[i].flags,
81 base + clks[i].offset,
82 clks[i].bit_idx,
83 clks[i].gate_flags,
84 clks[i].lock);
85
86 if (IS_ERR(clk)) {
87 pr_err("%s: failed to register clock %s\n",
88 __func__, clks[i].name);
89 continue;
90 }
91 if (clks[i].id)
92 unit->clk_table[clks[i].id] = clk;
93 }
94}
95
96void mmp_register_gate_clks(struct mmp_clk_unit *unit,
97 struct mmp_param_gate_clk *clks,
98 void __iomem *base, int size)
99{
100 struct clk *clk;
101 int i;
102
103 for (i = 0; i < size; i++) {
104 clk = mmp_clk_register_gate(NULL, clks[i].name,
105 clks[i].parent_name,
106 clks[i].flags,
107 base + clks[i].offset,
108 clks[i].mask,
109 clks[i].val_enable,
110 clks[i].val_disable,
111 clks[i].gate_flags,
112 clks[i].lock);
113
114 if (IS_ERR(clk)) {
115 pr_err("%s: failed to register clock %s\n",
116 __func__, clks[i].name);
117 continue;
118 }
119 if (clks[i].id)
120 unit->clk_table[clks[i].id] = clk;
121 }
122}
123
124void mmp_register_mux_clks(struct mmp_clk_unit *unit,
125 struct mmp_param_mux_clk *clks,
126 void __iomem *base, int size)
127{
128 struct clk *clk;
129 int i;
130
131 for (i = 0; i < size; i++) {
132 clk = clk_register_mux(NULL, clks[i].name,
133 clks[i].parent_name,
134 clks[i].num_parents,
135 clks[i].flags,
136 base + clks[i].offset,
137 clks[i].shift,
138 clks[i].width,
139 clks[i].mux_flags,
140 clks[i].lock);
141
142 if (IS_ERR(clk)) {
143 pr_err("%s: failed to register clock %s\n",
144 __func__, clks[i].name);
145 continue;
146 }
147 if (clks[i].id)
148 unit->clk_table[clks[i].id] = clk;
149 }
150}
151
152void mmp_register_div_clks(struct mmp_clk_unit *unit,
153 struct mmp_param_div_clk *clks,
154 void __iomem *base, int size)
155{
156 struct clk *clk;
157 int i;
158
159 for (i = 0; i < size; i++) {
160 clk = clk_register_divider(NULL, clks[i].name,
161 clks[i].parent_name,
162 clks[i].flags,
163 base + clks[i].offset,
164 clks[i].shift,
165 clks[i].width,
166 clks[i].div_flags,
167 clks[i].lock);
168
169 if (IS_ERR(clk)) {
170 pr_err("%s: failed to register clock %s\n",
171 __func__, clks[i].name);
172 continue;
173 }
174 if (clks[i].id)
175 unit->clk_table[clks[i].id] = clk;
176 }
177}
178
179void mmp_clk_add(struct mmp_clk_unit *unit, unsigned int id,
180 struct clk *clk)
181{
182 if (IS_ERR_OR_NULL(clk)) {
183 pr_err("CLK %d has invalid pointer %p\n", id, clk);
184 return;
185 }
186 if (id > unit->nr_clks) {
187 pr_err("CLK %d is invalid\n", id);
188 return;
189 }
190
191 unit->clk_table[id] = clk;
192}
diff --git a/drivers/clk/mmp/clk.h b/drivers/clk/mmp/clk.h
index 23371062072b..adf9b711b037 100644
--- a/drivers/clk/mmp/clk.h
+++ b/drivers/clk/mmp/clk.h
@@ -96,8 +96,8 @@ struct mmp_clk_mix {
96extern const struct clk_ops mmp_clk_mix_ops; 96extern const struct clk_ops mmp_clk_mix_ops;
97extern struct clk *mmp_clk_register_mix(struct device *dev, 97extern struct clk *mmp_clk_register_mix(struct device *dev,
98 const char *name, 98 const char *name,
99 u8 num_parents,
100 const char **parent_names, 99 const char **parent_names,
100 u8 num_parents,
101 unsigned long flags, 101 unsigned long flags,
102 struct mmp_clk_mix_config *config, 102 struct mmp_clk_mix_config *config,
103 spinlock_t *lock); 103 spinlock_t *lock);
@@ -132,4 +132,108 @@ extern struct clk *mmp_clk_register_apbc(const char *name,
132extern struct clk *mmp_clk_register_apmu(const char *name, 132extern struct clk *mmp_clk_register_apmu(const char *name,
133 const char *parent_name, void __iomem *base, u32 enable_mask, 133 const char *parent_name, void __iomem *base, u32 enable_mask,
134 spinlock_t *lock); 134 spinlock_t *lock);
135
136struct mmp_clk_unit {
137 unsigned int nr_clks;
138 struct clk **clk_table;
139 struct clk_onecell_data clk_data;
140};
141
142struct mmp_param_fixed_rate_clk {
143 unsigned int id;
144 char *name;
145 const char *parent_name;
146 unsigned long flags;
147 unsigned long fixed_rate;
148};
149void mmp_register_fixed_rate_clks(struct mmp_clk_unit *unit,
150 struct mmp_param_fixed_rate_clk *clks,
151 int size);
152
153struct mmp_param_fixed_factor_clk {
154 unsigned int id;
155 char *name;
156 const char *parent_name;
157 unsigned long mult;
158 unsigned long div;
159 unsigned long flags;
160};
161void mmp_register_fixed_factor_clks(struct mmp_clk_unit *unit,
162 struct mmp_param_fixed_factor_clk *clks,
163 int size);
164
165struct mmp_param_general_gate_clk {
166 unsigned int id;
167 const char *name;
168 const char *parent_name;
169 unsigned long flags;
170 unsigned long offset;
171 u8 bit_idx;
172 u8 gate_flags;
173 spinlock_t *lock;
174};
175void mmp_register_general_gate_clks(struct mmp_clk_unit *unit,
176 struct mmp_param_general_gate_clk *clks,
177 void __iomem *base, int size);
178
179struct mmp_param_gate_clk {
180 unsigned int id;
181 char *name;
182 const char *parent_name;
183 unsigned long flags;
184 unsigned long offset;
185 u32 mask;
186 u32 val_enable;
187 u32 val_disable;
188 unsigned int gate_flags;
189 spinlock_t *lock;
190};
191void mmp_register_gate_clks(struct mmp_clk_unit *unit,
192 struct mmp_param_gate_clk *clks,
193 void __iomem *base, int size);
194
195struct mmp_param_mux_clk {
196 unsigned int id;
197 char *name;
198 const char **parent_name;
199 u8 num_parents;
200 unsigned long flags;
201 unsigned long offset;
202 u8 shift;
203 u8 width;
204 u8 mux_flags;
205 spinlock_t *lock;
206};
207void mmp_register_mux_clks(struct mmp_clk_unit *unit,
208 struct mmp_param_mux_clk *clks,
209 void __iomem *base, int size);
210
211struct mmp_param_div_clk {
212 unsigned int id;
213 char *name;
214 const char *parent_name;
215 unsigned long flags;
216 unsigned long offset;
217 u8 shift;
218 u8 width;
219 u8 div_flags;
220 spinlock_t *lock;
221};
222void mmp_register_div_clks(struct mmp_clk_unit *unit,
223 struct mmp_param_div_clk *clks,
224 void __iomem *base, int size);
225
226#define DEFINE_MIX_REG_INFO(w_d, s_d, w_m, s_m, fc) \
227{ \
228 .width_div = (w_d), \
229 .shift_div = (s_d), \
230 .width_mux = (w_m), \
231 .shift_mux = (s_m), \
232 .bit_fc = (fc), \
233}
234
235void mmp_clk_init(struct device_node *np, struct mmp_clk_unit *unit,
236 int nr_clks);
237void mmp_clk_add(struct mmp_clk_unit *unit, unsigned int id,
238 struct clk *clk);
135#endif 239#endif