All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH V2 0/6] SPEAr: Move to common clock framework
@ 2012-04-19 16:28 Viresh Kumar
  2012-04-19 16:28 ` [PATCH V2 1/6] SPEAr: clk: Add VCO-PLL Synthesizer clock Viresh Kumar
                   ` (5 more replies)
  0 siblings, 6 replies; 16+ messages in thread
From: Viresh Kumar @ 2012-04-19 16:28 UTC (permalink / raw)
  To: linux-arm-kernel

Hello,

SPEAr now supports common clock framework. This patchset contains changes
related to this.

V1->V2:
- Removed first seven commits as they are directly picked by Mike into his next.
- Moved SPEAr clock support to drivers/clk/spear/ from arch/arm/
- Fixed error handling issues in spear clk drivers
- Rearranged patches to get git bisect working

This patchset is rebased over:
- clk: add a fixed factor clock - by Sascha Hauer
http://lists.infradead.org/pipermail/linux-arm-kernel/2012-March/090680.html

- common clk framework misc fixes - by Mike Turquette
https://lkml.org/lkml/2012/4/11/780

- V4: pinctrl: Add SPEAr pinctrl support
http://www.spinics.net/lists/arm-kernel/msg169387.html

- V3: SPEAr DT support updates
http://comments.gmane.org/gmane.linux.drivers.devicetree/14197


Viresh Kumar (6):
  SPEAr: clk: Add VCO-PLL Synthesizer clock
  SPEAr: clk: Add Auxiliary Synthesizer clock
  SPEAr: clk: Add Fractional Synthesizer clock
  SPEAr: clk: Add General Purpose Timer Synthesizer clock
  SPEAr: Call clk_prepare() before calling clk_enable
  SPEAr: Switch to common clock framework

 MAINTAINERS                                     |    4 +-
 arch/arm/Kconfig                                |    1 +
 arch/arm/mach-spear3xx/Makefile                 |    2 +-
 arch/arm/mach-spear3xx/clock.c                  |  892 --------------------
 arch/arm/mach-spear3xx/include/mach/generic.h   |    4 +-
 arch/arm/mach-spear3xx/include/mach/misc_regs.h |    2 +
 arch/arm/mach-spear3xx/include/mach/spear.h     |   13 +
 arch/arm/mach-spear3xx/spear300.c               |    1 -
 arch/arm/mach-spear3xx/spear310.c               |    1 -
 arch/arm/mach-spear3xx/spear320.c               |   12 +-
 arch/arm/mach-spear3xx/spear3xx.c               |    2 +
 arch/arm/mach-spear6xx/Makefile                 |    2 +-
 arch/arm/mach-spear6xx/clock.c                  |  789 ------------------
 arch/arm/mach-spear6xx/include/mach/misc_regs.h |    2 +
 arch/arm/mach-spear6xx/spear6xx.c               |    5 +-
 arch/arm/plat-spear/Makefile                    |    2 +-
 arch/arm/plat-spear/clock.c                     | 1005 -----------------------
 arch/arm/plat-spear/include/plat/clock.h        |  249 ------
 arch/arm/plat-spear/time.c                      |    8 +-
 drivers/clk/Makefile                            |    3 +
 drivers/clk/spear/Makefile                      |    8 +
 drivers/clk/spear/clk-aux-synth.c               |  187 +++++
 drivers/clk/spear/clk-frac-synth.c              |  156 ++++
 drivers/clk/spear/clk-gpt-synth.c               |  145 ++++
 drivers/clk/spear/clk-vco-pll.c                 |  346 ++++++++
 drivers/clk/spear/clk.h                         |  152 ++++
 drivers/clk/spear/spear3xx_clock.c              |  612 ++++++++++++++
 drivers/clk/spear/spear6xx_clock.c              |  342 ++++++++
 28 files changed, 1992 insertions(+), 2955 deletions(-)
 delete mode 100644 arch/arm/mach-spear3xx/clock.c
 delete mode 100644 arch/arm/mach-spear6xx/clock.c
 delete mode 100644 arch/arm/plat-spear/clock.c
 delete mode 100644 arch/arm/plat-spear/include/plat/clock.h
 create mode 100644 drivers/clk/spear/Makefile
 create mode 100644 drivers/clk/spear/clk-aux-synth.c
 create mode 100644 drivers/clk/spear/clk-frac-synth.c
 create mode 100644 drivers/clk/spear/clk-gpt-synth.c
 create mode 100644 drivers/clk/spear/clk-vco-pll.c
 create mode 100644 drivers/clk/spear/clk.h
 create mode 100644 drivers/clk/spear/spear3xx_clock.c
 create mode 100644 drivers/clk/spear/spear6xx_clock.c

-- 
1.7.9

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

* [PATCH V2 1/6] SPEAr: clk: Add VCO-PLL Synthesizer clock
  2012-04-19 16:28 [PATCH V2 0/6] SPEAr: Move to common clock framework Viresh Kumar
@ 2012-04-19 16:28 ` Viresh Kumar
  2012-04-23 19:15   ` Turquette, Mike
  2012-04-23 19:31   ` Turquette, Mike
  2012-04-19 16:28 ` [PATCH V2 2/6] SPEAr: clk: Add Auxiliary " Viresh Kumar
                   ` (4 subsequent siblings)
  5 siblings, 2 replies; 16+ messages in thread
From: Viresh Kumar @ 2012-04-19 16:28 UTC (permalink / raw)
  To: linux-arm-kernel

All SPEAr SoC's contain PLLs. Their Fout is derived based on following equations

- In normal mode
  vco = (2 * M[15:8] * Fin)/N

- In Dithered mode
  vco = (2 * M[15:0] * Fin)/(256 * N)

pll_rate = vco/2^p

vco and pll are very closely bound to each other,
"vco needs to program: mode, m & n" and "pll needs to program p",
both share common enable/disable logic and registers.

This patch adds in support for this type of clock.

Signed-off-by: Viresh Kumar <viresh.kumar@st.com>
---
 drivers/clk/Makefile            |    3 +
 drivers/clk/spear/Makefile      |    5 +
 drivers/clk/spear/clk-vco-pll.c |  346 +++++++++++++++++++++++++++++++++++++++
 drivers/clk/spear/clk.h         |   76 +++++++++
 4 files changed, 430 insertions(+), 0 deletions(-)
 create mode 100644 drivers/clk/spear/Makefile
 create mode 100644 drivers/clk/spear/clk-vco-pll.c
 create mode 100644 drivers/clk/spear/clk.h

diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile
index 24aa714..0f5e03d 100644
--- a/drivers/clk/Makefile
+++ b/drivers/clk/Makefile
@@ -2,3 +2,6 @@
 obj-$(CONFIG_CLKDEV_LOOKUP)	+= clkdev.o
 obj-$(CONFIG_COMMON_CLK)	+= clk.o clk-fixed-rate.o clk-gate.o \
 				   clk-mux.o clk-divider.o clk-fixed-factor.o
+
+# SoCs specific
+obj-$(CONFIG_PLAT_SPEAR)	+= spear/
diff --git a/drivers/clk/spear/Makefile b/drivers/clk/spear/Makefile
new file mode 100644
index 0000000..f59469f
--- /dev/null
+++ b/drivers/clk/spear/Makefile
@@ -0,0 +1,5 @@
+#
+# SPEAr Clock specific Makefile
+#
+
+obj-y	+= clk-vco-pll.o
diff --git a/drivers/clk/spear/clk-vco-pll.c b/drivers/clk/spear/clk-vco-pll.c
new file mode 100644
index 0000000..9efa30d
--- /dev/null
+++ b/drivers/clk/spear/clk-vco-pll.c
@@ -0,0 +1,346 @@
+/*
+ * Copyright (C) 2012 ST Microelectronics
+ * Viresh Kumar <viresh.kumar@st.com>
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2. This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ *
+ * VCO-PLL clock implementation
+ */
+
+#define pr_fmt(fmt) "clk-vco-pll: " fmt
+
+#include <linux/clk-provider.h>
+#include <linux/slab.h>
+#include <linux/io.h>
+#include <linux/err.h>
+#include "clk.h"
+
+/*
+ * DOC: VCO-PLL clock
+ *
+ * VCO and PLL rate are derived from following equations:
+ *
+ * In normal mode
+ * vco = (2 * M[15:8] * Fin)/N
+ *
+ * In Dithered mode
+ * vco = (2 * M[15:0] * Fin)/(256 * N)
+ *
+ * pll_rate = pll/2^p
+ *
+ * vco and pll are very closely bound to each other, "vco needs to program:
+ * mode, m & n" and "pll needs to program p", both share common enable/disable
+ * logic.
+ *
+ * clk_register_vco_pll() registers instances of both vco & pll.
+ * CLK_SET_RATE_PARENT flag is forced for pll, as it will always pass its
+ * set_rate to vco. A single rate table exists for both the clocks, which
+ * configures m, n and p.
+ */
+
+/* PLL_CTR register masks */
+#define PLL_MODE_NORMAL		0
+#define PLL_MODE_FRACTION	1
+#define PLL_MODE_DITH_DSM	2
+#define PLL_MODE_DITH_SSM	3
+#define PLL_MODE_MASK		3
+#define PLL_MODE_SHIFT		3
+#define PLL_ENABLE		2
+
+#define PLL_LOCK_SHIFT		0
+#define PLL_LOCK_MASK		1
+
+/* PLL FRQ register masks */
+#define PLL_NORM_FDBK_M_MASK	0xFF
+#define PLL_NORM_FDBK_M_SHIFT	24
+#define PLL_DITH_FDBK_M_MASK	0xFFFF
+#define PLL_DITH_FDBK_M_SHIFT	16
+#define PLL_DIV_P_MASK		0x7
+#define PLL_DIV_P_SHIFT		8
+#define PLL_DIV_N_MASK		0xFF
+#define PLL_DIV_N_SHIFT		0
+
+#define to_clk_vco(_hw) container_of(_hw, struct clk_vco, hw)
+#define to_clk_pll(_hw) container_of(_hw, struct clk_pll, hw)
+
+/* Calculates pll clk rate for specific value of mode, m, n and p */
+static unsigned long pll_calc_rate(struct pll_rate_tbl *rtbl,
+		unsigned long prate, int index, unsigned long *pll_rate)
+{
+	unsigned long rate = prate;
+	unsigned int mode;
+
+	mode = rtbl[index].mode ? 256 : 1;
+	rate = (((2 * rate / 10000) * rtbl[index].m) / (mode * rtbl[index].n));
+
+	if (pll_rate)
+		*pll_rate = (rate / (1 << rtbl[index].p)) * 10000;
+
+	return rate * 10000;
+}
+
+static long clk_pll_round_rate_index(struct clk_hw *hw, unsigned long drate,
+				unsigned long *prate, int *index)
+{
+	struct clk_pll *pll = to_clk_pll(hw);
+	unsigned long prev_rate, vco_prev_rate, rate = 0;
+	unsigned long vco_parent_rate =
+		__clk_get_rate(__clk_get_parent(__clk_get_parent(hw->clk)));
+
+	if (!prate) {
+		pr_err("%s: prate is must for pll clk\n", __func__);
+		return -EINVAL;
+	}
+
+	for (*index = 0; *index < pll->vco->rtbl_cnt; (*index)++) {
+		prev_rate = rate;
+		vco_prev_rate = *prate;
+		*prate = pll_calc_rate(pll->vco->rtbl, vco_parent_rate, *index,
+				&rate);
+		if (drate < rate) {
+			/* previous clock was best */
+			if (*index) {
+				rate = prev_rate;
+				*prate = vco_prev_rate;
+				(*index)--;
+			}
+			break;
+		}
+	}
+
+	return rate;
+}
+
+static long clk_pll_round_rate(struct clk_hw *hw, unsigned long drate,
+				unsigned long *prate)
+{
+	int unused;
+
+	return clk_pll_round_rate_index(hw, drate, prate, &unused);
+}
+
+static unsigned long clk_pll_recalc_rate(struct clk_hw *hw, unsigned long
+		parent_rate)
+{
+	struct clk_pll *pll = to_clk_pll(hw);
+	unsigned long flags = 0;
+	unsigned int p;
+
+	if (pll->vco->lock)
+		spin_lock_irqsave(pll->vco->lock, flags);
+
+	p = readl_relaxed(pll->vco->cfg_reg);
+
+	if (pll->vco->lock)
+		spin_unlock_irqrestore(pll->vco->lock, flags);
+
+	p = (p >> PLL_DIV_P_SHIFT) & PLL_DIV_P_MASK;
+
+	return parent_rate / (1 << p);
+}
+
+static int clk_pll_set_rate(struct clk_hw *hw, unsigned long drate)
+{
+	struct clk_pll *pll = to_clk_pll(hw);
+	struct pll_rate_tbl *rtbl = pll->vco->rtbl;
+	unsigned long flags = 0, val;
+	int i;
+
+	clk_pll_round_rate_index(hw, drate, NULL, &i);
+
+	if (pll->vco->lock)
+		spin_lock_irqsave(pll->vco->lock, flags);
+
+	val = readl_relaxed(pll->vco->cfg_reg);
+	val &= ~(PLL_DIV_P_MASK << PLL_DIV_P_SHIFT);
+	val |= (rtbl[i].p & PLL_DIV_P_MASK) << PLL_DIV_P_SHIFT;
+	writel_relaxed(val, pll->vco->cfg_reg);
+
+	if (pll->vco->lock)
+		spin_unlock_irqrestore(pll->vco->lock, flags);
+
+	return 0;
+}
+
+static struct clk_ops clk_pll_ops = {
+	.recalc_rate = clk_pll_recalc_rate,
+	.round_rate = clk_pll_round_rate,
+	.set_rate = clk_pll_set_rate,
+};
+
+static inline unsigned long vco_calc_rate(struct clk_hw *hw,
+		unsigned long prate, int index)
+{
+	struct clk_vco *vco = to_clk_vco(hw);
+
+	return pll_calc_rate(vco->rtbl, prate, index, NULL);
+}
+
+static long clk_vco_round_rate(struct clk_hw *hw, unsigned long drate,
+		unsigned long *prate)
+{
+	struct clk_vco *vco = to_clk_vco(hw);
+	int unused;
+
+	return clk_round_rate_index(hw, drate, vco_calc_rate, vco->rtbl_cnt,
+			&unused);
+}
+
+static unsigned long clk_vco_recalc_rate(struct clk_hw *hw,
+		unsigned long parent_rate)
+{
+	struct clk_vco *vco = to_clk_vco(hw);
+	unsigned long flags = 0;
+	unsigned int num = 2, den = 0, val, mode = 0;
+
+	if (vco->lock)
+		spin_lock_irqsave(vco->lock, flags);
+
+	mode = (readl_relaxed(vco->mode_reg) >> PLL_MODE_SHIFT) & PLL_MODE_MASK;
+
+	val = readl_relaxed(vco->cfg_reg);
+
+	if (vco->lock)
+		spin_unlock_irqrestore(vco->lock, flags);
+
+	den = (val >> PLL_DIV_N_SHIFT) & PLL_DIV_N_MASK;
+
+	/* calculate numerator & denominator */
+	if (!mode) {
+		/* Normal mode */
+		num *= (val >> PLL_NORM_FDBK_M_SHIFT) & PLL_NORM_FDBK_M_MASK;
+	} else {
+		/* Dithered mode */
+		num *= (val >> PLL_DITH_FDBK_M_SHIFT) & PLL_DITH_FDBK_M_MASK;
+		den *= 256;
+	}
+
+	if (!den) {
+		WARN(1, "%s: denominator can't be zero\n", __func__);
+		return 0;
+	}
+
+	return (((parent_rate / 10000) * num) / den) * 10000;
+}
+
+/* Configures new clock rate of vco */
+static int clk_vco_set_rate(struct clk_hw *hw, unsigned long drate)
+{
+	struct clk_vco *vco = to_clk_vco(hw);
+	struct pll_rate_tbl *rtbl = vco->rtbl;
+	unsigned long flags = 0, val;
+	int i;
+
+	clk_round_rate_index(hw, drate, vco_calc_rate, vco->rtbl_cnt, &i);
+
+	if (vco->lock)
+		spin_lock_irqsave(vco->lock, flags);
+
+	val = readl_relaxed(vco->mode_reg);
+	val &= ~(PLL_MODE_MASK << PLL_MODE_SHIFT);
+	val |= (rtbl[i].mode & PLL_MODE_MASK) << PLL_MODE_SHIFT;
+	writel_relaxed(val, vco->mode_reg);
+
+	val = readl_relaxed(vco->cfg_reg);
+	val &= ~(PLL_DIV_N_MASK << PLL_DIV_N_SHIFT);
+	val |= (rtbl[i].n & PLL_DIV_N_MASK) << PLL_DIV_N_SHIFT;
+
+	val &= ~(PLL_DITH_FDBK_M_MASK << PLL_DITH_FDBK_M_SHIFT);
+	if (rtbl[i].mode)
+		val |= (rtbl[i].m & PLL_DITH_FDBK_M_MASK) <<
+			PLL_DITH_FDBK_M_SHIFT;
+	else
+		val |= (rtbl[i].m & PLL_NORM_FDBK_M_MASK) <<
+			PLL_NORM_FDBK_M_SHIFT;
+
+	writel_relaxed(val, vco->cfg_reg);
+
+	if (vco->lock)
+		spin_unlock_irqrestore(vco->lock, flags);
+
+	return 0;
+}
+
+static struct clk_ops clk_vco_ops = {
+	.recalc_rate = clk_vco_recalc_rate,
+	.round_rate = clk_vco_round_rate,
+	.set_rate = clk_vco_set_rate,
+};
+
+struct clk *clk_register_vco_pll(const char *vco_name, const char *pll_name,
+		const char *vco_gate_name, const char *parent_name,
+		unsigned long flags, void __iomem *mode_reg, void __iomem
+		*cfg_reg, struct pll_rate_tbl *rtbl, u8 rtbl_cnt,
+		spinlock_t *lock, struct clk **pll_clk,
+		struct clk **vco_gate_clk)
+{
+	struct clk_vco *vco;
+	struct clk_pll *pll;
+	struct clk *vco_clk, *tpll_clk, *tvco_gate_clk;
+	const char **vco_parent_name;
+
+	if (!vco_name || !pll_name || !parent_name || !mode_reg || !cfg_reg ||
+			!rtbl || !rtbl_cnt) {
+		pr_err("Invalid arguments passed");
+		return ERR_PTR(-EINVAL);
+	}
+
+	vco = kzalloc(sizeof(*vco), GFP_KERNEL);
+	if (!vco) {
+		pr_err("could not allocate vco clk\n");
+		return ERR_PTR(-ENOMEM);
+	}
+
+	pll = kzalloc(sizeof(*pll), GFP_KERNEL);
+	if (!pll) {
+		pr_err("could not allocate pll clk\n");
+		goto free_vco;
+	}
+
+	/* struct clk_vco assignments */
+	vco->mode_reg = mode_reg;
+	vco->cfg_reg = cfg_reg;
+	vco->rtbl = rtbl;
+	vco->rtbl_cnt = rtbl_cnt;
+	vco->lock = lock;
+	pll->vco = vco;
+
+	if (vco_gate_name) {
+		tvco_gate_clk = clk_register_gate(NULL, vco_gate_name,
+				parent_name, 0, mode_reg, PLL_ENABLE, 0, lock);
+		if (IS_ERR_OR_NULL(tvco_gate_clk))
+			goto free_pll;
+
+		if (vco_gate_clk)
+			*vco_gate_clk = tvco_gate_clk;
+		vco_parent_name = &vco_gate_name;
+	} else {
+		vco_parent_name = &parent_name;
+	}
+
+	vco_clk = clk_register(NULL, vco_name, &clk_vco_ops, &vco->hw,
+			vco_parent_name, 1, flags);
+	if (IS_ERR_OR_NULL(vco_clk))
+		goto free_pll;
+
+	tpll_clk = clk_register(NULL, pll_name, &clk_pll_ops, &pll->hw,
+			&vco_name, 1, CLK_SET_RATE_PARENT);
+	if (IS_ERR_OR_NULL(tpll_clk))
+		goto free_pll;
+
+	if (pll_clk)
+		*pll_clk = tpll_clk;
+
+	return vco_clk;
+
+free_pll:
+	kfree(pll);
+free_vco:
+	kfree(vco);
+
+	pr_err("Failed to register vco pll clock\n");
+
+	return ERR_PTR(-ENOMEM);
+}
diff --git a/drivers/clk/spear/clk.h b/drivers/clk/spear/clk.h
new file mode 100644
index 0000000..a66024e
--- /dev/null
+++ b/drivers/clk/spear/clk.h
@@ -0,0 +1,76 @@
+/*
+ * Clock framework definitions for SPEAr platform
+ *
+ * Copyright (C) 2012 ST Microelectronics
+ * Viresh Kumar <viresh.kumar@st.com>
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2. This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#ifndef __PLAT_CLOCK_H
+#define __PLAT_CLOCK_H
+
+#include <linux/clk-provider.h>
+#include <linux/spinlock_types.h>
+#include <linux/types.h>
+
+/* VCO-PLL clk */
+struct pll_rate_tbl {
+	u8 mode;
+	u16 m;
+	u8 n;
+	u8 p;
+};
+
+struct clk_vco {
+	struct			clk_hw hw;
+	void __iomem		*mode_reg;
+	void __iomem		*cfg_reg;
+	struct pll_rate_tbl	*rtbl;
+	u8			rtbl_cnt;
+	spinlock_t		*lock;
+};
+
+struct clk_pll {
+	struct			clk_hw hw;
+	struct clk_vco		*vco;
+	const char		*parent[1];
+	spinlock_t		*lock;
+};
+
+typedef unsigned long (*clk_calc_rate)(struct clk_hw *hw, unsigned long prate,
+		int index);
+
+/* clk register routines */
+struct clk *clk_register_vco_pll(const char *vco_name, const char *pll_name,
+		const char *vco_gate_name, const char *parent_name,
+		unsigned long flags, void __iomem *mode_reg, void __iomem
+		*cfg_reg, struct pll_rate_tbl *rtbl, u8 rtbl_cnt,
+		spinlock_t *lock, struct clk **pll_clk,
+		struct clk **vco_gate_clk);
+
+static inline long clk_round_rate_index(struct clk_hw *hw, unsigned long drate,
+		clk_calc_rate calc_rate, u8 rtbl_cnt, int *index)
+{
+	unsigned long prev_rate, rate = 0;
+	unsigned long parent_rate = __clk_get_rate(__clk_get_parent(hw->clk));
+
+	for (*index = 0; *index < rtbl_cnt; (*index)++) {
+		prev_rate = rate;
+		rate = calc_rate(hw, parent_rate, *index);
+		if (drate < rate) {
+			/* previous clock was best */
+			if (*index) {
+				rate = prev_rate;
+				(*index)--;
+			}
+			break;
+		}
+	}
+
+	return rate;
+}
+
+#endif /* __PLAT_CLOCK_H */
-- 
1.7.9

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

* [PATCH V2 2/6] SPEAr: clk: Add Auxiliary Synthesizer clock
  2012-04-19 16:28 [PATCH V2 0/6] SPEAr: Move to common clock framework Viresh Kumar
  2012-04-19 16:28 ` [PATCH V2 1/6] SPEAr: clk: Add VCO-PLL Synthesizer clock Viresh Kumar
@ 2012-04-19 16:28 ` Viresh Kumar
  2012-04-23 12:33   ` viresh kumar
  2012-04-19 16:28 ` [PATCH V2 3/6] SPEAr: clk: Add Fractional " Viresh Kumar
                   ` (3 subsequent siblings)
  5 siblings, 1 reply; 16+ messages in thread
From: Viresh Kumar @ 2012-04-19 16:28 UTC (permalink / raw)
  To: linux-arm-kernel

All SPEAr SoC's contain Auxiliary Synthesizers. Their Fout is derived based on
values of eq, x and y.

Fout from synthesizer can be given from two equations:
Fout1 = (Fin * X/Y)/2		EQ1
Fout2 = Fin * X/Y		EQ2

This patch adds in support for this type of clock.

Signed-off-by: Viresh Kumar <viresh.kumar@st.com>
---
 drivers/clk/spear/Makefile        |    2 +-
 drivers/clk/spear/clk-aux-synth.c |  187 +++++++++++++++++++++++++++++++++++++
 drivers/clk/spear/clk.h           |   43 +++++++++
 3 files changed, 231 insertions(+), 1 deletions(-)
 create mode 100644 drivers/clk/spear/clk-aux-synth.c

diff --git a/drivers/clk/spear/Makefile b/drivers/clk/spear/Makefile
index f59469f..407a8e0 100644
--- a/drivers/clk/spear/Makefile
+++ b/drivers/clk/spear/Makefile
@@ -2,4 +2,4 @@
 # SPEAr Clock specific Makefile
 #
 
-obj-y	+= clk-vco-pll.o
+obj-y	+= clk-aux-synth.o clk-vco-pll.o
diff --git a/drivers/clk/spear/clk-aux-synth.c b/drivers/clk/spear/clk-aux-synth.c
new file mode 100644
index 0000000..1a7ab7d
--- /dev/null
+++ b/drivers/clk/spear/clk-aux-synth.c
@@ -0,0 +1,187 @@
+/*
+ * Copyright (C) 2012 ST Microelectronics
+ * Viresh Kumar <viresh.kumar@st.com>
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2. This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ *
+ * Auxiliary Synthesizer clock implementation
+ */
+
+#define pr_fmt(fmt) "clk-aux-synth: " fmt
+
+#include <linux/clk-provider.h>
+#include <linux/slab.h>
+#include <linux/io.h>
+#include <linux/err.h>
+#include "clk.h"
+
+/*
+ * DOC: Auxiliary Synthesizer clock
+ *
+ * Aux synth gives rate for different values of eq, x and y
+ *
+ * Fout from synthesizer can be given from two equations:
+ * Fout1 = (Fin * X/Y)/2		EQ1
+ * Fout2 = Fin * X/Y			EQ2
+ */
+
+#define to_clk_aux(_hw) container_of(_hw, struct clk_aux, hw)
+
+static struct aux_clk_masks default_aux_masks = {
+	.eq_sel_mask = AUX_EQ_SEL_MASK,
+	.eq_sel_shift = AUX_EQ_SEL_SHIFT,
+	.eq1_mask = AUX_EQ1_SEL,
+	.eq2_mask = AUX_EQ2_SEL,
+	.xscale_sel_mask = AUX_XSCALE_MASK,
+	.xscale_sel_shift = AUX_XSCALE_SHIFT,
+	.yscale_sel_mask = AUX_YSCALE_MASK,
+	.yscale_sel_shift = AUX_YSCALE_SHIFT,
+	.enable_bit = AUX_SYNT_ENB,
+};
+
+static unsigned long aux_calc_rate(struct clk_hw *hw, unsigned long prate,
+		int index)
+{
+	struct clk_aux *aux = to_clk_aux(hw);
+	struct aux_rate_tbl *rtbl = aux->rtbl;
+	u8 eq = rtbl[index].eq ? 1 : 2;
+
+	return (((prate / 10000) * rtbl[index].xscale) /
+			(rtbl[index].yscale * eq)) * 10000;
+}
+
+static long clk_aux_round_rate(struct clk_hw *hw, unsigned long drate,
+		unsigned long *prate)
+{
+	struct clk_aux *aux = to_clk_aux(hw);
+	int unused;
+
+	return clk_round_rate_index(hw, drate, aux_calc_rate, aux->rtbl_cnt,
+			&unused);
+}
+
+static unsigned long clk_aux_recalc_rate(struct clk_hw *hw,
+		unsigned long parent_rate)
+{
+	struct clk_aux *aux = to_clk_aux(hw);
+	unsigned int num = 1, den = 1, val, eqn;
+	unsigned long flags = 0;
+
+	if (aux->lock)
+		spin_lock_irqsave(aux->lock, flags);
+
+	val = readl_relaxed(aux->reg);
+
+	if (aux->lock)
+		spin_unlock_irqrestore(aux->lock, flags);
+
+	eqn = (val >> aux->masks->eq_sel_shift) & aux->masks->eq_sel_mask;
+	if (eqn == aux->masks->eq1_mask)
+		den = 2;
+
+	/* calculate numerator */
+	num = (val >> aux->masks->xscale_sel_shift) &
+		aux->masks->xscale_sel_mask;
+
+	/* calculate denominator */
+	den *= (val >> aux->masks->yscale_sel_shift) &
+		aux->masks->yscale_sel_mask;
+
+	if (!den)
+		return 0;
+
+	return (((parent_rate / 10000) * num) / den) * 10000;
+}
+
+/* Configures new clock rate of aux */
+static int clk_aux_set_rate(struct clk_hw *hw, unsigned long drate)
+{
+	struct clk_aux *aux = to_clk_aux(hw);
+	struct aux_rate_tbl *rtbl = aux->rtbl;
+	unsigned long val, flags = 0;
+	int i;
+
+	clk_round_rate_index(hw, drate, aux_calc_rate, aux->rtbl_cnt, &i);
+
+	if (aux->lock)
+		spin_lock_irqsave(aux->lock, flags);
+
+	val = readl_relaxed(aux->reg) &
+		~(aux->masks->eq_sel_mask << aux->masks->eq_sel_shift);
+	val |= (rtbl[i].eq & aux->masks->eq_sel_mask) <<
+		aux->masks->eq_sel_shift;
+	val &= ~(aux->masks->xscale_sel_mask << aux->masks->xscale_sel_shift);
+	val |= (rtbl[i].xscale & aux->masks->xscale_sel_mask) <<
+		aux->masks->xscale_sel_shift;
+	val &= ~(aux->masks->yscale_sel_mask << aux->masks->yscale_sel_shift);
+	val |= (rtbl[i].yscale & aux->masks->yscale_sel_mask) <<
+		aux->masks->yscale_sel_shift;
+	writel_relaxed(val, aux->reg);
+
+	if (aux->lock)
+		spin_unlock_irqrestore(aux->lock, flags);
+
+	return 0;
+}
+
+static struct clk_ops clk_aux_ops = {
+	.recalc_rate = clk_aux_recalc_rate,
+	.round_rate = clk_aux_round_rate,
+	.set_rate = clk_aux_set_rate,
+};
+
+struct clk *clk_register_aux(const char *aux_name, const char *gate_name,
+		const char *parent_name, unsigned long flags, void __iomem *reg,
+		struct aux_clk_masks *masks, struct aux_rate_tbl *rtbl,
+		u8 rtbl_cnt, spinlock_t *lock, struct clk **gate_clk)
+{
+	struct clk_aux *aux;
+	struct clk *clk;
+
+	if (!aux_name || !parent_name || !reg || !rtbl || !rtbl_cnt) {
+		pr_err("Invalid arguments passed");
+		return ERR_PTR(-EINVAL);
+	}
+
+	aux = kzalloc(sizeof(*aux), GFP_KERNEL);
+	if (!aux) {
+		pr_err("could not allocate aux clk\n");
+		return ERR_PTR(-ENOMEM);
+	}
+
+	/* struct clk_aux assignments */
+	if (!masks)
+		aux->masks = &default_aux_masks;
+
+	aux->reg = reg;
+	aux->rtbl = rtbl;
+	aux->rtbl_cnt = rtbl_cnt;
+	aux->lock = lock;
+
+	clk = clk_register(NULL, aux_name, &clk_aux_ops, &aux->hw, &parent_name,
+			1, flags);
+	if (IS_ERR_OR_NULL(clk))
+		goto free_aux;
+
+	if (gate_name) {
+		struct clk *tgate_clk;
+
+		tgate_clk = clk_register_gate(NULL, gate_name, aux_name, 0, reg,
+				aux->masks->enable_bit, 0, lock);
+		if (IS_ERR_OR_NULL(tgate_clk))
+			goto free_aux;
+
+		if (gate_clk)
+			*gate_clk = tgate_clk;
+	}
+
+	return clk;
+
+free_aux:
+	kfree(aux);
+	pr_err("clk register failed\n");
+
+	return NULL;
+}
diff --git a/drivers/clk/spear/clk.h b/drivers/clk/spear/clk.h
index a66024e..5e279ee 100644
--- a/drivers/clk/spear/clk.h
+++ b/drivers/clk/spear/clk.h
@@ -16,6 +16,45 @@
 #include <linux/spinlock_types.h>
 #include <linux/types.h>
 
+/* Auxiliary Synth clk */
+/* Default masks */
+#define AUX_EQ_SEL_SHIFT	30
+#define AUX_EQ_SEL_MASK		1
+#define AUX_EQ1_SEL		0
+#define AUX_EQ2_SEL		1
+#define AUX_XSCALE_SHIFT	16
+#define AUX_XSCALE_MASK		0xFFF
+#define AUX_YSCALE_SHIFT	0
+#define AUX_YSCALE_MASK		0xFFF
+#define AUX_SYNT_ENB		31
+
+struct aux_clk_masks {
+	u32 eq_sel_mask;
+	u32 eq_sel_shift;
+	u32 eq1_mask;
+	u32 eq2_mask;
+	u32 xscale_sel_mask;
+	u32 xscale_sel_shift;
+	u32 yscale_sel_mask;
+	u32 yscale_sel_shift;
+	u32 enable_bit;
+};
+
+struct aux_rate_tbl {
+	u16 xscale;
+	u16 yscale;
+	u8 eq;
+};
+
+struct clk_aux {
+	struct			clk_hw hw;
+	void __iomem		*reg;
+	struct aux_clk_masks	*masks;
+	struct aux_rate_tbl	*rtbl;
+	u8			rtbl_cnt;
+	spinlock_t		*lock;
+};
+
 /* VCO-PLL clk */
 struct pll_rate_tbl {
 	u8 mode;
@@ -44,6 +83,10 @@ typedef unsigned long (*clk_calc_rate)(struct clk_hw *hw, unsigned long prate,
 		int index);
 
 /* clk register routines */
+struct clk *clk_register_aux(const char *aux_name, const char *gate_name,
+		const char *parent_name, unsigned long flags, void __iomem *reg,
+		struct aux_clk_masks *masks, struct aux_rate_tbl *rtbl,
+		u8 rtbl_cnt, spinlock_t *lock, struct clk **gate_clk);
 struct clk *clk_register_vco_pll(const char *vco_name, const char *pll_name,
 		const char *vco_gate_name, const char *parent_name,
 		unsigned long flags, void __iomem *mode_reg, void __iomem
-- 
1.7.9

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

* [PATCH V2 3/6] SPEAr: clk: Add Fractional Synthesizer clock
  2012-04-19 16:28 [PATCH V2 0/6] SPEAr: Move to common clock framework Viresh Kumar
  2012-04-19 16:28 ` [PATCH V2 1/6] SPEAr: clk: Add VCO-PLL Synthesizer clock Viresh Kumar
  2012-04-19 16:28 ` [PATCH V2 2/6] SPEAr: clk: Add Auxiliary " Viresh Kumar
@ 2012-04-19 16:28 ` Viresh Kumar
  2012-04-19 16:28 ` [PATCH V2 4/6] SPEAr: clk: Add General Purpose Timer " Viresh Kumar
                   ` (2 subsequent siblings)
  5 siblings, 0 replies; 16+ messages in thread
From: Viresh Kumar @ 2012-04-19 16:28 UTC (permalink / raw)
  To: linux-arm-kernel

All SPEAr SoC's contain Fractional Synthesizers. Their Fout is derived from
following equations:

Fout = Fin / (2 * div) (division factor)
div is 17 bits:-
     0-13 (fractional part)
     14-16 (integer part)
     div is (16-14 bits).(13-0 bits) (in binary)

     Fout = Fin/(2 * div)
     Fout = ((Fin / 10000)/(2 * div)) * 10000
     Fout = (2^14 * (Fin / 10000)/(2^14 * (2 * div))) * 10000
     Fout = (((Fin / 10000) << 14)/(2 * (div << 14))) * 10000

div << 14 is simply 17 bit value written at register.

This patch adds in support for this type of clock.

Signed-off-by: Viresh Kumar <viresh.kumar@st.com>
---
 drivers/clk/spear/Makefile         |    2 +-
 drivers/clk/spear/clk-frac-synth.c |  156 ++++++++++++++++++++++++++++++++++++
 drivers/clk/spear/clk.h            |   16 ++++
 3 files changed, 173 insertions(+), 1 deletions(-)
 create mode 100644 drivers/clk/spear/clk-frac-synth.c

diff --git a/drivers/clk/spear/Makefile b/drivers/clk/spear/Makefile
index 407a8e0..3c722e0 100644
--- a/drivers/clk/spear/Makefile
+++ b/drivers/clk/spear/Makefile
@@ -2,4 +2,4 @@
 # SPEAr Clock specific Makefile
 #
 
-obj-y	+= clk-aux-synth.o clk-vco-pll.o
+obj-y	+= clk-aux-synth.o clk-frac-synth.o clk-vco-pll.o
diff --git a/drivers/clk/spear/clk-frac-synth.c b/drivers/clk/spear/clk-frac-synth.c
new file mode 100644
index 0000000..c6ccdab
--- /dev/null
+++ b/drivers/clk/spear/clk-frac-synth.c
@@ -0,0 +1,156 @@
+/*
+ * Copyright (C) 2012 ST Microelectronics
+ * Viresh Kumar <viresh.kumar@st.com>
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2. This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ *
+ * Fractional Synthesizer clock implementation
+ */
+
+#define pr_fmt(fmt) "clk-frac-synth: " fmt
+
+#include <linux/clk-provider.h>
+#include <linux/slab.h>
+#include <linux/io.h>
+#include <linux/err.h>
+#include "clk.h"
+
+#define DIV_FACTOR_MASK		0x1FFFF
+
+/*
+ * DOC: Fractional Synthesizer clock
+ *
+ * Fout from synthesizer can be given from below equation:
+ *
+ * Fout= Fin/2*div (division factor)
+ * div is 17 bits:-
+ *	0-13 (fractional part)
+ *	14-16 (integer part)
+ *	div is (16-14 bits).(13-0 bits) (in binary)
+ *
+ *	Fout = Fin/(2 * div)
+ *	Fout = ((Fin / 10000)/(2 * div)) * 10000
+ *	Fout = (2^14 * (Fin / 10000)/(2^14 * (2 * div))) * 10000
+ *	Fout = (((Fin / 10000) << 14)/(2 * (div << 14))) * 10000
+ *
+ * div << 14 simply 17 bit value written@register.
+ * Max error due to scaling down by 10000 is 10 KHz
+ */
+
+#define to_clk_frac(_hw) container_of(_hw, struct clk_frac, hw)
+
+static unsigned long frac_calc_rate(struct clk_hw *hw, unsigned long prate,
+		int index)
+{
+	struct clk_frac *frac = to_clk_frac(hw);
+	struct frac_rate_tbl *rtbl = frac->rtbl;
+
+	prate /= 10000;
+	prate <<= 14;
+	prate /= (2 * rtbl[index].div);
+	prate *= 10000;
+
+	return prate;
+}
+
+static long clk_frac_round_rate(struct clk_hw *hw, unsigned long drate,
+		unsigned long *prate)
+{
+	struct clk_frac *frac = to_clk_frac(hw);
+	int unused;
+
+	return clk_round_rate_index(hw, drate, frac_calc_rate, frac->rtbl_cnt,
+			&unused);
+}
+
+static unsigned long clk_frac_recalc_rate(struct clk_hw *hw,
+		unsigned long parent_rate)
+{
+	struct clk_frac *frac = to_clk_frac(hw);
+	unsigned long flags = 0;
+	unsigned int div = 1, val;
+
+	if (frac->lock)
+		spin_lock_irqsave(frac->lock, flags);
+
+	val = readl_relaxed(frac->reg);
+
+	if (frac->lock)
+		spin_unlock_irqrestore(frac->lock, flags);
+
+	div = val & DIV_FACTOR_MASK;
+
+	if (!div)
+		return 0;
+
+	parent_rate = parent_rate / 10000;
+
+	parent_rate = (parent_rate << 14) / (2 * div);
+	return parent_rate * 10000;
+}
+
+/* Configures new clock rate of frac */
+static int clk_frac_set_rate(struct clk_hw *hw, unsigned long drate)
+{
+	struct clk_frac *frac = to_clk_frac(hw);
+	struct frac_rate_tbl *rtbl = frac->rtbl;
+	unsigned long flags = 0, val;
+	int i;
+
+	clk_round_rate_index(hw, drate, frac_calc_rate, frac->rtbl_cnt, &i);
+
+	if (frac->lock)
+		spin_lock_irqsave(frac->lock, flags);
+
+	val = readl_relaxed(frac->reg) & ~DIV_FACTOR_MASK;
+	val |= rtbl[i].div & DIV_FACTOR_MASK;
+	writel_relaxed(val, frac->reg);
+
+	if (frac->lock)
+		spin_unlock_irqrestore(frac->lock, flags);
+
+	return 0;
+}
+
+struct clk_ops clk_frac_ops = {
+	.recalc_rate = clk_frac_recalc_rate,
+	.round_rate = clk_frac_round_rate,
+	.set_rate = clk_frac_set_rate,
+};
+
+struct clk *clk_register_frac(const char *name, const char *parent_name,
+		unsigned long flags, void __iomem *reg,
+		struct frac_rate_tbl *rtbl, u8 rtbl_cnt, spinlock_t *lock)
+{
+	struct clk_frac *frac;
+	struct clk *clk;
+
+	if (!name || !parent_name || !reg || !rtbl || !rtbl_cnt) {
+		pr_err("Invalid arguments passed");
+		return ERR_PTR(-EINVAL);
+	}
+
+	frac = kzalloc(sizeof(*frac), GFP_KERNEL);
+	if (!frac) {
+		pr_err("could not allocate frac clk\n");
+		return ERR_PTR(-ENOMEM);
+	}
+
+	/* struct clk_frac assignments */
+	frac->reg = reg;
+	frac->rtbl = rtbl;
+	frac->rtbl_cnt = rtbl_cnt;
+	frac->lock = lock;
+
+	clk = clk_register(NULL, name, &clk_frac_ops, &frac->hw, &parent_name,
+			1, flags);
+	if (!IS_ERR_OR_NULL(clk))
+		return clk;
+
+	pr_err("clk register failed\n");
+	kfree(frac);
+
+	return NULL;
+}
diff --git a/drivers/clk/spear/clk.h b/drivers/clk/spear/clk.h
index 5e279ee..e67e6cf 100644
--- a/drivers/clk/spear/clk.h
+++ b/drivers/clk/spear/clk.h
@@ -55,6 +55,19 @@ struct clk_aux {
 	spinlock_t		*lock;
 };
 
+/* Fractional Synth clk */
+struct frac_rate_tbl {
+	u32 div;
+};
+
+struct clk_frac {
+	struct			clk_hw hw;
+	void __iomem		*reg;
+	struct frac_rate_tbl	*rtbl;
+	u8			rtbl_cnt;
+	spinlock_t		*lock;
+};
+
 /* VCO-PLL clk */
 struct pll_rate_tbl {
 	u8 mode;
@@ -87,6 +100,9 @@ struct clk *clk_register_aux(const char *aux_name, const char *gate_name,
 		const char *parent_name, unsigned long flags, void __iomem *reg,
 		struct aux_clk_masks *masks, struct aux_rate_tbl *rtbl,
 		u8 rtbl_cnt, spinlock_t *lock, struct clk **gate_clk);
+struct clk *clk_register_frac(const char *name, const char *parent_name,
+		unsigned long flags, void __iomem *reg,
+		struct frac_rate_tbl *rtbl, u8 rtbl_cnt, spinlock_t *lock);
 struct clk *clk_register_vco_pll(const char *vco_name, const char *pll_name,
 		const char *vco_gate_name, const char *parent_name,
 		unsigned long flags, void __iomem *mode_reg, void __iomem
-- 
1.7.9

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

* [PATCH V2 4/6] SPEAr: clk: Add General Purpose Timer Synthesizer clock
  2012-04-19 16:28 [PATCH V2 0/6] SPEAr: Move to common clock framework Viresh Kumar
                   ` (2 preceding siblings ...)
  2012-04-19 16:28 ` [PATCH V2 3/6] SPEAr: clk: Add Fractional " Viresh Kumar
@ 2012-04-19 16:28 ` Viresh Kumar
  2012-04-19 16:28 ` [PATCH V2 5/6] SPEAr: Call clk_prepare() before calling clk_enable Viresh Kumar
       [not found] ` <ddade82f0666c3186b8a694aa2b79acd3f7e5d50.1334852395.git.viresh.kumar@st.com>
  5 siblings, 0 replies; 16+ messages in thread
From: Viresh Kumar @ 2012-04-19 16:28 UTC (permalink / raw)
  To: linux-arm-kernel

All SPEAr SoC's contain GPT Synthesizers. Their Fout is derived from
following equations:

Fout= Fin/((2 ^ (N+1)) * (M+1))

This patch adds in support for this type of clock.

Signed-off-by: Viresh Kumar <viresh.kumar@st.com>
---
 drivers/clk/spear/Makefile        |    2 +-
 drivers/clk/spear/clk-gpt-synth.c |  145 +++++++++++++++++++++++++++++++++++++
 drivers/clk/spear/clk.h           |   17 +++++
 3 files changed, 163 insertions(+), 1 deletions(-)
 create mode 100644 drivers/clk/spear/clk-gpt-synth.c

diff --git a/drivers/clk/spear/Makefile b/drivers/clk/spear/Makefile
index 3c722e0..389a431 100644
--- a/drivers/clk/spear/Makefile
+++ b/drivers/clk/spear/Makefile
@@ -2,4 +2,4 @@
 # SPEAr Clock specific Makefile
 #
 
-obj-y	+= clk-aux-synth.o clk-frac-synth.o clk-vco-pll.o
+obj-y	+= clk-aux-synth.o clk-frac-synth.o clk-gpt-synth.o clk-vco-pll.o
diff --git a/drivers/clk/spear/clk-gpt-synth.c b/drivers/clk/spear/clk-gpt-synth.c
new file mode 100644
index 0000000..514539c
--- /dev/null
+++ b/drivers/clk/spear/clk-gpt-synth.c
@@ -0,0 +1,145 @@
+/*
+ * Copyright (C) 2012 ST Microelectronics
+ * Viresh Kumar <viresh.kumar@st.com>
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2. This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ *
+ * General Purpose Timer Synthesizer clock implementation
+ */
+
+#define pr_fmt(fmt) "clk-gpt-synth: " fmt
+
+#include <linux/clk-provider.h>
+#include <linux/slab.h>
+#include <linux/io.h>
+#include <linux/err.h>
+#include "clk.h"
+
+#define GPT_MSCALE_MASK		0xFFF
+#define GPT_NSCALE_SHIFT	12
+#define GPT_NSCALE_MASK		0xF
+
+/*
+ * DOC: General Purpose Timer Synthesizer clock
+ *
+ * Calculates gpt synth clk rate for different values of mscale and nscale
+ *
+ * Fout= Fin/((2 ^ (N+1)) * (M+1))
+ */
+
+#define to_clk_gpt(_hw) container_of(_hw, struct clk_gpt, hw)
+
+static unsigned long gpt_calc_rate(struct clk_hw *hw, unsigned long prate,
+		int index)
+{
+	struct clk_gpt *gpt = to_clk_gpt(hw);
+	struct gpt_rate_tbl *rtbl = gpt->rtbl;
+
+	prate /= ((1 << (rtbl[index].nscale + 1)) * (rtbl[index].mscale + 1));
+
+	return prate;
+}
+
+static long clk_gpt_round_rate(struct clk_hw *hw, unsigned long drate,
+		unsigned long *prate)
+{
+	struct clk_gpt *gpt = to_clk_gpt(hw);
+	int unused;
+
+	return clk_round_rate_index(hw, drate, gpt_calc_rate, gpt->rtbl_cnt,
+			&unused);
+}
+
+static unsigned long clk_gpt_recalc_rate(struct clk_hw *hw,
+		unsigned long parent_rate)
+{
+	struct clk_gpt *gpt = to_clk_gpt(hw);
+	unsigned long flags = 0;
+	unsigned int div = 1, val;
+
+	if (gpt->lock)
+		spin_lock_irqsave(gpt->lock, flags);
+
+	val = readl_relaxed(gpt->reg);
+
+	if (gpt->lock)
+		spin_unlock_irqrestore(gpt->lock, flags);
+
+	div += val & GPT_MSCALE_MASK;
+	div *= 1 << (((val >> GPT_NSCALE_SHIFT) & GPT_NSCALE_MASK) + 1);
+
+	if (!div)
+		return 0;
+
+	return parent_rate / div;
+}
+
+/* Configures new clock rate of gpt */
+static int clk_gpt_set_rate(struct clk_hw *hw, unsigned long drate)
+{
+	struct clk_gpt *gpt = to_clk_gpt(hw);
+	struct gpt_rate_tbl *rtbl = gpt->rtbl;
+	unsigned long flags = 0, val;
+	int i;
+
+	clk_round_rate_index(hw, drate, gpt_calc_rate, gpt->rtbl_cnt, &i);
+
+	if (gpt->lock)
+		spin_lock_irqsave(gpt->lock, flags);
+
+	val = readl(gpt->reg) & ~GPT_MSCALE_MASK;
+	val &= ~(GPT_NSCALE_MASK << GPT_NSCALE_SHIFT);
+
+	val |= rtbl[i].mscale & GPT_MSCALE_MASK;
+	val |= (rtbl[i].nscale & GPT_NSCALE_MASK) << GPT_NSCALE_SHIFT;
+
+	writel_relaxed(val, gpt->reg);
+
+	if (gpt->lock)
+		spin_unlock_irqrestore(gpt->lock, flags);
+
+	return 0;
+}
+
+static struct clk_ops clk_gpt_ops = {
+	.recalc_rate = clk_gpt_recalc_rate,
+	.round_rate = clk_gpt_round_rate,
+	.set_rate = clk_gpt_set_rate,
+};
+
+struct clk *clk_register_gpt(const char *name, const char *parent_name, unsigned
+		long flags, void __iomem *reg, struct gpt_rate_tbl *rtbl, u8
+		rtbl_cnt, spinlock_t *lock)
+{
+	struct clk_gpt *gpt;
+	struct clk *clk;
+
+	if (!name || !parent_name || !reg || !rtbl || !rtbl_cnt) {
+		pr_err("Invalid arguments passed");
+		return ERR_PTR(-EINVAL);
+	}
+
+	gpt = kzalloc(sizeof(*gpt), GFP_KERNEL);
+	if (!gpt) {
+		pr_err("could not allocate gpt clk\n");
+		return ERR_PTR(-ENOMEM);
+	}
+
+	/* struct clk_gpt assignments */
+	gpt->reg = reg;
+	gpt->rtbl = rtbl;
+	gpt->rtbl_cnt = rtbl_cnt;
+	gpt->lock = lock;
+
+	clk = clk_register(NULL, name, &clk_gpt_ops, &gpt->hw, &parent_name, 1,
+			flags);
+	if (!IS_ERR_OR_NULL(clk))
+		return clk;
+
+	pr_err("clk register failed\n");
+	kfree(gpt);
+
+	return NULL;
+}
diff --git a/drivers/clk/spear/clk.h b/drivers/clk/spear/clk.h
index e67e6cf..67e529d 100644
--- a/drivers/clk/spear/clk.h
+++ b/drivers/clk/spear/clk.h
@@ -68,6 +68,20 @@ struct clk_frac {
 	spinlock_t		*lock;
 };
 
+/* GPT clk */
+struct gpt_rate_tbl {
+	u16 mscale;
+	u16 nscale;
+};
+
+struct clk_gpt {
+	struct			clk_hw hw;
+	void __iomem		*reg;
+	struct gpt_rate_tbl	*rtbl;
+	u8			rtbl_cnt;
+	spinlock_t		*lock;
+};
+
 /* VCO-PLL clk */
 struct pll_rate_tbl {
 	u8 mode;
@@ -103,6 +117,9 @@ struct clk *clk_register_aux(const char *aux_name, const char *gate_name,
 struct clk *clk_register_frac(const char *name, const char *parent_name,
 		unsigned long flags, void __iomem *reg,
 		struct frac_rate_tbl *rtbl, u8 rtbl_cnt, spinlock_t *lock);
+struct clk *clk_register_gpt(const char *name, const char *parent_name, unsigned
+		long flags, void __iomem *reg, struct gpt_rate_tbl *rtbl, u8
+		rtbl_cnt, spinlock_t *lock);
 struct clk *clk_register_vco_pll(const char *vco_name, const char *pll_name,
 		const char *vco_gate_name, const char *parent_name,
 		unsigned long flags, void __iomem *mode_reg, void __iomem
-- 
1.7.9

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

* [PATCH V2 5/6] SPEAr: Call clk_prepare() before calling clk_enable
  2012-04-19 16:28 [PATCH V2 0/6] SPEAr: Move to common clock framework Viresh Kumar
                   ` (3 preceding siblings ...)
  2012-04-19 16:28 ` [PATCH V2 4/6] SPEAr: clk: Add General Purpose Timer " Viresh Kumar
@ 2012-04-19 16:28 ` Viresh Kumar
       [not found] ` <ddade82f0666c3186b8a694aa2b79acd3f7e5d50.1334852395.git.viresh.kumar@st.com>
  5 siblings, 0 replies; 16+ messages in thread
From: Viresh Kumar @ 2012-04-19 16:28 UTC (permalink / raw)
  To: linux-arm-kernel

With common clock framework, it is must to call clk_{un}prepare() before/after
clk_{dis}enable. This patch fixes this for SPEAr timer.

Signed-off-by: Viresh Kumar <viresh.kumar@st.com>
---
 arch/arm/plat-spear/time.c |    8 ++++----
 1 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/arch/arm/plat-spear/time.c b/arch/arm/plat-spear/time.c
index a3164d1..4f05d26 100644
--- a/arch/arm/plat-spear/time.c
+++ b/arch/arm/plat-spear/time.c
@@ -218,10 +218,10 @@ void __init spear_setup_timer(resource_size_t base, int irq)
 		goto err_iomap;
 	}
 
-	ret = clk_enable(gpt_clk);
+	ret = clk_prepare_enable(gpt_clk);
 	if (ret < 0) {
-		pr_err("%s:couldn't enable gpt clock\n", __func__);
-		goto err_clk;
+		pr_err("%s:couldn't prepare-enable gpt clock\n", __func__);
+		goto err_prepare_enable_clk;
 	}
 
 	spear_clockevent_init(irq);
@@ -229,7 +229,7 @@ void __init spear_setup_timer(resource_size_t base, int irq)
 
 	return;
 
-err_clk:
+err_prepare_enable_clk:
 	clk_put(gpt_clk);
 err_iomap:
 	iounmap(gpt_base);
-- 
1.7.9

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

* [PATCH V2 6/6] SPEAr: Switch to common clock framework
       [not found] ` <ddade82f0666c3186b8a694aa2b79acd3f7e5d50.1334852395.git.viresh.kumar@st.com>
@ 2012-04-19 19:59   ` Arnd Bergmann
  2012-04-20  3:28     ` Viresh Kumar
  2012-04-23 20:56   ` Turquette, Mike
       [not found]   ` <CAJOA=zOvyJ9pqEqnhmU1CqHy1uPUOyC=c7VtKjkjK91cbHkGHw@mail.gmail.com>
  2 siblings, 1 reply; 16+ messages in thread
From: Arnd Bergmann @ 2012-04-19 19:59 UTC (permalink / raw)
  To: linux-arm-kernel

On Thursday 19 April 2012, Viresh Kumar wrote:
> SPEAr SoCs used its own clock framework since now. From now on they will move to
> use common clock framework.
> 
> This patch updates existing SPEAr machine support to adapt for common clock
> framework.
> 
> Signed-off-by: Viresh Kumar <viresh.kumar@st.com>

Acked-by: Arnd Bergmann <arnd@arndb.de>

> ---
>  MAINTAINERS                                     |    4 +-
>  arch/arm/Kconfig                                |    1 +
>  arch/arm/mach-spear3xx/Makefile                 |    2 +-
>  arch/arm/mach-spear3xx/clock.c                  |  892 --------------------
>  arch/arm/mach-spear3xx/include/mach/generic.h   |    4 +-
>  arch/arm/mach-spear3xx/include/mach/misc_regs.h |    2 +
>  arch/arm/mach-spear3xx/include/mach/spear.h     |   13 +
>  arch/arm/mach-spear3xx/spear300.c               |    1 -
>  arch/arm/mach-spear3xx/spear310.c               |    1 -
>  arch/arm/mach-spear3xx/spear320.c               |   12 +-
>  arch/arm/mach-spear3xx/spear3xx.c               |    2 +
>  arch/arm/mach-spear6xx/Makefile                 |    2 +-
>  arch/arm/mach-spear6xx/clock.c                  |  789 ------------------
>  arch/arm/mach-spear6xx/include/mach/misc_regs.h |    2 +
>  arch/arm/mach-spear6xx/spear6xx.c               |    5 +-
>  arch/arm/plat-spear/Makefile                    |    2 +-
>  arch/arm/plat-spear/clock.c                     | 1005 -----------------------
>  arch/arm/plat-spear/include/plat/clock.h        |  249 ------
>  drivers/clk/spear/Makefile                      |    3 +
>  drivers/clk/spear/spear3xx_clock.c              |  612 ++++++++++++++
>  drivers/clk/spear/spear6xx_clock.c              |  342 ++++++++
>  21 files changed, 994 insertions(+), 2951 deletions(-)

Great diffstat!

	Arnd

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

* [PATCH V2 6/6] SPEAr: Switch to common clock framework
  2012-04-19 19:59   ` [PATCH V2 6/6] SPEAr: Switch to common clock framework Arnd Bergmann
@ 2012-04-20  3:28     ` Viresh Kumar
  2012-04-20 16:02       ` Arnd Bergmann
  0 siblings, 1 reply; 16+ messages in thread
From: Viresh Kumar @ 2012-04-20  3:28 UTC (permalink / raw)
  To: linux-arm-kernel

On 4/20/2012 1:29 AM, Arnd Bergmann wrote:
> On Thursday 19 April 2012, Viresh Kumar wrote:
>> > SPEAr SoCs used its own clock framework since now. From now on they will move to
>> > use common clock framework.
>> > 
>> > This patch updates existing SPEAr machine support to adapt for common clock
>> > framework.
>> > 
>> > Signed-off-by: Viresh Kumar <viresh.kumar@st.com>
> Acked-by: Arnd Bergmann <arnd@arndb.de>
> 
>> >  21 files changed, 994 insertions(+), 2951 deletions(-)
> Great diffstat!

Thanks Arnd.

For this set to go through Mike's tree, we would require earlier pull request
of 3xx DT and pinmux to be upstreamed. When are you planning to do that?
After that i will ask Mike to apply these patches on latest linux-next. :)

-- 
viresh

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

* [PATCH V2 6/6] SPEAr: Switch to common clock framework
  2012-04-20  3:28     ` Viresh Kumar
@ 2012-04-20 16:02       ` Arnd Bergmann
  2012-04-20 16:57         ` viresh kumar
  0 siblings, 1 reply; 16+ messages in thread
From: Arnd Bergmann @ 2012-04-20 16:02 UTC (permalink / raw)
  To: linux-arm-kernel

On Friday 20 April 2012, Viresh Kumar wrote:
> For this set to go through Mike's tree, we would require earlier pull request
> of 3xx DT and pinmux to be upstreamed. When are you planning to do that?
> After that i will ask Mike to apply these patches on latest linux-next. :)

I plan to do it as soon as possible, but I've been procrastinating this
and let Olof take care of the merges in the last few weeks.

On the plus side, I've got the number of unread mails down from ~20000 to
640 (your pull request is among those),  built a new kernel for my laptop,
cleaned up my git trees and bought a new vaccuum cleaner. Now I'll just
pay the taxes and I'll be right with you there.

Sorry for the delay.

	Arnd

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

* [PATCH V2 6/6] SPEAr: Switch to common clock framework
  2012-04-20 16:02       ` Arnd Bergmann
@ 2012-04-20 16:57         ` viresh kumar
  0 siblings, 0 replies; 16+ messages in thread
From: viresh kumar @ 2012-04-20 16:57 UTC (permalink / raw)
  To: linux-arm-kernel

On 4/20/12, Arnd Bergmann <arnd@arndb.de> wrote:
> I plan to do it as soon as possible, but I've been procrastinating this
> and let Olof take care of the merges in the last few weeks.

:)

> On the plus side, I've got the number of unread mails down from ~20000 to
> 640 (your pull request is among those),  built a new kernel for my laptop,
> cleaned up my git trees and bought a new vaccuum cleaner. Now I'll just
> pay the taxes and I'll be right with you there.

Don't worry. I will not let you sit free. I am preparing another set of patches
for you to review. :)

> Sorry for the delay.

No Probs.

--
Viresh

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

* [PATCH V2 2/6] SPEAr: clk: Add Auxiliary Synthesizer clock
  2012-04-19 16:28 ` [PATCH V2 2/6] SPEAr: clk: Add Auxiliary " Viresh Kumar
@ 2012-04-23 12:33   ` viresh kumar
  0 siblings, 0 replies; 16+ messages in thread
From: viresh kumar @ 2012-04-23 12:33 UTC (permalink / raw)
  To: linux-arm-kernel

On 4/19/12, Viresh Kumar <viresh.linux@gmail.com> wrote:
> All SPEAr SoC's contain Auxiliary Synthesizers. Their Fout is derived based
> on
> values of eq, x and y.
>
> Fout from synthesizer can be given from two equations:
> Fout1 = (Fin * X/Y)/2		EQ1
> Fout2 = Fin * X/Y		EQ2
>
> This patch adds in support for this type of clock.
>
> Signed-off-by: Viresh Kumar <viresh.kumar@st.com>
> ---
>  drivers/clk/spear/Makefile        |    2 +-
>  drivers/clk/spear/clk-aux-synth.c |  187

Hi Mike,

What are your plans for this patchset? Can you push this in v3.5?
SPEAr dependency patches are already pushed by Arnd and are present
in linux-next now.

Please squash following fixup with this patch while applying:

From: Viresh Kumar <viresh.kumar@st.com>
Date: Fri, 20 Apr 2012 17:08:40 +0530
Subject: [PATCH] fixup! SPEAr: clk: Add Auxiliary Synthesizer clock

Set aux->masks to masks if it is valid.

---
 drivers/clk/spear/clk-aux-synth.c |    2 ++
 1 files changed, 2 insertions(+), 0 deletions(-)

diff --git a/drivers/clk/spear/clk-aux-synth.c
b/drivers/clk/spear/clk-aux-synth.c
index 1a7ab7d..e01a350 100644
--- a/drivers/clk/spear/clk-aux-synth.c
+++ b/drivers/clk/spear/clk-aux-synth.c
@@ -154,6 +154,8 @@ struct clk *clk_register_aux(const char *aux_name,
const char *gate_name,
 	/* struct clk_aux assignments */
 	if (!masks)
 		aux->masks = &default_aux_masks;
+	else
+		aux->masks = masks;

 	aux->reg = reg;
 	aux->rtbl = rtbl;

--
Viresh

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

* [PATCH V2 1/6] SPEAr: clk: Add VCO-PLL Synthesizer clock
  2012-04-19 16:28 ` [PATCH V2 1/6] SPEAr: clk: Add VCO-PLL Synthesizer clock Viresh Kumar
@ 2012-04-23 19:15   ` Turquette, Mike
  2012-04-23 19:31   ` Turquette, Mike
  1 sibling, 0 replies; 16+ messages in thread
From: Turquette, Mike @ 2012-04-23 19:15 UTC (permalink / raw)
  To: linux-arm-kernel

On Thu, Apr 19, 2012 at 9:28 AM, Viresh Kumar <viresh.linux@gmail.com> wrote:
> All SPEAr SoC's contain PLLs. Their Fout is derived based on following equations
>
> - In normal mode
> ?vco = (2 * M[15:8] * Fin)/N
>
> - In Dithered mode
> ?vco = (2 * M[15:0] * Fin)/(256 * N)
>
> pll_rate = vco/2^p
>
> vco and pll are very closely bound to each other,
> "vco needs to program: mode, m & n" and "pll needs to program p",
> both share common enable/disable logic and registers.
>
> This patch adds in support for this type of clock.
>
> Signed-off-by: Viresh Kumar <viresh.kumar@st.com>

Hi Viresh,

I took a quick glance through this code from the perspective of common
clk conformance and it looks good.

Reviewed-by: Mike Turquette <mturquette@linaro.org>

Regards,
Mike

> ---
> ?drivers/clk/Makefile ? ? ? ? ? ?| ? ?3 +
> ?drivers/clk/spear/Makefile ? ? ?| ? ?5 +
> ?drivers/clk/spear/clk-vco-pll.c | ?346 +++++++++++++++++++++++++++++++++++++++
> ?drivers/clk/spear/clk.h ? ? ? ? | ? 76 +++++++++
> ?4 files changed, 430 insertions(+), 0 deletions(-)
> ?create mode 100644 drivers/clk/spear/Makefile
> ?create mode 100644 drivers/clk/spear/clk-vco-pll.c
> ?create mode 100644 drivers/clk/spear/clk.h
>
> diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile
> index 24aa714..0f5e03d 100644
> --- a/drivers/clk/Makefile
> +++ b/drivers/clk/Makefile
> @@ -2,3 +2,6 @@
> ?obj-$(CONFIG_CLKDEV_LOOKUP) ? ?+= clkdev.o
> ?obj-$(CONFIG_COMMON_CLK) ? ? ? += clk.o clk-fixed-rate.o clk-gate.o \
> ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? clk-mux.o clk-divider.o clk-fixed-factor.o
> +
> +# SoCs specific
> +obj-$(CONFIG_PLAT_SPEAR) ? ? ? += spear/
> diff --git a/drivers/clk/spear/Makefile b/drivers/clk/spear/Makefile
> new file mode 100644
> index 0000000..f59469f
> --- /dev/null
> +++ b/drivers/clk/spear/Makefile
> @@ -0,0 +1,5 @@
> +#
> +# SPEAr Clock specific Makefile
> +#
> +
> +obj-y ?+= clk-vco-pll.o
> diff --git a/drivers/clk/spear/clk-vco-pll.c b/drivers/clk/spear/clk-vco-pll.c
> new file mode 100644
> index 0000000..9efa30d
> --- /dev/null
> +++ b/drivers/clk/spear/clk-vco-pll.c
> @@ -0,0 +1,346 @@
> +/*
> + * Copyright (C) 2012 ST Microelectronics
> + * Viresh Kumar <viresh.kumar@st.com>
> + *
> + * This file is licensed under the terms of the GNU General Public
> + * License version 2. This program is licensed "as is" without any
> + * warranty of any kind, whether express or implied.
> + *
> + * VCO-PLL clock implementation
> + */
> +
> +#define pr_fmt(fmt) "clk-vco-pll: " fmt
> +
> +#include <linux/clk-provider.h>
> +#include <linux/slab.h>
> +#include <linux/io.h>
> +#include <linux/err.h>
> +#include "clk.h"
> +
> +/*
> + * DOC: VCO-PLL clock
> + *
> + * VCO and PLL rate are derived from following equations:
> + *
> + * In normal mode
> + * vco = (2 * M[15:8] * Fin)/N
> + *
> + * In Dithered mode
> + * vco = (2 * M[15:0] * Fin)/(256 * N)
> + *
> + * pll_rate = pll/2^p
> + *
> + * vco and pll are very closely bound to each other, "vco needs to program:
> + * mode, m & n" and "pll needs to program p", both share common enable/disable
> + * logic.
> + *
> + * clk_register_vco_pll() registers instances of both vco & pll.
> + * CLK_SET_RATE_PARENT flag is forced for pll, as it will always pass its
> + * set_rate to vco. A single rate table exists for both the clocks, which
> + * configures m, n and p.
> + */
> +
> +/* PLL_CTR register masks */
> +#define PLL_MODE_NORMAL ? ? ? ? ? ? ? ?0
> +#define PLL_MODE_FRACTION ? ? ?1
> +#define PLL_MODE_DITH_DSM ? ? ?2
> +#define PLL_MODE_DITH_SSM ? ? ?3
> +#define PLL_MODE_MASK ? ? ? ? ?3
> +#define PLL_MODE_SHIFT ? ? ? ? 3
> +#define PLL_ENABLE ? ? ? ? ? ? 2
> +
> +#define PLL_LOCK_SHIFT ? ? ? ? 0
> +#define PLL_LOCK_MASK ? ? ? ? ?1
> +
> +/* PLL FRQ register masks */
> +#define PLL_NORM_FDBK_M_MASK ? 0xFF
> +#define PLL_NORM_FDBK_M_SHIFT ?24
> +#define PLL_DITH_FDBK_M_MASK ? 0xFFFF
> +#define PLL_DITH_FDBK_M_SHIFT ?16
> +#define PLL_DIV_P_MASK ? ? ? ? 0x7
> +#define PLL_DIV_P_SHIFT ? ? ? ? ? ? ? ?8
> +#define PLL_DIV_N_MASK ? ? ? ? 0xFF
> +#define PLL_DIV_N_SHIFT ? ? ? ? ? ? ? ?0
> +
> +#define to_clk_vco(_hw) container_of(_hw, struct clk_vco, hw)
> +#define to_clk_pll(_hw) container_of(_hw, struct clk_pll, hw)
> +
> +/* Calculates pll clk rate for specific value of mode, m, n and p */
> +static unsigned long pll_calc_rate(struct pll_rate_tbl *rtbl,
> + ? ? ? ? ? ? ? unsigned long prate, int index, unsigned long *pll_rate)
> +{
> + ? ? ? unsigned long rate = prate;
> + ? ? ? unsigned int mode;
> +
> + ? ? ? mode = rtbl[index].mode ? 256 : 1;
> + ? ? ? rate = (((2 * rate / 10000) * rtbl[index].m) / (mode * rtbl[index].n));
> +
> + ? ? ? if (pll_rate)
> + ? ? ? ? ? ? ? *pll_rate = (rate / (1 << rtbl[index].p)) * 10000;
> +
> + ? ? ? return rate * 10000;
> +}
> +
> +static long clk_pll_round_rate_index(struct clk_hw *hw, unsigned long drate,
> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? unsigned long *prate, int *index)
> +{
> + ? ? ? struct clk_pll *pll = to_clk_pll(hw);
> + ? ? ? unsigned long prev_rate, vco_prev_rate, rate = 0;
> + ? ? ? unsigned long vco_parent_rate =
> + ? ? ? ? ? ? ? __clk_get_rate(__clk_get_parent(__clk_get_parent(hw->clk)));
> +
> + ? ? ? if (!prate) {
> + ? ? ? ? ? ? ? pr_err("%s: prate is must for pll clk\n", __func__);
> + ? ? ? ? ? ? ? return -EINVAL;
> + ? ? ? }
> +
> + ? ? ? for (*index = 0; *index < pll->vco->rtbl_cnt; (*index)++) {
> + ? ? ? ? ? ? ? prev_rate = rate;
> + ? ? ? ? ? ? ? vco_prev_rate = *prate;
> + ? ? ? ? ? ? ? *prate = pll_calc_rate(pll->vco->rtbl, vco_parent_rate, *index,
> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? &rate);
> + ? ? ? ? ? ? ? if (drate < rate) {
> + ? ? ? ? ? ? ? ? ? ? ? /* previous clock was best */
> + ? ? ? ? ? ? ? ? ? ? ? if (*index) {
> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? rate = prev_rate;
> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? *prate = vco_prev_rate;
> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? (*index)--;
> + ? ? ? ? ? ? ? ? ? ? ? }
> + ? ? ? ? ? ? ? ? ? ? ? break;
> + ? ? ? ? ? ? ? }
> + ? ? ? }
> +
> + ? ? ? return rate;
> +}
> +
> +static long clk_pll_round_rate(struct clk_hw *hw, unsigned long drate,
> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? unsigned long *prate)
> +{
> + ? ? ? int unused;
> +
> + ? ? ? return clk_pll_round_rate_index(hw, drate, prate, &unused);
> +}
> +
> +static unsigned long clk_pll_recalc_rate(struct clk_hw *hw, unsigned long
> + ? ? ? ? ? ? ? parent_rate)
> +{
> + ? ? ? struct clk_pll *pll = to_clk_pll(hw);
> + ? ? ? unsigned long flags = 0;
> + ? ? ? unsigned int p;
> +
> + ? ? ? if (pll->vco->lock)
> + ? ? ? ? ? ? ? spin_lock_irqsave(pll->vco->lock, flags);
> +
> + ? ? ? p = readl_relaxed(pll->vco->cfg_reg);
> +
> + ? ? ? if (pll->vco->lock)
> + ? ? ? ? ? ? ? spin_unlock_irqrestore(pll->vco->lock, flags);
> +
> + ? ? ? p = (p >> PLL_DIV_P_SHIFT) & PLL_DIV_P_MASK;
> +
> + ? ? ? return parent_rate / (1 << p);
> +}
> +
> +static int clk_pll_set_rate(struct clk_hw *hw, unsigned long drate)
> +{
> + ? ? ? struct clk_pll *pll = to_clk_pll(hw);
> + ? ? ? struct pll_rate_tbl *rtbl = pll->vco->rtbl;
> + ? ? ? unsigned long flags = 0, val;
> + ? ? ? int i;
> +
> + ? ? ? clk_pll_round_rate_index(hw, drate, NULL, &i);
> +
> + ? ? ? if (pll->vco->lock)
> + ? ? ? ? ? ? ? spin_lock_irqsave(pll->vco->lock, flags);
> +
> + ? ? ? val = readl_relaxed(pll->vco->cfg_reg);
> + ? ? ? val &= ~(PLL_DIV_P_MASK << PLL_DIV_P_SHIFT);
> + ? ? ? val |= (rtbl[i].p & PLL_DIV_P_MASK) << PLL_DIV_P_SHIFT;
> + ? ? ? writel_relaxed(val, pll->vco->cfg_reg);
> +
> + ? ? ? if (pll->vco->lock)
> + ? ? ? ? ? ? ? spin_unlock_irqrestore(pll->vco->lock, flags);
> +
> + ? ? ? return 0;
> +}
> +
> +static struct clk_ops clk_pll_ops = {
> + ? ? ? .recalc_rate = clk_pll_recalc_rate,
> + ? ? ? .round_rate = clk_pll_round_rate,
> + ? ? ? .set_rate = clk_pll_set_rate,
> +};
> +
> +static inline unsigned long vco_calc_rate(struct clk_hw *hw,
> + ? ? ? ? ? ? ? unsigned long prate, int index)
> +{
> + ? ? ? struct clk_vco *vco = to_clk_vco(hw);
> +
> + ? ? ? return pll_calc_rate(vco->rtbl, prate, index, NULL);
> +}
> +
> +static long clk_vco_round_rate(struct clk_hw *hw, unsigned long drate,
> + ? ? ? ? ? ? ? unsigned long *prate)
> +{
> + ? ? ? struct clk_vco *vco = to_clk_vco(hw);
> + ? ? ? int unused;
> +
> + ? ? ? return clk_round_rate_index(hw, drate, vco_calc_rate, vco->rtbl_cnt,
> + ? ? ? ? ? ? ? ? ? ? ? &unused);
> +}
> +
> +static unsigned long clk_vco_recalc_rate(struct clk_hw *hw,
> + ? ? ? ? ? ? ? unsigned long parent_rate)
> +{
> + ? ? ? struct clk_vco *vco = to_clk_vco(hw);
> + ? ? ? unsigned long flags = 0;
> + ? ? ? unsigned int num = 2, den = 0, val, mode = 0;
> +
> + ? ? ? if (vco->lock)
> + ? ? ? ? ? ? ? spin_lock_irqsave(vco->lock, flags);
> +
> + ? ? ? mode = (readl_relaxed(vco->mode_reg) >> PLL_MODE_SHIFT) & PLL_MODE_MASK;
> +
> + ? ? ? val = readl_relaxed(vco->cfg_reg);
> +
> + ? ? ? if (vco->lock)
> + ? ? ? ? ? ? ? spin_unlock_irqrestore(vco->lock, flags);
> +
> + ? ? ? den = (val >> PLL_DIV_N_SHIFT) & PLL_DIV_N_MASK;
> +
> + ? ? ? /* calculate numerator & denominator */
> + ? ? ? if (!mode) {
> + ? ? ? ? ? ? ? /* Normal mode */
> + ? ? ? ? ? ? ? num *= (val >> PLL_NORM_FDBK_M_SHIFT) & PLL_NORM_FDBK_M_MASK;
> + ? ? ? } else {
> + ? ? ? ? ? ? ? /* Dithered mode */
> + ? ? ? ? ? ? ? num *= (val >> PLL_DITH_FDBK_M_SHIFT) & PLL_DITH_FDBK_M_MASK;
> + ? ? ? ? ? ? ? den *= 256;
> + ? ? ? }
> +
> + ? ? ? if (!den) {
> + ? ? ? ? ? ? ? WARN(1, "%s: denominator can't be zero\n", __func__);
> + ? ? ? ? ? ? ? return 0;
> + ? ? ? }
> +
> + ? ? ? return (((parent_rate / 10000) * num) / den) * 10000;
> +}
> +
> +/* Configures new clock rate of vco */
> +static int clk_vco_set_rate(struct clk_hw *hw, unsigned long drate)
> +{
> + ? ? ? struct clk_vco *vco = to_clk_vco(hw);
> + ? ? ? struct pll_rate_tbl *rtbl = vco->rtbl;
> + ? ? ? unsigned long flags = 0, val;
> + ? ? ? int i;
> +
> + ? ? ? clk_round_rate_index(hw, drate, vco_calc_rate, vco->rtbl_cnt, &i);
> +
> + ? ? ? if (vco->lock)
> + ? ? ? ? ? ? ? spin_lock_irqsave(vco->lock, flags);
> +
> + ? ? ? val = readl_relaxed(vco->mode_reg);
> + ? ? ? val &= ~(PLL_MODE_MASK << PLL_MODE_SHIFT);
> + ? ? ? val |= (rtbl[i].mode & PLL_MODE_MASK) << PLL_MODE_SHIFT;
> + ? ? ? writel_relaxed(val, vco->mode_reg);
> +
> + ? ? ? val = readl_relaxed(vco->cfg_reg);
> + ? ? ? val &= ~(PLL_DIV_N_MASK << PLL_DIV_N_SHIFT);
> + ? ? ? val |= (rtbl[i].n & PLL_DIV_N_MASK) << PLL_DIV_N_SHIFT;
> +
> + ? ? ? val &= ~(PLL_DITH_FDBK_M_MASK << PLL_DITH_FDBK_M_SHIFT);
> + ? ? ? if (rtbl[i].mode)
> + ? ? ? ? ? ? ? val |= (rtbl[i].m & PLL_DITH_FDBK_M_MASK) <<
> + ? ? ? ? ? ? ? ? ? ? ? PLL_DITH_FDBK_M_SHIFT;
> + ? ? ? else
> + ? ? ? ? ? ? ? val |= (rtbl[i].m & PLL_NORM_FDBK_M_MASK) <<
> + ? ? ? ? ? ? ? ? ? ? ? PLL_NORM_FDBK_M_SHIFT;
> +
> + ? ? ? writel_relaxed(val, vco->cfg_reg);
> +
> + ? ? ? if (vco->lock)
> + ? ? ? ? ? ? ? spin_unlock_irqrestore(vco->lock, flags);
> +
> + ? ? ? return 0;
> +}
> +
> +static struct clk_ops clk_vco_ops = {
> + ? ? ? .recalc_rate = clk_vco_recalc_rate,
> + ? ? ? .round_rate = clk_vco_round_rate,
> + ? ? ? .set_rate = clk_vco_set_rate,
> +};
> +
> +struct clk *clk_register_vco_pll(const char *vco_name, const char *pll_name,
> + ? ? ? ? ? ? ? const char *vco_gate_name, const char *parent_name,
> + ? ? ? ? ? ? ? unsigned long flags, void __iomem *mode_reg, void __iomem
> + ? ? ? ? ? ? ? *cfg_reg, struct pll_rate_tbl *rtbl, u8 rtbl_cnt,
> + ? ? ? ? ? ? ? spinlock_t *lock, struct clk **pll_clk,
> + ? ? ? ? ? ? ? struct clk **vco_gate_clk)
> +{
> + ? ? ? struct clk_vco *vco;
> + ? ? ? struct clk_pll *pll;
> + ? ? ? struct clk *vco_clk, *tpll_clk, *tvco_gate_clk;
> + ? ? ? const char **vco_parent_name;
> +
> + ? ? ? if (!vco_name || !pll_name || !parent_name || !mode_reg || !cfg_reg ||
> + ? ? ? ? ? ? ? ? ? ? ? !rtbl || !rtbl_cnt) {
> + ? ? ? ? ? ? ? pr_err("Invalid arguments passed");
> + ? ? ? ? ? ? ? return ERR_PTR(-EINVAL);
> + ? ? ? }
> +
> + ? ? ? vco = kzalloc(sizeof(*vco), GFP_KERNEL);
> + ? ? ? if (!vco) {
> + ? ? ? ? ? ? ? pr_err("could not allocate vco clk\n");
> + ? ? ? ? ? ? ? return ERR_PTR(-ENOMEM);
> + ? ? ? }
> +
> + ? ? ? pll = kzalloc(sizeof(*pll), GFP_KERNEL);
> + ? ? ? if (!pll) {
> + ? ? ? ? ? ? ? pr_err("could not allocate pll clk\n");
> + ? ? ? ? ? ? ? goto free_vco;
> + ? ? ? }
> +
> + ? ? ? /* struct clk_vco assignments */
> + ? ? ? vco->mode_reg = mode_reg;
> + ? ? ? vco->cfg_reg = cfg_reg;
> + ? ? ? vco->rtbl = rtbl;
> + ? ? ? vco->rtbl_cnt = rtbl_cnt;
> + ? ? ? vco->lock = lock;
> + ? ? ? pll->vco = vco;
> +
> + ? ? ? if (vco_gate_name) {
> + ? ? ? ? ? ? ? tvco_gate_clk = clk_register_gate(NULL, vco_gate_name,
> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? parent_name, 0, mode_reg, PLL_ENABLE, 0, lock);
> + ? ? ? ? ? ? ? if (IS_ERR_OR_NULL(tvco_gate_clk))
> + ? ? ? ? ? ? ? ? ? ? ? goto free_pll;
> +
> + ? ? ? ? ? ? ? if (vco_gate_clk)
> + ? ? ? ? ? ? ? ? ? ? ? *vco_gate_clk = tvco_gate_clk;
> + ? ? ? ? ? ? ? vco_parent_name = &vco_gate_name;
> + ? ? ? } else {
> + ? ? ? ? ? ? ? vco_parent_name = &parent_name;
> + ? ? ? }
> +
> + ? ? ? vco_clk = clk_register(NULL, vco_name, &clk_vco_ops, &vco->hw,
> + ? ? ? ? ? ? ? ? ? ? ? vco_parent_name, 1, flags);
> + ? ? ? if (IS_ERR_OR_NULL(vco_clk))
> + ? ? ? ? ? ? ? goto free_pll;
> +
> + ? ? ? tpll_clk = clk_register(NULL, pll_name, &clk_pll_ops, &pll->hw,
> + ? ? ? ? ? ? ? ? ? ? ? &vco_name, 1, CLK_SET_RATE_PARENT);
> + ? ? ? if (IS_ERR_OR_NULL(tpll_clk))
> + ? ? ? ? ? ? ? goto free_pll;
> +
> + ? ? ? if (pll_clk)
> + ? ? ? ? ? ? ? *pll_clk = tpll_clk;
> +
> + ? ? ? return vco_clk;
> +
> +free_pll:
> + ? ? ? kfree(pll);
> +free_vco:
> + ? ? ? kfree(vco);
> +
> + ? ? ? pr_err("Failed to register vco pll clock\n");
> +
> + ? ? ? return ERR_PTR(-ENOMEM);
> +}
> diff --git a/drivers/clk/spear/clk.h b/drivers/clk/spear/clk.h
> new file mode 100644
> index 0000000..a66024e
> --- /dev/null
> +++ b/drivers/clk/spear/clk.h
> @@ -0,0 +1,76 @@
> +/*
> + * Clock framework definitions for SPEAr platform
> + *
> + * Copyright (C) 2012 ST Microelectronics
> + * Viresh Kumar <viresh.kumar@st.com>
> + *
> + * This file is licensed under the terms of the GNU General Public
> + * License version 2. This program is licensed "as is" without any
> + * warranty of any kind, whether express or implied.
> + */
> +
> +#ifndef __PLAT_CLOCK_H
> +#define __PLAT_CLOCK_H
> +
> +#include <linux/clk-provider.h>
> +#include <linux/spinlock_types.h>
> +#include <linux/types.h>
> +
> +/* VCO-PLL clk */
> +struct pll_rate_tbl {
> + ? ? ? u8 mode;
> + ? ? ? u16 m;
> + ? ? ? u8 n;
> + ? ? ? u8 p;
> +};
> +
> +struct clk_vco {
> + ? ? ? struct ? ? ? ? ? ? ? ? ?clk_hw hw;
> + ? ? ? void __iomem ? ? ? ? ? ?*mode_reg;
> + ? ? ? void __iomem ? ? ? ? ? ?*cfg_reg;
> + ? ? ? struct pll_rate_tbl ? ? *rtbl;
> + ? ? ? u8 ? ? ? ? ? ? ? ? ? ? ?rtbl_cnt;
> + ? ? ? spinlock_t ? ? ? ? ? ? ?*lock;
> +};
> +
> +struct clk_pll {
> + ? ? ? struct ? ? ? ? ? ? ? ? ?clk_hw hw;
> + ? ? ? struct clk_vco ? ? ? ? ?*vco;
> + ? ? ? const char ? ? ? ? ? ? ?*parent[1];
> + ? ? ? spinlock_t ? ? ? ? ? ? ?*lock;
> +};
> +
> +typedef unsigned long (*clk_calc_rate)(struct clk_hw *hw, unsigned long prate,
> + ? ? ? ? ? ? ? int index);
> +
> +/* clk register routines */
> +struct clk *clk_register_vco_pll(const char *vco_name, const char *pll_name,
> + ? ? ? ? ? ? ? const char *vco_gate_name, const char *parent_name,
> + ? ? ? ? ? ? ? unsigned long flags, void __iomem *mode_reg, void __iomem
> + ? ? ? ? ? ? ? *cfg_reg, struct pll_rate_tbl *rtbl, u8 rtbl_cnt,
> + ? ? ? ? ? ? ? spinlock_t *lock, struct clk **pll_clk,
> + ? ? ? ? ? ? ? struct clk **vco_gate_clk);
> +
> +static inline long clk_round_rate_index(struct clk_hw *hw, unsigned long drate,
> + ? ? ? ? ? ? ? clk_calc_rate calc_rate, u8 rtbl_cnt, int *index)
> +{
> + ? ? ? unsigned long prev_rate, rate = 0;
> + ? ? ? unsigned long parent_rate = __clk_get_rate(__clk_get_parent(hw->clk));
> +
> + ? ? ? for (*index = 0; *index < rtbl_cnt; (*index)++) {
> + ? ? ? ? ? ? ? prev_rate = rate;
> + ? ? ? ? ? ? ? rate = calc_rate(hw, parent_rate, *index);
> + ? ? ? ? ? ? ? if (drate < rate) {
> + ? ? ? ? ? ? ? ? ? ? ? /* previous clock was best */
> + ? ? ? ? ? ? ? ? ? ? ? if (*index) {
> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? rate = prev_rate;
> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? (*index)--;
> + ? ? ? ? ? ? ? ? ? ? ? }
> + ? ? ? ? ? ? ? ? ? ? ? break;
> + ? ? ? ? ? ? ? }
> + ? ? ? }
> +
> + ? ? ? return rate;
> +}
> +
> +#endif /* __PLAT_CLOCK_H */
> --
> 1.7.9
>

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

* [PATCH V2 1/6] SPEAr: clk: Add VCO-PLL Synthesizer clock
  2012-04-19 16:28 ` [PATCH V2 1/6] SPEAr: clk: Add VCO-PLL Synthesizer clock Viresh Kumar
  2012-04-23 19:15   ` Turquette, Mike
@ 2012-04-23 19:31   ` Turquette, Mike
  2012-04-24  3:40     ` Viresh Kumar
  1 sibling, 1 reply; 16+ messages in thread
From: Turquette, Mike @ 2012-04-23 19:31 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Viresh,

Sent my first email too quickly.  A couple of small questions below.

On Thu, Apr 19, 2012 at 9:28 AM, Viresh Kumar <viresh.linux@gmail.com> wrote:
> diff --git a/drivers/clk/spear/clk.h b/drivers/clk/spear/clk.h
> new file mode 100644
> index 0000000..a66024e
> --- /dev/null
> +++ b/drivers/clk/spear/clk.h
> @@ -0,0 +1,76 @@
> +/*
> + * Clock framework definitions for SPEAr platform
> + *
> + * Copyright (C) 2012 ST Microelectronics
> + * Viresh Kumar <viresh.kumar@st.com>
> + *
> + * This file is licensed under the terms of the GNU General Public
> + * License version 2. This program is licensed "as is" without any
> + * warranty of any kind, whether express or implied.
> + */
> +
> +#ifndef __PLAT_CLOCK_H
> +#define __PLAT_CLOCK_H

Any reason to use __PLAT_CLOCK_H from drivers/clk/ now?  Is it
copy/paste from your old platform code?

...

> +static inline long clk_round_rate_index(struct clk_hw *hw, unsigned long drate,
> + ? ? ? ? ? ? ? clk_calc_rate calc_rate, u8 rtbl_cnt, int *index)
> +{
> + ? ? ? unsigned long prev_rate, rate = 0;
> + ? ? ? unsigned long parent_rate = __clk_get_rate(__clk_get_parent(hw->clk));
> +
> + ? ? ? for (*index = 0; *index < rtbl_cnt; (*index)++) {
> + ? ? ? ? ? ? ? prev_rate = rate;
> + ? ? ? ? ? ? ? rate = calc_rate(hw, parent_rate, *index);
> + ? ? ? ? ? ? ? if (drate < rate) {
> + ? ? ? ? ? ? ? ? ? ? ? /* previous clock was best */
> + ? ? ? ? ? ? ? ? ? ? ? if (*index) {
> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? rate = prev_rate;
> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? (*index)--;
> + ? ? ? ? ? ? ? ? ? ? ? }
> + ? ? ? ? ? ? ? ? ? ? ? break;
> + ? ? ? ? ? ? ? }
> + ? ? ? }
> +
> + ? ? ? return rate;
> +}

Any reason for this code to exist in a header?  I prefer code in C
files.  Also it is a bit large for an inline function.

Thanks,
Mike

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

* [PATCH V2 6/6] SPEAr: Switch to common clock framework
       [not found] ` <ddade82f0666c3186b8a694aa2b79acd3f7e5d50.1334852395.git.viresh.kumar@st.com>
  2012-04-19 19:59   ` [PATCH V2 6/6] SPEAr: Switch to common clock framework Arnd Bergmann
@ 2012-04-23 20:56   ` Turquette, Mike
       [not found]   ` <CAJOA=zOvyJ9pqEqnhmU1CqHy1uPUOyC=c7VtKjkjK91cbHkGHw@mail.gmail.com>
  2 siblings, 0 replies; 16+ messages in thread
From: Turquette, Mike @ 2012-04-23 20:56 UTC (permalink / raw)
  To: linux-arm-kernel

[resending to lakml since message length was too long]

On Thu, Apr 19, 2012 at 9:28 AM, Viresh Kumar <viresh.linux@gmail.com> wrote:
> SPEAr SoCs used its own clock framework since now. From now on they will move to
> use common clock framework.
>
> This patch updates existing SPEAr machine support to adapt for common clock
> framework.
>
> Signed-off-by: Viresh Kumar <viresh.kumar@st.com>

Hi Viresh,

This series looks good to me, except for the two small comments I had
in patch 1/6.

I also think that this code will not be affected by the changes to
struct clk_hw which are expected from Saravana.  Hopefully you have
avoided a big rebase.

I'll take these into my clk-next branch unless Arnd has any objection
based on arm-soc collisions.

Thanks,
Mike

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

* [PATCH V2 1/6] SPEAr: clk: Add VCO-PLL Synthesizer clock
  2012-04-23 19:31   ` Turquette, Mike
@ 2012-04-24  3:40     ` Viresh Kumar
  0 siblings, 0 replies; 16+ messages in thread
From: Viresh Kumar @ 2012-04-24  3:40 UTC (permalink / raw)
  To: linux-arm-kernel

On 4/24/2012 1:01 AM, Turquette, Mike wrote:
> On Thu, Apr 19, 2012 at 9:28 AM, Viresh Kumar <viresh.linux@gmail.com> wrote:
>> diff --git a/drivers/clk/spear/clk.h b/drivers/clk/spear/clk.h
>> new file mode 100644
>> index 0000000..a66024e
>> --- /dev/null
>> +++ b/drivers/clk/spear/clk.h
>> @@ -0,0 +1,76 @@
>> +/*
>> + * Clock framework definitions for SPEAr platform
>> + *
>> + * Copyright (C) 2012 ST Microelectronics
>> + * Viresh Kumar <viresh.kumar@st.com>
>> + *
>> + * This file is licensed under the terms of the GNU General Public
>> + * License version 2. This program is licensed "as is" without any
>> + * warranty of any kind, whether express or implied.
>> + */
>> +
>> +#ifndef __PLAT_CLOCK_H
>> +#define __PLAT_CLOCK_H
> 
> Any reason to use __PLAT_CLOCK_H from drivers/clk/ now?  Is it
> copy/paste from your old platform code?

Ya. Will fix it to __SPEAR_CLK_H

>> +static inline long clk_round_rate_index(struct clk_hw *hw, unsigned long drate,
>> +               clk_calc_rate calc_rate, u8 rtbl_cnt, int *index)
>> +{
>> +       unsigned long prev_rate, rate = 0;
>> +       unsigned long parent_rate = __clk_get_rate(__clk_get_parent(hw->clk));
>> +
>> +       for (*index = 0; *index < rtbl_cnt; (*index)++) {
>> +               prev_rate = rate;
>> +               rate = calc_rate(hw, parent_rate, *index);
>> +               if (drate < rate) {
>> +                       /* previous clock was best */
>> +                       if (*index) {
>> +                               rate = prev_rate;
>> +                               (*index)--;
>> +                       }
>> +                       break;
>> +               }
>> +       }
>> +
>> +       return rate;
>> +}
> 
> Any reason for this code to exist in a header?  I prefer code in C
> files.  Also it is a bit large for an inline function.

There is no C file common to entire SPEAr clock framework, so kept it in header.
Because this is called only from 2-3 places, inline would also be fine.

But if you insist, i can create clk.c in spear, where i can keep it.

-- 
viresh

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

* [PATCH V2 6/6] SPEAr: Switch to common clock framework
       [not found]   ` <CAJOA=zOvyJ9pqEqnhmU1CqHy1uPUOyC=c7VtKjkjK91cbHkGHw@mail.gmail.com>
@ 2012-04-24  4:09     ` Viresh Kumar
  0 siblings, 0 replies; 16+ messages in thread
From: Viresh Kumar @ 2012-04-24  4:09 UTC (permalink / raw)
  To: linux-arm-kernel

On 4/24/2012 2:12 AM, Turquette, Mike wrote:
> I also think that this code will not be affected by the changes to
> struct clk_hw which are expected from Saravana.  Hopefully you have
> avoided a big rebase.
> 
> I'll take these into my clk-next branch unless Arnd has any objection
> based on arm-soc collisions.

That sounds good.
I will send V3, for it. That will contain two additional dependency patches:

- clk: add a fixed factor clock - by Sascha Hauer
- CLKDEV: Add helper routines to allocate and add clkdevs for given struct clk *

-- 
viresh

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

end of thread, other threads:[~2012-04-24  4:09 UTC | newest]

Thread overview: 16+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2012-04-19 16:28 [PATCH V2 0/6] SPEAr: Move to common clock framework Viresh Kumar
2012-04-19 16:28 ` [PATCH V2 1/6] SPEAr: clk: Add VCO-PLL Synthesizer clock Viresh Kumar
2012-04-23 19:15   ` Turquette, Mike
2012-04-23 19:31   ` Turquette, Mike
2012-04-24  3:40     ` Viresh Kumar
2012-04-19 16:28 ` [PATCH V2 2/6] SPEAr: clk: Add Auxiliary " Viresh Kumar
2012-04-23 12:33   ` viresh kumar
2012-04-19 16:28 ` [PATCH V2 3/6] SPEAr: clk: Add Fractional " Viresh Kumar
2012-04-19 16:28 ` [PATCH V2 4/6] SPEAr: clk: Add General Purpose Timer " Viresh Kumar
2012-04-19 16:28 ` [PATCH V2 5/6] SPEAr: Call clk_prepare() before calling clk_enable Viresh Kumar
     [not found] ` <ddade82f0666c3186b8a694aa2b79acd3f7e5d50.1334852395.git.viresh.kumar@st.com>
2012-04-19 19:59   ` [PATCH V2 6/6] SPEAr: Switch to common clock framework Arnd Bergmann
2012-04-20  3:28     ` Viresh Kumar
2012-04-20 16:02       ` Arnd Bergmann
2012-04-20 16:57         ` viresh kumar
2012-04-23 20:56   ` Turquette, Mike
     [not found]   ` <CAJOA=zOvyJ9pqEqnhmU1CqHy1uPUOyC=c7VtKjkjK91cbHkGHw@mail.gmail.com>
2012-04-24  4:09     ` Viresh Kumar

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.