diff options
author | Stephen Boyd <sboyd@codeaurora.org> | 2016-02-02 20:09:26 -0500 |
---|---|---|
committer | Stephen Boyd <sboyd@codeaurora.org> | 2016-02-07 02:38:20 -0500 |
commit | 14b04f28a0a1a5903221fc55c61d231b76abd440 (patch) | |
tree | 58cf95d278d0531c9fbf90d2beb5c1f8ce5fcbb1 | |
parent | 4106a3d9ebb9839a8e93b0116c0f94dc4f10e4b2 (diff) |
clk: gpio: Make into a platform driver
clk_get() for DT based clks already returns EPROBE_DEFER when the
OF clk provider is not present. So having all this code in the
clk provider to return EPROBE_DEFER when the gpio isn't ready yet
can be replaced with a platform driver that doesn't add the clk
provider until the gpio can be requested. Get rid of the
OF_CLK_DECLARE and convert this to a platform driver instead.
Tested-by: Jyri Sarha <jsarha@ti.com>
Cc: Sergej Sawazki <ce3a@gmx.de>
Cc: Russell King <rmk+kernel@arm.linux.org.uk>
Cc: Fabio Estevam <fabio.estevam@freescale.com>
Cc: Jon Nettleton <jon@solid-run.com>
Cc: Shawn Guo <shawn.guo@linaro.org>
Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
-rw-r--r-- | drivers/clk/clk-gpio.c | 165 |
1 files changed, 52 insertions, 113 deletions
diff --git a/drivers/clk/clk-gpio.c b/drivers/clk/clk-gpio.c index cbbea2985cc9..fb32a7366ef6 100644 --- a/drivers/clk/clk-gpio.c +++ b/drivers/clk/clk-gpio.c | |||
@@ -20,6 +20,8 @@ | |||
20 | #include <linux/of_gpio.h> | 20 | #include <linux/of_gpio.h> |
21 | #include <linux/err.h> | 21 | #include <linux/err.h> |
22 | #include <linux/device.h> | 22 | #include <linux/device.h> |
23 | #include <linux/platform_device.h> | ||
24 | #include <linux/of_device.h> | ||
23 | 25 | ||
24 | /** | 26 | /** |
25 | * DOC: basic gpio gated clock which can be enabled and disabled | 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 | EXPORT_SYMBOL_GPL(clk_register_gpio_mux); | 202 | EXPORT_SYMBOL_GPL(clk_register_gpio_mux); |
201 | 203 | ||
202 | #ifdef CONFIG_OF | 204 | static int gpio_clk_driver_probe(struct platform_device *pdev) |
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) | ||
222 | { | 205 | { |
223 | struct clk_gpio_delayed_register_data *data = _data; | 206 | struct device_node *node = pdev->dev.of_node; |
224 | struct clk *clk; | 207 | const char **parent_names, *gpio_name; |
225 | int gpio; | 208 | int num_parents, gpio; |
226 | enum of_gpio_flags of_flags; | 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) { | 223 | of_clk_parent_fill(node, parent_names, num_parents); |
231 | mutex_unlock(&data->lock); | 224 | } else { |
232 | return data->clk; | 225 | parent_names = NULL; |
233 | } | 226 | } |
234 | 227 | ||
235 | gpio = of_get_named_gpio_flags(data->node, data->gpio_name, 0, | 228 | is_mux = of_device_is_compatible(node, "gpio-mux-clock"); |
236 | &of_flags); | 229 | |
230 | gpio_name = is_mux ? "select-gpios" : "enable-gpios"; | ||
231 | gpio = of_get_named_gpio_flags(node, gpio_name, 0, &of_flags); | ||
237 | if (gpio < 0) { | 232 | if (gpio < 0) { |
238 | mutex_unlock(&data->lock); | ||
239 | if (gpio == -EPROBE_DEFER) | 233 | if (gpio == -EPROBE_DEFER) |
240 | pr_debug("%s: %s: GPIOs not yet available, retry later\n", | 234 | pr_debug("%s: %s: GPIOs not yet available, retry later\n", |
241 | data->node->name, __func__); | 235 | node->name, __func__); |
242 | else | 236 | else |
243 | pr_err("%s: %s: Can't get '%s' DT property\n", | 237 | pr_err("%s: %s: Can't get '%s' DT property\n", |
244 | data->node->name, __func__, | 238 | node->name, __func__, |
245 | data->gpio_name); | 239 | gpio_name); |
246 | return ERR_PTR(gpio); | 240 | return gpio; |
247 | } | 241 | } |
248 | 242 | ||
249 | clk = data->clk_register_get(data->node->name, data->parent_names, | 243 | active_low = of_flags & OF_GPIO_ACTIVE_LOW; |
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; | ||
295 | 244 | ||
296 | if (num_parents) { | 245 | if (is_mux) |
297 | parent_names = kcalloc(num_parents, sizeof(char *), GFP_KERNEL); | 246 | clk = clk_register_gpio_mux(&pdev->dev, node->name, |
298 | if (!parent_names) { | 247 | parent_names, num_parents, gpio, active_low, 0); |
299 | kfree(data); | 248 | else |
300 | return; | 249 | clk = clk_register_gpio_gate(&pdev->dev, node->name, |
301 | } | 250 | parent_names ? parent_names[0] : NULL, gpio, |
302 | 251 | active_low, 0); | |
303 | for (i = 0; i < num_parents; i++) | 252 | if (IS_ERR(clk)) |
304 | parent_names[i] = of_clk_get_parent_name(node, i); | 253 | return PTR_ERR(clk); |
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); | ||
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) | 258 | static const struct of_device_id gpio_clk_match_table[] = { |
320 | { | 259 | { .compatible = "gpio-mux-clock" }, |
321 | of_gpio_clk_setup(node, "enable-gpios", | 260 | { .compatible = "gpio-gate-clock" }, |
322 | of_clk_gpio_gate_delayed_register_get); | 261 | { } |
323 | } | 262 | }; |
324 | CLK_OF_DECLARE(gpio_gate_clk, "gpio-gate-clock", of_gpio_gate_clk_setup); | ||
325 | 263 | ||
326 | void __init of_gpio_mux_clk_setup(struct device_node *node) | 264 | static struct platform_driver gpio_clk_driver = { |
327 | { | 265 | .probe = gpio_clk_driver_probe, |
328 | of_gpio_clk_setup(node, "select-gpios", | 266 | .driver = { |
329 | of_clk_gpio_mux_delayed_register_get); | 267 | .name = "gpio-clk", |
330 | } | 268 | .of_match_table = gpio_clk_match_table, |
331 | CLK_OF_DECLARE(gpio_mux_clk, "gpio-mux-clock", of_gpio_mux_clk_setup); | 269 | }, |
332 | #endif | 270 | }; |
271 | builtin_platform_driver(gpio_clk_driver); | ||