From patchwork Mon Jun 30 16:56:33 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Soren Brinkmann X-Patchwork-Id: 4453381 Return-Path: X-Original-To: patchwork-linux-arm@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork2.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.19.201]) by patchwork2.web.kernel.org (Postfix) with ESMTP id 32A4DBEEAA for ; Mon, 30 Jun 2014 16:59:35 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 5445220373 for ; Mon, 30 Jun 2014 16:59:34 +0000 (UTC) Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.9]) (using TLSv1.2 with cipher DHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 6A74C2020F for ; Mon, 30 Jun 2014 16:59:33 +0000 (UTC) Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.80.1 #2 (Red Hat Linux)) id 1X1eto-0003ZQ-EA; Mon, 30 Jun 2014 16:57:48 +0000 Received: from mail-pa0-x236.google.com ([2607:f8b0:400e:c03::236]) by bombadil.infradead.org with esmtps (Exim 4.80.1 #2 (Red Hat Linux)) id 1X1etG-0002km-Rh for linux-arm-kernel@lists.infradead.org; Mon, 30 Jun 2014 16:57:16 +0000 Received: by mail-pa0-f54.google.com with SMTP id et14so8951175pad.13 for ; Mon, 30 Jun 2014 09:56:53 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=sender:from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-type:content-transfer-encoding; bh=P4qyppKsGtILUPRKj2Oox6LZpugUG2hgxi8l9qi0yt4=; b=TCj1YiL0XoGWjjomIo4aKrbtBIll5gy9Zx5N3DUZnOmy2wmPBGp5k9AvLpFiULHqpe FNdEAqooHcYLqHqEOOkOuhGhthnM6OLXvOdDoOnlX/etNUbRMmtXiaYwGVJJvLOesxrX abMGR27lJtNXtseUE7pZZae8mL7C/UoqzM8IuPsfw2FNJV+l5SS8ChKTygt+9LgP8CYN kWf7yXWM3782pvtOfyWYnUIepqoG9+VY1veA5hhGEKNeLdYnAhN8WXokeSM03SGv+WA/ bh/eaGIyZJQtqdFMMx5yEhbiXCP/gdRUkdrJaxyzEx1su2DxA//zTgNaOU4EpdCU3mYH XJiw== X-Received: by 10.67.3.166 with SMTP id bx6mr53609170pad.7.1404147413376; Mon, 30 Jun 2014 09:56:53 -0700 (PDT) Received: from localhost ([149.199.62.254]) by mx.google.com with ESMTPSA id dd5sm28624190pbc.85.2014.06.30.09.56.51 for (version=TLSv1.2 cipher=RC4-SHA bits=128/128); Mon, 30 Jun 2014 09:56:52 -0700 (PDT) From: Soren Brinkmann To: Mike Turquette , "Rafael J. Wysocki" , Viresh Kumar Subject: [PATCH 1/4] clk: Introduce 'clk_find_nearest_rate()' Date: Mon, 30 Jun 2014 09:56:33 -0700 Message-Id: <1404147396-8041-2-git-send-email-soren.brinkmann@xilinx.com> X-Mailer: git-send-email 2.0.1.1.gfbfc394 In-Reply-To: <1404147396-8041-1-git-send-email-soren.brinkmann@xilinx.com> References: <1404147396-8041-1-git-send-email-soren.brinkmann@xilinx.com> MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20140630_095714_973149_9DE6A0D6 X-CRM114-Status: GOOD ( 14.77 ) X-Spam-Score: -0.7 (/) Cc: Russell King , linux-pm@vger.kernel.org, Nicolas Ferre , Michal Simek , cpufreq@vger.kernel.org, linux-kernel@vger.kernel.org, Soren Brinkmann , =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= , linux-arm-kernel@lists.infradead.org X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.18-1 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org X-Spam-Status: No, score=-1.8 required=5.0 tests=BAYES_00,DKIM_SIGNED, T_DKIM_INVALID, T_RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=no version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP Introduce a new API function to find the rate a clock can provide which is closest to a given rate. clk_round_rate() leaves it to the clock driver how rounding is done. Commonly implementations round down due to use-cases that have a certain frequency maximum that must not be exceeded. The new API call enables use-cases where accuracy is preferred. E.g. Ethernet clocks. Signed-off-by: Soren Brinkmann --- drivers/clk/clk.c | 57 +++++++++++++++++++++++++++++++++++++++++++++++++++++ include/linux/clk.h | 9 +++++++++ 2 files changed, 66 insertions(+) diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c index 8b73edef151d..fce1165cd879 100644 --- a/drivers/clk/clk.c +++ b/drivers/clk/clk.c @@ -1030,6 +1030,63 @@ long clk_round_rate(struct clk *clk, unsigned long rate) EXPORT_SYMBOL_GPL(clk_round_rate); /** + * clk_find_nearest_rate - round the given rate for a clk + * @clk: the clk for which we are rounding a rate + * @rate: the rate which is to be rounded + * + * Takes in a rate as input and finds the closest rate that the clk + * can actually use which is then returned. + * Note: This function relies on the clock's clk_round_rate() implementation. + * For cases clk_round_rate() rounds up, not the closest but the rounded up + * rate is found. + */ +long clk_find_nearest_rate(struct clk *clk, unsigned long rate) +{ + long ret, lower, upper; + unsigned long tmp; + + clk_prepare_lock(); + + lower = __clk_round_rate(clk, rate); + if (lower >= rate || lower < 0) { + ret = lower; + goto unlock; + } + + tmp = rate + (rate - lower) - 1; + if (tmp > LONG_MAX) + upper = LONG_MAX; + else + upper = tmp; + + upper = __clk_round_rate(clk, upper); + if (upper <= lower || upper < 0) { + ret = lower; + goto unlock; + } + + lower = rate + 1; + while (lower < upper) { + long rounded, mid; + + mid = lower + ((upper - lower) >> 1); + rounded = __clk_round_rate(clk, mid); + if (rounded < lower) + lower = mid + 1; + else + upper = rounded; + } + + ret = upper; + +unlock: + clk_prepare_unlock(); + + return ret; +} +EXPORT_SYMBOL_GPL(clk_find_nearest_rate); + +/** * __clk_notify - call clk notifier chain * @clk: struct clk * that is changing rate * @msg: clk notifier type (see include/linux/clk.h) diff --git a/include/linux/clk.h b/include/linux/clk.h index fb5e097d8f72..f8b53c515483 100644 --- a/include/linux/clk.h +++ b/include/linux/clk.h @@ -264,6 +264,15 @@ void devm_clk_put(struct device *dev, struct clk *clk); long clk_round_rate(struct clk *clk, unsigned long rate); /** + * clk_find_nearest_rate - Find nearest rate to the exact rate a clock can provide + * @clk: the clk for which we are rounding a rate + * @rate: the rate which is to be rounded + * + * Returns the rate closest to @rate the clock can provide. + */ +long clk_find_nearest_rate(struct clk *clk, unsigned long rate); + +/** * clk_set_rate - set the clock rate for a clock source * @clk: clock source * @rate: desired clock rate in Hz