linux-arm-kernel.lists.infradead.org archive mirror
 help / color / mirror / Atom feed
From: robherring2@gmail.com (Rob Herring)
To: linux-arm-kernel@lists.infradead.org
Subject: [PATCH v6 3/3] clk: basic clock hardware types
Date: Wed, 14 Mar 2012 13:38:59 -0500	[thread overview]
Message-ID: <4F60E5C3.1090006@gmail.com> (raw)
In-Reply-To: <20120314182345.GB29317@pengutronix.de>

On 03/14/2012 01:23 PM, Sascha Hauer wrote:
> On Fri, Mar 09, 2012 at 11:54:24PM -0800, Mike Turquette wrote:
>> Many platforms support simple gateable clocks, fixed-rate clocks,
>> adjustable divider clocks and multi-parent multiplexer clocks.
>>
>> This patch introduces basic clock types for the above-mentioned hardware
>> which share some common characteristics.
>>
>> Based on original work by Jeremy Kerr and contribution by Jamie Iles.
>> Dividers and multiplexor clocks originally contributed by Richard Zhao &
>> Sascha Hauer.
>>
>> Signed-off-by: Mike Turquette <mturquette@linaro.org>
>> Signed-off-by: Mike Turquette <mturquette@ti.com>
>> Cc: Russell King <linux@arm.linux.org.uk>
>> Cc: Jeremy Kerr <jeremy.kerr@canonical.com>
>> Cc: Thomas Gleixner <tglx@linutronix.de>
>> Cc: Arnd Bergman <arnd.bergmann@linaro.org>
>> Cc: Paul Walmsley <paul@pwsan.com>
>> Cc: Shawn Guo <shawn.guo@freescale.com>
>> Cc: Sascha Hauer <s.hauer@pengutronix.de>
>> Cc: Jamie Iles <jamie@jamieiles.com>
>> Cc: Richard Zhao <richard.zhao@linaro.org>
>> Cc: Saravana Kannan <skannan@codeaurora.org>
>> Cc: Magnus Damm <magnus.damm@gmail.com>
>> Cc: Rob Herring <rob.herring@calxeda.com>
>> Cc: Mark Brown <broonie@opensource.wolfsonmicro.com>
>> Cc: Linus Walleij <linus.walleij@stericsson.com>
>> Cc: Stephen Boyd <sboyd@codeaurora.org>
>> Cc: Amit Kucheria <amit.kucheria@linaro.org>
>> Cc: Deepak Saxena <dsaxena@linaro.org>
>> Cc: Grant Likely <grant.likely@secretlab.ca>
>> Cc: Andrew Lunn <andrew@lunn.ch>
>> ---
>> Changes since v5:
>>  * standardized the hw-specific locking in the basic clock types
>>  * export the individual ops for each basic clock type
>>  * improve registration for single-parent basic clocks (thanks Sascha)
>>  * fixed bugs in gate clock's static initializers (thanks Andrew)
>>
>>  drivers/clk/Makefile         |    3 +-
>>  drivers/clk/clk-divider.c    |  204 ++++++++++++++++++++++++++++++++++++++++++
>>  drivers/clk/clk-fixed-rate.c |   82 +++++++++++++++++
>>  drivers/clk/clk-gate.c       |  157 ++++++++++++++++++++++++++++++++
>>  drivers/clk/clk-mux.c        |  123 +++++++++++++++++++++++++
>>  include/linux/clk-private.h  |  124 +++++++++++++++++++++++++
>>  include/linux/clk-provider.h |  127 ++++++++++++++++++++++++++
>>  7 files changed, 819 insertions(+), 1 deletions(-)
>>  create mode 100644 drivers/clk/clk-divider.c
>>  create mode 100644 drivers/clk/clk-fixed-rate.c
>>  create mode 100644 drivers/clk/clk-gate.c
>>  create mode 100644 drivers/clk/clk-mux.c
>>
>> diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile
>> index ff362c4..1f736bc 100644
>> --- a/drivers/clk/Makefile
>> +++ b/drivers/clk/Makefile
>> @@ -1,3 +1,4 @@
>>  
>>  obj-$(CONFIG_CLKDEV_LOOKUP)	+= clkdev.o
>> -obj-$(CONFIG_COMMON_CLK)	+= clk.o
>> +obj-$(CONFIG_COMMON_CLK)	+= clk.o clk-fixed-rate.o clk-gate.o \
>> +				   clk-mux.o clk-divider.o
>> diff --git a/drivers/clk/clk-divider.c b/drivers/clk/clk-divider.c
>> new file mode 100644
>> index 0000000..c0c4e0b
>> --- /dev/null
>> +++ b/drivers/clk/clk-divider.c
>> @@ -0,0 +1,204 @@
>> +/*
>> + * Copyright (C) 2011 Sascha Hauer, Pengutronix <s.hauer@pengutronix.de>
>> + * Copyright (C) 2011 Richard Zhao, Linaro <richard.zhao@linaro.org>
>> + * Copyright (C) 2011-2012 Mike Turquette, Linaro Ltd <mturquette@linaro.org>
>> + *
>> + * This program is free software; you can redistribute it and/or modify
>> + * it under the terms of the GNU General Public License version 2 as
>> + * published by the Free Software Foundation.
>> + *
>> + * Adjustable divider clock implementation
>> + */
>> +
>> +#include <linux/clk-provider.h>
>> +#include <linux/module.h>
>> +#include <linux/slab.h>
>> +#include <linux/io.h>
>> +#include <linux/err.h>
>> +#include <linux/string.h>
>> +
>> +/*
>> + * DOC: basic adjustable divider clock that cannot gate
>> + *
>> + * Traits of this clock:
>> + * prepare - clk_prepare only ensures that parents are prepared
>> + * enable - clk_enable only ensures that parents are enabled
>> + * rate - rate is adjustable.  clk->rate = parent->rate / divisor
>> + * parent - fixed parent.  No clk_set_parent support
>> + */
>> +
>> +#define to_clk_divider(_hw) container_of(_hw, struct clk_divider, hw)
>> +
>> +static unsigned long clk_divider_recalc_rate(struct clk_hw *hw,
>> +		unsigned long parent_rate)
>> +{
>> +	struct clk_divider *divider = to_clk_divider(hw);
>> +	unsigned int div;
>> +	unsigned long flags = 0;
>> +
>> +	if (divider->lock)
>> +		spin_lock_irqsave(divider->lock, flags);
>> +
>> +	div = readl(divider->reg) >> divider->shift;
>> +	div &= (1 << divider->width) - 1;
>> +
>> +	if (divider->lock)
>> +		spin_unlock_irqrestore(divider->lock, flags);
>> +
>> +	if (!(divider->flags & CLK_DIVIDER_ONE_BASED))
>> +		div++;
>> +
>> +	return parent_rate / div;
>> +}
>> +EXPORT_SYMBOL_GPL(clk_divider_recalc_rate);
>> +
>> +static int clk_divider_bestdiv(struct clk_hw *hw, unsigned long rate,
>> +		unsigned long *best_parent_rate)
>> +{
>> +	struct clk_divider *divider = to_clk_divider(hw);
>> +	int i, bestdiv = 0;
>> +	unsigned long parent_rate, best = 0, now, maxdiv;
>> +
>> +	maxdiv = (1 << divider->width);
> 
> We need a check for rate == 0 here:
> 
> 	if (rate == 0)
> 		rate = 1;
> 
> Otherwise we divide by zero below.
> 
>> +
>> +	if (divider->flags & CLK_DIVIDER_ONE_BASED)
>> +		maxdiv--;
>> +
>> +	if (!(__clk_get_flags(hw->clk) & CLK_SET_RATE_PARENT)) {
>> +		parent_rate = __clk_get_rate(__clk_get_parent(hw->clk));
>> +		bestdiv = parent_rate / rate;
> 
> It's a bit strange but due to integer maths you must use DIV_ROUND_UP
> in round_rate and div = parent_rate / rate in set_rate.
> 
> Example:
> 
> parent_rate = 100
> rate = 34
> 
> Now the best divider would be 3 (100/3 = 33), but the above
> results in 2. With DIV_ROUND_UP round_rate correctly returns
> 33. Now when you use DIV_ROUND_UP in set_rate the resulting
> divider would be 4 which is wrong whereas 100/33 returns the correct
> result.

This gets into the problem with round_rate. You can't specify whether to
round up or down. For something like an SD card you would want to pass
in the max freq for the card and get back something less than or equal
to it. For something like an LCD pixel clock, you need a frequency
greater than or equal to the requested freq to maintain a minimum
refresh rate. There's been some discussion about this some time back.

But for now we shouldn't fix round_rate, and your solution is right (or
at least safer).

Rob

      reply	other threads:[~2012-03-14 18:38 UTC|newest]

Thread overview: 29+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2012-03-10  7:54 [PATCH v6 0/3] common clk framework Mike Turquette
2012-03-10  7:54 ` [PATCH v6 1/3] Documentation: common clk API Mike Turquette
2012-03-10 17:50   ` Andrew Lunn
2012-03-10  7:54 ` [PATCH v6 2/3] clk: introduce the common clock framework Mike Turquette
2012-03-10 10:51   ` Thomas Gleixner
2012-03-10 17:51   ` Andrew Lunn
2012-03-11  7:52   ` Richard Zhao
2012-03-11 21:02     ` Turquette, Mike
2012-03-11 11:34   ` Sascha Hauer
2012-03-11 21:24     ` Turquette, Mike
2012-03-12 11:51       ` Sascha Hauer
2012-03-13  3:16         ` Turquette, Mike
2012-03-13 12:05           ` Sascha Hauer
2012-03-15  0:51             ` Turquette, Mike
2012-03-15  9:43               ` Sascha Hauer
2012-03-16  6:22                 ` Turquette, Mike
2012-03-12 20:14   ` Rob Herring
2012-03-13 21:48   ` Rob Herring
2012-03-13 22:41     ` Turquette, Mike
2012-03-10  7:54 ` [PATCH v6 3/3] clk: basic clock hardware types Mike Turquette
2012-03-10 18:01   ` Andrew Lunn
2012-03-12 20:18   ` Rob Herring
2012-03-12 20:58     ` Turquette, Mike
2012-03-12 22:00       ` Rob Herring
2012-03-13  3:50   ` Matt Sealey
2012-03-13 10:38     ` Sascha Hauer
2012-03-14  8:54   ` Richard Zhao
2012-03-14 18:23   ` Sascha Hauer
2012-03-14 18:38     ` Rob Herring [this message]

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=4F60E5C3.1090006@gmail.com \
    --to=robherring2@gmail.com \
    --cc=linux-arm-kernel@lists.infradead.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).