diff options
author | Stephen Boyd <sboyd@kernel.org> | 2018-12-11 11:32:04 -0500 |
---|---|---|
committer | Stephen Boyd <sboyd@kernel.org> | 2019-03-01 14:16:14 -0500 |
commit | 1df4046a93e086f77d244ea47c21591b4acad3e2 (patch) | |
tree | 47ee347de39b70442db6653adc1fa581b4cede59 /drivers/clk/clk.c | |
parent | d13937116f1e82bf508a6325111b322c30c85eb9 (diff) |
clk: Combine __clk_get() and __clk_create_clk()
The __clk_get() function is practically a private clk implementation
detail now. No architecture defines it, and given that new code should
be using the common clk framework there isn't a need for it to keep
existing just to serve clkdev purposes. Let's fold it into the
__clk_create_clk() function and make that a little more generic by
renaming it to clk_hw_create_clk(). This will allow the framework to
create a struct clk handle to a particular clk_hw pointer and link it up
as a consumer wherever that's needed.
Doing this also lets us get rid of the __clk_free_clk() API that had to
be kept in sync with __clk_put(). Splitting that API up into the "link
and unlink from consumer list" phase and "free the clk pointer" phase
allows us to reuse that logic in a couple places, simplifying the code.
Cc: Miquel Raynal <miquel.raynal@bootlin.com>
Cc: Jerome Brunet <jbrunet@baylibre.com>
Cc: Russell King <linux@armlinux.org.uk>
Cc: Michael Turquette <mturquette@baylibre.com>
Cc: Jeffrey Hugo <jhugo@codeaurora.org>
Cc: Chen-Yu Tsai <wens@csie.org>
Signed-off-by: Stephen Boyd <sboyd@kernel.org>
Diffstat (limited to 'drivers/clk/clk.c')
-rw-r--r-- | drivers/clk/clk.c | 140 |
1 files changed, 94 insertions, 46 deletions
diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c index d2477a5058ac..fef937ea44f4 100644 --- a/drivers/clk/clk.c +++ b/drivers/clk/clk.c | |||
@@ -3209,43 +3209,104 @@ unlock: | |||
3209 | return ret; | 3209 | return ret; |
3210 | } | 3210 | } |
3211 | 3211 | ||
3212 | struct clk *__clk_create_clk(struct clk_hw *hw, const char *dev_id, | 3212 | /** |
3213 | * clk_core_link_consumer - Add a clk consumer to the list of consumers in a clk_core | ||
3214 | * @core: clk to add consumer to | ||
3215 | * @clk: consumer to link to a clk | ||
3216 | */ | ||
3217 | static void clk_core_link_consumer(struct clk_core *core, struct clk *clk) | ||
3218 | { | ||
3219 | clk_prepare_lock(); | ||
3220 | hlist_add_head(&clk->clks_node, &core->clks); | ||
3221 | clk_prepare_unlock(); | ||
3222 | } | ||
3223 | |||
3224 | /** | ||
3225 | * clk_core_unlink_consumer - Remove a clk consumer from the list of consumers in a clk_core | ||
3226 | * @clk: consumer to unlink | ||
3227 | */ | ||
3228 | static void clk_core_unlink_consumer(struct clk *clk) | ||
3229 | { | ||
3230 | lockdep_assert_held(&prepare_lock); | ||
3231 | hlist_del(&clk->clks_node); | ||
3232 | } | ||
3233 | |||
3234 | /** | ||
3235 | * alloc_clk - Allocate a clk consumer, but leave it unlinked to the clk_core | ||
3236 | * @core: clk to allocate a consumer for | ||
3237 | * @dev_id: string describing device name | ||
3238 | * @con_id: connection ID string on device | ||
3239 | * | ||
3240 | * Returns: clk consumer left unlinked from the consumer list | ||
3241 | */ | ||
3242 | static struct clk *alloc_clk(struct clk_core *core, const char *dev_id, | ||
3213 | const char *con_id) | 3243 | const char *con_id) |
3214 | { | 3244 | { |
3215 | struct clk *clk; | 3245 | struct clk *clk; |
3216 | 3246 | ||
3217 | /* This is to allow this function to be chained to others */ | ||
3218 | if (IS_ERR_OR_NULL(hw)) | ||
3219 | return ERR_CAST(hw); | ||
3220 | |||
3221 | clk = kzalloc(sizeof(*clk), GFP_KERNEL); | 3247 | clk = kzalloc(sizeof(*clk), GFP_KERNEL); |
3222 | if (!clk) | 3248 | if (!clk) |
3223 | return ERR_PTR(-ENOMEM); | 3249 | return ERR_PTR(-ENOMEM); |
3224 | 3250 | ||
3225 | clk->core = hw->core; | 3251 | clk->core = core; |
3226 | clk->dev_id = dev_id; | 3252 | clk->dev_id = dev_id; |
3227 | clk->con_id = kstrdup_const(con_id, GFP_KERNEL); | 3253 | clk->con_id = kstrdup_const(con_id, GFP_KERNEL); |
3228 | clk->max_rate = ULONG_MAX; | 3254 | clk->max_rate = ULONG_MAX; |
3229 | 3255 | ||
3230 | clk_prepare_lock(); | ||
3231 | hlist_add_head(&clk->clks_node, &hw->core->clks); | ||
3232 | clk_prepare_unlock(); | ||
3233 | |||
3234 | return clk; | 3256 | return clk; |
3235 | } | 3257 | } |
3236 | 3258 | ||
3237 | /* keep in sync with __clk_put */ | 3259 | /** |
3238 | void __clk_free_clk(struct clk *clk) | 3260 | * free_clk - Free a clk consumer |
3261 | * @clk: clk consumer to free | ||
3262 | * | ||
3263 | * Note, this assumes the clk has been unlinked from the clk_core consumer | ||
3264 | * list. | ||
3265 | */ | ||
3266 | static void free_clk(struct clk *clk) | ||
3239 | { | 3267 | { |
3240 | clk_prepare_lock(); | ||
3241 | hlist_del(&clk->clks_node); | ||
3242 | clk_prepare_unlock(); | ||
3243 | |||
3244 | kfree_const(clk->con_id); | 3268 | kfree_const(clk->con_id); |
3245 | kfree(clk); | 3269 | kfree(clk); |
3246 | } | 3270 | } |
3247 | 3271 | ||
3248 | /** | 3272 | /** |
3273 | * clk_hw_create_clk: Allocate and link a clk consumer to a clk_core given | ||
3274 | * a clk_hw | ||
3275 | * @hw: clk_hw associated with the clk being consumed | ||
3276 | * @dev_id: string describing device name | ||
3277 | * @con_id: connection ID string on device | ||
3278 | * | ||
3279 | * This is the main function used to create a clk pointer for use by clk | ||
3280 | * consumers. It connects a consumer to the clk_core and clk_hw structures | ||
3281 | * used by the framework and clk provider respectively. | ||
3282 | */ | ||
3283 | struct clk *clk_hw_create_clk(struct clk_hw *hw, | ||
3284 | const char *dev_id, const char *con_id) | ||
3285 | { | ||
3286 | struct clk *clk; | ||
3287 | struct clk_core *core; | ||
3288 | |||
3289 | /* This is to allow this function to be chained to others */ | ||
3290 | if (IS_ERR_OR_NULL(hw)) | ||
3291 | return ERR_CAST(hw); | ||
3292 | |||
3293 | core = hw->core; | ||
3294 | clk = alloc_clk(core, dev_id, con_id); | ||
3295 | if (IS_ERR(clk)) | ||
3296 | return clk; | ||
3297 | |||
3298 | if (!try_module_get(core->owner)) { | ||
3299 | free_clk(clk); | ||
3300 | return ERR_PTR(-ENOENT); | ||
3301 | } | ||
3302 | |||
3303 | kref_get(&core->ref); | ||
3304 | clk_core_link_consumer(core, clk); | ||
3305 | |||
3306 | return clk; | ||
3307 | } | ||
3308 | |||
3309 | /** | ||
3249 | * clk_register - allocate a new clock, register it and return an opaque cookie | 3310 | * clk_register - allocate a new clock, register it and return an opaque cookie |
3250 | * @dev: device that is registering this clock | 3311 | * @dev: device that is registering this clock |
3251 | * @hw: link to hardware-specific clock data | 3312 | * @hw: link to hardware-specific clock data |
@@ -3320,17 +3381,27 @@ struct clk *clk_register(struct device *dev, struct clk_hw *hw) | |||
3320 | 3381 | ||
3321 | INIT_HLIST_HEAD(&core->clks); | 3382 | INIT_HLIST_HEAD(&core->clks); |
3322 | 3383 | ||
3323 | hw->clk = __clk_create_clk(hw, NULL, NULL); | 3384 | /* |
3385 | * Don't call clk_hw_create_clk() here because that would pin the | ||
3386 | * provider module to itself and prevent it from ever being removed. | ||
3387 | */ | ||
3388 | hw->clk = alloc_clk(core, NULL, NULL); | ||
3324 | if (IS_ERR(hw->clk)) { | 3389 | if (IS_ERR(hw->clk)) { |
3325 | ret = PTR_ERR(hw->clk); | 3390 | ret = PTR_ERR(hw->clk); |
3326 | goto fail_parents; | 3391 | goto fail_parents; |
3327 | } | 3392 | } |
3328 | 3393 | ||
3394 | clk_core_link_consumer(hw->core, hw->clk); | ||
3395 | |||
3329 | ret = __clk_core_init(core); | 3396 | ret = __clk_core_init(core); |
3330 | if (!ret) | 3397 | if (!ret) |
3331 | return hw->clk; | 3398 | return hw->clk; |
3332 | 3399 | ||
3333 | __clk_free_clk(hw->clk); | 3400 | clk_prepare_lock(); |
3401 | clk_core_unlink_consumer(hw->clk); | ||
3402 | clk_prepare_unlock(); | ||
3403 | |||
3404 | free_clk(hw->clk); | ||
3334 | hw->clk = NULL; | 3405 | hw->clk = NULL; |
3335 | 3406 | ||
3336 | fail_parents: | 3407 | fail_parents: |
@@ -3601,20 +3672,7 @@ EXPORT_SYMBOL_GPL(devm_clk_hw_unregister); | |||
3601 | /* | 3672 | /* |
3602 | * clkdev helpers | 3673 | * clkdev helpers |
3603 | */ | 3674 | */ |
3604 | int __clk_get(struct clk *clk) | ||
3605 | { | ||
3606 | struct clk_core *core = !clk ? NULL : clk->core; | ||
3607 | |||
3608 | if (core) { | ||
3609 | if (!try_module_get(core->owner)) | ||
3610 | return 0; | ||
3611 | |||
3612 | kref_get(&core->ref); | ||
3613 | } | ||
3614 | return 1; | ||
3615 | } | ||
3616 | 3675 | ||
3617 | /* keep in sync with __clk_free_clk */ | ||
3618 | void __clk_put(struct clk *clk) | 3676 | void __clk_put(struct clk *clk) |
3619 | { | 3677 | { |
3620 | struct module *owner; | 3678 | struct module *owner; |
@@ -3648,8 +3706,7 @@ void __clk_put(struct clk *clk) | |||
3648 | 3706 | ||
3649 | module_put(owner); | 3707 | module_put(owner); |
3650 | 3708 | ||
3651 | kfree_const(clk->con_id); | 3709 | free_clk(clk); |
3652 | kfree(clk); | ||
3653 | } | 3710 | } |
3654 | 3711 | ||
3655 | /*** clk rate change notifiers ***/ | 3712 | /*** clk rate change notifiers ***/ |
@@ -4025,8 +4082,7 @@ struct clk *__of_clk_get_from_provider(struct of_phandle_args *clkspec, | |||
4025 | const char *dev_id, const char *con_id) | 4082 | const char *dev_id, const char *con_id) |
4026 | { | 4083 | { |
4027 | struct of_clk_provider *provider; | 4084 | struct of_clk_provider *provider; |
4028 | struct clk *clk = ERR_PTR(-EPROBE_DEFER); | 4085 | struct clk_hw *hw = ERR_PTR(-EPROBE_DEFER); |
4029 | struct clk_hw *hw; | ||
4030 | 4086 | ||
4031 | if (!clkspec) | 4087 | if (!clkspec) |
4032 | return ERR_PTR(-EINVAL); | 4088 | return ERR_PTR(-EINVAL); |
@@ -4036,21 +4092,13 @@ struct clk *__of_clk_get_from_provider(struct of_phandle_args *clkspec, | |||
4036 | list_for_each_entry(provider, &of_clk_providers, link) { | 4092 | list_for_each_entry(provider, &of_clk_providers, link) { |
4037 | if (provider->node == clkspec->np) { | 4093 | if (provider->node == clkspec->np) { |
4038 | hw = __of_clk_get_hw_from_provider(provider, clkspec); | 4094 | hw = __of_clk_get_hw_from_provider(provider, clkspec); |
4039 | clk = __clk_create_clk(hw, dev_id, con_id); | 4095 | if (!IS_ERR(hw)) |
4040 | } | 4096 | break; |
4041 | |||
4042 | if (!IS_ERR(clk)) { | ||
4043 | if (!__clk_get(clk)) { | ||
4044 | __clk_free_clk(clk); | ||
4045 | clk = ERR_PTR(-ENOENT); | ||
4046 | } | ||
4047 | |||
4048 | break; | ||
4049 | } | 4097 | } |
4050 | } | 4098 | } |
4051 | mutex_unlock(&of_clk_mutex); | 4099 | mutex_unlock(&of_clk_mutex); |
4052 | 4100 | ||
4053 | return clk; | 4101 | return clk_hw_create_clk(hw, dev_id, con_id); |
4054 | } | 4102 | } |
4055 | 4103 | ||
4056 | /** | 4104 | /** |