From: Jarkko Lavinen <jarkko.lavinen@nokia.com>
To: linux-omap-open-source@linux.omap.com
Subject: [PATCH] OMAP: Asynchronous clock disable
Date: Fri, 5 Oct 2007 15:50:28 +0300 [thread overview]
Message-ID: <20071005125028.GA32101@angel.research.nokia.com> (raw)
[-- Attachment #1: Type: text/plain, Size: 1507 bytes --]
Hi
In N800 mmc driver we enable and disable mmc clock in a continous
cycle with small delays.
I wonder if asynchronou clock disable has been suggested before?
I would like to be able to disable clocks asynchronously with a
small delay so that when doing repetitive clk enable/disable
cycle, the clock would just stay up and only shut down when
the continuos stream of requests is over.
What I would like to do is:
clk_enable(clk):
... process the request
clk_disable_async(clk, 2);
This would leave clock running for 2 ticks after returning from
clk_disable_async() and only then disable it. In mmc driver the
delay could be close to 50 ms.
If clk_disable_async() would be reapplies, the latter call would
stay in effect since it is done using mod_timer(). For example here
the clock would be disabled 1 tick after the second call to
clk_disable_async():
clk_enable(clk);
clk_disable_async(clk, HZ);
clk_enable(clk);
clk_disable_async(clk, 1);
If clk_disable() and clk_disable_async() would be mixed, clk_disable()
would not cancel pending clk disable since the usecount would still
be bigger than 0 after calling clk_disable():
clk_enable(clk);
clk_disable_async(clk, HZ);
clk_enable(clk);
clk_disable(clk);
For clearing up pending clock disables I use clk_flush_disable(clk)
clears out any pending disable immediately.
clk_enable(clk);
clk_disable_async(clk, HZ);
... later
clk_flush_disable(clk)
Jarkko Lavinen
[-- Attachment #2: 0001-OMAP-Add-asynchronous-clock-disable.patch --]
[-- Type: text/x-diff, Size: 4550 bytes --]
>From 557e94d0a43efbc7e312ab7c1d8a568d65a9310a Mon Sep 17 00:00:00 2001
From: Jarkko Lavinen <jarkko.lavinen@nokia.com>
Date: Fri, 5 Oct 2007 15:39:46 +0300
Subject: [PATCH] OMAP: Add asynchronous clock disable
Asynchronouse clock disable is useful for repetitive request processing,
where clock is enabled and disabled continuosly.
Signed-off-by: Jarkko Lavinen <jarkko.lavinen@nokia.com>
---
arch/arm/plat-omap/clock.c | 56 +++++++++++++++++++++++++++++++++++--
include/asm-arm/arch-omap/clock.h | 4 ++
include/linux/clk.h | 16 ++++++++++
3 files changed, 73 insertions(+), 3 deletions(-)
diff --git a/arch/arm/plat-omap/clock.c b/arch/arm/plat-omap/clock.c
index 70f2311..a94b122 100644
--- a/arch/arm/plat-omap/clock.c
+++ b/arch/arm/plat-omap/clock.c
@@ -127,7 +127,7 @@ int clk_enable(struct clk *clk)
}
EXPORT_SYMBOL(clk_enable);
-void clk_disable(struct clk *clk)
+void clk_disable_async(struct clk *clk, int ticks)
{
unsigned long flags;
@@ -142,14 +142,61 @@ void clk_disable(struct clk *clk)
goto out;
}
- if (arch_clock->clk_disable)
- arch_clock->clk_disable(clk);
+ if (ticks > 0) {
+ if ((clk->flags & CLOCK_ASYNC_DISABLE) == 0) {
+ printk(KERN_ERR "Trying to disable clock %s "
+ "asynchronousely without proper "
+ "initialization\n", clk->name);
+ WARN_ON(1);
+ } else {
+ if (timer_pending(&clk->disable_timer))
+ clk->usecount--;
+
+ mod_timer(&clk->disable_timer, jiffies + ticks);
+ }
+ } else
+ if (arch_clock->clk_disable)
+ arch_clock->clk_disable(clk);
+out:
+ spin_unlock_irqrestore(&clockfw_lock, flags);
+}
+EXPORT_SYMBOL(clk_disable_async);
+
+void clk_flush_disable(struct clk *clk)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&clockfw_lock, flags);
+ if ((clk->flags & CLOCK_ASYNC_DISABLE) == 0) {
+ printk(KERN_ERR "Trying to disable clock %s asynchronousely "
+ "without timer initialization\n", clk->name);
+ WARN_ON(1);
+ goto out;
+ }
+ if (timer_pending(&clk->disable_timer)) {
+ del_timer(&clk->disable_timer);
+ if (arch_clock->clk_disable)
+ arch_clock->clk_disable(clk);
+ }
out:
spin_unlock_irqrestore(&clockfw_lock, flags);
}
+EXPORT_SYMBOL(clk_flush_disable);
+
+void clk_disable(struct clk *clk)
+{
+ clk_disable_async(clk, 0);
+}
EXPORT_SYMBOL(clk_disable);
+static void clk_disable_timer(unsigned long data)
+{
+ struct clk *clk = (struct clk *) data;
+
+ clk_disable_async(clk, 0);
+}
+
int clk_get_usecount(struct clk *clk)
{
unsigned long flags;
@@ -336,6 +383,9 @@ int clk_register(struct clk *clk)
mutex_lock(&clocks_mutex);
list_add(&clk->node, &clocks);
+ if (clk->flags & CLOCK_ASYNC_DISABLE)
+ setup_timer(&clk->disable_timer, clk_disable_timer,
+ (unsigned long) clk);
if (clk->init)
clk->init(clk);
mutex_unlock(&clocks_mutex);
diff --git a/include/asm-arm/arch-omap/clock.h b/include/asm-arm/arch-omap/clock.h
index cb7a301..aa95aac 100644
--- a/include/asm-arm/arch-omap/clock.h
+++ b/include/asm-arm/arch-omap/clock.h
@@ -13,6 +13,8 @@
#ifndef __ARCH_ARM_OMAP_CLOCK_H
#define __ARCH_ARM_OMAP_CLOCK_H
+#include <linux/timer.h>
+
struct module;
struct clk;
@@ -57,6 +59,7 @@ struct clk {
void __iomem *enable_reg;
__u8 enable_bit;
__s8 usecount;
+ struct timer_list disable_timer;
void (*recalc)(struct clk *);
int (*set_rate)(struct clk *, unsigned long);
long (*round_rate)(struct clk *, unsigned long);
@@ -123,6 +126,7 @@ extern void clk_enable_init_clocks(void);
#define CLOCK_IN_OMAP243X (1 << 26)
#define CLOCK_IN_OMAP343X (1 << 27)
#define PARENT_CONTROLS_CLOCK (1 << 28)
+#define CLOCK_ASYNC_DISABLE (1 << 29)
/* Clksel_rate flags */
#define DEFAULT_RATE (1 << 0)
diff --git a/include/linux/clk.h b/include/linux/clk.h
index 5ca8c6f..c922f79 100644
--- a/include/linux/clk.h
+++ b/include/linux/clk.h
@@ -63,6 +63,22 @@ int clk_enable(struct clk *clk);
void clk_disable(struct clk *clk);
/**
+ * clk_disable_async - disable the clock after a delay
+ * @clk: clock source
+ * @ticks: delay
+ *
+ * Asyncronous clock disable is implemented with a timer which runs
+ * clk_disable when the timer expires.
+ */
+void clk_disable_async(struct clk *clk, int ticks);
+
+/**
+ * clk_sync_disable - Finish pending clock disable immediately
+ * @clk: clock source
+ */
+void clk_flush_disable(struct clk *clk);
+
+/**
* clk_get_rate - obtain the current clock rate (in Hz) for a clock source.
* This is only valid once the clock source has been enabled.
* @clk: clock source
--
1.5.3.1
[-- Attachment #3: Type: text/plain, Size: 0 bytes --]
next reply other threads:[~2007-10-05 12:50 UTC|newest]
Thread overview: 5+ messages / expand[flat|nested] mbox.gz Atom feed top
2007-10-05 12:50 Jarkko Lavinen [this message]
2007-10-05 13:25 ` [PATCH] OMAP: Asynchronous clock disable Igor Stoppa
2007-10-05 13:27 ` Woodruff, Richard
2007-10-08 3:51 ` Tony Lindgren
2007-10-09 22:17 ` Woodruff, Richard
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=20071005125028.GA32101@angel.research.nokia.com \
--to=jarkko.lavinen@nokia.com \
--cc=linux-omap-open-source@linux.omap.com \
/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