1

clk: provide devm_clk_get_optional_enabled_with_rate()

There are clock users in the kernel that can't use
devm_clk_get_optional_enabled() as they need to set rate after getting
the clock and before enabling it. Provide a managed helper that wraps
these operations in the correct order.

Signed-off-by: Bartosz Golaszewski <bartosz.golaszewski@linaro.org>
Link: https://lore.kernel.org/r/20240805-clk-new-helper-v2-1-e5fdd1e1d729@linaro.org
Signed-off-by: Stephen Boyd <sboyd@kernel.org>
This commit is contained in:
Bartosz Golaszewski 2024-08-05 10:57:31 +02:00 committed by Stephen Boyd
parent 706ae64464
commit 9934a1bd45
2 changed files with 61 additions and 0 deletions

View File

@ -99,6 +99,34 @@ struct clk *devm_clk_get_optional_enabled(struct device *dev, const char *id)
} }
EXPORT_SYMBOL_GPL(devm_clk_get_optional_enabled); EXPORT_SYMBOL_GPL(devm_clk_get_optional_enabled);
struct clk *devm_clk_get_optional_enabled_with_rate(struct device *dev,
const char *id,
unsigned long rate)
{
struct clk *clk;
int ret;
clk = __devm_clk_get(dev, id, clk_get_optional, NULL,
clk_disable_unprepare);
if (IS_ERR(clk))
return ERR_CAST(clk);
ret = clk_set_rate(clk, rate);
if (ret)
goto out_put_clk;
ret = clk_prepare_enable(clk);
if (ret)
goto out_put_clk;
return clk;
out_put_clk:
devm_clk_put(dev, clk);
return ERR_PTR(ret);
}
EXPORT_SYMBOL_GPL(devm_clk_get_optional_enabled_with_rate);
struct clk_bulk_devres { struct clk_bulk_devres {
struct clk_bulk_data *clks; struct clk_bulk_data *clks;
int num_clks; int num_clks;

View File

@ -640,6 +640,32 @@ struct clk *devm_clk_get_optional_prepared(struct device *dev, const char *id);
*/ */
struct clk *devm_clk_get_optional_enabled(struct device *dev, const char *id); struct clk *devm_clk_get_optional_enabled(struct device *dev, const char *id);
/**
* devm_clk_get_optional_enabled_with_rate - devm_clk_get_optional() +
* clk_set_rate() +
* clk_prepare_enable()
* @dev: device for clock "consumer"
* @id: clock consumer ID
* @rate: new clock rate
*
* Context: May sleep.
*
* Return: a struct clk corresponding to the clock producer, or
* valid IS_ERR() condition containing errno. The implementation
* uses @dev and @id to determine the clock consumer, and thereby
* the clock producer. If no such clk is found, it returns NULL
* which serves as a dummy clk. That's the only difference compared
* to devm_clk_get_enabled().
*
* The returned clk (if valid) is prepared and enabled and rate was set.
*
* The clock will automatically be disabled, unprepared and freed
* when the device is unbound from the bus.
*/
struct clk *devm_clk_get_optional_enabled_with_rate(struct device *dev,
const char *id,
unsigned long rate);
/** /**
* devm_get_clk_from_child - lookup and obtain a managed reference to a * devm_get_clk_from_child - lookup and obtain a managed reference to a
* clock producer from child node. * clock producer from child node.
@ -982,6 +1008,13 @@ static inline struct clk *devm_clk_get_optional_enabled(struct device *dev,
return NULL; return NULL;
} }
static inline struct clk *
devm_clk_get_optional_enabled_with_rate(struct device *dev, const char *id,
unsigned long rate)
{
return NULL;
}
static inline int __must_check devm_clk_bulk_get(struct device *dev, int num_clks, static inline int __must_check devm_clk_bulk_get(struct device *dev, int num_clks,
struct clk_bulk_data *clks) struct clk_bulk_data *clks)
{ {