linux-arm-msm.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v4 00/15] Add support for MSM's mmio clock/reset controller
@ 2013-12-24  1:12 Stephen Boyd
  2013-12-24  1:12 ` [PATCH v4 01/15] reset: Silence warning in reset-controller.h Stephen Boyd
                   ` (14 more replies)
  0 siblings, 15 replies; 34+ messages in thread
From: Stephen Boyd @ 2013-12-24  1:12 UTC (permalink / raw)
  To: Mike Turquette
  Cc: linux-kernel, linux-arm-msm, linux-arm-kernel, Saravana Kannan,
	Philipp Zabel, devicetree

The first breaks a reset-controller include ordering requirement. I hope it can
go through the clock tree.

The next 3 patches are generic clock framework patches. They add support for
regmap and for setting the rate and the parent at the same time based on
patches from James Hogan's remuxing set_rate series.

After that we add MSM clock hardware support and SoC specific drivers. The DT
node additions will be sent through the MSM maintainers once these patches are
accepted.

Changes since v3:
 * Moved binding include to clock/
 * New patch for 8660 GCC driver
 * Renamed directory to qcom to match vendor prefix
 * Added some missing clocks in 8974 GCC driver
 * New patch for 8974 MMCC driver

Changes since v2:

 * Completed 8960 and 8974 GCC data & dt-bindings
 * Added support for reset controllers
 * Squashed some bugs in 8974 gcc clocks
 * New patch to fix clk NULL pointer deref
 * New patch to fix #include requirement for reset-controller.h

Changes since v1:

 * Rewrote binding to use #clock-cells=1
 * Reworked library components (pll, rcg, branch) to use regmap
 * Dropped common clock framework patches that did DT parsing
 * New patches for regmap support in common clock framework

Stephen Boyd (15):
  reset: Silence warning in reset-controller.h
  clk: Allow drivers to pass in a regmap
  clk: Add regmap core helpers for enable/disable/is_enabled
  clk: Add set_rate_and_parent() op
  clk: qcom: Add support for phase locked loops (PLLs)
  clk: qcom: Add support for root clock generators (RCGs)
  clk: qcom: Add support for branches/gate clocks
  clk: qcom: Add reset controller support
  clk: qcom: Add support for MSM8960's global clock controller (GCC)
  clk: qcom: Add support for MSM8960's multimedia clock controller
    (MMCC)
  clk: qcom: Add support for MSM8974's global clock controller (GCC)
  clk: qcom: Add support for MSM8974's multimedia clock controller
    (MMCC)
  clk: qcom: Add support for MSM8660's global clock controller (GCC)
  devicetree: bindings: Document qcom,gcc
  devicetree: bindings: Document qcom,mmcc

 Documentation/clk.txt                              |    3 +
 .../devicetree/bindings/clock/qcom,gcc.txt         |   21 +
 .../devicetree/bindings/clock/qcom,mmcc.txt        |   21 +
 drivers/clk/Kconfig                                |    2 +
 drivers/clk/Makefile                               |    1 +
 drivers/clk/clk.c                                  |  156 +-
 drivers/clk/qcom/Kconfig                           |   47 +
 drivers/clk/qcom/Makefile                          |   13 +
 drivers/clk/qcom/clk-branch.c                      |  159 ++
 drivers/clk/qcom/clk-branch.h                      |   53 +
 drivers/clk/qcom/clk-pll.c                         |  222 ++
 drivers/clk/qcom/clk-pll.h                         |   65 +
 drivers/clk/qcom/clk-rcg.c                         |  517 ++++
 drivers/clk/qcom/clk-rcg.h                         |  157 +
 drivers/clk/qcom/clk-rcg2.c                        |  291 ++
 drivers/clk/qcom/gcc-msm8660.c                     | 2818 ++++++++++++++++++
 drivers/clk/qcom/gcc-msm8960.c                     | 2992 ++++++++++++++++++++
 drivers/clk/qcom/gcc-msm8974.c                     | 2693 ++++++++++++++++++
 drivers/clk/qcom/mmcc-msm8960.c                    | 2320 +++++++++++++++
 drivers/clk/qcom/mmcc-msm8974.c                    | 2624 +++++++++++++++++
 drivers/clk/qcom/reset.c                           |   63 +
 drivers/clk/qcom/reset.h                           |   37 +
 include/dt-bindings/clock/qcom,gcc-msm8660.h       |  276 ++
 include/dt-bindings/clock/qcom,gcc-msm8960.h       |  313 ++
 include/dt-bindings/clock/qcom,gcc-msm8974.h       |  320 +++
 include/dt-bindings/clock/qcom,mmcc-msm8960.h      |  137 +
 include/dt-bindings/clock/qcom,mmcc-msm8974.h      |  161 ++
 include/dt-bindings/reset/qcom,gcc-msm8660.h       |  134 +
 include/dt-bindings/reset/qcom,gcc-msm8960.h       |  118 +
 include/dt-bindings/reset/qcom,gcc-msm8974.h       |   96 +
 include/dt-bindings/reset/qcom,mmcc-msm8960.h      |   93 +
 include/dt-bindings/reset/qcom,mmcc-msm8974.h      |   62 +
 include/linux/clk-provider.h                       |   35 +
 include/linux/reset-controller.h                   |    1 +
 34 files changed, 17002 insertions(+), 19 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/clock/qcom,gcc.txt
 create mode 100644 Documentation/devicetree/bindings/clock/qcom,mmcc.txt
 create mode 100644 drivers/clk/qcom/Kconfig
 create mode 100644 drivers/clk/qcom/Makefile
 create mode 100644 drivers/clk/qcom/clk-branch.c
 create mode 100644 drivers/clk/qcom/clk-branch.h
 create mode 100644 drivers/clk/qcom/clk-pll.c
 create mode 100644 drivers/clk/qcom/clk-pll.h
 create mode 100644 drivers/clk/qcom/clk-rcg.c
 create mode 100644 drivers/clk/qcom/clk-rcg.h
 create mode 100644 drivers/clk/qcom/clk-rcg2.c
 create mode 100644 drivers/clk/qcom/gcc-msm8660.c
 create mode 100644 drivers/clk/qcom/gcc-msm8960.c
 create mode 100644 drivers/clk/qcom/gcc-msm8974.c
 create mode 100644 drivers/clk/qcom/mmcc-msm8960.c
 create mode 100644 drivers/clk/qcom/mmcc-msm8974.c
 create mode 100644 drivers/clk/qcom/reset.c
 create mode 100644 drivers/clk/qcom/reset.h
 create mode 100644 include/dt-bindings/clock/qcom,gcc-msm8660.h
 create mode 100644 include/dt-bindings/clock/qcom,gcc-msm8960.h
 create mode 100644 include/dt-bindings/clock/qcom,gcc-msm8974.h
 create mode 100644 include/dt-bindings/clock/qcom,mmcc-msm8960.h
 create mode 100644 include/dt-bindings/clock/qcom,mmcc-msm8974.h
 create mode 100644 include/dt-bindings/reset/qcom,gcc-msm8660.h
 create mode 100644 include/dt-bindings/reset/qcom,gcc-msm8960.h
 create mode 100644 include/dt-bindings/reset/qcom,gcc-msm8974.h
 create mode 100644 include/dt-bindings/reset/qcom,mmcc-msm8960.h
 create mode 100644 include/dt-bindings/reset/qcom,mmcc-msm8974.h

-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
hosted by The Linux Foundation

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

* [PATCH v4 01/15] reset: Silence warning in reset-controller.h
  2013-12-24  1:12 [PATCH v4 00/15] Add support for MSM's mmio clock/reset controller Stephen Boyd
@ 2013-12-24  1:12 ` Stephen Boyd
  2014-01-06 17:28   ` Philipp Zabel
  2013-12-24  1:12 ` [PATCH v4 02/15] clk: Allow drivers to pass in a regmap Stephen Boyd
                   ` (13 subsequent siblings)
  14 siblings, 1 reply; 34+ messages in thread
From: Stephen Boyd @ 2013-12-24  1:12 UTC (permalink / raw)
  To: Mike Turquette
  Cc: linux-kernel, linux-arm-msm, linux-arm-kernel, Saravana Kannan,
	Philipp Zabel

If a user of <linux/reset-controller.h> doesn't include
<linux/of.h> before including reset-controller.h they'll get a
warning as follows:

  include/linux/reset-controller.h:44:17:
  warning: 'struct of_phandle_args' declared inside parameter list

This is because of_phandle_args is not forward declared. Add the
declaration to silence this warning.

Cc: Philipp Zabel <p.zabel@pengutronix.de>
Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
---
 include/linux/reset-controller.h | 1 +
 1 file changed, 1 insertion(+)

diff --git a/include/linux/reset-controller.h b/include/linux/reset-controller.h
index 2f61311..41a4695 100644
--- a/include/linux/reset-controller.h
+++ b/include/linux/reset-controller.h
@@ -21,6 +21,7 @@ struct reset_control_ops {
 
 struct module;
 struct device_node;
+struct of_phandle_args;
 
 /**
  * struct reset_controller_dev - reset controller entity that might
-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
hosted by The Linux Foundation

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

* [PATCH v4 02/15] clk: Allow drivers to pass in a regmap
  2013-12-24  1:12 [PATCH v4 00/15] Add support for MSM's mmio clock/reset controller Stephen Boyd
  2013-12-24  1:12 ` [PATCH v4 01/15] reset: Silence warning in reset-controller.h Stephen Boyd
@ 2013-12-24  1:12 ` Stephen Boyd
  2013-12-24 13:13   ` Mark Brown
  2014-01-09  1:51   ` Mike Turquette
  2013-12-24  1:12 ` [PATCH v4 03/15] clk: Add regmap core helpers for enable/disable/is_enabled Stephen Boyd
                   ` (12 subsequent siblings)
  14 siblings, 2 replies; 34+ messages in thread
From: Stephen Boyd @ 2013-12-24  1:12 UTC (permalink / raw)
  To: Mike Turquette
  Cc: linux-arm-msm, Mark Brown, Saravana Kannan, linux-kernel,
	linux-arm-kernel

Add support to the clock core so that drivers can pass in a
regmap. If no regmap is specified try to query the device that's
registering the clock for its regmap. This should allow drivers
to use the core regmap helpers. This is based on a similar design
in the regulator framework.

Cc: Mark Brown <broonie@kernel.org>
Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
---
 drivers/clk/clk.c            | 8 ++++++++
 include/linux/clk-provider.h | 7 +++++++
 2 files changed, 15 insertions(+)

diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
index 9ad7b71..5e71f5c 100644
--- a/drivers/clk/clk.c
+++ b/drivers/clk/clk.c
@@ -20,6 +20,7 @@
 #include <linux/device.h>
 #include <linux/init.h>
 #include <linux/sched.h>
+#include <linux/regmap.h>
 
 static DEFINE_SPINLOCK(enable_lock);
 static DEFINE_MUTEX(prepare_lock);
@@ -1834,6 +1835,13 @@ static int _clk_register(struct device *dev, struct clk_hw *hw, struct clk *clk)
 	clk->num_parents = hw->init->num_parents;
 	hw->clk = clk;
 
+	if (hw->init->regmap)
+		hw->regmap = hw->init->regmap;
+	else if (dev && dev_get_regmap(dev, NULL))
+		hw->regmap = dev_get_regmap(dev, NULL);
+	else if (dev && dev->parent)
+		hw->regmap = dev_get_regmap(dev->parent, NULL);
+
 	/* allocate local copy in case parent_names is __initdata */
 	clk->parent_names = kcalloc(clk->num_parents, sizeof(char *),
 					GFP_KERNEL);
diff --git a/include/linux/clk-provider.h b/include/linux/clk-provider.h
index 7e59253..31f2890 100644
--- a/include/linux/clk-provider.h
+++ b/include/linux/clk-provider.h
@@ -142,6 +142,8 @@ struct clk_ops {
 	void		(*init)(struct clk_hw *hw);
 };
 
+struct regmap;
+
 /**
  * struct clk_init_data - holds init data that's common to all clocks and is
  * shared between the clock provider and the common clock framework.
@@ -151,6 +153,7 @@ struct clk_ops {
  * @parent_names: array of string names for all possible parents
  * @num_parents: number of possible parents
  * @flags: framework-level hints and quirks
+ * @regmap: regmap to use for regmap helpers and/or by providers
  */
 struct clk_init_data {
 	const char		*name;
@@ -158,6 +161,7 @@ struct clk_init_data {
 	const char		**parent_names;
 	u8			num_parents;
 	unsigned long		flags;
+	struct regmap		*regmap;
 };
 
 /**
@@ -171,10 +175,13 @@ struct clk_init_data {
  *
  * @init: pointer to struct clk_init_data that contains the init data shared
  * with the common clock framework.
+ *
+ * @regmap: regmap to use for regmap helpers and/or by providers
  */
 struct clk_hw {
 	struct clk *clk;
 	const struct clk_init_data *init;
+	struct regmap *regmap;
 };
 
 /*
-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
hosted by The Linux Foundation

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

* [PATCH v4 03/15] clk: Add regmap core helpers for enable/disable/is_enabled
  2013-12-24  1:12 [PATCH v4 00/15] Add support for MSM's mmio clock/reset controller Stephen Boyd
  2013-12-24  1:12 ` [PATCH v4 01/15] reset: Silence warning in reset-controller.h Stephen Boyd
  2013-12-24  1:12 ` [PATCH v4 02/15] clk: Allow drivers to pass in a regmap Stephen Boyd
@ 2013-12-24  1:12 ` Stephen Boyd
  2013-12-24 13:14   ` Mark Brown
  2013-12-24 15:07   ` Gerhard Sittig
  2013-12-24  1:12 ` [PATCH v4 04/15] clk: Add set_rate_and_parent() op Stephen Boyd
                   ` (11 subsequent siblings)
  14 siblings, 2 replies; 34+ messages in thread
From: Stephen Boyd @ 2013-12-24  1:12 UTC (permalink / raw)
  To: Mike Turquette
  Cc: linux-arm-msm, Mark Brown, Saravana Kannan, linux-kernel,
	linux-arm-kernel

The clock framework already has support for simple gate clocks
but if drivers want to use the gate clock functionality they need
to wrap the gate clock in another struct and chain the ops by
calling the gate ops from their own custom ops. Plus the gate
clock implementation only supports MMIO accessors so other bus
type clocks don't benefit from the potential code reuse. Add some
simple regmap helpers for enable/disable/is_enabled that drivers
can use as drop in replacements for their clock ops or as simple
functions they call from their own custom ops. This is based on 
similar helps in the regulator framework.

Cc: Mark Brown <broonie@kernel.org>
Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
---
 drivers/clk/clk.c            | 70 ++++++++++++++++++++++++++++++++++++++++++++
 include/linux/clk-provider.h | 13 ++++++++
 2 files changed, 83 insertions(+)

diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
index 5e71f5c..8b40170 100644
--- a/drivers/clk/clk.c
+++ b/drivers/clk/clk.c
@@ -742,6 +742,76 @@ out:
 	return best;
 }
 
+/**
+ * clk_is_enabled_regmap - standard is_enabled() for regmap users
+ *
+ * @hw: clk to operate on
+ *
+ * Clocks that use regmap for their register I/O can set the
+ * enable_reg and enable_mask fields in their struct clk_hw and then use
+ * this as their is_enabled operation, saving some code.
+ */
+int clk_is_enabled_regmap(struct clk_hw *hw)
+{
+	unsigned int val;
+	int ret;
+
+	ret = regmap_read(hw->regmap, hw->enable_reg, &val);
+	if (ret != 0)
+		return ret;
+
+	if (hw->enable_is_inverted)
+		return (val & hw->enable_mask) == 0;
+	else
+		return (val & hw->enable_mask) != 0;
+}
+EXPORT_SYMBOL_GPL(clk_is_enabled_regmap);
+
+/**
+ * clk_enable_regmap - standard enable() for regmap users
+ *
+ * @hw: clk to operate on
+ *
+ * Clocks that use regmap for their register I/O can set the
+ * enable_reg and enable_mask fields in their struct clk_hw and then use
+ * this as their enable() operation, saving some code.
+ */
+int clk_enable_regmap(struct clk_hw *hw)
+{
+	unsigned int val;
+
+	if (hw->enable_is_inverted)
+		val = 0;
+	else
+		val = hw->enable_mask;
+
+	return regmap_update_bits(hw->regmap, hw->enable_reg,
+				  hw->enable_mask, val);
+}
+EXPORT_SYMBOL_GPL(clk_enable_regmap);
+
+/**
+ * clk_disable_regmap - standard disable() for regmap users
+ *
+ * @hw: clk to operate on
+ *
+ * Clocks that use regmap for their register I/O can set the
+ * enable_reg and enable_mask fields in their struct clk_hw and then use
+ * this as their disable() operation, saving some code.
+ */
+void clk_disable_regmap(struct clk_hw *hw)
+{
+	unsigned int val;
+
+	if (hw->enable_is_inverted)
+		val = hw->enable_mask;
+	else
+		val = 0;
+
+	regmap_update_bits(hw->regmap, hw->enable_reg, hw->enable_mask, val);
+}
+EXPORT_SYMBOL_GPL(clk_disable_regmap);
+
 /***        clk api        ***/
 
 void __clk_unprepare(struct clk *clk)
diff --git a/include/linux/clk-provider.h b/include/linux/clk-provider.h
index 31f2890..61507fb 100644
--- a/include/linux/clk-provider.h
+++ b/include/linux/clk-provider.h
@@ -177,11 +177,21 @@ struct clk_init_data {
  * with the common clock framework.
  *
  * @regmap: regmap to use for regmap helpers and/or by providers
+ *
+ * @enable_reg: register when using regmap enable/disable ops
+ *
+ * @enable_mask: mask when using regmap enable/disable ops
+ *
+ * @enable_is_inverted: flag to indicate set enable_mask bits to disable
+ *                      when using clock_enable_regmap and friends APIs.
  */
 struct clk_hw {
 	struct clk *clk;
 	const struct clk_init_data *init;
 	struct regmap *regmap;
+	unsigned int enable_reg;
+	unsigned int enable_mask;
+	bool enable_is_inverted;
 };
 
 /*
@@ -447,6 +457,9 @@ struct clk *__clk_lookup(const char *name);
 long __clk_mux_determine_rate(struct clk_hw *hw, unsigned long rate,
 			      unsigned long *best_parent_rate,
 			      struct clk **best_parent_p);
+int clk_is_enabled_regmap(struct clk_hw *hw);
+int clk_enable_regmap(struct clk_hw *hw);
+void clk_disable_regmap(struct clk_hw *hw);
 
 /*
  * FIXME clock api without lock protection
-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
hosted by The Linux Foundation

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

* [PATCH v4 04/15] clk: Add set_rate_and_parent() op
  2013-12-24  1:12 [PATCH v4 00/15] Add support for MSM's mmio clock/reset controller Stephen Boyd
                   ` (2 preceding siblings ...)
  2013-12-24  1:12 ` [PATCH v4 03/15] clk: Add regmap core helpers for enable/disable/is_enabled Stephen Boyd
@ 2013-12-24  1:12 ` Stephen Boyd
  2013-12-24  1:12 ` [PATCH v4 05/15] clk: qcom: Add support for phase locked loops (PLLs) Stephen Boyd
                   ` (10 subsequent siblings)
  14 siblings, 0 replies; 34+ messages in thread
From: Stephen Boyd @ 2013-12-24  1:12 UTC (permalink / raw)
  To: Mike Turquette
  Cc: linux-arm-msm, Saravana Kannan, linux-kernel, linux-arm-kernel

Some of Qualcomm's clocks can change their parent and rate at the
same time with a single register write. Add support for this
hardware to the common clock framework by adding a new
set_rate_and_parent() op. When the clock framework determines
that both the parent and the rate are going to change during
clk_set_rate() it will call the .set_rate_and_parent() op if
available and fall back to calling .set_parent() followed by
.set_rate() otherwise.

Reviewed-by: James Hogan <james.hogan@imgtec.com>
Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
---
 Documentation/clk.txt        |  3 ++
 drivers/clk/clk.c            | 78 +++++++++++++++++++++++++++++++++-----------
 include/linux/clk-provider.h | 15 +++++++++
 3 files changed, 77 insertions(+), 19 deletions(-)

diff --git a/Documentation/clk.txt b/Documentation/clk.txt
index 3aeb5c4..79700ea 100644
--- a/Documentation/clk.txt
+++ b/Documentation/clk.txt
@@ -77,6 +77,9 @@ the operations defined in clk.h:
 		int		(*set_parent)(struct clk_hw *hw, u8 index);
 		u8		(*get_parent)(struct clk_hw *hw);
 		int		(*set_rate)(struct clk_hw *hw, unsigned long);
+		int		(*set_rate_and_parent)(struct clk_hw *hw,
+					    unsigned long rate,
+					    unsigned long parent_rate, u8 index);
 		void		(*init)(struct clk_hw *hw);
 	};
 
diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
index 8b40170..e33abeb 100644
--- a/drivers/clk/clk.c
+++ b/drivers/clk/clk.c
@@ -1200,10 +1200,9 @@ static void clk_reparent(struct clk *clk, struct clk *new_parent)
 	clk->parent = new_parent;
 }
 
-static int __clk_set_parent(struct clk *clk, struct clk *parent, u8 p_index)
+static struct clk *__clk_set_parent_before(struct clk *clk, struct clk *parent)
 {
 	unsigned long flags;
-	int ret = 0;
 	struct clk *old_parent = clk->parent;
 
 	/*
@@ -1234,6 +1233,34 @@ static int __clk_set_parent(struct clk *clk, struct clk *parent, u8 p_index)
 	clk_reparent(clk, parent);
 	clk_enable_unlock(flags);
 
+	return old_parent;
+}
+
+static void __clk_set_parent_after(struct clk *clk, struct clk *parent,
+		struct clk *old_parent)
+{
+	/*
+	 * Finish the migration of prepare state and undo the changes done
+	 * for preventing a race with clk_enable().
+	 */
+	if (clk->prepare_count) {
+		clk_disable(clk);
+		clk_disable(old_parent);
+		__clk_unprepare(old_parent);
+	}
+
+	/* update debugfs with new clk tree topology */
+	clk_debug_reparent(clk, parent);
+}
+
+static int __clk_set_parent(struct clk *clk, struct clk *parent, u8 p_index)
+{
+	unsigned long flags;
+	int ret = 0;
+	struct clk *old_parent;
+
+	old_parent = __clk_set_parent_before(clk, parent);
+
 	/* change clock input source */
 	if (parent && clk->ops->set_parent)
 		ret = clk->ops->set_parent(clk->hw, p_index);
@@ -1251,18 +1278,8 @@ static int __clk_set_parent(struct clk *clk, struct clk *parent, u8 p_index)
 		return ret;
 	}
 
-	/*
-	 * Finish the migration of prepare state and undo the changes done
-	 * for preventing a race with clk_enable().
-	 */
-	if (clk->prepare_count) {
-		clk_disable(clk);
-		clk_disable(old_parent);
-		__clk_unprepare(old_parent);
-	}
+	__clk_set_parent_after(clk, parent, old_parent);
 
-	/* update debugfs with new clk tree topology */
-	clk_debug_reparent(clk, parent);
 	return 0;
 }
 
@@ -1447,17 +1464,32 @@ static void clk_change_rate(struct clk *clk)
 	struct clk *child;
 	unsigned long old_rate;
 	unsigned long best_parent_rate = 0;
+	bool skip_set_rate = false;
+	struct clk *old_parent;
 
 	old_rate = clk->rate;
 
-	/* set parent */
-	if (clk->new_parent && clk->new_parent != clk->parent)
-		__clk_set_parent(clk, clk->new_parent, clk->new_parent_index);
-
-	if (clk->parent)
+	if (clk->new_parent)
+		best_parent_rate = clk->new_parent->rate;
+	else if (clk->parent)
 		best_parent_rate = clk->parent->rate;
 
-	if (clk->ops->set_rate)
+	if (clk->new_parent && clk->new_parent != clk->parent) {
+		old_parent = __clk_set_parent_before(clk, clk->new_parent);
+
+		if (clk->ops->set_rate_and_parent) {
+			skip_set_rate = true;
+			clk->ops->set_rate_and_parent(clk->hw, clk->new_rate,
+					best_parent_rate,
+					clk->new_parent_index);
+		} else if (clk->ops->set_parent) {
+			clk->ops->set_parent(clk->hw, clk->new_parent_index);
+		}
+
+		__clk_set_parent_after(clk, clk->new_parent, old_parent);
+	}
+
+	if (!skip_set_rate && clk->ops->set_rate)
 		clk->ops->set_rate(clk->hw, clk->new_rate, best_parent_rate);
 
 	if (clk->ops->recalc_rate)
@@ -1749,6 +1781,14 @@ int __clk_init(struct device *dev, struct clk *clk)
 		goto out;
 	}
 
+	if (clk->ops->set_rate_and_parent &&
+			!(clk->ops->set_parent && clk->ops->set_rate)) {
+		pr_warn("%s: %s must implement .set_parent & .set_rate\n",
+				__func__, clk->name);
+		ret = -EINVAL;
+		goto out;
+	}
+
 	/* throw a WARN if any entries in parent_names are NULL */
 	for (i = 0; i < clk->num_parents; i++)
 		WARN(!clk->parent_names[i],
diff --git a/include/linux/clk-provider.h b/include/linux/clk-provider.h
index 61507fb..3493c76 100644
--- a/include/linux/clk-provider.h
+++ b/include/linux/clk-provider.h
@@ -108,6 +108,18 @@ struct clk_hw;
  *		which is likely helpful for most .set_rate implementation.
  *		Returns 0 on success, -EERROR otherwise.
  *
+ * @set_rate_and_parent: Change the rate and the parent of this clock. The
+ *		requested rate is specified by the second argument, which
+ *		should typically be the return of .round_rate call.  The
+ *		third argument gives the parent rate which is likely helpful
+ *		for most .set_rate_and_parent implementation. The fourth
+ *		argument gives the parent index. This callback is optional (and
+ *		unnecessary) for clocks with 0 or 1 parents as well as
+ *		for clocks that can tolerate switching the rate and the parent
+ *		separately via calls to .set_parent and .set_rate.
+ *		Returns 0 on success, -EERROR otherwise.
+ *
+ *
  * The clk_enable/clk_disable and clk_prepare/clk_unprepare pairs allow
  * implementations to split any work between atomic (enable) and sleepable
  * (prepare) contexts.  If enabling a clock requires code that might sleep,
@@ -139,6 +151,9 @@ struct clk_ops {
 	u8		(*get_parent)(struct clk_hw *hw);
 	int		(*set_rate)(struct clk_hw *hw, unsigned long,
 				    unsigned long);
+	int		(*set_rate_and_parent)(struct clk_hw *hw,
+				    unsigned long rate,
+				    unsigned long parent_rate, u8 index);
 	void		(*init)(struct clk_hw *hw);
 };
 
-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
hosted by The Linux Foundation

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

* [PATCH v4 05/15] clk: qcom: Add support for phase locked loops (PLLs)
  2013-12-24  1:12 [PATCH v4 00/15] Add support for MSM's mmio clock/reset controller Stephen Boyd
                   ` (3 preceding siblings ...)
  2013-12-24  1:12 ` [PATCH v4 04/15] clk: Add set_rate_and_parent() op Stephen Boyd
@ 2013-12-24  1:12 ` Stephen Boyd
  2013-12-24  1:12 ` [PATCH v4 06/15] clk: qcom: Add support for root clock generators (RCGs) Stephen Boyd
                   ` (9 subsequent siblings)
  14 siblings, 0 replies; 34+ messages in thread
From: Stephen Boyd @ 2013-12-24  1:12 UTC (permalink / raw)
  To: Mike Turquette
  Cc: linux-kernel, linux-arm-msm, linux-arm-kernel, Saravana Kannan

Add support for Qualcomm's PLLs (phase locked loops). This is
sufficient enough to be able to determine the rate the PLL is
running at. We can add rate setting support later when it's
needed.

Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
---
 drivers/clk/Kconfig        |   2 +
 drivers/clk/Makefile       |   1 +
 drivers/clk/qcom/Kconfig   |   5 +
 drivers/clk/qcom/Makefile  |   3 +
 drivers/clk/qcom/clk-pll.c | 222 +++++++++++++++++++++++++++++++++++++++++++++
 drivers/clk/qcom/clk-pll.h |  65 +++++++++++++
 6 files changed, 298 insertions(+)
 create mode 100644 drivers/clk/qcom/Kconfig
 create mode 100644 drivers/clk/qcom/Makefile
 create mode 100644 drivers/clk/qcom/clk-pll.c
 create mode 100644 drivers/clk/qcom/clk-pll.h

diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig
index 5c51115..afd2a45 100644
--- a/drivers/clk/Kconfig
+++ b/drivers/clk/Kconfig
@@ -107,6 +107,8 @@ config COMMON_CLK_KEYSTONE
           Supports clock drivers for Keystone based SOCs. These SOCs have local
 	  a power sleep control module that gate the clock to the IPs and PLLs.
 
+source "drivers/clk/qcom/Kconfig"
+
 endmenu
 
 source "drivers/clk/mvebu/Kconfig"
diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile
index 7a10bc9..088b517 100644
--- a/drivers/clk/Makefile
+++ b/drivers/clk/Makefile
@@ -21,6 +21,7 @@ obj-$(CONFIG_PLAT_SPEAR)	+= spear/
 obj-$(CONFIG_ARCH_U300)		+= clk-u300.o
 obj-$(CONFIG_COMMON_CLK_VERSATILE) += versatile/
 obj-$(CONFIG_ARCH_SIRF)		+= clk-prima2.o
+obj-$(CONFIG_COMMON_CLK_QCOM)	+= qcom/
 obj-$(CONFIG_PLAT_ORION)	+= mvebu/
 ifeq ($(CONFIG_COMMON_CLK), y)
 obj-$(CONFIG_ARCH_MMP)		+= mmp/
diff --git a/drivers/clk/qcom/Kconfig b/drivers/clk/qcom/Kconfig
new file mode 100644
index 0000000..73a8c8f
--- /dev/null
+++ b/drivers/clk/qcom/Kconfig
@@ -0,0 +1,5 @@
+config COMMON_CLK_QCOM
+	tristate "Support for Qualcomm's clock controllers"
+	depends on OF
+	select REGMAP_MMIO
+
diff --git a/drivers/clk/qcom/Makefile b/drivers/clk/qcom/Makefile
new file mode 100644
index 0000000..9849a99
--- /dev/null
+++ b/drivers/clk/qcom/Makefile
@@ -0,0 +1,3 @@
+obj-$(CONFIG_COMMON_CLK_QCOM) += clk-qcom.o
+
+clk-qcom-$(CONFIG_COMMON_CLK_QCOM) += clk-pll.o
diff --git a/drivers/clk/qcom/clk-pll.c b/drivers/clk/qcom/clk-pll.c
new file mode 100644
index 0000000..b0d2a4e
--- /dev/null
+++ b/drivers/clk/qcom/clk-pll.c
@@ -0,0 +1,222 @@
+/*
+ * Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/kernel.h>
+#include <linux/bitops.h>
+#include <linux/err.h>
+#include <linux/bug.h>
+#include <linux/delay.h>
+#include <linux/export.h>
+#include <linux/clk-provider.h>
+#include <linux/regmap.h>
+
+#include <asm/div64.h>
+
+#include "clk-pll.h"
+
+#define PLL_OUTCTRL		BIT(0)
+#define PLL_BYPASSNL		BIT(1)
+#define PLL_RESET_N		BIT(2)
+#define PLL_LOCK_COUNT_SHIFT	8
+#define PLL_LOCK_COUNT_MASK	0x3f
+#define PLL_BIAS_COUNT_SHIFT	14
+#define PLL_BIAS_COUNT_MASK	0x3f
+#define PLL_VOTE_FSM_ENA	BIT(20)
+#define PLL_VOTE_FSM_RESET	BIT(21)
+
+static int clk_pll_enable(struct clk_hw *hw)
+{
+	struct clk_pll *pll = to_clk_pll(hw);
+	int ret;
+	u32 mask, val;
+
+	mask = PLL_OUTCTRL | PLL_RESET_N | PLL_BYPASSNL;
+	ret = regmap_read(hw->regmap, pll->mode_reg, &val);
+	if (ret)
+		return ret;
+
+	/* Skip if already enabled or in FSM mode */
+	if ((val & mask) == mask || val & PLL_VOTE_FSM_ENA)
+		return 0;
+
+	/* Disable PLL bypass mode. */
+	ret = regmap_update_bits(hw->regmap, pll->mode_reg, PLL_BYPASSNL,
+				 PLL_BYPASSNL);
+	if (ret)
+		return ret;
+
+	/*
+	 * H/W requires a 5us delay between disabling the bypass and
+	 * de-asserting the reset. Delay 10us just to be safe.
+	 */
+	udelay(10);
+
+	/* De-assert active-low PLL reset. */
+	ret = regmap_update_bits(hw->regmap, pll->mode_reg, PLL_RESET_N,
+				 PLL_RESET_N);
+	if (ret)
+		return ret;
+
+	/* Wait until PLL is locked. */
+	udelay(50);
+
+	/* Enable PLL output. */
+	ret = regmap_update_bits(hw->regmap, pll->mode_reg, PLL_OUTCTRL,
+				 PLL_OUTCTRL);
+	if (ret)
+		return ret;
+
+	return 0;
+}
+
+static void clk_pll_disable(struct clk_hw *hw)
+{
+	struct clk_pll *pll = to_clk_pll(hw);
+	u32 mask;
+	u32 val;
+
+	regmap_read(hw->regmap, pll->mode_reg, &val);
+	/* Skip if in FSM mode */
+	if (val & PLL_VOTE_FSM_ENA)
+		return;
+	mask = PLL_OUTCTRL | PLL_RESET_N | PLL_BYPASSNL;
+	regmap_update_bits(hw->regmap, pll->mode_reg, mask, 0);
+}
+
+static unsigned long
+clk_pll_recalc_rate(struct clk_hw *hw, unsigned long parent_rate)
+{
+	struct clk_pll *pll = to_clk_pll(hw);
+	u32 l, m, n;
+	unsigned long rate;
+	u64 tmp;
+
+	regmap_read(hw->regmap, pll->l_reg, &l);
+	regmap_read(hw->regmap, pll->m_reg, &m);
+	regmap_read(hw->regmap, pll->n_reg, &n);
+
+	l &= 0x3ff;
+	m &= 0x7ffff;
+	n &= 0x7ffff;
+
+	rate = parent_rate * l;
+	if (n) {
+		tmp = parent_rate;
+		tmp *= m;
+		do_div(tmp, n);
+		rate += tmp;
+	}
+	return rate;
+}
+
+const struct clk_ops clk_pll_ops = {
+	.enable = clk_pll_enable,
+	.disable = clk_pll_disable,
+	.recalc_rate = clk_pll_recalc_rate,
+};
+EXPORT_SYMBOL_GPL(clk_pll_ops);
+
+static int wait_for_pll(struct clk_pll *pll)
+{
+	u32 val;
+	int count;
+	int ret;
+	const char *name = __clk_get_name(pll->hw.clk);
+
+	/* Wait for pll to enable. */
+	for (count = 200; count > 0; count--) {
+		ret = regmap_read(pll->hw.regmap, pll->status_reg, &val);
+		if (ret)
+			return ret;
+		if (val & BIT(pll->status_bit))
+			return 0;
+		udelay(1);
+	}
+
+	WARN(1, "%s didn't enable after voting for it!\n", name);
+	return -ETIMEDOUT;
+}
+
+static int clk_pll_vote_enable(struct clk_hw *hw)
+{
+	int ret;
+	struct clk_pll *p = to_clk_pll(__clk_get_hw(__clk_get_parent(hw->clk)));
+
+	ret = clk_enable_regmap(hw);
+	if (ret)
+		return ret;
+
+	return wait_for_pll(p);
+}
+
+const struct clk_ops clk_pll_vote_ops = {
+	.enable = clk_pll_vote_enable,
+	.disable = clk_disable_regmap,
+};
+EXPORT_SYMBOL_GPL(clk_pll_vote_ops);
+
+static void
+clk_pll_set_fsm_mode(struct clk_pll *pll, struct regmap *regmap)
+{
+	u32 val;
+	u32 mask;
+
+	/* De-assert reset to FSM */
+	regmap_update_bits(regmap, pll->mode_reg, PLL_VOTE_FSM_RESET, 0);
+
+	/* Program bias count and lock count */
+	val = 1 << PLL_BIAS_COUNT_SHIFT;
+	mask = PLL_BIAS_COUNT_MASK << PLL_BIAS_COUNT_SHIFT;
+	mask |= PLL_LOCK_COUNT_MASK << PLL_LOCK_COUNT_SHIFT;
+	regmap_update_bits(regmap, pll->mode_reg, mask, val);
+
+	/* Enable PLL FSM voting */
+	regmap_update_bits(regmap, pll->mode_reg, PLL_VOTE_FSM_ENA,
+		PLL_VOTE_FSM_ENA);
+}
+
+static void clk_pll_configure(struct clk_pll *pll, struct regmap *regmap,
+	const struct pll_config *config)
+{
+	u32 val;
+	u32 mask;
+
+	regmap_write(regmap, pll->l_reg, config->l);
+	regmap_write(regmap, pll->m_reg, config->m);
+	regmap_write(regmap, pll->n_reg, config->n);
+
+	val = config->vco_val;
+	val |= config->pre_div_val;
+	val |= config->post_div_val;
+	val |= config->mn_ena_mask;
+	val |= config->main_output_mask;
+	val |= config->aux_output_mask;
+
+	mask = config->vco_mask;
+	mask |= config->pre_div_mask;
+	mask |= config->post_div_mask;
+	mask |= config->mn_ena_mask;
+	mask |= config->main_output_mask;
+	mask |= config->aux_output_mask;
+
+	regmap_update_bits(regmap, pll->config_reg, mask, val);
+}
+
+void clk_pll_configure_sr_hpm_lp(struct clk_pll *pll, struct regmap *regmap,
+		const struct pll_config *config, bool fsm_mode)
+{
+	clk_pll_configure(pll, regmap, config);
+	if (fsm_mode)
+		clk_pll_set_fsm_mode(pll, regmap);
+}
+EXPORT_SYMBOL_GPL(clk_pll_configure_sr_hpm_lp);
diff --git a/drivers/clk/qcom/clk-pll.h b/drivers/clk/qcom/clk-pll.h
new file mode 100644
index 0000000..86f8e90
--- /dev/null
+++ b/drivers/clk/qcom/clk-pll.h
@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef __MSM_CLK_PLL_H__
+#define __MSM_CLK_PLL_H__
+
+#include <linux/clk-provider.h>
+
+/**
+ * struct clk_pll - phase locked loop (PLL)
+ * @l_reg: L register
+ * @m_reg: M register
+ * @n_reg: N register
+ * @config_reg: config register
+ * @mode_reg: mode register
+ * @status_reg: status register
+ * @status_bit: ANDed with @status_reg to determine if PLL is enabled
+ * @hw: handle between common and hardware-specific interfaces
+ */
+struct clk_pll {
+	u32	l_reg;
+	u32	m_reg;
+	u32	n_reg;
+	u32	config_reg;
+	u32	mode_reg;
+	u32	status_reg;
+	u8	status_bit;
+
+	struct clk_hw	hw;
+};
+
+extern const struct clk_ops clk_pll_ops;
+extern const struct clk_ops clk_pll_vote_ops;
+
+#define to_clk_pll(_hw) container_of(_hw, struct clk_pll, hw)
+
+struct pll_config {
+	u16 l;
+	u32 m;
+	u32 n;
+	u32 vco_val;
+	u32 vco_mask;
+	u32 pre_div_val;
+	u32 pre_div_mask;
+	u32 post_div_val;
+	u32 post_div_mask;
+	u32 mn_ena_mask;
+	u32 main_output_mask;
+	u32 aux_output_mask;
+};
+
+void clk_pll_configure_sr_hpm_lp(struct clk_pll *pll, struct regmap *regmap,
+		const struct pll_config *config, bool fsm_mode);
+
+#endif
-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
hosted by The Linux Foundation

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

* [PATCH v4 06/15] clk: qcom: Add support for root clock generators (RCGs)
  2013-12-24  1:12 [PATCH v4 00/15] Add support for MSM's mmio clock/reset controller Stephen Boyd
                   ` (4 preceding siblings ...)
  2013-12-24  1:12 ` [PATCH v4 05/15] clk: qcom: Add support for phase locked loops (PLLs) Stephen Boyd
@ 2013-12-24  1:12 ` Stephen Boyd
  2013-12-24  1:12 ` [PATCH v4 07/15] clk: qcom: Add support for branches/gate clocks Stephen Boyd
                   ` (8 subsequent siblings)
  14 siblings, 0 replies; 34+ messages in thread
From: Stephen Boyd @ 2013-12-24  1:12 UTC (permalink / raw)
  To: Mike Turquette
  Cc: linux-kernel, linux-arm-msm, linux-arm-kernel, Saravana Kannan

Add support for the root clock generators on Qualcomm devices.
RCGs are highly customizable mux/divider/counter clocks that can
be used to generate almost any rate desired given some input
source that is faster than the desired rate.

Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
---
 drivers/clk/qcom/Makefile   |   2 +
 drivers/clk/qcom/clk-rcg.c  | 517 ++++++++++++++++++++++++++++++++++++++++++++
 drivers/clk/qcom/clk-rcg.h  | 157 ++++++++++++++
 drivers/clk/qcom/clk-rcg2.c | 291 +++++++++++++++++++++++++
 4 files changed, 967 insertions(+)
 create mode 100644 drivers/clk/qcom/clk-rcg.c
 create mode 100644 drivers/clk/qcom/clk-rcg.h
 create mode 100644 drivers/clk/qcom/clk-rcg2.c

diff --git a/drivers/clk/qcom/Makefile b/drivers/clk/qcom/Makefile
index 9849a99..7ed16d7 100644
--- a/drivers/clk/qcom/Makefile
+++ b/drivers/clk/qcom/Makefile
@@ -1,3 +1,5 @@
 obj-$(CONFIG_COMMON_CLK_QCOM) += clk-qcom.o
 
 clk-qcom-$(CONFIG_COMMON_CLK_QCOM) += clk-pll.o
+clk-qcom-$(CONFIG_COMMON_CLK_QCOM) += clk-rcg.o
+clk-qcom-$(CONFIG_COMMON_CLK_QCOM) += clk-rcg2.o
diff --git a/drivers/clk/qcom/clk-rcg.c b/drivers/clk/qcom/clk-rcg.c
new file mode 100644
index 0000000..afc0401
--- /dev/null
+++ b/drivers/clk/qcom/clk-rcg.c
@@ -0,0 +1,517 @@
+/*
+ * Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/kernel.h>
+#include <linux/bitops.h>
+#include <linux/err.h>
+#include <linux/export.h>
+#include <linux/clk-provider.h>
+#include <linux/regmap.h>
+
+#include <asm/div64.h>
+
+#include "clk-rcg.h"
+
+static u32 ns_to_src(struct src_sel *s, u32 ns)
+{
+	ns >>= s->src_sel_shift;
+	ns &= SRC_SEL_MASK;
+	return ns;
+}
+
+static u32 src_to_ns(struct src_sel *s, u8 src, u32 ns)
+{
+	u32 mask;
+
+	mask = SRC_SEL_MASK;
+	mask <<= s->src_sel_shift;
+	ns &= ~mask;
+
+	ns |= src << s->src_sel_shift;
+	return ns;
+}
+
+static u8 clk_rcg_get_parent(struct clk_hw *hw)
+{
+	struct clk_rcg *rcg = to_clk_rcg(hw);
+	int num_parents = __clk_get_num_parents(hw->clk);
+	u32 ns;
+	int i;
+
+	regmap_read(hw->regmap, rcg->ns_reg, &ns);
+	ns = ns_to_src(&rcg->s, ns);
+	for (i = 0; i < num_parents; i++)
+		if (ns == rcg->s.parent_map[i])
+			return i;
+
+	return -EINVAL;
+}
+
+static int reg_to_bank(struct clk_dyn_rcg *rcg, u32 bank)
+{
+	bank &= BIT(rcg->mux_sel_bit);
+	return !!bank;
+}
+
+static u8 clk_dyn_rcg_get_parent(struct clk_hw *hw)
+{
+	struct clk_dyn_rcg *rcg = to_clk_dyn_rcg(hw);
+	int num_parents = __clk_get_num_parents(hw->clk);
+	u32 ns, ctl;
+	int bank;
+	int i;
+	struct src_sel *s;
+
+	regmap_read(hw->regmap, hw->enable_reg, &ctl);
+	bank = reg_to_bank(rcg, ctl);
+	s = &rcg->s[bank];
+
+	regmap_read(hw->regmap, rcg->ns_reg, &ns);
+	ns = ns_to_src(s, ns);
+
+	for (i = 0; i < num_parents; i++)
+		if (ns == s->parent_map[i])
+			return i;
+
+	return -EINVAL;
+}
+
+static int clk_rcg_set_parent(struct clk_hw *hw, u8 index)
+{
+	struct clk_rcg *rcg = to_clk_rcg(hw);
+	u32 ns;
+
+	regmap_read(hw->regmap, rcg->ns_reg, &ns);
+	ns = src_to_ns(&rcg->s, rcg->s.parent_map[index], ns);
+	regmap_write(hw->regmap, rcg->ns_reg, ns);
+
+	return 0;
+}
+
+static u32 md_to_m(struct mn *mn, u32 md)
+{
+	md >>= mn->m_val_shift;
+	md &= BIT(mn->width) - 1;
+	return md;
+}
+
+static u32 ns_to_pre_div(struct pre_div *p, u32 ns)
+{
+	ns >>= p->pre_div_shift;
+	ns &= BIT(p->pre_div_width) - 1;
+	return ns;
+}
+
+static u32 pre_div_to_ns(struct pre_div *p, u8 pre_div, u32 ns)
+{
+	u32 mask;
+
+	mask = BIT(p->pre_div_width) - 1;
+	mask <<= p->pre_div_shift;
+	ns &= ~mask;
+
+	ns |= pre_div << p->pre_div_shift;
+	return ns;
+}
+
+static u32 mn_to_md(struct mn *mn, u32 m, u32 n, u32 md)
+{
+	u32 mask, mask_w;
+
+	mask_w = BIT(mn->width) - 1;
+	mask = (mask_w << mn->m_val_shift) | mask_w;
+	md &= ~mask;
+
+	if (n) {
+		m <<= mn->m_val_shift;
+		md |= m;
+		md |= ~n & mask_w;
+	}
+
+	return md;
+}
+
+static u32 ns_m_to_n(struct mn *mn, u32 ns, u32 m)
+{
+	ns = ~ns >> mn->n_val_shift;
+	ns &= BIT(mn->width) - 1;
+	return ns + m;
+}
+
+static u32 reg_to_mnctr_mode(struct mn *mn, u32 val)
+{
+	val >>= mn->mnctr_mode_shift;
+	val &= MNCTR_MODE_MASK;
+	return val;
+}
+
+static u32 mn_to_ns(struct mn *mn, u32 m, u32 n, u32 ns)
+{
+	u32 mask;
+
+	mask = BIT(mn->width) - 1;
+	mask <<= mn->n_val_shift;
+	ns &= ~mask;
+
+	if (n) {
+		n = n - m;
+		n = ~n;
+		n &= BIT(mn->width) - 1;
+		n <<= mn->n_val_shift;
+		ns |= n;
+	}
+
+	return ns;
+}
+
+static u32 mn_to_reg(struct mn *mn, u32 m, u32 n, u32 val)
+{
+	u32 mask;
+
+	mask = MNCTR_MODE_MASK << mn->mnctr_mode_shift;
+	mask |= BIT(mn->mnctr_en_bit);
+	val &= ~mask;
+
+	if (n) {
+		val |= BIT(mn->mnctr_en_bit);
+		val |= MNCTR_MODE_DUAL << mn->mnctr_mode_shift;
+	}
+
+	return val;
+}
+
+static void configure_bank(struct clk_dyn_rcg *rcg, const struct freq_tbl *f)
+{
+	u32 ns, md, ctl, *regp;
+	int bank, new_bank;
+	struct mn *mn;
+	struct pre_div *p;
+	struct src_sel *s;
+	bool enabled;
+	u32 md_reg;
+	u32 bank_reg;
+	bool banked_mn = !!rcg->mn[1].width;
+	struct clk_hw *hw = &rcg->hw;
+
+	enabled = __clk_is_enabled(rcg->hw.clk);
+
+	regmap_read(hw->regmap, rcg->ns_reg, &ns);
+	regmap_read(hw->regmap, hw->enable_reg, &ctl);
+
+	if (banked_mn) {
+		regp = &ctl;
+		bank_reg = hw->enable_reg;
+	} else {
+		regp = &ns;
+		bank_reg = rcg->ns_reg;
+	}
+
+	bank = reg_to_bank(rcg, *regp);
+	new_bank = enabled ? !bank : bank;
+
+	if (banked_mn) {
+		mn = &rcg->mn[new_bank];
+		md_reg = rcg->md_reg[new_bank];
+
+		ns |= BIT(mn->mnctr_reset_bit);
+		regmap_write(hw->regmap, rcg->ns_reg, ns);
+
+		regmap_read(hw->regmap, md_reg, &md);
+		md = mn_to_md(mn, f->m, f->n, md);
+		regmap_write(hw->regmap, md_reg, md);
+
+		ns = mn_to_ns(mn, f->m, f->n, ns);
+		regmap_write(hw->regmap, rcg->ns_reg, ns);
+
+		ctl = mn_to_reg(mn, f->m, f->n, ctl);
+		regmap_write(hw->regmap, hw->enable_reg, ctl);
+
+		ns &= ~BIT(mn->mnctr_reset_bit);
+		regmap_write(hw->regmap, rcg->ns_reg, ns);
+	} else {
+		p = &rcg->p[new_bank];
+		ns = pre_div_to_ns(p, f->pre_div - 1, ns);
+	}
+
+	s = &rcg->s[new_bank];
+	ns = src_to_ns(s, s->parent_map[f->src], ns);
+	regmap_write(hw->regmap, rcg->ns_reg, ns);
+
+	if (enabled) {
+		*regp ^= BIT(rcg->mux_sel_bit);
+		regmap_write(hw->regmap, bank_reg, *regp);
+	}
+}
+
+static int clk_dyn_rcg_set_parent(struct clk_hw *hw, u8 index)
+{
+	struct clk_dyn_rcg *rcg = to_clk_dyn_rcg(hw);
+	u32 ns, ctl, md, reg;
+	int bank;
+	struct freq_tbl f = { 0 };
+	bool banked_mn = !!rcg->mn[1].width;
+
+	regmap_read(hw->regmap, rcg->ns_reg, &ns);
+	regmap_read(hw->regmap, hw->enable_reg, &ctl);
+	reg = banked_mn ? ctl : ns;
+
+	bank = reg_to_bank(rcg, reg);
+
+	if (banked_mn) {
+		regmap_read(hw->regmap, rcg->md_reg[bank], &md);
+		f.m = md_to_m(&rcg->mn[bank], md);
+		f.n = ns_m_to_n(&rcg->mn[bank], ns, f.m);
+	} else {
+		f.pre_div = ns_to_pre_div(&rcg->p[bank], ns) + 1;
+	}
+	f.src = index;
+
+	configure_bank(rcg, &f);
+
+	return 0;
+}
+
+/*
+ * Calculate m/n:d rate
+ *
+ *          parent_rate     m
+ *   rate = ----------- x  ---
+ *            pre_div       n
+ */
+static unsigned long
+calc_rate(unsigned long rate, u32 m, u32 n, u32 mode, u32 pre_div)
+{
+	if (pre_div)
+		rate /= pre_div + 1;
+
+	if (mode) {
+		u64 tmp = rate;
+		tmp *= m;
+		do_div(tmp, n);
+		rate = tmp;
+	}
+
+	return rate;
+}
+
+static unsigned long
+clk_rcg_recalc_rate(struct clk_hw *hw, unsigned long parent_rate)
+{
+	struct clk_rcg *rcg = to_clk_rcg(hw);
+	u32 pre_div, m = 0, n = 0, ns, md, mode = 0;
+	struct mn *mn = &rcg->mn;
+
+	regmap_read(hw->regmap, rcg->ns_reg, &ns);
+	pre_div = ns_to_pre_div(&rcg->p, ns);
+
+	if (rcg->mn.width) {
+		regmap_read(hw->regmap, rcg->md_reg, &md);
+		m = md_to_m(mn, md);
+		n = ns_m_to_n(mn, ns, m);
+		/* MN counter mode is in hw.enable_reg sometimes */
+		if (hw->enable_reg != rcg->ns_reg)
+			regmap_read(hw->regmap, hw->enable_reg, &mode);
+		else
+			mode = ns;
+		mode = reg_to_mnctr_mode(mn, mode);
+	}
+
+	return calc_rate(parent_rate, m, n, mode, pre_div);
+}
+
+static unsigned long
+clk_dyn_rcg_recalc_rate(struct clk_hw *hw, unsigned long parent_rate)
+{
+	struct clk_dyn_rcg *rcg = to_clk_dyn_rcg(hw);
+	u32 m, n, pre_div, ns, md, mode, reg;
+	int bank;
+	struct mn *mn;
+	bool banked_mn = !!rcg->mn[1].width;
+
+	regmap_read(hw->regmap, rcg->ns_reg, &ns);
+
+	if (banked_mn)
+		regmap_read(hw->regmap, hw->enable_reg, &reg);
+	else
+		reg = ns;
+
+	bank = reg_to_bank(rcg, reg);
+
+	if (banked_mn) {
+		mn = &rcg->mn[bank];
+		regmap_read(hw->regmap, rcg->md_reg[bank], &md);
+		m = md_to_m(mn, md);
+		n = ns_m_to_n(mn, ns, m);
+		mode = reg_to_mnctr_mode(mn, reg);
+		return calc_rate(parent_rate, m, n, mode, 0);
+	} else {
+		pre_div = ns_to_pre_div(&rcg->p[bank], ns);
+		return calc_rate(parent_rate, 0, 0, 0, pre_div);
+	}
+}
+
+static const
+struct freq_tbl *find_freq(const struct freq_tbl *f, unsigned long rate)
+{
+	if (!f)
+		return NULL;
+
+	for (; f->freq; f++)
+		if (rate <= f->freq)
+			return f;
+
+	return NULL;
+}
+
+static long _freq_tbl_determine_rate(struct clk_hw *hw,
+		const struct freq_tbl *f, unsigned long rate,
+		unsigned long *p_rate, struct clk **p)
+{
+	unsigned long clk_flags;
+
+	f = find_freq(f, rate);
+	if (!f)
+		return -EINVAL;
+
+	clk_flags = __clk_get_flags(hw->clk);
+	*p = clk_get_parent_by_index(hw->clk, f->src);
+	if (clk_flags & CLK_SET_RATE_PARENT) {
+		rate = rate * f->pre_div;
+		if (f->n) {
+			u64 tmp = rate;
+			tmp = tmp * f->n;
+			do_div(tmp, f->m);
+			rate = tmp;
+		}
+	} else {
+		rate =  __clk_get_rate(*p);
+	}
+	*p_rate = rate;
+
+	return f->freq;
+}
+
+static long clk_rcg_determine_rate(struct clk_hw *hw, unsigned long rate,
+		unsigned long *p_rate, struct clk **p)
+{
+	struct clk_rcg *rcg = to_clk_rcg(hw);
+
+	return _freq_tbl_determine_rate(hw, rcg->freq_tbl, rate, p_rate, p);
+}
+
+static long clk_dyn_rcg_determine_rate(struct clk_hw *hw, unsigned long rate,
+		unsigned long *p_rate, struct clk **p)
+{
+	struct clk_dyn_rcg *rcg = to_clk_dyn_rcg(hw);
+
+	return _freq_tbl_determine_rate(hw, rcg->freq_tbl, rate, p_rate, p);
+}
+
+static int clk_rcg_set_rate(struct clk_hw *hw, unsigned long rate,
+			    unsigned long parent_rate)
+{
+	struct clk_rcg *rcg = to_clk_rcg(hw);
+	const struct freq_tbl *f;
+	u32 ns, md, ctl;
+	struct mn *mn = &rcg->mn;
+	u32 mask = 0;
+	unsigned int reset_reg;
+
+	f = find_freq(rcg->freq_tbl, rate);
+	if (!f)
+		return -EINVAL;
+
+	if (rcg->mn.reset_in_cc)
+		reset_reg = hw->enable_reg;
+	else
+		reset_reg = rcg->ns_reg;
+
+	if (rcg->mn.width) {
+		mask = BIT(mn->mnctr_reset_bit);
+		regmap_update_bits(hw->regmap, reset_reg, mask, mask);
+
+		regmap_read(hw->regmap, rcg->md_reg, &md);
+		md = mn_to_md(mn, f->m, f->n, md);
+		regmap_write(hw->regmap, rcg->md_reg, md);
+
+		regmap_read(hw->regmap, rcg->ns_reg, &ns);
+		/* MN counter mode is in hw.enable_reg sometimes */
+		if (hw->enable_reg != rcg->ns_reg) {
+			regmap_read(hw->regmap, hw->enable_reg, &ctl);
+			ctl = mn_to_reg(mn, f->m, f->n, ctl);
+			regmap_write(hw->regmap, hw->enable_reg, ctl);
+		} else {
+			ns = mn_to_reg(mn, f->m, f->n, ns);
+		}
+		ns = mn_to_ns(mn, f->m, f->n, ns);
+	} else {
+		regmap_read(hw->regmap, rcg->ns_reg, &ns);
+	}
+
+	ns = pre_div_to_ns(&rcg->p, f->pre_div - 1, ns);
+	regmap_write(hw->regmap, rcg->ns_reg, ns);
+
+	regmap_update_bits(hw->regmap, reset_reg, mask, 0);
+
+	return 0;
+}
+
+static int __clk_dyn_rcg_set_rate(struct clk_hw *hw, unsigned long rate)
+{
+	struct clk_dyn_rcg *rcg = to_clk_dyn_rcg(hw);
+	const struct freq_tbl *f;
+
+	f = find_freq(rcg->freq_tbl, rate);
+	if (!f)
+		return -EINVAL;
+
+	configure_bank(rcg, f);
+
+	return 0;
+}
+
+static int clk_dyn_rcg_set_rate(struct clk_hw *hw, unsigned long rate,
+			    unsigned long parent_rate)
+{
+	return __clk_dyn_rcg_set_rate(hw, rate);
+}
+
+static int clk_dyn_rcg_set_rate_and_parent(struct clk_hw *hw,
+		unsigned long rate, unsigned long parent_rate, u8 index)
+{
+	return __clk_dyn_rcg_set_rate(hw, rate);
+}
+
+const struct clk_ops clk_rcg_ops = {
+	.enable = clk_enable_regmap,
+	.disable = clk_disable_regmap,
+	.get_parent = clk_rcg_get_parent,
+	.set_parent = clk_rcg_set_parent,
+	.recalc_rate = clk_rcg_recalc_rate,
+	.determine_rate = clk_rcg_determine_rate,
+	.set_rate = clk_rcg_set_rate,
+};
+EXPORT_SYMBOL_GPL(clk_rcg_ops);
+
+const struct clk_ops clk_dyn_rcg_ops = {
+	.enable = clk_enable_regmap,
+	.is_enabled = clk_is_enabled_regmap,
+	.disable = clk_disable_regmap,
+	.get_parent = clk_dyn_rcg_get_parent,
+	.set_parent = clk_dyn_rcg_set_parent,
+	.recalc_rate = clk_dyn_rcg_recalc_rate,
+	.determine_rate = clk_dyn_rcg_determine_rate,
+	.set_rate = clk_dyn_rcg_set_rate,
+	.set_rate_and_parent = clk_dyn_rcg_set_rate_and_parent,
+};
+EXPORT_SYMBOL_GPL(clk_dyn_rcg_ops);
diff --git a/drivers/clk/qcom/clk-rcg.h b/drivers/clk/qcom/clk-rcg.h
new file mode 100644
index 0000000..3dfc73d
--- /dev/null
+++ b/drivers/clk/qcom/clk-rcg.h
@@ -0,0 +1,157 @@
+/*
+ * Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef __MSM_CLK_RCG_H__
+#define __MSM_CLK_RCG_H__
+
+#include <linux/clk-provider.h>
+
+struct freq_tbl {
+	unsigned long freq;
+	u8 src;
+	u8 pre_div;
+	u16 m;
+	u16 n;
+};
+
+/**
+ * struct mn - M/N:D counter
+ * @mnctr_en_bit: bit to enable mn counter
+ * @mnctr_reset_bit: bit to assert mn counter reset
+ * @mnctr_mode_shift: lowest bit of mn counter mode field
+ * @n_val_shift: lowest bit of n value field
+ * @m_val_shift: lowest bit of m value field
+ * @width: number of bits in m/n/d values
+ * @reset_in_cc: true if the mnctr_reset_bit is in the CC register
+ */
+struct mn {
+	u8		mnctr_en_bit;
+	u8		mnctr_reset_bit;
+	u8		mnctr_mode_shift;
+#define MNCTR_MODE_DUAL 0x2
+#define MNCTR_MODE_MASK 0x3
+	u8		n_val_shift;
+	u8		m_val_shift;
+	u8		width;
+	bool		reset_in_cc;
+};
+
+/**
+ * struct pre_div - pre-divider
+ * @pre_div_shift: lowest bit of pre divider field
+ * @pre_div_width: number of bits in predivider
+ */
+struct pre_div {
+	u8		pre_div_shift;
+	u8		pre_div_width;
+};
+
+/**
+ * struct src_sel - source selector
+ * @src_sel_shift: lowest bit of source selection field
+ * @parent_map: map from software's parent index to hardware's src_sel field
+ */
+struct src_sel {
+	u8		src_sel_shift;
+#define SRC_SEL_MASK	0x7
+	const u8	*parent_map;
+};
+
+/**
+ * struct clk_rcg - root clock generator
+ *
+ * @ns_reg: NS register
+ * @md_reg: MD register
+ * @mn: mn counter
+ * @p: pre divider
+ * @s: source selector
+ * @freq_tbl: frequency table
+ * @hw: handle between common and hardware-specific interfaces
+ * @lock: register lock
+ *
+ */
+struct clk_rcg {
+	u32		ns_reg;
+	u32		md_reg;
+
+	struct mn	mn;
+	struct pre_div	p;
+	struct src_sel	s;
+
+	const struct freq_tbl	*freq_tbl;
+
+	struct clk_hw	hw;
+};
+
+extern const struct clk_ops clk_rcg_ops;
+
+#define to_clk_rcg(_hw) container_of(_hw, struct clk_rcg, hw)
+
+/**
+ * struct clk_dyn_rcg - root clock generator with glitch free mux
+ *
+ * @mux_sel_bit: bit to switch glitch free mux
+ * @ns_reg: NS register
+ * @md_reg: MD0 and MD1 register
+ * @mn: mn counter (banked)
+ * @s: source selector (banked)
+ * @freq_tbl: frequency table
+ * @hw: handle between common and hardware-specific interfaces
+ * @lock: register lock
+ *
+ */
+struct clk_dyn_rcg {
+	u32	ns_reg;
+	u32	md_reg[2];
+
+	u8	mux_sel_bit;
+
+	struct mn	mn[2];
+	struct pre_div	p[2];
+	struct src_sel	s[2];
+
+	const struct freq_tbl	*freq_tbl;
+
+	struct clk_hw	hw;
+};
+
+extern const struct clk_ops clk_dyn_rcg_ops;
+
+#define to_clk_dyn_rcg(_hw) container_of(_hw, struct clk_dyn_rcg, hw)
+
+/**
+ * struct clk_rcg2 - root clock generator
+ *
+ * @cmd_rcgr: corresponds to *_CMD_RCGR
+ * @mnd_width: number of bits in m/n/d values
+ * @hid_width: number of bits in half integer divider
+ * @parent_map: map from software's parent index to hardware's src_sel field
+ * @freq_tbl: frequency table
+ * @hw: handle between common and hardware-specific interfaces
+ * @lock: register lock
+ *
+ */
+struct clk_rcg2 {
+	u32			cmd_rcgr;
+	u8			mnd_width;
+	u8			hid_width;
+	const u8		*parent_map;
+	const struct freq_tbl	*freq_tbl;
+	struct clk_hw		hw;
+};
+
+#define to_clk_rcg2(_hw) container_of(_hw, struct clk_rcg2, hw)
+
+extern const struct clk_ops clk_rcg2_ops;
+
+#endif
diff --git a/drivers/clk/qcom/clk-rcg2.c b/drivers/clk/qcom/clk-rcg2.c
new file mode 100644
index 0000000..94b8138
--- /dev/null
+++ b/drivers/clk/qcom/clk-rcg2.c
@@ -0,0 +1,291 @@
+/*
+ * Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/kernel.h>
+#include <linux/bitops.h>
+#include <linux/err.h>
+#include <linux/bug.h>
+#include <linux/export.h>
+#include <linux/clk-provider.h>
+#include <linux/delay.h>
+#include <linux/regmap.h>
+
+#include <asm/div64.h>
+
+#include "clk-rcg.h"
+
+#define CMD_REG			0x0
+#define CMD_UPDATE		BIT(0)
+#define CMD_ROOT_EN		BIT(1)
+#define CMD_DIRTY_CFG		BIT(4)
+#define CMD_DIRTY_N		BIT(5)
+#define CMD_DIRTY_M		BIT(6)
+#define CMD_DIRTY_D		BIT(7)
+#define CMD_ROOT_OFF		BIT(31)
+
+#define CFG_REG			0x4
+#define CFG_SRC_DIV_SHIFT	0
+#define CFG_SRC_SEL_SHIFT	8
+#define CFG_SRC_SEL_MASK	(0x7 << CFG_SRC_SEL_SHIFT)
+#define CFG_MODE_SHIFT		12
+#define CFG_MODE_MASK		(0x3 << CFG_MODE_SHIFT)
+#define CFG_MODE_DUAL_EDGE	(0x2 << CFG_MODE_SHIFT)
+
+#define M_REG			0x8
+#define N_REG			0xc
+#define D_REG			0x10
+
+static int clk_rcg2_is_enabled(struct clk_hw *hw)
+{
+	struct clk_rcg2 *rcg = to_clk_rcg2(hw);
+	u32 cmd;
+	int ret;
+
+	ret = regmap_read(hw->regmap, rcg->cmd_rcgr + CMD_REG, &cmd);
+	if (ret)
+		return ret;
+
+	return (cmd & CMD_ROOT_OFF) != 0;
+}
+
+static u8 clk_rcg2_get_parent(struct clk_hw *hw)
+{
+	struct clk_rcg2 *rcg = to_clk_rcg2(hw);
+	int num_parents = __clk_get_num_parents(hw->clk);
+	u32 cfg;
+	int i, ret;
+
+	ret = regmap_read(hw->regmap, rcg->cmd_rcgr + CFG_REG, &cfg);
+	if (ret)
+		return ret;
+
+	cfg &= CFG_SRC_SEL_MASK;
+	cfg >>= CFG_SRC_SEL_SHIFT;
+
+	for (i = 0; i < num_parents; i++)
+		if (cfg == rcg->parent_map[i])
+			return i;
+
+	return -EINVAL;
+}
+
+static int update_config(struct clk_rcg2 *rcg)
+{
+	int count, ret;
+	u32 cmd;
+	struct clk_hw *hw = &rcg->hw;
+	const char *name = __clk_get_name(hw->clk);
+
+	ret = regmap_update_bits(hw->regmap, rcg->cmd_rcgr + CMD_REG,
+				 CMD_UPDATE, CMD_UPDATE);
+	if (ret)
+		return ret;
+
+	/* Wait for update to take effect */
+	for (count = 500; count > 0; count--) {
+		ret = regmap_read(hw->regmap, rcg->cmd_rcgr + CMD_REG, &cmd);
+		if (ret)
+			return ret;
+		if (!(cmd & CMD_UPDATE))
+			return 0;
+		udelay(1);
+	}
+
+	WARN(1, "%s: rcg didn't update its configuration.", name);
+	return 0;
+}
+
+static int clk_rcg2_set_parent(struct clk_hw *hw, u8 index)
+{
+	struct clk_rcg2 *rcg = to_clk_rcg2(hw);
+	int ret;
+
+	ret = regmap_update_bits(hw->regmap, rcg->cmd_rcgr + CFG_REG,
+				 CFG_SRC_SEL_MASK,
+				 rcg->parent_map[index] << CFG_SRC_SEL_SHIFT);
+	if (ret)
+		return ret;
+
+	return update_config(rcg);
+}
+
+/*
+ * Calculate m/n:d rate
+ *
+ *          parent_rate     m
+ *   rate = ----------- x  ---
+ *            hid_div       n
+ */
+static unsigned long
+calc_rate(unsigned long rate, u32 m, u32 n, u32 mode, u32 hid_div)
+{
+	if (hid_div) {
+		rate *= 2;
+		rate /= hid_div + 1;
+	}
+
+	if (mode) {
+		u64 tmp = rate;
+		tmp *= m;
+		do_div(tmp, n);
+		rate = tmp;
+	}
+
+	return rate;
+}
+
+static unsigned long
+clk_rcg2_recalc_rate(struct clk_hw *hw, unsigned long parent_rate)
+{
+	struct clk_rcg2 *rcg = to_clk_rcg2(hw);
+	u32 cfg, hid_div, m = 0, n = 0, mode = 0, mask;
+
+	regmap_read(hw->regmap, rcg->cmd_rcgr + CFG_REG, &cfg);
+
+	if (rcg->mnd_width) {
+		mask = BIT(rcg->mnd_width) - 1;
+		regmap_read(hw->regmap, rcg->cmd_rcgr + M_REG, &m);
+		m &= mask;
+		regmap_read(hw->regmap, rcg->cmd_rcgr + N_REG, &n);
+		n =  ~n;
+		n &= mask;
+		n += m;
+		mode = cfg & CFG_MODE_MASK;
+		mode >>= CFG_MODE_SHIFT;
+	}
+
+	mask = BIT(rcg->hid_width) - 1;
+	hid_div = cfg >> CFG_SRC_DIV_SHIFT;
+	hid_div &= mask;
+
+	return calc_rate(parent_rate, m, n, mode, hid_div);
+}
+
+static const
+struct freq_tbl *find_freq(const struct freq_tbl *f, unsigned long rate)
+{
+	if (!f)
+		return NULL;
+
+	for (; f->freq; f++)
+		if (rate <= f->freq)
+			return f;
+
+	return NULL;
+}
+
+static long _freq_tbl_determine_rate(struct clk_hw *hw,
+		const struct freq_tbl *f, unsigned long rate,
+		unsigned long *p_rate, struct clk **p)
+{
+	unsigned long clk_flags;
+
+	f = find_freq(f, rate);
+	if (!f)
+		return -EINVAL;
+
+	clk_flags = __clk_get_flags(hw->clk);
+	*p = clk_get_parent_by_index(hw->clk, f->src);
+	if (clk_flags & CLK_SET_RATE_PARENT) {
+		if (f->pre_div) {
+			rate /= 2;
+			rate *= f->pre_div + 1;
+		}
+
+		if (f->n) {
+			u64 tmp = rate;
+			tmp = tmp * f->n;
+			do_div(tmp, f->m);
+			rate = tmp;
+		}
+	} else {
+		rate =  __clk_get_rate(*p);
+	}
+	*p_rate = rate;
+
+	return f->freq;
+}
+
+static long clk_rcg2_determine_rate(struct clk_hw *hw, unsigned long rate,
+		unsigned long *p_rate, struct clk **p)
+{
+	struct clk_rcg2 *rcg = to_clk_rcg2(hw);
+
+	return _freq_tbl_determine_rate(hw, rcg->freq_tbl, rate, p_rate, p);
+}
+
+static int __clk_rcg2_set_rate(struct clk_hw *hw, unsigned long rate)
+{
+	struct clk_rcg2 *rcg = to_clk_rcg2(hw);
+	const struct freq_tbl *f;
+	u32 cfg, mask;
+	int ret;
+
+	f = find_freq(rcg->freq_tbl, rate);
+	if (!f)
+		return -EINVAL;
+
+	if (rcg->mnd_width && f->n) {
+		mask = BIT(rcg->mnd_width) - 1;
+		ret = regmap_update_bits(hw->regmap, rcg->cmd_rcgr + M_REG,
+					 mask, f->m);
+		if (ret)
+			return ret;
+
+		ret = regmap_update_bits(hw->regmap, rcg->cmd_rcgr + N_REG,
+					 mask, ~(f->n - f->m));
+		if (ret)
+			return ret;
+
+		ret = regmap_update_bits(hw->regmap, rcg->cmd_rcgr + D_REG,
+					 mask, ~f->n);
+		if (ret)
+			return ret;
+	}
+
+	mask = BIT(rcg->hid_width) - 1;
+	mask |= CFG_SRC_SEL_MASK | CFG_MODE_MASK;
+	cfg = f->pre_div << CFG_SRC_DIV_SHIFT;
+	cfg |= rcg->parent_map[f->src] << CFG_SRC_SEL_SHIFT;
+	if (rcg->mnd_width && f->n)
+		cfg |= CFG_MODE_DUAL_EDGE;
+	ret = regmap_update_bits(hw->regmap, rcg->cmd_rcgr + CFG_REG, mask,
+			cfg);
+	if (ret)
+		return ret;
+
+	return update_config(rcg);
+}
+
+static int clk_rcg2_set_rate(struct clk_hw *hw, unsigned long rate,
+			    unsigned long parent_rate)
+{
+	return __clk_rcg2_set_rate(hw, rate);
+}
+
+static int clk_rcg2_set_rate_and_parent(struct clk_hw *hw,
+		unsigned long rate, unsigned long parent_rate, u8 index)
+{
+	return __clk_rcg2_set_rate(hw, rate);
+}
+
+const struct clk_ops clk_rcg2_ops = {
+	.is_enabled = clk_rcg2_is_enabled,
+	.get_parent = clk_rcg2_get_parent,
+	.set_parent = clk_rcg2_set_parent,
+	.recalc_rate = clk_rcg2_recalc_rate,
+	.determine_rate = clk_rcg2_determine_rate,
+	.set_rate = clk_rcg2_set_rate,
+	.set_rate_and_parent = clk_rcg2_set_rate_and_parent,
+};
+EXPORT_SYMBOL_GPL(clk_rcg2_ops);
-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
hosted by The Linux Foundation

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

* [PATCH v4 07/15] clk: qcom: Add support for branches/gate clocks
  2013-12-24  1:12 [PATCH v4 00/15] Add support for MSM's mmio clock/reset controller Stephen Boyd
                   ` (5 preceding siblings ...)
  2013-12-24  1:12 ` [PATCH v4 06/15] clk: qcom: Add support for root clock generators (RCGs) Stephen Boyd
@ 2013-12-24  1:12 ` Stephen Boyd
  2013-12-24  1:12 ` [PATCH v4 08/15] clk: qcom: Add reset controller support Stephen Boyd
                   ` (7 subsequent siblings)
  14 siblings, 0 replies; 34+ messages in thread
From: Stephen Boyd @ 2013-12-24  1:12 UTC (permalink / raw)
  To: Mike Turquette
  Cc: linux-kernel, linux-arm-msm, linux-arm-kernel, Saravana Kannan

Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
---
 drivers/clk/qcom/Makefile     |   1 +
 drivers/clk/qcom/clk-branch.c | 159 ++++++++++++++++++++++++++++++++++++++++++
 drivers/clk/qcom/clk-branch.h |  53 ++++++++++++++
 3 files changed, 213 insertions(+)
 create mode 100644 drivers/clk/qcom/clk-branch.c
 create mode 100644 drivers/clk/qcom/clk-branch.h

diff --git a/drivers/clk/qcom/Makefile b/drivers/clk/qcom/Makefile
index 7ed16d7..58a5ab3 100644
--- a/drivers/clk/qcom/Makefile
+++ b/drivers/clk/qcom/Makefile
@@ -3,3 +3,4 @@ obj-$(CONFIG_COMMON_CLK_QCOM) += clk-qcom.o
 clk-qcom-$(CONFIG_COMMON_CLK_QCOM) += clk-pll.o
 clk-qcom-$(CONFIG_COMMON_CLK_QCOM) += clk-rcg.o
 clk-qcom-$(CONFIG_COMMON_CLK_QCOM) += clk-rcg2.o
+clk-qcom-$(CONFIG_COMMON_CLK_QCOM) += clk-branch.o
diff --git a/drivers/clk/qcom/clk-branch.c b/drivers/clk/qcom/clk-branch.c
new file mode 100644
index 0000000..c2fa774
--- /dev/null
+++ b/drivers/clk/qcom/clk-branch.c
@@ -0,0 +1,159 @@
+/*
+ * Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/kernel.h>
+#include <linux/bitops.h>
+#include <linux/err.h>
+#include <linux/delay.h>
+#include <linux/export.h>
+#include <linux/clk-provider.h>
+#include <linux/regmap.h>
+
+#include "clk-branch.h"
+
+static bool clk_branch_in_hwcg_mode(const struct clk_branch *br)
+{
+	u32 val;
+
+	if (!br->hwcg_reg)
+		return 0;
+
+	regmap_read(br->hw.regmap, br->hwcg_reg, &val);
+
+	return !!(val & BIT(br->hwcg_bit));
+}
+
+static bool clk_branch_check_halt(const struct clk_branch *br, bool enabling)
+{
+	bool invert = (br->halt_check == BRANCH_HALT_ENABLE);
+	u32 val;
+
+	regmap_read(br->hw.regmap, br->halt_reg, &val);
+
+	val &= BIT(br->halt_bit);
+	if (invert)
+		val = !val;
+
+	return !!val == !enabling;
+}
+
+#define BRANCH_CLK_OFF			BIT(31)
+#define BRANCH_NOC_FSM_STATUS_SHIFT	28
+#define BRANCH_NOC_FSM_STATUS_MASK	0x7
+#define BRANCH_NOC_FSM_STATUS_ON	(0x2 << BRANCH_NOC_FSM_STATUS_SHIFT)
+
+static bool clk_branch2_check_halt(const struct clk_branch *br, bool enabling)
+{
+	u32 val;
+	u32 mask;
+
+	mask = BRANCH_NOC_FSM_STATUS_MASK << BRANCH_NOC_FSM_STATUS_SHIFT;
+	mask |= BRANCH_CLK_OFF;
+
+	regmap_read(br->hw.regmap, br->halt_reg, &val);
+
+	if (enabling) {
+		val &= mask;
+		return (val & BRANCH_CLK_OFF) == 0 ||
+			val == BRANCH_NOC_FSM_STATUS_ON;
+	} else {
+		return val & BRANCH_CLK_OFF;
+	}
+}
+
+static int clk_branch_wait(const struct clk_branch *br, bool enabling,
+		bool (check_halt)(const struct clk_branch *, bool))
+{
+	bool voted = br->halt_check & BRANCH_VOTED;
+	const char *name = __clk_get_name(br->hw.clk);
+
+	/* Skip checking halt bit if the clock is in hardware gated mode */
+	if (clk_branch_in_hwcg_mode(br))
+		return 0;
+
+	if (br->halt_check == BRANCH_HALT_DELAY || (!enabling && voted)) {
+		udelay(10);
+	} else if (br->halt_check == BRANCH_HALT_ENABLE ||
+		   br->halt_check == BRANCH_HALT ||
+		   (enabling && voted)) {
+		int count = 200;
+
+		while (count-- > 0) {
+			if (check_halt(br, enabling))
+				return 0;
+			udelay(1);
+		}
+		WARN(1, "%s status stuck at 'o%s'", name,
+				enabling ? "ff" : "n");
+		return -EBUSY;
+	}
+	return 0;
+}
+
+static int clk_branch_toggle(struct clk_hw *hw, bool en,
+		bool (check_halt)(const struct clk_branch *, bool))
+{
+	struct clk_branch *br = to_clk_branch(hw);
+	int ret;
+
+	if (en) {
+		ret = clk_enable_regmap(hw);
+		if (ret)
+			return ret;
+	} else {
+		clk_disable_regmap(hw);
+	}
+
+	return clk_branch_wait(br, en, check_halt);
+}
+
+static int clk_branch_enable(struct clk_hw *hw)
+{
+	return clk_branch_toggle(hw, true, clk_branch_check_halt);
+}
+
+static void clk_branch_disable(struct clk_hw *hw)
+{
+	clk_branch_toggle(hw, false, clk_branch_check_halt);
+}
+
+const struct clk_ops clk_branch_ops = {
+	.enable = clk_branch_enable,
+	.disable = clk_branch_disable,
+	.is_enabled = clk_is_enabled_regmap,
+};
+EXPORT_SYMBOL_GPL(clk_branch_ops);
+
+static int clk_branch2_enable(struct clk_hw *hw)
+{
+	return clk_branch_toggle(hw, true, clk_branch2_check_halt);
+}
+
+static void clk_branch2_disable(struct clk_hw *hw)
+{
+	clk_branch_toggle(hw, false, clk_branch2_check_halt);
+}
+
+const struct clk_ops clk_branch2_ops = {
+	.enable = clk_branch2_enable,
+	.disable = clk_branch2_disable,
+	.is_enabled = clk_is_enabled_regmap,
+};
+EXPORT_SYMBOL_GPL(clk_branch2_ops);
+
+const struct clk_ops clk_branch_simple_ops = {
+	.enable = clk_enable_regmap,
+	.disable = clk_disable_regmap,
+	.is_enabled = clk_is_enabled_regmap,
+};
+EXPORT_SYMBOL_GPL(clk_branch_simple_ops);
diff --git a/drivers/clk/qcom/clk-branch.h b/drivers/clk/qcom/clk-branch.h
new file mode 100644
index 0000000..25120eb
--- /dev/null
+++ b/drivers/clk/qcom/clk-branch.h
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef __MSM_CLK_BRANCH_H__
+#define __MSM_CLK_BRANCH_H__
+
+#include <linux/clk-provider.h>
+
+/**
+ * struct clk_branch - gating clock with status bit and dynamic hardware gating
+ *
+ * @hwcg_reg: dynamic hardware clock gating register
+ * @hwcg_bit: ORed with @hwcg_reg to enable dynamic hardware clock gating
+ * @halt_reg: halt register
+ * @halt_bit: ANDed with @halt_reg to test for clock halted
+ * @halt_check: type of halt checking to perform
+ * @hw: handle between common and hardware-specific interfaces
+ *
+ * Clock which can gate its output.
+ */
+struct clk_branch {
+	u32	hwcg_reg;
+	u32	halt_reg;
+	u8	hwcg_bit;
+	u8	halt_bit;
+	u8	halt_check;
+#define BRANCH_VOTED			BIT(7) /* Delay on disable */
+#define BRANCH_HALT			0 /* pol: 1 = halt */
+#define BRANCH_HALT_VOTED		(BRANCH_HALT | BRANCH_VOTED)
+#define BRANCH_HALT_ENABLE		1 /* pol: 0 = halt */
+#define BRANCH_HALT_ENABLE_VOTED	(BRANCH_HALT_ENABLE | BRANCH_VOTED)
+#define BRANCH_HALT_DELAY		2 /* No bit to check; just delay */
+
+	struct clk_hw	hw;
+};
+
+extern const struct clk_ops clk_branch_ops;
+extern const struct clk_ops clk_branch2_ops;
+extern const struct clk_ops clk_branch_simple_ops;
+
+#define to_clk_branch(_hw) container_of(_hw, struct clk_branch, hw)
+
+#endif
-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
hosted by The Linux Foundation

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

* [PATCH v4 08/15] clk: qcom: Add reset controller support
  2013-12-24  1:12 [PATCH v4 00/15] Add support for MSM's mmio clock/reset controller Stephen Boyd
                   ` (6 preceding siblings ...)
  2013-12-24  1:12 ` [PATCH v4 07/15] clk: qcom: Add support for branches/gate clocks Stephen Boyd
@ 2013-12-24  1:12 ` Stephen Boyd
  2013-12-24  1:12 ` [PATCH v4 09/15] clk: qcom: Add support for MSM8960's global clock controller (GCC) Stephen Boyd
                   ` (6 subsequent siblings)
  14 siblings, 0 replies; 34+ messages in thread
From: Stephen Boyd @ 2013-12-24  1:12 UTC (permalink / raw)
  To: Mike Turquette
  Cc: linux-kernel, linux-arm-msm, linux-arm-kernel, Saravana Kannan

Reset controllers and clock controllers are combined into one IP
block on Qualcomm chipsets. Usually a reset signal is associated
with each clock branch but sometimes a reset signal is associated
with a handful of clocks. Either way the register interface is
the same; set a bit to assert a reset and clear a bit to deassert
a reset. Add support for these types of resets signals.

Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
---
 drivers/clk/qcom/Kconfig  |  2 +-
 drivers/clk/qcom/Makefile |  1 +
 drivers/clk/qcom/reset.c  | 63 +++++++++++++++++++++++++++++++++++++++++++++++
 drivers/clk/qcom/reset.h  | 37 ++++++++++++++++++++++++++++
 4 files changed, 102 insertions(+), 1 deletion(-)
 create mode 100644 drivers/clk/qcom/reset.c
 create mode 100644 drivers/clk/qcom/reset.h

diff --git a/drivers/clk/qcom/Kconfig b/drivers/clk/qcom/Kconfig
index 73a8c8f..06ccce6 100644
--- a/drivers/clk/qcom/Kconfig
+++ b/drivers/clk/qcom/Kconfig
@@ -2,4 +2,4 @@ config COMMON_CLK_QCOM
 	tristate "Support for Qualcomm's clock controllers"
 	depends on OF
 	select REGMAP_MMIO
-
+	select RESET_CONTROLLER
diff --git a/drivers/clk/qcom/Makefile b/drivers/clk/qcom/Makefile
index 58a5ab3..b2568be 100644
--- a/drivers/clk/qcom/Makefile
+++ b/drivers/clk/qcom/Makefile
@@ -4,3 +4,4 @@ clk-qcom-$(CONFIG_COMMON_CLK_QCOM) += clk-pll.o
 clk-qcom-$(CONFIG_COMMON_CLK_QCOM) += clk-rcg.o
 clk-qcom-$(CONFIG_COMMON_CLK_QCOM) += clk-rcg2.o
 clk-qcom-$(CONFIG_COMMON_CLK_QCOM) += clk-branch.o
+clk-qcom-$(CONFIG_COMMON_CLK_QCOM) += reset.o
diff --git a/drivers/clk/qcom/reset.c b/drivers/clk/qcom/reset.c
new file mode 100644
index 0000000..6c977d3
--- /dev/null
+++ b/drivers/clk/qcom/reset.c
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/bitops.h>
+#include <linux/export.h>
+#include <linux/regmap.h>
+#include <linux/reset-controller.h>
+#include <linux/delay.h>
+
+#include "reset.h"
+
+static int qcom_reset(struct reset_controller_dev *rcdev, unsigned long id)
+{
+	rcdev->ops->assert(rcdev, id);
+	udelay(1);
+	rcdev->ops->deassert(rcdev, id);
+	return 0;
+}
+
+static int
+qcom_reset_assert(struct reset_controller_dev *rcdev, unsigned long id)
+{
+	struct qcom_reset_controller *rst;
+	const struct qcom_reset_map *map;
+	u32 mask;
+
+	rst = to_qcom_reset_controller(rcdev);
+	map = &rst->reset_map[id];
+	mask = BIT(map->bit);
+
+	return regmap_update_bits(rst->regmap, map->reg, mask, mask);
+}
+
+static int
+qcom_reset_deassert(struct reset_controller_dev *rcdev, unsigned long id)
+{
+	struct qcom_reset_controller *rst;
+	const struct qcom_reset_map *map;
+	u32 mask;
+
+	rst = to_qcom_reset_controller(rcdev);
+	map = &rst->reset_map[id];
+	mask = BIT(map->bit);
+
+	return regmap_update_bits(rst->regmap, map->reg, mask, 0);
+}
+
+struct reset_control_ops qcom_reset_ops = {
+	.reset = qcom_reset,
+	.assert = qcom_reset_assert,
+	.deassert = qcom_reset_deassert,
+};
+EXPORT_SYMBOL_GPL(qcom_reset_ops);
diff --git a/drivers/clk/qcom/reset.h b/drivers/clk/qcom/reset.h
new file mode 100644
index 0000000..e22b167
--- /dev/null
+++ b/drivers/clk/qcom/reset.h
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef __MSM_CLK_RESET_H__
+#define __MSM_CLK_RESET_H__
+
+#include <linux/reset-controller.h>
+
+struct qcom_reset_map {
+	unsigned int reg;
+	u8 bit;
+};
+
+struct regmap;
+
+struct qcom_reset_controller {
+	const struct qcom_reset_map *reset_map;
+	struct regmap *regmap;
+	struct reset_controller_dev rcdev;
+};
+
+#define to_qcom_reset_controller(r) \
+	container_of(r, struct qcom_reset_controller, rcdev);
+
+extern struct reset_control_ops qcom_reset_ops;
+
+#endif
-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
hosted by The Linux Foundation

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

* [PATCH v4 09/15] clk: qcom: Add support for MSM8960's global clock controller (GCC)
  2013-12-24  1:12 [PATCH v4 00/15] Add support for MSM's mmio clock/reset controller Stephen Boyd
                   ` (7 preceding siblings ...)
  2013-12-24  1:12 ` [PATCH v4 08/15] clk: qcom: Add reset controller support Stephen Boyd
@ 2013-12-24  1:12 ` Stephen Boyd
  2013-12-24  1:12 ` [PATCH v4 10/15] clk: qcom: Add support for MSM8960's multimedia clock controller (MMCC) Stephen Boyd
                   ` (5 subsequent siblings)
  14 siblings, 0 replies; 34+ messages in thread
From: Stephen Boyd @ 2013-12-24  1:12 UTC (permalink / raw)
  To: Mike Turquette
  Cc: linux-kernel, linux-arm-msm, linux-arm-kernel, Saravana Kannan

Add a driver for the global clock controller found on MSM8960
based platforms. This should allow most non-multimedia device
drivers to probe and control their clocks.

Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
---
 drivers/clk/qcom/Kconfig                     |    8 +
 drivers/clk/qcom/Makefile                    |    2 +
 drivers/clk/qcom/gcc-msm8960.c               | 2992 ++++++++++++++++++++++++++
 include/dt-bindings/clock/qcom,gcc-msm8960.h |  313 +++
 include/dt-bindings/reset/qcom,gcc-msm8960.h |  118 +
 5 files changed, 3433 insertions(+)
 create mode 100644 drivers/clk/qcom/gcc-msm8960.c
 create mode 100644 include/dt-bindings/clock/qcom,gcc-msm8960.h
 create mode 100644 include/dt-bindings/reset/qcom,gcc-msm8960.h

diff --git a/drivers/clk/qcom/Kconfig b/drivers/clk/qcom/Kconfig
index 06ccce6..8b39761 100644
--- a/drivers/clk/qcom/Kconfig
+++ b/drivers/clk/qcom/Kconfig
@@ -3,3 +3,11 @@ config COMMON_CLK_QCOM
 	depends on OF
 	select REGMAP_MMIO
 	select RESET_CONTROLLER
+
+config MSM_GCC_8960
+	tristate "MSM8960 Global Clock Controller"
+	depends on COMMON_CLK_QCOM
+	help
+	  Support for the global clock controller on msm8960 devices.
+	  Say Y if you want to use peripheral devices such as UART, SPI,
+	  i2c, USB, SD/eMMC, SATA, PCIe, etc.
diff --git a/drivers/clk/qcom/Makefile b/drivers/clk/qcom/Makefile
index b2568be..b8c816f 100644
--- a/drivers/clk/qcom/Makefile
+++ b/drivers/clk/qcom/Makefile
@@ -5,3 +5,5 @@ clk-qcom-$(CONFIG_COMMON_CLK_QCOM) += clk-rcg.o
 clk-qcom-$(CONFIG_COMMON_CLK_QCOM) += clk-rcg2.o
 clk-qcom-$(CONFIG_COMMON_CLK_QCOM) += clk-branch.o
 clk-qcom-$(CONFIG_COMMON_CLK_QCOM) += reset.o
+
+obj-$(CONFIG_MSM_GCC_8960) += gcc-msm8960.o
diff --git a/drivers/clk/qcom/gcc-msm8960.c b/drivers/clk/qcom/gcc-msm8960.c
new file mode 100644
index 0000000..c9d6f79
--- /dev/null
+++ b/drivers/clk/qcom/gcc-msm8960.c
@@ -0,0 +1,2992 @@
+/*
+ * Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/kernel.h>
+#include <linux/bitops.h>
+#include <linux/err.h>
+#include <linux/platform_device.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/clk-provider.h>
+#include <linux/regmap.h>
+#include <linux/reset-controller.h>
+
+#include <dt-bindings/clock/qcom,gcc-msm8960.h>
+#include <dt-bindings/reset/qcom,gcc-msm8960.h>
+
+#include "clk-pll.h"
+#include "clk-rcg.h"
+#include "clk-branch.h"
+#include "reset.h"
+
+static struct clk_pll pll3 = {
+	.l_reg = 0x3164,
+	.m_reg = 0x3168,
+	.n_reg = 0x316c,
+	.config_reg = 0x3174,
+	.mode_reg = 0x3160,
+	.status_reg = 0x3178,
+	.status_bit = 16,
+	.hw.init = &(struct clk_init_data){
+		.name = "pll3",
+		.parent_names = (const char *[]){ "pxo" },
+		.num_parents = 1,
+		.ops = &clk_pll_ops,
+	},
+};
+
+static struct clk_pll pll8 = {
+	.l_reg = 0x3144,
+	.m_reg = 0x3148,
+	.n_reg = 0x314c,
+	.config_reg = 0x3154,
+	.mode_reg = 0x3140,
+	.status_reg = 0x3158,
+	.status_bit = 16,
+	.hw.init = &(struct clk_init_data){
+		.name = "pll8",
+		.parent_names = (const char *[]){ "pxo" },
+		.num_parents = 1,
+		.ops = &clk_pll_ops,
+	},
+};
+
+static struct clk_hw pll8_vote = {
+	.enable_reg = 0x34c0,
+	.enable_mask = BIT(8),
+	.init = &(struct clk_init_data){
+		.name = "pll8_vote",
+		.parent_names = (const char *[]){ "pll8" },
+		.num_parents = 1,
+		.ops = &clk_pll_vote_ops,
+	},
+};
+
+static struct clk_pll pll14 = {
+	.l_reg = 0x31c4,
+	.m_reg = 0x31c8,
+	.n_reg = 0x31cc,
+	.config_reg = 0x31d4,
+	.mode_reg = 0x31c0,
+	.status_reg = 0x31d8,
+	.status_bit = 16,
+	.hw.init = &(struct clk_init_data){
+		.name = "pll14",
+		.parent_names = (const char *[]){ "pxo" },
+		.num_parents = 1,
+		.ops = &clk_pll_ops,
+	},
+};
+
+static struct clk_hw pll14_vote = {
+	.enable_reg = 0x34c0,
+	.enable_mask = BIT(14),
+	.init = &(struct clk_init_data){
+		.name = "pll14_vote",
+		.parent_names = (const char *[]){ "pll14" },
+		.num_parents = 1,
+		.ops = &clk_pll_vote_ops,
+	},
+};
+
+#define P_PXO	0
+#define P_PLL8	1
+#define P_CXO	2
+
+static const u8 gcc_pxo_pll8_map[] = {
+	[P_PXO]		= 0,
+	[P_PLL8]	= 3,
+};
+
+static const char *gcc_pxo_pll8[] = {
+	"pxo",
+	"pll8_vote",
+};
+
+static const u8 gcc_pxo_pll8_cxo_map[] = {
+	[P_PXO]		= 0,
+	[P_PLL8]	= 3,
+	[P_CXO]		= 5,
+};
+
+static const char *gcc_pxo_pll8_cxo[] = {
+	"pxo",
+	"pll8_vote",
+	"cxo",
+};
+
+static struct freq_tbl clk_tbl_gsbi_uart[] = {
+	{  1843200, P_PLL8, 2,  6, 625 },
+	{  3686400, P_PLL8, 2, 12, 625 },
+	{  7372800, P_PLL8, 2, 24, 625 },
+	{ 14745600, P_PLL8, 2, 48, 625 },
+	{ 16000000, P_PLL8, 4,  1,   6 },
+	{ 24000000, P_PLL8, 4,  1,   4 },
+	{ 32000000, P_PLL8, 4,  1,   3 },
+	{ 40000000, P_PLL8, 1,  5,  48 },
+	{ 46400000, P_PLL8, 1, 29, 240 },
+	{ 48000000, P_PLL8, 4,  1,   2 },
+	{ 51200000, P_PLL8, 1,  2,  15 },
+	{ 56000000, P_PLL8, 1,  7,  48 },
+	{ 58982400, P_PLL8, 1, 96, 625 },
+	{ 64000000, P_PLL8, 2,  1,   3 },
+	{ }
+};
+
+static struct clk_rcg gsbi1_uart_src = {
+	.ns_reg = 0x29d4,
+	.md_reg = 0x29d0,
+	.mn = {
+		.mnctr_en_bit = 8,
+		.mnctr_reset_bit = 7,
+		.mnctr_mode_shift = 5,
+		.n_val_shift = 16,
+		.m_val_shift = 16,
+		.width = 16,
+	},
+	.p = {
+		.pre_div_shift = 3,
+		.pre_div_width = 2,
+	},
+	.s = {
+		.src_sel_shift = 0,
+		.parent_map = gcc_pxo_pll8_map,
+	},
+	.freq_tbl = clk_tbl_gsbi_uart,
+	.hw = {
+		.enable_reg = 0x29d4,
+		.enable_mask = BIT(11),
+		.init = &(struct clk_init_data){
+			.name = "gsbi1_uart_src",
+			.parent_names = gcc_pxo_pll8,
+			.num_parents = 2,
+			.ops = &clk_rcg_ops,
+			.flags = CLK_SET_PARENT_GATE,
+		},
+	},
+};
+
+static struct clk_branch gsbi1_uart_clk = {
+	.halt_reg = 0x2fcc,
+	.halt_bit = 10,
+	.hw = {
+		.enable_reg = 0x29d4,
+		.enable_mask = BIT(9),
+		.init = &(struct clk_init_data){
+			.name = "gsbi1_uart_clk",
+			.parent_names = (const char *[]){
+				"gsbi1_uart_src",
+			},
+			.num_parents = 1,
+			.ops = &clk_branch_ops,
+			.flags = CLK_SET_RATE_PARENT,
+		},
+	},
+};
+
+static struct clk_rcg gsbi2_uart_src = {
+	.ns_reg = 0x29f4,
+	.md_reg = 0x29f0,
+	.mn = {
+		.mnctr_en_bit = 8,
+		.mnctr_reset_bit = 7,
+		.mnctr_mode_shift = 5,
+		.n_val_shift = 16,
+		.m_val_shift = 16,
+		.width = 16,
+	},
+	.p = {
+		.pre_div_shift = 3,
+		.pre_div_width = 2,
+	},
+	.s = {
+		.src_sel_shift = 0,
+		.parent_map = gcc_pxo_pll8_map,
+	},
+	.freq_tbl = clk_tbl_gsbi_uart,
+	.hw = {
+		.enable_reg = 0x29f4,
+		.enable_mask = BIT(11),
+		.init = &(struct clk_init_data){
+			.name = "gsbi2_uart_src",
+			.parent_names = gcc_pxo_pll8,
+			.num_parents = 2,
+			.ops = &clk_rcg_ops,
+			.flags = CLK_SET_PARENT_GATE,
+		},
+	},
+};
+
+static struct clk_branch gsbi2_uart_clk = {
+	.halt_reg = 0x2fcc,
+	.halt_bit = 6,
+	.hw = {
+		.enable_reg = 0x29f4,
+		.enable_mask = BIT(9),
+		.init = &(struct clk_init_data){
+			.name = "gsbi2_uart_clk",
+			.parent_names = (const char *[]){
+				"gsbi2_uart_src",
+			},
+			.num_parents = 1,
+			.ops = &clk_branch_ops,
+			.flags = CLK_SET_RATE_PARENT,
+		},
+	},
+};
+
+static struct clk_rcg gsbi3_uart_src = {
+	.ns_reg = 0x2a14,
+	.md_reg = 0x2a10,
+	.mn = {
+		.mnctr_en_bit = 8,
+		.mnctr_reset_bit = 7,
+		.mnctr_mode_shift = 5,
+		.n_val_shift = 16,
+		.m_val_shift = 16,
+		.width = 16,
+	},
+	.p = {
+		.pre_div_shift = 3,
+		.pre_div_width = 2,
+	},
+	.s = {
+		.src_sel_shift = 0,
+		.parent_map = gcc_pxo_pll8_map,
+	},
+	.freq_tbl = clk_tbl_gsbi_uart,
+	.hw = {
+		.enable_reg = 0x2a14,
+		.enable_mask = BIT(11),
+		.init = &(struct clk_init_data){
+			.name = "gsbi3_uart_src",
+			.parent_names = gcc_pxo_pll8,
+			.num_parents = 2,
+			.ops = &clk_rcg_ops,
+			.flags = CLK_SET_PARENT_GATE,
+		},
+	},
+};
+
+static struct clk_branch gsbi3_uart_clk = {
+	.halt_reg = 0x2fcc,
+	.halt_bit = 2,
+	.hw = {
+		.enable_reg = 0x2a14,
+		.enable_mask = BIT(9),
+		.init = &(struct clk_init_data){
+			.name = "gsbi3_uart_clk",
+			.parent_names = (const char *[]){
+				"gsbi3_uart_src",
+			},
+			.num_parents = 1,
+			.ops = &clk_branch_ops,
+			.flags = CLK_SET_RATE_PARENT,
+		},
+	},
+};
+
+static struct clk_rcg gsbi4_uart_src = {
+	.ns_reg = 0x2a34,
+	.md_reg = 0x2a30,
+	.mn = {
+		.mnctr_en_bit = 8,
+		.mnctr_reset_bit = 7,
+		.mnctr_mode_shift = 5,
+		.n_val_shift = 16,
+		.m_val_shift = 16,
+		.width = 16,
+	},
+	.p = {
+		.pre_div_shift = 3,
+		.pre_div_width = 2,
+	},
+	.s = {
+		.src_sel_shift = 0,
+		.parent_map = gcc_pxo_pll8_map,
+	},
+	.freq_tbl = clk_tbl_gsbi_uart,
+	.hw = {
+		.enable_reg = 0x2a34,
+		.enable_mask = BIT(11),
+		.init = &(struct clk_init_data){
+			.name = "gsbi4_uart_src",
+			.parent_names = gcc_pxo_pll8,
+			.num_parents = 2,
+			.ops = &clk_rcg_ops,
+			.flags = CLK_SET_PARENT_GATE,
+		},
+	},
+};
+
+static struct clk_branch gsbi4_uart_clk = {
+	.halt_reg = 0x2fd0,
+	.halt_bit = 26,
+	.hw = {
+		.enable_reg = 0x2a34,
+		.enable_mask = BIT(9),
+		.init = &(struct clk_init_data){
+			.name = "gsbi4_uart_clk",
+			.parent_names = (const char *[]){
+				"gsbi4_uart_src",
+			},
+			.num_parents = 1,
+			.ops = &clk_branch_ops,
+			.flags = CLK_SET_RATE_PARENT,
+		},
+	},
+};
+
+static struct clk_rcg gsbi5_uart_src = {
+	.ns_reg = 0x2a54,
+	.md_reg = 0x2a50,
+	.mn = {
+		.mnctr_en_bit = 8,
+		.mnctr_reset_bit = 7,
+		.mnctr_mode_shift = 5,
+		.n_val_shift = 16,
+		.m_val_shift = 16,
+		.width = 16,
+	},
+	.p = {
+		.pre_div_shift = 3,
+		.pre_div_width = 2,
+	},
+	.s = {
+		.src_sel_shift = 0,
+		.parent_map = gcc_pxo_pll8_map,
+	},
+	.freq_tbl = clk_tbl_gsbi_uart,
+	.hw = {
+		.enable_reg = 0x2a54,
+		.enable_mask = BIT(11),
+		.init = &(struct clk_init_data){
+			.name = "gsbi5_uart_src",
+			.parent_names = gcc_pxo_pll8,
+			.num_parents = 2,
+			.ops = &clk_rcg_ops,
+			.flags = CLK_SET_PARENT_GATE,
+		},
+	},
+};
+
+static struct clk_branch gsbi5_uart_clk = {
+	.halt_reg = 0x2fd0,
+	.halt_bit = 22,
+	.hw = {
+		.enable_reg = 0x2a54,
+		.enable_mask = BIT(9),
+		.init = &(struct clk_init_data){
+			.name = "gsbi5_uart_clk",
+			.parent_names = (const char *[]){
+				"gsbi5_uart_src",
+			},
+			.num_parents = 1,
+			.ops = &clk_branch_ops,
+			.flags = CLK_SET_RATE_PARENT,
+		},
+	},
+};
+
+static struct clk_rcg gsbi6_uart_src = {
+	.ns_reg = 0x2a74,
+	.md_reg = 0x2a70,
+	.mn = {
+		.mnctr_en_bit = 8,
+		.mnctr_reset_bit = 7,
+		.mnctr_mode_shift = 5,
+		.n_val_shift = 16,
+		.m_val_shift = 16,
+		.width = 16,
+	},
+	.p = {
+		.pre_div_shift = 3,
+		.pre_div_width = 2,
+	},
+	.s = {
+		.src_sel_shift = 0,
+		.parent_map = gcc_pxo_pll8_map,
+	},
+	.freq_tbl = clk_tbl_gsbi_uart,
+	.hw = {
+		.enable_reg = 0x2a74,
+		.enable_mask = BIT(11),
+		.init = &(struct clk_init_data){
+			.name = "gsbi6_uart_src",
+			.parent_names = gcc_pxo_pll8,
+			.num_parents = 2,
+			.ops = &clk_rcg_ops,
+			.flags = CLK_SET_PARENT_GATE,
+		},
+	},
+};
+
+static struct clk_branch gsbi6_uart_clk = {
+	.halt_reg = 0x2fd0,
+	.halt_bit = 18,
+	.hw = {
+		.enable_reg = 0x2a74,
+		.enable_mask = BIT(9),
+		.init = &(struct clk_init_data){
+			.name = "gsbi6_uart_clk",
+			.parent_names = (const char *[]){
+				"gsbi6_uart_src",
+			},
+			.num_parents = 1,
+			.ops = &clk_branch_ops,
+			.flags = CLK_SET_RATE_PARENT,
+		},
+	},
+};
+
+static struct clk_rcg gsbi7_uart_src = {
+	.ns_reg = 0x2a94,
+	.md_reg = 0x2a90,
+	.mn = {
+		.mnctr_en_bit = 8,
+		.mnctr_reset_bit = 7,
+		.mnctr_mode_shift = 5,
+		.n_val_shift = 16,
+		.m_val_shift = 16,
+		.width = 16,
+	},
+	.p = {
+		.pre_div_shift = 3,
+		.pre_div_width = 2,
+	},
+	.s = {
+		.src_sel_shift = 0,
+		.parent_map = gcc_pxo_pll8_map,
+	},
+	.freq_tbl = clk_tbl_gsbi_uart,
+	.hw = {
+		.enable_reg = 0x2a94,
+		.enable_mask = BIT(11),
+		.init = &(struct clk_init_data){
+			.name = "gsbi7_uart_src",
+			.parent_names = gcc_pxo_pll8,
+			.num_parents = 2,
+			.ops = &clk_rcg_ops,
+			.flags = CLK_SET_PARENT_GATE,
+		},
+	},
+};
+
+static struct clk_branch gsbi7_uart_clk = {
+	.halt_reg = 0x2fd0,
+	.halt_bit = 14,
+	.hw = {
+		.enable_reg = 0x2a94,
+		.enable_mask = BIT(9),
+		.init = &(struct clk_init_data){
+			.name = "gsbi7_uart_clk",
+			.parent_names = (const char *[]){
+				"gsbi7_uart_src",
+			},
+			.num_parents = 1,
+			.ops = &clk_branch_ops,
+			.flags = CLK_SET_RATE_PARENT,
+		},
+	},
+};
+
+static struct clk_rcg gsbi8_uart_src = {
+	.ns_reg = 0x2ab4,
+	.md_reg = 0x2ab0,
+	.mn = {
+		.mnctr_en_bit = 8,
+		.mnctr_reset_bit = 7,
+		.mnctr_mode_shift = 5,
+		.n_val_shift = 16,
+		.m_val_shift = 16,
+		.width = 16,
+	},
+	.p = {
+		.pre_div_shift = 3,
+		.pre_div_width = 2,
+	},
+	.s = {
+		.src_sel_shift = 0,
+		.parent_map = gcc_pxo_pll8_map,
+	},
+	.freq_tbl = clk_tbl_gsbi_uart,
+	.hw = {
+		.enable_reg = 0x2ab4,
+		.enable_mask = BIT(11),
+		.init = &(struct clk_init_data){
+			.name = "gsbi8_uart_src",
+			.parent_names = gcc_pxo_pll8,
+			.num_parents = 2,
+			.ops = &clk_rcg_ops,
+			.flags = CLK_SET_PARENT_GATE,
+		},
+	},
+};
+
+static struct clk_branch gsbi8_uart_clk = {
+	.halt_reg = 0x2fd0,
+	.halt_bit = 10,
+	.hw = {
+		.enable_reg = 0x2ab4,
+		.enable_mask = BIT(9),
+		.init = &(struct clk_init_data){
+			.name = "gsbi8_uart_clk",
+			.parent_names = (const char *[]){ "gsbi8_uart_src" },
+			.num_parents = 1,
+			.ops = &clk_branch_ops,
+			.flags = CLK_SET_RATE_PARENT,
+		},
+	},
+};
+
+static struct clk_rcg gsbi9_uart_src = {
+	.ns_reg = 0x2ad4,
+	.md_reg = 0x2ad0,
+	.mn = {
+		.mnctr_en_bit = 8,
+		.mnctr_reset_bit = 7,
+		.mnctr_mode_shift = 5,
+		.n_val_shift = 16,
+		.m_val_shift = 16,
+		.width = 16,
+	},
+	.p = {
+		.pre_div_shift = 3,
+		.pre_div_width = 2,
+	},
+	.s = {
+		.src_sel_shift = 0,
+		.parent_map = gcc_pxo_pll8_map,
+	},
+	.freq_tbl = clk_tbl_gsbi_uart,
+	.hw = {
+		.enable_reg = 0x2ad4,
+		.enable_mask = BIT(11),
+		.init = &(struct clk_init_data){
+			.name = "gsbi9_uart_src",
+			.parent_names = gcc_pxo_pll8,
+			.num_parents = 2,
+			.ops = &clk_rcg_ops,
+			.flags = CLK_SET_PARENT_GATE,
+		},
+	},
+};
+
+static struct clk_branch gsbi9_uart_clk = {
+	.halt_reg = 0x2fd0,
+	.halt_bit = 6,
+	.hw = {
+		.enable_reg = 0x2ad4,
+		.enable_mask = BIT(9),
+		.init = &(struct clk_init_data){
+			.name = "gsbi9_uart_clk",
+			.parent_names = (const char *[]){ "gsbi9_uart_src" },
+			.num_parents = 1,
+			.ops = &clk_branch_ops,
+			.flags = CLK_SET_RATE_PARENT,
+		},
+	},
+};
+
+static struct clk_rcg gsbi10_uart_src = {
+	.ns_reg = 0x2af4,
+	.md_reg = 0x2af0,
+	.mn = {
+		.mnctr_en_bit = 8,
+		.mnctr_reset_bit = 7,
+		.mnctr_mode_shift = 5,
+		.n_val_shift = 16,
+		.m_val_shift = 16,
+		.width = 16,
+	},
+	.p = {
+		.pre_div_shift = 3,
+		.pre_div_width = 2,
+	},
+	.s = {
+		.src_sel_shift = 0,
+		.parent_map = gcc_pxo_pll8_map,
+	},
+	.freq_tbl = clk_tbl_gsbi_uart,
+	.hw = {
+		.enable_reg = 0x2af4,
+		.enable_mask = BIT(11),
+		.init = &(struct clk_init_data){
+			.name = "gsbi10_uart_src",
+			.parent_names = gcc_pxo_pll8,
+			.num_parents = 2,
+			.ops = &clk_rcg_ops,
+			.flags = CLK_SET_PARENT_GATE,
+		},
+	},
+};
+
+static struct clk_branch gsbi10_uart_clk = {
+	.halt_reg = 0x2fd0,
+	.halt_bit = 2,
+	.hw = {
+		.enable_reg = 0x2af4,
+		.enable_mask = BIT(9),
+		.init = &(struct clk_init_data){
+			.name = "gsbi10_uart_clk",
+			.parent_names = (const char *[]){ "gsbi10_uart_src" },
+			.num_parents = 1,
+			.ops = &clk_branch_ops,
+			.flags = CLK_SET_RATE_PARENT,
+		},
+	},
+};
+
+static struct clk_rcg gsbi11_uart_src = {
+	.ns_reg = 0x2b14,
+	.md_reg = 0x2b10,
+	.mn = {
+		.mnctr_en_bit = 8,
+		.mnctr_reset_bit = 7,
+		.mnctr_mode_shift = 5,
+		.n_val_shift = 16,
+		.m_val_shift = 16,
+		.width = 16,
+	},
+	.p = {
+		.pre_div_shift = 3,
+		.pre_div_width = 2,
+	},
+	.s = {
+		.src_sel_shift = 0,
+		.parent_map = gcc_pxo_pll8_map,
+	},
+	.freq_tbl = clk_tbl_gsbi_uart,
+	.hw = {
+		.enable_reg = 0x2b14,
+		.enable_mask = BIT(11),
+		.init = &(struct clk_init_data){
+			.name = "gsbi11_uart_src",
+			.parent_names = gcc_pxo_pll8,
+			.num_parents = 2,
+			.ops = &clk_rcg_ops,
+			.flags = CLK_SET_PARENT_GATE,
+		},
+	},
+};
+
+static struct clk_branch gsbi11_uart_clk = {
+	.halt_reg = 0x2fd4,
+	.halt_bit = 17,
+	.hw = {
+		.enable_reg = 0x2b14,
+		.enable_mask = BIT(9),
+		.init = &(struct clk_init_data){
+			.name = "gsbi11_uart_clk",
+			.parent_names = (const char *[]){ "gsbi11_uart_src" },
+			.num_parents = 1,
+			.ops = &clk_branch_ops,
+			.flags = CLK_SET_RATE_PARENT,
+		},
+	},
+};
+
+static struct clk_rcg gsbi12_uart_src = {
+	.ns_reg = 0x2b34,
+	.md_reg = 0x2b30,
+	.mn = {
+		.mnctr_en_bit = 8,
+		.mnctr_reset_bit = 7,
+		.mnctr_mode_shift = 5,
+		.n_val_shift = 16,
+		.m_val_shift = 16,
+		.width = 16,
+	},
+	.p = {
+		.pre_div_shift = 3,
+		.pre_div_width = 2,
+	},
+	.s = {
+		.src_sel_shift = 0,
+		.parent_map = gcc_pxo_pll8_map,
+	},
+	.freq_tbl = clk_tbl_gsbi_uart,
+	.hw = {
+		.enable_reg = 0x2b34,
+		.enable_mask = BIT(11),
+		.init = &(struct clk_init_data){
+			.name = "gsbi12_uart_src",
+			.parent_names = gcc_pxo_pll8,
+			.num_parents = 2,
+			.ops = &clk_rcg_ops,
+			.flags = CLK_SET_PARENT_GATE,
+		},
+	},
+};
+
+static struct clk_branch gsbi12_uart_clk = {
+	.halt_reg = 0x2fd4,
+	.halt_bit = 13,
+	.hw = {
+		.enable_reg = 0x2b34,
+		.enable_mask = BIT(9),
+		.init = &(struct clk_init_data){
+			.name = "gsbi12_uart_clk",
+			.parent_names = (const char *[]){ "gsbi12_uart_src" },
+			.num_parents = 1,
+			.ops = &clk_branch_ops,
+			.flags = CLK_SET_RATE_PARENT,
+		},
+	},
+};
+
+static struct freq_tbl clk_tbl_gsbi_qup[] = {
+	{  1100000, P_PXO,  1, 2, 49 },
+	{  5400000, P_PXO,  1, 1,  5 },
+	{ 10800000, P_PXO,  1, 2,  5 },
+	{ 15060000, P_PLL8, 1, 2, 51 },
+	{ 24000000, P_PLL8, 4, 1,  4 },
+	{ 25600000, P_PLL8, 1, 1, 15 },
+	{ 27000000, P_PXO,  1, 0,  0 },
+	{ 48000000, P_PLL8, 4, 1,  2 },
+	{ 51200000, P_PLL8, 1, 2, 15 },
+	{ }
+};
+
+static struct clk_rcg gsbi1_qup_src = {
+	.ns_reg = 0x29cc,
+	.md_reg = 0x29c8,
+	.mn = {
+		.mnctr_en_bit = 8,
+		.mnctr_reset_bit = 7,
+		.mnctr_mode_shift = 5,
+		.n_val_shift = 16,
+		.m_val_shift = 16,
+		.width = 8,
+	},
+	.p = {
+		.pre_div_shift = 3,
+		.pre_div_width = 2,
+	},
+	.s = {
+		.src_sel_shift = 0,
+		.parent_map = gcc_pxo_pll8_map,
+	},
+	.freq_tbl = clk_tbl_gsbi_qup,
+	.hw = {
+		.enable_reg = 0x29cc,
+		.enable_mask = BIT(11),
+		.init = &(struct clk_init_data){
+			.name = "gsbi1_qup_src",
+			.parent_names = gcc_pxo_pll8,
+			.num_parents = 2,
+			.ops = &clk_rcg_ops,
+			.flags = CLK_SET_PARENT_GATE,
+		},
+	},
+};
+
+static struct clk_branch gsbi1_qup_clk = {
+	.halt_reg = 0x2fcc,
+	.halt_bit = 9,
+	.hw = {
+		.enable_reg = 0x29cc,
+		.enable_mask = BIT(9),
+		.init = &(struct clk_init_data){
+			.name = "gsbi1_qup_clk",
+			.parent_names = (const char *[]){ "gsbi1_qup_src" },
+			.num_parents = 1,
+			.ops = &clk_branch_ops,
+			.flags = CLK_SET_RATE_PARENT,
+		},
+	},
+};
+
+static struct clk_rcg gsbi2_qup_src = {
+	.ns_reg = 0x29ec,
+	.md_reg = 0x29e8,
+	.mn = {
+		.mnctr_en_bit = 8,
+		.mnctr_reset_bit = 7,
+		.mnctr_mode_shift = 5,
+		.n_val_shift = 16,
+		.m_val_shift = 16,
+		.width = 8,
+	},
+	.p = {
+		.pre_div_shift = 3,
+		.pre_div_width = 2,
+	},
+	.s = {
+		.src_sel_shift = 0,
+		.parent_map = gcc_pxo_pll8_map,
+	},
+	.freq_tbl = clk_tbl_gsbi_qup,
+	.hw = {
+		.enable_reg = 0x29ec,
+		.enable_mask = BIT(11),
+		.init = &(struct clk_init_data){
+			.name = "gsbi2_qup_src",
+			.parent_names = gcc_pxo_pll8,
+			.num_parents = 2,
+			.ops = &clk_rcg_ops,
+			.flags = CLK_SET_PARENT_GATE,
+		},
+	},
+};
+
+static struct clk_branch gsbi2_qup_clk = {
+	.halt_reg = 0x2fcc,
+	.halt_bit = 4,
+	.hw = {
+		.enable_reg = 0x29ec,
+		.enable_mask = BIT(9),
+		.init = &(struct clk_init_data){
+			.name = "gsbi2_qup_clk",
+			.parent_names = (const char *[]){ "gsbi2_qup_src" },
+			.num_parents = 1,
+			.ops = &clk_branch_ops,
+			.flags = CLK_SET_RATE_PARENT,
+		},
+	},
+};
+
+static struct clk_rcg gsbi3_qup_src = {
+	.ns_reg = 0x2a0c,
+	.md_reg = 0x2a08,
+	.mn = {
+		.mnctr_en_bit = 8,
+		.mnctr_reset_bit = 7,
+		.mnctr_mode_shift = 5,
+		.n_val_shift = 16,
+		.m_val_shift = 16,
+		.width = 8,
+	},
+	.p = {
+		.pre_div_shift = 3,
+		.pre_div_width = 2,
+	},
+	.s = {
+		.src_sel_shift = 0,
+		.parent_map = gcc_pxo_pll8_map,
+	},
+	.freq_tbl = clk_tbl_gsbi_qup,
+	.hw = {
+		.enable_reg = 0x2a0c,
+		.enable_mask = BIT(11),
+		.init = &(struct clk_init_data){
+			.name = "gsbi3_qup_src",
+			.parent_names = gcc_pxo_pll8,
+			.num_parents = 2,
+			.ops = &clk_rcg_ops,
+			.flags = CLK_SET_PARENT_GATE,
+		},
+	},
+};
+
+static struct clk_branch gsbi3_qup_clk = {
+	.halt_reg = 0x2fcc,
+	.halt_bit = 0,
+	.hw = {
+		.enable_reg = 0x2a0c,
+		.enable_mask = BIT(9),
+		.init = &(struct clk_init_data){
+			.name = "gsbi3_qup_clk",
+			.parent_names = (const char *[]){ "gsbi3_qup_src" },
+			.num_parents = 1,
+			.ops = &clk_branch_ops,
+			.flags = CLK_SET_RATE_PARENT,
+		},
+	},
+};
+
+static struct clk_rcg gsbi4_qup_src = {
+	.ns_reg = 0x2a2c,
+	.md_reg = 0x2a28,
+	.mn = {
+		.mnctr_en_bit = 8,
+		.mnctr_reset_bit = 7,
+		.mnctr_mode_shift = 5,
+		.n_val_shift = 16,
+		.m_val_shift = 16,
+		.width = 8,
+	},
+	.p = {
+		.pre_div_shift = 3,
+		.pre_div_width = 2,
+	},
+	.s = {
+		.src_sel_shift = 0,
+		.parent_map = gcc_pxo_pll8_map,
+	},
+	.freq_tbl = clk_tbl_gsbi_qup,
+	.hw = {
+		.enable_reg = 0x2a2c,
+		.enable_mask = BIT(11),
+		.init = &(struct clk_init_data){
+			.name = "gsbi4_qup_src",
+			.parent_names = gcc_pxo_pll8,
+			.num_parents = 2,
+			.ops = &clk_rcg_ops,
+			.flags = CLK_SET_PARENT_GATE,
+		},
+	},
+};
+
+static struct clk_branch gsbi4_qup_clk = {
+	.halt_reg = 0x2fd0,
+	.halt_bit = 24,
+	.hw = {
+		.enable_reg = 0x2a2c,
+		.enable_mask = BIT(9),
+		.init = &(struct clk_init_data){
+			.name = "gsbi4_qup_clk",
+			.parent_names = (const char *[]){ "gsbi4_qup_src" },
+			.num_parents = 1,
+			.ops = &clk_branch_ops,
+			.flags = CLK_SET_RATE_PARENT,
+		},
+	},
+};
+
+static struct clk_rcg gsbi5_qup_src = {
+	.ns_reg = 0x2a4c,
+	.md_reg = 0x2a48,
+	.mn = {
+		.mnctr_en_bit = 8,
+		.mnctr_reset_bit = 7,
+		.mnctr_mode_shift = 5,
+		.n_val_shift = 16,
+		.m_val_shift = 16,
+		.width = 8,
+	},
+	.p = {
+		.pre_div_shift = 3,
+		.pre_div_width = 2,
+	},
+	.s = {
+		.src_sel_shift = 0,
+		.parent_map = gcc_pxo_pll8_map,
+	},
+	.freq_tbl = clk_tbl_gsbi_qup,
+	.hw = {
+		.enable_reg = 0x2a4c,
+		.enable_mask = BIT(11),
+		.init = &(struct clk_init_data){
+			.name = "gsbi5_qup_src",
+			.parent_names = gcc_pxo_pll8,
+			.num_parents = 2,
+			.ops = &clk_rcg_ops,
+			.flags = CLK_SET_PARENT_GATE,
+		},
+	},
+};
+
+static struct clk_branch gsbi5_qup_clk = {
+	.halt_reg = 0x2fd0,
+	.halt_bit = 20,
+	.hw = {
+		.enable_reg = 0x2a4c,
+		.enable_mask = BIT(9),
+		.init = &(struct clk_init_data){
+			.name = "gsbi5_qup_clk",
+			.parent_names = (const char *[]){ "gsbi5_qup_src" },
+			.num_parents = 1,
+			.ops = &clk_branch_ops,
+			.flags = CLK_SET_RATE_PARENT,
+		},
+	},
+};
+
+static struct clk_rcg gsbi6_qup_src = {
+	.ns_reg = 0x2a6c,
+	.md_reg = 0x2a68,
+	.mn = {
+		.mnctr_en_bit = 8,
+		.mnctr_reset_bit = 7,
+		.mnctr_mode_shift = 5,
+		.n_val_shift = 16,
+		.m_val_shift = 16,
+		.width = 8,
+	},
+	.p = {
+		.pre_div_shift = 3,
+		.pre_div_width = 2,
+	},
+	.s = {
+		.src_sel_shift = 0,
+		.parent_map = gcc_pxo_pll8_map,
+	},
+	.freq_tbl = clk_tbl_gsbi_qup,
+	.hw = {
+		.enable_reg = 0x2a6c,
+		.enable_mask = BIT(11),
+		.init = &(struct clk_init_data){
+			.name = "gsbi6_qup_src",
+			.parent_names = gcc_pxo_pll8,
+			.num_parents = 2,
+			.ops = &clk_rcg_ops,
+			.flags = CLK_SET_PARENT_GATE,
+		},
+	},
+};
+
+static struct clk_branch gsbi6_qup_clk = {
+	.halt_reg = 0x2fd0,
+	.halt_bit = 16,
+	.hw = {
+		.enable_reg = 0x2a6c,
+		.enable_mask = BIT(9),
+		.init = &(struct clk_init_data){
+			.name = "gsbi6_qup_clk",
+			.parent_names = (const char *[]){ "gsbi6_qup_src" },
+			.num_parents = 1,
+			.ops = &clk_branch_ops,
+			.flags = CLK_SET_RATE_PARENT,
+		},
+	},
+};
+
+static struct clk_rcg gsbi7_qup_src = {
+	.ns_reg = 0x2a8c,
+	.md_reg = 0x2a88,
+	.mn = {
+		.mnctr_en_bit = 8,
+		.mnctr_reset_bit = 7,
+		.mnctr_mode_shift = 5,
+		.n_val_shift = 16,
+		.m_val_shift = 16,
+		.width = 8,
+	},
+	.p = {
+		.pre_div_shift = 3,
+		.pre_div_width = 2,
+	},
+	.s = {
+		.src_sel_shift = 0,
+		.parent_map = gcc_pxo_pll8_map,
+	},
+	.freq_tbl = clk_tbl_gsbi_qup,
+	.hw = {
+		.enable_reg = 0x2a8c,
+		.enable_mask = BIT(11),
+		.init = &(struct clk_init_data){
+			.name = "gsbi7_qup_src",
+			.parent_names = gcc_pxo_pll8,
+			.num_parents = 2,
+			.ops = &clk_rcg_ops,
+			.flags = CLK_SET_PARENT_GATE,
+		},
+	},
+};
+
+static struct clk_branch gsbi7_qup_clk = {
+	.halt_reg = 0x2fd0,
+	.halt_bit = 12,
+	.hw = {
+		.enable_reg = 0x2a8c,
+		.enable_mask = BIT(9),
+		.init = &(struct clk_init_data){
+			.name = "gsbi7_qup_clk",
+			.parent_names = (const char *[]){ "gsbi7_qup_src" },
+			.num_parents = 1,
+			.ops = &clk_branch_ops,
+			.flags = CLK_SET_RATE_PARENT,
+		},
+	},
+};
+
+static struct clk_rcg gsbi8_qup_src = {
+	.ns_reg = 0x2aac,
+	.md_reg = 0x2aa8,
+	.mn = {
+		.mnctr_en_bit = 8,
+		.mnctr_reset_bit = 7,
+		.mnctr_mode_shift = 5,
+		.n_val_shift = 16,
+		.m_val_shift = 16,
+		.width = 8,
+	},
+	.p = {
+		.pre_div_shift = 3,
+		.pre_div_width = 2,
+	},
+	.s = {
+		.src_sel_shift = 0,
+		.parent_map = gcc_pxo_pll8_map,
+	},
+	.freq_tbl = clk_tbl_gsbi_qup,
+	.hw = {
+		.enable_reg = 0x2aac,
+		.enable_mask = BIT(11),
+		.init = &(struct clk_init_data){
+			.name = "gsbi8_qup_src",
+			.parent_names = gcc_pxo_pll8,
+			.num_parents = 2,
+			.ops = &clk_rcg_ops,
+			.flags = CLK_SET_PARENT_GATE,
+		},
+	},
+};
+
+static struct clk_branch gsbi8_qup_clk = {
+	.halt_reg = 0x2fd0,
+	.halt_bit = 8,
+	.hw = {
+		.enable_reg = 0x2aac,
+		.enable_mask = BIT(9),
+		.init = &(struct clk_init_data){
+			.name = "gsbi8_qup_clk",
+			.parent_names = (const char *[]){ "gsbi8_qup_src" },
+			.num_parents = 1,
+			.ops = &clk_branch_ops,
+			.flags = CLK_SET_RATE_PARENT,
+		},
+	},
+};
+
+static struct clk_rcg gsbi9_qup_src = {
+	.ns_reg = 0x2acc,
+	.md_reg = 0x2ac8,
+	.mn = {
+		.mnctr_en_bit = 8,
+		.mnctr_reset_bit = 7,
+		.mnctr_mode_shift = 5,
+		.n_val_shift = 16,
+		.m_val_shift = 16,
+		.width = 8,
+	},
+	.p = {
+		.pre_div_shift = 3,
+		.pre_div_width = 2,
+	},
+	.s = {
+		.src_sel_shift = 0,
+		.parent_map = gcc_pxo_pll8_map,
+	},
+	.freq_tbl = clk_tbl_gsbi_qup,
+	.hw = {
+		.enable_reg = 0x2acc,
+		.enable_mask = BIT(11),
+		.init = &(struct clk_init_data){
+			.name = "gsbi9_qup_src",
+			.parent_names = gcc_pxo_pll8,
+			.num_parents = 2,
+			.ops = &clk_rcg_ops,
+			.flags = CLK_SET_PARENT_GATE,
+		},
+	},
+};
+
+static struct clk_branch gsbi9_qup_clk = {
+	.halt_reg = 0x2fd0,
+	.halt_bit = 4,
+	.hw = {
+		.enable_reg = 0x2acc,
+		.enable_mask = BIT(9),
+		.init = &(struct clk_init_data){
+			.name = "gsbi9_qup_clk",
+			.parent_names = (const char *[]){ "gsbi9_qup_src" },
+			.num_parents = 1,
+			.ops = &clk_branch_ops,
+			.flags = CLK_SET_RATE_PARENT,
+		},
+	},
+};
+
+static struct clk_rcg gsbi10_qup_src = {
+	.ns_reg = 0x2aec,
+	.md_reg = 0x2ae8,
+	.mn = {
+		.mnctr_en_bit = 8,
+		.mnctr_reset_bit = 7,
+		.mnctr_mode_shift = 5,
+		.n_val_shift = 16,
+		.m_val_shift = 16,
+		.width = 8,
+	},
+	.p = {
+		.pre_div_shift = 3,
+		.pre_div_width = 2,
+	},
+	.s = {
+		.src_sel_shift = 0,
+		.parent_map = gcc_pxo_pll8_map,
+	},
+	.freq_tbl = clk_tbl_gsbi_qup,
+	.hw = {
+		.enable_reg = 0x2aec,
+		.enable_mask = BIT(11),
+		.init = &(struct clk_init_data){
+			.name = "gsbi10_qup_src",
+			.parent_names = gcc_pxo_pll8,
+			.num_parents = 2,
+			.ops = &clk_rcg_ops,
+			.flags = CLK_SET_PARENT_GATE,
+		},
+	},
+};
+
+static struct clk_branch gsbi10_qup_clk = {
+	.halt_reg = 0x2fd0,
+	.halt_bit = 0,
+	.hw = {
+		.enable_reg = 0x2aec,
+		.enable_mask = BIT(9),
+		.init = &(struct clk_init_data){
+			.name = "gsbi10_qup_clk",
+			.parent_names = (const char *[]){ "gsbi10_qup_src" },
+			.num_parents = 1,
+			.ops = &clk_branch_ops,
+			.flags = CLK_SET_RATE_PARENT,
+		},
+	},
+};
+
+static struct clk_rcg gsbi11_qup_src = {
+	.ns_reg = 0x2b0c,
+	.md_reg = 0x2b08,
+	.mn = {
+		.mnctr_en_bit = 8,
+		.mnctr_reset_bit = 7,
+		.mnctr_mode_shift = 5,
+		.n_val_shift = 16,
+		.m_val_shift = 16,
+		.width = 8,
+	},
+	.p = {
+		.pre_div_shift = 3,
+		.pre_div_width = 2,
+	},
+	.s = {
+		.src_sel_shift = 0,
+		.parent_map = gcc_pxo_pll8_map,
+	},
+	.freq_tbl = clk_tbl_gsbi_qup,
+	.hw = {
+		.enable_reg = 0x2b0c,
+		.enable_mask = BIT(11),
+		.init = &(struct clk_init_data){
+			.name = "gsbi11_qup_src",
+			.parent_names = gcc_pxo_pll8,
+			.num_parents = 2,
+			.ops = &clk_rcg_ops,
+			.flags = CLK_SET_PARENT_GATE,
+		},
+	},
+};
+
+static struct clk_branch gsbi11_qup_clk = {
+	.halt_reg = 0x2fd4,
+	.halt_bit = 15,
+	.hw = {
+		.enable_reg = 0x2b0c,
+		.enable_mask = BIT(9),
+		.init = &(struct clk_init_data){
+			.name = "gsbi11_qup_clk",
+			.parent_names = (const char *[]){ "gsbi11_qup_src" },
+			.num_parents = 1,
+			.ops = &clk_branch_ops,
+			.flags = CLK_SET_RATE_PARENT,
+		},
+	},
+};
+
+static struct clk_rcg gsbi12_qup_src = {
+	.ns_reg = 0x2b2c,
+	.md_reg = 0x2b28,
+	.mn = {
+		.mnctr_en_bit = 8,
+		.mnctr_reset_bit = 7,
+		.mnctr_mode_shift = 5,
+		.n_val_shift = 16,
+		.m_val_shift = 16,
+		.width = 8,
+	},
+	.p = {
+		.pre_div_shift = 3,
+		.pre_div_width = 2,
+	},
+	.s = {
+		.src_sel_shift = 0,
+		.parent_map = gcc_pxo_pll8_map,
+	},
+	.freq_tbl = clk_tbl_gsbi_qup,
+	.hw = {
+		.enable_reg = 0x2b2c,
+		.enable_mask = BIT(11),
+		.init = &(struct clk_init_data){
+			.name = "gsbi12_qup_src",
+			.parent_names = gcc_pxo_pll8,
+			.num_parents = 2,
+			.ops = &clk_rcg_ops,
+			.flags = CLK_SET_PARENT_GATE,
+		},
+	},
+};
+
+static struct clk_branch gsbi12_qup_clk = {
+	.halt_reg = 0x2fd4,
+	.halt_bit = 11,
+	.hw = {
+		.enable_reg = 0x2b2c,
+		.enable_mask = BIT(9),
+		.init = &(struct clk_init_data){
+			.name = "gsbi12_qup_clk",
+			.parent_names = (const char *[]){ "gsbi12_qup_src" },
+			.num_parents = 1,
+			.ops = &clk_branch_ops,
+			.flags = CLK_SET_RATE_PARENT,
+		},
+	},
+};
+
+static const struct freq_tbl clk_tbl_gp[] = {
+	{ 9600000, P_CXO,  2, 0, 0 },
+	{ 13500000, P_PXO,  2, 0, 0 },
+	{ 19200000, P_CXO,  1, 0, 0 },
+	{ 27000000, P_PXO,  1, 0, 0 },
+	{ 64000000, P_PLL8, 2, 1, 3 },
+	{ 76800000, P_PLL8, 1, 1, 5 },
+	{ 96000000, P_PLL8, 4, 0, 0 },
+	{ 128000000, P_PLL8, 3, 0, 0 },
+	{ 192000000, P_PLL8, 2, 0, 0 },
+	{ }
+};
+
+static struct clk_rcg gp0_src = {
+	.ns_reg = 0x2d24,
+	.md_reg = 0x2d00,
+	.mn = {
+		.mnctr_en_bit = 8,
+		.mnctr_reset_bit = 7,
+		.mnctr_mode_shift = 5,
+		.n_val_shift = 16,
+		.m_val_shift = 16,
+		.width = 8,
+	},
+	.p = {
+		.pre_div_shift = 3,
+		.pre_div_width = 2,
+	},
+	.s = {
+		.src_sel_shift = 0,
+		.parent_map = gcc_pxo_pll8_cxo_map,
+	},
+	.freq_tbl = clk_tbl_gp,
+	.hw = {
+		.enable_reg = 0x2d24,
+		.enable_mask = BIT(11),
+		.init = &(struct clk_init_data){
+			.name = "gp0_src",
+			.parent_names = gcc_pxo_pll8_cxo,
+			.num_parents = 3,
+			.ops = &clk_rcg_ops,
+			.flags = CLK_SET_PARENT_GATE,
+		},
+	}
+};
+
+static struct clk_branch gp0_clk = {
+	.halt_reg = 0x2fd8,
+	.halt_bit = 7,
+	.hw = {
+		.enable_reg = 0x2d24,
+		.enable_mask = BIT(9),
+		.init = &(struct clk_init_data){
+			.name = "gp0_clk",
+			.parent_names = (const char *[]){ "gp0_src" },
+			.num_parents = 1,
+			.ops = &clk_branch_ops,
+			.flags = CLK_SET_RATE_PARENT,
+		},
+	},
+};
+
+static struct clk_rcg gp1_src = {
+	.ns_reg = 0x2d44,
+	.md_reg = 0x2d40,
+	.mn = {
+		.mnctr_en_bit = 8,
+		.mnctr_reset_bit = 7,
+		.mnctr_mode_shift = 5,
+		.n_val_shift = 16,
+		.m_val_shift = 16,
+		.width = 8,
+	},
+	.p = {
+		.pre_div_shift = 3,
+		.pre_div_width = 2,
+	},
+	.s = {
+		.src_sel_shift = 0,
+		.parent_map = gcc_pxo_pll8_cxo_map,
+	},
+	.freq_tbl = clk_tbl_gp,
+	.hw = {
+		.enable_reg = 0x2d44,
+		.enable_mask = BIT(11),
+		.init = &(struct clk_init_data){
+			.name = "gp1_src",
+			.parent_names = gcc_pxo_pll8_cxo,
+			.num_parents = 3,
+			.ops = &clk_rcg_ops,
+			.flags = CLK_SET_RATE_GATE,
+		},
+	}
+};
+
+static struct clk_branch gp1_clk = {
+	.halt_reg = 0x2fd8,
+	.halt_bit = 6,
+	.hw = {
+		.enable_reg = 0x2d44,
+		.enable_mask = BIT(9),
+		.init = &(struct clk_init_data){
+			.name = "gp1_clk",
+			.parent_names = (const char *[]){ "gp1_src" },
+			.num_parents = 1,
+			.ops = &clk_branch_ops,
+			.flags = CLK_SET_RATE_PARENT,
+		},
+	},
+};
+
+static struct clk_rcg gp2_src = {
+	.ns_reg = 0x2d64,
+	.md_reg = 0x2d60,
+	.mn = {
+		.mnctr_en_bit = 8,
+		.mnctr_reset_bit = 7,
+		.mnctr_mode_shift = 5,
+		.n_val_shift = 16,
+		.m_val_shift = 16,
+		.width = 8,
+	},
+	.p = {
+		.pre_div_shift = 3,
+		.pre_div_width = 2,
+	},
+	.s = {
+		.src_sel_shift = 0,
+		.parent_map = gcc_pxo_pll8_cxo_map,
+	},
+	.freq_tbl = clk_tbl_gp,
+	.hw = {
+		.enable_reg = 0x2d64,
+		.enable_mask = BIT(11),
+		.init = &(struct clk_init_data){
+			.name = "gp2_src",
+			.parent_names = gcc_pxo_pll8_cxo,
+			.num_parents = 3,
+			.ops = &clk_rcg_ops,
+			.flags = CLK_SET_RATE_GATE,
+		},
+	}
+};
+
+static struct clk_branch gp2_clk = {
+	.halt_reg = 0x2fd8,
+	.halt_bit = 5,
+	.hw = {
+		.enable_reg = 0x2d64,
+		.enable_mask = BIT(9),
+		.init = &(struct clk_init_data){
+			.name = "gp2_clk",
+			.parent_names = (const char *[]){ "gp2_src" },
+			.num_parents = 1,
+			.ops = &clk_branch_ops,
+			.flags = CLK_SET_RATE_PARENT,
+		},
+	},
+};
+
+static struct clk_branch pmem_clk = {
+	.hwcg_reg = 0x25a0,
+	.hwcg_bit = 6,
+	.halt_reg = 0x2fc8,
+	.halt_bit = 20,
+	.hw = {
+		.enable_reg = 0x25a0,
+		.enable_mask = BIT(4),
+		.init = &(struct clk_init_data){
+			.name = "pmem_clk",
+			.ops = &clk_branch_ops,
+			.flags = CLK_IS_ROOT,
+		},
+	},
+};
+
+static struct clk_rcg prng_src = {
+	.ns_reg = 0x2e80,
+	.p = {
+		.pre_div_shift = 3,
+		.pre_div_width = 4,
+	},
+	.s = {
+		.src_sel_shift = 0,
+		.parent_map = gcc_pxo_pll8_map,
+	},
+	.hw = {
+		.init = &(struct clk_init_data){
+			.name = "prng_src",
+			.parent_names = gcc_pxo_pll8,
+			.num_parents = 2,
+			.ops = &clk_rcg_ops,
+		},
+	},
+};
+
+static struct clk_branch prng_clk = {
+	.halt_reg = 0x2fd8,
+	.halt_check = BRANCH_HALT_VOTED,
+	.halt_bit = 10,
+	.hw = {
+		.enable_reg = 0x3080,
+		.enable_mask = BIT(10),
+		.init = &(struct clk_init_data){
+			.name = "prng_clk",
+			.parent_names = (const char *[]){ "prng_src" },
+			.num_parents = 1,
+			.ops = &clk_branch_ops,
+		},
+	},
+};
+
+static const struct freq_tbl clk_tbl_sdc[] = {
+	{    144000, P_PXO,   3, 2, 125 },
+	{    400000, P_PLL8,  4, 1, 240 },
+	{  16000000, P_PLL8,  4, 1,   6 },
+	{  17070000, P_PLL8,  1, 2,  45 },
+	{  20210000, P_PLL8,  1, 1,  19 },
+	{  24000000, P_PLL8,  4, 1,   4 },
+	{  48000000, P_PLL8,  4, 1,   2 },
+	{  64000000, P_PLL8,  3, 1,   2 },
+	{  96000000, P_PLL8,  4, 0,   0 },
+	{ 192000000, P_PLL8,  2, 0,   0 },
+	{ }
+};
+
+static struct clk_rcg sdc1_src = {
+	.ns_reg = 0x282c,
+	.md_reg = 0x2828,
+	.mn = {
+		.mnctr_en_bit = 8,
+		.mnctr_reset_bit = 7,
+		.mnctr_mode_shift = 5,
+		.n_val_shift = 16,
+		.m_val_shift = 16,
+		.width = 8,
+	},
+	.p = {
+		.pre_div_shift = 3,
+		.pre_div_width = 2,
+	},
+	.s = {
+		.src_sel_shift = 0,
+		.parent_map = gcc_pxo_pll8_map,
+	},
+	.freq_tbl = clk_tbl_sdc,
+	.hw = {
+		.enable_reg = 0x282c,
+		.enable_mask = BIT(11),
+		.init = &(struct clk_init_data){
+			.name = "sdc1_src",
+			.parent_names = gcc_pxo_pll8,
+			.num_parents = 2,
+			.ops = &clk_rcg_ops,
+			.flags = CLK_SET_RATE_GATE,
+		},
+	}
+};
+
+static struct clk_branch sdc1_clk = {
+	.halt_reg = 0x2fc8,
+	.halt_bit = 6,
+	.hw = {
+		.enable_reg = 0x282c,
+		.enable_mask = BIT(9),
+		.init = &(struct clk_init_data){
+			.name = "sdc1_clk",
+			.parent_names = (const char *[]){ "sdc1_src" },
+			.num_parents = 1,
+			.ops = &clk_branch_ops,
+			.flags = CLK_SET_RATE_PARENT,
+		},
+	},
+};
+
+static struct clk_rcg sdc2_src = {
+	.ns_reg = 0x284c,
+	.md_reg = 0x2848,
+	.mn = {
+		.mnctr_en_bit = 8,
+		.mnctr_reset_bit = 7,
+		.mnctr_mode_shift = 5,
+		.n_val_shift = 16,
+		.m_val_shift = 16,
+		.width = 8,
+	},
+	.p = {
+		.pre_div_shift = 3,
+		.pre_div_width = 2,
+	},
+	.s = {
+		.src_sel_shift = 0,
+		.parent_map = gcc_pxo_pll8_map,
+	},
+	.freq_tbl = clk_tbl_sdc,
+	.hw = {
+		.enable_reg = 0x284c,
+		.enable_mask = BIT(11),
+		.init = &(struct clk_init_data){
+			.name = "sdc2_src",
+			.parent_names = gcc_pxo_pll8,
+			.num_parents = 2,
+			.ops = &clk_rcg_ops,
+			.flags = CLK_SET_RATE_GATE,
+		},
+	}
+};
+
+static struct clk_branch sdc2_clk = {
+	.halt_reg = 0x2fc8,
+	.halt_bit = 5,
+	.hw = {
+		.enable_reg = 0x284c,
+		.enable_mask = BIT(9),
+		.init = &(struct clk_init_data){
+			.name = "sdc2_clk",
+			.parent_names = (const char *[]){ "sdc2_src" },
+			.num_parents = 1,
+			.ops = &clk_branch_ops,
+			.flags = CLK_SET_RATE_PARENT,
+		},
+	},
+};
+
+static struct clk_rcg sdc3_src = {
+	.ns_reg = 0x286c,
+	.md_reg = 0x2868,
+	.mn = {
+		.mnctr_en_bit = 8,
+		.mnctr_reset_bit = 7,
+		.mnctr_mode_shift = 5,
+		.n_val_shift = 16,
+		.m_val_shift = 16,
+		.width = 8,
+	},
+	.p = {
+		.pre_div_shift = 3,
+		.pre_div_width = 2,
+	},
+	.s = {
+		.src_sel_shift = 0,
+		.parent_map = gcc_pxo_pll8_map,
+	},
+	.freq_tbl = clk_tbl_sdc,
+	.hw = {
+		.enable_reg = 0x286c,
+		.enable_mask = BIT(11),
+		.init = &(struct clk_init_data){
+			.name = "sdc3_src",
+			.parent_names = gcc_pxo_pll8,
+			.num_parents = 2,
+			.ops = &clk_rcg_ops,
+			.flags = CLK_SET_RATE_GATE,
+		},
+	}
+};
+
+static struct clk_branch sdc3_clk = {
+	.halt_reg = 0x2fc8,
+	.halt_bit = 4,
+	.hw = {
+		.enable_reg = 0x286c,
+		.enable_mask = BIT(9),
+		.init = &(struct clk_init_data){
+			.name = "sdc3_clk",
+			.parent_names = (const char *[]){ "sdc3_src" },
+			.num_parents = 1,
+			.ops = &clk_branch_ops,
+			.flags = CLK_SET_RATE_PARENT,
+		},
+	},
+};
+
+static struct clk_rcg sdc4_src = {
+	.ns_reg = 0x288c,
+	.md_reg = 0x2888,
+	.mn = {
+		.mnctr_en_bit = 8,
+		.mnctr_reset_bit = 7,
+		.mnctr_mode_shift = 5,
+		.n_val_shift = 16,
+		.m_val_shift = 16,
+		.width = 8,
+	},
+	.p = {
+		.pre_div_shift = 3,
+		.pre_div_width = 2,
+	},
+	.s = {
+		.src_sel_shift = 0,
+		.parent_map = gcc_pxo_pll8_map,
+	},
+	.freq_tbl = clk_tbl_sdc,
+	.hw = {
+		.enable_reg = 0x288c,
+		.enable_mask = BIT(11),
+		.init = &(struct clk_init_data){
+			.name = "sdc4_src",
+			.parent_names = gcc_pxo_pll8,
+			.num_parents = 2,
+			.ops = &clk_rcg_ops,
+			.flags = CLK_SET_RATE_GATE,
+		},
+	}
+};
+
+static struct clk_branch sdc4_clk = {
+	.halt_reg = 0x2fc8,
+	.halt_bit = 3,
+	.hw = {
+		.enable_reg = 0x288c,
+		.enable_mask = BIT(9),
+		.init = &(struct clk_init_data){
+			.name = "sdc4_clk",
+			.parent_names = (const char *[]){ "sdc4_src" },
+			.num_parents = 1,
+			.ops = &clk_branch_ops,
+			.flags = CLK_SET_RATE_PARENT,
+		},
+	},
+};
+
+static struct clk_rcg sdc5_src = {
+	.ns_reg = 0x28ac,
+	.md_reg = 0x28a8,
+	.mn = {
+		.mnctr_en_bit = 8,
+		.mnctr_reset_bit = 7,
+		.mnctr_mode_shift = 5,
+		.n_val_shift = 16,
+		.m_val_shift = 16,
+		.width = 8,
+	},
+	.p = {
+		.pre_div_shift = 3,
+		.pre_div_width = 2,
+	},
+	.s = {
+		.src_sel_shift = 0,
+		.parent_map = gcc_pxo_pll8_map,
+	},
+	.freq_tbl = clk_tbl_sdc,
+	.hw = {
+		.enable_reg = 0x28ac,
+		.enable_mask = BIT(11),
+		.init = &(struct clk_init_data){
+			.name = "sdc5_src",
+			.parent_names = gcc_pxo_pll8,
+			.num_parents = 2,
+			.ops = &clk_rcg_ops,
+			.flags = CLK_SET_RATE_GATE,
+		},
+	}
+};
+
+static struct clk_branch sdc5_clk = {
+	.halt_reg = 0x2fc8,
+	.halt_bit = 2,
+	.hw = {
+		.enable_reg = 0x28ac,
+		.enable_mask = BIT(9),
+		.init = &(struct clk_init_data){
+			.name = "sdc5_clk",
+			.parent_names = (const char *[]){ "sdc5_src" },
+			.num_parents = 1,
+			.ops = &clk_branch_ops,
+			.flags = CLK_SET_RATE_PARENT,
+		},
+	},
+};
+
+static const struct freq_tbl clk_tbl_tsif_ref[] = {
+	{ 105000, P_PXO,  1, 1, 256 },
+	{ }
+};
+
+static struct clk_rcg tsif_ref_src = {
+	.ns_reg = 0x2710,
+	.md_reg = 0x270c,
+	.mn = {
+		.mnctr_en_bit = 8,
+		.mnctr_reset_bit = 7,
+		.mnctr_mode_shift = 5,
+		.n_val_shift = 16,
+		.m_val_shift = 16,
+		.width = 16,
+	},
+	.p = {
+		.pre_div_shift = 3,
+		.pre_div_width = 2,
+	},
+	.s = {
+		.src_sel_shift = 0,
+		.parent_map = gcc_pxo_pll8_map,
+	},
+	.freq_tbl = clk_tbl_tsif_ref,
+	.hw = {
+		.enable_reg = 0x2710,
+		.enable_mask = BIT(11),
+		.init = &(struct clk_init_data){
+			.name = "tsif_ref_src",
+			.parent_names = gcc_pxo_pll8,
+			.num_parents = 2,
+			.ops = &clk_rcg_ops,
+			.flags = CLK_SET_RATE_GATE,
+		},
+	}
+};
+
+static struct clk_branch tsif_ref_clk = {
+	.halt_reg = 0x2fd4,
+	.halt_bit = 5,
+	.hw = {
+		.enable_reg = 0x2710,
+		.enable_mask = BIT(9),
+		.init = &(struct clk_init_data){
+			.name = "tsif_ref_clk",
+			.parent_names = (const char *[]){ "tsif_ref_src" },
+			.num_parents = 1,
+			.ops = &clk_branch_ops,
+			.flags = CLK_SET_RATE_PARENT,
+		},
+	},
+};
+
+static const struct freq_tbl clk_tbl_usb[] = {
+	{ 60000000, P_PLL8, 1, 5, 32 },
+	{ }
+};
+
+static struct clk_rcg usb_hs1_xcvr_src = {
+	.ns_reg = 0x290c,
+	.md_reg = 0x2908,
+	.mn = {
+		.mnctr_en_bit = 8,
+		.mnctr_reset_bit = 7,
+		.mnctr_mode_shift = 5,
+		.n_val_shift = 16,
+		.m_val_shift = 16,
+		.width = 8,
+	},
+	.p = {
+		.pre_div_shift = 3,
+		.pre_div_width = 2,
+	},
+	.s = {
+		.src_sel_shift = 0,
+		.parent_map = gcc_pxo_pll8_map,
+	},
+	.freq_tbl = clk_tbl_usb,
+	.hw = {
+		.enable_reg = 0x290c,
+		.enable_mask = BIT(11),
+		.init = &(struct clk_init_data){
+			.name = "usb_hs1_xcvr_src",
+			.parent_names = gcc_pxo_pll8,
+			.num_parents = 2,
+			.ops = &clk_rcg_ops,
+			.flags = CLK_SET_RATE_GATE,
+		},
+	}
+};
+
+static struct clk_branch usb_hs1_xcvr_clk = {
+	.halt_reg = 0x2fc8,
+	.halt_bit = 0,
+	.hw = {
+		.enable_reg = 0x290c,
+		.enable_mask = BIT(9),
+		.init = &(struct clk_init_data){
+			.name = "usb_hs1_xcvr_clk",
+			.parent_names = (const char *[]){ "usb_hs1_xcvr_src" },
+			.num_parents = 1,
+			.ops = &clk_branch_ops,
+			.flags = CLK_SET_RATE_PARENT,
+		},
+	},
+};
+
+static struct clk_rcg usb_hsic_xcvr_fs_src = {
+	.ns_reg = 0x2928,
+	.md_reg = 0x2924,
+	.mn = {
+		.mnctr_en_bit = 8,
+		.mnctr_reset_bit = 7,
+		.mnctr_mode_shift = 5,
+		.n_val_shift = 16,
+		.m_val_shift = 16,
+		.width = 8,
+	},
+	.p = {
+		.pre_div_shift = 3,
+		.pre_div_width = 2,
+	},
+	.s = {
+		.src_sel_shift = 0,
+		.parent_map = gcc_pxo_pll8_map,
+	},
+	.freq_tbl = clk_tbl_usb,
+	.hw = {
+		.enable_reg = 0x2928,
+		.enable_mask = BIT(11),
+		.init = &(struct clk_init_data){
+			.name = "usb_hsic_xcvr_fs_src",
+			.parent_names = gcc_pxo_pll8,
+			.num_parents = 2,
+			.ops = &clk_rcg_ops,
+			.flags = CLK_SET_RATE_GATE,
+		},
+	}
+};
+
+static const char *usb_hsic_xcvr_fs_src_p[] = { "usb_hsic_xcvr_fs_src" };
+
+static struct clk_branch usb_hsic_xcvr_fs_clk = {
+	.halt_reg = 0x2fc8,
+	.halt_bit = 2,
+	.hw = {
+		.enable_reg = 0x2928,
+		.enable_mask = BIT(9),
+		.init = &(struct clk_init_data){
+			.name = "usb_hsic_xcvr_fs_clk",
+			.parent_names = usb_hsic_xcvr_fs_src_p,
+			.num_parents = 1,
+			.ops = &clk_branch_ops,
+			.flags = CLK_SET_RATE_PARENT,
+		},
+	},
+};
+
+static struct clk_branch usb_hsic_system_clk = {
+	.halt_reg = 0x2fcc,
+	.halt_bit = 24,
+	.hw = {
+		.enable_reg = 0x292c,
+		.enable_mask = BIT(4),
+		.init = &(struct clk_init_data){
+			.parent_names = usb_hsic_xcvr_fs_src_p,
+			.num_parents = 1,
+			.name = "usb_hsic_system_clk",
+			.ops = &clk_branch_ops,
+			.flags = CLK_SET_RATE_PARENT,
+		},
+	},
+};
+
+static struct clk_branch usb_hsic_hsic_clk = {
+	.halt_reg = 0x2fcc,
+	.halt_bit = 19,
+	.hw = {
+		.enable_reg = 0x2b44,
+		.enable_mask = BIT(0),
+		.init = &(struct clk_init_data){
+			.parent_names = (const char *[]){ "pll14_vote" },
+			.num_parents = 1,
+			.name = "usb_hsic_hsic_clk",
+			.ops = &clk_branch_ops,
+		},
+	},
+};
+
+static struct clk_branch usb_hsic_hsio_cal_clk = {
+	.halt_reg = 0x2fcc,
+	.halt_bit = 23,
+	.hw = {
+		.enable_reg = 0x2b48,
+		.enable_mask = BIT(0),
+		.init = &(struct clk_init_data){
+			.name = "usb_hsic_hsio_cal_clk",
+			.ops = &clk_branch_ops,
+			.flags = CLK_IS_ROOT,
+		},
+	},
+};
+
+static struct clk_rcg usb_fs1_xcvr_fs_src = {
+	.ns_reg = 0x2968,
+	.md_reg = 0x2964,
+	.mn = {
+		.mnctr_en_bit = 8,
+		.mnctr_reset_bit = 7,
+		.mnctr_mode_shift = 5,
+		.n_val_shift = 16,
+		.m_val_shift = 16,
+		.width = 8,
+	},
+	.p = {
+		.pre_div_shift = 3,
+		.pre_div_width = 2,
+	},
+	.s = {
+		.src_sel_shift = 0,
+		.parent_map = gcc_pxo_pll8_map,
+	},
+	.freq_tbl = clk_tbl_usb,
+	.hw = {
+		.enable_reg = 0x2968,
+		.enable_mask = BIT(11),
+		.init = &(struct clk_init_data){
+			.name = "usb_fs1_xcvr_fs_src",
+			.parent_names = gcc_pxo_pll8,
+			.num_parents = 2,
+			.ops = &clk_rcg_ops,
+			.flags = CLK_SET_RATE_GATE,
+		},
+	}
+};
+
+static const char *usb_fs1_xcvr_fs_src_p[] = { "usb_fs1_xcvr_fs_src" };
+
+static struct clk_branch usb_fs1_xcvr_fs_clk = {
+	.halt_reg = 0x2fcc,
+	.halt_bit = 15,
+	.hw = {
+		.enable_reg = 0x2968,
+		.enable_mask = BIT(9),
+		.init = &(struct clk_init_data){
+			.name = "usb_fs1_xcvr_fs_clk",
+			.parent_names = usb_fs1_xcvr_fs_src_p,
+			.num_parents = 1,
+			.ops = &clk_branch_ops,
+			.flags = CLK_SET_RATE_PARENT,
+		},
+	},
+};
+
+static struct clk_branch usb_fs1_system_clk = {
+	.halt_reg = 0x2fcc,
+	.halt_bit = 16,
+	.hw = {
+		.enable_reg = 0x296c,
+		.enable_mask = BIT(4),
+		.init = &(struct clk_init_data){
+			.parent_names = usb_fs1_xcvr_fs_src_p,
+			.num_parents = 1,
+			.name = "usb_fs1_system_clk",
+			.ops = &clk_branch_ops,
+			.flags = CLK_SET_RATE_PARENT,
+		},
+	},
+};
+
+static struct clk_rcg usb_fs2_xcvr_fs_src = {
+	.ns_reg = 0x2988,
+	.md_reg = 0x2984,
+	.mn = {
+		.mnctr_en_bit = 8,
+		.mnctr_reset_bit = 7,
+		.mnctr_mode_shift = 5,
+		.n_val_shift = 16,
+		.m_val_shift = 16,
+		.width = 8,
+	},
+	.p = {
+		.pre_div_shift = 3,
+		.pre_div_width = 2,
+	},
+	.s = {
+		.src_sel_shift = 0,
+		.parent_map = gcc_pxo_pll8_map,
+	},
+	.freq_tbl = clk_tbl_usb,
+	.hw = {
+		.enable_reg = 0x2988,
+		.enable_mask = BIT(11),
+		.init = &(struct clk_init_data){
+			.name = "usb_fs2_xcvr_fs_src",
+			.parent_names = gcc_pxo_pll8,
+			.num_parents = 2,
+			.ops = &clk_rcg_ops,
+			.flags = CLK_SET_RATE_GATE,
+		},
+	}
+};
+
+static const char *usb_fs2_xcvr_fs_src_p[] = { "usb_fs2_xcvr_fs_src" };
+
+static struct clk_branch usb_fs2_xcvr_fs_clk = {
+	.halt_reg = 0x2fcc,
+	.halt_bit = 12,
+	.hw = {
+		.enable_reg = 0x2988,
+		.enable_mask = BIT(9),
+		.init = &(struct clk_init_data){
+			.name = "usb_fs2_xcvr_fs_clk",
+			.parent_names = usb_fs2_xcvr_fs_src_p,
+			.num_parents = 1,
+			.ops = &clk_branch_ops,
+			.flags = CLK_SET_RATE_PARENT,
+		},
+	},
+};
+
+static struct clk_branch usb_fs2_system_clk = {
+	.halt_reg = 0x2fcc,
+	.halt_bit = 13,
+	.hw = {
+		.enable_reg = 0x298c,
+		.enable_mask = BIT(4),
+		.init = &(struct clk_init_data){
+			.name = "usb_fs2_system_clk",
+			.parent_names = usb_fs2_xcvr_fs_src_p,
+			.num_parents = 1,
+			.ops = &clk_branch_ops,
+			.flags = CLK_SET_RATE_PARENT,
+		},
+	},
+};
+
+static struct clk_branch ce1_core_clk = {
+	.hwcg_reg = 0x2724,
+	.hwcg_bit = 6,
+	.halt_reg = 0x2fd4,
+	.halt_bit = 27,
+	.hw = {
+		.enable_reg = 0x2724,
+		.enable_mask = BIT(4),
+		.init = &(struct clk_init_data){
+			.name = "ce1_core_clk",
+			.ops = &clk_branch_ops,
+			.flags = CLK_IS_ROOT,
+		},
+	},
+};
+
+static struct clk_branch ce1_h_clk = {
+	.halt_reg = 0x2fd4,
+	.halt_bit = 1,
+	.hw = {
+		.enable_reg = 0x2720,
+		.enable_mask = BIT(4),
+		.init = &(struct clk_init_data){
+			.name = "ce1_h_clk",
+			.ops = &clk_branch_ops,
+			.flags = CLK_IS_ROOT,
+		},
+	},
+};
+
+static struct clk_branch dma_bam_h_clk = {
+	.hwcg_reg = 0x25c0,
+	.hwcg_bit = 6,
+	.halt_reg = 0x2fc8,
+	.halt_bit = 12,
+	.hw = {
+		.enable_reg = 0x25c0,
+		.enable_mask = BIT(4),
+		.init = &(struct clk_init_data){
+			.name = "dma_bam_h_clk",
+			.ops = &clk_branch_ops,
+			.flags = CLK_IS_ROOT,
+		},
+	},
+};
+
+static struct clk_branch gsbi1_h_clk = {
+	.hwcg_reg = 0x29c0,
+	.hwcg_bit = 6,
+	.halt_reg = 0x2fcc,
+	.halt_bit = 11,
+	.hw = {
+		.enable_reg = 0x29c0,
+		.enable_mask = BIT(4),
+		.init = &(struct clk_init_data){
+			.name = "gsbi1_h_clk",
+			.ops = &clk_branch_ops,
+			.flags = CLK_IS_ROOT,
+		},
+	},
+};
+
+static struct clk_branch gsbi2_h_clk = {
+	.hwcg_reg = 0x29e0,
+	.hwcg_bit = 6,
+	.halt_reg = 0x2fcc,
+	.halt_bit = 7,
+	.hw = {
+		.enable_reg = 0x29e0,
+		.enable_mask = BIT(4),
+		.init = &(struct clk_init_data){
+			.name = "gsbi2_h_clk",
+			.ops = &clk_branch_ops,
+			.flags = CLK_IS_ROOT,
+		},
+	},
+};
+
+static struct clk_branch gsbi3_h_clk = {
+	.hwcg_reg = 0x2a00,
+	.hwcg_bit = 6,
+	.halt_reg = 0x2fcc,
+	.halt_bit = 3,
+	.hw = {
+		.enable_reg = 0x2a00,
+		.enable_mask = BIT(4),
+		.init = &(struct clk_init_data){
+			.name = "gsbi3_h_clk",
+			.ops = &clk_branch_ops,
+			.flags = CLK_IS_ROOT,
+		},
+	},
+};
+
+static struct clk_branch gsbi4_h_clk = {
+	.hwcg_reg = 0x2a20,
+	.hwcg_bit = 6,
+	.halt_reg = 0x2fd0,
+	.halt_bit = 27,
+	.hw = {
+		.enable_reg = 0x2a20,
+		.enable_mask = BIT(4),
+		.init = &(struct clk_init_data){
+			.name = "gsbi4_h_clk",
+			.ops = &clk_branch_ops,
+			.flags = CLK_IS_ROOT,
+		},
+	},
+};
+
+static struct clk_branch gsbi5_h_clk = {
+	.hwcg_reg = 0x2a40,
+	.hwcg_bit = 6,
+	.halt_reg = 0x2fd0,
+	.halt_bit = 23,
+	.hw = {
+		.enable_reg = 0x2a40,
+		.enable_mask = BIT(4),
+		.init = &(struct clk_init_data){
+			.name = "gsbi5_h_clk",
+			.ops = &clk_branch_ops,
+			.flags = CLK_IS_ROOT,
+		},
+	},
+};
+
+static struct clk_branch gsbi6_h_clk = {
+	.hwcg_reg = 0x2a60,
+	.hwcg_bit = 6,
+	.halt_reg = 0x2fd0,
+	.halt_bit = 19,
+	.hw = {
+		.enable_reg = 0x2a60,
+		.enable_mask = BIT(4),
+		.init = &(struct clk_init_data){
+			.name = "gsbi6_h_clk",
+			.ops = &clk_branch_ops,
+			.flags = CLK_IS_ROOT,
+		},
+	},
+};
+
+static struct clk_branch gsbi7_h_clk = {
+	.hwcg_reg = 0x2a80,
+	.hwcg_bit = 6,
+	.halt_reg = 0x2fd0,
+	.halt_bit = 15,
+	.hw = {
+		.enable_reg = 0x2a80,
+		.enable_mask = BIT(4),
+		.init = &(struct clk_init_data){
+			.name = "gsbi7_h_clk",
+			.ops = &clk_branch_ops,
+			.flags = CLK_IS_ROOT,
+		},
+	},
+};
+
+static struct clk_branch gsbi8_h_clk = {
+	.hwcg_reg = 0x2aa0,
+	.hwcg_bit = 6,
+	.halt_reg = 0x2fd0,
+	.halt_bit = 11,
+	.hw = {
+		.enable_reg = 0x2aa0,
+		.enable_mask = BIT(4),
+		.init = &(struct clk_init_data){
+			.name = "gsbi8_h_clk",
+			.ops = &clk_branch_ops,
+			.flags = CLK_IS_ROOT,
+		},
+	},
+};
+
+static struct clk_branch gsbi9_h_clk = {
+	.hwcg_reg = 0x2ac0,
+	.hwcg_bit = 6,
+	.halt_reg = 0x2fd0,
+	.halt_bit = 7,
+	.hw = {
+		.enable_reg = 0x2ac0,
+		.enable_mask = BIT(4),
+		.init = &(struct clk_init_data){
+			.name = "gsbi9_h_clk",
+			.ops = &clk_branch_ops,
+			.flags = CLK_IS_ROOT,
+		},
+	},
+};
+
+static struct clk_branch gsbi10_h_clk = {
+	.hwcg_reg = 0x2ae0,
+	.hwcg_bit = 6,
+	.halt_reg = 0x2fd0,
+	.halt_bit = 3,
+	.hw = {
+		.enable_reg = 0x2ae0,
+		.enable_mask = BIT(4),
+		.init = &(struct clk_init_data){
+			.name = "gsbi10_h_clk",
+			.ops = &clk_branch_ops,
+			.flags = CLK_IS_ROOT,
+		},
+	},
+};
+
+static struct clk_branch gsbi11_h_clk = {
+	.hwcg_reg = 0x2b00,
+	.hwcg_bit = 6,
+	.halt_reg = 0x2fd4,
+	.halt_bit = 18,
+	.hw = {
+		.enable_reg = 0x2b00,
+		.enable_mask = BIT(4),
+		.init = &(struct clk_init_data){
+			.name = "gsbi11_h_clk",
+			.ops = &clk_branch_ops,
+			.flags = CLK_IS_ROOT,
+		},
+	},
+};
+
+static struct clk_branch gsbi12_h_clk = {
+	.hwcg_reg = 0x2b20,
+	.hwcg_bit = 6,
+	.halt_reg = 0x2fd4,
+	.halt_bit = 14,
+	.hw = {
+		.enable_reg = 0x2b20,
+		.enable_mask = BIT(4),
+		.init = &(struct clk_init_data){
+			.name = "gsbi12_h_clk",
+			.ops = &clk_branch_ops,
+			.flags = CLK_IS_ROOT,
+		},
+	},
+};
+
+static struct clk_branch tsif_h_clk = {
+	.hwcg_reg = 0x2700,
+	.hwcg_bit = 6,
+	.halt_reg = 0x2fd4,
+	.halt_bit = 7,
+	.hw = {
+		.enable_reg = 0x2700,
+		.enable_mask = BIT(4),
+		.init = &(struct clk_init_data){
+			.name = "tsif_h_clk",
+			.ops = &clk_branch_ops,
+			.flags = CLK_IS_ROOT,
+		},
+	},
+};
+
+static struct clk_branch usb_fs1_h_clk = {
+	.halt_reg = 0x2fcc,
+	.halt_bit = 17,
+	.hw = {
+		.enable_reg = 0x2960,
+		.enable_mask = BIT(4),
+		.init = &(struct clk_init_data){
+			.name = "usb_fs1_h_clk",
+			.ops = &clk_branch_ops,
+			.flags = CLK_IS_ROOT,
+		},
+	},
+};
+
+static struct clk_branch usb_fs2_h_clk = {
+	.halt_reg = 0x2fcc,
+	.halt_bit = 14,
+	.hw = {
+		.enable_reg = 0x2980,
+		.enable_mask = BIT(4),
+		.init = &(struct clk_init_data){
+			.name = "usb_fs2_h_clk",
+			.ops = &clk_branch_ops,
+			.flags = CLK_IS_ROOT,
+		},
+	},
+};
+
+static struct clk_branch usb_hs1_h_clk = {
+	.hwcg_reg = 0x2900,
+	.hwcg_bit = 6,
+	.halt_reg = 0x2fc8,
+	.halt_bit = 1,
+	.hw = {
+		.enable_reg = 0x2900,
+		.enable_mask = BIT(4),
+		.init = &(struct clk_init_data){
+			.name = "usb_hs1_h_clk",
+			.ops = &clk_branch_ops,
+			.flags = CLK_IS_ROOT,
+		},
+	},
+};
+
+static struct clk_branch usb_hsic_h_clk = {
+	.halt_reg = 0x2fcc,
+	.halt_bit = 28,
+	.hw = {
+		.enable_reg = 0x2920,
+		.enable_mask = BIT(4),
+		.init = &(struct clk_init_data){
+			.name = "usb_hsic_h_clk",
+			.ops = &clk_branch_ops,
+			.flags = CLK_IS_ROOT,
+		},
+	},
+};
+
+static struct clk_branch sdc1_h_clk = {
+	.hwcg_reg = 0x2820,
+	.hwcg_bit = 6,
+	.halt_reg = 0x2fc8,
+	.halt_bit = 11,
+	.hw = {
+		.enable_reg = 0x2820,
+		.enable_mask = BIT(4),
+		.init = &(struct clk_init_data){
+			.name = "sdc1_h_clk",
+			.ops = &clk_branch_ops,
+			.flags = CLK_IS_ROOT,
+		},
+	},
+};
+
+static struct clk_branch sdc2_h_clk = {
+	.hwcg_reg = 0x2840,
+	.hwcg_bit = 6,
+	.halt_reg = 0x2fc8,
+	.halt_bit = 10,
+	.hw = {
+		.enable_reg = 0x2840,
+		.enable_mask = BIT(4),
+		.init = &(struct clk_init_data){
+			.name = "sdc2_h_clk",
+			.ops = &clk_branch_ops,
+			.flags = CLK_IS_ROOT,
+		},
+	},
+};
+
+static struct clk_branch sdc3_h_clk = {
+	.hwcg_reg = 0x2860,
+	.hwcg_bit = 6,
+	.halt_reg = 0x2fc8,
+	.halt_bit = 9,
+	.hw = {
+		.enable_reg = 0x2860,
+		.enable_mask = BIT(4),
+		.init = &(struct clk_init_data){
+			.name = "sdc3_h_clk",
+			.ops = &clk_branch_ops,
+			.flags = CLK_IS_ROOT,
+		},
+	},
+};
+
+static struct clk_branch sdc4_h_clk = {
+	.hwcg_reg = 0x2880,
+	.hwcg_bit = 6,
+	.halt_reg = 0x2fc8,
+	.halt_bit = 8,
+	.hw = {
+		.enable_reg = 0x2880,
+		.enable_mask = BIT(4),
+		.init = &(struct clk_init_data){
+			.name = "sdc4_h_clk",
+			.ops = &clk_branch_ops,
+			.flags = CLK_IS_ROOT,
+		},
+	},
+};
+
+static struct clk_branch sdc5_h_clk = {
+	.hwcg_reg = 0x28a0,
+	.hwcg_bit = 6,
+	.halt_reg = 0x2fc8,
+	.halt_bit = 7,
+	.hw = {
+		.enable_reg = 0x28a0,
+		.enable_mask = BIT(4),
+		.init = &(struct clk_init_data){
+			.name = "sdc5_h_clk",
+			.ops = &clk_branch_ops,
+			.flags = CLK_IS_ROOT,
+		},
+	},
+};
+
+static struct clk_branch adm0_clk = {
+	.halt_reg = 0x2fdc,
+	.halt_check = BRANCH_HALT_VOTED,
+	.halt_bit = 14,
+	.hw = {
+		.enable_reg = 0x3080,
+		.enable_mask = BIT(2),
+		.init = &(struct clk_init_data){
+			.name = "adm0_clk",
+			.ops = &clk_branch_ops,
+			.flags = CLK_IS_ROOT,
+		},
+	},
+};
+
+static struct clk_branch adm0_pbus_clk = {
+	.hwcg_reg = 0x2208,
+	.hwcg_bit = 6,
+	.halt_reg = 0x2fdc,
+	.halt_check = BRANCH_HALT_VOTED,
+	.halt_bit = 13,
+	.hw = {
+		.enable_reg = 0x3080,
+		.enable_mask = BIT(3),
+		.init = &(struct clk_init_data){
+			.name = "adm0_pbus_clk",
+			.ops = &clk_branch_ops,
+			.flags = CLK_IS_ROOT,
+		},
+	},
+};
+
+static struct clk_branch pmic_arb0_h_clk = {
+	.halt_reg = 0x2fd8,
+	.halt_check = BRANCH_HALT_VOTED,
+	.halt_bit = 22,
+	.hw = {
+		.enable_reg = 0x3080,
+		.enable_mask = BIT(8),
+		.init = &(struct clk_init_data){
+			.name = "pmic_arb0_h_clk",
+			.ops = &clk_branch_ops,
+			.flags = CLK_IS_ROOT,
+		},
+	},
+};
+
+static struct clk_branch pmic_arb1_h_clk = {
+	.halt_reg = 0x2fd8,
+	.halt_check = BRANCH_HALT_VOTED,
+	.halt_bit = 21,
+	.hw = {
+		.enable_reg = 0x3080,
+		.enable_mask = BIT(9),
+		.init = &(struct clk_init_data){
+			.name = "pmic_arb1_h_clk",
+			.ops = &clk_branch_ops,
+			.flags = CLK_IS_ROOT,
+		},
+	},
+};
+
+static struct clk_branch pmic_ssbi2_clk = {
+	.halt_reg = 0x2fd8,
+	.halt_check = BRANCH_HALT_VOTED,
+	.halt_bit = 23,
+	.hw = {
+		.enable_reg = 0x3080,
+		.enable_mask = BIT(7),
+		.init = &(struct clk_init_data){
+			.name = "pmic_ssbi2_clk",
+			.ops = &clk_branch_ops,
+			.flags = CLK_IS_ROOT,
+		},
+	},
+};
+
+static struct clk_branch rpm_msg_ram_h_clk = {
+	.hwcg_reg = 0x27e0,
+	.hwcg_bit = 6,
+	.halt_reg = 0x2fd8,
+	.halt_check = BRANCH_HALT_VOTED,
+	.halt_bit = 12,
+	.hw = {
+		.enable_reg = 0x3080,
+		.enable_mask = BIT(6),
+		.init = &(struct clk_init_data){
+			.name = "rpm_msg_ram_h_clk",
+			.ops = &clk_branch_ops,
+			.flags = CLK_IS_ROOT,
+		},
+	},
+};
+
+static struct clk_hw *gcc_msm8960_clks[] = {
+	[PLL3] = &pll3.hw,
+	[PLL8] = &pll8.hw,
+	[PLL8_VOTE] = &pll8_vote,
+	[PLL14] = &pll14.hw,
+	[PLL14_VOTE] = &pll14_vote,
+	[GSBI1_UART_SRC] = &gsbi1_uart_src.hw,
+	[GSBI1_UART_CLK] = &gsbi1_uart_clk.hw,
+	[GSBI2_UART_SRC] = &gsbi2_uart_src.hw,
+	[GSBI2_UART_CLK] = &gsbi2_uart_clk.hw,
+	[GSBI3_UART_SRC] = &gsbi3_uart_src.hw,
+	[GSBI3_UART_CLK] = &gsbi3_uart_clk.hw,
+	[GSBI4_UART_SRC] = &gsbi4_uart_src.hw,
+	[GSBI4_UART_CLK] = &gsbi4_uart_clk.hw,
+	[GSBI5_UART_SRC] = &gsbi5_uart_src.hw,
+	[GSBI5_UART_CLK] = &gsbi5_uart_clk.hw,
+	[GSBI6_UART_SRC] = &gsbi6_uart_src.hw,
+	[GSBI6_UART_CLK] = &gsbi6_uart_clk.hw,
+	[GSBI7_UART_SRC] = &gsbi7_uart_src.hw,
+	[GSBI7_UART_CLK] = &gsbi7_uart_clk.hw,
+	[GSBI8_UART_SRC] = &gsbi8_uart_src.hw,
+	[GSBI8_UART_CLK] = &gsbi8_uart_clk.hw,
+	[GSBI9_UART_SRC] = &gsbi9_uart_src.hw,
+	[GSBI9_UART_CLK] = &gsbi9_uart_clk.hw,
+	[GSBI10_UART_SRC] = &gsbi10_uart_src.hw,
+	[GSBI10_UART_CLK] = &gsbi10_uart_clk.hw,
+	[GSBI11_UART_SRC] = &gsbi11_uart_src.hw,
+	[GSBI11_UART_CLK] = &gsbi11_uart_clk.hw,
+	[GSBI12_UART_SRC] = &gsbi12_uart_src.hw,
+	[GSBI12_UART_CLK] = &gsbi12_uart_clk.hw,
+	[GSBI1_QUP_SRC] = &gsbi1_qup_src.hw,
+	[GSBI1_QUP_CLK] = &gsbi1_qup_clk.hw,
+	[GSBI2_QUP_SRC] = &gsbi2_qup_src.hw,
+	[GSBI2_QUP_CLK] = &gsbi2_qup_clk.hw,
+	[GSBI3_QUP_SRC] = &gsbi3_qup_src.hw,
+	[GSBI3_QUP_CLK] = &gsbi3_qup_clk.hw,
+	[GSBI4_QUP_SRC] = &gsbi4_qup_src.hw,
+	[GSBI4_QUP_CLK] = &gsbi4_qup_clk.hw,
+	[GSBI5_QUP_SRC] = &gsbi5_qup_src.hw,
+	[GSBI5_QUP_CLK] = &gsbi5_qup_clk.hw,
+	[GSBI6_QUP_SRC] = &gsbi6_qup_src.hw,
+	[GSBI6_QUP_CLK] = &gsbi6_qup_clk.hw,
+	[GSBI7_QUP_SRC] = &gsbi7_qup_src.hw,
+	[GSBI7_QUP_CLK] = &gsbi7_qup_clk.hw,
+	[GSBI8_QUP_SRC] = &gsbi8_qup_src.hw,
+	[GSBI8_QUP_CLK] = &gsbi8_qup_clk.hw,
+	[GSBI9_QUP_SRC] = &gsbi9_qup_src.hw,
+	[GSBI9_QUP_CLK] = &gsbi9_qup_clk.hw,
+	[GSBI10_QUP_SRC] = &gsbi10_qup_src.hw,
+	[GSBI10_QUP_CLK] = &gsbi10_qup_clk.hw,
+	[GSBI11_QUP_SRC] = &gsbi11_qup_src.hw,
+	[GSBI11_QUP_CLK] = &gsbi11_qup_clk.hw,
+	[GSBI12_QUP_SRC] = &gsbi12_qup_src.hw,
+	[GSBI12_QUP_CLK] = &gsbi12_qup_clk.hw,
+	[GP0_SRC] = &gp0_src.hw,
+	[GP0_CLK] = &gp0_clk.hw,
+	[GP1_SRC] = &gp1_src.hw,
+	[GP1_CLK] = &gp1_clk.hw,
+	[GP2_SRC] = &gp2_src.hw,
+	[GP2_CLK] = &gp2_clk.hw,
+	[PMEM_A_CLK] = &pmem_clk.hw,
+	[PRNG_SRC] = &prng_src.hw,
+	[PRNG_CLK] = &prng_clk.hw,
+	[SDC1_SRC] = &sdc1_src.hw,
+	[SDC1_CLK] = &sdc1_clk.hw,
+	[SDC2_SRC] = &sdc2_src.hw,
+	[SDC2_CLK] = &sdc2_clk.hw,
+	[SDC3_SRC] = &sdc3_src.hw,
+	[SDC3_CLK] = &sdc3_clk.hw,
+	[SDC4_SRC] = &sdc4_src.hw,
+	[SDC4_CLK] = &sdc4_clk.hw,
+	[SDC5_SRC] = &sdc5_src.hw,
+	[SDC5_CLK] = &sdc5_clk.hw,
+	[TSIF_REF_SRC] = &tsif_ref_src.hw,
+	[TSIF_REF_CLK] = &tsif_ref_clk.hw,
+	[USB_HS1_XCVR_SRC] = &usb_hs1_xcvr_src.hw,
+	[USB_HS1_XCVR_CLK] = &usb_hs1_xcvr_clk.hw,
+	[USB_HSIC_XCVR_FS_SRC] = &usb_hsic_xcvr_fs_src.hw,
+	[USB_HSIC_XCVR_FS_CLK] = &usb_hsic_xcvr_fs_clk.hw,
+	[USB_HSIC_SYSTEM_CLK] = &usb_hsic_system_clk.hw,
+	[USB_HSIC_HSIC_CLK] = &usb_hsic_hsic_clk.hw,
+	[USB_HSIC_HSIO_CAL_CLK] = &usb_hsic_hsio_cal_clk.hw,
+	[USB_FS1_XCVR_FS_SRC] = &usb_fs1_xcvr_fs_src.hw,
+	[USB_FS1_XCVR_FS_CLK] = &usb_fs1_xcvr_fs_clk.hw,
+	[USB_FS1_SYSTEM_CLK] = &usb_fs1_system_clk.hw,
+	[USB_FS2_XCVR_FS_SRC] = &usb_fs2_xcvr_fs_src.hw,
+	[USB_FS2_XCVR_FS_CLK] = &usb_fs2_xcvr_fs_clk.hw,
+	[USB_FS2_SYSTEM_CLK] = &usb_fs2_system_clk.hw,
+	[CE1_CORE_CLK] = &ce1_core_clk.hw,
+	[CE1_H_CLK] = &ce1_h_clk.hw,
+	[DMA_BAM_H_CLK] = &dma_bam_h_clk.hw,
+	[GSBI1_H_CLK] = &gsbi1_h_clk.hw,
+	[GSBI2_H_CLK] = &gsbi2_h_clk.hw,
+	[GSBI3_H_CLK] = &gsbi3_h_clk.hw,
+	[GSBI4_H_CLK] = &gsbi4_h_clk.hw,
+	[GSBI5_H_CLK] = &gsbi5_h_clk.hw,
+	[GSBI6_H_CLK] = &gsbi6_h_clk.hw,
+	[GSBI7_H_CLK] = &gsbi7_h_clk.hw,
+	[GSBI8_H_CLK] = &gsbi8_h_clk.hw,
+	[GSBI9_H_CLK] = &gsbi9_h_clk.hw,
+	[GSBI10_H_CLK] = &gsbi10_h_clk.hw,
+	[GSBI11_H_CLK] = &gsbi11_h_clk.hw,
+	[GSBI12_H_CLK] = &gsbi12_h_clk.hw,
+	[TSIF_H_CLK] = &tsif_h_clk.hw,
+	[USB_FS1_H_CLK] = &usb_fs1_h_clk.hw,
+	[USB_FS2_H_CLK] = &usb_fs2_h_clk.hw,
+	[USB_HS1_H_CLK] = &usb_hs1_h_clk.hw,
+	[USB_HSIC_H_CLK] = &usb_hsic_h_clk.hw,
+	[SDC1_H_CLK] = &sdc1_h_clk.hw,
+	[SDC2_H_CLK] = &sdc2_h_clk.hw,
+	[SDC3_H_CLK] = &sdc3_h_clk.hw,
+	[SDC4_H_CLK] = &sdc4_h_clk.hw,
+	[SDC5_H_CLK] = &sdc5_h_clk.hw,
+	[ADM0_CLK] = &adm0_clk.hw,
+	[ADM0_PBUS_CLK] = &adm0_pbus_clk.hw,
+	[PMIC_ARB0_H_CLK] = &pmic_arb0_h_clk.hw,
+	[PMIC_ARB1_H_CLK] = &pmic_arb1_h_clk.hw,
+	[PMIC_SSBI2_CLK] = &pmic_ssbi2_clk.hw,
+	[RPM_MSG_RAM_H_CLK] = &rpm_msg_ram_h_clk.hw,
+};
+
+static const struct qcom_reset_map gcc_msm8960_resets[] = {
+	[SFAB_MSS_Q6_SW_RESET] = { 0x2040, 7 },
+	[SFAB_MSS_Q6_FW_RESET] = { 0x2044, 7 },
+	[QDSS_STM_RESET] = { 0x2060, 6 },
+	[AFAB_SMPSS_S_RESET] = { 0x20b8, 2 },
+	[AFAB_SMPSS_M1_RESET] = { 0x20b8, 1 },
+	[AFAB_SMPSS_M0_RESET] = { 0x20b8 },
+	[AFAB_EBI1_CH0_RESET] = { 0x20c0, 7 },
+	[AFAB_EBI1_CH1_RESET] = { 0x20c4, 7},
+	[SFAB_ADM0_M0_RESET] = { 0x21e0, 7 },
+	[SFAB_ADM0_M1_RESET] = { 0x21e4, 7 },
+	[SFAB_ADM0_M2_RESET] = { 0x21e8, 7 },
+	[ADM0_C2_RESET] = { 0x220c, 4},
+	[ADM0_C1_RESET] = { 0x220c, 3},
+	[ADM0_C0_RESET] = { 0x220c, 2},
+	[ADM0_PBUS_RESET] = { 0x220c, 1 },
+	[ADM0_RESET] = { 0x220c },
+	[QDSS_CLKS_SW_RESET] = { 0x2260, 5 },
+	[QDSS_POR_RESET] = { 0x2260, 4 },
+	[QDSS_TSCTR_RESET] = { 0x2260, 3 },
+	[QDSS_HRESET_RESET] = { 0x2260, 2 },
+	[QDSS_AXI_RESET] = { 0x2260, 1 },
+	[QDSS_DBG_RESET] = { 0x2260 },
+	[PCIE_A_RESET] = { 0x22c0, 7 },
+	[PCIE_AUX_RESET] = { 0x22c8, 7 },
+	[PCIE_H_RESET] = { 0x22d0, 7 },
+	[SFAB_PCIE_M_RESET] = { 0x22d4, 1 },
+	[SFAB_PCIE_S_RESET] = { 0x22d4 },
+	[SFAB_MSS_M_RESET] = { 0x2340, 7 },
+	[SFAB_USB3_M_RESET] = { 0x2360, 7 },
+	[SFAB_RIVA_M_RESET] = { 0x2380, 7 },
+	[SFAB_LPASS_RESET] = { 0x23a0, 7 },
+	[SFAB_AFAB_M_RESET] = { 0x23e0, 7 },
+	[AFAB_SFAB_M0_RESET] = { 0x2420, 7 },
+	[AFAB_SFAB_M1_RESET] = { 0x2424, 7 },
+	[SFAB_SATA_S_RESET] = { 0x2480, 7 },
+	[SFAB_DFAB_M_RESET] = { 0x2500, 7 },
+	[DFAB_SFAB_M_RESET] = { 0x2520, 7 },
+	[DFAB_SWAY0_RESET] = { 0x2540, 7 },
+	[DFAB_SWAY1_RESET] = { 0x2544, 7 },
+	[DFAB_ARB0_RESET] = { 0x2560, 7 },
+	[DFAB_ARB1_RESET] = { 0x2564, 7 },
+	[PPSS_PROC_RESET] = { 0x2594, 1 },
+	[PPSS_RESET] = { 0x2594},
+	[DMA_BAM_RESET] = { 0x25c0, 7 },
+	[SIC_TIC_RESET] = { 0x2600, 7 },
+	[SLIMBUS_H_RESET] = { 0x2620, 7 },
+	[SFAB_CFPB_M_RESET] = { 0x2680, 7 },
+	[SFAB_CFPB_S_RESET] = { 0x26c0, 7 },
+	[TSIF_H_RESET] = { 0x2700, 7 },
+	[CE1_H_RESET] = { 0x2720, 7 },
+	[CE1_CORE_RESET] = { 0x2724, 7 },
+	[CE1_SLEEP_RESET] = { 0x2728, 7 },
+	[CE2_H_RESET] = { 0x2740, 7 },
+	[CE2_CORE_RESET] = { 0x2744, 7 },
+	[SFAB_SFPB_M_RESET] = { 0x2780, 7 },
+	[SFAB_SFPB_S_RESET] = { 0x27a0, 7 },
+	[RPM_PROC_RESET] = { 0x27c0, 7 },
+	[PMIC_SSBI2_RESET] = { 0x270c, 12 },
+	[SDC1_RESET] = { 0x2830 },
+	[SDC2_RESET] = { 0x2850 },
+	[SDC3_RESET] = { 0x2870 },
+	[SDC4_RESET] = { 0x2890 },
+	[SDC5_RESET] = { 0x28b0 },
+	[DFAB_A2_RESET] = { 0x28c0, 7 },
+	[USB_HS1_RESET] = { 0x2910 },
+	[USB_HSIC_RESET] = { 0x2934 },
+	[USB_FS1_XCVR_RESET] = { 0x2974, 1 },
+	[USB_FS1_RESET] = { 0x2974 },
+	[USB_FS2_XCVR_RESET] = { 0x2994, 1 },
+	[USB_FS2_RESET] = { 0x2994 },
+	[GSBI1_RESET] = { 0x29dc },
+	[GSBI2_RESET] = { 0x29fc },
+	[GSBI3_RESET] = { 0x2a1c },
+	[GSBI4_RESET] = { 0x2a3c },
+	[GSBI5_RESET] = { 0x2a5c },
+	[GSBI6_RESET] = { 0x2a7c },
+	[GSBI7_RESET] = { 0x2a9c },
+	[GSBI8_RESET] = { 0x2abc },
+	[GSBI9_RESET] = { 0x2adc },
+	[GSBI10_RESET] = { 0x2afc },
+	[GSBI11_RESET] = { 0x2b1c },
+	[GSBI12_RESET] = { 0x2b3c },
+	[SPDM_RESET] = { 0x2b6c },
+	[TLMM_H_RESET] = { 0x2ba0, 7 },
+	[SFAB_MSS_S_RESET] = { 0x2c00, 7 },
+	[MSS_SLP_RESET] = { 0x2c60, 7 },
+	[MSS_Q6SW_JTAG_RESET] = { 0x2c68, 7 },
+	[MSS_Q6FW_JTAG_RESET] = { 0x2c6c, 7 },
+	[MSS_RESET] = { 0x2c64 },
+	[SATA_H_RESET] = { 0x2c80, 7 },
+	[SATA_RXOOB_RESE] = { 0x2c8c, 7 },
+	[SATA_PMALIVE_RESET] = { 0x2c90, 7 },
+	[SATA_SFAB_M_RESET] = { 0x2c98, 7 },
+	[TSSC_RESET] = { 0x2ca0, 7 },
+	[PDM_RESET] = { 0x2cc0, 12 },
+	[MPM_H_RESET] = { 0x2da0, 7 },
+	[MPM_RESET] = { 0x2da4 },
+	[SFAB_SMPSS_S_RESET] = { 0x2e00, 7 },
+	[PRNG_RESET] = { 0x2e80, 12 },
+	[RIVA_RESET] = { 0x35e0 },
+};
+
+static const struct regmap_config gcc_msm8960_regmap_config = {
+	.reg_bits	= 32,
+	.reg_stride	= 4,
+	.val_bits	= 32,
+	.max_register	= 0x3660,
+	.fast_io	= true,
+};
+
+static const struct of_device_id gcc_msm8960_match_table[] = {
+	{ .compatible = "qcom,gcc-msm8960" },
+	{ }
+};
+MODULE_DEVICE_TABLE(of, gcc_msm8960_match_table);
+
+struct qcom_cc {
+	struct qcom_reset_controller reset;
+	struct clk_onecell_data data;
+	struct clk *clks[];
+};
+
+static int gcc_msm8960_probe(struct platform_device *pdev)
+{
+	void __iomem *base;
+	struct resource *res;
+	int i, ret;
+	struct device *dev = &pdev->dev;
+	struct clk *clk;
+	struct clk_onecell_data *data;
+	struct clk **clks;
+	struct regmap *regmap;
+	size_t num_clks;
+	struct qcom_reset_controller *reset;
+	struct qcom_cc *cc;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	base = devm_ioremap_resource(dev, res);
+	if (IS_ERR(base))
+		return PTR_ERR(base);
+
+	regmap = devm_regmap_init_mmio(dev, base, &gcc_msm8960_regmap_config);
+	if (IS_ERR(regmap))
+		return PTR_ERR(regmap);
+
+	num_clks = ARRAY_SIZE(gcc_msm8960_clks);
+	cc = devm_kzalloc(dev, sizeof(*cc) + sizeof(*clks) * num_clks,
+			  GFP_KERNEL);
+	if (!cc)
+		return -ENOMEM;
+
+	clks = cc->clks;
+	data = &cc->data;
+	data->clks = clks;
+	data->clk_num = num_clks;
+
+	/* Temporary until RPM clocks supported */
+	clk = clk_register_fixed_rate(dev, "cxo", NULL, CLK_IS_ROOT, 19200000);
+	if (IS_ERR(clk))
+		return PTR_ERR(clk);
+
+	clk = clk_register_fixed_rate(dev, "pxo", NULL, CLK_IS_ROOT, 27000000);
+	if (IS_ERR(clk))
+		return PTR_ERR(clk);
+
+	for (i = 0; i < num_clks; i++) {
+		if (!gcc_msm8960_clks[i])
+			continue;
+		clk = devm_clk_register(dev, gcc_msm8960_clks[i]);
+		if (IS_ERR(clk))
+			return PTR_ERR(clk);
+		clks[i] = clk;
+	}
+
+	ret = of_clk_add_provider(dev->of_node, of_clk_src_onecell_get, data);
+	if (ret)
+		return ret;
+
+	reset = &cc->reset;
+	reset->rcdev.of_node = dev->of_node;
+	reset->rcdev.ops = &qcom_reset_ops,
+	reset->rcdev.owner = THIS_MODULE,
+	reset->rcdev.nr_resets = ARRAY_SIZE(gcc_msm8960_resets),
+	reset->regmap = regmap;
+	reset->reset_map = gcc_msm8960_resets,
+	platform_set_drvdata(pdev, &reset->rcdev);
+
+	ret = reset_controller_register(&reset->rcdev);
+	if (ret)
+		of_clk_del_provider(dev->of_node);
+
+	return ret;
+}
+
+static int gcc_msm8960_remove(struct platform_device *pdev)
+{
+	of_clk_del_provider(pdev->dev.of_node);
+	reset_controller_unregister(platform_get_drvdata(pdev));
+	return 0;
+}
+
+static struct platform_driver gcc_msm8960_driver = {
+	.probe		= gcc_msm8960_probe,
+	.remove		= gcc_msm8960_remove,
+	.driver		= {
+		.name	= "gcc-msm8960",
+		.owner	= THIS_MODULE,
+		.of_match_table = gcc_msm8960_match_table,
+	},
+};
+
+static int __init gcc_msm8960_init(void)
+{
+	return platform_driver_register(&gcc_msm8960_driver);
+}
+core_initcall(gcc_msm8960_init);
+
+static void __exit gcc_msm8960_exit(void)
+{
+	platform_driver_unregister(&gcc_msm8960_driver);
+}
+module_exit(gcc_msm8960_exit);
+
+MODULE_DESCRIPTION("QCOM GCC MSM8960 Driver");
+MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("platform:gcc-msm8960");
diff --git a/include/dt-bindings/clock/qcom,gcc-msm8960.h b/include/dt-bindings/clock/qcom,gcc-msm8960.h
new file mode 100644
index 0000000..03bbf49
--- /dev/null
+++ b/include/dt-bindings/clock/qcom,gcc-msm8960.h
@@ -0,0 +1,313 @@
+/*
+ * Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef _DT_BINDINGS_CLK_MSM_GCC_8960_H
+#define _DT_BINDINGS_CLK_MSM_GCC_8960_H
+
+#define AFAB_CLK_SRC				0
+#define AFAB_CORE_CLK				1
+#define SFAB_MSS_Q6_SW_A_CLK			2
+#define SFAB_MSS_Q6_FW_A_CLK			3
+#define QDSS_STM_CLK				4
+#define SCSS_A_CLK				5
+#define SCSS_H_CLK				6
+#define SCSS_XO_SRC_CLK				7
+#define AFAB_EBI1_CH0_A_CLK			8
+#define AFAB_EBI1_CH1_A_CLK			9
+#define AFAB_AXI_S0_FCLK			10
+#define AFAB_AXI_S1_FCLK			11
+#define AFAB_AXI_S2_FCLK			12
+#define AFAB_AXI_S3_FCLK			13
+#define AFAB_AXI_S4_FCLK			14
+#define SFAB_CORE_CLK				15
+#define SFAB_AXI_S0_FCLK			16
+#define SFAB_AXI_S1_FCLK			17
+#define SFAB_AXI_S2_FCLK			18
+#define SFAB_AXI_S3_FCLK			19
+#define SFAB_AXI_S4_FCLK			20
+#define SFAB_AHB_S0_FCLK			21
+#define SFAB_AHB_S1_FCLK			22
+#define SFAB_AHB_S2_FCLK			23
+#define SFAB_AHB_S3_FCLK			24
+#define SFAB_AHB_S4_FCLK			25
+#define SFAB_AHB_S5_FCLK			26
+#define SFAB_AHB_S6_FCLK			27
+#define SFAB_AHB_S7_FCLK			28
+#define QDSS_AT_CLK_SRC				29
+#define QDSS_AT_CLK				30
+#define QDSS_TRACECLKIN_CLK_SRC			31
+#define QDSS_TRACECLKIN_CLK			32
+#define QDSS_TSCTR_CLK_SRC			33
+#define QDSS_TSCTR_CLK				34
+#define SFAB_ADM0_M0_A_CLK			35
+#define SFAB_ADM0_M1_A_CLK			36
+#define SFAB_ADM0_M2_A_CLK			37
+#define ADM0_CLK				38
+#define ADM0_PBUS_CLK				39
+#define MSS_XPU_CLK				40
+#define IMEM0_A_CLK				41
+#define QDSS_H_CLK				42
+#define PCIE_A_CLK				43
+#define PCIE_AUX_CLK				44
+#define PCIE_PHY_REF_CLK			45
+#define PCIE_H_CLK				46
+#define SFAB_CLK_SRC				47
+#define MAHB0_CLK				48
+#define Q6SW_CLK_SRC				49
+#define Q6SW_CLK				50
+#define Q6FW_CLK_SRC				51
+#define Q6FW_CLK				52
+#define SFAB_MSS_M_A_CLK			53
+#define SFAB_USB3_M_A_CLK			54
+#define SFAB_LPASS_Q6_A_CLK			55
+#define SFAB_AFAB_M_A_CLK			56
+#define AFAB_SFAB_M0_A_CLK			57
+#define AFAB_SFAB_M1_A_CLK			58
+#define SFAB_SATA_S_H_CLK			59
+#define DFAB_CLK_SRC				60
+#define DFAB_CLK				61
+#define SFAB_DFAB_M_A_CLK			62
+#define DFAB_SFAB_M_A_CLK			63
+#define DFAB_SWAY0_H_CLK			64
+#define DFAB_SWAY1_H_CLK			65
+#define DFAB_ARB0_H_CLK				66
+#define DFAB_ARB1_H_CLK				67
+#define PPSS_H_CLK				68
+#define PPSS_PROC_CLK				69
+#define PPSS_TIMER0_CLK				70
+#define PPSS_TIMER1_CLK				71
+#define PMEM_A_CLK				72
+#define DMA_BAM_H_CLK				73
+#define SIC_H_CLK				74
+#define SPS_TIC_H_CLK				75
+#define SLIMBUS_H_CLK				76
+#define SLIMBUS_XO_SRC_CLK			77
+#define CFPB_2X_CLK_SRC				78
+#define CFPB_CLK				79
+#define CFPB0_H_CLK				80
+#define CFPB1_H_CLK				81
+#define CFPB2_H_CLK				82
+#define SFAB_CFPB_M_H_CLK			83
+#define CFPB_MASTER_H_CLK			84
+#define SFAB_CFPB_S_HCLK			85
+#define CFPB_SPLITTER_H_CLK			86
+#define TSIF_H_CLK				87
+#define TSIF_INACTIVITY_TIMERS_CLK		88
+#define TSIF_REF_SRC				89
+#define TSIF_REF_CLK				90
+#define CE1_H_CLK				91
+#define CE1_CORE_CLK				92
+#define CE1_SLEEP_CLK				93
+#define CE2_H_CLK				94
+#define CE2_CORE_CLK				95
+#define CE2_SLEEP_CLK				96
+#define SFPB_H_CLK_SRC				97
+#define SFPB_H_CLK				98
+#define SFAB_SFPB_M_H_CLK			99
+#define SFAB_SFPB_S_H_CLK			100
+#define RPM_PROC_CLK				101
+#define RPM_BUS_H_CLK				102
+#define RPM_SLEEP_CLK				103
+#define RPM_TIMER_CLK				104
+#define RPM_MSG_RAM_H_CLK			105
+#define PMIC_ARB0_H_CLK				106
+#define PMIC_ARB1_H_CLK				107
+#define PMIC_SSBI2_SRC				108
+#define PMIC_SSBI2_CLK				109
+#define SDC1_H_CLK				110
+#define SDC2_H_CLK				111
+#define SDC3_H_CLK				112
+#define SDC4_H_CLK				113
+#define SDC5_H_CLK				114
+#define SDC1_SRC				115
+#define SDC2_SRC				116
+#define SDC3_SRC				117
+#define SDC4_SRC				118
+#define SDC5_SRC				119
+#define SDC1_CLK				120
+#define SDC2_CLK				121
+#define SDC3_CLK				122
+#define SDC4_CLK				123
+#define SDC5_CLK				124
+#define DFAB_A2_H_CLK				125
+#define USB_HS1_H_CLK				126
+#define USB_HS1_XCVR_SRC			127
+#define USB_HS1_XCVR_CLK			128
+#define USB_HSIC_H_CLK				129
+#define USB_HSIC_XCVR_FS_SRC			130
+#define USB_HSIC_XCVR_FS_CLK			131
+#define USB_HSIC_SYSTEM_CLK_SRC			132
+#define USB_HSIC_SYSTEM_CLK			133
+#define CFPB0_C0_H_CLK				134
+#define CFPB0_C1_H_CLK				135
+#define CFPB0_D0_H_CLK				136
+#define CFPB0_D1_H_CLK				137
+#define USB_FS1_H_CLK				138
+#define USB_FS1_XCVR_FS_SRC			139
+#define USB_FS1_XCVR_FS_CLK			140
+#define USB_FS1_SYSTEM_CLK			141
+#define USB_FS2_H_CLK				142
+#define USB_FS2_XCVR_FS_SRC			143
+#define USB_FS2_XCVR_FS_CLK			144
+#define USB_FS2_SYSTEM_CLK			145
+#define GSBI_COMMON_SIM_SRC			146
+#define GSBI1_H_CLK				147
+#define GSBI2_H_CLK				148
+#define GSBI3_H_CLK				149
+#define GSBI4_H_CLK				150
+#define GSBI5_H_CLK				151
+#define GSBI6_H_CLK				152
+#define GSBI7_H_CLK				153
+#define GSBI8_H_CLK				154
+#define GSBI9_H_CLK				155
+#define GSBI10_H_CLK				156
+#define GSBI11_H_CLK				157
+#define GSBI12_H_CLK				158
+#define GSBI1_UART_SRC				159
+#define GSBI1_UART_CLK				160
+#define GSBI2_UART_SRC				161
+#define GSBI2_UART_CLK				162
+#define GSBI3_UART_SRC				163
+#define GSBI3_UART_CLK				164
+#define GSBI4_UART_SRC				165
+#define GSBI4_UART_CLK				166
+#define GSBI5_UART_SRC				167
+#define GSBI5_UART_CLK				168
+#define GSBI6_UART_SRC				169
+#define GSBI6_UART_CLK				170
+#define GSBI7_UART_SRC				171
+#define GSBI7_UART_CLK				172
+#define GSBI8_UART_SRC				173
+#define GSBI8_UART_CLK				174
+#define GSBI9_UART_SRC				175
+#define GSBI9_UART_CLK				176
+#define GSBI10_UART_SRC				177
+#define GSBI10_UART_CLK				178
+#define GSBI11_UART_SRC				179
+#define GSBI11_UART_CLK				180
+#define GSBI12_UART_SRC				181
+#define GSBI12_UART_CLK				182
+#define GSBI1_QUP_SRC				183
+#define GSBI1_QUP_CLK				184
+#define GSBI2_QUP_SRC				185
+#define GSBI2_QUP_CLK				186
+#define GSBI3_QUP_SRC				187
+#define GSBI3_QUP_CLK				188
+#define GSBI4_QUP_SRC				189
+#define GSBI4_QUP_CLK				190
+#define GSBI5_QUP_SRC				191
+#define GSBI5_QUP_CLK				192
+#define GSBI6_QUP_SRC				193
+#define GSBI6_QUP_CLK				194
+#define GSBI7_QUP_SRC				195
+#define GSBI7_QUP_CLK				196
+#define GSBI8_QUP_SRC				197
+#define GSBI8_QUP_CLK				198
+#define GSBI9_QUP_SRC				199
+#define GSBI9_QUP_CLK				200
+#define GSBI10_QUP_SRC				201
+#define GSBI10_QUP_CLK				202
+#define GSBI11_QUP_SRC				203
+#define GSBI11_QUP_CLK				204
+#define GSBI12_QUP_SRC				205
+#define GSBI12_QUP_CLK				206
+#define GSBI1_SIM_CLK				207
+#define GSBI2_SIM_CLK				208
+#define GSBI3_SIM_CLK				209
+#define GSBI4_SIM_CLK				210
+#define GSBI5_SIM_CLK				211
+#define GSBI6_SIM_CLK				212
+#define GSBI7_SIM_CLK				213
+#define GSBI8_SIM_CLK				214
+#define GSBI9_SIM_CLK				215
+#define GSBI10_SIM_CLK				216
+#define GSBI11_SIM_CLK				217
+#define GSBI12_SIM_CLK				218
+#define USB_HSIC_HSIC_CLK_SRC			219
+#define USB_HSIC_HSIC_CLK			220
+#define USB_HSIC_HSIO_CAL_CLK			221
+#define SPDM_CFG_H_CLK				222
+#define SPDM_MSTR_H_CLK				223
+#define SPDM_FF_CLK_SRC				224
+#define SPDM_FF_CLK				225
+#define SEC_CTRL_CLK				226
+#define SEC_CTRL_ACC_CLK_SRC			227
+#define SEC_CTRL_ACC_CLK			228
+#define TLMM_H_CLK				229
+#define TLMM_CLK				230
+#define SFAB_MSS_S_H_CLK			231
+#define MSS_SLP_CLK				232
+#define MSS_Q6SW_JTAG_CLK			233
+#define MSS_Q6FW_JTAG_CLK			234
+#define MSS_S_H_CLK				235
+#define MSS_CXO_SRC_CLK				236
+#define SATA_H_CLK				237
+#define SATA_SRC_CLK				238
+#define SATA_RXOOB_CLK				239
+#define SATA_PMALIVE_CLK			240
+#define SATA_PHY_REF_CLK			241
+#define TSSC_CLK_SRC				242
+#define TSSC_CLK				243
+#define PDM_SRC					244
+#define PDM_CLK					245
+#define GP0_SRC					246
+#define GP0_CLK					247
+#define GP1_SRC					248
+#define GP1_CLK					249
+#define GP2_SRC					250
+#define GP2_CLK					251
+#define MPM_CLK					252
+#define EBI1_CLK_SRC				253
+#define EBI1_CH0_CLK				254
+#define EBI1_CH1_CLK				255
+#define EBI1_2X_CLK				256
+#define EBI1_CH0_DQ_CLK				257
+#define EBI1_CH1_DQ_CLK				258
+#define EBI1_CH0_CA_CLK				259
+#define EBI1_CH1_CA_CLK				260
+#define EBI1_XO_CLK				261
+#define SFAB_SMPSS_S_H_CLK			262
+#define PRNG_SRC				263
+#define PRNG_CLK				264
+#define PXO_SRC					265
+#define LPASS_CXO_CLK				266
+#define LPASS_PXO_CLK				267
+#define SPDM_CY_PORT0_CLK			268
+#define SPDM_CY_PORT1_CLK			269
+#define SPDM_CY_PORT2_CLK			270
+#define SPDM_CY_PORT3_CLK			271
+#define SPDM_CY_PORT4_CLK			272
+#define SPDM_CY_PORT5_CLK			273
+#define SPDM_CY_PORT6_CLK			274
+#define SPDM_CY_PORT7_CLK			275
+#define PLL0					276
+#define PLL0_VOTE				277
+#define PLL3					278
+#define PLL3_VOTE				279
+#define PLL4_VOTE				280
+#define PLL5					281
+#define PLL5_VOTE				282
+#define PLL6					283
+#define PLL6_VOTE				284
+#define PLL7_VOTE				285
+#define PLL8					286
+#define PLL8_VOTE				287
+#define PLL9					288
+#define PLL10					289
+#define PLL11					290
+#define PLL12					291
+#define PLL13					292
+#define PLL14					293
+#define PLL14_VOTE				294
+
+#endif
diff --git a/include/dt-bindings/reset/qcom,gcc-msm8960.h b/include/dt-bindings/reset/qcom,gcc-msm8960.h
new file mode 100644
index 0000000..a840e68
--- /dev/null
+++ b/include/dt-bindings/reset/qcom,gcc-msm8960.h
@@ -0,0 +1,118 @@
+/*
+ * Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef _DT_BINDINGS_RESET_MSM_GCC_8960_H
+#define _DT_BINDINGS_RESET_MSM_GCC_8960_H
+
+#define SFAB_MSS_Q6_SW_RESET				0
+#define SFAB_MSS_Q6_FW_RESET				1
+#define QDSS_STM_RESET					2
+#define AFAB_SMPSS_S_RESET				3
+#define AFAB_SMPSS_M1_RESET				4
+#define AFAB_SMPSS_M0_RESET				5
+#define AFAB_EBI1_CH0_RESET				6
+#define AFAB_EBI1_CH1_RESET				7
+#define SFAB_ADM0_M0_RESET				8
+#define SFAB_ADM0_M1_RESET				9
+#define SFAB_ADM0_M2_RESET				10
+#define ADM0_C2_RESET					11
+#define ADM0_C1_RESET					12
+#define ADM0_C0_RESET					13
+#define ADM0_PBUS_RESET					14
+#define ADM0_RESET					15
+#define QDSS_CLKS_SW_RESET				16
+#define QDSS_POR_RESET					17
+#define QDSS_TSCTR_RESET				18
+#define QDSS_HRESET_RESET				19
+#define QDSS_AXI_RESET					20
+#define QDSS_DBG_RESET					21
+#define PCIE_A_RESET					22
+#define PCIE_AUX_RESET					23
+#define PCIE_H_RESET					24
+#define SFAB_PCIE_M_RESET				25
+#define SFAB_PCIE_S_RESET				26
+#define SFAB_MSS_M_RESET				27
+#define SFAB_USB3_M_RESET				28
+#define SFAB_RIVA_M_RESET				29
+#define SFAB_LPASS_RESET				30
+#define SFAB_AFAB_M_RESET				31
+#define AFAB_SFAB_M0_RESET				32
+#define AFAB_SFAB_M1_RESET				33
+#define SFAB_SATA_S_RESET				34
+#define SFAB_DFAB_M_RESET				35
+#define DFAB_SFAB_M_RESET				36
+#define DFAB_SWAY0_RESET				37
+#define DFAB_SWAY1_RESET				38
+#define DFAB_ARB0_RESET					39
+#define DFAB_ARB1_RESET					40
+#define PPSS_PROC_RESET					41
+#define PPSS_RESET					42
+#define DMA_BAM_RESET					43
+#define SIC_TIC_RESET					44
+#define SLIMBUS_H_RESET					45
+#define SFAB_CFPB_M_RESET				46
+#define SFAB_CFPB_S_RESET				47
+#define TSIF_H_RESET					48
+#define CE1_H_RESET					49
+#define CE1_CORE_RESET					50
+#define CE1_SLEEP_RESET					51
+#define CE2_H_RESET					52
+#define CE2_CORE_RESET					53
+#define SFAB_SFPB_M_RESET				54
+#define SFAB_SFPB_S_RESET				55
+#define RPM_PROC_RESET					56
+#define PMIC_SSBI2_RESET				57
+#define SDC1_RESET					58
+#define SDC2_RESET					59
+#define SDC3_RESET					60
+#define SDC4_RESET					61
+#define SDC5_RESET					62
+#define DFAB_A2_RESET					63
+#define USB_HS1_RESET					64
+#define USB_HSIC_RESET					65
+#define USB_FS1_XCVR_RESET				66
+#define USB_FS1_RESET					67
+#define USB_FS2_XCVR_RESET				68
+#define USB_FS2_RESET					69
+#define GSBI1_RESET					70
+#define GSBI2_RESET					71
+#define GSBI3_RESET					72
+#define GSBI4_RESET					73
+#define GSBI5_RESET					74
+#define GSBI6_RESET					75
+#define GSBI7_RESET					76
+#define GSBI8_RESET					77
+#define GSBI9_RESET					78
+#define GSBI10_RESET					79
+#define GSBI11_RESET					80
+#define GSBI12_RESET					81
+#define SPDM_RESET					82
+#define TLMM_H_RESET					83
+#define SFAB_MSS_S_RESET				84
+#define MSS_SLP_RESET					85
+#define MSS_Q6SW_JTAG_RESET				86
+#define MSS_Q6FW_JTAG_RESET				87
+#define MSS_RESET					88
+#define SATA_H_RESET					89
+#define SATA_RXOOB_RESE					90
+#define SATA_PMALIVE_RESET				91
+#define SATA_SFAB_M_RESET				92
+#define TSSC_RESET					93
+#define PDM_RESET					94
+#define MPM_H_RESET					95
+#define MPM_RESET					96
+#define SFAB_SMPSS_S_RESET				97
+#define PRNG_RESET					98
+#define RIVA_RESET					99
+
+#endif
-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
hosted by The Linux Foundation

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

* [PATCH v4 10/15] clk: qcom: Add support for MSM8960's multimedia clock controller (MMCC)
  2013-12-24  1:12 [PATCH v4 00/15] Add support for MSM's mmio clock/reset controller Stephen Boyd
                   ` (8 preceding siblings ...)
  2013-12-24  1:12 ` [PATCH v4 09/15] clk: qcom: Add support for MSM8960's global clock controller (GCC) Stephen Boyd
@ 2013-12-24  1:12 ` Stephen Boyd
  2013-12-24  1:12 ` [PATCH v4 11/15] clk: qcom: Add support for MSM8974's global clock controller (GCC) Stephen Boyd
                   ` (4 subsequent siblings)
  14 siblings, 0 replies; 34+ messages in thread
From: Stephen Boyd @ 2013-12-24  1:12 UTC (permalink / raw)
  To: Mike Turquette
  Cc: linux-kernel, linux-arm-msm, linux-arm-kernel, Saravana Kannan

Add a driver for the multimedia clock controller found on MSM
8960 based platforms. This should allow multimedia device drivers
to probe and control their clocks.

Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
---
 drivers/clk/qcom/Kconfig                      |    9 +
 drivers/clk/qcom/Makefile                     |    1 +
 drivers/clk/qcom/mmcc-msm8960.c               | 2320 +++++++++++++++++++++++++
 include/dt-bindings/clock/qcom,mmcc-msm8960.h |  137 ++
 include/dt-bindings/reset/qcom,mmcc-msm8960.h |   93 +
 5 files changed, 2560 insertions(+)
 create mode 100644 drivers/clk/qcom/mmcc-msm8960.c
 create mode 100644 include/dt-bindings/clock/qcom,mmcc-msm8960.h
 create mode 100644 include/dt-bindings/reset/qcom,mmcc-msm8960.h

diff --git a/drivers/clk/qcom/Kconfig b/drivers/clk/qcom/Kconfig
index 8b39761..7152693 100644
--- a/drivers/clk/qcom/Kconfig
+++ b/drivers/clk/qcom/Kconfig
@@ -11,3 +11,12 @@ config MSM_GCC_8960
 	  Support for the global clock controller on msm8960 devices.
 	  Say Y if you want to use peripheral devices such as UART, SPI,
 	  i2c, USB, SD/eMMC, SATA, PCIe, etc.
+
+config MSM_MMCC_8960
+	tristate "MSM8960 Multimedia Clock Controller"
+	select MSM_GCC_8960
+	depends on COMMON_CLK_QCOM
+	help
+	  Support for the multimedia clock controller on msm8960 devices.
+	  Say Y if you want to support multimedia devices such as display,
+	  graphics, video encode/decode, camera, etc.
diff --git a/drivers/clk/qcom/Makefile b/drivers/clk/qcom/Makefile
index b8c816f..85eff39 100644
--- a/drivers/clk/qcom/Makefile
+++ b/drivers/clk/qcom/Makefile
@@ -7,3 +7,4 @@ clk-qcom-$(CONFIG_COMMON_CLK_QCOM) += clk-branch.o
 clk-qcom-$(CONFIG_COMMON_CLK_QCOM) += reset.o
 
 obj-$(CONFIG_MSM_GCC_8960) += gcc-msm8960.o
+obj-$(CONFIG_MSM_MMCC_8960) += mmcc-msm8960.o
diff --git a/drivers/clk/qcom/mmcc-msm8960.c b/drivers/clk/qcom/mmcc-msm8960.c
new file mode 100644
index 0000000..02c8e15
--- /dev/null
+++ b/drivers/clk/qcom/mmcc-msm8960.c
@@ -0,0 +1,2320 @@
+/*
+ * Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/kernel.h>
+#include <linux/bitops.h>
+#include <linux/err.h>
+#include <linux/delay.h>
+#include <linux/platform_device.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/clk-provider.h>
+#include <linux/regmap.h>
+#include <linux/reset-controller.h>
+
+#include <dt-bindings/clock/qcom,mmcc-msm8960.h>
+#include <dt-bindings/reset/qcom,mmcc-msm8960.h>
+
+#include "clk-pll.h"
+#include "clk-rcg.h"
+#include "clk-branch.h"
+#include "reset.h"
+
+#define P_PXO	0
+#define P_PLL8	1
+#define P_PLL2	2
+#define P_PLL3	3
+
+static u8 mmcc_pxo_pll8_pll2_map[] = {
+	[P_PXO]		= 0,
+	[P_PLL8]	= 2,
+	[P_PLL2]	= 1,
+};
+
+static const char *mmcc_pxo_pll8_pll2[] = {
+	"pxo",
+	"pll8_vote",
+	"pll2",
+};
+
+static u8 mmcc_pxo_pll8_pll2_pll3_map[] = {
+	[P_PXO]		= 0,
+	[P_PLL8]	= 2,
+	[P_PLL2]	= 1,
+	[P_PLL3]	= 3,
+};
+
+static const char *mmcc_pxo_pll8_pll2_pll3[] = {
+	"pxo",
+	"pll2",
+	"pll8_vote",
+	"pll3",
+};
+
+static struct clk_pll pll2 = {
+	.l_reg = 0x320,
+	.m_reg = 0x324,
+	.n_reg = 0x328,
+	.config_reg = 0x32c,
+	.mode_reg = 0x31c,
+	.status_reg = 0x334,
+	.status_bit = 16,
+	.hw.init = &(struct clk_init_data){
+		.name = "pll2",
+		.parent_names = (const char *[]){ "pxo" },
+		.num_parents = 1,
+		.ops = &clk_pll_ops,
+	},
+};
+
+static struct freq_tbl clk_tbl_cam[] = {
+	{   6000000, P_PLL8, 4, 1, 16 },
+	{   8000000, P_PLL8, 4, 1, 12 },
+	{  12000000, P_PLL8, 4, 1,  8 },
+	{  16000000, P_PLL8, 4, 1,  6 },
+	{  19200000, P_PLL8, 4, 1,  5 },
+	{  24000000, P_PLL8, 4, 1,  4 },
+	{  32000000, P_PLL8, 4, 1,  3 },
+	{  48000000, P_PLL8, 4, 1,  2 },
+	{  64000000, P_PLL8, 3, 1,  2 },
+	{  96000000, P_PLL8, 4, 0,  0 },
+	{ 128000000, P_PLL8, 3, 0,  0 },
+	{ }
+};
+
+static struct clk_rcg camclk0_src = {
+	.ns_reg = 0x0148,
+	.md_reg = 0x0144,
+	.mn = {
+		.mnctr_en_bit = 5,
+		.mnctr_reset_bit = 8,
+		.reset_in_cc = true,
+		.mnctr_mode_shift = 6,
+		.n_val_shift = 24,
+		.m_val_shift = 8,
+		.width = 8,
+	},
+	.p = {
+		.pre_div_shift = 14,
+		.pre_div_width = 2,
+	},
+	.s = {
+		.src_sel_shift = 0,
+		.parent_map = mmcc_pxo_pll8_pll2_map,
+	},
+	.freq_tbl = clk_tbl_cam,
+	.hw = {
+		.enable_reg = 0x0140,
+		.enable_mask = BIT(2),
+		.init = &(struct clk_init_data){
+			.name = "camclk0_src",
+			.parent_names = mmcc_pxo_pll8_pll2,
+			.num_parents = 3,
+			.ops = &clk_rcg_ops,
+		},
+	},
+};
+
+static struct clk_branch camclk0_clk = {
+	.halt_reg = 0x01e8,
+	.halt_bit = 15,
+	.hw = {
+		.enable_reg = 0x0140,
+		.enable_mask = BIT(0),
+		.init = &(struct clk_init_data){
+			.name = "camclk0_clk",
+			.parent_names = (const char *[]){ "camclk0_src" },
+			.num_parents = 1,
+			.ops = &clk_branch_ops,
+		},
+	},
+
+};
+
+static struct clk_rcg camclk1_src = {
+	.ns_reg = 0x015c,
+	.md_reg = 0x0158,
+	.mn = {
+		.mnctr_en_bit = 5,
+		.mnctr_reset_bit = 8,
+		.reset_in_cc = true,
+		.mnctr_mode_shift = 6,
+		.n_val_shift = 24,
+		.m_val_shift = 8,
+		.width = 8,
+	},
+	.p = {
+		.pre_div_shift = 14,
+		.pre_div_width = 2,
+	},
+	.s = {
+		.src_sel_shift = 0,
+		.parent_map = mmcc_pxo_pll8_pll2_map,
+	},
+	.freq_tbl = clk_tbl_cam,
+	.hw = {
+		.enable_reg = 0x0154,
+		.enable_mask = BIT(2),
+		.init = &(struct clk_init_data){
+			.name = "camclk1_src",
+			.parent_names = mmcc_pxo_pll8_pll2,
+			.num_parents = 3,
+			.ops = &clk_rcg_ops,
+		},
+	},
+};
+
+static struct clk_branch camclk1_clk = {
+	.halt_reg = 0x01e8,
+	.halt_bit = 16,
+	.hw = {
+		.enable_reg = 0x0154,
+		.enable_mask = BIT(0),
+		.init = &(struct clk_init_data){
+			.name = "camclk1_clk",
+			.parent_names = (const char *[]){ "camclk1_src" },
+			.num_parents = 1,
+			.ops = &clk_branch_ops,
+		},
+	},
+
+};
+
+static struct clk_rcg camclk2_src = {
+	.ns_reg = 0x0228,
+	.md_reg = 0x0224,
+	.mn = {
+		.mnctr_en_bit = 5,
+		.mnctr_reset_bit = 8,
+		.reset_in_cc = true,
+		.mnctr_mode_shift = 6,
+		.n_val_shift = 24,
+		.m_val_shift = 8,
+		.width = 8,
+	},
+	.p = {
+		.pre_div_shift = 14,
+		.pre_div_width = 2,
+	},
+	.s = {
+		.src_sel_shift = 0,
+		.parent_map = mmcc_pxo_pll8_pll2_map,
+	},
+	.freq_tbl = clk_tbl_cam,
+	.hw = {
+		.enable_reg = 0x0220,
+		.enable_mask = BIT(2),
+		.init = &(struct clk_init_data){
+			.name = "camclk2_src",
+			.parent_names = mmcc_pxo_pll8_pll2,
+			.num_parents = 3,
+			.ops = &clk_rcg_ops,
+		},
+	},
+};
+
+static struct clk_branch camclk2_clk = {
+	.halt_reg = 0x01e8,
+	.halt_bit = 16,
+	.hw = {
+		.enable_reg = 0x0220,
+		.enable_mask = BIT(0),
+		.init = &(struct clk_init_data){
+			.name = "camclk2_clk",
+			.parent_names = (const char *[]){ "camclk2_src" },
+			.num_parents = 1,
+			.ops = &clk_branch_ops,
+		},
+	},
+
+};
+
+static struct freq_tbl clk_tbl_csi[] = {
+	{  27000000, P_PXO,  1, 0, 0 },
+	{  85330000, P_PLL8, 1, 2, 9 },
+	{ 177780000, P_PLL2, 1, 2, 9 },
+	{ }
+};
+
+static struct clk_rcg csi0_src = {
+	.ns_reg = 0x0048,
+	.md_reg	= 0x0044,
+	.mn = {
+		.mnctr_en_bit = 5,
+		.mnctr_reset_bit = 7,
+		.mnctr_mode_shift = 6,
+		.n_val_shift = 24,
+		.m_val_shift = 8,
+		.width = 8,
+	},
+	.p = {
+		.pre_div_shift = 14,
+		.pre_div_width = 2,
+	},
+	.s = {
+		.src_sel_shift = 0,
+		.parent_map = mmcc_pxo_pll8_pll2_map,
+	},
+	.freq_tbl = clk_tbl_csi,
+	.hw = {
+		.enable_reg = 0x0040,
+		.enable_mask = BIT(2),
+		.init = &(struct clk_init_data){
+			.name = "csi0_src",
+			.parent_names = mmcc_pxo_pll8_pll2,
+			.num_parents = 3,
+			.ops = &clk_rcg_ops,
+		},
+	},
+};
+
+static struct clk_branch csi0_clk = {
+	.halt_reg = 0x01cc,
+	.halt_bit = 13,
+	.hw = {
+		.enable_reg = 0x0040,
+		.enable_mask = BIT(0),
+		.init = &(struct clk_init_data){
+			.parent_names = (const char *[]){ "csi0_src" },
+			.num_parents = 1,
+			.name = "csi0_clk",
+			.ops = &clk_branch_ops,
+			.flags = CLK_SET_RATE_PARENT,
+		},
+	},
+};
+
+static struct clk_branch csi0_phy_clk = {
+	.halt_reg = 0x01e8,
+	.halt_bit = 9,
+	.hw = {
+		.enable_reg = 0x0040,
+		.enable_mask = BIT(8),
+		.init = &(struct clk_init_data){
+			.parent_names = (const char *[]){ "csi0_src" },
+			.num_parents = 1,
+			.name = "csi0_phy_clk",
+			.ops = &clk_branch_ops,
+			.flags = CLK_SET_RATE_PARENT,
+		},
+	},
+};
+
+static struct clk_rcg csi1_src = {
+	.ns_reg = 0x0010,
+	.md_reg	= 0x0028,
+	.mn = {
+		.mnctr_en_bit = 5,
+		.mnctr_reset_bit = 7,
+		.mnctr_mode_shift = 6,
+		.n_val_shift = 24,
+		.m_val_shift = 8,
+		.width = 8,
+	},
+	.p = {
+		.pre_div_shift = 14,
+		.pre_div_width = 2,
+	},
+	.s = {
+		.src_sel_shift = 0,
+		.parent_map = mmcc_pxo_pll8_pll2_map,
+	},
+	.freq_tbl = clk_tbl_csi,
+	.hw = {
+		.enable_reg = 0x0024,
+		.enable_mask = BIT(2),
+		.init = &(struct clk_init_data){
+			.name = "csi1_src",
+			.parent_names = mmcc_pxo_pll8_pll2,
+			.num_parents = 3,
+			.ops = &clk_rcg_ops,
+		},
+	},
+};
+
+static struct clk_branch csi1_clk = {
+	.halt_reg = 0x01cc,
+	.halt_bit = 14,
+	.hw = {
+		.enable_reg = 0x0024,
+		.enable_mask = BIT(0),
+		.init = &(struct clk_init_data){
+			.parent_names = (const char *[]){ "csi1_src" },
+			.num_parents = 1,
+			.name = "csi1_clk",
+			.ops = &clk_branch_ops,
+			.flags = CLK_SET_RATE_PARENT,
+		},
+	},
+};
+
+static struct clk_branch csi1_phy_clk = {
+	.halt_reg = 0x01e8,
+	.halt_bit = 10,
+	.hw = {
+		.enable_reg = 0x0024,
+		.enable_mask = BIT(8),
+		.init = &(struct clk_init_data){
+			.parent_names = (const char *[]){ "csi1_src" },
+			.num_parents = 1,
+			.name = "csi1_phy_clk",
+			.ops = &clk_branch_ops,
+			.flags = CLK_SET_RATE_PARENT,
+		},
+	},
+};
+
+static struct clk_rcg csi2_src = {
+	.ns_reg = 0x0234,
+	.md_reg = 0x022c,
+	.mn = {
+		.mnctr_en_bit = 5,
+		.mnctr_reset_bit = 7,
+		.mnctr_mode_shift = 6,
+		.n_val_shift = 24,
+		.m_val_shift = 8,
+		.width = 8,
+	},
+	.p = {
+		.pre_div_shift = 14,
+		.pre_div_width = 2,
+	},
+	.s = {
+		.src_sel_shift = 0,
+		.parent_map = mmcc_pxo_pll8_pll2_map,
+	},
+	.freq_tbl = clk_tbl_csi,
+	.hw = {
+		.enable_reg = 0x022c,
+		.enable_mask = BIT(2),
+		.init = &(struct clk_init_data){
+			.name = "csi2_src",
+			.parent_names = mmcc_pxo_pll8_pll2,
+			.num_parents = 3,
+			.ops = &clk_rcg_ops,
+		},
+	},
+};
+
+static struct clk_branch csi2_clk = {
+	.halt_reg = 0x01cc,
+	.halt_bit = 29,
+	.hw = {
+		.enable_reg = 0x022c,
+		.enable_mask = BIT(0),
+		.init = &(struct clk_init_data){
+			.parent_names = (const char *[]){ "csi2_src" },
+			.num_parents = 1,
+			.name = "csi2_clk",
+			.ops = &clk_branch_ops,
+			.flags = CLK_SET_RATE_PARENT,
+		},
+	},
+};
+
+static struct clk_branch csi2_phy_clk = {
+	.halt_reg = 0x01e8,
+	.halt_bit = 29,
+	.hw = {
+		.enable_reg = 0x022c,
+		.enable_mask = BIT(8),
+		.init = &(struct clk_init_data){
+			.parent_names = (const char *[]){ "csi2_src" },
+			.num_parents = 1,
+			.name = "csi2_phy_clk",
+			.ops = &clk_branch_ops,
+			.flags = CLK_SET_RATE_PARENT,
+		},
+	},
+};
+
+struct clk_pix_rdi {
+	u32 s_reg;
+	u32 s_mask;
+	u32 s2_reg;
+	u32 s2_mask;
+	struct clk_hw hw;
+};
+
+#define to_clk_pix_rdi(_hw) container_of(_hw, struct clk_pix_rdi, hw)
+
+static int pix_rdi_set_parent(struct clk_hw *hw, u8 index)
+{
+	int i;
+	int ret = 0;
+	u32 val;
+	struct clk_pix_rdi *rdi = to_clk_pix_rdi(hw);
+	struct clk *clk = hw->clk;
+	int num_parents = __clk_get_num_parents(hw->clk);
+
+	/*
+	 * These clocks select three inputs via two muxes. One mux selects
+	 * between csi0 and csi1 and the second mux selects between that mux's
+	 * output and csi2. The source and destination selections for each
+	 * mux must be clocking for the switch to succeed so just turn on
+	 * all three sources because it's easier than figuring out what source
+	 * needs to be on at what time.
+	 */
+	for (i = 0; i < num_parents; i++) {
+		ret = clk_prepare_enable(clk_get_parent_by_index(clk, i));
+		if (ret)
+			goto err;
+	}
+
+	if (index == 2)
+		val = rdi->s2_mask;
+	else
+		val = 0;
+	regmap_update_bits(hw->regmap, rdi->s2_reg, rdi->s2_mask, val);
+	/*
+	 * Wait at least 6 cycles of slowest clock
+	 * for the glitch-free MUX to fully switch sources.
+	 */
+	udelay(1);
+
+	if (index == 1)
+		val = rdi->s_mask;
+	else
+		val = 0;
+	regmap_update_bits(hw->regmap, rdi->s_reg, rdi->s_mask, val);
+	/*
+	 * Wait at least 6 cycles of slowest clock
+	 * for the glitch-free MUX to fully switch sources.
+	 */
+	udelay(1);
+
+err:
+	for (i--; i >= 0; i--)
+		clk_disable_unprepare(clk_get_parent_by_index(clk, i));
+
+	return ret;
+}
+
+static u8 pix_rdi_get_parent(struct clk_hw *hw)
+{
+	u32 val;
+	struct clk_pix_rdi *rdi = to_clk_pix_rdi(hw);
+
+
+	regmap_read(hw->regmap, rdi->s2_reg, &val);
+	if (val & rdi->s2_mask)
+		return 2;
+
+	regmap_read(hw->regmap, rdi->s_reg, &val);
+	if (val & rdi->s_mask)
+		return 1;
+
+	return 0;
+}
+
+static const struct clk_ops clk_ops_pix_rdi = {
+	.enable = clk_enable_regmap,
+	.disable = clk_disable_regmap,
+	.set_parent = pix_rdi_set_parent,
+	.get_parent = pix_rdi_get_parent,
+	.determine_rate = __clk_mux_determine_rate,
+};
+
+static const char *pix_rdi_parents[] = {
+	"csi0_clk",
+	"csi1_clk",
+	"csi2_clk",
+};
+
+static struct clk_pix_rdi csi_pix_clk = {
+	.s_reg = 0x0058,
+	.s_mask = BIT(25),
+	.s2_reg = 0x0238,
+	.s2_mask = BIT(13),
+	.hw = {
+		.enable_reg = 0x0058,
+		.enable_mask = BIT(26),
+		.init = &(struct clk_init_data){
+			.name = "csi_pix_clk",
+			.parent_names = pix_rdi_parents,
+			.num_parents = 3,
+			.ops = &clk_ops_pix_rdi,
+		},
+	},
+};
+
+static struct clk_pix_rdi csi_pix1_clk = {
+	.s_reg = 0x0238,
+	.s_mask = BIT(8),
+	.s2_reg = 0x0238,
+	.s2_mask = BIT(9),
+	.hw = {
+		.enable_reg = 0x0238,
+		.enable_mask = BIT(10),
+		.init = &(struct clk_init_data){
+			.name = "csi_pix1_clk",
+			.parent_names = pix_rdi_parents,
+			.num_parents = 3,
+			.ops = &clk_ops_pix_rdi,
+		},
+	},
+};
+
+static struct clk_pix_rdi csi_rdi_clk = {
+	.s_reg = 0x0058,
+	.s_mask = BIT(12),
+	.s2_reg = 0x0238,
+	.s2_mask = BIT(12),
+	.hw = {
+		.enable_reg = 0x0058,
+		.enable_mask = BIT(13),
+		.enable_mask = BIT(10),
+		.init = &(struct clk_init_data){
+			.name = "csi_rdi_clk",
+			.parent_names = pix_rdi_parents,
+			.num_parents = 3,
+			.ops = &clk_ops_pix_rdi,
+		},
+	},
+};
+
+static struct clk_pix_rdi csi_rdi1_clk = {
+	.s_reg = 0x0238,
+	.s_mask = BIT(0),
+	.s2_reg = 0x0238,
+	.s2_mask = BIT(1),
+	.hw = {
+		.enable_reg = 0x0238,
+		.enable_mask = BIT(2),
+		.init = &(struct clk_init_data){
+			.name = "csi_rdi1_clk",
+			.parent_names = pix_rdi_parents,
+			.num_parents = 3,
+			.ops = &clk_ops_pix_rdi,
+		},
+	},
+};
+
+static struct clk_pix_rdi csi_rdi2_clk = {
+	.s_reg = 0x0238,
+	.s_mask = BIT(4),
+	.s2_reg = 0x0238,
+	.s2_mask = BIT(5),
+	.hw = {
+		.enable_reg = 0x0238,
+		.enable_mask = BIT(6),
+		.init = &(struct clk_init_data){
+			.name = "csi_rdi2_clk",
+			.parent_names = pix_rdi_parents,
+			.num_parents = 3,
+			.ops = &clk_ops_pix_rdi,
+		},
+	},
+};
+
+static struct freq_tbl clk_tbl_csiphytimer[] = {
+	{  85330000, P_PLL8, 1, 2, 9 },
+	{ 177780000, P_PLL2, 1, 2, 9 },
+	{ }
+};
+
+static struct clk_rcg csiphytimer_src = {
+	.ns_reg = 0x0168,
+	.md_reg = 0x0164,
+	.mn = {
+		.mnctr_en_bit = 5,
+		.mnctr_reset_bit = 8,
+		.reset_in_cc = true,
+		.mnctr_mode_shift = 6,
+		.n_val_shift = 24,
+		.m_val_shift = 8,
+		.width = 8,
+	},
+	.p = {
+		.pre_div_shift = 14,
+		.pre_div_width = 2,
+	},
+	.s = {
+		.src_sel_shift = 0,
+		.parent_map = mmcc_pxo_pll8_pll2_map,
+	},
+	.freq_tbl = clk_tbl_csiphytimer,
+	.hw = {
+		.enable_reg = 0x0160,
+		.enable_mask = BIT(2),
+		.init = &(struct clk_init_data){
+			.name = "csiphytimer_src",
+			.parent_names = mmcc_pxo_pll8_pll2,
+			.num_parents = 3,
+			.ops = &clk_rcg_ops,
+		},
+	},
+};
+
+static const char *csixphy_timer_src[] = { "csiphytimer_src" };
+
+static struct clk_branch csiphy0_timer_clk = {
+	.halt_reg = 0x01e8,
+	.halt_bit = 17,
+	.hw = {
+		.enable_reg = 0x0160,
+		.enable_mask = BIT(0),
+		.init = &(struct clk_init_data){
+			.parent_names = csixphy_timer_src,
+			.num_parents = 1,
+			.name = "csiphy0_timer_clk",
+			.ops = &clk_branch_ops,
+			.flags = CLK_SET_RATE_PARENT,
+		},
+	},
+};
+
+static struct clk_branch csiphy1_timer_clk = {
+	.halt_reg = 0x01e8,
+	.halt_bit = 18,
+	.hw = {
+		.enable_reg = 0x0160,
+		.enable_mask = BIT(9),
+		.init = &(struct clk_init_data){
+			.parent_names = csixphy_timer_src,
+			.num_parents = 1,
+			.name = "csiphy1_timer_clk",
+			.ops = &clk_branch_ops,
+			.flags = CLK_SET_RATE_PARENT,
+		},
+	},
+};
+
+static struct clk_branch csiphy2_timer_clk = {
+	.halt_reg = 0x01e8,
+	.halt_bit = 30,
+	.hw = {
+		.enable_reg = 0x0160,
+		.enable_mask = BIT(11),
+		.init = &(struct clk_init_data){
+			.parent_names = csixphy_timer_src,
+			.num_parents = 1,
+			.name = "csiphy2_timer_clk",
+			.ops = &clk_branch_ops,
+			.flags = CLK_SET_RATE_PARENT,
+		},
+	},
+};
+
+static struct freq_tbl clk_tbl_gfx2d[] = {
+	{  27000000, P_PXO,  1,  0 },
+	{  48000000, P_PLL8, 1,  8 },
+	{  54857000, P_PLL8, 1,  7 },
+	{  64000000, P_PLL8, 1,  6 },
+	{  76800000, P_PLL8, 1,  5 },
+	{  96000000, P_PLL8, 1,  4 },
+	{ 128000000, P_PLL8, 1,  3 },
+	{ 145455000, P_PLL2, 2, 11 },
+	{ 160000000, P_PLL2, 1,  5 },
+	{ 177778000, P_PLL2, 2,  9 },
+	{ 200000000, P_PLL2, 1,  4 },
+	{ 228571000, P_PLL2, 2,  7 },
+	{ }
+};
+
+static struct clk_dyn_rcg gfx2d0_src = {
+	.ns_reg = 0x0070,
+	.md_reg[0] = 0x0064,
+	.md_reg[1] = 0x0068,
+	.mn[0] = {
+		.mnctr_en_bit = 8,
+		.mnctr_reset_bit = 25,
+		.mnctr_mode_shift = 9,
+		.n_val_shift = 20,
+		.m_val_shift = 4,
+		.width = 4,
+	},
+	.mn[1] = {
+		.mnctr_en_bit = 5,
+		.mnctr_reset_bit = 24,
+		.mnctr_mode_shift = 6,
+		.n_val_shift = 16,
+		.m_val_shift = 4,
+		.width = 4,
+	},
+	.s[0] = {
+		.src_sel_shift = 3,
+		.parent_map = mmcc_pxo_pll8_pll2_map,
+	},
+	.s[1] = {
+		.src_sel_shift = 0,
+		.parent_map = mmcc_pxo_pll8_pll2_map,
+	},
+	.mux_sel_bit = 11,
+	.freq_tbl = clk_tbl_gfx2d,
+	.hw = {
+		.enable_reg = 0x0060,
+		.enable_mask = BIT(2),
+		.init = &(struct clk_init_data){
+			.name = "gfx2d0_src",
+			.parent_names = mmcc_pxo_pll8_pll2,
+			.num_parents = 3,
+			.ops = &clk_dyn_rcg_ops,
+		},
+	},
+};
+
+static struct clk_branch gfx2d0_clk = {
+	.halt_reg = 0x01c8,
+	.halt_bit = 9,
+	.hw = {
+		.enable_reg = 0x0060,
+		.enable_mask = BIT(0),
+		.init = &(struct clk_init_data){
+			.name = "gfx2d0_clk",
+			.parent_names = (const char *[]){ "gfx2d0_src" },
+			.num_parents = 1,
+			.ops = &clk_branch_ops,
+			.flags = CLK_SET_RATE_PARENT,
+		},
+	},
+};
+
+static struct clk_dyn_rcg gfx2d1_src = {
+	.ns_reg = 0x007c,
+	.md_reg[0] = 0x0078,
+	.md_reg[1] = 0x006c,
+	.mn[0] = {
+		.mnctr_en_bit = 8,
+		.mnctr_reset_bit = 25,
+		.mnctr_mode_shift = 9,
+		.n_val_shift = 20,
+		.m_val_shift = 4,
+		.width = 4,
+	},
+	.mn[1] = {
+		.mnctr_en_bit = 5,
+		.mnctr_reset_bit = 24,
+		.mnctr_mode_shift = 6,
+		.n_val_shift = 16,
+		.m_val_shift = 4,
+		.width = 4,
+	},
+	.s[0] = {
+		.src_sel_shift = 3,
+		.parent_map = mmcc_pxo_pll8_pll2_map,
+	},
+	.s[1] = {
+		.src_sel_shift = 0,
+		.parent_map = mmcc_pxo_pll8_pll2_map,
+	},
+	.mux_sel_bit = 11,
+	.freq_tbl = clk_tbl_gfx2d,
+	.hw = {
+		.enable_reg = 0x0074,
+		.enable_mask = BIT(2),
+		.init = &(struct clk_init_data){
+			.name = "gfx2d1_src",
+			.parent_names = mmcc_pxo_pll8_pll2,
+			.num_parents = 3,
+			.ops = &clk_dyn_rcg_ops,
+		},
+	},
+};
+
+static struct clk_branch gfx2d1_clk = {
+	.halt_reg = 0x01c8,
+	.halt_bit = 14,
+	.hw = {
+		.enable_reg = 0x0074,
+		.enable_mask = BIT(0),
+		.init = &(struct clk_init_data){
+			.name = "gfx2d1_clk",
+			.parent_names = (const char *[]){ "gfx2d1_src" },
+			.num_parents = 1,
+			.ops = &clk_branch_ops,
+			.flags = CLK_SET_RATE_PARENT,
+		},
+	},
+};
+
+static struct freq_tbl clk_tbl_gfx3d[] = {
+	{  27000000, P_PXO,  1,  0 },
+	{  48000000, P_PLL8, 1,  8 },
+	{  54857000, P_PLL8, 1,  7 },
+	{  64000000, P_PLL8, 1,  6 },
+	{  76800000, P_PLL8, 1,  5 },
+	{  96000000, P_PLL8, 1,  4 },
+	{ 128000000, P_PLL8, 1,  3 },
+	{ 145455000, P_PLL2, 2, 11 },
+	{ 160000000, P_PLL2, 1,  5 },
+	{ 177778000, P_PLL2, 2,  9 },
+	{ 200000000, P_PLL2, 1,  4 },
+	{ 228571000, P_PLL2, 2,  7 },
+	{ 266667000, P_PLL2, 1,  3 },
+	{ 300000000, P_PLL3, 1,  4 },
+	{ 320000000, P_PLL2, 2,  5 },
+	{ 400000000, P_PLL2, 1,  2 },
+	{ }
+};
+
+static struct clk_dyn_rcg gfx3d_src = {
+	.ns_reg = 0x008c,
+	.md_reg[0] = 0x0084,
+	.md_reg[1] = 0x0088,
+	.mn[0] = {
+		.mnctr_en_bit = 8,
+		.mnctr_reset_bit = 25,
+		.mnctr_mode_shift = 9,
+		.n_val_shift = 18,
+		.m_val_shift = 4,
+		.width = 4,
+	},
+	.mn[1] = {
+		.mnctr_en_bit = 5,
+		.mnctr_reset_bit = 24,
+		.mnctr_mode_shift = 6,
+		.n_val_shift = 14,
+		.m_val_shift = 4,
+		.width = 4,
+	},
+	.s[0] = {
+		.src_sel_shift = 3,
+		.parent_map = mmcc_pxo_pll8_pll2_pll3_map,
+	},
+	.s[1] = {
+		.src_sel_shift = 0,
+		.parent_map = mmcc_pxo_pll8_pll2_pll3_map,
+	},
+	.mux_sel_bit = 11,
+	.freq_tbl = clk_tbl_gfx3d,
+	.hw = {
+		.enable_reg = 0x0080,
+		.enable_mask = BIT(2),
+		.init = &(struct clk_init_data){
+			.name = "gfx3d_src",
+			.parent_names = mmcc_pxo_pll8_pll2_pll3,
+			.num_parents = 3,
+			.ops = &clk_dyn_rcg_ops,
+		},
+	},
+};
+
+static struct clk_branch gfx3d_clk = {
+	.halt_reg = 0x01c8,
+	.halt_bit = 4,
+	.hw = {
+		.enable_reg = 0x0080,
+		.enable_mask = BIT(0),
+		.init = &(struct clk_init_data){
+			.name = "gfx3d_clk",
+			.parent_names = (const char *[]){ "gfx3d_src" },
+			.num_parents = 1,
+			.ops = &clk_branch_ops,
+			.flags = CLK_SET_RATE_PARENT,
+		},
+	},
+};
+
+static struct freq_tbl clk_tbl_ijpeg[] = {
+	{  27000000, P_PXO,  1, 0,  0 },
+	{  36570000, P_PLL8, 1, 2, 21 },
+	{  54860000, P_PLL8, 7, 0,  0 },
+	{  96000000, P_PLL8, 4, 0,  0 },
+	{ 109710000, P_PLL8, 1, 2,  7 },
+	{ 128000000, P_PLL8, 3, 0,  0 },
+	{ 153600000, P_PLL8, 1, 2,  5 },
+	{ 200000000, P_PLL2, 4, 0,  0 },
+	{ 228571000, P_PLL2, 1, 2,  7 },
+	{ 266667000, P_PLL2, 1, 1,  3 },
+	{ 320000000, P_PLL2, 1, 2,  5 },
+	{ }
+};
+
+static struct clk_rcg ijpeg_src = {
+	.ns_reg = 0x00a0,
+	.md_reg = 0x009c,
+	.mn = {
+		.mnctr_en_bit = 5,
+		.mnctr_reset_bit = 7,
+		.mnctr_mode_shift = 6,
+		.n_val_shift = 16,
+		.m_val_shift = 8,
+		.width = 8,
+	},
+	.p = {
+		.pre_div_shift = 12,
+		.pre_div_width = 2,
+	},
+	.s = {
+		.src_sel_shift = 0,
+		.parent_map = mmcc_pxo_pll8_pll2_map,
+	},
+	.freq_tbl = clk_tbl_ijpeg,
+	.hw = {
+		.enable_reg = 0x0098,
+		.enable_mask = BIT(2),
+		.init = &(struct clk_init_data){
+			.name = "ijpeg_src",
+			.parent_names = mmcc_pxo_pll8_pll2,
+			.num_parents = 3,
+			.ops = &clk_rcg_ops,
+		},
+	},
+};
+
+static struct clk_branch ijpeg_clk = {
+	.halt_reg = 0x01c8,
+	.halt_bit = 24,
+	.hw = {
+		.enable_reg = 0x0098,
+		.enable_mask = BIT(0),
+		.init = &(struct clk_init_data){
+			.name = "ijpeg_clk",
+			.parent_names = (const char *[]){ "ijpeg_src" },
+			.num_parents = 1,
+			.ops = &clk_branch_ops,
+			.flags = CLK_SET_RATE_PARENT,
+		},
+	},
+};
+
+static struct freq_tbl clk_tbl_jpegd[] = {
+	{  64000000, P_PLL8, 6 },
+	{  76800000, P_PLL8, 5 },
+	{  96000000, P_PLL8, 4 },
+	{ 160000000, P_PLL2, 5 },
+	{ 200000000, P_PLL2, 4 },
+	{ }
+};
+
+static struct clk_rcg jpegd_src = {
+	.ns_reg = 0x00ac,
+	.p = {
+		.pre_div_shift = 12,
+		.pre_div_width = 2,
+	},
+	.s = {
+		.src_sel_shift = 0,
+		.parent_map = mmcc_pxo_pll8_pll2_map,
+	},
+	.freq_tbl = clk_tbl_jpegd,
+	.hw = {
+		.enable_reg = 0x00a4,
+		.enable_mask = BIT(2),
+		.init = &(struct clk_init_data){
+			.name = "jpegd_src",
+			.parent_names = mmcc_pxo_pll8_pll2,
+			.num_parents = 3,
+			.ops = &clk_rcg_ops,
+		},
+	},
+};
+
+static struct clk_branch jpegd_clk = {
+	.halt_reg = 0x01c8,
+	.halt_bit = 19,
+	.hw = {
+		.enable_reg = 0x00a4,
+		.enable_mask = BIT(0),
+		.init = &(struct clk_init_data){
+			.name = "jpegd_clk",
+			.parent_names = (const char *[]){ "jpegd_src" },
+			.num_parents = 1,
+			.ops = &clk_branch_ops,
+			.flags = CLK_SET_RATE_PARENT,
+		},
+	},
+};
+
+static struct freq_tbl clk_tbl_mdp[] = {
+	{   9600000, P_PLL8, 1, 1, 40 },
+	{  13710000, P_PLL8, 1, 1, 28 },
+	{  27000000, P_PXO,  1, 0,  0 },
+	{  29540000, P_PLL8, 1, 1, 13 },
+	{  34910000, P_PLL8, 1, 1, 11 },
+	{  38400000, P_PLL8, 1, 1, 10 },
+	{  59080000, P_PLL8, 1, 2, 13 },
+	{  76800000, P_PLL8, 1, 1,  5 },
+	{  85330000, P_PLL8, 1, 2,  9 },
+	{  96000000, P_PLL8, 1, 1,  4 },
+	{ 128000000, P_PLL8, 1, 1,  3 },
+	{ 160000000, P_PLL2, 1, 1,  5 },
+	{ 177780000, P_PLL2, 1, 2,  9 },
+	{ 200000000, P_PLL2, 1, 1,  4 },
+	{ 228571000, P_PLL2, 1, 2,  7 },
+	{ 266667000, P_PLL2, 1, 1,  3 },
+	{ }
+};
+
+static struct clk_dyn_rcg mdp_src = {
+	.ns_reg = 0x00d0,
+	.md_reg[0] = 0x00c4,
+	.md_reg[1] = 0x00c8,
+	.mn[0] = {
+		.mnctr_en_bit = 8,
+		.mnctr_reset_bit = 31,
+		.mnctr_mode_shift = 9,
+		.n_val_shift = 22,
+		.m_val_shift = 8,
+		.width = 8,
+	},
+	.mn[1] = {
+		.mnctr_en_bit = 5,
+		.mnctr_reset_bit = 30,
+		.mnctr_mode_shift = 6,
+		.n_val_shift = 14,
+		.m_val_shift = 8,
+		.width = 8,
+	},
+	.s[0] = {
+		.src_sel_shift = 3,
+		.parent_map = mmcc_pxo_pll8_pll2_map,
+	},
+	.s[1] = {
+		.src_sel_shift = 0,
+		.parent_map = mmcc_pxo_pll8_pll2_map,
+	},
+	.mux_sel_bit = 11,
+	.freq_tbl = clk_tbl_mdp,
+	.hw = {
+		.enable_reg = 0x00c0,
+		.enable_mask = BIT(2),
+		.init = &(struct clk_init_data){
+			.name = "mdp_src",
+			.parent_names = mmcc_pxo_pll8_pll2,
+			.num_parents = 3,
+			.ops = &clk_dyn_rcg_ops,
+		},
+	},
+};
+
+static struct clk_branch mdp_clk = {
+	.halt_reg = 0x01d0,
+	.halt_bit = 10,
+	.hw = {
+		.enable_reg = 0x00c0,
+		.enable_mask = BIT(0),
+		.init = &(struct clk_init_data){
+			.name = "mdp_clk",
+			.parent_names = (const char *[]){ "mdp_src" },
+			.num_parents = 1,
+			.ops = &clk_branch_ops,
+			.flags = CLK_SET_RATE_PARENT,
+		},
+	},
+};
+
+static struct clk_branch mdp_lut_clk = {
+	.halt_reg = 0x01e8,
+	.halt_bit = 13,
+	.hw = {
+		.enable_reg = 0x016c,
+		.enable_mask = BIT(0),
+		.init = &(struct clk_init_data){
+			.parent_names = (const char *[]){ "mdp_clk" },
+			.num_parents = 1,
+			.name = "mdp_lut_clk",
+			.ops = &clk_branch_ops,
+			.flags = CLK_SET_RATE_PARENT,
+		},
+	},
+};
+
+static struct clk_branch mdp_vsync_clk = {
+	.halt_reg = 0x01cc,
+	.halt_bit = 22,
+	.hw = {
+		.enable_reg = 0x0058,
+		.enable_mask = BIT(6),
+		.init = &(struct clk_init_data){
+			.name = "mdp_vsync_clk",
+			.parent_names = (const char *[]){ "pxo" },
+			.num_parents = 1,
+			.ops = &clk_branch_ops
+		},
+	},
+};
+
+static struct freq_tbl clk_tbl_rot[] = {
+	{  27000000, P_PXO,   1 },
+	{  29540000, P_PLL8, 13 },
+	{  32000000, P_PLL8, 12 },
+	{  38400000, P_PLL8, 10 },
+	{  48000000, P_PLL8,  8 },
+	{  54860000, P_PLL8,  7 },
+	{  64000000, P_PLL8,  6 },
+	{  76800000, P_PLL8,  5 },
+	{  96000000, P_PLL8,  4 },
+	{ 100000000, P_PLL2,  8 },
+	{ 114290000, P_PLL2,  7 },
+	{ 133330000, P_PLL2,  6 },
+	{ 160000000, P_PLL2,  5 },
+	{ 200000000, P_PLL2,  4 },
+	{ }
+};
+
+static struct clk_dyn_rcg rot_src = {
+	.ns_reg = 0x00e8,
+	.p[0] = {
+		.pre_div_shift = 22,
+		.pre_div_width = 4,
+	},
+	.p[1] = {
+		.pre_div_shift = 26,
+		.pre_div_width = 4,
+	},
+	.s[0] = {
+		.src_sel_shift = 16,
+		.parent_map = mmcc_pxo_pll8_pll2_map,
+	},
+	.s[1] = {
+		.src_sel_shift = 19,
+		.parent_map = mmcc_pxo_pll8_pll2_map,
+	},
+	.mux_sel_bit = 30,
+	.freq_tbl = clk_tbl_rot,
+	.hw = {
+		.enable_reg = 0x00e0,
+		.enable_mask = BIT(2),
+		.init = &(struct clk_init_data){
+			.name = "rot_src",
+			.parent_names = mmcc_pxo_pll8_pll2,
+			.num_parents = 3,
+			.ops = &clk_dyn_rcg_ops,
+		},
+	},
+};
+
+static struct clk_branch rot_clk = {
+	.halt_reg = 0x01d0,
+	.halt_bit = 15,
+	.hw = {
+		.enable_reg = 0x00e0,
+		.enable_mask = BIT(0),
+		.init = &(struct clk_init_data){
+			.name = "rot_clk",
+			.parent_names = (const char *[]){ "rot_src" },
+			.num_parents = 1,
+			.ops = &clk_branch_ops,
+			.flags = CLK_SET_RATE_PARENT,
+		},
+	},
+};
+
+#define P_HDMI_PLL 1
+
+static u8 mmcc_pxo_hdmi_map[] = {
+	[P_PXO]		= 0,
+	[P_HDMI_PLL]	= 2,
+};
+
+static const char *mmcc_pxo_hdmi[] = {
+	"pxo",
+	"hdmi_pll",
+};
+
+static struct freq_tbl clk_tbl_tv[] = {
+	{  25200000, P_HDMI_PLL, 1, 0, 0 },
+	{  27000000, P_HDMI_PLL, 1, 0, 0 },
+	{  27030000, P_HDMI_PLL, 1, 0, 0 },
+	{  74250000, P_HDMI_PLL, 1, 0, 0 },
+	{ 108000000, P_HDMI_PLL, 1, 0, 0 },
+	{ 148500000, P_HDMI_PLL, 1, 0, 0 },
+	{ }
+};
+
+static struct clk_rcg tv_src = {
+	.ns_reg = 0x00f4,
+	.md_reg = 0x00f0,
+	.mn = {
+		.mnctr_en_bit = 5,
+		.mnctr_reset_bit = 7,
+		.mnctr_mode_shift = 6,
+		.n_val_shift = 16,
+		.m_val_shift = 8,
+		.width = 8,
+	},
+	.p = {
+		.pre_div_shift = 14,
+		.pre_div_width = 2,
+	},
+	.s = {
+		.src_sel_shift = 0,
+		.parent_map = mmcc_pxo_hdmi_map,
+	},
+	.freq_tbl = clk_tbl_tv,
+	.hw = {
+		.enable_reg = 0x00ec,
+		.enable_mask = BIT(2),
+		.init = &(struct clk_init_data){
+			.name = "tv_src",
+			.parent_names = mmcc_pxo_hdmi,
+			.num_parents = 2,
+			.ops = &clk_rcg_ops,
+			.flags = CLK_SET_RATE_PARENT,
+		},
+	},
+};
+
+static const char *tv_src_name[] = { "tv_src" };
+
+static struct clk_branch tv_enc_clk = {
+	.halt_reg = 0x01d4,
+	.halt_bit = 9,
+	.hw = {
+		.enable_reg = 0x00ec,
+		.enable_mask = BIT(8),
+		.init = &(struct clk_init_data){
+			.parent_names = tv_src_name,
+			.num_parents = 1,
+			.name = "tv_enc_clk",
+			.ops = &clk_branch_ops,
+			.flags = CLK_SET_RATE_PARENT,
+		},
+	},
+};
+
+static struct clk_branch tv_dac_clk = {
+	.halt_reg = 0x01d4,
+	.halt_bit = 10,
+	.hw = {
+		.enable_reg = 0x00ec,
+		.enable_mask = BIT(10),
+		.init = &(struct clk_init_data){
+			.parent_names = tv_src_name,
+			.num_parents = 1,
+			.name = "tv_dac_clk",
+			.ops = &clk_branch_ops,
+			.flags = CLK_SET_RATE_PARENT,
+		},
+	},
+};
+
+static struct clk_branch mdp_tv_clk = {
+	.halt_reg = 0x01d4,
+	.halt_bit = 12,
+	.hw = {
+		.enable_reg = 0x00ec,
+		.enable_mask = BIT(0),
+		.init = &(struct clk_init_data){
+			.parent_names = tv_src_name,
+			.num_parents = 1,
+			.name = "mdp_tv_clk",
+			.ops = &clk_branch_ops,
+			.flags = CLK_SET_RATE_PARENT,
+		},
+	},
+};
+
+static struct clk_branch hdmi_tv_clk = {
+	.halt_reg = 0x01d4,
+	.halt_bit = 11,
+	.hw = {
+		.enable_reg = 0x00ec,
+		.enable_mask = BIT(12),
+		.init = &(struct clk_init_data){
+			.parent_names = tv_src_name,
+			.num_parents = 1,
+			.name = "hdmi_tv_clk",
+			.ops = &clk_branch_ops,
+			.flags = CLK_SET_RATE_PARENT,
+		},
+	},
+};
+
+static struct clk_branch hdmi_app_clk = {
+	.halt_reg = 0x01cc,
+	.halt_bit = 25,
+	.hw = {
+		.enable_reg = 0x005c,
+		.enable_mask = BIT(11),
+		.init = &(struct clk_init_data){
+			.parent_names = (const char *[]){ "pxo" },
+			.num_parents = 1,
+			.name = "hdmi_app_clk",
+			.ops = &clk_branch_ops,
+		},
+	},
+};
+
+static struct freq_tbl clk_tbl_vcodec[] = {
+	{  27000000, P_PXO,  1,  0 },
+	{  32000000, P_PLL8, 1, 12 },
+	{  48000000, P_PLL8, 1,  8 },
+	{  54860000, P_PLL8, 1,  7 },
+	{  96000000, P_PLL8, 1,  4 },
+	{ 133330000, P_PLL2, 1,  6 },
+	{ 200000000, P_PLL2, 1,  4 },
+	{ 228570000, P_PLL2, 2,  7 },
+	{ 266670000, P_PLL2, 1,  3 },
+	{ }
+};
+
+static struct clk_dyn_rcg vcodec_src = {
+	.ns_reg = 0x0100,
+	.md_reg[0] = 0x00fc,
+	.md_reg[1] = 0x0128,
+	.mn[0] = {
+		.mnctr_en_bit = 5,
+		.mnctr_reset_bit = 31,
+		.mnctr_mode_shift = 6,
+		.n_val_shift = 11,
+		.m_val_shift = 8,
+		.width = 8,
+	},
+	.mn[1] = {
+		.mnctr_en_bit = 10,
+		.mnctr_reset_bit = 30,
+		.mnctr_mode_shift = 11,
+		.n_val_shift = 19,
+		.m_val_shift = 8,
+		.width = 8,
+	},
+	.s[0] = {
+		.src_sel_shift = 27,
+		.parent_map = mmcc_pxo_pll8_pll2_map,
+	},
+	.s[1] = {
+		.src_sel_shift = 0,
+		.parent_map = mmcc_pxo_pll8_pll2_map,
+	},
+	.mux_sel_bit = 13,
+	.freq_tbl = clk_tbl_vcodec,
+	.hw = {
+		.enable_reg = 0x00f8,
+		.enable_mask = BIT(2),
+		.init = &(struct clk_init_data){
+			.name = "vcodec_src",
+			.parent_names = mmcc_pxo_pll8_pll2,
+			.num_parents = 3,
+			.ops = &clk_dyn_rcg_ops,
+		},
+	},
+};
+
+static struct clk_branch vcodec_clk = {
+	.halt_reg = 0x01d0,
+	.halt_bit = 29,
+	.hw = {
+		.enable_reg = 0x00f8,
+		.enable_mask = BIT(0),
+		.init = &(struct clk_init_data){
+			.name = "vcodec_clk",
+			.parent_names = (const char *[]){ "vcodec_src" },
+			.num_parents = 1,
+			.ops = &clk_branch_ops,
+			.flags = CLK_SET_RATE_PARENT,
+		},
+	},
+};
+
+static struct freq_tbl clk_tbl_vpe[] = {
+	{  27000000, P_PXO,   1 },
+	{  34909000, P_PLL8, 11 },
+	{  38400000, P_PLL8, 10 },
+	{  64000000, P_PLL8,  6 },
+	{  76800000, P_PLL8,  5 },
+	{  96000000, P_PLL8,  4 },
+	{ 100000000, P_PLL2,  8 },
+	{ 160000000, P_PLL2,  5 },
+	{ }
+};
+
+static struct clk_rcg vpe_src = {
+	.ns_reg = 0x0118,
+	.p = {
+		.pre_div_shift = 12,
+		.pre_div_width = 4,
+	},
+	.s = {
+		.src_sel_shift = 0,
+		.parent_map = mmcc_pxo_pll8_pll2_map,
+	},
+	.freq_tbl = clk_tbl_vpe,
+	.hw = {
+		.enable_reg = 0x0110,
+		.enable_mask = BIT(2),
+		.init = &(struct clk_init_data){
+			.name = "vpe_src",
+			.parent_names = mmcc_pxo_pll8_pll2,
+			.num_parents = 3,
+			.ops = &clk_rcg_ops,
+		},
+	},
+};
+
+static struct clk_branch vpe_clk = {
+	.halt_reg = 0x01c8,
+	.halt_bit = 28,
+	.hw = {
+		.enable_reg = 0x0110,
+		.enable_mask = BIT(0),
+		.init = &(struct clk_init_data){
+			.name = "vpe_clk",
+			.parent_names = (const char *[]){ "vpe_src" },
+			.num_parents = 1,
+			.ops = &clk_branch_ops,
+			.flags = CLK_SET_RATE_PARENT,
+		},
+	},
+};
+
+static struct freq_tbl clk_tbl_vfe[] = {
+	{  13960000, P_PLL8,  1, 2, 55 },
+	{  27000000, P_PXO,   1, 0,  0 },
+	{  36570000, P_PLL8,  1, 2, 21 },
+	{  38400000, P_PLL8,  2, 1,  5 },
+	{  45180000, P_PLL8,  1, 2, 17 },
+	{  48000000, P_PLL8,  2, 1,  4 },
+	{  54860000, P_PLL8,  1, 1,  7 },
+	{  64000000, P_PLL8,  2, 1,  3 },
+	{  76800000, P_PLL8,  1, 1,  5 },
+	{  96000000, P_PLL8,  2, 1,  2 },
+	{ 109710000, P_PLL8,  1, 2,  7 },
+	{ 128000000, P_PLL8,  1, 1,  3 },
+	{ 153600000, P_PLL8,  1, 2,  5 },
+	{ 200000000, P_PLL2,  2, 1,  2 },
+	{ 228570000, P_PLL2,  1, 2,  7 },
+	{ 266667000, P_PLL2,  1, 1,  3 },
+	{ 320000000, P_PLL2,  1, 2,  5 },
+	{ }
+};
+
+static struct clk_rcg vfe_src = {
+	.ns_reg = 0x0108,
+	.mn = {
+		.mnctr_en_bit = 5,
+		.mnctr_reset_bit = 7,
+		.mnctr_mode_shift = 6,
+		.n_val_shift = 16,
+		.m_val_shift = 8,
+		.width = 8,
+	},
+	.p = {
+		.pre_div_shift = 10,
+		.pre_div_width = 1,
+	},
+	.s = {
+		.src_sel_shift = 0,
+		.parent_map = mmcc_pxo_pll8_pll2_map,
+	},
+	.freq_tbl = clk_tbl_vfe,
+	.hw = {
+		.enable_reg = 0x0104,
+		.enable_mask = BIT(2),
+		.init = &(struct clk_init_data){
+			.name = "vfe_src",
+			.parent_names = mmcc_pxo_pll8_pll2,
+			.num_parents = 3,
+			.ops = &clk_rcg_ops,
+		},
+	},
+};
+
+static struct clk_branch vfe_clk = {
+	.halt_reg = 0x01cc,
+	.halt_bit = 6,
+	.hw = {
+		.enable_reg = 0x0104,
+		.enable_mask = BIT(0),
+		.init = &(struct clk_init_data){
+			.name = "vfe_clk",
+			.parent_names = (const char *[]){ "vfe_src" },
+			.num_parents = 1,
+			.ops = &clk_branch_ops,
+			.flags = CLK_SET_RATE_PARENT,
+		},
+	},
+};
+
+static struct clk_branch vfe_csi_clk = {
+	.halt_reg = 0x01cc,
+	.halt_bit = 8,
+	.hw = {
+		.enable_reg = 0x0104,
+		.enable_mask = BIT(12),
+		.init = &(struct clk_init_data){
+			.parent_names = (const char *[]){ "vfe_src" },
+			.num_parents = 1,
+			.name = "vfe_csi_clk",
+			.ops = &clk_branch_ops,
+			.flags = CLK_SET_RATE_PARENT,
+		},
+	},
+};
+
+static struct clk_branch gmem_axi_clk = {
+	.halt_reg = 0x01d8,
+	.halt_bit = 6,
+	.hw = {
+		.enable_reg = 0x0018,
+		.enable_mask = BIT(24),
+		.init = &(struct clk_init_data){
+			.name = "gmem_axi_clk",
+			.ops = &clk_branch_ops,
+			.flags = CLK_IS_ROOT,
+		},
+	},
+};
+
+static struct clk_branch ijpeg_axi_clk = {
+	.hwcg_reg = 0x0018,
+	.hwcg_bit = 11,
+	.halt_reg = 0x01d8,
+	.halt_bit = 4,
+	.hw = {
+		.enable_reg = 0x0018,
+		.enable_mask = BIT(21),
+		.init = &(struct clk_init_data){
+			.name = "ijpeg_axi_clk",
+			.ops = &clk_branch_ops,
+			.flags = CLK_IS_ROOT,
+		},
+	},
+};
+
+static struct clk_branch mmss_imem_axi_clk = {
+	.hwcg_reg = 0x0018,
+	.hwcg_bit = 15,
+	.halt_reg = 0x01d8,
+	.halt_bit = 7,
+	.hw = {
+		.enable_reg = 0x0018,
+		.enable_mask = BIT(22),
+		.init = &(struct clk_init_data){
+			.name = "mmss_imem_axi_clk",
+			.ops = &clk_branch_ops,
+			.flags = CLK_IS_ROOT,
+		},
+	},
+};
+
+static struct clk_branch jpegd_axi_clk = {
+	.halt_reg = 0x01d8,
+	.halt_bit = 5,
+	.hw = {
+		.enable_reg = 0x0018,
+		.enable_mask = BIT(25),
+		.init = &(struct clk_init_data){
+			.name = "jpegd_axi_clk",
+			.ops = &clk_branch_ops,
+			.flags = CLK_IS_ROOT,
+		},
+	},
+};
+
+static struct clk_branch vcodec_axi_b_clk = {
+	.hwcg_reg = 0x0114,
+	.hwcg_bit = 22,
+	.halt_reg = 0x01e8,
+	.halt_bit = 25,
+	.hw = {
+		.enable_reg = 0x0114,
+		.enable_mask = BIT(23),
+		.init = &(struct clk_init_data){
+			.name = "vcodec_axi_b_clk",
+			.ops = &clk_branch_ops,
+			.flags = CLK_IS_ROOT,
+		},
+	},
+};
+
+static struct clk_branch vcodec_axi_a_clk = {
+	.hwcg_reg = 0x0114,
+	.hwcg_bit = 24,
+	.halt_reg = 0x01e8,
+	.halt_bit = 26,
+	.hw = {
+		.enable_reg = 0x0114,
+		.enable_mask = BIT(25),
+		.init = &(struct clk_init_data){
+			.name = "vcodec_axi_a_clk",
+			.ops = &clk_branch_ops,
+			.flags = CLK_IS_ROOT,
+		},
+	},
+};
+
+static struct clk_branch vcodec_axi_clk = {
+	.hwcg_reg = 0x0018,
+	.hwcg_bit = 13,
+	.halt_reg = 0x01d8,
+	.halt_bit = 3,
+	.hw = {
+		.enable_reg = 0x0018,
+		.enable_mask = BIT(19),
+		.init = &(struct clk_init_data){
+			.name = "vcodec_axi_clk",
+			.ops = &clk_branch_ops,
+			.flags = CLK_IS_ROOT,
+		},
+	},
+};
+
+static struct clk_branch vfe_axi_clk = {
+	.halt_reg = 0x01d8,
+	.halt_bit = 0,
+	.hw = {
+		.enable_reg = 0x0018,
+		.enable_mask = BIT(18),
+		.init = &(struct clk_init_data){
+			.name = "vfe_axi_clk",
+			.ops = &clk_branch_ops,
+			.flags = CLK_IS_ROOT,
+		},
+	},
+};
+
+static struct clk_branch mdp_axi_clk = {
+	.hwcg_reg = 0x0018,
+	.hwcg_bit = 16,
+	.halt_reg = 0x01d8,
+	.halt_bit = 8,
+	.hw = {
+		.enable_reg = 0x0018,
+		.enable_mask = BIT(23),
+		.init = &(struct clk_init_data){
+			.name = "mdp_axi_clk",
+			.ops = &clk_branch_ops,
+			.flags = CLK_IS_ROOT,
+		},
+	},
+};
+
+static struct clk_branch rot_axi_clk = {
+	.hwcg_reg = 0x0020,
+	.hwcg_bit = 25,
+	.halt_reg = 0x01d8,
+	.halt_bit = 2,
+	.hw = {
+		.enable_reg = 0x0020,
+		.enable_mask = BIT(24),
+		.init = &(struct clk_init_data){
+			.name = "rot_axi_clk",
+			.ops = &clk_branch_ops,
+			.flags = CLK_IS_ROOT,
+		},
+	},
+};
+
+static struct clk_branch vpe_axi_clk = {
+	.hwcg_reg = 0x0020,
+	.hwcg_bit = 27,
+	.halt_reg = 0x01d8,
+	.halt_bit = 1,
+	.hw = {
+		.enable_reg = 0x0020,
+		.enable_mask = BIT(26),
+		.init = &(struct clk_init_data){
+			.name = "vpe_axi_clk",
+			.ops = &clk_branch_ops,
+			.flags = CLK_IS_ROOT,
+		},
+	},
+};
+
+static struct clk_branch gfx3d_axi_clk = {
+	.hwcg_reg = 0x0244,
+	.hwcg_bit = 24,
+	.halt_reg = 0x0240,
+	.halt_bit = 30,
+	.hw = {
+		.enable_reg = 0x0244,
+		.enable_mask = BIT(25),
+		.init = &(struct clk_init_data){
+			.name = "gfx3d_axi_clk",
+			.ops = &clk_branch_ops,
+			.flags = CLK_IS_ROOT,
+		},
+	},
+};
+
+static struct clk_branch amp_ahb_clk = {
+	.halt_reg = 0x01dc,
+	.halt_bit = 18,
+	.hw = {
+		.enable_reg = 0x0008,
+		.enable_mask = BIT(24),
+		.init = &(struct clk_init_data){
+			.name = "amp_ahb_clk",
+			.ops = &clk_branch_ops,
+			.flags = CLK_IS_ROOT,
+		},
+	},
+};
+
+static struct clk_branch csi_ahb_clk = {
+	.halt_reg = 0x01dc,
+	.halt_bit = 16,
+	.hw = {
+		.enable_reg = 0x0008,
+		.enable_mask = BIT(7),
+		.init = &(struct clk_init_data){
+			.name = "csi_ahb_clk",
+			.ops = &clk_branch_ops,
+			.flags = CLK_IS_ROOT
+		},
+	},
+};
+
+static struct clk_branch dsi_m_ahb_clk = {
+	.halt_reg = 0x01dc,
+	.halt_bit = 19,
+	.hw = {
+		.enable_reg = 0x0008,
+		.enable_mask = BIT(9),
+		.init = &(struct clk_init_data){
+			.name = "dsi_m_ahb_clk",
+			.ops = &clk_branch_ops,
+			.flags = CLK_IS_ROOT,
+		},
+	},
+};
+
+static struct clk_branch dsi_s_ahb_clk = {
+	.hwcg_reg = 0x0038,
+	.hwcg_bit = 20,
+	.halt_reg = 0x01dc,
+	.halt_bit = 21,
+	.hw = {
+		.enable_reg = 0x0008,
+		.enable_mask = BIT(18),
+		.init = &(struct clk_init_data){
+			.name = "dsi_s_ahb_clk",
+			.ops = &clk_branch_ops,
+			.flags = CLK_IS_ROOT,
+		},
+	},
+};
+
+static struct clk_branch dsi2_m_ahb_clk = {
+	.halt_reg = 0x01d8,
+	.halt_bit = 18,
+	.hw = {
+		.enable_reg = 0x0008,
+		.enable_mask = BIT(17),
+		.init = &(struct clk_init_data){
+			.name = "dsi2_m_ahb_clk",
+			.ops = &clk_branch_ops,
+			.flags = CLK_IS_ROOT
+		},
+	},
+};
+
+static struct clk_branch dsi2_s_ahb_clk = {
+	.hwcg_reg = 0x0038,
+	.hwcg_bit = 15,
+	.halt_reg = 0x01dc,
+	.halt_bit = 20,
+	.hw = {
+		.enable_reg = 0x0008,
+		.enable_mask = BIT(22),
+		.init = &(struct clk_init_data){
+			.name = "dsi2_s_ahb_clk",
+			.ops = &clk_branch_ops,
+			.flags = CLK_IS_ROOT,
+		},
+	},
+};
+
+static struct clk_branch gfx2d0_ahb_clk = {
+	.hwcg_reg = 0x0038,
+	.hwcg_bit = 28,
+	.halt_reg = 0x01dc,
+	.halt_bit = 2,
+	.hw = {
+		.enable_reg = 0x0008,
+		.enable_mask = BIT(19),
+		.init = &(struct clk_init_data){
+			.name = "gfx2d0_ahb_clk",
+			.ops = &clk_branch_ops,
+			.flags = CLK_IS_ROOT,
+		},
+	},
+};
+
+static struct clk_branch gfx2d1_ahb_clk = {
+	.hwcg_reg = 0x0038,
+	.hwcg_bit = 29,
+	.halt_reg = 0x01dc,
+	.halt_bit = 3,
+	.hw = {
+		.enable_reg = 0x0008,
+		.enable_mask = BIT(2),
+		.init = &(struct clk_init_data){
+			.name = "gfx2d1_ahb_clk",
+			.ops = &clk_branch_ops,
+			.flags = CLK_IS_ROOT,
+		},
+	},
+};
+
+static struct clk_branch gfx3d_ahb_clk = {
+	.hwcg_reg = 0x0038,
+	.hwcg_bit = 27,
+	.halt_reg = 0x01dc,
+	.halt_bit = 4,
+	.hw = {
+		.enable_reg = 0x0008,
+		.enable_mask = BIT(3),
+		.init = &(struct clk_init_data){
+			.name = "gfx3d_ahb_clk",
+			.ops = &clk_branch_ops,
+			.flags = CLK_IS_ROOT,
+		},
+	},
+};
+
+static struct clk_branch hdmi_m_ahb_clk = {
+	.hwcg_reg = 0x0038,
+	.hwcg_bit = 21,
+	.halt_reg = 0x01dc,
+	.halt_bit = 5,
+	.hw = {
+		.enable_reg = 0x0008,
+		.enable_mask = BIT(14),
+		.init = &(struct clk_init_data){
+			.name = "hdmi_m_ahb_clk",
+			.ops = &clk_branch_ops,
+			.flags = CLK_IS_ROOT,
+		},
+	},
+};
+
+static struct clk_branch hdmi_s_ahb_clk = {
+	.hwcg_reg = 0x0038,
+	.hwcg_bit = 22,
+	.halt_reg = 0x01dc,
+	.halt_bit = 6,
+	.hw = {
+		.enable_reg = 0x0008,
+		.enable_mask = BIT(4),
+		.init = &(struct clk_init_data){
+			.name = "hdmi_s_ahb_clk",
+			.ops = &clk_branch_ops,
+			.flags = CLK_IS_ROOT,
+		},
+	},
+};
+
+static struct clk_branch ijpeg_ahb_clk = {
+	.halt_reg = 0x01dc,
+	.halt_bit = 9,
+	.hw = {
+		.enable_reg = 0x0008,
+		.enable_mask = BIT(5),
+		.init = &(struct clk_init_data){
+			.name = "ijpeg_ahb_clk",
+			.ops = &clk_branch_ops,
+			.flags = CLK_IS_ROOT
+		},
+	},
+};
+
+static struct clk_branch mmss_imem_ahb_clk = {
+	.hwcg_reg = 0x0038,
+	.hwcg_bit = 12,
+	.halt_reg = 0x01dc,
+	.halt_bit = 10,
+	.hw = {
+		.enable_reg = 0x0008,
+		.enable_mask = BIT(6),
+		.init = &(struct clk_init_data){
+			.name = "mmss_imem_ahb_clk",
+			.ops = &clk_branch_ops,
+			.flags = CLK_IS_ROOT
+		},
+	},
+};
+
+static struct clk_branch jpegd_ahb_clk = {
+	.halt_reg = 0x01dc,
+	.halt_bit = 7,
+	.hw = {
+		.enable_reg = 0x0008,
+		.enable_mask = BIT(21),
+		.init = &(struct clk_init_data){
+			.name = "jpegd_ahb_clk",
+			.ops = &clk_branch_ops,
+			.flags = CLK_IS_ROOT,
+		},
+	},
+};
+
+static struct clk_branch mdp_ahb_clk = {
+	.halt_reg = 0x01dc,
+	.halt_bit = 11,
+	.hw = {
+		.enable_reg = 0x0008,
+		.enable_mask = BIT(10),
+		.init = &(struct clk_init_data){
+			.name = "mdp_ahb_clk",
+			.ops = &clk_branch_ops,
+			.flags = CLK_IS_ROOT,
+		},
+	},
+};
+
+static struct clk_branch rot_ahb_clk = {
+	.halt_reg = 0x01dc,
+	.halt_bit = 13,
+	.hw = {
+		.enable_reg = 0x0008,
+		.enable_mask = BIT(12),
+		.init = &(struct clk_init_data){
+			.name = "rot_ahb_clk",
+			.ops = &clk_branch_ops,
+			.flags = CLK_IS_ROOT
+		},
+	},
+};
+
+static struct clk_branch smmu_ahb_clk = {
+	.hwcg_reg = 0x0008,
+	.hwcg_bit = 26,
+	.halt_reg = 0x01dc,
+	.halt_bit = 22,
+	.hw = {
+		.enable_reg = 0x0008,
+		.enable_mask = BIT(15),
+		.init = &(struct clk_init_data){
+			.name = "smmu_ahb_clk",
+			.ops = &clk_branch_ops,
+			.flags = CLK_IS_ROOT,
+		},
+	},
+};
+
+static struct clk_branch tv_enc_ahb_clk = {
+	.halt_reg = 0x01dc,
+	.halt_bit = 23,
+	.hw = {
+		.enable_reg = 0x0008,
+		.enable_mask = BIT(25),
+		.init = &(struct clk_init_data){
+			.name = "tv_enc_ahb_clk",
+			.ops = &clk_branch_ops,
+			.flags = CLK_IS_ROOT,
+		},
+	},
+};
+
+static struct clk_branch vcodec_ahb_clk = {
+	.hwcg_reg = 0x0038,
+	.hwcg_bit = 26,
+	.halt_reg = 0x01dc,
+	.halt_bit = 12,
+	.hw = {
+		.enable_reg = 0x0008,
+		.enable_mask = BIT(11),
+		.init = &(struct clk_init_data){
+			.name = "vcodec_ahb_clk",
+			.ops = &clk_branch_ops,
+			.flags = CLK_IS_ROOT,
+		},
+	},
+};
+
+static struct clk_branch vfe_ahb_clk = {
+	.halt_reg = 0x01dc,
+	.halt_bit = 14,
+	.hw = {
+		.enable_reg = 0x0008,
+		.enable_mask = BIT(13),
+		.init = &(struct clk_init_data){
+			.name = "vfe_ahb_clk",
+			.ops = &clk_branch_ops,
+			.flags = CLK_IS_ROOT,
+		},
+	},
+};
+
+static struct clk_branch vpe_ahb_clk = {
+	.halt_reg = 0x01dc,
+	.halt_bit = 15,
+	.hw = {
+		.enable_reg = 0x0008,
+		.enable_mask = BIT(16),
+		.init = &(struct clk_init_data){
+			.name = "vpe_ahb_clk",
+			.ops = &clk_branch_ops,
+			.flags = CLK_IS_ROOT,
+		},
+	},
+};
+
+static struct clk_hw *mmcc_msm8960_clks[] = {
+	[TV_ENC_AHB_CLK] = &tv_enc_ahb_clk.hw,
+	[AMP_AHB_CLK] = &amp_ahb_clk.hw,
+	[DSI2_S_AHB_CLK] = &dsi2_s_ahb_clk.hw,
+	[JPEGD_AHB_CLK] = &jpegd_ahb_clk.hw,
+	[GFX2D0_AHB_CLK] = &gfx2d0_ahb_clk.hw,
+	[DSI_S_AHB_CLK] = &dsi_s_ahb_clk.hw,
+	[DSI2_M_AHB_CLK] = &dsi2_m_ahb_clk.hw,
+	[VPE_AHB_CLK] = &vpe_ahb_clk.hw,
+	[SMMU_AHB_CLK] = &smmu_ahb_clk.hw,
+	[HDMI_M_AHB_CLK] = &hdmi_m_ahb_clk.hw,
+	[VFE_AHB_CLK] = &vfe_ahb_clk.hw,
+	[ROT_AHB_CLK] = &rot_ahb_clk.hw,
+	[VCODEC_AHB_CLK] = &vcodec_ahb_clk.hw,
+	[MDP_AHB_CLK] = &mdp_ahb_clk.hw,
+	[DSI_M_AHB_CLK] = &dsi_m_ahb_clk.hw,
+	[CSI_AHB_CLK] = &csi_ahb_clk.hw,
+	[MMSS_IMEM_AHB_CLK] = &mmss_imem_ahb_clk.hw,
+	[IJPEG_AHB_CLK] = &ijpeg_ahb_clk.hw,
+	[HDMI_S_AHB_CLK] = &hdmi_s_ahb_clk.hw,
+	[GFX3D_AHB_CLK] = &gfx3d_ahb_clk.hw,
+	[GFX2D1_AHB_CLK] = &gfx2d1_ahb_clk.hw,
+	[JPEGD_AXI_CLK] = &jpegd_axi_clk.hw,
+	[GMEM_AXI_CLK] = &gmem_axi_clk.hw,
+	[MDP_AXI_CLK] = &mdp_axi_clk.hw,
+	[MMSS_IMEM_AXI_CLK] = &mmss_imem_axi_clk.hw,
+	[IJPEG_AXI_CLK] = &ijpeg_axi_clk.hw,
+	[GFX3D_AXI_CLK] = &gfx3d_axi_clk.hw,
+	[VCODEC_AXI_CLK] = &vcodec_axi_clk.hw,
+	[VFE_AXI_CLK] = &vfe_axi_clk.hw,
+	[VPE_AXI_CLK] = &vpe_axi_clk.hw,
+	[ROT_AXI_CLK] = &rot_axi_clk.hw,
+	[VCODEC_AXI_A_CLK] = &vcodec_axi_a_clk.hw,
+	[VCODEC_AXI_B_CLK] = &vcodec_axi_b_clk.hw,
+	[CSI0_SRC] = &csi0_src.hw,
+	[CSI0_CLK] = &csi0_clk.hw,
+	[CSI0_PHY_CLK] = &csi0_phy_clk.hw,
+	[CSI1_SRC] = &csi1_src.hw,
+	[CSI1_CLK] = &csi1_clk.hw,
+	[CSI1_PHY_CLK] = &csi1_phy_clk.hw,
+	[CSI2_SRC] = &csi2_src.hw,
+	[CSI2_CLK] = &csi2_clk.hw,
+	[CSI2_PHY_CLK] = &csi2_phy_clk.hw,
+	[CSI_PIX_CLK] = &csi_pix_clk.hw,
+	[CSI_RDI_CLK] = &csi_rdi_clk.hw,
+	[MDP_VSYNC_CLK] = &mdp_vsync_clk.hw,
+	[HDMI_APP_CLK] = &hdmi_app_clk.hw,
+	[CSI_PIX1_CLK] = &csi_pix1_clk.hw,
+	[CSI_RDI2_CLK] = &csi_rdi2_clk.hw,
+	[CSI_RDI1_CLK] = &csi_rdi1_clk.hw,
+	[GFX2D0_SRC] = &gfx2d0_src.hw,
+	[GFX2D0_CLK] = &gfx2d0_clk.hw,
+	[GFX2D1_SRC] = &gfx2d1_src.hw,
+	[GFX2D1_CLK] = &gfx2d1_clk.hw,
+	[GFX3D_SRC] = &gfx3d_src.hw,
+	[GFX3D_CLK] = &gfx3d_clk.hw,
+	[IJPEG_SRC] = &ijpeg_src.hw,
+	[IJPEG_CLK] = &ijpeg_clk.hw,
+	[JPEGD_SRC] = &jpegd_src.hw,
+	[JPEGD_CLK] = &jpegd_clk.hw,
+	[MDP_SRC] = &mdp_src.hw,
+	[MDP_CLK] = &mdp_clk.hw,
+	[MDP_LUT_CLK] = &mdp_lut_clk.hw,
+	[ROT_SRC] = &rot_src.hw,
+	[ROT_CLK] = &rot_clk.hw,
+	[TV_ENC_CLK] = &tv_enc_clk.hw,
+	[TV_DAC_CLK] = &tv_dac_clk.hw,
+	[HDMI_TV_CLK] = &hdmi_tv_clk.hw,
+	[MDP_TV_CLK] = &mdp_tv_clk.hw,
+	[TV_SRC] = &tv_src.hw,
+	[VCODEC_SRC] = &vcodec_src.hw,
+	[VCODEC_CLK] = &vcodec_clk.hw,
+	[VFE_SRC] = &vfe_src.hw,
+	[VFE_CLK] = &vfe_clk.hw,
+	[VFE_CSI_CLK] = &vfe_csi_clk.hw,
+	[VPE_SRC] = &vpe_src.hw,
+	[VPE_CLK] = &vpe_clk.hw,
+	[CAMCLK0_SRC] = &camclk0_src.hw,
+	[CAMCLK0_CLK] = &camclk0_clk.hw,
+	[CAMCLK1_SRC] = &camclk1_src.hw,
+	[CAMCLK1_CLK] = &camclk1_clk.hw,
+	[CAMCLK2_SRC] = &camclk2_src.hw,
+	[CAMCLK2_CLK] = &camclk2_clk.hw,
+	[CSIPHYTIMER_SRC] = &csiphytimer_src.hw,
+	[CSIPHY2_TIMER_CLK] = &csiphy2_timer_clk.hw,
+	[CSIPHY1_TIMER_CLK] = &csiphy1_timer_clk.hw,
+	[CSIPHY0_TIMER_CLK] = &csiphy0_timer_clk.hw,
+	[PLL2] = &pll2.hw,
+};
+
+static const struct qcom_reset_map mmcc_msm8960_resets[] = {
+	[VPE_AXI_RESET] = { 0x0208, 15 },
+	[IJPEG_AXI_RESET] = { 0x0208, 14 },
+	[MPD_AXI_RESET] = { 0x0208, 13 },
+	[VFE_AXI_RESET] = { 0x0208, 9 },
+	[SP_AXI_RESET] = { 0x0208, 8 },
+	[VCODEC_AXI_RESET] = { 0x0208, 7 },
+	[ROT_AXI_RESET] = { 0x0208, 6 },
+	[VCODEC_AXI_A_RESET] = { 0x0208, 5 },
+	[VCODEC_AXI_B_RESET] = { 0x0208, 4 },
+	[FAB_S3_AXI_RESET] = { 0x0208, 3 },
+	[FAB_S2_AXI_RESET] = { 0x0208, 2 },
+	[FAB_S1_AXI_RESET] = { 0x0208, 1 },
+	[FAB_S0_AXI_RESET] = { 0x0208 },
+	[SMMU_GFX3D_ABH_RESET] = { 0x020c, 31 },
+	[SMMU_VPE_AHB_RESET] = { 0x020c, 30 },
+	[SMMU_VFE_AHB_RESET] = { 0x020c, 29 },
+	[SMMU_ROT_AHB_RESET] = { 0x020c, 28 },
+	[SMMU_VCODEC_B_AHB_RESET] = { 0x020c, 27 },
+	[SMMU_VCODEC_A_AHB_RESET] = { 0x020c, 26 },
+	[SMMU_MDP1_AHB_RESET] = { 0x020c, 25 },
+	[SMMU_MDP0_AHB_RESET] = { 0x020c, 24 },
+	[SMMU_JPEGD_AHB_RESET] = { 0x020c, 23 },
+	[SMMU_IJPEG_AHB_RESET] = { 0x020c, 22 },
+	[SMMU_GFX2D0_AHB_RESET] = { 0x020c, 21 },
+	[SMMU_GFX2D1_AHB_RESET] = { 0x020c, 20 },
+	[APU_AHB_RESET] = { 0x020c, 18 },
+	[CSI_AHB_RESET] = { 0x020c, 17 },
+	[TV_ENC_AHB_RESET] = { 0x020c, 15 },
+	[VPE_AHB_RESET] = { 0x020c, 14 },
+	[FABRIC_AHB_RESET] = { 0x020c, 13 },
+	[GFX2D0_AHB_RESET] = { 0x020c, 12 },
+	[GFX2D1_AHB_RESET] = { 0x020c, 11 },
+	[GFX3D_AHB_RESET] = { 0x020c, 10 },
+	[HDMI_AHB_RESET] = { 0x020c, 9 },
+	[MSSS_IMEM_AHB_RESET] = { 0x020c, 8 },
+	[IJPEG_AHB_RESET] = { 0x020c, 7 },
+	[DSI_M_AHB_RESET] = { 0x020c, 6 },
+	[DSI_S_AHB_RESET] = { 0x020c, 5 },
+	[JPEGD_AHB_RESET] = { 0x020c, 4 },
+	[MDP_AHB_RESET] = { 0x020c, 3 },
+	[ROT_AHB_RESET] = { 0x020c, 2 },
+	[VCODEC_AHB_RESET] = { 0x020c, 1 },
+	[VFE_AHB_RESET] = { 0x020c, 0 },
+	[DSI2_M_AHB_RESET] = { 0x0210, 31 },
+	[DSI2_S_AHB_RESET] = { 0x0210, 30 },
+	[CSIPHY2_RESET] = { 0x0210, 29 },
+	[CSI_PIX1_RESET] = { 0x0210, 28 },
+	[CSIPHY0_RESET] = { 0x0210, 27 },
+	[CSIPHY1_RESET] = { 0x0210, 26 },
+	[DSI2_RESET] = { 0x0210, 25 },
+	[VFE_CSI_RESET] = { 0x0210, 24 },
+	[MDP_RESET] = { 0x0210, 21 },
+	[AMP_RESET] = { 0x0210, 20 },
+	[JPEGD_RESET] = { 0x0210, 19 },
+	[CSI1_RESET] = { 0x0210, 18 },
+	[VPE_RESET] = { 0x0210, 17 },
+	[MMSS_FABRIC_RESET] = { 0x0210, 16 },
+	[VFE_RESET] = { 0x0210, 15 },
+	[GFX2D0_RESET] = { 0x0210, 14 },
+	[GFX2D1_RESET] = { 0x0210, 13 },
+	[GFX3D_RESET] = { 0x0210, 12 },
+	[HDMI_RESET] = { 0x0210, 11 },
+	[MMSS_IMEM_RESET] = { 0x0210, 10 },
+	[IJPEG_RESET] = { 0x0210, 9 },
+	[CSI0_RESET] = { 0x0210, 8 },
+	[DSI_RESET] = { 0x0210, 7 },
+	[VCODEC_RESET] = { 0x0210, 6 },
+	[MDP_TV_RESET] = { 0x0210, 4 },
+	[MDP_VSYNC_RESET] = { 0x0210, 3 },
+	[ROT_RESET] = { 0x0210, 2 },
+	[TV_HDMI_RESET] = { 0x0210, 1 },
+	[TV_ENC_RESET] = { 0x0210 },
+	[CSI2_RESET] = { 0x0214, 2 },
+	[CSI_RDI1_RESET] = { 0x0214, 1 },
+	[CSI_RDI2_RESET] = { 0x0214 },
+};
+
+static const struct regmap_config mmcc_msm8960_regmap_config = {
+	.reg_bits	= 32,
+	.reg_stride	= 4,
+	.val_bits	= 32,
+	.max_register	= 0x334,
+	.fast_io	= true,
+};
+
+static const struct of_device_id mmcc_msm8960_match_table[] = {
+	{ .compatible = "qcom,mmcc-msm8960" },
+	{ }
+};
+MODULE_DEVICE_TABLE(of, mmcc_msm8960_match_table);
+
+struct qcom_cc {
+	struct qcom_reset_controller reset;
+	struct clk_onecell_data data;
+	struct clk *clks[];
+};
+
+static int mmcc_msm8960_probe(struct platform_device *pdev)
+{
+	void __iomem *base;
+	struct resource *res;
+	int i, ret;
+	struct device *dev = &pdev->dev;
+	struct clk *clk;
+	struct clk_onecell_data *data;
+	struct clk **clks;
+	struct regmap *regmap;
+	size_t num_clks;
+	struct qcom_reset_controller *reset;
+	struct qcom_cc *cc;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	base = devm_ioremap_resource(dev, res);
+	if (IS_ERR(base))
+		return PTR_ERR(base);
+
+	regmap = devm_regmap_init_mmio(dev, base, &mmcc_msm8960_regmap_config);
+	if (IS_ERR(regmap))
+		return PTR_ERR(regmap);
+
+	num_clks = ARRAY_SIZE(mmcc_msm8960_clks);
+	cc = devm_kzalloc(dev, sizeof(*cc) + sizeof(*clks) * num_clks,
+			  GFP_KERNEL);
+	if (!cc)
+		return -ENOMEM;
+
+	clks = cc->clks;
+	data = &cc->data;
+	data->clks = clks;
+	data->clk_num = num_clks;
+
+	for (i = 0; i < num_clks; i++) {
+		if (!mmcc_msm8960_clks[i])
+			continue;
+		clk = devm_clk_register(dev, mmcc_msm8960_clks[i]);
+		if (IS_ERR(clk))
+			return PTR_ERR(clk);
+		clks[i] = clk;
+	}
+
+	ret = of_clk_add_provider(dev->of_node, of_clk_src_onecell_get, data);
+	if (ret)
+		return ret;
+
+	reset = &cc->reset;
+	reset->rcdev.of_node = dev->of_node;
+	reset->rcdev.ops = &qcom_reset_ops,
+	reset->rcdev.owner = THIS_MODULE,
+	reset->rcdev.nr_resets = ARRAY_SIZE(mmcc_msm8960_resets),
+	reset->regmap = regmap;
+	reset->reset_map = mmcc_msm8960_resets,
+	platform_set_drvdata(pdev, &reset->rcdev);
+
+	ret = reset_controller_register(&reset->rcdev);
+	if (ret)
+		of_clk_del_provider(dev->of_node);
+
+	return ret;
+}
+
+static int mmcc_msm8960_remove(struct platform_device *pdev)
+{
+	of_clk_del_provider(pdev->dev.of_node);
+	reset_controller_unregister(platform_get_drvdata(pdev));
+	return 0;
+}
+
+static struct platform_driver mmcc_msm8960_driver = {
+	.probe		= mmcc_msm8960_probe,
+	.remove		= mmcc_msm8960_remove,
+	.driver		= {
+		.name	= "mmcc-msm8960",
+		.owner	= THIS_MODULE,
+		.of_match_table = mmcc_msm8960_match_table,
+	},
+};
+
+module_platform_driver(mmcc_msm8960_driver);
+
+MODULE_DESCRIPTION("QCOM MMCC MSM8960 Driver");
+MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("platform:mmcc-msm8960");
diff --git a/include/dt-bindings/clock/qcom,mmcc-msm8960.h b/include/dt-bindings/clock/qcom,mmcc-msm8960.h
new file mode 100644
index 0000000..5868ef1
--- /dev/null
+++ b/include/dt-bindings/clock/qcom,mmcc-msm8960.h
@@ -0,0 +1,137 @@
+/*
+ * Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef _DT_BINDINGS_CLK_MSM_MMCC_8960_H
+#define _DT_BINDINGS_CLK_MSM_MMCC_8960_H
+
+#define MMSS_AHB_SRC					0
+#define FAB_AHB_CLK					1
+#define APU_AHB_CLK					2
+#define TV_ENC_AHB_CLK					3
+#define AMP_AHB_CLK					4
+#define DSI2_S_AHB_CLK					5
+#define JPEGD_AHB_CLK					6
+#define GFX2D0_AHB_CLK					7
+#define DSI_S_AHB_CLK					8
+#define DSI2_M_AHB_CLK					9
+#define VPE_AHB_CLK					10
+#define SMMU_AHB_CLK					11
+#define HDMI_M_AHB_CLK					12
+#define VFE_AHB_CLK					13
+#define ROT_AHB_CLK					14
+#define VCODEC_AHB_CLK					15
+#define MDP_AHB_CLK					16
+#define DSI_M_AHB_CLK					17
+#define CSI_AHB_CLK					18
+#define MMSS_IMEM_AHB_CLK				19
+#define IJPEG_AHB_CLK					20
+#define HDMI_S_AHB_CLK					21
+#define GFX3D_AHB_CLK					22
+#define GFX2D1_AHB_CLK					23
+#define MMSS_FPB_CLK					24
+#define MMSS_AXI_SRC					25
+#define MMSS_FAB_CORE					26
+#define FAB_MSP_AXI_CLK					27
+#define JPEGD_AXI_CLK					28
+#define GMEM_AXI_CLK					29
+#define MDP_AXI_CLK					30
+#define MMSS_IMEM_AXI_CLK				31
+#define IJPEG_AXI_CLK					32
+#define GFX3D_AXI_CLK					33
+#define VCODEC_AXI_CLK					34
+#define VFE_AXI_CLK					35
+#define VPE_AXI_CLK					36
+#define ROT_AXI_CLK					37
+#define VCODEC_AXI_A_CLK				38
+#define VCODEC_AXI_B_CLK				39
+#define MM_AXI_S3_FCLK					40
+#define MM_AXI_S2_FCLK					41
+#define MM_AXI_S1_FCLK					42
+#define MM_AXI_S0_FCLK					43
+#define MM_AXI_S2_CLK					44
+#define MM_AXI_S1_CLK					45
+#define MM_AXI_S0_CLK					46
+#define CSI0_SRC					47
+#define CSI0_CLK					48
+#define CSI0_PHY_CLK					49
+#define CSI1_SRC					50
+#define CSI1_CLK					51
+#define CSI1_PHY_CLK					52
+#define CSI2_SRC					53
+#define CSI2_CLK					54
+#define CSI2_PHY_CLK					55
+#define DSI_SRC						56
+#define DSI_CLK						57
+#define CSI_PIX_CLK					58
+#define CSI_RDI_CLK					59
+#define MDP_VSYNC_CLK					60
+#define HDMI_DIV_CLK					61
+#define HDMI_APP_CLK					62
+#define CSI_PIX1_CLK					63
+#define CSI_RDI2_CLK					64
+#define CSI_RDI1_CLK					65
+#define GFX2D0_SRC					66
+#define GFX2D0_CLK					67
+#define GFX2D1_SRC					68
+#define GFX2D1_CLK					69
+#define GFX3D_SRC					70
+#define GFX3D_CLK					71
+#define IJPEG_SRC					72
+#define IJPEG_CLK					73
+#define JPEGD_SRC					74
+#define JPEGD_CLK					75
+#define MDP_SRC						76
+#define MDP_CLK						77
+#define MDP_LUT_CLK					78
+#define DSI2_PIXEL_SRC					79
+#define DSI2_PIXEL_CLK					80
+#define DSI2_SRC					81
+#define DSI2_CLK					82
+#define DSI1_BYTE_SRC					83
+#define DSI1_BYTE_CLK					84
+#define DSI2_BYTE_SRC					85
+#define DSI2_BYTE_CLK					86
+#define DSI1_ESC_SRC					87
+#define DSI1_ESC_CLK					88
+#define DSI2_ESC_SRC					89
+#define DSI2_ESC_CLK					90
+#define ROT_SRC						91
+#define ROT_CLK						92
+#define TV_ENC_CLK					93
+#define TV_DAC_CLK					94
+#define HDMI_TV_CLK					95
+#define MDP_TV_CLK					96
+#define TV_SRC						97
+#define VCODEC_SRC					98
+#define VCODEC_CLK					99
+#define VFE_SRC						100
+#define VFE_CLK						101
+#define VFE_CSI_CLK					102
+#define VPE_SRC						103
+#define VPE_CLK						104
+#define DSI_PIXEL_SRC					105
+#define DSI_PIXEL_CLK					106
+#define CAMCLK0_SRC					107
+#define CAMCLK0_CLK					108
+#define CAMCLK1_SRC					109
+#define CAMCLK1_CLK					110
+#define CAMCLK2_SRC					111
+#define CAMCLK2_CLK					112
+#define CSIPHYTIMER_SRC					113
+#define CSIPHY2_TIMER_CLK				114
+#define CSIPHY1_TIMER_CLK				115
+#define CSIPHY0_TIMER_CLK				116
+#define PLL1						117
+#define PLL2						118
+
+#endif
diff --git a/include/dt-bindings/reset/qcom,mmcc-msm8960.h b/include/dt-bindings/reset/qcom,mmcc-msm8960.h
new file mode 100644
index 0000000..ba36ec6
--- /dev/null
+++ b/include/dt-bindings/reset/qcom,mmcc-msm8960.h
@@ -0,0 +1,93 @@
+/*
+ * Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef _DT_BINDINGS_RESET_MSM_MMCC_8960_H
+#define _DT_BINDINGS_RESET_MSM_MMCC_8960_H
+
+#define VPE_AXI_RESET					0
+#define IJPEG_AXI_RESET					1
+#define MPD_AXI_RESET					2
+#define VFE_AXI_RESET					3
+#define SP_AXI_RESET					4
+#define VCODEC_AXI_RESET				5
+#define ROT_AXI_RESET					6
+#define VCODEC_AXI_A_RESET				7
+#define VCODEC_AXI_B_RESET				8
+#define FAB_S3_AXI_RESET				9
+#define FAB_S2_AXI_RESET				10
+#define FAB_S1_AXI_RESET				11
+#define FAB_S0_AXI_RESET				12
+#define SMMU_GFX3D_ABH_RESET				13
+#define SMMU_VPE_AHB_RESET				14
+#define SMMU_VFE_AHB_RESET				15
+#define SMMU_ROT_AHB_RESET				16
+#define SMMU_VCODEC_B_AHB_RESET				17
+#define SMMU_VCODEC_A_AHB_RESET				18
+#define SMMU_MDP1_AHB_RESET				19
+#define SMMU_MDP0_AHB_RESET				20
+#define SMMU_JPEGD_AHB_RESET				21
+#define SMMU_IJPEG_AHB_RESET				22
+#define SMMU_GFX2D0_AHB_RESET				23
+#define SMMU_GFX2D1_AHB_RESET				24
+#define APU_AHB_RESET					25
+#define CSI_AHB_RESET					26
+#define TV_ENC_AHB_RESET				27
+#define VPE_AHB_RESET					28
+#define FABRIC_AHB_RESET				29
+#define GFX2D0_AHB_RESET				30
+#define GFX2D1_AHB_RESET				31
+#define GFX3D_AHB_RESET					32
+#define HDMI_AHB_RESET					33
+#define MSSS_IMEM_AHB_RESET				34
+#define IJPEG_AHB_RESET					35
+#define DSI_M_AHB_RESET					36
+#define DSI_S_AHB_RESET					37
+#define JPEGD_AHB_RESET					38
+#define MDP_AHB_RESET					39
+#define ROT_AHB_RESET					40
+#define VCODEC_AHB_RESET				41
+#define VFE_AHB_RESET					42
+#define DSI2_M_AHB_RESET				43
+#define DSI2_S_AHB_RESET				44
+#define CSIPHY2_RESET					45
+#define CSI_PIX1_RESET					46
+#define CSIPHY0_RESET					47
+#define CSIPHY1_RESET					48
+#define DSI2_RESET					49
+#define VFE_CSI_RESET					50
+#define MDP_RESET					51
+#define AMP_RESET					52
+#define JPEGD_RESET					53
+#define CSI1_RESET					54
+#define VPE_RESET					55
+#define MMSS_FABRIC_RESET				56
+#define VFE_RESET					57
+#define GFX2D0_RESET					58
+#define GFX2D1_RESET					59
+#define GFX3D_RESET					60
+#define HDMI_RESET					61
+#define MMSS_IMEM_RESET					62
+#define IJPEG_RESET					63
+#define CSI0_RESET					64
+#define DSI_RESET					65
+#define VCODEC_RESET					66
+#define MDP_TV_RESET					67
+#define MDP_VSYNC_RESET					68
+#define ROT_RESET					69
+#define TV_HDMI_RESET					70
+#define TV_ENC_RESET					71
+#define CSI2_RESET					72
+#define CSI_RDI1_RESET					73
+#define CSI_RDI2_RESET					74
+
+#endif
-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
hosted by The Linux Foundation

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

* [PATCH v4 11/15] clk: qcom: Add support for MSM8974's global clock controller (GCC)
  2013-12-24  1:12 [PATCH v4 00/15] Add support for MSM's mmio clock/reset controller Stephen Boyd
                   ` (9 preceding siblings ...)
  2013-12-24  1:12 ` [PATCH v4 10/15] clk: qcom: Add support for MSM8960's multimedia clock controller (MMCC) Stephen Boyd
@ 2013-12-24  1:12 ` Stephen Boyd
  2013-12-24  1:12 ` [PATCH v4 12/15] clk: qcom: Add support for MSM8974's multimedia clock controller (MMCC) Stephen Boyd
                   ` (3 subsequent siblings)
  14 siblings, 0 replies; 34+ messages in thread
From: Stephen Boyd @ 2013-12-24  1:12 UTC (permalink / raw)
  To: Mike Turquette
  Cc: linux-kernel, linux-arm-msm, linux-arm-kernel, Saravana Kannan

Add a driver for the global clock controller found on MSM 8974
based platforms. This should allow most non-multimedia device
drivers to probe and control their clocks.

Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
---
 drivers/clk/qcom/Kconfig                     |    8 +
 drivers/clk/qcom/Makefile                    |    1 +
 drivers/clk/qcom/gcc-msm8974.c               | 2693 ++++++++++++++++++++++++++
 include/dt-bindings/clock/qcom,gcc-msm8974.h |  320 +++
 include/dt-bindings/reset/qcom,gcc-msm8974.h |   96 +
 5 files changed, 3118 insertions(+)
 create mode 100644 drivers/clk/qcom/gcc-msm8974.c
 create mode 100644 include/dt-bindings/clock/qcom,gcc-msm8974.h
 create mode 100644 include/dt-bindings/reset/qcom,gcc-msm8974.h

diff --git a/drivers/clk/qcom/Kconfig b/drivers/clk/qcom/Kconfig
index 7152693..7a13251 100644
--- a/drivers/clk/qcom/Kconfig
+++ b/drivers/clk/qcom/Kconfig
@@ -20,3 +20,11 @@ config MSM_MMCC_8960
 	  Support for the multimedia clock controller on msm8960 devices.
 	  Say Y if you want to support multimedia devices such as display,
 	  graphics, video encode/decode, camera, etc.
+
+config MSM_GCC_8974
+	tristate "MSM8974 Global Clock Controller"
+	depends on COMMON_CLK_QCOM
+	help
+	  Support for the global clock controller on msm8974 devices.
+	  Say Y if you want to use peripheral devices such as UART, SPI,
+	  i2c, USB, SD/eMMC, SATA, PCIe, etc.
diff --git a/drivers/clk/qcom/Makefile b/drivers/clk/qcom/Makefile
index 85eff39..47a9a02 100644
--- a/drivers/clk/qcom/Makefile
+++ b/drivers/clk/qcom/Makefile
@@ -7,4 +7,5 @@ clk-qcom-$(CONFIG_COMMON_CLK_QCOM) += clk-branch.o
 clk-qcom-$(CONFIG_COMMON_CLK_QCOM) += reset.o
 
 obj-$(CONFIG_MSM_GCC_8960) += gcc-msm8960.o
+obj-$(CONFIG_MSM_GCC_8974) += gcc-msm8974.o
 obj-$(CONFIG_MSM_MMCC_8960) += mmcc-msm8960.o
diff --git a/drivers/clk/qcom/gcc-msm8974.c b/drivers/clk/qcom/gcc-msm8974.c
new file mode 100644
index 0000000..19745de
--- /dev/null
+++ b/drivers/clk/qcom/gcc-msm8974.c
@@ -0,0 +1,2693 @@
+/*
+ * Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/kernel.h>
+#include <linux/bitops.h>
+#include <linux/err.h>
+#include <linux/platform_device.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/clk-provider.h>
+#include <linux/regmap.h>
+#include <linux/reset-controller.h>
+
+#include <dt-bindings/clock/qcom,gcc-msm8974.h>
+#include <dt-bindings/reset/qcom,gcc-msm8974.h>
+
+#include "clk-pll.h"
+#include "clk-rcg.h"
+#include "clk-branch.h"
+#include "reset.h"
+
+#define P_XO	0
+#define P_GPLL0	1
+#define P_GPLL1	1
+
+static const u8 gcc_xo_gpll0_map[] = {
+	[P_XO]		= 0,
+	[P_GPLL0]	= 1,
+};
+
+static const char *gcc_xo_gpll0[] = {
+	"xo",
+	"gpll0_vote",
+};
+
+#define F(f, s, h, m, n) { (f), (s), (2 * (h) - 1), (m), (n) }
+
+static struct clk_pll gpll0 = {
+	.l_reg = 0x0004,
+	.m_reg = 0x0008,
+	.n_reg = 0x000c,
+	.config_reg = 0x0014,
+	.mode_reg = 0x0000,
+	.status_reg = 0x001c,
+	.status_bit = 17,
+	.hw.init = &(struct clk_init_data){
+		.name = "gpll0",
+		.parent_names = (const char *[]){ "xo" },
+		.num_parents = 1,
+		.ops = &clk_pll_ops,
+	},
+};
+
+static struct clk_hw gpll0_vote = {
+	.enable_reg = 0x1480,
+	.enable_mask = BIT(0),
+	.init = &(struct clk_init_data){
+		.name = "gpll0_vote",
+		.parent_names = (const char *[]){ "gpll0" },
+		.num_parents = 1,
+		.ops = &clk_pll_vote_ops,
+	},
+};
+
+static struct clk_rcg2 config_noc_clk_src = {
+	.cmd_rcgr = 0x0150,
+	.hid_width = 5,
+	.parent_map = gcc_xo_gpll0_map,
+	.hw.init = &(struct clk_init_data){
+		.name = "config_noc_clk_src",
+		.parent_names = gcc_xo_gpll0,
+		.num_parents = 2,
+		.ops = &clk_rcg2_ops,
+	},
+};
+
+static struct clk_rcg2 periph_noc_clk_src = {
+	.cmd_rcgr = 0x0190,
+	.hid_width = 5,
+	.parent_map = gcc_xo_gpll0_map,
+	.hw.init = &(struct clk_init_data){
+		.name = "periph_noc_clk_src",
+		.parent_names = gcc_xo_gpll0,
+		.num_parents = 2,
+		.ops = &clk_rcg2_ops,
+	},
+};
+
+static struct clk_rcg2 system_noc_clk_src = {
+	.cmd_rcgr = 0x0120,
+	.hid_width = 5,
+	.parent_map = gcc_xo_gpll0_map,
+	.hw.init = &(struct clk_init_data){
+		.name = "system_noc_clk_src",
+		.parent_names = gcc_xo_gpll0,
+		.num_parents = 2,
+		.ops = &clk_rcg2_ops,
+	},
+};
+
+static struct clk_pll gpll1 = {
+	.l_reg = 0x0044,
+	.m_reg = 0x0048,
+	.n_reg = 0x004c,
+	.config_reg = 0x0054,
+	.mode_reg = 0x0040,
+	.status_reg = 0x005c,
+	.status_bit = 17,
+	.hw.init = &(struct clk_init_data){
+		.name = "gpll1",
+		.parent_names = (const char *[]){ "xo" },
+		.num_parents = 1,
+		.ops = &clk_pll_ops,
+	},
+};
+
+static struct clk_hw gpll1_vote = {
+	.enable_reg = 0x1480,
+	.enable_mask = BIT(1),
+	.init = &(struct clk_init_data){
+		.name = "gpll1_vote",
+		.parent_names = (const char *[]){ "gpll1" },
+		.num_parents = 1,
+		.ops = &clk_pll_vote_ops,
+	},
+};
+
+static const struct freq_tbl ftbl_gcc_usb30_master_clk[] = {
+	F(125000000, P_GPLL0, 1, 5, 24),
+	{ }
+};
+
+static struct clk_rcg2 usb30_master_clk_src = {
+	.cmd_rcgr = 0x03d4,
+	.mnd_width = 8,
+	.hid_width = 5,
+	.parent_map = gcc_xo_gpll0_map,
+	.freq_tbl = ftbl_gcc_usb30_master_clk,
+	.hw.init = &(struct clk_init_data){
+		.name = "usb30_master_clk_src",
+		.parent_names = gcc_xo_gpll0,
+		.num_parents = 2,
+		.ops = &clk_rcg2_ops,
+	},
+};
+
+static const struct freq_tbl ftbl_gcc_blsp1_2_qup1_6_i2c_apps_clk[] = {
+	F(19200000, P_XO, 1, 0, 0),
+	F(37500000, P_GPLL0, 16, 0, 0),
+	F(50000000, P_GPLL0, 12, 0, 0),
+	{ }
+};
+
+static struct clk_rcg2 blsp1_qup1_i2c_apps_clk_src = {
+	.cmd_rcgr = 0x0660,
+	.hid_width = 5,
+	.parent_map = gcc_xo_gpll0_map,
+	.freq_tbl = ftbl_gcc_blsp1_2_qup1_6_i2c_apps_clk,
+	.hw.init = &(struct clk_init_data){
+		.name = "blsp1_qup1_i2c_apps_clk_src",
+		.parent_names = gcc_xo_gpll0,
+		.num_parents = 2,
+		.ops = &clk_rcg2_ops,
+	},
+};
+
+static const struct freq_tbl ftbl_gcc_blsp1_2_qup1_6_spi_apps_clk[] = {
+	F(960000, P_XO, 10, 1, 2),
+	F(4800000, P_XO, 4, 0, 0),
+	F(9600000, P_XO, 2, 0, 0),
+	F(15000000, P_GPLL0, 10, 1, 4),
+	F(19200000, P_XO, 1, 0, 0),
+	F(25000000, P_GPLL0, 12, 1, 2),
+	F(50000000, P_GPLL0, 12, 0, 0),
+	{ }
+};
+
+static struct clk_rcg2 blsp1_qup1_spi_apps_clk_src = {
+	.cmd_rcgr = 0x064c,
+	.mnd_width = 8,
+	.hid_width = 5,
+	.parent_map = gcc_xo_gpll0_map,
+	.freq_tbl = ftbl_gcc_blsp1_2_qup1_6_spi_apps_clk,
+	.hw.init = &(struct clk_init_data){
+		.name = "blsp1_qup1_spi_apps_clk_src",
+		.parent_names = gcc_xo_gpll0,
+		.num_parents = 2,
+		.ops = &clk_rcg2_ops,
+	},
+};
+
+static struct clk_rcg2 blsp1_qup2_i2c_apps_clk_src = {
+	.cmd_rcgr = 0x06e0,
+	.hid_width = 5,
+	.parent_map = gcc_xo_gpll0_map,
+	.freq_tbl = ftbl_gcc_blsp1_2_qup1_6_i2c_apps_clk,
+	.hw.init = &(struct clk_init_data){
+		.name = "blsp1_qup2_i2c_apps_clk_src",
+		.parent_names = gcc_xo_gpll0,
+		.num_parents = 2,
+		.ops = &clk_rcg2_ops,
+	},
+};
+
+static struct clk_rcg2 blsp1_qup2_spi_apps_clk_src = {
+	.cmd_rcgr = 0x06cc,
+	.mnd_width = 8,
+	.hid_width = 5,
+	.parent_map = gcc_xo_gpll0_map,
+	.freq_tbl = ftbl_gcc_blsp1_2_qup1_6_spi_apps_clk,
+	.hw.init = &(struct clk_init_data){
+		.name = "blsp1_qup2_spi_apps_clk_src",
+		.parent_names = gcc_xo_gpll0,
+		.num_parents = 2,
+		.ops = &clk_rcg2_ops,
+	},
+};
+
+static struct clk_rcg2 blsp1_qup3_i2c_apps_clk_src = {
+	.cmd_rcgr = 0x0760,
+	.hid_width = 5,
+	.parent_map = gcc_xo_gpll0_map,
+	.freq_tbl = ftbl_gcc_blsp1_2_qup1_6_i2c_apps_clk,
+	.hw.init = &(struct clk_init_data){
+		.name = "blsp1_qup3_i2c_apps_clk_src",
+		.parent_names = gcc_xo_gpll0,
+		.num_parents = 2,
+		.ops = &clk_rcg2_ops,
+	},
+};
+
+static struct clk_rcg2 blsp1_qup3_spi_apps_clk_src = {
+	.cmd_rcgr = 0x074c,
+	.mnd_width = 8,
+	.hid_width = 5,
+	.parent_map = gcc_xo_gpll0_map,
+	.freq_tbl = ftbl_gcc_blsp1_2_qup1_6_spi_apps_clk,
+	.hw.init = &(struct clk_init_data){
+		.name = "blsp1_qup3_spi_apps_clk_src",
+		.parent_names = gcc_xo_gpll0,
+		.num_parents = 2,
+		.ops = &clk_rcg2_ops,
+	},
+};
+
+static struct clk_rcg2 blsp1_qup4_i2c_apps_clk_src = {
+	.cmd_rcgr = 0x07e0,
+	.hid_width = 5,
+	.parent_map = gcc_xo_gpll0_map,
+	.freq_tbl = ftbl_gcc_blsp1_2_qup1_6_i2c_apps_clk,
+	.hw.init = &(struct clk_init_data){
+		.name = "blsp1_qup4_i2c_apps_clk_src",
+		.parent_names = gcc_xo_gpll0,
+		.num_parents = 2,
+		.ops = &clk_rcg2_ops,
+	},
+};
+
+static struct clk_rcg2 blsp1_qup4_spi_apps_clk_src = {
+	.cmd_rcgr = 0x07cc,
+	.mnd_width = 8,
+	.hid_width = 5,
+	.parent_map = gcc_xo_gpll0_map,
+	.freq_tbl = ftbl_gcc_blsp1_2_qup1_6_spi_apps_clk,
+	.hw.init = &(struct clk_init_data){
+		.name = "blsp1_qup4_spi_apps_clk_src",
+		.parent_names = gcc_xo_gpll0,
+		.num_parents = 2,
+		.ops = &clk_rcg2_ops,
+	},
+};
+
+static struct clk_rcg2 blsp1_qup5_i2c_apps_clk_src = {
+	.cmd_rcgr = 0x0860,
+	.hid_width = 5,
+	.parent_map = gcc_xo_gpll0_map,
+	.freq_tbl = ftbl_gcc_blsp1_2_qup1_6_i2c_apps_clk,
+	.hw.init = &(struct clk_init_data){
+		.name = "blsp1_qup5_i2c_apps_clk_src",
+		.parent_names = gcc_xo_gpll0,
+		.num_parents = 2,
+		.ops = &clk_rcg2_ops,
+	},
+};
+
+static struct clk_rcg2 blsp1_qup5_spi_apps_clk_src = {
+	.cmd_rcgr = 0x084c,
+	.mnd_width = 8,
+	.hid_width = 5,
+	.parent_map = gcc_xo_gpll0_map,
+	.freq_tbl = ftbl_gcc_blsp1_2_qup1_6_spi_apps_clk,
+	.hw.init = &(struct clk_init_data){
+		.name = "blsp1_qup5_spi_apps_clk_src",
+		.parent_names = gcc_xo_gpll0,
+		.num_parents = 2,
+		.ops = &clk_rcg2_ops,
+	},
+};
+
+static struct clk_rcg2 blsp1_qup6_i2c_apps_clk_src = {
+	.cmd_rcgr = 0x08e0,
+	.hid_width = 5,
+	.parent_map = gcc_xo_gpll0_map,
+	.freq_tbl = ftbl_gcc_blsp1_2_qup1_6_i2c_apps_clk,
+	.hw.init = &(struct clk_init_data){
+		.name = "blsp1_qup6_i2c_apps_clk_src",
+		.parent_names = gcc_xo_gpll0,
+		.num_parents = 2,
+		.ops = &clk_rcg2_ops,
+	},
+};
+
+static struct clk_rcg2 blsp1_qup6_spi_apps_clk_src = {
+	.cmd_rcgr = 0x08cc,
+	.mnd_width = 8,
+	.hid_width = 5,
+	.parent_map = gcc_xo_gpll0_map,
+	.freq_tbl = ftbl_gcc_blsp1_2_qup1_6_spi_apps_clk,
+	.hw.init = &(struct clk_init_data){
+		.name = "blsp1_qup6_spi_apps_clk_src",
+		.parent_names = gcc_xo_gpll0,
+		.num_parents = 2,
+		.ops = &clk_rcg2_ops,
+	},
+};
+
+static const struct freq_tbl ftbl_gcc_blsp1_2_uart1_6_apps_clk[] = {
+	F(3686400, P_GPLL0, 1, 96, 15625),
+	F(7372800, P_GPLL0, 1, 192, 15625),
+	F(14745600, P_GPLL0, 1, 384, 15625),
+	F(16000000, P_GPLL0, 5, 2, 15),
+	F(19200000, P_XO, 1, 0, 0),
+	F(24000000, P_GPLL0, 5, 1, 5),
+	F(32000000, P_GPLL0, 1, 4, 75),
+	F(40000000, P_GPLL0, 15, 0, 0),
+	F(46400000, P_GPLL0, 1, 29, 375),
+	F(48000000, P_GPLL0, 12.5, 0, 0),
+	F(51200000, P_GPLL0, 1, 32, 375),
+	F(56000000, P_GPLL0, 1, 7, 75),
+	F(58982400, P_GPLL0, 1, 1536, 15625),
+	F(60000000, P_GPLL0, 10, 0, 0),
+	F(63160000, P_GPLL0, 9.5, 0, 0),
+	{ }
+};
+
+static struct clk_rcg2 blsp1_uart1_apps_clk_src = {
+	.cmd_rcgr = 0x068c,
+	.mnd_width = 16,
+	.hid_width = 5,
+	.parent_map = gcc_xo_gpll0_map,
+	.freq_tbl = ftbl_gcc_blsp1_2_uart1_6_apps_clk,
+	.hw.init = &(struct clk_init_data){
+		.name = "blsp1_uart1_apps_clk_src",
+		.parent_names = gcc_xo_gpll0,
+		.num_parents = 2,
+		.ops = &clk_rcg2_ops,
+	},
+};
+
+static struct clk_rcg2 blsp1_uart2_apps_clk_src = {
+	.cmd_rcgr = 0x070c,
+	.mnd_width = 16,
+	.hid_width = 5,
+	.parent_map = gcc_xo_gpll0_map,
+	.freq_tbl = ftbl_gcc_blsp1_2_uart1_6_apps_clk,
+	.hw.init = &(struct clk_init_data){
+		.name = "blsp1_uart2_apps_clk_src",
+		.parent_names = gcc_xo_gpll0,
+		.num_parents = 2,
+		.ops = &clk_rcg2_ops,
+	},
+};
+
+static struct clk_rcg2 blsp1_uart3_apps_clk_src = {
+	.cmd_rcgr = 0x078c,
+	.mnd_width = 16,
+	.hid_width = 5,
+	.parent_map = gcc_xo_gpll0_map,
+	.freq_tbl = ftbl_gcc_blsp1_2_uart1_6_apps_clk,
+	.hw.init = &(struct clk_init_data){
+		.name = "blsp1_uart3_apps_clk_src",
+		.parent_names = gcc_xo_gpll0,
+		.num_parents = 2,
+		.ops = &clk_rcg2_ops,
+	},
+};
+
+static struct clk_rcg2 blsp1_uart4_apps_clk_src = {
+	.cmd_rcgr = 0x080c,
+	.mnd_width = 16,
+	.hid_width = 5,
+	.parent_map = gcc_xo_gpll0_map,
+	.freq_tbl = ftbl_gcc_blsp1_2_uart1_6_apps_clk,
+	.hw.init = &(struct clk_init_data){
+		.name = "blsp1_uart4_apps_clk_src",
+		.parent_names = gcc_xo_gpll0,
+		.num_parents = 2,
+		.ops = &clk_rcg2_ops,
+	},
+};
+
+static struct clk_rcg2 blsp1_uart5_apps_clk_src = {
+	.cmd_rcgr = 0x088c,
+	.mnd_width = 16,
+	.hid_width = 5,
+	.parent_map = gcc_xo_gpll0_map,
+	.freq_tbl = ftbl_gcc_blsp1_2_uart1_6_apps_clk,
+	.hw.init = &(struct clk_init_data){
+		.name = "blsp1_uart5_apps_clk_src",
+		.parent_names = gcc_xo_gpll0,
+		.num_parents = 2,
+		.ops = &clk_rcg2_ops,
+	},
+};
+
+static struct clk_rcg2 blsp1_uart6_apps_clk_src = {
+	.cmd_rcgr = 0x090c,
+	.mnd_width = 16,
+	.hid_width = 5,
+	.parent_map = gcc_xo_gpll0_map,
+	.freq_tbl = ftbl_gcc_blsp1_2_uart1_6_apps_clk,
+	.hw.init = &(struct clk_init_data){
+		.name = "blsp1_uart6_apps_clk_src",
+		.parent_names = gcc_xo_gpll0,
+		.num_parents = 2,
+		.ops = &clk_rcg2_ops,
+	},
+};
+
+static struct clk_rcg2 blsp2_qup1_i2c_apps_clk_src = {
+	.cmd_rcgr = 0x09a0,
+	.hid_width = 5,
+	.parent_map = gcc_xo_gpll0_map,
+	.freq_tbl = ftbl_gcc_blsp1_2_qup1_6_i2c_apps_clk,
+	.hw.init = &(struct clk_init_data){
+		.name = "blsp2_qup1_i2c_apps_clk_src",
+		.parent_names = gcc_xo_gpll0,
+		.num_parents = 2,
+		.ops = &clk_rcg2_ops,
+	},
+};
+
+static struct clk_rcg2 blsp2_qup1_spi_apps_clk_src = {
+	.cmd_rcgr = 0x098c,
+	.mnd_width = 8,
+	.hid_width = 5,
+	.parent_map = gcc_xo_gpll0_map,
+	.freq_tbl = ftbl_gcc_blsp1_2_qup1_6_spi_apps_clk,
+	.hw.init = &(struct clk_init_data){
+		.name = "blsp2_qup1_spi_apps_clk_src",
+		.parent_names = gcc_xo_gpll0,
+		.num_parents = 2,
+		.ops = &clk_rcg2_ops,
+	},
+};
+
+static struct clk_rcg2 blsp2_qup2_i2c_apps_clk_src = {
+	.cmd_rcgr = 0x0a20,
+	.hid_width = 5,
+	.parent_map = gcc_xo_gpll0_map,
+	.freq_tbl = ftbl_gcc_blsp1_2_qup1_6_i2c_apps_clk,
+	.hw.init = &(struct clk_init_data){
+		.name = "blsp2_qup2_i2c_apps_clk_src",
+		.parent_names = gcc_xo_gpll0,
+		.num_parents = 2,
+		.ops = &clk_rcg2_ops,
+	},
+};
+
+static struct clk_rcg2 blsp2_qup2_spi_apps_clk_src = {
+	.cmd_rcgr = 0x0a0c,
+	.mnd_width = 8,
+	.hid_width = 5,
+	.parent_map = gcc_xo_gpll0_map,
+	.freq_tbl = ftbl_gcc_blsp1_2_qup1_6_spi_apps_clk,
+	.hw.init = &(struct clk_init_data){
+		.name = "blsp2_qup2_spi_apps_clk_src",
+		.parent_names = gcc_xo_gpll0,
+		.num_parents = 2,
+		.ops = &clk_rcg2_ops,
+	},
+};
+
+static struct clk_rcg2 blsp2_qup3_i2c_apps_clk_src = {
+	.cmd_rcgr = 0x0aa0,
+	.hid_width = 5,
+	.parent_map = gcc_xo_gpll0_map,
+	.freq_tbl = ftbl_gcc_blsp1_2_qup1_6_i2c_apps_clk,
+	.hw.init = &(struct clk_init_data){
+		.name = "blsp2_qup3_i2c_apps_clk_src",
+		.parent_names = gcc_xo_gpll0,
+		.num_parents = 2,
+		.ops = &clk_rcg2_ops,
+	},
+};
+
+static struct clk_rcg2 blsp2_qup3_spi_apps_clk_src = {
+	.cmd_rcgr = 0x0a8c,
+	.mnd_width = 8,
+	.hid_width = 5,
+	.parent_map = gcc_xo_gpll0_map,
+	.freq_tbl = ftbl_gcc_blsp1_2_qup1_6_spi_apps_clk,
+	.hw.init = &(struct clk_init_data){
+		.name = "blsp2_qup3_spi_apps_clk_src",
+		.parent_names = gcc_xo_gpll0,
+		.num_parents = 2,
+		.ops = &clk_rcg2_ops,
+	},
+};
+
+static struct clk_rcg2 blsp2_qup4_i2c_apps_clk_src = {
+	.cmd_rcgr = 0x0b20,
+	.hid_width = 5,
+	.parent_map = gcc_xo_gpll0_map,
+	.freq_tbl = ftbl_gcc_blsp1_2_qup1_6_i2c_apps_clk,
+	.hw.init = &(struct clk_init_data){
+		.name = "blsp2_qup4_i2c_apps_clk_src",
+		.parent_names = gcc_xo_gpll0,
+		.num_parents = 2,
+		.ops = &clk_rcg2_ops,
+	},
+};
+
+static struct clk_rcg2 blsp2_qup4_spi_apps_clk_src = {
+	.cmd_rcgr = 0x0b0c,
+	.mnd_width = 8,
+	.hid_width = 5,
+	.parent_map = gcc_xo_gpll0_map,
+	.freq_tbl = ftbl_gcc_blsp1_2_qup1_6_spi_apps_clk,
+	.hw.init = &(struct clk_init_data){
+		.name = "blsp2_qup4_spi_apps_clk_src",
+		.parent_names = gcc_xo_gpll0,
+		.num_parents = 2,
+		.ops = &clk_rcg2_ops,
+	},
+};
+
+static struct clk_rcg2 blsp2_qup5_i2c_apps_clk_src = {
+	.cmd_rcgr = 0x0ba0,
+	.hid_width = 5,
+	.parent_map = gcc_xo_gpll0_map,
+	.freq_tbl = ftbl_gcc_blsp1_2_qup1_6_i2c_apps_clk,
+	.hw.init = &(struct clk_init_data){
+		.name = "blsp2_qup5_i2c_apps_clk_src",
+		.parent_names = gcc_xo_gpll0,
+		.num_parents = 2,
+		.ops = &clk_rcg2_ops,
+	},
+};
+
+static struct clk_rcg2 blsp2_qup5_spi_apps_clk_src = {
+	.cmd_rcgr = 0x0b8c,
+	.mnd_width = 8,
+	.hid_width = 5,
+	.parent_map = gcc_xo_gpll0_map,
+	.freq_tbl = ftbl_gcc_blsp1_2_qup1_6_spi_apps_clk,
+	.hw.init = &(struct clk_init_data){
+		.name = "blsp2_qup5_spi_apps_clk_src",
+		.parent_names = gcc_xo_gpll0,
+		.num_parents = 2,
+		.ops = &clk_rcg2_ops,
+	},
+};
+
+static struct clk_rcg2 blsp2_qup6_i2c_apps_clk_src = {
+	.cmd_rcgr = 0x0c20,
+	.hid_width = 5,
+	.parent_map = gcc_xo_gpll0_map,
+	.freq_tbl = ftbl_gcc_blsp1_2_qup1_6_i2c_apps_clk,
+	.hw.init = &(struct clk_init_data){
+		.name = "blsp2_qup6_i2c_apps_clk_src",
+		.parent_names = gcc_xo_gpll0,
+		.num_parents = 2,
+		.ops = &clk_rcg2_ops,
+	},
+};
+
+static struct clk_rcg2 blsp2_qup6_spi_apps_clk_src = {
+	.cmd_rcgr = 0x0c0c,
+	.mnd_width = 8,
+	.hid_width = 5,
+	.parent_map = gcc_xo_gpll0_map,
+	.freq_tbl = ftbl_gcc_blsp1_2_qup1_6_spi_apps_clk,
+	.hw.init = &(struct clk_init_data){
+		.name = "blsp2_qup6_spi_apps_clk_src",
+		.parent_names = gcc_xo_gpll0,
+		.num_parents = 2,
+		.ops = &clk_rcg2_ops,
+	},
+};
+
+static struct clk_rcg2 blsp2_uart1_apps_clk_src = {
+	.cmd_rcgr = 0x09cc,
+	.mnd_width = 16,
+	.hid_width = 5,
+	.parent_map = gcc_xo_gpll0_map,
+	.freq_tbl = ftbl_gcc_blsp1_2_uart1_6_apps_clk,
+	.hw.init = &(struct clk_init_data){
+		.name = "blsp2_uart1_apps_clk_src",
+		.parent_names = gcc_xo_gpll0,
+		.num_parents = 2,
+		.ops = &clk_rcg2_ops,
+	},
+};
+
+static struct clk_rcg2 blsp2_uart2_apps_clk_src = {
+	.cmd_rcgr = 0x0a4c,
+	.mnd_width = 16,
+	.hid_width = 5,
+	.parent_map = gcc_xo_gpll0_map,
+	.freq_tbl = ftbl_gcc_blsp1_2_uart1_6_apps_clk,
+	.hw.init = &(struct clk_init_data){
+		.name = "blsp2_uart2_apps_clk_src",
+		.parent_names = gcc_xo_gpll0,
+		.num_parents = 2,
+		.ops = &clk_rcg2_ops,
+	},
+};
+
+static struct clk_rcg2 blsp2_uart3_apps_clk_src = {
+	.cmd_rcgr = 0x0acc,
+	.mnd_width = 16,
+	.hid_width = 5,
+	.parent_map = gcc_xo_gpll0_map,
+	.freq_tbl = ftbl_gcc_blsp1_2_uart1_6_apps_clk,
+	.hw.init = &(struct clk_init_data){
+		.name = "blsp2_uart3_apps_clk_src",
+		.parent_names = gcc_xo_gpll0,
+		.num_parents = 2,
+		.ops = &clk_rcg2_ops,
+	},
+};
+
+static struct clk_rcg2 blsp2_uart4_apps_clk_src = {
+	.cmd_rcgr = 0x0b4c,
+	.mnd_width = 16,
+	.hid_width = 5,
+	.parent_map = gcc_xo_gpll0_map,
+	.freq_tbl = ftbl_gcc_blsp1_2_uart1_6_apps_clk,
+	.hw.init = &(struct clk_init_data){
+		.name = "blsp2_uart4_apps_clk_src",
+		.parent_names = gcc_xo_gpll0,
+		.num_parents = 2,
+		.ops = &clk_rcg2_ops,
+	},
+};
+
+static struct clk_rcg2 blsp2_uart5_apps_clk_src = {
+	.cmd_rcgr = 0x0bcc,
+	.mnd_width = 16,
+	.hid_width = 5,
+	.parent_map = gcc_xo_gpll0_map,
+	.freq_tbl = ftbl_gcc_blsp1_2_uart1_6_apps_clk,
+	.hw.init = &(struct clk_init_data){
+		.name = "blsp2_uart5_apps_clk_src",
+		.parent_names = gcc_xo_gpll0,
+		.num_parents = 2,
+		.ops = &clk_rcg2_ops,
+	},
+};
+
+static struct clk_rcg2 blsp2_uart6_apps_clk_src = {
+	.cmd_rcgr = 0x0c4c,
+	.mnd_width = 16,
+	.hid_width = 5,
+	.parent_map = gcc_xo_gpll0_map,
+	.freq_tbl = ftbl_gcc_blsp1_2_uart1_6_apps_clk,
+	.hw.init = &(struct clk_init_data){
+		.name = "blsp2_uart6_apps_clk_src",
+		.parent_names = gcc_xo_gpll0,
+		.num_parents = 2,
+		.ops = &clk_rcg2_ops,
+	},
+};
+
+static const struct freq_tbl ftbl_gcc_ce1_clk[] = {
+	F(50000000, P_GPLL0, 12, 0, 0),
+	F(75000000, P_GPLL0, 8, 0, 0),
+	F(100000000, P_GPLL0, 6, 0, 0),
+	F(150000000, P_GPLL0, 4, 0, 0),
+	{ }
+};
+
+static struct clk_rcg2 ce1_clk_src = {
+	.cmd_rcgr = 0x1050,
+	.hid_width = 5,
+	.parent_map = gcc_xo_gpll0_map,
+	.freq_tbl = ftbl_gcc_ce1_clk,
+	.hw.init = &(struct clk_init_data){
+		.name = "ce1_clk_src",
+		.parent_names = gcc_xo_gpll0,
+		.num_parents = 2,
+		.ops = &clk_rcg2_ops,
+	},
+};
+
+static const struct freq_tbl ftbl_gcc_ce2_clk[] = {
+	F(50000000, P_GPLL0, 12, 0, 0),
+	F(75000000, P_GPLL0, 8, 0, 0),
+	F(100000000, P_GPLL0, 6, 0, 0),
+	F(150000000, P_GPLL0, 4, 0, 0),
+	{ }
+};
+
+static struct clk_rcg2 ce2_clk_src = {
+	.cmd_rcgr = 0x1090,
+	.hid_width = 5,
+	.parent_map = gcc_xo_gpll0_map,
+	.freq_tbl = ftbl_gcc_ce2_clk,
+	.hw.init = &(struct clk_init_data){
+		.name = "ce2_clk_src",
+		.parent_names = gcc_xo_gpll0,
+		.num_parents = 2,
+		.ops = &clk_rcg2_ops,
+	},
+};
+
+static const struct freq_tbl ftbl_gcc_gp_clk[] = {
+	F(4800000, P_XO, 4, 0, 0),
+	F(6000000, P_GPLL0, 10, 1, 10),
+	F(6750000, P_GPLL0, 1, 1, 89),
+	F(8000000, P_GPLL0, 15, 1, 5),
+	F(9600000, P_XO, 2, 0, 0),
+	F(16000000, P_GPLL0, 1, 2, 75),
+	F(19200000, P_XO, 1, 0, 0),
+	F(24000000, P_GPLL0, 5, 1, 5),
+	{ }
+};
+
+
+static struct clk_rcg2 gp1_clk_src = {
+	.cmd_rcgr = 0x1904,
+	.mnd_width = 8,
+	.hid_width = 5,
+	.parent_map = gcc_xo_gpll0_map,
+	.freq_tbl = ftbl_gcc_gp_clk,
+	.hw.init = &(struct clk_init_data){
+		.name = "gp1_clk_src",
+		.parent_names = gcc_xo_gpll0,
+		.num_parents = 2,
+		.ops = &clk_rcg2_ops,
+	},
+};
+
+static struct clk_rcg2 gp2_clk_src = {
+	.cmd_rcgr = 0x1944,
+	.mnd_width = 8,
+	.hid_width = 5,
+	.parent_map = gcc_xo_gpll0_map,
+	.freq_tbl = ftbl_gcc_gp_clk,
+	.hw.init = &(struct clk_init_data){
+		.name = "gp2_clk_src",
+		.parent_names = gcc_xo_gpll0,
+		.num_parents = 2,
+		.ops = &clk_rcg2_ops,
+	},
+};
+
+static struct clk_rcg2 gp3_clk_src = {
+	.cmd_rcgr = 0x1984,
+	.mnd_width = 8,
+	.hid_width = 5,
+	.parent_map = gcc_xo_gpll0_map,
+	.freq_tbl = ftbl_gcc_gp_clk,
+	.hw.init = &(struct clk_init_data){
+		.name = "gp3_clk_src",
+		.parent_names = gcc_xo_gpll0,
+		.num_parents = 2,
+		.ops = &clk_rcg2_ops,
+	},
+};
+
+static const struct freq_tbl ftbl_gcc_pdm2_clk[] = {
+	F(60000000, P_GPLL0, 10, 0, 0),
+	{ }
+};
+
+static struct clk_rcg2 pdm2_clk_src = {
+	.cmd_rcgr = 0x0cd0,
+	.hid_width = 5,
+	.parent_map = gcc_xo_gpll0_map,
+	.freq_tbl = ftbl_gcc_pdm2_clk,
+	.hw.init = &(struct clk_init_data){
+		.name = "pdm2_clk_src",
+		.parent_names = gcc_xo_gpll0,
+		.num_parents = 2,
+		.ops = &clk_rcg2_ops,
+	},
+};
+
+static const struct freq_tbl ftbl_gcc_sdcc1_4_apps_clk[] = {
+	F(144000, P_XO, 16, 3, 25),
+	F(400000, P_XO, 12, 1, 4),
+	F(20000000, P_GPLL0, 15, 1, 2),
+	F(25000000, P_GPLL0, 12, 1, 2),
+	F(50000000, P_GPLL0, 12, 0, 0),
+	F(100000000, P_GPLL0, 6, 0, 0),
+	F(200000000, P_GPLL0, 3, 0, 0),
+	{ }
+};
+
+static struct clk_rcg2 sdcc1_apps_clk_src = {
+	.cmd_rcgr = 0x04d0,
+	.mnd_width = 8,
+	.hid_width = 5,
+	.parent_map = gcc_xo_gpll0_map,
+	.freq_tbl = ftbl_gcc_sdcc1_4_apps_clk,
+	.hw.init = &(struct clk_init_data){
+		.name = "sdcc1_apps_clk_src",
+		.parent_names = gcc_xo_gpll0,
+		.num_parents = 2,
+		.ops = &clk_rcg2_ops,
+	},
+};
+
+static struct clk_rcg2 sdcc2_apps_clk_src = {
+	.cmd_rcgr = 0x0510,
+	.mnd_width = 8,
+	.hid_width = 5,
+	.parent_map = gcc_xo_gpll0_map,
+	.freq_tbl = ftbl_gcc_sdcc1_4_apps_clk,
+	.hw.init = &(struct clk_init_data){
+		.name = "sdcc2_apps_clk_src",
+		.parent_names = gcc_xo_gpll0,
+		.num_parents = 2,
+		.ops = &clk_rcg2_ops,
+	},
+};
+
+static struct clk_rcg2 sdcc3_apps_clk_src = {
+	.cmd_rcgr = 0x0550,
+	.mnd_width = 8,
+	.hid_width = 5,
+	.parent_map = gcc_xo_gpll0_map,
+	.freq_tbl = ftbl_gcc_sdcc1_4_apps_clk,
+	.hw.init = &(struct clk_init_data){
+		.name = "sdcc3_apps_clk_src",
+		.parent_names = gcc_xo_gpll0,
+		.num_parents = 2,
+		.ops = &clk_rcg2_ops,
+	},
+};
+
+static struct clk_rcg2 sdcc4_apps_clk_src = {
+	.cmd_rcgr = 0x0590,
+	.mnd_width = 8,
+	.hid_width = 5,
+	.parent_map = gcc_xo_gpll0_map,
+	.freq_tbl = ftbl_gcc_sdcc1_4_apps_clk,
+	.hw.init = &(struct clk_init_data){
+		.name = "sdcc4_apps_clk_src",
+		.parent_names = gcc_xo_gpll0,
+		.num_parents = 2,
+		.ops = &clk_rcg2_ops,
+	},
+};
+
+static const struct freq_tbl ftbl_gcc_tsif_ref_clk[] = {
+	F(105000, P_XO, 2, 1, 91),
+	{ }
+};
+
+static struct clk_rcg2 tsif_ref_clk_src = {
+	.cmd_rcgr = 0x0d90,
+	.mnd_width = 8,
+	.hid_width = 5,
+	.parent_map = gcc_xo_gpll0_map,
+	.freq_tbl = ftbl_gcc_tsif_ref_clk,
+	.hw.init = &(struct clk_init_data){
+		.name = "tsif_ref_clk_src",
+		.parent_names = gcc_xo_gpll0,
+		.num_parents = 2,
+		.ops = &clk_rcg2_ops,
+	},
+};
+
+static const struct freq_tbl ftbl_gcc_usb30_mock_utmi_clk[] = {
+	F(60000000, P_GPLL0, 10, 0, 0),
+	{ }
+};
+
+static struct clk_rcg2 usb30_mock_utmi_clk_src = {
+	.cmd_rcgr = 0x03e8,
+	.hid_width = 5,
+	.parent_map = gcc_xo_gpll0_map,
+	.freq_tbl = ftbl_gcc_usb30_mock_utmi_clk,
+	.hw.init = &(struct clk_init_data){
+		.name = "usb30_mock_utmi_clk_src",
+		.parent_names = gcc_xo_gpll0,
+		.num_parents = 2,
+		.ops = &clk_rcg2_ops,
+	},
+};
+
+static const struct freq_tbl ftbl_gcc_usb_hs_system_clk[] = {
+	F(60000000, P_GPLL0, 10, 0, 0),
+	F(75000000, P_GPLL0, 8, 0, 0),
+	{ }
+};
+
+static struct clk_rcg2 usb_hs_system_clk_src = {
+	.cmd_rcgr = 0x0490,
+	.hid_width = 5,
+	.parent_map = gcc_xo_gpll0_map,
+	.freq_tbl = ftbl_gcc_usb_hs_system_clk,
+	.hw.init = &(struct clk_init_data){
+		.name = "usb_hs_system_clk_src",
+		.parent_names = gcc_xo_gpll0,
+		.num_parents = 2,
+		.ops = &clk_rcg2_ops,
+	},
+};
+
+static const struct freq_tbl ftbl_gcc_usb_hsic_clk[] = {
+	F(480000000, P_GPLL1, 1, 0, 0),
+	{ }
+};
+
+static u8 usb_hsic_clk_src_map[] = {
+	[P_XO]		= 0,
+	[P_GPLL1]	= 4,
+};
+
+static struct clk_rcg2 usb_hsic_clk_src = {
+	.cmd_rcgr = 0x0440,
+	.hid_width = 5,
+	.parent_map = usb_hsic_clk_src_map,
+	.freq_tbl = ftbl_gcc_usb_hsic_clk,
+	.hw.init = &(struct clk_init_data){
+		.name = "usb_hsic_clk_src",
+		.parent_names = (const char *[]){
+			"xo",
+			"gpll1_vote",
+		},
+		.num_parents = 2,
+		.ops = &clk_rcg2_ops,
+	},
+};
+
+static const struct freq_tbl ftbl_gcc_usb_hsic_io_cal_clk[] = {
+	F(9600000, P_XO, 2, 0, 0),
+	{ }
+};
+
+static struct clk_rcg2 usb_hsic_io_cal_clk_src = {
+	.cmd_rcgr = 0x0458,
+	.hid_width = 5,
+	.parent_map = gcc_xo_gpll0_map,
+	.freq_tbl = ftbl_gcc_usb_hsic_io_cal_clk,
+	.hw.init = &(struct clk_init_data){
+		.name = "usb_hsic_io_cal_clk_src",
+		.parent_names = gcc_xo_gpll0,
+		.num_parents = 1,
+		.ops = &clk_rcg2_ops,
+	},
+};
+
+static const struct freq_tbl ftbl_gcc_usb_hsic_system_clk[] = {
+	F(60000000, P_GPLL0, 10, 0, 0),
+	F(75000000, P_GPLL0, 8, 0, 0),
+	{ }
+};
+
+static struct clk_rcg2 usb_hsic_system_clk_src = {
+	.cmd_rcgr = 0x041c,
+	.hid_width = 5,
+	.parent_map = gcc_xo_gpll0_map,
+	.freq_tbl = ftbl_gcc_usb_hsic_system_clk,
+	.hw.init = &(struct clk_init_data){
+		.name = "usb_hsic_system_clk_src",
+		.parent_names = gcc_xo_gpll0,
+		.num_parents = 2,
+		.ops = &clk_rcg2_ops,
+	},
+};
+
+static struct clk_hw gcc_mmss_gpll0_clk_src = {
+	.enable_reg = 0x1484,
+	.enable_mask = BIT(26),
+	.init = &(struct clk_init_data){
+		.name = "mmss_gpll0_vote",
+		.parent_names = (const char *[]){
+			"gpll0_vote",
+		},
+		.num_parents = 1,
+		.ops = &clk_branch_simple_ops,
+	},
+};
+
+static struct clk_branch gcc_bam_dma_ahb_clk = {
+	.halt_reg = 0x0d44,
+	.halt_check = BRANCH_HALT_VOTED,
+	.hw = {
+		.enable_reg = 0x1484,
+		.enable_mask = BIT(12),
+		.init = &(struct clk_init_data){
+			.name = "gcc_bam_dma_ahb_clk",
+			.parent_names = (const char *[]){
+				"periph_noc_clk_src",
+			},
+			.num_parents = 1,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch gcc_blsp1_ahb_clk = {
+	.halt_reg = 0x05c4,
+	.halt_check = BRANCH_HALT_VOTED,
+	.hw = {
+		.enable_reg = 0x1484,
+		.enable_mask = BIT(17),
+		.init = &(struct clk_init_data){
+			.name = "gcc_blsp1_ahb_clk",
+			.parent_names = (const char *[]){
+				"periph_noc_clk_src",
+			},
+			.num_parents = 1,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch gcc_blsp1_qup1_i2c_apps_clk = {
+	.halt_reg = 0x0648,
+	.hw = {
+		.enable_reg = 0x0648,
+		.enable_mask = BIT(0),
+		.init = &(struct clk_init_data){
+			.name = "gcc_blsp1_qup1_i2c_apps_clk",
+			.parent_names = (const char *[]){
+				"blsp1_qup1_i2c_apps_clk_src",
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch gcc_blsp1_qup1_spi_apps_clk = {
+	.halt_reg = 0x0644,
+	.hw = {
+		.enable_reg = 0x0644,
+		.enable_mask = BIT(0),
+		.init = &(struct clk_init_data){
+			.name = "gcc_blsp1_qup1_spi_apps_clk",
+			.parent_names = (const char *[]){
+				"blsp1_qup1_spi_apps_clk_src",
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch gcc_blsp1_qup2_i2c_apps_clk = {
+	.halt_reg = 0x06c8,
+	.hw = {
+		.enable_reg = 0x06c8,
+		.enable_mask = BIT(0),
+		.init = &(struct clk_init_data){
+			.name = "gcc_blsp1_qup2_i2c_apps_clk",
+			.parent_names = (const char *[]){
+				"blsp1_qup2_i2c_apps_clk_src",
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch gcc_blsp1_qup2_spi_apps_clk = {
+	.halt_reg = 0x06c4,
+	.hw = {
+		.enable_reg = 0x06c4,
+		.enable_mask = BIT(0),
+		.init = &(struct clk_init_data){
+			.name = "gcc_blsp1_qup2_spi_apps_clk",
+			.parent_names = (const char *[]){
+				"blsp1_qup2_spi_apps_clk_src",
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch gcc_blsp1_qup3_i2c_apps_clk = {
+	.halt_reg = 0x0748,
+	.hw = {
+		.enable_reg = 0x0748,
+		.enable_mask = BIT(0),
+		.init = &(struct clk_init_data){
+			.name = "gcc_blsp1_qup3_i2c_apps_clk",
+			.parent_names = (const char *[]){
+				"blsp1_qup3_i2c_apps_clk_src",
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch gcc_blsp1_qup3_spi_apps_clk = {
+	.halt_reg = 0x0744,
+	.hw = {
+		.enable_reg = 0x0744,
+		.enable_mask = BIT(0),
+		.init = &(struct clk_init_data){
+			.name = "gcc_blsp1_qup3_spi_apps_clk",
+			.parent_names = (const char *[]){
+				"blsp1_qup3_spi_apps_clk_src",
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch gcc_blsp1_qup4_i2c_apps_clk = {
+	.halt_reg = 0x07c8,
+	.hw = {
+		.enable_reg = 0x07c8,
+		.enable_mask = BIT(0),
+		.init = &(struct clk_init_data){
+			.name = "gcc_blsp1_qup4_i2c_apps_clk",
+			.parent_names = (const char *[]){
+				"blsp1_qup4_i2c_apps_clk_src",
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch gcc_blsp1_qup4_spi_apps_clk = {
+	.halt_reg = 0x07c4,
+	.hw = {
+		.enable_reg = 0x07c4,
+		.enable_mask = BIT(0),
+		.init = &(struct clk_init_data){
+			.name = "gcc_blsp1_qup4_spi_apps_clk",
+			.parent_names = (const char *[]){
+				"blsp1_qup4_spi_apps_clk_src",
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch gcc_blsp1_qup5_i2c_apps_clk = {
+	.halt_reg = 0x0848,
+	.hw = {
+		.enable_reg = 0x0848,
+		.enable_mask = BIT(0),
+		.init = &(struct clk_init_data){
+			.name = "gcc_blsp1_qup5_i2c_apps_clk",
+			.parent_names = (const char *[]){
+				"blsp1_qup5_i2c_apps_clk_src",
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch gcc_blsp1_qup5_spi_apps_clk = {
+	.halt_reg = 0x0844,
+	.hw = {
+		.enable_reg = 0x0844,
+		.enable_mask = BIT(0),
+		.init = &(struct clk_init_data){
+			.name = "gcc_blsp1_qup5_spi_apps_clk",
+			.parent_names = (const char *[]){
+				"blsp1_qup5_spi_apps_clk_src",
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch gcc_blsp1_qup6_i2c_apps_clk = {
+	.halt_reg = 0x08c8,
+	.hw = {
+		.enable_reg = 0x08c8,
+		.enable_mask = BIT(0),
+		.init = &(struct clk_init_data){
+			.name = "gcc_blsp1_qup6_i2c_apps_clk",
+			.parent_names = (const char *[]){
+				"blsp1_qup6_i2c_apps_clk_src",
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch gcc_blsp1_qup6_spi_apps_clk = {
+	.halt_reg = 0x08c4,
+	.hw = {
+		.enable_reg = 0x08c4,
+		.enable_mask = BIT(0),
+		.init = &(struct clk_init_data){
+			.name = "gcc_blsp1_qup6_spi_apps_clk",
+			.parent_names = (const char *[]){
+				"blsp1_qup6_spi_apps_clk_src",
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch gcc_blsp1_uart1_apps_clk = {
+	.halt_reg = 0x0684,
+	.hw = {
+		.enable_reg = 0x0684,
+		.enable_mask = BIT(0),
+		.init = &(struct clk_init_data){
+			.name = "gcc_blsp1_uart1_apps_clk",
+			.parent_names = (const char *[]){
+				"blsp1_uart1_apps_clk_src",
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch gcc_blsp1_uart2_apps_clk = {
+	.halt_reg = 0x0704,
+	.hw = {
+		.enable_reg = 0x0704,
+		.enable_mask = BIT(0),
+		.init = &(struct clk_init_data){
+			.name = "gcc_blsp1_uart2_apps_clk",
+			.parent_names = (const char *[]){
+				"blsp1_uart2_apps_clk_src",
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch gcc_blsp1_uart3_apps_clk = {
+	.halt_reg = 0x0784,
+	.hw = {
+		.enable_reg = 0x0784,
+		.enable_mask = BIT(0),
+		.init = &(struct clk_init_data){
+			.name = "gcc_blsp1_uart3_apps_clk",
+			.parent_names = (const char *[]){
+				"blsp1_uart3_apps_clk_src",
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch gcc_blsp1_uart4_apps_clk = {
+	.halt_reg = 0x0804,
+	.hw = {
+		.enable_reg = 0x0804,
+		.enable_mask = BIT(0),
+		.init = &(struct clk_init_data){
+			.name = "gcc_blsp1_uart4_apps_clk",
+			.parent_names = (const char *[]){
+				"blsp1_uart4_apps_clk_src",
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch gcc_blsp1_uart5_apps_clk = {
+	.halt_reg = 0x0884,
+	.hw = {
+		.enable_reg = 0x0884,
+		.enable_mask = BIT(0),
+		.init = &(struct clk_init_data){
+			.name = "gcc_blsp1_uart5_apps_clk",
+			.parent_names = (const char *[]){
+				"blsp1_uart5_apps_clk_src",
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch gcc_blsp1_uart6_apps_clk = {
+	.halt_reg = 0x0904,
+	.hw = {
+		.enable_reg = 0x0904,
+		.enable_mask = BIT(0),
+		.init = &(struct clk_init_data){
+			.name = "gcc_blsp1_uart6_apps_clk",
+			.parent_names = (const char *[]){
+				"blsp1_uart6_apps_clk_src",
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch gcc_blsp2_ahb_clk = {
+	.halt_reg = 0x05c4,
+	.halt_check = BRANCH_HALT_VOTED,
+	.hw = {
+		.enable_reg = 0x1484,
+		.enable_mask = BIT(15),
+		.init = &(struct clk_init_data){
+			.name = "gcc_blsp2_ahb_clk",
+			.parent_names = (const char *[]){
+				"periph_noc_clk_src",
+			},
+			.num_parents = 1,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch gcc_blsp2_qup1_i2c_apps_clk = {
+	.halt_reg = 0x0988,
+	.hw = {
+		.enable_reg = 0x0988,
+		.enable_mask = BIT(0),
+		.init = &(struct clk_init_data){
+			.name = "gcc_blsp2_qup1_i2c_apps_clk",
+			.parent_names = (const char *[]){
+				"blsp2_qup1_i2c_apps_clk_src",
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch gcc_blsp2_qup1_spi_apps_clk = {
+	.halt_reg = 0x0984,
+	.hw = {
+		.enable_reg = 0x0984,
+		.enable_mask = BIT(0),
+		.init = &(struct clk_init_data){
+			.name = "gcc_blsp2_qup1_spi_apps_clk",
+			.parent_names = (const char *[]){
+				"blsp2_qup1_spi_apps_clk_src",
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch gcc_blsp2_qup2_i2c_apps_clk = {
+	.halt_reg = 0x0a08,
+	.hw = {
+		.enable_reg = 0x0a08,
+		.enable_mask = BIT(0),
+		.init = &(struct clk_init_data){
+			.name = "gcc_blsp2_qup2_i2c_apps_clk",
+			.parent_names = (const char *[]){
+				"blsp2_qup2_i2c_apps_clk_src",
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch gcc_blsp2_qup2_spi_apps_clk = {
+	.halt_reg = 0x0a04,
+	.hw = {
+		.enable_reg = 0x0a04,
+		.enable_mask = BIT(0),
+		.init = &(struct clk_init_data){
+			.name = "gcc_blsp2_qup2_spi_apps_clk",
+			.parent_names = (const char *[]){
+				"blsp2_qup2_spi_apps_clk_src",
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch gcc_blsp2_qup3_i2c_apps_clk = {
+	.halt_reg = 0x0a88,
+	.hw = {
+		.enable_reg = 0x0a88,
+		.enable_mask = BIT(0),
+		.init = &(struct clk_init_data){
+			.name = "gcc_blsp2_qup3_i2c_apps_clk",
+			.parent_names = (const char *[]){
+				"blsp2_qup3_i2c_apps_clk_src",
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch gcc_blsp2_qup3_spi_apps_clk = {
+	.halt_reg = 0x0a84,
+	.hw = {
+		.enable_reg = 0x0a84,
+		.enable_mask = BIT(0),
+		.init = &(struct clk_init_data){
+			.name = "gcc_blsp2_qup3_spi_apps_clk",
+			.parent_names = (const char *[]){
+				"blsp2_qup3_spi_apps_clk_src",
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch gcc_blsp2_qup4_i2c_apps_clk = {
+	.halt_reg = 0x0b08,
+	.hw = {
+		.enable_reg = 0x0b08,
+		.enable_mask = BIT(0),
+		.init = &(struct clk_init_data){
+			.name = "gcc_blsp2_qup4_i2c_apps_clk",
+			.parent_names = (const char *[]){
+				"blsp2_qup4_i2c_apps_clk_src",
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch gcc_blsp2_qup4_spi_apps_clk = {
+	.halt_reg = 0x0b04,
+	.hw = {
+		.enable_reg = 0x0b04,
+		.enable_mask = BIT(0),
+		.init = &(struct clk_init_data){
+			.name = "gcc_blsp2_qup4_spi_apps_clk",
+			.parent_names = (const char *[]){
+				"blsp2_qup4_spi_apps_clk_src",
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch gcc_blsp2_qup5_i2c_apps_clk = {
+	.halt_reg = 0x0b88,
+	.hw = {
+		.enable_reg = 0x0b88,
+		.enable_mask = BIT(0),
+		.init = &(struct clk_init_data){
+			.name = "gcc_blsp2_qup5_i2c_apps_clk",
+			.parent_names = (const char *[]){
+				"blsp2_qup5_i2c_apps_clk_src",
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch gcc_blsp2_qup5_spi_apps_clk = {
+	.halt_reg = 0x0b84,
+	.hw = {
+		.enable_reg = 0x0b84,
+		.enable_mask = BIT(0),
+		.init = &(struct clk_init_data){
+			.name = "gcc_blsp2_qup5_spi_apps_clk",
+			.parent_names = (const char *[]){
+				"blsp2_qup5_spi_apps_clk_src",
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch gcc_blsp2_qup6_i2c_apps_clk = {
+	.halt_reg = 0x0c08,
+	.hw = {
+		.enable_reg = 0x0c08,
+		.enable_mask = BIT(0),
+		.init = &(struct clk_init_data){
+			.name = "gcc_blsp2_qup6_i2c_apps_clk",
+			.parent_names = (const char *[]){
+				"blsp2_qup6_i2c_apps_clk_src",
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch gcc_blsp2_qup6_spi_apps_clk = {
+	.halt_reg = 0x0c04,
+	.hw = {
+		.enable_reg = 0x0c04,
+		.enable_mask = BIT(0),
+		.init = &(struct clk_init_data){
+			.name = "gcc_blsp2_qup6_spi_apps_clk",
+			.parent_names = (const char *[]){
+				"blsp2_qup6_spi_apps_clk_src",
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch gcc_blsp2_uart1_apps_clk = {
+	.halt_reg = 0x09c4,
+	.hw = {
+		.enable_reg = 0x09c4,
+		.enable_mask = BIT(0),
+		.init = &(struct clk_init_data){
+			.name = "gcc_blsp2_uart1_apps_clk",
+			.parent_names = (const char *[]){
+				"blsp2_uart1_apps_clk_src",
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch gcc_blsp2_uart2_apps_clk = {
+	.halt_reg = 0x0a44,
+	.hw = {
+		.enable_reg = 0x0a44,
+		.enable_mask = BIT(0),
+		.init = &(struct clk_init_data){
+			.name = "gcc_blsp2_uart2_apps_clk",
+			.parent_names = (const char *[]){
+				"blsp2_uart2_apps_clk_src",
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch gcc_blsp2_uart3_apps_clk = {
+	.halt_reg = 0x0ac4,
+	.hw = {
+		.enable_reg = 0x0ac4,
+		.enable_mask = BIT(0),
+		.init = &(struct clk_init_data){
+			.name = "gcc_blsp2_uart3_apps_clk",
+			.parent_names = (const char *[]){
+				"blsp2_uart3_apps_clk_src",
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch gcc_blsp2_uart4_apps_clk = {
+	.halt_reg = 0x0b44,
+	.hw = {
+		.enable_reg = 0x0b44,
+		.enable_mask = BIT(0),
+		.init = &(struct clk_init_data){
+			.name = "gcc_blsp2_uart4_apps_clk",
+			.parent_names = (const char *[]){
+				"blsp2_uart4_apps_clk_src",
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch gcc_blsp2_uart5_apps_clk = {
+	.halt_reg = 0x0bc4,
+	.hw = {
+		.enable_reg = 0x0bc4,
+		.enable_mask = BIT(0),
+		.init = &(struct clk_init_data){
+			.name = "gcc_blsp2_uart5_apps_clk",
+			.parent_names = (const char *[]){
+				"blsp2_uart5_apps_clk_src",
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch gcc_blsp2_uart6_apps_clk = {
+	.halt_reg = 0x0c44,
+	.hw = {
+		.enable_reg = 0x0c44,
+		.enable_mask = BIT(0),
+		.init = &(struct clk_init_data){
+			.name = "gcc_blsp2_uart6_apps_clk",
+			.parent_names = (const char *[]){
+				"blsp2_uart6_apps_clk_src",
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch gcc_boot_rom_ahb_clk = {
+	.halt_reg = 0x0e04,
+	.halt_check = BRANCH_HALT_VOTED,
+	.hw = {
+		.enable_reg = 0x1484,
+		.enable_mask = BIT(10),
+		.init = &(struct clk_init_data){
+			.name = "gcc_boot_rom_ahb_clk",
+			.parent_names = (const char *[]){
+				"config_noc_clk_src",
+			},
+			.num_parents = 1,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch gcc_ce1_ahb_clk = {
+	.halt_reg = 0x104c,
+	.halt_check = BRANCH_HALT_VOTED,
+	.hw = {
+		.enable_reg = 0x1484,
+		.enable_mask = BIT(3),
+		.init = &(struct clk_init_data){
+			.name = "gcc_ce1_ahb_clk",
+			.parent_names = (const char *[]){
+				"config_noc_clk_src",
+			},
+			.num_parents = 1,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch gcc_ce1_axi_clk = {
+	.halt_reg = 0x1048,
+	.halt_check = BRANCH_HALT_VOTED,
+	.hw = {
+		.enable_reg = 0x1484,
+		.enable_mask = BIT(4),
+		.init = &(struct clk_init_data){
+			.name = "gcc_ce1_axi_clk",
+			.parent_names = (const char *[]){
+				"system_noc_clk_src",
+			},
+			.num_parents = 1,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch gcc_ce1_clk = {
+	.halt_reg = 0x1050,
+	.halt_check = BRANCH_HALT_VOTED,
+	.hw = {
+		.enable_reg = 0x1484,
+		.enable_mask = BIT(5),
+		.init = &(struct clk_init_data){
+			.name = "gcc_ce1_clk",
+			.parent_names = (const char *[]){
+				"ce1_clk_src",
+			},
+			.num_parents = 1,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch gcc_ce2_ahb_clk = {
+	.halt_reg = 0x108c,
+	.halt_check = BRANCH_HALT_VOTED,
+	.hw = {
+		.enable_reg = 0x1484,
+		.enable_mask = BIT(0),
+		.init = &(struct clk_init_data){
+			.name = "gcc_ce2_ahb_clk",
+			.parent_names = (const char *[]){
+				"config_noc_clk_src",
+			},
+			.num_parents = 1,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch gcc_ce2_axi_clk = {
+	.halt_reg = 0x1088,
+	.halt_check = BRANCH_HALT_VOTED,
+	.hw = {
+		.enable_reg = 0x1484,
+		.enable_mask = BIT(1),
+		.init = &(struct clk_init_data){
+			.name = "gcc_ce2_axi_clk",
+			.parent_names = (const char *[]){
+				"system_noc_clk_src",
+			},
+			.num_parents = 1,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch gcc_ce2_clk = {
+	.halt_reg = 0x1090,
+	.halt_check = BRANCH_HALT_VOTED,
+	.hw = {
+		.enable_reg = 0x1484,
+		.enable_mask = BIT(2),
+		.init = &(struct clk_init_data){
+			.name = "gcc_ce2_clk",
+			.parent_names = (const char *[]){
+				"ce2_clk_src",
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch gcc_gp1_clk = {
+	.halt_reg = 0x1900,
+	.hw = {
+		.enable_reg = 0x1900,
+		.enable_mask = BIT(0),
+		.init = &(struct clk_init_data){
+			.name = "gcc_gp1_clk",
+			.parent_names = (const char *[]){
+				"gp1_clk_src",
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch gcc_gp2_clk = {
+	.halt_reg = 0x1940,
+	.hw = {
+		.enable_reg = 0x1940,
+		.enable_mask = BIT(0),
+		.init = &(struct clk_init_data){
+			.name = "gcc_gp2_clk",
+			.parent_names = (const char *[]){
+				"gp2_clk_src",
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch gcc_gp3_clk = {
+	.halt_reg = 0x1980,
+	.hw = {
+		.enable_reg = 0x1980,
+		.enable_mask = BIT(0),
+		.init = &(struct clk_init_data){
+			.name = "gcc_gp3_clk",
+			.parent_names = (const char *[]){
+				"gp3_clk_src",
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch gcc_lpass_q6_axi_clk = {
+	.halt_reg = 0x11c0,
+	.hw = {
+		.enable_reg = 0x11c0,
+		.enable_mask = BIT(0),
+		.init = &(struct clk_init_data){
+			.name = "gcc_lpass_q6_axi_clk",
+			.parent_names = (const char *[]){
+				"system_noc_clk_src",
+			},
+			.num_parents = 1,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch gcc_mmss_noc_cfg_ahb_clk = {
+	.halt_reg = 0x024c,
+	.hw = {
+		.enable_reg = 0x024c,
+		.enable_mask = BIT(0),
+		.init = &(struct clk_init_data){
+			.name = "gcc_mmss_noc_cfg_ahb_clk",
+			.parent_names = (const char *[]){
+				"config_noc_clk_src",
+			},
+			.num_parents = 1,
+			.ops = &clk_branch2_ops,
+			.flags = CLK_IGNORE_UNUSED,
+		},
+	},
+};
+
+static struct clk_branch gcc_ocmem_noc_cfg_ahb_clk = {
+	.halt_reg = 0x0248,
+	.hw = {
+		.enable_reg = 0x0248,
+		.enable_mask = BIT(0),
+		.init = &(struct clk_init_data){
+			.name = "gcc_ocmem_noc_cfg_ahb_clk",
+			.parent_names = (const char *[]){
+				"config_noc_clk_src",
+			},
+			.num_parents = 1,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch gcc_mss_cfg_ahb_clk = {
+	.halt_reg = 0x0280,
+	.hw = {
+		.enable_reg = 0x0280,
+		.enable_mask = BIT(0),
+		.init = &(struct clk_init_data){
+			.name = "gcc_mss_cfg_ahb_clk",
+			.parent_names = (const char *[]){
+				"config_noc_clk_src",
+			},
+			.num_parents = 1,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch gcc_mss_q6_bimc_axi_clk = {
+	.halt_reg = 0x0284,
+	.hw = {
+		.enable_reg = 0x0284,
+		.enable_mask = BIT(0),
+		.init = &(struct clk_init_data){
+			.name = "gcc_mss_q6_bimc_axi_clk",
+			.flags = CLK_IS_ROOT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch gcc_pdm2_clk = {
+	.halt_reg = 0x0ccc,
+	.hw = {
+		.enable_reg = 0x0ccc,
+		.enable_mask = BIT(0),
+		.init = &(struct clk_init_data){
+			.name = "gcc_pdm2_clk",
+			.parent_names = (const char *[]){
+				"pdm2_clk_src",
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch gcc_pdm_ahb_clk = {
+	.halt_reg = 0x0cc4,
+	.hw = {
+		.enable_reg = 0x0cc4,
+		.enable_mask = BIT(0),
+		.init = &(struct clk_init_data){
+			.name = "gcc_pdm_ahb_clk",
+			.parent_names = (const char *[]){
+				"periph_noc_clk_src",
+			},
+			.num_parents = 1,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch gcc_prng_ahb_clk = {
+	.halt_reg = 0x0d04,
+	.halt_check = BRANCH_HALT_VOTED,
+	.hw = {
+		.enable_reg = 0x1484,
+		.enable_mask = BIT(13),
+		.init = &(struct clk_init_data){
+			.name = "gcc_prng_ahb_clk",
+			.parent_names = (const char *[]){
+				"periph_noc_clk_src",
+			},
+			.num_parents = 1,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch gcc_sdcc1_ahb_clk = {
+	.halt_reg = 0x04c8,
+	.hw = {
+		.enable_reg = 0x04c8,
+		.enable_mask = BIT(0),
+		.init = &(struct clk_init_data){
+			.name = "gcc_sdcc1_ahb_clk",
+			.parent_names = (const char *[]){
+				"periph_noc_clk_src",
+			},
+			.num_parents = 1,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch gcc_sdcc1_apps_clk = {
+	.halt_reg = 0x04c4,
+	.hw = {
+		.enable_reg = 0x04c4,
+		.enable_mask = BIT(0),
+		.init = &(struct clk_init_data){
+			.name = "gcc_sdcc1_apps_clk",
+			.parent_names = (const char *[]){
+				"sdcc1_apps_clk_src",
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch gcc_sdcc2_ahb_clk = {
+	.halt_reg = 0x0508,
+	.hw = {
+		.enable_reg = 0x0508,
+		.enable_mask = BIT(0),
+		.init = &(struct clk_init_data){
+			.name = "gcc_sdcc2_ahb_clk",
+			.parent_names = (const char *[]){
+				"periph_noc_clk_src",
+			},
+			.num_parents = 1,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch gcc_sdcc2_apps_clk = {
+	.halt_reg = 0x0504,
+	.hw = {
+		.enable_reg = 0x0504,
+		.enable_mask = BIT(0),
+		.init = &(struct clk_init_data){
+			.name = "gcc_sdcc2_apps_clk",
+			.parent_names = (const char *[]){
+				"sdcc2_apps_clk_src",
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch gcc_sdcc3_ahb_clk = {
+	.halt_reg = 0x0548,
+	.hw = {
+		.enable_reg = 0x0548,
+		.enable_mask = BIT(0),
+		.init = &(struct clk_init_data){
+			.name = "gcc_sdcc3_ahb_clk",
+			.parent_names = (const char *[]){
+				"periph_noc_clk_src",
+			},
+			.num_parents = 1,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch gcc_sdcc3_apps_clk = {
+	.halt_reg = 0x0544,
+	.hw = {
+		.enable_reg = 0x0544,
+		.enable_mask = BIT(0),
+		.init = &(struct clk_init_data){
+			.name = "gcc_sdcc3_apps_clk",
+			.parent_names = (const char *[]){
+				"sdcc3_apps_clk_src",
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch gcc_sdcc4_ahb_clk = {
+	.halt_reg = 0x0588,
+	.hw = {
+		.enable_reg = 0x0588,
+		.enable_mask = BIT(0),
+		.init = &(struct clk_init_data){
+			.name = "gcc_sdcc4_ahb_clk",
+			.parent_names = (const char *[]){
+				"periph_noc_clk_src",
+			},
+			.num_parents = 1,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch gcc_sdcc4_apps_clk = {
+	.halt_reg = 0x0584,
+	.hw = {
+		.enable_reg = 0x0584,
+		.enable_mask = BIT(0),
+		.init = &(struct clk_init_data){
+			.name = "gcc_sdcc4_apps_clk",
+			.parent_names = (const char *[]){
+				"sdcc4_apps_clk_src",
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch gcc_sys_noc_usb3_axi_clk = {
+	.halt_reg = 0x0108,
+	.hw = {
+		.enable_reg = 0x0108,
+		.enable_mask = BIT(0),
+		.init = &(struct clk_init_data){
+			.name = "gcc_sys_noc_usb3_axi_clk",
+			.parent_names = (const char *[]){
+				"usb30_master_clk_src",
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch gcc_tsif_ahb_clk = {
+	.halt_reg = 0x0d84,
+	.hw = {
+		.enable_reg = 0x0d84,
+		.enable_mask = BIT(0),
+		.init = &(struct clk_init_data){
+			.name = "gcc_tsif_ahb_clk",
+			.parent_names = (const char *[]){
+				"periph_noc_clk_src",
+			},
+			.num_parents = 1,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch gcc_tsif_ref_clk = {
+	.halt_reg = 0x0d88,
+	.hw = {
+		.enable_reg = 0x0d88,
+		.enable_mask = BIT(0),
+		.init = &(struct clk_init_data){
+			.name = "gcc_tsif_ref_clk",
+			.parent_names = (const char *[]){
+				"tsif_ref_clk_src",
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch gcc_usb2a_phy_sleep_clk = {
+	.halt_reg = 0x04ac,
+	.hw = {
+		.enable_reg = 0x04ac,
+		.enable_mask = BIT(0),
+		.init = &(struct clk_init_data){
+			.name = "gcc_usb2a_phy_sleep_clk",
+			.parent_names = (const char *[]){
+				"sleep_clk_src",
+			},
+			.num_parents = 1,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch gcc_usb2b_phy_sleep_clk = {
+	.halt_reg = 0x04b4,
+	.hw = {
+		.enable_reg = 0x04b4,
+		.enable_mask = BIT(0),
+		.init = &(struct clk_init_data){
+			.name = "gcc_usb2b_phy_sleep_clk",
+			.parent_names = (const char *[]){
+				"sleep_clk_src",
+			},
+			.num_parents = 1,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch gcc_usb30_master_clk = {
+	.halt_reg = 0x03c8,
+	.hw = {
+		.enable_reg = 0x03c8,
+		.enable_mask = BIT(0),
+		.init = &(struct clk_init_data){
+			.name = "gcc_usb30_master_clk",
+			.parent_names = (const char *[]){
+				"usb30_master_clk_src",
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch gcc_usb30_mock_utmi_clk = {
+	.halt_reg = 0x03d0,
+	.hw = {
+		.enable_reg = 0x03d0,
+		.enable_mask = BIT(0),
+		.init = &(struct clk_init_data){
+			.name = "gcc_usb30_mock_utmi_clk",
+			.parent_names = (const char *[]){
+				"usb30_mock_utmi_clk_src",
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch gcc_usb30_sleep_clk = {
+	.halt_reg = 0x03cc,
+	.hw = {
+		.enable_reg = 0x03cc,
+		.enable_mask = BIT(0),
+		.init = &(struct clk_init_data){
+			.name = "gcc_usb30_sleep_clk",
+			.parent_names = (const char *[]){
+				"sleep_clk_src",
+			},
+			.num_parents = 1,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch gcc_usb_hs_ahb_clk = {
+	.halt_reg = 0x0488,
+	.hw = {
+		.enable_reg = 0x0488,
+		.enable_mask = BIT(0),
+		.init = &(struct clk_init_data){
+			.name = "gcc_usb_hs_ahb_clk",
+			.parent_names = (const char *[]){
+				"periph_noc_clk_src",
+			},
+			.num_parents = 1,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch gcc_usb_hs_system_clk = {
+	.halt_reg = 0x0484,
+	.hw = {
+		.enable_reg = 0x0484,
+		.enable_mask = BIT(0),
+		.init = &(struct clk_init_data){
+			.name = "gcc_usb_hs_system_clk",
+			.parent_names = (const char *[]){
+				"usb_hs_system_clk_src",
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch gcc_usb_hsic_ahb_clk = {
+	.halt_reg = 0x0408,
+	.hw = {
+		.enable_reg = 0x0408,
+		.enable_mask = BIT(0),
+		.init = &(struct clk_init_data){
+			.name = "gcc_usb_hsic_ahb_clk",
+			.parent_names = (const char *[]){
+				"periph_noc_clk_src",
+			},
+			.num_parents = 1,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch gcc_usb_hsic_clk = {
+	.halt_reg = 0x0410,
+	.hw = {
+		.enable_reg = 0x0410,
+		.enable_mask = BIT(0),
+		.init = &(struct clk_init_data){
+			.name = "gcc_usb_hsic_clk",
+			.parent_names = (const char *[]){
+				"usb_hsic_clk_src",
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch gcc_usb_hsic_io_cal_clk = {
+	.halt_reg = 0x0414,
+	.hw = {
+		.enable_reg = 0x0414,
+		.enable_mask = BIT(0),
+		.init = &(struct clk_init_data){
+			.name = "gcc_usb_hsic_io_cal_clk",
+			.parent_names = (const char *[]){
+				"usb_hsic_io_cal_clk_src",
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch gcc_usb_hsic_io_cal_sleep_clk = {
+	.halt_reg = 0x0418,
+	.hw = {
+		.enable_reg = 0x0418,
+		.enable_mask = BIT(0),
+		.init = &(struct clk_init_data){
+			.name = "gcc_usb_hsic_io_cal_sleep_clk",
+			.parent_names = (const char *[]){
+				"sleep_clk_src",
+			},
+			.num_parents = 1,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch gcc_usb_hsic_system_clk = {
+	.halt_reg = 0x040c,
+	.hw = {
+		.enable_reg = 0x040c,
+		.enable_mask = BIT(0),
+		.init = &(struct clk_init_data){
+			.name = "gcc_usb_hsic_system_clk",
+			.parent_names = (const char *[]){
+				"usb_hsic_system_clk_src",
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_hw *gcc_msm8974_clocks[] = {
+	[GPLL0] = &gpll0.hw,
+	[GPLL0_VOTE] = &gpll0_vote,
+	[CONFIG_NOC_CLK_SRC] = &config_noc_clk_src.hw,
+	[PERIPH_NOC_CLK_SRC] = &periph_noc_clk_src.hw,
+	[SYSTEM_NOC_CLK_SRC] = &system_noc_clk_src.hw,
+	[GPLL1] = &gpll1.hw,
+	[GPLL1_VOTE] = &gpll1_vote,
+	[USB30_MASTER_CLK_SRC] = &usb30_master_clk_src.hw,
+	[BLSP1_QUP1_I2C_APPS_CLK_SRC] = &blsp1_qup1_i2c_apps_clk_src.hw,
+	[BLSP1_QUP1_SPI_APPS_CLK_SRC] = &blsp1_qup1_spi_apps_clk_src.hw,
+	[BLSP1_QUP2_I2C_APPS_CLK_SRC] = &blsp1_qup2_i2c_apps_clk_src.hw,
+	[BLSP1_QUP2_SPI_APPS_CLK_SRC] = &blsp1_qup2_spi_apps_clk_src.hw,
+	[BLSP1_QUP3_I2C_APPS_CLK_SRC] = &blsp1_qup3_i2c_apps_clk_src.hw,
+	[BLSP1_QUP3_SPI_APPS_CLK_SRC] = &blsp1_qup3_spi_apps_clk_src.hw,
+	[BLSP1_QUP4_I2C_APPS_CLK_SRC] = &blsp1_qup4_i2c_apps_clk_src.hw,
+	[BLSP1_QUP4_SPI_APPS_CLK_SRC] = &blsp1_qup4_spi_apps_clk_src.hw,
+	[BLSP1_QUP5_I2C_APPS_CLK_SRC] = &blsp1_qup5_i2c_apps_clk_src.hw,
+	[BLSP1_QUP5_SPI_APPS_CLK_SRC] = &blsp1_qup5_spi_apps_clk_src.hw,
+	[BLSP1_QUP6_I2C_APPS_CLK_SRC] = &blsp1_qup6_i2c_apps_clk_src.hw,
+	[BLSP1_QUP6_SPI_APPS_CLK_SRC] = &blsp1_qup6_spi_apps_clk_src.hw,
+	[BLSP1_UART1_APPS_CLK_SRC] = &blsp1_uart1_apps_clk_src.hw,
+	[BLSP1_UART2_APPS_CLK_SRC] = &blsp1_uart2_apps_clk_src.hw,
+	[BLSP1_UART3_APPS_CLK_SRC] = &blsp1_uart3_apps_clk_src.hw,
+	[BLSP1_UART4_APPS_CLK_SRC] = &blsp1_uart4_apps_clk_src.hw,
+	[BLSP1_UART5_APPS_CLK_SRC] = &blsp1_uart5_apps_clk_src.hw,
+	[BLSP1_UART6_APPS_CLK_SRC] = &blsp1_uart6_apps_clk_src.hw,
+	[BLSP2_QUP1_I2C_APPS_CLK_SRC] = &blsp2_qup1_i2c_apps_clk_src.hw,
+	[BLSP2_QUP1_SPI_APPS_CLK_SRC] = &blsp2_qup1_spi_apps_clk_src.hw,
+	[BLSP2_QUP2_I2C_APPS_CLK_SRC] = &blsp2_qup2_i2c_apps_clk_src.hw,
+	[BLSP2_QUP2_SPI_APPS_CLK_SRC] = &blsp2_qup2_spi_apps_clk_src.hw,
+	[BLSP2_QUP3_I2C_APPS_CLK_SRC] = &blsp2_qup3_i2c_apps_clk_src.hw,
+	[BLSP2_QUP3_SPI_APPS_CLK_SRC] = &blsp2_qup3_spi_apps_clk_src.hw,
+	[BLSP2_QUP4_I2C_APPS_CLK_SRC] = &blsp2_qup4_i2c_apps_clk_src.hw,
+	[BLSP2_QUP4_SPI_APPS_CLK_SRC] = &blsp2_qup4_spi_apps_clk_src.hw,
+	[BLSP2_QUP5_I2C_APPS_CLK_SRC] = &blsp2_qup5_i2c_apps_clk_src.hw,
+	[BLSP2_QUP5_SPI_APPS_CLK_SRC] = &blsp2_qup5_spi_apps_clk_src.hw,
+	[BLSP2_QUP6_I2C_APPS_CLK_SRC] = &blsp2_qup6_i2c_apps_clk_src.hw,
+	[BLSP2_QUP6_SPI_APPS_CLK_SRC] = &blsp2_qup6_spi_apps_clk_src.hw,
+	[BLSP2_UART1_APPS_CLK_SRC] = &blsp2_uart1_apps_clk_src.hw,
+	[BLSP2_UART2_APPS_CLK_SRC] = &blsp2_uart2_apps_clk_src.hw,
+	[BLSP2_UART3_APPS_CLK_SRC] = &blsp2_uart3_apps_clk_src.hw,
+	[BLSP2_UART4_APPS_CLK_SRC] = &blsp2_uart4_apps_clk_src.hw,
+	[BLSP2_UART5_APPS_CLK_SRC] = &blsp2_uart5_apps_clk_src.hw,
+	[BLSP2_UART6_APPS_CLK_SRC] = &blsp2_uart6_apps_clk_src.hw,
+	[CE1_CLK_SRC] = &ce1_clk_src.hw,
+	[CE2_CLK_SRC] = &ce2_clk_src.hw,
+	[GP1_CLK_SRC] = &gp1_clk_src.hw,
+	[GP2_CLK_SRC] = &gp2_clk_src.hw,
+	[GP3_CLK_SRC] = &gp3_clk_src.hw,
+	[PDM2_CLK_SRC] = &pdm2_clk_src.hw,
+	[SDCC1_APPS_CLK_SRC] = &sdcc1_apps_clk_src.hw,
+	[SDCC2_APPS_CLK_SRC] = &sdcc2_apps_clk_src.hw,
+	[SDCC3_APPS_CLK_SRC] = &sdcc3_apps_clk_src.hw,
+	[SDCC4_APPS_CLK_SRC] = &sdcc4_apps_clk_src.hw,
+	[TSIF_REF_CLK_SRC] = &tsif_ref_clk_src.hw,
+	[USB30_MOCK_UTMI_CLK_SRC] = &usb30_mock_utmi_clk_src.hw,
+	[USB_HS_SYSTEM_CLK_SRC] = &usb_hs_system_clk_src.hw,
+	[USB_HSIC_CLK_SRC] = &usb_hsic_clk_src.hw,
+	[USB_HSIC_IO_CAL_CLK_SRC] = &usb_hsic_io_cal_clk_src.hw,
+	[USB_HSIC_SYSTEM_CLK_SRC] = &usb_hsic_system_clk_src.hw,
+	[GCC_BAM_DMA_AHB_CLK] = &gcc_bam_dma_ahb_clk.hw,
+	[GCC_BLSP1_AHB_CLK] = &gcc_blsp1_ahb_clk.hw,
+	[GCC_BLSP1_QUP1_I2C_APPS_CLK] = &gcc_blsp1_qup1_i2c_apps_clk.hw,
+	[GCC_BLSP1_QUP1_SPI_APPS_CLK] = &gcc_blsp1_qup1_spi_apps_clk.hw,
+	[GCC_BLSP1_QUP2_I2C_APPS_CLK] = &gcc_blsp1_qup2_i2c_apps_clk.hw,
+	[GCC_BLSP1_QUP2_SPI_APPS_CLK] = &gcc_blsp1_qup2_spi_apps_clk.hw,
+	[GCC_BLSP1_QUP3_I2C_APPS_CLK] = &gcc_blsp1_qup3_i2c_apps_clk.hw,
+	[GCC_BLSP1_QUP3_SPI_APPS_CLK] = &gcc_blsp1_qup3_spi_apps_clk.hw,
+	[GCC_BLSP1_QUP4_I2C_APPS_CLK] = &gcc_blsp1_qup4_i2c_apps_clk.hw,
+	[GCC_BLSP1_QUP4_SPI_APPS_CLK] = &gcc_blsp1_qup4_spi_apps_clk.hw,
+	[GCC_BLSP1_QUP5_I2C_APPS_CLK] = &gcc_blsp1_qup5_i2c_apps_clk.hw,
+	[GCC_BLSP1_QUP5_SPI_APPS_CLK] = &gcc_blsp1_qup5_spi_apps_clk.hw,
+	[GCC_BLSP1_QUP6_I2C_APPS_CLK] = &gcc_blsp1_qup6_i2c_apps_clk.hw,
+	[GCC_BLSP1_QUP6_SPI_APPS_CLK] = &gcc_blsp1_qup6_spi_apps_clk.hw,
+	[GCC_BLSP1_UART1_APPS_CLK] = &gcc_blsp1_uart1_apps_clk.hw,
+	[GCC_BLSP1_UART2_APPS_CLK] = &gcc_blsp1_uart2_apps_clk.hw,
+	[GCC_BLSP1_UART3_APPS_CLK] = &gcc_blsp1_uart3_apps_clk.hw,
+	[GCC_BLSP1_UART4_APPS_CLK] = &gcc_blsp1_uart4_apps_clk.hw,
+	[GCC_BLSP1_UART5_APPS_CLK] = &gcc_blsp1_uart5_apps_clk.hw,
+	[GCC_BLSP1_UART6_APPS_CLK] = &gcc_blsp1_uart6_apps_clk.hw,
+	[GCC_BLSP2_AHB_CLK] = &gcc_blsp2_ahb_clk.hw,
+	[GCC_BLSP2_QUP1_I2C_APPS_CLK] = &gcc_blsp2_qup1_i2c_apps_clk.hw,
+	[GCC_BLSP2_QUP1_SPI_APPS_CLK] = &gcc_blsp2_qup1_spi_apps_clk.hw,
+	[GCC_BLSP2_QUP2_I2C_APPS_CLK] = &gcc_blsp2_qup2_i2c_apps_clk.hw,
+	[GCC_BLSP2_QUP2_SPI_APPS_CLK] = &gcc_blsp2_qup2_spi_apps_clk.hw,
+	[GCC_BLSP2_QUP3_I2C_APPS_CLK] = &gcc_blsp2_qup3_i2c_apps_clk.hw,
+	[GCC_BLSP2_QUP3_SPI_APPS_CLK] = &gcc_blsp2_qup3_spi_apps_clk.hw,
+	[GCC_BLSP2_QUP4_I2C_APPS_CLK] = &gcc_blsp2_qup4_i2c_apps_clk.hw,
+	[GCC_BLSP2_QUP4_SPI_APPS_CLK] = &gcc_blsp2_qup4_spi_apps_clk.hw,
+	[GCC_BLSP2_QUP5_I2C_APPS_CLK] = &gcc_blsp2_qup5_i2c_apps_clk.hw,
+	[GCC_BLSP2_QUP5_SPI_APPS_CLK] = &gcc_blsp2_qup5_spi_apps_clk.hw,
+	[GCC_BLSP2_QUP6_I2C_APPS_CLK] = &gcc_blsp2_qup6_i2c_apps_clk.hw,
+	[GCC_BLSP2_QUP6_SPI_APPS_CLK] = &gcc_blsp2_qup6_spi_apps_clk.hw,
+	[GCC_BLSP2_UART1_APPS_CLK] = &gcc_blsp2_uart1_apps_clk.hw,
+	[GCC_BLSP2_UART2_APPS_CLK] = &gcc_blsp2_uart2_apps_clk.hw,
+	[GCC_BLSP2_UART3_APPS_CLK] = &gcc_blsp2_uart3_apps_clk.hw,
+	[GCC_BLSP2_UART4_APPS_CLK] = &gcc_blsp2_uart4_apps_clk.hw,
+	[GCC_BLSP2_UART5_APPS_CLK] = &gcc_blsp2_uart5_apps_clk.hw,
+	[GCC_BLSP2_UART6_APPS_CLK] = &gcc_blsp2_uart6_apps_clk.hw,
+	[GCC_BOOT_ROM_AHB_CLK] = &gcc_boot_rom_ahb_clk.hw,
+	[GCC_CE1_AHB_CLK] = &gcc_ce1_ahb_clk.hw,
+	[GCC_CE1_AXI_CLK] = &gcc_ce1_axi_clk.hw,
+	[GCC_CE1_CLK] = &gcc_ce1_clk.hw,
+	[GCC_CE2_AHB_CLK] = &gcc_ce2_ahb_clk.hw,
+	[GCC_CE2_AXI_CLK] = &gcc_ce2_axi_clk.hw,
+	[GCC_CE2_CLK] = &gcc_ce2_clk.hw,
+	[GCC_GP1_CLK] = &gcc_gp1_clk.hw,
+	[GCC_GP2_CLK] = &gcc_gp2_clk.hw,
+	[GCC_GP3_CLK] = &gcc_gp3_clk.hw,
+	[GCC_LPASS_Q6_AXI_CLK] = &gcc_lpass_q6_axi_clk.hw,
+	[GCC_MMSS_NOC_CFG_AHB_CLK] = &gcc_mmss_noc_cfg_ahb_clk.hw,
+	[GCC_OCMEM_NOC_CFG_AHB_CLK] = &gcc_ocmem_noc_cfg_ahb_clk.hw,
+	[GCC_MSS_CFG_AHB_CLK] = &gcc_mss_cfg_ahb_clk.hw,
+	[GCC_MSS_Q6_BIMC_AXI_CLK] = &gcc_mss_q6_bimc_axi_clk.hw,
+	[GCC_PDM2_CLK] = &gcc_pdm2_clk.hw,
+	[GCC_PDM_AHB_CLK] = &gcc_pdm_ahb_clk.hw,
+	[GCC_PRNG_AHB_CLK] = &gcc_prng_ahb_clk.hw,
+	[GCC_SDCC1_AHB_CLK] = &gcc_sdcc1_ahb_clk.hw,
+	[GCC_SDCC1_APPS_CLK] = &gcc_sdcc1_apps_clk.hw,
+	[GCC_SDCC2_AHB_CLK] = &gcc_sdcc2_ahb_clk.hw,
+	[GCC_SDCC2_APPS_CLK] = &gcc_sdcc2_apps_clk.hw,
+	[GCC_SDCC3_AHB_CLK] = &gcc_sdcc3_ahb_clk.hw,
+	[GCC_SDCC3_APPS_CLK] = &gcc_sdcc3_apps_clk.hw,
+	[GCC_SDCC4_AHB_CLK] = &gcc_sdcc4_ahb_clk.hw,
+	[GCC_SDCC4_APPS_CLK] = &gcc_sdcc4_apps_clk.hw,
+	[GCC_SYS_NOC_USB3_AXI_CLK] = &gcc_sys_noc_usb3_axi_clk.hw,
+	[GCC_TSIF_AHB_CLK] = &gcc_tsif_ahb_clk.hw,
+	[GCC_TSIF_REF_CLK] = &gcc_tsif_ref_clk.hw,
+	[GCC_USB2A_PHY_SLEEP_CLK] = &gcc_usb2a_phy_sleep_clk.hw,
+	[GCC_USB2B_PHY_SLEEP_CLK] = &gcc_usb2b_phy_sleep_clk.hw,
+	[GCC_USB30_MASTER_CLK] = &gcc_usb30_master_clk.hw,
+	[GCC_USB30_MOCK_UTMI_CLK] = &gcc_usb30_mock_utmi_clk.hw,
+	[GCC_USB30_SLEEP_CLK] = &gcc_usb30_sleep_clk.hw,
+	[GCC_USB_HS_AHB_CLK] = &gcc_usb_hs_ahb_clk.hw,
+	[GCC_USB_HS_SYSTEM_CLK] = &gcc_usb_hs_system_clk.hw,
+	[GCC_USB_HSIC_AHB_CLK] = &gcc_usb_hsic_ahb_clk.hw,
+	[GCC_USB_HSIC_CLK] = &gcc_usb_hsic_clk.hw,
+	[GCC_USB_HSIC_IO_CAL_CLK] = &gcc_usb_hsic_io_cal_clk.hw,
+	[GCC_USB_HSIC_IO_CAL_SLEEP_CLK] = &gcc_usb_hsic_io_cal_sleep_clk.hw,
+	[GCC_USB_HSIC_SYSTEM_CLK] = &gcc_usb_hsic_system_clk.hw,
+	[GCC_MMSS_GPLL0_CLK_SRC] = &gcc_mmss_gpll0_clk_src,
+};
+
+static const struct qcom_reset_map gcc_msm8974_resets[] = {
+	[GCC_SYSTEM_NOC_BCR] = { 0x0100 },
+	[GCC_CONFIG_NOC_BCR] = { 0x0140 },
+	[GCC_PERIPH_NOC_BCR] = { 0x0180 },
+	[GCC_IMEM_BCR] = { 0x0200 },
+	[GCC_MMSS_BCR] = { 0x0240 },
+	[GCC_QDSS_BCR] = { 0x0300 },
+	[GCC_USB_30_BCR] = { 0x03c0 },
+	[GCC_USB3_PHY_BCR] = { 0x03fc },
+	[GCC_USB_HS_HSIC_BCR] = { 0x0400 },
+	[GCC_USB_HS_BCR] = { 0x0480 },
+	[GCC_USB2A_PHY_BCR] = { 0x04a8 },
+	[GCC_USB2B_PHY_BCR] = { 0x04b0 },
+	[GCC_SDCC1_BCR] = { 0x04c0 },
+	[GCC_SDCC2_BCR] = { 0x0500 },
+	[GCC_SDCC3_BCR] = { 0x0540 },
+	[GCC_SDCC4_BCR] = { 0x0580 },
+	[GCC_BLSP1_BCR] = { 0x05c0 },
+	[GCC_BLSP1_QUP1_BCR] = { 0x0640 },
+	[GCC_BLSP1_UART1_BCR] = { 0x0680 },
+	[GCC_BLSP1_QUP2_BCR] = { 0x06c0 },
+	[GCC_BLSP1_UART2_BCR] = { 0x0700 },
+	[GCC_BLSP1_QUP3_BCR] = { 0x0740 },
+	[GCC_BLSP1_UART3_BCR] = { 0x0780 },
+	[GCC_BLSP1_QUP4_BCR] = { 0x07c0 },
+	[GCC_BLSP1_UART4_BCR] = { 0x0800 },
+	[GCC_BLSP1_QUP5_BCR] = { 0x0840 },
+	[GCC_BLSP1_UART5_BCR] = { 0x0880 },
+	[GCC_BLSP1_QUP6_BCR] = { 0x08c0 },
+	[GCC_BLSP1_UART6_BCR] = { 0x0900 },
+	[GCC_BLSP2_BCR] = { 0x0940 },
+	[GCC_BLSP2_QUP1_BCR] = { 0x0980 },
+	[GCC_BLSP2_UART1_BCR] = { 0x09c0 },
+	[GCC_BLSP2_QUP2_BCR] = { 0x0a00 },
+	[GCC_BLSP2_UART2_BCR] = { 0x0a40 },
+	[GCC_BLSP2_QUP3_BCR] = { 0x0a80 },
+	[GCC_BLSP2_UART3_BCR] = { 0x0ac0 },
+	[GCC_BLSP2_QUP4_BCR] = { 0x0b00 },
+	[GCC_BLSP2_UART4_BCR] = { 0x0b40 },
+	[GCC_BLSP2_QUP5_BCR] = { 0x0b80 },
+	[GCC_BLSP2_UART5_BCR] = { 0x0bc0 },
+	[GCC_BLSP2_QUP6_BCR] = { 0x0c00 },
+	[GCC_BLSP2_UART6_BCR] = { 0x0c40 },
+	[GCC_PDM_BCR] = { 0x0cc0 },
+	[GCC_BAM_DMA_BCR] = { 0x0d40 },
+	[GCC_TSIF_BCR] = { 0x0d80 },
+	[GCC_TCSR_BCR] = { 0x0dc0 },
+	[GCC_BOOT_ROM_BCR] = { 0x0e00 },
+	[GCC_MSG_RAM_BCR] = { 0x0e40 },
+	[GCC_TLMM_BCR] = { 0x0e80 },
+	[GCC_MPM_BCR] = { 0x0ec0 },
+	[GCC_SEC_CTRL_BCR] = { 0x0f40 },
+	[GCC_SPMI_BCR] = { 0x0fc0 },
+	[GCC_SPDM_BCR] = { 0x1000 },
+	[GCC_CE1_BCR] = { 0x1040 },
+	[GCC_CE2_BCR] = { 0x1080 },
+	[GCC_BIMC_BCR] = { 0x1100 },
+	[GCC_MPM_NON_AHB_RESET] = { 0x0ec4, 2 },
+	[GCC_MPM_AHB_RESET] = {	0x0ec4, 1 },
+	[GCC_SNOC_BUS_TIMEOUT0_BCR] = { 0x1240 },
+	[GCC_SNOC_BUS_TIMEOUT2_BCR] = { 0x1248 },
+	[GCC_PNOC_BUS_TIMEOUT0_BCR] = { 0x1280 },
+	[GCC_PNOC_BUS_TIMEOUT1_BCR] = { 0x1288 },
+	[GCC_PNOC_BUS_TIMEOUT2_BCR] = { 0x1290 },
+	[GCC_PNOC_BUS_TIMEOUT3_BCR] = { 0x1298 },
+	[GCC_PNOC_BUS_TIMEOUT4_BCR] = { 0x12a0 },
+	[GCC_CNOC_BUS_TIMEOUT0_BCR] = { 0x12c0 },
+	[GCC_CNOC_BUS_TIMEOUT1_BCR] = { 0x12c8 },
+	[GCC_CNOC_BUS_TIMEOUT2_BCR] = { 0x12d0 },
+	[GCC_CNOC_BUS_TIMEOUT3_BCR] = { 0x12d8 },
+	[GCC_CNOC_BUS_TIMEOUT4_BCR] = { 0x12e0 },
+	[GCC_CNOC_BUS_TIMEOUT5_BCR] = { 0x12e8 },
+	[GCC_CNOC_BUS_TIMEOUT6_BCR] = { 0x12f0 },
+	[GCC_DEHR_BCR] = { 0x1300 },
+	[GCC_RBCPR_BCR] = { 0x1380 },
+	[GCC_MSS_RESTART] = { 0x1680 },
+	[GCC_LPASS_RESTART] = { 0x16c0 },
+	[GCC_WCSS_RESTART] = { 0x1700 },
+	[GCC_VENUS_RESTART] = { 0x1740 },
+};
+
+static const struct regmap_config gcc_msm8974_regmap_config = {
+	.reg_bits	= 32,
+	.reg_stride	= 4,
+	.val_bits	= 32,
+	.max_register	= 0x1fc0,
+	.fast_io	= true,
+};
+
+static const struct of_device_id gcc_msm8974_match_table[] = {
+	{ .compatible = "qcom,gcc-msm8974" },
+	{ }
+};
+MODULE_DEVICE_TABLE(of, gcc_msm8974_match_table);
+
+struct qcom_cc {
+	struct qcom_reset_controller reset;
+	struct clk_onecell_data data;
+	struct clk *clks[];
+};
+
+static int gcc_msm8974_probe(struct platform_device *pdev)
+{
+	void __iomem *base;
+	struct resource *res;
+	int i, ret;
+	struct device *dev = &pdev->dev;
+	struct clk *clk;
+	struct clk_onecell_data *data;
+	struct clk **clks;
+	struct regmap *regmap;
+	size_t num_clks;
+	struct qcom_reset_controller *reset;
+	struct qcom_cc *cc;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	base = devm_ioremap_resource(dev, res);
+	if (IS_ERR(base))
+		return PTR_ERR(base);
+
+	regmap = devm_regmap_init_mmio(dev, base, &gcc_msm8974_regmap_config);
+	if (IS_ERR(regmap))
+		return PTR_ERR(regmap);
+
+	num_clks = ARRAY_SIZE(gcc_msm8974_clocks);
+	cc = devm_kzalloc(dev, sizeof(*cc) + sizeof(*clks) * num_clks,
+			  GFP_KERNEL);
+	if (!cc)
+		return -ENOMEM;
+
+	clks = cc->clks;
+	data = &cc->data;
+	data->clks = clks;
+	data->clk_num = num_clks;
+
+	/* Temporary until RPM clocks supported */
+	clk = clk_register_fixed_rate(dev, "xo", NULL, CLK_IS_ROOT, 19200000);
+	if (IS_ERR(clk))
+		return PTR_ERR(clk);
+
+	/* Should move to DT node? */
+	clk = clk_register_fixed_rate(dev, "sleep_clk_src", NULL,
+				      CLK_IS_ROOT, 32768);
+	if (IS_ERR(clk))
+		return PTR_ERR(clk);
+
+	for (i = 0; i < num_clks; i++) {
+		if (!gcc_msm8974_clocks[i])
+			continue;
+		clk = devm_clk_register(dev, gcc_msm8974_clocks[i]);
+		if (IS_ERR(clk))
+			return PTR_ERR(clk);
+		clks[i] = clk;
+	}
+
+	ret = of_clk_add_provider(dev->of_node, of_clk_src_onecell_get, data);
+	if (ret)
+		return ret;
+
+	reset = &cc->reset;
+	reset->rcdev.of_node = dev->of_node;
+	reset->rcdev.ops = &qcom_reset_ops,
+	reset->rcdev.owner = THIS_MODULE,
+	reset->rcdev.nr_resets = ARRAY_SIZE(gcc_msm8974_resets),
+	reset->regmap = regmap;
+	reset->reset_map = gcc_msm8974_resets,
+	platform_set_drvdata(pdev, &reset->rcdev);
+
+	ret = reset_controller_register(&reset->rcdev);
+	if (ret)
+		of_clk_del_provider(dev->of_node);
+
+	return ret;
+}
+
+static int gcc_msm8974_remove(struct platform_device *pdev)
+{
+	of_clk_del_provider(pdev->dev.of_node);
+	reset_controller_unregister(platform_get_drvdata(pdev));
+	return 0;
+}
+
+static struct platform_driver gcc_msm8974_driver = {
+	.probe		= gcc_msm8974_probe,
+	.remove		= gcc_msm8974_remove,
+	.driver		= {
+		.name	= "gcc-msm8974",
+		.owner	= THIS_MODULE,
+		.of_match_table = gcc_msm8974_match_table,
+	},
+};
+
+static int __init gcc_msm8974_init(void)
+{
+	return platform_driver_register(&gcc_msm8974_driver);
+}
+core_initcall(gcc_msm8974_init);
+
+static void __exit gcc_msm8974_exit(void)
+{
+	platform_driver_unregister(&gcc_msm8974_driver);
+}
+module_exit(gcc_msm8974_exit);
+
+MODULE_DESCRIPTION("QCOM GCC MSM8974 Driver");
+MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("platform:gcc-msm8974");
diff --git a/include/dt-bindings/clock/qcom,gcc-msm8974.h b/include/dt-bindings/clock/qcom,gcc-msm8974.h
new file mode 100644
index 0000000..223ca17
--- /dev/null
+++ b/include/dt-bindings/clock/qcom,gcc-msm8974.h
@@ -0,0 +1,320 @@
+/*
+ * Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef _DT_BINDINGS_CLK_MSM_GCC_8974_H
+#define _DT_BINDINGS_CLK_MSM_GCC_8974_H
+
+#define GPLL0							0
+#define GPLL0_VOTE						1
+#define CONFIG_NOC_CLK_SRC					2
+#define GPLL2							3
+#define GPLL2_VOTE						4
+#define GPLL3							5
+#define GPLL3_VOTE						6
+#define PERIPH_NOC_CLK_SRC					7
+#define BLSP_UART_SIM_CLK_SRC					8
+#define QDSS_TSCTR_CLK_SRC					9
+#define BIMC_DDR_CLK_SRC					10
+#define SYSTEM_NOC_CLK_SRC					11
+#define GPLL1							12
+#define GPLL1_VOTE						13
+#define RPM_CLK_SRC						14
+#define GCC_BIMC_CLK						15
+#define BIMC_DDR_CPLL0_ROOT_CLK_SRC				16
+#define KPSS_AHB_CLK_SRC					17
+#define QDSS_AT_CLK_SRC						18
+#define USB30_MASTER_CLK_SRC					19
+#define BIMC_DDR_CPLL1_ROOT_CLK_SRC				20
+#define QDSS_STM_CLK_SRC					21
+#define ACC_CLK_SRC						22
+#define SEC_CTRL_CLK_SRC					23
+#define BLSP1_QUP1_I2C_APPS_CLK_SRC				24
+#define BLSP1_QUP1_SPI_APPS_CLK_SRC				25
+#define BLSP1_QUP2_I2C_APPS_CLK_SRC				26
+#define BLSP1_QUP2_SPI_APPS_CLK_SRC				27
+#define BLSP1_QUP3_I2C_APPS_CLK_SRC				28
+#define BLSP1_QUP3_SPI_APPS_CLK_SRC				29
+#define BLSP1_QUP4_I2C_APPS_CLK_SRC				30
+#define BLSP1_QUP4_SPI_APPS_CLK_SRC				31
+#define BLSP1_QUP5_I2C_APPS_CLK_SRC				32
+#define BLSP1_QUP5_SPI_APPS_CLK_SRC				33
+#define BLSP1_QUP6_I2C_APPS_CLK_SRC				34
+#define BLSP1_QUP6_SPI_APPS_CLK_SRC				35
+#define BLSP1_UART1_APPS_CLK_SRC				36
+#define BLSP1_UART2_APPS_CLK_SRC				37
+#define BLSP1_UART3_APPS_CLK_SRC				38
+#define BLSP1_UART4_APPS_CLK_SRC				39
+#define BLSP1_UART5_APPS_CLK_SRC				40
+#define BLSP1_UART6_APPS_CLK_SRC				41
+#define BLSP2_QUP1_I2C_APPS_CLK_SRC				42
+#define BLSP2_QUP1_SPI_APPS_CLK_SRC				43
+#define BLSP2_QUP2_I2C_APPS_CLK_SRC				44
+#define BLSP2_QUP2_SPI_APPS_CLK_SRC				45
+#define BLSP2_QUP3_I2C_APPS_CLK_SRC				46
+#define BLSP2_QUP3_SPI_APPS_CLK_SRC				47
+#define BLSP2_QUP4_I2C_APPS_CLK_SRC				48
+#define BLSP2_QUP4_SPI_APPS_CLK_SRC				49
+#define BLSP2_QUP5_I2C_APPS_CLK_SRC				50
+#define BLSP2_QUP5_SPI_APPS_CLK_SRC				51
+#define BLSP2_QUP6_I2C_APPS_CLK_SRC				52
+#define BLSP2_QUP6_SPI_APPS_CLK_SRC				53
+#define BLSP2_UART1_APPS_CLK_SRC				54
+#define BLSP2_UART2_APPS_CLK_SRC				55
+#define BLSP2_UART3_APPS_CLK_SRC				56
+#define BLSP2_UART4_APPS_CLK_SRC				57
+#define BLSP2_UART5_APPS_CLK_SRC				58
+#define BLSP2_UART6_APPS_CLK_SRC				59
+#define CE1_CLK_SRC						60
+#define CE2_CLK_SRC						61
+#define GP1_CLK_SRC						62
+#define GP2_CLK_SRC						63
+#define GP3_CLK_SRC						64
+#define PDM2_CLK_SRC						65
+#define QDSS_TRACECLKIN_CLK_SRC					66
+#define RBCPR_CLK_SRC						67
+#define SDCC1_APPS_CLK_SRC					68
+#define SDCC2_APPS_CLK_SRC					69
+#define SDCC3_APPS_CLK_SRC					70
+#define SDCC4_APPS_CLK_SRC					71
+#define SPMI_AHB_CLK_SRC					72
+#define SPMI_SER_CLK_SRC					73
+#define TSIF_REF_CLK_SRC					74
+#define USB30_MOCK_UTMI_CLK_SRC					75
+#define USB_HS_SYSTEM_CLK_SRC					76
+#define USB_HSIC_CLK_SRC					77
+#define USB_HSIC_IO_CAL_CLK_SRC					78
+#define USB_HSIC_SYSTEM_CLK_SRC					79
+#define GCC_BAM_DMA_AHB_CLK					80
+#define GCC_BAM_DMA_INACTIVITY_TIMERS_CLK			81
+#define GCC_BIMC_CFG_AHB_CLK					82
+#define GCC_BIMC_KPSS_AXI_CLK					83
+#define GCC_BIMC_SLEEP_CLK					84
+#define GCC_BIMC_SYSNOC_AXI_CLK					85
+#define GCC_BIMC_XO_CLK						86
+#define GCC_BLSP1_AHB_CLK					87
+#define GCC_BLSP1_SLEEP_CLK					88
+#define GCC_BLSP1_QUP1_I2C_APPS_CLK				89
+#define GCC_BLSP1_QUP1_SPI_APPS_CLK				90
+#define GCC_BLSP1_QUP2_I2C_APPS_CLK				91
+#define GCC_BLSP1_QUP2_SPI_APPS_CLK				92
+#define GCC_BLSP1_QUP3_I2C_APPS_CLK				93
+#define GCC_BLSP1_QUP3_SPI_APPS_CLK				94
+#define GCC_BLSP1_QUP4_I2C_APPS_CLK				95
+#define GCC_BLSP1_QUP4_SPI_APPS_CLK				96
+#define GCC_BLSP1_QUP5_I2C_APPS_CLK				97
+#define GCC_BLSP1_QUP5_SPI_APPS_CLK				98
+#define GCC_BLSP1_QUP6_I2C_APPS_CLK				99
+#define GCC_BLSP1_QUP6_SPI_APPS_CLK				100
+#define GCC_BLSP1_UART1_APPS_CLK				101
+#define GCC_BLSP1_UART1_SIM_CLK					102
+#define GCC_BLSP1_UART2_APPS_CLK				103
+#define GCC_BLSP1_UART2_SIM_CLK					104
+#define GCC_BLSP1_UART3_APPS_CLK				105
+#define GCC_BLSP1_UART3_SIM_CLK					106
+#define GCC_BLSP1_UART4_APPS_CLK				107
+#define GCC_BLSP1_UART4_SIM_CLK					108
+#define GCC_BLSP1_UART5_APPS_CLK				109
+#define GCC_BLSP1_UART5_SIM_CLK					110
+#define GCC_BLSP1_UART6_APPS_CLK				111
+#define GCC_BLSP1_UART6_SIM_CLK					112
+#define GCC_BLSP2_AHB_CLK					113
+#define GCC_BLSP2_SLEEP_CLK					114
+#define GCC_BLSP2_QUP1_I2C_APPS_CLK				115
+#define GCC_BLSP2_QUP1_SPI_APPS_CLK				116
+#define GCC_BLSP2_QUP2_I2C_APPS_CLK				117
+#define GCC_BLSP2_QUP2_SPI_APPS_CLK				118
+#define GCC_BLSP2_QUP3_I2C_APPS_CLK				119
+#define GCC_BLSP2_QUP3_SPI_APPS_CLK				120
+#define GCC_BLSP2_QUP4_I2C_APPS_CLK				121
+#define GCC_BLSP2_QUP4_SPI_APPS_CLK				122
+#define GCC_BLSP2_QUP5_I2C_APPS_CLK				123
+#define GCC_BLSP2_QUP5_SPI_APPS_CLK				124
+#define GCC_BLSP2_QUP6_I2C_APPS_CLK				125
+#define GCC_BLSP2_QUP6_SPI_APPS_CLK				126
+#define GCC_BLSP2_UART1_APPS_CLK				127
+#define GCC_BLSP2_UART1_SIM_CLK					128
+#define GCC_BLSP2_UART2_APPS_CLK				129
+#define GCC_BLSP2_UART2_SIM_CLK					130
+#define GCC_BLSP2_UART3_APPS_CLK				131
+#define GCC_BLSP2_UART3_SIM_CLK					132
+#define GCC_BLSP2_UART4_APPS_CLK				133
+#define GCC_BLSP2_UART4_SIM_CLK					134
+#define GCC_BLSP2_UART5_APPS_CLK				135
+#define GCC_BLSP2_UART5_SIM_CLK					136
+#define GCC_BLSP2_UART6_APPS_CLK				137
+#define GCC_BLSP2_UART6_SIM_CLK					138
+#define GCC_BOOT_ROM_AHB_CLK					139
+#define GCC_CE1_AHB_CLK						140
+#define GCC_CE1_AXI_CLK						141
+#define GCC_CE1_CLK						142
+#define GCC_CE2_AHB_CLK						143
+#define GCC_CE2_AXI_CLK						144
+#define GCC_CE2_CLK						145
+#define GCC_CNOC_BUS_TIMEOUT0_AHB_CLK				146
+#define GCC_CNOC_BUS_TIMEOUT1_AHB_CLK				147
+#define GCC_CNOC_BUS_TIMEOUT2_AHB_CLK				148
+#define GCC_CNOC_BUS_TIMEOUT3_AHB_CLK				149
+#define GCC_CNOC_BUS_TIMEOUT4_AHB_CLK				150
+#define GCC_CNOC_BUS_TIMEOUT5_AHB_CLK				151
+#define GCC_CNOC_BUS_TIMEOUT6_AHB_CLK				152
+#define GCC_CFG_NOC_AHB_CLK					153
+#define GCC_CFG_NOC_DDR_CFG_CLK					154
+#define GCC_CFG_NOC_RPM_AHB_CLK					155
+#define GCC_BIMC_DDR_CPLL0_CLK					156
+#define GCC_BIMC_DDR_CPLL1_CLK					157
+#define GCC_DDR_DIM_CFG_CLK					158
+#define GCC_DDR_DIM_SLEEP_CLK					159
+#define GCC_DEHR_CLK						160
+#define GCC_AHB_CLK						161
+#define GCC_IM_SLEEP_CLK					162
+#define GCC_XO_CLK						163
+#define GCC_XO_DIV4_CLK						164
+#define GCC_GP1_CLK						165
+#define GCC_GP2_CLK						166
+#define GCC_GP3_CLK						167
+#define GCC_IMEM_AXI_CLK					168
+#define GCC_IMEM_CFG_AHB_CLK					169
+#define GCC_KPSS_AHB_CLK					170
+#define GCC_KPSS_AXI_CLK					171
+#define GCC_LPASS_Q6_AXI_CLK					172
+#define GCC_MMSS_NOC_AT_CLK					173
+#define GCC_MMSS_NOC_CFG_AHB_CLK				174
+#define GCC_OCMEM_NOC_CFG_AHB_CLK				175
+#define GCC_OCMEM_SYS_NOC_AXI_CLK				176
+#define GCC_MPM_AHB_CLK						177
+#define GCC_MSG_RAM_AHB_CLK					178
+#define GCC_MSS_CFG_AHB_CLK					179
+#define GCC_MSS_Q6_BIMC_AXI_CLK					180
+#define GCC_NOC_CONF_XPU_AHB_CLK				181
+#define GCC_PDM2_CLK						182
+#define GCC_PDM_AHB_CLK						183
+#define GCC_PDM_XO4_CLK						184
+#define GCC_PERIPH_NOC_AHB_CLK					185
+#define GCC_PERIPH_NOC_AT_CLK					186
+#define GCC_PERIPH_NOC_CFG_AHB_CLK				187
+#define GCC_PERIPH_NOC_MPU_CFG_AHB_CLK				188
+#define GCC_PERIPH_XPU_AHB_CLK					189
+#define GCC_PNOC_BUS_TIMEOUT0_AHB_CLK				190
+#define GCC_PNOC_BUS_TIMEOUT1_AHB_CLK				191
+#define GCC_PNOC_BUS_TIMEOUT2_AHB_CLK				192
+#define GCC_PNOC_BUS_TIMEOUT3_AHB_CLK				193
+#define GCC_PNOC_BUS_TIMEOUT4_AHB_CLK				194
+#define GCC_PRNG_AHB_CLK					195
+#define GCC_QDSS_AT_CLK						196
+#define GCC_QDSS_CFG_AHB_CLK					197
+#define GCC_QDSS_DAP_AHB_CLK					198
+#define GCC_QDSS_DAP_CLK					199
+#define GCC_QDSS_ETR_USB_CLK					200
+#define GCC_QDSS_STM_CLK					201
+#define GCC_QDSS_TRACECLKIN_CLK					202
+#define GCC_QDSS_TSCTR_DIV16_CLK				203
+#define GCC_QDSS_TSCTR_DIV2_CLK					204
+#define GCC_QDSS_TSCTR_DIV3_CLK					205
+#define GCC_QDSS_TSCTR_DIV4_CLK					206
+#define GCC_QDSS_TSCTR_DIV8_CLK					207
+#define GCC_QDSS_RBCPR_XPU_AHB_CLK				208
+#define GCC_RBCPR_AHB_CLK					209
+#define GCC_RBCPR_CLK						210
+#define GCC_RPM_BUS_AHB_CLK					211
+#define GCC_RPM_PROC_HCLK					212
+#define GCC_RPM_SLEEP_CLK					213
+#define GCC_RPM_TIMER_CLK					214
+#define GCC_SDCC1_AHB_CLK					215
+#define GCC_SDCC1_APPS_CLK					216
+#define GCC_SDCC1_INACTIVITY_TIMERS_CLK				217
+#define GCC_SDCC2_AHB_CLK					218
+#define GCC_SDCC2_APPS_CLK					219
+#define GCC_SDCC2_INACTIVITY_TIMERS_CLK				220
+#define GCC_SDCC3_AHB_CLK					221
+#define GCC_SDCC3_APPS_CLK					222
+#define GCC_SDCC3_INACTIVITY_TIMERS_CLK				223
+#define GCC_SDCC4_AHB_CLK					224
+#define GCC_SDCC4_APPS_CLK					225
+#define GCC_SDCC4_INACTIVITY_TIMERS_CLK				226
+#define GCC_SEC_CTRL_ACC_CLK					227
+#define GCC_SEC_CTRL_AHB_CLK					228
+#define GCC_SEC_CTRL_BOOT_ROM_PATCH_CLK				229
+#define GCC_SEC_CTRL_CLK					230
+#define GCC_SEC_CTRL_SENSE_CLK					231
+#define GCC_SNOC_BUS_TIMEOUT0_AHB_CLK				232
+#define GCC_SNOC_BUS_TIMEOUT2_AHB_CLK				233
+#define GCC_SPDM_BIMC_CY_CLK					234
+#define GCC_SPDM_CFG_AHB_CLK					235
+#define GCC_SPDM_DEBUG_CY_CLK					236
+#define GCC_SPDM_FF_CLK						237
+#define GCC_SPDM_MSTR_AHB_CLK					238
+#define GCC_SPDM_PNOC_CY_CLK					239
+#define GCC_SPDM_RPM_CY_CLK					240
+#define GCC_SPDM_SNOC_CY_CLK					241
+#define GCC_SPMI_AHB_CLK					242
+#define GCC_SPMI_CNOC_AHB_CLK					243
+#define GCC_SPMI_SER_CLK					244
+#define GCC_SNOC_CNOC_AHB_CLK					245
+#define GCC_SNOC_PNOC_AHB_CLK					246
+#define GCC_SYS_NOC_AT_CLK					247
+#define GCC_SYS_NOC_AXI_CLK					248
+#define GCC_SYS_NOC_KPSS_AHB_CLK				249
+#define GCC_SYS_NOC_QDSS_STM_AXI_CLK				250
+#define GCC_SYS_NOC_USB3_AXI_CLK				251
+#define GCC_TCSR_AHB_CLK					252
+#define GCC_TLMM_AHB_CLK					253
+#define GCC_TLMM_CLK						254
+#define GCC_TSIF_AHB_CLK					255
+#define GCC_TSIF_INACTIVITY_TIMERS_CLK				256
+#define GCC_TSIF_REF_CLK					257
+#define GCC_USB2A_PHY_SLEEP_CLK					258
+#define GCC_USB2B_PHY_SLEEP_CLK					259
+#define GCC_USB30_MASTER_CLK					260
+#define GCC_USB30_MOCK_UTMI_CLK					261
+#define GCC_USB30_SLEEP_CLK					262
+#define GCC_USB_HS_AHB_CLK					263
+#define GCC_USB_HS_INACTIVITY_TIMERS_CLK			264
+#define GCC_USB_HS_SYSTEM_CLK					265
+#define GCC_USB_HSIC_AHB_CLK					266
+#define GCC_USB_HSIC_CLK					267
+#define GCC_USB_HSIC_IO_CAL_CLK					268
+#define GCC_USB_HSIC_IO_CAL_SLEEP_CLK				269
+#define GCC_USB_HSIC_SYSTEM_CLK					270
+#define GCC_WCSS_GPLL1_CLK_SRC					271
+#define GCC_MMSS_GPLL0_CLK_SRC					272
+#define GCC_LPASS_GPLL0_CLK_SRC					273
+#define GCC_WCSS_GPLL1_CLK_SRC_SLEEP_ENA			274
+#define GCC_MMSS_GPLL0_CLK_SRC_SLEEP_ENA			275
+#define GCC_LPASS_GPLL0_CLK_SRC_SLEEP_ENA			276
+#define GCC_IMEM_AXI_CLK_SLEEP_ENA				277
+#define GCC_SYS_NOC_KPSS_AHB_CLK_SLEEP_ENA			278
+#define GCC_BIMC_KPSS_AXI_CLK_SLEEP_ENA				279
+#define GCC_KPSS_AHB_CLK_SLEEP_ENA				280
+#define GCC_KPSS_AXI_CLK_SLEEP_ENA				281
+#define GCC_MPM_AHB_CLK_SLEEP_ENA				282
+#define GCC_OCMEM_SYS_NOC_AXI_CLK_SLEEP_ENA			283
+#define GCC_BLSP1_AHB_CLK_SLEEP_ENA				284
+#define GCC_BLSP1_SLEEP_CLK_SLEEP_ENA				285
+#define GCC_BLSP2_AHB_CLK_SLEEP_ENA				286
+#define GCC_BLSP2_SLEEP_CLK_SLEEP_ENA				287
+#define GCC_PRNG_AHB_CLK_SLEEP_ENA				288
+#define GCC_BAM_DMA_AHB_CLK_SLEEP_ENA				289
+#define GCC_BAM_DMA_INACTIVITY_TIMERS_CLK_SLEEP_ENA		290
+#define GCC_BOOT_ROM_AHB_CLK_SLEEP_ENA				291
+#define GCC_MSG_RAM_AHB_CLK_SLEEP_ENA				292
+#define GCC_TLMM_AHB_CLK_SLEEP_ENA				293
+#define GCC_TLMM_CLK_SLEEP_ENA					294
+#define GCC_SPMI_CNOC_AHB_CLK_SLEEP_ENA				295
+#define GCC_CE1_CLK_SLEEP_ENA					296
+#define GCC_CE1_AXI_CLK_SLEEP_ENA				297
+#define GCC_CE1_AHB_CLK_SLEEP_ENA				298
+#define GCC_CE2_CLK_SLEEP_ENA					299
+#define GCC_CE2_AXI_CLK_SLEEP_ENA				300
+#define GCC_CE2_AHB_CLK_SLEEP_ENA				301
+
+#endif
diff --git a/include/dt-bindings/reset/qcom,gcc-msm8974.h b/include/dt-bindings/reset/qcom,gcc-msm8974.h
new file mode 100644
index 0000000..9bdf543
--- /dev/null
+++ b/include/dt-bindings/reset/qcom,gcc-msm8974.h
@@ -0,0 +1,96 @@
+/*
+ * Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef _DT_BINDINGS_RESET_MSM_GCC_8974_H
+#define _DT_BINDINGS_RESET_MSM_GCC_8974_H
+
+#define GCC_SYSTEM_NOC_BCR			0
+#define GCC_CONFIG_NOC_BCR			1
+#define GCC_PERIPH_NOC_BCR			2
+#define GCC_IMEM_BCR				3
+#define GCC_MMSS_BCR				4
+#define GCC_QDSS_BCR				5
+#define GCC_USB_30_BCR				6
+#define GCC_USB3_PHY_BCR			7
+#define GCC_USB_HS_HSIC_BCR			8
+#define GCC_USB_HS_BCR				9
+#define GCC_USB2A_PHY_BCR			10
+#define GCC_USB2B_PHY_BCR			11
+#define GCC_SDCC1_BCR				12
+#define GCC_SDCC2_BCR				13
+#define GCC_SDCC3_BCR				14
+#define GCC_SDCC4_BCR				15
+#define GCC_BLSP1_BCR				16
+#define GCC_BLSP1_QUP1_BCR			17
+#define GCC_BLSP1_UART1_BCR			18
+#define GCC_BLSP1_QUP2_BCR			19
+#define GCC_BLSP1_UART2_BCR			20
+#define GCC_BLSP1_QUP3_BCR			21
+#define GCC_BLSP1_UART3_BCR			22
+#define GCC_BLSP1_QUP4_BCR			23
+#define GCC_BLSP1_UART4_BCR			24
+#define GCC_BLSP1_QUP5_BCR			25
+#define GCC_BLSP1_UART5_BCR			26
+#define GCC_BLSP1_QUP6_BCR			27
+#define GCC_BLSP1_UART6_BCR			28
+#define GCC_BLSP2_BCR				29
+#define GCC_BLSP2_QUP1_BCR			30
+#define GCC_BLSP2_UART1_BCR			31
+#define GCC_BLSP2_QUP2_BCR			32
+#define GCC_BLSP2_UART2_BCR			33
+#define GCC_BLSP2_QUP3_BCR			34
+#define GCC_BLSP2_UART3_BCR			35
+#define GCC_BLSP2_QUP4_BCR			36
+#define GCC_BLSP2_UART4_BCR			37
+#define GCC_BLSP2_QUP5_BCR			38
+#define GCC_BLSP2_UART5_BCR			39
+#define GCC_BLSP2_QUP6_BCR			40
+#define GCC_BLSP2_UART6_BCR			41
+#define GCC_PDM_BCR				42
+#define GCC_BAM_DMA_BCR				43
+#define GCC_TSIF_BCR				44
+#define GCC_TCSR_BCR				45
+#define GCC_BOOT_ROM_BCR			46
+#define GCC_MSG_RAM_BCR				47
+#define GCC_TLMM_BCR				48
+#define GCC_MPM_BCR				49
+#define GCC_SEC_CTRL_BCR			50
+#define GCC_SPMI_BCR				51
+#define GCC_SPDM_BCR				52
+#define GCC_CE1_BCR				53
+#define GCC_CE2_BCR				54
+#define GCC_BIMC_BCR				55
+#define GCC_MPM_NON_AHB_RESET			56
+#define GCC_MPM_AHB_RESET			57
+#define GCC_SNOC_BUS_TIMEOUT0_BCR		58
+#define GCC_SNOC_BUS_TIMEOUT2_BCR		59
+#define GCC_PNOC_BUS_TIMEOUT0_BCR		60
+#define GCC_PNOC_BUS_TIMEOUT1_BCR		61
+#define GCC_PNOC_BUS_TIMEOUT2_BCR		62
+#define GCC_PNOC_BUS_TIMEOUT3_BCR		63
+#define GCC_PNOC_BUS_TIMEOUT4_BCR		64
+#define GCC_CNOC_BUS_TIMEOUT0_BCR		65
+#define GCC_CNOC_BUS_TIMEOUT1_BCR		66
+#define GCC_CNOC_BUS_TIMEOUT2_BCR		67
+#define GCC_CNOC_BUS_TIMEOUT3_BCR		68
+#define GCC_CNOC_BUS_TIMEOUT4_BCR		69
+#define GCC_CNOC_BUS_TIMEOUT5_BCR		70
+#define GCC_CNOC_BUS_TIMEOUT6_BCR		71
+#define GCC_DEHR_BCR				72
+#define GCC_RBCPR_BCR				73
+#define GCC_MSS_RESTART				74
+#define GCC_LPASS_RESTART			75
+#define GCC_WCSS_RESTART			76
+#define GCC_VENUS_RESTART			77
+
+#endif
-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
hosted by The Linux Foundation

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

* [PATCH v4 12/15] clk: qcom: Add support for MSM8974's multimedia clock controller (MMCC)
  2013-12-24  1:12 [PATCH v4 00/15] Add support for MSM's mmio clock/reset controller Stephen Boyd
                   ` (10 preceding siblings ...)
  2013-12-24  1:12 ` [PATCH v4 11/15] clk: qcom: Add support for MSM8974's global clock controller (GCC) Stephen Boyd
@ 2013-12-24  1:12 ` Stephen Boyd
  2013-12-24  1:12 ` [PATCH v4 13/15] clk: qcom: Add support for MSM8660's global clock controller (GCC) Stephen Boyd
                   ` (2 subsequent siblings)
  14 siblings, 0 replies; 34+ messages in thread
From: Stephen Boyd @ 2013-12-24  1:12 UTC (permalink / raw)
  To: Mike Turquette
  Cc: linux-kernel, linux-arm-msm, linux-arm-kernel, Saravana Kannan

Add a driver for the global clock controller found on MSM 8974
based platforms. This should allow most multimedia device drivers
to probe and control their clocks.

Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
---
 drivers/clk/qcom/Kconfig                      |    9 +
 drivers/clk/qcom/Makefile                     |    1 +
 drivers/clk/qcom/mmcc-msm8974.c               | 2624 +++++++++++++++++++++++++
 include/dt-bindings/clock/qcom,mmcc-msm8974.h |  161 ++
 include/dt-bindings/reset/qcom,mmcc-msm8974.h |   62 +
 5 files changed, 2857 insertions(+)
 create mode 100644 drivers/clk/qcom/mmcc-msm8974.c
 create mode 100644 include/dt-bindings/clock/qcom,mmcc-msm8974.h
 create mode 100644 include/dt-bindings/reset/qcom,mmcc-msm8974.h

diff --git a/drivers/clk/qcom/Kconfig b/drivers/clk/qcom/Kconfig
index 7a13251..7b582dd 100644
--- a/drivers/clk/qcom/Kconfig
+++ b/drivers/clk/qcom/Kconfig
@@ -28,3 +28,12 @@ config MSM_GCC_8974
 	  Support for the global clock controller on msm8974 devices.
 	  Say Y if you want to use peripheral devices such as UART, SPI,
 	  i2c, USB, SD/eMMC, SATA, PCIe, etc.
+
+config MSM_MMCC_8974
+	tristate "MSM8974 Multimedia Clock Controller"
+	select MSM_GCC_8974
+	depends on COMMON_CLK_QCOM
+	help
+	  Support for the multimedia clock controller on msm8974 devices.
+	  Say Y if you want to support multimedia devices such as display,
+	  graphics, video encode/decode, camera, etc.
diff --git a/drivers/clk/qcom/Makefile b/drivers/clk/qcom/Makefile
index 47a9a02..d9480357 100644
--- a/drivers/clk/qcom/Makefile
+++ b/drivers/clk/qcom/Makefile
@@ -9,3 +9,4 @@ clk-qcom-$(CONFIG_COMMON_CLK_QCOM) += reset.o
 obj-$(CONFIG_MSM_GCC_8960) += gcc-msm8960.o
 obj-$(CONFIG_MSM_GCC_8974) += gcc-msm8974.o
 obj-$(CONFIG_MSM_MMCC_8960) += mmcc-msm8960.o
+obj-$(CONFIG_MSM_MMCC_8974) += mmcc-msm8974.o
diff --git a/drivers/clk/qcom/mmcc-msm8974.c b/drivers/clk/qcom/mmcc-msm8974.c
new file mode 100644
index 0000000..534e15b
--- /dev/null
+++ b/drivers/clk/qcom/mmcc-msm8974.c
@@ -0,0 +1,2624 @@
+/*
+ * Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/kernel.h>
+#include <linux/bitops.h>
+#include <linux/err.h>
+#include <linux/platform_device.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/clk-provider.h>
+#include <linux/regmap.h>
+#include <linux/reset-controller.h>
+
+#include <dt-bindings/clock/qcom,mmcc-msm8974.h>
+#include <dt-bindings/reset/qcom,mmcc-msm8974.h>
+
+#include "clk-pll.h"
+#include "clk-rcg.h"
+#include "clk-branch.h"
+#include "reset.h"
+
+#define P_XO		0
+#define P_MMPLL0	1
+#define P_EDPLINK	1
+#define P_MMPLL1	2
+#define P_HDMIPLL	2
+#define P_GPLL0		3
+#define P_EDPVCO	3
+#define P_GPLL1		4
+#define P_DSI0PLL	4
+#define P_MMPLL2	4
+#define P_MMPLL3	4
+#define P_DSI1PLL	5
+
+static const u8 mmcc_xo_mmpll0_mmpll1_gpll0_map[] = {
+	[P_XO]		= 0,
+	[P_MMPLL0]	= 1,
+	[P_MMPLL1]	= 2,
+	[P_GPLL0]	= 5,
+};
+
+static const char *mmcc_xo_mmpll0_mmpll1_gpll0[] = {
+	"xo",
+	"mmpll0_vote",
+	"mmpll1_vote",
+	"mmss_gpll0_vote",
+};
+
+static const u8 mmcc_xo_mmpll0_dsi_hdmi_gpll0_map[] = {
+	[P_XO]		= 0,
+	[P_MMPLL0]	= 1,
+	[P_HDMIPLL]	= 4,
+	[P_GPLL0]	= 5,
+	[P_DSI0PLL]	= 2,
+	[P_DSI1PLL]	= 3,
+};
+
+static const char *mmcc_xo_mmpll0_dsi_hdmi_gpll0[] = {
+	"xo",
+	"mmpll0_vote",
+	"hdmipll",
+	"mmss_gpll0_vote",
+	"dsi0pll",
+	"dsi1pll",
+};
+
+static const u8 mmcc_xo_mmpll0_1_2_gpll0_map[] = {
+	[P_XO]		= 0,
+	[P_MMPLL0]	= 1,
+	[P_MMPLL1]	= 2,
+	[P_GPLL0]	= 5,
+	[P_MMPLL2]	= 3,
+};
+
+static const char *mmcc_xo_mmpll0_1_2_gpll0[] = {
+	"xo",
+	"mmpll0_vote",
+	"mmpll1_vote",
+	"mmss_gpll0_vote",
+	"mmpll2",
+};
+
+static const u8 mmcc_xo_mmpll0_1_3_gpll0_map[] = {
+	[P_XO]		= 0,
+	[P_MMPLL0]	= 1,
+	[P_MMPLL1]	= 2,
+	[P_GPLL0]	= 5,
+	[P_MMPLL3]	= 3,
+};
+
+static const char *mmcc_xo_mmpll0_1_3_gpll0[] = {
+	"xo",
+	"mmpll0_vote",
+	"mmpll1_vote",
+	"mmss_gpll0_vote",
+	"mmpll3",
+};
+
+static const u8 mmcc_xo_mmpll0_1_gpll1_0_map[] = {
+	[P_XO]		= 0,
+	[P_MMPLL0]	= 1,
+	[P_MMPLL1]	= 2,
+	[P_GPLL0]	= 5,
+	[P_GPLL1]	= 4,
+};
+
+static const char *mmcc_xo_mmpll0_1_gpll1_0[] = {
+	"xo",
+	"mmpll0_vote",
+	"mmpll1_vote",
+	"mmss_gpll0_vote",
+	"gpll1_vote",
+};
+
+static const u8 mmcc_xo_dsi_hdmi_edp_map[] = {
+	[P_XO]		= 0,
+	[P_EDPLINK]	= 4,
+	[P_HDMIPLL]	= 3,
+	[P_EDPVCO]	= 5,
+	[P_DSI0PLL]	= 1,
+	[P_DSI1PLL]	= 2,
+};
+
+static const char *mmcc_xo_dsi_hdmi_edp[] = {
+	"xo",
+	"edp_link_clk",
+	"hdmipll",
+	"edp_vco_div",
+	"dsi0pll",
+	"dsi1pll",
+};
+
+static const u8 mmcc_xo_dsi_hdmi_edp_gpll0_map[] = {
+	[P_XO]		= 0,
+	[P_EDPLINK]	= 4,
+	[P_HDMIPLL]	= 3,
+	[P_GPLL0]	= 5,
+	[P_DSI0PLL]	= 1,
+	[P_DSI1PLL]	= 2,
+};
+
+static const char *mmcc_xo_dsi_hdmi_edp_gpll0[] = {
+	"xo",
+	"edp_link_clk",
+	"hdmipll",
+	"gpll0_vote",
+	"dsi0pll",
+	"dsi1pll",
+};
+
+#define F(f, s, h, m, n) { (f), (s), (2 * (h) - 1), (m), (n) }
+
+static struct clk_pll mmpll0 = {
+	.l_reg = 0x0004,
+	.m_reg = 0x0008,
+	.n_reg = 0x000c,
+	.config_reg = 0x0014,
+	.mode_reg = 0x0000,
+	.status_reg = 0x001c,
+        .hw.init = &(struct clk_init_data){
+                .name = "mmpll0",
+                .parent_names = (const char *[]){ "xo" },
+                .num_parents = 1,
+                .ops = &clk_pll_ops,
+        },
+};
+
+static struct clk_hw mmpll0_vote = {
+	.enable_reg = 0x0100,
+	.enable_mask = BIT(0),
+	.init = &(struct clk_init_data){
+		.name = "mmpll0_vote",
+		.parent_names = (const char *[]){ "mmpll0" },
+		.num_parents = 1,
+		.ops = &clk_pll_vote_ops,
+	},
+};
+
+static struct clk_pll mmpll1 = {
+	.l_reg = 0x0044,
+	.m_reg = 0x0048,
+	.n_reg = 0x004c,
+	.config_reg = 0x0054,
+	.mode_reg = 0x0040,
+	.status_reg = 0x005c,
+        .hw.init = &(struct clk_init_data){
+                .name = "mmpll1",
+                .parent_names = (const char *[]){ "xo" },
+                .num_parents = 1,
+                .ops = &clk_pll_ops,
+        },
+};
+
+static struct clk_hw mmpll1_vote = {
+	.enable_reg = 0x0100,
+	.enable_mask = BIT(1),
+	.init = &(struct clk_init_data){
+		.name = "mmpll1_vote",
+		.parent_names = (const char *[]){ "mmpll1" },
+		.num_parents = 1,
+		.ops = &clk_pll_vote_ops,
+	},
+};
+
+static struct clk_pll mmpll2 = {
+	.l_reg = 0x4104,
+	.m_reg = 0x4108,
+	.n_reg = 0x410c,
+	.config_reg = 0x4114,
+	.mode_reg = 0x4100,
+	.status_reg = 0x411c,
+        .hw.init = &(struct clk_init_data){
+                .name = "mmpll2",
+                .parent_names = (const char *[]){ "xo" },
+                .num_parents = 1,
+                .ops = &clk_pll_ops,
+        },
+};
+
+static struct clk_pll mmpll3 = {
+	.l_reg = 0x0084,
+	.m_reg = 0x0088,
+	.n_reg = 0x008c,
+	.config_reg = 0x0094,
+	.mode_reg = 0x0080,
+	.status_reg = 0x009c,
+        .hw.init = &(struct clk_init_data){
+                .name = "mmpll3",
+                .parent_names = (const char *[]){ "xo" },
+                .num_parents = 1,
+                .ops = &clk_pll_ops,
+        },
+};
+
+static struct clk_rcg2 mmss_ahb_clk_src = {
+	.cmd_rcgr = 0x5000,
+	.hid_width = 5,
+	.parent_map = mmcc_xo_mmpll0_mmpll1_gpll0_map,
+	.hw.init = &(struct clk_init_data){
+		.name = "mmss_ahb_clk_src",
+		.parent_names = mmcc_xo_mmpll0_mmpll1_gpll0,
+		.num_parents = 4,
+		.ops = &clk_rcg2_ops,
+	},
+};
+
+static struct freq_tbl ftbl_mmss_axi_clk[] = {
+	F( 19200000, P_XO, 1, 0, 0),
+	F( 37500000, P_GPLL0, 16, 0, 0),
+	F( 50000000, P_GPLL0, 12, 0, 0),
+	F( 75000000, P_GPLL0, 8, 0, 0),
+	F(100000000, P_GPLL0, 6, 0, 0),
+	F(150000000, P_GPLL0, 4, 0, 0),
+	F(291750000, P_MMPLL1, 4, 0, 0),
+	F(400000000, P_MMPLL0, 2, 0, 0),
+	F(466800000, P_MMPLL1, 2.5, 0, 0),
+};
+
+static struct clk_rcg2 mmss_axi_clk_src = {
+	.cmd_rcgr = 0x5040,
+	.hid_width = 5,
+	.parent_map = mmcc_xo_mmpll0_mmpll1_gpll0_map,
+	.freq_tbl = ftbl_mmss_axi_clk,
+	.hw.init = &(struct clk_init_data){
+		.name = "mmss_axi_clk_src",
+		.parent_names = mmcc_xo_mmpll0_mmpll1_gpll0,
+		.num_parents = 4,
+		.ops = &clk_rcg2_ops,
+	},
+};
+
+static struct freq_tbl ftbl_ocmemnoc_clk[] = {
+	F( 19200000, P_XO, 1, 0, 0),
+	F( 37500000, P_GPLL0, 16, 0, 0),
+	F( 50000000, P_GPLL0, 12, 0, 0),
+	F( 75000000, P_GPLL0, 8, 0, 0),
+	F(100000000, P_GPLL0, 6, 0, 0),
+	F(150000000, P_GPLL0, 4, 0, 0),
+	F(291750000, P_MMPLL1, 4, 0, 0),
+	F(400000000, P_MMPLL0, 2, 0, 0),
+};
+
+static struct clk_rcg2 ocmemnoc_clk_src = {
+	.cmd_rcgr = 0x5090,
+	.hid_width = 5,
+	.parent_map = mmcc_xo_mmpll0_mmpll1_gpll0_map,
+	.freq_tbl = ftbl_ocmemnoc_clk,
+	.hw.init = &(struct clk_init_data){
+		.name = "ocmemnoc_clk_src",
+		.parent_names = mmcc_xo_mmpll0_mmpll1_gpll0,
+		.num_parents = 4,
+		.ops = &clk_rcg2_ops,
+	},
+};
+
+static struct freq_tbl ftbl_camss_csi0_3_clk[] = {
+	F(100000000, P_GPLL0, 6, 0, 0),
+	F(200000000, P_MMPLL0, 4, 0, 0),
+	{ }
+};
+
+static struct clk_rcg2 csi0_clk_src = {
+	.cmd_rcgr = 0x3090,
+	.hid_width = 5,
+	.parent_map = mmcc_xo_mmpll0_mmpll1_gpll0_map,
+	.freq_tbl = ftbl_camss_csi0_3_clk,
+	.hw.init = &(struct clk_init_data){
+		.name = "csi0_clk_src",
+		.parent_names = mmcc_xo_mmpll0_mmpll1_gpll0,
+		.num_parents = 4,
+		.ops = &clk_rcg2_ops,
+	},
+};
+
+static struct clk_rcg2 csi1_clk_src = {
+	.cmd_rcgr = 0x3100,
+	.hid_width = 5,
+	.parent_map = mmcc_xo_mmpll0_mmpll1_gpll0_map,
+	.freq_tbl = ftbl_camss_csi0_3_clk,
+	.hw.init = &(struct clk_init_data){
+		.name = "csi1_clk_src",
+		.parent_names = mmcc_xo_mmpll0_mmpll1_gpll0,
+		.num_parents = 4,
+		.ops = &clk_rcg2_ops,
+	},
+};
+
+static struct clk_rcg2 csi2_clk_src = {
+	.cmd_rcgr = 0x3160,
+	.hid_width = 5,
+	.parent_map = mmcc_xo_mmpll0_mmpll1_gpll0_map,
+	.freq_tbl = ftbl_camss_csi0_3_clk,
+	.hw.init = &(struct clk_init_data){
+		.name = "csi2_clk_src",
+		.parent_names = mmcc_xo_mmpll0_mmpll1_gpll0,
+		.num_parents = 4,
+		.ops = &clk_rcg2_ops,
+	},
+};
+
+static struct clk_rcg2 csi3_clk_src = {
+	.cmd_rcgr = 0x31c0,
+	.hid_width = 5,
+	.parent_map = mmcc_xo_mmpll0_mmpll1_gpll0_map,
+	.freq_tbl = ftbl_camss_csi0_3_clk,
+	.hw.init = &(struct clk_init_data){
+		.name = "csi3_clk_src",
+		.parent_names = mmcc_xo_mmpll0_mmpll1_gpll0,
+		.num_parents = 4,
+		.ops = &clk_rcg2_ops,
+	},
+};
+
+static struct freq_tbl ftbl_camss_vfe_vfe0_1_clk[] = {
+	F(37500000, P_GPLL0, 16, 0, 0),
+	F(50000000, P_GPLL0, 12, 0, 0),
+	F(60000000, P_GPLL0, 10, 0, 0),
+	F(80000000, P_GPLL0, 7.5, 0, 0),
+	F(100000000, P_GPLL0, 6, 0, 0),
+	F(109090000, P_GPLL0, 5.5, 0, 0),
+	F(133330000, P_GPLL0, 4.5, 0, 0),
+	F(200000000, P_GPLL0, 3, 0, 0),
+	F(228570000, P_MMPLL0, 3.5, 0, 0),
+	F(266670000, P_MMPLL0, 3, 0, 0),
+	F(320000000, P_MMPLL0, 2.5, 0, 0),
+	F(400000000, P_MMPLL0, 2, 0, 0),
+	F(465000000, P_MMPLL3, 2, 0, 0),
+	{ }
+};
+
+static struct clk_rcg2 vfe0_clk_src = {
+	.cmd_rcgr = 0x3600,
+	.hid_width = 5,
+	.parent_map = mmcc_xo_mmpll0_mmpll1_gpll0_map,
+	.freq_tbl = ftbl_camss_vfe_vfe0_1_clk,
+	.hw.init = &(struct clk_init_data){
+		.name = "vfe0_clk_src",
+		.parent_names = mmcc_xo_mmpll0_mmpll1_gpll0,
+		.num_parents = 4,
+		.ops = &clk_rcg2_ops,
+	},
+};
+
+static struct clk_rcg2 vfe1_clk_src = {
+	.cmd_rcgr = 0x3620,
+	.hid_width = 5,
+	.parent_map = mmcc_xo_mmpll0_mmpll1_gpll0_map,
+	.freq_tbl = ftbl_camss_vfe_vfe0_1_clk,
+	.hw.init = &(struct clk_init_data){
+		.name = "vfe1_clk_src",
+		.parent_names = mmcc_xo_mmpll0_mmpll1_gpll0,
+		.num_parents = 4,
+		.ops = &clk_rcg2_ops,
+	},
+};
+
+static struct freq_tbl ftbl_mdss_mdp_clk[] = {
+	F(37500000, P_GPLL0, 16, 0, 0),
+	F(60000000, P_GPLL0, 10, 0, 0),
+	F(75000000, P_GPLL0, 8, 0, 0),
+	F(85710000, P_GPLL0, 7, 0, 0),
+	F(100000000, P_GPLL0, 6, 0, 0),
+	F(133330000, P_MMPLL0, 6, 0, 0),
+	F(160000000, P_MMPLL0, 5, 0, 0),
+	F(200000000, P_MMPLL0, 4, 0, 0),
+	F(228570000, P_MMPLL0, 3.5, 0, 0),
+	F(240000000, P_GPLL0, 2.5, 0, 0),
+	F(266670000, P_MMPLL0, 3, 0, 0),
+	F(320000000, P_MMPLL0, 2.5, 0, 0),
+	{ }
+};
+
+static struct clk_rcg2 mdp_clk_src = {
+	.cmd_rcgr = 0x2040,
+	.hid_width = 5,
+	.parent_map = mmcc_xo_mmpll0_dsi_hdmi_gpll0_map,
+	.freq_tbl = ftbl_mdss_mdp_clk,
+	.hw.init = &(struct clk_init_data){
+		.name = "mdp_clk_src",
+		.parent_names = mmcc_xo_mmpll0_dsi_hdmi_gpll0,
+		.num_parents = 6,
+		.ops = &clk_rcg2_ops,
+	},
+};
+
+static struct clk_rcg2 gfx3d_clk_src = {
+	.cmd_rcgr = 0x4000,
+	.hid_width = 5,
+	.parent_map = mmcc_xo_mmpll0_1_2_gpll0_map,
+	.hw.init = &(struct clk_init_data){
+		.name = "gfx3d_clk_src",
+		.parent_names = mmcc_xo_mmpll0_1_2_gpll0,
+		.num_parents = 5,
+		.ops = &clk_rcg2_ops,
+	},
+};
+
+static struct freq_tbl ftbl_camss_jpeg_jpeg0_2_clk[] = {
+	F(75000000, P_GPLL0, 8, 0, 0),
+	F(133330000, P_GPLL0, 4.5, 0, 0),
+	F(200000000, P_GPLL0, 3, 0, 0),
+	F(228570000, P_MMPLL0, 3.5, 0, 0),
+	F(266670000, P_MMPLL0, 3, 0, 0),
+	F(320000000, P_MMPLL0, 2.5, 0, 0),
+	{ }
+};
+
+static struct clk_rcg2 jpeg0_clk_src = {
+	.cmd_rcgr = 0x3500,
+	.hid_width = 5,
+	.parent_map = mmcc_xo_mmpll0_mmpll1_gpll0_map,
+	.freq_tbl = ftbl_camss_jpeg_jpeg0_2_clk,
+	.hw.init = &(struct clk_init_data){
+		.name = "jpeg0_clk_src",
+		.parent_names = mmcc_xo_mmpll0_mmpll1_gpll0,
+		.num_parents = 4,
+		.ops = &clk_rcg2_ops,
+	},
+};
+
+static struct clk_rcg2 jpeg1_clk_src = {
+	.cmd_rcgr = 0x3520,
+	.hid_width = 5,
+	.parent_map = mmcc_xo_mmpll0_mmpll1_gpll0_map,
+	.freq_tbl = ftbl_camss_jpeg_jpeg0_2_clk,
+	.hw.init = &(struct clk_init_data){
+		.name = "jpeg1_clk_src",
+		.parent_names = mmcc_xo_mmpll0_mmpll1_gpll0,
+		.num_parents = 4,
+		.ops = &clk_rcg2_ops,
+	},
+};
+
+static struct clk_rcg2 jpeg2_clk_src = {
+	.cmd_rcgr = 0x3540,
+	.hid_width = 5,
+	.parent_map = mmcc_xo_mmpll0_mmpll1_gpll0_map,
+	.freq_tbl = ftbl_camss_jpeg_jpeg0_2_clk,
+	.hw.init = &(struct clk_init_data){
+		.name = "jpeg2_clk_src",
+		.parent_names = mmcc_xo_mmpll0_mmpll1_gpll0,
+		.num_parents = 4,
+		.ops = &clk_rcg2_ops,
+	},
+};
+
+static struct freq_tbl ftbl_mdss_pclk0_clk[] = {
+	F(125000000, P_DSI0PLL, 2, 0, 0),
+	F(250000000, P_DSI0PLL, 1, 0, 0),
+	{ }
+};
+
+static struct freq_tbl ftbl_mdss_pclk1_clk[] = {
+	F(125000000, P_DSI1PLL, 2, 0, 0),
+	F(250000000, P_DSI1PLL, 1, 0, 0),
+	{ }
+};
+
+static struct clk_rcg2 pclk0_clk_src = {
+	.cmd_rcgr = 0x2000,
+	.mnd_width = 8,
+	.hid_width = 5,
+	.parent_map = mmcc_xo_dsi_hdmi_edp_gpll0_map,
+	.freq_tbl = ftbl_mdss_pclk0_clk,
+	.hw.init = &(struct clk_init_data){
+		.name = "pclk0_clk_src",
+		.parent_names = mmcc_xo_dsi_hdmi_edp_gpll0,
+		.num_parents = 6,
+		.ops = &clk_rcg2_ops,
+	},
+};
+
+static struct clk_rcg2 pclk1_clk_src = {
+	.cmd_rcgr = 0x2020,
+	.mnd_width = 8,
+	.hid_width = 5,
+	.parent_map = mmcc_xo_dsi_hdmi_edp_gpll0_map,
+	.freq_tbl = ftbl_mdss_pclk1_clk,
+	.hw.init = &(struct clk_init_data){
+		.name = "pclk1_clk_src",
+		.parent_names = mmcc_xo_dsi_hdmi_edp_gpll0,
+		.num_parents = 6,
+		.ops = &clk_rcg2_ops,
+	},
+};
+
+static struct freq_tbl ftbl_venus0_vcodec0_clk[] = {
+	F(50000000, P_GPLL0, 12, 0, 0),
+	F(100000000, P_GPLL0, 6, 0, 0),
+	F(133330000, P_MMPLL0, 6, 0, 0),
+	F(200000000, P_MMPLL0, 4, 0, 0),
+	F(266670000, P_MMPLL0, 3, 0, 0),
+	F(465000000, P_MMPLL3, 2, 0, 0),
+	{ }
+};
+
+static struct clk_rcg2 vcodec0_clk_src = {
+	.cmd_rcgr = 0x1000,
+	.mnd_width = 8,
+	.hid_width = 5,
+	.parent_map = mmcc_xo_mmpll0_1_3_gpll0_map,
+	.freq_tbl = ftbl_venus0_vcodec0_clk,
+	.hw.init = &(struct clk_init_data){
+		.name = "vcodec0_clk_src",
+		.parent_names = mmcc_xo_mmpll0_1_3_gpll0,
+		.num_parents = 5,
+		.ops = &clk_rcg2_ops,
+	},
+};
+
+static struct freq_tbl ftbl_camss_cci_cci_clk[] = {
+	F(19200000, P_XO, 1, 0, 0),
+	{ }
+};
+
+static struct clk_rcg2 cci_clk_src = {
+	.cmd_rcgr = 0x3300,
+	.hid_width = 5,
+	.parent_map = mmcc_xo_mmpll0_mmpll1_gpll0_map,
+	.freq_tbl = ftbl_camss_cci_cci_clk,
+	.hw.init = &(struct clk_init_data){
+		.name = "cci_clk_src",
+		.parent_names = mmcc_xo_mmpll0_mmpll1_gpll0,
+		.num_parents = 4,
+		.ops = &clk_rcg2_ops,
+	},
+};
+
+static struct freq_tbl ftbl_camss_gp0_1_clk[] = {
+	F(10000, P_XO, 16, 1, 120),
+	F(24000, P_XO, 16, 1, 50),
+	F(6000000, P_GPLL0, 10, 1, 10),
+	F(12000000, P_GPLL0, 10, 1, 5),
+	F(13000000, P_GPLL0, 4, 13, 150),
+	F(24000000, P_GPLL0, 5, 1, 5),
+	{ }
+};
+
+static struct clk_rcg2 camss_gp0_clk_src = {
+	.cmd_rcgr = 0x3420,
+	.mnd_width = 8,
+	.hid_width = 5,
+	.parent_map = mmcc_xo_mmpll0_1_gpll1_0_map,
+	.freq_tbl = ftbl_camss_gp0_1_clk,
+	.hw.init = &(struct clk_init_data){
+		.name = "camss_gp0_clk_src",
+		.parent_names = mmcc_xo_mmpll0_1_gpll1_0,
+		.num_parents = 5,
+		.ops = &clk_rcg2_ops,
+	},
+};
+
+static struct clk_rcg2 camss_gp1_clk_src = {
+	.cmd_rcgr = 0x3450,
+	.mnd_width = 8,
+	.hid_width = 5,
+	.parent_map = mmcc_xo_mmpll0_1_gpll1_0_map,
+	.freq_tbl = ftbl_camss_gp0_1_clk,
+	.hw.init = &(struct clk_init_data){
+		.name = "camss_gp1_clk_src",
+		.parent_names = mmcc_xo_mmpll0_1_gpll1_0,
+		.num_parents = 5,
+		.ops = &clk_rcg2_ops,
+	},
+};
+
+static struct freq_tbl ftbl_camss_mclk0_3_clk[] = {
+	F(4800000, P_XO, 4, 0, 0),
+	F(6000000, P_GPLL0, 10, 1, 10),
+	F(8000000, P_GPLL0, 15, 1, 5),
+	F(9600000, P_XO, 2, 0, 0),
+	F(16000000, P_GPLL0, 12.5, 1, 3),
+	F(19200000, P_XO, 1, 0, 0),
+	F(24000000, P_GPLL0, 5, 1, 5),
+	F(32000000, P_MMPLL0, 5, 1, 5),
+	F(48000000, P_GPLL0, 12.5, 0, 0),
+	F(64000000, P_MMPLL0, 12.5, 0, 0),
+	F(66670000, P_GPLL0, 9, 0, 0),
+	{ }
+};
+
+static struct clk_rcg2 mclk0_clk_src = {
+	.cmd_rcgr = 0x3360,
+	.hid_width = 5,
+	.parent_map = mmcc_xo_mmpll0_mmpll1_gpll0_map,
+	.freq_tbl = ftbl_camss_mclk0_3_clk,
+	.hw.init = &(struct clk_init_data){
+		.name = "mclk0_clk_src",
+		.parent_names = mmcc_xo_mmpll0_mmpll1_gpll0,
+		.num_parents = 4,
+		.ops = &clk_rcg2_ops,
+	},
+};
+
+static struct clk_rcg2 mclk1_clk_src = {
+	.cmd_rcgr = 0x3390,
+	.hid_width = 5,
+	.parent_map = mmcc_xo_mmpll0_mmpll1_gpll0_map,
+	.freq_tbl = ftbl_camss_mclk0_3_clk,
+	.hw.init = &(struct clk_init_data){
+		.name = "mclk1_clk_src",
+		.parent_names = mmcc_xo_mmpll0_mmpll1_gpll0,
+		.num_parents = 4,
+		.ops = &clk_rcg2_ops,
+	},
+};
+
+static struct clk_rcg2 mclk2_clk_src = {
+	.cmd_rcgr = 0x33c0,
+	.hid_width = 5,
+	.parent_map = mmcc_xo_mmpll0_mmpll1_gpll0_map,
+	.freq_tbl = ftbl_camss_mclk0_3_clk,
+	.hw.init = &(struct clk_init_data){
+		.name = "mclk2_clk_src",
+		.parent_names = mmcc_xo_mmpll0_mmpll1_gpll0,
+		.num_parents = 4,
+		.ops = &clk_rcg2_ops,
+	},
+};
+
+static struct clk_rcg2 mclk3_clk_src = {
+	.cmd_rcgr = 0x33f0,
+	.hid_width = 5,
+	.parent_map = mmcc_xo_mmpll0_mmpll1_gpll0_map,
+	.freq_tbl = ftbl_camss_mclk0_3_clk,
+	.hw.init = &(struct clk_init_data){
+		.name = "mclk3_clk_src",
+		.parent_names = mmcc_xo_mmpll0_mmpll1_gpll0,
+		.num_parents = 4,
+		.ops = &clk_rcg2_ops,
+	},
+};
+
+static struct freq_tbl ftbl_camss_phy0_2_csi0_2phytimer_clk[] = {
+	F(100000000, P_GPLL0, 6, 0, 0),
+	F(200000000, P_MMPLL0, 4, 0, 0),
+	{ }
+};
+
+static struct clk_rcg2 csi0phytimer_clk_src = {
+	.cmd_rcgr = 0x3000,
+	.hid_width = 5,
+	.parent_map = mmcc_xo_mmpll0_mmpll1_gpll0_map,
+	.freq_tbl = ftbl_camss_phy0_2_csi0_2phytimer_clk,
+	.hw.init = &(struct clk_init_data){
+		.name = "csi0phytimer_clk_src",
+		.parent_names = mmcc_xo_mmpll0_mmpll1_gpll0,
+		.num_parents = 4,
+		.ops = &clk_rcg2_ops,
+	},
+};
+
+static struct clk_rcg2 csi1phytimer_clk_src = {
+	.cmd_rcgr = 0x3030,
+	.hid_width = 5,
+	.parent_map = mmcc_xo_mmpll0_mmpll1_gpll0_map,
+	.freq_tbl = ftbl_camss_phy0_2_csi0_2phytimer_clk,
+	.hw.init = &(struct clk_init_data){
+		.name = "csi1phytimer_clk_src",
+		.parent_names = mmcc_xo_mmpll0_mmpll1_gpll0,
+		.num_parents = 4,
+		.ops = &clk_rcg2_ops,
+	},
+};
+
+static struct clk_rcg2 csi2phytimer_clk_src = {
+	.cmd_rcgr = 0x3060,
+	.hid_width = 5,
+	.parent_map = mmcc_xo_mmpll0_mmpll1_gpll0_map,
+	.freq_tbl = ftbl_camss_phy0_2_csi0_2phytimer_clk,
+	.hw.init = &(struct clk_init_data){
+		.name = "csi2phytimer_clk_src",
+		.parent_names = mmcc_xo_mmpll0_mmpll1_gpll0,
+		.num_parents = 4,
+		.ops = &clk_rcg2_ops,
+	},
+};
+
+static struct freq_tbl ftbl_camss_vfe_cpp_clk[] = {
+	F(133330000, P_GPLL0, 4.5, 0, 0),
+	F(266670000, P_MMPLL0, 3, 0, 0),
+	F(320000000, P_MMPLL0, 2.5, 0, 0),
+	F(400000000, P_MMPLL0, 2, 0, 0),
+	F(465000000, P_MMPLL3, 2, 0, 0),
+	{ }
+};
+
+static struct clk_rcg2 cpp_clk_src = {
+	.cmd_rcgr = 0x3640,
+	.hid_width = 5,
+	.parent_map = mmcc_xo_mmpll0_mmpll1_gpll0_map,
+	.freq_tbl = ftbl_camss_vfe_cpp_clk,
+	.hw.init = &(struct clk_init_data){
+		.name = "cpp_clk_src",
+		.parent_names = mmcc_xo_mmpll0_mmpll1_gpll0,
+		.num_parents = 4,
+		.ops = &clk_rcg2_ops,
+	},
+};
+
+static struct freq_tbl ftbl_mdss_byte0_clk[] = {
+	F(93750000, P_DSI0PLL, 8, 0, 0),
+	F(187500000, P_DSI0PLL, 4, 0, 0),
+	{ }
+};
+
+static struct freq_tbl ftbl_mdss_byte1_clk[] = {
+	F(93750000, P_DSI1PLL, 8, 0, 0),
+	F(187500000, P_DSI1PLL, 4, 0, 0),
+	{ }
+};
+
+static struct clk_rcg2 byte0_clk_src = {
+	.cmd_rcgr = 0x2120,
+	.hid_width = 5,
+	.parent_map = mmcc_xo_dsi_hdmi_edp_gpll0_map,
+	.freq_tbl = ftbl_mdss_byte0_clk,
+	.hw.init = &(struct clk_init_data){
+		.name = "byte0_clk_src",
+		.parent_names = mmcc_xo_dsi_hdmi_edp_gpll0,
+		.num_parents = 6,
+		.ops = &clk_rcg2_ops,
+	},
+};
+
+static struct clk_rcg2 byte1_clk_src = {
+	.cmd_rcgr = 0x2140,
+	.hid_width = 5,
+	.parent_map = mmcc_xo_dsi_hdmi_edp_gpll0_map,
+	.freq_tbl = ftbl_mdss_byte1_clk,
+	.hw.init = &(struct clk_init_data){
+		.name = "byte1_clk_src",
+		.parent_names = mmcc_xo_dsi_hdmi_edp_gpll0,
+		.num_parents = 6,
+		.ops = &clk_rcg2_ops,
+	},
+};
+
+static struct freq_tbl ftbl_mdss_edpaux_clk[] = {
+	F(19200000, P_XO, 1, 0, 0),
+	{ }
+};
+
+static struct clk_rcg2 edpaux_clk_src = {
+	.cmd_rcgr = 0x20e0,
+	.hid_width = 5,
+	.parent_map = mmcc_xo_mmpll0_mmpll1_gpll0_map,
+	.freq_tbl = ftbl_mdss_edpaux_clk,
+	.hw.init = &(struct clk_init_data){
+		.name = "edpaux_clk_src",
+		.parent_names = mmcc_xo_mmpll0_mmpll1_gpll0,
+		.num_parents = 4,
+		.ops = &clk_rcg2_ops,
+	},
+};
+
+static struct freq_tbl ftbl_mdss_edplink_clk[] = {
+	F(135000000, P_EDPLINK, 2, 0, 0),
+	F(270000000, P_EDPLINK, 11, 0, 0),
+	{ }
+};
+
+static struct clk_rcg2 edplink_clk_src = {
+	.cmd_rcgr = 0x20c0,
+	.hid_width = 5,
+	.parent_map = mmcc_xo_dsi_hdmi_edp_gpll0_map,
+	.freq_tbl = ftbl_mdss_edplink_clk,
+	.hw.init = &(struct clk_init_data){
+		.name = "edplink_clk_src",
+		.parent_names = mmcc_xo_dsi_hdmi_edp_gpll0,
+		.num_parents = 6,
+		.ops = &clk_rcg2_ops,
+	},
+};
+
+static struct freq_tbl ftbl_mdss_edppixel_clk[] = {
+	F(175000000, P_EDPVCO, 2, 0, 0),
+	F(350000000, P_EDPVCO, 11, 0, 0),
+	{ }
+};
+
+static struct clk_rcg2 edppixel_clk_src = {
+	.cmd_rcgr = 0x20a0,
+	.mnd_width = 8,
+	.hid_width = 5,
+	.parent_map = mmcc_xo_dsi_hdmi_edp_map,
+	.freq_tbl = ftbl_mdss_edppixel_clk,
+	.hw.init = &(struct clk_init_data){
+		.name = "edppixel_clk_src",
+		.parent_names = mmcc_xo_dsi_hdmi_edp,
+		.num_parents = 6,
+		.ops = &clk_rcg2_ops,
+	},
+};
+
+static struct freq_tbl ftbl_mdss_esc0_1_clk[] = {
+	F(19200000, P_XO, 1, 0, 0),
+	{ }
+};
+
+static struct clk_rcg2 esc0_clk_src = {
+	.cmd_rcgr = 0x2160,
+	.hid_width = 5,
+	.parent_map = mmcc_xo_dsi_hdmi_edp_gpll0_map,
+	.freq_tbl = ftbl_mdss_esc0_1_clk,
+	.hw.init = &(struct clk_init_data){
+		.name = "esc0_clk_src",
+		.parent_names = mmcc_xo_dsi_hdmi_edp_gpll0,
+		.num_parents = 6,
+		.ops = &clk_rcg2_ops,
+	},
+};
+
+static struct clk_rcg2 esc1_clk_src = {
+	.cmd_rcgr = 0x2180,
+	.hid_width = 5,
+	.parent_map = mmcc_xo_dsi_hdmi_edp_gpll0_map,
+	.freq_tbl = ftbl_mdss_esc0_1_clk,
+	.hw.init = &(struct clk_init_data){
+		.name = "esc1_clk_src",
+		.parent_names = mmcc_xo_dsi_hdmi_edp_gpll0,
+		.num_parents = 6,
+		.ops = &clk_rcg2_ops,
+	},
+};
+
+static struct freq_tbl ftbl_mdss_extpclk_clk[] = {
+	F(25200000, P_HDMIPLL, 1, 0, 0),
+	F(27000000, P_HDMIPLL, 1, 0, 0),
+	F(27030000, P_HDMIPLL, 1, 0, 0),
+	F(65000000, P_HDMIPLL, 1, 0, 0),
+	F(74250000, P_HDMIPLL, 1, 0, 0),
+	F(108000000, P_HDMIPLL, 1, 0, 0),
+	F(148500000, P_HDMIPLL, 1, 0, 0),
+	F(268500000, P_HDMIPLL, 1, 0, 0),
+	F(297000000, P_HDMIPLL, 1, 0, 0),
+	{ }
+};
+
+static struct clk_rcg2 extpclk_clk_src = {
+	.cmd_rcgr = 0x2060,
+	.hid_width = 5,
+	.parent_map = mmcc_xo_dsi_hdmi_edp_gpll0_map,
+	.freq_tbl = ftbl_mdss_extpclk_clk,
+	.hw.init = &(struct clk_init_data){
+		.name = "extpclk_clk_src",
+		.parent_names = mmcc_xo_dsi_hdmi_edp_gpll0,
+		.num_parents = 6,
+		.ops = &clk_rcg2_ops,
+	},
+};
+
+static struct freq_tbl ftbl_mdss_hdmi_clk[] = {
+	F(19200000, P_XO, 1, 0, 0),
+	{ }
+};
+
+static struct clk_rcg2 hdmi_clk_src = {
+	.cmd_rcgr = 0x2100,
+	.hid_width = 5,
+	.parent_map = mmcc_xo_mmpll0_mmpll1_gpll0_map,
+	.freq_tbl = ftbl_mdss_hdmi_clk,
+	.hw.init = &(struct clk_init_data){
+		.name = "hdmi_clk_src",
+		.parent_names = mmcc_xo_mmpll0_mmpll1_gpll0,
+		.num_parents = 4,
+		.ops = &clk_rcg2_ops,
+	},
+};
+
+static struct freq_tbl ftbl_mdss_vsync_clk[] = {
+	F(19200000, P_XO, 1, 0, 0),
+	{ }
+};
+
+static struct clk_rcg2 vsync_clk_src = {
+	.cmd_rcgr = 0x2080,
+	.hid_width = 5,
+	.parent_map = mmcc_xo_mmpll0_mmpll1_gpll0_map,
+	.freq_tbl = ftbl_mdss_vsync_clk,
+	.hw.init = &(struct clk_init_data){
+		.name = "vsync_clk_src",
+		.parent_names = mmcc_xo_mmpll0_mmpll1_gpll0,
+		.num_parents = 4,
+		.ops = &clk_rcg2_ops,
+	},
+};
+
+static struct clk_branch camss_cci_cci_ahb_clk = {
+	.halt_reg = 0x3348,
+	.hw = {
+		.enable_reg = 0x3348,
+		.enable_mask = BIT(0),
+		.init = &(struct clk_init_data){
+			.name = "camss_cci_cci_ahb_clk",
+			.parent_names = (const char *[]){
+				"mmss_ahb_clk_src",
+			},
+			.num_parents = 1,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch camss_cci_cci_clk = {
+	.halt_reg = 0x3344,
+	.hw = {
+		.enable_reg = 0x3344,
+		.enable_mask = BIT(0),
+		.init = &(struct clk_init_data){
+			.name = "camss_cci_cci_clk",
+			.parent_names = (const char *[]){
+				"cci_clk_src",
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch camss_csi0_ahb_clk = {
+	.halt_reg = 0x30bc,
+	.hw = {
+		.enable_reg = 0x30bc,
+		.enable_mask = BIT(0),
+		.init = &(struct clk_init_data){
+			.name = "camss_csi0_ahb_clk",
+			.parent_names = (const char *[]){
+				"mmss_ahb_clk_src",
+			},
+			.num_parents = 1,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch camss_csi0_clk = {
+	.halt_reg = 0x30b4,
+	.hw = {
+		.enable_reg = 0x30b4,
+		.enable_mask = BIT(0),
+		.init = &(struct clk_init_data){
+			.name = "camss_csi0_clk",
+			.parent_names = (const char *[]){
+				"csi0_clk_src",
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch camss_csi0phy_clk = {
+	.halt_reg = 0x30c4,
+	.hw = {
+		.enable_reg = 0x30c4,
+		.enable_mask = BIT(0),
+		.init = &(struct clk_init_data){
+			.name = "camss_csi0phy_clk",
+			.parent_names = (const char *[]){
+				"csi0_clk_src",
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch camss_csi0pix_clk = {
+	.halt_reg = 0x30e4,
+	.hw = {
+		.enable_reg = 0x30e4,
+		.enable_mask = BIT(0),
+		.init = &(struct clk_init_data){
+			.name = "camss_csi0pix_clk",
+			.parent_names = (const char *[]){
+				"csi0_clk_src",
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch camss_csi0rdi_clk = {
+	.halt_reg = 0x30d4,
+	.hw = {
+		.enable_reg = 0x30d4,
+		.enable_mask = BIT(0),
+		.init = &(struct clk_init_data){
+			.name = "camss_csi0rdi_clk",
+			.parent_names = (const char *[]){
+				"csi0_clk_src",
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch camss_csi1_ahb_clk = {
+	.halt_reg = 0x3128,
+	.hw = {
+		.enable_reg = 0x3128,
+		.enable_mask = BIT(0),
+		.init = &(struct clk_init_data){
+			.name = "camss_csi1_ahb_clk",
+			.parent_names = (const char *[]){
+				"mmss_ahb_clk_src",
+			},
+			.num_parents = 1,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch camss_csi1_clk = {
+	.halt_reg = 0x3124,
+	.hw = {
+		.enable_reg = 0x3124,
+		.enable_mask = BIT(0),
+		.init = &(struct clk_init_data){
+			.name = "camss_csi1_clk",
+			.parent_names = (const char *[]){
+				"csi1_clk_src",
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch camss_csi1phy_clk = {
+	.halt_reg = 0x3134,
+	.hw = {
+		.enable_reg = 0x3134,
+		.enable_mask = BIT(0),
+		.init = &(struct clk_init_data){
+			.name = "camss_csi1phy_clk",
+			.parent_names = (const char *[]){
+				"csi1_clk_src",
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch camss_csi1pix_clk = {
+	.halt_reg = 0x3154,
+	.hw = {
+		.enable_reg = 0x3154,
+		.enable_mask = BIT(0),
+		.init = &(struct clk_init_data){
+			.name = "camss_csi1pix_clk",
+			.parent_names = (const char *[]){
+				"csi1_clk_src",
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch camss_csi1rdi_clk = {
+	.halt_reg = 0x3144,
+	.hw = {
+		.enable_reg = 0x3144,
+		.enable_mask = BIT(0),
+		.init = &(struct clk_init_data){
+			.name = "camss_csi1rdi_clk",
+			.parent_names = (const char *[]){
+				"csi1_clk_src",
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch camss_csi2_ahb_clk = {
+	.halt_reg = 0x3188,
+	.hw = {
+		.enable_reg = 0x3188,
+		.enable_mask = BIT(0),
+		.init = &(struct clk_init_data){
+			.name = "camss_csi2_ahb_clk",
+			.parent_names = (const char *[]){
+				"mmss_ahb_clk_src",
+			},
+			.num_parents = 1,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch camss_csi2_clk = {
+	.halt_reg = 0x3184,
+	.hw = {
+		.enable_reg = 0x3184,
+		.enable_mask = BIT(0),
+		.init = &(struct clk_init_data){
+			.name = "camss_csi2_clk",
+			.parent_names = (const char *[]){
+				"csi2_clk_src",
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch camss_csi2phy_clk = {
+	.halt_reg = 0x3194,
+	.hw = {
+		.enable_reg = 0x3194,
+		.enable_mask = BIT(0),
+		.init = &(struct clk_init_data){
+			.name = "camss_csi2phy_clk",
+			.parent_names = (const char *[]){
+				"csi2_clk_src",
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch camss_csi2pix_clk = {
+	.halt_reg = 0x31b4,
+	.hw = {
+		.enable_reg = 0x31b4,
+		.enable_mask = BIT(0),
+		.init = &(struct clk_init_data){
+			.name = "camss_csi2pix_clk",
+			.parent_names = (const char *[]){
+				"csi2_clk_src",
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch camss_csi2rdi_clk = {
+	.halt_reg = 0x31a4,
+	.hw = {
+		.enable_reg = 0x31a4,
+		.enable_mask = BIT(0),
+		.init = &(struct clk_init_data){
+			.name = "camss_csi2rdi_clk",
+			.parent_names = (const char *[]){
+				"csi2_clk_src",
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch camss_csi3_ahb_clk = {
+	.halt_reg = 0x31e8,
+	.hw = {
+		.enable_reg = 0x31e8,
+		.enable_mask = BIT(0),
+		.init = &(struct clk_init_data){
+			.name = "camss_csi3_ahb_clk",
+			.parent_names = (const char *[]){
+				"mmss_ahb_clk_src",
+			},
+			.num_parents = 1,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch camss_csi3_clk = {
+	.halt_reg = 0x31e4,
+	.hw = {
+		.enable_reg = 0x31e4,
+		.enable_mask = BIT(0),
+		.init = &(struct clk_init_data){
+			.name = "camss_csi3_clk",
+			.parent_names = (const char *[]){
+				"csi3_clk_src",
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch camss_csi3phy_clk = {
+	.halt_reg = 0x31f4,
+	.hw = {
+		.enable_reg = 0x31f4,
+		.enable_mask = BIT(0),
+		.init = &(struct clk_init_data){
+			.name = "camss_csi3phy_clk",
+			.parent_names = (const char *[]){
+				"csi3_clk_src",
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch camss_csi3pix_clk = {
+	.halt_reg = 0x3214,
+	.hw = {
+		.enable_reg = 0x3214,
+		.enable_mask = BIT(0),
+		.init = &(struct clk_init_data){
+			.name = "camss_csi3pix_clk",
+			.parent_names = (const char *[]){
+				"csi3_clk_src",
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch camss_csi3rdi_clk = {
+	.halt_reg = 0x3204,
+	.hw = {
+		.enable_reg = 0x3204,
+		.enable_mask = BIT(0),
+		.init = &(struct clk_init_data){
+			.name = "camss_csi3rdi_clk",
+			.parent_names = (const char *[]){
+				"csi3_clk_src",
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch camss_csi_vfe0_clk = {
+	.halt_reg = 0x3704,
+	.hw = {
+		.enable_reg = 0x3704,
+		.enable_mask = BIT(0),
+		.init = &(struct clk_init_data){
+			.name = "camss_csi_vfe0_clk",
+			.parent_names = (const char *[]){
+				"vfe0_clk_src",
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch camss_csi_vfe1_clk = {
+	.halt_reg = 0x3714,
+	.hw = {
+		.enable_reg = 0x3714,
+		.enable_mask = BIT(0),
+		.init = &(struct clk_init_data){
+			.name = "camss_csi_vfe1_clk",
+			.parent_names = (const char *[]){
+				"vfe1_clk_src",
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch camss_gp0_clk = {
+	.halt_reg = 0x3444,
+	.hw = {
+		.enable_reg = 0x3444,
+		.enable_mask = BIT(0),
+		.init = &(struct clk_init_data){
+			.name = "camss_gp0_clk",
+			.parent_names = (const char *[]){
+				"camss_gp0_clk_src",
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch camss_gp1_clk = {
+	.halt_reg = 0x3474,
+	.hw = {
+		.enable_reg = 0x3474,
+		.enable_mask = BIT(0),
+		.init = &(struct clk_init_data){
+			.name = "camss_gp1_clk",
+			.parent_names = (const char *[]){
+				"camss_gp1_clk_src",
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch camss_ispif_ahb_clk = {
+	.halt_reg = 0x3224,
+	.hw = {
+		.enable_reg = 0x3224,
+		.enable_mask = BIT(0),
+		.init = &(struct clk_init_data){
+			.name = "camss_ispif_ahb_clk",
+			.parent_names = (const char *[]){
+				"mmss_ahb_clk_src",
+			},
+			.num_parents = 1,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch camss_jpeg_jpeg0_clk = {
+	.halt_reg = 0x35a8,
+	.hw = {
+		.enable_reg = 0x35a8,
+		.enable_mask = BIT(0),
+		.init = &(struct clk_init_data){
+			.name = "camss_jpeg_jpeg0_clk",
+			.parent_names = (const char *[]){
+				"jpeg0_clk_src",
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch camss_jpeg_jpeg1_clk = {
+	.halt_reg = 0x35ac,
+	.hw = {
+		.enable_reg = 0x35ac,
+		.enable_mask = BIT(0),
+		.init = &(struct clk_init_data){
+			.name = "camss_jpeg_jpeg1_clk",
+			.parent_names = (const char *[]){
+				"jpeg1_clk_src",
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch camss_jpeg_jpeg2_clk = {
+	.halt_reg = 0x35b0,
+	.hw = {
+		.enable_reg = 0x35b0,
+		.enable_mask = BIT(0),
+		.init = &(struct clk_init_data){
+			.name = "camss_jpeg_jpeg2_clk",
+			.parent_names = (const char *[]){
+				"jpeg2_clk_src",
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch camss_jpeg_jpeg_ahb_clk = {
+	.halt_reg = 0x35b4,
+	.hw = {
+		.enable_reg = 0x35b4,
+		.enable_mask = BIT(0),
+		.init = &(struct clk_init_data){
+			.name = "camss_jpeg_jpeg_ahb_clk",
+			.parent_names = (const char *[]){
+				"mmss_ahb_clk_src",
+			},
+			.num_parents = 1,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch camss_jpeg_jpeg_axi_clk = {
+	.halt_reg = 0x35b8,
+	.hw = {
+		.enable_reg = 0x35b8,
+		.enable_mask = BIT(0),
+		.init = &(struct clk_init_data){
+			.name = "camss_jpeg_jpeg_axi_clk",
+			.parent_names = (const char *[]){
+				"mmss_axi_clk_src",
+			},
+			.num_parents = 1,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch camss_jpeg_jpeg_ocmemnoc_clk = {
+	.halt_reg = 0x35bc,
+	.hw = {
+		.enable_reg = 0x35bc,
+		.enable_mask = BIT(0),
+		.init = &(struct clk_init_data){
+			.name = "camss_jpeg_jpeg_ocmemnoc_clk",
+			.parent_names = (const char *[]){
+				"ocmemnoc_clk_src",
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch camss_mclk0_clk = {
+	.halt_reg = 0x3384,
+	.hw = {
+		.enable_reg = 0x3384,
+		.enable_mask = BIT(0),
+		.init = &(struct clk_init_data){
+			.name = "camss_mclk0_clk",
+			.parent_names = (const char *[]){
+				"mclk0_clk_src",
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch camss_mclk1_clk = {
+	.halt_reg = 0x33b4,
+	.hw = {
+		.enable_reg = 0x33b4,
+		.enable_mask = BIT(0),
+		.init = &(struct clk_init_data){
+			.name = "camss_mclk1_clk",
+			.parent_names = (const char *[]){
+				"mclk1_clk_src",
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch camss_mclk2_clk = {
+	.halt_reg = 0x33e4,
+	.hw = {
+		.enable_reg = 0x33e4,
+		.enable_mask = BIT(0),
+		.init = &(struct clk_init_data){
+			.name = "camss_mclk2_clk",
+			.parent_names = (const char *[]){
+				"mclk2_clk_src",
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch camss_mclk3_clk = {
+	.halt_reg = 0x3414,
+	.hw = {
+		.enable_reg = 0x3414,
+		.enable_mask = BIT(0),
+		.init = &(struct clk_init_data){
+			.name = "camss_mclk3_clk",
+			.parent_names = (const char *[]){
+				"mclk3_clk_src",
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch camss_micro_ahb_clk = {
+	.halt_reg = 0x3494,
+	.hw = {
+		.enable_reg = 0x3494,
+		.enable_mask = BIT(0),
+		.init = &(struct clk_init_data){
+			.name = "camss_micro_ahb_clk",
+			.parent_names = (const char *[]){
+				"mmss_ahb_clk_src",
+			},
+			.num_parents = 1,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch camss_phy0_csi0phytimer_clk = {
+	.halt_reg = 0x3024,
+	.hw = {
+		.enable_reg = 0x3024,
+		.enable_mask = BIT(0),
+		.init = &(struct clk_init_data){
+			.name = "camss_phy0_csi0phytimer_clk",
+			.parent_names = (const char *[]){
+				"csi0phytimer_clk_src",
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch camss_phy1_csi1phytimer_clk = {
+	.halt_reg = 0x3054,
+	.hw = {
+		.enable_reg = 0x3054,
+		.enable_mask = BIT(0),
+		.init = &(struct clk_init_data){
+			.name = "camss_phy1_csi1phytimer_clk",
+			.parent_names = (const char *[]){
+				"csi1phytimer_clk_src",
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch camss_phy2_csi2phytimer_clk = {
+	.halt_reg = 0x3084,
+	.hw = {
+		.enable_reg = 0x3084,
+		.enable_mask = BIT(0),
+		.init = &(struct clk_init_data){
+			.name = "camss_phy2_csi2phytimer_clk",
+			.parent_names = (const char *[]){
+				"csi2phytimer_clk_src",
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch camss_top_ahb_clk = {
+	.halt_reg = 0x3484,
+	.hw = {
+		.enable_reg = 0x3484,
+		.enable_mask = BIT(0),
+		.init = &(struct clk_init_data){
+			.name = "camss_top_ahb_clk",
+			.parent_names = (const char *[]){
+				"mmss_ahb_clk_src",
+			},
+			.num_parents = 1,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch camss_vfe_cpp_ahb_clk = {
+	.halt_reg = 0x36b4,
+	.hw = {
+		.enable_reg = 0x36b4,
+		.enable_mask = BIT(0),
+		.init = &(struct clk_init_data){
+			.name = "camss_vfe_cpp_ahb_clk",
+			.parent_names = (const char *[]){
+				"mmss_ahb_clk_src",
+			},
+			.num_parents = 1,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch camss_vfe_cpp_clk = {
+	.halt_reg = 0x36b0,
+	.hw = {
+		.enable_reg = 0x36b0,
+		.enable_mask = BIT(0),
+		.init = &(struct clk_init_data){
+			.name = "camss_vfe_cpp_clk",
+			.parent_names = (const char *[]){
+				"cpp_clk_src",
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch camss_vfe_vfe0_clk = {
+	.halt_reg = 0x36a8,
+	.hw = {
+		.enable_reg = 0x36a8,
+		.enable_mask = BIT(0),
+		.init = &(struct clk_init_data){
+			.name = "camss_vfe_vfe0_clk",
+			.parent_names = (const char *[]){
+				"vfe0_clk_src",
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch camss_vfe_vfe1_clk = {
+	.halt_reg = 0x36ac,
+	.hw = {
+		.enable_reg = 0x36ac,
+		.enable_mask = BIT(0),
+		.init = &(struct clk_init_data){
+			.name = "camss_vfe_vfe1_clk",
+			.parent_names = (const char *[]){
+				"vfe1_clk_src",
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch camss_vfe_vfe_ahb_clk = {
+	.halt_reg = 0x36b8,
+	.hw = {
+		.enable_reg = 0x36b8,
+		.enable_mask = BIT(0),
+		.init = &(struct clk_init_data){
+			.name = "camss_vfe_vfe_ahb_clk",
+			.parent_names = (const char *[]){
+				"mmss_ahb_clk_src",
+			},
+			.num_parents = 1,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch camss_vfe_vfe_axi_clk = {
+	.halt_reg = 0x36bc,
+	.hw = {
+		.enable_reg = 0x36bc,
+		.enable_mask = BIT(0),
+		.init = &(struct clk_init_data){
+			.name = "camss_vfe_vfe_axi_clk",
+			.parent_names = (const char *[]){
+				"mmss_axi_clk_src",
+			},
+			.num_parents = 1,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch camss_vfe_vfe_ocmemnoc_clk = {
+	.halt_reg = 0x36c0,
+	.hw = {
+		.enable_reg = 0x36c0,
+		.enable_mask = BIT(0),
+		.init = &(struct clk_init_data){
+			.name = "camss_vfe_vfe_ocmemnoc_clk",
+			.parent_names = (const char *[]){
+				"ocmemnoc_clk_src",
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch mdss_ahb_clk = {
+	.halt_reg = 0x2308,
+	.hw = {
+		.enable_reg = 0x2308,
+		.enable_mask = BIT(0),
+		.init = &(struct clk_init_data){
+			.name = "mdss_ahb_clk",
+			.parent_names = (const char *[]){
+				"mmss_ahb_clk_src",
+			},
+			.num_parents = 1,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch mdss_axi_clk = {
+	.halt_reg = 0x2310,
+	.hw = {
+		.enable_reg = 0x2310,
+		.enable_mask = BIT(0),
+		.init = &(struct clk_init_data){
+			.name = "mdss_axi_clk",
+			.parent_names = (const char *[]){
+				"mmss_axi_clk_src",
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch mdss_byte0_clk = {
+	.halt_reg = 0x233c,
+	.hw = {
+		.enable_reg = 0x233c,
+		.enable_mask = BIT(0),
+		.init = &(struct clk_init_data){
+			.name = "mdss_byte0_clk",
+			.parent_names = (const char *[]){
+				"byte0_clk_src",
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch mdss_byte1_clk = {
+	.halt_reg = 0x2340,
+	.hw = {
+		.enable_reg = 0x2340,
+		.enable_mask = BIT(0),
+		.init = &(struct clk_init_data){
+			.name = "mdss_byte1_clk",
+			.parent_names = (const char *[]){
+				"byte1_clk_src",
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch mdss_edpaux_clk = {
+	.halt_reg = 0x2334,
+	.hw = {
+		.enable_reg = 0x2334,
+		.enable_mask = BIT(0),
+		.init = &(struct clk_init_data){
+			.name = "mdss_edpaux_clk",
+			.parent_names = (const char *[]){
+				"edpaux_clk_src",
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch mdss_edplink_clk = {
+	.halt_reg = 0x2330,
+	.hw = {
+		.enable_reg = 0x2330,
+		.enable_mask = BIT(0),
+		.init = &(struct clk_init_data){
+			.name = "mdss_edplink_clk",
+			.parent_names = (const char *[]){
+				"edplink_clk_src",
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch mdss_edppixel_clk = {
+	.halt_reg = 0x232c,
+	.hw = {
+		.enable_reg = 0x232c,
+		.enable_mask = BIT(0),
+		.init = &(struct clk_init_data){
+			.name = "mdss_edppixel_clk",
+			.parent_names = (const char *[]){
+				"edppixel_clk_src",
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch mdss_esc0_clk = {
+	.halt_reg = 0x2344,
+	.hw = {
+		.enable_reg = 0x2344,
+		.enable_mask = BIT(0),
+		.init = &(struct clk_init_data){
+			.name = "mdss_esc0_clk",
+			.parent_names = (const char *[]){
+				"esc0_clk_src",
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch mdss_esc1_clk = {
+	.halt_reg = 0x2348,
+	.hw = {
+		.enable_reg = 0x2348,
+		.enable_mask = BIT(0),
+		.init = &(struct clk_init_data){
+			.name = "mdss_esc1_clk",
+			.parent_names = (const char *[]){
+				"esc1_clk_src",
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch mdss_extpclk_clk = {
+	.halt_reg = 0x2324,
+	.hw = {
+		.enable_reg = 0x2324,
+		.enable_mask = BIT(0),
+		.init = &(struct clk_init_data){
+			.name = "mdss_extpclk_clk",
+			.parent_names = (const char *[]){
+				"extpclk_clk_src",
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch mdss_hdmi_ahb_clk = {
+	.halt_reg = 0x230c,
+	.hw = {
+		.enable_reg = 0x230c,
+		.enable_mask = BIT(0),
+		.init = &(struct clk_init_data){
+			.name = "mdss_hdmi_ahb_clk",
+			.parent_names = (const char *[]){
+				"mmss_ahb_clk_src",
+			},
+			.num_parents = 1,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch mdss_hdmi_clk = {
+	.halt_reg = 0x2338,
+	.hw = {
+		.enable_reg = 0x2338,
+		.enable_mask = BIT(0),
+		.init = &(struct clk_init_data){
+			.name = "mdss_hdmi_clk",
+			.parent_names = (const char *[]){
+				"hdmi_clk_src",
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch mdss_mdp_clk = {
+	.halt_reg = 0x231c,
+	.hw = {
+		.enable_reg = 0x231c,
+		.enable_mask = BIT(0),
+		.init = &(struct clk_init_data){
+			.name = "mdss_mdp_clk",
+			.parent_names = (const char *[]){
+				"mdp_clk_src",
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch mdss_mdp_lut_clk = {
+	.halt_reg = 0x2320,
+	.hw = {
+		.enable_reg = 0x2320,
+		.enable_mask = BIT(0),
+		.init = &(struct clk_init_data){
+			.name = "mdss_mdp_lut_clk",
+			.parent_names = (const char *[]){
+				"mdp_clk_src",
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch mdss_pclk0_clk = {
+	.halt_reg = 0x2314,
+	.hw = {
+		.enable_reg = 0x2314,
+		.enable_mask = BIT(0),
+		.init = &(struct clk_init_data){
+			.name = "mdss_pclk0_clk",
+			.parent_names = (const char *[]){
+				"pclk0_clk_src",
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch mdss_pclk1_clk = {
+	.halt_reg = 0x2318,
+	.hw = {
+		.enable_reg = 0x2318,
+		.enable_mask = BIT(0),
+		.init = &(struct clk_init_data){
+			.name = "mdss_pclk1_clk",
+			.parent_names = (const char *[]){
+				"pclk1_clk_src",
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch mdss_vsync_clk = {
+	.halt_reg = 0x2328,
+	.hw = {
+		.enable_reg = 0x2328,
+		.enable_mask = BIT(0),
+		.init = &(struct clk_init_data){
+			.name = "mdss_vsync_clk",
+			.parent_names = (const char *[]){
+				"vsync_clk_src",
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch mmss_misc_ahb_clk = {
+	.halt_reg = 0x502c,
+	.hw = {
+		.enable_reg = 0x502c,
+		.enable_mask = BIT(0),
+		.init = &(struct clk_init_data){
+			.name = "mmss_misc_ahb_clk",
+			.parent_names = (const char *[]){
+				"mmss_ahb_clk_src",
+			},
+			.num_parents = 1,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch mmss_mmssnoc_ahb_clk = {
+	.halt_reg = 0x5024,
+	.hw = {
+		.enable_reg = 0x5024,
+		.enable_mask = BIT(0),
+		.init = &(struct clk_init_data){
+			.name = "mmss_mmssnoc_ahb_clk",
+			.parent_names = (const char *[]){
+				"mmss_ahb_clk_src",
+			},
+			.num_parents = 1,
+			.ops = &clk_branch2_ops,
+			.flags = CLK_IGNORE_UNUSED,
+		},
+	},
+};
+
+static struct clk_branch mmss_mmssnoc_bto_ahb_clk = {
+	.halt_reg = 0x5028,
+	.hw = {
+		.enable_reg = 0x5028,
+		.enable_mask = BIT(0),
+		.init = &(struct clk_init_data){
+			.name = "mmss_mmssnoc_bto_ahb_clk",
+			.parent_names = (const char *[]){
+				"mmss_ahb_clk_src",
+			},
+			.num_parents = 1,
+			.ops = &clk_branch2_ops,
+			.flags = CLK_IGNORE_UNUSED,
+		},
+	},
+};
+
+static struct clk_branch mmss_mmssnoc_axi_clk = {
+	.halt_reg = 0x506c,
+	.hw = {
+		.enable_reg = 0x506c,
+		.enable_mask = BIT(0),
+		.init = &(struct clk_init_data){
+			.name = "mmss_mmssnoc_axi_clk",
+			.parent_names = (const char *[]){
+				"mmss_axi_clk_src",
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch mmss_s0_axi_clk = {
+	.halt_reg = 0x5064,
+	.hw = {
+		.enable_reg = 0x5064,
+		.enable_mask = BIT(0),
+		.init = &(struct clk_init_data){
+			.name = "mmss_s0_axi_clk",
+			.parent_names = (const char *[]){
+				"mmss_axi_clk_src",
+			},
+			.num_parents = 1,
+			.ops = &clk_branch2_ops,
+			.flags = CLK_IGNORE_UNUSED,
+		},
+	},
+};
+
+static struct clk_branch ocmemcx_ahb_clk = {
+	.halt_reg = 0x405c,
+	.hw = {
+		.enable_reg = 0x405c,
+		.enable_mask = BIT(0),
+		.init = &(struct clk_init_data){
+			.name = "ocmemcx_ahb_clk",
+			.parent_names = (const char *[]){
+				"mmss_ahb_clk_src",
+			},
+			.num_parents = 1,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch ocmemcx_ocmemnoc_clk = {
+	.halt_reg = 0x4058,
+	.hw = {
+		.enable_reg = 0x4058,
+		.enable_mask = BIT(0),
+		.init = &(struct clk_init_data){
+			.name = "ocmemcx_ocmemnoc_clk",
+			.parent_names = (const char *[]){
+				"ocmemnoc_clk_src",
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch oxili_ocmemgx_clk = {
+	.halt_reg = 0x402c,
+	.hw = {
+		.enable_reg = 0x402c,
+		.enable_mask = BIT(0),
+		.init = &(struct clk_init_data){
+			.name = "oxili_ocmemgx_clk",
+			.parent_names = (const char *[]){
+				"gfx3d_clk_src",
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch ocmemnoc_clk = {
+	.halt_reg = 0x50b4,
+	.hw = {
+		.enable_reg = 0x50b4,
+		.enable_mask = BIT(0),
+		.init = &(struct clk_init_data){
+			.name = "ocmemnoc_clk",
+			.parent_names = (const char *[]){
+				"ocmemnoc_clk_src",
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch oxili_gfx3d_clk = {
+	.halt_reg = 0x4028,
+	.hw = {
+		.enable_reg = 0x4028,
+		.enable_mask = BIT(0),
+		.init = &(struct clk_init_data){
+			.name = "oxili_gfx3d_clk",
+			.parent_names = (const char *[]){
+				"gfx3d_clk_src",
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch oxilicx_ahb_clk = {
+	.halt_reg = 0x403c,
+	.hw = {
+		.enable_reg = 0x403c,
+		.enable_mask = BIT(0),
+		.init = &(struct clk_init_data){
+			.name = "oxilicx_ahb_clk",
+			.parent_names = (const char *[]){
+				"mmss_ahb_clk_src",
+			},
+			.num_parents = 1,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch oxilicx_axi_clk = {
+	.halt_reg = 0x4038,
+	.hw = {
+		.enable_reg = 0x4038,
+		.enable_mask = BIT(0),
+		.init = &(struct clk_init_data){
+			.name = "oxilicx_axi_clk",
+			.parent_names = (const char *[]){
+				"mmss_axi_clk_src",
+			},
+			.num_parents = 1,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch venus0_ahb_clk = {
+	.halt_reg = 0x1030,
+	.hw = {
+		.enable_reg = 0x1030,
+		.enable_mask = BIT(0),
+		.init = &(struct clk_init_data){
+			.name = "venus0_ahb_clk",
+			.parent_names = (const char *[]){
+				"mmss_ahb_clk_src",
+			},
+			.num_parents = 1,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch venus0_axi_clk = {
+	.halt_reg = 0x1034,
+	.hw = {
+		.enable_reg = 0x1034,
+		.enable_mask = BIT(0),
+		.init = &(struct clk_init_data){
+			.name = "venus0_axi_clk",
+			.parent_names = (const char *[]){
+				"mmss_axi_clk_src",
+			},
+			.num_parents = 1,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch venus0_ocmemnoc_clk = {
+	.halt_reg = 0x1038,
+	.hw = {
+		.enable_reg = 0x1038,
+		.enable_mask = BIT(0),
+		.init = &(struct clk_init_data){
+			.name = "venus0_ocmemnoc_clk",
+			.parent_names = (const char *[]){
+				"ocmemnoc_clk_src",
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static struct clk_branch venus0_vcodec0_clk = {
+	.halt_reg = 0x1028,
+	.hw = {
+		.enable_reg = 0x1028,
+		.enable_mask = BIT(0),
+		.init = &(struct clk_init_data){
+			.name = "venus0_vcodec0_clk",
+			.parent_names = (const char *[]){
+				"vcodec0_clk_src",
+			},
+			.num_parents = 1,
+			.flags = CLK_SET_RATE_PARENT,
+			.ops = &clk_branch2_ops,
+		},
+	},
+};
+
+static const struct pll_config mmpll1_config = {
+	.l = 60,
+	.m = 25,
+	.n = 32,
+	.vco_val = 0x0,
+	.vco_mask = 0x3 << 20,
+	.pre_div_val = 0x0,
+	.pre_div_mask = 0x3 << 12,
+	.post_div_val = 0x0,
+	.post_div_mask = 0x3 << 8,
+	.mn_ena_mask = BIT(24),
+	.main_output_mask = BIT(0),
+};
+
+static struct pll_config mmpll3_config = {
+	.l = 48,
+	.m = 7,
+	.n = 16,
+	.vco_val = 0x0,
+	.vco_mask = 0x3 << 20,
+	.pre_div_val = 0x0,
+	.pre_div_mask = 0x3 << 12,
+	.post_div_val = 0x0,
+	.post_div_mask = 0x3 << 8,
+	.mn_ena_mask = BIT(24),
+	.main_output_mask = BIT(0),
+	.aux_output_mask = BIT(1),
+};
+
+static struct clk_hw *mmcc_msm8974_clocks[] = {
+	[MMSS_AHB_CLK_SRC] = &mmss_ahb_clk_src.hw,
+	[MMSS_AXI_CLK_SRC] = &mmss_axi_clk_src.hw,
+	[OCMEMNOC_CLK_SRC] = &ocmemnoc_clk_src.hw,
+	[MMPLL0] = &mmpll0.hw,
+	[MMPLL0_VOTE] = &mmpll0_vote,
+	[MMPLL1] = &mmpll1.hw,
+	[MMPLL1_VOTE] = &mmpll1_vote,
+	[MMPLL2] = &mmpll2.hw,
+	[MMPLL3] = &mmpll3.hw,
+	[CSI0_CLK_SRC] = &csi0_clk_src.hw,
+	[CSI1_CLK_SRC] = &csi1_clk_src.hw,
+	[CSI2_CLK_SRC] = &csi2_clk_src.hw,
+	[CSI3_CLK_SRC] = &csi3_clk_src.hw,
+	[VFE0_CLK_SRC] = &vfe0_clk_src.hw,
+	[VFE1_CLK_SRC] = &vfe1_clk_src.hw,
+	[MDP_CLK_SRC] = &mdp_clk_src.hw,
+	[GFX3D_CLK_SRC] = &gfx3d_clk_src.hw,
+	[JPEG0_CLK_SRC] = &jpeg0_clk_src.hw,
+	[JPEG1_CLK_SRC] = &jpeg1_clk_src.hw,
+	[JPEG2_CLK_SRC] = &jpeg2_clk_src.hw,
+	[PCLK0_CLK_SRC] = &pclk0_clk_src.hw,
+	[PCLK1_CLK_SRC] = &pclk1_clk_src.hw,
+	[VCODEC0_CLK_SRC] = &vcodec0_clk_src.hw,
+	[CCI_CLK_SRC] = &cci_clk_src.hw,
+	[CAMSS_GP0_CLK_SRC] = &camss_gp0_clk_src.hw,
+	[CAMSS_GP1_CLK_SRC] = &camss_gp1_clk_src.hw,
+	[MCLK0_CLK_SRC] = &mclk0_clk_src.hw,
+	[MCLK1_CLK_SRC] = &mclk1_clk_src.hw,
+	[MCLK2_CLK_SRC] = &mclk2_clk_src.hw,
+	[MCLK3_CLK_SRC] = &mclk3_clk_src.hw,
+	[CSI0PHYTIMER_CLK_SRC] = &csi0phytimer_clk_src.hw,
+	[CSI1PHYTIMER_CLK_SRC] = &csi1phytimer_clk_src.hw,
+	[CSI2PHYTIMER_CLK_SRC] = &csi2phytimer_clk_src.hw,
+	[CPP_CLK_SRC] = &cpp_clk_src.hw,
+	[BYTE0_CLK_SRC] = &byte0_clk_src.hw,
+	[BYTE1_CLK_SRC] = &byte1_clk_src.hw,
+	[EDPAUX_CLK_SRC] = &edpaux_clk_src.hw,
+	[EDPLINK_CLK_SRC] = &edplink_clk_src.hw,
+	[EDPPIXEL_CLK_SRC] = &edppixel_clk_src.hw,
+	[ESC0_CLK_SRC] = &esc0_clk_src.hw,
+	[ESC1_CLK_SRC] = &esc1_clk_src.hw,
+	[EXTPCLK_CLK_SRC] = &extpclk_clk_src.hw,
+	[HDMI_CLK_SRC] = &hdmi_clk_src.hw,
+	[VSYNC_CLK_SRC] = &vsync_clk_src.hw,
+	[CAMSS_CCI_CCI_AHB_CLK] = &camss_cci_cci_ahb_clk.hw,
+	[CAMSS_CCI_CCI_CLK] = &camss_cci_cci_clk.hw,
+	[CAMSS_CSI0_AHB_CLK] = &camss_csi0_ahb_clk.hw,
+	[CAMSS_CSI0_CLK] = &camss_csi0_clk.hw,
+	[CAMSS_CSI0PHY_CLK] = &camss_csi0phy_clk.hw,
+	[CAMSS_CSI0PIX_CLK] = &camss_csi0pix_clk.hw,
+	[CAMSS_CSI0RDI_CLK] = &camss_csi0rdi_clk.hw,
+	[CAMSS_CSI1_AHB_CLK] = &camss_csi1_ahb_clk.hw,
+	[CAMSS_CSI1_CLK] = &camss_csi1_clk.hw,
+	[CAMSS_CSI1PHY_CLK] = &camss_csi1phy_clk.hw,
+	[CAMSS_CSI1PIX_CLK] = &camss_csi1pix_clk.hw,
+	[CAMSS_CSI1RDI_CLK] = &camss_csi1rdi_clk.hw,
+	[CAMSS_CSI2_AHB_CLK] = &camss_csi2_ahb_clk.hw,
+	[CAMSS_CSI2_CLK] = &camss_csi2_clk.hw,
+	[CAMSS_CSI2PHY_CLK] = &camss_csi2phy_clk.hw,
+	[CAMSS_CSI2PIX_CLK] = &camss_csi2pix_clk.hw,
+	[CAMSS_CSI2RDI_CLK] = &camss_csi2rdi_clk.hw,
+	[CAMSS_CSI3_AHB_CLK] = &camss_csi3_ahb_clk.hw,
+	[CAMSS_CSI3_CLK] = &camss_csi3_clk.hw,
+	[CAMSS_CSI3PHY_CLK] = &camss_csi3phy_clk.hw,
+	[CAMSS_CSI3PIX_CLK] = &camss_csi3pix_clk.hw,
+	[CAMSS_CSI3RDI_CLK] = &camss_csi3rdi_clk.hw,
+	[CAMSS_CSI_VFE0_CLK] = &camss_csi_vfe0_clk.hw,
+	[CAMSS_CSI_VFE1_CLK] = &camss_csi_vfe1_clk.hw,
+	[CAMSS_GP0_CLK] = &camss_gp0_clk.hw,
+	[CAMSS_GP1_CLK] = &camss_gp1_clk.hw,
+	[CAMSS_ISPIF_AHB_CLK] = &camss_ispif_ahb_clk.hw,
+	[CAMSS_JPEG_JPEG0_CLK] = &camss_jpeg_jpeg0_clk.hw,
+	[CAMSS_JPEG_JPEG1_CLK] = &camss_jpeg_jpeg1_clk.hw,
+	[CAMSS_JPEG_JPEG2_CLK] = &camss_jpeg_jpeg2_clk.hw,
+	[CAMSS_JPEG_JPEG_AHB_CLK] = &camss_jpeg_jpeg_ahb_clk.hw,
+	[CAMSS_JPEG_JPEG_AXI_CLK] = &camss_jpeg_jpeg_axi_clk.hw,
+	[CAMSS_JPEG_JPEG_OCMEMNOC_CLK] = &camss_jpeg_jpeg_ocmemnoc_clk.hw,
+	[CAMSS_MCLK0_CLK] = &camss_mclk0_clk.hw,
+	[CAMSS_MCLK1_CLK] = &camss_mclk1_clk.hw,
+	[CAMSS_MCLK2_CLK] = &camss_mclk2_clk.hw,
+	[CAMSS_MCLK3_CLK] = &camss_mclk3_clk.hw,
+	[CAMSS_MICRO_AHB_CLK] = &camss_micro_ahb_clk.hw,
+	[CAMSS_PHY0_CSI0PHYTIMER_CLK] = &camss_phy0_csi0phytimer_clk.hw,
+	[CAMSS_PHY1_CSI1PHYTIMER_CLK] = &camss_phy1_csi1phytimer_clk.hw,
+	[CAMSS_PHY2_CSI2PHYTIMER_CLK] = &camss_phy2_csi2phytimer_clk.hw,
+	[CAMSS_TOP_AHB_CLK] = &camss_top_ahb_clk.hw,
+	[CAMSS_VFE_CPP_AHB_CLK] = &camss_vfe_cpp_ahb_clk.hw,
+	[CAMSS_VFE_CPP_CLK] = &camss_vfe_cpp_clk.hw,
+	[CAMSS_VFE_VFE0_CLK] = &camss_vfe_vfe0_clk.hw,
+	[CAMSS_VFE_VFE1_CLK] = &camss_vfe_vfe1_clk.hw,
+	[CAMSS_VFE_VFE_AHB_CLK] = &camss_vfe_vfe_ahb_clk.hw,
+	[CAMSS_VFE_VFE_AXI_CLK] = &camss_vfe_vfe_axi_clk.hw,
+	[CAMSS_VFE_VFE_OCMEMNOC_CLK] = &camss_vfe_vfe_ocmemnoc_clk.hw,
+	[MDSS_AHB_CLK] = &mdss_ahb_clk.hw,
+	[MDSS_AXI_CLK] = &mdss_axi_clk.hw,
+	[MDSS_BYTE0_CLK] = &mdss_byte0_clk.hw,
+	[MDSS_BYTE1_CLK] = &mdss_byte1_clk.hw,
+	[MDSS_EDPAUX_CLK] = &mdss_edpaux_clk.hw,
+	[MDSS_EDPLINK_CLK] = &mdss_edplink_clk.hw,
+	[MDSS_EDPPIXEL_CLK] = &mdss_edppixel_clk.hw,
+	[MDSS_ESC0_CLK] = &mdss_esc0_clk.hw,
+	[MDSS_ESC1_CLK] = &mdss_esc1_clk.hw,
+	[MDSS_EXTPCLK_CLK] = &mdss_extpclk_clk.hw,
+	[MDSS_HDMI_AHB_CLK] = &mdss_hdmi_ahb_clk.hw,
+	[MDSS_HDMI_CLK] = &mdss_hdmi_clk.hw,
+	[MDSS_MDP_CLK] = &mdss_mdp_clk.hw,
+	[MDSS_MDP_LUT_CLK] = &mdss_mdp_lut_clk.hw,
+	[MDSS_PCLK0_CLK] = &mdss_pclk0_clk.hw,
+	[MDSS_PCLK1_CLK] = &mdss_pclk1_clk.hw,
+	[MDSS_VSYNC_CLK] = &mdss_vsync_clk.hw,
+	[MMSS_MISC_AHB_CLK] = &mmss_misc_ahb_clk.hw,
+	[MMSS_MMSSNOC_AHB_CLK] = &mmss_mmssnoc_ahb_clk.hw,
+	[MMSS_MMSSNOC_BTO_AHB_CLK] = &mmss_mmssnoc_bto_ahb_clk.hw,
+	[MMSS_MMSSNOC_AXI_CLK] = &mmss_mmssnoc_axi_clk.hw,
+	[MMSS_S0_AXI_CLK] = &mmss_s0_axi_clk.hw,
+	[OCMEMCX_AHB_CLK] = &ocmemcx_ahb_clk.hw,
+	[OCMEMCX_OCMEMNOC_CLK] = &ocmemcx_ocmemnoc_clk.hw,
+	[OXILI_OCMEMGX_CLK] = &oxili_ocmemgx_clk.hw,
+	[OCMEMNOC_CLK] = &ocmemnoc_clk.hw,
+	[OXILI_GFX3D_CLK] = &oxili_gfx3d_clk.hw,
+	[OXILICX_AHB_CLK] = &oxilicx_ahb_clk.hw,
+	[OXILICX_AXI_CLK] = &oxilicx_axi_clk.hw,
+	[VENUS0_AHB_CLK] = &venus0_ahb_clk.hw,
+	[VENUS0_AXI_CLK] = &venus0_axi_clk.hw,
+	[VENUS0_OCMEMNOC_CLK] = &venus0_ocmemnoc_clk.hw,
+	[VENUS0_VCODEC0_CLK] = &venus0_vcodec0_clk.hw,
+};
+
+static const struct qcom_reset_map mmcc_msm8974_resets[] = {
+	[SPDM_RESET] = { 0x0200 },
+	[SPDM_RM_RESET] = { 0x0300 },
+	[VENUS0_RESET] = { 0x1020 },
+	[MDSS_RESET] = { 0x2300 },
+	[CAMSS_PHY0_RESET] = { 0x3020 },
+	[CAMSS_PHY1_RESET] = { 0x3050 },
+	[CAMSS_PHY2_RESET] = { 0x3080 },
+	[CAMSS_CSI0_RESET] = { 0x30b0 },
+	[CAMSS_CSI0PHY_RESET] = { 0x30c0 },
+	[CAMSS_CSI0RDI_RESET] = { 0x30d0 },
+	[CAMSS_CSI0PIX_RESET] = { 0x30e0 },
+	[CAMSS_CSI1_RESET] = { 0x3120 },
+	[CAMSS_CSI1PHY_RESET] = { 0x3130 },
+	[CAMSS_CSI1RDI_RESET] = { 0x3140 },
+	[CAMSS_CSI1PIX_RESET] = { 0x3150 },
+	[CAMSS_CSI2_RESET] = { 0x3180 },
+	[CAMSS_CSI2PHY_RESET] = { 0x3190 },
+	[CAMSS_CSI2RDI_RESET] = { 0x31a0 },
+	[CAMSS_CSI2PIX_RESET] = { 0x31b0 },
+	[CAMSS_CSI3_RESET] = { 0x31e0 },
+	[CAMSS_CSI3PHY_RESET] = { 0x31f0 },
+	[CAMSS_CSI3RDI_RESET] = { 0x3200 },
+	[CAMSS_CSI3PIX_RESET] = { 0x3210 },
+	[CAMSS_ISPIF_RESET] = { 0x3220 },
+	[CAMSS_CCI_RESET] = { 0x3340 },
+	[CAMSS_MCLK0_RESET] = { 0x3380 },
+	[CAMSS_MCLK1_RESET] = { 0x33b0 },
+	[CAMSS_MCLK2_RESET] = { 0x33e0 },
+	[CAMSS_MCLK3_RESET] = { 0x3410 },
+	[CAMSS_GP0_RESET] = { 0x3440 },
+	[CAMSS_GP1_RESET] = { 0x3470 },
+	[CAMSS_TOP_RESET] = { 0x3480 },
+	[CAMSS_MICRO_RESET] = { 0x3490 },
+	[CAMSS_JPEG_RESET] = { 0x35a0 },
+	[CAMSS_VFE_RESET] = { 0x36a0 },
+	[CAMSS_CSI_VFE0_RESET] = { 0x3700 },
+	[CAMSS_CSI_VFE1_RESET] = { 0x3710 },
+	[OXILI_RESET] = { 0x4020 },
+	[OXILICX_RESET] = { 0x4030 },
+	[OCMEMCX_RESET] = { 0x4050 },
+	[MMSS_RBCRP_RESET] = { 0x4080 },
+	[MMSSNOCAHB_RESET] = { 0x5020 },
+	[MMSSNOCAXI_RESET] = { 0x5060 },
+	[OCMEMNOC_RESET] = { 0x50b0 },
+};
+
+static const struct regmap_config mmcc_msm8974_regmap_config = {
+	.reg_bits	= 32,
+	.reg_stride	= 4,
+	.val_bits	= 32,
+	.max_register	= 0x5104,
+	.fast_io	= true,
+};
+
+static const struct of_device_id mmcc_msm8974_match_table[] = {
+	{ .compatible = "qcom,mmcc-msm8974" },
+	{ }
+};
+MODULE_DEVICE_TABLE(of, mmcc_msm8974_match_table);
+
+struct qcom_cc {
+	struct qcom_reset_controller reset;
+	struct clk_onecell_data data;
+	struct clk *clks[];
+};
+
+static int mmcc_msm8974_probe(struct platform_device *pdev)
+{
+	void __iomem *base;
+	struct resource *res;
+	int i, ret;
+	struct device *dev = &pdev->dev;
+	struct clk *clk;
+	struct clk_onecell_data *data;
+	struct clk **clks;
+	struct regmap *regmap;
+	size_t num_clks;
+	struct qcom_reset_controller *reset;
+	struct qcom_cc *cc;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	base = devm_ioremap_resource(dev, res);
+	if (IS_ERR(base))
+		return PTR_ERR(base);
+
+	regmap = devm_regmap_init_mmio(dev, base, &mmcc_msm8974_regmap_config);
+	if (IS_ERR(regmap))
+		return PTR_ERR(regmap);
+
+	num_clks = ARRAY_SIZE(mmcc_msm8974_clocks);
+	cc = devm_kzalloc(dev, sizeof(*cc) + sizeof(*clks) * num_clks,
+			  GFP_KERNEL);
+	if (!cc)
+		return -ENOMEM;
+
+	clks = cc->clks;
+	data = &cc->data;
+	data->clks = clks;
+	data->clk_num = num_clks;
+
+	clk_pll_configure_sr_hpm_lp(&mmpll1, regmap, &mmpll1_config, true);
+	clk_pll_configure_sr_hpm_lp(&mmpll3, regmap, &mmpll3_config, false);
+
+	for (i = 0; i < num_clks; i++) {
+		if (!mmcc_msm8974_clocks[i])
+			continue;
+		clk = devm_clk_register(dev, mmcc_msm8974_clocks[i]);
+		if (IS_ERR(clk))
+			return PTR_ERR(clk);
+		clks[i] = clk;
+	}
+
+	ret = of_clk_add_provider(dev->of_node, of_clk_src_onecell_get, data);
+	if (ret)
+		return ret;
+
+	reset = &cc->reset;
+	reset->rcdev.of_node = dev->of_node;
+	reset->rcdev.ops = &qcom_reset_ops,
+	reset->rcdev.owner = THIS_MODULE,
+	reset->rcdev.nr_resets = ARRAY_SIZE(mmcc_msm8974_resets),
+	reset->regmap = regmap;
+	reset->reset_map = mmcc_msm8974_resets,
+	platform_set_drvdata(pdev, &reset->rcdev);
+
+	ret = reset_controller_register(&reset->rcdev);
+	if (ret)
+		of_clk_del_provider(dev->of_node);
+
+	return ret;
+}
+
+static int mmcc_msm8974_remove(struct platform_device *pdev)
+{
+	of_clk_del_provider(pdev->dev.of_node);
+	reset_controller_unregister(platform_get_drvdata(pdev));
+	return 0;
+}
+
+static struct platform_driver mmcc_msm8974_driver = {
+	.probe		= mmcc_msm8974_probe,
+	.remove		= mmcc_msm8974_remove,
+	.driver		= {
+		.name	= "mmcc-msm8974",
+		.owner	= THIS_MODULE,
+		.of_match_table = mmcc_msm8974_match_table,
+	},
+};
+module_platform_driver(mmcc_msm8974_driver);
+
+MODULE_DESCRIPTION("QCOM MMCC MSM8974 Driver");
+MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("platform:mmcc-msm8974");
diff --git a/include/dt-bindings/clock/qcom,mmcc-msm8974.h b/include/dt-bindings/clock/qcom,mmcc-msm8974.h
new file mode 100644
index 0000000..04d318d
--- /dev/null
+++ b/include/dt-bindings/clock/qcom,mmcc-msm8974.h
@@ -0,0 +1,161 @@
+/*
+ * Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef _DT_BINDINGS_CLK_MSM_MMCC_8974_H
+#define _DT_BINDINGS_CLK_MSM_MMCC_8974_H
+
+#define MMSS_AHB_CLK_SRC				0
+#define MMSS_AXI_CLK_SRC				1
+#define MMPLL0						2
+#define MMPLL0_VOTE					3
+#define MMPLL1						4
+#define MMPLL1_VOTE					5
+#define MMPLL2						6
+#define MMPLL3						7
+#define CSI0_CLK_SRC					8
+#define CSI1_CLK_SRC					9
+#define CSI2_CLK_SRC					10
+#define CSI3_CLK_SRC					11
+#define VFE0_CLK_SRC					12
+#define VFE1_CLK_SRC					13
+#define MDP_CLK_SRC					14
+#define GFX3D_CLK_SRC					15
+#define JPEG0_CLK_SRC					16
+#define JPEG1_CLK_SRC					17
+#define JPEG2_CLK_SRC					18
+#define PCLK0_CLK_SRC					19
+#define PCLK1_CLK_SRC					20
+#define VCODEC0_CLK_SRC					21
+#define CCI_CLK_SRC					22
+#define CAMSS_GP0_CLK_SRC				23
+#define CAMSS_GP1_CLK_SRC				24
+#define MCLK0_CLK_SRC					25
+#define MCLK1_CLK_SRC					26
+#define MCLK2_CLK_SRC					27
+#define MCLK3_CLK_SRC					28
+#define CSI0PHYTIMER_CLK_SRC				29
+#define CSI1PHYTIMER_CLK_SRC				30
+#define CSI2PHYTIMER_CLK_SRC				31
+#define CPP_CLK_SRC					32
+#define BYTE0_CLK_SRC					33
+#define BYTE1_CLK_SRC					34
+#define EDPAUX_CLK_SRC					35
+#define EDPLINK_CLK_SRC					36
+#define EDPPIXEL_CLK_SRC				37
+#define ESC0_CLK_SRC					38
+#define ESC1_CLK_SRC					39
+#define EXTPCLK_CLK_SRC					40
+#define HDMI_CLK_SRC					41
+#define VSYNC_CLK_SRC					42
+#define RBCPR_CLK_SRC					43
+#define CAMSS_CCI_CCI_AHB_CLK				44
+#define CAMSS_CCI_CCI_CLK				45
+#define CAMSS_CSI0_AHB_CLK				46
+#define CAMSS_CSI0_CLK					47
+#define CAMSS_CSI0PHY_CLK				48
+#define CAMSS_CSI0PIX_CLK				49
+#define CAMSS_CSI0RDI_CLK				50
+#define CAMSS_CSI1_AHB_CLK				51
+#define CAMSS_CSI1_CLK					52
+#define CAMSS_CSI1PHY_CLK				53
+#define CAMSS_CSI1PIX_CLK				54
+#define CAMSS_CSI1RDI_CLK				55
+#define CAMSS_CSI2_AHB_CLK				56
+#define CAMSS_CSI2_CLK					57
+#define CAMSS_CSI2PHY_CLK				58
+#define CAMSS_CSI2PIX_CLK				59
+#define CAMSS_CSI2RDI_CLK				60
+#define CAMSS_CSI3_AHB_CLK				61
+#define CAMSS_CSI3_CLK					62
+#define CAMSS_CSI3PHY_CLK				63
+#define CAMSS_CSI3PIX_CLK				64
+#define CAMSS_CSI3RDI_CLK				65
+#define CAMSS_CSI_VFE0_CLK				66
+#define CAMSS_CSI_VFE1_CLK				67
+#define CAMSS_GP0_CLK					68
+#define CAMSS_GP1_CLK					69
+#define CAMSS_ISPIF_AHB_CLK				70
+#define CAMSS_JPEG_JPEG0_CLK				71
+#define CAMSS_JPEG_JPEG1_CLK				72
+#define CAMSS_JPEG_JPEG2_CLK				73
+#define CAMSS_JPEG_JPEG_AHB_CLK				74
+#define CAMSS_JPEG_JPEG_AXI_CLK				75
+#define CAMSS_JPEG_JPEG_OCMEMNOC_CLK			76
+#define CAMSS_MCLK0_CLK					77
+#define CAMSS_MCLK1_CLK					78
+#define CAMSS_MCLK2_CLK					79
+#define CAMSS_MCLK3_CLK					80
+#define CAMSS_MICRO_AHB_CLK				81
+#define CAMSS_PHY0_CSI0PHYTIMER_CLK			82
+#define CAMSS_PHY1_CSI1PHYTIMER_CLK			83
+#define CAMSS_PHY2_CSI2PHYTIMER_CLK			84
+#define CAMSS_TOP_AHB_CLK				85
+#define CAMSS_VFE_CPP_AHB_CLK				86
+#define CAMSS_VFE_CPP_CLK				87
+#define CAMSS_VFE_VFE0_CLK				88
+#define CAMSS_VFE_VFE1_CLK				89
+#define CAMSS_VFE_VFE_AHB_CLK				90
+#define CAMSS_VFE_VFE_AXI_CLK				91
+#define CAMSS_VFE_VFE_OCMEMNOC_CLK			92
+#define MDSS_AHB_CLK					93
+#define MDSS_AXI_CLK					94
+#define MDSS_BYTE0_CLK					95
+#define MDSS_BYTE1_CLK					96
+#define MDSS_EDPAUX_CLK					97
+#define MDSS_EDPLINK_CLK				98
+#define MDSS_EDPPIXEL_CLK				99
+#define MDSS_ESC0_CLK					100
+#define MDSS_ESC1_CLK					101
+#define MDSS_EXTPCLK_CLK				102
+#define MDSS_HDMI_AHB_CLK				103
+#define MDSS_HDMI_CLK					104
+#define MDSS_MDP_CLK					105
+#define MDSS_MDP_LUT_CLK				106
+#define MDSS_PCLK0_CLK					107
+#define MDSS_PCLK1_CLK					108
+#define MDSS_VSYNC_CLK					109
+#define MMSS_MISC_AHB_CLK				110
+#define MMSS_MMSSNOC_AHB_CLK				111
+#define MMSS_MMSSNOC_BTO_AHB_CLK			112
+#define MMSS_MMSSNOC_AXI_CLK				113
+#define MMSS_S0_AXI_CLK					114
+#define OCMEMCX_AHB_CLK					115
+#define OCMEMCX_OCMEMNOC_CLK				116
+#define OXILI_OCMEMGX_CLK				117
+#define OCMEMNOC_CLK					118
+#define OXILI_GFX3D_CLK					119
+#define OXILICX_AHB_CLK					120
+#define OXILICX_AXI_CLK					121
+#define VENUS0_AHB_CLK					122
+#define VENUS0_AXI_CLK					123
+#define VENUS0_OCMEMNOC_CLK				124
+#define VENUS0_VCODEC0_CLK				125
+#define OCMEMNOC_CLK_SRC				126
+#define SPDM_JPEG0					127
+#define SPDM_JPEG1					128
+#define SPDM_MDP					129
+#define SPDM_AXI					130
+#define SPDM_VCODEC0					131
+#define SPDM_VFE0					132
+#define SPDM_VFE1					133
+#define SPDM_JPEG2					134
+#define SPDM_PCLK1					135
+#define SPDM_GFX3D					136
+#define SPDM_AHB					137
+#define SPDM_PCLK0					138
+#define SPDM_OCMEMNOC					139
+#define SPDM_CSI0					140
+#define SPDM_RM_AXI					141
+#define SPDM_RM_OCMEMNOC				142
+
+#endif
diff --git a/include/dt-bindings/reset/qcom,mmcc-msm8974.h b/include/dt-bindings/reset/qcom,mmcc-msm8974.h
new file mode 100644
index 0000000..da3ec37
--- /dev/null
+++ b/include/dt-bindings/reset/qcom,mmcc-msm8974.h
@@ -0,0 +1,62 @@
+/*
+ * Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef _DT_BINDINGS_RESET_MSM_MMCC_8974_H
+#define _DT_BINDINGS_RESET_MSM_MMCC_8974_H
+
+#define SPDM_RESET			0
+#define SPDM_RM_RESET			1
+#define VENUS0_RESET			2
+#define MDSS_RESET			3
+#define CAMSS_PHY0_RESET		4
+#define CAMSS_PHY1_RESET		5
+#define CAMSS_PHY2_RESET		6
+#define CAMSS_CSI0_RESET		7
+#define CAMSS_CSI0PHY_RESET		8
+#define CAMSS_CSI0RDI_RESET		9
+#define CAMSS_CSI0PIX_RESET		10
+#define CAMSS_CSI1_RESET		11
+#define CAMSS_CSI1PHY_RESET		12
+#define CAMSS_CSI1RDI_RESET		13
+#define CAMSS_CSI1PIX_RESET		14
+#define CAMSS_CSI2_RESET		15
+#define CAMSS_CSI2PHY_RESET		16
+#define CAMSS_CSI2RDI_RESET		17
+#define CAMSS_CSI2PIX_RESET		18
+#define CAMSS_CSI3_RESET		19
+#define CAMSS_CSI3PHY_RESET		20
+#define CAMSS_CSI3RDI_RESET		21
+#define CAMSS_CSI3PIX_RESET		22
+#define CAMSS_ISPIF_RESET		23
+#define CAMSS_CCI_RESET			24
+#define CAMSS_MCLK0_RESET		25
+#define CAMSS_MCLK1_RESET		26
+#define CAMSS_MCLK2_RESET		27
+#define CAMSS_MCLK3_RESET		28
+#define CAMSS_GP0_RESET			29
+#define CAMSS_GP1_RESET			30
+#define CAMSS_TOP_RESET			31
+#define CAMSS_MICRO_RESET		32
+#define CAMSS_JPEG_RESET		33
+#define CAMSS_VFE_RESET			34
+#define CAMSS_CSI_VFE0_RESET		35
+#define CAMSS_CSI_VFE1_RESET		36
+#define OXILI_RESET			37
+#define OXILICX_RESET			38
+#define OCMEMCX_RESET			39
+#define MMSS_RBCRP_RESET		40
+#define MMSSNOCAHB_RESET		41
+#define MMSSNOCAXI_RESET		42
+#define OCMEMNOC_RESET			43
+
+#endif
-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
hosted by The Linux Foundation

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

* [PATCH v4 13/15] clk: qcom: Add support for MSM8660's global clock controller (GCC)
  2013-12-24  1:12 [PATCH v4 00/15] Add support for MSM's mmio clock/reset controller Stephen Boyd
                   ` (11 preceding siblings ...)
  2013-12-24  1:12 ` [PATCH v4 12/15] clk: qcom: Add support for MSM8974's multimedia clock controller (MMCC) Stephen Boyd
@ 2013-12-24  1:12 ` Stephen Boyd
  2013-12-24  1:12 ` [PATCH v4 14/15] devicetree: bindings: Document qcom,gcc Stephen Boyd
  2013-12-24  1:12 ` [PATCH v4 15/15] devicetree: bindings: Document qcom,mmcc Stephen Boyd
  14 siblings, 0 replies; 34+ messages in thread
From: Stephen Boyd @ 2013-12-24  1:12 UTC (permalink / raw)
  To: Mike Turquette
  Cc: linux-kernel, linux-arm-msm, linux-arm-kernel, Saravana Kannan

Add a driver for the global clock controller found on MSM8660
based platforms. This should allow most non-multimedia device
drivers to probe and control their clocks.

Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
---
 drivers/clk/qcom/Kconfig                     |    8 +
 drivers/clk/qcom/Makefile                    |    1 +
 drivers/clk/qcom/gcc-msm8660.c               | 2818 ++++++++++++++++++++++++++
 include/dt-bindings/clock/qcom,gcc-msm8660.h |  276 +++
 include/dt-bindings/reset/qcom,gcc-msm8660.h |  134 ++
 5 files changed, 3237 insertions(+)
 create mode 100644 drivers/clk/qcom/gcc-msm8660.c
 create mode 100644 include/dt-bindings/clock/qcom,gcc-msm8660.h
 create mode 100644 include/dt-bindings/reset/qcom,gcc-msm8660.h

diff --git a/drivers/clk/qcom/Kconfig b/drivers/clk/qcom/Kconfig
index 7b582dd..995bcfa 100644
--- a/drivers/clk/qcom/Kconfig
+++ b/drivers/clk/qcom/Kconfig
@@ -4,6 +4,14 @@ config COMMON_CLK_QCOM
 	select REGMAP_MMIO
 	select RESET_CONTROLLER
 
+config MSM_GCC_8660
+	tristate "MSM8660 Global Clock Controller"
+	depends on COMMON_CLK_QCOM
+	help
+	  Support for the global clock controller on msm8660 devices.
+	  Say Y if you want to use peripheral devices such as UART, SPI,
+	  i2c, USB, SD/eMMC, etc.
+
 config MSM_GCC_8960
 	tristate "MSM8960 Global Clock Controller"
 	depends on COMMON_CLK_QCOM
diff --git a/drivers/clk/qcom/Makefile b/drivers/clk/qcom/Makefile
index d9480357..82bc40e 100644
--- a/drivers/clk/qcom/Makefile
+++ b/drivers/clk/qcom/Makefile
@@ -6,6 +6,7 @@ clk-qcom-$(CONFIG_COMMON_CLK_QCOM) += clk-rcg2.o
 clk-qcom-$(CONFIG_COMMON_CLK_QCOM) += clk-branch.o
 clk-qcom-$(CONFIG_COMMON_CLK_QCOM) += reset.o
 
+obj-$(CONFIG_MSM_GCC_8660) += gcc-msm8660.o
 obj-$(CONFIG_MSM_GCC_8960) += gcc-msm8960.o
 obj-$(CONFIG_MSM_GCC_8974) += gcc-msm8974.o
 obj-$(CONFIG_MSM_MMCC_8960) += mmcc-msm8960.o
diff --git a/drivers/clk/qcom/gcc-msm8660.c b/drivers/clk/qcom/gcc-msm8660.c
new file mode 100644
index 0000000..007d41a
--- /dev/null
+++ b/drivers/clk/qcom/gcc-msm8660.c
@@ -0,0 +1,2818 @@
+/*
+ * Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/kernel.h>
+#include <linux/bitops.h>
+#include <linux/err.h>
+#include <linux/platform_device.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/clk-provider.h>
+#include <linux/regmap.h>
+#include <linux/reset-controller.h>
+
+#include <dt-bindings/clock/qcom,gcc-msm8660.h>
+#include <dt-bindings/reset/qcom,gcc-msm8660.h>
+
+#include "clk-pll.h"
+#include "clk-rcg.h"
+#include "clk-branch.h"
+#include "reset.h"
+
+static struct clk_pll pll8 = {
+	.l_reg = 0x3144,
+	.m_reg = 0x3148,
+	.n_reg = 0x314c,
+	.config_reg = 0x3154,
+	.mode_reg = 0x3140,
+	.status_reg = 0x3158,
+	.status_bit = 16,
+	.hw.init = &(struct clk_init_data){
+		.name = "pll8",
+		.parent_names = (const char *[]){ "pxo" },
+		.num_parents = 1,
+		.ops = &clk_pll_ops,
+	},
+};
+
+static struct clk_hw pll8_vote = {
+	.enable_reg = 0x34c0,
+	.enable_mask = BIT(8),
+	.init = &(struct clk_init_data){
+		.name = "pll8_vote",
+		.parent_names = (const char *[]){ "pll8" },
+		.num_parents = 1,
+		.ops = &clk_pll_vote_ops,
+	},
+};
+
+#define P_PXO	0
+#define P_PLL8	1
+#define P_CXO	2
+
+static const u8 gcc_pxo_pll8_map[] = {
+	[P_PXO]		= 0,
+	[P_PLL8]	= 3,
+};
+
+static const char *gcc_pxo_pll8[] = {
+	"pxo",
+	"pll8_vote",
+};
+
+static const u8 gcc_pxo_pll8_cxo_map[] = {
+	[P_PXO]		= 0,
+	[P_PLL8]	= 3,
+	[P_CXO]		= 5,
+};
+
+static const char *gcc_pxo_pll8_cxo[] = {
+	"pxo",
+	"pll8_vote",
+	"cxo",
+};
+
+static struct freq_tbl clk_tbl_gsbi_uart[] = {
+	{  1843200, P_PLL8, 2,  6, 625 },
+	{  3686400, P_PLL8, 2, 12, 625 },
+	{  7372800, P_PLL8, 2, 24, 625 },
+	{ 14745600, P_PLL8, 2, 48, 625 },
+	{ 16000000, P_PLL8, 4,  1,   6 },
+	{ 24000000, P_PLL8, 4,  1,   4 },
+	{ 32000000, P_PLL8, 4,  1,   3 },
+	{ 40000000, P_PLL8, 1,  5,  48 },
+	{ 46400000, P_PLL8, 1, 29, 240 },
+	{ 48000000, P_PLL8, 4,  1,   2 },
+	{ 51200000, P_PLL8, 1,  2,  15 },
+	{ 56000000, P_PLL8, 1,  7,  48 },
+	{ 58982400, P_PLL8, 1, 96, 625 },
+	{ 64000000, P_PLL8, 2,  1,   3 },
+	{ }
+};
+
+static struct clk_rcg gsbi1_uart_src = {
+	.ns_reg = 0x29d4,
+	.md_reg = 0x29d0,
+	.mn = {
+		.mnctr_en_bit = 8,
+		.mnctr_reset_bit = 7,
+		.mnctr_mode_shift = 5,
+		.n_val_shift = 16,
+		.m_val_shift = 16,
+		.width = 16,
+	},
+	.p = {
+		.pre_div_shift = 3,
+		.pre_div_width = 2,
+	},
+	.s = {
+		.src_sel_shift = 0,
+		.parent_map = gcc_pxo_pll8_map,
+	},
+	.freq_tbl = clk_tbl_gsbi_uart,
+	.hw = {
+		.enable_reg = 0x29d4,
+		.enable_mask = BIT(11),
+		.init = &(struct clk_init_data){
+			.name = "gsbi1_uart_src",
+			.parent_names = gcc_pxo_pll8,
+			.num_parents = 2,
+			.ops = &clk_rcg_ops,
+			.flags = CLK_SET_PARENT_GATE,
+		},
+	},
+};
+
+static struct clk_branch gsbi1_uart_clk = {
+	.halt_reg = 0x2fcc,
+	.halt_bit = 10,
+	.hw = {
+		.enable_reg = 0x29d4,
+		.enable_mask = BIT(9),
+		.init = &(struct clk_init_data){
+			.name = "gsbi1_uart_clk",
+			.parent_names = (const char *[]){
+				"gsbi1_uart_src",
+			},
+			.num_parents = 1,
+			.ops = &clk_branch_ops,
+			.flags = CLK_SET_RATE_PARENT,
+		},
+	},
+};
+
+static struct clk_rcg gsbi2_uart_src = {
+	.ns_reg = 0x29f4,
+	.md_reg = 0x29f0,
+	.mn = {
+		.mnctr_en_bit = 8,
+		.mnctr_reset_bit = 7,
+		.mnctr_mode_shift = 5,
+		.n_val_shift = 16,
+		.m_val_shift = 16,
+		.width = 16,
+	},
+	.p = {
+		.pre_div_shift = 3,
+		.pre_div_width = 2,
+	},
+	.s = {
+		.src_sel_shift = 0,
+		.parent_map = gcc_pxo_pll8_map,
+	},
+	.freq_tbl = clk_tbl_gsbi_uart,
+	.hw = {
+		.enable_reg = 0x29f4,
+		.enable_mask = BIT(11),
+		.init = &(struct clk_init_data){
+			.name = "gsbi2_uart_src",
+			.parent_names = gcc_pxo_pll8,
+			.num_parents = 2,
+			.ops = &clk_rcg_ops,
+			.flags = CLK_SET_PARENT_GATE,
+		},
+	},
+};
+
+static struct clk_branch gsbi2_uart_clk = {
+	.halt_reg = 0x2fcc,
+	.halt_bit = 6,
+	.hw = {
+		.enable_reg = 0x29f4,
+		.enable_mask = BIT(9),
+		.init = &(struct clk_init_data){
+			.name = "gsbi2_uart_clk",
+			.parent_names = (const char *[]){
+				"gsbi2_uart_src",
+			},
+			.num_parents = 1,
+			.ops = &clk_branch_ops,
+			.flags = CLK_SET_RATE_PARENT,
+		},
+	},
+};
+
+static struct clk_rcg gsbi3_uart_src = {
+	.ns_reg = 0x2a14,
+	.md_reg = 0x2a10,
+	.mn = {
+		.mnctr_en_bit = 8,
+		.mnctr_reset_bit = 7,
+		.mnctr_mode_shift = 5,
+		.n_val_shift = 16,
+		.m_val_shift = 16,
+		.width = 16,
+	},
+	.p = {
+		.pre_div_shift = 3,
+		.pre_div_width = 2,
+	},
+	.s = {
+		.src_sel_shift = 0,
+		.parent_map = gcc_pxo_pll8_map,
+	},
+	.freq_tbl = clk_tbl_gsbi_uart,
+	.hw = {
+		.enable_reg = 0x2a14,
+		.enable_mask = BIT(11),
+		.init = &(struct clk_init_data){
+			.name = "gsbi3_uart_src",
+			.parent_names = gcc_pxo_pll8,
+			.num_parents = 2,
+			.ops = &clk_rcg_ops,
+			.flags = CLK_SET_PARENT_GATE,
+		},
+	},
+};
+
+static struct clk_branch gsbi3_uart_clk = {
+	.halt_reg = 0x2fcc,
+	.halt_bit = 2,
+	.hw = {
+		.enable_reg = 0x2a14,
+		.enable_mask = BIT(9),
+		.init = &(struct clk_init_data){
+			.name = "gsbi3_uart_clk",
+			.parent_names = (const char *[]){
+				"gsbi3_uart_src",
+			},
+			.num_parents = 1,
+			.ops = &clk_branch_ops,
+			.flags = CLK_SET_RATE_PARENT,
+		},
+	},
+};
+
+static struct clk_rcg gsbi4_uart_src = {
+	.ns_reg = 0x2a34,
+	.md_reg = 0x2a30,
+	.mn = {
+		.mnctr_en_bit = 8,
+		.mnctr_reset_bit = 7,
+		.mnctr_mode_shift = 5,
+		.n_val_shift = 16,
+		.m_val_shift = 16,
+		.width = 16,
+	},
+	.p = {
+		.pre_div_shift = 3,
+		.pre_div_width = 2,
+	},
+	.s = {
+		.src_sel_shift = 0,
+		.parent_map = gcc_pxo_pll8_map,
+	},
+	.freq_tbl = clk_tbl_gsbi_uart,
+	.hw = {
+		.enable_reg = 0x2a34,
+		.enable_mask = BIT(11),
+		.init = &(struct clk_init_data){
+			.name = "gsbi4_uart_src",
+			.parent_names = gcc_pxo_pll8,
+			.num_parents = 2,
+			.ops = &clk_rcg_ops,
+			.flags = CLK_SET_PARENT_GATE,
+		},
+	},
+};
+
+static struct clk_branch gsbi4_uart_clk = {
+	.halt_reg = 0x2fd0,
+	.halt_bit = 26,
+	.hw = {
+		.enable_reg = 0x2a34,
+		.enable_mask = BIT(9),
+		.init = &(struct clk_init_data){
+			.name = "gsbi4_uart_clk",
+			.parent_names = (const char *[]){
+				"gsbi4_uart_src",
+			},
+			.num_parents = 1,
+			.ops = &clk_branch_ops,
+			.flags = CLK_SET_RATE_PARENT,
+		},
+	},
+};
+
+static struct clk_rcg gsbi5_uart_src = {
+	.ns_reg = 0x2a54,
+	.md_reg = 0x2a50,
+	.mn = {
+		.mnctr_en_bit = 8,
+		.mnctr_reset_bit = 7,
+		.mnctr_mode_shift = 5,
+		.n_val_shift = 16,
+		.m_val_shift = 16,
+		.width = 16,
+	},
+	.p = {
+		.pre_div_shift = 3,
+		.pre_div_width = 2,
+	},
+	.s = {
+		.src_sel_shift = 0,
+		.parent_map = gcc_pxo_pll8_map,
+	},
+	.freq_tbl = clk_tbl_gsbi_uart,
+	.hw = {
+		.enable_reg = 0x2a54,
+		.enable_mask = BIT(11),
+		.init = &(struct clk_init_data){
+			.name = "gsbi5_uart_src",
+			.parent_names = gcc_pxo_pll8,
+			.num_parents = 2,
+			.ops = &clk_rcg_ops,
+			.flags = CLK_SET_PARENT_GATE,
+		},
+	},
+};
+
+static struct clk_branch gsbi5_uart_clk = {
+	.halt_reg = 0x2fd0,
+	.halt_bit = 22,
+	.hw = {
+		.enable_reg = 0x2a54,
+		.enable_mask = BIT(9),
+		.init = &(struct clk_init_data){
+			.name = "gsbi5_uart_clk",
+			.parent_names = (const char *[]){
+				"gsbi5_uart_src",
+			},
+			.num_parents = 1,
+			.ops = &clk_branch_ops,
+			.flags = CLK_SET_RATE_PARENT,
+		},
+	},
+};
+
+static struct clk_rcg gsbi6_uart_src = {
+	.ns_reg = 0x2a74,
+	.md_reg = 0x2a70,
+	.mn = {
+		.mnctr_en_bit = 8,
+		.mnctr_reset_bit = 7,
+		.mnctr_mode_shift = 5,
+		.n_val_shift = 16,
+		.m_val_shift = 16,
+		.width = 16,
+	},
+	.p = {
+		.pre_div_shift = 3,
+		.pre_div_width = 2,
+	},
+	.s = {
+		.src_sel_shift = 0,
+		.parent_map = gcc_pxo_pll8_map,
+	},
+	.freq_tbl = clk_tbl_gsbi_uart,
+	.hw = {
+		.enable_reg = 0x2a74,
+		.enable_mask = BIT(11),
+		.init = &(struct clk_init_data){
+			.name = "gsbi6_uart_src",
+			.parent_names = gcc_pxo_pll8,
+			.num_parents = 2,
+			.ops = &clk_rcg_ops,
+			.flags = CLK_SET_PARENT_GATE,
+		},
+	},
+};
+
+static struct clk_branch gsbi6_uart_clk = {
+	.halt_reg = 0x2fd0,
+	.halt_bit = 18,
+	.hw = {
+		.enable_reg = 0x2a74,
+		.enable_mask = BIT(9),
+		.init = &(struct clk_init_data){
+			.name = "gsbi6_uart_clk",
+			.parent_names = (const char *[]){
+				"gsbi6_uart_src",
+			},
+			.num_parents = 1,
+			.ops = &clk_branch_ops,
+			.flags = CLK_SET_RATE_PARENT,
+		},
+	},
+};
+
+static struct clk_rcg gsbi7_uart_src = {
+	.ns_reg = 0x2a94,
+	.md_reg = 0x2a90,
+	.mn = {
+		.mnctr_en_bit = 8,
+		.mnctr_reset_bit = 7,
+		.mnctr_mode_shift = 5,
+		.n_val_shift = 16,
+		.m_val_shift = 16,
+		.width = 16,
+	},
+	.p = {
+		.pre_div_shift = 3,
+		.pre_div_width = 2,
+	},
+	.s = {
+		.src_sel_shift = 0,
+		.parent_map = gcc_pxo_pll8_map,
+	},
+	.freq_tbl = clk_tbl_gsbi_uart,
+	.hw = {
+		.enable_reg = 0x2a94,
+		.enable_mask = BIT(11),
+		.init = &(struct clk_init_data){
+			.name = "gsbi7_uart_src",
+			.parent_names = gcc_pxo_pll8,
+			.num_parents = 2,
+			.ops = &clk_rcg_ops,
+			.flags = CLK_SET_PARENT_GATE,
+		},
+	},
+};
+
+static struct clk_branch gsbi7_uart_clk = {
+	.halt_reg = 0x2fd0,
+	.halt_bit = 14,
+	.hw = {
+		.enable_reg = 0x2a94,
+		.enable_mask = BIT(9),
+		.init = &(struct clk_init_data){
+			.name = "gsbi7_uart_clk",
+			.parent_names = (const char *[]){
+				"gsbi7_uart_src",
+			},
+			.num_parents = 1,
+			.ops = &clk_branch_ops,
+			.flags = CLK_SET_RATE_PARENT,
+		},
+	},
+};
+
+static struct clk_rcg gsbi8_uart_src = {
+	.ns_reg = 0x2ab4,
+	.md_reg = 0x2ab0,
+	.mn = {
+		.mnctr_en_bit = 8,
+		.mnctr_reset_bit = 7,
+		.mnctr_mode_shift = 5,
+		.n_val_shift = 16,
+		.m_val_shift = 16,
+		.width = 16,
+	},
+	.p = {
+		.pre_div_shift = 3,
+		.pre_div_width = 2,
+	},
+	.s = {
+		.src_sel_shift = 0,
+		.parent_map = gcc_pxo_pll8_map,
+	},
+	.freq_tbl = clk_tbl_gsbi_uart,
+	.hw = {
+		.enable_reg = 0x2ab4,
+		.enable_mask = BIT(11),
+		.init = &(struct clk_init_data){
+			.name = "gsbi8_uart_src",
+			.parent_names = gcc_pxo_pll8,
+			.num_parents = 2,
+			.ops = &clk_rcg_ops,
+			.flags = CLK_SET_PARENT_GATE,
+		},
+	},
+};
+
+static struct clk_branch gsbi8_uart_clk = {
+	.halt_reg = 0x2fd0,
+	.halt_bit = 10,
+	.hw = {
+		.enable_reg = 0x2ab4,
+		.enable_mask = BIT(9),
+		.init = &(struct clk_init_data){
+			.name = "gsbi8_uart_clk",
+			.parent_names = (const char *[]){ "gsbi8_uart_src" },
+			.num_parents = 1,
+			.ops = &clk_branch_ops,
+			.flags = CLK_SET_RATE_PARENT,
+		},
+	},
+};
+
+static struct clk_rcg gsbi9_uart_src = {
+	.ns_reg = 0x2ad4,
+	.md_reg = 0x2ad0,
+	.mn = {
+		.mnctr_en_bit = 8,
+		.mnctr_reset_bit = 7,
+		.mnctr_mode_shift = 5,
+		.n_val_shift = 16,
+		.m_val_shift = 16,
+		.width = 16,
+	},
+	.p = {
+		.pre_div_shift = 3,
+		.pre_div_width = 2,
+	},
+	.s = {
+		.src_sel_shift = 0,
+		.parent_map = gcc_pxo_pll8_map,
+	},
+	.freq_tbl = clk_tbl_gsbi_uart,
+	.hw = {
+		.enable_reg = 0x2ad4,
+		.enable_mask = BIT(11),
+		.init = &(struct clk_init_data){
+			.name = "gsbi9_uart_src",
+			.parent_names = gcc_pxo_pll8,
+			.num_parents = 2,
+			.ops = &clk_rcg_ops,
+			.flags = CLK_SET_PARENT_GATE,
+		},
+	},
+};
+
+static struct clk_branch gsbi9_uart_clk = {
+	.halt_reg = 0x2fd0,
+	.halt_bit = 6,
+	.hw = {
+		.enable_reg = 0x2ad4,
+		.enable_mask = BIT(9),
+		.init = &(struct clk_init_data){
+			.name = "gsbi9_uart_clk",
+			.parent_names = (const char *[]){ "gsbi9_uart_src" },
+			.num_parents = 1,
+			.ops = &clk_branch_ops,
+			.flags = CLK_SET_RATE_PARENT,
+		},
+	},
+};
+
+static struct clk_rcg gsbi10_uart_src = {
+	.ns_reg = 0x2af4,
+	.md_reg = 0x2af0,
+	.mn = {
+		.mnctr_en_bit = 8,
+		.mnctr_reset_bit = 7,
+		.mnctr_mode_shift = 5,
+		.n_val_shift = 16,
+		.m_val_shift = 16,
+		.width = 16,
+	},
+	.p = {
+		.pre_div_shift = 3,
+		.pre_div_width = 2,
+	},
+	.s = {
+		.src_sel_shift = 0,
+		.parent_map = gcc_pxo_pll8_map,
+	},
+	.freq_tbl = clk_tbl_gsbi_uart,
+	.hw = {
+		.enable_reg = 0x2af4,
+		.enable_mask = BIT(11),
+		.init = &(struct clk_init_data){
+			.name = "gsbi10_uart_src",
+			.parent_names = gcc_pxo_pll8,
+			.num_parents = 2,
+			.ops = &clk_rcg_ops,
+			.flags = CLK_SET_PARENT_GATE,
+		},
+	},
+};
+
+static struct clk_branch gsbi10_uart_clk = {
+	.halt_reg = 0x2fd0,
+	.halt_bit = 2,
+	.hw = {
+		.enable_reg = 0x2af4,
+		.enable_mask = BIT(9),
+		.init = &(struct clk_init_data){
+			.name = "gsbi10_uart_clk",
+			.parent_names = (const char *[]){ "gsbi10_uart_src" },
+			.num_parents = 1,
+			.ops = &clk_branch_ops,
+			.flags = CLK_SET_RATE_PARENT,
+		},
+	},
+};
+
+static struct clk_rcg gsbi11_uart_src = {
+	.ns_reg = 0x2b14,
+	.md_reg = 0x2b10,
+	.mn = {
+		.mnctr_en_bit = 8,
+		.mnctr_reset_bit = 7,
+		.mnctr_mode_shift = 5,
+		.n_val_shift = 16,
+		.m_val_shift = 16,
+		.width = 16,
+	},
+	.p = {
+		.pre_div_shift = 3,
+		.pre_div_width = 2,
+	},
+	.s = {
+		.src_sel_shift = 0,
+		.parent_map = gcc_pxo_pll8_map,
+	},
+	.freq_tbl = clk_tbl_gsbi_uart,
+	.hw = {
+		.enable_reg = 0x2b14,
+		.enable_mask = BIT(11),
+		.init = &(struct clk_init_data){
+			.name = "gsbi11_uart_src",
+			.parent_names = gcc_pxo_pll8,
+			.num_parents = 2,
+			.ops = &clk_rcg_ops,
+			.flags = CLK_SET_PARENT_GATE,
+		},
+	},
+};
+
+static struct clk_branch gsbi11_uart_clk = {
+	.halt_reg = 0x2fd4,
+	.halt_bit = 17,
+	.hw = {
+		.enable_reg = 0x2b14,
+		.enable_mask = BIT(9),
+		.init = &(struct clk_init_data){
+			.name = "gsbi11_uart_clk",
+			.parent_names = (const char *[]){ "gsbi11_uart_src" },
+			.num_parents = 1,
+			.ops = &clk_branch_ops,
+			.flags = CLK_SET_RATE_PARENT,
+		},
+	},
+};
+
+static struct clk_rcg gsbi12_uart_src = {
+	.ns_reg = 0x2b34,
+	.md_reg = 0x2b30,
+	.mn = {
+		.mnctr_en_bit = 8,
+		.mnctr_reset_bit = 7,
+		.mnctr_mode_shift = 5,
+		.n_val_shift = 16,
+		.m_val_shift = 16,
+		.width = 16,
+	},
+	.p = {
+		.pre_div_shift = 3,
+		.pre_div_width = 2,
+	},
+	.s = {
+		.src_sel_shift = 0,
+		.parent_map = gcc_pxo_pll8_map,
+	},
+	.freq_tbl = clk_tbl_gsbi_uart,
+	.hw = {
+		.enable_reg = 0x2b34,
+		.enable_mask = BIT(11),
+		.init = &(struct clk_init_data){
+			.name = "gsbi12_uart_src",
+			.parent_names = gcc_pxo_pll8,
+			.num_parents = 2,
+			.ops = &clk_rcg_ops,
+			.flags = CLK_SET_PARENT_GATE,
+		},
+	},
+};
+
+static struct clk_branch gsbi12_uart_clk = {
+	.halt_reg = 0x2fd4,
+	.halt_bit = 13,
+	.hw = {
+		.enable_reg = 0x2b34,
+		.enable_mask = BIT(9),
+		.init = &(struct clk_init_data){
+			.name = "gsbi12_uart_clk",
+			.parent_names = (const char *[]){ "gsbi12_uart_src" },
+			.num_parents = 1,
+			.ops = &clk_branch_ops,
+			.flags = CLK_SET_RATE_PARENT,
+		},
+	},
+};
+
+static struct freq_tbl clk_tbl_gsbi_qup[] = {
+	{  1100000, P_PXO,  1, 2, 49 },
+	{  5400000, P_PXO,  1, 1,  5 },
+	{ 10800000, P_PXO,  1, 2,  5 },
+	{ 15060000, P_PLL8, 1, 2, 51 },
+	{ 24000000, P_PLL8, 4, 1,  4 },
+	{ 25600000, P_PLL8, 1, 1, 15 },
+	{ 27000000, P_PXO,  1, 0,  0 },
+	{ 48000000, P_PLL8, 4, 1,  2 },
+	{ 51200000, P_PLL8, 1, 2, 15 },
+	{ }
+};
+
+static struct clk_rcg gsbi1_qup_src = {
+	.ns_reg = 0x29cc,
+	.md_reg = 0x29c8,
+	.mn = {
+		.mnctr_en_bit = 8,
+		.mnctr_reset_bit = 7,
+		.mnctr_mode_shift = 5,
+		.n_val_shift = 16,
+		.m_val_shift = 16,
+		.width = 8,
+	},
+	.p = {
+		.pre_div_shift = 3,
+		.pre_div_width = 2,
+	},
+	.s = {
+		.src_sel_shift = 0,
+		.parent_map = gcc_pxo_pll8_map,
+	},
+	.freq_tbl = clk_tbl_gsbi_qup,
+	.hw = {
+		.enable_reg = 0x29cc,
+		.enable_mask = BIT(11),
+		.init = &(struct clk_init_data){
+			.name = "gsbi1_qup_src",
+			.parent_names = gcc_pxo_pll8,
+			.num_parents = 2,
+			.ops = &clk_rcg_ops,
+			.flags = CLK_SET_PARENT_GATE,
+		},
+	},
+};
+
+static struct clk_branch gsbi1_qup_clk = {
+	.halt_reg = 0x2fcc,
+	.halt_bit = 9,
+	.hw = {
+		.enable_reg = 0x29cc,
+		.enable_mask = BIT(9),
+		.init = &(struct clk_init_data){
+			.name = "gsbi1_qup_clk",
+			.parent_names = (const char *[]){ "gsbi1_qup_src" },
+			.num_parents = 1,
+			.ops = &clk_branch_ops,
+			.flags = CLK_SET_RATE_PARENT,
+		},
+	},
+};
+
+static struct clk_rcg gsbi2_qup_src = {
+	.ns_reg = 0x29ec,
+	.md_reg = 0x29e8,
+	.mn = {
+		.mnctr_en_bit = 8,
+		.mnctr_reset_bit = 7,
+		.mnctr_mode_shift = 5,
+		.n_val_shift = 16,
+		.m_val_shift = 16,
+		.width = 8,
+	},
+	.p = {
+		.pre_div_shift = 3,
+		.pre_div_width = 2,
+	},
+	.s = {
+		.src_sel_shift = 0,
+		.parent_map = gcc_pxo_pll8_map,
+	},
+	.freq_tbl = clk_tbl_gsbi_qup,
+	.hw = {
+		.enable_reg = 0x29ec,
+		.enable_mask = BIT(11),
+		.init = &(struct clk_init_data){
+			.name = "gsbi2_qup_src",
+			.parent_names = gcc_pxo_pll8,
+			.num_parents = 2,
+			.ops = &clk_rcg_ops,
+			.flags = CLK_SET_PARENT_GATE,
+		},
+	},
+};
+
+static struct clk_branch gsbi2_qup_clk = {
+	.halt_reg = 0x2fcc,
+	.halt_bit = 4,
+	.hw = {
+		.enable_reg = 0x29ec,
+		.enable_mask = BIT(9),
+		.init = &(struct clk_init_data){
+			.name = "gsbi2_qup_clk",
+			.parent_names = (const char *[]){ "gsbi2_qup_src" },
+			.num_parents = 1,
+			.ops = &clk_branch_ops,
+			.flags = CLK_SET_RATE_PARENT,
+		},
+	},
+};
+
+static struct clk_rcg gsbi3_qup_src = {
+	.ns_reg = 0x2a0c,
+	.md_reg = 0x2a08,
+	.mn = {
+		.mnctr_en_bit = 8,
+		.mnctr_reset_bit = 7,
+		.mnctr_mode_shift = 5,
+		.n_val_shift = 16,
+		.m_val_shift = 16,
+		.width = 8,
+	},
+	.p = {
+		.pre_div_shift = 3,
+		.pre_div_width = 2,
+	},
+	.s = {
+		.src_sel_shift = 0,
+		.parent_map = gcc_pxo_pll8_map,
+	},
+	.freq_tbl = clk_tbl_gsbi_qup,
+	.hw = {
+		.enable_reg = 0x2a0c,
+		.enable_mask = BIT(11),
+		.init = &(struct clk_init_data){
+			.name = "gsbi3_qup_src",
+			.parent_names = gcc_pxo_pll8,
+			.num_parents = 2,
+			.ops = &clk_rcg_ops,
+			.flags = CLK_SET_PARENT_GATE,
+		},
+	},
+};
+
+static struct clk_branch gsbi3_qup_clk = {
+	.halt_reg = 0x2fcc,
+	.halt_bit = 0,
+	.hw = {
+		.enable_reg = 0x2a0c,
+		.enable_mask = BIT(9),
+		.init = &(struct clk_init_data){
+			.name = "gsbi3_qup_clk",
+			.parent_names = (const char *[]){ "gsbi3_qup_src" },
+			.num_parents = 1,
+			.ops = &clk_branch_ops,
+			.flags = CLK_SET_RATE_PARENT,
+		},
+	},
+};
+
+static struct clk_rcg gsbi4_qup_src = {
+	.ns_reg = 0x2a2c,
+	.md_reg = 0x2a28,
+	.mn = {
+		.mnctr_en_bit = 8,
+		.mnctr_reset_bit = 7,
+		.mnctr_mode_shift = 5,
+		.n_val_shift = 16,
+		.m_val_shift = 16,
+		.width = 8,
+	},
+	.p = {
+		.pre_div_shift = 3,
+		.pre_div_width = 2,
+	},
+	.s = {
+		.src_sel_shift = 0,
+		.parent_map = gcc_pxo_pll8_map,
+	},
+	.freq_tbl = clk_tbl_gsbi_qup,
+	.hw = {
+		.enable_reg = 0x2a2c,
+		.enable_mask = BIT(11),
+		.init = &(struct clk_init_data){
+			.name = "gsbi4_qup_src",
+			.parent_names = gcc_pxo_pll8,
+			.num_parents = 2,
+			.ops = &clk_rcg_ops,
+			.flags = CLK_SET_PARENT_GATE,
+		},
+	},
+};
+
+static struct clk_branch gsbi4_qup_clk = {
+	.halt_reg = 0x2fd0,
+	.halt_bit = 24,
+	.hw = {
+		.enable_reg = 0x2a2c,
+		.enable_mask = BIT(9),
+		.init = &(struct clk_init_data){
+			.name = "gsbi4_qup_clk",
+			.parent_names = (const char *[]){ "gsbi4_qup_src" },
+			.num_parents = 1,
+			.ops = &clk_branch_ops,
+			.flags = CLK_SET_RATE_PARENT,
+		},
+	},
+};
+
+static struct clk_rcg gsbi5_qup_src = {
+	.ns_reg = 0x2a4c,
+	.md_reg = 0x2a48,
+	.mn = {
+		.mnctr_en_bit = 8,
+		.mnctr_reset_bit = 7,
+		.mnctr_mode_shift = 5,
+		.n_val_shift = 16,
+		.m_val_shift = 16,
+		.width = 8,
+	},
+	.p = {
+		.pre_div_shift = 3,
+		.pre_div_width = 2,
+	},
+	.s = {
+		.src_sel_shift = 0,
+		.parent_map = gcc_pxo_pll8_map,
+	},
+	.freq_tbl = clk_tbl_gsbi_qup,
+	.hw = {
+		.enable_reg = 0x2a4c,
+		.enable_mask = BIT(11),
+		.init = &(struct clk_init_data){
+			.name = "gsbi5_qup_src",
+			.parent_names = gcc_pxo_pll8,
+			.num_parents = 2,
+			.ops = &clk_rcg_ops,
+			.flags = CLK_SET_PARENT_GATE,
+		},
+	},
+};
+
+static struct clk_branch gsbi5_qup_clk = {
+	.halt_reg = 0x2fd0,
+	.halt_bit = 20,
+	.hw = {
+		.enable_reg = 0x2a4c,
+		.enable_mask = BIT(9),
+		.init = &(struct clk_init_data){
+			.name = "gsbi5_qup_clk",
+			.parent_names = (const char *[]){ "gsbi5_qup_src" },
+			.num_parents = 1,
+			.ops = &clk_branch_ops,
+			.flags = CLK_SET_RATE_PARENT,
+		},
+	},
+};
+
+static struct clk_rcg gsbi6_qup_src = {
+	.ns_reg = 0x2a6c,
+	.md_reg = 0x2a68,
+	.mn = {
+		.mnctr_en_bit = 8,
+		.mnctr_reset_bit = 7,
+		.mnctr_mode_shift = 5,
+		.n_val_shift = 16,
+		.m_val_shift = 16,
+		.width = 8,
+	},
+	.p = {
+		.pre_div_shift = 3,
+		.pre_div_width = 2,
+	},
+	.s = {
+		.src_sel_shift = 0,
+		.parent_map = gcc_pxo_pll8_map,
+	},
+	.freq_tbl = clk_tbl_gsbi_qup,
+	.hw = {
+		.enable_reg = 0x2a6c,
+		.enable_mask = BIT(11),
+		.init = &(struct clk_init_data){
+			.name = "gsbi6_qup_src",
+			.parent_names = gcc_pxo_pll8,
+			.num_parents = 2,
+			.ops = &clk_rcg_ops,
+			.flags = CLK_SET_PARENT_GATE,
+		},
+	},
+};
+
+static struct clk_branch gsbi6_qup_clk = {
+	.halt_reg = 0x2fd0,
+	.halt_bit = 16,
+	.hw = {
+		.enable_reg = 0x2a6c,
+		.enable_mask = BIT(9),
+		.init = &(struct clk_init_data){
+			.name = "gsbi6_qup_clk",
+			.parent_names = (const char *[]){ "gsbi6_qup_src" },
+			.num_parents = 1,
+			.ops = &clk_branch_ops,
+			.flags = CLK_SET_RATE_PARENT,
+		},
+	},
+};
+
+static struct clk_rcg gsbi7_qup_src = {
+	.ns_reg = 0x2a8c,
+	.md_reg = 0x2a88,
+	.mn = {
+		.mnctr_en_bit = 8,
+		.mnctr_reset_bit = 7,
+		.mnctr_mode_shift = 5,
+		.n_val_shift = 16,
+		.m_val_shift = 16,
+		.width = 8,
+	},
+	.p = {
+		.pre_div_shift = 3,
+		.pre_div_width = 2,
+	},
+	.s = {
+		.src_sel_shift = 0,
+		.parent_map = gcc_pxo_pll8_map,
+	},
+	.freq_tbl = clk_tbl_gsbi_qup,
+	.hw = {
+		.enable_reg = 0x2a8c,
+		.enable_mask = BIT(11),
+		.init = &(struct clk_init_data){
+			.name = "gsbi7_qup_src",
+			.parent_names = gcc_pxo_pll8,
+			.num_parents = 2,
+			.ops = &clk_rcg_ops,
+			.flags = CLK_SET_PARENT_GATE,
+		},
+	},
+};
+
+static struct clk_branch gsbi7_qup_clk = {
+	.halt_reg = 0x2fd0,
+	.halt_bit = 12,
+	.hw = {
+		.enable_reg = 0x2a8c,
+		.enable_mask = BIT(9),
+		.init = &(struct clk_init_data){
+			.name = "gsbi7_qup_clk",
+			.parent_names = (const char *[]){ "gsbi7_qup_src" },
+			.num_parents = 1,
+			.ops = &clk_branch_ops,
+			.flags = CLK_SET_RATE_PARENT,
+		},
+	},
+};
+
+static struct clk_rcg gsbi8_qup_src = {
+	.ns_reg = 0x2aac,
+	.md_reg = 0x2aa8,
+	.mn = {
+		.mnctr_en_bit = 8,
+		.mnctr_reset_bit = 7,
+		.mnctr_mode_shift = 5,
+		.n_val_shift = 16,
+		.m_val_shift = 16,
+		.width = 8,
+	},
+	.p = {
+		.pre_div_shift = 3,
+		.pre_div_width = 2,
+	},
+	.s = {
+		.src_sel_shift = 0,
+		.parent_map = gcc_pxo_pll8_map,
+	},
+	.freq_tbl = clk_tbl_gsbi_qup,
+	.hw = {
+		.enable_reg = 0x2aac,
+		.enable_mask = BIT(11),
+		.init = &(struct clk_init_data){
+			.name = "gsbi8_qup_src",
+			.parent_names = gcc_pxo_pll8,
+			.num_parents = 2,
+			.ops = &clk_rcg_ops,
+			.flags = CLK_SET_PARENT_GATE,
+		},
+	},
+};
+
+static struct clk_branch gsbi8_qup_clk = {
+	.halt_reg = 0x2fd0,
+	.halt_bit = 8,
+	.hw = {
+		.enable_reg = 0x2aac,
+		.enable_mask = BIT(9),
+		.init = &(struct clk_init_data){
+			.name = "gsbi8_qup_clk",
+			.parent_names = (const char *[]){ "gsbi8_qup_src" },
+			.num_parents = 1,
+			.ops = &clk_branch_ops,
+			.flags = CLK_SET_RATE_PARENT,
+		},
+	},
+};
+
+static struct clk_rcg gsbi9_qup_src = {
+	.ns_reg = 0x2acc,
+	.md_reg = 0x2ac8,
+	.mn = {
+		.mnctr_en_bit = 8,
+		.mnctr_reset_bit = 7,
+		.mnctr_mode_shift = 5,
+		.n_val_shift = 16,
+		.m_val_shift = 16,
+		.width = 8,
+	},
+	.p = {
+		.pre_div_shift = 3,
+		.pre_div_width = 2,
+	},
+	.s = {
+		.src_sel_shift = 0,
+		.parent_map = gcc_pxo_pll8_map,
+	},
+	.freq_tbl = clk_tbl_gsbi_qup,
+	.hw = {
+		.enable_reg = 0x2acc,
+		.enable_mask = BIT(11),
+		.init = &(struct clk_init_data){
+			.name = "gsbi9_qup_src",
+			.parent_names = gcc_pxo_pll8,
+			.num_parents = 2,
+			.ops = &clk_rcg_ops,
+			.flags = CLK_SET_PARENT_GATE,
+		},
+	},
+};
+
+static struct clk_branch gsbi9_qup_clk = {
+	.halt_reg = 0x2fd0,
+	.halt_bit = 4,
+	.hw = {
+		.enable_reg = 0x2acc,
+		.enable_mask = BIT(9),
+		.init = &(struct clk_init_data){
+			.name = "gsbi9_qup_clk",
+			.parent_names = (const char *[]){ "gsbi9_qup_src" },
+			.num_parents = 1,
+			.ops = &clk_branch_ops,
+			.flags = CLK_SET_RATE_PARENT,
+		},
+	},
+};
+
+static struct clk_rcg gsbi10_qup_src = {
+	.ns_reg = 0x2aec,
+	.md_reg = 0x2ae8,
+	.mn = {
+		.mnctr_en_bit = 8,
+		.mnctr_reset_bit = 7,
+		.mnctr_mode_shift = 5,
+		.n_val_shift = 16,
+		.m_val_shift = 16,
+		.width = 8,
+	},
+	.p = {
+		.pre_div_shift = 3,
+		.pre_div_width = 2,
+	},
+	.s = {
+		.src_sel_shift = 0,
+		.parent_map = gcc_pxo_pll8_map,
+	},
+	.freq_tbl = clk_tbl_gsbi_qup,
+	.hw = {
+		.enable_reg = 0x2aec,
+		.enable_mask = BIT(11),
+		.init = &(struct clk_init_data){
+			.name = "gsbi10_qup_src",
+			.parent_names = gcc_pxo_pll8,
+			.num_parents = 2,
+			.ops = &clk_rcg_ops,
+			.flags = CLK_SET_PARENT_GATE,
+		},
+	},
+};
+
+static struct clk_branch gsbi10_qup_clk = {
+	.halt_reg = 0x2fd0,
+	.halt_bit = 0,
+	.hw = {
+		.enable_reg = 0x2aec,
+		.enable_mask = BIT(9),
+		.init = &(struct clk_init_data){
+			.name = "gsbi10_qup_clk",
+			.parent_names = (const char *[]){ "gsbi10_qup_src" },
+			.num_parents = 1,
+			.ops = &clk_branch_ops,
+			.flags = CLK_SET_RATE_PARENT,
+		},
+	},
+};
+
+static struct clk_rcg gsbi11_qup_src = {
+	.ns_reg = 0x2b0c,
+	.md_reg = 0x2b08,
+	.mn = {
+		.mnctr_en_bit = 8,
+		.mnctr_reset_bit = 7,
+		.mnctr_mode_shift = 5,
+		.n_val_shift = 16,
+		.m_val_shift = 16,
+		.width = 8,
+	},
+	.p = {
+		.pre_div_shift = 3,
+		.pre_div_width = 2,
+	},
+	.s = {
+		.src_sel_shift = 0,
+		.parent_map = gcc_pxo_pll8_map,
+	},
+	.freq_tbl = clk_tbl_gsbi_qup,
+	.hw = {
+		.enable_reg = 0x2b0c,
+		.enable_mask = BIT(11),
+		.init = &(struct clk_init_data){
+			.name = "gsbi11_qup_src",
+			.parent_names = gcc_pxo_pll8,
+			.num_parents = 2,
+			.ops = &clk_rcg_ops,
+			.flags = CLK_SET_PARENT_GATE,
+		},
+	},
+};
+
+static struct clk_branch gsbi11_qup_clk = {
+	.halt_reg = 0x2fd4,
+	.halt_bit = 15,
+	.hw = {
+		.enable_reg = 0x2b0c,
+		.enable_mask = BIT(9),
+		.init = &(struct clk_init_data){
+			.name = "gsbi11_qup_clk",
+			.parent_names = (const char *[]){ "gsbi11_qup_src" },
+			.num_parents = 1,
+			.ops = &clk_branch_ops,
+			.flags = CLK_SET_RATE_PARENT,
+		},
+	},
+};
+
+static struct clk_rcg gsbi12_qup_src = {
+	.ns_reg = 0x2b2c,
+	.md_reg = 0x2b28,
+	.mn = {
+		.mnctr_en_bit = 8,
+		.mnctr_reset_bit = 7,
+		.mnctr_mode_shift = 5,
+		.n_val_shift = 16,
+		.m_val_shift = 16,
+		.width = 8,
+	},
+	.p = {
+		.pre_div_shift = 3,
+		.pre_div_width = 2,
+	},
+	.s = {
+		.src_sel_shift = 0,
+		.parent_map = gcc_pxo_pll8_map,
+	},
+	.freq_tbl = clk_tbl_gsbi_qup,
+	.hw = {
+		.enable_reg = 0x2b2c,
+		.enable_mask = BIT(11),
+		.init = &(struct clk_init_data){
+			.name = "gsbi12_qup_src",
+			.parent_names = gcc_pxo_pll8,
+			.num_parents = 2,
+			.ops = &clk_rcg_ops,
+			.flags = CLK_SET_PARENT_GATE,
+		},
+	},
+};
+
+static struct clk_branch gsbi12_qup_clk = {
+	.halt_reg = 0x2fd4,
+	.halt_bit = 11,
+	.hw = {
+		.enable_reg = 0x2b2c,
+		.enable_mask = BIT(9),
+		.init = &(struct clk_init_data){
+			.name = "gsbi12_qup_clk",
+			.parent_names = (const char *[]){ "gsbi12_qup_src" },
+			.num_parents = 1,
+			.ops = &clk_branch_ops,
+			.flags = CLK_SET_RATE_PARENT,
+		},
+	},
+};
+
+static const struct freq_tbl clk_tbl_gp[] = {
+	{ 9600000, P_CXO,  2, 0, 0 },
+	{ 13500000, P_PXO,  2, 0, 0 },
+	{ 19200000, P_CXO,  1, 0, 0 },
+	{ 27000000, P_PXO,  1, 0, 0 },
+	{ 64000000, P_PLL8, 2, 1, 3 },
+	{ 76800000, P_PLL8, 1, 1, 5 },
+	{ 96000000, P_PLL8, 4, 0, 0 },
+	{ 128000000, P_PLL8, 3, 0, 0 },
+	{ 192000000, P_PLL8, 2, 0, 0 },
+	{ }
+};
+
+static struct clk_rcg gp0_src = {
+	.ns_reg = 0x2d24,
+	.md_reg = 0x2d00,
+	.mn = {
+		.mnctr_en_bit = 8,
+		.mnctr_reset_bit = 7,
+		.mnctr_mode_shift = 5,
+		.n_val_shift = 16,
+		.m_val_shift = 16,
+		.width = 8,
+	},
+	.p = {
+		.pre_div_shift = 3,
+		.pre_div_width = 2,
+	},
+	.s = {
+		.src_sel_shift = 0,
+		.parent_map = gcc_pxo_pll8_cxo_map,
+	},
+	.freq_tbl = clk_tbl_gp,
+	.hw = {
+		.enable_reg = 0x2d24,
+		.enable_mask = BIT(11),
+		.init = &(struct clk_init_data){
+			.name = "gp0_src",
+			.parent_names = gcc_pxo_pll8_cxo,
+			.num_parents = 3,
+			.ops = &clk_rcg_ops,
+			.flags = CLK_SET_PARENT_GATE,
+		},
+	}
+};
+
+static struct clk_branch gp0_clk = {
+	.halt_reg = 0x2fd8,
+	.halt_bit = 7,
+	.hw = {
+		.enable_reg = 0x2d24,
+		.enable_mask = BIT(9),
+		.init = &(struct clk_init_data){
+			.name = "gp0_clk",
+			.parent_names = (const char *[]){ "gp0_src" },
+			.num_parents = 1,
+			.ops = &clk_branch_ops,
+			.flags = CLK_SET_RATE_PARENT,
+		},
+	},
+};
+
+static struct clk_rcg gp1_src = {
+	.ns_reg = 0x2d44,
+	.md_reg = 0x2d40,
+	.mn = {
+		.mnctr_en_bit = 8,
+		.mnctr_reset_bit = 7,
+		.mnctr_mode_shift = 5,
+		.n_val_shift = 16,
+		.m_val_shift = 16,
+		.width = 8,
+	},
+	.p = {
+		.pre_div_shift = 3,
+		.pre_div_width = 2,
+	},
+	.s = {
+		.src_sel_shift = 0,
+		.parent_map = gcc_pxo_pll8_cxo_map,
+	},
+	.freq_tbl = clk_tbl_gp,
+	.hw = {
+		.enable_reg = 0x2d44,
+		.enable_mask = BIT(11),
+		.init = &(struct clk_init_data){
+			.name = "gp1_src",
+			.parent_names = gcc_pxo_pll8_cxo,
+			.num_parents = 3,
+			.ops = &clk_rcg_ops,
+			.flags = CLK_SET_RATE_GATE,
+		},
+	}
+};
+
+static struct clk_branch gp1_clk = {
+	.halt_reg = 0x2fd8,
+	.halt_bit = 6,
+	.hw = {
+		.enable_reg = 0x2d44,
+		.enable_mask = BIT(9),
+		.init = &(struct clk_init_data){
+			.name = "gp1_clk",
+			.parent_names = (const char *[]){ "gp1_src" },
+			.num_parents = 1,
+			.ops = &clk_branch_ops,
+			.flags = CLK_SET_RATE_PARENT,
+		},
+	},
+};
+
+static struct clk_rcg gp2_src = {
+	.ns_reg = 0x2d64,
+	.md_reg = 0x2d60,
+	.mn = {
+		.mnctr_en_bit = 8,
+		.mnctr_reset_bit = 7,
+		.mnctr_mode_shift = 5,
+		.n_val_shift = 16,
+		.m_val_shift = 16,
+		.width = 8,
+	},
+	.p = {
+		.pre_div_shift = 3,
+		.pre_div_width = 2,
+	},
+	.s = {
+		.src_sel_shift = 0,
+		.parent_map = gcc_pxo_pll8_cxo_map,
+	},
+	.freq_tbl = clk_tbl_gp,
+	.hw = {
+		.enable_reg = 0x2d64,
+		.enable_mask = BIT(11),
+		.init = &(struct clk_init_data){
+			.name = "gp2_src",
+			.parent_names = gcc_pxo_pll8_cxo,
+			.num_parents = 3,
+			.ops = &clk_rcg_ops,
+			.flags = CLK_SET_RATE_GATE,
+		},
+	}
+};
+
+static struct clk_branch gp2_clk = {
+	.halt_reg = 0x2fd8,
+	.halt_bit = 5,
+	.hw = {
+		.enable_reg = 0x2d64,
+		.enable_mask = BIT(9),
+		.init = &(struct clk_init_data){
+			.name = "gp2_clk",
+			.parent_names = (const char *[]){ "gp2_src" },
+			.num_parents = 1,
+			.ops = &clk_branch_ops,
+			.flags = CLK_SET_RATE_PARENT,
+		},
+	},
+};
+
+static struct clk_branch pmem_clk = {
+	.hwcg_reg = 0x25a0,
+	.hwcg_bit = 6,
+	.halt_reg = 0x2fc8,
+	.halt_bit = 20,
+	.hw = {
+		.enable_reg = 0x25a0,
+		.enable_mask = BIT(4),
+		.init = &(struct clk_init_data){
+			.name = "pmem_clk",
+			.ops = &clk_branch_ops,
+			.flags = CLK_IS_ROOT,
+		},
+	},
+};
+
+static struct clk_rcg prng_src = {
+	.ns_reg = 0x2e80,
+	.p = {
+		.pre_div_shift = 3,
+		.pre_div_width = 4,
+	},
+	.s = {
+		.src_sel_shift = 0,
+		.parent_map = gcc_pxo_pll8_map,
+	},
+	.hw = {
+		.init = &(struct clk_init_data){
+			.name = "prng_src",
+			.parent_names = gcc_pxo_pll8,
+			.num_parents = 2,
+			.ops = &clk_rcg_ops,
+		},
+	},
+};
+
+static struct clk_branch prng_clk = {
+	.halt_reg = 0x2fd8,
+	.halt_check = BRANCH_HALT_VOTED,
+	.halt_bit = 10,
+	.hw = {
+		.enable_reg = 0x3080,
+		.enable_mask = BIT(10),
+		.init = &(struct clk_init_data){
+			.name = "prng_clk",
+			.parent_names = (const char *[]){ "prng_src" },
+			.num_parents = 1,
+			.ops = &clk_branch_ops,
+		},
+	},
+};
+
+static const struct freq_tbl clk_tbl_sdc[] = {
+	{    144000, P_PXO,   3, 2, 125 },
+	{    400000, P_PLL8,  4, 1, 240 },
+	{  16000000, P_PLL8,  4, 1,   6 },
+	{  17070000, P_PLL8,  1, 2,  45 },
+	{  20210000, P_PLL8,  1, 1,  19 },
+	{  24000000, P_PLL8,  4, 1,   4 },
+	{  48000000, P_PLL8,  4, 1,   2 },
+	{ }
+};
+
+static struct clk_rcg sdc1_src = {
+	.ns_reg = 0x282c,
+	.md_reg = 0x2828,
+	.mn = {
+		.mnctr_en_bit = 8,
+		.mnctr_reset_bit = 7,
+		.mnctr_mode_shift = 5,
+		.n_val_shift = 16,
+		.m_val_shift = 16,
+		.width = 8,
+	},
+	.p = {
+		.pre_div_shift = 3,
+		.pre_div_width = 2,
+	},
+	.s = {
+		.src_sel_shift = 0,
+		.parent_map = gcc_pxo_pll8_map,
+	},
+	.freq_tbl = clk_tbl_sdc,
+	.hw = {
+		.enable_reg = 0x282c,
+		.enable_mask = BIT(11),
+		.init = &(struct clk_init_data){
+			.name = "sdc1_src",
+			.parent_names = gcc_pxo_pll8,
+			.num_parents = 2,
+			.ops = &clk_rcg_ops,
+			.flags = CLK_SET_RATE_GATE,
+		},
+	}
+};
+
+static struct clk_branch sdc1_clk = {
+	.halt_reg = 0x2fc8,
+	.halt_bit = 6,
+	.hw = {
+		.enable_reg = 0x282c,
+		.enable_mask = BIT(9),
+		.init = &(struct clk_init_data){
+			.name = "sdc1_clk",
+			.parent_names = (const char *[]){ "sdc1_src" },
+			.num_parents = 1,
+			.ops = &clk_branch_ops,
+			.flags = CLK_SET_RATE_PARENT,
+		},
+	},
+};
+
+static struct clk_rcg sdc2_src = {
+	.ns_reg = 0x284c,
+	.md_reg = 0x2848,
+	.mn = {
+		.mnctr_en_bit = 8,
+		.mnctr_reset_bit = 7,
+		.mnctr_mode_shift = 5,
+		.n_val_shift = 16,
+		.m_val_shift = 16,
+		.width = 8,
+	},
+	.p = {
+		.pre_div_shift = 3,
+		.pre_div_width = 2,
+	},
+	.s = {
+		.src_sel_shift = 0,
+		.parent_map = gcc_pxo_pll8_map,
+	},
+	.freq_tbl = clk_tbl_sdc,
+	.hw = {
+		.enable_reg = 0x284c,
+		.enable_mask = BIT(11),
+		.init = &(struct clk_init_data){
+			.name = "sdc2_src",
+			.parent_names = gcc_pxo_pll8,
+			.num_parents = 2,
+			.ops = &clk_rcg_ops,
+			.flags = CLK_SET_RATE_GATE,
+		},
+	}
+};
+
+static struct clk_branch sdc2_clk = {
+	.halt_reg = 0x2fc8,
+	.halt_bit = 5,
+	.hw = {
+		.enable_reg = 0x284c,
+		.enable_mask = BIT(9),
+		.init = &(struct clk_init_data){
+			.name = "sdc2_clk",
+			.parent_names = (const char *[]){ "sdc2_src" },
+			.num_parents = 1,
+			.ops = &clk_branch_ops,
+			.flags = CLK_SET_RATE_PARENT,
+		},
+	},
+};
+
+static struct clk_rcg sdc3_src = {
+	.ns_reg = 0x286c,
+	.md_reg = 0x2868,
+	.mn = {
+		.mnctr_en_bit = 8,
+		.mnctr_reset_bit = 7,
+		.mnctr_mode_shift = 5,
+		.n_val_shift = 16,
+		.m_val_shift = 16,
+		.width = 8,
+	},
+	.p = {
+		.pre_div_shift = 3,
+		.pre_div_width = 2,
+	},
+	.s = {
+		.src_sel_shift = 0,
+		.parent_map = gcc_pxo_pll8_map,
+	},
+	.freq_tbl = clk_tbl_sdc,
+	.hw = {
+		.enable_reg = 0x286c,
+		.enable_mask = BIT(11),
+		.init = &(struct clk_init_data){
+			.name = "sdc3_src",
+			.parent_names = gcc_pxo_pll8,
+			.num_parents = 2,
+			.ops = &clk_rcg_ops,
+			.flags = CLK_SET_RATE_GATE,
+		},
+	}
+};
+
+static struct clk_branch sdc3_clk = {
+	.halt_reg = 0x2fc8,
+	.halt_bit = 4,
+	.hw = {
+		.enable_reg = 0x286c,
+		.enable_mask = BIT(9),
+		.init = &(struct clk_init_data){
+			.name = "sdc3_clk",
+			.parent_names = (const char *[]){ "sdc3_src" },
+			.num_parents = 1,
+			.ops = &clk_branch_ops,
+			.flags = CLK_SET_RATE_PARENT,
+		},
+	},
+};
+
+static struct clk_rcg sdc4_src = {
+	.ns_reg = 0x288c,
+	.md_reg = 0x2888,
+	.mn = {
+		.mnctr_en_bit = 8,
+		.mnctr_reset_bit = 7,
+		.mnctr_mode_shift = 5,
+		.n_val_shift = 16,
+		.m_val_shift = 16,
+		.width = 8,
+	},
+	.p = {
+		.pre_div_shift = 3,
+		.pre_div_width = 2,
+	},
+	.s = {
+		.src_sel_shift = 0,
+		.parent_map = gcc_pxo_pll8_map,
+	},
+	.freq_tbl = clk_tbl_sdc,
+	.hw = {
+		.enable_reg = 0x288c,
+		.enable_mask = BIT(11),
+		.init = &(struct clk_init_data){
+			.name = "sdc4_src",
+			.parent_names = gcc_pxo_pll8,
+			.num_parents = 2,
+			.ops = &clk_rcg_ops,
+			.flags = CLK_SET_RATE_GATE,
+		},
+	}
+};
+
+static struct clk_branch sdc4_clk = {
+	.halt_reg = 0x2fc8,
+	.halt_bit = 3,
+	.hw = {
+		.enable_reg = 0x288c,
+		.enable_mask = BIT(9),
+		.init = &(struct clk_init_data){
+			.name = "sdc4_clk",
+			.parent_names = (const char *[]){ "sdc4_src" },
+			.num_parents = 1,
+			.ops = &clk_branch_ops,
+			.flags = CLK_SET_RATE_PARENT,
+		},
+	},
+};
+
+static struct clk_rcg sdc5_src = {
+	.ns_reg = 0x28ac,
+	.md_reg = 0x28a8,
+	.mn = {
+		.mnctr_en_bit = 8,
+		.mnctr_reset_bit = 7,
+		.mnctr_mode_shift = 5,
+		.n_val_shift = 16,
+		.m_val_shift = 16,
+		.width = 8,
+	},
+	.p = {
+		.pre_div_shift = 3,
+		.pre_div_width = 2,
+	},
+	.s = {
+		.src_sel_shift = 0,
+		.parent_map = gcc_pxo_pll8_map,
+	},
+	.freq_tbl = clk_tbl_sdc,
+	.hw = {
+		.enable_reg = 0x28ac,
+		.enable_mask = BIT(11),
+		.init = &(struct clk_init_data){
+			.name = "sdc5_src",
+			.parent_names = gcc_pxo_pll8,
+			.num_parents = 2,
+			.ops = &clk_rcg_ops,
+			.flags = CLK_SET_RATE_GATE,
+		},
+	}
+};
+
+static struct clk_branch sdc5_clk = {
+	.halt_reg = 0x2fc8,
+	.halt_bit = 2,
+	.hw = {
+		.enable_reg = 0x28ac,
+		.enable_mask = BIT(9),
+		.init = &(struct clk_init_data){
+			.name = "sdc5_clk",
+			.parent_names = (const char *[]){ "sdc5_src" },
+			.num_parents = 1,
+			.ops = &clk_branch_ops,
+			.flags = CLK_SET_RATE_PARENT,
+		},
+	},
+};
+
+static const struct freq_tbl clk_tbl_tsif_ref[] = {
+	{ 105000, P_PXO,  1, 1, 256 },
+	{ }
+};
+
+static struct clk_rcg tsif_ref_src = {
+	.ns_reg = 0x2710,
+	.md_reg = 0x270c,
+	.mn = {
+		.mnctr_en_bit = 8,
+		.mnctr_reset_bit = 7,
+		.mnctr_mode_shift = 5,
+		.n_val_shift = 16,
+		.m_val_shift = 16,
+		.width = 16,
+	},
+	.p = {
+		.pre_div_shift = 3,
+		.pre_div_width = 2,
+	},
+	.s = {
+		.src_sel_shift = 0,
+		.parent_map = gcc_pxo_pll8_map,
+	},
+	.freq_tbl = clk_tbl_tsif_ref,
+	.hw = {
+		.enable_reg = 0x2710,
+		.enable_mask = BIT(11),
+		.init = &(struct clk_init_data){
+			.name = "tsif_ref_src",
+			.parent_names = gcc_pxo_pll8,
+			.num_parents = 2,
+			.ops = &clk_rcg_ops,
+			.flags = CLK_SET_RATE_GATE,
+		},
+	}
+};
+
+static struct clk_branch tsif_ref_clk = {
+	.halt_reg = 0x2fd4,
+	.halt_bit = 5,
+	.hw = {
+		.enable_reg = 0x2710,
+		.enable_mask = BIT(9),
+		.init = &(struct clk_init_data){
+			.name = "tsif_ref_clk",
+			.parent_names = (const char *[]){ "tsif_ref_src" },
+			.num_parents = 1,
+			.ops = &clk_branch_ops,
+			.flags = CLK_SET_RATE_PARENT,
+		},
+	},
+};
+
+static const struct freq_tbl clk_tbl_usb[] = {
+	{ 60000000, P_PLL8, 1, 5, 32 },
+	{ }
+};
+
+static struct clk_rcg usb_hs1_xcvr_src = {
+	.ns_reg = 0x290c,
+	.md_reg = 0x2908,
+	.mn = {
+		.mnctr_en_bit = 8,
+		.mnctr_reset_bit = 7,
+		.mnctr_mode_shift = 5,
+		.n_val_shift = 16,
+		.m_val_shift = 16,
+		.width = 8,
+	},
+	.p = {
+		.pre_div_shift = 3,
+		.pre_div_width = 2,
+	},
+	.s = {
+		.src_sel_shift = 0,
+		.parent_map = gcc_pxo_pll8_map,
+	},
+	.freq_tbl = clk_tbl_usb,
+	.hw = {
+		.enable_reg = 0x290c,
+		.enable_mask = BIT(11),
+		.init = &(struct clk_init_data){
+			.name = "usb_hs1_xcvr_src",
+			.parent_names = gcc_pxo_pll8,
+			.num_parents = 2,
+			.ops = &clk_rcg_ops,
+			.flags = CLK_SET_RATE_GATE,
+		},
+	}
+};
+
+static struct clk_branch usb_hs1_xcvr_clk = {
+	.halt_reg = 0x2fc8,
+	.halt_bit = 0,
+	.hw = {
+		.enable_reg = 0x290c,
+		.enable_mask = BIT(9),
+		.init = &(struct clk_init_data){
+			.name = "usb_hs1_xcvr_clk",
+			.parent_names = (const char *[]){ "usb_hs1_xcvr_src" },
+			.num_parents = 1,
+			.ops = &clk_branch_ops,
+			.flags = CLK_SET_RATE_PARENT,
+		},
+	},
+};
+
+static struct clk_rcg usb_fs1_xcvr_fs_src = {
+	.ns_reg = 0x2968,
+	.md_reg = 0x2964,
+	.mn = {
+		.mnctr_en_bit = 8,
+		.mnctr_reset_bit = 7,
+		.mnctr_mode_shift = 5,
+		.n_val_shift = 16,
+		.m_val_shift = 16,
+		.width = 8,
+	},
+	.p = {
+		.pre_div_shift = 3,
+		.pre_div_width = 2,
+	},
+	.s = {
+		.src_sel_shift = 0,
+		.parent_map = gcc_pxo_pll8_map,
+	},
+	.freq_tbl = clk_tbl_usb,
+	.hw = {
+		.enable_reg = 0x2968,
+		.enable_mask = BIT(11),
+		.init = &(struct clk_init_data){
+			.name = "usb_fs1_xcvr_fs_src",
+			.parent_names = gcc_pxo_pll8,
+			.num_parents = 2,
+			.ops = &clk_rcg_ops,
+			.flags = CLK_SET_RATE_GATE,
+		},
+	}
+};
+
+static const char *usb_fs1_xcvr_fs_src_p[] = { "usb_fs1_xcvr_fs_src" };
+
+static struct clk_branch usb_fs1_xcvr_fs_clk = {
+	.halt_reg = 0x2fcc,
+	.halt_bit = 15,
+	.hw = {
+		.enable_reg = 0x2968,
+		.enable_mask = BIT(9),
+		.init = &(struct clk_init_data){
+			.name = "usb_fs1_xcvr_fs_clk",
+			.parent_names = usb_fs1_xcvr_fs_src_p,
+			.num_parents = 1,
+			.ops = &clk_branch_ops,
+			.flags = CLK_SET_RATE_PARENT,
+		},
+	},
+};
+
+static struct clk_branch usb_fs1_system_clk = {
+	.halt_reg = 0x2fcc,
+	.halt_bit = 16,
+	.hw = {
+		.enable_reg = 0x296c,
+		.enable_mask = BIT(4),
+		.init = &(struct clk_init_data){
+			.parent_names = usb_fs1_xcvr_fs_src_p,
+			.num_parents = 1,
+			.name = "usb_fs1_system_clk",
+			.ops = &clk_branch_ops,
+			.flags = CLK_SET_RATE_PARENT,
+		},
+	},
+};
+
+static struct clk_rcg usb_fs2_xcvr_fs_src = {
+	.ns_reg = 0x2988,
+	.md_reg = 0x2984,
+	.mn = {
+		.mnctr_en_bit = 8,
+		.mnctr_reset_bit = 7,
+		.mnctr_mode_shift = 5,
+		.n_val_shift = 16,
+		.m_val_shift = 16,
+		.width = 8,
+	},
+	.p = {
+		.pre_div_shift = 3,
+		.pre_div_width = 2,
+	},
+	.s = {
+		.src_sel_shift = 0,
+		.parent_map = gcc_pxo_pll8_map,
+	},
+	.freq_tbl = clk_tbl_usb,
+	.hw = {
+		.enable_reg = 0x2988,
+		.enable_mask = BIT(11),
+		.init = &(struct clk_init_data){
+			.name = "usb_fs2_xcvr_fs_src",
+			.parent_names = gcc_pxo_pll8,
+			.num_parents = 2,
+			.ops = &clk_rcg_ops,
+			.flags = CLK_SET_RATE_GATE,
+		},
+	}
+};
+
+static const char *usb_fs2_xcvr_fs_src_p[] = { "usb_fs2_xcvr_fs_src" };
+
+static struct clk_branch usb_fs2_xcvr_fs_clk = {
+	.halt_reg = 0x2fcc,
+	.halt_bit = 12,
+	.hw = {
+		.enable_reg = 0x2988,
+		.enable_mask = BIT(9),
+		.init = &(struct clk_init_data){
+			.name = "usb_fs2_xcvr_fs_clk",
+			.parent_names = usb_fs2_xcvr_fs_src_p,
+			.num_parents = 1,
+			.ops = &clk_branch_ops,
+			.flags = CLK_SET_RATE_PARENT,
+		},
+	},
+};
+
+static struct clk_branch usb_fs2_system_clk = {
+	.halt_reg = 0x2fcc,
+	.halt_bit = 13,
+	.hw = {
+		.enable_reg = 0x298c,
+		.enable_mask = BIT(4),
+		.init = &(struct clk_init_data){
+			.name = "usb_fs2_system_clk",
+			.parent_names = usb_fs2_xcvr_fs_src_p,
+			.num_parents = 1,
+			.ops = &clk_branch_ops,
+			.flags = CLK_SET_RATE_PARENT,
+		},
+	},
+};
+
+static struct clk_branch gsbi1_h_clk = {
+	.halt_reg = 0x2fcc,
+	.halt_bit = 11,
+	.hw = {
+		.enable_reg = 0x29c0,
+		.enable_mask = BIT(4),
+		.init = &(struct clk_init_data){
+			.name = "gsbi1_h_clk",
+			.ops = &clk_branch_ops,
+			.flags = CLK_IS_ROOT,
+		},
+	},
+};
+
+static struct clk_branch gsbi2_h_clk = {
+	.halt_reg = 0x2fcc,
+	.halt_bit = 7,
+	.hw = {
+		.enable_reg = 0x29e0,
+		.enable_mask = BIT(4),
+		.init = &(struct clk_init_data){
+			.name = "gsbi2_h_clk",
+			.ops = &clk_branch_ops,
+			.flags = CLK_IS_ROOT,
+		},
+	},
+};
+
+static struct clk_branch gsbi3_h_clk = {
+	.halt_reg = 0x2fcc,
+	.halt_bit = 3,
+	.hw = {
+		.enable_reg = 0x2a00,
+		.enable_mask = BIT(4),
+		.init = &(struct clk_init_data){
+			.name = "gsbi3_h_clk",
+			.ops = &clk_branch_ops,
+			.flags = CLK_IS_ROOT,
+		},
+	},
+};
+
+static struct clk_branch gsbi4_h_clk = {
+	.halt_reg = 0x2fd0,
+	.halt_bit = 27,
+	.hw = {
+		.enable_reg = 0x2a20,
+		.enable_mask = BIT(4),
+		.init = &(struct clk_init_data){
+			.name = "gsbi4_h_clk",
+			.ops = &clk_branch_ops,
+			.flags = CLK_IS_ROOT,
+		},
+	},
+};
+
+static struct clk_branch gsbi5_h_clk = {
+	.halt_reg = 0x2fd0,
+	.halt_bit = 23,
+	.hw = {
+		.enable_reg = 0x2a40,
+		.enable_mask = BIT(4),
+		.init = &(struct clk_init_data){
+			.name = "gsbi5_h_clk",
+			.ops = &clk_branch_ops,
+			.flags = CLK_IS_ROOT,
+		},
+	},
+};
+
+static struct clk_branch gsbi6_h_clk = {
+	.halt_reg = 0x2fd0,
+	.halt_bit = 19,
+	.hw = {
+		.enable_reg = 0x2a60,
+		.enable_mask = BIT(4),
+		.init = &(struct clk_init_data){
+			.name = "gsbi6_h_clk",
+			.ops = &clk_branch_ops,
+			.flags = CLK_IS_ROOT,
+		},
+	},
+};
+
+static struct clk_branch gsbi7_h_clk = {
+	.halt_reg = 0x2fd0,
+	.halt_bit = 15,
+	.hw = {
+		.enable_reg = 0x2a80,
+		.enable_mask = BIT(4),
+		.init = &(struct clk_init_data){
+			.name = "gsbi7_h_clk",
+			.ops = &clk_branch_ops,
+			.flags = CLK_IS_ROOT,
+		},
+	},
+};
+
+static struct clk_branch gsbi8_h_clk = {
+	.halt_reg = 0x2fd0,
+	.halt_bit = 11,
+	.hw = {
+		.enable_reg = 0x2aa0,
+		.enable_mask = BIT(4),
+		.init = &(struct clk_init_data){
+			.name = "gsbi8_h_clk",
+			.ops = &clk_branch_ops,
+			.flags = CLK_IS_ROOT,
+		},
+	},
+};
+
+static struct clk_branch gsbi9_h_clk = {
+	.halt_reg = 0x2fd0,
+	.halt_bit = 7,
+	.hw = {
+		.enable_reg = 0x2ac0,
+		.enable_mask = BIT(4),
+		.init = &(struct clk_init_data){
+			.name = "gsbi9_h_clk",
+			.ops = &clk_branch_ops,
+			.flags = CLK_IS_ROOT,
+		},
+	},
+};
+
+static struct clk_branch gsbi10_h_clk = {
+	.halt_reg = 0x2fd0,
+	.halt_bit = 3,
+	.hw = {
+		.enable_reg = 0x2ae0,
+		.enable_mask = BIT(4),
+		.init = &(struct clk_init_data){
+			.name = "gsbi10_h_clk",
+			.ops = &clk_branch_ops,
+			.flags = CLK_IS_ROOT,
+		},
+	},
+};
+
+static struct clk_branch gsbi11_h_clk = {
+	.halt_reg = 0x2fd4,
+	.halt_bit = 18,
+	.hw = {
+		.enable_reg = 0x2b00,
+		.enable_mask = BIT(4),
+		.init = &(struct clk_init_data){
+			.name = "gsbi11_h_clk",
+			.ops = &clk_branch_ops,
+			.flags = CLK_IS_ROOT,
+		},
+	},
+};
+
+static struct clk_branch gsbi12_h_clk = {
+	.halt_reg = 0x2fd4,
+	.halt_bit = 14,
+	.hw = {
+		.enable_reg = 0x2b20,
+		.enable_mask = BIT(4),
+		.init = &(struct clk_init_data){
+			.name = "gsbi12_h_clk",
+			.ops = &clk_branch_ops,
+			.flags = CLK_IS_ROOT,
+		},
+	},
+};
+
+static struct clk_branch tsif_h_clk = {
+	.halt_reg = 0x2fd4,
+	.halt_bit = 7,
+	.hw = {
+		.enable_reg = 0x2700,
+		.enable_mask = BIT(4),
+		.init = &(struct clk_init_data){
+			.name = "tsif_h_clk",
+			.ops = &clk_branch_ops,
+			.flags = CLK_IS_ROOT,
+		},
+	},
+};
+
+static struct clk_branch usb_fs1_h_clk = {
+	.halt_reg = 0x2fcc,
+	.halt_bit = 17,
+	.hw = {
+		.enable_reg = 0x2960,
+		.enable_mask = BIT(4),
+		.init = &(struct clk_init_data){
+			.name = "usb_fs1_h_clk",
+			.ops = &clk_branch_ops,
+			.flags = CLK_IS_ROOT,
+		},
+	},
+};
+
+static struct clk_branch usb_fs2_h_clk = {
+	.halt_reg = 0x2fcc,
+	.halt_bit = 14,
+	.hw = {
+		.enable_reg = 0x2980,
+		.enable_mask = BIT(4),
+		.init = &(struct clk_init_data){
+			.name = "usb_fs2_h_clk",
+			.ops = &clk_branch_ops,
+			.flags = CLK_IS_ROOT,
+		},
+	},
+};
+
+static struct clk_branch usb_hs1_h_clk = {
+	.halt_reg = 0x2fc8,
+	.halt_bit = 1,
+	.hw = {
+		.enable_reg = 0x2900,
+		.enable_mask = BIT(4),
+		.init = &(struct clk_init_data){
+			.name = "usb_hs1_h_clk",
+			.ops = &clk_branch_ops,
+			.flags = CLK_IS_ROOT,
+		},
+	},
+};
+
+static struct clk_branch sdc1_h_clk = {
+	.halt_reg = 0x2fc8,
+	.halt_bit = 11,
+	.hw = {
+		.enable_reg = 0x2820,
+		.enable_mask = BIT(4),
+		.init = &(struct clk_init_data){
+			.name = "sdc1_h_clk",
+			.ops = &clk_branch_ops,
+			.flags = CLK_IS_ROOT,
+		},
+	},
+};
+
+static struct clk_branch sdc2_h_clk = {
+	.halt_reg = 0x2fc8,
+	.halt_bit = 10,
+	.hw = {
+		.enable_reg = 0x2840,
+		.enable_mask = BIT(4),
+		.init = &(struct clk_init_data){
+			.name = "sdc2_h_clk",
+			.ops = &clk_branch_ops,
+			.flags = CLK_IS_ROOT,
+		},
+	},
+};
+
+static struct clk_branch sdc3_h_clk = {
+	.halt_reg = 0x2fc8,
+	.halt_bit = 9,
+	.hw = {
+		.enable_reg = 0x2860,
+		.enable_mask = BIT(4),
+		.init = &(struct clk_init_data){
+			.name = "sdc3_h_clk",
+			.ops = &clk_branch_ops,
+			.flags = CLK_IS_ROOT,
+		},
+	},
+};
+
+static struct clk_branch sdc4_h_clk = {
+	.halt_reg = 0x2fc8,
+	.halt_bit = 8,
+	.hw = {
+		.enable_reg = 0x2880,
+		.enable_mask = BIT(4),
+		.init = &(struct clk_init_data){
+			.name = "sdc4_h_clk",
+			.ops = &clk_branch_ops,
+			.flags = CLK_IS_ROOT,
+		},
+	},
+};
+
+static struct clk_branch sdc5_h_clk = {
+	.halt_reg = 0x2fc8,
+	.halt_bit = 7,
+	.hw = {
+		.enable_reg = 0x28a0,
+		.enable_mask = BIT(4),
+		.init = &(struct clk_init_data){
+			.name = "sdc5_h_clk",
+			.ops = &clk_branch_ops,
+			.flags = CLK_IS_ROOT,
+		},
+	},
+};
+
+static struct clk_branch adm0_clk = {
+	.halt_reg = 0x2fdc,
+	.halt_check = BRANCH_HALT_VOTED,
+	.halt_bit = 14,
+	.hw = {
+		.enable_reg = 0x3080,
+		.enable_mask = BIT(2),
+		.init = &(struct clk_init_data){
+			.name = "adm0_clk",
+			.ops = &clk_branch_ops,
+			.flags = CLK_IS_ROOT,
+		},
+	},
+};
+
+static struct clk_branch adm0_pbus_clk = {
+	.halt_reg = 0x2fdc,
+	.halt_check = BRANCH_HALT_VOTED,
+	.halt_bit = 13,
+	.hw = {
+		.enable_reg = 0x3080,
+		.enable_mask = BIT(3),
+		.init = &(struct clk_init_data){
+			.name = "adm0_pbus_clk",
+			.ops = &clk_branch_ops,
+			.flags = CLK_IS_ROOT,
+		},
+	},
+};
+
+static struct clk_branch adm1_clk = {
+	.halt_reg = 0x2fdc,
+	.halt_bit = 12,
+	.halt_check = BRANCH_HALT_VOTED,
+	.hw = {
+		.enable_reg = 0x3080,
+		.enable_mask = BIT(4),
+		.init = &(struct clk_init_data){
+			.name = "adm1_clk",
+			.ops = &clk_branch_ops,
+			.flags = CLK_IS_ROOT,
+		},
+	},
+};
+
+static struct clk_branch adm1_pbus_clk = {
+	.halt_reg = 0x2fdc,
+	.halt_bit = 11,
+	.halt_check = BRANCH_HALT_VOTED,
+	.hw = {
+		.enable_reg = 0x3080,
+		.enable_mask = BIT(5),
+		.init = &(struct clk_init_data){
+			.name = "adm1_pbus_clk",
+			.ops = &clk_branch_ops,
+			.flags = CLK_IS_ROOT,
+		},
+	},
+};
+
+static struct clk_branch modem_ahb1_h_clk = {
+	.halt_reg = 0x2fdc,
+	.halt_bit = 8,
+	.halt_check = BRANCH_HALT_VOTED,
+	.hw = {
+		.enable_reg = 0x3080,
+		.enable_mask = BIT(0),
+		.init = &(struct clk_init_data){
+			.name = "modem_ahb1_h_clk",
+			.ops = &clk_branch_ops,
+			.flags = CLK_IS_ROOT,
+		},
+	},
+};
+
+static struct clk_branch modem_ahb2_h_clk = {
+	.halt_reg = 0x2fdc,
+	.halt_bit = 7,
+	.halt_check = BRANCH_HALT_VOTED,
+	.hw = {
+		.enable_reg = 0x3080,
+		.enable_mask = BIT(1),
+		.init = &(struct clk_init_data){
+			.name = "modem_ahb2_h_clk",
+			.ops = &clk_branch_ops,
+			.flags = CLK_IS_ROOT,
+		},
+	},
+};
+
+static struct clk_branch pmic_arb0_h_clk = {
+	.halt_reg = 0x2fd8,
+	.halt_check = BRANCH_HALT_VOTED,
+	.halt_bit = 22,
+	.hw = {
+		.enable_reg = 0x3080,
+		.enable_mask = BIT(8),
+		.init = &(struct clk_init_data){
+			.name = "pmic_arb0_h_clk",
+			.ops = &clk_branch_ops,
+			.flags = CLK_IS_ROOT,
+		},
+	},
+};
+
+static struct clk_branch pmic_arb1_h_clk = {
+	.halt_reg = 0x2fd8,
+	.halt_check = BRANCH_HALT_VOTED,
+	.halt_bit = 21,
+	.hw = {
+		.enable_reg = 0x3080,
+		.enable_mask = BIT(9),
+		.init = &(struct clk_init_data){
+			.name = "pmic_arb1_h_clk",
+			.ops = &clk_branch_ops,
+			.flags = CLK_IS_ROOT,
+		},
+	},
+};
+
+static struct clk_branch pmic_ssbi2_clk = {
+	.halt_reg = 0x2fd8,
+	.halt_check = BRANCH_HALT_VOTED,
+	.halt_bit = 23,
+	.hw = {
+		.enable_reg = 0x3080,
+		.enable_mask = BIT(7),
+		.init = &(struct clk_init_data){
+			.name = "pmic_ssbi2_clk",
+			.ops = &clk_branch_ops,
+			.flags = CLK_IS_ROOT,
+		},
+	},
+};
+
+static struct clk_branch rpm_msg_ram_h_clk = {
+	.hwcg_reg = 0x27e0,
+	.hwcg_bit = 6,
+	.halt_reg = 0x2fd8,
+	.halt_check = BRANCH_HALT_VOTED,
+	.halt_bit = 12,
+	.hw = {
+		.enable_reg = 0x3080,
+		.enable_mask = BIT(6),
+		.init = &(struct clk_init_data){
+			.name = "rpm_msg_ram_h_clk",
+			.ops = &clk_branch_ops,
+			.flags = CLK_IS_ROOT,
+		},
+	},
+};
+
+static struct clk_hw *gcc_msm8660_clks[] = {
+	[PLL8] = &pll8.hw,
+	[PLL8_VOTE] = &pll8_vote,
+	[GSBI1_UART_SRC] = &gsbi1_uart_src.hw,
+	[GSBI1_UART_CLK] = &gsbi1_uart_clk.hw,
+	[GSBI2_UART_SRC] = &gsbi2_uart_src.hw,
+	[GSBI2_UART_CLK] = &gsbi2_uart_clk.hw,
+	[GSBI3_UART_SRC] = &gsbi3_uart_src.hw,
+	[GSBI3_UART_CLK] = &gsbi3_uart_clk.hw,
+	[GSBI4_UART_SRC] = &gsbi4_uart_src.hw,
+	[GSBI4_UART_CLK] = &gsbi4_uart_clk.hw,
+	[GSBI5_UART_SRC] = &gsbi5_uart_src.hw,
+	[GSBI5_UART_CLK] = &gsbi5_uart_clk.hw,
+	[GSBI6_UART_SRC] = &gsbi6_uart_src.hw,
+	[GSBI6_UART_CLK] = &gsbi6_uart_clk.hw,
+	[GSBI7_UART_SRC] = &gsbi7_uart_src.hw,
+	[GSBI7_UART_CLK] = &gsbi7_uart_clk.hw,
+	[GSBI8_UART_SRC] = &gsbi8_uart_src.hw,
+	[GSBI8_UART_CLK] = &gsbi8_uart_clk.hw,
+	[GSBI9_UART_SRC] = &gsbi9_uart_src.hw,
+	[GSBI9_UART_CLK] = &gsbi9_uart_clk.hw,
+	[GSBI10_UART_SRC] = &gsbi10_uart_src.hw,
+	[GSBI10_UART_CLK] = &gsbi10_uart_clk.hw,
+	[GSBI11_UART_SRC] = &gsbi11_uart_src.hw,
+	[GSBI11_UART_CLK] = &gsbi11_uart_clk.hw,
+	[GSBI12_UART_SRC] = &gsbi12_uart_src.hw,
+	[GSBI12_UART_CLK] = &gsbi12_uart_clk.hw,
+	[GSBI1_QUP_SRC] = &gsbi1_qup_src.hw,
+	[GSBI1_QUP_CLK] = &gsbi1_qup_clk.hw,
+	[GSBI2_QUP_SRC] = &gsbi2_qup_src.hw,
+	[GSBI2_QUP_CLK] = &gsbi2_qup_clk.hw,
+	[GSBI3_QUP_SRC] = &gsbi3_qup_src.hw,
+	[GSBI3_QUP_CLK] = &gsbi3_qup_clk.hw,
+	[GSBI4_QUP_SRC] = &gsbi4_qup_src.hw,
+	[GSBI4_QUP_CLK] = &gsbi4_qup_clk.hw,
+	[GSBI5_QUP_SRC] = &gsbi5_qup_src.hw,
+	[GSBI5_QUP_CLK] = &gsbi5_qup_clk.hw,
+	[GSBI6_QUP_SRC] = &gsbi6_qup_src.hw,
+	[GSBI6_QUP_CLK] = &gsbi6_qup_clk.hw,
+	[GSBI7_QUP_SRC] = &gsbi7_qup_src.hw,
+	[GSBI7_QUP_CLK] = &gsbi7_qup_clk.hw,
+	[GSBI8_QUP_SRC] = &gsbi8_qup_src.hw,
+	[GSBI8_QUP_CLK] = &gsbi8_qup_clk.hw,
+	[GSBI9_QUP_SRC] = &gsbi9_qup_src.hw,
+	[GSBI9_QUP_CLK] = &gsbi9_qup_clk.hw,
+	[GSBI10_QUP_SRC] = &gsbi10_qup_src.hw,
+	[GSBI10_QUP_CLK] = &gsbi10_qup_clk.hw,
+	[GSBI11_QUP_SRC] = &gsbi11_qup_src.hw,
+	[GSBI11_QUP_CLK] = &gsbi11_qup_clk.hw,
+	[GSBI12_QUP_SRC] = &gsbi12_qup_src.hw,
+	[GSBI12_QUP_CLK] = &gsbi12_qup_clk.hw,
+	[GP0_SRC] = &gp0_src.hw,
+	[GP0_CLK] = &gp0_clk.hw,
+	[GP1_SRC] = &gp1_src.hw,
+	[GP1_CLK] = &gp1_clk.hw,
+	[GP2_SRC] = &gp2_src.hw,
+	[GP2_CLK] = &gp2_clk.hw,
+	[PMEM_CLK] = &pmem_clk.hw,
+	[PRNG_SRC] = &prng_src.hw,
+	[PRNG_CLK] = &prng_clk.hw,
+	[SDC1_SRC] = &sdc1_src.hw,
+	[SDC1_CLK] = &sdc1_clk.hw,
+	[SDC2_SRC] = &sdc2_src.hw,
+	[SDC2_CLK] = &sdc2_clk.hw,
+	[SDC3_SRC] = &sdc3_src.hw,
+	[SDC3_CLK] = &sdc3_clk.hw,
+	[SDC4_SRC] = &sdc4_src.hw,
+	[SDC4_CLK] = &sdc4_clk.hw,
+	[SDC5_SRC] = &sdc5_src.hw,
+	[SDC5_CLK] = &sdc5_clk.hw,
+	[TSIF_REF_SRC] = &tsif_ref_src.hw,
+	[TSIF_REF_CLK] = &tsif_ref_clk.hw,
+	[USB_HS1_XCVR_SRC] = &usb_hs1_xcvr_src.hw,
+	[USB_HS1_XCVR_CLK] = &usb_hs1_xcvr_clk.hw,
+	[USB_FS1_XCVR_FS_SRC] = &usb_fs1_xcvr_fs_src.hw,
+	[USB_FS1_XCVR_FS_CLK] = &usb_fs1_xcvr_fs_clk.hw,
+	[USB_FS1_SYSTEM_CLK] = &usb_fs1_system_clk.hw,
+	[USB_FS2_XCVR_FS_SRC] = &usb_fs2_xcvr_fs_src.hw,
+	[USB_FS2_XCVR_FS_CLK] = &usb_fs2_xcvr_fs_clk.hw,
+	[USB_FS2_SYSTEM_CLK] = &usb_fs2_system_clk.hw,
+	[GSBI1_H_CLK] = &gsbi1_h_clk.hw,
+	[GSBI2_H_CLK] = &gsbi2_h_clk.hw,
+	[GSBI3_H_CLK] = &gsbi3_h_clk.hw,
+	[GSBI4_H_CLK] = &gsbi4_h_clk.hw,
+	[GSBI5_H_CLK] = &gsbi5_h_clk.hw,
+	[GSBI6_H_CLK] = &gsbi6_h_clk.hw,
+	[GSBI7_H_CLK] = &gsbi7_h_clk.hw,
+	[GSBI8_H_CLK] = &gsbi8_h_clk.hw,
+	[GSBI9_H_CLK] = &gsbi9_h_clk.hw,
+	[GSBI10_H_CLK] = &gsbi10_h_clk.hw,
+	[GSBI11_H_CLK] = &gsbi11_h_clk.hw,
+	[GSBI12_H_CLK] = &gsbi12_h_clk.hw,
+	[TSIF_H_CLK] = &tsif_h_clk.hw,
+	[USB_FS1_H_CLK] = &usb_fs1_h_clk.hw,
+	[USB_FS2_H_CLK] = &usb_fs2_h_clk.hw,
+	[USB_HS1_H_CLK] = &usb_hs1_h_clk.hw,
+	[SDC1_H_CLK] = &sdc1_h_clk.hw,
+	[SDC2_H_CLK] = &sdc2_h_clk.hw,
+	[SDC3_H_CLK] = &sdc3_h_clk.hw,
+	[SDC4_H_CLK] = &sdc4_h_clk.hw,
+	[SDC5_H_CLK] = &sdc5_h_clk.hw,
+	[ADM0_CLK] = &adm0_clk.hw,
+	[ADM0_PBUS_CLK] = &adm0_pbus_clk.hw,
+	[ADM1_CLK] = &adm1_clk.hw,
+	[ADM1_PBUS_CLK] = &adm1_pbus_clk.hw,
+	[MODEM_AHB1_H_CLK] = &modem_ahb1_h_clk.hw,
+	[MODEM_AHB2_H_CLK] = &modem_ahb2_h_clk.hw,
+	[PMIC_ARB0_H_CLK] = &pmic_arb0_h_clk.hw,
+	[PMIC_ARB1_H_CLK] = &pmic_arb1_h_clk.hw,
+	[PMIC_SSBI2_CLK] = &pmic_ssbi2_clk.hw,
+	[RPM_MSG_RAM_H_CLK] = &rpm_msg_ram_h_clk.hw,
+};
+
+static const struct qcom_reset_map gcc_msm8660_resets[] = {
+	[AFAB_CORE_RESET] = { 0x2080, 7 },
+	[SCSS_SYS_RESET] = { 0x20b4, 1 },
+	[SCSS_SYS_POR_RESET] = { 0x20b4 },
+	[AFAB_SMPSS_S_RESET] = { 0x20b8, 2 },
+	[AFAB_SMPSS_M1_RESET] = { 0x20b8, 1 },
+	[AFAB_SMPSS_M0_RESET] = { 0x20b8 },
+	[AFAB_EBI1_S_RESET] = { 0x20c0, 7 },
+	[SFAB_CORE_RESET] = { 0x2120, 7 },
+	[SFAB_ADM0_M0_RESET] = { 0x21e0, 7 },
+	[SFAB_ADM0_M1_RESET] = { 0x21e4, 7 },
+	[SFAB_ADM0_M2_RESET] = { 0x21e4, 7 },
+	[ADM0_C2_RESET] = { 0x220c, 4 },
+	[ADM0_C1_RESET] = { 0x220c, 3 },
+	[ADM0_C0_RESET] = { 0x220c, 2 },
+	[ADM0_PBUS_RESET] = { 0x220c, 1 },
+	[ADM0_RESET] = { 0x220c },
+	[SFAB_ADM1_M0_RESET] = { 0x2220, 7 },
+	[SFAB_ADM1_M1_RESET] = { 0x2224, 7 },
+	[SFAB_ADM1_M2_RESET] = { 0x2228, 7 },
+	[MMFAB_ADM1_M3_RESET] = { 0x2240, 7 },
+	[ADM1_C3_RESET] = { 0x226c, 5 },
+	[ADM1_C2_RESET] = { 0x226c, 4 },
+	[ADM1_C1_RESET] = { 0x226c, 3 },
+	[ADM1_C0_RESET] = { 0x226c, 2 },
+	[ADM1_PBUS_RESET] = { 0x226c, 1 },
+	[ADM1_RESET] = { 0x226c },
+	[IMEM0_RESET] = { 0x2280, 7 },
+	[SFAB_LPASS_Q6_RESET] = { 0x23a0, 7 },
+	[SFAB_AFAB_M_RESET] = { 0x23e0, 7 },
+	[AFAB_SFAB_M0_RESET] = { 0x2420, 7 },
+	[AFAB_SFAB_M1_RESET] = { 0x2424, 7 },
+	[DFAB_CORE_RESET] = { 0x24ac, 7 },
+	[SFAB_DFAB_M_RESET] = { 0x2500, 7 },
+	[DFAB_SFAB_M_RESET] = { 0x2520, 7 },
+	[DFAB_SWAY0_RESET] = { 0x2540, 7 },
+	[DFAB_SWAY1_RESET] = { 0x2544, 7 },
+	[DFAB_ARB0_RESET] = { 0x2560, 7 },
+	[DFAB_ARB1_RESET] = { 0x2564, 7 },
+	[PPSS_PROC_RESET] = { 0x2594, 1 },
+	[PPSS_RESET] = { 0x2594 },
+	[PMEM_RESET] = { 0x25a0, 7 },
+	[DMA_BAM_RESET] = { 0x25c0, 7 },
+	[SIC_RESET] = { 0x25e0, 7 },
+	[SPS_TIC_RESET] = { 0x2600, 7 },
+	[CFBP0_RESET] = { 0x2650, 7 },
+	[CFBP1_RESET] = { 0x2654, 7 },
+	[CFBP2_RESET] = { 0x2658, 7 },
+	[EBI2_RESET] = { 0x2664, 7 },
+	[SFAB_CFPB_M_RESET] = { 0x2680, 7 },
+	[CFPB_MASTER_RESET] = { 0x26a0, 7 },
+	[SFAB_CFPB_S_RESET] = { 0x26c0, 7 },
+	[CFPB_SPLITTER_RESET] = { 0x26e0, 7 },
+	[TSIF_RESET] = { 0x2700, 7 },
+	[CE1_RESET] = { 0x2720, 7 },
+	[CE2_RESET] = { 0x2740, 7 },
+	[SFAB_SFPB_M_RESET] = { 0x2780, 7 },
+	[SFAB_SFPB_S_RESET] = { 0x27a0, 7 },
+	[RPM_PROC_RESET] = { 0x27c0, 7 },
+	[RPM_BUS_RESET] = { 0x27c4, 7 },
+	[RPM_MSG_RAM_RESET] = { 0x27e0, 7 },
+	[PMIC_ARB0_RESET] = { 0x2800, 7 },
+	[PMIC_ARB1_RESET] = { 0x2804, 7 },
+	[PMIC_SSBI2_RESET] = { 0x280c, 12 },
+	[SDC1_RESET] = { 0x2830 },
+	[SDC2_RESET] = { 0x2850 },
+	[SDC3_RESET] = { 0x2870 },
+	[SDC4_RESET] = { 0x2890 },
+	[SDC5_RESET] = { 0x28b0 },
+	[USB_HS1_RESET] = { 0x2910 },
+	[USB_HS2_XCVR_RESET] = { 0x2934, 1 },
+	[USB_HS2_RESET] = { 0x2934 },
+	[USB_FS1_XCVR_RESET] = { 0x2974, 1 },
+	[USB_FS1_RESET] = { 0x2974 },
+	[USB_FS2_XCVR_RESET] = { 0x2994, 1 },
+	[USB_FS2_RESET] = { 0x2994 },
+	[GSBI1_RESET] = { 0x29dc },
+	[GSBI2_RESET] = { 0x29fc },
+	[GSBI3_RESET] = { 0x2a1c },
+	[GSBI4_RESET] = { 0x2a3c },
+	[GSBI5_RESET] = { 0x2a5c },
+	[GSBI6_RESET] = { 0x2a7c },
+	[GSBI7_RESET] = { 0x2a9c },
+	[GSBI8_RESET] = { 0x2abc },
+	[GSBI9_RESET] = { 0x2adc },
+	[GSBI10_RESET] = { 0x2afc },
+	[GSBI11_RESET] = { 0x2b1c },
+	[GSBI12_RESET] = { 0x2b3c },
+	[SPDM_RESET] = { 0x2b6c },
+	[SEC_CTRL_RESET] = { 0x2b80, 7 },
+	[TLMM_H_RESET] = { 0x2ba0, 7 },
+	[TLMM_RESET] = { 0x2ba4, 7 },
+	[MARRM_PWRON_RESET] = { 0x2bd4, 1 },
+	[MARM_RESET] = { 0x2bd4 },
+	[MAHB1_RESET] = { 0x2be4, 7 },
+	[SFAB_MSS_S_RESET] = { 0x2c00, 7 },
+	[MAHB2_RESET] = { 0x2c20, 7 },
+	[MODEM_SW_AHB_RESET] = { 0x2c48, 1 },
+	[MODEM_RESET] = { 0x2c48 },
+	[SFAB_MSS_MDM1_RESET] = { 0x2c4c, 1 },
+	[SFAB_MSS_MDM0_RESET] = { 0x2c4c },
+	[MSS_SLP_RESET] = { 0x2c60, 7 },
+	[MSS_MARM_SAW_RESET] = { 0x2c68, 1 },
+	[MSS_WDOG_RESET] = { 0x2c68 },
+	[TSSC_RESET] = { 0x2ca0, 7 },
+	[PDM_RESET] = { 0x2cc0, 12 },
+	[SCSS_CORE0_RESET] = { 0x2d60, 1 },
+	[SCSS_CORE0_POR_RESET] = { 0x2d60 },
+	[SCSS_CORE1_RESET] = { 0x2d80, 1 },
+	[SCSS_CORE1_POR_RESET] = { 0x2d80 },
+	[MPM_RESET] = { 0x2da4, 1 },
+	[EBI1_1X_DIV_RESET] = { 0x2dec, 9 },
+	[EBI1_RESET] = { 0x2dec, 7 },
+	[SFAB_SMPSS_S_RESET] = { 0x2e00, 7 },
+	[USB_PHY0_RESET] = { 0x2e20 },
+	[USB_PHY1_RESET] = { 0x2e40 },
+	[PRNG_RESET] = { 0x2e80, 12 },
+};
+
+static const struct regmap_config gcc_msm8660_regmap_config = {
+	.reg_bits	= 32,
+	.reg_stride	= 4,
+	.val_bits	= 32,
+	.max_register	= 0x363c,
+	.fast_io	= true,
+};
+
+static const struct of_device_id gcc_msm8660_match_table[] = {
+	{ .compatible = "qcom,gcc-msm8660" },
+	{ }
+};
+MODULE_DEVICE_TABLE(of, gcc_msm8660_match_table);
+
+struct qcom_cc {
+	struct qcom_reset_controller reset;
+	struct clk_onecell_data data;
+	struct clk *clks[];
+};
+
+static int gcc_msm8660_probe(struct platform_device *pdev)
+{
+	void __iomem *base;
+	struct resource *res;
+	int i, ret;
+	struct device *dev = &pdev->dev;
+	struct clk *clk;
+	struct clk_onecell_data *data;
+	struct clk **clks;
+	struct regmap *regmap;
+	size_t num_clks;
+	struct qcom_reset_controller *reset;
+	struct qcom_cc *cc;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	base = devm_ioremap_resource(dev, res);
+	if (IS_ERR(base))
+		return PTR_ERR(base);
+
+	regmap = devm_regmap_init_mmio(dev, base, &gcc_msm8660_regmap_config);
+	if (IS_ERR(regmap))
+		return PTR_ERR(regmap);
+
+	num_clks = ARRAY_SIZE(gcc_msm8660_clks);
+	cc = devm_kzalloc(dev, sizeof(*cc) + sizeof(*clks) * num_clks,
+			  GFP_KERNEL);
+	if (!cc)
+		return -ENOMEM;
+
+	clks = cc->clks;
+	data = &cc->data;
+	data->clks = clks;
+	data->clk_num = num_clks;
+
+	/* Temporary until RPM clocks supported */
+	clk = clk_register_fixed_rate(dev, "cxo", NULL, CLK_IS_ROOT, 19200000);
+	if (IS_ERR(clk))
+		return PTR_ERR(clk);
+
+	clk = clk_register_fixed_rate(dev, "pxo", NULL, CLK_IS_ROOT, 27000000);
+	if (IS_ERR(clk))
+		return PTR_ERR(clk);
+
+	for (i = 0; i < num_clks; i++) {
+		if (!gcc_msm8660_clks[i])
+			continue;
+		clk = devm_clk_register(dev, gcc_msm8660_clks[i]);
+		if (IS_ERR(clk))
+			return PTR_ERR(clk);
+		clks[i] = clk;
+	}
+
+	ret = of_clk_add_provider(dev->of_node, of_clk_src_onecell_get, data);
+	if (ret)
+		return ret;
+
+	reset = &cc->reset;
+	reset->rcdev.of_node = dev->of_node;
+	reset->rcdev.ops = &qcom_reset_ops,
+	reset->rcdev.owner = THIS_MODULE,
+	reset->rcdev.nr_resets = ARRAY_SIZE(gcc_msm8660_resets),
+	reset->regmap = regmap;
+	reset->reset_map = gcc_msm8660_resets,
+	platform_set_drvdata(pdev, &reset->rcdev);
+
+	ret = reset_controller_register(&reset->rcdev);
+	if (ret)
+		of_clk_del_provider(dev->of_node);
+
+	return ret;
+}
+
+static int gcc_msm8660_remove(struct platform_device *pdev)
+{
+	of_clk_del_provider(pdev->dev.of_node);
+	reset_controller_unregister(platform_get_drvdata(pdev));
+	return 0;
+}
+
+static struct platform_driver gcc_msm8660_driver = {
+	.probe		= gcc_msm8660_probe,
+	.remove		= gcc_msm8660_remove,
+	.driver		= {
+		.name	= "gcc-msm8660",
+		.owner	= THIS_MODULE,
+		.of_match_table = gcc_msm8660_match_table,
+	},
+};
+
+static int __init gcc_msm8660_init(void)
+{
+	return platform_driver_register(&gcc_msm8660_driver);
+}
+core_initcall(gcc_msm8660_init);
+
+static void __exit gcc_msm8660_exit(void)
+{
+	platform_driver_unregister(&gcc_msm8660_driver);
+}
+module_exit(gcc_msm8660_exit);
+
+MODULE_DESCRIPTION("GCC MSM 8660 Driver");
+MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("platform:gcc-msm8660");
diff --git a/include/dt-bindings/clock/qcom,gcc-msm8660.h b/include/dt-bindings/clock/qcom,gcc-msm8660.h
new file mode 100644
index 0000000..67665f6
--- /dev/null
+++ b/include/dt-bindings/clock/qcom,gcc-msm8660.h
@@ -0,0 +1,276 @@
+/*
+ * Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef _DT_BINDINGS_CLK_MSM_GCC_8660_H
+#define _DT_BINDINGS_CLK_MSM_GCC_8660_H
+
+#define AFAB_CLK_SRC				0
+#define AFAB_CORE_CLK				1
+#define SCSS_A_CLK				2
+#define SCSS_H_CLK				3
+#define SCSS_XO_SRC_CLK				4
+#define AFAB_EBI1_CH0_A_CLK			5
+#define AFAB_EBI1_CH1_A_CLK			6
+#define AFAB_AXI_S0_FCLK			7
+#define AFAB_AXI_S1_FCLK			8
+#define AFAB_AXI_S2_FCLK			9
+#define AFAB_AXI_S3_FCLK			10
+#define AFAB_AXI_S4_FCLK			11
+#define SFAB_CORE_CLK				12
+#define SFAB_AXI_S0_FCLK			13
+#define SFAB_AXI_S1_FCLK			14
+#define SFAB_AXI_S2_FCLK			15
+#define SFAB_AXI_S3_FCLK			16
+#define SFAB_AXI_S4_FCLK			17
+#define SFAB_AHB_S0_FCLK			18
+#define SFAB_AHB_S1_FCLK			19
+#define SFAB_AHB_S2_FCLK			20
+#define SFAB_AHB_S3_FCLK			21
+#define SFAB_AHB_S4_FCLK			22
+#define SFAB_AHB_S5_FCLK			23
+#define SFAB_AHB_S6_FCLK			24
+#define SFAB_ADM0_M0_A_CLK			25
+#define SFAB_ADM0_M1_A_CLK			26
+#define SFAB_ADM0_M2_A_CLK			27
+#define ADM0_CLK				28
+#define ADM0_PBUS_CLK				29
+#define SFAB_ADM1_M0_A_CLK			30
+#define SFAB_ADM1_M1_A_CLK			31
+#define SFAB_ADM1_M2_A_CLK			32
+#define MMFAB_ADM1_M3_A_CLK			33
+#define ADM1_CLK				34
+#define ADM1_PBUS_CLK				35
+#define IMEM0_A_CLK				36
+#define MAHB0_CLK				37
+#define SFAB_LPASS_Q6_A_CLK			38
+#define SFAB_AFAB_M_A_CLK			39
+#define AFAB_SFAB_M0_A_CLK			40
+#define AFAB_SFAB_M1_A_CLK			41
+#define DFAB_CLK_SRC				42
+#define DFAB_CLK				43
+#define DFAB_CORE_CLK				44
+#define SFAB_DFAB_M_A_CLK			45
+#define DFAB_SFAB_M_A_CLK			46
+#define DFAB_SWAY0_H_CLK			47
+#define DFAB_SWAY1_H_CLK			48
+#define DFAB_ARB0_H_CLK				49
+#define DFAB_ARB1_H_CLK				50
+#define PPSS_H_CLK				51
+#define PPSS_PROC_CLK				52
+#define PPSS_TIMER0_CLK				53
+#define PPSS_TIMER1_CLK				54
+#define PMEM_A_CLK				55
+#define DMA_BAM_H_CLK				56
+#define SIC_H_CLK				57
+#define SPS_TIC_H_CLK				58
+#define SLIMBUS_H_CLK				59
+#define SLIMBUS_XO_SRC_CLK			60
+#define CFPB_2X_CLK_SRC				61
+#define CFPB_CLK				62
+#define CFPB0_H_CLK				63
+#define CFPB1_H_CLK				64
+#define CFPB2_H_CLK				65
+#define EBI2_2X_CLK				66
+#define EBI2_CLK				67
+#define SFAB_CFPB_M_H_CLK			68
+#define CFPB_MASTER_H_CLK			69
+#define SFAB_CFPB_S_HCLK			70
+#define CFPB_SPLITTER_H_CLK			71
+#define TSIF_H_CLK				72
+#define TSIF_INACTIVITY_TIMERS_CLK		73
+#define TSIF_REF_SRC				74
+#define TSIF_REF_CLK				75
+#define CE1_H_CLK				76
+#define CE2_H_CLK				77
+#define SFPB_H_CLK_SRC				78
+#define SFPB_H_CLK				79
+#define SFAB_SFPB_M_H_CLK			80
+#define SFAB_SFPB_S_H_CLK			81
+#define RPM_PROC_CLK				82
+#define RPM_BUS_H_CLK				83
+#define RPM_SLEEP_CLK				84
+#define RPM_TIMER_CLK				85
+#define MODEM_AHB1_H_CLK			86
+#define MODEM_AHB2_H_CLK			87
+#define RPM_MSG_RAM_H_CLK			88
+#define SC_H_CLK				89
+#define SC_A_CLK				90
+#define PMIC_ARB0_H_CLK				91
+#define PMIC_ARB1_H_CLK				92
+#define PMIC_SSBI2_SRC				93
+#define PMIC_SSBI2_CLK				94
+#define SDC1_H_CLK				95
+#define SDC2_H_CLK				96
+#define SDC3_H_CLK				97
+#define SDC4_H_CLK				98
+#define SDC5_H_CLK				99
+#define SDC1_SRC				100
+#define SDC2_SRC				101
+#define SDC3_SRC				102
+#define SDC4_SRC				103
+#define SDC5_SRC				104
+#define SDC1_CLK				105
+#define SDC2_CLK				106
+#define SDC3_CLK				107
+#define SDC4_CLK				108
+#define SDC5_CLK				109
+#define USB_HS1_H_CLK				110
+#define USB_HS1_XCVR_SRC			111
+#define USB_HS1_XCVR_CLK			112
+#define USB_HS2_H_CLK				113
+#define USB_HS2_XCVR_SRC			114
+#define USB_HS2_XCVR_CLK			115
+#define USB_FS1_H_CLK				116
+#define USB_FS1_XCVR_FS_SRC			117
+#define USB_FS1_XCVR_FS_CLK			118
+#define USB_FS1_SYSTEM_CLK			119
+#define USB_FS2_H_CLK				120
+#define USB_FS2_XCVR_FS_SRC			121
+#define USB_FS2_XCVR_FS_CLK			122
+#define USB_FS2_SYSTEM_CLK			123
+#define GSBI_COMMON_SIM_SRC			124
+#define GSBI1_H_CLK				125
+#define GSBI2_H_CLK				126
+#define GSBI3_H_CLK				127
+#define GSBI4_H_CLK				128
+#define GSBI5_H_CLK				129
+#define GSBI6_H_CLK				130
+#define GSBI7_H_CLK				131
+#define GSBI8_H_CLK				132
+#define GSBI9_H_CLK				133
+#define GSBI10_H_CLK				134
+#define GSBI11_H_CLK				135
+#define GSBI12_H_CLK				136
+#define GSBI1_UART_SRC				137
+#define GSBI1_UART_CLK				138
+#define GSBI2_UART_SRC				139
+#define GSBI2_UART_CLK				140
+#define GSBI3_UART_SRC				141
+#define GSBI3_UART_CLK				142
+#define GSBI4_UART_SRC				143
+#define GSBI4_UART_CLK				144
+#define GSBI5_UART_SRC				145
+#define GSBI5_UART_CLK				146
+#define GSBI6_UART_SRC				147
+#define GSBI6_UART_CLK				148
+#define GSBI7_UART_SRC				149
+#define GSBI7_UART_CLK				150
+#define GSBI8_UART_SRC				151
+#define GSBI8_UART_CLK				152
+#define GSBI9_UART_SRC				153
+#define GSBI9_UART_CLK				154
+#define GSBI10_UART_SRC				155
+#define GSBI10_UART_CLK				156
+#define GSBI11_UART_SRC				157
+#define GSBI11_UART_CLK				158
+#define GSBI12_UART_SRC				159
+#define GSBI12_UART_CLK				160
+#define GSBI1_QUP_SRC				161
+#define GSBI1_QUP_CLK				162
+#define GSBI2_QUP_SRC				163
+#define GSBI2_QUP_CLK				164
+#define GSBI3_QUP_SRC				165
+#define GSBI3_QUP_CLK				166
+#define GSBI4_QUP_SRC				167
+#define GSBI4_QUP_CLK				168
+#define GSBI5_QUP_SRC				169
+#define GSBI5_QUP_CLK				170
+#define GSBI6_QUP_SRC				171
+#define GSBI6_QUP_CLK				172
+#define GSBI7_QUP_SRC				173
+#define GSBI7_QUP_CLK				174
+#define GSBI8_QUP_SRC				175
+#define GSBI8_QUP_CLK				176
+#define GSBI9_QUP_SRC				177
+#define GSBI9_QUP_CLK				178
+#define GSBI10_QUP_SRC				179
+#define GSBI10_QUP_CLK				180
+#define GSBI11_QUP_SRC				181
+#define GSBI11_QUP_CLK				182
+#define GSBI12_QUP_SRC				183
+#define GSBI12_QUP_CLK				184
+#define GSBI1_SIM_CLK				185
+#define GSBI2_SIM_CLK				186
+#define GSBI3_SIM_CLK				187
+#define GSBI4_SIM_CLK				188
+#define GSBI5_SIM_CLK				189
+#define GSBI6_SIM_CLK				190
+#define GSBI7_SIM_CLK				191
+#define GSBI8_SIM_CLK				192
+#define GSBI9_SIM_CLK				193
+#define GSBI10_SIM_CLK				194
+#define GSBI11_SIM_CLK				195
+#define GSBI12_SIM_CLK				196
+#define SPDM_CFG_H_CLK				197
+#define SPDM_MSTR_H_CLK				198
+#define SPDM_FF_CLK_SRC				199
+#define SPDM_FF_CLK				200
+#define SEC_CTRL_CLK				201
+#define SEC_CTRL_ACC_CLK_SRC			202
+#define SEC_CTRL_ACC_CLK			203
+#define TLMM_H_CLK				204
+#define TLMM_CLK				205
+#define MARM_CLK_SRC				206
+#define MARM_CLK				207
+#define MAHB1_SRC				208
+#define MAHB1_CLK				209
+#define SFAB_MSS_S_H_CLK			210
+#define MAHB2_SRC				211
+#define MAHB2_CLK				212
+#define MSS_MODEM_CLK_SRC			213
+#define MSS_MODEM_CXO_CLK			214
+#define MSS_SLP_CLK				215
+#define MSS_SYS_REF_CLK				216
+#define TSSC_CLK_SRC				217
+#define TSSC_CLK				218
+#define PDM_SRC					219
+#define PDM_CLK					220
+#define GP0_SRC					221
+#define GP0_CLK					222
+#define GP1_SRC					223
+#define GP1_CLK					224
+#define GP2_SRC					225
+#define GP2_CLK					226
+#define PMEM_CLK				227
+#define MPM_CLK					228
+#define EBI1_ASFAB_SRC				229
+#define EBI1_CLK_SRC				230
+#define EBI1_CH0_CLK				231
+#define EBI1_CH1_CLK				232
+#define SFAB_SMPSS_S_H_CLK			233
+#define PRNG_SRC				234
+#define PRNG_CLK				235
+#define PXO_SRC					236
+#define LPASS_CXO_CLK				237
+#define LPASS_PXO_CLK				238
+#define SPDM_CY_PORT0_CLK			239
+#define SPDM_CY_PORT1_CLK			240
+#define SPDM_CY_PORT2_CLK			241
+#define SPDM_CY_PORT3_CLK			242
+#define SPDM_CY_PORT4_CLK			243
+#define SPDM_CY_PORT5_CLK			244
+#define SPDM_CY_PORT6_CLK			245
+#define SPDM_CY_PORT7_CLK			246
+#define PLL0					247
+#define PLL0_VOTE				248
+#define PLL5					249
+#define PLL6					250
+#define PLL6_VOTE				251
+#define PLL8					252
+#define PLL8_VOTE				253
+#define PLL9					254
+#define PLL10					255
+#define PLL11					256
+#define PLL12					257
+
+#endif
diff --git a/include/dt-bindings/reset/qcom,gcc-msm8660.h b/include/dt-bindings/reset/qcom,gcc-msm8660.h
new file mode 100644
index 0000000..a83282f
--- /dev/null
+++ b/include/dt-bindings/reset/qcom,gcc-msm8660.h
@@ -0,0 +1,134 @@
+/*
+ * Copyright (c) 2013, The Linux Foundation. All rights reserved.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef _DT_BINDINGS_RESET_MSM_GCC_8660_H
+#define _DT_BINDINGS_RESET_MSM_GCC_8660_H
+
+#define AFAB_CORE_RESET					0
+#define SCSS_SYS_RESET					1
+#define SCSS_SYS_POR_RESET				2
+#define AFAB_SMPSS_S_RESET				3
+#define AFAB_SMPSS_M1_RESET				4
+#define AFAB_SMPSS_M0_RESET				5
+#define AFAB_EBI1_S_RESET				6
+#define SFAB_CORE_RESET					7
+#define SFAB_ADM0_M0_RESET				8
+#define SFAB_ADM0_M1_RESET				9
+#define SFAB_ADM0_M2_RESET				10
+#define ADM0_C2_RESET					11
+#define ADM0_C1_RESET					12
+#define ADM0_C0_RESET					13
+#define ADM0_PBUS_RESET					14
+#define ADM0_RESET					15
+#define SFAB_ADM1_M0_RESET				16
+#define SFAB_ADM1_M1_RESET				17
+#define SFAB_ADM1_M2_RESET				18
+#define MMFAB_ADM1_M3_RESET				19
+#define ADM1_C3_RESET					20
+#define ADM1_C2_RESET					21
+#define ADM1_C1_RESET					22
+#define ADM1_C0_RESET					23
+#define ADM1_PBUS_RESET					24
+#define ADM1_RESET					25
+#define IMEM0_RESET					26
+#define SFAB_LPASS_Q6_RESET				27
+#define SFAB_AFAB_M_RESET				28
+#define AFAB_SFAB_M0_RESET				29
+#define AFAB_SFAB_M1_RESET				30
+#define DFAB_CORE_RESET					31
+#define SFAB_DFAB_M_RESET				32
+#define DFAB_SFAB_M_RESET				33
+#define DFAB_SWAY0_RESET				34
+#define DFAB_SWAY1_RESET				35
+#define DFAB_ARB0_RESET					36
+#define DFAB_ARB1_RESET					37
+#define PPSS_PROC_RESET					38
+#define PPSS_RESET					39
+#define PMEM_RESET					40
+#define DMA_BAM_RESET					41
+#define SIC_RESET					42
+#define SPS_TIC_RESET					43
+#define CFBP0_RESET					44
+#define CFBP1_RESET					45
+#define CFBP2_RESET					46
+#define EBI2_RESET					47
+#define SFAB_CFPB_M_RESET				48
+#define CFPB_MASTER_RESET				49
+#define SFAB_CFPB_S_RESET				50
+#define CFPB_SPLITTER_RESET				51
+#define TSIF_RESET					52
+#define CE1_RESET					53
+#define CE2_RESET					54
+#define SFAB_SFPB_M_RESET				55
+#define SFAB_SFPB_S_RESET				56
+#define RPM_PROC_RESET					57
+#define RPM_BUS_RESET					58
+#define RPM_MSG_RAM_RESET				59
+#define PMIC_ARB0_RESET					60
+#define PMIC_ARB1_RESET					61
+#define PMIC_SSBI2_RESET				62
+#define SDC1_RESET					63
+#define SDC2_RESET					64
+#define SDC3_RESET					65
+#define SDC4_RESET					66
+#define SDC5_RESET					67
+#define USB_HS1_RESET					68
+#define USB_HS2_XCVR_RESET				69
+#define USB_HS2_RESET					70
+#define USB_FS1_XCVR_RESET				71
+#define USB_FS1_RESET					72
+#define USB_FS2_XCVR_RESET				73
+#define USB_FS2_RESET					74
+#define GSBI1_RESET					75
+#define GSBI2_RESET					76
+#define GSBI3_RESET					77
+#define GSBI4_RESET					78
+#define GSBI5_RESET					79
+#define GSBI6_RESET					80
+#define GSBI7_RESET					81
+#define GSBI8_RESET					82
+#define GSBI9_RESET					83
+#define GSBI10_RESET					84
+#define GSBI11_RESET					85
+#define GSBI12_RESET					86
+#define SPDM_RESET					87
+#define SEC_CTRL_RESET					88
+#define TLMM_H_RESET					89
+#define TLMM_RESET					90
+#define MARRM_PWRON_RESET				91
+#define MARM_RESET					92
+#define MAHB1_RESET					93
+#define SFAB_MSS_S_RESET				94
+#define MAHB2_RESET					95
+#define MODEM_SW_AHB_RESET				96
+#define MODEM_RESET					97
+#define SFAB_MSS_MDM1_RESET				98
+#define SFAB_MSS_MDM0_RESET				99
+#define MSS_SLP_RESET					100
+#define MSS_MARM_SAW_RESET				101
+#define MSS_WDOG_RESET					102
+#define TSSC_RESET					103
+#define PDM_RESET					104
+#define SCSS_CORE0_RESET				105
+#define SCSS_CORE0_POR_RESET				106
+#define SCSS_CORE1_RESET				107
+#define SCSS_CORE1_POR_RESET				108
+#define MPM_RESET					109
+#define EBI1_1X_DIV_RESET				110
+#define EBI1_RESET					111
+#define SFAB_SMPSS_S_RESET				112
+#define USB_PHY0_RESET					113
+#define USB_PHY1_RESET					114
+#define PRNG_RESET					115
+
+#endif
-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
hosted by The Linux Foundation

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

* [PATCH v4 14/15] devicetree: bindings: Document qcom,gcc
  2013-12-24  1:12 [PATCH v4 00/15] Add support for MSM's mmio clock/reset controller Stephen Boyd
                   ` (12 preceding siblings ...)
  2013-12-24  1:12 ` [PATCH v4 13/15] clk: qcom: Add support for MSM8660's global clock controller (GCC) Stephen Boyd
@ 2013-12-24  1:12 ` Stephen Boyd
  2013-12-24  1:12 ` [PATCH v4 15/15] devicetree: bindings: Document qcom,mmcc Stephen Boyd
  14 siblings, 0 replies; 34+ messages in thread
From: Stephen Boyd @ 2013-12-24  1:12 UTC (permalink / raw)
  To: Mike Turquette
  Cc: linux-kernel, linux-arm-msm, linux-arm-kernel, Saravana Kannan,
	devicetree

Document the global clock controller found on MSM devices.

Cc: <devicetree@vger.kernel.org>
Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
---
 .../devicetree/bindings/clock/qcom,gcc.txt          | 21 +++++++++++++++++++++
 1 file changed, 21 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/clock/qcom,gcc.txt

diff --git a/Documentation/devicetree/bindings/clock/qcom,gcc.txt b/Documentation/devicetree/bindings/clock/qcom,gcc.txt
new file mode 100644
index 0000000..767401f
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/qcom,gcc.txt
@@ -0,0 +1,21 @@
+Qualcomm Global Clock & Reset Controller Binding
+------------------------------------------------
+
+Required properties :
+- compatible : shall contain only one of the following:
+
+			"qcom,gcc-msm8660"
+			"qcom,gcc-msm8960"
+			"qcom,gcc-msm8974"
+
+- reg : shall contain base register location and length
+- #clock-cells : shall contain 1
+- #reset-cells : shall contain 1
+
+Example:
+	clock-controller@900000 {
+		compatible = "qcom,gcc-msm8960";
+		reg = <0x900000 0x4000>;
+		#clock-cells = <1>;
+		#reset-cells = <1>;
+	};
-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
hosted by The Linux Foundation

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

* [PATCH v4 15/15] devicetree: bindings: Document qcom,mmcc
  2013-12-24  1:12 [PATCH v4 00/15] Add support for MSM's mmio clock/reset controller Stephen Boyd
                   ` (13 preceding siblings ...)
  2013-12-24  1:12 ` [PATCH v4 14/15] devicetree: bindings: Document qcom,gcc Stephen Boyd
@ 2013-12-24  1:12 ` Stephen Boyd
  14 siblings, 0 replies; 34+ messages in thread
From: Stephen Boyd @ 2013-12-24  1:12 UTC (permalink / raw)
  To: Mike Turquette
  Cc: linux-kernel, linux-arm-msm, linux-arm-kernel, Saravana Kannan,
	devicetree

Document the multimedia clock controller found on MSM devices

Cc: <devicetree@vger.kernel.org>
Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
---
 .../devicetree/bindings/clock/qcom,mmcc.txt         | 21 +++++++++++++++++++++
 1 file changed, 21 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/clock/qcom,mmcc.txt

diff --git a/Documentation/devicetree/bindings/clock/qcom,mmcc.txt b/Documentation/devicetree/bindings/clock/qcom,mmcc.txt
new file mode 100644
index 0000000..d572e99
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/qcom,mmcc.txt
@@ -0,0 +1,21 @@
+Qualcomm Multimedia Clock & Reset Controller Binding
+----------------------------------------------------
+
+Required properties :
+- compatible : shall contain only one of the following:
+
+			"qcom,mmcc-msm8660"
+			"qcom,mmcc-msm8960"
+			"qcom,mmcc-msm8974"
+
+- reg : shall contain base register location and length
+- #clock-cells : shall contain 1
+- #reset-cells : shall contain 1
+
+Example:
+	clock-controller@4000000 {
+		compatible = "qcom,mmcc-msm8960";
+		reg = <0x4000000 0x1000>;
+		#clock-cells = <1>;
+		#reset-cells = <1>;
+	};
-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
hosted by The Linux Foundation

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

* Re: [PATCH v4 02/15] clk: Allow drivers to pass in a regmap
  2013-12-24  1:12 ` [PATCH v4 02/15] clk: Allow drivers to pass in a regmap Stephen Boyd
@ 2013-12-24 13:13   ` Mark Brown
  2014-01-09  1:51   ` Mike Turquette
  1 sibling, 0 replies; 34+ messages in thread
From: Mark Brown @ 2013-12-24 13:13 UTC (permalink / raw)
  To: Stephen Boyd
  Cc: Mike Turquette, linux-kernel, linux-arm-msm, linux-arm-kernel,
	Saravana Kannan

On Mon, Dec 23, 2013 at 05:12:26PM -0800, Stephen Boyd wrote:
> Add support to the clock core so that drivers can pass in a
> regmap. If no regmap is specified try to query the device that's
> registering the clock for its regmap. This should allow drivers
> to use the core regmap helpers. This is based on a similar design
> in the regulator framework.

Reviewed-by: Mark Brown <broonie@linaro.org>

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

* Re: [PATCH v4 03/15] clk: Add regmap core helpers for enable/disable/is_enabled
  2013-12-24  1:12 ` [PATCH v4 03/15] clk: Add regmap core helpers for enable/disable/is_enabled Stephen Boyd
@ 2013-12-24 13:14   ` Mark Brown
  2013-12-24 15:07   ` Gerhard Sittig
  1 sibling, 0 replies; 34+ messages in thread
From: Mark Brown @ 2013-12-24 13:14 UTC (permalink / raw)
  To: Stephen Boyd
  Cc: Mike Turquette, linux-kernel, linux-arm-msm, linux-arm-kernel,
	Saravana Kannan

On Mon, Dec 23, 2013 at 05:12:27PM -0800, Stephen Boyd wrote:
> The clock framework already has support for simple gate clocks
> but if drivers want to use the gate clock functionality they need
> to wrap the gate clock in another struct and chain the ops by
> calling the gate ops from their own custom ops. Plus the gate

Reviewed-by: Mark Brown <broonie@linaro.org>

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

* Re: [PATCH v4 03/15] clk: Add regmap core helpers for enable/disable/is_enabled
  2013-12-24  1:12 ` [PATCH v4 03/15] clk: Add regmap core helpers for enable/disable/is_enabled Stephen Boyd
  2013-12-24 13:14   ` Mark Brown
@ 2013-12-24 15:07   ` Gerhard Sittig
  2013-12-26 19:31     ` Stephen Boyd
  1 sibling, 1 reply; 34+ messages in thread
From: Gerhard Sittig @ 2013-12-24 15:07 UTC (permalink / raw)
  To: Stephen Boyd
  Cc: Mike Turquette, linux-arm-msm, Mark Brown, Saravana Kannan,
	linux-kernel, linux-arm-kernel

On Mon, Dec 23, 2013 at 17:12 -0800, Stephen Boyd wrote:
> 
> The clock framework already has support for simple gate clocks
> but if drivers want to use the gate clock functionality they need
> to wrap the gate clock in another struct and chain the ops by
> calling the gate ops from their own custom ops. Plus the gate
> clock implementation only supports MMIO accessors so other bus
> type clocks don't benefit from the potential code reuse. Add some
> simple regmap helpers for enable/disable/is_enabled that drivers
> can use as drop in replacements for their clock ops or as simple
> functions they call from their own custom ops. This is based on 
> similar helps in the regulator framework.

The same comment applies as to the previous version.  Is it
useful to introduce copies of the gate handling while the
difference in only in how the hardware registers get accessed?

> --- a/include/linux/clk-provider.h
> +++ b/include/linux/clk-provider.h
> @@ -177,11 +177,21 @@ struct clk_init_data {
> [ ... ]
> @@ -447,6 +457,9 @@ struct clk *__clk_lookup(const char *name);
>  long __clk_mux_determine_rate(struct clk_hw *hw, unsigned long rate,
>  			      unsigned long *best_parent_rate,
>  			      struct clk **best_parent_p);
> +int clk_is_enabled_regmap(struct clk_hw *hw);
> +int clk_enable_regmap(struct clk_hw *hw);
> +void clk_disable_regmap(struct clk_hw *hw);

Looking at the patch:  Do you expect callers to remember whether
a clock gate is backed by mmio or by regmap access, to call a
different set of routines?  Should this not be hidden behind the
API and be transparent after clock registration?

I'd suggest to fold regmap support into Tero Kristo's ll_ops
approach, and to discuss this in his v12 thread.


virtually yours
Gerhard Sittig
-- 
DENX Software Engineering GmbH,     MD: Wolfgang Denk & Detlev Zundel
HRB 165235 Munich, Office: Kirchenstr. 5, D-82194 Groebenzell, Germany
Phone: +49-8142-66989-0 Fax: +49-8142-66989-80  Email: office@denx.de

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

* Re: [PATCH v4 03/15] clk: Add regmap core helpers for enable/disable/is_enabled
  2013-12-24 15:07   ` Gerhard Sittig
@ 2013-12-26 19:31     ` Stephen Boyd
  2013-12-31 13:02       ` Gerhard Sittig
  0 siblings, 1 reply; 34+ messages in thread
From: Stephen Boyd @ 2013-12-26 19:31 UTC (permalink / raw)
  To: Mike Turquette, linux-arm-msm, Mark Brown, Saravana Kannan,
	linux-kernel, linux-arm-kernel

On 12/24, Gerhard Sittig wrote:
> On Mon, Dec 23, 2013 at 17:12 -0800, Stephen Boyd wrote:
> > 
> > The clock framework already has support for simple gate clocks
> > but if drivers want to use the gate clock functionality they need
> > to wrap the gate clock in another struct and chain the ops by
> > calling the gate ops from their own custom ops. Plus the gate
> > clock implementation only supports MMIO accessors so other bus
> > type clocks don't benefit from the potential code reuse. Add some
> > simple regmap helpers for enable/disable/is_enabled that drivers
> > can use as drop in replacements for their clock ops or as simple
> > functions they call from their own custom ops. This is based on 
> > similar helps in the regulator framework.
> 
> The same comment applies as to the previous version.  Is it
> useful to introduce copies of the gate handling while the
> difference in only in how the hardware registers get accessed?
> 

I don't plan to use the clk-gate.c implementation because I need
more than just a bit toggling clock. We can easily make
clk-gate.c use these helpers if you're worried about the very
small amount of code duplication between the two. I'd be glad to
do that, I just didn't include it here because I don't have a use
for it.

> > --- a/include/linux/clk-provider.h
> > +++ b/include/linux/clk-provider.h
> > @@ -177,11 +177,21 @@ struct clk_init_data {
> > [ ... ]
> > @@ -447,6 +457,9 @@ struct clk *__clk_lookup(const char *name);
> >  long __clk_mux_determine_rate(struct clk_hw *hw, unsigned long rate,
> >  			      unsigned long *best_parent_rate,
> >  			      struct clk **best_parent_p);
> > +int clk_is_enabled_regmap(struct clk_hw *hw);
> > +int clk_enable_regmap(struct clk_hw *hw);
> > +void clk_disable_regmap(struct clk_hw *hw);
> 
> Looking at the patch:  Do you expect callers to remember whether
> a clock gate is backed by mmio or by regmap access, to call a
> different set of routines? 

There are only regmap functions. I'm not sure where the choice
is, but I expect the callers to know what they're doing. If you
look at the rest of this series you'll see that I assign these
functions directly to the clk_ops, or I call them from the
enable/disable functions that need to do some status bit polling
after the clock is enabled or disabled.

> Should this not be hidden behind the
> API and be transparent after clock registration?

I don't really understand what you mean by hiding it behind the
API? What API? If we're talking about clk_register_gate() I think
we would need to add a clk_register_regmap_gate() function
because the reg argument is an __iomem pointer. It doesn't look
like it can be transparent unless that pointer is reused as an
offset. I don't attempt to do anything about that here though
because I don't use the clk-gate.c code.

> 
> I'd suggest to fold regmap support into Tero Kristo's ll_ops
> approach, and to discuss this in his v12 thread.

Sure, I'll go look at and reply to that thread. How do you think
I can benefit from Tero's patch series? From what I can tell
ll_ops are a simplified version of regmap. Was regmap dismissed
because the omap clock driver is not actually a platform driver?
There doesn't seem to be any details in the thread(s) about why
the ll_ops were proposed over regmap. From my perspective, using
a regmap like is proposed in my patches is the better way to do
this and it doesn't require any thing like ll_ops or clk_readl()
to do it.

-- 
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
hosted by The Linux Foundation

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

* Re: [PATCH v4 03/15] clk: Add regmap core helpers for enable/disable/is_enabled
  2013-12-26 19:31     ` Stephen Boyd
@ 2013-12-31 13:02       ` Gerhard Sittig
  0 siblings, 0 replies; 34+ messages in thread
From: Gerhard Sittig @ 2013-12-31 13:02 UTC (permalink / raw)
  To: Stephen Boyd
  Cc: Mike Turquette, linux-arm-msm, Mark Brown, Saravana Kannan,
	linux-kernel, linux-arm-kernel

On Thu, Dec 26, 2013 at 11:31 -0800, Stephen Boyd wrote:
> 
> On 12/24, Gerhard Sittig wrote:
> > On Mon, Dec 23, 2013 at 17:12 -0800, Stephen Boyd wrote:
> > > 
> > > The clock framework already has support for simple gate clocks
> > > but if drivers want to use the gate clock functionality they need
> > > to wrap the gate clock in another struct and chain the ops by
> > > calling the gate ops from their own custom ops. Plus the gate
> > > clock implementation only supports MMIO accessors so other bus
> > > type clocks don't benefit from the potential code reuse. Add some
> > > simple regmap helpers for enable/disable/is_enabled that drivers
> > > can use as drop in replacements for their clock ops or as simple
> > > functions they call from their own custom ops. This is based on 
> > > similar helps in the regulator framework.
> > 
> > The same comment applies as to the previous version.  Is it
> > useful to introduce copies of the gate handling while the
> > difference in only in how the hardware registers get accessed?
> > 
> 
> I don't plan to use the clk-gate.c implementation because I need
> more than just a bit toggling clock. We can easily make
> clk-gate.c use these helpers if you're worried about the very
> small amount of code duplication between the two. I'd be glad to
> do that, I just didn't include it here because I don't have a use
> for it.

OK, then I simply misunderstood.  From past threads I got the
impression that your clock item was "a gate with regmap instead
of mmio for hardware access, everything else being the same".
The concerns were not so much about the size of duplicated code,
but the "quality step" in starting duplication at all.  But since
I was wrong, nevermind.


> > > --- a/include/linux/clk-provider.h
> > > +++ b/include/linux/clk-provider.h
> > > @@ -177,11 +177,21 @@ struct clk_init_data {
> > > [ ... ]
> > > @@ -447,6 +457,9 @@ struct clk *__clk_lookup(const char *name);
> > >  long __clk_mux_determine_rate(struct clk_hw *hw, unsigned long rate,
> > >  			      unsigned long *best_parent_rate,
> > >  			      struct clk **best_parent_p);
> > > +int clk_is_enabled_regmap(struct clk_hw *hw);
> > > +int clk_enable_regmap(struct clk_hw *hw);
> > > +void clk_disable_regmap(struct clk_hw *hw);
> > 
> > Looking at the patch:  Do you expect callers to remember whether
> > a clock gate is backed by mmio or by regmap access, to call a
> > different set of routines? 
> 
> There are only regmap functions. I'm not sure where the choice
> is, but I expect the callers to know what they're doing. If you
> look at the rest of this series you'll see that I assign these
> functions directly to the clk_ops, or I call them from the
> enable/disable functions that need to do some status bit polling
> after the clock is enabled or disabled.
> 
> > Should this not be hidden behind the
> > API and be transparent after clock registration?
> 
> I don't really understand what you mean by hiding it behind the
> API? What API? If we're talking about clk_register_gate() I think
> we would need to add a clk_register_regmap_gate() function
> because the reg argument is an __iomem pointer. It doesn't look
> like it can be transparent unless that pointer is reused as an
> offset. I don't attempt to do anything about that here though
> because I don't use the clk-gate.c code.

See above, it's simple.  I misunderstood, asked (in a previous
thread), got no response, saw another submission, asked again.
Now that you told me, it's clear I got something wrong.  Thank
you for telling me what I missed before.


virtually yours
Gerhard Sittig
-- 
DENX Software Engineering GmbH,     MD: Wolfgang Denk & Detlev Zundel
HRB 165235 Munich, Office: Kirchenstr. 5, D-82194 Groebenzell, Germany
Phone: +49-8142-66989-0 Fax: +49-8142-66989-80  Email: office@denx.de

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

* Re: [PATCH v4 01/15] reset: Silence warning in reset-controller.h
  2013-12-24  1:12 ` [PATCH v4 01/15] reset: Silence warning in reset-controller.h Stephen Boyd
@ 2014-01-06 17:28   ` Philipp Zabel
  0 siblings, 0 replies; 34+ messages in thread
From: Philipp Zabel @ 2014-01-06 17:28 UTC (permalink / raw)
  To: Stephen Boyd
  Cc: Mike Turquette, linux-kernel, linux-arm-msm, linux-arm-kernel,
	Saravana Kannan

Am Montag, den 23.12.2013, 17:12 -0800 schrieb Stephen Boyd:
> If a user of <linux/reset-controller.h> doesn't include
> <linux/of.h> before including reset-controller.h they'll get a
> warning as follows:
> 
>   include/linux/reset-controller.h:44:17:
>   warning: 'struct of_phandle_args' declared inside parameter list
> 
> This is because of_phandle_args is not forward declared. Add the
> declaration to silence this warning.
> 
> Cc: Philipp Zabel <p.zabel@pengutronix.de>
> Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
> ---
>  include/linux/reset-controller.h | 1 +
>  1 file changed, 1 insertion(+)
> 
> diff --git a/include/linux/reset-controller.h b/include/linux/reset-controller.h
> index 2f61311..41a4695 100644
> --- a/include/linux/reset-controller.h
> +++ b/include/linux/reset-controller.h
> @@ -21,6 +21,7 @@ struct reset_control_ops {
>  
>  struct module;
>  struct device_node;
> +struct of_phandle_args;
>  
>  /**
>   * struct reset_controller_dev - reset controller entity that might

Since this is only a warning, I see no need for this to go through the
clock tree. On the other hand there are no merge conflicts to be
expected, so that's fine with me either way.

Acked-by: Philipp Zabel <p.zabel@pengutronix.de>

regards
Philipp

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

* Re: [PATCH v4 02/15] clk: Allow drivers to pass in a regmap
  2013-12-24  1:12 ` [PATCH v4 02/15] clk: Allow drivers to pass in a regmap Stephen Boyd
  2013-12-24 13:13   ` Mark Brown
@ 2014-01-09  1:51   ` Mike Turquette
  2014-01-09  2:11     ` Stephen Boyd
  2014-01-14  3:54     ` Saravana Kannan
  1 sibling, 2 replies; 34+ messages in thread
From: Mike Turquette @ 2014-01-09  1:51 UTC (permalink / raw)
  To: Stephen Boyd
  Cc: linux-arm-msm, Mark Brown, Saravana Kannan, linux-kernel,
	linux-arm-kernel

Quoting Stephen Boyd (2013-12-23 17:12:26)
> Add support to the clock core so that drivers can pass in a
> regmap. If no regmap is specified try to query the device that's
> registering the clock for its regmap. This should allow drivers
> to use the core regmap helpers. This is based on a similar design
> in the regulator framework.
> 
> Cc: Mark Brown <broonie@kernel.org>
> Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
> ---
>  drivers/clk/clk.c            | 8 ++++++++
>  include/linux/clk-provider.h | 7 +++++++
>  2 files changed, 15 insertions(+)
> 
> diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
> index 9ad7b71..5e71f5c 100644
> --- a/drivers/clk/clk.c
> +++ b/drivers/clk/clk.c
> @@ -20,6 +20,7 @@
>  #include <linux/device.h>
>  #include <linux/init.h>
>  #include <linux/sched.h>
> +#include <linux/regmap.h>
>  
>  static DEFINE_SPINLOCK(enable_lock);
>  static DEFINE_MUTEX(prepare_lock);
> @@ -1834,6 +1835,13 @@ static int _clk_register(struct device *dev, struct clk_hw *hw, struct clk *clk)
>         clk->num_parents = hw->init->num_parents;
>         hw->clk = clk;
>  
> +       if (hw->init->regmap)
> +               hw->regmap = hw->init->regmap;

Hi Stephen,

The whole series looks good to me except for the placement of the regmap
details inside struct clk_hw. That structure exists only to hide struct
clk from the hardware-specific clock structure and I'd not like to set
the precedent of shoving per-clock data into it.

As an alternative, how about finding a way to put these per-clock regmap
details into the hardware-specific clock structure? I understand that
you want to make these ops available to others, which is why they are in
the public struct clk_hw. I'm just wondering if that is the right way to
do it...

Patch #3 illustrates the sort of struct-member-creep that worries me.
What is to stop someone from putting "unsigned int divider_reg" or
"unsigned int mux_reg", and then the thing just keeps growing.

Regards,
Mike

> +       else if (dev && dev_get_regmap(dev, NULL))
> +               hw->regmap = dev_get_regmap(dev, NULL);
> +       else if (dev && dev->parent)
> +               hw->regmap = dev_get_regmap(dev->parent, NULL);
> +
>         /* allocate local copy in case parent_names is __initdata */
>         clk->parent_names = kcalloc(clk->num_parents, sizeof(char *),
>                                         GFP_KERNEL);
> diff --git a/include/linux/clk-provider.h b/include/linux/clk-provider.h
> index 7e59253..31f2890 100644
> --- a/include/linux/clk-provider.h
> +++ b/include/linux/clk-provider.h
> @@ -142,6 +142,8 @@ struct clk_ops {
>         void            (*init)(struct clk_hw *hw);
>  };
>  
> +struct regmap;
> +
>  /**
>   * struct clk_init_data - holds init data that's common to all clocks and is
>   * shared between the clock provider and the common clock framework.
> @@ -151,6 +153,7 @@ struct clk_ops {
>   * @parent_names: array of string names for all possible parents
>   * @num_parents: number of possible parents
>   * @flags: framework-level hints and quirks
> + * @regmap: regmap to use for regmap helpers and/or by providers
>   */
>  struct clk_init_data {
>         const char              *name;
> @@ -158,6 +161,7 @@ struct clk_init_data {
>         const char              **parent_names;
>         u8                      num_parents;
>         unsigned long           flags;
> +       struct regmap           *regmap;
>  };
>  
>  /**
> @@ -171,10 +175,13 @@ struct clk_init_data {
>   *
>   * @init: pointer to struct clk_init_data that contains the init data shared
>   * with the common clock framework.
> + *
> + * @regmap: regmap to use for regmap helpers and/or by providers
>   */
>  struct clk_hw {
>         struct clk *clk;
>         const struct clk_init_data *init;
> +       struct regmap *regmap;
>  };
>  
>  /*
> -- 
> The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
> hosted by The Linux Foundation
> 

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

* Re: [PATCH v4 02/15] clk: Allow drivers to pass in a regmap
  2014-01-09  1:51   ` Mike Turquette
@ 2014-01-09  2:11     ` Stephen Boyd
  2014-01-09 22:12       ` Stephen Boyd
  2014-01-10  5:44       ` Mike Turquette
  2014-01-14  3:54     ` Saravana Kannan
  1 sibling, 2 replies; 34+ messages in thread
From: Stephen Boyd @ 2014-01-09  2:11 UTC (permalink / raw)
  To: Mike Turquette
  Cc: linux-kernel, linux-arm-msm, linux-arm-kernel, Saravana Kannan,
	Mark Brown

On 01/08/14 17:51, Mike Turquette wrote:
> Quoting Stephen Boyd (2013-12-23 17:12:26)
>> Add support to the clock core so that drivers can pass in a
>> regmap. If no regmap is specified try to query the device that's
>> registering the clock for its regmap. This should allow drivers
>> to use the core regmap helpers. This is based on a similar design
>> in the regulator framework.
>>
>> Cc: Mark Brown <broonie@kernel.org>
>> Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
>> ---
>>  drivers/clk/clk.c            | 8 ++++++++
>>  include/linux/clk-provider.h | 7 +++++++
>>  2 files changed, 15 insertions(+)
>>
>> diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
>> index 9ad7b71..5e71f5c 100644
>> --- a/drivers/clk/clk.c
>> +++ b/drivers/clk/clk.c
>> @@ -20,6 +20,7 @@
>>  #include <linux/device.h>
>>  #include <linux/init.h>
>>  #include <linux/sched.h>
>> +#include <linux/regmap.h>
>>  
>>  static DEFINE_SPINLOCK(enable_lock);
>>  static DEFINE_MUTEX(prepare_lock);
>> @@ -1834,6 +1835,13 @@ static int _clk_register(struct device *dev, struct clk_hw *hw, struct clk *clk)
>>         clk->num_parents = hw->init->num_parents;
>>         hw->clk = clk;
>>  
>> +       if (hw->init->regmap)
>> +               hw->regmap = hw->init->regmap;
> Hi Stephen,
>
> The whole series looks good to me except for the placement of the regmap
> details inside struct clk_hw. That structure exists only to hide struct
> clk from the hardware-specific clock structure and I'd not like to set
> the precedent of shoving per-clock data into it.
>
> As an alternative, how about finding a way to put these per-clock regmap
> details into the hardware-specific clock structure? I understand that
> you want to make these ops available to others, which is why they are in
> the public struct clk_hw. I'm just wondering if that is the right way to
> do it...

The regulator framework has gone this way. It seemed like a similar
approach in the clock framework would be the right way to go too.

>
> Patch #3 illustrates the sort of struct-member-creep that worries me.
> What is to stop someone from putting "unsigned int divider_reg" or
> "unsigned int mux_reg", and then the thing just keeps growing.
>

I see two ways forward if you don't want these members in struct clk_hw.

1) Inheritance: struct clk_regmap wrapper struct and
clk_register_regmap() and devm_clk_register_regmap() and then another
wrapper struct around that.

 example:

struct clk_regmap {
        struct clk_hw hw;
        struct regmap *regmap;
        unsigned int enable_reg;
        unsigned int enable_mask;
        bool enable_is_inverted;
};

struct clk_branch {
        u32     hwcg_reg;
        u32     halt_reg;
        u8      hwcg_bit;
        u8      halt_bit;
        u8      halt_check;

        struct clk_regmap       clkr;
};

static struct clk_branch gsbi1_uart_clk = {
        .halt_reg = 0x2fcc,
        .halt_bit = 10,
        .clkr = {
                .enable_reg = 0x29d4,
                .enable_mask = BIT(9),
                .hw.init = &(struct clk_init_data){
                        .name = "gsbi1_uart_clk",
                        .parent_names = (const char *[]){
                                "gsbi1_uart_src",
                        },
                        .num_parents = 1,
                        .ops = &clk_branch_ops,
                        .flags = CLK_SET_RATE_PARENT,
                },
        },
};


2) Interfaces: Add a void *data in struct clk_hw that can point to
whatever I want and still have the same clk_regmap_register() and
devm_clk_regmap_register()

Example:

struct clk_hw {
        struct clk *clk;
        const struct clk_init_data *init;
        void *data;
};

struct clk_regmap {
        struct regmap *regmap;
        unsigned int enable_reg;
        unsigned int enable_mask;
        bool enable_is_inverted;
};

struct clk_branch {
        u32     hwcg_reg;
        u32     halt_reg;
        u8      hwcg_bit;
        u8      halt_bit;
        u8      halt_check;

        struct clk_hw;
};

static struct clk_branch gsbi1_uart_clk = {
        .halt_reg = 0x2fcc,
        .halt_bit = 10,
        .hw = {
                .data = &(struct clk_regmap){
                        .enable_reg = 0x29d4,
                        .enable_mask = BIT(9),
                 };
                .init = &(struct clk_init_data){
                        .name = "gsbi1_uart_clk",
                        .parent_names = (const char *[]){
                                "gsbi1_uart_src",
                        },
                        .num_parents = 1,
                        .ops = &clk_branch_ops,
                        .flags = CLK_SET_RATE_PARENT,
                },
        },
};

I guess option 2 is less likely given your comment about clk_hw being
nothing more than a traversal mechanism.

-- 
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
hosted by The Linux Foundation

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

* Re: [PATCH v4 02/15] clk: Allow drivers to pass in a regmap
  2014-01-09  2:11     ` Stephen Boyd
@ 2014-01-09 22:12       ` Stephen Boyd
  2014-01-10  5:44       ` Mike Turquette
  1 sibling, 0 replies; 34+ messages in thread
From: Stephen Boyd @ 2014-01-09 22:12 UTC (permalink / raw)
  To: Mike Turquette
  Cc: linux-kernel, linux-arm-msm, linux-arm-kernel, Saravana Kannan,
	Mark Brown

On 01/08/14 18:11, Stephen Boyd wrote:
> On 01/08/14 17:51, Mike Turquette wrote:
>> Patch #3 illustrates the sort of struct-member-creep that worries me.
>> What is to stop someone from putting "unsigned int divider_reg" or
>> "unsigned int mux_reg", and then the thing just keeps growing.
>>
> I see two ways forward if you don't want these members in struct clk_hw.
>
> 1) Inheritance: struct clk_regmap wrapper struct and
> clk_register_regmap() and devm_clk_register_regmap() and then another
> wrapper struct around that.
>
>  example:
>
> struct clk_regmap {
>         struct clk_hw hw;
>         struct regmap *regmap;
>         unsigned int enable_reg;
>         unsigned int enable_mask;
>         bool enable_is_inverted;
> };
>
> struct clk_branch {
>         u32     hwcg_reg;
>         u32     halt_reg;
>         u8      hwcg_bit;
>         u8      halt_bit;
>         u8      halt_check;
>
>         struct clk_regmap       clkr;
> };
>
> static struct clk_branch gsbi1_uart_clk = {
>         .halt_reg = 0x2fcc,
>         .halt_bit = 10,
>         .clkr = {
>                 .enable_reg = 0x29d4,
>                 .enable_mask = BIT(9),
>                 .hw.init = &(struct clk_init_data){
>                         .name = "gsbi1_uart_clk",
>                         .parent_names = (const char *[]){
>                                 "gsbi1_uart_src",
>                         },
>                         .num_parents = 1,
>                         .ops = &clk_branch_ops,
>                         .flags = CLK_SET_RATE_PARENT,
>                 },
>         },
> };

The downside to this approach is that we have to have two similar
structs for struct clk_gate if we want to support regmap in that code
path. If we put the regmap inside struct clk_hw we don't have two
different structs, we would just assign different ops.

struct clk_gate {
        struct clk_hw hw;
        void __iomem    *reg;
        u8              bit_idx;
        u8              flags;
        spinlock_t      *lock;
};

and

struct clk_gate_regmap {
        struct clk_regmap hw;
        u8              flags;
        spinlock_t      *lock;
};

Do you have any preference on which way we move forward here? I have the
wrapper method all finished and ready to send if you agree with that
approach.

-- 
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
hosted by The Linux Foundation

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

* Re: [PATCH v4 02/15] clk: Allow drivers to pass in a regmap
  2014-01-09  2:11     ` Stephen Boyd
  2014-01-09 22:12       ` Stephen Boyd
@ 2014-01-10  5:44       ` Mike Turquette
  2014-01-10  7:05         ` Stephen Boyd
  1 sibling, 1 reply; 34+ messages in thread
From: Mike Turquette @ 2014-01-10  5:44 UTC (permalink / raw)
  To: Stephen Boyd
  Cc: linux-arm-msm, Mark Brown, Saravana Kannan, linux-kernel,
	linux-arm-kernel

Quoting Stephen Boyd (2014-01-08 18:11:40)
> On 01/08/14 17:51, Mike Turquette wrote:
> > Quoting Stephen Boyd (2013-12-23 17:12:26)
> >> Add support to the clock core so that drivers can pass in a
> >> regmap. If no regmap is specified try to query the device that's
> >> registering the clock for its regmap. This should allow drivers
> >> to use the core regmap helpers. This is based on a similar design
> >> in the regulator framework.
> >>
> >> Cc: Mark Brown <broonie@kernel.org>
> >> Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
> >> ---
> >>  drivers/clk/clk.c            | 8 ++++++++
> >>  include/linux/clk-provider.h | 7 +++++++
> >>  2 files changed, 15 insertions(+)
> >>
> >> diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
> >> index 9ad7b71..5e71f5c 100644
> >> --- a/drivers/clk/clk.c
> >> +++ b/drivers/clk/clk.c
> >> @@ -20,6 +20,7 @@
> >>  #include <linux/device.h>
> >>  #include <linux/init.h>
> >>  #include <linux/sched.h>
> >> +#include <linux/regmap.h>
> >>  
> >>  static DEFINE_SPINLOCK(enable_lock);
> >>  static DEFINE_MUTEX(prepare_lock);
> >> @@ -1834,6 +1835,13 @@ static int _clk_register(struct device *dev, struct clk_hw *hw, struct clk *clk)
> >>         clk->num_parents = hw->init->num_parents;
> >>         hw->clk = clk;
> >>  
> >> +       if (hw->init->regmap)
> >> +               hw->regmap = hw->init->regmap;
> > Hi Stephen,
> >
> > The whole series looks good to me except for the placement of the regmap
> > details inside struct clk_hw. That structure exists only to hide struct
> > clk from the hardware-specific clock structure and I'd not like to set
> > the precedent of shoving per-clock data into it.
> >
> > As an alternative, how about finding a way to put these per-clock regmap
> > details into the hardware-specific clock structure? I understand that
> > you want to make these ops available to others, which is why they are in
> > the public struct clk_hw. I'm just wondering if that is the right way to
> > do it...
> 
> The regulator framework has gone this way. It seemed like a similar
> approach in the clock framework would be the right way to go too.
> 
> >
> > Patch #3 illustrates the sort of struct-member-creep that worries me.
> > What is to stop someone from putting "unsigned int divider_reg" or
> > "unsigned int mux_reg", and then the thing just keeps growing.
> >
> 
> I see two ways forward if you don't want these members in struct clk_hw.
> 
> 1) Inheritance: struct clk_regmap wrapper struct and
> clk_register_regmap() and devm_clk_register_regmap() and then another
> wrapper struct around that.
> 
>  example:
> 
> struct clk_regmap {
>         struct clk_hw hw;
>         struct regmap *regmap;
>         unsigned int enable_reg;
>         unsigned int enable_mask;
>         bool enable_is_inverted;
> };
> 
> struct clk_branch {
>         u32     hwcg_reg;
>         u32     halt_reg;
>         u8      hwcg_bit;
>         u8      halt_bit;
>         u8      halt_check;
> 
>         struct clk_regmap       clkr;
> };
> 
> static struct clk_branch gsbi1_uart_clk = {
>         .halt_reg = 0x2fcc,
>         .halt_bit = 10,
>         .clkr = {
>                 .enable_reg = 0x29d4,
>                 .enable_mask = BIT(9),
>                 .hw.init = &(struct clk_init_data){
>                         .name = "gsbi1_uart_clk",
>                         .parent_names = (const char *[]){
>                                 "gsbi1_uart_src",
>                         },
>                         .num_parents = 1,
>                         .ops = &clk_branch_ops,
>                         .flags = CLK_SET_RATE_PARENT,
>                 },
>         },
> };

If we're going to use these wrappers, why make it regmap specific? The
struct clk_desc patches[1][2] can achieve this, but in a more generic
way.

> 
> 
> 2) Interfaces: Add a void *data in struct clk_hw that can point to
> whatever I want and still have the same clk_regmap_register() and
> devm_clk_regmap_register()
> 
> Example:
> 
> struct clk_hw {
>         struct clk *clk;
>         const struct clk_init_data *init;
>         void *data;
> };
> 
> struct clk_regmap {
>         struct regmap *regmap;
>         unsigned int enable_reg;
>         unsigned int enable_mask;
>         bool enable_is_inverted;
> };
> 
> struct clk_branch {
>         u32     hwcg_reg;
>         u32     halt_reg;
>         u8      hwcg_bit;
>         u8      halt_bit;
>         u8      halt_check;
> 
>         struct clk_hw;
> };
> 
> static struct clk_branch gsbi1_uart_clk = {
>         .halt_reg = 0x2fcc,
>         .halt_bit = 10,
>         .hw = {
>                 .data = &(struct clk_regmap){
>                         .enable_reg = 0x29d4,
>                         .enable_mask = BIT(9),
>                  };
>                 .init = &(struct clk_init_data){
>                         .name = "gsbi1_uart_clk",
>                         .parent_names = (const char *[]){
>                                 "gsbi1_uart_src",
>                         },
>                         .num_parents = 1,
>                         .ops = &clk_branch_ops,
>                         .flags = CLK_SET_RATE_PARENT,
>                 },
>         },
> };
> 
> I guess option 2 is less likely given your comment about clk_hw being
> nothing more than a traversal mechanism.

Instead of private data, how about a .register() callback function that
can point to anything you like? The clk_desc patches implement this and
it would suffice for registering regmap ops or anything else, without
polluting struct clk_hw.

[1] http://www.spinics.net/lists/linux-omap/msg101822.html
[2] http://www.spinics.net/lists/linux-omap/msg101698.html

So you could statically define gsbi1_uart_clk with:

static struct clk_branch_desc gsbi1_uart_clk_desc = {
	.halt_reg = 0x2fcc,
	.halt_bit = 10,
	.enable_reg = 0x29d4,
	.enable_mask = BIT(9),
	.desc = {
		.name = "gsbi1_uart_clk",
		.parent_names = (const char *[]){
			"gsbi1_uart_src",
		},
		.num_parents = 1,
		.ops = &clk_branch_ops,
		.flags = CLK_SET_RATE_PARENT,
	},
};

And then register it with:

clk_register_desc(NULL, &gsbi1_uart_clk_desc.desc);

This is very analogous to the way that you use use &gsbi1_uart_clk.hw
but it is more generic and also doesn't pollute clk_hw any further. I
also think your static data is quite a bit prettier using this method.

Thoughts?

Regards,
Mike

> 
> -- 
> Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
> hosted by The Linux Foundation
> 

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

* Re: [PATCH v4 02/15] clk: Allow drivers to pass in a regmap
  2014-01-10  5:44       ` Mike Turquette
@ 2014-01-10  7:05         ` Stephen Boyd
  2014-01-14  2:25           ` Stephen Boyd
  2014-01-15  9:28           ` Mike Turquette
  0 siblings, 2 replies; 34+ messages in thread
From: Stephen Boyd @ 2014-01-10  7:05 UTC (permalink / raw)
  To: Mike Turquette
  Cc: linux-kernel, linux-arm-msm, linux-arm-kernel, Saravana Kannan,
	Mark Brown

On 01/09, Mike Turquette wrote:
> If we're going to use these wrappers, why make it regmap specific? The
> struct clk_desc patches[1][2] can achieve this, but in a more generic
> way.
> 

I think you're suggesting a way to avoid adding a
clk_register_regmap() function? But won't we need to write the
same code:

        if (dev && dev_get_regmap(dev, NULL))
                [clk_type]->regmap = dev_get_regmap(dev, NULL);
        else if (dev && dev->parent)
                [clk_type]->regmap = dev_get_regmap(dev->parent, NULL);

everytime we want to assign the regmap pointer to a different clock type?
A macro might work for this little snippet, but it wouldn't have
any type safety.

> > 
> > 
> > 2) Interfaces: Add a void *data in struct clk_hw that can point to
> > whatever I want and still have the same clk_regmap_register() and
> > devm_clk_regmap_register()
> > 
> > Example:
> > 
> > struct clk_hw {
> >         struct clk *clk;
> >         const struct clk_init_data *init;
> >         void *data;
> > };
> > 
> > struct clk_regmap {
> >         struct regmap *regmap;
> >         unsigned int enable_reg;
> >         unsigned int enable_mask;
> >         bool enable_is_inverted;
> > };
> > 
> > struct clk_branch {
> >         u32     hwcg_reg;
> >         u32     halt_reg;
> >         u8      hwcg_bit;
> >         u8      halt_bit;
> >         u8      halt_check;
> > 
> >         struct clk_hw;
> > };
> > 
> > static struct clk_branch gsbi1_uart_clk = {
> >         .halt_reg = 0x2fcc,
> >         .halt_bit = 10,
> >         .hw = {
> >                 .data = &(struct clk_regmap){
> >                         .enable_reg = 0x29d4,
> >                         .enable_mask = BIT(9),
> >                  };
> >                 .init = &(struct clk_init_data){
> >                         .name = "gsbi1_uart_clk",
> >                         .parent_names = (const char *[]){
> >                                 "gsbi1_uart_src",
> >                         },
> >                         .num_parents = 1,
> >                         .ops = &clk_branch_ops,
> >                         .flags = CLK_SET_RATE_PARENT,
> >                 },
> >         },
> > };
> > 
> > I guess option 2 is less likely given your comment about clk_hw being
> > nothing more than a traversal mechanism.
> 
> Instead of private data, how about a .register() callback function that
> can point to anything you like? The clk_desc patches implement this and
> it would suffice for registering regmap ops or anything else, without
> polluting struct clk_hw.
> 
> [1] http://www.spinics.net/lists/linux-omap/msg101822.html
> [2] http://www.spinics.net/lists/linux-omap/msg101698.html
> 
> So you could statically define gsbi1_uart_clk with:
> 
> static struct clk_branch_desc gsbi1_uart_clk_desc = {
> 	.halt_reg = 0x2fcc,
> 	.halt_bit = 10,
> 	.enable_reg = 0x29d4,
> 	.enable_mask = BIT(9),
> 	.desc = {
> 		.name = "gsbi1_uart_clk",
> 		.parent_names = (const char *[]){
> 			"gsbi1_uart_src",
> 		},
> 		.num_parents = 1,
> 		.ops = &clk_branch_ops,
> 		.flags = CLK_SET_RATE_PARENT,
> 	},
> };
> 
> And then register it with:
> 
> clk_register_desc(NULL, &gsbi1_uart_clk_desc.desc);
> 
> This is very analogous to the way that you use use &gsbi1_uart_clk.hw
> but it is more generic and also doesn't pollute clk_hw any further. I
> also think your static data is quite a bit prettier using this method.
> 
> Thoughts?

Is the plan to allocate a struct clk_branch at runtime and then
copy all the fields over one by one? I'm trying to avoid that
because it takes more time and more runtime memory. If I had to
go the descriptor route I would probably avoid copying any fields
and just point to the descriptor from struct clk_branch, i.e.

 struct clk_branch {
 	struct clk_branch_desc *desc;
	struct clk_hw;
 };

but that still seems wasteful to allocate a bunch of little
pointer wrappers when I could have just embedded the clk_hw
struct inside the clk_branch struct from the start.

It feels another key point is being missed though. The regmap
pointer and the enable_reg/enable_mask is embedded in clk_hw to
allow the same code to be used by different types of surrounding
structs. Each struct: clk_pll, clk_rcg, and clk_branch in this
series use the regmap interface to enable/disable the clock and
they can easily do so by passing something that's always
available from struct clk_hw (be it via a wrapper struct, private
data member, or addition of new fields to clk_hw). If the regmap
members move into each specific type of clock we can't just pass
a single pointer to the enable/disable regmap functions anymore.
This is the reason why I suggested a driver data pointer or
container struct so that everything regmap related is contained
within one type.

-- 
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
hosted by The Linux Foundation

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

* Re: [PATCH v4 02/15] clk: Allow drivers to pass in a regmap
  2014-01-10  7:05         ` Stephen Boyd
@ 2014-01-14  2:25           ` Stephen Boyd
  2014-01-15  9:28           ` Mike Turquette
  1 sibling, 0 replies; 34+ messages in thread
From: Stephen Boyd @ 2014-01-14  2:25 UTC (permalink / raw)
  To: Mike Turquette
  Cc: linux-kernel, linux-arm-msm, linux-arm-kernel, Saravana Kannan,
	Mark Brown

On 01/09/14 23:05, Stephen Boyd wrote:
> It feels another key point is being missed though. The regmap
> pointer and the enable_reg/enable_mask is embedded in clk_hw to
> allow the same code to be used by different types of surrounding
> structs. Each struct: clk_pll, clk_rcg, and clk_branch in this
> series use the regmap interface to enable/disable the clock and
> they can easily do so by passing something that's always
> available from struct clk_hw (be it via a wrapper struct, private
> data member, or addition of new fields to clk_hw). If the regmap
> members move into each specific type of clock we can't just pass
> a single pointer to the enable/disable regmap functions anymore.
> This is the reason why I suggested a driver data pointer or
> container struct so that everything regmap related is contained
> within one type.
>

Any thoughts?

-- 
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
hosted by The Linux Foundation

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

* Re: [PATCH v4 02/15] clk: Allow drivers to pass in a regmap
  2014-01-09  1:51   ` Mike Turquette
  2014-01-09  2:11     ` Stephen Boyd
@ 2014-01-14  3:54     ` Saravana Kannan
  2014-01-15  9:36       ` Mike Turquette
  1 sibling, 1 reply; 34+ messages in thread
From: Saravana Kannan @ 2014-01-14  3:54 UTC (permalink / raw)
  To: Mike Turquette
  Cc: Stephen Boyd, linux-kernel, linux-arm-msm, linux-arm-kernel, Mark Brown

On 01/08/2014 05:51 PM, Mike Turquette wrote:
> Quoting Stephen Boyd (2013-12-23 17:12:26)
>> Add support to the clock core so that drivers can pass in a
>> regmap. If no regmap is specified try to query the device that's
>> registering the clock for its regmap. This should allow drivers
>> to use the core regmap helpers. This is based on a similar design
>> in the regulator framework.
>>
>> Cc: Mark Brown <broonie@kernel.org>
>> Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
>> ---
>>   drivers/clk/clk.c            | 8 ++++++++
>>   include/linux/clk-provider.h | 7 +++++++
>>   2 files changed, 15 insertions(+)
>>
>> diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
>> index 9ad7b71..5e71f5c 100644
>> --- a/drivers/clk/clk.c
>> +++ b/drivers/clk/clk.c
>> @@ -20,6 +20,7 @@
>>   #include <linux/device.h>
>>   #include <linux/init.h>
>>   #include <linux/sched.h>
>> +#include <linux/regmap.h>
>>
>>   static DEFINE_SPINLOCK(enable_lock);
>>   static DEFINE_MUTEX(prepare_lock);
>> @@ -1834,6 +1835,13 @@ static int _clk_register(struct device *dev, struct clk_hw *hw, struct clk *clk)
>>          clk->num_parents = hw->init->num_parents;
>>          hw->clk = clk;
>>
>> +       if (hw->init->regmap)
>> +               hw->regmap = hw->init->regmap;
>
> Hi Stephen,
>
> The whole series looks good to me except for the placement of the regmap
> details inside struct clk_hw. That structure exists only to hide struct
> clk from the hardware-specific clock structure and I'd not like to set
> the precedent of shoving per-clock data into it.
>
> As an alternative, how about finding a way to put these per-clock regmap
> details into the hardware-specific clock structure? I understand that
> you want to make these ops available to others, which is why they are in
> the public struct clk_hw. I'm just wondering if that is the right way to
> do it...
>
> Patch #3 illustrates the sort of struct-member-creep that worries me.
> What is to stop someone from putting "unsigned int divider_reg" or
> "unsigned int mux_reg", and then the thing just keeps growing.

I agree with Mike here. This definitely encourages struct field creep if 
more people want to use it.

I talked to Stephen is person and my recommendation is to not have any 
new fields other than struct regmap in clk_hw and remove the above 2 
lines of code.

>> +       else if (dev && dev_get_regmap(dev, NULL))
>> +               hw->regmap = dev_get_regmap(dev, NULL);

Move "struct regmap *regmap" into struct clk_hw (since it's truly 
reusable across clock types and is technically purely HW related) and 
update it from the device's regmap like above.

We can then provide __clk_regmap_enable(regmap, offset, enable_mask) 
helper functions. Then clock specific functions can use the helper. We 
can even a simple macro to generate these wrappers.

#define DEFINE_REGMAP_EN_DIS(clktype) \

int clk_type##_enable(clktype *c, ....) { }
int clk_type##_disable(clktype *c, ....) { }


That to me seems like a reasonable compromise.

Thanks,
Saravana
-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
hosted by The Linux Foundation

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

* Re: [PATCH v4 02/15] clk: Allow drivers to pass in a regmap
  2014-01-10  7:05         ` Stephen Boyd
  2014-01-14  2:25           ` Stephen Boyd
@ 2014-01-15  9:28           ` Mike Turquette
  2014-01-15 19:03             ` Stephen Boyd
  1 sibling, 1 reply; 34+ messages in thread
From: Mike Turquette @ 2014-01-15  9:28 UTC (permalink / raw)
  To: Stephen Boyd
  Cc: linux-arm-msm, Mark Brown, Saravana Kannan, linux-kernel,
	linux-arm-kernel

Quoting Stephen Boyd (2014-01-09 23:05:17)
> On 01/09, Mike Turquette wrote:
> > If we're going to use these wrappers, why make it regmap specific? The
> > struct clk_desc patches[1][2] can achieve this, but in a more generic
> > way.
> > 
> 
> I think you're suggesting a way to avoid adding a
> clk_register_regmap() function? But won't we need to write the
> same code:
> 
>         if (dev && dev_get_regmap(dev, NULL))
>                 [clk_type]->regmap = dev_get_regmap(dev, NULL);
>         else if (dev && dev->parent)
>                 [clk_type]->regmap = dev_get_regmap(dev->parent, NULL);
> 
> everytime we want to assign the regmap pointer to a different clock type?
> A macro might work for this little snippet, but it wouldn't have
> any type safety.

Hi Stephen,

Avoiding a new clk_register_regmap() function is one thing worth doing.
But additionally I think that this regmap infrastructure in the core
code still is not the right way forward.

Looking at patch #3 I can already see how those helper functions will
grow just like the basic clock type implementations. Take a look at
drivers/clk/clk-divider.c and check out the HIWORD_MASK stuff. That
really shouldn't belong there, but multiple platforms are using the
Designware IP that needs this so in the Name Of Consolidation it was
done. Basically that code is gross.

A more relevant example: look at the gate clock with a busy bit
implementation in arch/arm/mach-imx/clk-gate2.c. The same could be done
for your clk_enable_regmap() function: someone could subclass it and add
a busy bit or status bit to poll on. But should they? The extra layer of
indirection buys us nothing and takes a clean piece of code and
complicates it.

I'd rather your .enable, .disable and .is_enabled implementations live
in drivers/clk/msm/ so that we can avoid this sort of feature creep in
the future. It's perfectly fine if others implement the same code in
their clock drivers.

With all of that said, then there is no point in keeping struct regmap
*regmap inside of struct clk_hw. It can be moved inside of your struct
clk_rcg, struct clk_branch and struct clk_pll definitions.

> 
> > > 
> > > 
> > > 2) Interfaces: Add a void *data in struct clk_hw that can point to
> > > whatever I want and still have the same clk_regmap_register() and
> > > devm_clk_regmap_register()
> > > 
> > > Example:
> > > 
> > > struct clk_hw {
> > >         struct clk *clk;
> > >         const struct clk_init_data *init;
> > >         void *data;
> > > };
> > > 
> > > struct clk_regmap {
> > >         struct regmap *regmap;
> > >         unsigned int enable_reg;
> > >         unsigned int enable_mask;
> > >         bool enable_is_inverted;
> > > };
> > > 
> > > struct clk_branch {
> > >         u32     hwcg_reg;
> > >         u32     halt_reg;
> > >         u8      hwcg_bit;
> > >         u8      halt_bit;
> > >         u8      halt_check;
> > > 
> > >         struct clk_hw;
> > > };
> > > 
> > > static struct clk_branch gsbi1_uart_clk = {
> > >         .halt_reg = 0x2fcc,
> > >         .halt_bit = 10,
> > >         .hw = {
> > >                 .data = &(struct clk_regmap){
> > >                         .enable_reg = 0x29d4,
> > >                         .enable_mask = BIT(9),
> > >                  };
> > >                 .init = &(struct clk_init_data){
> > >                         .name = "gsbi1_uart_clk",
> > >                         .parent_names = (const char *[]){
> > >                                 "gsbi1_uart_src",
> > >                         },
> > >                         .num_parents = 1,
> > >                         .ops = &clk_branch_ops,
> > >                         .flags = CLK_SET_RATE_PARENT,
> > >                 },
> > >         },
> > > };
> > > 
> > > I guess option 2 is less likely given your comment about clk_hw being
> > > nothing more than a traversal mechanism.
> > 
> > Instead of private data, how about a .register() callback function that
> > can point to anything you like? The clk_desc patches implement this and
> > it would suffice for registering regmap ops or anything else, without
> > polluting struct clk_hw.
> > 
> > [1] http://www.spinics.net/lists/linux-omap/msg101822.html
> > [2] http://www.spinics.net/lists/linux-omap/msg101698.html
> > 
> > So you could statically define gsbi1_uart_clk with:
> > 
> > static struct clk_branch_desc gsbi1_uart_clk_desc = {
> >       .halt_reg = 0x2fcc,
> >       .halt_bit = 10,
> >       .enable_reg = 0x29d4,
> >       .enable_mask = BIT(9),
> >       .desc = {
> >               .name = "gsbi1_uart_clk",
> >               .parent_names = (const char *[]){
> >                       "gsbi1_uart_src",
> >               },
> >               .num_parents = 1,
> >               .ops = &clk_branch_ops,
> >               .flags = CLK_SET_RATE_PARENT,
> >       },
> > };
> > 
> > And then register it with:
> > 
> > clk_register_desc(NULL, &gsbi1_uart_clk_desc.desc);
> > 
> > This is very analogous to the way that you use use &gsbi1_uart_clk.hw
> > but it is more generic and also doesn't pollute clk_hw any further. I
> > also think your static data is quite a bit prettier using this method.
> > 
> > Thoughts?
> 
> Is the plan to allocate a struct clk_branch at runtime and then
> copy all the fields over one by one? I'm trying to avoid that
> because it takes more time and more runtime memory. If I had to
> go the descriptor route I would probably avoid copying any fields
> and just point to the descriptor from struct clk_branch, i.e.
> 
>  struct clk_branch {
>         struct clk_branch_desc *desc;
>         struct clk_hw;
>  };
> 
> but that still seems wasteful to allocate a bunch of little
> pointer wrappers when I could have just embedded the clk_hw
> struct inside the clk_branch struct from the start.
> 

The pointer copy stuff was done so that every instance of struct
clk_init_data could be marked as __initdata.

> It feels another key point is being missed though. The regmap
> pointer and the enable_reg/enable_mask is embedded in clk_hw to
> allow the same code to be used by different types of surrounding
> structs. Each struct: clk_pll, clk_rcg, and clk_branch in this
> series use the regmap interface to enable/disable the clock and
> they can easily do so by passing something that's always
> available from struct clk_hw (be it via a wrapper struct, private
> data member, or addition of new fields to clk_hw). If the regmap
> members move into each specific type of clock we can't just pass
> a single pointer to the enable/disable regmap functions anymore.
> This is the reason why I suggested a driver data pointer or
> container struct so that everything regmap related is contained
> within one type.

I get understand the goal of reuse and I applaud it. But even if we did
pack the regmap data into struct clk_hw it would start to grow out of
control as I mentioned in a previous email. In order for this to work
you have to package more than just struct regmap *regmap into struct
clk_hw. You need the register offset as well as any relevant masks and
bit field values. And then you need more stuff for muxes and dividers.
And hey now you need busy/poll register values and another platform
needs to program shadow registers before flipping the Go Bit ... the
list goes on and on.

So in summary: consolidation is over-rated. You can put your regmap
functions into drivers/clk/msm/ and not convert over to struct clk_desc
by the way, just to remove any confusion on that point.

> 
> -- 
> Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
> hosted by The Linux Foundation

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

* Re: [PATCH v4 02/15] clk: Allow drivers to pass in a regmap
  2014-01-14  3:54     ` Saravana Kannan
@ 2014-01-15  9:36       ` Mike Turquette
  2014-01-15 10:54         ` Mark Brown
  2014-01-17  1:38         ` Saravana Kannan
  0 siblings, 2 replies; 34+ messages in thread
From: Mike Turquette @ 2014-01-15  9:36 UTC (permalink / raw)
  To: Saravana Kannan
  Cc: linux-arm-msm, Mark Brown, Stephen Boyd, linux-kernel, linux-arm-kernel

Quoting Saravana Kannan (2014-01-13 19:54:42)
> On 01/08/2014 05:51 PM, Mike Turquette wrote:
> > Quoting Stephen Boyd (2013-12-23 17:12:26)
> >> Add support to the clock core so that drivers can pass in a
> >> regmap. If no regmap is specified try to query the device that's
> >> registering the clock for its regmap. This should allow drivers
> >> to use the core regmap helpers. This is based on a similar design
> >> in the regulator framework.
> >>
> >> Cc: Mark Brown <broonie@kernel.org>
> >> Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
> >> ---
> >>   drivers/clk/clk.c            | 8 ++++++++
> >>   include/linux/clk-provider.h | 7 +++++++
> >>   2 files changed, 15 insertions(+)
> >>
> >> diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
> >> index 9ad7b71..5e71f5c 100644
> >> --- a/drivers/clk/clk.c
> >> +++ b/drivers/clk/clk.c
> >> @@ -20,6 +20,7 @@
> >>   #include <linux/device.h>
> >>   #include <linux/init.h>
> >>   #include <linux/sched.h>
> >> +#include <linux/regmap.h>
> >>
> >>   static DEFINE_SPINLOCK(enable_lock);
> >>   static DEFINE_MUTEX(prepare_lock);
> >> @@ -1834,6 +1835,13 @@ static int _clk_register(struct device *dev, struct clk_hw *hw, struct clk *clk)
> >>          clk->num_parents = hw->init->num_parents;
> >>          hw->clk = clk;
> >>
> >> +       if (hw->init->regmap)
> >> +               hw->regmap = hw->init->regmap;
> >
> > Hi Stephen,
> >
> > The whole series looks good to me except for the placement of the regmap
> > details inside struct clk_hw. That structure exists only to hide struct
> > clk from the hardware-specific clock structure and I'd not like to set
> > the precedent of shoving per-clock data into it.
> >
> > As an alternative, how about finding a way to put these per-clock regmap
> > details into the hardware-specific clock structure? I understand that
> > you want to make these ops available to others, which is why they are in
> > the public struct clk_hw. I'm just wondering if that is the right way to
> > do it...
> >
> > Patch #3 illustrates the sort of struct-member-creep that worries me.
> > What is to stop someone from putting "unsigned int divider_reg" or
> > "unsigned int mux_reg", and then the thing just keeps growing.
> 
> I agree with Mike here. This definitely encourages struct field creep if 
> more people want to use it.
> 
> I talked to Stephen is person and my recommendation is to not have any 
> new fields other than struct regmap in clk_hw and remove the above 2 
> lines of code.
> 
> >> +       else if (dev && dev_get_regmap(dev, NULL))
> >> +               hw->regmap = dev_get_regmap(dev, NULL);
> 
> Move "struct regmap *regmap" into struct clk_hw (since it's truly 
> reusable across clock types and is technically purely HW related) and 
> update it from the device's regmap like above.

Hi Saravana,

Thanks for your comments. In the paragraph above you mean "struct
clk_hw" or do you mean the hardware-specific structure(s) defined in a
clock driver?

> 
> We can then provide __clk_regmap_enable(regmap, offset, enable_mask) 
> helper functions. Then clock specific functions can use the helper. We 
> can even a simple macro to generate these wrappers.
> 
> #define DEFINE_REGMAP_EN_DIS(clktype) \
> 
> int clk_type##_enable(clktype *c, ....) { }
> int clk_type##_disable(clktype *c, ....) { }
> 
> 
> That to me seems like a reasonable compromise.

Providing common functions for the basic case (e.g. read-modify-write on
a register using a known mask) is reasonable. But that is exactly what
the existing basic clock types do (sans regmap) and they have all become
pretty ugly over time. And the clk-composite implementation just makes
me a sad panda.

I'm not opposed to providing public implementations of clk_ops callbacks
that use regmap, but I will be very mindful of any feature creep in the
future.

I am still unconvinced that adding struct regmap to struct clk_hw is a
good idea. The regmap data is a function of hardware-specific details
and those details always have and always will belong in the clock
driver.

Regards,
Mike

> 
> Thanks,
> Saravana
> -- 
> The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
> hosted by The Linux Foundation

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

* Re: [PATCH v4 02/15] clk: Allow drivers to pass in a regmap
  2014-01-15  9:36       ` Mike Turquette
@ 2014-01-15 10:54         ` Mark Brown
  2014-01-17  1:38         ` Saravana Kannan
  1 sibling, 0 replies; 34+ messages in thread
From: Mark Brown @ 2014-01-15 10:54 UTC (permalink / raw)
  To: Mike Turquette
  Cc: Saravana Kannan, Stephen Boyd, linux-kernel, linux-arm-msm,
	linux-arm-kernel

[-- Attachment #1: Type: text/plain, Size: 772 bytes --]

On Wed, Jan 15, 2014 at 01:36:41AM -0800, Mike Turquette wrote:

> Providing common functions for the basic case (e.g. read-modify-write on
> a register using a known mask) is reasonable. But that is exactly what
> the existing basic clock types do (sans regmap) and they have all become
> pretty ugly over time. And the clk-composite implementation just makes
> me a sad panda.

What we've tried to do with regulators is just have multiple helper
functions in the core rather than trying to merge their implementation,
the drivers pick the right one for their usage, and in cases where there
aren't many drivers doing the same thing we just have the driver either
copy the bits of the implementation they reuse or call the helper
function from within the implementation.

[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 836 bytes --]

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

* Re: [PATCH v4 02/15] clk: Allow drivers to pass in a regmap
  2014-01-15  9:28           ` Mike Turquette
@ 2014-01-15 19:03             ` Stephen Boyd
  0 siblings, 0 replies; 34+ messages in thread
From: Stephen Boyd @ 2014-01-15 19:03 UTC (permalink / raw)
  To: Mike Turquette
  Cc: linux-kernel, linux-arm-msm, linux-arm-kernel, Saravana Kannan,
	Mark Brown

On 01/15, Mike Turquette wrote:
> 
> So in summary: consolidation is over-rated. You can put your regmap
> functions into drivers/clk/msm/ and not convert over to struct clk_desc
> by the way, just to remove any confusion on that point.
> 

Ok I've made the wrapper struct clk_regmap and posted the
patches. I think I've addressed all your concerns.

-- 
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
hosted by The Linux Foundation

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

* Re: [PATCH v4 02/15] clk: Allow drivers to pass in a regmap
  2014-01-15  9:36       ` Mike Turquette
  2014-01-15 10:54         ` Mark Brown
@ 2014-01-17  1:38         ` Saravana Kannan
  1 sibling, 0 replies; 34+ messages in thread
From: Saravana Kannan @ 2014-01-17  1:38 UTC (permalink / raw)
  To: Mike Turquette
  Cc: Stephen Boyd, linux-kernel, linux-arm-msm, linux-arm-kernel, Mark Brown

On 01/15/2014 01:36 AM, Mike Turquette wrote:
> Quoting Saravana Kannan (2014-01-13 19:54:42)
>> On 01/08/2014 05:51 PM, Mike Turquette wrote:
>>> Quoting Stephen Boyd (2013-12-23 17:12:26)
>>>> Add support to the clock core so that drivers can pass in a
>>>> regmap. If no regmap is specified try to query the device that's
>>>> registering the clock for its regmap. This should allow drivers
>>>> to use the core regmap helpers. This is based on a similar design
>>>> in the regulator framework.
>>>>
>>>> Cc: Mark Brown <broonie@kernel.org>
>>>> Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
>>>> ---
>>>>    drivers/clk/clk.c            | 8 ++++++++
>>>>    include/linux/clk-provider.h | 7 +++++++
>>>>    2 files changed, 15 insertions(+)
>>>>
>>>> diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
>>>> index 9ad7b71..5e71f5c 100644
>>>> --- a/drivers/clk/clk.c
>>>> +++ b/drivers/clk/clk.c
>>>> @@ -20,6 +20,7 @@
>>>>    #include <linux/device.h>
>>>>    #include <linux/init.h>
>>>>    #include <linux/sched.h>
>>>> +#include <linux/regmap.h>
>>>>
>>>>    static DEFINE_SPINLOCK(enable_lock);
>>>>    static DEFINE_MUTEX(prepare_lock);
>>>> @@ -1834,6 +1835,13 @@ static int _clk_register(struct device *dev, struct clk_hw *hw, struct clk *clk)
>>>>           clk->num_parents = hw->init->num_parents;
>>>>           hw->clk = clk;
>>>>
>>>> +       if (hw->init->regmap)
>>>> +               hw->regmap = hw->init->regmap;
>>>
>>> Hi Stephen,
>>>
>>> The whole series looks good to me except for the placement of the regmap
>>> details inside struct clk_hw. That structure exists only to hide struct
>>> clk from the hardware-specific clock structure and I'd not like to set
>>> the precedent of shoving per-clock data into it.
>>>
>>> As an alternative, how about finding a way to put these per-clock regmap
>>> details into the hardware-specific clock structure? I understand that
>>> you want to make these ops available to others, which is why they are in
>>> the public struct clk_hw. I'm just wondering if that is the right way to
>>> do it...
>>>
>>> Patch #3 illustrates the sort of struct-member-creep that worries me.
>>> What is to stop someone from putting "unsigned int divider_reg" or
>>> "unsigned int mux_reg", and then the thing just keeps growing.
>>
>> I agree with Mike here. This definitely encourages struct field creep if
>> more people want to use it.
>>
>> I talked to Stephen is person and my recommendation is to not have any
>> new fields other than struct regmap in clk_hw and remove the above 2
>> lines of code.
>>
>>>> +       else if (dev && dev_get_regmap(dev, NULL))
>>>> +               hw->regmap = dev_get_regmap(dev, NULL);
>>
>> Move "struct regmap *regmap" into struct clk_hw (since it's truly
>> reusable across clock types and is technically purely HW related) and
>> update it from the device's regmap like above.
>
> Hi Saravana,
>
> Thanks for your comments. In the paragraph above you mean "struct
> clk_hw" or do you mean the hardware-specific structure(s) defined in a
> clock driver?
>
>>
>> We can then provide __clk_regmap_enable(regmap, offset, enable_mask)
>> helper functions. Then clock specific functions can use the helper. We
>> can even a simple macro to generate these wrappers.
>>
>> #define DEFINE_REGMAP_EN_DIS(clktype) \
>>
>> int clk_type##_enable(clktype *c, ....) { }
>> int clk_type##_disable(clktype *c, ....) { }
>>
>>
>> That to me seems like a reasonable compromise.
>
> Providing common functions for the basic case (e.g. read-modify-write on
> a register using a known mask) is reasonable. But that is exactly what
> the existing basic clock types do (sans regmap) and they have all become
> pretty ugly over time. And the clk-composite implementation just makes
> me a sad panda.
>
> I'm not opposed to providing public implementations of clk_ops callbacks
> that use regmap, but I will be very mindful of any feature creep in the
> future.
>
> I am still unconvinced that adding struct regmap to struct clk_hw is a
> good idea. The regmap data is a function of hardware-specific details
> and those details always have and always will belong in the clock
> driver

The details of the bits inside the register and how it's used would be 
clock type specific. Meaning, a Vendor X clock gate might have a busy 
bit and Vendor Y clock gate might not have a busy bit.

Regmap doesn't try to consolidate that. I'm not saying those clock gates 
should not be consolidated, but that's not what regmap is trying to do.

Regmap is helpful to consolidate clocks that behave exactly the same 
way, but differ in how the clock registers are accessed. Eg: mem-mapped 
IO, I2C, CP15 read/writes. So, even with a MSM based board, just because 
the way to access the registers are different, we could have to 
implement 3 different clock gate types. Which I think would be the wrong 
thing to do. Regmap cleanly consolidates this because the clock types 
just need to store the offsets and operate on them as usual using regmap 
APIs.

Since the regmap for the clock is assigned based on the device that's 
registering the enable/disable code for a clock gate can be agnostic of 
how the registers are accesses. Yes, regmap does provide helpers for 
read/modify writes, but that's not the main reason for using it.

Btw, this is a very real case on MSMs. The CPU clocks are accesses thru 
CP15 instructions, and the other clock trees are accessed through 
mem-mapped IO. But they pretty much behave the same way. That's what reg 
map is solving.

And I think this is a common problem for ANY clock type that one might 
implement. Which is why I think it should be in some common clock 
struct. The clock drivers will need access to the regmap. So, I picked 
clk_hw (the struct defined by the clock framework) and not struct clk. 
This also allows for the framework registration code to go populate the 
regmap pointer for all clocks from the regmap of the device.

Thoughts?

Thanks,
Saravana

-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
hosted by The Linux Foundation

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

end of thread, other threads:[~2014-01-17  1:38 UTC | newest]

Thread overview: 34+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2013-12-24  1:12 [PATCH v4 00/15] Add support for MSM's mmio clock/reset controller Stephen Boyd
2013-12-24  1:12 ` [PATCH v4 01/15] reset: Silence warning in reset-controller.h Stephen Boyd
2014-01-06 17:28   ` Philipp Zabel
2013-12-24  1:12 ` [PATCH v4 02/15] clk: Allow drivers to pass in a regmap Stephen Boyd
2013-12-24 13:13   ` Mark Brown
2014-01-09  1:51   ` Mike Turquette
2014-01-09  2:11     ` Stephen Boyd
2014-01-09 22:12       ` Stephen Boyd
2014-01-10  5:44       ` Mike Turquette
2014-01-10  7:05         ` Stephen Boyd
2014-01-14  2:25           ` Stephen Boyd
2014-01-15  9:28           ` Mike Turquette
2014-01-15 19:03             ` Stephen Boyd
2014-01-14  3:54     ` Saravana Kannan
2014-01-15  9:36       ` Mike Turquette
2014-01-15 10:54         ` Mark Brown
2014-01-17  1:38         ` Saravana Kannan
2013-12-24  1:12 ` [PATCH v4 03/15] clk: Add regmap core helpers for enable/disable/is_enabled Stephen Boyd
2013-12-24 13:14   ` Mark Brown
2013-12-24 15:07   ` Gerhard Sittig
2013-12-26 19:31     ` Stephen Boyd
2013-12-31 13:02       ` Gerhard Sittig
2013-12-24  1:12 ` [PATCH v4 04/15] clk: Add set_rate_and_parent() op Stephen Boyd
2013-12-24  1:12 ` [PATCH v4 05/15] clk: qcom: Add support for phase locked loops (PLLs) Stephen Boyd
2013-12-24  1:12 ` [PATCH v4 06/15] clk: qcom: Add support for root clock generators (RCGs) Stephen Boyd
2013-12-24  1:12 ` [PATCH v4 07/15] clk: qcom: Add support for branches/gate clocks Stephen Boyd
2013-12-24  1:12 ` [PATCH v4 08/15] clk: qcom: Add reset controller support Stephen Boyd
2013-12-24  1:12 ` [PATCH v4 09/15] clk: qcom: Add support for MSM8960's global clock controller (GCC) Stephen Boyd
2013-12-24  1:12 ` [PATCH v4 10/15] clk: qcom: Add support for MSM8960's multimedia clock controller (MMCC) Stephen Boyd
2013-12-24  1:12 ` [PATCH v4 11/15] clk: qcom: Add support for MSM8974's global clock controller (GCC) Stephen Boyd
2013-12-24  1:12 ` [PATCH v4 12/15] clk: qcom: Add support for MSM8974's multimedia clock controller (MMCC) Stephen Boyd
2013-12-24  1:12 ` [PATCH v4 13/15] clk: qcom: Add support for MSM8660's global clock controller (GCC) Stephen Boyd
2013-12-24  1:12 ` [PATCH v4 14/15] devicetree: bindings: Document qcom,gcc Stephen Boyd
2013-12-24  1:12 ` [PATCH v4 15/15] devicetree: bindings: Document qcom,mmcc Stephen Boyd

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).