msm: clock: Support clk_prepare/unprepare()
Fill in the boiler plate prepare()/unprepare() code. Add a
prepare count and a prepare lock to protect the prepare/unprepare
paths. Also handle the parent/child relationship similarly to how
enable/disable is done.
In particular, WARN() whenever a driver calls clk_enable() before
calling clk_prepare() and whenever a driver calls clk_unprepare()
before calling clk_disable(). This should catch a few bugs even
though it's technically not SMP safe if an enable call is racing
with an unprepare call for example.
We also mark PLLs and XOs as already warned since those are
mostly internal clocks that driver authors aren't aware of. The
markings will be removed when the local clock driver is updated
to handle prepare/unprepare in another patch.
Change-Id: I41dd39d27a279f3477c6e1cef292ac5308d65243
Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
diff --git a/arch/arm/mach-msm/clock.h b/arch/arm/mach-msm/clock.h
index 4210bd9..bce2e0f 100644
--- a/arch/arm/mach-msm/clock.h
+++ b/arch/arm/mach-msm/clock.h
@@ -21,6 +21,7 @@
#include <linux/list.h>
#include <linux/clkdev.h>
#include <linux/spinlock.h>
+#include <linux/mutex.h>
#include <mach/clk.h>
@@ -63,8 +64,10 @@
}
struct clk_ops {
+ int (*prepare)(struct clk *clk);
int (*enable)(struct clk *clk);
void (*disable)(struct clk *clk);
+ void (*unprepare)(struct clk *clk);
void (*auto_off)(struct clk *clk);
void (*enable_hwcg)(struct clk *clk);
void (*disable_hwcg)(struct clk *clk);
@@ -85,11 +88,14 @@
/**
* struct clk
+ * @prepare_count: prepare refcount
+ * @prepare_lock: protects clk_prepare()/clk_unprepare() path and @prepare_count
* @count: enable refcount
* @lock: protects clk_enable()/clk_disable() path and @count
* @depends: non-direct parent of clock to enable when this clock is enabled
* @vdd_class: voltage scaling requirement class
* @fmax: maximum frequency in Hz supported at each voltage level
+ * @warned: true if the clock has warned of incorrect usage, false otherwise
*/
struct clk {
uint32_t flags;
@@ -103,12 +109,16 @@
struct list_head children;
struct list_head siblings;
+ bool warned;
unsigned count;
spinlock_t lock;
+ unsigned prepare_count;
+ struct mutex prepare_lock;
};
#define CLK_INIT(name) \
.lock = __SPIN_LOCK_UNLOCKED((name).lock), \
+ .prepare_lock = __MUTEX_INITIALIZER((name).prepare_lock), \
.children = LIST_HEAD_INIT((name).children), \
.siblings = LIST_HEAD_INIT((name).siblings)