unsigned int protect_count;
unsigned long min_rate;
unsigned long max_rate;
- unsigned long default_request_rate;
unsigned long accuracy;
int phase;
struct clk_duty duty;
struct hlist_head children;
struct hlist_node child_node;
struct hlist_head clks;
- struct list_head pending_requests;
unsigned int notifier_count;
#ifdef CONFIG_DEBUG_FS
struct dentry *dentry;
struct hlist_node clks_node;
};
-struct clk_request {
- struct list_head list;
- struct clk *clk;
- unsigned long rate;
-};
-
/*** runtime pm ***/
static int clk_pm_runtime_get(struct clk_core *core)
{
{
int ret;
struct clk_rate_request req;
- struct clk_request *clk_req;
clk_core_init_rate_req(hw->core, &req, rate);
- list_for_each_entry(clk_req, &hw->core->pending_requests, list)
- req.min_rate = max(clk_req->rate, req.min_rate);
-
ret = clk_core_round_rate_nolock(hw->core, &req);
if (ret)
return 0;
long clk_round_rate(struct clk *clk, unsigned long rate)
{
struct clk_rate_request req;
- struct clk_request *clk_req;
int ret;
if (!clk)
clk_core_init_rate_req(clk->core, &req, rate);
- list_for_each_entry(clk_req, &clk->core->pending_requests, list)
- req.min_rate = max(clk_req->rate, req.min_rate);
-
ret = clk_core_round_rate_nolock(clk->core, &req);
if (clk->exclusive_count)
unsigned long new_rate;
unsigned long min_rate;
unsigned long max_rate;
- struct clk_request *req;
int p_index = 0;
long ret;
clk_core_get_boundaries(core, &min_rate, &max_rate);
- list_for_each_entry(req, &core->pending_requests, list)
- min_rate = max(req->rate, min_rate);
-
/* find the closest rate and parent clk/rate */
if (clk_core_can_round(core)) {
struct clk_rate_request req;
{
int ret, cnt;
struct clk_rate_request req;
- struct clk_request *clk_req;
lockdep_assert_held(&prepare_lock);
clk_core_init_rate_req(core, &req, req_rate);
- list_for_each_entry(clk_req, &core->pending_requests, list)
- req.min_rate = max(clk_req->rate, req.min_rate);
-
ret = clk_core_round_rate_nolock(core, &req);
/* restore the protection */
ret = clk_core_set_rate_nolock(clk->core, rate);
- if (!list_empty(&clk->core->pending_requests))
- clk->core->default_request_rate = rate;
-
if (clk->exclusive_count)
clk_core_rate_protect(clk->core);
}
EXPORT_SYMBOL_GPL(clk_set_max_rate);
-/**
- * clk_request_start - Request a rate to be enforced temporarily
- * @clk: the clk to act on
- * @rate: the new rate asked for
- *
- * This function will create a request to temporarily increase the rate
- * of the clock to a given rate to a certain minimum.
- *
- * This is meant as a best effort mechanism and while the rate of the
- * clock will be guaranteed to be equal or higher than the requested
- * rate, there's none on what the actual rate will be due to other
- * factors (other requests previously set, clock boundaries, etc.).
- *
- * Once the request is marked as done through clk_request_done(), the
- * rate will be reverted back to what the rate was before the request.
- *
- * The reported boundaries of the clock will also be adjusted so that
- * clk_round_rate() take those requests into account. A call to
- * clk_set_rate() during a request will affect the rate the clock will
- * return to after the requests on that clock are done.
- *
- * Returns 0 on success, an ERR_PTR otherwise.
- */
-struct clk_request *clk_request_start(struct clk *clk, unsigned long rate)
-{
- struct clk_request *req;
- int ret;
-
- if (!clk)
- return ERR_PTR(-EINVAL);
-
- req = kzalloc(sizeof(*req), GFP_KERNEL);
- if (!req)
- return ERR_PTR(-ENOMEM);
-
- clk_prepare_lock();
-
- req->clk = clk;
- req->rate = rate;
-
- if (list_empty(&clk->core->pending_requests))
- clk->core->default_request_rate = clk_core_get_rate_recalc(clk->core);
-
- ret = clk_core_set_rate_nolock(clk->core, rate);
- if (ret) {
- clk_prepare_unlock();
- kfree(req);
- return ERR_PTR(ret);
- }
-
- list_add_tail(&req->list, &clk->core->pending_requests);
- clk_prepare_unlock();
-
- return req;
-}
-EXPORT_SYMBOL_GPL(clk_request_start);
-
-/**
- * clk_request_done - Mark a clk_request as done
- * @req: the request to mark done
- *
- * This function will remove the rate request from the clock and adjust
- * the clock rate back to either to what it was before the request
- * started, or if there's any other request on that clock to a proper
- * rate for them.
- */
-void clk_request_done(struct clk_request *req)
-{
- struct clk_core *core = req->clk->core;
-
- clk_prepare_lock();
-
- list_del(&req->list);
-
- if (list_empty(&core->pending_requests)) {
- clk_core_set_rate_nolock(core, core->default_request_rate);
- core->default_request_rate = 0;
- } else {
- struct clk_request *cur_req;
- unsigned long new_rate = 0;
-
- list_for_each_entry(cur_req, &core->pending_requests, list)
- new_rate = max(new_rate, cur_req->rate);
-
- clk_core_set_rate_nolock(core, new_rate);
- }
-
- clk_prepare_unlock();
-
- kfree(req);
-}
-EXPORT_SYMBOL_GPL(clk_request_done);
-
/**
* clk_get_parent - return the parent of a clk
* @clk: the clk whose parent gets returned
goto fail_parents;
INIT_HLIST_HEAD(&core->clks);
- INIT_LIST_HEAD(&core->pending_requests);
/*
* Don't call clk_hw_create_clk() here because that would pin the