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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.