* [PATCH v2 0/9] Add support for MSM's mmio clocks
@ 2013-10-02 19:06 Stephen Boyd
2013-10-02 19:06 ` [PATCH v2 1/9] clk: Allow drivers to pass in a regmap Stephen Boyd
` (8 more replies)
0 siblings, 9 replies; 10+ messages in thread
From: Stephen Boyd @ 2013-10-02 19:06 UTC (permalink / raw)
To: linux-arm-kernel
The first 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. The GCC 8974 driver is mostly finished but I didn't do the full
treatment on 8960 just yet.
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
Some starter questions:
1) The clock controller is also a reset and power domain controller.
Should we put that code in the drivers under drivers/clk/msm?
2) Should the directory be renamed to qcom to match the binding?
3) What is the right place for clock dt binding #defines? clk/ or clock/?
Stephen Boyd (9):
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: msm: Add support for phase locked loops (PLLs)
clk: msm: Add support for root clock generators (RCGs)
clk: msm: Add support for branches/gate clocks
clk: msm: Add support for MSM8960's global clock controller (GCC)
clk: msm: Add support for MSM8960's multimedia clock controller (MMCC)
clk: msm: Add support for MSM8974's global clock controller (GCC)
Documentation/clk.txt | 3 +
.../devicetree/bindings/clock/qcom,gcc.txt | 20 +
.../devicetree/bindings/clock/qcom,mmcc.txt | 19 +
drivers/clk/Kconfig | 2 +
drivers/clk/Makefile | 1 +
drivers/clk/clk.c | 156 +-
drivers/clk/msm/Kconfig | 29 +
drivers/clk/msm/Makefile | 10 +
drivers/clk/msm/clk-branch.c | 153 ++
drivers/clk/msm/clk-branch.h | 50 +
drivers/clk/msm/clk-pll.c | 147 ++
drivers/clk/msm/clk-pll.h | 45 +
drivers/clk/msm/clk-rcg.c | 491 ++++
drivers/clk/msm/clk-rcg.h | 149 ++
drivers/clk/msm/clk-rcg2.c | 272 +++
drivers/clk/msm/gcc-8960.c | 381 +++
drivers/clk/msm/gcc-8974.c | 2488 ++++++++++++++++++++
drivers/clk/msm/mmcc-8960.c | 297 +++
include/dt-bindings/clk/msm-gcc-8960.h | 28 +
include/dt-bindings/clk/msm-gcc-8974.h | 154 ++
include/dt-bindings/clk/msm-mmcc-8960.h | 24 +
include/linux/clk-provider.h | 35 +
22 files changed, 4935 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/msm/Kconfig
create mode 100644 drivers/clk/msm/Makefile
create mode 100644 drivers/clk/msm/clk-branch.c
create mode 100644 drivers/clk/msm/clk-branch.h
create mode 100644 drivers/clk/msm/clk-pll.c
create mode 100644 drivers/clk/msm/clk-pll.h
create mode 100644 drivers/clk/msm/clk-rcg.c
create mode 100644 drivers/clk/msm/clk-rcg.h
create mode 100644 drivers/clk/msm/clk-rcg2.c
create mode 100644 drivers/clk/msm/gcc-8960.c
create mode 100644 drivers/clk/msm/gcc-8974.c
create mode 100644 drivers/clk/msm/mmcc-8960.c
create mode 100644 include/dt-bindings/clk/msm-gcc-8960.h
create mode 100644 include/dt-bindings/clk/msm-gcc-8974.h
create mode 100644 include/dt-bindings/clk/msm-mmcc-8960.h
--
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
hosted by The Linux Foundation
^ permalink raw reply [flat|nested] 10+ messages in thread
* [PATCH v2 1/9] clk: Allow drivers to pass in a regmap
2013-10-02 19:06 [PATCH v2 0/9] Add support for MSM's mmio clocks Stephen Boyd
@ 2013-10-02 19:06 ` Stephen Boyd
2013-10-02 19:06 ` [PATCH v2 2/9] clk: Add regmap core helpers for enable/disable/is_enabled Stephen Boyd
` (7 subsequent siblings)
8 siblings, 0 replies; 10+ messages in thread
From: Stephen Boyd @ 2013-10-02 19:06 UTC (permalink / raw)
To: 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.
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 a004769..6107daa 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);
@@ -1829,6 +1830,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->parent)
+ hw->regmap = dev_get_regmap(dev->parent, NULL);
+
/* allocate local copy in case parent_names is __initdata */
clk->parent_names = kzalloc((sizeof(char*) * clk->num_parents),
GFP_KERNEL);
diff --git a/include/linux/clk-provider.h b/include/linux/clk-provider.h
index 73bdb69..6ed62f1 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] 10+ messages in thread
* [PATCH v2 2/9] clk: Add regmap core helpers for enable/disable/is_enabled
2013-10-02 19:06 [PATCH v2 0/9] Add support for MSM's mmio clocks Stephen Boyd
2013-10-02 19:06 ` [PATCH v2 1/9] clk: Allow drivers to pass in a regmap Stephen Boyd
@ 2013-10-02 19:06 ` Stephen Boyd
2013-10-02 19:07 ` [PATCH v2 3/9] clk: Add set_rate_and_parent() op Stephen Boyd
` (6 subsequent siblings)
8 siblings, 0 replies; 10+ messages in thread
From: Stephen Boyd @ 2013-10-02 19:06 UTC (permalink / raw)
To: 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.
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 6107daa..7e4519b 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 6ed62f1..4087a9b 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] 10+ messages in thread
* [PATCH v2 3/9] clk: Add set_rate_and_parent() op
2013-10-02 19:06 [PATCH v2 0/9] Add support for MSM's mmio clocks Stephen Boyd
2013-10-02 19:06 ` [PATCH v2 1/9] clk: Allow drivers to pass in a regmap Stephen Boyd
2013-10-02 19:06 ` [PATCH v2 2/9] clk: Add regmap core helpers for enable/disable/is_enabled Stephen Boyd
@ 2013-10-02 19:07 ` Stephen Boyd
2013-10-02 19:07 ` [PATCH v2 4/9] clk: msm: Add support for phase locked loops (PLLs) Stephen Boyd
` (5 subsequent siblings)
8 siblings, 0 replies; 10+ messages in thread
From: Stephen Boyd @ 2013-10-02 19:07 UTC (permalink / raw)
To: 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 7e4519b..a814dd1 100644
--- a/drivers/clk/clk.c
+++ b/drivers/clk/clk.c
@@ -1194,10 +1194,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;
/*
@@ -1228,6 +1227,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);
@@ -1245,18 +1272,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;
}
@@ -1441,17 +1458,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)
@@ -1743,6 +1775,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 4087a9b..2bd6617 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] 10+ messages in thread
* [PATCH v2 4/9] clk: msm: Add support for phase locked loops (PLLs)
2013-10-02 19:06 [PATCH v2 0/9] Add support for MSM's mmio clocks Stephen Boyd
` (2 preceding siblings ...)
2013-10-02 19:07 ` [PATCH v2 3/9] clk: Add set_rate_and_parent() op Stephen Boyd
@ 2013-10-02 19:07 ` Stephen Boyd
2013-10-02 19:07 ` [PATCH v2 5/9] clk: msm: Add support for root clock generators (RCGs) Stephen Boyd
` (4 subsequent siblings)
8 siblings, 0 replies; 10+ messages in thread
From: Stephen Boyd @ 2013-10-02 19:07 UTC (permalink / raw)
To: linux-arm-kernel
Add support for MSM'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/msm/Kconfig | 5 ++
drivers/clk/msm/Makefile | 3 +
drivers/clk/msm/clk-pll.c | 147 ++++++++++++++++++++++++++++++++++++++++++++++
drivers/clk/msm/clk-pll.h | 45 ++++++++++++++
6 files changed, 203 insertions(+)
create mode 100644 drivers/clk/msm/Kconfig
create mode 100644 drivers/clk/msm/Makefile
create mode 100644 drivers/clk/msm/clk-pll.c
create mode 100644 drivers/clk/msm/clk-pll.h
diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig
index 279407a..efb7606 100644
--- a/drivers/clk/Kconfig
+++ b/drivers/clk/Kconfig
@@ -93,6 +93,8 @@ config CLK_PPC_CORENET
This adds the clock driver support for Freescale PowerPC corenet
platforms using common clock framework.
+source "drivers/clk/msm/Kconfig"
+
endmenu
source "drivers/clk/mvebu/Kconfig"
diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile
index 7b11106..6838b07 100644
--- a/drivers/clk/Makefile
+++ b/drivers/clk/Makefile
@@ -20,6 +20,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_MSM) += msm/
obj-$(CONFIG_PLAT_ORION) += mvebu/
ifeq ($(CONFIG_COMMON_CLK), y)
obj-$(CONFIG_ARCH_MMP) += mmp/
diff --git a/drivers/clk/msm/Kconfig b/drivers/clk/msm/Kconfig
new file mode 100644
index 0000000..91558ce
--- /dev/null
+++ b/drivers/clk/msm/Kconfig
@@ -0,0 +1,5 @@
+config COMMON_CLK_MSM
+ tristate "Support for Qualcomm's MSM designs"
+ depends on OF
+ select REGMAP_MMIO
+
diff --git a/drivers/clk/msm/Makefile b/drivers/clk/msm/Makefile
new file mode 100644
index 0000000..16b750f
--- /dev/null
+++ b/drivers/clk/msm/Makefile
@@ -0,0 +1,3 @@
+obj-$(CONFIG_COMMON_CLK_MSM) += clk-msm.o
+
+clk-msm-$(CONFIG_COMMON_CLK_MSM) += clk-pll.o
diff --git a/drivers/clk/msm/clk-pll.c b/drivers/clk/msm/clk-pll.c
new file mode 100644
index 0000000..7470bdd
--- /dev/null
+++ b/drivers/clk/msm/clk-pll.c
@@ -0,0 +1,147 @@
+/*
+ * 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 to_clk_pll(_hw) container_of(_hw, struct clk_pll, hw)
+
+#define PLL_OUTCTRL BIT(0)
+#define PLL_BYPASSNL BIT(1)
+#define PLL_RESET_N BIT(2)
+
+static int clk_pll_enable(struct clk_hw *hw)
+{
+ struct clk_pll *pll = to_clk_pll(hw);
+ int ret;
+
+ /* 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;
+
+ 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("%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);
diff --git a/drivers/clk/msm/clk-pll.h b/drivers/clk/msm/clk-pll.h
new file mode 100644
index 0000000..a15125c
--- /dev/null
+++ b/drivers/clk/msm/clk-pll.h
@@ -0,0 +1,45 @@
+/*
+ * 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;
+
+#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] 10+ messages in thread
* [PATCH v2 5/9] clk: msm: Add support for root clock generators (RCGs)
2013-10-02 19:06 [PATCH v2 0/9] Add support for MSM's mmio clocks Stephen Boyd
` (3 preceding siblings ...)
2013-10-02 19:07 ` [PATCH v2 4/9] clk: msm: Add support for phase locked loops (PLLs) Stephen Boyd
@ 2013-10-02 19:07 ` Stephen Boyd
2013-10-02 19:07 ` [PATCH v2 6/9] clk: msm: Add support for branches/gate clocks Stephen Boyd
` (3 subsequent siblings)
8 siblings, 0 replies; 10+ messages in thread
From: Stephen Boyd @ 2013-10-02 19:07 UTC (permalink / raw)
To: linux-arm-kernel
Add support for the root clock generators on MSM 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/msm/Makefile | 2 +
drivers/clk/msm/clk-rcg.c | 491 +++++++++++++++++++++++++++++++++++++++++++++
drivers/clk/msm/clk-rcg.h | 149 ++++++++++++++
drivers/clk/msm/clk-rcg2.c | 272 +++++++++++++++++++++++++
4 files changed, 914 insertions(+)
create mode 100644 drivers/clk/msm/clk-rcg.c
create mode 100644 drivers/clk/msm/clk-rcg.h
create mode 100644 drivers/clk/msm/clk-rcg2.c
diff --git a/drivers/clk/msm/Makefile b/drivers/clk/msm/Makefile
index 16b750f..fb78ac9 100644
--- a/drivers/clk/msm/Makefile
+++ b/drivers/clk/msm/Makefile
@@ -1,3 +1,5 @@
obj-$(CONFIG_COMMON_CLK_MSM) += clk-msm.o
clk-msm-$(CONFIG_COMMON_CLK_MSM) += clk-pll.o
+clk-msm-$(CONFIG_COMMON_CLK_MSM) += clk-rcg.o
+clk-msm-$(CONFIG_COMMON_CLK_MSM) += clk-rcg2.o
diff --git a/drivers/clk/msm/clk-rcg.c b/drivers/clk/msm/clk-rcg.c
new file mode 100644
index 0000000..15f52d5
--- /dev/null
+++ b/drivers/clk/msm/clk-rcg.c
@@ -0,0 +1,491 @@
+/*
+ * 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"
+
+#define to_clk_rcg(_hw) container_of(_hw, struct clk_rcg, hw)
+
+#define to_clk_dyn_rcg(_hw) container_of(_hw, struct clk_dyn_rcg, hw)
+
+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, n, ns, md, mode;
+ struct mn *mn = &rcg->mn;
+
+ regmap_read(hw->regmap, rcg->ns_reg, &ns);
+ regmap_read(hw->regmap, rcg->md_reg, &md);
+
+ pre_div = ns_to_pre_div(&rcg->p, ns);
+ 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, ®);
+ 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)
+{
+ 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)
+{
+ f = find_freq(f, rate);
+ if (!f)
+ return -EINVAL;
+
+ *p = clk_get_parent_by_index(hw->clk, f->src);
+ *p_rate = __clk_get_rate(*p);
+
+ 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;
+
+ f = find_freq(rcg->freq_tbl, rate);
+ if (!f)
+ return -EINVAL;
+
+ regmap_read(hw->regmap, rcg->ns_reg, &ns);
+ ns |= BIT(mn->mnctr_reset_bit);
+ regmap_write(hw->regmap, rcg->ns_reg, ns);
+
+ 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);
+
+ /* 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);
+ ns = pre_div_to_ns(&rcg->p, f->pre_div - 1, ns);
+ regmap_write(hw->regmap, rcg->ns_reg, ns);
+
+ ns &= ~BIT(mn->mnctr_reset_bit);
+ regmap_write(hw->regmap, rcg->ns_reg, ns);
+
+ 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/msm/clk-rcg.h b/drivers/clk/msm/clk-rcg.h
new file mode 100644
index 0000000..2335176
--- /dev/null
+++ b/drivers/clk/msm/clk-rcg.h
@@ -0,0 +1,149 @@
+/*
+ * 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
+ */
+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;
+};
+
+/**
+ * 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
+ 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;
+
+/**
+ * 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;
+
+/**
+ * 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;
+ u8 *parent_map;
+ const struct freq_tbl *freq_tbl;
+ struct clk_hw hw;
+};
+
+extern const struct clk_ops clk_rcg2_ops;
+
+#endif
diff --git a/drivers/clk/msm/clk-rcg2.c b/drivers/clk/msm/clk-rcg2.c
new file mode 100644
index 0000000..c970261
--- /dev/null
+++ b/drivers/clk/msm/clk-rcg2.c
@@ -0,0 +1,272 @@
+/*
+ * 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
+
+#define to_clk_rcg2(_hw) container_of(_hw, struct clk_rcg2, hw)
+
+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)
+{
+ 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)
+{
+ f = find_freq(f, rate);
+ if (!f)
+ return -EINVAL;
+
+ *p = clk_get_parent_by_index(hw->clk, f->src);
+ *p_rate = __clk_get_rate(*p);
+
+ 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] 10+ messages in thread
* [PATCH v2 6/9] clk: msm: Add support for branches/gate clocks
2013-10-02 19:06 [PATCH v2 0/9] Add support for MSM's mmio clocks Stephen Boyd
` (4 preceding siblings ...)
2013-10-02 19:07 ` [PATCH v2 5/9] clk: msm: Add support for root clock generators (RCGs) Stephen Boyd
@ 2013-10-02 19:07 ` Stephen Boyd
2013-10-02 19:07 ` [PATCH v2 7/9] clk: msm: Add support for MSM8960's global clock controller (GCC) Stephen Boyd
` (2 subsequent siblings)
8 siblings, 0 replies; 10+ messages in thread
From: Stephen Boyd @ 2013-10-02 19:07 UTC (permalink / raw)
To: linux-arm-kernel
Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
---
drivers/clk/msm/Makefile | 1 +
drivers/clk/msm/clk-branch.c | 153 +++++++++++++++++++++++++++++++++++++++++++
drivers/clk/msm/clk-branch.h | 50 ++++++++++++++
3 files changed, 204 insertions(+)
create mode 100644 drivers/clk/msm/clk-branch.c
create mode 100644 drivers/clk/msm/clk-branch.h
diff --git a/drivers/clk/msm/Makefile b/drivers/clk/msm/Makefile
index fb78ac9..e1cee29 100644
--- a/drivers/clk/msm/Makefile
+++ b/drivers/clk/msm/Makefile
@@ -3,3 +3,4 @@ obj-$(CONFIG_COMMON_CLK_MSM) += clk-msm.o
clk-msm-$(CONFIG_COMMON_CLK_MSM) += clk-pll.o
clk-msm-$(CONFIG_COMMON_CLK_MSM) += clk-rcg.o
clk-msm-$(CONFIG_COMMON_CLK_MSM) += clk-rcg2.o
+clk-msm-$(CONFIG_COMMON_CLK_MSM) += clk-branch.o
diff --git a/drivers/clk/msm/clk-branch.c b/drivers/clk/msm/clk-branch.c
new file mode 100644
index 0000000..3c67b43
--- /dev/null
+++ b/drivers/clk/msm/clk-branch.c
@@ -0,0 +1,153 @@
+/*
+ * 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"
+
+#define to_clk_branch(_hw) container_of(_hw, struct clk_branch, hw)
+
+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("%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);
diff --git a/drivers/clk/msm/clk-branch.h b/drivers/clk/msm/clk-branch.h
new file mode 100644
index 0000000..28874cf
--- /dev/null
+++ b/drivers/clk/msm/clk-branch.h
@@ -0,0 +1,50 @@
+/*
+ * 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;
+
+#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] 10+ messages in thread
* [PATCH v2 7/9] clk: msm: Add support for MSM8960's global clock controller (GCC)
2013-10-02 19:06 [PATCH v2 0/9] Add support for MSM's mmio clocks Stephen Boyd
` (5 preceding siblings ...)
2013-10-02 19:07 ` [PATCH v2 6/9] clk: msm: Add support for branches/gate clocks Stephen Boyd
@ 2013-10-02 19:07 ` Stephen Boyd
2013-10-02 19:07 ` [PATCH v2 8/9] clk: msm: Add support for MSM8960's multimedia clock controller (MMCC) Stephen Boyd
2013-10-02 19:07 ` [PATCH v2 9/9] clk: msm: Add support for MSM8974's global clock controller (GCC) Stephen Boyd
8 siblings, 0 replies; 10+ messages in thread
From: Stephen Boyd @ 2013-10-02 19:07 UTC (permalink / raw)
To: linux-arm-kernel
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.
TODO: Fill out reset of data and define all clocks
Cc: <devicetree@vger.kernel.org>
Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
---
.../devicetree/bindings/clock/qcom,gcc.txt | 19 +
drivers/clk/msm/Kconfig | 7 +
drivers/clk/msm/Makefile | 2 +
drivers/clk/msm/gcc-8960.c | 381 +++++++++++++++++++++
include/dt-bindings/clk/msm-gcc-8960.h | 28 ++
5 files changed, 437 insertions(+)
create mode 100644 Documentation/devicetree/bindings/clock/qcom,gcc.txt
create mode 100644 drivers/clk/msm/gcc-8960.c
create mode 100644 include/dt-bindings/clk/msm-gcc-8960.h
diff --git a/Documentation/devicetree/bindings/clock/qcom,gcc.txt b/Documentation/devicetree/bindings/clock/qcom,gcc.txt
new file mode 100644
index 0000000..e31423a
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/qcom,gcc.txt
@@ -0,0 +1,19 @@
+MSM Global Clock Controller Binding
+-----------------------------------
+
+Required properties :
+- compatible : shall contain at least "qcom,gcc" and only one of the
+ following:
+
+ "qcom,gcc-8660"
+ "qcom,gcc-8960"
+
+- reg : shall contain base register location and length
+- #clock-cells : shall contain 1
+
+Example:
+ clock-controller at 900000 {
+ compatible = "qcom,gcc-8960", "qcom,gcc";
+ reg = <0x900000 0x4000>;
+ #clock-cells = <1>;
+ };
diff --git a/drivers/clk/msm/Kconfig b/drivers/clk/msm/Kconfig
index 91558ce..241fafc 100644
--- a/drivers/clk/msm/Kconfig
+++ b/drivers/clk/msm/Kconfig
@@ -3,3 +3,10 @@ config COMMON_CLK_MSM
depends on OF
select REGMAP_MMIO
+config MSM_GCC_8960
+ tristate "MSM8960 Global Clock Controller"
+ depends on COMMON_CLK_MSM
+ 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/msm/Makefile b/drivers/clk/msm/Makefile
index e1cee29..804fbe1 100644
--- a/drivers/clk/msm/Makefile
+++ b/drivers/clk/msm/Makefile
@@ -4,3 +4,5 @@ clk-msm-$(CONFIG_COMMON_CLK_MSM) += clk-pll.o
clk-msm-$(CONFIG_COMMON_CLK_MSM) += clk-rcg.o
clk-msm-$(CONFIG_COMMON_CLK_MSM) += clk-rcg2.o
clk-msm-$(CONFIG_COMMON_CLK_MSM) += clk-branch.o
+
+obj-$(CONFIG_MSM_GCC_8960) += gcc-8960.o
diff --git a/drivers/clk/msm/gcc-8960.c b/drivers/clk/msm/gcc-8960.c
new file mode 100644
index 0000000..41c8a2f
--- /dev/null
+++ b/drivers/clk/msm/gcc-8960.c
@@ -0,0 +1,381 @@
+/*
+ * 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/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 <dt-bindings/clk/msm-gcc-8960.h>
+
+#include "clk-pll.h"
+#include "clk-rcg.h"
+#include "clk-branch.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
+
+static u8 gcc_pxo_pll8_map[] = {
+ [P_PXO] = 0,
+ [P_PLL8] = 3,
+};
+
+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 gsbi5_uart_rcg = {
+ .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_rcg",
+ .parent_names = (const char *[]){
+ "pxo",
+ "pll8_vote",
+ },
+ .num_parents = 2,
+ .ops = &clk_rcg_ops,
+ },
+ },
+};
+
+static struct clk_branch gsbi5_uart_cxc = {
+ .halt_reg = 0x2fd0,
+ .halt_bit = 22,
+ .hw = {
+ .enable_reg = 0x2a54,
+ .enable_mask = BIT(9),
+ .init = &(struct clk_init_data){
+ .name = "gsbi5_uart_cxc",
+ .parent_names = (const char *[]){
+ "gsbi5_uart_rcg",
+ },
+ .num_parents = 1,
+ .ops = &clk_branch_ops,
+ },
+ },
+};
+
+static struct clk_rcg gsbi6_uart_rcg = {
+ .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_rcg",
+ .parent_names = (const char *[]){
+ "pxo",
+ "pll8_vote",
+ },
+ .num_parents = 2,
+ .ops = &clk_rcg_ops,
+ },
+ },
+};
+
+static struct clk_branch gsbi6_uart_cxc = {
+ .halt_reg = 0x2fd0,
+ .halt_bit = 18,
+ .hw = {
+ .enable_reg = 0x2a74,
+ .enable_mask = BIT(9),
+ .init = &(struct clk_init_data){
+ .name = "gsbi6_uart_cxc",
+ .parent_names = (const char *[]){
+ "gsbi6_uart_rcg",
+ },
+ .num_parents = 1,
+ .ops = &clk_branch_ops,
+ },
+ },
+};
+
+static struct clk_branch gsbi5_uart_ahb = {
+ .halt_reg = 0x2fd0,
+ .halt_bit = 23,
+ .hwcg_reg = 0x2a40,
+ .hwcg_bit = 6,
+ .hw = {
+ .enable_reg = 0x2a40,
+ .enable_mask = BIT(4),
+ .init = &(struct clk_init_data){
+ .name = "gsbi5_uart_ahb",
+ .ops = &clk_branch_ops,
+ },
+ },
+};
+
+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 gsbi5_qup_rcg = {
+ .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 = 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_qup,
+ .hw = {
+ .enable_reg = 0x2a4c,
+ .enable_mask = BIT(11),
+ .init = &(struct clk_init_data){
+ .name = "gsbi5_qup_rcg",
+ .parent_names = (const char *[]){
+ "pxo",
+ "pll8_vote",
+ },
+ .num_parents = 2,
+ .ops = &clk_rcg_ops,
+ },
+ },
+};
+
+static struct clk_branch gsbi5_qup_cxc = {
+ .halt_reg = 0x2fd0,
+ .halt_bit = 20,
+ .hw = {
+ .enable_reg = 0x2a4c,
+ .enable_mask = BIT(9),
+ .init = &(struct clk_init_data){
+ .name = "gsbi5_qup_cxc",
+ .parent_names = (const char *[]){
+ "gsbi5_qup_rcg",
+ },
+ .num_parents = 1,
+ .ops = &clk_branch_ops,
+ },
+ },
+};
+
+struct clk_map {
+ unsigned long id;
+ struct clk_hw *hw;
+};
+
+#define MAP(i, h) [i] = { .id = i, .hw = h }
+
+static const struct clk_map map[] = {
+ MAP(PLL8, &pll8.hw),
+ MAP(PLL8_VOTE, &pll8_vote),
+ MAP(GSBI5_UART_RCG, &gsbi5_uart_rcg.hw),
+ MAP(GSBI5_UART_CXC, &gsbi5_uart_cxc.hw),
+ MAP(GSBI6_UART_RCG, &gsbi6_uart_rcg.hw),
+ MAP(GSBI6_UART_CXC, &gsbi6_uart_cxc.hw),
+ MAP(GSBI5_UART_AHB, &gsbi5_uart_ahb.hw),
+ MAP(GSBI5_QUP_RCG, &gsbi5_qup_rcg.hw),
+ MAP(GSBI5_QUP_CXC, &gsbi5_qup_cxc.hw),
+};
+
+static const struct regmap_config msm_gcc_8960_regmap_config = {
+ .reg_bits = 32,
+ .reg_stride = 4,
+ .val_bits = 32,
+ .max_register = 0x3660,
+ .fast_io = true,
+};
+
+static const struct of_device_id msm_gcc_8960_match_table[] = {
+ { .compatible = "qcom,gcc-8960" },
+ { }
+};
+MODULE_DEVICE_TABLE(of, msm_gcc_8960_match_table);
+
+static int msm_gcc_8960_probe(struct platform_device *pdev)
+{
+ void __iomem *base;
+ struct resource *res;
+ int i;
+ struct device *dev = &pdev->dev;
+ struct clk *clk;
+ struct clk_onecell_data *data;
+ struct clk **clks;
+ struct regmap *regmap;
+ size_t num_clks;
+
+ 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, &msm_gcc_8960_regmap_config);
+ if (IS_ERR(regmap))
+ return PTR_ERR(regmap);
+
+ num_clks = ARRAY_SIZE(map);
+ data = devm_kzalloc(dev, sizeof(*data) + sizeof(*clks) * num_clks,
+ GFP_KERNEL);
+ if (!data)
+ return -ENOMEM;
+
+ clks = (struct clk **)(data + 1);
+ 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 (!map[i].hw)
+ continue;
+ clk = devm_clk_register(dev, map[i].hw);
+ if (IS_ERR(clk))
+ return PTR_ERR(clk);
+ clks[map[i].id] = clk;
+ }
+
+ return of_clk_add_provider(dev->of_node, of_clk_src_onecell_get, data);
+}
+
+static int msm_gcc_8960_remove(struct platform_device *pdev)
+{
+ of_clk_del_provider(pdev->dev.of_node);
+ return 0;
+}
+
+static struct platform_driver msm_gcc_8960_driver = {
+ .probe = msm_gcc_8960_probe,
+ .remove = msm_gcc_8960_remove,
+ .driver = {
+ .name = "msm-gcc-8960",
+ .owner = THIS_MODULE,
+ .of_match_table = msm_gcc_8960_match_table,
+ },
+};
+
+static int __init msm_gcc_8960_init(void)
+{
+ return platform_driver_register(&msm_gcc_8960_driver);
+}
+core_initcall(msm_gcc_8960_init);
+
+static void __exit msm_gcc_8960_exit(void)
+{
+ platform_driver_unregister(&msm_gcc_8960_driver);
+}
+module_exit(msm_gcc_8960_exit);
+
+MODULE_DESCRIPTION("MSM GCC 8960 Driver");
+MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("platform:msm-gcc-8960");
diff --git a/include/dt-bindings/clk/msm-gcc-8960.h b/include/dt-bindings/clk/msm-gcc-8960.h
new file mode 100644
index 0000000..685b118
--- /dev/null
+++ b/include/dt-bindings/clk/msm-gcc-8960.h
@@ -0,0 +1,28 @@
+/*
+ * 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 PLL8 0
+#define PLL8_VOTE 1
+#define GSBI5_UART_RCG 2
+#define GSBI5_UART_CXC 3
+#define GSBI6_UART_RCG 4
+#define GSBI6_UART_CXC 5
+#define GSBI6_UART_AHB 6
+#define GSBI5_UART_AHB 7
+#define GSBI5_QUP_RCG 8
+#define GSBI5_QUP_CXC 9
+
+#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] 10+ messages in thread
* [PATCH v2 8/9] clk: msm: Add support for MSM8960's multimedia clock controller (MMCC)
2013-10-02 19:06 [PATCH v2 0/9] Add support for MSM's mmio clocks Stephen Boyd
` (6 preceding siblings ...)
2013-10-02 19:07 ` [PATCH v2 7/9] clk: msm: Add support for MSM8960's global clock controller (GCC) Stephen Boyd
@ 2013-10-02 19:07 ` Stephen Boyd
2013-10-02 19:07 ` [PATCH v2 9/9] clk: msm: Add support for MSM8974's global clock controller (GCC) Stephen Boyd
8 siblings, 0 replies; 10+ messages in thread
From: Stephen Boyd @ 2013-10-02 19:07 UTC (permalink / raw)
To: linux-arm-kernel
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.
TODO: Fill out reset of data and define all clocks
Cc: <devicetree@vger.kernel.org>
Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
---
.../devicetree/bindings/clock/qcom,mmcc.txt | 19 ++
drivers/clk/msm/Kconfig | 9 +
drivers/clk/msm/Makefile | 1 +
drivers/clk/msm/mmcc-8960.c | 297 +++++++++++++++++++++
include/dt-bindings/clk/msm-mmcc-8960.h | 24 ++
5 files changed, 350 insertions(+)
create mode 100644 Documentation/devicetree/bindings/clock/qcom,mmcc.txt
create mode 100644 drivers/clk/msm/mmcc-8960.c
create mode 100644 include/dt-bindings/clk/msm-mmcc-8960.h
diff --git a/Documentation/devicetree/bindings/clock/qcom,mmcc.txt b/Documentation/devicetree/bindings/clock/qcom,mmcc.txt
new file mode 100644
index 0000000..c29d472
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/qcom,mmcc.txt
@@ -0,0 +1,19 @@
+MSM Multimedia Clock Controller Binding
+-----------------------------------------
+
+Required properties :
+- compatible : shall contain at least "qcom,mmcc" and only one of the
+ following:
+
+ "qcom,mmcc-8660"
+ "qcom,mmcc-8960"
+
+- reg : shall contain base register location and length
+- #clock-cells : shall contain 1
+
+Example:
+ clock-controller at 4000000 {
+ compatible = "qcom,mmcc-8960", "qcom,mmcc";
+ reg = <0x4000000 0x1000>;
+ #clock-cells = <1>;
+ };
diff --git a/drivers/clk/msm/Kconfig b/drivers/clk/msm/Kconfig
index 241fafc..66f5ccf 100644
--- a/drivers/clk/msm/Kconfig
+++ b/drivers/clk/msm/Kconfig
@@ -10,3 +10,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_MSM
+ 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/msm/Makefile b/drivers/clk/msm/Makefile
index 804fbe1..f6ceb52 100644
--- a/drivers/clk/msm/Makefile
+++ b/drivers/clk/msm/Makefile
@@ -6,3 +6,4 @@ clk-msm-$(CONFIG_COMMON_CLK_MSM) += clk-rcg2.o
clk-msm-$(CONFIG_COMMON_CLK_MSM) += clk-branch.o
obj-$(CONFIG_MSM_GCC_8960) += gcc-8960.o
+obj-$(CONFIG_MSM_MMCC_8960) += mmcc-8960.o
diff --git a/drivers/clk/msm/mmcc-8960.c b/drivers/clk/msm/mmcc-8960.c
new file mode 100644
index 0000000..ea660ab
--- /dev/null
+++ b/drivers/clk/msm/mmcc-8960.c
@@ -0,0 +1,297 @@
+/*
+ * 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/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 <dt-bindings/clk/msm-mmcc-8960.h>
+
+#include "clk-pll.h"
+#include "clk-rcg.h"
+#include "clk-branch.h"
+
+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,
+ },
+};
+
+#define P_PXO 0
+#define P_PLL2 1
+#define P_PLL8 2
+
+static u8 mmcc_pxo_pll2_pll8_map[] = {
+ [P_PXO] = 0,
+ [P_PLL2] = 1,
+ [P_PLL8] = 2,
+};
+
+static struct freq_tbl clk_tbl_mdp[] = {
+ { 9600000, P_PLL8, 0, 1, 40 },
+ { 13710000, P_PLL8, 0, 1, 28 },
+ { 27000000, P_PXO, 0, 0, 0 },
+ { 29540000, P_PLL8, 0, 1, 13 },
+ { 34910000, P_PLL8, 0, 1, 11 },
+ { 38400000, P_PLL8, 0, 1, 10 },
+ { 59080000, P_PLL8, 0, 2, 13 },
+ { 76800000, P_PLL8, 0, 1, 5 },
+ { 85330000, P_PLL8, 0, 2, 9 },
+ { 96000000, P_PLL8, 0, 1, 4 },
+ { 128000000, P_PLL8, 0, 1, 3 },
+ { 160000000, P_PLL2, 0, 1, 5 },
+ { 177780000, P_PLL2, 0, 2, 9 },
+ { 200000000, P_PLL2, 0, 1, 4 },
+ { 228571000, P_PLL2, 0, 2, 7 },
+ { 266667000, P_PLL2, 0, 1, 3 },
+ { }
+};
+
+static struct clk_dyn_rcg mdp_rcg = {
+ .ns_reg = 0xd0,
+ .md_reg[0] = 0xc4,
+ .md_reg[1] = 0xc8,
+ .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_pll2_pll8_map,
+ },
+ .s[1] = {
+ .src_sel_shift = 0,
+ .parent_map = mmcc_pxo_pll2_pll8_map,
+ },
+ .mux_sel_bit = 11,
+ .freq_tbl = clk_tbl_mdp,
+ .hw = {
+ .enable_reg = 0xc0,
+ .enable_mask = BIT(2),
+ .init = &(struct clk_init_data){
+ .name = "mdp_rcg",
+ .parent_names = (const char *[]){
+ "pxo", "pll2", "pll8_vote"
+ },
+ .num_parents = 3,
+ .ops = &clk_dyn_rcg_ops,
+ },
+ },
+};
+
+static struct clk_branch mdp_cxc = {
+ .halt_reg = 0x1d0,
+ .halt_bit = 10,
+ .hw = {
+ .enable_reg = 0xc0,
+ .enable_mask = BIT(0),
+ .init = &(struct clk_init_data){
+ .name = "mdp_cxc",
+ .parent_names = (const char *[]){
+ "mdp_rcg",
+ },
+ .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_rcg = {
+ .ns_reg = 0xe8,
+ .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_pll2_pll8_map,
+ },
+ .s[1] = {
+ .src_sel_shift = 19,
+ .parent_map = mmcc_pxo_pll2_pll8_map,
+ },
+ .mux_sel_bit = 30,
+ .freq_tbl = clk_tbl_rot,
+ .hw = {
+ .enable_reg = 0xe0,
+ .enable_mask = BIT(2),
+ .init = &(struct clk_init_data){
+ .name = "rot_rcg",
+ .parent_names = (const char *[]){
+ "pxo", "pll2", "pll8_vote"
+ },
+ .num_parents = 3,
+ .ops = &clk_dyn_rcg_ops,
+ },
+ },
+};
+
+static struct clk_branch rot_cxc = {
+ .halt_reg = 0x1d0,
+ .halt_bit = 15,
+ .hw = {
+ .enable_reg = 0xe0,
+ .enable_mask = BIT(0),
+ .init = &(struct clk_init_data){
+ .name = "rot_cxc",
+ .parent_names = (const char *[]){
+ "rot_rcg",
+ },
+ .num_parents = 1,
+ .ops = &clk_branch_ops,
+ },
+ },
+};
+
+struct clk_map {
+ unsigned long id;
+ struct clk_hw *hw;
+};
+
+#define MAP(i, h) [i] = { .id = i, .hw = h }
+
+static const struct clk_map map[] = {
+ MAP(PLL2, &pll2.hw),
+ MAP(MDP_RCG, &mdp_rcg.hw),
+ MAP(MDP_CXC, &mdp_cxc.hw),
+ MAP(ROT_RCG, &rot_rcg.hw),
+ MAP(ROT_CXC, &rot_cxc.hw),
+};
+
+static const struct regmap_config msm_mmcc_8960_regmap_config = {
+ .reg_bits = 32,
+ .reg_stride = 4,
+ .val_bits = 32,
+ .max_register = 0x334,
+ .fast_io = true,
+};
+
+static const struct of_device_id msm_mmcc_8960_match_table[] = {
+ { .compatible = "qcom,mmcc-8960" },
+ { }
+};
+MODULE_DEVICE_TABLE(of, msm_mmcc_8960_match_table);
+
+static int msm_mmcc_8960_probe(struct platform_device *pdev)
+{
+ void __iomem *base;
+ struct resource *res;
+ int i;
+ struct device *dev = &pdev->dev;
+ struct clk *clk;
+ struct clk_onecell_data *data;
+ struct clk **clks;
+ struct regmap *regmap;
+ size_t num_clks;
+
+ 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, &msm_mmcc_8960_regmap_config);
+ if (IS_ERR(regmap))
+ return PTR_ERR(regmap);
+
+ num_clks = ARRAY_SIZE(map);
+ data = devm_kzalloc(dev, sizeof(*data) + sizeof(*clks) * num_clks,
+ GFP_KERNEL);
+ if (!data)
+ return -ENOMEM;
+
+ clks = (struct clk **)(data + 1);
+ data->clks = clks;
+ data->clk_num = num_clks;
+
+ for (i = 0; i < num_clks; i++) {
+ if (!map[i].hw)
+ continue;
+ clk = devm_clk_register(dev, map[i].hw);
+ if (IS_ERR(clk))
+ return PTR_ERR(clk);
+ clks[map[i].id] = clk;
+ }
+
+ return of_clk_add_provider(dev->of_node, of_clk_src_onecell_get, data);
+}
+
+static int msm_mmcc_8960_remove(struct platform_device *pdev)
+{
+ of_clk_del_provider(pdev->dev.of_node);
+ return 0;
+}
+
+static struct platform_driver msm_mmcc_8960_driver = {
+ .probe = msm_mmcc_8960_probe,
+ .remove = msm_mmcc_8960_remove,
+ .driver = {
+ .name = "msm-mmcc-8960",
+ .owner = THIS_MODULE,
+ .of_match_table = msm_mmcc_8960_match_table,
+ },
+};
+
+module_platform_driver(msm_mmcc_8960_driver);
+
+MODULE_DESCRIPTION("MSM MMCC 8960 Driver");
+MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("platform:msm-mmcc-8960");
diff --git a/include/dt-bindings/clk/msm-mmcc-8960.h b/include/dt-bindings/clk/msm-mmcc-8960.h
new file mode 100644
index 0000000..86eca3f
--- /dev/null
+++ b/include/dt-bindings/clk/msm-mmcc-8960.h
@@ -0,0 +1,24 @@
+/*
+ * 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 PLL2 0
+#define MDP_RCG 1
+#define MDP_CXC 2
+#define ROT_RCG 3
+#define ROT_CXC 4
+
+#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] 10+ messages in thread
* [PATCH v2 9/9] clk: msm: Add support for MSM8974's global clock controller (GCC)
2013-10-02 19:06 [PATCH v2 0/9] Add support for MSM's mmio clocks Stephen Boyd
` (7 preceding siblings ...)
2013-10-02 19:07 ` [PATCH v2 8/9] clk: msm: Add support for MSM8960's multimedia clock controller (MMCC) Stephen Boyd
@ 2013-10-02 19:07 ` Stephen Boyd
8 siblings, 0 replies; 10+ messages in thread
From: Stephen Boyd @ 2013-10-02 19:07 UTC (permalink / raw)
To: linux-arm-kernel
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.
TODO: define all clocks in binding
Cc: <devicetree@vger.kernel.org>
Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
---
.../devicetree/bindings/clock/qcom,gcc.txt | 1 +
drivers/clk/msm/Kconfig | 8 +
drivers/clk/msm/Makefile | 1 +
drivers/clk/msm/gcc-8974.c | 2488 ++++++++++++++++++++
include/dt-bindings/clk/msm-gcc-8974.h | 154 ++
5 files changed, 2652 insertions(+)
create mode 100644 drivers/clk/msm/gcc-8974.c
create mode 100644 include/dt-bindings/clk/msm-gcc-8974.h
diff --git a/Documentation/devicetree/bindings/clock/qcom,gcc.txt b/Documentation/devicetree/bindings/clock/qcom,gcc.txt
index e31423a..376f100 100644
--- a/Documentation/devicetree/bindings/clock/qcom,gcc.txt
+++ b/Documentation/devicetree/bindings/clock/qcom,gcc.txt
@@ -7,6 +7,7 @@ Required properties :
"qcom,gcc-8660"
"qcom,gcc-8960"
+ "qcom,gcc-8974"
- reg : shall contain base register location and length
- #clock-cells : shall contain 1
diff --git a/drivers/clk/msm/Kconfig b/drivers/clk/msm/Kconfig
index 66f5ccf..3c2586f 100644
--- a/drivers/clk/msm/Kconfig
+++ b/drivers/clk/msm/Kconfig
@@ -19,3 +19,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_MSM
+ 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/msm/Makefile b/drivers/clk/msm/Makefile
index f6ceb52..d11b9a2 100644
--- a/drivers/clk/msm/Makefile
+++ b/drivers/clk/msm/Makefile
@@ -6,4 +6,5 @@ clk-msm-$(CONFIG_COMMON_CLK_MSM) += clk-rcg2.o
clk-msm-$(CONFIG_COMMON_CLK_MSM) += clk-branch.o
obj-$(CONFIG_MSM_GCC_8960) += gcc-8960.o
+obj-$(CONFIG_MSM_GCC_8974) += gcc-8974.o
obj-$(CONFIG_MSM_MMCC_8960) += mmcc-8960.o
diff --git a/drivers/clk/msm/gcc-8974.c b/drivers/clk/msm/gcc-8974.c
new file mode 100644
index 0000000..73ae19e
--- /dev/null
+++ b/drivers/clk/msm/gcc-8974.c
@@ -0,0 +1,2488 @@
+/*
+ * 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/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 <dt-bindings/clk/msm-gcc-8974.h>
+
+#include "clk-pll.h"
+#include "clk-rcg.h"
+#include "clk-branch.h"
+
+#define P_XO 0
+#define P_GPLL0 1
+#define P_GPLL1 2
+
+static u8 gcc_xo_gpll0_gpll1_map[] = {
+ [P_XO] = 0,
+ [P_GPLL0] = 1,
+ [P_GPLL1] = 2,
+};
+
+#define F(f, s, h, m, n) { (f), (s), (2 * (h) - 1), (m), (n) }
+
+static struct clk_pll gpll0 = {
+ .l_reg = 0x0000 + 0x4,
+ .m_reg = 0x0000 + 0x8,
+ .n_reg = 0x0000 + 0xc,
+ .config_reg = 0x0000 + 0x14,
+ .mode_reg = 0x0000,
+ .status_reg = 0x0000 + 0x1c,
+ .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_gpll1_map,
+ .hw.init = &(struct clk_init_data){
+ .name = "config_noc_clk_src",
+ .parent_names = (const char *[]){
+ "xo",
+ "gpll0_vote",
+ },
+ .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_gpll1_map,
+ .hw.init = &(struct clk_init_data){
+ .name = "periph_noc_clk_src",
+ .parent_names = (const char *[]){
+ "xo",
+ "gpll0_vote",
+ },
+ .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_gpll1_map,
+ .hw.init = &(struct clk_init_data){
+ .name = "system_noc_clk_src",
+ .parent_names = (const char *[]){
+ "xo",
+ "gpll0_vote",
+ },
+ .num_parents = 2,
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static struct clk_pll gpll1 = {
+ .l_reg = 0x0040 + 0x4,
+ .m_reg = 0x0040 + 0x8,
+ .n_reg = 0x0040 + 0xc,
+ .config_reg = 0x0040 + 0x14,
+ .mode_reg = 0x0040,
+ .status_reg = 0x0040 + 0x1c,
+ .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 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_gpll1_map,
+ .freq_tbl = ftbl_gcc_usb30_master_clk,
+ .hw.init = &(struct clk_init_data){
+ .name = "usb30_master_clk_src",
+ .parent_names = (const char *[]){
+ "xo",
+ "gpll0_vote",
+ "gpll1_vote",
+ },
+ .num_parents = 3,
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static 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_gpll1_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 = (const char *[]){
+ "xo",
+ "gpll0_vote",
+ },
+ .num_parents = 2,
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static 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_gpll1_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 = (const char *[]){
+ "xo",
+ "gpll0_vote",
+ },
+ .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_gpll1_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 = (const char *[]){
+ "xo",
+ "gpll0_vote",
+ },
+ .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_gpll1_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 = (const char *[]){
+ "xo",
+ "gpll0_vote",
+ },
+ .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_gpll1_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 = (const char *[]){
+ "xo",
+ "gpll0_vote",
+ },
+ .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_gpll1_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 = (const char *[]){
+ "xo",
+ "gpll0_vote",
+ },
+ .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_gpll1_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 = (const char *[]){
+ "xo",
+ "gpll0_vote",
+ },
+ .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_gpll1_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 = (const char *[]){
+ "xo",
+ "gpll0_vote",
+ },
+ .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_gpll1_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 = (const char *[]){
+ "xo",
+ "gpll0_vote",
+ },
+ .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_gpll1_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 = (const char *[]){
+ "xo",
+ "gpll0_vote",
+ },
+ .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_gpll1_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 = (const char *[]){
+ "xo",
+ "gpll0_vote",
+ },
+ .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_gpll1_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 = (const char *[]){
+ "xo",
+ "gpll0_vote",
+ },
+ .num_parents = 2,
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static 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_gpll1_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 = (const char *[]){
+ "xo",
+ "gpll0_vote",
+ },
+ .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_gpll1_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 = (const char *[]){
+ "xo",
+ "gpll0_vote",
+ },
+ .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_gpll1_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 = (const char *[]){
+ "xo",
+ "gpll0_vote",
+ },
+ .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_gpll1_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 = (const char *[]){
+ "xo",
+ "gpll0_vote",
+ },
+ .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_gpll1_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 = (const char *[]){
+ "xo",
+ "gpll0_vote",
+ },
+ .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_gpll1_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 = (const char *[]){
+ "xo",
+ "gpll0_vote",
+ },
+ .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_gpll1_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 = (const char *[]){
+ "xo",
+ "gpll0_vote",
+ },
+ .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_gpll1_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 = (const char *[]){
+ "xo",
+ "gpll0_vote",
+ },
+ .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_gpll1_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 = (const char *[]){
+ "xo",
+ "gpll0_vote",
+ },
+ .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_gpll1_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 = (const char *[]){
+ "xo",
+ "gpll0_vote",
+ },
+ .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_gpll1_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 = (const char *[]){
+ "xo",
+ "gpll0_vote",
+ },
+ .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_gpll1_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 = (const char *[]){
+ "xo",
+ "gpll0_vote",
+ },
+ .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_gpll1_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 = (const char *[]){
+ "xo",
+ "gpll0_vote",
+ },
+ .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_gpll1_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 = (const char *[]){
+ "xo",
+ "gpll0_vote",
+ },
+ .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_gpll1_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 = (const char *[]){
+ "xo",
+ "gpll0_vote",
+ },
+ .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_gpll1_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 = (const char *[]){
+ "xo",
+ "gpll0_vote",
+ },
+ .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_gpll1_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 = (const char *[]){
+ "xo",
+ "gpll0_vote",
+ },
+ .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_gpll1_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 = (const char *[]){
+ "xo",
+ "gpll0_vote",
+ },
+ .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_gpll1_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 = (const char *[]){
+ "xo",
+ "gpll0_vote",
+ },
+ .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_gpll1_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 = (const char *[]){
+ "xo",
+ "gpll0_vote",
+ },
+ .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_gpll1_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 = (const char *[]){
+ "xo",
+ "gpll0_vote",
+ },
+ .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_gpll1_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 = (const char *[]){
+ "xo",
+ "gpll0_vote",
+ },
+ .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_gpll1_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 = (const char *[]){
+ "xo",
+ "gpll0_vote",
+ },
+ .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_gpll1_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 = (const char *[]){
+ "xo",
+ "gpll0_vote",
+ },
+ .num_parents = 2,
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static 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_gpll1_map,
+ .freq_tbl = ftbl_gcc_ce1_clk,
+ .hw.init = &(struct clk_init_data){
+ .name = "ce1_clk_src",
+ .parent_names = (const char *[]){
+ "xo",
+ "gpll0_vote",
+ },
+ .num_parents = 2,
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static 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_gpll1_map,
+ .freq_tbl = ftbl_gcc_ce2_clk,
+ .hw.init = &(struct clk_init_data){
+ .name = "ce2_clk_src",
+ .parent_names = (const char *[]){
+ "xo",
+ "gpll0_vote",
+ },
+ .num_parents = 2,
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static struct clk_rcg2 gp1_clk_src = {
+ .cmd_rcgr = 0x1904,
+ .mnd_width = 8,
+ .hid_width = 5,
+ .parent_map = gcc_xo_gpll0_gpll1_map,
+ .hw.init = &(struct clk_init_data){
+ .name = "gp1_clk_src",
+ .parent_names = (const char *[]){
+ "xo",
+ "gpll0_vote",
+ "gpll1_vote",
+ },
+ .num_parents = 3,
+ .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_gpll1_map,
+ .hw.init = &(struct clk_init_data){
+ .name = "gp2_clk_src",
+ .parent_names = (const char *[]){
+ "xo",
+ "gpll0_vote",
+ "gpll1_vote",
+ },
+ .num_parents = 3,
+ .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_gpll1_map,
+ .hw.init = &(struct clk_init_data){
+ .name = "gp3_clk_src",
+ .parent_names = (const char *[]){
+ "xo",
+ "gpll0_vote",
+ },
+ .num_parents = 2,
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static 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_gpll1_map,
+ .freq_tbl = ftbl_gcc_pdm2_clk,
+ .hw.init = &(struct clk_init_data){
+ .name = "pdm2_clk_src",
+ .parent_names = (const char *[]){
+ "xo",
+ "gpll0",
+ },
+ .num_parents = 2,
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static 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_gpll1_map,
+ .freq_tbl = ftbl_gcc_sdcc1_4_apps_clk,
+ .hw.init = &(struct clk_init_data){
+ .name = "sdcc1_apps_clk_src",
+ .parent_names = (const char *[]){
+ "xo",
+ "gpll0_vote",
+ },
+ .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_gpll1_map,
+ .freq_tbl = ftbl_gcc_sdcc1_4_apps_clk,
+ .hw.init = &(struct clk_init_data){
+ .name = "sdcc2_apps_clk_src",
+ .parent_names = (const char *[]){
+ "xo",
+ "gpll0_vote",
+ },
+ .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_gpll1_map,
+ .freq_tbl = ftbl_gcc_sdcc1_4_apps_clk,
+ .hw.init = &(struct clk_init_data){
+ .name = "sdcc3_apps_clk_src",
+ .parent_names = (const char *[]){
+ "xo",
+ "gpll0_vote",
+ },
+ .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_gpll1_map,
+ .freq_tbl = ftbl_gcc_sdcc1_4_apps_clk,
+ .hw.init = &(struct clk_init_data){
+ .name = "sdcc4_apps_clk_src",
+ .parent_names = (const char *[]){
+ "xo",
+ "gpll0_vote",
+ },
+ .num_parents = 2,
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static 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_gpll1_map,
+ .freq_tbl = ftbl_gcc_tsif_ref_clk,
+ .hw.init = &(struct clk_init_data){
+ .name = "tsif_ref_clk_src",
+ .parent_names = (const char *[]){
+ "xo",
+ "gpll0_vote",
+ "aud_ref_clk",
+ },
+ .num_parents = 3,
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static 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_gpll1_map,
+ .freq_tbl = ftbl_gcc_usb30_mock_utmi_clk,
+ .hw.init = &(struct clk_init_data){
+ .name = "usb30_mock_utmi_clk_src",
+ .parent_names = (const char *[]){
+ "xo",
+ "gpll0_vote",
+ },
+ .num_parents = 2,
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static 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_gpll1_map,
+ .freq_tbl = ftbl_gcc_usb_hs_system_clk,
+ .hw.init = &(struct clk_init_data){
+ .name = "usb_hs_system_clk_src",
+ .parent_names = (const char *[]){
+ "xo",
+ "gpll0_vote",
+ },
+ .num_parents = 2,
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static struct freq_tbl ftbl_gcc_usb_hsic_clk[] = {
+ F(480000000, P_GPLL1, 0, 0, 0),
+ { }
+};
+
+static struct clk_rcg2 usb_hsic_clk_src = {
+ .cmd_rcgr = 0x0440,
+ .hid_width = 5,
+ .parent_map = gcc_xo_gpll0_gpll1_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 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_gpll1_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 = (const char *[]){
+ "xo",
+ },
+ .num_parents = 1,
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static 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_gpll1_map,
+ .freq_tbl = ftbl_gcc_usb_hsic_system_clk,
+ .hw.init = &(struct clk_init_data){
+ .name = "usb_hsic_system_clk_src",
+ .parent_names = (const char *[]){
+ "xo",
+ "gpll0_vote",
+ },
+ .num_parents = 2,
+ .ops = &clk_rcg2_ops,
+ },
+};
+
+static struct clk_branch gcc_bam_dma_ahb_clk = {
+ .halt_reg = 0x0d44,
+ .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,
+ .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,
+ .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,
+ .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,
+ .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,
+ .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,
+ .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,
+ .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,
+ .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,
+ .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,
+ .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_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_prng_ahb_clk = {
+ .halt_reg = 0x0d04,
+ .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_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_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_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_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_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 *[]){
+ "gcc_sleep_clk_src",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .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 *[]){
+ "gcc_sleep_clk_src",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .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 *[]){
+ "gcc_sleep_clk_src",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .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_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 *[]){
+ "gcc_sleep_clk_src",
+ },
+ .num_parents = 1,
+ .flags = CLK_SET_RATE_PARENT,
+ .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,
+ },
+ },
+};
+
+struct clk_map {
+ unsigned long id;
+ struct clk_hw *hw;
+};
+
+#define MAP(i, h) [i] = { .id = i, .hw = h }
+
+static const struct clk_map map[] = {
+ MAP(GPLL0, &gpll0.hw),
+ MAP(GPLL0_VOTE, &gpll0_vote),
+ MAP(CONFIG_NOC_CLK_SRC, &config_noc_clk_src.hw),
+ MAP(PERIPH_NOC_CLK_SRC, &periph_noc_clk_src.hw),
+ MAP(SYSTEM_NOC_CLK_SRC, &system_noc_clk_src.hw),
+ MAP(GPLL1, &gpll1.hw),
+ MAP(GPLL1_VOTE, &gpll1_vote),
+ MAP(USB30_MASTER_CLK_SRC, &usb30_master_clk_src.hw),
+ MAP(BLSP1_QUP1_I2C_APPS_CLK_SRC, &blsp1_qup1_i2c_apps_clk_src.hw),
+ MAP(BLSP1_QUP1_SPI_APPS_CLK_SRC, &blsp1_qup1_spi_apps_clk_src.hw),
+ MAP(BLSP1_QUP2_I2C_APPS_CLK_SRC, &blsp1_qup2_i2c_apps_clk_src.hw),
+ MAP(BLSP1_QUP2_SPI_APPS_CLK_SRC, &blsp1_qup2_spi_apps_clk_src.hw),
+ MAP(BLSP1_QUP3_I2C_APPS_CLK_SRC, &blsp1_qup3_i2c_apps_clk_src.hw),
+ MAP(BLSP1_QUP3_SPI_APPS_CLK_SRC, &blsp1_qup3_spi_apps_clk_src.hw),
+ MAP(BLSP1_QUP4_I2C_APPS_CLK_SRC, &blsp1_qup4_i2c_apps_clk_src.hw),
+ MAP(BLSP1_QUP4_SPI_APPS_CLK_SRC, &blsp1_qup4_spi_apps_clk_src.hw),
+ MAP(BLSP1_QUP5_I2C_APPS_CLK_SRC, &blsp1_qup5_i2c_apps_clk_src.hw),
+ MAP(BLSP1_QUP5_SPI_APPS_CLK_SRC, &blsp1_qup5_spi_apps_clk_src.hw),
+ MAP(BLSP1_QUP6_I2C_APPS_CLK_SRC, &blsp1_qup6_i2c_apps_clk_src.hw),
+ MAP(BLSP1_QUP6_SPI_APPS_CLK_SRC, &blsp1_qup6_spi_apps_clk_src.hw),
+ MAP(BLSP1_UART1_APPS_CLK_SRC, &blsp1_uart1_apps_clk_src.hw),
+ MAP(BLSP1_UART2_APPS_CLK_SRC, &blsp1_uart2_apps_clk_src.hw),
+ MAP(BLSP1_UART3_APPS_CLK_SRC, &blsp1_uart3_apps_clk_src.hw),
+ MAP(BLSP1_UART4_APPS_CLK_SRC, &blsp1_uart4_apps_clk_src.hw),
+ MAP(BLSP1_UART5_APPS_CLK_SRC, &blsp1_uart5_apps_clk_src.hw),
+ MAP(BLSP1_UART6_APPS_CLK_SRC, &blsp1_uart6_apps_clk_src.hw),
+ MAP(BLSP2_QUP1_I2C_APPS_CLK_SRC, &blsp2_qup1_i2c_apps_clk_src.hw),
+ MAP(BLSP2_QUP1_SPI_APPS_CLK_SRC, &blsp2_qup1_spi_apps_clk_src.hw),
+ MAP(BLSP2_QUP2_I2C_APPS_CLK_SRC, &blsp2_qup2_i2c_apps_clk_src.hw),
+ MAP(BLSP2_QUP2_SPI_APPS_CLK_SRC, &blsp2_qup2_spi_apps_clk_src.hw),
+ MAP(BLSP2_QUP3_I2C_APPS_CLK_SRC, &blsp2_qup3_i2c_apps_clk_src.hw),
+ MAP(BLSP2_QUP3_SPI_APPS_CLK_SRC, &blsp2_qup3_spi_apps_clk_src.hw),
+ MAP(BLSP2_QUP4_I2C_APPS_CLK_SRC, &blsp2_qup4_i2c_apps_clk_src.hw),
+ MAP(BLSP2_QUP4_SPI_APPS_CLK_SRC, &blsp2_qup4_spi_apps_clk_src.hw),
+ MAP(BLSP2_QUP5_I2C_APPS_CLK_SRC, &blsp2_qup5_i2c_apps_clk_src.hw),
+ MAP(BLSP2_QUP5_SPI_APPS_CLK_SRC, &blsp2_qup5_spi_apps_clk_src.hw),
+ MAP(BLSP2_QUP6_I2C_APPS_CLK_SRC, &blsp2_qup6_i2c_apps_clk_src.hw),
+ MAP(BLSP2_QUP6_SPI_APPS_CLK_SRC, &blsp2_qup6_spi_apps_clk_src.hw),
+ MAP(BLSP2_UART1_APPS_CLK_SRC, &blsp2_uart1_apps_clk_src.hw),
+ MAP(BLSP2_UART2_APPS_CLK_SRC, &blsp2_uart2_apps_clk_src.hw),
+ MAP(BLSP2_UART3_APPS_CLK_SRC, &blsp2_uart3_apps_clk_src.hw),
+ MAP(BLSP2_UART4_APPS_CLK_SRC, &blsp2_uart4_apps_clk_src.hw),
+ MAP(BLSP2_UART5_APPS_CLK_SRC, &blsp2_uart5_apps_clk_src.hw),
+ MAP(BLSP2_UART6_APPS_CLK_SRC, &blsp2_uart6_apps_clk_src.hw),
+ MAP(CE1_CLK_SRC, &ce1_clk_src.hw),
+ MAP(CE2_CLK_SRC, &ce2_clk_src.hw),
+ MAP(GP1_CLK_SRC, &gp1_clk_src.hw),
+ MAP(GP2_CLK_SRC, &gp2_clk_src.hw),
+ MAP(GP3_CLK_SRC, &gp3_clk_src.hw),
+ MAP(PDM2_CLK_SRC, &pdm2_clk_src.hw),
+ MAP(SDCC1_APPS_CLK_SRC, &sdcc1_apps_clk_src.hw),
+ MAP(SDCC2_APPS_CLK_SRC, &sdcc2_apps_clk_src.hw),
+ MAP(SDCC3_APPS_CLK_SRC, &sdcc3_apps_clk_src.hw),
+ MAP(SDCC4_APPS_CLK_SRC, &sdcc4_apps_clk_src.hw),
+ MAP(TSIF_REF_CLK_SRC, &tsif_ref_clk_src.hw),
+ MAP(USB30_MOCK_UTMI_CLK_SRC, &usb30_mock_utmi_clk_src.hw),
+ MAP(USB_HS_SYSTEM_CLK_SRC, &usb_hs_system_clk_src.hw),
+ MAP(USB_HSIC_CLK_SRC, &usb_hsic_clk_src.hw),
+ MAP(USB_HSIC_IO_CAL_CLK_SRC, &usb_hsic_io_cal_clk_src.hw),
+ MAP(USB_HSIC_SYSTEM_CLK_SRC, &usb_hsic_system_clk_src.hw),
+ MAP(GCC_BAM_DMA_AHB_CLK, &gcc_bam_dma_ahb_clk.hw),
+ MAP(GCC_BLSP1_AHB_CLK, &gcc_blsp1_ahb_clk.hw),
+ MAP(GCC_BLSP1_QUP1_I2C_APPS_CLK, &gcc_blsp1_qup1_i2c_apps_clk.hw),
+ MAP(GCC_BLSP1_QUP1_SPI_APPS_CLK, &gcc_blsp1_qup1_spi_apps_clk.hw),
+ MAP(GCC_BLSP1_QUP2_I2C_APPS_CLK, &gcc_blsp1_qup2_i2c_apps_clk.hw),
+ MAP(GCC_BLSP1_QUP2_SPI_APPS_CLK, &gcc_blsp1_qup2_spi_apps_clk.hw),
+ MAP(GCC_BLSP1_QUP3_I2C_APPS_CLK, &gcc_blsp1_qup3_i2c_apps_clk.hw),
+ MAP(GCC_BLSP1_QUP3_SPI_APPS_CLK, &gcc_blsp1_qup3_spi_apps_clk.hw),
+ MAP(GCC_BLSP1_QUP4_I2C_APPS_CLK, &gcc_blsp1_qup4_i2c_apps_clk.hw),
+ MAP(GCC_BLSP1_QUP4_SPI_APPS_CLK, &gcc_blsp1_qup4_spi_apps_clk.hw),
+ MAP(GCC_BLSP1_QUP5_I2C_APPS_CLK, &gcc_blsp1_qup5_i2c_apps_clk.hw),
+ MAP(GCC_BLSP1_QUP5_SPI_APPS_CLK, &gcc_blsp1_qup5_spi_apps_clk.hw),
+ MAP(GCC_BLSP1_QUP6_I2C_APPS_CLK, &gcc_blsp1_qup6_i2c_apps_clk.hw),
+ MAP(GCC_BLSP1_QUP6_SPI_APPS_CLK, &gcc_blsp1_qup6_spi_apps_clk.hw),
+ MAP(GCC_BLSP1_UART1_APPS_CLK, &gcc_blsp1_uart1_apps_clk.hw),
+ MAP(GCC_BLSP1_UART2_APPS_CLK, &gcc_blsp1_uart2_apps_clk.hw),
+ MAP(GCC_BLSP1_UART3_APPS_CLK, &gcc_blsp1_uart3_apps_clk.hw),
+ MAP(GCC_BLSP1_UART4_APPS_CLK, &gcc_blsp1_uart4_apps_clk.hw),
+ MAP(GCC_BLSP1_UART5_APPS_CLK, &gcc_blsp1_uart5_apps_clk.hw),
+ MAP(GCC_BLSP1_UART6_APPS_CLK, &gcc_blsp1_uart6_apps_clk.hw),
+ MAP(GCC_BLSP2_AHB_CLK, &gcc_blsp2_ahb_clk.hw),
+ MAP(GCC_BLSP2_QUP1_I2C_APPS_CLK, &gcc_blsp2_qup1_i2c_apps_clk.hw),
+ MAP(GCC_BLSP2_QUP1_SPI_APPS_CLK, &gcc_blsp2_qup1_spi_apps_clk.hw),
+ MAP(GCC_BLSP2_QUP2_I2C_APPS_CLK, &gcc_blsp2_qup2_i2c_apps_clk.hw),
+ MAP(GCC_BLSP2_QUP2_SPI_APPS_CLK, &gcc_blsp2_qup2_spi_apps_clk.hw),
+ MAP(GCC_BLSP2_QUP3_I2C_APPS_CLK, &gcc_blsp2_qup3_i2c_apps_clk.hw),
+ MAP(GCC_BLSP2_QUP3_SPI_APPS_CLK, &gcc_blsp2_qup3_spi_apps_clk.hw),
+ MAP(GCC_BLSP2_QUP4_I2C_APPS_CLK, &gcc_blsp2_qup4_i2c_apps_clk.hw),
+ MAP(GCC_BLSP2_QUP4_SPI_APPS_CLK, &gcc_blsp2_qup4_spi_apps_clk.hw),
+ MAP(GCC_BLSP2_QUP5_I2C_APPS_CLK, &gcc_blsp2_qup5_i2c_apps_clk.hw),
+ MAP(GCC_BLSP2_QUP5_SPI_APPS_CLK, &gcc_blsp2_qup5_spi_apps_clk.hw),
+ MAP(GCC_BLSP2_QUP6_I2C_APPS_CLK, &gcc_blsp2_qup6_i2c_apps_clk.hw),
+ MAP(GCC_BLSP2_QUP6_SPI_APPS_CLK, &gcc_blsp2_qup6_spi_apps_clk.hw),
+ MAP(GCC_BLSP2_UART1_APPS_CLK, &gcc_blsp2_uart1_apps_clk.hw),
+ MAP(GCC_BLSP2_UART2_APPS_CLK, &gcc_blsp2_uart2_apps_clk.hw),
+ MAP(GCC_BLSP2_UART3_APPS_CLK, &gcc_blsp2_uart3_apps_clk.hw),
+ MAP(GCC_BLSP2_UART4_APPS_CLK, &gcc_blsp2_uart4_apps_clk.hw),
+ MAP(GCC_BLSP2_UART5_APPS_CLK, &gcc_blsp2_uart5_apps_clk.hw),
+ MAP(GCC_BLSP2_UART6_APPS_CLK, &gcc_blsp2_uart6_apps_clk.hw),
+ MAP(GCC_BOOT_ROM_AHB_CLK, &gcc_boot_rom_ahb_clk.hw),
+ MAP(GCC_CE1_AHB_CLK, &gcc_ce1_ahb_clk.hw),
+ MAP(GCC_CE1_AXI_CLK, &gcc_ce1_axi_clk.hw),
+ MAP(GCC_CE1_CLK, &gcc_ce1_clk.hw),
+ MAP(GCC_CE2_AHB_CLK, &gcc_ce2_ahb_clk.hw),
+ MAP(GCC_CE2_AXI_CLK, &gcc_ce2_axi_clk.hw),
+ MAP(GCC_CE2_CLK, &gcc_ce2_clk.hw),
+ MAP(GCC_GP1_CLK, &gcc_gp1_clk.hw),
+ MAP(GCC_GP2_CLK, &gcc_gp2_clk.hw),
+ MAP(GCC_GP3_CLK, &gcc_gp3_clk.hw),
+ MAP(GCC_PDM2_CLK, &gcc_pdm2_clk.hw),
+ MAP(GCC_PRNG_AHB_CLK, &gcc_prng_ahb_clk.hw),
+ MAP(GCC_SDCC1_APPS_CLK, &gcc_sdcc1_apps_clk.hw),
+ MAP(GCC_SDCC2_APPS_CLK, &gcc_sdcc2_apps_clk.hw),
+ MAP(GCC_SDCC3_APPS_CLK, &gcc_sdcc3_apps_clk.hw),
+ MAP(GCC_SDCC4_APPS_CLK, &gcc_sdcc4_apps_clk.hw),
+ MAP(GCC_SYS_NOC_USB3_AXI_CLK, &gcc_sys_noc_usb3_axi_clk.hw),
+ MAP(GCC_TSIF_REF_CLK, &gcc_tsif_ref_clk.hw),
+ MAP(GCC_USB2A_PHY_SLEEP_CLK, &gcc_usb2a_phy_sleep_clk.hw),
+ MAP(GCC_USB2B_PHY_SLEEP_CLK, &gcc_usb2b_phy_sleep_clk.hw),
+ MAP(GCC_USB30_MASTER_CLK, &gcc_usb30_master_clk.hw),
+ MAP(GCC_USB30_MOCK_UTMI_CLK, &gcc_usb30_mock_utmi_clk.hw),
+ MAP(GCC_USB30_SLEEP_CLK, &gcc_usb30_sleep_clk.hw),
+ MAP(GCC_USB_HS_SYSTEM_CLK, &gcc_usb_hs_system_clk.hw),
+ MAP(GCC_USB_HSIC_CLK, &gcc_usb_hsic_clk.hw),
+ MAP(GCC_USB_HSIC_IO_CAL_CLK, &gcc_usb_hsic_io_cal_clk.hw),
+ MAP(GCC_USB_HSIC_IO_CAL_SLEEP_CLK, &gcc_usb_hsic_io_cal_sleep_clk.hw),
+ MAP(GCC_USB_HSIC_SYSTEM_CLK, &gcc_usb_hsic_system_clk.hw),
+};
+
+static const struct regmap_config msm_gcc_8974_regmap_config = {
+ .reg_bits = 32,
+ .reg_stride = 4,
+ .val_bits = 32,
+ .max_register = 0x1a00,
+ .fast_io = true,
+};
+
+static const struct of_device_id msm_gcc_8974_match_table[] = {
+ { .compatible = "qcom,gcc-8974" },
+ { }
+};
+MODULE_DEVICE_TABLE(of, msm_gcc_8974_match_table);
+
+static int msm_gcc_8974_probe(struct platform_device *pdev)
+{
+ void __iomem *base;
+ struct resource *res;
+ int i;
+ struct device *dev = &pdev->dev;
+ struct clk *clk;
+ struct clk_onecell_data *data;
+ struct clk **clks;
+ struct regmap *regmap;
+ size_t num_clks;
+
+ 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, &msm_gcc_8974_regmap_config);
+ if (IS_ERR(regmap))
+ return PTR_ERR(regmap);
+
+ num_clks = ARRAY_SIZE(map);
+ data = devm_kzalloc(dev, sizeof(*data) + sizeof(*clks) * num_clks,
+ GFP_KERNEL);
+ if (!data)
+ return -ENOMEM;
+
+ clks = (struct clk **)(data + 1);
+ 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, "gcc_sleep_clk_src", NULL,
+ CLK_IS_ROOT, 32768);
+ if (IS_ERR(clk))
+ return PTR_ERR(clk);
+
+ for (i = 0; i < num_clks; i++) {
+ if (!map[i].hw)
+ continue;
+ clk = devm_clk_register(dev, map[i].hw);
+ if (IS_ERR(clk))
+ return PTR_ERR(clk);
+ clks[map[i].id] = clk;
+ }
+
+ return of_clk_add_provider(dev->of_node, of_clk_src_onecell_get, data);
+}
+
+static int msm_gcc_8974_remove(struct platform_device *pdev)
+{
+ of_clk_del_provider(pdev->dev.of_node);
+ return 0;
+}
+
+static struct platform_driver msm_gcc_8974_driver = {
+ .probe = msm_gcc_8974_probe,
+ .remove = msm_gcc_8974_remove,
+ .driver = {
+ .name = "msm-gcc-8974",
+ .owner = THIS_MODULE,
+ .of_match_table = msm_gcc_8974_match_table,
+ },
+};
+
+static int __init msm_gcc_8974_init(void)
+{
+ return platform_driver_register(&msm_gcc_8974_driver);
+}
+core_initcall(msm_gcc_8974_init);
+
+static void __exit msm_gcc_8974_exit(void)
+{
+ platform_driver_unregister(&msm_gcc_8974_driver);
+}
+module_exit(msm_gcc_8974_exit);
+
+MODULE_DESCRIPTION("MSM GCC 8974 Driver");
+MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("platform:msm-gcc-8974");
diff --git a/include/dt-bindings/clk/msm-gcc-8974.h b/include/dt-bindings/clk/msm-gcc-8974.h
new file mode 100644
index 0000000..207ec32
--- /dev/null
+++ b/include/dt-bindings/clk/msm-gcc-8974.h
@@ -0,0 +1,154 @@
+/*
+ * 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 PERIPH_NOC_CLK_SRC 3
+#define SYSTEM_NOC_CLK_SRC 4
+#define GPLL1 5
+#define GPLL1_VOTE 6
+#define USB30_MASTER_CLK_SRC 7
+#define BLSP1_QUP1_I2C_APPS_CLK_SRC 8
+#define BLSP1_QUP1_SPI_APPS_CLK_SRC 9
+#define BLSP1_QUP2_I2C_APPS_CLK_SRC 10
+#define BLSP1_QUP2_SPI_APPS_CLK_SRC 11
+#define BLSP1_QUP3_I2C_APPS_CLK_SRC 12
+#define BLSP1_QUP3_SPI_APPS_CLK_SRC 13
+#define BLSP1_QUP4_I2C_APPS_CLK_SRC 14
+#define BLSP1_QUP4_SPI_APPS_CLK_SRC 15
+#define BLSP1_QUP5_I2C_APPS_CLK_SRC 16
+#define BLSP1_QUP5_SPI_APPS_CLK_SRC 17
+#define BLSP1_QUP6_I2C_APPS_CLK_SRC 18
+#define BLSP1_QUP6_SPI_APPS_CLK_SRC 19
+#define BLSP1_UART1_APPS_CLK_SRC 20
+#define BLSP1_UART2_APPS_CLK_SRC 21
+#define BLSP1_UART3_APPS_CLK_SRC 22
+#define BLSP1_UART4_APPS_CLK_SRC 23
+#define BLSP1_UART5_APPS_CLK_SRC 24
+#define BLSP1_UART6_APPS_CLK_SRC 25
+#define BLSP2_QUP1_I2C_APPS_CLK_SRC 26
+#define BLSP2_QUP1_SPI_APPS_CLK_SRC 27
+#define BLSP2_QUP2_I2C_APPS_CLK_SRC 28
+#define BLSP2_QUP2_SPI_APPS_CLK_SRC 29
+#define BLSP2_QUP3_I2C_APPS_CLK_SRC 30
+#define BLSP2_QUP3_SPI_APPS_CLK_SRC 31
+#define BLSP2_QUP4_I2C_APPS_CLK_SRC 32
+#define BLSP2_QUP4_SPI_APPS_CLK_SRC 33
+#define BLSP2_QUP5_I2C_APPS_CLK_SRC 34
+#define BLSP2_QUP5_SPI_APPS_CLK_SRC 35
+#define BLSP2_QUP6_I2C_APPS_CLK_SRC 36
+#define BLSP2_QUP6_SPI_APPS_CLK_SRC 37
+#define BLSP2_UART1_APPS_CLK_SRC 38
+#define BLSP2_UART2_APPS_CLK_SRC 39
+#define BLSP2_UART3_APPS_CLK_SRC 40
+#define BLSP2_UART4_APPS_CLK_SRC 41
+#define BLSP2_UART5_APPS_CLK_SRC 42
+#define BLSP2_UART6_APPS_CLK_SRC 43
+#define CE1_CLK_SRC 44
+#define CE2_CLK_SRC 45
+#define GP1_CLK_SRC 46
+#define GP2_CLK_SRC 47
+#define GP3_CLK_SRC 48
+#define PDM2_CLK_SRC 49
+#define SDCC1_APPS_CLK_SRC 50
+#define SDCC2_APPS_CLK_SRC 51
+#define SDCC3_APPS_CLK_SRC 52
+#define SDCC4_APPS_CLK_SRC 53
+#define TSIF_REF_CLK_SRC 54
+#define USB30_MOCK_UTMI_CLK_SRC 55
+#define USB_HS_SYSTEM_CLK_SRC 56
+#define USB_HSIC_CLK_SRC 57
+#define USB_HSIC_IO_CAL_CLK_SRC 58
+#define USB_HSIC_SYSTEM_CLK_SRC 59
+#define GCC_BAM_DMA_AHB_CLK 60
+#define GCC_BLSP1_AHB_CLK 61
+#define GCC_BLSP1_QUP1_I2C_APPS_CLK 62
+#define GCC_BLSP1_QUP1_SPI_APPS_CLK 63
+#define GCC_BLSP1_QUP2_I2C_APPS_CLK 64
+#define GCC_BLSP1_QUP2_SPI_APPS_CLK 65
+#define GCC_BLSP1_QUP3_I2C_APPS_CLK 66
+#define GCC_BLSP1_QUP3_SPI_APPS_CLK 67
+#define GCC_BLSP1_QUP4_I2C_APPS_CLK 68
+#define GCC_BLSP1_QUP4_SPI_APPS_CLK 69
+#define GCC_BLSP1_QUP5_I2C_APPS_CLK 70
+#define GCC_BLSP1_QUP5_SPI_APPS_CLK 71
+#define GCC_BLSP1_QUP6_I2C_APPS_CLK 72
+#define GCC_BLSP1_QUP6_SPI_APPS_CLK 73
+#define GCC_BLSP1_UART1_APPS_CLK 74
+#define GCC_BLSP1_UART1_SIM_CLK 75
+#define GCC_BLSP1_UART2_APPS_CLK 76
+#define GCC_BLSP1_UART2_SIM_CLK 77
+#define GCC_BLSP1_UART3_APPS_CLK 78
+#define GCC_BLSP1_UART3_SIM_CLK 79
+#define GCC_BLSP1_UART4_APPS_CLK 80
+#define GCC_BLSP1_UART4_SIM_CLK 81
+#define GCC_BLSP1_UART5_APPS_CLK 82
+#define GCC_BLSP1_UART5_SIM_CLK 83
+#define GCC_BLSP1_UART6_APPS_CLK 84
+#define GCC_BLSP1_UART6_SIM_CLK 85
+#define GCC_BLSP2_AHB_CLK 86
+#define GCC_BLSP2_QUP1_I2C_APPS_CLK 87
+#define GCC_BLSP2_QUP1_SPI_APPS_CLK 88
+#define GCC_BLSP2_QUP2_I2C_APPS_CLK 89
+#define GCC_BLSP2_QUP2_SPI_APPS_CLK 90
+#define GCC_BLSP2_QUP3_I2C_APPS_CLK 91
+#define GCC_BLSP2_QUP3_SPI_APPS_CLK 92
+#define GCC_BLSP2_QUP4_I2C_APPS_CLK 93
+#define GCC_BLSP2_QUP4_SPI_APPS_CLK 94
+#define GCC_BLSP2_QUP5_I2C_APPS_CLK 95
+#define GCC_BLSP2_QUP5_SPI_APPS_CLK 96
+#define GCC_BLSP2_QUP6_I2C_APPS_CLK 97
+#define GCC_BLSP2_QUP6_SPI_APPS_CLK 98
+#define GCC_BLSP2_UART1_APPS_CLK 99
+#define GCC_BLSP2_UART2_APPS_CLK 100
+#define GCC_BLSP2_UART3_APPS_CLK 101
+#define GCC_BLSP2_UART4_APPS_CLK 102
+#define GCC_BLSP2_UART5_APPS_CLK 103
+#define GCC_BLSP2_UART6_APPS_CLK 104
+#define GCC_BOOT_ROM_AHB_CLK 105
+#define GCC_CE1_AHB_CLK 106
+#define GCC_CE1_AXI_CLK 107
+#define GCC_CE1_CLK 108
+#define GCC_CE2_AHB_CLK 109
+#define GCC_CE2_AXI_CLK 110
+#define GCC_CE2_CLK 111
+#define GCC_XO_CLK 112
+#define GCC_XO_DIV4_CLK 113
+#define GCC_GP1_CLK 114
+#define GCC_GP2_CLK 115
+#define GCC_GP3_CLK 116
+#define GCC_MSS_Q6_BIMC_AXI_CLK 117
+#define GCC_PDM2_CLK 118
+#define GCC_PRNG_AHB_CLK 119
+#define GCC_SDCC1_APPS_CLK 120
+#define GCC_SDCC2_APPS_CLK 121
+#define GCC_SDCC3_APPS_CLK 122
+#define GCC_SDCC4_APPS_CLK 123
+#define GCC_SYS_NOC_USB3_AXI_CLK 124
+#define GCC_TSIF_REF_CLK 125
+#define GCC_USB2A_PHY_SLEEP_CLK 126
+#define GCC_USB2B_PHY_SLEEP_CLK 127
+#define GCC_USB30_MASTER_CLK 128
+#define GCC_USB30_MOCK_UTMI_CLK 129
+#define GCC_USB30_SLEEP_CLK 130
+#define GCC_USB_HS_SYSTEM_CLK 131
+#define GCC_USB_HSIC_CLK 132
+#define GCC_USB_HSIC_IO_CAL_CLK 133
+#define GCC_USB_HSIC_IO_CAL_SLEEP_CLK 134
+#define GCC_USB_HSIC_SYSTEM_CLK 135
+
+#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] 10+ messages in thread
end of thread, other threads:[~2013-10-02 19:07 UTC | newest]
Thread overview: 10+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2013-10-02 19:06 [PATCH v2 0/9] Add support for MSM's mmio clocks Stephen Boyd
2013-10-02 19:06 ` [PATCH v2 1/9] clk: Allow drivers to pass in a regmap Stephen Boyd
2013-10-02 19:06 ` [PATCH v2 2/9] clk: Add regmap core helpers for enable/disable/is_enabled Stephen Boyd
2013-10-02 19:07 ` [PATCH v2 3/9] clk: Add set_rate_and_parent() op Stephen Boyd
2013-10-02 19:07 ` [PATCH v2 4/9] clk: msm: Add support for phase locked loops (PLLs) Stephen Boyd
2013-10-02 19:07 ` [PATCH v2 5/9] clk: msm: Add support for root clock generators (RCGs) Stephen Boyd
2013-10-02 19:07 ` [PATCH v2 6/9] clk: msm: Add support for branches/gate clocks Stephen Boyd
2013-10-02 19:07 ` [PATCH v2 7/9] clk: msm: Add support for MSM8960's global clock controller (GCC) Stephen Boyd
2013-10-02 19:07 ` [PATCH v2 8/9] clk: msm: Add support for MSM8960's multimedia clock controller (MMCC) Stephen Boyd
2013-10-02 19:07 ` [PATCH v2 9/9] clk: msm: Add support for MSM8974's global clock controller (GCC) 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).