mirror of
https://github.com/Fishwaldo/build.git
synced 2025-03-27 01:02:19 +00:00
112 lines
3.3 KiB
Diff
112 lines
3.3 KiB
Diff
From 88cb11f99ca3a209274faa0da15ac27bcda99959 Mon Sep 17 00:00:00 2001
|
|
From: Jerome Brunet <jbrunet@baylibre.com>
|
|
Date: Thu, 18 May 2017 13:42:12 +0200
|
|
Subject: [PATCH 51/79] clk: add clk_set_rate_protect
|
|
|
|
clk_set_rate_protect is a combination of clk_set_rate and clk_rate_protect
|
|
within a critical section. In case where several protecting consumers
|
|
compete to set the rate of the same provider, it provides a way to make
|
|
sure that at least one of them will be satisfied before the resource is
|
|
locked.
|
|
|
|
This is to avoid the unlikely situation where several consumers protect a
|
|
clock provider and none actually get a rate it can work with.
|
|
|
|
Signed-off-by: Jerome Brunet <jbrunet@baylibre.com>
|
|
Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>
|
|
---
|
|
drivers/clk/clk.c | 45 +++++++++++++++++++++++++++++++++++++++++++++
|
|
include/linux/clk.h | 14 ++++++++++++++
|
|
2 files changed, 59 insertions(+)
|
|
|
|
diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
|
|
index d688b8f..d91236e 100644
|
|
--- a/drivers/clk/clk.c
|
|
+++ b/drivers/clk/clk.c
|
|
@@ -1809,6 +1809,51 @@ int clk_set_rate(struct clk *clk, unsigned long rate)
|
|
EXPORT_SYMBOL_GPL(clk_set_rate);
|
|
|
|
/**
|
|
+ * clk_set_rate_protect - specify a new rate and protect it
|
|
+ * @clk: the clk whose rate is being changed
|
|
+ * @rate: the new rate for clk
|
|
+ *
|
|
+ * This is a combination of clk_set_rate and clk_rate_protect within
|
|
+ * a critical section
|
|
+ *
|
|
+ * This can be used initially to ensure that at least 1 consumers is
|
|
+ * statisfied when several protecting consummers are competing for the
|
|
+ * same clock provider.
|
|
+ *
|
|
+ * The protection is not applied if setting the rate failed.
|
|
+ *
|
|
+ * Returns 0 on success, -EERROR otherwise.
|
|
+ */
|
|
+int clk_set_rate_protect(struct clk *clk, unsigned long rate)
|
|
+{
|
|
+ int ret;
|
|
+
|
|
+ if (!clk)
|
|
+ return 0;
|
|
+
|
|
+ /* prevent racing with updates to the clock topology */
|
|
+ clk_prepare_lock();
|
|
+
|
|
+ /*
|
|
+ * The temporary protection removal is not here, on purpose
|
|
+ * This function is meant to be used in instead of clk_rate_protect,
|
|
+ * so before the consumer code path protect the clock provider
|
|
+ */
|
|
+
|
|
+ ret = clk_core_set_rate_nolock(clk->core, rate);
|
|
+
|
|
+ if (!ret) {
|
|
+ clk_core_rate_protect(clk->core);
|
|
+ clk->protect_count++;
|
|
+ }
|
|
+
|
|
+ clk_prepare_unlock();
|
|
+
|
|
+ return ret;
|
|
+}
|
|
+EXPORT_SYMBOL_GPL(clk_set_rate_protect);
|
|
+
|
|
+/**
|
|
* clk_set_rate_range - set a rate range for a clock source
|
|
* @clk: clock source
|
|
* @min: desired minimum clock rate in Hz, inclusive
|
|
diff --git a/include/linux/clk.h b/include/linux/clk.h
|
|
index 85d73e0..d3c299d 100644
|
|
--- a/include/linux/clk.h
|
|
+++ b/include/linux/clk.h
|
|
@@ -388,6 +388,15 @@ struct clk *devm_get_clk_from_child(struct device *dev,
|
|
int clk_set_rate(struct clk *clk, unsigned long rate);
|
|
|
|
/**
|
|
+ * clk_set_rate_protect - set and protect the clock rate for a clock source
|
|
+ * @clk: clock source
|
|
+ * @rate: desired clock rate in Hz
|
|
+ *
|
|
+ * Returns success (0) or negative errno.
|
|
+ */
|
|
+int clk_set_rate_protect(struct clk *clk, unsigned long rate);
|
|
+
|
|
+/**
|
|
* clk_has_parent - check if a clock is a possible parent for another
|
|
* @clk: clock source
|
|
* @parent: parent clock source
|
|
@@ -506,6 +515,11 @@ static inline int clk_set_rate(struct clk *clk, unsigned long rate)
|
|
return 0;
|
|
}
|
|
|
|
+static inline int clk_set_rate_protect(struct clk *clk, unsigned long rate)
|
|
+{
|
|
+ return 0;
|
|
+}
|
|
+
|
|
static inline long clk_round_rate(struct clk *clk, unsigned long rate)
|
|
{
|
|
return 0;
|
|
--
|
|
1.9.1
|
|
|