All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 0/2] clk: add helpers for generic clocks
@ 2018-01-18 11:01 Jerome Brunet
  2018-01-18 11:01 ` [PATCH 1/2] clk: divider: export clk_div_mask() helper Jerome Brunet
  2018-01-18 11:01 ` [PATCH 2/2] clk: mux: add helper function for index/value translation Jerome Brunet
  0 siblings, 2 replies; 3+ messages in thread
From: Jerome Brunet @ 2018-01-18 11:01 UTC (permalink / raw)
  To: Stephen Boyd, Michael Turquette; +Cc: Jerome Brunet, linux-clk, linux-kernel

This series exports an helper providing the divider mask in the generic
divider and helpers to translate the between the index and the register
value in the generic mux.

The goal is to avoid duplicating this code in clock providers deriving
from these generic clocks, something I plan do doing in upcoming
changeset for meson clocks [0]

In patch 1, I have 's/div_mask/clk_div_mask' to avoid the conflict with
tegra's divider, which also defines the macro div_mask() but does not
actually derives from the generic divider.

[0]: https://github.com/jeromebrunet/linux/commit/b1bfb0fc79d1b14cd4b74ec8d1d9167171973af0

Jerome Brunet (2):
  clk: divider: export clk_div_mask() helper
  clk: mux: add helper function for index/value translation

 drivers/clk/clk-divider.c    | 24 +++++++-------
 drivers/clk/clk-mux.c        | 75 +++++++++++++++++++++++++-------------------
 include/linux/clk-provider.h |  5 +++
 3 files changed, 59 insertions(+), 45 deletions(-)

-- 
2.14.3

^ permalink raw reply	[flat|nested] 3+ messages in thread

* [PATCH 1/2] clk: divider: export clk_div_mask() helper
  2018-01-18 11:01 [PATCH 0/2] clk: add helpers for generic clocks Jerome Brunet
@ 2018-01-18 11:01 ` Jerome Brunet
  2018-01-18 11:01 ` [PATCH 2/2] clk: mux: add helper function for index/value translation Jerome Brunet
  1 sibling, 0 replies; 3+ messages in thread
From: Jerome Brunet @ 2018-01-18 11:01 UTC (permalink / raw)
  To: Stephen Boyd, Michael Turquette; +Cc: Jerome Brunet, linux-clk, linux-kernel

Export clk_div_mask() in clk-provider header so every clock providers
derived from the generic clock divider may share the definition instead
of redefining it.

Signed-off-by: Jerome Brunet <jbrunet@baylibre.com>
---
 drivers/clk/clk-divider.c    | 24 +++++++++++-------------
 include/linux/clk-provider.h |  1 +
 2 files changed, 12 insertions(+), 13 deletions(-)

diff --git a/drivers/clk/clk-divider.c b/drivers/clk/clk-divider.c
index 3eb2b27f3513..b859620be4d2 100644
--- a/drivers/clk/clk-divider.c
+++ b/drivers/clk/clk-divider.c
@@ -28,12 +28,10 @@
  * parent - fixed parent.  No clk_set_parent support
  */
 
-#define div_mask(width)	((1 << (width)) - 1)
-
 static unsigned int _get_table_maxdiv(const struct clk_div_table *table,
 				      u8 width)
 {
-	unsigned int maxdiv = 0, mask = div_mask(width);
+	unsigned int maxdiv = 0, mask = clk_div_mask(width);
 	const struct clk_div_table *clkt;
 
 	for (clkt = table; clkt->div; clkt++)
@@ -57,12 +55,12 @@ static unsigned int _get_maxdiv(const struct clk_div_table *table, u8 width,
 				unsigned long flags)
 {
 	if (flags & CLK_DIVIDER_ONE_BASED)
-		return div_mask(width);
+		return clk_div_mask(width);
 	if (flags & CLK_DIVIDER_POWER_OF_TWO)
-		return 1 << div_mask(width);
+		return 1 << clk_div_mask(width);
 	if (table)
 		return _get_table_maxdiv(table, width);
-	return div_mask(width) + 1;
+	return clk_div_mask(width) + 1;
 }
 
 static unsigned int _get_table_div(const struct clk_div_table *table,
@@ -84,7 +82,7 @@ static unsigned int _get_div(const struct clk_div_table *table,
 	if (flags & CLK_DIVIDER_POWER_OF_TWO)
 		return 1 << val;
 	if (flags & CLK_DIVIDER_MAX_AT_ZERO)
-		return val ? val : div_mask(width) + 1;
+		return val ? val : clk_div_mask(width) + 1;
 	if (table)
 		return _get_table_div(table, val);
 	return val + 1;
@@ -109,7 +107,7 @@ static unsigned int _get_val(const struct clk_div_table *table,
 	if (flags & CLK_DIVIDER_POWER_OF_TWO)
 		return __ffs(div);
 	if (flags & CLK_DIVIDER_MAX_AT_ZERO)
-		return (div == div_mask(width) + 1) ? 0 : div;
+		return (div == clk_div_mask(width) + 1) ? 0 : div;
 	if (table)
 		return  _get_table_val(table, div);
 	return div - 1;
@@ -141,7 +139,7 @@ static unsigned long clk_divider_recalc_rate(struct clk_hw *hw,
 	unsigned int val;
 
 	val = clk_readl(divider->reg) >> divider->shift;
-	val &= div_mask(divider->width);
+	val &= clk_div_mask(divider->width);
 
 	return divider_recalc_rate(hw, parent_rate, val, divider->table,
 				   divider->flags, divider->width);
@@ -375,7 +373,7 @@ static long clk_divider_round_rate(struct clk_hw *hw, unsigned long rate,
 	/* if read only, just return current value */
 	if (divider->flags & CLK_DIVIDER_READ_ONLY) {
 		val = clk_readl(divider->reg) >> divider->shift;
-		val &= div_mask(divider->width);
+		val &= clk_div_mask(divider->width);
 
 		return divider_ro_round_rate(hw, rate, prate, divider->table,
 					     divider->width, divider->flags,
@@ -399,7 +397,7 @@ int divider_get_val(unsigned long rate, unsigned long parent_rate,
 
 	value = _get_val(table, div, flags, width);
 
-	return min_t(unsigned int, value, div_mask(width));
+	return min_t(unsigned int, value, clk_div_mask(width));
 }
 EXPORT_SYMBOL_GPL(divider_get_val);
 
@@ -422,10 +420,10 @@ static int clk_divider_set_rate(struct clk_hw *hw, unsigned long rate,
 		__acquire(divider->lock);
 
 	if (divider->flags & CLK_DIVIDER_HIWORD_MASK) {
-		val = div_mask(divider->width) << (divider->shift + 16);
+		val = clk_div_mask(divider->width) << (divider->shift + 16);
 	} else {
 		val = clk_readl(divider->reg);
-		val &= ~(div_mask(divider->width) << divider->shift);
+		val &= ~(clk_div_mask(divider->width) << divider->shift);
 	}
 	val |= (u32)value << divider->shift;
 	clk_writel(val, divider->reg);
diff --git a/include/linux/clk-provider.h b/include/linux/clk-provider.h
index 2f3a9aae1abb..38861e75b017 100644
--- a/include/linux/clk-provider.h
+++ b/include/linux/clk-provider.h
@@ -397,6 +397,7 @@ struct clk_divider {
 	spinlock_t	*lock;
 };
 
+#define clk_div_mask(width)	((1 << (width)) - 1)
 #define to_clk_divider(_hw) container_of(_hw, struct clk_divider, hw)
 
 #define CLK_DIVIDER_ONE_BASED		BIT(0)
-- 
2.14.3

^ permalink raw reply related	[flat|nested] 3+ messages in thread

* [PATCH 2/2] clk: mux: add helper function for index/value translation
  2018-01-18 11:01 [PATCH 0/2] clk: add helpers for generic clocks Jerome Brunet
  2018-01-18 11:01 ` [PATCH 1/2] clk: divider: export clk_div_mask() helper Jerome Brunet
@ 2018-01-18 11:01 ` Jerome Brunet
  1 sibling, 0 replies; 3+ messages in thread
From: Jerome Brunet @ 2018-01-18 11:01 UTC (permalink / raw)
  To: Stephen Boyd, Michael Turquette; +Cc: Jerome Brunet, linux-clk, linux-kernel

Add helper functions for the translation between parent index and
register value in the generic multiplexer function. The purpose of
this change is avoid duplicating the code in other clock providers,
using the same generic logic.

Signed-off-by: Jerome Brunet <jbrunet@baylibre.com>
---
 drivers/clk/clk-mux.c        | 75 +++++++++++++++++++++++++-------------------
 include/linux/clk-provider.h |  4 +++
 2 files changed, 47 insertions(+), 32 deletions(-)

diff --git a/drivers/clk/clk-mux.c b/drivers/clk/clk-mux.c
index 39cabe157163..ac4a042f8658 100644
--- a/drivers/clk/clk-mux.c
+++ b/drivers/clk/clk-mux.c
@@ -26,35 +26,24 @@
  * parent - parent is adjustable through clk_set_parent
  */
 
-static u8 clk_mux_get_parent(struct clk_hw *hw)
+int clk_mux_val_to_index(struct clk_hw *hw, u32 *table, unsigned int flags,
+			 unsigned int val)
 {
-	struct clk_mux *mux = to_clk_mux(hw);
 	int num_parents = clk_hw_get_num_parents(hw);
-	u32 val;
 
-	/*
-	 * FIXME need a mux-specific flag to determine if val is bitwise or numeric
-	 * e.g. sys_clkin_ck's clksel field is 3 bits wide, but ranges from 0x1
-	 * to 0x7 (index starts at one)
-	 * OTOH, pmd_trace_clk_mux_ck uses a separate bit for each clock, so
-	 * val = 0x4 really means "bit 2, index starts at bit 0"
-	 */
-	val = clk_readl(mux->reg) >> mux->shift;
-	val &= mux->mask;
-
-	if (mux->table) {
+	if (table) {
 		int i;
 
 		for (i = 0; i < num_parents; i++)
-			if (mux->table[i] == val)
+			if (table[i] == val)
 				return i;
 		return -EINVAL;
 	}
 
-	if (val && (mux->flags & CLK_MUX_INDEX_BIT))
+	if (val && (flags & CLK_MUX_INDEX_BIT))
 		val = ffs(val) - 1;
 
-	if (val && (mux->flags & CLK_MUX_INDEX_ONE))
+	if (val && (flags & CLK_MUX_INDEX_ONE))
 		val--;
 
 	if (val >= num_parents)
@@ -62,36 +51,58 @@ static u8 clk_mux_get_parent(struct clk_hw *hw)
 
 	return val;
 }
+EXPORT_SYMBOL_GPL(clk_mux_val_to_index);
 
-static int clk_mux_set_parent(struct clk_hw *hw, u8 index)
+unsigned int clk_mux_index_to_val(u32 *table, unsigned int flags, u8 index)
 {
-	struct clk_mux *mux = to_clk_mux(hw);
-	u32 val;
-	unsigned long flags = 0;
+	unsigned int val = index;
 
-	if (mux->table) {
-		index = mux->table[index];
+	if (table) {
+		val = table[index];
 	} else {
-		if (mux->flags & CLK_MUX_INDEX_BIT)
-			index = 1 << index;
+		if (flags & CLK_MUX_INDEX_BIT)
+			val = 1 << index;
 
-		if (mux->flags & CLK_MUX_INDEX_ONE)
-			index++;
+		if (flags & CLK_MUX_INDEX_ONE)
+			val++;
 	}
 
+	return val;
+}
+EXPORT_SYMBOL_GPL(clk_mux_index_to_val);
+
+static u8 clk_mux_get_parent(struct clk_hw *hw)
+{
+	struct clk_mux *mux = to_clk_mux(hw);
+	u32 val;
+
+	val = clk_readl(mux->reg) >> mux->shift;
+	val &= mux->mask;
+
+	return clk_mux_val_to_index(hw, mux->table, mux->flags, val);
+}
+
+static int clk_mux_set_parent(struct clk_hw *hw, u8 index)
+{
+	struct clk_mux *mux = to_clk_mux(hw);
+	u32 val = clk_mux_index_to_val(mux->table, mux->flags, index);
+	unsigned long flags = 0;
+	u32 reg;
+
 	if (mux->lock)
 		spin_lock_irqsave(mux->lock, flags);
 	else
 		__acquire(mux->lock);
 
 	if (mux->flags & CLK_MUX_HIWORD_MASK) {
-		val = mux->mask << (mux->shift + 16);
+		reg = mux->mask << (mux->shift + 16);
 	} else {
-		val = clk_readl(mux->reg);
-		val &= ~(mux->mask << mux->shift);
+		reg = clk_readl(mux->reg);
+		reg &= ~(mux->mask << mux->shift);
 	}
-	val |= index << mux->shift;
-	clk_writel(val, mux->reg);
+	val = val << mux->shift;
+	reg |= val;
+	clk_writel(reg, mux->reg);
 
 	if (mux->lock)
 		spin_unlock_irqrestore(mux->lock, flags);
diff --git a/include/linux/clk-provider.h b/include/linux/clk-provider.h
index 38861e75b017..cf3bf8aabced 100644
--- a/include/linux/clk-provider.h
+++ b/include/linux/clk-provider.h
@@ -514,6 +514,10 @@ struct clk_hw *clk_hw_register_mux_table(struct device *dev, const char *name,
 		void __iomem *reg, u8 shift, u32 mask,
 		u8 clk_mux_flags, u32 *table, spinlock_t *lock);
 
+int clk_mux_val_to_index(struct clk_hw *hw, u32 *table, unsigned int flags,
+			 unsigned int val);
+unsigned int clk_mux_index_to_val(u32 *table, unsigned int flags, u8 index);
+
 void clk_unregister_mux(struct clk *clk);
 void clk_hw_unregister_mux(struct clk_hw *hw);
 
-- 
2.14.3

^ permalink raw reply related	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2018-01-18 11:04 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-01-18 11:01 [PATCH 0/2] clk: add helpers for generic clocks Jerome Brunet
2018-01-18 11:01 ` [PATCH 1/2] clk: divider: export clk_div_mask() helper Jerome Brunet
2018-01-18 11:01 ` [PATCH 2/2] clk: mux: add helper function for index/value translation Jerome Brunet

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.