|
20 | 20 | #include <linux/of_gpio.h>
|
21 | 21 | #include <linux/err.h>
|
22 | 22 | #include <linux/device.h>
|
| 23 | +#include <linux/platform_device.h> |
| 24 | +#include <linux/of_device.h> |
23 | 25 |
|
24 | 26 | /**
|
25 | 27 | * DOC: basic gpio gated clock which can be enabled and disabled
|
@@ -199,134 +201,71 @@ struct clk *clk_register_gpio_mux(struct device *dev, const char *name,
|
199 | 201 | }
|
200 | 202 | EXPORT_SYMBOL_GPL(clk_register_gpio_mux);
|
201 | 203 |
|
202 |
| -#ifdef CONFIG_OF |
203 |
| -/** |
204 |
| - * clk_register_get() has to be delayed, because -EPROBE_DEFER |
205 |
| - * can not be handled properly at of_clk_init() call time. |
206 |
| - */ |
207 |
| - |
208 |
| -struct clk_gpio_delayed_register_data { |
209 |
| - const char *gpio_name; |
210 |
| - int num_parents; |
211 |
| - const char **parent_names; |
212 |
| - struct device_node *node; |
213 |
| - struct mutex lock; |
214 |
| - struct clk *clk; |
215 |
| - struct clk *(*clk_register_get)(const char *name, |
216 |
| - const char * const *parent_names, u8 num_parents, |
217 |
| - unsigned gpio, bool active_low); |
218 |
| -}; |
219 |
| - |
220 |
| -static struct clk *of_clk_gpio_delayed_register_get( |
221 |
| - struct of_phandle_args *clkspec, void *_data) |
| 204 | +static int gpio_clk_driver_probe(struct platform_device *pdev) |
222 | 205 | {
|
223 |
| - struct clk_gpio_delayed_register_data *data = _data; |
224 |
| - struct clk *clk; |
225 |
| - int gpio; |
| 206 | + struct device_node *node = pdev->dev.of_node; |
| 207 | + const char **parent_names, *gpio_name; |
| 208 | + int num_parents, gpio; |
226 | 209 | enum of_gpio_flags of_flags;
|
| 210 | + struct clk *clk; |
| 211 | + bool active_low, is_mux; |
| 212 | + |
| 213 | + num_parents = of_clk_get_parent_count(node); |
| 214 | + if (num_parents < 0) |
| 215 | + return -EINVAL; |
227 | 216 |
|
228 |
| - mutex_lock(&data->lock); |
| 217 | + if (num_parents) { |
| 218 | + parent_names = devm_kcalloc(&pdev->dev, num_parents, |
| 219 | + sizeof(char *), GFP_KERNEL); |
| 220 | + if (!parent_names) |
| 221 | + return -ENOMEM; |
229 | 222 |
|
230 |
| - if (data->clk) { |
231 |
| - mutex_unlock(&data->lock); |
232 |
| - return data->clk; |
| 223 | + of_clk_parent_fill(node, parent_names, num_parents); |
| 224 | + } else { |
| 225 | + parent_names = NULL; |
233 | 226 | }
|
234 | 227 |
|
235 |
| - gpio = of_get_named_gpio_flags(data->node, data->gpio_name, 0, |
236 |
| - &of_flags); |
| 228 | + is_mux = of_device_is_compatible(node, "gpio-mux-clock"); |
| 229 | + |
| 230 | + gpio_name = is_mux ? "select-gpios" : "enable-gpios"; |
| 231 | + gpio = of_get_named_gpio_flags(node, gpio_name, 0, &of_flags); |
237 | 232 | if (gpio < 0) {
|
238 |
| - mutex_unlock(&data->lock); |
239 | 233 | if (gpio == -EPROBE_DEFER)
|
240 | 234 | pr_debug("%s: %s: GPIOs not yet available, retry later\n",
|
241 |
| - data->node->name, __func__); |
| 235 | + node->name, __func__); |
242 | 236 | else
|
243 | 237 | pr_err("%s: %s: Can't get '%s' DT property\n",
|
244 |
| - data->node->name, __func__, |
245 |
| - data->gpio_name); |
246 |
| - return ERR_PTR(gpio); |
| 238 | + node->name, __func__, |
| 239 | + gpio_name); |
| 240 | + return gpio; |
247 | 241 | }
|
248 | 242 |
|
249 |
| - clk = data->clk_register_get(data->node->name, data->parent_names, |
250 |
| - data->num_parents, gpio, of_flags & OF_GPIO_ACTIVE_LOW); |
251 |
| - if (IS_ERR(clk)) |
252 |
| - goto out; |
253 |
| - |
254 |
| - data->clk = clk; |
255 |
| -out: |
256 |
| - mutex_unlock(&data->lock); |
257 |
| - |
258 |
| - return clk; |
259 |
| -} |
260 |
| - |
261 |
| -static struct clk *of_clk_gpio_gate_delayed_register_get(const char *name, |
262 |
| - const char * const *parent_names, u8 num_parents, |
263 |
| - unsigned gpio, bool active_low) |
264 |
| -{ |
265 |
| - return clk_register_gpio_gate(NULL, name, parent_names ? |
266 |
| - parent_names[0] : NULL, gpio, active_low, 0); |
267 |
| -} |
268 |
| - |
269 |
| -static struct clk *of_clk_gpio_mux_delayed_register_get(const char *name, |
270 |
| - const char * const *parent_names, u8 num_parents, unsigned gpio, |
271 |
| - bool active_low) |
272 |
| -{ |
273 |
| - return clk_register_gpio_mux(NULL, name, parent_names, num_parents, |
274 |
| - gpio, active_low, 0); |
275 |
| -} |
276 |
| - |
277 |
| -static void __init of_gpio_clk_setup(struct device_node *node, |
278 |
| - const char *gpio_name, |
279 |
| - struct clk *(*clk_register_get)(const char *name, |
280 |
| - const char * const *parent_names, |
281 |
| - u8 num_parents, |
282 |
| - unsigned gpio, bool active_low)) |
283 |
| -{ |
284 |
| - struct clk_gpio_delayed_register_data *data; |
285 |
| - const char **parent_names; |
286 |
| - int i, num_parents; |
287 |
| - |
288 |
| - num_parents = of_clk_get_parent_count(node); |
289 |
| - if (num_parents < 0) |
290 |
| - return; |
291 |
| - |
292 |
| - data = kzalloc(sizeof(*data), GFP_KERNEL); |
293 |
| - if (!data) |
294 |
| - return; |
| 243 | + active_low = of_flags & OF_GPIO_ACTIVE_LOW; |
295 | 244 |
|
296 |
| - if (num_parents) { |
297 |
| - parent_names = kcalloc(num_parents, sizeof(char *), GFP_KERNEL); |
298 |
| - if (!parent_names) { |
299 |
| - kfree(data); |
300 |
| - return; |
301 |
| - } |
302 |
| - |
303 |
| - for (i = 0; i < num_parents; i++) |
304 |
| - parent_names[i] = of_clk_get_parent_name(node, i); |
305 |
| - } else { |
306 |
| - parent_names = NULL; |
307 |
| - } |
308 |
| - |
309 |
| - data->num_parents = num_parents; |
310 |
| - data->parent_names = parent_names; |
311 |
| - data->node = node; |
312 |
| - data->gpio_name = gpio_name; |
313 |
| - data->clk_register_get = clk_register_get; |
314 |
| - mutex_init(&data->lock); |
| 245 | + if (is_mux) |
| 246 | + clk = clk_register_gpio_mux(&pdev->dev, node->name, |
| 247 | + parent_names, num_parents, gpio, active_low, 0); |
| 248 | + else |
| 249 | + clk = clk_register_gpio_gate(&pdev->dev, node->name, |
| 250 | + parent_names ? parent_names[0] : NULL, gpio, |
| 251 | + active_low, 0); |
| 252 | + if (IS_ERR(clk)) |
| 253 | + return PTR_ERR(clk); |
315 | 254 |
|
316 |
| - of_clk_add_provider(node, of_clk_gpio_delayed_register_get, data); |
| 255 | + return of_clk_add_provider(node, of_clk_src_simple_get, clk); |
317 | 256 | }
|
318 | 257 |
|
319 |
| -static void __init of_gpio_gate_clk_setup(struct device_node *node) |
320 |
| -{ |
321 |
| - of_gpio_clk_setup(node, "enable-gpios", |
322 |
| - of_clk_gpio_gate_delayed_register_get); |
323 |
| -} |
324 |
| -CLK_OF_DECLARE(gpio_gate_clk, "gpio-gate-clock", of_gpio_gate_clk_setup); |
| 258 | +static const struct of_device_id gpio_clk_match_table[] = { |
| 259 | + { .compatible = "gpio-mux-clock" }, |
| 260 | + { .compatible = "gpio-gate-clock" }, |
| 261 | + { } |
| 262 | +}; |
325 | 263 |
|
326 |
| -void __init of_gpio_mux_clk_setup(struct device_node *node) |
327 |
| -{ |
328 |
| - of_gpio_clk_setup(node, "select-gpios", |
329 |
| - of_clk_gpio_mux_delayed_register_get); |
330 |
| -} |
331 |
| -CLK_OF_DECLARE(gpio_mux_clk, "gpio-mux-clock", of_gpio_mux_clk_setup); |
332 |
| -#endif |
| 264 | +static struct platform_driver gpio_clk_driver = { |
| 265 | + .probe = gpio_clk_driver_probe, |
| 266 | + .driver = { |
| 267 | + .name = "gpio-clk", |
| 268 | + .of_match_table = gpio_clk_match_table, |
| 269 | + }, |
| 270 | +}; |
| 271 | +builtin_platform_driver(gpio_clk_driver); |
0 commit comments