From patchwork Tue Mar 19 13:28:32 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Bill Huang X-Patchwork-Id: 15432 Return-Path: X-Original-To: patchwork@peony.canonical.com Delivered-To: patchwork@peony.canonical.com Received: from fiordland.canonical.com (fiordland.canonical.com [91.189.94.145]) by peony.canonical.com (Postfix) with ESMTP id 83CB223E75 for ; Tue, 19 Mar 2013 13:31:27 +0000 (UTC) Received: from mail-vb0-f47.google.com (mail-vb0-f47.google.com [209.85.212.47]) by fiordland.canonical.com (Postfix) with ESMTP id 08234A18C24 for ; Tue, 19 Mar 2013 13:31:26 +0000 (UTC) Received: by mail-vb0-f47.google.com with SMTP id e21so304451vbm.20 for ; Tue, 19 Mar 2013 06:31:26 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20120113; h=x-received:x-forwarded-to:x-forwarded-for:delivered-to:x-received :received-spf:x-pgp-universal:from:to:cc:subject:date:message-id :x-mailer:x-nvconfidentiality:mime-version:content-type :x-gm-message-state; bh=wTX3RRr9xKxyB5PpJbO3LLIrIdq6u0axyjS8o64fhq4=; b=jHoMyOI0rCNFYzUH0W2gMBXgmvTaebKVWJoRG2uEC8twep8mk8Y87YsAwehFH6fAbg 0KPrBGhTbyCrnqE1b7KrZrTDceeRbA1ignpSZdMftEYtHPJJ4NCSdxwyVdF92oPzDY3R f2uhUGkbwVKf/jS4HSEmfaMD+YAoOxR8rV5Kcg/W7dXwU5OmwjTa8WsFLCjw26CCYyhR rjWR6uUGtat039UGZqtzBfDRzR9uFydvdj4fW0WtJT5rDAbSDokXSaOiWmhcDAQrPwpx EHAYdunF6rw9j7Jjv0ZUiyE+DII/3xgM4z0MQLMGrklZ8lzcDNCzgQzw5R5U+pZCv79P ppRg== X-Received: by 10.52.29.18 with SMTP id f18mr2021680vdh.57.1363699886429; Tue, 19 Mar 2013 06:31:26 -0700 (PDT) X-Forwarded-To: linaro-patchwork@canonical.com X-Forwarded-For: patch@linaro.org linaro-patchwork@canonical.com Delivered-To: patches@linaro.org Received: by 10.58.127.98 with SMTP id nf2csp100118veb; Tue, 19 Mar 2013 06:31:25 -0700 (PDT) X-Received: by 10.68.196.168 with SMTP id in8mr3117990pbc.61.1363699884923; Tue, 19 Mar 2013 06:31:24 -0700 (PDT) Received: from hqemgate03.nvidia.com (hqemgate03.nvidia.com. [216.228.121.140]) by mx.google.com with ESMTPS id yf1si25822697pbc.253.2013.03.19.06.31.22 (version=TLSv1 cipher=RC4-SHA bits=128/128); Tue, 19 Mar 2013 06:31:24 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of bilhuang@nvidia.com designates 216.228.121.140 as permitted sender) client-ip=216.228.121.140; Authentication-Results: mx.google.com; spf=pass (google.com: best guess record for domain of bilhuang@nvidia.com designates 216.228.121.140 as permitted sender) smtp.mail=bilhuang@nvidia.com Received: from hqnvupgp07.nvidia.com (Not Verified[216.228.121.13]) by hqemgate03.nvidia.com id ; Tue, 19 Mar 2013 06:36:42 -0700 Received: from hqemhub01.nvidia.com ([172.17.108.22]) by hqnvupgp07.nvidia.com (PGP Universal service); Tue, 19 Mar 2013 06:31:22 -0700 X-PGP-Universal: processed; by hqnvupgp07.nvidia.com on Tue, 19 Mar 2013 06:31:22 -0700 Received: from localhost.localdomain (172.20.144.16) by hqemhub01.nvidia.com (172.20.150.30) with Microsoft SMTP Server (TLS) id 8.3.298.1; Tue, 19 Mar 2013 06:31:21 -0700 From: Bill Huang To: CC: , , , , Bill Huang Subject: [PATCH 1/1] clk: Add notifier support in clk_prepare/clk_unprepare Date: Tue, 19 Mar 2013 06:28:32 -0700 Message-ID: <1363699712-8124-1-git-send-email-bilhuang@nvidia.com> X-Mailer: git-send-email 1.7.9.5 X-NVConfidentiality: public MIME-Version: 1.0 X-Gm-Message-State: ALoCoQmIsXIfarVvyhJkiTI8YYaph+Rk/BkixFxkB3gvaS6SXPHDck77cSNd7H1FvoMskx3DN4il Add notifier calls in clk_prepare and clk_unprepare so drivers which are interested in knowing that clk_prepare/unprepare call can act accordingly. The existing "clk_set_rate" notifier is not enough for normal DVFS inplementation since clock might be enabled/disabled at runtime. Adding these notifiers is useful on DVFS core which take clk_prepare as a hint on that the notified clock might be enabled later so it can raise voltage to a safe level before enabling the clock, and take clk_unprepare as a hint that the clock has been disabled and is safe to lower the voltage. The added notifier events are: PRE_CLK_PREPARE POST_CLK_PREPARE ABORT_CLK_PREPARE PRE_CLK_UNPREPARE POST_CLK_UNPREPARE Signed-off-by: Bill Huang --- drivers/clk/clk.c | 88 ++++++++++++++++++++++++++++++--------------------- include/linux/clk.h | 5 +++ 2 files changed, 57 insertions(+), 36 deletions(-) diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c index ed87b24..ac07c6e 100644 --- a/drivers/clk/clk.c +++ b/drivers/clk/clk.c @@ -516,6 +516,42 @@ struct clk *__clk_lookup(const char *name) /*** clk api ***/ +/** + * __clk_notify - call clk notifier chain + * @clk: struct clk * that is changing rate + * @msg: clk notifier type (see include/linux/clk.h) + * @old_rate: old clk rate + * @new_rate: new clk rate + * + * Triggers a notifier call chain on the clk rate-change notification + * for 'clk'. Passes a pointer to the struct clk and the previous + * and current rates to the notifier callback. Intended to be called by + * internal clock code only. Returns NOTIFY_DONE from the last driver + * called if all went well, or NOTIFY_STOP or NOTIFY_BAD immediately if + * a driver returns that. + */ +static int __clk_notify(struct clk *clk, unsigned long msg, + unsigned long old_rate, unsigned long new_rate) +{ + struct clk_notifier *cn; + struct clk_notifier_data cnd; + int ret = NOTIFY_DONE; + + cnd.clk = clk; + cnd.old_rate = old_rate; + cnd.new_rate = new_rate; + + list_for_each_entry(cn, &clk_notifier_list, node) { + if (cn->clk == clk) { + ret = srcu_notifier_call_chain(&cn->notifier_head, msg, + &cnd); + break; + } + } + + return ret; +} + void __clk_unprepare(struct clk *clk) { if (!clk) @@ -549,7 +585,14 @@ void __clk_unprepare(struct clk *clk) void clk_unprepare(struct clk *clk) { mutex_lock(&prepare_lock); + + if (clk->notifier_count) + __clk_notify(clk, PRE_CLK_UNPREPARE, clk->rate, clk->rate); + __clk_unprepare(clk); + if (clk->notifier_count) + __clk_notify(clk, POST_CLK_UNPREPARE, clk->rate, clk->rate); + mutex_unlock(&prepare_lock); } EXPORT_SYMBOL_GPL(clk_unprepare); @@ -597,7 +640,16 @@ int clk_prepare(struct clk *clk) int ret; mutex_lock(&prepare_lock); + + if (clk->notifier_count) + __clk_notify(clk, PRE_CLK_PREPARE, clk->rate, clk->rate); + ret = __clk_prepare(clk); + if (!ret && clk->notifier_count) + __clk_notify(clk, POST_CLK_PREPARE, clk->rate, clk->rate); + else if (clk->notifier_count) + __clk_notify(clk, ABORT_CLK_PREPARE, clk->rate, clk->rate); + mutex_unlock(&prepare_lock); return ret; @@ -749,42 +801,6 @@ long clk_round_rate(struct clk *clk, unsigned long rate) EXPORT_SYMBOL_GPL(clk_round_rate); /** - * __clk_notify - call clk notifier chain - * @clk: struct clk * that is changing rate - * @msg: clk notifier type (see include/linux/clk.h) - * @old_rate: old clk rate - * @new_rate: new clk rate - * - * Triggers a notifier call chain on the clk rate-change notification - * for 'clk'. Passes a pointer to the struct clk and the previous - * and current rates to the notifier callback. Intended to be called by - * internal clock code only. Returns NOTIFY_DONE from the last driver - * called if all went well, or NOTIFY_STOP or NOTIFY_BAD immediately if - * a driver returns that. - */ -static int __clk_notify(struct clk *clk, unsigned long msg, - unsigned long old_rate, unsigned long new_rate) -{ - struct clk_notifier *cn; - struct clk_notifier_data cnd; - int ret = NOTIFY_DONE; - - cnd.clk = clk; - cnd.old_rate = old_rate; - cnd.new_rate = new_rate; - - list_for_each_entry(cn, &clk_notifier_list, node) { - if (cn->clk == clk) { - ret = srcu_notifier_call_chain(&cn->notifier_head, msg, - &cnd); - break; - } - } - - return ret; -} - -/** * __clk_recalc_rates * @clk: first clk in the subtree * @msg: notification type (see include/linux/clk.h) diff --git a/include/linux/clk.h b/include/linux/clk.h index b3ac22d..41d567d 100644 --- a/include/linux/clk.h +++ b/include/linux/clk.h @@ -43,6 +43,11 @@ struct clk; #define PRE_RATE_CHANGE BIT(0) #define POST_RATE_CHANGE BIT(1) #define ABORT_RATE_CHANGE BIT(2) +#define PRE_CLK_PREPARE BIT(3) +#define POST_CLK_PREPARE BIT(4) +#define ABORT_CLK_PREPARE BIT(5) +#define PRE_CLK_UNPREPARE BIT(6) +#define POST_CLK_UNPREPARE BIT(7) /** * struct clk_notifier - associate a clk with a notifier