From 76cb841cb886eef6b3bee341a2266c76578724ad Mon Sep 17 00:00:00 2001
From: Daniel Baumann <daniel.baumann@progress-linux.org>
Date: Mon, 6 May 2024 03:02:30 +0200
Subject: Adding upstream version 4.19.249.

Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
---
 drivers/clk/spear/Makefile          |   11 +
 drivers/clk/spear/clk-aux-synth.c   |  197 ++++++
 drivers/clk/spear/clk-frac-synth.c  |  163 +++++
 drivers/clk/spear/clk-gpt-synth.c   |  152 +++++
 drivers/clk/spear/clk-vco-pll.c     |  359 +++++++++++
 drivers/clk/spear/clk.c             |   39 ++
 drivers/clk/spear/clk.h             |  134 +++++
 drivers/clk/spear/spear1310_clock.c | 1122 +++++++++++++++++++++++++++++++++++
 drivers/clk/spear/spear1340_clock.c | 1015 +++++++++++++++++++++++++++++++
 drivers/clk/spear/spear3xx_clock.c  |  667 +++++++++++++++++++++
 drivers/clk/spear/spear6xx_clock.c  |  340 +++++++++++
 11 files changed, 4199 insertions(+)
 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.c
 create mode 100644 drivers/clk/spear/clk.h
 create mode 100644 drivers/clk/spear/spear1310_clock.c
 create mode 100644 drivers/clk/spear/spear1340_clock.c
 create mode 100644 drivers/clk/spear/spear3xx_clock.c
 create mode 100644 drivers/clk/spear/spear6xx_clock.c

(limited to 'drivers/clk/spear')

diff --git a/drivers/clk/spear/Makefile b/drivers/clk/spear/Makefile
new file mode 100644
index 000000000..d7e75d2d4
--- /dev/null
+++ b/drivers/clk/spear/Makefile
@@ -0,0 +1,11 @@
+# SPDX-License-Identifier: GPL-2.0
+#
+# SPEAr Clock specific Makefile
+#
+
+obj-y	+= clk.o clk-aux-synth.o clk-frac-synth.o clk-gpt-synth.o clk-vco-pll.o
+
+obj-$(CONFIG_ARCH_SPEAR3XX)	+= spear3xx_clock.o
+obj-$(CONFIG_ARCH_SPEAR6XX)	+= spear6xx_clock.o
+obj-$(CONFIG_MACH_SPEAR1310)	+= spear1310_clock.o
+obj-$(CONFIG_MACH_SPEAR1340)	+= spear1340_clock.o
diff --git a/drivers/clk/spear/clk-aux-synth.c b/drivers/clk/spear/clk-aux-synth.c
new file mode 100644
index 000000000..906410413
--- /dev/null
+++ b/drivers/clk/spear/clk-aux-synth.c
@@ -0,0 +1,197 @@
+/*
+ * Copyright (C) 2012 ST Microelectronics
+ * Viresh Kumar <vireshk@kernel.org>
+ *
+ * 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 const  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, *prate, 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,
+				unsigned long prate)
+{
+	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, prate, 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 const 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,
+	        const 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_init_data init;
+	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)
+		return ERR_PTR(-ENOMEM);
+
+	/* struct clk_aux assignments */
+	if (!masks)
+		aux->masks = &default_aux_masks;
+	else
+		aux->masks = masks;
+
+	aux->reg = reg;
+	aux->rtbl = rtbl;
+	aux->rtbl_cnt = rtbl_cnt;
+	aux->lock = lock;
+	aux->hw.init = &init;
+
+	init.name = aux_name;
+	init.ops = &clk_aux_ops;
+	init.flags = flags;
+	init.parent_names = &parent_name;
+	init.num_parents = 1;
+
+	clk = clk_register(NULL, &aux->hw);
+	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,
+				CLK_SET_RATE_PARENT, 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-frac-synth.c b/drivers/clk/spear/clk-frac-synth.c
new file mode 100644
index 000000000..f5be02205
--- /dev/null
+++ b/drivers/clk/spear/clk-frac-synth.c
@@ -0,0 +1,163 @@
+/*
+ * Copyright (C) 2012 ST Microelectronics
+ * Viresh Kumar <vireshk@kernel.org>
+ *
+ * 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 at 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, *prate, 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,
+				unsigned long prate)
+{
+	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, prate, 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;
+}
+
+static const 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_init_data init;
+	struct clk_frac *frac;
+	struct clk *clk;
+
+	if (!name || !parent_name || !reg || !rtbl || !rtbl_cnt) {
+		pr_err("Invalid arguments passed\n");
+		return ERR_PTR(-EINVAL);
+	}
+
+	frac = kzalloc(sizeof(*frac), GFP_KERNEL);
+	if (!frac)
+		return ERR_PTR(-ENOMEM);
+
+	/* struct clk_frac assignments */
+	frac->reg = reg;
+	frac->rtbl = rtbl;
+	frac->rtbl_cnt = rtbl_cnt;
+	frac->lock = lock;
+	frac->hw.init = &init;
+
+	init.name = name;
+	init.ops = &clk_frac_ops;
+	init.flags = flags;
+	init.parent_names = &parent_name;
+	init.num_parents = 1;
+
+	clk = clk_register(NULL, &frac->hw);
+	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-gpt-synth.c b/drivers/clk/spear/clk-gpt-synth.c
new file mode 100644
index 000000000..6ed406d94
--- /dev/null
+++ b/drivers/clk/spear/clk-gpt-synth.c
@@ -0,0 +1,152 @@
+/*
+ * Copyright (C) 2012 ST Microelectronics
+ * Viresh Kumar <vireshk@kernel.org>
+ *
+ * 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, *prate, 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,
+				unsigned long prate)
+{
+	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, prate, 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 const 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_init_data init;
+	struct clk_gpt *gpt;
+	struct clk *clk;
+
+	if (!name || !parent_name || !reg || !rtbl || !rtbl_cnt) {
+		pr_err("Invalid arguments passed\n");
+		return ERR_PTR(-EINVAL);
+	}
+
+	gpt = kzalloc(sizeof(*gpt), GFP_KERNEL);
+	if (!gpt)
+		return ERR_PTR(-ENOMEM);
+
+	/* struct clk_gpt assignments */
+	gpt->reg = reg;
+	gpt->rtbl = rtbl;
+	gpt->rtbl_cnt = rtbl_cnt;
+	gpt->lock = lock;
+	gpt->hw.init = &init;
+
+	init.name = name;
+	init.ops = &clk_gpt_ops;
+	init.flags = flags;
+	init.parent_names = &parent_name;
+	init.num_parents = 1;
+
+	clk = clk_register(NULL, &gpt->hw);
+	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-vco-pll.c b/drivers/clk/spear/clk-vco-pll.c
new file mode 100644
index 000000000..c08dec30b
--- /dev/null
+++ b/drivers/clk/spear/clk-vco-pll.c
@@ -0,0 +1,359 @@
+/*
+ * Copyright (C) 2012 ST Microelectronics
+ * Viresh Kumar <vireshk@kernel.org>
+ *
+ * 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_hw_get_rate(clk_hw_get_parent(clk_hw_get_parent(hw)));
+
+	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,
+				unsigned long prate)
+{
+	struct clk_pll *pll = to_clk_pll(hw);
+	struct pll_rate_tbl *rtbl = pll->vco->rtbl;
+	unsigned long flags = 0, val;
+	int uninitialized_var(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 const 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, *prate, 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,
+				unsigned long prate)
+{
+	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, prate, 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 const 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;
+	struct clk_init_data vco_init, pll_init;
+	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)
+		return ERR_PTR(-ENOMEM);
+
+	pll = kzalloc(sizeof(*pll), GFP_KERNEL);
+	if (!pll)
+		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;
+	vco->hw.init = &vco_init;
+
+	pll->vco = vco;
+	pll->hw.init = &pll_init;
+
+	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_init.name = vco_name;
+	vco_init.ops = &clk_vco_ops;
+	vco_init.flags = flags;
+	vco_init.parent_names = vco_parent_name;
+	vco_init.num_parents = 1;
+
+	pll_init.name = pll_name;
+	pll_init.ops = &clk_pll_ops;
+	pll_init.flags = CLK_SET_RATE_PARENT;
+	pll_init.parent_names = &vco_name;
+	pll_init.num_parents = 1;
+
+	vco_clk = clk_register(NULL, &vco->hw);
+	if (IS_ERR_OR_NULL(vco_clk))
+		goto free_pll;
+
+	tpll_clk = clk_register(NULL, &pll->hw);
+	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.c b/drivers/clk/spear/clk.c
new file mode 100644
index 000000000..157fe099e
--- /dev/null
+++ b/drivers/clk/spear/clk.c
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2012 ST Microelectronics
+ * Viresh Kumar <vireshk@kernel.org>
+ *
+ * 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.
+ *
+ * SPEAr clk - Common routines
+ */
+
+#include <linux/clk-provider.h>
+#include <linux/types.h>
+#include "clk.h"
+
+long clk_round_rate_index(struct clk_hw *hw, unsigned long drate,
+		unsigned long parent_rate, clk_calc_rate calc_rate, u8 rtbl_cnt,
+		int *index)
+{
+	unsigned long prev_rate, rate = 0;
+
+	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;
+		}
+	}
+
+	if ((*index) == rtbl_cnt)
+		(*index)--;
+
+	return rate;
+}
diff --git a/drivers/clk/spear/clk.h b/drivers/clk/spear/clk.h
new file mode 100644
index 000000000..af0e25f49
--- /dev/null
+++ b/drivers/clk/spear/clk.h
@@ -0,0 +1,134 @@
+/*
+ * Clock framework definitions for SPEAr platform
+ *
+ * Copyright (C) 2012 ST Microelectronics
+ * Viresh Kumar <vireshk@kernel.org>
+ *
+ * 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 __SPEAR_CLK_H
+#define __SPEAR_CLK_H
+
+#include <linux/clk-provider.h>
+#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;
+	const struct aux_clk_masks *masks;
+	struct aux_rate_tbl	*rtbl;
+	u8			rtbl_cnt;
+	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;
+};
+
+/* 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;
+	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_aux(const char *aux_name, const char *gate_name,
+		const char *parent_name, unsigned long flags, void __iomem *reg,
+		const 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_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
+		*cfg_reg, struct pll_rate_tbl *rtbl, u8 rtbl_cnt,
+		spinlock_t *lock, struct clk **pll_clk,
+		struct clk **vco_gate_clk);
+
+long clk_round_rate_index(struct clk_hw *hw, unsigned long drate,
+		unsigned long parent_rate, clk_calc_rate calc_rate, u8 rtbl_cnt,
+		int *index);
+
+#endif /* __SPEAR_CLK_H */
diff --git a/drivers/clk/spear/spear1310_clock.c b/drivers/clk/spear/spear1310_clock.c
new file mode 100644
index 000000000..591248c9a
--- /dev/null
+++ b/drivers/clk/spear/spear1310_clock.c
@@ -0,0 +1,1122 @@
+/*
+ * arch/arm/mach-spear13xx/spear1310_clock.c
+ *
+ * SPEAr1310 machine clock framework source file
+ *
+ * Copyright (C) 2012 ST Microelectronics
+ * Viresh Kumar <vireshk@kernel.org>
+ *
+ * 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.
+ */
+
+#include <linux/clkdev.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/of_platform.h>
+#include <linux/spinlock_types.h>
+#include "clk.h"
+
+/* PLL related registers and bit values */
+#define SPEAR1310_PLL_CFG			(misc_base + 0x210)
+	/* PLL_CFG bit values */
+	#define SPEAR1310_CLCD_SYNT_CLK_MASK		1
+	#define SPEAR1310_CLCD_SYNT_CLK_SHIFT		31
+	#define SPEAR1310_RAS_SYNT2_3_CLK_MASK		2
+	#define SPEAR1310_RAS_SYNT2_3_CLK_SHIFT		29
+	#define SPEAR1310_RAS_SYNT_CLK_MASK		2
+	#define SPEAR1310_RAS_SYNT0_1_CLK_SHIFT		27
+	#define SPEAR1310_PLL_CLK_MASK			2
+	#define SPEAR1310_PLL3_CLK_SHIFT		24
+	#define SPEAR1310_PLL2_CLK_SHIFT		22
+	#define SPEAR1310_PLL1_CLK_SHIFT		20
+
+#define SPEAR1310_PLL1_CTR			(misc_base + 0x214)
+#define SPEAR1310_PLL1_FRQ			(misc_base + 0x218)
+#define SPEAR1310_PLL2_CTR			(misc_base + 0x220)
+#define SPEAR1310_PLL2_FRQ			(misc_base + 0x224)
+#define SPEAR1310_PLL3_CTR			(misc_base + 0x22C)
+#define SPEAR1310_PLL3_FRQ			(misc_base + 0x230)
+#define SPEAR1310_PLL4_CTR			(misc_base + 0x238)
+#define SPEAR1310_PLL4_FRQ			(misc_base + 0x23C)
+#define SPEAR1310_PERIP_CLK_CFG			(misc_base + 0x244)
+	/* PERIP_CLK_CFG bit values */
+	#define SPEAR1310_GPT_OSC24_VAL			0
+	#define SPEAR1310_GPT_APB_VAL			1
+	#define SPEAR1310_GPT_CLK_MASK			1
+	#define SPEAR1310_GPT3_CLK_SHIFT		11
+	#define SPEAR1310_GPT2_CLK_SHIFT		10
+	#define SPEAR1310_GPT1_CLK_SHIFT		9
+	#define SPEAR1310_GPT0_CLK_SHIFT		8
+	#define SPEAR1310_UART_CLK_PLL5_VAL		0
+	#define SPEAR1310_UART_CLK_OSC24_VAL		1
+	#define SPEAR1310_UART_CLK_SYNT_VAL		2
+	#define SPEAR1310_UART_CLK_MASK			2
+	#define SPEAR1310_UART_CLK_SHIFT		4
+
+	#define SPEAR1310_AUX_CLK_PLL5_VAL		0
+	#define SPEAR1310_AUX_CLK_SYNT_VAL		1
+	#define SPEAR1310_CLCD_CLK_MASK			2
+	#define SPEAR1310_CLCD_CLK_SHIFT		2
+	#define SPEAR1310_C3_CLK_MASK			1
+	#define SPEAR1310_C3_CLK_SHIFT			1
+
+#define SPEAR1310_GMAC_CLK_CFG			(misc_base + 0x248)
+	#define SPEAR1310_GMAC_PHY_IF_SEL_MASK		3
+	#define SPEAR1310_GMAC_PHY_IF_SEL_SHIFT		4
+	#define SPEAR1310_GMAC_PHY_CLK_MASK		1
+	#define SPEAR1310_GMAC_PHY_CLK_SHIFT		3
+	#define SPEAR1310_GMAC_PHY_INPUT_CLK_MASK	2
+	#define SPEAR1310_GMAC_PHY_INPUT_CLK_SHIFT	1
+
+#define SPEAR1310_I2S_CLK_CFG			(misc_base + 0x24C)
+	/* I2S_CLK_CFG register mask */
+	#define SPEAR1310_I2S_SCLK_X_MASK		0x1F
+	#define SPEAR1310_I2S_SCLK_X_SHIFT		27
+	#define SPEAR1310_I2S_SCLK_Y_MASK		0x1F
+	#define SPEAR1310_I2S_SCLK_Y_SHIFT		22
+	#define SPEAR1310_I2S_SCLK_EQ_SEL_SHIFT		21
+	#define SPEAR1310_I2S_SCLK_SYNTH_ENB		20
+	#define SPEAR1310_I2S_PRS1_CLK_X_MASK		0xFF
+	#define SPEAR1310_I2S_PRS1_CLK_X_SHIFT		12
+	#define SPEAR1310_I2S_PRS1_CLK_Y_MASK		0xFF
+	#define SPEAR1310_I2S_PRS1_CLK_Y_SHIFT		4
+	#define SPEAR1310_I2S_PRS1_EQ_SEL_SHIFT		3
+	#define SPEAR1310_I2S_REF_SEL_MASK		1
+	#define SPEAR1310_I2S_REF_SHIFT			2
+	#define SPEAR1310_I2S_SRC_CLK_MASK		2
+	#define SPEAR1310_I2S_SRC_CLK_SHIFT		0
+
+#define SPEAR1310_C3_CLK_SYNT			(misc_base + 0x250)
+#define SPEAR1310_UART_CLK_SYNT			(misc_base + 0x254)
+#define SPEAR1310_GMAC_CLK_SYNT			(misc_base + 0x258)
+#define SPEAR1310_SDHCI_CLK_SYNT		(misc_base + 0x25C)
+#define SPEAR1310_CFXD_CLK_SYNT			(misc_base + 0x260)
+#define SPEAR1310_ADC_CLK_SYNT			(misc_base + 0x264)
+#define SPEAR1310_AMBA_CLK_SYNT			(misc_base + 0x268)
+#define SPEAR1310_CLCD_CLK_SYNT			(misc_base + 0x270)
+#define SPEAR1310_RAS_CLK_SYNT0			(misc_base + 0x280)
+#define SPEAR1310_RAS_CLK_SYNT1			(misc_base + 0x288)
+#define SPEAR1310_RAS_CLK_SYNT2			(misc_base + 0x290)
+#define SPEAR1310_RAS_CLK_SYNT3			(misc_base + 0x298)
+	/* Check Fractional synthesizer reg masks */
+
+#define SPEAR1310_PERIP1_CLK_ENB		(misc_base + 0x300)
+	/* PERIP1_CLK_ENB register masks */
+	#define SPEAR1310_RTC_CLK_ENB			31
+	#define SPEAR1310_ADC_CLK_ENB			30
+	#define SPEAR1310_C3_CLK_ENB			29
+	#define SPEAR1310_JPEG_CLK_ENB			28
+	#define SPEAR1310_CLCD_CLK_ENB			27
+	#define SPEAR1310_DMA_CLK_ENB			25
+	#define SPEAR1310_GPIO1_CLK_ENB			24
+	#define SPEAR1310_GPIO0_CLK_ENB			23
+	#define SPEAR1310_GPT1_CLK_ENB			22
+	#define SPEAR1310_GPT0_CLK_ENB			21
+	#define SPEAR1310_I2S0_CLK_ENB			20
+	#define SPEAR1310_I2S1_CLK_ENB			19
+	#define SPEAR1310_I2C0_CLK_ENB			18
+	#define SPEAR1310_SSP_CLK_ENB			17
+	#define SPEAR1310_UART_CLK_ENB			15
+	#define SPEAR1310_PCIE_SATA_2_CLK_ENB		14
+	#define SPEAR1310_PCIE_SATA_1_CLK_ENB		13
+	#define SPEAR1310_PCIE_SATA_0_CLK_ENB		12
+	#define SPEAR1310_UOC_CLK_ENB			11
+	#define SPEAR1310_UHC1_CLK_ENB			10
+	#define SPEAR1310_UHC0_CLK_ENB			9
+	#define SPEAR1310_GMAC_CLK_ENB			8
+	#define SPEAR1310_CFXD_CLK_ENB			7
+	#define SPEAR1310_SDHCI_CLK_ENB			6
+	#define SPEAR1310_SMI_CLK_ENB			5
+	#define SPEAR1310_FSMC_CLK_ENB			4
+	#define SPEAR1310_SYSRAM0_CLK_ENB		3
+	#define SPEAR1310_SYSRAM1_CLK_ENB		2
+	#define SPEAR1310_SYSROM_CLK_ENB		1
+	#define SPEAR1310_BUS_CLK_ENB			0
+
+#define SPEAR1310_PERIP2_CLK_ENB		(misc_base + 0x304)
+	/* PERIP2_CLK_ENB register masks */
+	#define SPEAR1310_THSENS_CLK_ENB		8
+	#define SPEAR1310_I2S_REF_PAD_CLK_ENB		7
+	#define SPEAR1310_ACP_CLK_ENB			6
+	#define SPEAR1310_GPT3_CLK_ENB			5
+	#define SPEAR1310_GPT2_CLK_ENB			4
+	#define SPEAR1310_KBD_CLK_ENB			3
+	#define SPEAR1310_CPU_DBG_CLK_ENB		2
+	#define SPEAR1310_DDR_CORE_CLK_ENB		1
+	#define SPEAR1310_DDR_CTRL_CLK_ENB		0
+
+#define SPEAR1310_RAS_CLK_ENB			(misc_base + 0x310)
+	/* RAS_CLK_ENB register masks */
+	#define SPEAR1310_SYNT3_CLK_ENB			17
+	#define SPEAR1310_SYNT2_CLK_ENB			16
+	#define SPEAR1310_SYNT1_CLK_ENB			15
+	#define SPEAR1310_SYNT0_CLK_ENB			14
+	#define SPEAR1310_PCLK3_CLK_ENB			13
+	#define SPEAR1310_PCLK2_CLK_ENB			12
+	#define SPEAR1310_PCLK1_CLK_ENB			11
+	#define SPEAR1310_PCLK0_CLK_ENB			10
+	#define SPEAR1310_PLL3_CLK_ENB			9
+	#define SPEAR1310_PLL2_CLK_ENB			8
+	#define SPEAR1310_C125M_PAD_CLK_ENB		7
+	#define SPEAR1310_C30M_CLK_ENB			6
+	#define SPEAR1310_C48M_CLK_ENB			5
+	#define SPEAR1310_OSC_25M_CLK_ENB		4
+	#define SPEAR1310_OSC_32K_CLK_ENB		3
+	#define SPEAR1310_OSC_24M_CLK_ENB		2
+	#define SPEAR1310_PCLK_CLK_ENB			1
+	#define SPEAR1310_ACLK_CLK_ENB			0
+
+/* RAS Area Control Register */
+#define SPEAR1310_RAS_CTRL_REG0			(ras_base + 0x000)
+	#define SPEAR1310_SSP1_CLK_MASK			3
+	#define SPEAR1310_SSP1_CLK_SHIFT		26
+	#define SPEAR1310_TDM_CLK_MASK			1
+	#define SPEAR1310_TDM2_CLK_SHIFT		24
+	#define SPEAR1310_TDM1_CLK_SHIFT		23
+	#define SPEAR1310_I2C_CLK_MASK			1
+	#define SPEAR1310_I2C7_CLK_SHIFT		22
+	#define SPEAR1310_I2C6_CLK_SHIFT		21
+	#define SPEAR1310_I2C5_CLK_SHIFT		20
+	#define SPEAR1310_I2C4_CLK_SHIFT		19
+	#define SPEAR1310_I2C3_CLK_SHIFT		18
+	#define SPEAR1310_I2C2_CLK_SHIFT		17
+	#define SPEAR1310_I2C1_CLK_SHIFT		16
+	#define SPEAR1310_GPT64_CLK_MASK		1
+	#define SPEAR1310_GPT64_CLK_SHIFT		15
+	#define SPEAR1310_RAS_UART_CLK_MASK		1
+	#define SPEAR1310_UART5_CLK_SHIFT		14
+	#define SPEAR1310_UART4_CLK_SHIFT		13
+	#define SPEAR1310_UART3_CLK_SHIFT		12
+	#define SPEAR1310_UART2_CLK_SHIFT		11
+	#define SPEAR1310_UART1_CLK_SHIFT		10
+	#define SPEAR1310_PCI_CLK_MASK			1
+	#define SPEAR1310_PCI_CLK_SHIFT			0
+
+#define SPEAR1310_RAS_CTRL_REG1			(ras_base + 0x004)
+	#define SPEAR1310_PHY_CLK_MASK			0x3
+	#define SPEAR1310_RMII_PHY_CLK_SHIFT		0
+	#define SPEAR1310_SMII_RGMII_PHY_CLK_SHIFT	2
+
+#define SPEAR1310_RAS_SW_CLK_CTRL		(ras_base + 0x0148)
+	#define SPEAR1310_CAN1_CLK_ENB			25
+	#define SPEAR1310_CAN0_CLK_ENB			24
+	#define SPEAR1310_GPT64_CLK_ENB			23
+	#define SPEAR1310_SSP1_CLK_ENB			22
+	#define SPEAR1310_I2C7_CLK_ENB			21
+	#define SPEAR1310_I2C6_CLK_ENB			20
+	#define SPEAR1310_I2C5_CLK_ENB			19
+	#define SPEAR1310_I2C4_CLK_ENB			18
+	#define SPEAR1310_I2C3_CLK_ENB			17
+	#define SPEAR1310_I2C2_CLK_ENB			16
+	#define SPEAR1310_I2C1_CLK_ENB			15
+	#define SPEAR1310_UART5_CLK_ENB			14
+	#define SPEAR1310_UART4_CLK_ENB			13
+	#define SPEAR1310_UART3_CLK_ENB			12
+	#define SPEAR1310_UART2_CLK_ENB			11
+	#define SPEAR1310_UART1_CLK_ENB			10
+	#define SPEAR1310_RS485_1_CLK_ENB		9
+	#define SPEAR1310_RS485_0_CLK_ENB		8
+	#define SPEAR1310_TDM2_CLK_ENB			7
+	#define SPEAR1310_TDM1_CLK_ENB			6
+	#define SPEAR1310_PCI_CLK_ENB			5
+	#define SPEAR1310_GMII_CLK_ENB			4
+	#define SPEAR1310_MII2_CLK_ENB			3
+	#define SPEAR1310_MII1_CLK_ENB			2
+	#define SPEAR1310_MII0_CLK_ENB			1
+	#define SPEAR1310_ESRAM_CLK_ENB			0
+
+static DEFINE_SPINLOCK(_lock);
+
+/* pll rate configuration table, in ascending order of rates */
+static struct pll_rate_tbl pll_rtbl[] = {
+	/* PCLK 24MHz */
+	{.mode = 0, .m = 0x83, .n = 0x04, .p = 0x5}, /* vco 1572, pll 49.125 MHz */
+	{.mode = 0, .m = 0x7D, .n = 0x06, .p = 0x3}, /* vco 1000, pll 125 MHz */
+	{.mode = 0, .m = 0x64, .n = 0x06, .p = 0x1}, /* vco 800, pll 400 MHz */
+	{.mode = 0, .m = 0x7D, .n = 0x06, .p = 0x1}, /* vco 1000, pll 500 MHz */
+	{.mode = 0, .m = 0xA6, .n = 0x06, .p = 0x1}, /* vco 1328, pll 664 MHz */
+	{.mode = 0, .m = 0xC8, .n = 0x06, .p = 0x1}, /* vco 1600, pll 800 MHz */
+	{.mode = 0, .m = 0x7D, .n = 0x06, .p = 0x0}, /* vco 1, pll 1 GHz */
+};
+
+/* vco-pll4 rate configuration table, in ascending order of rates */
+static struct pll_rate_tbl pll4_rtbl[] = {
+	{.mode = 0, .m = 0x7D, .n = 0x06, .p = 0x2}, /* vco 1000, pll 250 MHz */
+	{.mode = 0, .m = 0xA6, .n = 0x06, .p = 0x2}, /* vco 1328, pll 332 MHz */
+	{.mode = 0, .m = 0xC8, .n = 0x06, .p = 0x2}, /* vco 1600, pll 400 MHz */
+	{.mode = 0, .m = 0x7D, .n = 0x06, .p = 0x0}, /* vco 1, pll 1 GHz */
+};
+
+/* aux rate configuration table, in ascending order of rates */
+static struct aux_rate_tbl aux_rtbl[] = {
+	/* For VCO1div2 = 500 MHz */
+	{.xscale = 10, .yscale = 204, .eq = 0}, /* 12.29 MHz */
+	{.xscale = 4, .yscale = 21, .eq = 0}, /* 48 MHz */
+	{.xscale = 2, .yscale = 6, .eq = 0}, /* 83 MHz */
+	{.xscale = 2, .yscale = 4, .eq = 0}, /* 125 MHz */
+	{.xscale = 1, .yscale = 3, .eq = 1}, /* 166 MHz */
+	{.xscale = 1, .yscale = 2, .eq = 1}, /* 250 MHz */
+};
+
+/* gmac rate configuration table, in ascending order of rates */
+static struct aux_rate_tbl gmac_rtbl[] = {
+	/* For gmac phy input clk */
+	{.xscale = 2, .yscale = 6, .eq = 0}, /* divided by 6 */
+	{.xscale = 2, .yscale = 4, .eq = 0}, /* divided by 4 */
+	{.xscale = 1, .yscale = 3, .eq = 1}, /* divided by 3 */
+	{.xscale = 1, .yscale = 2, .eq = 1}, /* divided by 2 */
+};
+
+/* clcd rate configuration table, in ascending order of rates */
+static struct frac_rate_tbl clcd_rtbl[] = {
+	{.div = 0x14000}, /* 25 Mhz , for vc01div4 = 250 MHz*/
+	{.div = 0x1284B}, /* 27 Mhz , for vc01div4 = 250 MHz*/
+	{.div = 0x0D8D3}, /* 58 Mhz , for vco1div4 = 393 MHz */
+	{.div = 0x0B72C}, /* 58 Mhz , for vco1div4 = 332 MHz */
+	{.div = 0x089EE}, /* 58 Mhz , for vc01div4 = 250 MHz*/
+	{.div = 0x06f1C}, /* 72 Mhz , for vc01div4 = 250 MHz*/
+	{.div = 0x06E58}, /* 58 Mhz , for vco1div4 = 200 MHz */
+	{.div = 0x06c1B}, /* 74 Mhz , for vc01div4 = 250 MHz*/
+	{.div = 0x04A12}, /* 108 Mhz , for vc01div4 = 250 MHz*/
+	{.div = 0x0378E}, /* 144 Mhz , for vc01div4 = 250 MHz*/
+};
+
+/* i2s prescaler1 masks */
+static const struct aux_clk_masks i2s_prs1_masks = {
+	.eq_sel_mask = AUX_EQ_SEL_MASK,
+	.eq_sel_shift = SPEAR1310_I2S_PRS1_EQ_SEL_SHIFT,
+	.eq1_mask = AUX_EQ1_SEL,
+	.eq2_mask = AUX_EQ2_SEL,
+	.xscale_sel_mask = SPEAR1310_I2S_PRS1_CLK_X_MASK,
+	.xscale_sel_shift = SPEAR1310_I2S_PRS1_CLK_X_SHIFT,
+	.yscale_sel_mask = SPEAR1310_I2S_PRS1_CLK_Y_MASK,
+	.yscale_sel_shift = SPEAR1310_I2S_PRS1_CLK_Y_SHIFT,
+};
+
+/* i2s sclk (bit clock) syynthesizers masks */
+static struct aux_clk_masks i2s_sclk_masks = {
+	.eq_sel_mask = AUX_EQ_SEL_MASK,
+	.eq_sel_shift = SPEAR1310_I2S_SCLK_EQ_SEL_SHIFT,
+	.eq1_mask = AUX_EQ1_SEL,
+	.eq2_mask = AUX_EQ2_SEL,
+	.xscale_sel_mask = SPEAR1310_I2S_SCLK_X_MASK,
+	.xscale_sel_shift = SPEAR1310_I2S_SCLK_X_SHIFT,
+	.yscale_sel_mask = SPEAR1310_I2S_SCLK_Y_MASK,
+	.yscale_sel_shift = SPEAR1310_I2S_SCLK_Y_SHIFT,
+	.enable_bit = SPEAR1310_I2S_SCLK_SYNTH_ENB,
+};
+
+/* i2s prs1 aux rate configuration table, in ascending order of rates */
+static struct aux_rate_tbl i2s_prs1_rtbl[] = {
+	/* For parent clk = 49.152 MHz */
+	{.xscale = 1, .yscale = 12, .eq = 0}, /* 2.048 MHz, smp freq = 8Khz */
+	{.xscale = 11, .yscale = 96, .eq = 0}, /* 2.816 MHz, smp freq = 11Khz */
+	{.xscale = 1, .yscale = 6, .eq = 0}, /* 4.096 MHz, smp freq = 16Khz */
+	{.xscale = 11, .yscale = 48, .eq = 0}, /* 5.632 MHz, smp freq = 22Khz */
+
+	/*
+	 * with parent clk = 49.152, freq gen is 8.192 MHz, smp freq = 32Khz
+	 * with parent clk = 12.288, freq gen is 2.048 MHz, smp freq = 8Khz
+	 */
+	{.xscale = 1, .yscale = 3, .eq = 0},
+
+	/* For parent clk = 49.152 MHz */
+	{.xscale = 17, .yscale = 37, .eq = 0}, /* 11.289 MHz, smp freq = 44Khz*/
+
+	{.xscale = 1, .yscale = 2, .eq = 0}, /* 12.288 MHz */
+};
+
+/* i2s sclk aux rate configuration table, in ascending order of rates */
+static struct aux_rate_tbl i2s_sclk_rtbl[] = {
+	/* For i2s_ref_clk = 12.288MHz */
+	{.xscale = 1, .yscale = 4, .eq = 0}, /* 1.53 MHz */
+	{.xscale = 1, .yscale = 2, .eq = 0}, /* 3.07 Mhz */
+};
+
+/* adc rate configuration table, in ascending order of rates */
+/* possible adc range is 2.5 MHz to 20 MHz. */
+static struct aux_rate_tbl adc_rtbl[] = {
+	/* For ahb = 166.67 MHz */
+	{.xscale = 1, .yscale = 31, .eq = 0}, /* 2.68 MHz */
+	{.xscale = 2, .yscale = 21, .eq = 0}, /* 7.94 MHz */
+	{.xscale = 4, .yscale = 21, .eq = 0}, /* 15.87 MHz */
+	{.xscale = 10, .yscale = 42, .eq = 0}, /* 19.84 MHz */
+};
+
+/* General synth rate configuration table, in ascending order of rates */
+static struct frac_rate_tbl gen_rtbl[] = {
+	/* For vco1div4 = 250 MHz */
+	{.div = 0x14000}, /* 25 MHz */
+	{.div = 0x0A000}, /* 50 MHz */
+	{.div = 0x05000}, /* 100 MHz */
+	{.div = 0x02000}, /* 250 MHz */
+};
+
+/* clock parents */
+static const char *vco_parents[] = { "osc_24m_clk", "osc_25m_clk", };
+static const char *gpt_parents[] = { "osc_24m_clk", "apb_clk", };
+static const char *uart0_parents[] = { "pll5_clk", "uart_syn_gclk", };
+static const char *c3_parents[] = { "pll5_clk", "c3_syn_gclk", };
+static const char *gmac_phy_input_parents[] = { "gmii_pad_clk", "pll2_clk",
+	"osc_25m_clk", };
+static const char *gmac_phy_parents[] = { "phy_input_mclk", "phy_syn_gclk", };
+static const char *clcd_synth_parents[] = { "vco1div4_clk", "pll2_clk", };
+static const char *clcd_pixel_parents[] = { "pll5_clk", "clcd_syn_clk", };
+static const char *i2s_src_parents[] = { "vco1div2_clk", "none", "pll3_clk",
+	"i2s_src_pad_clk", };
+static const char *i2s_ref_parents[] = { "i2s_src_mclk", "i2s_prs1_clk", };
+static const char *gen_synth0_1_parents[] = { "vco1div4_clk", "vco3div2_clk",
+	"pll3_clk", };
+static const char *gen_synth2_3_parents[] = { "vco1div4_clk", "vco3div2_clk",
+	"pll2_clk", };
+static const char *rmii_phy_parents[] = { "ras_tx50_clk", "none",
+	"ras_pll2_clk", "ras_syn0_clk", };
+static const char *smii_rgmii_phy_parents[] = { "none", "ras_tx125_clk",
+	"ras_pll2_clk", "ras_syn0_clk", };
+static const char *uart_parents[] = { "ras_apb_clk", "gen_syn3_clk", };
+static const char *i2c_parents[] = { "ras_apb_clk", "gen_syn1_clk", };
+static const char *ssp1_parents[] = { "ras_apb_clk", "gen_syn1_clk",
+	"ras_plclk0_clk", };
+static const char *pci_parents[] = { "ras_pll3_clk", "gen_syn2_clk", };
+static const char *tdm_parents[] = { "ras_pll3_clk", "gen_syn1_clk", };
+
+void __init spear1310_clk_init(void __iomem *misc_base, void __iomem *ras_base)
+{
+	struct clk *clk, *clk1;
+
+	clk = clk_register_fixed_rate(NULL, "osc_32k_clk", NULL, 0, 32000);
+	clk_register_clkdev(clk, "osc_32k_clk", NULL);
+
+	clk = clk_register_fixed_rate(NULL, "osc_24m_clk", NULL, 0, 24000000);
+	clk_register_clkdev(clk, "osc_24m_clk", NULL);
+
+	clk = clk_register_fixed_rate(NULL, "osc_25m_clk", NULL, 0, 25000000);
+	clk_register_clkdev(clk, "osc_25m_clk", NULL);
+
+	clk = clk_register_fixed_rate(NULL, "gmii_pad_clk", NULL, 0, 125000000);
+	clk_register_clkdev(clk, "gmii_pad_clk", NULL);
+
+	clk = clk_register_fixed_rate(NULL, "i2s_src_pad_clk", NULL, 0,
+				      12288000);
+	clk_register_clkdev(clk, "i2s_src_pad_clk", NULL);
+
+	/* clock derived from 32 KHz osc clk */
+	clk = clk_register_gate(NULL, "rtc-spear", "osc_32k_clk", 0,
+			SPEAR1310_PERIP1_CLK_ENB, SPEAR1310_RTC_CLK_ENB, 0,
+			&_lock);
+	clk_register_clkdev(clk, NULL, "e0580000.rtc");
+
+	/* clock derived from 24 or 25 MHz osc clk */
+	/* vco-pll */
+	clk = clk_register_mux(NULL, "vco1_mclk", vco_parents,
+			ARRAY_SIZE(vco_parents), CLK_SET_RATE_NO_REPARENT,
+			SPEAR1310_PLL_CFG, SPEAR1310_PLL1_CLK_SHIFT,
+			SPEAR1310_PLL_CLK_MASK, 0, &_lock);
+	clk_register_clkdev(clk, "vco1_mclk", NULL);
+	clk = clk_register_vco_pll("vco1_clk", "pll1_clk", NULL, "vco1_mclk",
+			0, SPEAR1310_PLL1_CTR, SPEAR1310_PLL1_FRQ, pll_rtbl,
+			ARRAY_SIZE(pll_rtbl), &_lock, &clk1, NULL);
+	clk_register_clkdev(clk, "vco1_clk", NULL);
+	clk_register_clkdev(clk1, "pll1_clk", NULL);
+
+	clk = clk_register_mux(NULL, "vco2_mclk", vco_parents,
+			ARRAY_SIZE(vco_parents), CLK_SET_RATE_NO_REPARENT,
+			SPEAR1310_PLL_CFG, SPEAR1310_PLL2_CLK_SHIFT,
+			SPEAR1310_PLL_CLK_MASK, 0, &_lock);
+	clk_register_clkdev(clk, "vco2_mclk", NULL);
+	clk = clk_register_vco_pll("vco2_clk", "pll2_clk", NULL, "vco2_mclk",
+			0, SPEAR1310_PLL2_CTR, SPEAR1310_PLL2_FRQ, pll_rtbl,
+			ARRAY_SIZE(pll_rtbl), &_lock, &clk1, NULL);
+	clk_register_clkdev(clk, "vco2_clk", NULL);
+	clk_register_clkdev(clk1, "pll2_clk", NULL);
+
+	clk = clk_register_mux(NULL, "vco3_mclk", vco_parents,
+			ARRAY_SIZE(vco_parents), CLK_SET_RATE_NO_REPARENT,
+			SPEAR1310_PLL_CFG, SPEAR1310_PLL3_CLK_SHIFT,
+			SPEAR1310_PLL_CLK_MASK, 0, &_lock);
+	clk_register_clkdev(clk, "vco3_mclk", NULL);
+	clk = clk_register_vco_pll("vco3_clk", "pll3_clk", NULL, "vco3_mclk",
+			0, SPEAR1310_PLL3_CTR, SPEAR1310_PLL3_FRQ, pll_rtbl,
+			ARRAY_SIZE(pll_rtbl), &_lock, &clk1, NULL);
+	clk_register_clkdev(clk, "vco3_clk", NULL);
+	clk_register_clkdev(clk1, "pll3_clk", NULL);
+
+	clk = clk_register_vco_pll("vco4_clk", "pll4_clk", NULL, "osc_24m_clk",
+			0, SPEAR1310_PLL4_CTR, SPEAR1310_PLL4_FRQ, pll4_rtbl,
+			ARRAY_SIZE(pll4_rtbl), &_lock, &clk1, NULL);
+	clk_register_clkdev(clk, "vco4_clk", NULL);
+	clk_register_clkdev(clk1, "pll4_clk", NULL);
+
+	clk = clk_register_fixed_rate(NULL, "pll5_clk", "osc_24m_clk", 0,
+			48000000);
+	clk_register_clkdev(clk, "pll5_clk", NULL);
+
+	clk = clk_register_fixed_rate(NULL, "pll6_clk", "osc_25m_clk", 0,
+			25000000);
+	clk_register_clkdev(clk, "pll6_clk", NULL);
+
+	/* vco div n clocks */
+	clk = clk_register_fixed_factor(NULL, "vco1div2_clk", "vco1_clk", 0, 1,
+			2);
+	clk_register_clkdev(clk, "vco1div2_clk", NULL);
+
+	clk = clk_register_fixed_factor(NULL, "vco1div4_clk", "vco1_clk", 0, 1,
+			4);
+	clk_register_clkdev(clk, "vco1div4_clk", NULL);
+
+	clk = clk_register_fixed_factor(NULL, "vco2div2_clk", "vco2_clk", 0, 1,
+			2);
+	clk_register_clkdev(clk, "vco2div2_clk", NULL);
+
+	clk = clk_register_fixed_factor(NULL, "vco3div2_clk", "vco3_clk", 0, 1,
+			2);
+	clk_register_clkdev(clk, "vco3div2_clk", NULL);
+
+	/* peripherals */
+	clk_register_fixed_factor(NULL, "thermal_clk", "osc_24m_clk", 0, 1,
+			128);
+	clk = clk_register_gate(NULL, "thermal_gclk", "thermal_clk", 0,
+			SPEAR1310_PERIP2_CLK_ENB, SPEAR1310_THSENS_CLK_ENB, 0,
+			&_lock);
+	clk_register_clkdev(clk, NULL, "spear_thermal");
+
+	/* clock derived from pll4 clk */
+	clk = clk_register_fixed_factor(NULL, "ddr_clk", "pll4_clk", 0, 1,
+			1);
+	clk_register_clkdev(clk, "ddr_clk", NULL);
+
+	/* clock derived from pll1 clk */
+	clk = clk_register_fixed_factor(NULL, "cpu_clk", "pll1_clk",
+			CLK_SET_RATE_PARENT, 1, 2);
+	clk_register_clkdev(clk, "cpu_clk", NULL);
+
+	clk = clk_register_fixed_factor(NULL, "wdt_clk", "cpu_clk", 0, 1,
+			2);
+	clk_register_clkdev(clk, NULL, "ec800620.wdt");
+
+	clk = clk_register_fixed_factor(NULL, "smp_twd_clk", "cpu_clk", 0, 1,
+			2);
+	clk_register_clkdev(clk, NULL, "smp_twd");
+
+	clk = clk_register_fixed_factor(NULL, "ahb_clk", "pll1_clk", 0, 1,
+			6);
+	clk_register_clkdev(clk, "ahb_clk", NULL);
+
+	clk = clk_register_fixed_factor(NULL, "apb_clk", "pll1_clk", 0, 1,
+			12);
+	clk_register_clkdev(clk, "apb_clk", NULL);
+
+	/* gpt clocks */
+	clk = clk_register_mux(NULL, "gpt0_mclk", gpt_parents,
+			ARRAY_SIZE(gpt_parents), CLK_SET_RATE_NO_REPARENT,
+			SPEAR1310_PERIP_CLK_CFG, SPEAR1310_GPT0_CLK_SHIFT,
+			SPEAR1310_GPT_CLK_MASK, 0, &_lock);
+	clk_register_clkdev(clk, "gpt0_mclk", NULL);
+	clk = clk_register_gate(NULL, "gpt0_clk", "gpt0_mclk", 0,
+			SPEAR1310_PERIP1_CLK_ENB, SPEAR1310_GPT0_CLK_ENB, 0,
+			&_lock);
+	clk_register_clkdev(clk, NULL, "gpt0");
+
+	clk = clk_register_mux(NULL, "gpt1_mclk", gpt_parents,
+			ARRAY_SIZE(gpt_parents), CLK_SET_RATE_NO_REPARENT,
+			SPEAR1310_PERIP_CLK_CFG, SPEAR1310_GPT1_CLK_SHIFT,
+			SPEAR1310_GPT_CLK_MASK, 0, &_lock);
+	clk_register_clkdev(clk, "gpt1_mclk", NULL);
+	clk = clk_register_gate(NULL, "gpt1_clk", "gpt1_mclk", 0,
+			SPEAR1310_PERIP1_CLK_ENB, SPEAR1310_GPT1_CLK_ENB, 0,
+			&_lock);
+	clk_register_clkdev(clk, NULL, "gpt1");
+
+	clk = clk_register_mux(NULL, "gpt2_mclk", gpt_parents,
+			ARRAY_SIZE(gpt_parents), CLK_SET_RATE_NO_REPARENT,
+			SPEAR1310_PERIP_CLK_CFG, SPEAR1310_GPT2_CLK_SHIFT,
+			SPEAR1310_GPT_CLK_MASK, 0, &_lock);
+	clk_register_clkdev(clk, "gpt2_mclk", NULL);
+	clk = clk_register_gate(NULL, "gpt2_clk", "gpt2_mclk", 0,
+			SPEAR1310_PERIP2_CLK_ENB, SPEAR1310_GPT2_CLK_ENB, 0,
+			&_lock);
+	clk_register_clkdev(clk, NULL, "gpt2");
+
+	clk = clk_register_mux(NULL, "gpt3_mclk", gpt_parents,
+			ARRAY_SIZE(gpt_parents), CLK_SET_RATE_NO_REPARENT,
+			SPEAR1310_PERIP_CLK_CFG, SPEAR1310_GPT3_CLK_SHIFT,
+			SPEAR1310_GPT_CLK_MASK, 0, &_lock);
+	clk_register_clkdev(clk, "gpt3_mclk", NULL);
+	clk = clk_register_gate(NULL, "gpt3_clk", "gpt3_mclk", 0,
+			SPEAR1310_PERIP2_CLK_ENB, SPEAR1310_GPT3_CLK_ENB, 0,
+			&_lock);
+	clk_register_clkdev(clk, NULL, "gpt3");
+
+	/* others */
+	clk = clk_register_aux("uart_syn_clk", "uart_syn_gclk", "vco1div2_clk",
+			0, SPEAR1310_UART_CLK_SYNT, NULL, aux_rtbl,
+			ARRAY_SIZE(aux_rtbl), &_lock, &clk1);
+	clk_register_clkdev(clk, "uart_syn_clk", NULL);
+	clk_register_clkdev(clk1, "uart_syn_gclk", NULL);
+
+	clk = clk_register_mux(NULL, "uart0_mclk", uart0_parents,
+			ARRAY_SIZE(uart0_parents),
+			CLK_SET_RATE_PARENT | CLK_SET_RATE_NO_REPARENT,
+			SPEAR1310_PERIP_CLK_CFG, SPEAR1310_UART_CLK_SHIFT,
+			SPEAR1310_UART_CLK_MASK, 0, &_lock);
+	clk_register_clkdev(clk, "uart0_mclk", NULL);
+
+	clk = clk_register_gate(NULL, "uart0_clk", "uart0_mclk",
+			CLK_SET_RATE_PARENT, SPEAR1310_PERIP1_CLK_ENB,
+			SPEAR1310_UART_CLK_ENB, 0, &_lock);
+	clk_register_clkdev(clk, NULL, "e0000000.serial");
+
+	clk = clk_register_aux("sdhci_syn_clk", "sdhci_syn_gclk",
+			"vco1div2_clk", 0, SPEAR1310_SDHCI_CLK_SYNT, NULL,
+			aux_rtbl, ARRAY_SIZE(aux_rtbl), &_lock, &clk1);
+	clk_register_clkdev(clk, "sdhci_syn_clk", NULL);
+	clk_register_clkdev(clk1, "sdhci_syn_gclk", NULL);
+
+	clk = clk_register_gate(NULL, "sdhci_clk", "sdhci_syn_gclk",
+			CLK_SET_RATE_PARENT, SPEAR1310_PERIP1_CLK_ENB,
+			SPEAR1310_SDHCI_CLK_ENB, 0, &_lock);
+	clk_register_clkdev(clk, NULL, "b3000000.sdhci");
+
+	clk = clk_register_aux("cfxd_syn_clk", "cfxd_syn_gclk", "vco1div2_clk",
+			0, SPEAR1310_CFXD_CLK_SYNT, NULL, aux_rtbl,
+			ARRAY_SIZE(aux_rtbl), &_lock, &clk1);
+	clk_register_clkdev(clk, "cfxd_syn_clk", NULL);
+	clk_register_clkdev(clk1, "cfxd_syn_gclk", NULL);
+
+	clk = clk_register_gate(NULL, "cfxd_clk", "cfxd_syn_gclk",
+			CLK_SET_RATE_PARENT, SPEAR1310_PERIP1_CLK_ENB,
+			SPEAR1310_CFXD_CLK_ENB, 0, &_lock);
+	clk_register_clkdev(clk, NULL, "b2800000.cf");
+	clk_register_clkdev(clk, NULL, "arasan_xd");
+
+	clk = clk_register_aux("c3_syn_clk", "c3_syn_gclk", "vco1div2_clk",
+			0, SPEAR1310_C3_CLK_SYNT, NULL, aux_rtbl,
+			ARRAY_SIZE(aux_rtbl), &_lock, &clk1);
+	clk_register_clkdev(clk, "c3_syn_clk", NULL);
+	clk_register_clkdev(clk1, "c3_syn_gclk", NULL);
+
+	clk = clk_register_mux(NULL, "c3_mclk", c3_parents,
+			ARRAY_SIZE(c3_parents),
+			CLK_SET_RATE_PARENT | CLK_SET_RATE_NO_REPARENT,
+			SPEAR1310_PERIP_CLK_CFG, SPEAR1310_C3_CLK_SHIFT,
+			SPEAR1310_C3_CLK_MASK, 0, &_lock);
+	clk_register_clkdev(clk, "c3_mclk", NULL);
+
+	clk = clk_register_gate(NULL, "c3_clk", "c3_mclk", 0,
+			SPEAR1310_PERIP1_CLK_ENB, SPEAR1310_C3_CLK_ENB, 0,
+			&_lock);
+	clk_register_clkdev(clk, NULL, "c3");
+
+	/* gmac */
+	clk = clk_register_mux(NULL, "phy_input_mclk", gmac_phy_input_parents,
+			ARRAY_SIZE(gmac_phy_input_parents),
+			CLK_SET_RATE_NO_REPARENT, SPEAR1310_GMAC_CLK_CFG,
+			SPEAR1310_GMAC_PHY_INPUT_CLK_SHIFT,
+			SPEAR1310_GMAC_PHY_INPUT_CLK_MASK, 0, &_lock);
+	clk_register_clkdev(clk, "phy_input_mclk", NULL);
+
+	clk = clk_register_aux("phy_syn_clk", "phy_syn_gclk", "phy_input_mclk",
+			0, SPEAR1310_GMAC_CLK_SYNT, NULL, gmac_rtbl,
+			ARRAY_SIZE(gmac_rtbl), &_lock, &clk1);
+	clk_register_clkdev(clk, "phy_syn_clk", NULL);
+	clk_register_clkdev(clk1, "phy_syn_gclk", NULL);
+
+	clk = clk_register_mux(NULL, "phy_mclk", gmac_phy_parents,
+			ARRAY_SIZE(gmac_phy_parents), CLK_SET_RATE_NO_REPARENT,
+			SPEAR1310_PERIP_CLK_CFG, SPEAR1310_GMAC_PHY_CLK_SHIFT,
+			SPEAR1310_GMAC_PHY_CLK_MASK, 0, &_lock);
+	clk_register_clkdev(clk, "stmmacphy.0", NULL);
+
+	/* clcd */
+	clk = clk_register_mux(NULL, "clcd_syn_mclk", clcd_synth_parents,
+			ARRAY_SIZE(clcd_synth_parents),
+			CLK_SET_RATE_NO_REPARENT, SPEAR1310_CLCD_CLK_SYNT,
+			SPEAR1310_CLCD_SYNT_CLK_SHIFT,
+			SPEAR1310_CLCD_SYNT_CLK_MASK, 0, &_lock);
+	clk_register_clkdev(clk, "clcd_syn_mclk", NULL);
+
+	clk = clk_register_frac("clcd_syn_clk", "clcd_syn_mclk", 0,
+			SPEAR1310_CLCD_CLK_SYNT, clcd_rtbl,
+			ARRAY_SIZE(clcd_rtbl), &_lock);
+	clk_register_clkdev(clk, "clcd_syn_clk", NULL);
+
+	clk = clk_register_mux(NULL, "clcd_pixel_mclk", clcd_pixel_parents,
+			ARRAY_SIZE(clcd_pixel_parents),
+			CLK_SET_RATE_PARENT | CLK_SET_RATE_NO_REPARENT,
+			SPEAR1310_PERIP_CLK_CFG, SPEAR1310_CLCD_CLK_SHIFT,
+			SPEAR1310_CLCD_CLK_MASK, 0, &_lock);
+	clk_register_clkdev(clk, "clcd_pixel_mclk", NULL);
+
+	clk = clk_register_gate(NULL, "clcd_clk", "clcd_pixel_mclk", 0,
+			SPEAR1310_PERIP1_CLK_ENB, SPEAR1310_CLCD_CLK_ENB, 0,
+			&_lock);
+	clk_register_clkdev(clk, NULL, "e1000000.clcd");
+
+	/* i2s */
+	clk = clk_register_mux(NULL, "i2s_src_mclk", i2s_src_parents,
+			ARRAY_SIZE(i2s_src_parents), CLK_SET_RATE_NO_REPARENT,
+			SPEAR1310_I2S_CLK_CFG, SPEAR1310_I2S_SRC_CLK_SHIFT,
+			SPEAR1310_I2S_SRC_CLK_MASK, 0, &_lock);
+	clk_register_clkdev(clk, "i2s_src_mclk", NULL);
+
+	clk = clk_register_aux("i2s_prs1_clk", NULL, "i2s_src_mclk", 0,
+			SPEAR1310_I2S_CLK_CFG, &i2s_prs1_masks, i2s_prs1_rtbl,
+			ARRAY_SIZE(i2s_prs1_rtbl), &_lock, NULL);
+	clk_register_clkdev(clk, "i2s_prs1_clk", NULL);
+
+	clk = clk_register_mux(NULL, "i2s_ref_mclk", i2s_ref_parents,
+			ARRAY_SIZE(i2s_ref_parents),
+			CLK_SET_RATE_PARENT | CLK_SET_RATE_NO_REPARENT,
+			SPEAR1310_I2S_CLK_CFG, SPEAR1310_I2S_REF_SHIFT,
+			SPEAR1310_I2S_REF_SEL_MASK, 0, &_lock);
+	clk_register_clkdev(clk, "i2s_ref_mclk", NULL);
+
+	clk = clk_register_gate(NULL, "i2s_ref_pad_clk", "i2s_ref_mclk", 0,
+			SPEAR1310_PERIP2_CLK_ENB, SPEAR1310_I2S_REF_PAD_CLK_ENB,
+			0, &_lock);
+	clk_register_clkdev(clk, "i2s_ref_pad_clk", NULL);
+
+	clk = clk_register_aux("i2s_sclk_clk", "i2s_sclk_gclk",
+			"i2s_ref_mclk", 0, SPEAR1310_I2S_CLK_CFG,
+			&i2s_sclk_masks, i2s_sclk_rtbl,
+			ARRAY_SIZE(i2s_sclk_rtbl), &_lock, &clk1);
+	clk_register_clkdev(clk, "i2s_sclk_clk", NULL);
+	clk_register_clkdev(clk1, "i2s_sclk_gclk", NULL);
+
+	/* clock derived from ahb clk */
+	clk = clk_register_gate(NULL, "i2c0_clk", "ahb_clk", 0,
+			SPEAR1310_PERIP1_CLK_ENB, SPEAR1310_I2C0_CLK_ENB, 0,
+			&_lock);
+	clk_register_clkdev(clk, NULL, "e0280000.i2c");
+
+	clk = clk_register_gate(NULL, "dma_clk", "ahb_clk", 0,
+			SPEAR1310_PERIP1_CLK_ENB, SPEAR1310_DMA_CLK_ENB, 0,
+			&_lock);
+	clk_register_clkdev(clk, NULL, "ea800000.dma");
+	clk_register_clkdev(clk, NULL, "eb000000.dma");
+
+	clk = clk_register_gate(NULL, "jpeg_clk", "ahb_clk", 0,
+			SPEAR1310_PERIP1_CLK_ENB, SPEAR1310_JPEG_CLK_ENB, 0,
+			&_lock);
+	clk_register_clkdev(clk, NULL, "b2000000.jpeg");
+
+	clk = clk_register_gate(NULL, "gmac_clk", "ahb_clk", 0,
+			SPEAR1310_PERIP1_CLK_ENB, SPEAR1310_GMAC_CLK_ENB, 0,
+			&_lock);
+	clk_register_clkdev(clk, NULL, "e2000000.eth");
+
+	clk = clk_register_gate(NULL, "fsmc_clk", "ahb_clk", 0,
+			SPEAR1310_PERIP1_CLK_ENB, SPEAR1310_FSMC_CLK_ENB, 0,
+			&_lock);
+	clk_register_clkdev(clk, NULL, "b0000000.flash");
+
+	clk = clk_register_gate(NULL, "smi_clk", "ahb_clk", 0,
+			SPEAR1310_PERIP1_CLK_ENB, SPEAR1310_SMI_CLK_ENB, 0,
+			&_lock);
+	clk_register_clkdev(clk, NULL, "ea000000.flash");
+
+	clk = clk_register_gate(NULL, "usbh0_clk", "ahb_clk", 0,
+			SPEAR1310_PERIP1_CLK_ENB, SPEAR1310_UHC0_CLK_ENB, 0,
+			&_lock);
+	clk_register_clkdev(clk, NULL, "e4000000.ohci");
+	clk_register_clkdev(clk, NULL, "e4800000.ehci");
+
+	clk = clk_register_gate(NULL, "usbh1_clk", "ahb_clk", 0,
+			SPEAR1310_PERIP1_CLK_ENB, SPEAR1310_UHC1_CLK_ENB, 0,
+			&_lock);
+	clk_register_clkdev(clk, NULL, "e5000000.ohci");
+	clk_register_clkdev(clk, NULL, "e5800000.ehci");
+
+	clk = clk_register_gate(NULL, "uoc_clk", "ahb_clk", 0,
+			SPEAR1310_PERIP1_CLK_ENB, SPEAR1310_UOC_CLK_ENB, 0,
+			&_lock);
+	clk_register_clkdev(clk, NULL, "e3800000.otg");
+
+	clk = clk_register_gate(NULL, "pcie_sata_0_clk", "ahb_clk", 0,
+			SPEAR1310_PERIP1_CLK_ENB, SPEAR1310_PCIE_SATA_0_CLK_ENB,
+			0, &_lock);
+	clk_register_clkdev(clk, NULL, "b1000000.pcie");
+	clk_register_clkdev(clk, NULL, "b1000000.ahci");
+
+	clk = clk_register_gate(NULL, "pcie_sata_1_clk", "ahb_clk", 0,
+			SPEAR1310_PERIP1_CLK_ENB, SPEAR1310_PCIE_SATA_1_CLK_ENB,
+			0, &_lock);
+	clk_register_clkdev(clk, NULL, "b1800000.pcie");
+	clk_register_clkdev(clk, NULL, "b1800000.ahci");
+
+	clk = clk_register_gate(NULL, "pcie_sata_2_clk", "ahb_clk", 0,
+			SPEAR1310_PERIP1_CLK_ENB, SPEAR1310_PCIE_SATA_2_CLK_ENB,
+			0, &_lock);
+	clk_register_clkdev(clk, NULL, "b4000000.pcie");
+	clk_register_clkdev(clk, NULL, "b4000000.ahci");
+
+	clk = clk_register_gate(NULL, "sysram0_clk", "ahb_clk", 0,
+			SPEAR1310_PERIP1_CLK_ENB, SPEAR1310_SYSRAM0_CLK_ENB, 0,
+			&_lock);
+	clk_register_clkdev(clk, "sysram0_clk", NULL);
+
+	clk = clk_register_gate(NULL, "sysram1_clk", "ahb_clk", 0,
+			SPEAR1310_PERIP1_CLK_ENB, SPEAR1310_SYSRAM1_CLK_ENB, 0,
+			&_lock);
+	clk_register_clkdev(clk, "sysram1_clk", NULL);
+
+	clk = clk_register_aux("adc_syn_clk", "adc_syn_gclk", "ahb_clk",
+			0, SPEAR1310_ADC_CLK_SYNT, NULL, adc_rtbl,
+			ARRAY_SIZE(adc_rtbl), &_lock, &clk1);
+	clk_register_clkdev(clk, "adc_syn_clk", NULL);
+	clk_register_clkdev(clk1, "adc_syn_gclk", NULL);
+
+	clk = clk_register_gate(NULL, "adc_clk", "adc_syn_gclk",
+			CLK_SET_RATE_PARENT, SPEAR1310_PERIP1_CLK_ENB,
+			SPEAR1310_ADC_CLK_ENB, 0, &_lock);
+	clk_register_clkdev(clk, NULL, "e0080000.adc");
+
+	/* clock derived from apb clk */
+	clk = clk_register_gate(NULL, "ssp0_clk", "apb_clk", 0,
+			SPEAR1310_PERIP1_CLK_ENB, SPEAR1310_SSP_CLK_ENB, 0,
+			&_lock);
+	clk_register_clkdev(clk, NULL, "e0100000.spi");
+
+	clk = clk_register_gate(NULL, "gpio0_clk", "apb_clk", 0,
+			SPEAR1310_PERIP1_CLK_ENB, SPEAR1310_GPIO0_CLK_ENB, 0,
+			&_lock);
+	clk_register_clkdev(clk, NULL, "e0600000.gpio");
+
+	clk = clk_register_gate(NULL, "gpio1_clk", "apb_clk", 0,
+			SPEAR1310_PERIP1_CLK_ENB, SPEAR1310_GPIO1_CLK_ENB, 0,
+			&_lock);
+	clk_register_clkdev(clk, NULL, "e0680000.gpio");
+
+	clk = clk_register_gate(NULL, "i2s0_clk", "apb_clk", 0,
+			SPEAR1310_PERIP1_CLK_ENB, SPEAR1310_I2S0_CLK_ENB, 0,
+			&_lock);
+	clk_register_clkdev(clk, NULL, "e0180000.i2s");
+
+	clk = clk_register_gate(NULL, "i2s1_clk", "apb_clk", 0,
+			SPEAR1310_PERIP1_CLK_ENB, SPEAR1310_I2S1_CLK_ENB, 0,
+			&_lock);
+	clk_register_clkdev(clk, NULL, "e0200000.i2s");
+
+	clk = clk_register_gate(NULL, "kbd_clk", "apb_clk", 0,
+			SPEAR1310_PERIP2_CLK_ENB, SPEAR1310_KBD_CLK_ENB, 0,
+			&_lock);
+	clk_register_clkdev(clk, NULL, "e0300000.kbd");
+
+	/* RAS clks */
+	clk = clk_register_mux(NULL, "gen_syn0_1_mclk", gen_synth0_1_parents,
+			ARRAY_SIZE(gen_synth0_1_parents),
+			CLK_SET_RATE_NO_REPARENT, SPEAR1310_PLL_CFG,
+			SPEAR1310_RAS_SYNT0_1_CLK_SHIFT,
+			SPEAR1310_RAS_SYNT_CLK_MASK, 0, &_lock);
+	clk_register_clkdev(clk, "gen_syn0_1_clk", NULL);
+
+	clk = clk_register_mux(NULL, "gen_syn2_3_mclk", gen_synth2_3_parents,
+			ARRAY_SIZE(gen_synth2_3_parents),
+			CLK_SET_RATE_NO_REPARENT, SPEAR1310_PLL_CFG,
+			SPEAR1310_RAS_SYNT2_3_CLK_SHIFT,
+			SPEAR1310_RAS_SYNT_CLK_MASK, 0, &_lock);
+	clk_register_clkdev(clk, "gen_syn2_3_clk", NULL);
+
+	clk = clk_register_frac("gen_syn0_clk", "gen_syn0_1_clk", 0,
+			SPEAR1310_RAS_CLK_SYNT0, gen_rtbl, ARRAY_SIZE(gen_rtbl),
+			&_lock);
+	clk_register_clkdev(clk, "gen_syn0_clk", NULL);
+
+	clk = clk_register_frac("gen_syn1_clk", "gen_syn0_1_clk", 0,
+			SPEAR1310_RAS_CLK_SYNT1, gen_rtbl, ARRAY_SIZE(gen_rtbl),
+			&_lock);
+	clk_register_clkdev(clk, "gen_syn1_clk", NULL);
+
+	clk = clk_register_frac("gen_syn2_clk", "gen_syn2_3_clk", 0,
+			SPEAR1310_RAS_CLK_SYNT2, gen_rtbl, ARRAY_SIZE(gen_rtbl),
+			&_lock);
+	clk_register_clkdev(clk, "gen_syn2_clk", NULL);
+
+	clk = clk_register_frac("gen_syn3_clk", "gen_syn2_3_clk", 0,
+			SPEAR1310_RAS_CLK_SYNT3, gen_rtbl, ARRAY_SIZE(gen_rtbl),
+			&_lock);
+	clk_register_clkdev(clk, "gen_syn3_clk", NULL);
+
+	clk = clk_register_gate(NULL, "ras_osc_24m_clk", "osc_24m_clk", 0,
+			SPEAR1310_RAS_CLK_ENB, SPEAR1310_OSC_24M_CLK_ENB, 0,
+			&_lock);
+	clk_register_clkdev(clk, "ras_osc_24m_clk", NULL);
+
+	clk = clk_register_gate(NULL, "ras_osc_25m_clk", "osc_25m_clk", 0,
+			SPEAR1310_RAS_CLK_ENB, SPEAR1310_OSC_25M_CLK_ENB, 0,
+			&_lock);
+	clk_register_clkdev(clk, "ras_osc_25m_clk", NULL);
+
+	clk = clk_register_gate(NULL, "ras_osc_32k_clk", "osc_32k_clk", 0,
+			SPEAR1310_RAS_CLK_ENB, SPEAR1310_OSC_32K_CLK_ENB, 0,
+			&_lock);
+	clk_register_clkdev(clk, "ras_osc_32k_clk", NULL);
+
+	clk = clk_register_gate(NULL, "ras_pll2_clk", "pll2_clk", 0,
+			SPEAR1310_RAS_CLK_ENB, SPEAR1310_PLL2_CLK_ENB, 0,
+			&_lock);
+	clk_register_clkdev(clk, "ras_pll2_clk", NULL);
+
+	clk = clk_register_gate(NULL, "ras_pll3_clk", "pll3_clk", 0,
+			SPEAR1310_RAS_CLK_ENB, SPEAR1310_PLL3_CLK_ENB, 0,
+			&_lock);
+	clk_register_clkdev(clk, "ras_pll3_clk", NULL);
+
+	clk = clk_register_gate(NULL, "ras_tx125_clk", "gmii_pad_clk", 0,
+			SPEAR1310_RAS_CLK_ENB, SPEAR1310_C125M_PAD_CLK_ENB, 0,
+			&_lock);
+	clk_register_clkdev(clk, "ras_tx125_clk", NULL);
+
+	clk = clk_register_fixed_rate(NULL, "ras_30m_fixed_clk", "pll5_clk", 0,
+			30000000);
+	clk = clk_register_gate(NULL, "ras_30m_clk", "ras_30m_fixed_clk", 0,
+			SPEAR1310_RAS_CLK_ENB, SPEAR1310_C30M_CLK_ENB, 0,
+			&_lock);
+	clk_register_clkdev(clk, "ras_30m_clk", NULL);
+
+	clk = clk_register_fixed_rate(NULL, "ras_48m_fixed_clk", "pll5_clk", 0,
+			48000000);
+	clk = clk_register_gate(NULL, "ras_48m_clk", "ras_48m_fixed_clk", 0,
+			SPEAR1310_RAS_CLK_ENB, SPEAR1310_C48M_CLK_ENB, 0,
+			&_lock);
+	clk_register_clkdev(clk, "ras_48m_clk", NULL);
+
+	clk = clk_register_gate(NULL, "ras_ahb_clk", "ahb_clk", 0,
+			SPEAR1310_RAS_CLK_ENB, SPEAR1310_ACLK_CLK_ENB, 0,
+			&_lock);
+	clk_register_clkdev(clk, "ras_ahb_clk", NULL);
+
+	clk = clk_register_gate(NULL, "ras_apb_clk", "apb_clk", 0,
+			SPEAR1310_RAS_CLK_ENB, SPEAR1310_PCLK_CLK_ENB, 0,
+			&_lock);
+	clk_register_clkdev(clk, "ras_apb_clk", NULL);
+
+	clk = clk_register_fixed_rate(NULL, "ras_plclk0_clk", NULL, 0,
+			50000000);
+
+	clk = clk_register_fixed_rate(NULL, "ras_tx50_clk", NULL, 0, 50000000);
+
+	clk = clk_register_gate(NULL, "can0_clk", "apb_clk", 0,
+			SPEAR1310_RAS_SW_CLK_CTRL, SPEAR1310_CAN0_CLK_ENB, 0,
+			&_lock);
+	clk_register_clkdev(clk, NULL, "c_can_platform.0");
+
+	clk = clk_register_gate(NULL, "can1_clk", "apb_clk", 0,
+			SPEAR1310_RAS_SW_CLK_CTRL, SPEAR1310_CAN1_CLK_ENB, 0,
+			&_lock);
+	clk_register_clkdev(clk, NULL, "c_can_platform.1");
+
+	clk = clk_register_gate(NULL, "ras_smii0_clk", "ras_ahb_clk", 0,
+			SPEAR1310_RAS_SW_CLK_CTRL, SPEAR1310_MII0_CLK_ENB, 0,
+			&_lock);
+	clk_register_clkdev(clk, NULL, "5c400000.eth");
+
+	clk = clk_register_gate(NULL, "ras_smii1_clk", "ras_ahb_clk", 0,
+			SPEAR1310_RAS_SW_CLK_CTRL, SPEAR1310_MII1_CLK_ENB, 0,
+			&_lock);
+	clk_register_clkdev(clk, NULL, "5c500000.eth");
+
+	clk = clk_register_gate(NULL, "ras_smii2_clk", "ras_ahb_clk", 0,
+			SPEAR1310_RAS_SW_CLK_CTRL, SPEAR1310_MII2_CLK_ENB, 0,
+			&_lock);
+	clk_register_clkdev(clk, NULL, "5c600000.eth");
+
+	clk = clk_register_gate(NULL, "ras_rgmii_clk", "ras_ahb_clk", 0,
+			SPEAR1310_RAS_SW_CLK_CTRL, SPEAR1310_GMII_CLK_ENB, 0,
+			&_lock);
+	clk_register_clkdev(clk, NULL, "5c700000.eth");
+
+	clk = clk_register_mux(NULL, "smii_rgmii_phy_mclk",
+			smii_rgmii_phy_parents,
+			ARRAY_SIZE(smii_rgmii_phy_parents),
+			CLK_SET_RATE_NO_REPARENT, SPEAR1310_RAS_CTRL_REG1,
+			SPEAR1310_SMII_RGMII_PHY_CLK_SHIFT,
+			SPEAR1310_PHY_CLK_MASK, 0, &_lock);
+	clk_register_clkdev(clk, "stmmacphy.1", NULL);
+	clk_register_clkdev(clk, "stmmacphy.2", NULL);
+	clk_register_clkdev(clk, "stmmacphy.4", NULL);
+
+	clk = clk_register_mux(NULL, "rmii_phy_mclk", rmii_phy_parents,
+			ARRAY_SIZE(rmii_phy_parents), CLK_SET_RATE_NO_REPARENT,
+			SPEAR1310_RAS_CTRL_REG1, SPEAR1310_RMII_PHY_CLK_SHIFT,
+			SPEAR1310_PHY_CLK_MASK, 0, &_lock);
+	clk_register_clkdev(clk, "stmmacphy.3", NULL);
+
+	clk = clk_register_mux(NULL, "uart1_mclk", uart_parents,
+			ARRAY_SIZE(uart_parents), CLK_SET_RATE_NO_REPARENT,
+			SPEAR1310_RAS_CTRL_REG0, SPEAR1310_UART1_CLK_SHIFT,
+			SPEAR1310_RAS_UART_CLK_MASK, 0, &_lock);
+	clk_register_clkdev(clk, "uart1_mclk", NULL);
+
+	clk = clk_register_gate(NULL, "uart1_clk", "uart1_mclk", 0,
+			SPEAR1310_RAS_SW_CLK_CTRL, SPEAR1310_UART1_CLK_ENB, 0,
+			&_lock);
+	clk_register_clkdev(clk, NULL, "5c800000.serial");
+
+	clk = clk_register_mux(NULL, "uart2_mclk", uart_parents,
+			ARRAY_SIZE(uart_parents), CLK_SET_RATE_NO_REPARENT,
+			SPEAR1310_RAS_CTRL_REG0, SPEAR1310_UART2_CLK_SHIFT,
+			SPEAR1310_RAS_UART_CLK_MASK, 0, &_lock);
+	clk_register_clkdev(clk, "uart2_mclk", NULL);
+
+	clk = clk_register_gate(NULL, "uart2_clk", "uart2_mclk", 0,
+			SPEAR1310_RAS_SW_CLK_CTRL, SPEAR1310_UART2_CLK_ENB, 0,
+			&_lock);
+	clk_register_clkdev(clk, NULL, "5c900000.serial");
+
+	clk = clk_register_mux(NULL, "uart3_mclk", uart_parents,
+			ARRAY_SIZE(uart_parents), CLK_SET_RATE_NO_REPARENT,
+			SPEAR1310_RAS_CTRL_REG0, SPEAR1310_UART3_CLK_SHIFT,
+			SPEAR1310_RAS_UART_CLK_MASK, 0, &_lock);
+	clk_register_clkdev(clk, "uart3_mclk", NULL);
+
+	clk = clk_register_gate(NULL, "uart3_clk", "uart3_mclk", 0,
+			SPEAR1310_RAS_SW_CLK_CTRL, SPEAR1310_UART3_CLK_ENB, 0,
+			&_lock);
+	clk_register_clkdev(clk, NULL, "5ca00000.serial");
+
+	clk = clk_register_mux(NULL, "uart4_mclk", uart_parents,
+			ARRAY_SIZE(uart_parents), CLK_SET_RATE_NO_REPARENT,
+			SPEAR1310_RAS_CTRL_REG0, SPEAR1310_UART4_CLK_SHIFT,
+			SPEAR1310_RAS_UART_CLK_MASK, 0, &_lock);
+	clk_register_clkdev(clk, "uart4_mclk", NULL);
+
+	clk = clk_register_gate(NULL, "uart4_clk", "uart4_mclk", 0,
+			SPEAR1310_RAS_SW_CLK_CTRL, SPEAR1310_UART4_CLK_ENB, 0,
+			&_lock);
+	clk_register_clkdev(clk, NULL, "5cb00000.serial");
+
+	clk = clk_register_mux(NULL, "uart5_mclk", uart_parents,
+			ARRAY_SIZE(uart_parents), CLK_SET_RATE_NO_REPARENT,
+			SPEAR1310_RAS_CTRL_REG0, SPEAR1310_UART5_CLK_SHIFT,
+			SPEAR1310_RAS_UART_CLK_MASK, 0, &_lock);
+	clk_register_clkdev(clk, "uart5_mclk", NULL);
+
+	clk = clk_register_gate(NULL, "uart5_clk", "uart5_mclk", 0,
+			SPEAR1310_RAS_SW_CLK_CTRL, SPEAR1310_UART5_CLK_ENB, 0,
+			&_lock);
+	clk_register_clkdev(clk, NULL, "5cc00000.serial");
+
+	clk = clk_register_mux(NULL, "i2c1_mclk", i2c_parents,
+			ARRAY_SIZE(i2c_parents), CLK_SET_RATE_NO_REPARENT,
+			SPEAR1310_RAS_CTRL_REG0, SPEAR1310_I2C1_CLK_SHIFT,
+			SPEAR1310_I2C_CLK_MASK, 0, &_lock);
+	clk_register_clkdev(clk, "i2c1_mclk", NULL);
+
+	clk = clk_register_gate(NULL, "i2c1_clk", "i2c1_mclk", 0,
+			SPEAR1310_RAS_SW_CLK_CTRL, SPEAR1310_I2C1_CLK_ENB, 0,
+			&_lock);
+	clk_register_clkdev(clk, NULL, "5cd00000.i2c");
+
+	clk = clk_register_mux(NULL, "i2c2_mclk", i2c_parents,
+			ARRAY_SIZE(i2c_parents), CLK_SET_RATE_NO_REPARENT,
+			SPEAR1310_RAS_CTRL_REG0, SPEAR1310_I2C2_CLK_SHIFT,
+			SPEAR1310_I2C_CLK_MASK, 0, &_lock);
+	clk_register_clkdev(clk, "i2c2_mclk", NULL);
+
+	clk = clk_register_gate(NULL, "i2c2_clk", "i2c2_mclk", 0,
+			SPEAR1310_RAS_SW_CLK_CTRL, SPEAR1310_I2C2_CLK_ENB, 0,
+			&_lock);
+	clk_register_clkdev(clk, NULL, "5ce00000.i2c");
+
+	clk = clk_register_mux(NULL, "i2c3_mclk", i2c_parents,
+			ARRAY_SIZE(i2c_parents), CLK_SET_RATE_NO_REPARENT,
+			SPEAR1310_RAS_CTRL_REG0, SPEAR1310_I2C3_CLK_SHIFT,
+			SPEAR1310_I2C_CLK_MASK, 0, &_lock);
+	clk_register_clkdev(clk, "i2c3_mclk", NULL);
+
+	clk = clk_register_gate(NULL, "i2c3_clk", "i2c3_mclk", 0,
+			SPEAR1310_RAS_SW_CLK_CTRL, SPEAR1310_I2C3_CLK_ENB, 0,
+			&_lock);
+	clk_register_clkdev(clk, NULL, "5cf00000.i2c");
+
+	clk = clk_register_mux(NULL, "i2c4_mclk", i2c_parents,
+			ARRAY_SIZE(i2c_parents), CLK_SET_RATE_NO_REPARENT,
+			SPEAR1310_RAS_CTRL_REG0, SPEAR1310_I2C4_CLK_SHIFT,
+			SPEAR1310_I2C_CLK_MASK, 0, &_lock);
+	clk_register_clkdev(clk, "i2c4_mclk", NULL);
+
+	clk = clk_register_gate(NULL, "i2c4_clk", "i2c4_mclk", 0,
+			SPEAR1310_RAS_SW_CLK_CTRL, SPEAR1310_I2C4_CLK_ENB, 0,
+			&_lock);
+	clk_register_clkdev(clk, NULL, "5d000000.i2c");
+
+	clk = clk_register_mux(NULL, "i2c5_mclk", i2c_parents,
+			ARRAY_SIZE(i2c_parents), CLK_SET_RATE_NO_REPARENT,
+			SPEAR1310_RAS_CTRL_REG0, SPEAR1310_I2C5_CLK_SHIFT,
+			SPEAR1310_I2C_CLK_MASK, 0, &_lock);
+	clk_register_clkdev(clk, "i2c5_mclk", NULL);
+
+	clk = clk_register_gate(NULL, "i2c5_clk", "i2c5_mclk", 0,
+			SPEAR1310_RAS_SW_CLK_CTRL, SPEAR1310_I2C5_CLK_ENB, 0,
+			&_lock);
+	clk_register_clkdev(clk, NULL, "5d100000.i2c");
+
+	clk = clk_register_mux(NULL, "i2c6_mclk", i2c_parents,
+			ARRAY_SIZE(i2c_parents), CLK_SET_RATE_NO_REPARENT,
+			SPEAR1310_RAS_CTRL_REG0, SPEAR1310_I2C6_CLK_SHIFT,
+			SPEAR1310_I2C_CLK_MASK, 0, &_lock);
+	clk_register_clkdev(clk, "i2c6_mclk", NULL);
+
+	clk = clk_register_gate(NULL, "i2c6_clk", "i2c6_mclk", 0,
+			SPEAR1310_RAS_SW_CLK_CTRL, SPEAR1310_I2C6_CLK_ENB, 0,
+			&_lock);
+	clk_register_clkdev(clk, NULL, "5d200000.i2c");
+
+	clk = clk_register_mux(NULL, "i2c7_mclk", i2c_parents,
+			ARRAY_SIZE(i2c_parents), CLK_SET_RATE_NO_REPARENT,
+			SPEAR1310_RAS_CTRL_REG0, SPEAR1310_I2C7_CLK_SHIFT,
+			SPEAR1310_I2C_CLK_MASK, 0, &_lock);
+	clk_register_clkdev(clk, "i2c7_mclk", NULL);
+
+	clk = clk_register_gate(NULL, "i2c7_clk", "i2c7_mclk", 0,
+			SPEAR1310_RAS_SW_CLK_CTRL, SPEAR1310_I2C7_CLK_ENB, 0,
+			&_lock);
+	clk_register_clkdev(clk, NULL, "5d300000.i2c");
+
+	clk = clk_register_mux(NULL, "ssp1_mclk", ssp1_parents,
+			ARRAY_SIZE(ssp1_parents), CLK_SET_RATE_NO_REPARENT,
+			SPEAR1310_RAS_CTRL_REG0, SPEAR1310_SSP1_CLK_SHIFT,
+			SPEAR1310_SSP1_CLK_MASK, 0, &_lock);
+	clk_register_clkdev(clk, "ssp1_mclk", NULL);
+
+	clk = clk_register_gate(NULL, "ssp1_clk", "ssp1_mclk", 0,
+			SPEAR1310_RAS_SW_CLK_CTRL, SPEAR1310_SSP1_CLK_ENB, 0,
+			&_lock);
+	clk_register_clkdev(clk, NULL, "5d400000.spi");
+
+	clk = clk_register_mux(NULL, "pci_mclk", pci_parents,
+			ARRAY_SIZE(pci_parents), CLK_SET_RATE_NO_REPARENT,
+			SPEAR1310_RAS_CTRL_REG0, SPEAR1310_PCI_CLK_SHIFT,
+			SPEAR1310_PCI_CLK_MASK, 0, &_lock);
+	clk_register_clkdev(clk, "pci_mclk", NULL);
+
+	clk = clk_register_gate(NULL, "pci_clk", "pci_mclk", 0,
+			SPEAR1310_RAS_SW_CLK_CTRL, SPEAR1310_PCI_CLK_ENB, 0,
+			&_lock);
+	clk_register_clkdev(clk, NULL, "pci");
+
+	clk = clk_register_mux(NULL, "tdm1_mclk", tdm_parents,
+			ARRAY_SIZE(tdm_parents), CLK_SET_RATE_NO_REPARENT,
+			SPEAR1310_RAS_CTRL_REG0, SPEAR1310_TDM1_CLK_SHIFT,
+			SPEAR1310_TDM_CLK_MASK, 0, &_lock);
+	clk_register_clkdev(clk, "tdm1_mclk", NULL);
+
+	clk = clk_register_gate(NULL, "tdm1_clk", "tdm1_mclk", 0,
+			SPEAR1310_RAS_SW_CLK_CTRL, SPEAR1310_TDM1_CLK_ENB, 0,
+			&_lock);
+	clk_register_clkdev(clk, NULL, "tdm_hdlc.0");
+
+	clk = clk_register_mux(NULL, "tdm2_mclk", tdm_parents,
+			ARRAY_SIZE(tdm_parents), CLK_SET_RATE_NO_REPARENT,
+			SPEAR1310_RAS_CTRL_REG0, SPEAR1310_TDM2_CLK_SHIFT,
+			SPEAR1310_TDM_CLK_MASK, 0, &_lock);
+	clk_register_clkdev(clk, "tdm2_mclk", NULL);
+
+	clk = clk_register_gate(NULL, "tdm2_clk", "tdm2_mclk", 0,
+			SPEAR1310_RAS_SW_CLK_CTRL, SPEAR1310_TDM2_CLK_ENB, 0,
+			&_lock);
+	clk_register_clkdev(clk, NULL, "tdm_hdlc.1");
+}
diff --git a/drivers/clk/spear/spear1340_clock.c b/drivers/clk/spear/spear1340_clock.c
new file mode 100644
index 000000000..e5bc8c828
--- /dev/null
+++ b/drivers/clk/spear/spear1340_clock.c
@@ -0,0 +1,1015 @@
+/*
+ * arch/arm/mach-spear13xx/spear1340_clock.c
+ *
+ * SPEAr1340 machine clock framework source file
+ *
+ * Copyright (C) 2012 ST Microelectronics
+ * Viresh Kumar <vireshk@kernel.org>
+ *
+ * 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.
+ */
+
+#include <linux/clkdev.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/of_platform.h>
+#include <linux/spinlock_types.h>
+#include "clk.h"
+
+/* Clock Configuration Registers */
+#define SPEAR1340_SYS_CLK_CTRL			(misc_base + 0x200)
+	#define SPEAR1340_HCLK_SRC_SEL_SHIFT	27
+	#define SPEAR1340_HCLK_SRC_SEL_MASK	1
+	#define SPEAR1340_SCLK_SRC_SEL_SHIFT	23
+	#define SPEAR1340_SCLK_SRC_SEL_MASK	3
+
+/* PLL related registers and bit values */
+#define SPEAR1340_PLL_CFG			(misc_base + 0x210)
+	/* PLL_CFG bit values */
+	#define SPEAR1340_CLCD_SYNT_CLK_MASK		1
+	#define SPEAR1340_CLCD_SYNT_CLK_SHIFT		31
+	#define SPEAR1340_GEN_SYNT2_3_CLK_SHIFT		29
+	#define SPEAR1340_GEN_SYNT_CLK_MASK		2
+	#define SPEAR1340_GEN_SYNT0_1_CLK_SHIFT		27
+	#define SPEAR1340_PLL_CLK_MASK			2
+	#define SPEAR1340_PLL3_CLK_SHIFT		24
+	#define SPEAR1340_PLL2_CLK_SHIFT		22
+	#define SPEAR1340_PLL1_CLK_SHIFT		20
+
+#define SPEAR1340_PLL1_CTR			(misc_base + 0x214)
+#define SPEAR1340_PLL1_FRQ			(misc_base + 0x218)
+#define SPEAR1340_PLL2_CTR			(misc_base + 0x220)
+#define SPEAR1340_PLL2_FRQ			(misc_base + 0x224)
+#define SPEAR1340_PLL3_CTR			(misc_base + 0x22C)
+#define SPEAR1340_PLL3_FRQ			(misc_base + 0x230)
+#define SPEAR1340_PLL4_CTR			(misc_base + 0x238)
+#define SPEAR1340_PLL4_FRQ			(misc_base + 0x23C)
+#define SPEAR1340_PERIP_CLK_CFG			(misc_base + 0x244)
+	/* PERIP_CLK_CFG bit values */
+	#define SPEAR1340_SPDIF_CLK_MASK		1
+	#define SPEAR1340_SPDIF_OUT_CLK_SHIFT		15
+	#define SPEAR1340_SPDIF_IN_CLK_SHIFT		14
+	#define SPEAR1340_GPT3_CLK_SHIFT		13
+	#define SPEAR1340_GPT2_CLK_SHIFT		12
+	#define SPEAR1340_GPT_CLK_MASK			1
+	#define SPEAR1340_GPT1_CLK_SHIFT		9
+	#define SPEAR1340_GPT0_CLK_SHIFT		8
+	#define SPEAR1340_UART_CLK_MASK			2
+	#define SPEAR1340_UART1_CLK_SHIFT		6
+	#define SPEAR1340_UART0_CLK_SHIFT		4
+	#define SPEAR1340_CLCD_CLK_MASK			2
+	#define SPEAR1340_CLCD_CLK_SHIFT		2
+	#define SPEAR1340_C3_CLK_MASK			1
+	#define SPEAR1340_C3_CLK_SHIFT			1
+
+#define SPEAR1340_GMAC_CLK_CFG			(misc_base + 0x248)
+	#define SPEAR1340_GMAC_PHY_CLK_MASK		1
+	#define SPEAR1340_GMAC_PHY_CLK_SHIFT		2
+	#define SPEAR1340_GMAC_PHY_INPUT_CLK_MASK	2
+	#define SPEAR1340_GMAC_PHY_INPUT_CLK_SHIFT	0
+
+#define SPEAR1340_I2S_CLK_CFG			(misc_base + 0x24C)
+	/* I2S_CLK_CFG register mask */
+	#define SPEAR1340_I2S_SCLK_X_MASK		0x1F
+	#define SPEAR1340_I2S_SCLK_X_SHIFT		27
+	#define SPEAR1340_I2S_SCLK_Y_MASK		0x1F
+	#define SPEAR1340_I2S_SCLK_Y_SHIFT		22
+	#define SPEAR1340_I2S_SCLK_EQ_SEL_SHIFT		21
+	#define SPEAR1340_I2S_SCLK_SYNTH_ENB		20
+	#define SPEAR1340_I2S_PRS1_CLK_X_MASK		0xFF
+	#define SPEAR1340_I2S_PRS1_CLK_X_SHIFT		12
+	#define SPEAR1340_I2S_PRS1_CLK_Y_MASK		0xFF
+	#define SPEAR1340_I2S_PRS1_CLK_Y_SHIFT		4
+	#define SPEAR1340_I2S_PRS1_EQ_SEL_SHIFT		3
+	#define SPEAR1340_I2S_REF_SEL_MASK		1
+	#define SPEAR1340_I2S_REF_SHIFT			2
+	#define SPEAR1340_I2S_SRC_CLK_MASK		2
+	#define SPEAR1340_I2S_SRC_CLK_SHIFT		0
+
+#define SPEAR1340_C3_CLK_SYNT			(misc_base + 0x250)
+#define SPEAR1340_UART0_CLK_SYNT		(misc_base + 0x254)
+#define SPEAR1340_UART1_CLK_SYNT		(misc_base + 0x258)
+#define SPEAR1340_GMAC_CLK_SYNT			(misc_base + 0x25C)
+#define SPEAR1340_SDHCI_CLK_SYNT		(misc_base + 0x260)
+#define SPEAR1340_CFXD_CLK_SYNT			(misc_base + 0x264)
+#define SPEAR1340_ADC_CLK_SYNT			(misc_base + 0x270)
+#define SPEAR1340_AMBA_CLK_SYNT			(misc_base + 0x274)
+#define SPEAR1340_CLCD_CLK_SYNT			(misc_base + 0x27C)
+#define SPEAR1340_SYS_CLK_SYNT			(misc_base + 0x284)
+#define SPEAR1340_GEN_CLK_SYNT0			(misc_base + 0x28C)
+#define SPEAR1340_GEN_CLK_SYNT1			(misc_base + 0x294)
+#define SPEAR1340_GEN_CLK_SYNT2			(misc_base + 0x29C)
+#define SPEAR1340_GEN_CLK_SYNT3			(misc_base + 0x304)
+#define SPEAR1340_PERIP1_CLK_ENB		(misc_base + 0x30C)
+	#define SPEAR1340_RTC_CLK_ENB			31
+	#define SPEAR1340_ADC_CLK_ENB			30
+	#define SPEAR1340_C3_CLK_ENB			29
+	#define SPEAR1340_CLCD_CLK_ENB			27
+	#define SPEAR1340_DMA_CLK_ENB			25
+	#define SPEAR1340_GPIO1_CLK_ENB			24
+	#define SPEAR1340_GPIO0_CLK_ENB			23
+	#define SPEAR1340_GPT1_CLK_ENB			22
+	#define SPEAR1340_GPT0_CLK_ENB			21
+	#define SPEAR1340_I2S_PLAY_CLK_ENB		20
+	#define SPEAR1340_I2S_REC_CLK_ENB		19
+	#define SPEAR1340_I2C0_CLK_ENB			18
+	#define SPEAR1340_SSP_CLK_ENB			17
+	#define SPEAR1340_UART0_CLK_ENB			15
+	#define SPEAR1340_PCIE_SATA_CLK_ENB		12
+	#define SPEAR1340_UOC_CLK_ENB			11
+	#define SPEAR1340_UHC1_CLK_ENB			10
+	#define SPEAR1340_UHC0_CLK_ENB			9
+	#define SPEAR1340_GMAC_CLK_ENB			8
+	#define SPEAR1340_CFXD_CLK_ENB			7
+	#define SPEAR1340_SDHCI_CLK_ENB			6
+	#define SPEAR1340_SMI_CLK_ENB			5
+	#define SPEAR1340_FSMC_CLK_ENB			4
+	#define SPEAR1340_SYSRAM0_CLK_ENB		3
+	#define SPEAR1340_SYSRAM1_CLK_ENB		2
+	#define SPEAR1340_SYSROM_CLK_ENB		1
+	#define SPEAR1340_BUS_CLK_ENB			0
+
+#define SPEAR1340_PERIP2_CLK_ENB		(misc_base + 0x310)
+	#define SPEAR1340_THSENS_CLK_ENB		8
+	#define SPEAR1340_I2S_REF_PAD_CLK_ENB		7
+	#define SPEAR1340_ACP_CLK_ENB			6
+	#define SPEAR1340_GPT3_CLK_ENB			5
+	#define SPEAR1340_GPT2_CLK_ENB			4
+	#define SPEAR1340_KBD_CLK_ENB			3
+	#define SPEAR1340_CPU_DBG_CLK_ENB		2
+	#define SPEAR1340_DDR_CORE_CLK_ENB		1
+	#define SPEAR1340_DDR_CTRL_CLK_ENB		0
+
+#define SPEAR1340_PERIP3_CLK_ENB		(misc_base + 0x314)
+	#define SPEAR1340_PLGPIO_CLK_ENB		18
+	#define SPEAR1340_VIDEO_DEC_CLK_ENB		16
+	#define SPEAR1340_VIDEO_ENC_CLK_ENB		15
+	#define SPEAR1340_SPDIF_OUT_CLK_ENB		13
+	#define SPEAR1340_SPDIF_IN_CLK_ENB		12
+	#define SPEAR1340_VIDEO_IN_CLK_ENB		11
+	#define SPEAR1340_CAM0_CLK_ENB			10
+	#define SPEAR1340_CAM1_CLK_ENB			9
+	#define SPEAR1340_CAM2_CLK_ENB			8
+	#define SPEAR1340_CAM3_CLK_ENB			7
+	#define SPEAR1340_MALI_CLK_ENB			6
+	#define SPEAR1340_CEC0_CLK_ENB			5
+	#define SPEAR1340_CEC1_CLK_ENB			4
+	#define SPEAR1340_PWM_CLK_ENB			3
+	#define SPEAR1340_I2C1_CLK_ENB			2
+	#define SPEAR1340_UART1_CLK_ENB			1
+
+static DEFINE_SPINLOCK(_lock);
+
+/* pll rate configuration table, in ascending order of rates */
+static struct pll_rate_tbl pll_rtbl[] = {
+	/* PCLK 24MHz */
+	{.mode = 0, .m = 0x83, .n = 0x04, .p = 0x5}, /* vco 1572, pll 49.125 MHz */
+	{.mode = 0, .m = 0x7D, .n = 0x06, .p = 0x3}, /* vco 1000, pll 125 MHz */
+	{.mode = 0, .m = 0x64, .n = 0x06, .p = 0x1}, /* vco 800, pll 400 MHz */
+	{.mode = 0, .m = 0x7D, .n = 0x06, .p = 0x1}, /* vco 1000, pll 500 MHz */
+	{.mode = 0, .m = 0xA6, .n = 0x06, .p = 0x1}, /* vco 1328, pll 664 MHz */
+	{.mode = 0, .m = 0xC8, .n = 0x06, .p = 0x1}, /* vco 1600, pll 800 MHz */
+	{.mode = 0, .m = 0x7D, .n = 0x06, .p = 0x0}, /* vco 1, pll 1 GHz */
+	{.mode = 0, .m = 0x96, .n = 0x06, .p = 0x0}, /* vco 1200, pll 1200 MHz */
+};
+
+/* vco-pll4 rate configuration table, in ascending order of rates */
+static struct pll_rate_tbl pll4_rtbl[] = {
+	{.mode = 0, .m = 0x7D, .n = 0x06, .p = 0x2}, /* vco 1000, pll 250 MHz */
+	{.mode = 0, .m = 0xA6, .n = 0x06, .p = 0x2}, /* vco 1328, pll 332 MHz */
+	{.mode = 0, .m = 0xC8, .n = 0x06, .p = 0x2}, /* vco 1600, pll 400 MHz */
+	{.mode = 0, .m = 0x7D, .n = 0x06, .p = 0x0}, /* vco 1, pll 1 GHz */
+};
+
+/*
+ * All below entries generate 166 MHz for
+ * different values of vco1div2
+ */
+static struct frac_rate_tbl amba_synth_rtbl[] = {
+	{.div = 0x073A8}, /* for vco1div2 = 600 MHz */
+	{.div = 0x06062}, /* for vco1div2 = 500 MHz */
+	{.div = 0x04D1B}, /* for vco1div2 = 400 MHz */
+	{.div = 0x04000}, /* for vco1div2 = 332 MHz */
+	{.div = 0x03031}, /* for vco1div2 = 250 MHz */
+	{.div = 0x0268D}, /* for vco1div2 = 200 MHz */
+};
+
+/*
+ * Synthesizer Clock derived from vcodiv2. This clock is one of the
+ * possible clocks to feed cpu directly.
+ * We can program this synthesizer to make cpu run on different clock
+ * frequencies.
+ * Following table provides configuration values to let cpu run on 200,
+ * 250, 332, 400 or 500 MHz considering different possibilites of input
+ * (vco1div2) clock.
+ *
+ * --------------------------------------------------------------------
+ * vco1div2(Mhz)	fout(Mhz)	cpuclk = fout/2		div
+ * --------------------------------------------------------------------
+ * 400			200		100			0x04000
+ * 400			250		125			0x03333
+ * 400			332		166			0x0268D
+ * 400			400		200			0x02000
+ * --------------------------------------------------------------------
+ * 500			200		100			0x05000
+ * 500			250		125			0x04000
+ * 500			332		166			0x03031
+ * 500			400		200			0x02800
+ * 500			500		250			0x02000
+ * --------------------------------------------------------------------
+ * 600			200		100			0x06000
+ * 600			250		125			0x04CCE
+ * 600			332		166			0x039D5
+ * 600			400		200			0x03000
+ * 600			500		250			0x02666
+ * --------------------------------------------------------------------
+ * 664			200		100			0x06a38
+ * 664			250		125			0x054FD
+ * 664			332		166			0x04000
+ * 664			400		200			0x0351E
+ * 664			500		250			0x02A7E
+ * --------------------------------------------------------------------
+ * 800			200		100			0x08000
+ * 800			250		125			0x06666
+ * 800			332		166			0x04D18
+ * 800			400		200			0x04000
+ * 800			500		250			0x03333
+ * --------------------------------------------------------------------
+ * sys rate configuration table is in descending order of divisor.
+ */
+static struct frac_rate_tbl sys_synth_rtbl[] = {
+	{.div = 0x08000},
+	{.div = 0x06a38},
+	{.div = 0x06666},
+	{.div = 0x06000},
+	{.div = 0x054FD},
+	{.div = 0x05000},
+	{.div = 0x04D18},
+	{.div = 0x04CCE},
+	{.div = 0x04000},
+	{.div = 0x039D5},
+	{.div = 0x0351E},
+	{.div = 0x03333},
+	{.div = 0x03031},
+	{.div = 0x03000},
+	{.div = 0x02A7E},
+	{.div = 0x02800},
+	{.div = 0x0268D},
+	{.div = 0x02666},
+	{.div = 0x02000},
+};
+
+/* aux rate configuration table, in ascending order of rates */
+static struct aux_rate_tbl aux_rtbl[] = {
+	/* 12.29MHz for vic1div2=600MHz and 10.24MHz for VCO1div2=500MHz */
+	{.xscale = 5, .yscale = 122, .eq = 0},
+	/* 14.70MHz for vic1div2=600MHz and 12.29MHz for VCO1div2=500MHz */
+	{.xscale = 10, .yscale = 204, .eq = 0},
+	/* 48MHz for vic1div2=600MHz and 40 MHz for VCO1div2=500MHz */
+	{.xscale = 4, .yscale = 25, .eq = 0},
+	/* 57.14MHz for vic1div2=600MHz and 48 MHz for VCO1div2=500MHz */
+	{.xscale = 4, .yscale = 21, .eq = 0},
+	/* 83.33MHz for vic1div2=600MHz and 69.44MHz for VCO1div2=500MHz */
+	{.xscale = 5, .yscale = 18, .eq = 0},
+	/* 100MHz for vic1div2=600MHz and 83.33 MHz for VCO1div2=500MHz */
+	{.xscale = 2, .yscale = 6, .eq = 0},
+	/* 125MHz for vic1div2=600MHz and 104.1MHz for VCO1div2=500MHz */
+	{.xscale = 5, .yscale = 12, .eq = 0},
+	/* 150MHz for vic1div2=600MHz and 125MHz for VCO1div2=500MHz */
+	{.xscale = 2, .yscale = 4, .eq = 0},
+	/* 166MHz for vic1div2=600MHz and 138.88MHz for VCO1div2=500MHz */
+	{.xscale = 5, .yscale = 18, .eq = 1},
+	/* 200MHz for vic1div2=600MHz and 166MHz for VCO1div2=500MHz */
+	{.xscale = 1, .yscale = 3, .eq = 1},
+	/* 250MHz for vic1div2=600MHz and 208.33MHz for VCO1div2=500MHz */
+	{.xscale = 5, .yscale = 12, .eq = 1},
+	/* 300MHz for vic1div2=600MHz and 250MHz for VCO1div2=500MHz */
+	{.xscale = 1, .yscale = 2, .eq = 1},
+};
+
+/* gmac rate configuration table, in ascending order of rates */
+static struct aux_rate_tbl gmac_rtbl[] = {
+	/* For gmac phy input clk */
+	{.xscale = 2, .yscale = 6, .eq = 0}, /* divided by 6 */
+	{.xscale = 2, .yscale = 4, .eq = 0}, /* divided by 4 */
+	{.xscale = 1, .yscale = 3, .eq = 1}, /* divided by 3 */
+	{.xscale = 1, .yscale = 2, .eq = 1}, /* divided by 2 */
+};
+
+/* clcd rate configuration table, in ascending order of rates */
+static struct frac_rate_tbl clcd_rtbl[] = {
+	{.div = 0x18000}, /* 25 Mhz , for vc01div4 = 300 MHz*/
+	{.div = 0x1638E}, /* 27 Mhz , for vc01div4 = 300 MHz*/
+	{.div = 0x14000}, /* 25 Mhz , for vc01div4 = 250 MHz*/
+	{.div = 0x1284B}, /* 27 Mhz , for vc01div4 = 250 MHz*/
+	{.div = 0x0D8D3}, /* 58 Mhz , for vco1div4 = 393 MHz */
+	{.div = 0x0B72C}, /* 58 Mhz , for vco1div4 = 332 MHz */
+	{.div = 0x0A584}, /* 58 Mhz , for vco1div4 = 300 MHz */
+	{.div = 0x093B1}, /* 65 Mhz , for vc01div4 = 300 MHz*/
+	{.div = 0x089EE}, /* 58 Mhz , for vc01div4 = 250 MHz*/
+	{.div = 0x081BA}, /* 74 Mhz , for vc01div4 = 300 MHz*/
+	{.div = 0x07BA0}, /* 65 Mhz , for vc01div4 = 250 MHz*/
+	{.div = 0x06f1C}, /* 72 Mhz , for vc01div4 = 250 MHz*/
+	{.div = 0x06E58}, /* 58 Mhz , for vco1div4 = 200 MHz */
+	{.div = 0x06c1B}, /* 74 Mhz , for vc01div4 = 250 MHz*/
+	{.div = 0x058E3}, /* 108 Mhz , for vc01div4 = 300 MHz*/
+	{.div = 0x04A12}, /* 108 Mhz , for vc01div4 = 250 MHz*/
+	{.div = 0x040A5}, /* 148.5 Mhz , for vc01div4 = 300 MHz*/
+	{.div = 0x0378E}, /* 144 Mhz , for vc01div4 = 250 MHz*/
+	{.div = 0x0360D}, /* 148 Mhz , for vc01div4 = 250 MHz*/
+	{.div = 0x035E0}, /* 148.5 MHz, for vc01div4 = 250 MHz*/
+};
+
+/* i2s prescaler1 masks */
+static const struct aux_clk_masks i2s_prs1_masks = {
+	.eq_sel_mask = AUX_EQ_SEL_MASK,
+	.eq_sel_shift = SPEAR1340_I2S_PRS1_EQ_SEL_SHIFT,
+	.eq1_mask = AUX_EQ1_SEL,
+	.eq2_mask = AUX_EQ2_SEL,
+	.xscale_sel_mask = SPEAR1340_I2S_PRS1_CLK_X_MASK,
+	.xscale_sel_shift = SPEAR1340_I2S_PRS1_CLK_X_SHIFT,
+	.yscale_sel_mask = SPEAR1340_I2S_PRS1_CLK_Y_MASK,
+	.yscale_sel_shift = SPEAR1340_I2S_PRS1_CLK_Y_SHIFT,
+};
+
+/* i2s sclk (bit clock) syynthesizers masks */
+static struct aux_clk_masks i2s_sclk_masks = {
+	.eq_sel_mask = AUX_EQ_SEL_MASK,
+	.eq_sel_shift = SPEAR1340_I2S_SCLK_EQ_SEL_SHIFT,
+	.eq1_mask = AUX_EQ1_SEL,
+	.eq2_mask = AUX_EQ2_SEL,
+	.xscale_sel_mask = SPEAR1340_I2S_SCLK_X_MASK,
+	.xscale_sel_shift = SPEAR1340_I2S_SCLK_X_SHIFT,
+	.yscale_sel_mask = SPEAR1340_I2S_SCLK_Y_MASK,
+	.yscale_sel_shift = SPEAR1340_I2S_SCLK_Y_SHIFT,
+	.enable_bit = SPEAR1340_I2S_SCLK_SYNTH_ENB,
+};
+
+/* i2s prs1 aux rate configuration table, in ascending order of rates */
+static struct aux_rate_tbl i2s_prs1_rtbl[] = {
+	/* For parent clk = 49.152 MHz */
+	{.xscale = 1, .yscale = 12, .eq = 0}, /* 2.048 MHz, smp freq = 8Khz */
+	{.xscale = 11, .yscale = 96, .eq = 0}, /* 2.816 MHz, smp freq = 11Khz */
+	{.xscale = 1, .yscale = 6, .eq = 0}, /* 4.096 MHz, smp freq = 16Khz */
+	{.xscale = 11, .yscale = 48, .eq = 0}, /* 5.632 MHz, smp freq = 22Khz */
+
+	/*
+	 * with parent clk = 49.152, freq gen is 8.192 MHz, smp freq = 32Khz
+	 * with parent clk = 12.288, freq gen is 2.048 MHz, smp freq = 8Khz
+	 */
+	{.xscale = 1, .yscale = 3, .eq = 0},
+
+	/* For parent clk = 49.152 MHz */
+	{.xscale = 17, .yscale = 37, .eq = 0}, /* 11.289 MHz, smp freq = 44Khz*/
+	{.xscale = 1, .yscale = 2, .eq = 0}, /* 12.288 MHz, smp freq = 48Khz*/
+};
+
+/* i2s sclk aux rate configuration table, in ascending order of rates */
+static struct aux_rate_tbl i2s_sclk_rtbl[] = {
+	/* For sclk = ref_clk * x/2/y */
+	{.xscale = 1, .yscale = 4, .eq = 0},
+	{.xscale = 1, .yscale = 2, .eq = 0},
+};
+
+/* adc rate configuration table, in ascending order of rates */
+/* possible adc range is 2.5 MHz to 20 MHz. */
+static struct aux_rate_tbl adc_rtbl[] = {
+	/* For ahb = 166.67 MHz */
+	{.xscale = 1, .yscale = 31, .eq = 0}, /* 2.68 MHz */
+	{.xscale = 2, .yscale = 21, .eq = 0}, /* 7.94 MHz */
+	{.xscale = 4, .yscale = 21, .eq = 0}, /* 15.87 MHz */
+	{.xscale = 10, .yscale = 42, .eq = 0}, /* 19.84 MHz */
+};
+
+/* General synth rate configuration table, in ascending order of rates */
+static struct frac_rate_tbl gen_rtbl[] = {
+	{.div = 0x1A92B}, /* 22.5792 MHz for vco1div4=300 MHz*/
+	{.div = 0x186A0}, /* 24.576 MHz for vco1div4=300 MHz*/
+	{.div = 0x18000}, /* 25 MHz for vco1div4=300 MHz*/
+	{.div = 0x1624E}, /* 22.5792 MHz for vco1div4=250 MHz*/
+	{.div = 0x14585}, /* 24.576 MHz for vco1div4=250 MHz*/
+	{.div = 0x14000}, /* 25 MHz for vco1div4=250 MHz*/
+	{.div = 0x0D495}, /* 45.1584 MHz for vco1div4=300 MHz*/
+	{.div = 0x0C000}, /* 50 MHz for vco1div4=300 MHz*/
+	{.div = 0x0B127}, /* 45.1584 MHz for vco1div4=250 MHz*/
+	{.div = 0x0A000}, /* 50 MHz for vco1div4=250 MHz*/
+	{.div = 0x07530}, /* 81.92 MHz for vco1div4=300 MHz*/
+	{.div = 0x061A8}, /* 81.92 MHz for vco1div4=250 MHz*/
+	{.div = 0x06000}, /* 100 MHz for vco1div4=300 MHz*/
+	{.div = 0x05000}, /* 100 MHz for vco1div4=250 MHz*/
+	{.div = 0x03000}, /* 200 MHz for vco1div4=300 MHz*/
+	{.div = 0x02DB6}, /* 210 MHz for vco1div4=300 MHz*/
+	{.div = 0x02BA2}, /* 220 MHz for vco1div4=300 MHz*/
+	{.div = 0x029BD}, /* 230 MHz for vco1div4=300 MHz*/
+	{.div = 0x02800}, /* 200 MHz for vco1div4=250 MHz*/
+	{.div = 0x02666}, /* 250 MHz for vco1div4=300 MHz*/
+	{.div = 0x02620}, /* 210 MHz for vco1div4=250 MHz*/
+	{.div = 0x02460}, /* 220 MHz for vco1div4=250 MHz*/
+	{.div = 0x022C0}, /* 230 MHz for vco1div4=250 MHz*/
+	{.div = 0x02160}, /* 240 MHz for vco1div4=250 MHz*/
+	{.div = 0x02000}, /* 250 MHz for vco1div4=250 MHz*/
+};
+
+/* clock parents */
+static const char *vco_parents[] = { "osc_24m_clk", "osc_25m_clk", };
+static const char *sys_parents[] = { "pll1_clk", "pll1_clk", "pll1_clk",
+	"pll1_clk", "sys_syn_clk", "sys_syn_clk", "pll2_clk", "pll3_clk", };
+static const char *ahb_parents[] = { "cpu_div3_clk", "amba_syn_clk", };
+static const char *gpt_parents[] = { "osc_24m_clk", "apb_clk", };
+static const char *uart0_parents[] = { "pll5_clk", "osc_24m_clk",
+	"uart0_syn_gclk", };
+static const char *uart1_parents[] = { "pll5_clk", "osc_24m_clk",
+	"uart1_syn_gclk", };
+static const char *c3_parents[] = { "pll5_clk", "c3_syn_gclk", };
+static const char *gmac_phy_input_parents[] = { "gmii_pad_clk", "pll2_clk",
+	"osc_25m_clk", };
+static const char *gmac_phy_parents[] = { "phy_input_mclk", "phy_syn_gclk", };
+static const char *clcd_synth_parents[] = { "vco1div4_clk", "pll2_clk", };
+static const char *clcd_pixel_parents[] = { "pll5_clk", "clcd_syn_clk", };
+static const char *i2s_src_parents[] = { "vco1div2_clk", "pll2_clk", "pll3_clk",
+	"i2s_src_pad_clk", };
+static const char *i2s_ref_parents[] = { "i2s_src_mclk", "i2s_prs1_clk", };
+static const char *spdif_out_parents[] = { "i2s_src_pad_clk", "gen_syn2_clk", };
+static const char *spdif_in_parents[] = { "pll2_clk", "gen_syn3_clk", };
+
+static const char *gen_synth0_1_parents[] = { "vco1div4_clk", "vco3div2_clk",
+	"pll3_clk", };
+static const char *gen_synth2_3_parents[] = { "vco1div4_clk", "vco2div2_clk",
+	"pll2_clk", };
+
+void __init spear1340_clk_init(void __iomem *misc_base)
+{
+	struct clk *clk, *clk1;
+
+	clk = clk_register_fixed_rate(NULL, "osc_32k_clk", NULL, 0, 32000);
+	clk_register_clkdev(clk, "osc_32k_clk", NULL);
+
+	clk = clk_register_fixed_rate(NULL, "osc_24m_clk", NULL, 0, 24000000);
+	clk_register_clkdev(clk, "osc_24m_clk", NULL);
+
+	clk = clk_register_fixed_rate(NULL, "osc_25m_clk", NULL, 0, 25000000);
+	clk_register_clkdev(clk, "osc_25m_clk", NULL);
+
+	clk = clk_register_fixed_rate(NULL, "gmii_pad_clk", NULL, 0, 125000000);
+	clk_register_clkdev(clk, "gmii_pad_clk", NULL);
+
+	clk = clk_register_fixed_rate(NULL, "i2s_src_pad_clk", NULL, 0,
+				      12288000);
+	clk_register_clkdev(clk, "i2s_src_pad_clk", NULL);
+
+	/* clock derived from 32 KHz osc clk */
+	clk = clk_register_gate(NULL, "rtc-spear", "osc_32k_clk", 0,
+			SPEAR1340_PERIP1_CLK_ENB, SPEAR1340_RTC_CLK_ENB, 0,
+			&_lock);
+	clk_register_clkdev(clk, NULL, "e0580000.rtc");
+
+	/* clock derived from 24 or 25 MHz osc clk */
+	/* vco-pll */
+	clk = clk_register_mux(NULL, "vco1_mclk", vco_parents,
+			ARRAY_SIZE(vco_parents), CLK_SET_RATE_NO_REPARENT,
+			SPEAR1340_PLL_CFG, SPEAR1340_PLL1_CLK_SHIFT,
+			SPEAR1340_PLL_CLK_MASK, 0, &_lock);
+	clk_register_clkdev(clk, "vco1_mclk", NULL);
+	clk = clk_register_vco_pll("vco1_clk", "pll1_clk", NULL, "vco1_mclk", 0,
+			SPEAR1340_PLL1_CTR, SPEAR1340_PLL1_FRQ, pll_rtbl,
+			ARRAY_SIZE(pll_rtbl), &_lock, &clk1, NULL);
+	clk_register_clkdev(clk, "vco1_clk", NULL);
+	clk_register_clkdev(clk1, "pll1_clk", NULL);
+
+	clk = clk_register_mux(NULL, "vco2_mclk", vco_parents,
+			ARRAY_SIZE(vco_parents), CLK_SET_RATE_NO_REPARENT,
+			SPEAR1340_PLL_CFG, SPEAR1340_PLL2_CLK_SHIFT,
+			SPEAR1340_PLL_CLK_MASK, 0, &_lock);
+	clk_register_clkdev(clk, "vco2_mclk", NULL);
+	clk = clk_register_vco_pll("vco2_clk", "pll2_clk", NULL, "vco2_mclk", 0,
+			SPEAR1340_PLL2_CTR, SPEAR1340_PLL2_FRQ, pll_rtbl,
+			ARRAY_SIZE(pll_rtbl), &_lock, &clk1, NULL);
+	clk_register_clkdev(clk, "vco2_clk", NULL);
+	clk_register_clkdev(clk1, "pll2_clk", NULL);
+
+	clk = clk_register_mux(NULL, "vco3_mclk", vco_parents,
+			ARRAY_SIZE(vco_parents), CLK_SET_RATE_NO_REPARENT,
+			SPEAR1340_PLL_CFG, SPEAR1340_PLL3_CLK_SHIFT,
+			SPEAR1340_PLL_CLK_MASK, 0, &_lock);
+	clk_register_clkdev(clk, "vco3_mclk", NULL);
+	clk = clk_register_vco_pll("vco3_clk", "pll3_clk", NULL, "vco3_mclk", 0,
+			SPEAR1340_PLL3_CTR, SPEAR1340_PLL3_FRQ, pll_rtbl,
+			ARRAY_SIZE(pll_rtbl), &_lock, &clk1, NULL);
+	clk_register_clkdev(clk, "vco3_clk", NULL);
+	clk_register_clkdev(clk1, "pll3_clk", NULL);
+
+	clk = clk_register_vco_pll("vco4_clk", "pll4_clk", NULL, "osc_24m_clk",
+			0, SPEAR1340_PLL4_CTR, SPEAR1340_PLL4_FRQ, pll4_rtbl,
+			ARRAY_SIZE(pll4_rtbl), &_lock, &clk1, NULL);
+	clk_register_clkdev(clk, "vco4_clk", NULL);
+	clk_register_clkdev(clk1, "pll4_clk", NULL);
+
+	clk = clk_register_fixed_rate(NULL, "pll5_clk", "osc_24m_clk", 0,
+			48000000);
+	clk_register_clkdev(clk, "pll5_clk", NULL);
+
+	clk = clk_register_fixed_rate(NULL, "pll6_clk", "osc_25m_clk", 0,
+			25000000);
+	clk_register_clkdev(clk, "pll6_clk", NULL);
+
+	/* vco div n clocks */
+	clk = clk_register_fixed_factor(NULL, "vco1div2_clk", "vco1_clk", 0, 1,
+			2);
+	clk_register_clkdev(clk, "vco1div2_clk", NULL);
+
+	clk = clk_register_fixed_factor(NULL, "vco1div4_clk", "vco1_clk", 0, 1,
+			4);
+	clk_register_clkdev(clk, "vco1div4_clk", NULL);
+
+	clk = clk_register_fixed_factor(NULL, "vco2div2_clk", "vco2_clk", 0, 1,
+			2);
+	clk_register_clkdev(clk, "vco2div2_clk", NULL);
+
+	clk = clk_register_fixed_factor(NULL, "vco3div2_clk", "vco3_clk", 0, 1,
+			2);
+	clk_register_clkdev(clk, "vco3div2_clk", NULL);
+
+	/* peripherals */
+	clk_register_fixed_factor(NULL, "thermal_clk", "osc_24m_clk", 0, 1,
+			128);
+	clk = clk_register_gate(NULL, "thermal_gclk", "thermal_clk", 0,
+			SPEAR1340_PERIP2_CLK_ENB, SPEAR1340_THSENS_CLK_ENB, 0,
+			&_lock);
+	clk_register_clkdev(clk, NULL, "e07008c4.thermal");
+
+	/* clock derived from pll4 clk */
+	clk = clk_register_fixed_factor(NULL, "ddr_clk", "pll4_clk", 0, 1,
+			1);
+	clk_register_clkdev(clk, "ddr_clk", NULL);
+
+	/* clock derived from pll1 clk */
+	clk = clk_register_frac("sys_syn_clk", "vco1div2_clk", 0,
+			SPEAR1340_SYS_CLK_SYNT, sys_synth_rtbl,
+			ARRAY_SIZE(sys_synth_rtbl), &_lock);
+	clk_register_clkdev(clk, "sys_syn_clk", NULL);
+
+	clk = clk_register_frac("amba_syn_clk", "vco1div2_clk", 0,
+			SPEAR1340_AMBA_CLK_SYNT, amba_synth_rtbl,
+			ARRAY_SIZE(amba_synth_rtbl), &_lock);
+	clk_register_clkdev(clk, "amba_syn_clk", NULL);
+
+	clk = clk_register_mux(NULL, "sys_mclk", sys_parents,
+			ARRAY_SIZE(sys_parents), CLK_SET_RATE_NO_REPARENT,
+			SPEAR1340_SYS_CLK_CTRL, SPEAR1340_SCLK_SRC_SEL_SHIFT,
+			SPEAR1340_SCLK_SRC_SEL_MASK, 0, &_lock);
+	clk_register_clkdev(clk, "sys_mclk", NULL);
+
+	clk = clk_register_fixed_factor(NULL, "cpu_clk", "sys_mclk", 0, 1,
+			2);
+	clk_register_clkdev(clk, "cpu_clk", NULL);
+
+	clk = clk_register_fixed_factor(NULL, "cpu_div3_clk", "cpu_clk", 0, 1,
+			3);
+	clk_register_clkdev(clk, "cpu_div3_clk", NULL);
+
+	clk = clk_register_fixed_factor(NULL, "wdt_clk", "cpu_clk", 0, 1,
+			2);
+	clk_register_clkdev(clk, NULL, "ec800620.wdt");
+
+	clk = clk_register_fixed_factor(NULL, "smp_twd_clk", "cpu_clk", 0, 1,
+			2);
+	clk_register_clkdev(clk, NULL, "smp_twd");
+
+	clk = clk_register_mux(NULL, "ahb_clk", ahb_parents,
+			ARRAY_SIZE(ahb_parents), CLK_SET_RATE_NO_REPARENT,
+			SPEAR1340_SYS_CLK_CTRL, SPEAR1340_HCLK_SRC_SEL_SHIFT,
+			SPEAR1340_HCLK_SRC_SEL_MASK, 0, &_lock);
+	clk_register_clkdev(clk, "ahb_clk", NULL);
+
+	clk = clk_register_fixed_factor(NULL, "apb_clk", "ahb_clk", 0, 1,
+			2);
+	clk_register_clkdev(clk, "apb_clk", NULL);
+
+	/* gpt clocks */
+	clk = clk_register_mux(NULL, "gpt0_mclk", gpt_parents,
+			ARRAY_SIZE(gpt_parents), CLK_SET_RATE_NO_REPARENT,
+			SPEAR1340_PERIP_CLK_CFG, SPEAR1340_GPT0_CLK_SHIFT,
+			SPEAR1340_GPT_CLK_MASK, 0, &_lock);
+	clk_register_clkdev(clk, "gpt0_mclk", NULL);
+	clk = clk_register_gate(NULL, "gpt0_clk", "gpt0_mclk", 0,
+			SPEAR1340_PERIP1_CLK_ENB, SPEAR1340_GPT0_CLK_ENB, 0,
+			&_lock);
+	clk_register_clkdev(clk, NULL, "gpt0");
+
+	clk = clk_register_mux(NULL, "gpt1_mclk", gpt_parents,
+			ARRAY_SIZE(gpt_parents), CLK_SET_RATE_NO_REPARENT,
+			SPEAR1340_PERIP_CLK_CFG, SPEAR1340_GPT1_CLK_SHIFT,
+			SPEAR1340_GPT_CLK_MASK, 0, &_lock);
+	clk_register_clkdev(clk, "gpt1_mclk", NULL);
+	clk = clk_register_gate(NULL, "gpt1_clk", "gpt1_mclk", 0,
+			SPEAR1340_PERIP1_CLK_ENB, SPEAR1340_GPT1_CLK_ENB, 0,
+			&_lock);
+	clk_register_clkdev(clk, NULL, "gpt1");
+
+	clk = clk_register_mux(NULL, "gpt2_mclk", gpt_parents,
+			ARRAY_SIZE(gpt_parents), CLK_SET_RATE_NO_REPARENT,
+			SPEAR1340_PERIP_CLK_CFG, SPEAR1340_GPT2_CLK_SHIFT,
+			SPEAR1340_GPT_CLK_MASK, 0, &_lock);
+	clk_register_clkdev(clk, "gpt2_mclk", NULL);
+	clk = clk_register_gate(NULL, "gpt2_clk", "gpt2_mclk", 0,
+			SPEAR1340_PERIP2_CLK_ENB, SPEAR1340_GPT2_CLK_ENB, 0,
+			&_lock);
+	clk_register_clkdev(clk, NULL, "gpt2");
+
+	clk = clk_register_mux(NULL, "gpt3_mclk", gpt_parents,
+			ARRAY_SIZE(gpt_parents), CLK_SET_RATE_NO_REPARENT,
+			SPEAR1340_PERIP_CLK_CFG, SPEAR1340_GPT3_CLK_SHIFT,
+			SPEAR1340_GPT_CLK_MASK, 0, &_lock);
+	clk_register_clkdev(clk, "gpt3_mclk", NULL);
+	clk = clk_register_gate(NULL, "gpt3_clk", "gpt3_mclk", 0,
+			SPEAR1340_PERIP2_CLK_ENB, SPEAR1340_GPT3_CLK_ENB, 0,
+			&_lock);
+	clk_register_clkdev(clk, NULL, "gpt3");
+
+	/* others */
+	clk = clk_register_aux("uart0_syn_clk", "uart0_syn_gclk",
+			"vco1div2_clk", 0, SPEAR1340_UART0_CLK_SYNT, NULL,
+			aux_rtbl, ARRAY_SIZE(aux_rtbl), &_lock, &clk1);
+	clk_register_clkdev(clk, "uart0_syn_clk", NULL);
+	clk_register_clkdev(clk1, "uart0_syn_gclk", NULL);
+
+	clk = clk_register_mux(NULL, "uart0_mclk", uart0_parents,
+			ARRAY_SIZE(uart0_parents),
+			CLK_SET_RATE_PARENT | CLK_SET_RATE_NO_REPARENT,
+			SPEAR1340_PERIP_CLK_CFG, SPEAR1340_UART0_CLK_SHIFT,
+			SPEAR1340_UART_CLK_MASK, 0, &_lock);
+	clk_register_clkdev(clk, "uart0_mclk", NULL);
+
+	clk = clk_register_gate(NULL, "uart0_clk", "uart0_mclk",
+			CLK_SET_RATE_PARENT, SPEAR1340_PERIP1_CLK_ENB,
+			SPEAR1340_UART0_CLK_ENB, 0, &_lock);
+	clk_register_clkdev(clk, NULL, "e0000000.serial");
+
+	clk = clk_register_aux("uart1_syn_clk", "uart1_syn_gclk",
+			"vco1div2_clk", 0, SPEAR1340_UART1_CLK_SYNT, NULL,
+			aux_rtbl, ARRAY_SIZE(aux_rtbl), &_lock, &clk1);
+	clk_register_clkdev(clk, "uart1_syn_clk", NULL);
+	clk_register_clkdev(clk1, "uart1_syn_gclk", NULL);
+
+	clk = clk_register_mux(NULL, "uart1_mclk", uart1_parents,
+			ARRAY_SIZE(uart1_parents), CLK_SET_RATE_NO_REPARENT,
+			SPEAR1340_PERIP_CLK_CFG, SPEAR1340_UART1_CLK_SHIFT,
+			SPEAR1340_UART_CLK_MASK, 0, &_lock);
+	clk_register_clkdev(clk, "uart1_mclk", NULL);
+
+	clk = clk_register_gate(NULL, "uart1_clk", "uart1_mclk", 0,
+			SPEAR1340_PERIP3_CLK_ENB, SPEAR1340_UART1_CLK_ENB, 0,
+			&_lock);
+	clk_register_clkdev(clk, NULL, "b4100000.serial");
+
+	clk = clk_register_aux("sdhci_syn_clk", "sdhci_syn_gclk",
+			"vco1div2_clk", 0, SPEAR1340_SDHCI_CLK_SYNT, NULL,
+			aux_rtbl, ARRAY_SIZE(aux_rtbl), &_lock, &clk1);
+	clk_register_clkdev(clk, "sdhci_syn_clk", NULL);
+	clk_register_clkdev(clk1, "sdhci_syn_gclk", NULL);
+
+	clk = clk_register_gate(NULL, "sdhci_clk", "sdhci_syn_gclk",
+			CLK_SET_RATE_PARENT, SPEAR1340_PERIP1_CLK_ENB,
+			SPEAR1340_SDHCI_CLK_ENB, 0, &_lock);
+	clk_register_clkdev(clk, NULL, "b3000000.sdhci");
+
+	clk = clk_register_aux("cfxd_syn_clk", "cfxd_syn_gclk", "vco1div2_clk",
+			0, SPEAR1340_CFXD_CLK_SYNT, NULL, aux_rtbl,
+			ARRAY_SIZE(aux_rtbl), &_lock, &clk1);
+	clk_register_clkdev(clk, "cfxd_syn_clk", NULL);
+	clk_register_clkdev(clk1, "cfxd_syn_gclk", NULL);
+
+	clk = clk_register_gate(NULL, "cfxd_clk", "cfxd_syn_gclk",
+			CLK_SET_RATE_PARENT, SPEAR1340_PERIP1_CLK_ENB,
+			SPEAR1340_CFXD_CLK_ENB, 0, &_lock);
+	clk_register_clkdev(clk, NULL, "b2800000.cf");
+	clk_register_clkdev(clk, NULL, "arasan_xd");
+
+	clk = clk_register_aux("c3_syn_clk", "c3_syn_gclk", "vco1div2_clk", 0,
+			SPEAR1340_C3_CLK_SYNT, NULL, aux_rtbl,
+			ARRAY_SIZE(aux_rtbl), &_lock, &clk1);
+	clk_register_clkdev(clk, "c3_syn_clk", NULL);
+	clk_register_clkdev(clk1, "c3_syn_gclk", NULL);
+
+	clk = clk_register_mux(NULL, "c3_mclk", c3_parents,
+			ARRAY_SIZE(c3_parents),
+			CLK_SET_RATE_PARENT | CLK_SET_RATE_NO_REPARENT,
+			SPEAR1340_PERIP_CLK_CFG, SPEAR1340_C3_CLK_SHIFT,
+			SPEAR1340_C3_CLK_MASK, 0, &_lock);
+	clk_register_clkdev(clk, "c3_mclk", NULL);
+
+	clk = clk_register_gate(NULL, "c3_clk", "c3_mclk", CLK_SET_RATE_PARENT,
+			SPEAR1340_PERIP1_CLK_ENB, SPEAR1340_C3_CLK_ENB, 0,
+			&_lock);
+	clk_register_clkdev(clk, NULL, "e1800000.c3");
+
+	/* gmac */
+	clk = clk_register_mux(NULL, "phy_input_mclk", gmac_phy_input_parents,
+			ARRAY_SIZE(gmac_phy_input_parents),
+			CLK_SET_RATE_NO_REPARENT, SPEAR1340_GMAC_CLK_CFG,
+			SPEAR1340_GMAC_PHY_INPUT_CLK_SHIFT,
+			SPEAR1340_GMAC_PHY_INPUT_CLK_MASK, 0, &_lock);
+	clk_register_clkdev(clk, "phy_input_mclk", NULL);
+
+	clk = clk_register_aux("phy_syn_clk", "phy_syn_gclk", "phy_input_mclk",
+			0, SPEAR1340_GMAC_CLK_SYNT, NULL, gmac_rtbl,
+			ARRAY_SIZE(gmac_rtbl), &_lock, &clk1);
+	clk_register_clkdev(clk, "phy_syn_clk", NULL);
+	clk_register_clkdev(clk1, "phy_syn_gclk", NULL);
+
+	clk = clk_register_mux(NULL, "phy_mclk", gmac_phy_parents,
+			ARRAY_SIZE(gmac_phy_parents), CLK_SET_RATE_NO_REPARENT,
+			SPEAR1340_PERIP_CLK_CFG, SPEAR1340_GMAC_PHY_CLK_SHIFT,
+			SPEAR1340_GMAC_PHY_CLK_MASK, 0, &_lock);
+	clk_register_clkdev(clk, "stmmacphy.0", NULL);
+
+	/* clcd */
+	clk = clk_register_mux(NULL, "clcd_syn_mclk", clcd_synth_parents,
+			ARRAY_SIZE(clcd_synth_parents),
+			CLK_SET_RATE_NO_REPARENT, SPEAR1340_CLCD_CLK_SYNT,
+			SPEAR1340_CLCD_SYNT_CLK_SHIFT,
+			SPEAR1340_CLCD_SYNT_CLK_MASK, 0, &_lock);
+	clk_register_clkdev(clk, "clcd_syn_mclk", NULL);
+
+	clk = clk_register_frac("clcd_syn_clk", "clcd_syn_mclk", 0,
+			SPEAR1340_CLCD_CLK_SYNT, clcd_rtbl,
+			ARRAY_SIZE(clcd_rtbl), &_lock);
+	clk_register_clkdev(clk, "clcd_syn_clk", NULL);
+
+	clk = clk_register_mux(NULL, "clcd_pixel_mclk", clcd_pixel_parents,
+			ARRAY_SIZE(clcd_pixel_parents),
+			CLK_SET_RATE_PARENT | CLK_SET_RATE_NO_REPARENT,
+			SPEAR1340_PERIP_CLK_CFG, SPEAR1340_CLCD_CLK_SHIFT,
+			SPEAR1340_CLCD_CLK_MASK, 0, &_lock);
+	clk_register_clkdev(clk, "clcd_pixel_mclk", NULL);
+
+	clk = clk_register_gate(NULL, "clcd_clk", "clcd_pixel_mclk", 0,
+			SPEAR1340_PERIP1_CLK_ENB, SPEAR1340_CLCD_CLK_ENB, 0,
+			&_lock);
+	clk_register_clkdev(clk, NULL, "e1000000.clcd");
+
+	/* i2s */
+	clk = clk_register_mux(NULL, "i2s_src_mclk", i2s_src_parents,
+			ARRAY_SIZE(i2s_src_parents), CLK_SET_RATE_NO_REPARENT,
+			SPEAR1340_I2S_CLK_CFG, SPEAR1340_I2S_SRC_CLK_SHIFT,
+			SPEAR1340_I2S_SRC_CLK_MASK, 0, &_lock);
+	clk_register_clkdev(clk, "i2s_src_mclk", NULL);
+
+	clk = clk_register_aux("i2s_prs1_clk", NULL, "i2s_src_mclk",
+			CLK_SET_RATE_PARENT, SPEAR1340_I2S_CLK_CFG,
+			&i2s_prs1_masks, i2s_prs1_rtbl,
+			ARRAY_SIZE(i2s_prs1_rtbl), &_lock, NULL);
+	clk_register_clkdev(clk, "i2s_prs1_clk", NULL);
+
+	clk = clk_register_mux(NULL, "i2s_ref_mclk", i2s_ref_parents,
+			ARRAY_SIZE(i2s_ref_parents),
+			CLK_SET_RATE_PARENT | CLK_SET_RATE_NO_REPARENT,
+			SPEAR1340_I2S_CLK_CFG, SPEAR1340_I2S_REF_SHIFT,
+			SPEAR1340_I2S_REF_SEL_MASK, 0, &_lock);
+	clk_register_clkdev(clk, "i2s_ref_mclk", NULL);
+
+	clk = clk_register_gate(NULL, "i2s_ref_pad_clk", "i2s_ref_mclk", 0,
+			SPEAR1340_PERIP2_CLK_ENB, SPEAR1340_I2S_REF_PAD_CLK_ENB,
+			0, &_lock);
+	clk_register_clkdev(clk, "i2s_ref_pad_clk", NULL);
+
+	clk = clk_register_aux("i2s_sclk_clk", "i2s_sclk_gclk", "i2s_ref_mclk",
+			0, SPEAR1340_I2S_CLK_CFG, &i2s_sclk_masks,
+			i2s_sclk_rtbl, ARRAY_SIZE(i2s_sclk_rtbl), &_lock,
+			&clk1);
+	clk_register_clkdev(clk, "i2s_sclk_clk", NULL);
+	clk_register_clkdev(clk1, "i2s_sclk_gclk", NULL);
+
+	/* clock derived from ahb clk */
+	clk = clk_register_gate(NULL, "i2c0_clk", "ahb_clk", 0,
+			SPEAR1340_PERIP1_CLK_ENB, SPEAR1340_I2C0_CLK_ENB, 0,
+			&_lock);
+	clk_register_clkdev(clk, NULL, "e0280000.i2c");
+
+	clk = clk_register_gate(NULL, "i2c1_clk", "ahb_clk", 0,
+			SPEAR1340_PERIP3_CLK_ENB, SPEAR1340_I2C1_CLK_ENB, 0,
+			&_lock);
+	clk_register_clkdev(clk, NULL, "b4000000.i2c");
+
+	clk = clk_register_gate(NULL, "dma_clk", "ahb_clk", 0,
+			SPEAR1340_PERIP1_CLK_ENB, SPEAR1340_DMA_CLK_ENB, 0,
+			&_lock);
+	clk_register_clkdev(clk, NULL, "ea800000.dma");
+	clk_register_clkdev(clk, NULL, "eb000000.dma");
+
+	clk = clk_register_gate(NULL, "gmac_clk", "ahb_clk", 0,
+			SPEAR1340_PERIP1_CLK_ENB, SPEAR1340_GMAC_CLK_ENB, 0,
+			&_lock);
+	clk_register_clkdev(clk, NULL, "e2000000.eth");
+
+	clk = clk_register_gate(NULL, "fsmc_clk", "ahb_clk", 0,
+			SPEAR1340_PERIP1_CLK_ENB, SPEAR1340_FSMC_CLK_ENB, 0,
+			&_lock);
+	clk_register_clkdev(clk, NULL, "b0000000.flash");
+
+	clk = clk_register_gate(NULL, "smi_clk", "ahb_clk", 0,
+			SPEAR1340_PERIP1_CLK_ENB, SPEAR1340_SMI_CLK_ENB, 0,
+			&_lock);
+	clk_register_clkdev(clk, NULL, "ea000000.flash");
+
+	clk = clk_register_gate(NULL, "usbh0_clk", "ahb_clk", 0,
+			SPEAR1340_PERIP1_CLK_ENB, SPEAR1340_UHC0_CLK_ENB, 0,
+			&_lock);
+	clk_register_clkdev(clk, NULL, "e4000000.ohci");
+	clk_register_clkdev(clk, NULL, "e4800000.ehci");
+
+	clk = clk_register_gate(NULL, "usbh1_clk", "ahb_clk", 0,
+			SPEAR1340_PERIP1_CLK_ENB, SPEAR1340_UHC1_CLK_ENB, 0,
+			&_lock);
+	clk_register_clkdev(clk, NULL, "e5000000.ohci");
+	clk_register_clkdev(clk, NULL, "e5800000.ehci");
+
+	clk = clk_register_gate(NULL, "uoc_clk", "ahb_clk", 0,
+			SPEAR1340_PERIP1_CLK_ENB, SPEAR1340_UOC_CLK_ENB, 0,
+			&_lock);
+	clk_register_clkdev(clk, NULL, "e3800000.otg");
+
+	clk = clk_register_gate(NULL, "pcie_sata_clk", "ahb_clk", 0,
+			SPEAR1340_PERIP1_CLK_ENB, SPEAR1340_PCIE_SATA_CLK_ENB,
+			0, &_lock);
+	clk_register_clkdev(clk, NULL, "b1000000.pcie");
+	clk_register_clkdev(clk, NULL, "b1000000.ahci");
+
+	clk = clk_register_gate(NULL, "sysram0_clk", "ahb_clk", 0,
+			SPEAR1340_PERIP1_CLK_ENB, SPEAR1340_SYSRAM0_CLK_ENB, 0,
+			&_lock);
+	clk_register_clkdev(clk, "sysram0_clk", NULL);
+
+	clk = clk_register_gate(NULL, "sysram1_clk", "ahb_clk", 0,
+			SPEAR1340_PERIP1_CLK_ENB, SPEAR1340_SYSRAM1_CLK_ENB, 0,
+			&_lock);
+	clk_register_clkdev(clk, "sysram1_clk", NULL);
+
+	clk = clk_register_aux("adc_syn_clk", "adc_syn_gclk", "ahb_clk",
+			0, SPEAR1340_ADC_CLK_SYNT, NULL, adc_rtbl,
+			ARRAY_SIZE(adc_rtbl), &_lock, &clk1);
+	clk_register_clkdev(clk, "adc_syn_clk", NULL);
+	clk_register_clkdev(clk1, "adc_syn_gclk", NULL);
+
+	clk = clk_register_gate(NULL, "adc_clk", "adc_syn_gclk",
+			CLK_SET_RATE_PARENT, SPEAR1340_PERIP1_CLK_ENB,
+			SPEAR1340_ADC_CLK_ENB, 0, &_lock);
+	clk_register_clkdev(clk, NULL, "e0080000.adc");
+
+	/* clock derived from apb clk */
+	clk = clk_register_gate(NULL, "ssp_clk", "apb_clk", 0,
+			SPEAR1340_PERIP1_CLK_ENB, SPEAR1340_SSP_CLK_ENB, 0,
+			&_lock);
+	clk_register_clkdev(clk, NULL, "e0100000.spi");
+
+	clk = clk_register_gate(NULL, "gpio0_clk", "apb_clk", 0,
+			SPEAR1340_PERIP1_CLK_ENB, SPEAR1340_GPIO0_CLK_ENB, 0,
+			&_lock);
+	clk_register_clkdev(clk, NULL, "e0600000.gpio");
+
+	clk = clk_register_gate(NULL, "gpio1_clk", "apb_clk", 0,
+			SPEAR1340_PERIP1_CLK_ENB, SPEAR1340_GPIO1_CLK_ENB, 0,
+			&_lock);
+	clk_register_clkdev(clk, NULL, "e0680000.gpio");
+
+	clk = clk_register_gate(NULL, "i2s_play_clk", "apb_clk", 0,
+			SPEAR1340_PERIP1_CLK_ENB, SPEAR1340_I2S_PLAY_CLK_ENB, 0,
+			&_lock);
+	clk_register_clkdev(clk, NULL, "b2400000.i2s-play");
+
+	clk = clk_register_gate(NULL, "i2s_rec_clk", "apb_clk", 0,
+			SPEAR1340_PERIP1_CLK_ENB, SPEAR1340_I2S_REC_CLK_ENB, 0,
+			&_lock);
+	clk_register_clkdev(clk, NULL, "b2000000.i2s-rec");
+
+	clk = clk_register_gate(NULL, "kbd_clk", "apb_clk", 0,
+			SPEAR1340_PERIP2_CLK_ENB, SPEAR1340_KBD_CLK_ENB, 0,
+			&_lock);
+	clk_register_clkdev(clk, NULL, "e0300000.kbd");
+
+	/* RAS clks */
+	clk = clk_register_mux(NULL, "gen_syn0_1_mclk", gen_synth0_1_parents,
+			ARRAY_SIZE(gen_synth0_1_parents),
+			CLK_SET_RATE_NO_REPARENT, SPEAR1340_PLL_CFG,
+			SPEAR1340_GEN_SYNT0_1_CLK_SHIFT,
+			SPEAR1340_GEN_SYNT_CLK_MASK, 0, &_lock);
+	clk_register_clkdev(clk, "gen_syn0_1_mclk", NULL);
+
+	clk = clk_register_mux(NULL, "gen_syn2_3_mclk", gen_synth2_3_parents,
+			ARRAY_SIZE(gen_synth2_3_parents),
+			CLK_SET_RATE_NO_REPARENT, SPEAR1340_PLL_CFG,
+			SPEAR1340_GEN_SYNT2_3_CLK_SHIFT,
+			SPEAR1340_GEN_SYNT_CLK_MASK, 0, &_lock);
+	clk_register_clkdev(clk, "gen_syn2_3_mclk", NULL);
+
+	clk = clk_register_frac("gen_syn0_clk", "gen_syn0_1_mclk", 0,
+			SPEAR1340_GEN_CLK_SYNT0, gen_rtbl, ARRAY_SIZE(gen_rtbl),
+			&_lock);
+	clk_register_clkdev(clk, "gen_syn0_clk", NULL);
+
+	clk = clk_register_frac("gen_syn1_clk", "gen_syn0_1_mclk", 0,
+			SPEAR1340_GEN_CLK_SYNT1, gen_rtbl, ARRAY_SIZE(gen_rtbl),
+			&_lock);
+	clk_register_clkdev(clk, "gen_syn1_clk", NULL);
+
+	clk = clk_register_frac("gen_syn2_clk", "gen_syn2_3_mclk", 0,
+			SPEAR1340_GEN_CLK_SYNT2, gen_rtbl, ARRAY_SIZE(gen_rtbl),
+			&_lock);
+	clk_register_clkdev(clk, "gen_syn2_clk", NULL);
+
+	clk = clk_register_frac("gen_syn3_clk", "gen_syn2_3_mclk", 0,
+			SPEAR1340_GEN_CLK_SYNT3, gen_rtbl, ARRAY_SIZE(gen_rtbl),
+			&_lock);
+	clk_register_clkdev(clk, "gen_syn3_clk", NULL);
+
+	clk = clk_register_gate(NULL, "mali_clk", "gen_syn3_clk",
+			CLK_SET_RATE_PARENT, SPEAR1340_PERIP3_CLK_ENB,
+			SPEAR1340_MALI_CLK_ENB, 0, &_lock);
+	clk_register_clkdev(clk, NULL, "mali");
+
+	clk = clk_register_gate(NULL, "cec0_clk", "ahb_clk", 0,
+			SPEAR1340_PERIP3_CLK_ENB, SPEAR1340_CEC0_CLK_ENB, 0,
+			&_lock);
+	clk_register_clkdev(clk, NULL, "spear_cec.0");
+
+	clk = clk_register_gate(NULL, "cec1_clk", "ahb_clk", 0,
+			SPEAR1340_PERIP3_CLK_ENB, SPEAR1340_CEC1_CLK_ENB, 0,
+			&_lock);
+	clk_register_clkdev(clk, NULL, "spear_cec.1");
+
+	clk = clk_register_mux(NULL, "spdif_out_mclk", spdif_out_parents,
+			ARRAY_SIZE(spdif_out_parents),
+			CLK_SET_RATE_PARENT | CLK_SET_RATE_NO_REPARENT,
+			SPEAR1340_PERIP_CLK_CFG, SPEAR1340_SPDIF_OUT_CLK_SHIFT,
+			SPEAR1340_SPDIF_CLK_MASK, 0, &_lock);
+	clk_register_clkdev(clk, "spdif_out_mclk", NULL);
+
+	clk = clk_register_gate(NULL, "spdif_out_clk", "spdif_out_mclk",
+			CLK_SET_RATE_PARENT, SPEAR1340_PERIP3_CLK_ENB,
+			SPEAR1340_SPDIF_OUT_CLK_ENB, 0, &_lock);
+	clk_register_clkdev(clk, NULL, "d0000000.spdif-out");
+
+	clk = clk_register_mux(NULL, "spdif_in_mclk", spdif_in_parents,
+			ARRAY_SIZE(spdif_in_parents),
+			CLK_SET_RATE_PARENT | CLK_SET_RATE_NO_REPARENT,
+			SPEAR1340_PERIP_CLK_CFG, SPEAR1340_SPDIF_IN_CLK_SHIFT,
+			SPEAR1340_SPDIF_CLK_MASK, 0, &_lock);
+	clk_register_clkdev(clk, "spdif_in_mclk", NULL);
+
+	clk = clk_register_gate(NULL, "spdif_in_clk", "spdif_in_mclk",
+			CLK_SET_RATE_PARENT, SPEAR1340_PERIP3_CLK_ENB,
+			SPEAR1340_SPDIF_IN_CLK_ENB, 0, &_lock);
+	clk_register_clkdev(clk, NULL, "d0100000.spdif-in");
+
+	clk = clk_register_gate(NULL, "acp_clk", "ahb_clk", 0,
+			SPEAR1340_PERIP2_CLK_ENB, SPEAR1340_ACP_CLK_ENB, 0,
+			&_lock);
+	clk_register_clkdev(clk, NULL, "acp_clk");
+
+	clk = clk_register_gate(NULL, "plgpio_clk", "ahb_clk", 0,
+			SPEAR1340_PERIP3_CLK_ENB, SPEAR1340_PLGPIO_CLK_ENB, 0,
+			&_lock);
+	clk_register_clkdev(clk, NULL, "e2800000.gpio");
+
+	clk = clk_register_gate(NULL, "video_dec_clk", "ahb_clk", 0,
+			SPEAR1340_PERIP3_CLK_ENB, SPEAR1340_VIDEO_DEC_CLK_ENB,
+			0, &_lock);
+	clk_register_clkdev(clk, NULL, "video_dec");
+
+	clk = clk_register_gate(NULL, "video_enc_clk", "ahb_clk", 0,
+			SPEAR1340_PERIP3_CLK_ENB, SPEAR1340_VIDEO_ENC_CLK_ENB,
+			0, &_lock);
+	clk_register_clkdev(clk, NULL, "video_enc");
+
+	clk = clk_register_gate(NULL, "video_in_clk", "ahb_clk", 0,
+			SPEAR1340_PERIP3_CLK_ENB, SPEAR1340_VIDEO_IN_CLK_ENB, 0,
+			&_lock);
+	clk_register_clkdev(clk, NULL, "spear_vip");
+
+	clk = clk_register_gate(NULL, "cam0_clk", "ahb_clk", 0,
+			SPEAR1340_PERIP3_CLK_ENB, SPEAR1340_CAM0_CLK_ENB, 0,
+			&_lock);
+	clk_register_clkdev(clk, NULL, "d0200000.cam0");
+
+	clk = clk_register_gate(NULL, "cam1_clk", "ahb_clk", 0,
+			SPEAR1340_PERIP3_CLK_ENB, SPEAR1340_CAM1_CLK_ENB, 0,
+			&_lock);
+	clk_register_clkdev(clk, NULL, "d0300000.cam1");
+
+	clk = clk_register_gate(NULL, "cam2_clk", "ahb_clk", 0,
+			SPEAR1340_PERIP3_CLK_ENB, SPEAR1340_CAM2_CLK_ENB, 0,
+			&_lock);
+	clk_register_clkdev(clk, NULL, "d0400000.cam2");
+
+	clk = clk_register_gate(NULL, "cam3_clk", "ahb_clk", 0,
+			SPEAR1340_PERIP3_CLK_ENB, SPEAR1340_CAM3_CLK_ENB, 0,
+			&_lock);
+	clk_register_clkdev(clk, NULL, "d0500000.cam3");
+
+	clk = clk_register_gate(NULL, "pwm_clk", "ahb_clk", 0,
+			SPEAR1340_PERIP3_CLK_ENB, SPEAR1340_PWM_CLK_ENB, 0,
+			&_lock);
+	clk_register_clkdev(clk, NULL, "e0180000.pwm");
+}
diff --git a/drivers/clk/spear/spear3xx_clock.c b/drivers/clk/spear/spear3xx_clock.c
new file mode 100644
index 000000000..c403c66b6
--- /dev/null
+++ b/drivers/clk/spear/spear3xx_clock.c
@@ -0,0 +1,667 @@
+/*
+ * SPEAr3xx machines clock framework source file
+ *
+ * Copyright (C) 2012 ST Microelectronics
+ * Viresh Kumar <vireshk@kernel.org>
+ *
+ * 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.
+ */
+
+#include <linux/clk.h>
+#include <linux/clkdev.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/of_platform.h>
+#include <linux/spinlock_types.h>
+#include "clk.h"
+
+static DEFINE_SPINLOCK(_lock);
+
+#define PLL1_CTR			(misc_base + 0x008)
+#define PLL1_FRQ			(misc_base + 0x00C)
+#define PLL2_CTR			(misc_base + 0x014)
+#define PLL2_FRQ			(misc_base + 0x018)
+#define PLL_CLK_CFG			(misc_base + 0x020)
+	/* PLL_CLK_CFG register masks */
+	#define MCTR_CLK_SHIFT		28
+	#define MCTR_CLK_MASK		3
+
+#define CORE_CLK_CFG			(misc_base + 0x024)
+	/* CORE CLK CFG register masks */
+	#define GEN_SYNTH2_3_CLK_SHIFT	18
+	#define GEN_SYNTH2_3_CLK_MASK	1
+
+	#define HCLK_RATIO_SHIFT	10
+	#define HCLK_RATIO_MASK		2
+	#define PCLK_RATIO_SHIFT	8
+	#define PCLK_RATIO_MASK		2
+
+#define PERIP_CLK_CFG			(misc_base + 0x028)
+	/* PERIP_CLK_CFG register masks */
+	#define UART_CLK_SHIFT		4
+	#define UART_CLK_MASK		1
+	#define FIRDA_CLK_SHIFT		5
+	#define FIRDA_CLK_MASK		2
+	#define GPT0_CLK_SHIFT		8
+	#define GPT1_CLK_SHIFT		11
+	#define GPT2_CLK_SHIFT		12
+	#define GPT_CLK_MASK		1
+
+#define PERIP1_CLK_ENB			(misc_base + 0x02C)
+	/* PERIP1_CLK_ENB register masks */
+	#define UART_CLK_ENB		3
+	#define SSP_CLK_ENB		5
+	#define I2C_CLK_ENB		7
+	#define JPEG_CLK_ENB		8
+	#define FIRDA_CLK_ENB		10
+	#define GPT1_CLK_ENB		11
+	#define GPT2_CLK_ENB		12
+	#define ADC_CLK_ENB		15
+	#define RTC_CLK_ENB		17
+	#define GPIO_CLK_ENB		18
+	#define DMA_CLK_ENB		19
+	#define SMI_CLK_ENB		21
+	#define GMAC_CLK_ENB		23
+	#define USBD_CLK_ENB		24
+	#define USBH_CLK_ENB		25
+	#define C3_CLK_ENB		31
+
+#define RAS_CLK_ENB			(misc_base + 0x034)
+	#define RAS_AHB_CLK_ENB		0
+	#define RAS_PLL1_CLK_ENB	1
+	#define RAS_APB_CLK_ENB		2
+	#define RAS_32K_CLK_ENB		3
+	#define RAS_24M_CLK_ENB		4
+	#define RAS_48M_CLK_ENB		5
+	#define RAS_PLL2_CLK_ENB	7
+	#define RAS_SYNT0_CLK_ENB	8
+	#define RAS_SYNT1_CLK_ENB	9
+	#define RAS_SYNT2_CLK_ENB	10
+	#define RAS_SYNT3_CLK_ENB	11
+
+#define PRSC0_CLK_CFG			(misc_base + 0x044)
+#define PRSC1_CLK_CFG			(misc_base + 0x048)
+#define PRSC2_CLK_CFG			(misc_base + 0x04C)
+#define AMEM_CLK_CFG			(misc_base + 0x050)
+	#define AMEM_CLK_ENB		0
+
+#define CLCD_CLK_SYNT			(misc_base + 0x05C)
+#define FIRDA_CLK_SYNT			(misc_base + 0x060)
+#define UART_CLK_SYNT			(misc_base + 0x064)
+#define GMAC_CLK_SYNT			(misc_base + 0x068)
+#define GEN0_CLK_SYNT			(misc_base + 0x06C)
+#define GEN1_CLK_SYNT			(misc_base + 0x070)
+#define GEN2_CLK_SYNT			(misc_base + 0x074)
+#define GEN3_CLK_SYNT			(misc_base + 0x078)
+
+/* pll rate configuration table, in ascending order of rates */
+static struct pll_rate_tbl pll_rtbl[] = {
+	{.mode = 0, .m = 0x53, .n = 0x0C, .p = 0x1}, /* vco 332 & pll 166 MHz */
+	{.mode = 0, .m = 0x85, .n = 0x0C, .p = 0x1}, /* vco 532 & pll 266 MHz */
+	{.mode = 0, .m = 0xA6, .n = 0x0C, .p = 0x1}, /* vco 664 & pll 332 MHz */
+};
+
+/* aux rate configuration table, in ascending order of rates */
+static struct aux_rate_tbl aux_rtbl[] = {
+	/* For PLL1 = 332 MHz */
+	{.xscale = 1, .yscale = 81, .eq = 0}, /* 2.049 MHz */
+	{.xscale = 1, .yscale = 59, .eq = 0}, /* 2.822 MHz */
+	{.xscale = 2, .yscale = 81, .eq = 0}, /* 4.098 MHz */
+	{.xscale = 3, .yscale = 89, .eq = 0}, /* 5.644 MHz */
+	{.xscale = 4, .yscale = 81, .eq = 0}, /* 8.197 MHz */
+	{.xscale = 4, .yscale = 59, .eq = 0}, /* 11.254 MHz */
+	{.xscale = 2, .yscale = 27, .eq = 0}, /* 12.296 MHz */
+	{.xscale = 2, .yscale = 8, .eq = 0}, /* 41.5 MHz */
+	{.xscale = 2, .yscale = 4, .eq = 0}, /* 83 MHz */
+	{.xscale = 1, .yscale = 2, .eq = 1}, /* 166 MHz */
+};
+
+/* gpt rate configuration table, in ascending order of rates */
+static struct gpt_rate_tbl gpt_rtbl[] = {
+	/* For pll1 = 332 MHz */
+	{.mscale = 4, .nscale = 0}, /* 41.5 MHz */
+	{.mscale = 2, .nscale = 0}, /* 55.3 MHz */
+	{.mscale = 1, .nscale = 0}, /* 83 MHz */
+};
+
+/* clock parents */
+static const char *uart0_parents[] = { "pll3_clk", "uart_syn_gclk", };
+static const char *firda_parents[] = { "pll3_clk", "firda_syn_gclk",
+};
+static const char *gpt0_parents[] = { "pll3_clk", "gpt0_syn_clk", };
+static const char *gpt1_parents[] = { "pll3_clk", "gpt1_syn_clk", };
+static const char *gpt2_parents[] = { "pll3_clk", "gpt2_syn_clk", };
+static const char *gen2_3_parents[] = { "pll1_clk", "pll2_clk", };
+static const char *ddr_parents[] = { "ahb_clk", "ahbmult2_clk", "none",
+	"pll2_clk", };
+
+#ifdef CONFIG_MACH_SPEAR300
+static void __init spear300_clk_init(void)
+{
+	struct clk *clk;
+
+	clk = clk_register_fixed_factor(NULL, "clcd_clk", "ras_pll3_clk", 0,
+			1, 1);
+	clk_register_clkdev(clk, NULL, "60000000.clcd");
+
+	clk = clk_register_fixed_factor(NULL, "fsmc_clk", "ras_ahb_clk", 0, 1,
+			1);
+	clk_register_clkdev(clk, NULL, "94000000.flash");
+
+	clk = clk_register_fixed_factor(NULL, "sdhci_clk", "ras_ahb_clk", 0, 1,
+			1);
+	clk_register_clkdev(clk, NULL, "70000000.sdhci");
+
+	clk = clk_register_fixed_factor(NULL, "gpio1_clk", "ras_apb_clk", 0, 1,
+			1);
+	clk_register_clkdev(clk, NULL, "a9000000.gpio");
+
+	clk = clk_register_fixed_factor(NULL, "kbd_clk", "ras_apb_clk", 0, 1,
+			1);
+	clk_register_clkdev(clk, NULL, "a0000000.kbd");
+}
+#else
+static inline void spear300_clk_init(void) { }
+#endif
+
+/* array of all spear 310 clock lookups */
+#ifdef CONFIG_MACH_SPEAR310
+static void __init spear310_clk_init(void)
+{
+	struct clk *clk;
+
+	clk = clk_register_fixed_factor(NULL, "emi_clk", "ras_ahb_clk", 0, 1,
+			1);
+	clk_register_clkdev(clk, "emi", NULL);
+
+	clk = clk_register_fixed_factor(NULL, "fsmc_clk", "ras_ahb_clk", 0, 1,
+			1);
+	clk_register_clkdev(clk, NULL, "44000000.flash");
+
+	clk = clk_register_fixed_factor(NULL, "tdm_clk", "ras_ahb_clk", 0, 1,
+			1);
+	clk_register_clkdev(clk, NULL, "tdm");
+
+	clk = clk_register_fixed_factor(NULL, "uart1_clk", "ras_apb_clk", 0, 1,
+			1);
+	clk_register_clkdev(clk, NULL, "b2000000.serial");
+
+	clk = clk_register_fixed_factor(NULL, "uart2_clk", "ras_apb_clk", 0, 1,
+			1);
+	clk_register_clkdev(clk, NULL, "b2080000.serial");
+
+	clk = clk_register_fixed_factor(NULL, "uart3_clk", "ras_apb_clk", 0, 1,
+			1);
+	clk_register_clkdev(clk, NULL, "b2100000.serial");
+
+	clk = clk_register_fixed_factor(NULL, "uart4_clk", "ras_apb_clk", 0, 1,
+			1);
+	clk_register_clkdev(clk, NULL, "b2180000.serial");
+
+	clk = clk_register_fixed_factor(NULL, "uart5_clk", "ras_apb_clk", 0, 1,
+			1);
+	clk_register_clkdev(clk, NULL, "b2200000.serial");
+}
+#else
+static inline void spear310_clk_init(void) { }
+#endif
+
+/* array of all spear 320 clock lookups */
+#ifdef CONFIG_MACH_SPEAR320
+
+#define SPEAR320_CONTROL_REG		(soc_config_base + 0x0010)
+#define SPEAR320_EXT_CTRL_REG		(soc_config_base + 0x0018)
+
+	#define SPEAR320_UARTX_PCLK_MASK		0x1
+	#define SPEAR320_UART2_PCLK_SHIFT		8
+	#define SPEAR320_UART3_PCLK_SHIFT		9
+	#define SPEAR320_UART4_PCLK_SHIFT		10
+	#define SPEAR320_UART5_PCLK_SHIFT		11
+	#define SPEAR320_UART6_PCLK_SHIFT		12
+	#define SPEAR320_RS485_PCLK_SHIFT		13
+	#define SMII_PCLK_SHIFT				18
+	#define SMII_PCLK_MASK				2
+	#define SMII_PCLK_VAL_PAD			0x0
+	#define SMII_PCLK_VAL_PLL2			0x1
+	#define SMII_PCLK_VAL_SYNTH0			0x2
+	#define SDHCI_PCLK_SHIFT			15
+	#define SDHCI_PCLK_MASK				1
+	#define SDHCI_PCLK_VAL_48M			0x0
+	#define SDHCI_PCLK_VAL_SYNTH3			0x1
+	#define I2S_REF_PCLK_SHIFT			8
+	#define I2S_REF_PCLK_MASK			1
+	#define I2S_REF_PCLK_SYNTH_VAL			0x1
+	#define I2S_REF_PCLK_PLL2_VAL			0x0
+	#define UART1_PCLK_SHIFT			6
+	#define UART1_PCLK_MASK				1
+	#define SPEAR320_UARTX_PCLK_VAL_SYNTH1		0x0
+	#define SPEAR320_UARTX_PCLK_VAL_APB		0x1
+
+static const char *i2s_ref_parents[] = { "ras_pll2_clk", "ras_syn2_gclk", };
+static const char *sdhci_parents[] = { "ras_pll3_clk", "ras_syn3_gclk", };
+static const char *smii0_parents[] = { "smii_125m_pad", "ras_pll2_clk",
+	"ras_syn0_gclk", };
+static const char *uartx_parents[] = { "ras_syn1_gclk", "ras_apb_clk", };
+
+static void __init spear320_clk_init(void __iomem *soc_config_base,
+				     struct clk *ras_apb_clk)
+{
+	struct clk *clk;
+
+	clk = clk_register_fixed_rate(NULL, "smii_125m_pad_clk", NULL,
+			0, 125000000);
+	clk_register_clkdev(clk, "smii_125m_pad", NULL);
+
+	clk = clk_register_fixed_factor(NULL, "clcd_clk", "ras_pll3_clk", 0,
+			1, 1);
+	clk_register_clkdev(clk, NULL, "90000000.clcd");
+
+	clk = clk_register_fixed_factor(NULL, "emi_clk", "ras_ahb_clk", 0, 1,
+			1);
+	clk_register_clkdev(clk, "emi", NULL);
+
+	clk = clk_register_fixed_factor(NULL, "fsmc_clk", "ras_ahb_clk", 0, 1,
+			1);
+	clk_register_clkdev(clk, NULL, "4c000000.flash");
+
+	clk = clk_register_fixed_factor(NULL, "i2c1_clk", "ras_ahb_clk", 0, 1,
+			1);
+	clk_register_clkdev(clk, NULL, "a7000000.i2c");
+
+	clk = clk_register_fixed_factor(NULL, "pwm_clk", "ras_ahb_clk", 0, 1,
+			1);
+	clk_register_clkdev(clk, NULL, "a8000000.pwm");
+
+	clk = clk_register_fixed_factor(NULL, "ssp1_clk", "ras_ahb_clk", 0, 1,
+			1);
+	clk_register_clkdev(clk, NULL, "a5000000.spi");
+
+	clk = clk_register_fixed_factor(NULL, "ssp2_clk", "ras_ahb_clk", 0, 1,
+			1);
+	clk_register_clkdev(clk, NULL, "a6000000.spi");
+
+	clk = clk_register_fixed_factor(NULL, "can0_clk", "ras_apb_clk", 0, 1,
+			1);
+	clk_register_clkdev(clk, NULL, "c_can_platform.0");
+
+	clk = clk_register_fixed_factor(NULL, "can1_clk", "ras_apb_clk", 0, 1,
+			1);
+	clk_register_clkdev(clk, NULL, "c_can_platform.1");
+
+	clk = clk_register_fixed_factor(NULL, "i2s_clk", "ras_apb_clk", 0, 1,
+			1);
+	clk_register_clkdev(clk, NULL, "a9400000.i2s");
+
+	clk = clk_register_mux(NULL, "i2s_ref_clk", i2s_ref_parents,
+			ARRAY_SIZE(i2s_ref_parents),
+			CLK_SET_RATE_PARENT | CLK_SET_RATE_NO_REPARENT,
+			SPEAR320_CONTROL_REG, I2S_REF_PCLK_SHIFT,
+			I2S_REF_PCLK_MASK, 0, &_lock);
+	clk_register_clkdev(clk, "i2s_ref_clk", NULL);
+
+	clk = clk_register_fixed_factor(NULL, "i2s_sclk", "i2s_ref_clk",
+			CLK_SET_RATE_PARENT, 1,
+			4);
+	clk_register_clkdev(clk, "i2s_sclk", NULL);
+
+	clk = clk_register_fixed_factor(NULL, "macb1_clk", "ras_apb_clk", 0, 1,
+			1);
+	clk_register_clkdev(clk, "hclk", "aa000000.eth");
+
+	clk = clk_register_fixed_factor(NULL, "macb2_clk", "ras_apb_clk", 0, 1,
+			1);
+	clk_register_clkdev(clk, "hclk", "ab000000.eth");
+
+	clk = clk_register_mux(NULL, "rs485_clk", uartx_parents,
+			ARRAY_SIZE(uartx_parents),
+			CLK_SET_RATE_PARENT | CLK_SET_RATE_NO_REPARENT,
+			SPEAR320_EXT_CTRL_REG, SPEAR320_RS485_PCLK_SHIFT,
+			SPEAR320_UARTX_PCLK_MASK, 0, &_lock);
+	clk_register_clkdev(clk, NULL, "a9300000.serial");
+
+	clk = clk_register_mux(NULL, "sdhci_clk", sdhci_parents,
+			ARRAY_SIZE(sdhci_parents),
+			CLK_SET_RATE_PARENT | CLK_SET_RATE_NO_REPARENT,
+			SPEAR320_CONTROL_REG, SDHCI_PCLK_SHIFT, SDHCI_PCLK_MASK,
+			0, &_lock);
+	clk_register_clkdev(clk, NULL, "70000000.sdhci");
+
+	clk = clk_register_mux(NULL, "smii_pclk", smii0_parents,
+			ARRAY_SIZE(smii0_parents), CLK_SET_RATE_NO_REPARENT,
+			SPEAR320_CONTROL_REG, SMII_PCLK_SHIFT, SMII_PCLK_MASK,
+			0, &_lock);
+	clk_register_clkdev(clk, NULL, "smii_pclk");
+
+	clk = clk_register_fixed_factor(NULL, "smii_clk", "smii_pclk", 0, 1, 1);
+	clk_register_clkdev(clk, NULL, "smii");
+
+	clk = clk_register_mux(NULL, "uart1_clk", uartx_parents,
+			ARRAY_SIZE(uartx_parents),
+			CLK_SET_RATE_PARENT | CLK_SET_RATE_NO_REPARENT,
+			SPEAR320_CONTROL_REG, UART1_PCLK_SHIFT, UART1_PCLK_MASK,
+			0, &_lock);
+	clk_register_clkdev(clk, NULL, "a3000000.serial");
+	/* Enforce ras_apb_clk */
+	clk_set_parent(clk, ras_apb_clk);
+
+	clk = clk_register_mux(NULL, "uart2_clk", uartx_parents,
+			ARRAY_SIZE(uartx_parents),
+			CLK_SET_RATE_PARENT | CLK_SET_RATE_NO_REPARENT,
+			SPEAR320_EXT_CTRL_REG, SPEAR320_UART2_PCLK_SHIFT,
+			SPEAR320_UARTX_PCLK_MASK, 0, &_lock);
+	clk_register_clkdev(clk, NULL, "a4000000.serial");
+	/* Enforce ras_apb_clk */
+	clk_set_parent(clk, ras_apb_clk);
+
+	clk = clk_register_mux(NULL, "uart3_clk", uartx_parents,
+			ARRAY_SIZE(uartx_parents),
+			CLK_SET_RATE_PARENT | CLK_SET_RATE_NO_REPARENT,
+			SPEAR320_EXT_CTRL_REG, SPEAR320_UART3_PCLK_SHIFT,
+			SPEAR320_UARTX_PCLK_MASK, 0, &_lock);
+	clk_register_clkdev(clk, NULL, "a9100000.serial");
+
+	clk = clk_register_mux(NULL, "uart4_clk", uartx_parents,
+			ARRAY_SIZE(uartx_parents),
+			CLK_SET_RATE_PARENT | CLK_SET_RATE_NO_REPARENT,
+			SPEAR320_EXT_CTRL_REG, SPEAR320_UART4_PCLK_SHIFT,
+			SPEAR320_UARTX_PCLK_MASK, 0, &_lock);
+	clk_register_clkdev(clk, NULL, "a9200000.serial");
+
+	clk = clk_register_mux(NULL, "uart5_clk", uartx_parents,
+			ARRAY_SIZE(uartx_parents),
+			CLK_SET_RATE_PARENT | CLK_SET_RATE_NO_REPARENT,
+			SPEAR320_EXT_CTRL_REG, SPEAR320_UART5_PCLK_SHIFT,
+			SPEAR320_UARTX_PCLK_MASK, 0, &_lock);
+	clk_register_clkdev(clk, NULL, "60000000.serial");
+
+	clk = clk_register_mux(NULL, "uart6_clk", uartx_parents,
+			ARRAY_SIZE(uartx_parents),
+			CLK_SET_RATE_PARENT | CLK_SET_RATE_NO_REPARENT,
+			SPEAR320_EXT_CTRL_REG, SPEAR320_UART6_PCLK_SHIFT,
+			SPEAR320_UARTX_PCLK_MASK, 0, &_lock);
+	clk_register_clkdev(clk, NULL, "60100000.serial");
+}
+#else
+static inline void spear320_clk_init(void __iomem *sb, struct clk *rc) { }
+#endif
+
+void __init spear3xx_clk_init(void __iomem *misc_base, void __iomem *soc_config_base)
+{
+	struct clk *clk, *clk1, *ras_apb_clk;
+
+	clk = clk_register_fixed_rate(NULL, "osc_32k_clk", NULL, 0, 32000);
+	clk_register_clkdev(clk, "osc_32k_clk", NULL);
+
+	clk = clk_register_fixed_rate(NULL, "osc_24m_clk", NULL, 0, 24000000);
+	clk_register_clkdev(clk, "osc_24m_clk", NULL);
+
+	/* clock derived from 32 KHz osc clk */
+	clk = clk_register_gate(NULL, "rtc-spear", "osc_32k_clk", 0,
+			PERIP1_CLK_ENB, RTC_CLK_ENB, 0, &_lock);
+	clk_register_clkdev(clk, NULL, "fc900000.rtc");
+
+	/* clock derived from 24 MHz osc clk */
+	clk = clk_register_fixed_rate(NULL, "pll3_clk", "osc_24m_clk", 0,
+			48000000);
+	clk_register_clkdev(clk, "pll3_clk", NULL);
+
+	clk = clk_register_fixed_factor(NULL, "wdt_clk", "osc_24m_clk", 0, 1,
+			1);
+	clk_register_clkdev(clk, NULL, "fc880000.wdt");
+
+	clk = clk_register_vco_pll("vco1_clk", "pll1_clk", NULL,
+			"osc_24m_clk", 0, PLL1_CTR, PLL1_FRQ, pll_rtbl,
+			ARRAY_SIZE(pll_rtbl), &_lock, &clk1, NULL);
+	clk_register_clkdev(clk, "vco1_clk", NULL);
+	clk_register_clkdev(clk1, "pll1_clk", NULL);
+
+	clk = clk_register_vco_pll("vco2_clk", "pll2_clk", NULL,
+			"osc_24m_clk", 0, PLL2_CTR, PLL2_FRQ, pll_rtbl,
+			ARRAY_SIZE(pll_rtbl), &_lock, &clk1, NULL);
+	clk_register_clkdev(clk, "vco2_clk", NULL);
+	clk_register_clkdev(clk1, "pll2_clk", NULL);
+
+	/* clock derived from pll1 clk */
+	clk = clk_register_fixed_factor(NULL, "cpu_clk", "pll1_clk",
+			CLK_SET_RATE_PARENT, 1, 1);
+	clk_register_clkdev(clk, "cpu_clk", NULL);
+
+	clk = clk_register_divider(NULL, "ahb_clk", "pll1_clk",
+			CLK_SET_RATE_PARENT, CORE_CLK_CFG, HCLK_RATIO_SHIFT,
+			HCLK_RATIO_MASK, 0, &_lock);
+	clk_register_clkdev(clk, "ahb_clk", NULL);
+
+	clk = clk_register_aux("uart_syn_clk", "uart_syn_gclk", "pll1_clk", 0,
+			UART_CLK_SYNT, NULL, aux_rtbl, ARRAY_SIZE(aux_rtbl),
+			&_lock, &clk1);
+	clk_register_clkdev(clk, "uart_syn_clk", NULL);
+	clk_register_clkdev(clk1, "uart_syn_gclk", NULL);
+
+	clk = clk_register_mux(NULL, "uart0_mclk", uart0_parents,
+			ARRAY_SIZE(uart0_parents),
+			CLK_SET_RATE_PARENT | CLK_SET_RATE_NO_REPARENT,
+			PERIP_CLK_CFG, UART_CLK_SHIFT, UART_CLK_MASK, 0,
+			&_lock);
+	clk_register_clkdev(clk, "uart0_mclk", NULL);
+
+	clk = clk_register_gate(NULL, "uart0", "uart0_mclk",
+			CLK_SET_RATE_PARENT, PERIP1_CLK_ENB, UART_CLK_ENB, 0,
+			&_lock);
+	clk_register_clkdev(clk, NULL, "d0000000.serial");
+
+	clk = clk_register_aux("firda_syn_clk", "firda_syn_gclk", "pll1_clk", 0,
+			FIRDA_CLK_SYNT, NULL, aux_rtbl, ARRAY_SIZE(aux_rtbl),
+			&_lock, &clk1);
+	clk_register_clkdev(clk, "firda_syn_clk", NULL);
+	clk_register_clkdev(clk1, "firda_syn_gclk", NULL);
+
+	clk = clk_register_mux(NULL, "firda_mclk", firda_parents,
+			ARRAY_SIZE(firda_parents),
+			CLK_SET_RATE_PARENT | CLK_SET_RATE_NO_REPARENT,
+			PERIP_CLK_CFG, FIRDA_CLK_SHIFT, FIRDA_CLK_MASK, 0,
+			&_lock);
+	clk_register_clkdev(clk, "firda_mclk", NULL);
+
+	clk = clk_register_gate(NULL, "firda_clk", "firda_mclk",
+			CLK_SET_RATE_PARENT, PERIP1_CLK_ENB, FIRDA_CLK_ENB, 0,
+			&_lock);
+	clk_register_clkdev(clk, NULL, "firda");
+
+	/* gpt clocks */
+	clk_register_gpt("gpt0_syn_clk", "pll1_clk", 0, PRSC0_CLK_CFG, gpt_rtbl,
+			ARRAY_SIZE(gpt_rtbl), &_lock);
+	clk = clk_register_mux(NULL, "gpt0_clk", gpt0_parents,
+			ARRAY_SIZE(gpt0_parents),
+			CLK_SET_RATE_PARENT | CLK_SET_RATE_NO_REPARENT,
+			PERIP_CLK_CFG, GPT0_CLK_SHIFT, GPT_CLK_MASK, 0, &_lock);
+	clk_register_clkdev(clk, NULL, "gpt0");
+
+	clk_register_gpt("gpt1_syn_clk", "pll1_clk", 0, PRSC1_CLK_CFG, gpt_rtbl,
+			ARRAY_SIZE(gpt_rtbl), &_lock);
+	clk = clk_register_mux(NULL, "gpt1_mclk", gpt1_parents,
+			ARRAY_SIZE(gpt1_parents),
+			CLK_SET_RATE_PARENT | CLK_SET_RATE_NO_REPARENT,
+			PERIP_CLK_CFG, GPT1_CLK_SHIFT, GPT_CLK_MASK, 0, &_lock);
+	clk_register_clkdev(clk, "gpt1_mclk", NULL);
+	clk = clk_register_gate(NULL, "gpt1_clk", "gpt1_mclk",
+			CLK_SET_RATE_PARENT, PERIP1_CLK_ENB, GPT1_CLK_ENB, 0,
+			&_lock);
+	clk_register_clkdev(clk, NULL, "gpt1");
+
+	clk_register_gpt("gpt2_syn_clk", "pll1_clk", 0, PRSC2_CLK_CFG, gpt_rtbl,
+			ARRAY_SIZE(gpt_rtbl), &_lock);
+	clk = clk_register_mux(NULL, "gpt2_mclk", gpt2_parents,
+			ARRAY_SIZE(gpt2_parents),
+			CLK_SET_RATE_PARENT | CLK_SET_RATE_NO_REPARENT,
+			PERIP_CLK_CFG, GPT2_CLK_SHIFT, GPT_CLK_MASK, 0, &_lock);
+	clk_register_clkdev(clk, "gpt2_mclk", NULL);
+	clk = clk_register_gate(NULL, "gpt2_clk", "gpt2_mclk",
+			CLK_SET_RATE_PARENT, PERIP1_CLK_ENB, GPT2_CLK_ENB, 0,
+			&_lock);
+	clk_register_clkdev(clk, NULL, "gpt2");
+
+	/* general synths clocks */
+	clk = clk_register_aux("gen0_syn_clk", "gen0_syn_gclk", "pll1_clk",
+			0, GEN0_CLK_SYNT, NULL, aux_rtbl, ARRAY_SIZE(aux_rtbl),
+			&_lock, &clk1);
+	clk_register_clkdev(clk, "gen0_syn_clk", NULL);
+	clk_register_clkdev(clk1, "gen0_syn_gclk", NULL);
+
+	clk = clk_register_aux("gen1_syn_clk", "gen1_syn_gclk", "pll1_clk",
+			0, GEN1_CLK_SYNT, NULL, aux_rtbl, ARRAY_SIZE(aux_rtbl),
+			&_lock, &clk1);
+	clk_register_clkdev(clk, "gen1_syn_clk", NULL);
+	clk_register_clkdev(clk1, "gen1_syn_gclk", NULL);
+
+	clk = clk_register_mux(NULL, "gen2_3_par_clk", gen2_3_parents,
+			ARRAY_SIZE(gen2_3_parents), CLK_SET_RATE_NO_REPARENT,
+			CORE_CLK_CFG, GEN_SYNTH2_3_CLK_SHIFT,
+			GEN_SYNTH2_3_CLK_MASK, 0, &_lock);
+	clk_register_clkdev(clk, "gen2_3_par_clk", NULL);
+
+	clk = clk_register_aux("gen2_syn_clk", "gen2_syn_gclk",
+			"gen2_3_par_clk", 0, GEN2_CLK_SYNT, NULL, aux_rtbl,
+			ARRAY_SIZE(aux_rtbl), &_lock, &clk1);
+	clk_register_clkdev(clk, "gen2_syn_clk", NULL);
+	clk_register_clkdev(clk1, "gen2_syn_gclk", NULL);
+
+	clk = clk_register_aux("gen3_syn_clk", "gen3_syn_gclk",
+			"gen2_3_par_clk", 0, GEN3_CLK_SYNT, NULL, aux_rtbl,
+			ARRAY_SIZE(aux_rtbl), &_lock, &clk1);
+	clk_register_clkdev(clk, "gen3_syn_clk", NULL);
+	clk_register_clkdev(clk1, "gen3_syn_gclk", NULL);
+
+	/* clock derived from pll3 clk */
+	clk = clk_register_gate(NULL, "usbh_clk", "pll3_clk", 0, PERIP1_CLK_ENB,
+			USBH_CLK_ENB, 0, &_lock);
+	clk_register_clkdev(clk, NULL, "e1800000.ehci");
+	clk_register_clkdev(clk, NULL, "e1900000.ohci");
+	clk_register_clkdev(clk, NULL, "e2100000.ohci");
+
+	clk = clk_register_fixed_factor(NULL, "usbh.0_clk", "usbh_clk", 0, 1,
+			1);
+	clk_register_clkdev(clk, "usbh.0_clk", NULL);
+
+	clk = clk_register_fixed_factor(NULL, "usbh.1_clk", "usbh_clk", 0, 1,
+			1);
+	clk_register_clkdev(clk, "usbh.1_clk", NULL);
+
+	clk = clk_register_gate(NULL, "usbd_clk", "pll3_clk", 0, PERIP1_CLK_ENB,
+			USBD_CLK_ENB, 0, &_lock);
+	clk_register_clkdev(clk, NULL, "e1100000.usbd");
+
+	/* clock derived from ahb clk */
+	clk = clk_register_fixed_factor(NULL, "ahbmult2_clk", "ahb_clk", 0, 2,
+			1);
+	clk_register_clkdev(clk, "ahbmult2_clk", NULL);
+
+	clk = clk_register_mux(NULL, "ddr_clk", ddr_parents,
+			ARRAY_SIZE(ddr_parents), CLK_SET_RATE_NO_REPARENT,
+			PLL_CLK_CFG, MCTR_CLK_SHIFT, MCTR_CLK_MASK, 0, &_lock);
+	clk_register_clkdev(clk, "ddr_clk", NULL);
+
+	clk = clk_register_divider(NULL, "apb_clk", "ahb_clk",
+			CLK_SET_RATE_PARENT, CORE_CLK_CFG, PCLK_RATIO_SHIFT,
+			PCLK_RATIO_MASK, 0, &_lock);
+	clk_register_clkdev(clk, "apb_clk", NULL);
+
+	clk = clk_register_gate(NULL, "amem_clk", "ahb_clk", 0, AMEM_CLK_CFG,
+			AMEM_CLK_ENB, 0, &_lock);
+	clk_register_clkdev(clk, "amem_clk", NULL);
+
+	clk = clk_register_gate(NULL, "c3_clk", "ahb_clk", 0, PERIP1_CLK_ENB,
+			C3_CLK_ENB, 0, &_lock);
+	clk_register_clkdev(clk, NULL, "c3_clk");
+
+	clk = clk_register_gate(NULL, "dma_clk", "ahb_clk", 0, PERIP1_CLK_ENB,
+			DMA_CLK_ENB, 0, &_lock);
+	clk_register_clkdev(clk, NULL, "fc400000.dma");
+
+	clk = clk_register_gate(NULL, "gmac_clk", "ahb_clk", 0, PERIP1_CLK_ENB,
+			GMAC_CLK_ENB, 0, &_lock);
+	clk_register_clkdev(clk, NULL, "e0800000.eth");
+
+	clk = clk_register_gate(NULL, "i2c0_clk", "ahb_clk", 0, PERIP1_CLK_ENB,
+			I2C_CLK_ENB, 0, &_lock);
+	clk_register_clkdev(clk, NULL, "d0180000.i2c");
+
+	clk = clk_register_gate(NULL, "jpeg_clk", "ahb_clk", 0, PERIP1_CLK_ENB,
+			JPEG_CLK_ENB, 0, &_lock);
+	clk_register_clkdev(clk, NULL, "jpeg");
+
+	clk = clk_register_gate(NULL, "smi_clk", "ahb_clk", 0, PERIP1_CLK_ENB,
+			SMI_CLK_ENB, 0, &_lock);
+	clk_register_clkdev(clk, NULL, "fc000000.flash");
+
+	/* clock derived from apb clk */
+	clk = clk_register_gate(NULL, "adc_clk", "apb_clk", 0, PERIP1_CLK_ENB,
+			ADC_CLK_ENB, 0, &_lock);
+	clk_register_clkdev(clk, NULL, "d0080000.adc");
+
+	clk = clk_register_gate(NULL, "gpio0_clk", "apb_clk", 0, PERIP1_CLK_ENB,
+			GPIO_CLK_ENB, 0, &_lock);
+	clk_register_clkdev(clk, NULL, "fc980000.gpio");
+
+	clk = clk_register_gate(NULL, "ssp0_clk", "apb_clk", 0, PERIP1_CLK_ENB,
+			SSP_CLK_ENB, 0, &_lock);
+	clk_register_clkdev(clk, NULL, "d0100000.spi");
+
+	/* RAS clk enable */
+	clk = clk_register_gate(NULL, "ras_ahb_clk", "ahb_clk", 0, RAS_CLK_ENB,
+			RAS_AHB_CLK_ENB, 0, &_lock);
+	clk_register_clkdev(clk, "ras_ahb_clk", NULL);
+
+	clk = clk_register_gate(NULL, "ras_apb_clk", "apb_clk", 0, RAS_CLK_ENB,
+			RAS_APB_CLK_ENB, 0, &_lock);
+	clk_register_clkdev(clk, "ras_apb_clk", NULL);
+	ras_apb_clk = clk;
+
+	clk = clk_register_gate(NULL, "ras_32k_clk", "osc_32k_clk", 0,
+			RAS_CLK_ENB, RAS_32K_CLK_ENB, 0, &_lock);
+	clk_register_clkdev(clk, "ras_32k_clk", NULL);
+
+	clk = clk_register_gate(NULL, "ras_24m_clk", "osc_24m_clk", 0,
+			RAS_CLK_ENB, RAS_24M_CLK_ENB, 0, &_lock);
+	clk_register_clkdev(clk, "ras_24m_clk", NULL);
+
+	clk = clk_register_gate(NULL, "ras_pll1_clk", "pll1_clk", 0,
+			RAS_CLK_ENB, RAS_PLL1_CLK_ENB, 0, &_lock);
+	clk_register_clkdev(clk, "ras_pll1_clk", NULL);
+
+	clk = clk_register_gate(NULL, "ras_pll2_clk", "pll2_clk", 0,
+			RAS_CLK_ENB, RAS_PLL2_CLK_ENB, 0, &_lock);
+	clk_register_clkdev(clk, "ras_pll2_clk", NULL);
+
+	clk = clk_register_gate(NULL, "ras_pll3_clk", "pll3_clk", 0,
+			RAS_CLK_ENB, RAS_48M_CLK_ENB, 0, &_lock);
+	clk_register_clkdev(clk, "ras_pll3_clk", NULL);
+
+	clk = clk_register_gate(NULL, "ras_syn0_gclk", "gen0_syn_gclk",
+			CLK_SET_RATE_PARENT, RAS_CLK_ENB, RAS_SYNT0_CLK_ENB, 0,
+			&_lock);
+	clk_register_clkdev(clk, "ras_syn0_gclk", NULL);
+
+	clk = clk_register_gate(NULL, "ras_syn1_gclk", "gen1_syn_gclk",
+			CLK_SET_RATE_PARENT, RAS_CLK_ENB, RAS_SYNT1_CLK_ENB, 0,
+			&_lock);
+	clk_register_clkdev(clk, "ras_syn1_gclk", NULL);
+
+	clk = clk_register_gate(NULL, "ras_syn2_gclk", "gen2_syn_gclk",
+			CLK_SET_RATE_PARENT, RAS_CLK_ENB, RAS_SYNT2_CLK_ENB, 0,
+			&_lock);
+	clk_register_clkdev(clk, "ras_syn2_gclk", NULL);
+
+	clk = clk_register_gate(NULL, "ras_syn3_gclk", "gen3_syn_gclk",
+			CLK_SET_RATE_PARENT, RAS_CLK_ENB, RAS_SYNT3_CLK_ENB, 0,
+			&_lock);
+	clk_register_clkdev(clk, "ras_syn3_gclk", NULL);
+
+	if (of_machine_is_compatible("st,spear300"))
+		spear300_clk_init();
+	else if (of_machine_is_compatible("st,spear310"))
+		spear310_clk_init();
+	else if (of_machine_is_compatible("st,spear320"))
+		spear320_clk_init(soc_config_base, ras_apb_clk);
+}
diff --git a/drivers/clk/spear/spear6xx_clock.c b/drivers/clk/spear/spear6xx_clock.c
new file mode 100644
index 000000000..47810be7f
--- /dev/null
+++ b/drivers/clk/spear/spear6xx_clock.c
@@ -0,0 +1,340 @@
+/*
+ * SPEAr6xx machines clock framework source file
+ *
+ * Copyright (C) 2012 ST Microelectronics
+ * Viresh Kumar <vireshk@kernel.org>
+ *
+ * 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.
+ */
+
+#include <linux/clkdev.h>
+#include <linux/io.h>
+#include <linux/spinlock_types.h>
+#include "clk.h"
+
+static DEFINE_SPINLOCK(_lock);
+
+#define PLL1_CTR			(misc_base + 0x008)
+#define PLL1_FRQ			(misc_base + 0x00C)
+#define PLL2_CTR			(misc_base + 0x014)
+#define PLL2_FRQ			(misc_base + 0x018)
+#define PLL_CLK_CFG			(misc_base + 0x020)
+	/* PLL_CLK_CFG register masks */
+	#define MCTR_CLK_SHIFT		28
+	#define MCTR_CLK_MASK		3
+
+#define CORE_CLK_CFG			(misc_base + 0x024)
+	/* CORE CLK CFG register masks */
+	#define HCLK_RATIO_SHIFT	10
+	#define HCLK_RATIO_MASK		2
+	#define PCLK_RATIO_SHIFT	8
+	#define PCLK_RATIO_MASK		2
+
+#define PERIP_CLK_CFG			(misc_base + 0x028)
+	/* PERIP_CLK_CFG register masks */
+	#define CLCD_CLK_SHIFT		2
+	#define CLCD_CLK_MASK		2
+	#define UART_CLK_SHIFT		4
+	#define UART_CLK_MASK		1
+	#define FIRDA_CLK_SHIFT		5
+	#define FIRDA_CLK_MASK		2
+	#define GPT0_CLK_SHIFT		8
+	#define GPT1_CLK_SHIFT		10
+	#define GPT2_CLK_SHIFT		11
+	#define GPT3_CLK_SHIFT		12
+	#define GPT_CLK_MASK		1
+
+#define PERIP1_CLK_ENB			(misc_base + 0x02C)
+	/* PERIP1_CLK_ENB register masks */
+	#define UART0_CLK_ENB		3
+	#define UART1_CLK_ENB		4
+	#define SSP0_CLK_ENB		5
+	#define SSP1_CLK_ENB		6
+	#define I2C_CLK_ENB		7
+	#define JPEG_CLK_ENB		8
+	#define FSMC_CLK_ENB		9
+	#define FIRDA_CLK_ENB		10
+	#define GPT2_CLK_ENB		11
+	#define GPT3_CLK_ENB		12
+	#define GPIO2_CLK_ENB		13
+	#define SSP2_CLK_ENB		14
+	#define ADC_CLK_ENB		15
+	#define GPT1_CLK_ENB		11
+	#define RTC_CLK_ENB		17
+	#define GPIO1_CLK_ENB		18
+	#define DMA_CLK_ENB		19
+	#define SMI_CLK_ENB		21
+	#define CLCD_CLK_ENB		22
+	#define GMAC_CLK_ENB		23
+	#define USBD_CLK_ENB		24
+	#define USBH0_CLK_ENB		25
+	#define USBH1_CLK_ENB		26
+
+#define PRSC0_CLK_CFG			(misc_base + 0x044)
+#define PRSC1_CLK_CFG			(misc_base + 0x048)
+#define PRSC2_CLK_CFG			(misc_base + 0x04C)
+
+#define CLCD_CLK_SYNT			(misc_base + 0x05C)
+#define FIRDA_CLK_SYNT			(misc_base + 0x060)
+#define UART_CLK_SYNT			(misc_base + 0x064)
+
+/* vco rate configuration table, in ascending order of rates */
+static struct pll_rate_tbl pll_rtbl[] = {
+	{.mode = 0, .m = 0x53, .n = 0x0F, .p = 0x1}, /* vco 332 & pll 166 MHz */
+	{.mode = 0, .m = 0x85, .n = 0x0F, .p = 0x1}, /* vco 532 & pll 266 MHz */
+	{.mode = 0, .m = 0xA6, .n = 0x0F, .p = 0x1}, /* vco 664 & pll 332 MHz */
+};
+
+/* aux rate configuration table, in ascending order of rates */
+static struct aux_rate_tbl aux_rtbl[] = {
+	/* For PLL1 = 332 MHz */
+	{.xscale = 2, .yscale = 27, .eq = 0}, /* 12.296 MHz */
+	{.xscale = 2, .yscale = 8, .eq = 0}, /* 41.5 MHz */
+	{.xscale = 2, .yscale = 4, .eq = 0}, /* 83 MHz */
+	{.xscale = 1, .yscale = 2, .eq = 1}, /* 166 MHz */
+};
+
+static const char *clcd_parents[] = { "pll3_clk", "clcd_syn_gclk", };
+static const char *firda_parents[] = { "pll3_clk", "firda_syn_gclk", };
+static const char *uart_parents[] = { "pll3_clk", "uart_syn_gclk", };
+static const char *gpt0_1_parents[] = { "pll3_clk", "gpt0_1_syn_clk", };
+static const char *gpt2_parents[] = { "pll3_clk", "gpt2_syn_clk", };
+static const char *gpt3_parents[] = { "pll3_clk", "gpt3_syn_clk", };
+static const char *ddr_parents[] = { "ahb_clk", "ahbmult2_clk", "none",
+	"pll2_clk", };
+
+/* gpt rate configuration table, in ascending order of rates */
+static struct gpt_rate_tbl gpt_rtbl[] = {
+	/* For pll1 = 332 MHz */
+	{.mscale = 4, .nscale = 0}, /* 41.5 MHz */
+	{.mscale = 2, .nscale = 0}, /* 55.3 MHz */
+	{.mscale = 1, .nscale = 0}, /* 83 MHz */
+};
+
+void __init spear6xx_clk_init(void __iomem *misc_base)
+{
+	struct clk *clk, *clk1;
+
+	clk = clk_register_fixed_rate(NULL, "osc_32k_clk", NULL, 0, 32000);
+	clk_register_clkdev(clk, "osc_32k_clk", NULL);
+
+	clk = clk_register_fixed_rate(NULL, "osc_30m_clk", NULL, 0, 30000000);
+	clk_register_clkdev(clk, "osc_30m_clk", NULL);
+
+	/* clock derived from 32 KHz osc clk */
+	clk = clk_register_gate(NULL, "rtc_spear", "osc_32k_clk", 0,
+			PERIP1_CLK_ENB, RTC_CLK_ENB, 0, &_lock);
+	clk_register_clkdev(clk, NULL, "rtc-spear");
+
+	/* clock derived from 30 MHz osc clk */
+	clk = clk_register_fixed_rate(NULL, "pll3_clk", "osc_24m_clk", 0,
+			48000000);
+	clk_register_clkdev(clk, "pll3_clk", NULL);
+
+	clk = clk_register_vco_pll("vco1_clk", "pll1_clk", NULL, "osc_30m_clk",
+			0, PLL1_CTR, PLL1_FRQ, pll_rtbl, ARRAY_SIZE(pll_rtbl),
+			&_lock, &clk1, NULL);
+	clk_register_clkdev(clk, "vco1_clk", NULL);
+	clk_register_clkdev(clk1, "pll1_clk", NULL);
+
+	clk = clk_register_vco_pll("vco2_clk", "pll2_clk", NULL, "osc_30m_clk",
+			0, PLL2_CTR, PLL2_FRQ, pll_rtbl, ARRAY_SIZE(pll_rtbl),
+			&_lock, &clk1, NULL);
+	clk_register_clkdev(clk, "vco2_clk", NULL);
+	clk_register_clkdev(clk1, "pll2_clk", NULL);
+
+	clk = clk_register_fixed_factor(NULL, "wdt_clk", "osc_30m_clk", 0, 1,
+			1);
+	clk_register_clkdev(clk, NULL, "fc880000.wdt");
+
+	/* clock derived from pll1 clk */
+	clk = clk_register_fixed_factor(NULL, "cpu_clk", "pll1_clk",
+			CLK_SET_RATE_PARENT, 1, 1);
+	clk_register_clkdev(clk, "cpu_clk", NULL);
+
+	clk = clk_register_divider(NULL, "ahb_clk", "pll1_clk",
+			CLK_SET_RATE_PARENT, CORE_CLK_CFG, HCLK_RATIO_SHIFT,
+			HCLK_RATIO_MASK, 0, &_lock);
+	clk_register_clkdev(clk, "ahb_clk", NULL);
+
+	clk = clk_register_aux("uart_syn_clk", "uart_syn_gclk", "pll1_clk", 0,
+			UART_CLK_SYNT, NULL, aux_rtbl, ARRAY_SIZE(aux_rtbl),
+			&_lock, &clk1);
+	clk_register_clkdev(clk, "uart_syn_clk", NULL);
+	clk_register_clkdev(clk1, "uart_syn_gclk", NULL);
+
+	clk = clk_register_mux(NULL, "uart_mclk", uart_parents,
+			ARRAY_SIZE(uart_parents), CLK_SET_RATE_NO_REPARENT,
+			PERIP_CLK_CFG, UART_CLK_SHIFT, UART_CLK_MASK, 0,
+			&_lock);
+	clk_register_clkdev(clk, "uart_mclk", NULL);
+
+	clk = clk_register_gate(NULL, "uart0", "uart_mclk", 0, PERIP1_CLK_ENB,
+			UART0_CLK_ENB, 0, &_lock);
+	clk_register_clkdev(clk, NULL, "d0000000.serial");
+
+	clk = clk_register_gate(NULL, "uart1", "uart_mclk", 0, PERIP1_CLK_ENB,
+			UART1_CLK_ENB, 0, &_lock);
+	clk_register_clkdev(clk, NULL, "d0080000.serial");
+
+	clk = clk_register_aux("firda_syn_clk", "firda_syn_gclk", "pll1_clk",
+			0, FIRDA_CLK_SYNT, NULL, aux_rtbl, ARRAY_SIZE(aux_rtbl),
+			&_lock, &clk1);
+	clk_register_clkdev(clk, "firda_syn_clk", NULL);
+	clk_register_clkdev(clk1, "firda_syn_gclk", NULL);
+
+	clk = clk_register_mux(NULL, "firda_mclk", firda_parents,
+			ARRAY_SIZE(firda_parents), CLK_SET_RATE_NO_REPARENT,
+			PERIP_CLK_CFG, FIRDA_CLK_SHIFT, FIRDA_CLK_MASK, 0,
+			&_lock);
+	clk_register_clkdev(clk, "firda_mclk", NULL);
+
+	clk = clk_register_gate(NULL, "firda_clk", "firda_mclk", 0,
+			PERIP1_CLK_ENB, FIRDA_CLK_ENB, 0, &_lock);
+	clk_register_clkdev(clk, NULL, "firda");
+
+	clk = clk_register_aux("clcd_syn_clk", "clcd_syn_gclk", "pll1_clk",
+			0, CLCD_CLK_SYNT, NULL, aux_rtbl, ARRAY_SIZE(aux_rtbl),
+			&_lock, &clk1);
+	clk_register_clkdev(clk, "clcd_syn_clk", NULL);
+	clk_register_clkdev(clk1, "clcd_syn_gclk", NULL);
+
+	clk = clk_register_mux(NULL, "clcd_mclk", clcd_parents,
+			ARRAY_SIZE(clcd_parents), CLK_SET_RATE_NO_REPARENT,
+			PERIP_CLK_CFG, CLCD_CLK_SHIFT, CLCD_CLK_MASK, 0,
+			&_lock);
+	clk_register_clkdev(clk, "clcd_mclk", NULL);
+
+	clk = clk_register_gate(NULL, "clcd_clk", "clcd_mclk", 0,
+			PERIP1_CLK_ENB, CLCD_CLK_ENB, 0, &_lock);
+	clk_register_clkdev(clk, NULL, "clcd");
+
+	/* gpt clocks */
+	clk = clk_register_gpt("gpt0_1_syn_clk", "pll1_clk", 0, PRSC0_CLK_CFG,
+			gpt_rtbl, ARRAY_SIZE(gpt_rtbl), &_lock);
+	clk_register_clkdev(clk, "gpt0_1_syn_clk", NULL);
+
+	clk = clk_register_mux(NULL, "gpt0_mclk", gpt0_1_parents,
+			ARRAY_SIZE(gpt0_1_parents), CLK_SET_RATE_NO_REPARENT,
+			PERIP_CLK_CFG, GPT0_CLK_SHIFT, GPT_CLK_MASK, 0, &_lock);
+	clk_register_clkdev(clk, NULL, "gpt0");
+
+	clk = clk_register_mux(NULL, "gpt1_mclk", gpt0_1_parents,
+			ARRAY_SIZE(gpt0_1_parents), CLK_SET_RATE_NO_REPARENT,
+			PERIP_CLK_CFG, GPT1_CLK_SHIFT, GPT_CLK_MASK, 0, &_lock);
+	clk_register_clkdev(clk, "gpt1_mclk", NULL);
+
+	clk = clk_register_gate(NULL, "gpt1_clk", "gpt1_mclk", 0,
+			PERIP1_CLK_ENB, GPT1_CLK_ENB, 0, &_lock);
+	clk_register_clkdev(clk, NULL, "gpt1");
+
+	clk = clk_register_gpt("gpt2_syn_clk", "pll1_clk", 0, PRSC1_CLK_CFG,
+			gpt_rtbl, ARRAY_SIZE(gpt_rtbl), &_lock);
+	clk_register_clkdev(clk, "gpt2_syn_clk", NULL);
+
+	clk = clk_register_mux(NULL, "gpt2_mclk", gpt2_parents,
+			ARRAY_SIZE(gpt2_parents), CLK_SET_RATE_NO_REPARENT,
+			PERIP_CLK_CFG, GPT2_CLK_SHIFT, GPT_CLK_MASK, 0, &_lock);
+	clk_register_clkdev(clk, "gpt2_mclk", NULL);
+
+	clk = clk_register_gate(NULL, "gpt2_clk", "gpt2_mclk", 0,
+			PERIP1_CLK_ENB, GPT2_CLK_ENB, 0, &_lock);
+	clk_register_clkdev(clk, NULL, "gpt2");
+
+	clk = clk_register_gpt("gpt3_syn_clk", "pll1_clk", 0, PRSC2_CLK_CFG,
+			gpt_rtbl, ARRAY_SIZE(gpt_rtbl), &_lock);
+	clk_register_clkdev(clk, "gpt3_syn_clk", NULL);
+
+	clk = clk_register_mux(NULL, "gpt3_mclk", gpt3_parents,
+			ARRAY_SIZE(gpt3_parents), CLK_SET_RATE_NO_REPARENT,
+			PERIP_CLK_CFG, GPT3_CLK_SHIFT, GPT_CLK_MASK, 0, &_lock);
+	clk_register_clkdev(clk, "gpt3_mclk", NULL);
+
+	clk = clk_register_gate(NULL, "gpt3_clk", "gpt3_mclk", 0,
+			PERIP1_CLK_ENB, GPT3_CLK_ENB, 0, &_lock);
+	clk_register_clkdev(clk, NULL, "gpt3");
+
+	/* clock derived from pll3 clk */
+	clk = clk_register_gate(NULL, "usbh0_clk", "pll3_clk", 0,
+			PERIP1_CLK_ENB, USBH0_CLK_ENB, 0, &_lock);
+	clk_register_clkdev(clk, NULL, "e1800000.ehci");
+	clk_register_clkdev(clk, NULL, "e1900000.ohci");
+
+	clk = clk_register_gate(NULL, "usbh1_clk", "pll3_clk", 0,
+			PERIP1_CLK_ENB, USBH1_CLK_ENB, 0, &_lock);
+	clk_register_clkdev(clk, NULL, "e2000000.ehci");
+	clk_register_clkdev(clk, NULL, "e2100000.ohci");
+
+	clk = clk_register_gate(NULL, "usbd_clk", "pll3_clk", 0, PERIP1_CLK_ENB,
+			USBD_CLK_ENB, 0, &_lock);
+	clk_register_clkdev(clk, NULL, "designware_udc");
+
+	/* clock derived from ahb clk */
+	clk = clk_register_fixed_factor(NULL, "ahbmult2_clk", "ahb_clk", 0, 2,
+			1);
+	clk_register_clkdev(clk, "ahbmult2_clk", NULL);
+
+	clk = clk_register_mux(NULL, "ddr_clk", ddr_parents,
+			ARRAY_SIZE(ddr_parents), CLK_SET_RATE_NO_REPARENT,
+			PLL_CLK_CFG, MCTR_CLK_SHIFT, MCTR_CLK_MASK, 0, &_lock);
+	clk_register_clkdev(clk, "ddr_clk", NULL);
+
+	clk = clk_register_divider(NULL, "apb_clk", "ahb_clk",
+			CLK_SET_RATE_PARENT, CORE_CLK_CFG, PCLK_RATIO_SHIFT,
+			PCLK_RATIO_MASK, 0, &_lock);
+	clk_register_clkdev(clk, "apb_clk", NULL);
+
+	clk = clk_register_gate(NULL, "dma_clk", "ahb_clk", 0, PERIP1_CLK_ENB,
+			DMA_CLK_ENB, 0, &_lock);
+	clk_register_clkdev(clk, NULL, "fc400000.dma");
+
+	clk = clk_register_gate(NULL, "fsmc_clk", "ahb_clk", 0, PERIP1_CLK_ENB,
+			FSMC_CLK_ENB, 0, &_lock);
+	clk_register_clkdev(clk, NULL, "d1800000.flash");
+
+	clk = clk_register_gate(NULL, "gmac_clk", "ahb_clk", 0, PERIP1_CLK_ENB,
+			GMAC_CLK_ENB, 0, &_lock);
+	clk_register_clkdev(clk, NULL, "e0800000.ethernet");
+
+	clk = clk_register_gate(NULL, "i2c_clk", "ahb_clk", 0, PERIP1_CLK_ENB,
+			I2C_CLK_ENB, 0, &_lock);
+	clk_register_clkdev(clk, NULL, "d0200000.i2c");
+
+	clk = clk_register_gate(NULL, "jpeg_clk", "ahb_clk", 0, PERIP1_CLK_ENB,
+			JPEG_CLK_ENB, 0, &_lock);
+	clk_register_clkdev(clk, NULL, "jpeg");
+
+	clk = clk_register_gate(NULL, "smi_clk", "ahb_clk", 0, PERIP1_CLK_ENB,
+			SMI_CLK_ENB, 0, &_lock);
+	clk_register_clkdev(clk, NULL, "fc000000.flash");
+
+	/* clock derived from apb clk */
+	clk = clk_register_gate(NULL, "adc_clk", "apb_clk", 0, PERIP1_CLK_ENB,
+			ADC_CLK_ENB, 0, &_lock);
+	clk_register_clkdev(clk, NULL, "d820b000.adc");
+
+	clk = clk_register_fixed_factor(NULL, "gpio0_clk", "apb_clk", 0, 1, 1);
+	clk_register_clkdev(clk, NULL, "f0100000.gpio");
+
+	clk = clk_register_gate(NULL, "gpio1_clk", "apb_clk", 0, PERIP1_CLK_ENB,
+			GPIO1_CLK_ENB, 0, &_lock);
+	clk_register_clkdev(clk, NULL, "fc980000.gpio");
+
+	clk = clk_register_gate(NULL, "gpio2_clk", "apb_clk", 0, PERIP1_CLK_ENB,
+			GPIO2_CLK_ENB, 0, &_lock);
+	clk_register_clkdev(clk, NULL, "d8100000.gpio");
+
+	clk = clk_register_gate(NULL, "ssp0_clk", "apb_clk", 0, PERIP1_CLK_ENB,
+			SSP0_CLK_ENB, 0, &_lock);
+	clk_register_clkdev(clk, NULL, "ssp-pl022.0");
+
+	clk = clk_register_gate(NULL, "ssp1_clk", "apb_clk", 0, PERIP1_CLK_ENB,
+			SSP1_CLK_ENB, 0, &_lock);
+	clk_register_clkdev(clk, NULL, "ssp-pl022.1");
+
+	clk = clk_register_gate(NULL, "ssp2_clk", "apb_clk", 0, PERIP1_CLK_ENB,
+			SSP2_CLK_ENB, 0, &_lock);
+	clk_register_clkdev(clk, NULL, "ssp-pl022.2");
+}
-- 
cgit v1.2.3