12
12
#include <linux/slab.h>
13
13
#include <linux/err.h>
14
14
#include <linux/of.h>
15
+ #include <linux/platform_device.h>
15
16
16
17
/*
17
18
* DOC: basic fixed multiplier and divider clock that cannot gate
@@ -147,27 +148,25 @@ static const struct of_device_id set_rate_parent_matches[] = {
147
148
{ /* Sentinel */ },
148
149
};
149
150
150
- /**
151
- * of_fixed_factor_clk_setup() - Setup function for simple fixed factor clock
152
- */
153
- void __init of_fixed_factor_clk_setup (struct device_node * node )
151
+ static struct clk * _of_fixed_factor_clk_setup (struct device_node * node )
154
152
{
155
153
struct clk * clk ;
156
154
const char * clk_name = node -> name ;
157
155
const char * parent_name ;
158
156
unsigned long flags = 0 ;
159
157
u32 div , mult ;
158
+ int ret ;
160
159
161
160
if (of_property_read_u32 (node , "clock-div" , & div )) {
162
161
pr_err ("%s Fixed factor clock <%s> must have a clock-div property\n" ,
163
162
__func__ , node -> name );
164
- return ;
163
+ return ERR_PTR ( - EIO ) ;
165
164
}
166
165
167
166
if (of_property_read_u32 (node , "clock-mult" , & mult )) {
168
167
pr_err ("%s Fixed factor clock <%s> must have a clock-mult property\n" ,
169
168
__func__ , node -> name );
170
- return ;
169
+ return ERR_PTR ( - EIO ) ;
171
170
}
172
171
173
172
of_property_read_string (node , "clock-output-names" , & clk_name );
@@ -178,10 +177,68 @@ void __init of_fixed_factor_clk_setup(struct device_node *node)
178
177
179
178
clk = clk_register_fixed_factor (NULL , clk_name , parent_name , flags ,
180
179
mult , div );
181
- if (!IS_ERR (clk ))
182
- of_clk_add_provider (node , of_clk_src_simple_get , clk );
180
+ if (IS_ERR (clk ))
181
+ return clk ;
182
+
183
+ ret = of_clk_add_provider (node , of_clk_src_simple_get , clk );
184
+ if (ret ) {
185
+ clk_unregister (clk );
186
+ return ERR_PTR (ret );
187
+ }
188
+
189
+ return clk ;
190
+ }
191
+
192
+ /**
193
+ * of_fixed_factor_clk_setup() - Setup function for simple fixed factor clock
194
+ */
195
+ void __init of_fixed_factor_clk_setup (struct device_node * node )
196
+ {
197
+ _of_fixed_factor_clk_setup (node );
183
198
}
184
199
EXPORT_SYMBOL_GPL (of_fixed_factor_clk_setup );
185
200
CLK_OF_DECLARE (fixed_factor_clk , "fixed-factor-clock" ,
186
201
of_fixed_factor_clk_setup );
202
+
203
+ static int of_fixed_factor_clk_remove (struct platform_device * pdev )
204
+ {
205
+ struct clk * clk = platform_get_drvdata (pdev );
206
+
207
+ clk_unregister_fixed_factor (clk );
208
+
209
+ return 0 ;
210
+ }
211
+
212
+ static int of_fixed_factor_clk_probe (struct platform_device * pdev )
213
+ {
214
+ struct clk * clk ;
215
+
216
+ /*
217
+ * This function is not executed when of_fixed_factor_clk_setup
218
+ * succeeded.
219
+ */
220
+ clk = _of_fixed_factor_clk_setup (pdev -> dev .of_node );
221
+ if (IS_ERR (clk ))
222
+ return PTR_ERR (clk );
223
+
224
+ platform_set_drvdata (pdev , clk );
225
+
226
+ return 0 ;
227
+ }
228
+
229
+ static const struct of_device_id of_fixed_factor_clk_ids [] = {
230
+ { .compatible = "fixed-factor-clock" },
231
+ { }
232
+ };
233
+ MODULE_DEVICE_TABLE (of , of_fixed_factor_clk_ids );
234
+
235
+ static struct platform_driver of_fixed_factor_clk_driver = {
236
+ .driver = {
237
+ .name = "of_fixed_factor_clk" ,
238
+ .of_match_table = of_fixed_factor_clk_ids ,
239
+ },
240
+ .probe = of_fixed_factor_clk_probe ,
241
+ .remove = of_fixed_factor_clk_remove ,
242
+ };
243
+ builtin_platform_driver (of_fixed_factor_clk_driver );
187
244
#endif
0 commit comments