* [PATCH 01/22] msm: clock: Remove unused code and definitions
2010-12-17 0:49 [PATCH 00/22] MSM clock driver updates Stephen Boyd
@ 2010-12-17 0:49 ` Stephen Boyd
2010-12-17 0:49 ` [PATCH 02/22] msm: clock: Move debugfs code from clock.c to clock-debug.c Stephen Boyd
` (20 subsequent siblings)
21 siblings, 0 replies; 23+ messages in thread
From: Stephen Boyd @ 2010-12-17 0:49 UTC (permalink / raw)
To: linux-arm-kernel
Remove dead code and push out clock-7x30.h and clock-pcom.h to
where they are actually used.
Reviewed-by: Saravana Kannan <skannan@codeaurora.org>
Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
---
arch/arm/mach-msm/board-msm8x60.c | 5 ----
arch/arm/mach-msm/clock-pcom.c | 1 +
arch/arm/mach-msm/clock.c | 21 ++--------------
arch/arm/mach-msm/clock.h | 45 -----------------------------------
arch/arm/mach-msm/devices-msm7x30.c | 1 +
arch/arm/mach-msm/devices-qsd8x50.c | 1 +
6 files changed, 6 insertions(+), 68 deletions(-)
diff --git a/arch/arm/mach-msm/board-msm8x60.c b/arch/arm/mach-msm/board-msm8x60.c
index 7486a68..852428b 100644
--- a/arch/arm/mach-msm/board-msm8x60.c
+++ b/arch/arm/mach-msm/board-msm8x60.c
@@ -30,11 +30,6 @@
void __iomem *gic_cpu_base_addr;
-unsigned long clk_get_max_axi_khz(void)
-{
- return 0;
-}
-
static void __init msm8x60_map_io(void)
{
msm_map_msm8x60_io();
diff --git a/arch/arm/mach-msm/clock-pcom.c b/arch/arm/mach-msm/clock-pcom.c
index a3b4562..8c4e867 100644
--- a/arch/arm/mach-msm/clock-pcom.c
+++ b/arch/arm/mach-msm/clock-pcom.c
@@ -20,6 +20,7 @@
#include "proc_comm.h"
#include "clock.h"
+#include "clock-pcom.h"
/*
* glue for the proc_comm interface
diff --git a/arch/arm/mach-msm/clock.c b/arch/arm/mach-msm/clock.c
index 2069bfa..8f71f8d 100644
--- a/arch/arm/mach-msm/clock.c
+++ b/arch/arm/mach-msm/clock.c
@@ -29,6 +29,7 @@
#include "clock.h"
#include "proc_comm.h"
#include "clock-7x30.h"
+#include "clock-pcom.h"
static DEFINE_MUTEX(clocks_mutex);
static DEFINE_SPINLOCK(clocks_lock);
@@ -37,13 +38,6 @@ struct clk *msm_clocks;
unsigned msm_num_clocks;
/*
- * Bitmap of enabled clocks, excluding ACPU which is always
- * enabled
- */
-static DECLARE_BITMAP(clock_map_enabled, NR_CLKS);
-static DEFINE_SPINLOCK(clock_map_lock);
-
-/*
* Standard clock functions defined in include/linux/clk.h
*/
struct clk *clk_get(struct device *dev, const char *id)
@@ -77,12 +71,8 @@ int clk_enable(struct clk *clk)
unsigned long flags;
spin_lock_irqsave(&clocks_lock, flags);
clk->count++;
- if (clk->count == 1) {
+ if (clk->count == 1)
clk->ops->enable(clk->id);
- spin_lock(&clock_map_lock);
- clock_map_enabled[BIT_WORD(clk->id)] |= BIT_MASK(clk->id);
- spin_unlock(&clock_map_lock);
- }
spin_unlock_irqrestore(&clocks_lock, flags);
return 0;
}
@@ -94,12 +84,8 @@ void clk_disable(struct clk *clk)
spin_lock_irqsave(&clocks_lock, flags);
BUG_ON(clk->count == 0);
clk->count--;
- if (clk->count == 0) {
+ if (clk->count == 0)
clk->ops->disable(clk->id);
- spin_lock(&clock_map_lock);
- clock_map_enabled[BIT_WORD(clk->id)] &= ~BIT_MASK(clk->id);
- spin_unlock(&clock_map_lock);
- }
spin_unlock_irqrestore(&clocks_lock, flags);
}
EXPORT_SYMBOL(clk_disable);
@@ -196,7 +182,6 @@ void __init msm_clock_init(struct clk *clock_tbl, unsigned num_clocks)
{
unsigned n;
- spin_lock_init(&clocks_lock);
mutex_lock(&clocks_mutex);
msm_clocks = clock_tbl;
msm_num_clocks = num_clocks;
diff --git a/arch/arm/mach-msm/clock.h b/arch/arm/mach-msm/clock.h
index c270b55..6a0cade 100644
--- a/arch/arm/mach-msm/clock.h
+++ b/arch/arm/mach-msm/clock.h
@@ -20,9 +20,6 @@
#include <linux/list.h>
#include <mach/clk.h>
-#include "clock-pcom.h"
-#include "clock-7x30.h"
-
#define CLKFLAG_INVERT 0x00000001
#define CLKFLAG_NOINVERT 0x00000002
#define CLKFLAG_NONEST 0x00000004
@@ -59,51 +56,9 @@ struct clk {
struct device *dev;
};
-#define A11S_CLK_CNTL_ADDR (MSM_CSR_BASE + 0x100)
-#define A11S_CLK_SEL_ADDR (MSM_CSR_BASE + 0x104)
-#define A11S_VDD_SVS_PLEVEL_ADDR (MSM_CSR_BASE + 0x124)
-
-#ifdef CONFIG_DEBUG_FS
-#define CLOCK_DBG_NAME(x) .dbg_name = x,
-#else
-#define CLOCK_DBG_NAME(x)
-#endif
-
-#define CLOCK(clk_name, clk_id, clk_dev, clk_flags) { \
- .name = clk_name, \
- .id = clk_id, \
- .flags = clk_flags, \
- .dev = clk_dev, \
- CLOCK_DBG_NAME(#clk_id) \
- }
-
#define OFF CLKFLAG_AUTO_OFF
#define CLK_MIN CLKFLAG_MIN
#define CLK_MAX CLKFLAG_MAX
#define CLK_MINMAX (CLK_MIN | CLK_MAX)
-#define NR_CLKS P_NR_CLKS
-
-enum {
- PLL_0 = 0,
- PLL_1,
- PLL_2,
- PLL_3,
- PLL_4,
- PLL_5,
- PLL_6,
- NUM_PLL
-};
-
-enum clkvote_client {
- CLKVOTE_ACPUCLK = 0,
- CLKVOTE_PMQOS,
- CLKVOTE_MAX,
-};
-
-int msm_clock_require_tcxo(unsigned long *reason, int nbits);
-int msm_clock_get_name(uint32_t id, char *name, uint32_t size);
-int ebi1_clk_set_min_rate(enum clkvote_client client, unsigned long rate);
-unsigned long clk_get_max_axi_khz(void);
#endif
-
diff --git a/arch/arm/mach-msm/devices-msm7x30.c b/arch/arm/mach-msm/devices-msm7x30.c
index 7fcf2e3..2a9958f 100644
--- a/arch/arm/mach-msm/devices-msm7x30.c
+++ b/arch/arm/mach-msm/devices-msm7x30.c
@@ -28,6 +28,7 @@
#include <asm/mach/flash.h>
#include "clock-pcom.h"
+#include "clock-7x30.h"
#include <mach/mmc.h>
diff --git a/arch/arm/mach-msm/devices-qsd8x50.c b/arch/arm/mach-msm/devices-qsd8x50.c
index 6fe67c5..f92c5c2 100644
--- a/arch/arm/mach-msm/devices-qsd8x50.c
+++ b/arch/arm/mach-msm/devices-qsd8x50.c
@@ -27,6 +27,7 @@
#include <asm/mach/flash.h>
#include <mach/mmc.h>
+#include "clock-pcom.h"
static struct resource resources_uart3[] = {
{
--
Sent by an employee of the Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum.
^ permalink raw reply related [flat|nested] 23+ messages in thread* [PATCH 02/22] msm: clock: Move debugfs code from clock.c to clock-debug.c
2010-12-17 0:49 [PATCH 00/22] MSM clock driver updates Stephen Boyd
2010-12-17 0:49 ` [PATCH 01/22] msm: clock: Remove unused code and definitions Stephen Boyd
@ 2010-12-17 0:49 ` Stephen Boyd
2010-12-17 0:49 ` [PATCH 03/22] msm: clock: Invert debugfs directory layout Stephen Boyd
` (19 subsequent siblings)
21 siblings, 0 replies; 23+ messages in thread
From: Stephen Boyd @ 2010-12-17 0:49 UTC (permalink / raw)
To: linux-arm-kernel
From: Matt Wagantall <mattw@codeaurora.org>
The clock debugfs code is large enough, and easy enough to separate,
that it deserves its own file which is compiled only when
CONFIG_DEBUG_FS is enabled.
Also, cleanup header file #includes that are no longer required.
Reviewed-by: Saravana Kannan <skannan@codeaurora.org>
Signed-off-by: Matt Wagantall <mattw@codeaurora.org>
Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
---
arch/arm/mach-msm/Makefile | 3 +
arch/arm/mach-msm/clock-debug.c | 133 +++++++++++++++++++++++++++++++++++++++
arch/arm/mach-msm/clock.c | 127 ++-----------------------------------
arch/arm/mach-msm/clock.h | 9 +++
4 files changed, 150 insertions(+), 122 deletions(-)
create mode 100644 arch/arm/mach-msm/clock-debug.c
diff --git a/arch/arm/mach-msm/Makefile b/arch/arm/mach-msm/Makefile
index 59646bb..dc8ef08 100644
--- a/arch/arm/mach-msm/Makefile
+++ b/arch/arm/mach-msm/Makefile
@@ -1,4 +1,7 @@
obj-y += io.o idle.o timer.o
+ifdef CONFIG_MSM_PROC_COMM
+obj-$(CONFIG_DEBUG_FS) += clock-debug.o
+endif
ifndef CONFIG_ARCH_MSM8X60
obj-y += acpuclock-arm11.o
obj-y += dma.o
diff --git a/arch/arm/mach-msm/clock-debug.c b/arch/arm/mach-msm/clock-debug.c
new file mode 100644
index 0000000..6f603ed
--- /dev/null
+++ b/arch/arm/mach-msm/clock-debug.c
@@ -0,0 +1,133 @@
+/*
+ * Copyright (C) 2007 Google, Inc.
+ * Copyright (c) 2007-2010, Code Aurora Forum. 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/module.h>
+#include <linux/ctype.h>
+#include <linux/debugfs.h>
+#include <linux/clk.h>
+#include "clock.h"
+#include "clock-pcom.h"
+
+static int clock_debug_rate_set(void *data, u64 val)
+{
+ struct clk *clock = data;
+ int ret;
+
+ /* Only increases to max rate will succeed, but that's actually good
+ * for debugging purposes so we don't check for error. */
+ if (clock->flags & CLK_MAX)
+ clk_set_max_rate(clock, val);
+ if (clock->flags & CLK_MIN)
+ ret = clk_set_min_rate(clock, val);
+ else
+ ret = clk_set_rate(clock, val);
+ if (ret != 0)
+ printk(KERN_ERR "clk_set%s_rate failed (%d)\n",
+ (clock->flags & CLK_MIN) ? "_min" : "", ret);
+ return ret;
+}
+
+static int clock_debug_rate_get(void *data, u64 *val)
+{
+ struct clk *clock = data;
+ *val = clk_get_rate(clock);
+ return 0;
+}
+
+DEFINE_SIMPLE_ATTRIBUTE(clock_rate_fops, clock_debug_rate_get,
+ clock_debug_rate_set, "%llu\n");
+
+static int clock_debug_enable_set(void *data, u64 val)
+{
+ struct clk *clock = data;
+ int rc = 0;
+
+ if (val)
+ rc = clock->ops->enable(clock->id);
+ else
+ clock->ops->disable(clock->id);
+
+ return rc;
+}
+
+static int clock_debug_enable_get(void *data, u64 *val)
+{
+ struct clk *clock = data;
+
+ *val = clock->ops->is_enabled(clock->id);
+
+ return 0;
+}
+
+DEFINE_SIMPLE_ATTRIBUTE(clock_enable_fops, clock_debug_enable_get,
+ clock_debug_enable_set, "%llu\n");
+
+static int clock_debug_local_get(void *data, u64 *val)
+{
+ struct clk *clock = data;
+
+ *val = clock->ops != &clk_ops_pcom;
+
+ return 0;
+}
+
+DEFINE_SIMPLE_ATTRIBUTE(clock_local_fops, clock_debug_local_get,
+ NULL, "%llu\n");
+
+static struct dentry *dent_rate, *dent_enable, *dent_local;
+
+int __init clock_debug_init(void)
+{
+ dent_rate = debugfs_create_dir("clk_rate", 0);
+ if (!dent_rate)
+ goto err;
+
+ dent_enable = debugfs_create_dir("clk_enable", 0);
+ if (!dent_enable)
+ goto err;
+
+ dent_local = debugfs_create_dir("clk_local", NULL);
+ if (!dent_local)
+ goto err;
+
+ return 0;
+err:
+ debugfs_remove(dent_local);
+ debugfs_remove(dent_enable);
+ debugfs_remove(dent_rate);
+ return -ENOMEM;
+}
+
+int __init clock_debug_add(struct clk *clock)
+{
+ char temp[50], *ptr;
+
+ if (!dent_rate || !dent_enable || !dent_local)
+ return -ENOMEM;
+
+ strncpy(temp, clock->dbg_name, ARRAY_SIZE(temp)-1);
+ for (ptr = temp; *ptr; ptr++)
+ *ptr = tolower(*ptr);
+
+ debugfs_create_file(temp, S_IRUGO | S_IWUSR, dent_rate,
+ clock, &clock_rate_fops);
+ debugfs_create_file(temp, S_IRUGO | S_IWUSR, dent_enable,
+ clock, &clock_enable_fops);
+ debugfs_create_file(temp, S_IRUGO, dent_local,
+ clock, &clock_local_fops);
+
+ return 0;
+}
diff --git a/arch/arm/mach-msm/clock.c b/arch/arm/mach-msm/clock.c
index 8f71f8d..8c2b4dd 100644
--- a/arch/arm/mach-msm/clock.c
+++ b/arch/arm/mach-msm/clock.c
@@ -15,16 +15,10 @@
*/
#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/module.h>
#include <linux/list.h>
#include <linux/err.h>
-#include <linux/clk.h>
#include <linux/spinlock.h>
-#include <linux/debugfs.h>
-#include <linux/ctype.h>
#include <linux/pm_qos_params.h>
-#include <mach/clk.h>
#include "clock.h"
#include "proc_comm.h"
@@ -34,8 +28,6 @@
static DEFINE_MUTEX(clocks_mutex);
static DEFINE_SPINLOCK(clocks_lock);
static LIST_HEAD(clocks);
-struct clk *msm_clocks;
-unsigned msm_num_clocks;
/*
* Standard clock functions defined in include/linux/clk.h
@@ -183,11 +175,9 @@ void __init msm_clock_init(struct clk *clock_tbl, unsigned num_clocks)
unsigned n;
mutex_lock(&clocks_mutex);
- msm_clocks = clock_tbl;
- msm_num_clocks = num_clocks;
- for (n = 0; n < msm_num_clocks; n++) {
- set_clock_ops(&msm_clocks[n]);
- list_add_tail(&msm_clocks[n].list, &clocks);
+ for (n = 0; n < num_clocks; n++) {
+ set_clock_ops(&clock_tbl[n]);
+ list_add_tail(&clock_tbl[n].list, &clocks);
}
mutex_unlock(&clocks_mutex);
@@ -196,115 +186,6 @@ void __init msm_clock_init(struct clk *clock_tbl, unsigned num_clocks)
}
-#if defined(CONFIG_DEBUG_FS)
-static struct clk *msm_clock_get_nth(unsigned index)
-{
- if (index < msm_num_clocks)
- return msm_clocks + index;
- else
- return 0;
-}
-
-static int clock_debug_rate_set(void *data, u64 val)
-{
- struct clk *clock = data;
- int ret;
-
- /* Only increases to max rate will succeed, but that's actually good
- * for debugging purposes. So we don't check for error. */
- if (clock->flags & CLK_MAX)
- clk_set_max_rate(clock, val);
- if (clock->flags & CLK_MIN)
- ret = clk_set_min_rate(clock, val);
- else
- ret = clk_set_rate(clock, val);
- if (ret != 0)
- printk(KERN_ERR "clk_set%s_rate failed (%d)\n",
- (clock->flags & CLK_MIN) ? "_min" : "", ret);
- return ret;
-}
-
-static int clock_debug_rate_get(void *data, u64 *val)
-{
- struct clk *clock = data;
- *val = clk_get_rate(clock);
- return 0;
-}
-
-static int clock_debug_enable_set(void *data, u64 val)
-{
- struct clk *clock = data;
- int rc = 0;
-
- if (val)
- rc = clock->ops->enable(clock->id);
- else
- clock->ops->disable(clock->id);
-
- return rc;
-}
-
-static int clock_debug_enable_get(void *data, u64 *val)
-{
- struct clk *clock = data;
-
- *val = clock->ops->is_enabled(clock->id);
-
- return 0;
-}
-
-static int clock_debug_local_get(void *data, u64 *val)
-{
- struct clk *clock = data;
-
- *val = clock->ops != &clk_ops_pcom;
-
- return 0;
-}
-
-DEFINE_SIMPLE_ATTRIBUTE(clock_rate_fops, clock_debug_rate_get,
- clock_debug_rate_set, "%llu\n");
-DEFINE_SIMPLE_ATTRIBUTE(clock_enable_fops, clock_debug_enable_get,
- clock_debug_enable_set, "%llu\n");
-DEFINE_SIMPLE_ATTRIBUTE(clock_local_fops, clock_debug_local_get,
- NULL, "%llu\n");
-
-static int __init clock_debug_init(void)
-{
- struct dentry *dent_rate, *dent_enable, *dent_local;
- struct clk *clock;
- unsigned n = 0;
- char temp[50], *ptr;
-
- dent_rate = debugfs_create_dir("clk_rate", 0);
- if (IS_ERR(dent_rate))
- return PTR_ERR(dent_rate);
-
- dent_enable = debugfs_create_dir("clk_enable", 0);
- if (IS_ERR(dent_enable))
- return PTR_ERR(dent_enable);
-
- dent_local = debugfs_create_dir("clk_local", NULL);
- if (IS_ERR(dent_local))
- return PTR_ERR(dent_local);
-
- while ((clock = msm_clock_get_nth(n++)) != 0) {
- strncpy(temp, clock->dbg_name, ARRAY_SIZE(temp)-1);
- for (ptr = temp; *ptr; ptr++)
- *ptr = tolower(*ptr);
- debugfs_create_file(temp, 0644, dent_rate,
- clock, &clock_rate_fops);
- debugfs_create_file(temp, 0644, dent_enable,
- clock, &clock_enable_fops);
- debugfs_create_file(temp, S_IRUGO, dent_local,
- clock, &clock_local_fops);
- }
- return 0;
-}
-
-device_initcall(clock_debug_init);
-#endif
-
/* The bootloader and/or AMSS may have left various clocks enabled.
* Disable any clocks that belong to us (CLKFLAG_AUTO_OFF) but have
* not been explicitly enabled by a clk_enable() call.
@@ -315,8 +196,10 @@ static int __init clock_late_init(void)
struct clk *clk;
unsigned count = 0;
+ clock_debug_init();
mutex_lock(&clocks_mutex);
list_for_each_entry(clk, &clocks, list) {
+ clock_debug_add(clk);
if (clk->flags & CLKFLAG_AUTO_OFF) {
spin_lock_irqsave(&clocks_lock, flags);
if (!clk->count) {
diff --git a/arch/arm/mach-msm/clock.h b/arch/arm/mach-msm/clock.h
index 6a0cade..70216b0 100644
--- a/arch/arm/mach-msm/clock.h
+++ b/arch/arm/mach-msm/clock.h
@@ -17,6 +17,7 @@
#ifndef __ARCH_ARM_MACH_MSM_CLOCK_H
#define __ARCH_ARM_MACH_MSM_CLOCK_H
+#include <linux/init.h>
#include <linux/list.h>
#include <mach/clk.h>
@@ -61,4 +62,12 @@ struct clk {
#define CLK_MAX CLKFLAG_MAX
#define CLK_MINMAX (CLK_MIN | CLK_MAX)
+#ifdef CONFIG_DEBUG_FS
+int __init clock_debug_init(void);
+int __init clock_debug_add(struct clk *clock);
+#else
+static inline int __init clock_debug_init(void) { return 0; }
+static inline int __init clock_debug_add(struct clk *clock) { return 0; }
+#endif
+
#endif
--
Sent by an employee of the Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum.
^ permalink raw reply related [flat|nested] 23+ messages in thread* [PATCH 03/22] msm: clock: Invert debugfs directory layout
2010-12-17 0:49 [PATCH 00/22] MSM clock driver updates Stephen Boyd
2010-12-17 0:49 ` [PATCH 01/22] msm: clock: Remove unused code and definitions Stephen Boyd
2010-12-17 0:49 ` [PATCH 02/22] msm: clock: Move debugfs code from clock.c to clock-debug.c Stephen Boyd
@ 2010-12-17 0:49 ` Stephen Boyd
2010-12-17 0:49 ` [PATCH 04/22] msm: clock: Add support for more proc_comm clocks Stephen Boyd
` (18 subsequent siblings)
21 siblings, 0 replies; 23+ messages in thread
From: Stephen Boyd @ 2010-12-17 0:49 UTC (permalink / raw)
To: linux-arm-kernel
There are currently 3 separate directories for clock debugging in
debugfs: clk_enable, clk_rate, and clk_local. Each of these
directories contains a list of clocks. This is rather annoying
when you are focusing on one clock and want to enable/disable it
and then check its rate. You either have to cd to the other
directory or cat ../clk_rate/<clk>.
Invert the layout so that there is one clock directory containing
a directory for each clock. Inside each respective clock
directory place an enable, rate, and is_local file relating to
the clk_enable, clk_disable, and clk_local directories that exist
today.
Reviewed-by: Saravana Kannan <skannan@codeaurora.org>
Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
---
arch/arm/mach-msm/clock-debug.c | 48 ++++++++++++++++++--------------------
1 files changed, 23 insertions(+), 25 deletions(-)
diff --git a/arch/arm/mach-msm/clock-debug.c b/arch/arm/mach-msm/clock-debug.c
index 6f603ed..b67b9e82 100644
--- a/arch/arm/mach-msm/clock-debug.c
+++ b/arch/arm/mach-msm/clock-debug.c
@@ -87,47 +87,45 @@ static int clock_debug_local_get(void *data, u64 *val)
DEFINE_SIMPLE_ATTRIBUTE(clock_local_fops, clock_debug_local_get,
NULL, "%llu\n");
-static struct dentry *dent_rate, *dent_enable, *dent_local;
+static struct dentry *debugfs_base;
int __init clock_debug_init(void)
{
- dent_rate = debugfs_create_dir("clk_rate", 0);
- if (!dent_rate)
- goto err;
-
- dent_enable = debugfs_create_dir("clk_enable", 0);
- if (!dent_enable)
- goto err;
-
- dent_local = debugfs_create_dir("clk_local", NULL);
- if (!dent_local)
- goto err;
-
+ debugfs_base = debugfs_create_dir("clk", NULL);
+ if (!debugfs_base)
+ return -ENOMEM;
return 0;
-err:
- debugfs_remove(dent_local);
- debugfs_remove(dent_enable);
- debugfs_remove(dent_rate);
- return -ENOMEM;
}
int __init clock_debug_add(struct clk *clock)
{
char temp[50], *ptr;
+ struct dentry *clk_dir;
- if (!dent_rate || !dent_enable || !dent_local)
+ if (!debugfs_base)
return -ENOMEM;
strncpy(temp, clock->dbg_name, ARRAY_SIZE(temp)-1);
for (ptr = temp; *ptr; ptr++)
*ptr = tolower(*ptr);
- debugfs_create_file(temp, S_IRUGO | S_IWUSR, dent_rate,
- clock, &clock_rate_fops);
- debugfs_create_file(temp, S_IRUGO | S_IWUSR, dent_enable,
- clock, &clock_enable_fops);
- debugfs_create_file(temp, S_IRUGO, dent_local,
- clock, &clock_local_fops);
+ clk_dir = debugfs_create_dir(temp, debugfs_base);
+ if (!clk_dir)
+ return -ENOMEM;
+
+ if (!debugfs_create_file("rate", S_IRUGO | S_IWUSR, clk_dir,
+ clock, &clock_rate_fops))
+ goto error;
+ if (!debugfs_create_file("enable", S_IRUGO | S_IWUSR, clk_dir,
+ clock, &clock_enable_fops))
+ goto error;
+
+ if (!debugfs_create_file("is_local", S_IRUGO, clk_dir, clock,
+ &clock_local_fops))
+ goto error;
return 0;
+error:
+ debugfs_remove_recursive(clk_dir);
+ return -ENOMEM;
}
--
Sent by an employee of the Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum.
^ permalink raw reply related [flat|nested] 23+ messages in thread* [PATCH 04/22] msm: clock: Add support for more proc_comm clocks
2010-12-17 0:49 [PATCH 00/22] MSM clock driver updates Stephen Boyd
` (2 preceding siblings ...)
2010-12-17 0:49 ` [PATCH 03/22] msm: clock: Invert debugfs directory layout Stephen Boyd
@ 2010-12-17 0:49 ` Stephen Boyd
2010-12-17 0:49 ` [PATCH 05/22] msm: clock-7x30: Add 7x30 local clock driver Stephen Boyd
` (17 subsequent siblings)
21 siblings, 0 replies; 23+ messages in thread
From: Stephen Boyd @ 2010-12-17 0:49 UTC (permalink / raw)
To: linux-arm-kernel
Support the CE_CLK and CODEC_SSBI_CLK. Also add support for sdc,
uart, and i2c clocks on targets which support proc_comm clocks.
Reviewed-by: Saravana Kannan <skannan@codeaurora.org>
Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
---
arch/arm/mach-msm/clock-pcom.h | 4 +++-
arch/arm/mach-msm/devices-msm7x30.c | 2 ++
arch/arm/mach-msm/devices-qsd8x50.c | 14 ++++++++++++++
3 files changed, 19 insertions(+), 1 deletions(-)
diff --git a/arch/arm/mach-msm/clock-pcom.h b/arch/arm/mach-msm/clock-pcom.h
index 17d027b..2c813f1 100644
--- a/arch/arm/mach-msm/clock-pcom.h
+++ b/arch/arm/mach-msm/clock-pcom.h
@@ -132,8 +132,10 @@
#define P_CSI1_P_CLK 97
#define P_GSBI_CLK 98
#define P_GSBI_P_CLK 99
+#define P_CE_CLK 100 /* Crypto engine */
+#define P_CODEC_SSBI_CLK 101
-#define P_NR_CLKS 100
+#define P_NR_CLKS 102
struct clk_ops;
extern struct clk_ops clk_ops_pcom;
diff --git a/arch/arm/mach-msm/devices-msm7x30.c b/arch/arm/mach-msm/devices-msm7x30.c
index 2a9958f..2816be3 100644
--- a/arch/arm/mach-msm/devices-msm7x30.c
+++ b/arch/arm/mach-msm/devices-msm7x30.c
@@ -62,6 +62,8 @@ struct clk msm_clocks_7x30[] = {
CLK_PCOM("adsp_clk", ADSP_CLK, NULL, 0),
CLK_PCOM("cam_m_clk", CAM_M_CLK, NULL, 0),
CLK_PCOM("camif_pad_pclk", CAMIF_PAD_P_CLK, NULL, OFF),
+ CLK_PCOM("ce_clk", CE_CLK, NULL, 0),
+ CLK_PCOM("codec_ssbi_clk", CODEC_SSBI_CLK, NULL, 0),
CLK_PCOM("ebi1_clk", EBI1_CLK, NULL, CLK_MIN),
CLK_PCOM("ecodec_clk", ECODEC_CLK, NULL, 0),
CLK_PCOM("emdh_clk", EMDH_CLK, NULL, OFF | CLK_MINMAX),
diff --git a/arch/arm/mach-msm/devices-qsd8x50.c b/arch/arm/mach-msm/devices-qsd8x50.c
index f92c5c2..271c8bb 100644
--- a/arch/arm/mach-msm/devices-qsd8x50.c
+++ b/arch/arm/mach-msm/devices-qsd8x50.c
@@ -56,12 +56,14 @@ struct platform_device msm_device_smd = {
struct clk msm_clocks_8x50[] = {
CLK_PCOM("adm_clk", ADM_CLK, NULL, 0),
+ CLK_PCOM("ce_clk", CE_CLK, NULL, 0),
CLK_PCOM("ebi1_clk", EBI1_CLK, NULL, CLK_MIN),
CLK_PCOM("ebi2_clk", EBI2_CLK, NULL, 0),
CLK_PCOM("ecodec_clk", ECODEC_CLK, NULL, 0),
CLK_PCOM("emdh_clk", EMDH_CLK, NULL, OFF | CLK_MINMAX),
CLK_PCOM("gp_clk", GP_CLK, NULL, 0),
CLK_PCOM("grp_clk", GRP_3D_CLK, NULL, 0),
+ CLK_PCOM("i2c_clk", I2C_CLK, NULL, 0),
CLK_PCOM("icodec_rx_clk", ICODEC_RX_CLK, NULL, 0),
CLK_PCOM("icodec_tx_clk", ICODEC_TX_CLK, NULL, 0),
CLK_PCOM("imem_clk", IMEM_CLK, NULL, OFF),
@@ -74,12 +76,24 @@ struct clk msm_clocks_8x50[] = {
CLK_PCOM("pbus_clk", PBUS_CLK, NULL, CLK_MIN),
CLK_PCOM("pcm_clk", PCM_CLK, NULL, 0),
CLK_PCOM("sdac_clk", SDAC_CLK, NULL, OFF),
+ CLK_PCOM("sdc_clk", SDC1_CLK, NULL, OFF),
+ CLK_PCOM("sdc_pclk", SDC1_P_CLK, NULL, OFF),
+ CLK_PCOM("sdc_clk", SDC2_CLK, NULL, OFF),
+ CLK_PCOM("sdc_pclk", SDC2_P_CLK, NULL, OFF),
+ CLK_PCOM("sdc_clk", SDC3_CLK, NULL, OFF),
+ CLK_PCOM("sdc_pclk", SDC3_P_CLK, NULL, OFF),
+ CLK_PCOM("sdc_clk", SDC4_CLK, NULL, OFF),
+ CLK_PCOM("sdc_pclk", SDC4_P_CLK, NULL, OFF),
CLK_PCOM("spi_clk", SPI_CLK, NULL, 0),
CLK_PCOM("tsif_clk", TSIF_CLK, NULL, 0),
CLK_PCOM("tsif_ref_clk", TSIF_REF_CLK, NULL, 0),
CLK_PCOM("tv_dac_clk", TV_DAC_CLK, NULL, 0),
CLK_PCOM("tv_enc_clk", TV_ENC_CLK, NULL, 0),
+ CLK_PCOM("uart_clk", UART1_CLK, NULL, OFF),
+ CLK_PCOM("uart_clk", UART2_CLK, NULL, 0),
CLK_PCOM("uart_clk", UART3_CLK, &msm_device_uart3.dev, OFF),
+ CLK_PCOM("uartdm_clk", UART1DM_CLK, NULL, OFF),
+ CLK_PCOM("uartdm_clk", UART2DM_CLK, NULL, 0),
CLK_PCOM("usb_hs_clk", USB_HS_CLK, NULL, OFF),
CLK_PCOM("usb_hs_pclk", USB_HS_P_CLK, NULL, OFF),
CLK_PCOM("usb_otg_clk", USB_OTG_CLK, NULL, 0),
--
Sent by an employee of the Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum.
^ permalink raw reply related [flat|nested] 23+ messages in thread* [PATCH 05/22] msm: clock-7x30: Add 7x30 local clock driver
2010-12-17 0:49 [PATCH 00/22] MSM clock driver updates Stephen Boyd
` (3 preceding siblings ...)
2010-12-17 0:49 ` [PATCH 04/22] msm: clock: Add support for more proc_comm clocks Stephen Boyd
@ 2010-12-17 0:49 ` Stephen Boyd
2010-12-17 0:49 ` [PATCH 06/22] msm: clock-7x30: Update clock table Stephen Boyd
` (16 subsequent siblings)
21 siblings, 0 replies; 23+ messages in thread
From: Stephen Boyd @ 2010-12-17 0:49 UTC (permalink / raw)
To: linux-arm-kernel
From: Saravana Kannan <skannan@codeaurora.org>
Support locally controllable clocks on the 7x30 target.
Signed-off-by: Saravana Kannan <skannan@codeaurora.org>
Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
---
arch/arm/mach-msm/Makefile | 1 +
arch/arm/mach-msm/clock-7x30.c | 1550 ++++++++++++++++++++++++++++++++++++++++
arch/arm/mach-msm/clock-7x30.h | 38 +-
arch/arm/mach-msm/clock.c | 13 +-
arch/arm/mach-msm/clock.h | 12 +
arch/arm/mach-msm/proc_comm.h | 1 +
6 files changed, 1599 insertions(+), 16 deletions(-)
create mode 100644 arch/arm/mach-msm/clock-7x30.c
diff --git a/arch/arm/mach-msm/Makefile b/arch/arm/mach-msm/Makefile
index dc8ef08..8588b57 100644
--- a/arch/arm/mach-msm/Makefile
+++ b/arch/arm/mach-msm/Makefile
@@ -2,6 +2,7 @@ obj-y += io.o idle.o timer.o
ifdef CONFIG_MSM_PROC_COMM
obj-$(CONFIG_DEBUG_FS) += clock-debug.o
endif
+obj-$(CONFIG_ARCH_MSM7X30) += clock-7x30.o
ifndef CONFIG_ARCH_MSM8X60
obj-y += acpuclock-arm11.o
obj-y += dma.o
diff --git a/arch/arm/mach-msm/clock-7x30.c b/arch/arm/mach-msm/clock-7x30.c
new file mode 100644
index 0000000..beca3a6
--- /dev/null
+++ b/arch/arm/mach-msm/clock-7x30.c
@@ -0,0 +1,1550 @@
+/* Copyright (c) 2009-2010, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/err.h>
+#include <linux/ctype.h>
+#include <linux/bitops.h>
+#include <linux/io.h>
+#include <linux/spinlock.h>
+#include <linux/delay.h>
+
+#include <mach/msm_iomap.h>
+#include <mach/clk.h>
+
+#include "clock.h"
+#include "clock-7x30.h"
+#include "clock-pcom.h"
+#include "proc_comm.h"
+
+#define REG_BASE(off) (MSM_CLK_CTL_BASE + off)
+#define REG(off) (MSM_CLK_CTL_SH2_BASE + off)
+#define MNCNTR_EN_MASK B(8)
+#define MNCNTR_RST_MASK B(7)
+#define MNCNTR_MODE_MASK BM(6, 5)
+#define MNCNTR_MODE BVAL(6, 5, 0x2) /* Dual-edge mode. */
+
+/* Shadow-region 2 (SH2) registers. */
+#define QUP_I2C_NS_REG REG(0x04F0)
+#define CAM_NS_REG REG(0x0374)
+#define CAM_VFE_NS_REG REG(0x0044)
+#define CLK_HALT_STATEA_REG REG(0x0108)
+#define CLK_HALT_STATEB_REG REG(0x010C)
+#define CLK_HALT_STATEC_REG REG(0x02D4)
+#define CSI_NS_REG REG(0x0174)
+#define EMDH_NS_REG REG(0x0050)
+#define GLBL_CLK_ENA_2_SC_REG REG(0x03C0)
+#define GLBL_CLK_ENA_SC_REG REG(0x03BC)
+#define GLBL_CLK_STATE_2_REG REG(0x037C)
+#define GLBL_CLK_STATE_REG REG(0x0004)
+#define GRP_2D_NS_REG REG(0x0034)
+#define GRP_NS_REG REG(0x0084)
+#define HDMI_NS_REG REG(0x0484)
+#define I2C_2_NS_REG REG(0x02D8)
+#define I2C_NS_REG REG(0x0068)
+#define JPEG_NS_REG REG(0x0164)
+#define LPA_CORE_CLK_MA0_REG REG(0x04F4)
+#define LPA_CORE_CLK_MA2_REG REG(0x04FC)
+#define LPA_NS_REG REG(0x02E8)
+#define MDC_NS_REG REG(0x007C)
+#define MDP_LCDC_NS_REG REG(0x0390)
+#define MDP_NS_REG REG(0x014C)
+#define MDP_VSYNC_REG REG(0x0460)
+#define MFC_NS_REG REG(0x0154)
+#define MI2S_CODEC_RX_DIV_REG REG(0x02EC)
+#define MI2S_CODEC_TX_DIV_REG REG(0x02F0)
+#define MI2S_DIV_REG REG(0x02E4)
+#define MI2S_NS_REG REG(0x02E0)
+#define MI2S_RX_NS_REG REG(0x0070)
+#define MI2S_TX_NS_REG REG(0x0078)
+#define MIDI_NS_REG REG(0x02D0)
+#define PLL_ENA_REG REG(0x0264)
+#define PMDH_NS_REG REG(0x008C)
+#define SDAC_NS_REG REG(0x009C)
+#define SDCn_NS_REG(n) REG(0x00A4+(0x8*((n)-1)))
+#define SPI_NS_REG REG(0x02C8)
+#define TSIF_NS_REG REG(0x00C4)
+#define TV_NS_REG REG(0x00CC)
+#define UART1DM_NS_REG REG(0x00D4)
+#define UART2DM_NS_REG REG(0x00DC)
+#define UART2_NS_REG REG(0x0464)
+#define UART_NS_REG REG(0x00E0)
+#define USBH2_NS_REG REG(0x046C)
+#define USBH3_NS_REG REG(0x0470)
+#define USBH_MD_REG REG(0x02BC)
+#define USBH_NS_REG REG(0x02C0)
+#define VPE_NS_REG REG(0x015C)
+
+/* Registers in the base (non-shadow) region. */
+#define PLL0_STATUS_BASE_REG REG_BASE(0x0318)
+#define PLL1_STATUS_BASE_REG REG_BASE(0x0334)
+#define PLL2_STATUS_BASE_REG REG_BASE(0x0350)
+#define PLL3_STATUS_BASE_REG REG_BASE(0x036C)
+#define PLL4_STATUS_BASE_REG REG_BASE(0x0254)
+#define PLL5_STATUS_BASE_REG REG_BASE(0x0258)
+#define PLL6_STATUS_BASE_REG REG_BASE(0x04EC)
+#define SH2_OWN_APPS1_BASE_REG REG_BASE(0x040C)
+#define SH2_OWN_APPS2_BASE_REG REG_BASE(0x0414)
+#define SH2_OWN_APPS3_BASE_REG REG_BASE(0x0444)
+#define SH2_OWN_GLBL_BASE_REG REG_BASE(0x0404)
+#define SH2_OWN_ROW1_BASE_REG REG_BASE(0x041C)
+#define SH2_OWN_ROW2_BASE_REG REG_BASE(0x0424)
+
+struct clk_freq_tbl {
+ uint32_t freq_hz;
+ uint32_t src;
+ uint32_t md_val;
+ uint32_t ns_val;
+ uint32_t mode;
+ unsigned msmc1;
+};
+
+struct clk_local {
+ uint32_t count;
+ uint32_t type;
+ void __iomem *md_reg;
+ void __iomem *ns_reg;
+ uint32_t freq_mask;
+ uint32_t br_en_mask;
+ uint32_t root_en_mask;
+ int parent;
+ uint32_t *children;
+ const struct clk_freq_tbl *freq_tbl;
+ const struct clk_freq_tbl *current_freq;
+ void __iomem *halt_reg;
+ uint32_t halt_mask;
+ uint32_t test_vector;
+};
+
+
+enum {
+ SRC_PLL0 = 4, /* Modem PLL */
+ SRC_PLL1 = 1, /* Global PLL */
+ SRC_PLL3 = 3, /* Multimedia/Peripheral PLL or Backup PLL1 */
+ SRC_PLL4 = 2, /* Display PLL */
+ SRC_LPXO = 6, /* Low power XO. */
+ SRC_TCXO = 0, /* Used for sources that always source from tcxo */
+ SRC_AXI = 100, /* Used for rates that sync to AXI */
+ SRC_NONE /* Used for sources that can't be turned on/off. */
+};
+
+static uint32_t src_pll_tbl[] = {
+ [SRC_PLL0] = PLL_0,
+ [SRC_PLL1] = PLL_1,
+ [SRC_PLL3] = PLL_3,
+ [SRC_PLL4] = PLL_4,
+};
+
+#define B(x) BIT(x)
+#define BM(msb, lsb) (((((uint32_t)-1) << (31-msb)) >> (31-msb+lsb)) << lsb)
+#define BVAL(msb, lsb, val) (((val) << lsb) & BM(msb, lsb))
+
+#define MD8(m, n) (BVAL(15, 8, m) | BVAL(7, 0, ~(n)))
+#define N8(msb, lsb, m, n) (BVAL(msb, lsb, ~(n-m)))
+#define MD16(m, n) (BVAL(31, 16, m) | BVAL(15, 0, ~(n)))
+#define N16(m, n) (BVAL(31, 16, ~(n-m)))
+#define SPDIV(s, d) (BVAL(4, 3, d-1) | BVAL(2, 0, s))
+#define SDIV(s, d) (BVAL(6, 3, d-1) | BVAL(2, 0, s))
+#define F_MASK_BASIC (BM(6, 3)|BM(2, 0))
+#define F_MASK_MND16 (BM(31, 16)|BM(4, 3)|BM(2, 0))
+#define F_MASK_MND8(m, l) (BM(m, l)|BM(4, 3)|BM(2, 0))
+
+#define F_RAW(f, s, m_v, n_v, mde, v) { \
+ .freq_hz = f, \
+ .src = s, \
+ .md_val = m_v, \
+ .ns_val = n_v, \
+ .mode = mde, \
+ .msmc1 = v \
+ }
+
+#define FREQ_END 0
+#define F_BASIC(f, s, div, v) F_RAW(f, s, 0, SDIV(s, div), 0, v)
+#define F_MND16(f, s, div, m, n, v) \
+ F_RAW(f, s, MD16(m, n), N16(m, n)|SPDIV(s, div), !!(n), v)
+#define F_MND8(f, nmsb, nlsb, s, div, m, n, v) \
+ F_RAW(f, s, MD8(m, n), N8(nmsb, nlsb, m, n)|SPDIV(s, div), !!(n), v)
+#define F_END F_RAW(FREQ_END, SRC_NONE, 0, 0, 0, MSMC1_END)
+
+static const struct clk_freq_tbl clk_tbl_csi[] = {
+ F_MND8(153600000, 24, 17, SRC_PLL1, 2, 2, 5, NOMINAL),
+ F_MND8(192000000, 24, 17, SRC_PLL1, 4, 0, 0, NOMINAL),
+ F_MND8(384000000, 24, 17, SRC_PLL1, 2, 0, 0, NOMINAL),
+ F_END,
+};
+
+static const struct clk_freq_tbl clk_tbl_tcxo[] = {
+ F_RAW(19200000, SRC_TCXO, 0, 0, 0, NOMINAL),
+ F_END,
+};
+
+static const struct clk_freq_tbl clk_tbl_axi[] = {
+ F_RAW(1, SRC_AXI, 0, 0, 0, NOMINAL),
+ F_END,
+};
+
+static const struct clk_freq_tbl clk_tbl_uartdm[] = {
+ F_MND16( 3686400, SRC_PLL3, 3, 3, 200, NOMINAL),
+ F_MND16( 7372800, SRC_PLL3, 3, 3, 100, NOMINAL),
+ F_MND16(14745600, SRC_PLL3, 3, 3, 50, NOMINAL),
+ F_MND16(32000000, SRC_PLL3, 3, 25, 192, NOMINAL),
+ F_MND16(40000000, SRC_PLL3, 3, 125, 768, NOMINAL),
+ F_MND16(46400000, SRC_PLL3, 3, 145, 768, NOMINAL),
+ F_MND16(48000000, SRC_PLL3, 3, 25, 128, NOMINAL),
+ F_MND16(51200000, SRC_PLL3, 3, 5, 24, NOMINAL),
+ F_MND16(56000000, SRC_PLL3, 3, 175, 768, NOMINAL),
+ F_MND16(58982400, SRC_PLL3, 3, 6, 25, NOMINAL),
+ F_MND16(64000000, SRC_PLL1, 4, 1, 3, NOMINAL),
+ F_END,
+};
+
+static const struct clk_freq_tbl clk_tbl_mdh[] = {
+ F_BASIC( 49150000, SRC_PLL3, 15, NOMINAL),
+ F_BASIC( 92160000, SRC_PLL3, 8, NOMINAL),
+ F_BASIC(122880000, SRC_PLL3, 6, NOMINAL),
+ F_BASIC(184320000, SRC_PLL3, 4, NOMINAL),
+ F_BASIC(245760000, SRC_PLL3, 3, NOMINAL),
+ F_BASIC(368640000, SRC_PLL3, 2, NOMINAL),
+ F_BASIC(384000000, SRC_PLL1, 2, NOMINAL),
+ F_BASIC(445500000, SRC_PLL4, 2, NOMINAL),
+ F_END,
+};
+
+static const struct clk_freq_tbl clk_tbl_grp[] = {
+ F_BASIC( 24576000, SRC_LPXO, 1, NOMINAL),
+ F_BASIC( 46080000, SRC_PLL3, 16, NOMINAL),
+ F_BASIC( 49152000, SRC_PLL3, 15, NOMINAL),
+ F_BASIC( 52662875, SRC_PLL3, 14, NOMINAL),
+ F_BASIC( 56713846, SRC_PLL3, 13, NOMINAL),
+ F_BASIC( 61440000, SRC_PLL3, 12, NOMINAL),
+ F_BASIC( 67025454, SRC_PLL3, 11, NOMINAL),
+ F_BASIC( 73728000, SRC_PLL3, 10, NOMINAL),
+ F_BASIC( 81920000, SRC_PLL3, 9, NOMINAL),
+ F_BASIC( 92160000, SRC_PLL3, 8, NOMINAL),
+ F_BASIC(105325714, SRC_PLL3, 7, NOMINAL),
+ F_BASIC(122880000, SRC_PLL3, 6, NOMINAL),
+ F_BASIC(147456000, SRC_PLL3, 5, NOMINAL),
+ F_BASIC(184320000, SRC_PLL3, 4, NOMINAL),
+ F_BASIC(192000000, SRC_PLL1, 4, NOMINAL),
+ F_BASIC(245760000, SRC_PLL3, 3, HIGH),
+ /* Sync to AXI. Hence this "rate" is not fixed. */
+ F_RAW(1, SRC_AXI, 0, B(14), 0, NOMINAL),
+ F_END,
+};
+
+static const struct clk_freq_tbl clk_tbl_sdc1_3[] = {
+ F_MND8( 144000, 19, 12, SRC_LPXO, 1, 1, 171, NOMINAL),
+ F_MND8( 400000, 19, 12, SRC_LPXO, 1, 2, 123, NOMINAL),
+ F_MND8(16027000, 19, 12, SRC_PLL3, 3, 14, 215, NOMINAL),
+ F_MND8(17000000, 19, 12, SRC_PLL3, 4, 19, 206, NOMINAL),
+ F_MND8(20480000, 19, 12, SRC_PLL3, 4, 23, 212, NOMINAL),
+ F_MND8(24576000, 19, 12, SRC_LPXO, 1, 0, 0, NOMINAL),
+ F_MND8(49152000, 19, 12, SRC_PLL3, 3, 1, 5, NOMINAL),
+ F_END,
+};
+
+static const struct clk_freq_tbl clk_tbl_sdc2_4[] = {
+ F_MND8( 144000, 20, 13, SRC_LPXO, 1, 1, 171, NOMINAL),
+ F_MND8( 400000, 20, 13, SRC_LPXO, 1, 2, 123, NOMINAL),
+ F_MND8(16027000, 20, 13, SRC_PLL3, 3, 14, 215, NOMINAL),
+ F_MND8(17000000, 20, 13, SRC_PLL3, 4, 19, 206, NOMINAL),
+ F_MND8(20480000, 20, 13, SRC_PLL3, 4, 23, 212, NOMINAL),
+ F_MND8(24576000, 20, 13, SRC_LPXO, 1, 0, 0, NOMINAL),
+ F_MND8(49152000, 20, 13, SRC_PLL3, 3, 1, 5, NOMINAL),
+ F_END,
+};
+
+static const struct clk_freq_tbl clk_tbl_mdp_core[] = {
+ F_BASIC( 46080000, SRC_PLL3, 16, NOMINAL),
+ F_BASIC( 49152000, SRC_PLL3, 15, NOMINAL),
+ F_BASIC( 52663000, SRC_PLL3, 14, NOMINAL),
+ F_BASIC( 92160000, SRC_PLL3, 8, NOMINAL),
+ F_BASIC(122880000, SRC_PLL3, 6, NOMINAL),
+ F_BASIC(147456000, SRC_PLL3, 5, NOMINAL),
+ F_BASIC(153600000, SRC_PLL1, 5, NOMINAL),
+ F_BASIC(192000000, SRC_PLL1, 4, HIGH),
+ F_END,
+};
+
+static const struct clk_freq_tbl clk_tbl_mdp_lcdc[] = {
+ F_MND16(24576000, SRC_LPXO, 1, 0, 0, NOMINAL),
+ F_MND16(30720000, SRC_PLL3, 4, 1, 6, NOMINAL),
+ F_MND16(32768000, SRC_PLL3, 3, 2, 15, NOMINAL),
+ F_MND16(40960000, SRC_PLL3, 2, 1, 9, NOMINAL),
+ F_MND16(73728000, SRC_PLL3, 2, 1, 5, NOMINAL),
+ F_END,
+};
+
+static const struct clk_freq_tbl clk_tbl_mdp_vsync[] = {
+ F_RAW(24576000, SRC_LPXO, 0, 0, 0, NOMINAL),
+ F_END,
+};
+
+static const struct clk_freq_tbl clk_tbl_mi2s_codec[] = {
+ F_MND16( 2048000, SRC_LPXO, 4, 1, 3, NOMINAL),
+ F_MND16(12288000, SRC_LPXO, 2, 0, 0, NOMINAL),
+ F_END,
+};
+
+static const struct clk_freq_tbl clk_tbl_mi2s[] = {
+ F_MND16(12288000, SRC_LPXO, 2, 0, 0, NOMINAL),
+ F_END,
+};
+
+static const struct clk_freq_tbl clk_tbl_midi[] = {
+ F_MND8(98304000, 19, 12, SRC_PLL3, 3, 2, 5, NOMINAL),
+ F_END,
+};
+
+static const struct clk_freq_tbl clk_tbl_sdac[] = {
+ F_MND16( 256000, SRC_LPXO, 4, 1, 24, NOMINAL),
+ F_MND16( 352800, SRC_LPXO, 1, 147, 10240, NOMINAL),
+ F_MND16( 384000, SRC_LPXO, 4, 1, 16, NOMINAL),
+ F_MND16( 512000, SRC_LPXO, 4, 1, 12, NOMINAL),
+ F_MND16( 705600, SRC_LPXO, 1, 147, 5120, NOMINAL),
+ F_MND16( 768000, SRC_LPXO, 4, 1, 8, NOMINAL),
+ F_MND16(1024000, SRC_LPXO, 4, 1, 6, NOMINAL),
+ F_MND16(1411200, SRC_LPXO, 1, 147, 2560, NOMINAL),
+ F_MND16(1536000, SRC_LPXO, 4, 1, 4, NOMINAL),
+ F_END,
+};
+
+static const struct clk_freq_tbl clk_tbl_tv[] = {
+ F_MND8(27000000, 23, 16, SRC_PLL4, 2, 2, 33, NOMINAL),
+ F_MND8(74250000, 23, 16, SRC_PLL4, 2, 1, 6, NOMINAL),
+ F_END,
+};
+
+static const struct clk_freq_tbl clk_tbl_usb[] = {
+ F_MND8(60000000, 23, 16, SRC_PLL1, 2, 5, 32, NOMINAL),
+ F_END,
+};
+
+static const struct clk_freq_tbl clk_tbl_vfe_jpeg[] = {
+ F_MND16( 36864000, SRC_PLL3, 4, 1, 5, NOMINAL),
+ F_MND16( 46080000, SRC_PLL3, 4, 1, 4, NOMINAL),
+ F_MND16( 61440000, SRC_PLL3, 4, 1, 3, NOMINAL),
+ F_MND16( 73728000, SRC_PLL3, 2, 1, 5, NOMINAL),
+ F_MND16( 81920000, SRC_PLL3, 3, 1, 3, NOMINAL),
+ F_MND16( 92160000, SRC_PLL3, 4, 1, 2, NOMINAL),
+ F_MND16( 98304000, SRC_PLL3, 3, 2, 5, NOMINAL),
+ F_MND16(105326000, SRC_PLL3, 2, 2, 7, NOMINAL),
+ F_MND16(122880000, SRC_PLL3, 2, 1, 3, NOMINAL),
+ F_MND16(147456000, SRC_PLL3, 2, 2, 5, NOMINAL),
+ F_MND16(153600000, SRC_PLL1, 2, 2, 5, NOMINAL),
+ F_END,
+};
+
+static const struct clk_freq_tbl clk_tbl_cam[] = {
+ F_MND16( 6000000, SRC_PLL1, 4, 1, 32, NOMINAL),
+ F_MND16( 8000000, SRC_PLL1, 4, 1, 24, NOMINAL),
+ F_MND16(12000000, SRC_PLL1, 4, 1, 16, NOMINAL),
+ F_MND16(16000000, SRC_PLL1, 4, 1, 12, NOMINAL),
+ F_MND16(19200000, SRC_PLL1, 4, 1, 10, NOMINAL),
+ F_MND16(24000000, SRC_PLL1, 4, 1, 8, NOMINAL),
+ F_MND16(32000000, SRC_PLL1, 4, 1, 6, NOMINAL),
+ F_MND16(48000000, SRC_PLL1, 4, 1, 4, NOMINAL),
+ F_MND16(64000000, SRC_PLL1, 4, 1, 3, NOMINAL),
+ F_END,
+};
+
+static const struct clk_freq_tbl clk_tbl_vpe[] = {
+ F_MND8( 24576000, 22, 15, SRC_LPXO, 1, 0, 0, NOMINAL),
+ F_MND8( 30720000, 22, 15, SRC_PLL3, 4, 1, 6, NOMINAL),
+ F_MND8( 61440000, 22, 15, SRC_PLL3, 4, 1, 3, NOMINAL),
+ F_MND8( 81920000, 22, 15, SRC_PLL3, 3, 1, 3, NOMINAL),
+ F_MND8(122880000, 22, 15, SRC_PLL3, 3, 1, 2, NOMINAL),
+ F_MND8(147456000, 22, 15, SRC_PLL3, 1, 1, 5, NOMINAL),
+ F_MND8(153600000, 22, 15, SRC_PLL1, 1, 1, 5, NOMINAL),
+ F_END,
+};
+
+static const struct clk_freq_tbl clk_tbl_mfc[] = {
+ F_MND8( 24576000, 24, 17, SRC_LPXO, 1, 0, 0, NOMINAL),
+ F_MND8( 30720000, 24, 17, SRC_PLL3, 4, 1, 6, NOMINAL),
+ F_MND8( 61440000, 24, 17, SRC_PLL3, 4, 1, 3, NOMINAL),
+ F_MND8( 81920000, 24, 17, SRC_PLL3, 3, 1, 3, NOMINAL),
+ F_MND8(122880000, 24, 17, SRC_PLL3, 3, 1, 2, NOMINAL),
+ F_MND8(147456000, 24, 17, SRC_PLL3, 1, 1, 5, NOMINAL),
+ F_MND8(153600000, 24, 17, SRC_PLL1, 1, 1, 5, NOMINAL),
+ F_MND8(170667000, 24, 17, SRC_PLL1, 1, 2, 9, NOMINAL),
+ F_END,
+};
+
+static const struct clk_freq_tbl clk_tbl_spi[] = {
+ F_MND8( 9963243, 19, 12, SRC_PLL3, 4, 7, 129, NOMINAL),
+ F_MND8(26331429, 19, 12, SRC_PLL3, 4, 34, 241, NOMINAL),
+ F_END,
+};
+
+static const struct clk_freq_tbl clk_tbl_lpa_codec[] = {
+ F_RAW(1, SRC_NONE, 0, 0, 0, MSMC1_END), /* src = MI2S_CODEC_RX */
+ F_RAW(2, SRC_NONE, 0, 1, 0, MSMC1_END), /* src = ECODEC_CIF */
+ F_RAW(3, SRC_NONE, 0, 2, 0, MSMC1_END), /* src = MI2S */
+ F_RAW(4, SRC_NONE, 0, 3, 0, MSMC1_END), /* src = SDAC */
+ F_END,
+};
+
+static struct clk_freq_tbl dummy_freq = F_END;
+
+#define MND 1 /* Integer predivider and fractional MN:D divider. */
+#define BASIC 2 /* Integer divider. */
+#define NORATE 3 /* Just on/off. */
+
+#define C(x) L_7X30_##x##_CLK
+
+#define CLK_LOCAL(id, t, md, ns, f_msk, br, root, tbl, \
+ par, chld_lst, h, hm, tv) \
+ [C(id)] = { \
+ .type = t, \
+ .md_reg = md, \
+ .ns_reg = ns, \
+ .freq_mask = f_msk, \
+ .br_en_mask = br, \
+ .root_en_mask = root, \
+ .parent = C(par), \
+ .children = chld_lst, \
+ .freq_tbl = tbl, \
+ .current_freq = &dummy_freq, \
+ .halt_reg = h, \
+ .halt_mask = hm, \
+ .test_vector = tv, \
+ }
+
+#define CLK_BASIC(id, ns, br, root, tbl, par, h, hm, tv) \
+ CLK_LOCAL(id, BASIC, 0, ns, F_MASK_BASIC, br, root, tbl, \
+ par, NULL, h, hm, tv)
+#define CLK_MND8_P(id, ns, m, l, br, root, tbl, par, chld_lst, h, hm, tv) \
+ CLK_LOCAL(id, MND, (ns-4), ns, F_MASK_MND8(m, l), br, root, \
+ tbl, par, chld_lst, h, hm, tv)
+#define CLK_MND8(id, ns, m, l, br, root, tbl, chld_lst, h, hm, tv) \
+ CLK_MND8_P(id, ns, m, l, br, root, tbl, NONE, chld_lst, \
+ h, hm, tv)
+#define CLK_MND16(id, ns, br, root, tbl, par, chld_lst, h, hm, tv) \
+ CLK_LOCAL(id, MND, (ns-4), ns, F_MASK_MND16, br, root, tbl, \
+ par, chld_lst, h, hm, tv)
+#define CLK_1RATE(id, ns, br, root, tbl, h, hm, tv) \
+ CLK_LOCAL(id, BASIC, 0, ns, 0, br, root, tbl, NONE, NULL, \
+ h, hm, tv)
+#define CLK_SLAVE(id, ns, br, par, h, hm, tv) \
+ CLK_LOCAL(id, NORATE, 0, ns, 0, br, 0, NULL, par, NULL, \
+ h, hm, tv)
+#define CLK_NORATE(id, ns, br, root, h, hm, tv) \
+ CLK_LOCAL(id, NORATE, 0, ns, 0, br, root, NULL, NONE, NULL, \
+ h, hm, tv)
+#define CLK_GLBL(id, glbl, br, h, hm, tv) \
+ CLK_LOCAL(id, NORATE, 0, glbl, 0, br, 0, NULL, GLBL_ROOT, \
+ NULL, h, hm, tv)
+#define CLK_BRIDGE(id, glbl, br, par, h, hm, tv) \
+ CLK_LOCAL(id, NORATE, 0, glbl, 0, br, 0, NULL, par, NULL, \
+ h, hm, tv)
+
+static uint32_t *pll_status_addr[NUM_PLL] = {
+ [PLL_0] = PLL0_STATUS_BASE_REG,
+ [PLL_1] = PLL1_STATUS_BASE_REG,
+ [PLL_2] = PLL2_STATUS_BASE_REG,
+ [PLL_3] = PLL3_STATUS_BASE_REG,
+ [PLL_4] = PLL4_STATUS_BASE_REG,
+ [PLL_5] = PLL5_STATUS_BASE_REG,
+ [PLL_6] = PLL6_STATUS_BASE_REG,
+};
+
+static uint32_t pll_count[NUM_PLL];
+
+static uint32_t chld_grp_3d_src[] = {C(IMEM), C(GRP_3D), C(NONE)};
+static uint32_t chld_mdp_lcdc_p[] = {C(MDP_LCDC_PAD_PCLK), C(NONE)};
+static uint32_t chld_mfc[] = {C(MFC_DIV2), C(NONE)};
+static uint32_t chld_mi2s_codec_rx[] = {C(MI2S_CODEC_RX_S), C(NONE)};
+static uint32_t chld_mi2s_codec_tx[] = {C(MI2S_CODEC_TX_S), C(NONE)};
+static uint32_t chld_mi2s[] = {C(MI2S_S), C(NONE)};
+static uint32_t chld_sdac[] = {C(SDAC_M), C(NONE)};
+static uint32_t chld_tv[] = {C(TV_DAC), C(TV_ENC), C(TSIF_REF),
+ C(HDMI), C(NONE)};
+static uint32_t chld_usb_src[] = {C(USB_HS), C(USB_HS_CORE),
+ C(USB_HS2), C(USB_HS2_CORE),
+ C(USB_HS3), C(USB_HS3_CORE),
+ C(NONE)};
+static uint32_t chld_vfe[] = {C(VFE_MDC), C(VFE_CAMIF), C(CSI0_VFE),
+ C(NONE)};
+
+static struct clk_local clk_local_tbl[] = {
+ CLK_NORATE(MDC, MDC_NS_REG, B(9), B(11),
+ CLK_HALT_STATEA_REG, 10, 0x4D56),
+ CLK_NORATE(LPA_CORE, LPA_NS_REG, B(5), 0,
+ CLK_HALT_STATEC_REG, 5, 0x0E),
+
+ CLK_1RATE(I2C, I2C_NS_REG, B(9), B(11), clk_tbl_tcxo,
+ CLK_HALT_STATEA_REG, 15, 0x4D4D),
+ CLK_1RATE(I2C_2, I2C_2_NS_REG, B(0), B(2), clk_tbl_tcxo,
+ CLK_HALT_STATEC_REG, 2, 0x0B),
+ CLK_1RATE(QUP_I2C, QUP_I2C_NS_REG, B(0), B(2), clk_tbl_tcxo,
+ CLK_HALT_STATEB_REG, 31, 0x1C),
+ CLK_1RATE(UART1, UART_NS_REG, B(5), B(4), clk_tbl_tcxo,
+ CLK_HALT_STATEB_REG, 7, 0x4D6F),
+ CLK_1RATE(UART2, UART2_NS_REG, B(5), B(4), clk_tbl_tcxo,
+ CLK_HALT_STATEB_REG, 5, 0x4D71),
+
+ CLK_BASIC(EMDH, EMDH_NS_REG, 0, B(11), clk_tbl_mdh, AXI_LI_ADSP_A,
+ NULL, 0, 0x4F00),
+ CLK_BASIC(PMDH, PMDH_NS_REG, 0, B(11), clk_tbl_mdh, AXI_LI_ADSP_A,
+ NULL, 0, 0x5500),
+ CLK_BASIC(MDP, MDP_NS_REG, B(9), B(11), clk_tbl_mdp_core, AXI_MDP,
+ CLK_HALT_STATEB_REG, 16, 0x5400),
+
+ CLK_MND8_P(VPE, VPE_NS_REG, 22, 15, B(9), B(11), clk_tbl_vpe,
+ AXI_VPE, NULL, CLK_HALT_STATEC_REG, 10, 0x6C00),
+ CLK_MND8_P(MFC, MFC_NS_REG, 24, 17, B(9), B(11), clk_tbl_mfc,
+ AXI_MFC, chld_mfc, CLK_HALT_STATEC_REG,
+ 12, 0x38),
+ CLK_SLAVE(MFC_DIV2, MFC_NS_REG, B(15), MFC, CLK_HALT_STATEC_REG,
+ 11, 0x1F),
+
+ CLK_MND8(SDC1, SDCn_NS_REG(1), 19, 12, B(9), B(11), clk_tbl_sdc1_3,
+ NULL, CLK_HALT_STATEA_REG, 1, 0x4D62),
+ CLK_MND8(SDC2, SDCn_NS_REG(2), 20, 13, B(9), B(11), clk_tbl_sdc2_4,
+ NULL, CLK_HALT_STATEA_REG, 0, 0x4D64),
+ CLK_MND8(SDC3, SDCn_NS_REG(3), 19, 12, B(9), B(11), clk_tbl_sdc1_3,
+ NULL, CLK_HALT_STATEB_REG, 24, 0x4D7A),
+ CLK_MND8(SDC4, SDCn_NS_REG(4), 20, 13, B(9), B(11), clk_tbl_sdc2_4,
+ NULL, CLK_HALT_STATEB_REG, 25, 0x4D7C),
+ CLK_MND8(SPI, SPI_NS_REG, 19, 12, B(9), B(11), clk_tbl_spi, NULL,
+ CLK_HALT_STATEC_REG, 0, 0x09),
+ CLK_MND8(MIDI, MIDI_NS_REG, 19, 12, B(9), B(11), clk_tbl_midi, NULL,
+ CLK_HALT_STATEC_REG, 1, 0x0A),
+ CLK_MND8_P(USB_HS_SRC, USBH_NS_REG, 23, 16, 0, B(11), clk_tbl_usb,
+ AXI_LI_ADSP_A, chld_usb_src, NULL, 0, 0),
+ CLK_SLAVE(USB_HS, USBH_NS_REG, B(9), USB_HS_SRC,
+ CLK_HALT_STATEB_REG, 26, 0x4D7F),
+ CLK_SLAVE(USB_HS_CORE, USBH_NS_REG, B(13), USB_HS_SRC,
+ CLK_HALT_STATEA_REG, 27, 0x14),
+ CLK_SLAVE(USB_HS2, USBH2_NS_REG, B(9), USB_HS_SRC,
+ CLK_HALT_STATEB_REG, 3, 0x4D73),
+ CLK_SLAVE(USB_HS2_CORE, USBH2_NS_REG, B(4), USB_HS_SRC,
+ CLK_HALT_STATEA_REG, 28, 0x15),
+ CLK_SLAVE(USB_HS3, USBH3_NS_REG, B(9), USB_HS_SRC,
+ CLK_HALT_STATEB_REG, 2, 0x4D74),
+ CLK_SLAVE(USB_HS3_CORE, USBH3_NS_REG, B(4), USB_HS_SRC,
+ CLK_HALT_STATEA_REG, 29, 0x16),
+ CLK_MND8(TV, TV_NS_REG, 23, 16, 0, B(11), clk_tbl_tv, chld_tv,
+ NULL, 0, 0),
+ CLK_SLAVE(HDMI, HDMI_NS_REG, B(9), TV,
+ CLK_HALT_STATEC_REG, 7, 0x13),
+ CLK_SLAVE(TV_DAC, TV_NS_REG, B(12), TV,
+ CLK_HALT_STATEB_REG, 27, 0x4D6C),
+ CLK_SLAVE(TV_ENC, TV_NS_REG, B(9), TV,
+ CLK_HALT_STATEB_REG, 10, 0x4D6B),
+ /* Hacking root & branch into one param. */
+ CLK_SLAVE(TSIF_REF, TSIF_NS_REG, B(9)|B(11), TV,
+ CLK_HALT_STATEB_REG, 11, 0x4D6A),
+
+ CLK_MND16(UART1DM, UART1DM_NS_REG, B(9), B(11), clk_tbl_uartdm, NONE,
+ NULL, CLK_HALT_STATEB_REG, 6, 0x4D70),
+ CLK_MND16(UART2DM, UART2DM_NS_REG, B(9), B(11), clk_tbl_uartdm, NONE,
+ NULL, CLK_HALT_STATEB_REG, 23, 0x4D7D),
+ CLK_MND16(JPEG, JPEG_NS_REG, B(9), B(11), clk_tbl_vfe_jpeg, AXI_LI_JPEG,
+ NULL, CLK_HALT_STATEB_REG, 1, 0x6000),
+ CLK_MND16(CAM_M, CAM_NS_REG, 0, B(9), clk_tbl_cam, NONE, NULL,
+ NULL, 0, 0x4D44),
+ CLK_MND16(VFE, CAM_VFE_NS_REG, B(9), B(13), clk_tbl_vfe_jpeg,
+ AXI_LI_VFE, chld_vfe, CLK_HALT_STATEB_REG,
+ 0, 0x4D76),
+ CLK_SLAVE(VFE_MDC, CAM_VFE_NS_REG, B(11), VFE, CLK_HALT_STATEA_REG,
+ 9, 0x4D57),
+ CLK_SLAVE(VFE_CAMIF, CAM_VFE_NS_REG, B(15), VFE, CLK_HALT_STATEC_REG,
+ 13, 0x7000),
+ CLK_SLAVE(CSI0_VFE, CSI_NS_REG, B(15), VFE, CLK_HALT_STATEC_REG,
+ 16, 0),
+
+ CLK_MND16(SDAC, SDAC_NS_REG, B(9), B(11), clk_tbl_sdac,
+ NONE, chld_sdac, CLK_HALT_STATEA_REG, 2, 0x4D60),
+ CLK_SLAVE(SDAC_M, SDAC_NS_REG, B(12), SDAC, CLK_HALT_STATEB_REG,
+ 17, 0x4D66),
+
+ CLK_MND16(MDP_LCDC_PCLK, MDP_LCDC_NS_REG, B(9), B(11),
+ clk_tbl_mdp_lcdc, NONE, chld_mdp_lcdc_p,
+ CLK_HALT_STATEB_REG, 28, 0x4200),
+ CLK_SLAVE(MDP_LCDC_PAD_PCLK, MDP_LCDC_NS_REG, B(12), MDP_LCDC_PCLK,
+ CLK_HALT_STATEB_REG, 29, 0x4100),
+ CLK_1RATE(MDP_VSYNC, MDP_VSYNC_REG, B(0), 0, clk_tbl_mdp_vsync,
+ CLK_HALT_STATEB_REG, 30, 0x4D53),
+
+ CLK_MND16(MI2S_CODEC_RX_M, MI2S_RX_NS_REG, B(12), B(11),
+ clk_tbl_mi2s_codec, NONE, chld_mi2s_codec_rx,
+ CLK_HALT_STATEA_REG, 12, 0x4D4E),
+ CLK_SLAVE(MI2S_CODEC_RX_S, MI2S_RX_NS_REG, B(9), MI2S_CODEC_RX_M,
+ CLK_HALT_STATEA_REG, 13, 0x4D4F),
+
+ CLK_MND16(MI2S_CODEC_TX_M, MI2S_TX_NS_REG, B(12), B(11),
+ clk_tbl_mi2s_codec, NONE, chld_mi2s_codec_tx,
+ CLK_HALT_STATEC_REG, 8, 0x4D50),
+ CLK_SLAVE(MI2S_CODEC_TX_S, MI2S_TX_NS_REG, B(9), MI2S_CODEC_TX_M,
+ CLK_HALT_STATEA_REG, 11, 0x17),
+
+ CLK_MND16(MI2S_M, MI2S_NS_REG, B(12), B(11),
+ clk_tbl_mi2s, NONE, chld_mi2s, CLK_HALT_STATEC_REG,
+ 4, 0x0D),
+ CLK_SLAVE(MI2S_S, MI2S_NS_REG, B(9), MI2S_M, CLK_HALT_STATEC_REG,
+ 3, 0),
+
+ CLK_LOCAL(GRP_2D, BASIC, 0, GRP_2D_NS_REG, F_MASK_BASIC | (7 << 12),
+ B(7), B(11), clk_tbl_grp, AXI_GRP_2D, NULL,
+ CLK_HALT_STATEA_REG, 31, 0x5C00),
+ CLK_LOCAL(GRP_3D_SRC, BASIC, 0, GRP_NS_REG, F_MASK_BASIC | (7 << 12),
+ 0, B(11), clk_tbl_grp, AXI_LI_GRP, chld_grp_3d_src,
+ 0, 0, 0),
+ CLK_SLAVE(GRP_3D, GRP_NS_REG, B(7), GRP_3D_SRC, CLK_HALT_STATEB_REG,
+ 18, 0x5E00),
+ CLK_SLAVE(IMEM, GRP_NS_REG, B(9), GRP_3D_SRC, CLK_HALT_STATEB_REG,
+ 19, 0x5F00),
+ CLK_LOCAL(LPA_CODEC, BASIC, 0, LPA_NS_REG, BM(1, 0), B(9), 0,
+ clk_tbl_lpa_codec, NONE, NULL, CLK_HALT_STATEC_REG,
+ 6, 0x0F),
+
+ CLK_MND8(CSI0, CSI_NS_REG, 24, 17, B(9), B(11), clk_tbl_csi, NULL,
+ CLK_HALT_STATEC_REG, 17, 0x5F00),
+
+ /* For global clocks to be on we must have GLBL_ROOT_ENA set */
+ CLK_1RATE(GLBL_ROOT, GLBL_CLK_ENA_SC_REG, 0, B(29), clk_tbl_axi,
+ NULL, 0, 0),
+
+ /* Peripheral bus clocks. */
+ CLK_BRIDGE(ADM, GLBL_CLK_ENA_SC_REG, B(5), AXI_LI_APPS,
+ GLBL_CLK_STATE_REG, 5, 0x4000),
+ CLK_GLBL(ADM_P, GLBL_CLK_ENA_2_SC_REG, B(15),
+ GLBL_CLK_STATE_2_REG, 15, 0x11),
+ CLK_GLBL(CE, GLBL_CLK_ENA_SC_REG, B(6),
+ GLBL_CLK_STATE_REG, 6, 0x4D43),
+ CLK_GLBL(CAMIF_PAD_P, GLBL_CLK_ENA_SC_REG, B(9),
+ GLBL_CLK_STATE_REG, 9, 0x1A),
+ CLK_GLBL(CSI0_P, GLBL_CLK_ENA_SC_REG, B(30),
+ GLBL_CLK_STATE_REG, 30, 0),
+ CLK_GLBL(EMDH_P, GLBL_CLK_ENA_2_SC_REG, B(3),
+ GLBL_CLK_STATE_2_REG, 3, 0x03),
+ CLK_GLBL(GRP_2D_P, GLBL_CLK_ENA_SC_REG, B(24),
+ GLBL_CLK_STATE_REG, 24, 0x4D4C),
+ CLK_GLBL(GRP_3D_P, GLBL_CLK_ENA_2_SC_REG, B(17),
+ GLBL_CLK_STATE_2_REG, 17, 0x4D67),
+ CLK_GLBL(JPEG_P, GLBL_CLK_ENA_2_SC_REG, B(24),
+ GLBL_CLK_STATE_2_REG, 24, 0x4D5E),
+ CLK_GLBL(LPA_P, GLBL_CLK_ENA_2_SC_REG, B(7),
+ GLBL_CLK_STATE_2_REG, 7, 0x07),
+ CLK_GLBL(MDP_P, GLBL_CLK_ENA_2_SC_REG, B(6),
+ GLBL_CLK_STATE_2_REG, 6, 0x06),
+ CLK_GLBL(MFC_P, GLBL_CLK_ENA_2_SC_REG, B(26),
+ GLBL_CLK_STATE_2_REG, 26, 0x4D75),
+ CLK_GLBL(PMDH_P, GLBL_CLK_ENA_2_SC_REG, B(4),
+ GLBL_CLK_STATE_2_REG, 4, 0x04),
+ CLK_GLBL(ROTATOR_IMEM, GLBL_CLK_ENA_2_SC_REG, B(23),
+ GLBL_CLK_STATE_2_REG, 23, 0x6600),
+ CLK_GLBL(ROTATOR_P, GLBL_CLK_ENA_2_SC_REG, B(25),
+ GLBL_CLK_STATE_2_REG, 25, 0x4D6D),
+ CLK_GLBL(SDC1_P, GLBL_CLK_ENA_SC_REG, B(7),
+ GLBL_CLK_STATE_REG, 7, 0x4D61),
+ CLK_GLBL(SDC2_P, GLBL_CLK_ENA_SC_REG, B(8),
+ GLBL_CLK_STATE_REG, 8, 0x4F63),
+ CLK_GLBL(SDC3_P, GLBL_CLK_ENA_SC_REG, B(27),
+ GLBL_CLK_STATE_REG, 27, 0x4D79),
+ CLK_GLBL(SDC4_P, GLBL_CLK_ENA_SC_REG, B(28),
+ GLBL_CLK_STATE_REG, 28, 0x4D7B),
+ CLK_GLBL(SPI_P, GLBL_CLK_ENA_2_SC_REG, B(10),
+ GLBL_CLK_STATE_2_REG, 10, 0x18),
+ CLK_GLBL(TSIF_P, GLBL_CLK_ENA_SC_REG, B(18),
+ GLBL_CLK_STATE_REG, 18, 0x4D65),
+ CLK_GLBL(UART1DM_P, GLBL_CLK_ENA_SC_REG, B(17),
+ GLBL_CLK_STATE_REG, 17, 0x4D5C),
+ CLK_GLBL(UART2DM_P, GLBL_CLK_ENA_SC_REG, B(26),
+ GLBL_CLK_STATE_REG, 26, 0x4D7E),
+ CLK_GLBL(USB_HS2_P, GLBL_CLK_ENA_2_SC_REG, B(8),
+ GLBL_CLK_STATE_2_REG, 8, 0x08),
+ CLK_GLBL(USB_HS3_P, GLBL_CLK_ENA_2_SC_REG, B(9),
+ GLBL_CLK_STATE_2_REG, 9, 0x10),
+ CLK_GLBL(USB_HS_P, GLBL_CLK_ENA_SC_REG, B(25),
+ GLBL_CLK_STATE_REG, 25, 0x4D58),
+ CLK_GLBL(VFE_P, GLBL_CLK_ENA_2_SC_REG, B(27),
+ GLBL_CLK_STATE_2_REG, 27, 0x4D55),
+
+ /* AXI bridge clocks. */
+ CLK_BRIDGE(AXI_LI_APPS, GLBL_CLK_ENA_SC_REG, B(2), GLBL_ROOT,
+ GLBL_CLK_STATE_REG, 2, 0x4900),
+ CLK_BRIDGE(AXI_LI_ADSP_A, GLBL_CLK_ENA_2_SC_REG, B(14), AXI_LI_APPS,
+ GLBL_CLK_STATE_2_REG, 14, 0x6400),
+ CLK_BRIDGE(AXI_LI_JPEG, GLBL_CLK_ENA_2_SC_REG, B(19), AXI_LI_APPS,
+ GLBL_CLK_STATE_2_REG, 19, 0x4E00),
+ CLK_BRIDGE(AXI_LI_VFE, GLBL_CLK_ENA_SC_REG, B(23), AXI_LI_APPS,
+ GLBL_CLK_STATE_REG, 23, 0x5B00),
+ CLK_BRIDGE(AXI_MDP, GLBL_CLK_ENA_2_SC_REG, B(29), AXI_LI_APPS,
+ GLBL_CLK_STATE_2_REG, 29, 0x6B00),
+
+ CLK_BRIDGE(AXI_IMEM, GLBL_CLK_ENA_2_SC_REG, B(18), GLBL_ROOT,
+ GLBL_CLK_STATE_2_REG, 18, 0x4B00),
+
+ CLK_BRIDGE(AXI_LI_VG, GLBL_CLK_ENA_SC_REG, B(3), GLBL_ROOT,
+ GLBL_CLK_STATE_REG, 3, 0x4700),
+ CLK_BRIDGE(AXI_GRP_2D, GLBL_CLK_ENA_SC_REG, B(21), AXI_LI_VG,
+ GLBL_CLK_STATE_REG, 21, 0x5900),
+ CLK_BRIDGE(AXI_LI_GRP, GLBL_CLK_ENA_SC_REG, B(22), AXI_LI_VG,
+ GLBL_CLK_STATE_REG, 22, 0x5A00),
+ CLK_BRIDGE(AXI_MFC, GLBL_CLK_ENA_2_SC_REG, B(20), AXI_LI_VG,
+ GLBL_CLK_STATE_2_REG, 20, 0x6A00),
+ CLK_BRIDGE(AXI_ROTATOR, GLBL_CLK_ENA_2_SC_REG, B(22), AXI_LI_VG,
+ GLBL_CLK_STATE_2_REG, 22, 0x4300),
+ CLK_BRIDGE(AXI_VPE, GLBL_CLK_ENA_2_SC_REG, B(21), AXI_LI_VG,
+ GLBL_CLK_STATE_2_REG, 21, 0x6700),
+};
+
+static DEFINE_SPINLOCK(clock_reg_lock);
+static DEFINE_SPINLOCK(pll_vote_lock);
+
+enum {
+ TCXO,
+ LPXO,
+ NUM_XO
+};
+static unsigned xo_votes[NUM_XO]; /* Tracks the number of users for each XO */
+
+/* Map PLLs to which XO they use */
+static const unsigned pll_to_xo[] = {
+ [PLL_0] = TCXO,
+ [PLL_1] = TCXO,
+ [PLL_2] = TCXO,
+ [PLL_3] = LPXO,
+ [PLL_4] = LPXO,
+ [PLL_5] = TCXO,
+ [PLL_6] = TCXO,
+};
+
+static void vote_for_xo(unsigned xo)
+{
+ BUG_ON(xo >= NUM_XO);
+
+ if (!xo_votes[xo]) {
+ int enable = 1;
+ unsigned p_xo = xo;
+ msm_proc_comm(PCOM_CLKCTL_RPC_SRC_REQUEST, &p_xo, &enable);
+ }
+ xo_votes[xo]++;
+}
+
+static void unvote_for_xo(unsigned xo)
+{
+ BUG_ON(xo >= NUM_XO);
+
+ if (xo_votes[xo]) {
+ xo_votes[xo]--;
+ } else {
+ pr_warning("%s: Reference count mismatch!\n", __func__);
+ return;
+ }
+
+ if (xo_votes[xo] == 0) {
+ int enable = 0;
+ msm_proc_comm(PCOM_CLKCTL_RPC_SRC_REQUEST, &xo, &enable);
+ }
+}
+
+#define PLL_ACTIVE_MASK B(16)
+void pll_enable(uint32_t pll)
+{
+ uint32_t reg_val;
+ unsigned long flags;
+
+ BUG_ON(pll >= NUM_PLL);
+
+ spin_lock_irqsave(&pll_vote_lock, flags);
+ if (!pll_count[pll]) {
+ vote_for_xo(pll_to_xo[pll]);
+ reg_val = readl(PLL_ENA_REG);
+ reg_val |= (1 << pll);
+ writel(reg_val, PLL_ENA_REG);
+ }
+ pll_count[pll]++;
+ spin_unlock_irqrestore(&pll_vote_lock, flags);
+
+ /* Wait until PLL is enabled. */
+ while ((readl(pll_status_addr[pll]) & PLL_ACTIVE_MASK) == 0)
+ cpu_relax();
+}
+
+void pll_disable(uint32_t pll)
+{
+ uint32_t reg_val;
+ unsigned long flags;
+
+ BUG_ON(pll >= NUM_PLL);
+
+ spin_lock_irqsave(&pll_vote_lock, flags);
+ if (pll_count[pll]) {
+ pll_count[pll]--;
+ } else {
+ pr_warning("Reference count mismatch in PLL disable!\n");
+ goto out;
+ }
+
+ if (pll_count[pll] == 0) {
+ reg_val = readl(PLL_ENA_REG);
+ reg_val &= ~(1 << pll);
+ writel(reg_val, PLL_ENA_REG);
+ unvote_for_xo(pll_to_xo[pll]);
+ }
+out:
+ spin_unlock_irqrestore(&pll_vote_lock, flags);
+}
+
+static void src_enable(uint32_t src)
+{
+ switch (src) {
+ case SRC_NONE:
+ /*
+ * SRC_NONE is used as a placeholder for some freqencies that
+ * don't have any direct PLL dependency. Instead they source
+ * off an external/internal clock which takes care of any
+ * PLL or XO dependency.
+ */
+ break;
+ case SRC_TCXO:
+ vote_for_xo(TCXO);
+ break;
+ case SRC_AXI:
+ case SRC_LPXO:
+ /*
+ * AXI could use LPXO or TCXO. Map it to LPXO to make sure
+ * there is at least once XO available for the AXI (LPXO is
+ * the lower powered one so just use that).
+ */
+ vote_for_xo(LPXO);
+ break;
+ default:
+ pll_enable(src_pll_tbl[src]);
+ break;
+ }
+}
+
+static void src_disable(uint32_t src)
+{
+ switch (src) {
+ case SRC_NONE:
+ /*
+ * SRC_NONE is used as a placeholder for some freqencies that
+ * don't have any direct PLL dependency. Instead they source
+ * off an external/internal clock which takes care of any
+ * PLL or XO dependency.
+ */
+ break;
+ case SRC_TCXO:
+ unvote_for_xo(TCXO);
+ break;
+ case SRC_AXI:
+ case SRC_LPXO:
+ /*
+ * AXI could use LPXO or TCXO. Map it to LPXO to make sure
+ * there is@least once XO available for the AXI (LPXO is
+ * the lower powered one so just use that).
+ */
+ unvote_for_xo(LPXO);
+ break;
+ default:
+ pll_disable(src_pll_tbl[src]);
+ break;
+ }
+}
+
+static unsigned msmc1_votes[MSMC1_END];
+static unsigned msmc1_level;
+
+static int update_msmc1(void)
+{
+ int err, target, mvolts;
+
+ if (msmc1_votes[HIGH])
+ target = 1200;
+ else if (msmc1_votes[NOMINAL])
+ target = 1100;
+ else
+ target = 1000;
+
+ if (target == msmc1_level)
+ return 0;
+
+ mvolts = target;
+ err = msm_proc_comm(PCOM_CLKCTL_RPC_MIN_MSMC1, &mvolts, NULL);
+ if (err)
+ goto out;
+
+ if (mvolts) {
+ err = -EINVAL;
+ goto out;
+ }
+ msmc1_level = target;
+out:
+ return err;
+}
+
+static void unvote_msmc1(unsigned level)
+{
+ if (level >= ARRAY_SIZE(msmc1_votes))
+ return;
+
+ if (msmc1_votes[level]) {
+ msmc1_votes[level]--;
+ } else {
+ pr_warning("%s: Reference counts are incorrect\n", __func__);
+ return;
+ }
+
+ update_msmc1();
+}
+
+static int vote_msmc1(unsigned level)
+{
+ int ret;
+
+ if (level >= ARRAY_SIZE(msmc1_votes))
+ return 0;
+
+ msmc1_votes[level]++;
+ ret = update_msmc1();
+ if (ret)
+ msmc1_votes[level]--;
+
+ return ret;
+}
+
+/*
+ * SoC specific register-based control of clocks.
+ */
+static int _soc_clk_enable(unsigned id)
+{
+ struct clk_local *t = &clk_local_tbl[id];
+ void *ns_reg = t->ns_reg;
+ uint32_t reg_val = 0;
+
+ WARN((t->type != NORATE) && (t->current_freq == &dummy_freq),
+ "Attempting to enable clock %d before setting its rate. "
+ "Set the rate first!\n", id);
+
+ reg_val = readl(ns_reg);
+ if (t->type == MND) {
+ /* mode can be either 0 or 1. So the R-value of the
+ * expression will evaluate to MNCNTR_EN_MASK or 0. This
+ * avoids the need for a "if(mode == 1)". A "&" will not work
+ * here. */
+ reg_val |= (MNCNTR_EN_MASK * t->current_freq->mode);
+ writel(reg_val, ns_reg);
+ }
+ if (t->root_en_mask) {
+ reg_val |= t->root_en_mask;
+ writel(reg_val, ns_reg);
+ }
+ if (t->br_en_mask) {
+ reg_val |= t->br_en_mask;
+ writel(reg_val, ns_reg);
+ }
+ if (t->halt_reg) {
+ uint32_t halted, count = 0;
+
+ /* Wait for the halt bit to clear, but timeout after 100usecs
+ * since the halt bit may be buggy. */
+ while ((halted = readl(t->halt_reg) & BIT(t->halt_mask))
+ && count++ < 100)
+ udelay(1);
+ if (halted)
+ pr_warning("%s: clock %d never turned on\n", __func__,
+ id);
+ }
+ return 0;
+}
+
+static void _soc_clk_disable(unsigned id)
+{
+ struct clk_local *t = &clk_local_tbl[id];
+ void *ns_reg = t->ns_reg;
+ uint32_t reg_val = 0;
+
+ reg_val = readl(ns_reg);
+
+ if (t->br_en_mask) {
+ reg_val &= ~(t->br_en_mask);
+ writel(reg_val, ns_reg);
+ }
+ if (t->halt_reg) {
+ uint32_t halted, count = 0;
+
+ /* Wait for the halt bit to be set, but timeout after 100usecs
+ * since the halt bit may be buggy. */
+ while (!(halted = readl(t->halt_reg) & BIT(t->halt_mask))
+ && count++ < 100)
+ udelay(1);
+ if (!halted)
+ pr_warning("%s: clock %d never turned off\n", __func__,
+ id);
+ }
+ if (t->root_en_mask) {
+ reg_val &= ~(t->root_en_mask);
+ writel(reg_val, ns_reg);
+ }
+ if (t->type == MND) {
+ reg_val &= ~MNCNTR_EN_MASK;
+ writel(reg_val, ns_reg);
+ }
+}
+
+static int soc_clk_enable_nolock(unsigned id)
+{
+ struct clk_local *t = &clk_local_tbl[id];
+ int ret = 0;
+
+ if (!t->count) {
+ ret = vote_msmc1(t->current_freq->msmc1);
+ if (ret)
+ return ret;
+ if (t->parent != C(NONE)) {
+ ret = soc_clk_enable_nolock(t->parent);
+ if (ret)
+ return ret;
+ }
+ src_enable(t->current_freq->src);
+ ret = _soc_clk_enable(id);
+ }
+ t->count++;
+
+ return ret;
+}
+
+static void soc_clk_disable_nolock(unsigned id)
+{
+ struct clk_local *t = &clk_local_tbl[id];
+
+ if (!t->count) {
+ pr_warning("Reference count mismatch in clock disable!\n");
+ return;
+ }
+ if (t->count)
+ t->count--;
+ if (t->count == 0) {
+ _soc_clk_disable(id);
+ src_disable(t->current_freq->src);
+ unvote_msmc1(t->current_freq->msmc1);
+ if (t->parent != C(NONE))
+ soc_clk_disable_nolock(t->parent);
+ }
+
+ return;
+}
+
+static int update_pwr_rail(unsigned id, int enable)
+{
+ /* TODO: Implement internal power rail control */
+ return 0;
+}
+
+static int soc_clk_enable(unsigned id)
+{
+ int ret = 0;
+ unsigned long flags;
+
+ spin_lock_irqsave(&clock_reg_lock, flags);
+ ret = soc_clk_enable_nolock(id);
+ if (ret)
+ goto unlock;
+ /*
+ * The modem might modify the register bits for the clock branch when
+ * the rail is enabled/disabled, so enable the rail inside the lock
+ * instead of outside it.
+ */
+ ret = update_pwr_rail(id, 1);
+ if (ret)
+ soc_clk_disable_nolock(id);
+unlock:
+ spin_unlock_irqrestore(&clock_reg_lock, flags);
+
+ return ret;
+}
+
+static void soc_clk_disable(unsigned id)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&clock_reg_lock, flags);
+ update_pwr_rail(id, 0);
+ soc_clk_disable_nolock(id);
+ spin_unlock_irqrestore(&clock_reg_lock, flags);
+}
+
+static void soc_clk_auto_off(unsigned id)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&clock_reg_lock, flags);
+ _soc_clk_disable(id);
+ spin_unlock_irqrestore(&clock_reg_lock, flags);
+}
+
+static long soc_clk_round_rate(unsigned id, unsigned rate)
+{
+ struct clk_local *t = &clk_local_tbl[id];
+ const struct clk_freq_tbl *f;
+
+ if (t->type != MND && t->type != BASIC)
+ return -EINVAL;
+
+ for (f = t->freq_tbl; f->freq_hz != FREQ_END; f++)
+ if (f->freq_hz >= rate)
+ return f->freq_hz;
+
+ return -EPERM;
+}
+
+static int soc_clk_set_rate(unsigned id, unsigned rate)
+{
+ struct clk_local *t = &clk_local_tbl[id];
+ const struct clk_freq_tbl *cf;
+ const struct clk_freq_tbl *nf;
+ uint32_t *chld = t->children;
+ void *ns_reg = t->ns_reg;
+ void *md_reg = t->md_reg;
+ uint32_t reg_val = 0;
+ int i, ret = 0;
+ unsigned long flags;
+ long rounded;
+
+ rounded = soc_clk_round_rate(id, rate);
+ if (rounded != rate)
+ pr_warning("Use clk_round_rate() before clk_set_rate() with "
+ "clock %u\n", id);
+ rate = rounded;
+
+ if (t->type != MND && t->type != BASIC)
+ return -EPERM;
+
+ spin_lock_irqsave(&clock_reg_lock, flags);
+ cf = t->current_freq;
+
+ if (rate == cf->freq_hz)
+ goto release_lock;
+
+ for (nf = t->freq_tbl; nf->freq_hz != FREQ_END; nf++)
+ if (nf->freq_hz == rate)
+ break;
+
+ if (nf->freq_hz == FREQ_END) {
+ ret = -EINVAL;
+ goto release_lock;
+ }
+
+ if (t->freq_mask == 0) {
+ t->current_freq = nf;
+ goto release_lock;
+ }
+
+ /* Disable all branches before changing rate to prevent jitter. */
+ for (i = 0; chld && chld[i] != C(NONE); i++) {
+ struct clk_local *ch = &clk_local_tbl[chld[i]];
+ /* Don't bother turning off if it is already off.
+ * Checking ch->count is cheaper (cache) than reading and
+ * writing to a register (uncached/unbuffered). */
+ if (ch->count) {
+ reg_val = readl(ch->ns_reg);
+ reg_val &= ~(ch->br_en_mask);
+ writel(reg_val, ch->ns_reg);
+ }
+ }
+
+ if (t->count) {
+ _soc_clk_disable(id);
+
+ ret = vote_msmc1(nf->msmc1);
+ if (ret)
+ goto msmc1_err;
+ /* Turn on PLL of the new freq. */
+ src_enable(nf->src);
+ }
+
+ /* Some clocks share the same register, so must be careful when
+ * assuming a register doesn't need to be re-read. */
+ reg_val = readl(ns_reg);
+ if (t->type == MND) {
+ reg_val |= MNCNTR_RST_MASK;
+ writel(reg_val, ns_reg);
+ /* TODO: Currently writing 0's into reserved bits for 8-bit
+ * MND. Can be avoided by adding md_mask. */
+ if (nf->mode)
+ writel(nf->md_val, md_reg);
+ reg_val &= ~MNCNTR_MODE_MASK;
+ reg_val |= (MNCNTR_MODE * nf->mode);
+ }
+ reg_val &= ~(t->freq_mask);
+ reg_val |= nf->ns_val;
+ writel(reg_val, ns_reg);
+
+ if (t->type == MND) {
+ reg_val &= ~MNCNTR_RST_MASK;
+ writel(reg_val, ns_reg);
+ }
+
+ if (t->count) {
+ /* Turn off PLL of the old freq. */
+ src_disable(cf->src);
+ unvote_msmc1(cf->msmc1);
+ }
+
+ /* Current freq must be updated before _soc_clk_enable() is called to
+ * make sure the MNCNTR_E bit is set correctly. */
+ t->current_freq = nf;
+
+msmc1_err:
+ if (t->count)
+ _soc_clk_enable(id);
+ /* Enable only branches that were ON before. */
+ for (i = 0; chld && chld[i] != C(NONE); i++) {
+ struct clk_local *ch = &clk_local_tbl[chld[i]];
+ if (ch->count) {
+ reg_val = readl(ch->ns_reg);
+ reg_val |= ch->br_en_mask;
+ writel(reg_val, ch->ns_reg);
+ }
+ }
+
+release_lock:
+ spin_unlock_irqrestore(&clock_reg_lock, flags);
+ return ret;
+}
+
+static int soc_clk_set_min_rate(unsigned id, unsigned rate)
+{
+ long rounded = soc_clk_round_rate(id, rate);
+ return soc_clk_set_rate(id, rounded);
+}
+
+static int soc_clk_set_max_rate(unsigned id, unsigned rate)
+{
+ return -EPERM;
+}
+
+static int soc_clk_set_flags(unsigned id, unsigned clk_flags)
+{
+ uint32_t regval, ret = 0;
+ unsigned long flags;
+
+ spin_lock_irqsave(&clock_reg_lock, flags);
+ switch (id) {
+ case C(VFE):
+ regval = readl(CAM_VFE_NS_REG);
+ /* Flag values chosen for backward compatibility
+ * with proc_comm remote clock control. */
+ if (clk_flags == 0x00000100) {
+ /* Select external source. */
+ regval |= B(14);
+ } else if (clk_flags == 0x00000200) {
+ /* Select internal source. */
+ regval &= ~B(14);
+ } else
+ ret = -EINVAL;
+
+ writel(regval, CAM_VFE_NS_REG);
+ break;
+ default:
+ ret = -EPERM;
+ }
+ spin_unlock_irqrestore(&clock_reg_lock, flags);
+
+ return ret;
+}
+
+static unsigned soc_clk_get_rate(unsigned id)
+{
+ struct clk_local *t = &clk_local_tbl[id];
+ unsigned long flags;
+ unsigned ret = 0;
+
+ if (t->type == NORATE)
+ return 0;
+
+ spin_lock_irqsave(&clock_reg_lock, flags);
+ ret = t->current_freq->freq_hz;
+ spin_unlock_irqrestore(&clock_reg_lock, flags);
+
+ /* Return 0 if the rate has never been set. Might not be correct,
+ * but it's good enough. */
+ if (ret == FREQ_END)
+ ret = 0;
+
+ return ret;
+}
+
+static unsigned soc_clk_is_enabled(unsigned id)
+{
+ return !!(clk_local_tbl[id].count);
+}
+
+
+struct clk_ops clk_ops_7x30 = {
+ .enable = soc_clk_enable,
+ .disable = soc_clk_disable,
+ .auto_off = soc_clk_auto_off,
+ .set_rate = soc_clk_set_rate,
+ .set_min_rate = soc_clk_set_min_rate,
+ .set_max_rate = soc_clk_set_max_rate,
+ .reset = pc_clk_reset,
+ .set_flags = soc_clk_set_flags,
+ .get_rate = soc_clk_get_rate,
+ .is_enabled = soc_clk_is_enabled,
+ .round_rate = soc_clk_round_rate,
+};
+
+/*
+ * Clock ownership detection code
+ */
+
+enum {
+ SH2_OWN_GLBL,
+ SH2_OWN_APPS1,
+ SH2_OWN_APPS2,
+ SH2_OWN_ROW1,
+ SH2_OWN_ROW2,
+ SH2_OWN_APPS3,
+ NUM_OWNERSHIP
+};
+static __initdata uint32_t ownership_regs[NUM_OWNERSHIP];
+
+static void __init cache_ownership(void)
+{
+ ownership_regs[SH2_OWN_GLBL] = readl(SH2_OWN_GLBL_BASE_REG);
+ ownership_regs[SH2_OWN_APPS1] = readl(SH2_OWN_APPS1_BASE_REG);
+ ownership_regs[SH2_OWN_APPS2] = readl(SH2_OWN_APPS2_BASE_REG);
+ ownership_regs[SH2_OWN_ROW1] = readl(SH2_OWN_ROW1_BASE_REG);
+ ownership_regs[SH2_OWN_ROW2] = readl(SH2_OWN_ROW2_BASE_REG);
+ ownership_regs[SH2_OWN_APPS3] = readl(SH2_OWN_APPS3_BASE_REG);
+}
+
+static void __init print_ownership(void)
+{
+ pr_info("Clock ownership\n");
+ pr_info(" GLBL : %08x\n", ownership_regs[SH2_OWN_GLBL]);
+ pr_info(" APPS : %08x %08x %08x\n", ownership_regs[SH2_OWN_APPS1],
+ ownership_regs[SH2_OWN_APPS2], ownership_regs[SH2_OWN_APPS3]);
+ pr_info(" ROW : %08x %08x\n", ownership_regs[SH2_OWN_ROW1],
+ ownership_regs[SH2_OWN_ROW2]);
+}
+
+/*
+ * This is a many-to-one mapping since we don't know how the remote clock code
+ * has decided to handle the dependencies between clocks for a particular
+ * hardware block. We determine the ownership for all the clocks on a block by
+ * checking the ownership bit of one register (usually the ns register).
+ */
+#define O(x) (&ownership_regs[(x)])
+static const struct clk_local_ownership {
+ const uint32_t *reg;
+ const uint32_t bit;
+} ownership_map[] __initconst = {
+ [C(GRP_2D)] = { O(SH2_OWN_APPS1), B(6) },
+ [C(GRP_2D_P)] = { O(SH2_OWN_APPS1), B(6) },
+ [C(HDMI)] = { O(SH2_OWN_APPS1), B(31) },
+ [C(JPEG)] = { O(SH2_OWN_APPS1), B(0) },
+ [C(JPEG_P)] = { O(SH2_OWN_APPS1), B(0) },
+ [C(LPA_CODEC)] = { O(SH2_OWN_APPS1), B(23) },
+ [C(LPA_CORE)] = { O(SH2_OWN_APPS1), B(23) },
+ [C(LPA_P)] = { O(SH2_OWN_APPS1), B(23) },
+ [C(MI2S_M)] = { O(SH2_OWN_APPS1), B(28) },
+ [C(MI2S_S)] = { O(SH2_OWN_APPS1), B(28) },
+ [C(MI2S_CODEC_RX_M)] = { O(SH2_OWN_APPS1), B(12) },
+ [C(MI2S_CODEC_RX_S)] = { O(SH2_OWN_APPS1), B(12) },
+ [C(MI2S_CODEC_TX_M)] = { O(SH2_OWN_APPS1), B(14) },
+ [C(MI2S_CODEC_TX_S)] = { O(SH2_OWN_APPS1), B(14) },
+ [C(MIDI)] = { O(SH2_OWN_APPS1), B(22) },
+ [C(SDAC)] = { O(SH2_OWN_APPS1), B(26) },
+ [C(SDAC_M)] = { O(SH2_OWN_APPS1), B(26) },
+ [C(VFE)] = { O(SH2_OWN_APPS1), B(8) },
+ [C(VFE_CAMIF)] = { O(SH2_OWN_APPS1), B(8) },
+ [C(VFE_MDC)] = { O(SH2_OWN_APPS1), B(8) },
+ [C(VFE_P)] = { O(SH2_OWN_APPS1), B(8) },
+
+ [C(GRP_3D)] = { O(SH2_OWN_APPS2), B(0) },
+ [C(GRP_3D_P)] = { O(SH2_OWN_APPS2), B(0) },
+ [C(GRP_3D_SRC)] = { O(SH2_OWN_APPS2), B(0) },
+ [C(IMEM)] = { O(SH2_OWN_APPS2), B(0) },
+ [C(MDP_LCDC_PAD_PCLK)] = { O(SH2_OWN_APPS2), B(4) },
+ [C(MDP_LCDC_PCLK)] = { O(SH2_OWN_APPS2), B(4) },
+ [C(MDP_P)] = { O(SH2_OWN_APPS2), B(4) },
+ [C(MDP_VSYNC)] = { O(SH2_OWN_APPS2), B(28) },
+ [C(TSIF_REF)] = { O(SH2_OWN_APPS2), B(5) },
+ [C(TSIF_P)] = { O(SH2_OWN_APPS2), B(5) },
+ [C(TV)] = { O(SH2_OWN_APPS2), B(2) },
+ [C(TV_DAC)] = { O(SH2_OWN_APPS2), B(2) },
+ [C(TV_ENC)] = { O(SH2_OWN_APPS2), B(2) },
+
+ [C(EMDH)] = { O(SH2_OWN_ROW1), B(7) },
+ [C(EMDH_P)] = { O(SH2_OWN_ROW1), B(7) },
+ [C(I2C)] = { O(SH2_OWN_ROW1), B(11) },
+ [C(I2C_2)] = { O(SH2_OWN_ROW1), B(12) },
+ [C(MDC)] = { O(SH2_OWN_ROW1), B(17) },
+ [C(PMDH)] = { O(SH2_OWN_ROW1), B(19) },
+ [C(PMDH_P)] = { O(SH2_OWN_ROW1), B(19) },
+ [C(SDC1)] = { O(SH2_OWN_ROW1), B(23) },
+ [C(SDC1_P)] = { O(SH2_OWN_ROW1), B(23) },
+ [C(SDC2)] = { O(SH2_OWN_ROW1), B(25) },
+ [C(SDC2_P)] = { O(SH2_OWN_ROW1), B(25) },
+ [C(SDC3)] = { O(SH2_OWN_ROW1), B(27) },
+ [C(SDC3_P)] = { O(SH2_OWN_ROW1), B(27) },
+ [C(SDC4)] = { O(SH2_OWN_ROW1), B(29) },
+ [C(SDC4_P)] = { O(SH2_OWN_ROW1), B(29) },
+ [C(UART2)] = { O(SH2_OWN_ROW1), B(0) },
+ [C(USB_HS2)] = { O(SH2_OWN_ROW1), B(2) },
+ [C(USB_HS2_CORE)] = { O(SH2_OWN_ROW1), B(2) },
+ [C(USB_HS2_P)] = { O(SH2_OWN_ROW1), B(2) },
+ [C(USB_HS3)] = { O(SH2_OWN_ROW1), B(4) },
+ [C(USB_HS3_CORE)] = { O(SH2_OWN_ROW1), B(4) },
+ [C(USB_HS3_P)] = { O(SH2_OWN_ROW1), B(4) },
+
+ [C(QUP_I2C)] = { O(SH2_OWN_ROW2), B(3) },
+ [C(SPI)] = { O(SH2_OWN_ROW2), B(1) },
+ [C(SPI_P)] = { O(SH2_OWN_ROW2), B(1) },
+ [C(UART1)] = { O(SH2_OWN_ROW2), B(9) },
+ [C(UART1DM)] = { O(SH2_OWN_ROW2), B(6) },
+ [C(UART1DM_P)] = { O(SH2_OWN_ROW2), B(6) },
+ [C(UART2DM)] = { O(SH2_OWN_ROW2), B(8) },
+ [C(UART2DM_P)] = { O(SH2_OWN_ROW2), B(8) },
+ [C(USB_HS)] = { O(SH2_OWN_ROW2), B(11) },
+ [C(USB_HS_CORE)] = { O(SH2_OWN_ROW2), B(11) },
+ [C(USB_HS_SRC)] = { O(SH2_OWN_ROW2), B(11) },
+ [C(USB_HS_P)] = { O(SH2_OWN_ROW2), B(11) },
+
+ [C(CAM_M)] = { O(SH2_OWN_APPS3), B(6) },
+ [C(CAMIF_PAD_P)] = { O(SH2_OWN_APPS3), B(6) },
+ [C(CSI0)] = { O(SH2_OWN_APPS3), B(11) },
+ [C(CSI0_VFE)] = { O(SH2_OWN_APPS3), B(11) },
+ [C(CSI0_P)] = { O(SH2_OWN_APPS3), B(11) },
+ [C(MDP)] = { O(SH2_OWN_APPS3), B(0) },
+ [C(MFC)] = { O(SH2_OWN_APPS3), B(2) },
+ [C(MFC_DIV2)] = { O(SH2_OWN_APPS3), B(2) },
+ [C(MFC_P)] = { O(SH2_OWN_APPS3), B(2) },
+ [C(VPE)] = { O(SH2_OWN_APPS3), B(4) },
+
+ [C(ADM)] = { O(SH2_OWN_GLBL), B(8) },
+ [C(ADM_P)] = { O(SH2_OWN_GLBL), B(13) },
+ [C(CE)] = { O(SH2_OWN_GLBL), B(8) },
+ [C(AXI_ROTATOR)] = { O(SH2_OWN_GLBL), B(13) },
+ [C(ROTATOR_IMEM)] = { O(SH2_OWN_GLBL), B(13) },
+ [C(ROTATOR_P)] = { O(SH2_OWN_GLBL), B(13) },
+};
+
+static bool __init clk_is_local(uint32_t id)
+{
+ uint32_t bit = ownership_map[id].bit;
+ const uint32_t *reg = ownership_map[id].reg;
+
+ BUG_ON(id >= ARRAY_SIZE(ownership_map) || !reg);
+
+ return *reg & bit;
+}
+
+static const struct reg_init {
+ const void __iomem *reg;
+ uint32_t mask;
+ uint32_t val;
+} ri_list[] __initconst = {
+ /* Enable UMDX_P clock. Known to causes issues, so never turn off. */
+ {GLBL_CLK_ENA_2_SC_REG, B(2), B(2)},
+
+ {EMDH_NS_REG, BM(18, 17) , BVAL(18, 17, 0x3)}, /* RX div = div-4. */
+ {PMDH_NS_REG, BM(18, 17), BVAL(18, 17, 0x3)}, /* RX div = div-4. */
+ /* MI2S_CODEC_RX_S src = MI2S_CODEC_RX_M. */
+ {MI2S_RX_NS_REG, B(14), 0x0},
+ /* MI2S_CODEC_TX_S src = MI2S_CODEC_TX_M. */
+ {MI2S_TX_NS_REG, B(14), 0x0},
+ {MI2S_NS_REG, B(14), 0x0}, /* MI2S_S src = MI2S_M. */
+ /* Allow DSP to decide the LPA CORE src. */
+ {LPA_CORE_CLK_MA0_REG, B(0), B(0)},
+ {LPA_CORE_CLK_MA2_REG, B(0), B(0)},
+ {MI2S_CODEC_RX_DIV_REG, 0xF, 0xD}, /* MI2S_CODEC_RX_S div = div-8. */
+ {MI2S_CODEC_TX_DIV_REG, 0xF, 0xD}, /* MI2S_CODEC_TX_S div = div-8. */
+ {MI2S_DIV_REG, 0xF, 0x7}, /* MI2S_S div = div-8. */
+ {MDC_NS_REG, 0x3, 0x3}, /* MDC src = external MDH src. */
+ {SDAC_NS_REG, BM(15, 14), 0x0}, /* SDAC div = div-1. */
+ /* Disable sources TCXO/5 & TCXO/6. UART1 src = TCXO*/
+ {UART_NS_REG, BM(26, 25) | BM(2, 0), 0x0},
+ {MDP_VSYNC_REG, 0xC, 0x4}, /* MDP VSYNC src = LPXO. */
+ /* HDMI div = div-1, non-inverted. tv_enc_src = tv_clk_src */
+ {HDMI_NS_REG, 0x7, 0x0},
+ {TV_NS_REG, BM(15, 14), 0x0}, /* tv_clk_src_div2 = div-1 */
+
+ /* USBH core clocks src = USB_HS_SRC. */
+ {USBH_NS_REG, B(15), B(15)},
+ {USBH2_NS_REG, B(6), B(6)},
+ {USBH3_NS_REG, B(6), B(6)},
+};
+
+/* SoC-specific clk_ops initialization. */
+void __init msm_clk_soc_set_ops(struct clk *clk)
+{
+ if (!clk->ops) {
+ if (clk_is_local(clk->id))
+ clk->ops = &clk_ops_7x30;
+ else {
+ clk->ops = &clk_ops_pcom;
+ clk->id = clk->remote_id;
+ }
+ }
+}
+
+#define set_1rate(clk) \
+ soc_clk_set_rate(C(clk), clk_local_tbl[C(clk)].freq_tbl->freq_hz)
+void __init msm_clk_soc_init(void)
+{
+ int i;
+ uint32_t val;
+
+ cache_ownership();
+ print_ownership();
+
+ /* When we have no local clock control, the rest of the code in this
+ * function is a NOP since writes to shadow regions that we don't own
+ * are ignored. */
+
+ /* Disable all the child clocks of USB_HS_SRC. This needs to be done
+ * before the register init loop since it changes the source of the
+ * USB HS core clocks. */
+ for (i = 0; chld_usb_src[i] != C(NONE); i++)
+ if (clk_is_local(chld_usb_src[i]))
+ _soc_clk_disable(chld_usb_src[i]);
+
+ if (clk_is_local(C(USB_HS_SRC)))
+ soc_clk_set_rate(C(USB_HS_SRC), clk_tbl_usb[0].freq_hz);
+
+ for (i = 0; i < ARRAY_SIZE(ri_list); i++) {
+ val = readl(ri_list[i].reg);
+ val &= ~ri_list[i].mask;
+ val |= ri_list[i].val;
+ writel(val, ri_list[i].reg);
+ }
+
+ set_1rate(I2C);
+ set_1rate(I2C_2);
+ set_1rate(QUP_I2C);
+ set_1rate(UART1);
+ set_1rate(UART2);
+ set_1rate(MI2S_M);
+ set_1rate(MIDI);
+ set_1rate(MDP_VSYNC);
+ set_1rate(LPA_CODEC);
+ set_1rate(GLBL_ROOT);
+
+ /* Sync the GRP2D clock to AXI */
+ soc_clk_set_rate(C(GRP_2D), 1);
+}
diff --git a/arch/arm/mach-msm/clock-7x30.h b/arch/arm/mach-msm/clock-7x30.h
index e16f72f..d41acb7 100644
--- a/arch/arm/mach-msm/clock-7x30.h
+++ b/arch/arm/mach-msm/clock-7x30.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2009, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2009-2010, Code Aurora Forum. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
@@ -33,6 +33,8 @@
enum {
L_7X30_NONE_CLK = -1,
L_7X30_ADM_CLK,
+ L_7X30_ADM_P_CLK,
+ L_7X30_CE_CLK,
L_7X30_I2C_CLK,
L_7X30_I2C_2_CLK,
L_7X30_QUP_I2C_CLK,
@@ -135,17 +137,30 @@ enum {
L_7X30_NR_CLKS
};
-struct clk_ops;
-extern struct clk_ops clk_ops_7x30;
-
-struct clk_ops *clk_7x30_is_local(uint32_t id);
-int clk_7x30_init(void);
-
void pll_enable(uint32_t pll);
void pll_disable(uint32_t pll);
+enum {
+ PLL_0 = 0,
+ PLL_1,
+ PLL_2,
+ PLL_3,
+ PLL_4,
+ PLL_5,
+ PLL_6,
+ NUM_PLL
+};
+
+enum {
+ LOW,
+ NOMINAL,
+ HIGH,
+ MSMC1_END
+};
+
extern int internal_pwr_rail_ctl_auto(unsigned rail_id, bool enable);
+extern struct clk_ops clk_ops_7x30;
#define CLK_7X30(clk_name, clk_id, clk_dev, clk_flags) { \
.name = clk_name, \
.id = L_7X30_##clk_id, \
@@ -164,5 +179,14 @@ extern int internal_pwr_rail_ctl_auto(unsigned rail_id, bool enable);
.dbg_name = #l_id, \
}
+#define CLK_7X30L(clk_name, l_id, clk_dev, clk_flags) { \
+ .name = clk_name, \
+ .id = L_7X30_##l_id, \
+ .flags = clk_flags, \
+ .dev = clk_dev, \
+ .dbg_name = #l_id, \
+ .ops = &clk_ops_7x30, \
+ }
+
#endif
diff --git a/arch/arm/mach-msm/clock.c b/arch/arm/mach-msm/clock.c
index 8c2b4dd..56c7549 100644
--- a/arch/arm/mach-msm/clock.c
+++ b/arch/arm/mach-msm/clock.c
@@ -162,21 +162,16 @@ EXPORT_SYMBOL(clk_set_flags);
*/
static struct clk *ebi1_clk;
-static void __init set_clock_ops(struct clk *clk)
-{
- if (!clk->ops) {
- clk->ops = &clk_ops_pcom;
- clk->id = clk->remote_id;
- }
-}
-
void __init msm_clock_init(struct clk *clock_tbl, unsigned num_clocks)
{
unsigned n;
+ /* Do SoC-speficic clock init operations. */
+ msm_clk_soc_init();
+
mutex_lock(&clocks_mutex);
for (n = 0; n < num_clocks; n++) {
- set_clock_ops(&clock_tbl[n]);
+ msm_clk_soc_set_ops(&clock_tbl[n]);
list_add_tail(&clock_tbl[n].list, &clocks);
}
mutex_unlock(&clocks_mutex);
diff --git a/arch/arm/mach-msm/clock.h b/arch/arm/mach-msm/clock.h
index 70216b0..4841ab6 100644
--- a/arch/arm/mach-msm/clock.h
+++ b/arch/arm/mach-msm/clock.h
@@ -62,6 +62,18 @@ struct clk {
#define CLK_MAX CLKFLAG_MAX
#define CLK_MINMAX (CLK_MIN | CLK_MAX)
+#ifdef CONFIG_ARCH_MSM7X30
+void __init msm_clk_soc_set_ops(struct clk *clk);
+#else
+static inline void __init msm_clk_soc_set_ops(struct clk *clk) { }
+#endif
+
+#if defined(CONFIG_ARCH_MSM7X30)
+void __init msm_clk_soc_init(void);
+#else
+static inline void __init msm_clk_soc_init(void) { }
+#endif
+
#ifdef CONFIG_DEBUG_FS
int __init clock_debug_init(void);
int __init clock_debug_add(struct clk *clock);
diff --git a/arch/arm/mach-msm/proc_comm.h b/arch/arm/mach-msm/proc_comm.h
index 12da4ca..e2f2d5a 100644
--- a/arch/arm/mach-msm/proc_comm.h
+++ b/arch/arm/mach-msm/proc_comm.h
@@ -137,6 +137,7 @@ enum {
PCOM_CLKCTL_RPC_RAIL_DISABLE,
PCOM_CLKCTL_RPC_RAIL_CONTROL,
PCOM_CLKCTL_RPC_MIN_MSMC1,
+ PCOM_CLKCTL_RPC_SRC_REQUEST,
PCOM_NUM_CMDS,
};
--
Sent by an employee of the Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum.
^ permalink raw reply related [flat|nested] 23+ messages in thread* [PATCH 06/22] msm: clock-7x30: Update clock table
2010-12-17 0:49 [PATCH 00/22] MSM clock driver updates Stephen Boyd
` (4 preceding siblings ...)
2010-12-17 0:49 ` [PATCH 05/22] msm: clock-7x30: Add 7x30 local clock driver Stephen Boyd
@ 2010-12-17 0:49 ` Stephen Boyd
2010-12-17 0:49 ` [PATCH 07/22] msm: clock: Refactor clock-7x30 into generic clock-local driver Stephen Boyd
` (15 subsequent siblings)
21 siblings, 0 replies; 23+ messages in thread
From: Stephen Boyd @ 2010-12-17 0:49 UTC (permalink / raw)
To: linux-arm-kernel
Mark clocks with CLK_7X30 to indicate they have the potential to
be locally controllable. If it's determined at runtime that these
clocks are not locally owned, revert the clocks to proc_comm
control. Mark clocks with CLK_PCOM when we know that they can't
be locally controlled.
Reviewed-by: Saravana Kannan <skannan@codeaurora.org>
Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
---
arch/arm/mach-msm/devices-msm7x30.c | 147 ++++++++++++++++++++---------------
1 files changed, 85 insertions(+), 62 deletions(-)
diff --git a/arch/arm/mach-msm/devices-msm7x30.c b/arch/arm/mach-msm/devices-msm7x30.c
index 2816be3..55382c4 100644
--- a/arch/arm/mach-msm/devices-msm7x30.c
+++ b/arch/arm/mach-msm/devices-msm7x30.c
@@ -58,78 +58,101 @@ struct platform_device msm_device_smd = {
};
struct clk msm_clocks_7x30[] = {
- CLK_PCOM("adm_clk", ADM_CLK, NULL, 0),
CLK_PCOM("adsp_clk", ADSP_CLK, NULL, 0),
CLK_PCOM("cam_m_clk", CAM_M_CLK, NULL, 0),
CLK_PCOM("camif_pad_pclk", CAMIF_PAD_P_CLK, NULL, OFF),
- CLK_PCOM("ce_clk", CE_CLK, NULL, 0),
CLK_PCOM("codec_ssbi_clk", CODEC_SSBI_CLK, NULL, 0),
CLK_PCOM("ebi1_clk", EBI1_CLK, NULL, CLK_MIN),
CLK_PCOM("ecodec_clk", ECODEC_CLK, NULL, 0),
- CLK_PCOM("emdh_clk", EMDH_CLK, NULL, OFF | CLK_MINMAX),
- CLK_PCOM("emdh_pclk", EMDH_P_CLK, NULL, OFF),
CLK_PCOM("gp_clk", GP_CLK, NULL, 0),
- CLK_PCOM("grp_2d_clk", GRP_2D_CLK, NULL, 0),
- CLK_PCOM("grp_2d_pclk", GRP_2D_P_CLK, NULL, 0),
- CLK_PCOM("grp_clk", GRP_3D_CLK, NULL, 0),
- CLK_PCOM("grp_pclk", GRP_3D_P_CLK, NULL, 0),
- CLK_7X30S("grp_src_clk", GRP_3D_SRC_CLK, GRP_3D_CLK, NULL, 0),
- CLK_PCOM("hdmi_clk", HDMI_CLK, NULL, 0),
- CLK_PCOM("imem_clk", IMEM_CLK, NULL, OFF),
- CLK_PCOM("jpeg_clk", JPEG_CLK, NULL, OFF),
- CLK_PCOM("jpeg_pclk", JPEG_P_CLK, NULL, OFF),
- CLK_PCOM("lpa_codec_clk", LPA_CODEC_CLK, NULL, 0),
- CLK_PCOM("lpa_core_clk", LPA_CORE_CLK, NULL, 0),
- CLK_PCOM("lpa_pclk", LPA_P_CLK, NULL, 0),
- CLK_PCOM("mdc_clk", MDC_CLK, NULL, 0),
- CLK_PCOM("mddi_clk", PMDH_CLK, NULL, OFF | CLK_MINMAX),
- CLK_PCOM("mddi_pclk", PMDH_P_CLK, NULL, 0),
- CLK_PCOM("mdp_clk", MDP_CLK, NULL, OFF),
- CLK_PCOM("mdp_pclk", MDP_P_CLK, NULL, 0),
- CLK_PCOM("mdp_lcdc_pclk_clk", MDP_LCDC_PCLK_CLK, NULL, 0),
- CLK_PCOM("mdp_lcdc_pad_pclk_clk", MDP_LCDC_PAD_PCLK_CLK, NULL, 0),
- CLK_PCOM("mdp_vsync_clk", MDP_VSYNC_CLK, NULL, 0),
- CLK_PCOM("mfc_clk", MFC_CLK, NULL, 0),
- CLK_PCOM("mfc_div2_clk", MFC_DIV2_CLK, NULL, 0),
- CLK_PCOM("mfc_pclk", MFC_P_CLK, NULL, 0),
- CLK_PCOM("mi2s_m_clk", MI2S_M_CLK, NULL, 0),
- CLK_PCOM("mi2s_s_clk", MI2S_S_CLK, NULL, 0),
- CLK_PCOM("mi2s_codec_rx_m_clk", MI2S_CODEC_RX_M_CLK, NULL, 0),
- CLK_PCOM("mi2s_codec_rx_s_clk", MI2S_CODEC_RX_S_CLK, NULL, 0),
- CLK_PCOM("mi2s_codec_tx_m_clk", MI2S_CODEC_TX_M_CLK, NULL, 0),
- CLK_PCOM("mi2s_codec_tx_s_clk", MI2S_CODEC_TX_S_CLK, NULL, 0),
- CLK_PCOM("pbus_clk", PBUS_CLK, NULL, CLK_MIN),
- CLK_PCOM("pcm_clk", PCM_CLK, NULL, 0),
- CLK_PCOM("rotator_clk", AXI_ROTATOR_CLK, NULL, 0),
- CLK_PCOM("rotator_imem_clk", ROTATOR_IMEM_CLK, NULL, OFF),
- CLK_PCOM("rotator_pclk", ROTATOR_P_CLK, NULL, OFF),
- CLK_PCOM("sdac_clk", SDAC_CLK, NULL, OFF),
- CLK_PCOM("spi_clk", SPI_CLK, NULL, 0),
- CLK_PCOM("spi_pclk", SPI_P_CLK, NULL, 0),
- CLK_7X30S("tv_src_clk", TV_CLK, TV_ENC_CLK, NULL, 0),
- CLK_PCOM("tv_dac_clk", TV_DAC_CLK, NULL, 0),
- CLK_PCOM("tv_enc_clk", TV_ENC_CLK, NULL, 0),
- CLK_PCOM("uart_clk", UART2_CLK, &msm_device_uart2.dev, 0),
- CLK_PCOM("usb_hs_clk", USB_HS_CLK, NULL, OFF),
- CLK_PCOM("usb_hs_pclk", USB_HS_P_CLK, NULL, OFF),
- CLK_PCOM("usb_hs_core_clk", USB_HS_CORE_CLK, NULL, OFF),
- CLK_PCOM("usb_hs2_clk", USB_HS2_CLK, NULL, OFF),
- CLK_PCOM("usb_hs2_pclk", USB_HS2_P_CLK, NULL, OFF),
- CLK_PCOM("usb_hs2_core_clk", USB_HS2_CORE_CLK, NULL, OFF),
- CLK_PCOM("usb_hs3_clk", USB_HS3_CLK, NULL, OFF),
- CLK_PCOM("usb_hs3_pclk", USB_HS3_P_CLK, NULL, OFF),
- CLK_PCOM("usb_hs3_core_clk", USB_HS3_CORE_CLK, NULL, OFF),
+ CLK_PCOM("uart_clk", UART3_CLK, NULL, OFF),
+ CLK_PCOM("usb_phy_clk", USB_PHY_CLK, NULL, 0),
CLK_PCOM("vdc_clk", VDC_CLK, NULL, OFF | CLK_MIN),
- CLK_PCOM("vfe_camif_clk", VFE_CAMIF_CLK, NULL, 0),
- CLK_PCOM("vfe_clk", VFE_CLK, NULL, 0),
- CLK_PCOM("vfe_mdc_clk", VFE_MDC_CLK, NULL, 0),
- CLK_PCOM("vfe_pclk", VFE_P_CLK, NULL, OFF),
- CLK_PCOM("vpe_clk", VPE_CLK, NULL, 0),
+ CLK_PCOM("pbus_clk", PBUS_CLK, NULL, CLK_MIN),
+
+ CLK_7X30("adm_clk", ADM_CLK, NULL, 0),
+ CLK_7X30L("adm_pclk", ADM_P_CLK, NULL, 0),
+ CLK_7X30("cam_m_clk", CAM_M_CLK, NULL, 0),
+ CLK_7X30("camif_pad_pclk", CAMIF_PAD_P_CLK, NULL, OFF),
+ CLK_7X30("ce_clk", CE_CLK, NULL, 0),
+ CLK_7X30("emdh_clk", EMDH_CLK, NULL, OFF | CLK_MINMAX),
+ CLK_7X30("emdh_pclk", EMDH_P_CLK, NULL, OFF),
+ CLK_7X30("grp_2d_clk", GRP_2D_CLK, NULL, 0),
+ CLK_7X30("grp_2d_pclk", GRP_2D_P_CLK, NULL, 0),
+ CLK_7X30("grp_clk", GRP_3D_CLK, NULL, 0),
+ CLK_7X30("grp_pclk", GRP_3D_P_CLK, NULL, 0),
+ CLK_7X30S("grp_src_clk", GRP_3D_SRC_CLK, GRP_3D_CLK, NULL, 0),
+ CLK_7X30("hdmi_clk", HDMI_CLK, NULL, 0),
+ CLK_7X30("i2c_clk", I2C_CLK, NULL, 0),
+ CLK_7X30("i2c_clk", I2C_2_CLK, NULL, 0),
+ CLK_7X30("imem_clk", IMEM_CLK, NULL, OFF),
+ CLK_7X30("jpeg_clk", JPEG_CLK, NULL, OFF),
+ CLK_7X30("jpeg_pclk", JPEG_P_CLK, NULL, OFF),
+ CLK_7X30("lpa_codec_clk", LPA_CODEC_CLK, NULL, 0),
+ CLK_7X30("lpa_core_clk", LPA_CORE_CLK, NULL, 0),
+ CLK_7X30("lpa_pclk", LPA_P_CLK, NULL, 0),
+ CLK_7X30("mdc_clk", MDC_CLK, NULL, 0),
+ CLK_7X30("mddi_clk", PMDH_CLK, NULL, OFF | CLK_MINMAX),
+ CLK_7X30("mddi_pclk", PMDH_P_CLK, NULL, 0),
+ CLK_7X30("mdp_clk", MDP_CLK, NULL, OFF),
+ CLK_7X30("mdp_pclk", MDP_P_CLK, NULL, 0),
+ CLK_7X30("mdp_lcdc_pclk_clk", MDP_LCDC_PCLK_CLK, NULL, 0),
+ CLK_7X30("mdp_lcdc_pad_pclk_clk", MDP_LCDC_PAD_PCLK_CLK, NULL, 0),
+ CLK_7X30("mdp_vsync_clk", MDP_VSYNC_CLK, NULL, OFF),
+ CLK_7X30("mfc_clk", MFC_CLK, NULL, 0),
+ CLK_7X30("mfc_div2_clk", MFC_DIV2_CLK, NULL, 0),
+ CLK_7X30("mfc_pclk", MFC_P_CLK, NULL, 0),
+ CLK_7X30("mi2s_codec_rx_m_clk", MI2S_CODEC_RX_M_CLK, NULL, 0),
+ CLK_7X30("mi2s_codec_rx_s_clk", MI2S_CODEC_RX_S_CLK, NULL, 0),
+ CLK_7X30("mi2s_codec_tx_m_clk", MI2S_CODEC_TX_M_CLK, NULL, 0),
+ CLK_7X30("mi2s_codec_tx_s_clk", MI2S_CODEC_TX_S_CLK, NULL, 0),
+ CLK_7X30("mi2s_m_clk", MI2S_M_CLK, NULL, 0),
+ CLK_7X30("mi2s_s_clk", MI2S_S_CLK, NULL, 0),
+ CLK_7X30("qup_clk", QUP_I2C_CLK, NULL, 0),
+ CLK_7X30("rotator_clk", AXI_ROTATOR_CLK, NULL, 0),
+ CLK_7X30("rotator_imem_clk", ROTATOR_IMEM_CLK, NULL, OFF),
+ CLK_7X30("rotator_pclk", ROTATOR_P_CLK, NULL, OFF),
+ CLK_7X30("sdac_clk", SDAC_CLK, NULL, OFF),
+ CLK_7X30("sdc_clk", SDC1_CLK, NULL, OFF),
+ CLK_7X30("sdc_pclk", SDC1_P_CLK, NULL, OFF),
+ CLK_7X30("sdc_clk", SDC2_CLK, NULL, OFF),
+ CLK_7X30("sdc_pclk", SDC2_P_CLK, NULL, OFF),
+ CLK_7X30("sdc_clk", SDC3_CLK, NULL, OFF),
+ CLK_7X30("sdc_pclk", SDC3_P_CLK, NULL, OFF),
+ CLK_7X30("sdc_clk", SDC4_CLK, NULL, OFF),
+ CLK_7X30("sdc_pclk", SDC4_P_CLK, NULL, OFF),
+ CLK_7X30("spi_clk", SPI_CLK, NULL, 0),
+ CLK_7X30("spi_pclk", SPI_P_CLK, NULL, 0),
+ CLK_7X30("tsif_ref_clk", TSIF_REF_CLK, NULL, 0),
+ CLK_7X30("tsif_pclk", TSIF_P_CLK, NULL, 0),
+ CLK_7X30("tv_dac_clk", TV_DAC_CLK, NULL, 0),
+ CLK_7X30("tv_enc_clk", TV_ENC_CLK, NULL, 0),
+ CLK_7X30S("tv_src_clk", TV_CLK, TV_ENC_CLK, NULL, 0),
+ CLK_7X30("uart_clk", UART1_CLK, NULL, OFF),
+ CLK_7X30("uart_clk", UART2_CLK, &msm_device_uart2.dev, 0),
+ CLK_7X30("uartdm_clk", UART1DM_CLK, NULL, OFF),
+ CLK_7X30L("uartdm_pclk", UART1DM_P_CLK, NULL, 0),
+ CLK_7X30("uartdm_clk", UART2DM_CLK, NULL, 0),
+ CLK_7X30L("uartdm_pclk", UART2DM_P_CLK, NULL, 0),
+ CLK_7X30("usb_hs_clk", USB_HS_CLK, NULL, OFF),
+ CLK_7X30("usb_hs_pclk", USB_HS_P_CLK, NULL, OFF),
+ CLK_7X30("usb_hs_core_clk", USB_HS_CORE_CLK, NULL, OFF),
+ CLK_7X30("usb_hs2_clk", USB_HS2_CLK, NULL, OFF),
+ CLK_7X30("usb_hs2_pclk", USB_HS2_P_CLK, NULL, OFF),
+ CLK_7X30("usb_hs2_core_clk", USB_HS2_CORE_CLK, NULL, OFF),
+ CLK_7X30("usb_hs3_clk", USB_HS3_CLK, NULL, OFF),
+ CLK_7X30("usb_hs3_pclk", USB_HS3_P_CLK, NULL, OFF),
+ CLK_7X30("usb_hs3_core_clk", USB_HS3_CORE_CLK, NULL, OFF),
+ CLK_7X30("vfe_camif_clk", VFE_CAMIF_CLK, NULL, 0),
+ CLK_7X30("vfe_clk", VFE_CLK, NULL, 0),
+ CLK_7X30("vfe_mdc_clk", VFE_MDC_CLK, NULL, 0),
+ CLK_7X30("vfe_pclk", VFE_P_CLK, NULL, OFF),
+ CLK_7X30("vpe_clk", VPE_CLK, NULL, 0),
/* 7x30 v2 hardware only. */
- CLK_PCOM("csi_clk", CSI0_CLK, NULL, 0),
- CLK_PCOM("csi_pclk", CSI0_P_CLK, NULL, 0),
- CLK_PCOM("csi_vfe_clk", CSI0_VFE_CLK, NULL, 0),
+ CLK_7X30("csi_clk", CSI0_CLK, NULL, 0),
+ CLK_7X30("csi_pclk", CSI0_P_CLK, NULL, 0),
+ CLK_7X30("csi_vfe_clk", CSI0_VFE_CLK, NULL, 0),
};
unsigned msm_num_clocks_7x30 = ARRAY_SIZE(msm_clocks_7x30);
--
Sent by an employee of the Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum.
^ permalink raw reply related [flat|nested] 23+ messages in thread* [PATCH 07/22] msm: clock: Refactor clock-7x30 into generic clock-local driver
2010-12-17 0:49 [PATCH 00/22] MSM clock driver updates Stephen Boyd
` (5 preceding siblings ...)
2010-12-17 0:49 ` [PATCH 06/22] msm: clock-7x30: Update clock table Stephen Boyd
@ 2010-12-17 0:49 ` Stephen Boyd
2010-12-17 0:49 ` [PATCH 08/22] msm: clock-8x60: Add msm8x60 local clock driver Stephen Boyd
` (14 subsequent siblings)
21 siblings, 0 replies; 23+ messages in thread
From: Stephen Boyd @ 2010-12-17 0:49 UTC (permalink / raw)
To: linux-arm-kernel
From: Matt Wagantall <mattw@codeaurora.org>
The generic 'clock-local' driver is introduced to facilitate
sharing of common code among local clock drivers for different
SoCs. Presently, only 7x30 makes use of this driver.
SoC-independent code is implemented in clock-local.c, while
SoC-specific code is implemented in other clock-* files (ex.
clock-7x30.c).
Reviewed-by: Saravana Kannan <skannan@codeaurora.org>
Signed-off-by: Matt Wagantall <mattw@codeaurora.org>
Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
---
arch/arm/mach-msm/Makefile | 1 +
arch/arm/mach-msm/clock-7x30.c | 1462 +++++++++++++--------------------------
arch/arm/mach-msm/clock-7x30.h | 230 +++----
arch/arm/mach-msm/clock-local.c | 679 ++++++++++++++++++
arch/arm/mach-msm/clock-local.h | 232 +++++++
5 files changed, 1516 insertions(+), 1088 deletions(-)
create mode 100644 arch/arm/mach-msm/clock-local.c
create mode 100644 arch/arm/mach-msm/clock-local.h
diff --git a/arch/arm/mach-msm/Makefile b/arch/arm/mach-msm/Makefile
index 8588b57..33f0c39 100644
--- a/arch/arm/mach-msm/Makefile
+++ b/arch/arm/mach-msm/Makefile
@@ -2,6 +2,7 @@ obj-y += io.o idle.o timer.o
ifdef CONFIG_MSM_PROC_COMM
obj-$(CONFIG_DEBUG_FS) += clock-debug.o
endif
+obj-$(CONFIG_ARCH_MSM7X30) += clock-local.o
obj-$(CONFIG_ARCH_MSM7X30) += clock-7x30.o
ifndef CONFIG_ARCH_MSM8X60
obj-y += acpuclock-arm11.o
diff --git a/arch/arm/mach-msm/clock-7x30.c b/arch/arm/mach-msm/clock-7x30.c
index beca3a6..0637bee 100644
--- a/arch/arm/mach-msm/clock-7x30.c
+++ b/arch/arm/mach-msm/clock-7x30.c
@@ -29,16 +29,13 @@
#include <mach/clk.h>
#include "clock.h"
+#include "clock-local.h"
#include "clock-7x30.h"
#include "clock-pcom.h"
#include "proc_comm.h"
-#define REG_BASE(off) (MSM_CLK_CTL_BASE + off)
-#define REG(off) (MSM_CLK_CTL_SH2_BASE + off)
-#define MNCNTR_EN_MASK B(8)
-#define MNCNTR_RST_MASK B(7)
-#define MNCNTR_MODE_MASK BM(6, 5)
-#define MNCNTR_MODE BVAL(6, 5, 0x2) /* Dual-edge mode. */
+#define REG_BASE(off) (MSM_CLK_CTL_BASE + (off))
+#define REG(off) (MSM_CLK_CTL_SH2_BASE + (off))
/* Shadow-region 2 (SH2) registers. */
#define QUP_I2C_NS_REG REG(0x04F0)
@@ -106,1142 +103,597 @@
#define SH2_OWN_ROW1_BASE_REG REG_BASE(0x041C)
#define SH2_OWN_ROW2_BASE_REG REG_BASE(0x0424)
-struct clk_freq_tbl {
- uint32_t freq_hz;
- uint32_t src;
- uint32_t md_val;
- uint32_t ns_val;
- uint32_t mode;
- unsigned msmc1;
-};
-
-struct clk_local {
- uint32_t count;
- uint32_t type;
- void __iomem *md_reg;
- void __iomem *ns_reg;
- uint32_t freq_mask;
- uint32_t br_en_mask;
- uint32_t root_en_mask;
- int parent;
- uint32_t *children;
- const struct clk_freq_tbl *freq_tbl;
- const struct clk_freq_tbl *current_freq;
- void __iomem *halt_reg;
- uint32_t halt_mask;
- uint32_t test_vector;
-};
-
-
-enum {
- SRC_PLL0 = 4, /* Modem PLL */
- SRC_PLL1 = 1, /* Global PLL */
- SRC_PLL3 = 3, /* Multimedia/Peripheral PLL or Backup PLL1 */
- SRC_PLL4 = 2, /* Display PLL */
- SRC_LPXO = 6, /* Low power XO. */
- SRC_TCXO = 0, /* Used for sources that always source from tcxo */
- SRC_AXI = 100, /* Used for rates that sync to AXI */
- SRC_NONE /* Used for sources that can't be turned on/off. */
-};
-
-static uint32_t src_pll_tbl[] = {
- [SRC_PLL0] = PLL_0,
- [SRC_PLL1] = PLL_1,
- [SRC_PLL3] = PLL_3,
- [SRC_PLL4] = PLL_4,
-};
-
-#define B(x) BIT(x)
-#define BM(msb, lsb) (((((uint32_t)-1) << (31-msb)) >> (31-msb+lsb)) << lsb)
-#define BVAL(msb, lsb, val) (((val) << lsb) & BM(msb, lsb))
+/* MUX source input identifiers. */
+#define SRC_SEL_PLL0 4 /* Modem PLL */
+#define SRC_SEL_PLL1 1 /* Global PLL */
+#define SRC_SEL_PLL3 3 /* Multimedia/Peripheral PLL or Backup PLL1 */
+#define SRC_SEL_PLL4 2 /* Display PLL */
+#define SRC_SEL_LPXO 6 /* Low-power XO */
+#define SRC_SEL_TCXO 0 /* Used for sources that always source from TCXO */
+#define SRC_SEL_AXI 0 /* Used for rates that sync to AXI */
+
+/* Source name to PLL mappings. */
+#define SRC_PLL0 PLL_0
+#define SRC_PLL1 PLL_1
+#define SRC_PLL3 PLL_3
+#define SRC_PLL4 PLL_4
+#define SRC_LPXO LPXO
+#define SRC_TCXO TCXO
+#define SRC_AXI AXI
+
+/* Clock declaration macros. */
+#define MN_MODE_DUAL_EDGE 0x2
#define MD8(m, n) (BVAL(15, 8, m) | BVAL(7, 0, ~(n)))
-#define N8(msb, lsb, m, n) (BVAL(msb, lsb, ~(n-m)))
+#define N8(msb, lsb, m, n) (BVAL(msb, lsb, ~(n-m)) | BVAL(6, 5, \
+ (MN_MODE_DUAL_EDGE * !!(n))))
#define MD16(m, n) (BVAL(31, 16, m) | BVAL(15, 0, ~(n)))
-#define N16(m, n) (BVAL(31, 16, ~(n-m)))
+#define N16(m, n) (BVAL(31, 16, ~(n-m)) | BVAL(6, 5, \
+ (MN_MODE_DUAL_EDGE * !!(n))))
#define SPDIV(s, d) (BVAL(4, 3, d-1) | BVAL(2, 0, s))
#define SDIV(s, d) (BVAL(6, 3, d-1) | BVAL(2, 0, s))
#define F_MASK_BASIC (BM(6, 3)|BM(2, 0))
-#define F_MASK_MND16 (BM(31, 16)|BM(4, 3)|BM(2, 0))
-#define F_MASK_MND8(m, l) (BM(m, l)|BM(4, 3)|BM(2, 0))
-
-#define F_RAW(f, s, m_v, n_v, mde, v) { \
- .freq_hz = f, \
- .src = s, \
- .md_val = m_v, \
- .ns_val = n_v, \
- .mode = mde, \
- .msmc1 = v \
- }
+#define F_MASK_MND16 (BM(31, 16)|BM(6, 5)|BM(4, 3)|BM(2, 0))
+#define F_MASK_MND8(m, l) (BM(m, l)|BM(6, 5)|BM(4, 3)|BM(2, 0))
-#define FREQ_END 0
-#define F_BASIC(f, s, div, v) F_RAW(f, s, 0, SDIV(s, div), 0, v)
+/*
+ * Clock frequency definitions and macros
+ */
+#define F_BASIC(f, s, div, v) \
+ F_RAW(f, SRC_##s, 0, SDIV(SRC_SEL_##s, div), 0, 0, v, NULL)
#define F_MND16(f, s, div, m, n, v) \
- F_RAW(f, s, MD16(m, n), N16(m, n)|SPDIV(s, div), !!(n), v)
+ F_RAW(f, SRC_##s, MD16(m, n), N16(m, n)|SPDIV(SRC_SEL_##s, div), \
+ 0, (B(8) * !!(n)), v, NULL)
#define F_MND8(f, nmsb, nlsb, s, div, m, n, v) \
- F_RAW(f, s, MD8(m, n), N8(nmsb, nlsb, m, n)|SPDIV(s, div), !!(n), v)
-#define F_END F_RAW(FREQ_END, SRC_NONE, 0, 0, 0, MSMC1_END)
-
-static const struct clk_freq_tbl clk_tbl_csi[] = {
- F_MND8(153600000, 24, 17, SRC_PLL1, 2, 2, 5, NOMINAL),
- F_MND8(192000000, 24, 17, SRC_PLL1, 4, 0, 0, NOMINAL),
- F_MND8(384000000, 24, 17, SRC_PLL1, 2, 0, 0, NOMINAL),
+ F_RAW(f, SRC_##s, MD8(m, n), \
+ N8(nmsb, nlsb, m, n)|SPDIV(SRC_SEL_##s, div), 0, \
+ (B(8) * !!(n)), v, NULL)
+
+static struct clk_freq_tbl clk_tbl_csi[] = {
+ F_MND8(153600000, 24, 17, PLL1, 2, 2, 5, NOMINAL),
+ F_MND8(192000000, 24, 17, PLL1, 4, 0, 0, NOMINAL),
+ F_MND8(384000000, 24, 17, PLL1, 2, 0, 0, NOMINAL),
F_END,
};
-static const struct clk_freq_tbl clk_tbl_tcxo[] = {
- F_RAW(19200000, SRC_TCXO, 0, 0, 0, NOMINAL),
+static struct clk_freq_tbl clk_tbl_tcxo[] = {
+ F_RAW(19200000, SRC_TCXO, 0, 0, 0, 0, NOMINAL, NULL),
F_END,
};
-static const struct clk_freq_tbl clk_tbl_axi[] = {
- F_RAW(1, SRC_AXI, 0, 0, 0, NOMINAL),
+static struct clk_freq_tbl clk_tbl_axi[] = {
+ F_RAW(1, SRC_AXI, 0, 0, 0, 0, NOMINAL, NULL),
F_END,
};
-static const struct clk_freq_tbl clk_tbl_uartdm[] = {
- F_MND16( 3686400, SRC_PLL3, 3, 3, 200, NOMINAL),
- F_MND16( 7372800, SRC_PLL3, 3, 3, 100, NOMINAL),
- F_MND16(14745600, SRC_PLL3, 3, 3, 50, NOMINAL),
- F_MND16(32000000, SRC_PLL3, 3, 25, 192, NOMINAL),
- F_MND16(40000000, SRC_PLL3, 3, 125, 768, NOMINAL),
- F_MND16(46400000, SRC_PLL3, 3, 145, 768, NOMINAL),
- F_MND16(48000000, SRC_PLL3, 3, 25, 128, NOMINAL),
- F_MND16(51200000, SRC_PLL3, 3, 5, 24, NOMINAL),
- F_MND16(56000000, SRC_PLL3, 3, 175, 768, NOMINAL),
- F_MND16(58982400, SRC_PLL3, 3, 6, 25, NOMINAL),
- F_MND16(64000000, SRC_PLL1, 4, 1, 3, NOMINAL),
+static struct clk_freq_tbl clk_tbl_uartdm[] = {
+ F_MND16( 3686400, PLL3, 3, 3, 200, NOMINAL),
+ F_MND16( 7372800, PLL3, 3, 3, 100, NOMINAL),
+ F_MND16(14745600, PLL3, 3, 3, 50, NOMINAL),
+ F_MND16(32000000, PLL3, 3, 25, 192, NOMINAL),
+ F_MND16(40000000, PLL3, 3, 125, 768, NOMINAL),
+ F_MND16(46400000, PLL3, 3, 145, 768, NOMINAL),
+ F_MND16(48000000, PLL3, 3, 25, 128, NOMINAL),
+ F_MND16(51200000, PLL3, 3, 5, 24, NOMINAL),
+ F_MND16(56000000, PLL3, 3, 175, 768, NOMINAL),
+ F_MND16(58982400, PLL3, 3, 6, 25, NOMINAL),
+ F_MND16(64000000, PLL1, 4, 1, 3, NOMINAL),
F_END,
};
-static const struct clk_freq_tbl clk_tbl_mdh[] = {
- F_BASIC( 49150000, SRC_PLL3, 15, NOMINAL),
- F_BASIC( 92160000, SRC_PLL3, 8, NOMINAL),
- F_BASIC(122880000, SRC_PLL3, 6, NOMINAL),
- F_BASIC(184320000, SRC_PLL3, 4, NOMINAL),
- F_BASIC(245760000, SRC_PLL3, 3, NOMINAL),
- F_BASIC(368640000, SRC_PLL3, 2, NOMINAL),
- F_BASIC(384000000, SRC_PLL1, 2, NOMINAL),
- F_BASIC(445500000, SRC_PLL4, 2, NOMINAL),
+static struct clk_freq_tbl clk_tbl_mdh[] = {
+ F_BASIC( 49150000, PLL3, 15, NOMINAL),
+ F_BASIC( 92160000, PLL3, 8, NOMINAL),
+ F_BASIC(122880000, PLL3, 6, NOMINAL),
+ F_BASIC(184320000, PLL3, 4, NOMINAL),
+ F_BASIC(245760000, PLL3, 3, NOMINAL),
+ F_BASIC(368640000, PLL3, 2, NOMINAL),
+ F_BASIC(384000000, PLL1, 2, NOMINAL),
+ F_BASIC(445500000, PLL4, 2, NOMINAL),
F_END,
};
-static const struct clk_freq_tbl clk_tbl_grp[] = {
- F_BASIC( 24576000, SRC_LPXO, 1, NOMINAL),
- F_BASIC( 46080000, SRC_PLL3, 16, NOMINAL),
- F_BASIC( 49152000, SRC_PLL3, 15, NOMINAL),
- F_BASIC( 52662875, SRC_PLL3, 14, NOMINAL),
- F_BASIC( 56713846, SRC_PLL3, 13, NOMINAL),
- F_BASIC( 61440000, SRC_PLL3, 12, NOMINAL),
- F_BASIC( 67025454, SRC_PLL3, 11, NOMINAL),
- F_BASIC( 73728000, SRC_PLL3, 10, NOMINAL),
- F_BASIC( 81920000, SRC_PLL3, 9, NOMINAL),
- F_BASIC( 92160000, SRC_PLL3, 8, NOMINAL),
- F_BASIC(105325714, SRC_PLL3, 7, NOMINAL),
- F_BASIC(122880000, SRC_PLL3, 6, NOMINAL),
- F_BASIC(147456000, SRC_PLL3, 5, NOMINAL),
- F_BASIC(184320000, SRC_PLL3, 4, NOMINAL),
- F_BASIC(192000000, SRC_PLL1, 4, NOMINAL),
- F_BASIC(245760000, SRC_PLL3, 3, HIGH),
+static struct clk_freq_tbl clk_tbl_grp[] = {
+ F_BASIC( 24576000, LPXO, 1, NOMINAL),
+ F_BASIC( 46080000, PLL3, 16, NOMINAL),
+ F_BASIC( 49152000, PLL3, 15, NOMINAL),
+ F_BASIC( 52662875, PLL3, 14, NOMINAL),
+ F_BASIC( 56713846, PLL3, 13, NOMINAL),
+ F_BASIC( 61440000, PLL3, 12, NOMINAL),
+ F_BASIC( 67025454, PLL3, 11, NOMINAL),
+ F_BASIC( 73728000, PLL3, 10, NOMINAL),
+ F_BASIC( 81920000, PLL3, 9, NOMINAL),
+ F_BASIC( 92160000, PLL3, 8, NOMINAL),
+ F_BASIC(105325714, PLL3, 7, NOMINAL),
+ F_BASIC(122880000, PLL3, 6, NOMINAL),
+ F_BASIC(147456000, PLL3, 5, NOMINAL),
+ F_BASIC(184320000, PLL3, 4, NOMINAL),
+ F_BASIC(192000000, PLL1, 4, NOMINAL),
+ F_BASIC(245760000, PLL3, 3, HIGH),
/* Sync to AXI. Hence this "rate" is not fixed. */
- F_RAW(1, SRC_AXI, 0, B(14), 0, NOMINAL),
+ F_RAW(1, SRC_AXI, 0, B(14), 0, 0, NOMINAL, NULL),
F_END,
};
-static const struct clk_freq_tbl clk_tbl_sdc1_3[] = {
- F_MND8( 144000, 19, 12, SRC_LPXO, 1, 1, 171, NOMINAL),
- F_MND8( 400000, 19, 12, SRC_LPXO, 1, 2, 123, NOMINAL),
- F_MND8(16027000, 19, 12, SRC_PLL3, 3, 14, 215, NOMINAL),
- F_MND8(17000000, 19, 12, SRC_PLL3, 4, 19, 206, NOMINAL),
- F_MND8(20480000, 19, 12, SRC_PLL3, 4, 23, 212, NOMINAL),
- F_MND8(24576000, 19, 12, SRC_LPXO, 1, 0, 0, NOMINAL),
- F_MND8(49152000, 19, 12, SRC_PLL3, 3, 1, 5, NOMINAL),
+static struct clk_freq_tbl clk_tbl_sdc1_3[] = {
+ F_MND8( 144000, 19, 12, LPXO, 1, 1, 171, NOMINAL),
+ F_MND8( 400000, 19, 12, LPXO, 1, 2, 123, NOMINAL),
+ F_MND8(16027000, 19, 12, PLL3, 3, 14, 215, NOMINAL),
+ F_MND8(17000000, 19, 12, PLL3, 4, 19, 206, NOMINAL),
+ F_MND8(20480000, 19, 12, PLL3, 4, 23, 212, NOMINAL),
+ F_MND8(24576000, 19, 12, LPXO, 1, 0, 0, NOMINAL),
+ F_MND8(49152000, 19, 12, PLL3, 3, 1, 5, NOMINAL),
F_END,
};
-static const struct clk_freq_tbl clk_tbl_sdc2_4[] = {
- F_MND8( 144000, 20, 13, SRC_LPXO, 1, 1, 171, NOMINAL),
- F_MND8( 400000, 20, 13, SRC_LPXO, 1, 2, 123, NOMINAL),
- F_MND8(16027000, 20, 13, SRC_PLL3, 3, 14, 215, NOMINAL),
- F_MND8(17000000, 20, 13, SRC_PLL3, 4, 19, 206, NOMINAL),
- F_MND8(20480000, 20, 13, SRC_PLL3, 4, 23, 212, NOMINAL),
- F_MND8(24576000, 20, 13, SRC_LPXO, 1, 0, 0, NOMINAL),
- F_MND8(49152000, 20, 13, SRC_PLL3, 3, 1, 5, NOMINAL),
+static struct clk_freq_tbl clk_tbl_sdc2_4[] = {
+ F_MND8( 144000, 20, 13, LPXO, 1, 1, 171, NOMINAL),
+ F_MND8( 400000, 20, 13, LPXO, 1, 2, 123, NOMINAL),
+ F_MND8(16027000, 20, 13, PLL3, 3, 14, 215, NOMINAL),
+ F_MND8(17000000, 20, 13, PLL3, 4, 19, 206, NOMINAL),
+ F_MND8(20480000, 20, 13, PLL3, 4, 23, 212, NOMINAL),
+ F_MND8(24576000, 20, 13, LPXO, 1, 0, 0, NOMINAL),
+ F_MND8(49152000, 20, 13, PLL3, 3, 1, 5, NOMINAL),
F_END,
};
-static const struct clk_freq_tbl clk_tbl_mdp_core[] = {
- F_BASIC( 46080000, SRC_PLL3, 16, NOMINAL),
- F_BASIC( 49152000, SRC_PLL3, 15, NOMINAL),
- F_BASIC( 52663000, SRC_PLL3, 14, NOMINAL),
- F_BASIC( 92160000, SRC_PLL3, 8, NOMINAL),
- F_BASIC(122880000, SRC_PLL3, 6, NOMINAL),
- F_BASIC(147456000, SRC_PLL3, 5, NOMINAL),
- F_BASIC(153600000, SRC_PLL1, 5, NOMINAL),
- F_BASIC(192000000, SRC_PLL1, 4, HIGH),
+static struct clk_freq_tbl clk_tbl_mdp_core[] = {
+ F_BASIC( 46080000, PLL3, 16, NOMINAL),
+ F_BASIC( 49152000, PLL3, 15, NOMINAL),
+ F_BASIC( 52663000, PLL3, 14, NOMINAL),
+ F_BASIC( 92160000, PLL3, 8, NOMINAL),
+ F_BASIC(122880000, PLL3, 6, NOMINAL),
+ F_BASIC(147456000, PLL3, 5, NOMINAL),
+ F_BASIC(153600000, PLL1, 5, NOMINAL),
+ F_BASIC(192000000, PLL1, 4, HIGH),
F_END,
};
-static const struct clk_freq_tbl clk_tbl_mdp_lcdc[] = {
- F_MND16(24576000, SRC_LPXO, 1, 0, 0, NOMINAL),
- F_MND16(30720000, SRC_PLL3, 4, 1, 6, NOMINAL),
- F_MND16(32768000, SRC_PLL3, 3, 2, 15, NOMINAL),
- F_MND16(40960000, SRC_PLL3, 2, 1, 9, NOMINAL),
- F_MND16(73728000, SRC_PLL3, 2, 1, 5, NOMINAL),
+static struct clk_freq_tbl clk_tbl_mdp_lcdc[] = {
+ F_MND16(24576000, LPXO, 1, 0, 0, NOMINAL),
+ F_MND16(30720000, PLL3, 4, 1, 6, NOMINAL),
+ F_MND16(32768000, PLL3, 3, 2, 15, NOMINAL),
+ F_MND16(40960000, PLL3, 2, 1, 9, NOMINAL),
+ F_MND16(73728000, PLL3, 2, 1, 5, NOMINAL),
F_END,
};
-static const struct clk_freq_tbl clk_tbl_mdp_vsync[] = {
- F_RAW(24576000, SRC_LPXO, 0, 0, 0, NOMINAL),
+static struct clk_freq_tbl clk_tbl_mdp_vsync[] = {
+ F_RAW(24576000, SRC_LPXO, 0, 0, 0, 0, NOMINAL, NULL),
F_END,
};
-static const struct clk_freq_tbl clk_tbl_mi2s_codec[] = {
- F_MND16( 2048000, SRC_LPXO, 4, 1, 3, NOMINAL),
- F_MND16(12288000, SRC_LPXO, 2, 0, 0, NOMINAL),
+static struct clk_freq_tbl clk_tbl_mi2s_codec[] = {
+ F_MND16( 2048000, LPXO, 4, 1, 3, NOMINAL),
+ F_MND16(12288000, LPXO, 2, 0, 0, NOMINAL),
F_END,
};
-static const struct clk_freq_tbl clk_tbl_mi2s[] = {
- F_MND16(12288000, SRC_LPXO, 2, 0, 0, NOMINAL),
+static struct clk_freq_tbl clk_tbl_mi2s[] = {
+ F_MND16(12288000, LPXO, 2, 0, 0, NOMINAL),
F_END,
};
-static const struct clk_freq_tbl clk_tbl_midi[] = {
- F_MND8(98304000, 19, 12, SRC_PLL3, 3, 2, 5, NOMINAL),
+static struct clk_freq_tbl clk_tbl_midi[] = {
+ F_MND8(98304000, 19, 12, PLL3, 3, 2, 5, NOMINAL),
F_END,
};
-static const struct clk_freq_tbl clk_tbl_sdac[] = {
- F_MND16( 256000, SRC_LPXO, 4, 1, 24, NOMINAL),
- F_MND16( 352800, SRC_LPXO, 1, 147, 10240, NOMINAL),
- F_MND16( 384000, SRC_LPXO, 4, 1, 16, NOMINAL),
- F_MND16( 512000, SRC_LPXO, 4, 1, 12, NOMINAL),
- F_MND16( 705600, SRC_LPXO, 1, 147, 5120, NOMINAL),
- F_MND16( 768000, SRC_LPXO, 4, 1, 8, NOMINAL),
- F_MND16(1024000, SRC_LPXO, 4, 1, 6, NOMINAL),
- F_MND16(1411200, SRC_LPXO, 1, 147, 2560, NOMINAL),
- F_MND16(1536000, SRC_LPXO, 4, 1, 4, NOMINAL),
+static struct clk_freq_tbl clk_tbl_sdac[] = {
+ F_MND16( 256000, LPXO, 4, 1, 24, NOMINAL),
+ F_MND16( 352800, LPXO, 1, 147, 10240, NOMINAL),
+ F_MND16( 384000, LPXO, 4, 1, 16, NOMINAL),
+ F_MND16( 512000, LPXO, 4, 1, 12, NOMINAL),
+ F_MND16( 705600, LPXO, 1, 147, 5120, NOMINAL),
+ F_MND16( 768000, LPXO, 4, 1, 8, NOMINAL),
+ F_MND16(1024000, LPXO, 4, 1, 6, NOMINAL),
+ F_MND16(1411200, LPXO, 1, 147, 2560, NOMINAL),
+ F_MND16(1536000, LPXO, 4, 1, 4, NOMINAL),
F_END,
};
-static const struct clk_freq_tbl clk_tbl_tv[] = {
- F_MND8(27000000, 23, 16, SRC_PLL4, 2, 2, 33, NOMINAL),
- F_MND8(74250000, 23, 16, SRC_PLL4, 2, 1, 6, NOMINAL),
+static struct clk_freq_tbl clk_tbl_tv[] = {
+ F_MND8(27000000, 23, 16, PLL4, 2, 2, 33, NOMINAL),
+ F_MND8(74250000, 23, 16, PLL4, 2, 1, 6, NOMINAL),
F_END,
};
-static const struct clk_freq_tbl clk_tbl_usb[] = {
- F_MND8(60000000, 23, 16, SRC_PLL1, 2, 5, 32, NOMINAL),
+static struct clk_freq_tbl clk_tbl_usb[] = {
+ F_MND8(60000000, 23, 16, PLL1, 2, 5, 32, NOMINAL),
F_END,
};
-static const struct clk_freq_tbl clk_tbl_vfe_jpeg[] = {
- F_MND16( 36864000, SRC_PLL3, 4, 1, 5, NOMINAL),
- F_MND16( 46080000, SRC_PLL3, 4, 1, 4, NOMINAL),
- F_MND16( 61440000, SRC_PLL3, 4, 1, 3, NOMINAL),
- F_MND16( 73728000, SRC_PLL3, 2, 1, 5, NOMINAL),
- F_MND16( 81920000, SRC_PLL3, 3, 1, 3, NOMINAL),
- F_MND16( 92160000, SRC_PLL3, 4, 1, 2, NOMINAL),
- F_MND16( 98304000, SRC_PLL3, 3, 2, 5, NOMINAL),
- F_MND16(105326000, SRC_PLL3, 2, 2, 7, NOMINAL),
- F_MND16(122880000, SRC_PLL3, 2, 1, 3, NOMINAL),
- F_MND16(147456000, SRC_PLL3, 2, 2, 5, NOMINAL),
- F_MND16(153600000, SRC_PLL1, 2, 2, 5, NOMINAL),
+static struct clk_freq_tbl clk_tbl_vfe_jpeg[] = {
+ F_MND16( 36864000, PLL3, 4, 1, 5, NOMINAL),
+ F_MND16( 46080000, PLL3, 4, 1, 4, NOMINAL),
+ F_MND16( 61440000, PLL3, 4, 1, 3, NOMINAL),
+ F_MND16( 73728000, PLL3, 2, 1, 5, NOMINAL),
+ F_MND16( 81920000, PLL3, 3, 1, 3, NOMINAL),
+ F_MND16( 92160000, PLL3, 4, 1, 2, NOMINAL),
+ F_MND16( 98304000, PLL3, 3, 2, 5, NOMINAL),
+ F_MND16(105326000, PLL3, 2, 2, 7, NOMINAL),
+ F_MND16(122880000, PLL3, 2, 1, 3, NOMINAL),
+ F_MND16(147456000, PLL3, 2, 2, 5, NOMINAL),
+ F_MND16(153600000, PLL1, 2, 2, 5, NOMINAL),
F_END,
};
-static const struct clk_freq_tbl clk_tbl_cam[] = {
- F_MND16( 6000000, SRC_PLL1, 4, 1, 32, NOMINAL),
- F_MND16( 8000000, SRC_PLL1, 4, 1, 24, NOMINAL),
- F_MND16(12000000, SRC_PLL1, 4, 1, 16, NOMINAL),
- F_MND16(16000000, SRC_PLL1, 4, 1, 12, NOMINAL),
- F_MND16(19200000, SRC_PLL1, 4, 1, 10, NOMINAL),
- F_MND16(24000000, SRC_PLL1, 4, 1, 8, NOMINAL),
- F_MND16(32000000, SRC_PLL1, 4, 1, 6, NOMINAL),
- F_MND16(48000000, SRC_PLL1, 4, 1, 4, NOMINAL),
- F_MND16(64000000, SRC_PLL1, 4, 1, 3, NOMINAL),
+static struct clk_freq_tbl clk_tbl_cam[] = {
+ F_MND16( 6000000, PLL1, 4, 1, 32, NOMINAL),
+ F_MND16( 8000000, PLL1, 4, 1, 24, NOMINAL),
+ F_MND16(12000000, PLL1, 4, 1, 16, NOMINAL),
+ F_MND16(16000000, PLL1, 4, 1, 12, NOMINAL),
+ F_MND16(19200000, PLL1, 4, 1, 10, NOMINAL),
+ F_MND16(24000000, PLL1, 4, 1, 8, NOMINAL),
+ F_MND16(32000000, PLL1, 4, 1, 6, NOMINAL),
+ F_MND16(48000000, PLL1, 4, 1, 4, NOMINAL),
+ F_MND16(64000000, PLL1, 4, 1, 3, NOMINAL),
F_END,
};
-static const struct clk_freq_tbl clk_tbl_vpe[] = {
- F_MND8( 24576000, 22, 15, SRC_LPXO, 1, 0, 0, NOMINAL),
- F_MND8( 30720000, 22, 15, SRC_PLL3, 4, 1, 6, NOMINAL),
- F_MND8( 61440000, 22, 15, SRC_PLL3, 4, 1, 3, NOMINAL),
- F_MND8( 81920000, 22, 15, SRC_PLL3, 3, 1, 3, NOMINAL),
- F_MND8(122880000, 22, 15, SRC_PLL3, 3, 1, 2, NOMINAL),
- F_MND8(147456000, 22, 15, SRC_PLL3, 1, 1, 5, NOMINAL),
- F_MND8(153600000, 22, 15, SRC_PLL1, 1, 1, 5, NOMINAL),
+static struct clk_freq_tbl clk_tbl_vpe[] = {
+ F_MND8( 24576000, 22, 15, LPXO, 1, 0, 0, NOMINAL),
+ F_MND8( 30720000, 22, 15, PLL3, 4, 1, 6, NOMINAL),
+ F_MND8( 61440000, 22, 15, PLL3, 4, 1, 3, NOMINAL),
+ F_MND8( 81920000, 22, 15, PLL3, 3, 1, 3, NOMINAL),
+ F_MND8(122880000, 22, 15, PLL3, 3, 1, 2, NOMINAL),
+ F_MND8(147456000, 22, 15, PLL3, 1, 1, 5, NOMINAL),
+ F_MND8(153600000, 22, 15, PLL1, 1, 1, 5, NOMINAL),
F_END,
};
-static const struct clk_freq_tbl clk_tbl_mfc[] = {
- F_MND8( 24576000, 24, 17, SRC_LPXO, 1, 0, 0, NOMINAL),
- F_MND8( 30720000, 24, 17, SRC_PLL3, 4, 1, 6, NOMINAL),
- F_MND8( 61440000, 24, 17, SRC_PLL3, 4, 1, 3, NOMINAL),
- F_MND8( 81920000, 24, 17, SRC_PLL3, 3, 1, 3, NOMINAL),
- F_MND8(122880000, 24, 17, SRC_PLL3, 3, 1, 2, NOMINAL),
- F_MND8(147456000, 24, 17, SRC_PLL3, 1, 1, 5, NOMINAL),
- F_MND8(153600000, 24, 17, SRC_PLL1, 1, 1, 5, NOMINAL),
- F_MND8(170667000, 24, 17, SRC_PLL1, 1, 2, 9, NOMINAL),
+static struct clk_freq_tbl clk_tbl_mfc[] = {
+ F_MND8( 24576000, 24, 17, LPXO, 1, 0, 0, NOMINAL),
+ F_MND8( 30720000, 24, 17, PLL3, 4, 1, 6, NOMINAL),
+ F_MND8( 61440000, 24, 17, PLL3, 4, 1, 3, NOMINAL),
+ F_MND8( 81920000, 24, 17, PLL3, 3, 1, 3, NOMINAL),
+ F_MND8(122880000, 24, 17, PLL3, 3, 1, 2, NOMINAL),
+ F_MND8(147456000, 24, 17, PLL3, 1, 1, 5, NOMINAL),
+ F_MND8(153600000, 24, 17, PLL1, 1, 1, 5, NOMINAL),
+ F_MND8(170667000, 24, 17, PLL1, 1, 2, 9, NOMINAL),
F_END,
};
-static const struct clk_freq_tbl clk_tbl_spi[] = {
- F_MND8( 9963243, 19, 12, SRC_PLL3, 4, 7, 129, NOMINAL),
- F_MND8(26331429, 19, 12, SRC_PLL3, 4, 34, 241, NOMINAL),
+static struct clk_freq_tbl clk_tbl_spi[] = {
+ F_MND8( 9963243, 19, 12, PLL3, 4, 7, 129, NOMINAL),
+ F_MND8(26331429, 19, 12, PLL3, 4, 34, 241, NOMINAL),
F_END,
};
-static const struct clk_freq_tbl clk_tbl_lpa_codec[] = {
- F_RAW(1, SRC_NONE, 0, 0, 0, MSMC1_END), /* src = MI2S_CODEC_RX */
- F_RAW(2, SRC_NONE, 0, 1, 0, MSMC1_END), /* src = ECODEC_CIF */
- F_RAW(3, SRC_NONE, 0, 2, 0, MSMC1_END), /* src = MI2S */
- F_RAW(4, SRC_NONE, 0, 3, 0, MSMC1_END), /* src = SDAC */
+static struct clk_freq_tbl clk_tbl_lpa_codec[] = {
+ F_RAW(1, SRC_NONE, 0, 0, 0, 0, LOW, NULL), /* src = MI2S_CODEC_RX */
+ F_RAW(2, SRC_NONE, 0, 1, 0, 0, LOW, NULL), /* src = ECODEC_CIF */
+ F_RAW(3, SRC_NONE, 0, 2, 0, 0, LOW, NULL), /* src = MI2S */
+ F_RAW(4, SRC_NONE, 0, 3, 0, 0, LOW, NULL), /* src = SDAC */
F_END,
};
-static struct clk_freq_tbl dummy_freq = F_END;
-
-#define MND 1 /* Integer predivider and fractional MN:D divider. */
-#define BASIC 2 /* Integer divider. */
-#define NORATE 3 /* Just on/off. */
-
-#define C(x) L_7X30_##x##_CLK
-
-#define CLK_LOCAL(id, t, md, ns, f_msk, br, root, tbl, \
- par, chld_lst, h, hm, tv) \
- [C(id)] = { \
- .type = t, \
- .md_reg = md, \
- .ns_reg = ns, \
- .freq_mask = f_msk, \
- .br_en_mask = br, \
- .root_en_mask = root, \
- .parent = C(par), \
- .children = chld_lst, \
- .freq_tbl = tbl, \
- .current_freq = &dummy_freq, \
- .halt_reg = h, \
- .halt_mask = hm, \
- .test_vector = tv, \
- }
-
-#define CLK_BASIC(id, ns, br, root, tbl, par, h, hm, tv) \
- CLK_LOCAL(id, BASIC, 0, ns, F_MASK_BASIC, br, root, tbl, \
- par, NULL, h, hm, tv)
-#define CLK_MND8_P(id, ns, m, l, br, root, tbl, par, chld_lst, h, hm, tv) \
- CLK_LOCAL(id, MND, (ns-4), ns, F_MASK_MND8(m, l), br, root, \
- tbl, par, chld_lst, h, hm, tv)
-#define CLK_MND8(id, ns, m, l, br, root, tbl, chld_lst, h, hm, tv) \
- CLK_MND8_P(id, ns, m, l, br, root, tbl, NONE, chld_lst, \
- h, hm, tv)
-#define CLK_MND16(id, ns, br, root, tbl, par, chld_lst, h, hm, tv) \
- CLK_LOCAL(id, MND, (ns-4), ns, F_MASK_MND16, br, root, tbl, \
- par, chld_lst, h, hm, tv)
-#define CLK_1RATE(id, ns, br, root, tbl, h, hm, tv) \
- CLK_LOCAL(id, BASIC, 0, ns, 0, br, root, tbl, NONE, NULL, \
- h, hm, tv)
-#define CLK_SLAVE(id, ns, br, par, h, hm, tv) \
- CLK_LOCAL(id, NORATE, 0, ns, 0, br, 0, NULL, par, NULL, \
- h, hm, tv)
-#define CLK_NORATE(id, ns, br, root, h, hm, tv) \
- CLK_LOCAL(id, NORATE, 0, ns, 0, br, root, NULL, NONE, NULL, \
- h, hm, tv)
-#define CLK_GLBL(id, glbl, br, h, hm, tv) \
- CLK_LOCAL(id, NORATE, 0, glbl, 0, br, 0, NULL, GLBL_ROOT, \
- NULL, h, hm, tv)
-#define CLK_BRIDGE(id, glbl, br, par, h, hm, tv) \
- CLK_LOCAL(id, NORATE, 0, glbl, 0, br, 0, NULL, par, NULL, \
- h, hm, tv)
-
-static uint32_t *pll_status_addr[NUM_PLL] = {
- [PLL_0] = PLL0_STATUS_BASE_REG,
- [PLL_1] = PLL1_STATUS_BASE_REG,
- [PLL_2] = PLL2_STATUS_BASE_REG,
- [PLL_3] = PLL3_STATUS_BASE_REG,
- [PLL_4] = PLL4_STATUS_BASE_REG,
- [PLL_5] = PLL5_STATUS_BASE_REG,
- [PLL_6] = PLL6_STATUS_BASE_REG,
-};
-
-static uint32_t pll_count[NUM_PLL];
-
-static uint32_t chld_grp_3d_src[] = {C(IMEM), C(GRP_3D), C(NONE)};
-static uint32_t chld_mdp_lcdc_p[] = {C(MDP_LCDC_PAD_PCLK), C(NONE)};
-static uint32_t chld_mfc[] = {C(MFC_DIV2), C(NONE)};
-static uint32_t chld_mi2s_codec_rx[] = {C(MI2S_CODEC_RX_S), C(NONE)};
-static uint32_t chld_mi2s_codec_tx[] = {C(MI2S_CODEC_TX_S), C(NONE)};
-static uint32_t chld_mi2s[] = {C(MI2S_S), C(NONE)};
-static uint32_t chld_sdac[] = {C(SDAC_M), C(NONE)};
-static uint32_t chld_tv[] = {C(TV_DAC), C(TV_ENC), C(TSIF_REF),
- C(HDMI), C(NONE)};
-static uint32_t chld_usb_src[] = {C(USB_HS), C(USB_HS_CORE),
+/*
+ * Clock children lists
+ */
+static const uint32_t chld_grp_3d_src[] = {C(IMEM), C(GRP_3D), C(NONE)};
+static const uint32_t chld_mdp_lcdc_p[] = {C(MDP_LCDC_PAD_PCLK), C(NONE)};
+static const uint32_t chld_mfc[] = {C(MFC_DIV2), C(NONE)};
+static const uint32_t chld_mi2s_codec_rx[] = {C(MI2S_CODEC_RX_S), C(NONE)};
+static const uint32_t chld_mi2s_codec_tx[] = {C(MI2S_CODEC_TX_S), C(NONE)};
+static const uint32_t chld_mi2s[] = {C(MI2S_S), C(NONE)};
+static const uint32_t chld_sdac[] = {C(SDAC_M), C(NONE)};
+static const uint32_t chld_tv[] = {C(TV_DAC), C(TV_ENC), C(HDMI),
+ C(TSIF_REF), C(NONE)};
+static const uint32_t chld_usb_src[] = {C(USB_HS), C(USB_HS_CORE),
C(USB_HS2), C(USB_HS2_CORE),
C(USB_HS3), C(USB_HS3_CORE),
C(NONE)};
-static uint32_t chld_vfe[] = {C(VFE_MDC), C(VFE_CAMIF), C(CSI0_VFE),
+static uint32_t const chld_vfe[] = {C(VFE_MDC), C(VFE_CAMIF), C(CSI0_VFE),
C(NONE)};
-static struct clk_local clk_local_tbl[] = {
+/*
+ * Clock declaration macros
+ */
+#define CLK_BASIC(id, ns, br, root, tbl, par, h_r, h_c, h_b, tv) \
+ CLK(id, BASIC, ns, ns, NULL, NULL, 0, h_r, h_c, \
+ h_b, br, root, F_MASK_BASIC, 0, set_rate_basic, tbl, \
+ NULL, par, NULL, tv)
+#define CLK_MND8_P(id, ns, m, l, br, root, tbl, par, chld_lst, \
+ h_r, h_c, h_b, tv) \
+ CLK(id, MND, ns, ns, (ns-4), NULL, 0, h_r, h_c, \
+ h_b, br, root, F_MASK_MND8(m, l), 0, set_rate_mnd, \
+ tbl, NULL, par, chld_lst, tv)
+#define CLK_MND8(id, ns, m, l, br, root, tbl, chld_lst, h_r, h_c, h_b, tv) \
+ CLK_MND8_P(id, ns, m, l, br, root, tbl, NONE, chld_lst, \
+ h_r, h_c, h_b, tv)
+#define CLK_MND16(id, ns, br, root, tbl, par, chld_lst, h_r, h_c, h_b, tv) \
+ CLK(id, MND, ns, ns, (ns-4), NULL, 0, h_r, h_c, \
+ h_b, br, root, F_MASK_MND16, 0, set_rate_mnd, tbl, \
+ NULL, par, chld_lst, tv)
+#define CLK_1RATE(id, ns, br, root, tbl, h_r, h_c, h_b, tv) \
+ CLK(id, BASIC, NULL, ns, NULL, NULL, 0, h_r, h_c, \
+ h_b, br, root, 0, 0, set_rate_nop, tbl, \
+ NULL, NONE, NULL, tv)
+#define CLK_SLAVE(id, ns, br, par, h_r, h_c, h_b, tv) \
+ CLK(id, NORATE, NULL, ns, NULL, NULL, 0, h_r, h_c, \
+ h_b, br, 0, 0, 0, NULL, NULL, NULL, par, NULL, tv)
+#define CLK_NORATE(id, ns, br, root, h_r, h_c, h_b, tv) \
+ CLK(id, NORATE, NULL, ns, NULL, NULL, 0, h_r, h_c, \
+ h_b, br, root, 0, 0, NULL, NULL, NULL, NONE, NULL, tv)
+#define CLK_GLBL(id, glbl, br, h_r, h_c, h_b, tv) \
+ CLK(id, NORATE, NULL, glbl, NULL, NULL, 0, h_r, h_c, \
+ h_b, br, 0, 0, 0, NULL, NULL, NULL, NONE, NULL, tv)
+#define CLK_BRIDGE(id, glbl, br, par, h_r, h_c, h_b, tv) \
+ CLK(id, NORATE, NULL, glbl, NULL, NULL, 0, h_r, h_c, \
+ h_b, br, 0, 0, 0, NULL, NULL, NULL, par, NULL, tv)
+
+/*
+ * Clock table
+ */
+struct clk_local soc_clk_local_tbl[] = {
CLK_NORATE(MDC, MDC_NS_REG, B(9), B(11),
- CLK_HALT_STATEA_REG, 10, 0x4D56),
+ CLK_HALT_STATEA_REG, HALT, 10, 0x4D56),
CLK_NORATE(LPA_CORE, LPA_NS_REG, B(5), 0,
- CLK_HALT_STATEC_REG, 5, 0x0E),
+ CLK_HALT_STATEC_REG, HALT, 5, 0x0E),
CLK_1RATE(I2C, I2C_NS_REG, B(9), B(11), clk_tbl_tcxo,
- CLK_HALT_STATEA_REG, 15, 0x4D4D),
+ CLK_HALT_STATEA_REG, HALT, 15, 0x4D4D),
CLK_1RATE(I2C_2, I2C_2_NS_REG, B(0), B(2), clk_tbl_tcxo,
- CLK_HALT_STATEC_REG, 2, 0x0B),
+ CLK_HALT_STATEC_REG, HALT, 2, 0x0B),
CLK_1RATE(QUP_I2C, QUP_I2C_NS_REG, B(0), B(2), clk_tbl_tcxo,
- CLK_HALT_STATEB_REG, 31, 0x1C),
+ CLK_HALT_STATEB_REG, HALT, 31, 0x1C),
CLK_1RATE(UART1, UART_NS_REG, B(5), B(4), clk_tbl_tcxo,
- CLK_HALT_STATEB_REG, 7, 0x4D6F),
+ CLK_HALT_STATEB_REG, HALT, 7, 0x4D6F),
CLK_1RATE(UART2, UART2_NS_REG, B(5), B(4), clk_tbl_tcxo,
- CLK_HALT_STATEB_REG, 5, 0x4D71),
+ CLK_HALT_STATEB_REG, HALT, 5, 0x4D71),
CLK_BASIC(EMDH, EMDH_NS_REG, 0, B(11), clk_tbl_mdh, AXI_LI_ADSP_A,
- NULL, 0, 0x4F00),
+ NULL, DELAY, 0, 0x4F00),
CLK_BASIC(PMDH, PMDH_NS_REG, 0, B(11), clk_tbl_mdh, AXI_LI_ADSP_A,
- NULL, 0, 0x5500),
+ NULL, DELAY, 0, 0x5500),
CLK_BASIC(MDP, MDP_NS_REG, B(9), B(11), clk_tbl_mdp_core, AXI_MDP,
- CLK_HALT_STATEB_REG, 16, 0x5400),
+ CLK_HALT_STATEB_REG, HALT, 16, 0x5400),
CLK_MND8_P(VPE, VPE_NS_REG, 22, 15, B(9), B(11), clk_tbl_vpe,
- AXI_VPE, NULL, CLK_HALT_STATEC_REG, 10, 0x6C00),
+ AXI_VPE, NULL, CLK_HALT_STATEC_REG, HALT, 10, 0x6C00),
CLK_MND8_P(MFC, MFC_NS_REG, 24, 17, B(9), B(11), clk_tbl_mfc,
AXI_MFC, chld_mfc, CLK_HALT_STATEC_REG,
- 12, 0x38),
+ HALT, 12, 0x38),
CLK_SLAVE(MFC_DIV2, MFC_NS_REG, B(15), MFC, CLK_HALT_STATEC_REG,
- 11, 0x1F),
+ HALT, 11, 0x1F),
CLK_MND8(SDC1, SDCn_NS_REG(1), 19, 12, B(9), B(11), clk_tbl_sdc1_3,
- NULL, CLK_HALT_STATEA_REG, 1, 0x4D62),
+ NULL, CLK_HALT_STATEA_REG, HALT, 1, 0x4D62),
CLK_MND8(SDC2, SDCn_NS_REG(2), 20, 13, B(9), B(11), clk_tbl_sdc2_4,
- NULL, CLK_HALT_STATEA_REG, 0, 0x4D64),
+ NULL, CLK_HALT_STATEA_REG, HALT, 0, 0x4D64),
CLK_MND8(SDC3, SDCn_NS_REG(3), 19, 12, B(9), B(11), clk_tbl_sdc1_3,
- NULL, CLK_HALT_STATEB_REG, 24, 0x4D7A),
+ NULL, CLK_HALT_STATEB_REG, HALT, 24, 0x4D7A),
CLK_MND8(SDC4, SDCn_NS_REG(4), 20, 13, B(9), B(11), clk_tbl_sdc2_4,
- NULL, CLK_HALT_STATEB_REG, 25, 0x4D7C),
+ NULL, CLK_HALT_STATEB_REG, HALT, 25, 0x4D7C),
CLK_MND8(SPI, SPI_NS_REG, 19, 12, B(9), B(11), clk_tbl_spi, NULL,
- CLK_HALT_STATEC_REG, 0, 0x09),
+ CLK_HALT_STATEC_REG, HALT, 0, 0x09),
CLK_MND8(MIDI, MIDI_NS_REG, 19, 12, B(9), B(11), clk_tbl_midi, NULL,
- CLK_HALT_STATEC_REG, 1, 0x0A),
+ CLK_HALT_STATEC_REG, HALT, 1, 0x0A),
CLK_MND8_P(USB_HS_SRC, USBH_NS_REG, 23, 16, 0, B(11), clk_tbl_usb,
- AXI_LI_ADSP_A, chld_usb_src, NULL, 0, 0),
+ AXI_LI_ADSP_A, chld_usb_src, NULL, NOCHECK, 0, 0),
CLK_SLAVE(USB_HS, USBH_NS_REG, B(9), USB_HS_SRC,
- CLK_HALT_STATEB_REG, 26, 0x4D7F),
+ CLK_HALT_STATEB_REG, HALT, 26, 0x4D7F),
CLK_SLAVE(USB_HS_CORE, USBH_NS_REG, B(13), USB_HS_SRC,
- CLK_HALT_STATEA_REG, 27, 0x14),
+ CLK_HALT_STATEA_REG, HALT, 27, 0x14),
CLK_SLAVE(USB_HS2, USBH2_NS_REG, B(9), USB_HS_SRC,
- CLK_HALT_STATEB_REG, 3, 0x4D73),
+ CLK_HALT_STATEB_REG, HALT, 3, 0x4D73),
CLK_SLAVE(USB_HS2_CORE, USBH2_NS_REG, B(4), USB_HS_SRC,
- CLK_HALT_STATEA_REG, 28, 0x15),
+ CLK_HALT_STATEA_REG, HALT, 28, 0x15),
CLK_SLAVE(USB_HS3, USBH3_NS_REG, B(9), USB_HS_SRC,
- CLK_HALT_STATEB_REG, 2, 0x4D74),
+ CLK_HALT_STATEB_REG, HALT, 2, 0x4D74),
CLK_SLAVE(USB_HS3_CORE, USBH3_NS_REG, B(4), USB_HS_SRC,
- CLK_HALT_STATEA_REG, 29, 0x16),
+ CLK_HALT_STATEA_REG, HALT, 29, 0x16),
CLK_MND8(TV, TV_NS_REG, 23, 16, 0, B(11), clk_tbl_tv, chld_tv,
- NULL, 0, 0),
+ NULL, NOCHECK, 0, 0),
CLK_SLAVE(HDMI, HDMI_NS_REG, B(9), TV,
- CLK_HALT_STATEC_REG, 7, 0x13),
+ CLK_HALT_STATEC_REG, HALT, 7, 0x13),
CLK_SLAVE(TV_DAC, TV_NS_REG, B(12), TV,
- CLK_HALT_STATEB_REG, 27, 0x4D6C),
+ CLK_HALT_STATEB_REG, HALT, 27, 0x4D6C),
CLK_SLAVE(TV_ENC, TV_NS_REG, B(9), TV,
- CLK_HALT_STATEB_REG, 10, 0x4D6B),
+ CLK_HALT_STATEB_REG, HALT, 10, 0x4D6B),
/* Hacking root & branch into one param. */
CLK_SLAVE(TSIF_REF, TSIF_NS_REG, B(9)|B(11), TV,
- CLK_HALT_STATEB_REG, 11, 0x4D6A),
+ CLK_HALT_STATEB_REG, HALT, 11, 0x4D6A),
CLK_MND16(UART1DM, UART1DM_NS_REG, B(9), B(11), clk_tbl_uartdm, NONE,
- NULL, CLK_HALT_STATEB_REG, 6, 0x4D70),
+ NULL, CLK_HALT_STATEB_REG, HALT, 6, 0x4D70),
CLK_MND16(UART2DM, UART2DM_NS_REG, B(9), B(11), clk_tbl_uartdm, NONE,
- NULL, CLK_HALT_STATEB_REG, 23, 0x4D7D),
+ NULL, CLK_HALT_STATEB_REG, HALT, 23, 0x4D7D),
CLK_MND16(JPEG, JPEG_NS_REG, B(9), B(11), clk_tbl_vfe_jpeg, AXI_LI_JPEG,
- NULL, CLK_HALT_STATEB_REG, 1, 0x6000),
+ NULL, CLK_HALT_STATEB_REG, HALT, 1, 0x6000),
CLK_MND16(CAM_M, CAM_NS_REG, 0, B(9), clk_tbl_cam, NONE, NULL,
- NULL, 0, 0x4D44),
+ NULL, DELAY, 0, 0x4D44),
CLK_MND16(VFE, CAM_VFE_NS_REG, B(9), B(13), clk_tbl_vfe_jpeg,
AXI_LI_VFE, chld_vfe, CLK_HALT_STATEB_REG,
- 0, 0x4D76),
+ HALT, 0, 0x4D76),
CLK_SLAVE(VFE_MDC, CAM_VFE_NS_REG, B(11), VFE, CLK_HALT_STATEA_REG,
- 9, 0x4D57),
+ HALT, 9, 0x4D57),
CLK_SLAVE(VFE_CAMIF, CAM_VFE_NS_REG, B(15), VFE, CLK_HALT_STATEC_REG,
- 13, 0x7000),
+ HALT, 13, 0x7000),
CLK_SLAVE(CSI0_VFE, CSI_NS_REG, B(15), VFE, CLK_HALT_STATEC_REG,
- 16, 0),
+ HALT, 16, 0),
CLK_MND16(SDAC, SDAC_NS_REG, B(9), B(11), clk_tbl_sdac,
- NONE, chld_sdac, CLK_HALT_STATEA_REG, 2, 0x4D60),
+ NONE, chld_sdac, CLK_HALT_STATEA_REG, HALT, 2, 0x4D60),
CLK_SLAVE(SDAC_M, SDAC_NS_REG, B(12), SDAC, CLK_HALT_STATEB_REG,
- 17, 0x4D66),
+ HALT, 17, 0x4D66),
CLK_MND16(MDP_LCDC_PCLK, MDP_LCDC_NS_REG, B(9), B(11),
clk_tbl_mdp_lcdc, NONE, chld_mdp_lcdc_p,
- CLK_HALT_STATEB_REG, 28, 0x4200),
+ CLK_HALT_STATEB_REG, HALT, 28, 0x4200),
CLK_SLAVE(MDP_LCDC_PAD_PCLK, MDP_LCDC_NS_REG, B(12), MDP_LCDC_PCLK,
- CLK_HALT_STATEB_REG, 29, 0x4100),
+ CLK_HALT_STATEB_REG, HALT, 29, 0x4100),
CLK_1RATE(MDP_VSYNC, MDP_VSYNC_REG, B(0), 0, clk_tbl_mdp_vsync,
- CLK_HALT_STATEB_REG, 30, 0x4D53),
+ CLK_HALT_STATEB_REG, HALT, 30, 0x4D53),
CLK_MND16(MI2S_CODEC_RX_M, MI2S_RX_NS_REG, B(12), B(11),
clk_tbl_mi2s_codec, NONE, chld_mi2s_codec_rx,
- CLK_HALT_STATEA_REG, 12, 0x4D4E),
+ CLK_HALT_STATEA_REG, HALT, 12, 0x4D4E),
CLK_SLAVE(MI2S_CODEC_RX_S, MI2S_RX_NS_REG, B(9), MI2S_CODEC_RX_M,
- CLK_HALT_STATEA_REG, 13, 0x4D4F),
+ CLK_HALT_STATEA_REG, HALT, 13, 0x4D4F),
CLK_MND16(MI2S_CODEC_TX_M, MI2S_TX_NS_REG, B(12), B(11),
clk_tbl_mi2s_codec, NONE, chld_mi2s_codec_tx,
- CLK_HALT_STATEC_REG, 8, 0x4D50),
+ CLK_HALT_STATEC_REG, HALT, 8, 0x4D50),
CLK_SLAVE(MI2S_CODEC_TX_S, MI2S_TX_NS_REG, B(9), MI2S_CODEC_TX_M,
- CLK_HALT_STATEA_REG, 11, 0x17),
+ CLK_HALT_STATEA_REG, HALT, 11, 0x17),
CLK_MND16(MI2S_M, MI2S_NS_REG, B(12), B(11),
clk_tbl_mi2s, NONE, chld_mi2s, CLK_HALT_STATEC_REG,
- 4, 0x0D),
+ HALT, 4, 0x0D),
CLK_SLAVE(MI2S_S, MI2S_NS_REG, B(9), MI2S_M, CLK_HALT_STATEC_REG,
- 3, 0),
-
- CLK_LOCAL(GRP_2D, BASIC, 0, GRP_2D_NS_REG, F_MASK_BASIC | (7 << 12),
- B(7), B(11), clk_tbl_grp, AXI_GRP_2D, NULL,
- CLK_HALT_STATEA_REG, 31, 0x5C00),
- CLK_LOCAL(GRP_3D_SRC, BASIC, 0, GRP_NS_REG, F_MASK_BASIC | (7 << 12),
- 0, B(11), clk_tbl_grp, AXI_LI_GRP, chld_grp_3d_src,
- 0, 0, 0),
+ HALT, 3, 0),
+
+ CLK(GRP_2D, BASIC, GRP_2D_NS_REG, GRP_2D_NS_REG, NULL, NULL, 0,
+ CLK_HALT_STATEA_REG, HALT, 31, B(7), B(11),
+ F_MASK_BASIC | (7 << 12), 0, set_rate_basic,
+ clk_tbl_grp, NULL, AXI_GRP_2D, NULL, 0x5C00),
+ CLK(GRP_3D_SRC, BASIC, GRP_NS_REG, GRP_NS_REG, NULL, NULL, 0,
+ NULL, NOCHECK, 0, 0, B(11), F_MASK_BASIC | (7 << 12),
+ 0, set_rate_basic, clk_tbl_grp, NULL, AXI_LI_GRP,
+ chld_grp_3d_src, 0),
CLK_SLAVE(GRP_3D, GRP_NS_REG, B(7), GRP_3D_SRC, CLK_HALT_STATEB_REG,
- 18, 0x5E00),
+ HALT, 18, 0x5E00),
CLK_SLAVE(IMEM, GRP_NS_REG, B(9), GRP_3D_SRC, CLK_HALT_STATEB_REG,
- 19, 0x5F00),
- CLK_LOCAL(LPA_CODEC, BASIC, 0, LPA_NS_REG, BM(1, 0), B(9), 0,
- clk_tbl_lpa_codec, NONE, NULL, CLK_HALT_STATEC_REG,
- 6, 0x0F),
+ HALT, 19, 0x5F00),
+ CLK(LPA_CODEC, BASIC, LPA_NS_REG, LPA_NS_REG, NULL, NULL, 0,
+ CLK_HALT_STATEC_REG, HALT, 6, B(9), 0, BM(1, 0), 0,
+ set_rate_basic, clk_tbl_lpa_codec, NULL, NONE, NULL,
+ 0x0F),
CLK_MND8(CSI0, CSI_NS_REG, 24, 17, B(9), B(11), clk_tbl_csi, NULL,
- CLK_HALT_STATEC_REG, 17, 0x5F00),
+ CLK_HALT_STATEC_REG, HALT, 17, 0x5F00),
/* For global clocks to be on we must have GLBL_ROOT_ENA set */
CLK_1RATE(GLBL_ROOT, GLBL_CLK_ENA_SC_REG, 0, B(29), clk_tbl_axi,
- NULL, 0, 0),
+ NULL, NOCHECK, 0, 0),
/* Peripheral bus clocks. */
CLK_BRIDGE(ADM, GLBL_CLK_ENA_SC_REG, B(5), AXI_LI_APPS,
- GLBL_CLK_STATE_REG, 5, 0x4000),
+ GLBL_CLK_STATE_REG, HALT_VOTED, 5, 0x4000),
CLK_GLBL(ADM_P, GLBL_CLK_ENA_2_SC_REG, B(15),
- GLBL_CLK_STATE_2_REG, 15, 0x11),
+ GLBL_CLK_STATE_2_REG, HALT_VOTED, 15, 0x11),
CLK_GLBL(CE, GLBL_CLK_ENA_SC_REG, B(6),
- GLBL_CLK_STATE_REG, 6, 0x4D43),
+ GLBL_CLK_STATE_REG, HALT_VOTED, 6, 0x4D43),
CLK_GLBL(CAMIF_PAD_P, GLBL_CLK_ENA_SC_REG, B(9),
- GLBL_CLK_STATE_REG, 9, 0x1A),
+ GLBL_CLK_STATE_REG, HALT_VOTED, 9, 0x1A),
CLK_GLBL(CSI0_P, GLBL_CLK_ENA_SC_REG, B(30),
- GLBL_CLK_STATE_REG, 30, 0),
+ GLBL_CLK_STATE_REG, HALT_VOTED, 30, 0),
CLK_GLBL(EMDH_P, GLBL_CLK_ENA_2_SC_REG, B(3),
- GLBL_CLK_STATE_2_REG, 3, 0x03),
+ GLBL_CLK_STATE_2_REG, HALT_VOTED, 3, 0x03),
CLK_GLBL(GRP_2D_P, GLBL_CLK_ENA_SC_REG, B(24),
- GLBL_CLK_STATE_REG, 24, 0x4D4C),
+ GLBL_CLK_STATE_REG, HALT_VOTED, 24, 0x4D4C),
CLK_GLBL(GRP_3D_P, GLBL_CLK_ENA_2_SC_REG, B(17),
- GLBL_CLK_STATE_2_REG, 17, 0x4D67),
+ GLBL_CLK_STATE_2_REG, HALT_VOTED, 17, 0x4D67),
CLK_GLBL(JPEG_P, GLBL_CLK_ENA_2_SC_REG, B(24),
- GLBL_CLK_STATE_2_REG, 24, 0x4D5E),
+ GLBL_CLK_STATE_2_REG, HALT_VOTED, 24, 0x4D5E),
CLK_GLBL(LPA_P, GLBL_CLK_ENA_2_SC_REG, B(7),
- GLBL_CLK_STATE_2_REG, 7, 0x07),
+ GLBL_CLK_STATE_2_REG, HALT_VOTED, 7, 0x07),
CLK_GLBL(MDP_P, GLBL_CLK_ENA_2_SC_REG, B(6),
- GLBL_CLK_STATE_2_REG, 6, 0x06),
+ GLBL_CLK_STATE_2_REG, HALT_VOTED, 6, 0x06),
CLK_GLBL(MFC_P, GLBL_CLK_ENA_2_SC_REG, B(26),
- GLBL_CLK_STATE_2_REG, 26, 0x4D75),
+ GLBL_CLK_STATE_2_REG, HALT_VOTED, 26, 0x4D75),
CLK_GLBL(PMDH_P, GLBL_CLK_ENA_2_SC_REG, B(4),
- GLBL_CLK_STATE_2_REG, 4, 0x04),
+ GLBL_CLK_STATE_2_REG, HALT_VOTED, 4, 0x04),
CLK_GLBL(ROTATOR_IMEM, GLBL_CLK_ENA_2_SC_REG, B(23),
- GLBL_CLK_STATE_2_REG, 23, 0x6600),
+ GLBL_CLK_STATE_2_REG, HALT_VOTED, 23, 0x6600),
CLK_GLBL(ROTATOR_P, GLBL_CLK_ENA_2_SC_REG, B(25),
- GLBL_CLK_STATE_2_REG, 25, 0x4D6D),
+ GLBL_CLK_STATE_2_REG, HALT_VOTED, 25, 0x4D6D),
CLK_GLBL(SDC1_P, GLBL_CLK_ENA_SC_REG, B(7),
- GLBL_CLK_STATE_REG, 7, 0x4D61),
+ GLBL_CLK_STATE_REG, HALT_VOTED, 7, 0x4D61),
CLK_GLBL(SDC2_P, GLBL_CLK_ENA_SC_REG, B(8),
- GLBL_CLK_STATE_REG, 8, 0x4F63),
+ GLBL_CLK_STATE_REG, HALT_VOTED, 8, 0x4F63),
CLK_GLBL(SDC3_P, GLBL_CLK_ENA_SC_REG, B(27),
- GLBL_CLK_STATE_REG, 27, 0x4D79),
+ GLBL_CLK_STATE_REG, HALT_VOTED, 27, 0x4D79),
CLK_GLBL(SDC4_P, GLBL_CLK_ENA_SC_REG, B(28),
- GLBL_CLK_STATE_REG, 28, 0x4D7B),
+ GLBL_CLK_STATE_REG, HALT_VOTED, 28, 0x4D7B),
CLK_GLBL(SPI_P, GLBL_CLK_ENA_2_SC_REG, B(10),
- GLBL_CLK_STATE_2_REG, 10, 0x18),
+ GLBL_CLK_STATE_2_REG, HALT_VOTED, 10, 0x18),
CLK_GLBL(TSIF_P, GLBL_CLK_ENA_SC_REG, B(18),
- GLBL_CLK_STATE_REG, 18, 0x4D65),
+ GLBL_CLK_STATE_REG, HALT_VOTED, 18, 0x4D65),
CLK_GLBL(UART1DM_P, GLBL_CLK_ENA_SC_REG, B(17),
- GLBL_CLK_STATE_REG, 17, 0x4D5C),
+ GLBL_CLK_STATE_REG, HALT_VOTED, 17, 0x4D5C),
CLK_GLBL(UART2DM_P, GLBL_CLK_ENA_SC_REG, B(26),
- GLBL_CLK_STATE_REG, 26, 0x4D7E),
+ GLBL_CLK_STATE_REG, HALT_VOTED, 26, 0x4D7E),
CLK_GLBL(USB_HS2_P, GLBL_CLK_ENA_2_SC_REG, B(8),
- GLBL_CLK_STATE_2_REG, 8, 0x08),
+ GLBL_CLK_STATE_2_REG, HALT_VOTED, 8, 0x08),
CLK_GLBL(USB_HS3_P, GLBL_CLK_ENA_2_SC_REG, B(9),
- GLBL_CLK_STATE_2_REG, 9, 0x10),
+ GLBL_CLK_STATE_2_REG, HALT_VOTED, 9, 0x10),
CLK_GLBL(USB_HS_P, GLBL_CLK_ENA_SC_REG, B(25),
- GLBL_CLK_STATE_REG, 25, 0x4D58),
+ GLBL_CLK_STATE_REG, HALT_VOTED, 25, 0x4D58),
CLK_GLBL(VFE_P, GLBL_CLK_ENA_2_SC_REG, B(27),
- GLBL_CLK_STATE_2_REG, 27, 0x4D55),
+ GLBL_CLK_STATE_2_REG, HALT_VOTED, 27, 0x4D55),
/* AXI bridge clocks. */
CLK_BRIDGE(AXI_LI_APPS, GLBL_CLK_ENA_SC_REG, B(2), GLBL_ROOT,
- GLBL_CLK_STATE_REG, 2, 0x4900),
+ GLBL_CLK_STATE_REG, HALT_VOTED, 2, 0x4900),
CLK_BRIDGE(AXI_LI_ADSP_A, GLBL_CLK_ENA_2_SC_REG, B(14), AXI_LI_APPS,
- GLBL_CLK_STATE_2_REG, 14, 0x6400),
+ GLBL_CLK_STATE_2_REG, HALT_VOTED, 14, 0x6400),
CLK_BRIDGE(AXI_LI_JPEG, GLBL_CLK_ENA_2_SC_REG, B(19), AXI_LI_APPS,
- GLBL_CLK_STATE_2_REG, 19, 0x4E00),
+ GLBL_CLK_STATE_2_REG, HALT_VOTED, 19, 0x4E00),
CLK_BRIDGE(AXI_LI_VFE, GLBL_CLK_ENA_SC_REG, B(23), AXI_LI_APPS,
- GLBL_CLK_STATE_REG, 23, 0x5B00),
+ GLBL_CLK_STATE_REG, HALT_VOTED, 23, 0x5B00),
CLK_BRIDGE(AXI_MDP, GLBL_CLK_ENA_2_SC_REG, B(29), AXI_LI_APPS,
- GLBL_CLK_STATE_2_REG, 29, 0x6B00),
+ GLBL_CLK_STATE_2_REG, HALT_VOTED, 29, 0x6B00),
CLK_BRIDGE(AXI_IMEM, GLBL_CLK_ENA_2_SC_REG, B(18), GLBL_ROOT,
- GLBL_CLK_STATE_2_REG, 18, 0x4B00),
+ GLBL_CLK_STATE_2_REG, HALT_VOTED, 18, 0x4B00),
CLK_BRIDGE(AXI_LI_VG, GLBL_CLK_ENA_SC_REG, B(3), GLBL_ROOT,
- GLBL_CLK_STATE_REG, 3, 0x4700),
+ GLBL_CLK_STATE_REG, HALT_VOTED, 3, 0x4700),
CLK_BRIDGE(AXI_GRP_2D, GLBL_CLK_ENA_SC_REG, B(21), AXI_LI_VG,
- GLBL_CLK_STATE_REG, 21, 0x5900),
+ GLBL_CLK_STATE_REG, HALT_VOTED, 21, 0x5900),
CLK_BRIDGE(AXI_LI_GRP, GLBL_CLK_ENA_SC_REG, B(22), AXI_LI_VG,
- GLBL_CLK_STATE_REG, 22, 0x5A00),
+ GLBL_CLK_STATE_REG, HALT_VOTED, 22, 0x5A00),
CLK_BRIDGE(AXI_MFC, GLBL_CLK_ENA_2_SC_REG, B(20), AXI_LI_VG,
- GLBL_CLK_STATE_2_REG, 20, 0x6A00),
+ GLBL_CLK_STATE_2_REG, HALT_VOTED, 20, 0x6A00),
CLK_BRIDGE(AXI_ROTATOR, GLBL_CLK_ENA_2_SC_REG, B(22), AXI_LI_VG,
- GLBL_CLK_STATE_2_REG, 22, 0x4300),
+ GLBL_CLK_STATE_2_REG, HALT_VOTED, 22, 0x4300),
CLK_BRIDGE(AXI_VPE, GLBL_CLK_ENA_2_SC_REG, B(21), AXI_LI_VG,
- GLBL_CLK_STATE_2_REG, 21, 0x6700),
-};
-
-static DEFINE_SPINLOCK(clock_reg_lock);
-static DEFINE_SPINLOCK(pll_vote_lock);
-
-enum {
- TCXO,
- LPXO,
- NUM_XO
+ GLBL_CLK_STATE_2_REG, HALT_VOTED, 21, 0x6700),
};
-static unsigned xo_votes[NUM_XO]; /* Tracks the number of users for each XO */
-
-/* Map PLLs to which XO they use */
-static const unsigned pll_to_xo[] = {
- [PLL_0] = TCXO,
- [PLL_1] = TCXO,
- [PLL_2] = TCXO,
- [PLL_3] = LPXO,
- [PLL_4] = LPXO,
- [PLL_5] = TCXO,
- [PLL_6] = TCXO,
-};
-
-static void vote_for_xo(unsigned xo)
-{
- BUG_ON(xo >= NUM_XO);
-
- if (!xo_votes[xo]) {
- int enable = 1;
- unsigned p_xo = xo;
- msm_proc_comm(PCOM_CLKCTL_RPC_SRC_REQUEST, &p_xo, &enable);
- }
- xo_votes[xo]++;
-}
-
-static void unvote_for_xo(unsigned xo)
-{
- BUG_ON(xo >= NUM_XO);
- if (xo_votes[xo]) {
- xo_votes[xo]--;
- } else {
- pr_warning("%s: Reference count mismatch!\n", __func__);
- return;
- }
-
- if (xo_votes[xo] == 0) {
- int enable = 0;
- msm_proc_comm(PCOM_CLKCTL_RPC_SRC_REQUEST, &xo, &enable);
- }
-}
-
-#define PLL_ACTIVE_MASK B(16)
-void pll_enable(uint32_t pll)
-{
- uint32_t reg_val;
- unsigned long flags;
-
- BUG_ON(pll >= NUM_PLL);
-
- spin_lock_irqsave(&pll_vote_lock, flags);
- if (!pll_count[pll]) {
- vote_for_xo(pll_to_xo[pll]);
- reg_val = readl(PLL_ENA_REG);
- reg_val |= (1 << pll);
- writel(reg_val, PLL_ENA_REG);
- }
- pll_count[pll]++;
- spin_unlock_irqrestore(&pll_vote_lock, flags);
-
- /* Wait until PLL is enabled. */
- while ((readl(pll_status_addr[pll]) & PLL_ACTIVE_MASK) == 0)
- cpu_relax();
-}
-
-void pll_disable(uint32_t pll)
-{
- uint32_t reg_val;
- unsigned long flags;
-
- BUG_ON(pll >= NUM_PLL);
-
- spin_lock_irqsave(&pll_vote_lock, flags);
- if (pll_count[pll]) {
- pll_count[pll]--;
- } else {
- pr_warning("Reference count mismatch in PLL disable!\n");
- goto out;
- }
-
- if (pll_count[pll] == 0) {
- reg_val = readl(PLL_ENA_REG);
- reg_val &= ~(1 << pll);
- writel(reg_val, PLL_ENA_REG);
- unvote_for_xo(pll_to_xo[pll]);
- }
-out:
- spin_unlock_irqrestore(&pll_vote_lock, flags);
-}
-
-static void src_enable(uint32_t src)
-{
- switch (src) {
- case SRC_NONE:
- /*
- * SRC_NONE is used as a placeholder for some freqencies that
- * don't have any direct PLL dependency. Instead they source
- * off an external/internal clock which takes care of any
- * PLL or XO dependency.
- */
- break;
- case SRC_TCXO:
- vote_for_xo(TCXO);
- break;
- case SRC_AXI:
- case SRC_LPXO:
- /*
- * AXI could use LPXO or TCXO. Map it to LPXO to make sure
- * there is at least once XO available for the AXI (LPXO is
- * the lower powered one so just use that).
- */
- vote_for_xo(LPXO);
- break;
- default:
- pll_enable(src_pll_tbl[src]);
- break;
- }
-}
-
-static void src_disable(uint32_t src)
-{
- switch (src) {
- case SRC_NONE:
- /*
- * SRC_NONE is used as a placeholder for some freqencies that
- * don't have any direct PLL dependency. Instead they source
- * off an external/internal clock which takes care of any
- * PLL or XO dependency.
- */
- break;
- case SRC_TCXO:
- unvote_for_xo(TCXO);
- break;
- case SRC_AXI:
- case SRC_LPXO:
- /*
- * AXI could use LPXO or TCXO. Map it to LPXO to make sure
- * there is@least once XO available for the AXI (LPXO is
- * the lower powered one so just use that).
- */
- unvote_for_xo(LPXO);
- break;
- default:
- pll_disable(src_pll_tbl[src]);
- break;
- }
-}
-
-static unsigned msmc1_votes[MSMC1_END];
-static unsigned msmc1_level;
+/*
+ * SoC-specific functions required by clock-local driver
+ */
-static int update_msmc1(void)
+/* Update the sys_vdd voltage given a level. */
+int soc_update_sys_vdd(enum sys_vdd_level level)
{
- int err, target, mvolts;
-
- if (msmc1_votes[HIGH])
- target = 1200;
- else if (msmc1_votes[NOMINAL])
- target = 1100;
- else
- target = 1000;
-
- if (target == msmc1_level)
- return 0;
-
- mvolts = target;
- err = msm_proc_comm(PCOM_CLKCTL_RPC_MIN_MSMC1, &mvolts, NULL);
- if (err)
+ int rc, target_mv;
+ static const int mv[NUM_SYS_VDD_LEVELS] = {
+ [NONE...LOW] = 1000,
+ [NOMINAL] = 1100,
+ [HIGH] = 1200,
+ };
+
+ target_mv = mv[level];
+ rc = msm_proc_comm(PCOM_CLKCTL_RPC_MIN_MSMC1, &target_mv, NULL);
+ if (rc)
goto out;
-
- if (mvolts) {
- err = -EINVAL;
+ if (target_mv) {
+ rc = -EINVAL;
goto out;
}
- msmc1_level = target;
out:
- return err;
-}
-
-static void unvote_msmc1(unsigned level)
-{
- if (level >= ARRAY_SIZE(msmc1_votes))
- return;
-
- if (msmc1_votes[level]) {
- msmc1_votes[level]--;
- } else {
- pr_warning("%s: Reference counts are incorrect\n", __func__);
- return;
- }
-
- update_msmc1();
-}
-
-static int vote_msmc1(unsigned level)
-{
- int ret;
-
- if (level >= ARRAY_SIZE(msmc1_votes))
- return 0;
-
- msmc1_votes[level]++;
- ret = update_msmc1();
- if (ret)
- msmc1_votes[level]--;
-
- return ret;
-}
-
-/*
- * SoC specific register-based control of clocks.
- */
-static int _soc_clk_enable(unsigned id)
-{
- struct clk_local *t = &clk_local_tbl[id];
- void *ns_reg = t->ns_reg;
- uint32_t reg_val = 0;
-
- WARN((t->type != NORATE) && (t->current_freq == &dummy_freq),
- "Attempting to enable clock %d before setting its rate. "
- "Set the rate first!\n", id);
-
- reg_val = readl(ns_reg);
- if (t->type == MND) {
- /* mode can be either 0 or 1. So the R-value of the
- * expression will evaluate to MNCNTR_EN_MASK or 0. This
- * avoids the need for a "if(mode == 1)". A "&" will not work
- * here. */
- reg_val |= (MNCNTR_EN_MASK * t->current_freq->mode);
- writel(reg_val, ns_reg);
- }
- if (t->root_en_mask) {
- reg_val |= t->root_en_mask;
- writel(reg_val, ns_reg);
- }
- if (t->br_en_mask) {
- reg_val |= t->br_en_mask;
- writel(reg_val, ns_reg);
- }
- if (t->halt_reg) {
- uint32_t halted, count = 0;
-
- /* Wait for the halt bit to clear, but timeout after 100usecs
- * since the halt bit may be buggy. */
- while ((halted = readl(t->halt_reg) & BIT(t->halt_mask))
- && count++ < 100)
- udelay(1);
- if (halted)
- pr_warning("%s: clock %d never turned on\n", __func__,
- id);
- }
- return 0;
-}
-
-static void _soc_clk_disable(unsigned id)
-{
- struct clk_local *t = &clk_local_tbl[id];
- void *ns_reg = t->ns_reg;
- uint32_t reg_val = 0;
-
- reg_val = readl(ns_reg);
-
- if (t->br_en_mask) {
- reg_val &= ~(t->br_en_mask);
- writel(reg_val, ns_reg);
- }
- if (t->halt_reg) {
- uint32_t halted, count = 0;
-
- /* Wait for the halt bit to be set, but timeout after 100usecs
- * since the halt bit may be buggy. */
- while (!(halted = readl(t->halt_reg) & BIT(t->halt_mask))
- && count++ < 100)
- udelay(1);
- if (!halted)
- pr_warning("%s: clock %d never turned off\n", __func__,
- id);
- }
- if (t->root_en_mask) {
- reg_val &= ~(t->root_en_mask);
- writel(reg_val, ns_reg);
- }
- if (t->type == MND) {
- reg_val &= ~MNCNTR_EN_MASK;
- writel(reg_val, ns_reg);
- }
+ return rc;
}
-static int soc_clk_enable_nolock(unsigned id)
-{
- struct clk_local *t = &clk_local_tbl[id];
- int ret = 0;
-
- if (!t->count) {
- ret = vote_msmc1(t->current_freq->msmc1);
- if (ret)
- return ret;
- if (t->parent != C(NONE)) {
- ret = soc_clk_enable_nolock(t->parent);
- if (ret)
- return ret;
- }
- src_enable(t->current_freq->src);
- ret = _soc_clk_enable(id);
- }
- t->count++;
-
- return ret;
-}
-
-static void soc_clk_disable_nolock(unsigned id)
-{
- struct clk_local *t = &clk_local_tbl[id];
-
- if (!t->count) {
- pr_warning("Reference count mismatch in clock disable!\n");
- return;
- }
- if (t->count)
- t->count--;
- if (t->count == 0) {
- _soc_clk_disable(id);
- src_disable(t->current_freq->src);
- unvote_msmc1(t->current_freq->msmc1);
- if (t->parent != C(NONE))
- soc_clk_disable_nolock(t->parent);
- }
-
- return;
-}
-
-static int update_pwr_rail(unsigned id, int enable)
+/* Enable/disable a power rail associated with a clock. */
+int soc_set_pwr_rail(unsigned id, int enable)
{
/* TODO: Implement internal power rail control */
return 0;
}
-static int soc_clk_enable(unsigned id)
-{
- int ret = 0;
- unsigned long flags;
-
- spin_lock_irqsave(&clock_reg_lock, flags);
- ret = soc_clk_enable_nolock(id);
- if (ret)
- goto unlock;
- /*
- * The modem might modify the register bits for the clock branch when
- * the rail is enabled/disabled, so enable the rail inside the lock
- * instead of outside it.
- */
- ret = update_pwr_rail(id, 1);
- if (ret)
- soc_clk_disable_nolock(id);
-unlock:
- spin_unlock_irqrestore(&clock_reg_lock, flags);
-
- return ret;
-}
-
-static void soc_clk_disable(unsigned id)
-{
- unsigned long flags;
-
- spin_lock_irqsave(&clock_reg_lock, flags);
- update_pwr_rail(id, 0);
- soc_clk_disable_nolock(id);
- spin_unlock_irqrestore(&clock_reg_lock, flags);
-}
-
-static void soc_clk_auto_off(unsigned id)
-{
- unsigned long flags;
-
- spin_lock_irqsave(&clock_reg_lock, flags);
- _soc_clk_disable(id);
- spin_unlock_irqrestore(&clock_reg_lock, flags);
-}
-
-static long soc_clk_round_rate(unsigned id, unsigned rate)
-{
- struct clk_local *t = &clk_local_tbl[id];
- const struct clk_freq_tbl *f;
-
- if (t->type != MND && t->type != BASIC)
- return -EINVAL;
-
- for (f = t->freq_tbl; f->freq_hz != FREQ_END; f++)
- if (f->freq_hz >= rate)
- return f->freq_hz;
-
- return -EPERM;
-}
-
-static int soc_clk_set_rate(unsigned id, unsigned rate)
-{
- struct clk_local *t = &clk_local_tbl[id];
- const struct clk_freq_tbl *cf;
- const struct clk_freq_tbl *nf;
- uint32_t *chld = t->children;
- void *ns_reg = t->ns_reg;
- void *md_reg = t->md_reg;
- uint32_t reg_val = 0;
- int i, ret = 0;
- unsigned long flags;
- long rounded;
-
- rounded = soc_clk_round_rate(id, rate);
- if (rounded != rate)
- pr_warning("Use clk_round_rate() before clk_set_rate() with "
- "clock %u\n", id);
- rate = rounded;
-
- if (t->type != MND && t->type != BASIC)
- return -EPERM;
-
- spin_lock_irqsave(&clock_reg_lock, flags);
- cf = t->current_freq;
-
- if (rate == cf->freq_hz)
- goto release_lock;
-
- for (nf = t->freq_tbl; nf->freq_hz != FREQ_END; nf++)
- if (nf->freq_hz == rate)
- break;
-
- if (nf->freq_hz == FREQ_END) {
- ret = -EINVAL;
- goto release_lock;
- }
-
- if (t->freq_mask == 0) {
- t->current_freq = nf;
- goto release_lock;
- }
-
- /* Disable all branches before changing rate to prevent jitter. */
- for (i = 0; chld && chld[i] != C(NONE); i++) {
- struct clk_local *ch = &clk_local_tbl[chld[i]];
- /* Don't bother turning off if it is already off.
- * Checking ch->count is cheaper (cache) than reading and
- * writing to a register (uncached/unbuffered). */
- if (ch->count) {
- reg_val = readl(ch->ns_reg);
- reg_val &= ~(ch->br_en_mask);
- writel(reg_val, ch->ns_reg);
- }
- }
-
- if (t->count) {
- _soc_clk_disable(id);
-
- ret = vote_msmc1(nf->msmc1);
- if (ret)
- goto msmc1_err;
- /* Turn on PLL of the new freq. */
- src_enable(nf->src);
- }
-
- /* Some clocks share the same register, so must be careful when
- * assuming a register doesn't need to be re-read. */
- reg_val = readl(ns_reg);
- if (t->type == MND) {
- reg_val |= MNCNTR_RST_MASK;
- writel(reg_val, ns_reg);
- /* TODO: Currently writing 0's into reserved bits for 8-bit
- * MND. Can be avoided by adding md_mask. */
- if (nf->mode)
- writel(nf->md_val, md_reg);
- reg_val &= ~MNCNTR_MODE_MASK;
- reg_val |= (MNCNTR_MODE * nf->mode);
- }
- reg_val &= ~(t->freq_mask);
- reg_val |= nf->ns_val;
- writel(reg_val, ns_reg);
-
- if (t->type == MND) {
- reg_val &= ~MNCNTR_RST_MASK;
- writel(reg_val, ns_reg);
- }
-
- if (t->count) {
- /* Turn off PLL of the old freq. */
- src_disable(cf->src);
- unvote_msmc1(cf->msmc1);
- }
-
- /* Current freq must be updated before _soc_clk_enable() is called to
- * make sure the MNCNTR_E bit is set correctly. */
- t->current_freq = nf;
-
-msmc1_err:
- if (t->count)
- _soc_clk_enable(id);
- /* Enable only branches that were ON before. */
- for (i = 0; chld && chld[i] != C(NONE); i++) {
- struct clk_local *ch = &clk_local_tbl[chld[i]];
- if (ch->count) {
- reg_val = readl(ch->ns_reg);
- reg_val |= ch->br_en_mask;
- writel(reg_val, ch->ns_reg);
- }
- }
-
-release_lock:
- spin_unlock_irqrestore(&clock_reg_lock, flags);
- return ret;
-}
-
-static int soc_clk_set_min_rate(unsigned id, unsigned rate)
-{
- long rounded = soc_clk_round_rate(id, rate);
- return soc_clk_set_rate(id, rounded);
-}
-
-static int soc_clk_set_max_rate(unsigned id, unsigned rate)
-{
- return -EPERM;
-}
-
-static int soc_clk_set_flags(unsigned id, unsigned clk_flags)
+/* Implementation for clk_set_flags(). */
+int soc_clk_set_flags(unsigned id, unsigned clk_flags)
{
uint32_t regval, ret = 0;
unsigned long flags;
- spin_lock_irqsave(&clock_reg_lock, flags);
+ spin_lock_irqsave(&local_clock_reg_lock, flags);
switch (id) {
case C(VFE):
regval = readl(CAM_VFE_NS_REG);
@@ -1261,50 +713,102 @@ static int soc_clk_set_flags(unsigned id, unsigned clk_flags)
default:
ret = -EPERM;
}
- spin_unlock_irqrestore(&clock_reg_lock, flags);
+ spin_unlock_irqrestore(&local_clock_reg_lock, flags);
return ret;
}
-static unsigned soc_clk_get_rate(unsigned id)
+/* Enable function for TCXO and LPXO. */
+static int soc_xo_enable(unsigned src, unsigned enable)
{
- struct clk_local *t = &clk_local_tbl[id];
- unsigned long flags;
- unsigned ret = 0;
+ unsigned pcom_xo_id;
- if (t->type == NORATE)
+ if (src == TCXO)
+ pcom_xo_id = 0;
+ else if (src == LPXO)
+ pcom_xo_id = 1;
+ else
return 0;
- spin_lock_irqsave(&clock_reg_lock, flags);
- ret = t->current_freq->freq_hz;
- spin_unlock_irqrestore(&clock_reg_lock, flags);
-
- /* Return 0 if the rate has never been set. Might not be correct,
- * but it's good enough. */
- if (ret == FREQ_END)
- ret = 0;
-
- return ret;
+ return msm_proc_comm(PCOM_CLKCTL_RPC_SRC_REQUEST, &pcom_xo_id, &enable);
}
-static unsigned soc_clk_is_enabled(unsigned id)
+/* Enable function for PLLs. */
+static int soc_pll_enable(unsigned src, unsigned enable)
{
- return !!(clk_local_tbl[id].count);
-}
+ static const struct pll_ena {
+ uint32_t *const reg;
+ const uint32_t mask;
+ } soc_pll_ena[NUM_SRC] = {
+ [PLL_0] = {PLL_ENA_REG, B(0)},
+ [PLL_1] = {PLL_ENA_REG, B(1)},
+ [PLL_2] = {PLL_ENA_REG, B(2)},
+ [PLL_3] = {PLL_ENA_REG, B(3)},
+ [PLL_4] = {PLL_ENA_REG, B(4)},
+ [PLL_5] = {PLL_ENA_REG, B(5)},
+ [PLL_6] = {PLL_ENA_REG, B(6)},
+ };
+ uint32_t *const soc_pll_status_reg[NUM_SRC] = {
+
+ [PLL_0] = PLL0_STATUS_BASE_REG,
+ [PLL_1] = PLL1_STATUS_BASE_REG,
+ [PLL_2] = PLL2_STATUS_BASE_REG,
+ [PLL_3] = PLL3_STATUS_BASE_REG,
+ [PLL_4] = PLL4_STATUS_BASE_REG,
+ [PLL_5] = PLL5_STATUS_BASE_REG,
+ [PLL_6] = PLL6_STATUS_BASE_REG,
+ };
+ uint32_t reg_val;
+ reg_val = readl(soc_pll_ena[src].reg);
-struct clk_ops clk_ops_7x30 = {
- .enable = soc_clk_enable,
- .disable = soc_clk_disable,
- .auto_off = soc_clk_auto_off,
- .set_rate = soc_clk_set_rate,
- .set_min_rate = soc_clk_set_min_rate,
- .set_max_rate = soc_clk_set_max_rate,
- .reset = pc_clk_reset,
- .set_flags = soc_clk_set_flags,
- .get_rate = soc_clk_get_rate,
- .is_enabled = soc_clk_is_enabled,
- .round_rate = soc_clk_round_rate,
+ if (enable)
+ reg_val |= soc_pll_ena[src].mask;
+ else
+ reg_val &= ~(soc_pll_ena[src].mask);
+
+ writel(reg_val, soc_pll_ena[src].reg);
+
+ if (enable) {
+ /* Wait until PLL is enabled */
+ while ((readl(soc_pll_status_reg[src]) & B(16)) == 0)
+ cpu_relax();
+ }
+
+ return 0;
+}
+
+struct clk_source soc_clk_sources[NUM_SRC] = {
+ [TCXO] = { .enable_func = soc_xo_enable,
+ .par = SRC_NONE,
+ },
+ [LPXO] = { .enable_func = soc_xo_enable,
+ .par = SRC_NONE,
+ },
+ [AXI] = { .enable_func = NULL,
+ .par = LPXO,
+ },
+ [PLL_0] = { .enable_func = soc_pll_enable,
+ .par = TCXO,
+ },
+ [PLL_1] = { .enable_func = soc_pll_enable,
+ .par = TCXO,
+ },
+ [PLL_2] = { .enable_func = soc_pll_enable,
+ .par = TCXO,
+ },
+ [PLL_3] = { .enable_func = soc_pll_enable,
+ .par = LPXO,
+ },
+ [PLL_4] = { .enable_func = soc_pll_enable,
+ .par = LPXO,
+ },
+ [PLL_5] = { .enable_func = soc_pll_enable,
+ .par = TCXO,
+ },
+ [PLL_6] = { .enable_func = soc_pll_enable,
+ .par = TCXO,
+ },
};
/*
@@ -1454,6 +958,22 @@ static bool __init clk_is_local(uint32_t id)
return *reg & bit;
}
+/* SoC-specific clk_ops initialization. */
+void __init msm_clk_soc_set_ops(struct clk *clk)
+{
+ if (!clk->ops) {
+ if (clk_is_local(clk->id))
+ clk->ops = &soc_clk_ops_7x30;
+ else {
+ clk->ops = &clk_ops_pcom;
+ clk->id = clk->remote_id;
+ }
+ }
+}
+
+/*
+ * Miscellaneous clock register initializations
+ */
static const struct reg_init {
const void __iomem *reg;
uint32_t mask;
@@ -1490,21 +1010,7 @@ static const struct reg_init {
{USBH3_NS_REG, B(6), B(6)},
};
-/* SoC-specific clk_ops initialization. */
-void __init msm_clk_soc_set_ops(struct clk *clk)
-{
- if (!clk->ops) {
- if (clk_is_local(clk->id))
- clk->ops = &clk_ops_7x30;
- else {
- clk->ops = &clk_ops_pcom;
- clk->id = clk->remote_id;
- }
- }
-}
-
-#define set_1rate(clk) \
- soc_clk_set_rate(C(clk), clk_local_tbl[C(clk)].freq_tbl->freq_hz)
+/* Local clock driver initialization. */
void __init msm_clk_soc_init(void)
{
int i;
@@ -1522,10 +1028,10 @@ void __init msm_clk_soc_init(void)
* USB HS core clocks. */
for (i = 0; chld_usb_src[i] != C(NONE); i++)
if (clk_is_local(chld_usb_src[i]))
- _soc_clk_disable(chld_usb_src[i]);
+ local_clk_disable_reg(chld_usb_src[i]);
if (clk_is_local(C(USB_HS_SRC)))
- soc_clk_set_rate(C(USB_HS_SRC), clk_tbl_usb[0].freq_hz);
+ local_clk_set_rate(C(USB_HS_SRC), clk_tbl_usb[0].freq_hz);
for (i = 0; i < ARRAY_SIZE(ri_list); i++) {
val = readl(ri_list[i].reg);
@@ -1546,5 +1052,23 @@ void __init msm_clk_soc_init(void)
set_1rate(GLBL_ROOT);
/* Sync the GRP2D clock to AXI */
- soc_clk_set_rate(C(GRP_2D), 1);
+ local_clk_set_rate(C(GRP_2D), 1);
}
+
+
+/*
+ * Clock operation handler registration
+ */
+struct clk_ops soc_clk_ops_7x30 = {
+ .enable = local_clk_enable,
+ .disable = local_clk_disable,
+ .auto_off = local_clk_auto_off,
+ .set_rate = local_clk_set_rate,
+ .set_min_rate = local_clk_set_min_rate,
+ .set_max_rate = local_clk_set_max_rate,
+ .get_rate = local_clk_get_rate,
+ .is_enabled = local_clk_is_enabled,
+ .round_rate = local_clk_round_rate,
+ .reset = pc_clk_reset,
+ .set_flags = soc_clk_set_flags,
+};
diff --git a/arch/arm/mach-msm/clock-7x30.h b/arch/arm/mach-msm/clock-7x30.h
index d41acb7..01c49c7 100644
--- a/arch/arm/mach-msm/clock-7x30.h
+++ b/arch/arm/mach-msm/clock-7x30.h
@@ -31,116 +31,112 @@
#define __ARCH_ARM_MACH_MSM_CLOCK_7X30_H
enum {
- L_7X30_NONE_CLK = -1,
- L_7X30_ADM_CLK,
- L_7X30_ADM_P_CLK,
- L_7X30_CE_CLK,
- L_7X30_I2C_CLK,
- L_7X30_I2C_2_CLK,
- L_7X30_QUP_I2C_CLK,
- L_7X30_UART1DM_CLK,
- L_7X30_UART1DM_P_CLK,
- L_7X30_UART2DM_CLK,
- L_7X30_UART2DM_P_CLK,
- L_7X30_EMDH_CLK,
- L_7X30_EMDH_P_CLK,
- L_7X30_PMDH_CLK,
- L_7X30_PMDH_P_CLK,
- L_7X30_GRP_2D_CLK,
- L_7X30_GRP_2D_P_CLK,
- L_7X30_GRP_3D_SRC_CLK,
- L_7X30_GRP_3D_CLK,
- L_7X30_GRP_3D_P_CLK,
- L_7X30_IMEM_CLK,
- L_7X30_SDC1_CLK,
- L_7X30_SDC1_P_CLK,
- L_7X30_SDC2_CLK,
- L_7X30_SDC2_P_CLK,
- L_7X30_SDC3_CLK,
- L_7X30_SDC3_P_CLK,
- L_7X30_SDC4_CLK,
- L_7X30_SDC4_P_CLK,
- L_7X30_MDP_CLK,
- L_7X30_MDP_P_CLK,
- L_7X30_MDP_LCDC_PCLK_CLK,
- L_7X30_MDP_LCDC_PAD_PCLK_CLK,
- L_7X30_MDP_VSYNC_CLK,
- L_7X30_MI2S_CODEC_RX_M_CLK,
- L_7X30_MI2S_CODEC_RX_S_CLK,
- L_7X30_MI2S_CODEC_TX_M_CLK,
- L_7X30_MI2S_CODEC_TX_S_CLK,
- L_7X30_MI2S_M_CLK,
- L_7X30_MI2S_S_CLK,
- L_7X30_LPA_CODEC_CLK,
- L_7X30_LPA_CORE_CLK,
- L_7X30_LPA_P_CLK,
- L_7X30_MIDI_CLK,
- L_7X30_MDC_CLK,
- L_7X30_ROTATOR_IMEM_CLK,
- L_7X30_ROTATOR_P_CLK,
- L_7X30_SDAC_M_CLK,
- L_7X30_SDAC_CLK,
- L_7X30_UART1_CLK,
- L_7X30_UART2_CLK,
- L_7X30_UART3_CLK,
- L_7X30_TV_CLK,
- L_7X30_TV_DAC_CLK,
- L_7X30_TV_ENC_CLK,
- L_7X30_HDMI_CLK,
- L_7X30_TSIF_REF_CLK,
- L_7X30_TSIF_P_CLK,
- L_7X30_USB_HS_SRC_CLK,
- L_7X30_USB_HS_CLK,
- L_7X30_USB_HS_CORE_CLK,
- L_7X30_USB_HS_P_CLK,
- L_7X30_USB_HS2_CLK,
- L_7X30_USB_HS2_CORE_CLK,
- L_7X30_USB_HS2_P_CLK,
- L_7X30_USB_HS3_CLK,
- L_7X30_USB_HS3_CORE_CLK,
- L_7X30_USB_HS3_P_CLK,
- L_7X30_VFE_CLK,
- L_7X30_VFE_P_CLK,
- L_7X30_VFE_MDC_CLK,
- L_7X30_VFE_CAMIF_CLK,
- L_7X30_CAMIF_PAD_P_CLK,
- L_7X30_CAM_M_CLK,
- L_7X30_JPEG_CLK,
- L_7X30_JPEG_P_CLK,
- L_7X30_VPE_CLK,
- L_7X30_MFC_CLK,
- L_7X30_MFC_DIV2_CLK,
- L_7X30_MFC_P_CLK,
- L_7X30_SPI_CLK,
- L_7X30_SPI_P_CLK,
- L_7X30_CSI0_CLK,
- L_7X30_CSI0_VFE_CLK,
- L_7X30_CSI0_P_CLK,
- L_7X30_CSI1_CLK,
- L_7X30_CSI1_VFE_CLK,
- L_7X30_CSI1_P_CLK,
- L_7X30_GLBL_ROOT_CLK,
+ L_ADM_CLK,
+ L_ADM_P_CLK,
+ L_CE_CLK,
+ L_I2C_CLK,
+ L_I2C_2_CLK,
+ L_QUP_I2C_CLK,
+ L_UART1DM_CLK,
+ L_UART1DM_P_CLK,
+ L_UART2DM_CLK,
+ L_UART2DM_P_CLK,
+ L_EMDH_CLK,
+ L_EMDH_P_CLK,
+ L_PMDH_CLK,
+ L_PMDH_P_CLK,
+ L_GRP_2D_CLK,
+ L_GRP_2D_P_CLK,
+ L_GRP_3D_SRC_CLK,
+ L_GRP_3D_CLK,
+ L_GRP_3D_P_CLK,
+ L_IMEM_CLK,
+ L_SDC1_CLK,
+ L_SDC1_P_CLK,
+ L_SDC2_CLK,
+ L_SDC2_P_CLK,
+ L_SDC3_CLK,
+ L_SDC3_P_CLK,
+ L_SDC4_CLK,
+ L_SDC4_P_CLK,
+ L_MDP_CLK,
+ L_MDP_P_CLK,
+ L_MDP_LCDC_PCLK_CLK,
+ L_MDP_LCDC_PAD_PCLK_CLK,
+ L_MDP_VSYNC_CLK,
+ L_MI2S_CODEC_RX_M_CLK,
+ L_MI2S_CODEC_RX_S_CLK,
+ L_MI2S_CODEC_TX_M_CLK,
+ L_MI2S_CODEC_TX_S_CLK,
+ L_MI2S_M_CLK,
+ L_MI2S_S_CLK,
+ L_LPA_CODEC_CLK,
+ L_LPA_CORE_CLK,
+ L_LPA_P_CLK,
+ L_MIDI_CLK,
+ L_MDC_CLK,
+ L_ROTATOR_IMEM_CLK,
+ L_ROTATOR_P_CLK,
+ L_SDAC_M_CLK,
+ L_SDAC_CLK,
+ L_UART1_CLK,
+ L_UART2_CLK,
+ L_UART3_CLK,
+ L_TV_CLK,
+ L_TV_DAC_CLK,
+ L_TV_ENC_CLK,
+ L_HDMI_CLK,
+ L_TSIF_REF_CLK,
+ L_TSIF_P_CLK,
+ L_USB_HS_SRC_CLK,
+ L_USB_HS_CLK,
+ L_USB_HS_CORE_CLK,
+ L_USB_HS_P_CLK,
+ L_USB_HS2_CLK,
+ L_USB_HS2_CORE_CLK,
+ L_USB_HS2_P_CLK,
+ L_USB_HS3_CLK,
+ L_USB_HS3_CORE_CLK,
+ L_USB_HS3_P_CLK,
+ L_VFE_CLK,
+ L_VFE_P_CLK,
+ L_VFE_MDC_CLK,
+ L_VFE_CAMIF_CLK,
+ L_CAMIF_PAD_P_CLK,
+ L_CAM_M_CLK,
+ L_JPEG_CLK,
+ L_JPEG_P_CLK,
+ L_VPE_CLK,
+ L_MFC_CLK,
+ L_MFC_DIV2_CLK,
+ L_MFC_P_CLK,
+ L_SPI_CLK,
+ L_SPI_P_CLK,
+ L_CSI0_CLK,
+ L_CSI0_VFE_CLK,
+ L_CSI0_P_CLK,
+ L_CSI1_CLK,
+ L_CSI1_VFE_CLK,
+ L_CSI1_P_CLK,
+ L_GLBL_ROOT_CLK,
- L_7X30_AXI_LI_VG_CLK,
- L_7X30_AXI_LI_GRP_CLK,
- L_7X30_AXI_LI_JPEG_CLK,
- L_7X30_AXI_GRP_2D_CLK,
- L_7X30_AXI_MFC_CLK,
- L_7X30_AXI_VPE_CLK,
- L_7X30_AXI_LI_VFE_CLK,
- L_7X30_AXI_LI_APPS_CLK,
- L_7X30_AXI_MDP_CLK,
- L_7X30_AXI_IMEM_CLK,
- L_7X30_AXI_LI_ADSP_A_CLK,
- L_7X30_AXI_ROTATOR_CLK,
+ L_AXI_LI_VG_CLK,
+ L_AXI_LI_GRP_CLK,
+ L_AXI_LI_JPEG_CLK,
+ L_AXI_GRP_2D_CLK,
+ L_AXI_MFC_CLK,
+ L_AXI_VPE_CLK,
+ L_AXI_LI_VFE_CLK,
+ L_AXI_LI_APPS_CLK,
+ L_AXI_MDP_CLK,
+ L_AXI_IMEM_CLK,
+ L_AXI_LI_ADSP_A_CLK,
+ L_AXI_ROTATOR_CLK,
- L_7X30_NR_CLKS
+ L_NR_CLKS
};
-void pll_enable(uint32_t pll);
-void pll_disable(uint32_t pll);
-
-enum {
+enum clk_sources {
PLL_0 = 0,
PLL_1,
PLL_2,
@@ -148,22 +144,18 @@ enum {
PLL_4,
PLL_5,
PLL_6,
- NUM_PLL
-};
-
-enum {
- LOW,
- NOMINAL,
- HIGH,
- MSMC1_END
+ AXI,
+ LPXO,
+ TCXO,
+ NUM_SRC
};
extern int internal_pwr_rail_ctl_auto(unsigned rail_id, bool enable);
-extern struct clk_ops clk_ops_7x30;
+extern struct clk_ops soc_clk_ops_7x30;
#define CLK_7X30(clk_name, clk_id, clk_dev, clk_flags) { \
.name = clk_name, \
- .id = L_7X30_##clk_id, \
+ .id = L_##clk_id, \
.remote_id = P_##clk_id, \
.flags = clk_flags, \
.dev = clk_dev, \
@@ -172,7 +164,7 @@ extern struct clk_ops clk_ops_7x30;
#define CLK_7X30S(clk_name, l_id, r_id, clk_dev, clk_flags) { \
.name = clk_name, \
- .id = L_7X30_##l_id, \
+ .id = L_##l_id, \
.remote_id = P_##r_id, \
.flags = clk_flags, \
.dev = clk_dev, \
@@ -181,11 +173,11 @@ extern struct clk_ops clk_ops_7x30;
#define CLK_7X30L(clk_name, l_id, clk_dev, clk_flags) { \
.name = clk_name, \
- .id = L_7X30_##l_id, \
+ .id = L_##l_id, \
.flags = clk_flags, \
.dev = clk_dev, \
.dbg_name = #l_id, \
- .ops = &clk_ops_7x30, \
+ .ops = &soc_clk_ops_7x30, \
}
#endif
diff --git a/arch/arm/mach-msm/clock-local.c b/arch/arm/mach-msm/clock-local.c
new file mode 100644
index 0000000..d6eb6c6
--- /dev/null
+++ b/arch/arm/mach-msm/clock-local.c
@@ -0,0 +1,679 @@
+/* Copyright (c) 2009-2010, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/err.h>
+#include <linux/ctype.h>
+#include <linux/bitops.h>
+#include <linux/io.h>
+#include <linux/spinlock.h>
+#include <linux/delay.h>
+#include <mach/msm_iomap.h>
+#include <mach/clk.h>
+
+#include "clock.h"
+#include "clock-local.h"
+
+/* When enabling/disabling a clock, check the halt bit up to this number
+ * number of times (with a 1 us delay in between) before continuing. */
+#define HALT_CHECK_MAX_LOOPS 100
+/* For clock without halt checking, wait this long after enables/disables. */
+#define HALT_CHECK_DELAY_US 10
+
+DEFINE_SPINLOCK(local_clock_reg_lock);
+struct clk_freq_tbl local_dummy_freq = F_END;
+
+#define MAX_SOURCES 20
+static int src_votes[MAX_SOURCES];
+static DEFINE_SPINLOCK(src_vote_lock);
+
+unsigned local_sys_vdd_votes[NUM_SYS_VDD_LEVELS];
+static DEFINE_SPINLOCK(sys_vdd_vote_lock);
+
+static int local_clk_enable_nolock(unsigned id);
+static int local_clk_disable_nolock(unsigned id);
+static int local_src_enable_nolock(int src);
+static int local_src_disable_nolock(int src);
+
+/*
+ * Common Set-Rate Functions
+ */
+/* For clocks with integer dividers only. */
+void set_rate_basic(struct clk_local *clk, struct clk_freq_tbl *nf)
+{
+ uint32_t reg_val;
+
+ reg_val = readl(clk->ns_reg);
+ reg_val &= ~(clk->ns_mask);
+ reg_val |= nf->ns_val;
+ writel(reg_val, clk->ns_reg);
+}
+
+/* For clocks with MND dividers. */
+void set_rate_mnd(struct clk_local *clk, struct clk_freq_tbl *nf)
+{
+ uint32_t ns_reg_val, cc_reg_val;
+
+ /* Assert MND reset. */
+ ns_reg_val = readl(clk->ns_reg);
+ ns_reg_val |= B(7);
+ writel(ns_reg_val, clk->ns_reg);
+
+ /* Program M and D values. */
+ writel(nf->md_val, clk->md_reg);
+
+ /* Program NS register. */
+ ns_reg_val &= ~(clk->ns_mask);
+ ns_reg_val |= nf->ns_val;
+ writel(ns_reg_val, clk->ns_reg);
+
+ /* If the clock has a separate CC register, program it. */
+ if (clk->ns_reg != clk->cc_reg) {
+ cc_reg_val = readl(clk->cc_reg);
+ cc_reg_val &= ~(clk->cc_mask);
+ cc_reg_val |= nf->cc_val;
+ writel(cc_reg_val, clk->cc_reg);
+ }
+
+ /* Deassert MND reset. */
+ ns_reg_val &= ~B(7);
+ writel(ns_reg_val, clk->ns_reg);
+}
+
+void set_rate_nop(struct clk_local *clk, struct clk_freq_tbl *nf)
+{
+ /* Nothing to do for fixed-rate clocks. */
+}
+
+/*
+ * SYS_VDD voting functions
+ */
+
+/* Update system voltage level given the current votes. */
+static int local_update_sys_vdd(void)
+{
+ static int cur_level = NUM_SYS_VDD_LEVELS;
+ int level, rc = 0;
+
+ if (local_sys_vdd_votes[HIGH])
+ level = HIGH;
+ else if (local_sys_vdd_votes[NOMINAL])
+ level = NOMINAL;
+ else if (local_sys_vdd_votes[LOW])
+ level = LOW;
+ else
+ level = NONE;
+
+ if (level == cur_level)
+ return rc;
+
+ rc = soc_update_sys_vdd(level);
+ if (!rc)
+ cur_level = level;
+
+ return rc;
+}
+
+/* Vote for a system voltage level. */
+int local_vote_sys_vdd(unsigned level)
+{
+ int rc = 0;
+ unsigned long flags;
+
+ /* Bounds checking. */
+ if (level >= ARRAY_SIZE(local_sys_vdd_votes))
+ return -EINVAL;
+
+ spin_lock_irqsave(&sys_vdd_vote_lock, flags);
+ local_sys_vdd_votes[level]++;
+ rc = local_update_sys_vdd();
+ if (rc)
+ local_sys_vdd_votes[level]--;
+ spin_unlock_irqrestore(&sys_vdd_vote_lock, flags);
+
+ return rc;
+}
+
+/* Remove vote for a system voltage level. */
+int local_unvote_sys_vdd(unsigned level)
+{
+ int rc = 0;
+ unsigned long flags;
+
+ /* Bounds checking. */
+ if (level >= ARRAY_SIZE(local_sys_vdd_votes))
+ return -EINVAL;
+
+ spin_lock_irqsave(&sys_vdd_vote_lock, flags);
+ if (local_sys_vdd_votes[level])
+ local_sys_vdd_votes[level]--;
+ else {
+ pr_warning("%s: Reference counts are incorrect for level %d!\n",
+ __func__, level);
+ goto out;
+ }
+
+ rc = local_update_sys_vdd();
+ if (rc)
+ local_sys_vdd_votes[level]++;
+out:
+ spin_unlock_irqrestore(&sys_vdd_vote_lock, flags);
+ return rc;
+}
+
+/*
+ * Clock source (PLL/XO) control functions
+ */
+
+/* Enable clock source without taking the lock. */
+static int local_src_enable_nolock(int src)
+{
+ int rc = 0;
+
+ if (!src_votes[src]) {
+ if (soc_clk_sources[src].par != SRC_NONE)
+ rc = local_src_enable_nolock(soc_clk_sources[src].par);
+ if (rc)
+ goto err_par;
+ /* Perform source-specific enable operations. */
+ if (soc_clk_sources[src].enable_func)
+ rc = soc_clk_sources[src].enable_func(src, 1);
+ if (rc)
+ goto err_enable;
+ }
+ src_votes[src]++;
+
+ return rc;
+
+err_enable:
+ if (soc_clk_sources[src].par != SRC_NONE)
+ local_src_disable_nolock(soc_clk_sources[src].par);
+err_par:
+ return rc;
+}
+
+/* Enable clock source. */
+int local_src_enable(int src)
+{
+ int rc = 0;
+ unsigned long flags;
+
+ if (src == SRC_NONE)
+ return rc;
+
+ spin_lock_irqsave(&src_vote_lock, flags);
+ rc = local_src_enable_nolock(src);
+ spin_unlock_irqrestore(&src_vote_lock, flags);
+
+ return rc;
+}
+
+/* Disable clock source without taking the lock. */
+static int local_src_disable_nolock(int src)
+{
+ int rc = 0;
+
+ if (src_votes[src] > 0)
+ src_votes[src]--;
+ else {
+ pr_warning("%s: Reference counts are incorrect for "
+ "src %d!\n", __func__, src);
+ return rc;
+ }
+
+ if (src_votes[src] == 0) {
+ /* Perform source-specific disable operations. */
+ if (soc_clk_sources[src].enable_func)
+ rc = soc_clk_sources[src].enable_func(src, 0);
+ if (rc)
+ goto err_disable;
+ if (soc_clk_sources[src].par != SRC_NONE)
+ rc = local_src_disable_nolock(soc_clk_sources[src].par);
+ if (rc)
+ goto err_disable_par;
+
+ }
+
+ return rc;
+
+err_disable_par:
+ soc_clk_sources[src].enable_func(src, 1);
+err_disable:
+ src_votes[src]++;
+ return rc;
+}
+
+/* Disable clock source. */
+int local_src_disable(int src)
+{
+ int rc = 0;
+ unsigned long flags;
+
+ if (src == SRC_NONE)
+ return rc;
+
+ spin_lock_irqsave(&src_vote_lock, flags);
+ rc = local_src_disable_nolock(src);
+ spin_unlock_irqrestore(&src_vote_lock, flags);
+
+ return rc;
+}
+
+/*
+ * Clock enable/disable functions
+ */
+
+/* Return non-zero if a clock status registers shows the clock is halted. */
+static int local_clk_is_halted(unsigned id)
+{
+ struct clk_local *clk = &soc_clk_local_tbl[id];
+ int invert = (clk->halt_check == ENABLE);
+ int status_bit = readl(clk->halt_reg) & B(clk->halt_bit);
+ return invert ? !status_bit : status_bit;
+}
+
+/* Perform any register operations required to enable the clock. */
+void local_clk_enable_reg(unsigned id)
+{
+ struct clk_local *clk = &soc_clk_local_tbl[id];
+ void *reg = clk->cc_reg;
+ uint32_t reg_val;
+
+ WARN((clk->type != NORATE) && (clk->current_freq == &local_dummy_freq),
+ "Attempting to enable clock %d before setting its rate. "
+ "Set the rate first!\n", id);
+
+ /* Enable MN counter, if applicable. */
+ reg_val = readl(reg);
+ if (clk->type == MND) {
+ reg_val |= clk->current_freq->mnd_en_mask;
+ writel(reg_val, reg);
+ }
+ /* Enable root. */
+ if (clk->root_en_mask) {
+ reg_val |= clk->root_en_mask;
+ writel(reg_val, reg);
+ }
+ /* Enable branch. */
+ if (clk->br_en_mask) {
+ reg_val |= clk->br_en_mask;
+ writel(reg_val, reg);
+ }
+
+ /* Wait for clock to enable before returning. */
+ if (clk->halt_check == DELAY)
+ udelay(HALT_CHECK_DELAY_US);
+ else if (clk->halt_check == ENABLE || clk->halt_check == HALT
+ || clk->halt_check == ENABLE_VOTED
+ || clk->halt_check == HALT_VOTED) {
+ int count;
+
+ /* Wait up to HALT_CHECK_MAX_LOOPS for clock to enable. */
+ for (count = HALT_CHECK_MAX_LOOPS; local_clk_is_halted(id)
+ && count > 0; count--)
+ udelay(1);
+ if (count == 0)
+ pr_warning("%s: clock %d status stuck at 'off' (bit %d "
+ "of 0x%p).\n", __func__, id, clk->halt_bit,
+ clk->halt_reg);
+ }
+}
+
+/* Perform any register operations required to enable the clock. */
+void local_clk_disable_reg(unsigned id)
+{
+ struct clk_local *clk = &soc_clk_local_tbl[id];
+ void *reg = clk->cc_reg;
+ uint32_t reg_val;
+
+ /* Disable branch. */
+ reg_val = readl(reg);
+ if (clk->br_en_mask) {
+ reg_val &= ~(clk->br_en_mask);
+ writel(reg_val, reg);
+ }
+
+ /* Wait for clock to disable before continuing. */
+ if (clk->halt_check == DELAY || clk->halt_check == ENABLE_VOTED
+ || clk->halt_check == HALT_VOTED)
+ udelay(HALT_CHECK_DELAY_US);
+ else if (clk->halt_check == ENABLE || clk->halt_check == HALT) {
+ int count;
+
+ /* Wait up to HALT_CHECK_MAX_LOOPS for clock to disable. */
+ for (count = HALT_CHECK_MAX_LOOPS; !local_clk_is_halted(id)
+ && count > 0; count--)
+ udelay(1);
+ if (count == 0)
+ pr_warning("%s: clock %d status stuck at 'on' (bit %d "
+ "of 0x%p).\n", __func__, id, clk->halt_bit,
+ clk->halt_reg);
+ }
+
+ /* Disable root. */
+ if (clk->root_en_mask) {
+ reg_val &= ~(clk->root_en_mask);
+ writel(reg_val, reg);
+ }
+ /* Disable MN counter, if applicable. */
+ if (clk->type == MND) {
+ reg_val &= ~(clk->current_freq->mnd_en_mask);
+ writel(reg_val, reg);
+ }
+}
+
+/* Enable a clock with no locking, enabling parent clocks as needed. */
+static int local_clk_enable_nolock(unsigned id)
+{
+ struct clk_local *clk = &soc_clk_local_tbl[id];
+ int rc = 0;
+
+ if (clk->type == RESET)
+ return -EPERM;
+
+ if (!clk->count) {
+ rc = local_vote_sys_vdd(clk->current_freq->sys_vdd);
+ if (rc)
+ goto err_vdd;
+ if (clk->parent != C(NONE)) {
+ rc = local_clk_enable_nolock(clk->parent);
+ if (rc)
+ goto err_par;
+ }
+ rc = local_src_enable(clk->current_freq->src);
+ if (rc)
+ goto err_src;
+ local_clk_enable_reg(id);
+ }
+ clk->count++;
+
+ return rc;
+
+err_src:
+ if (clk->parent != C(NONE))
+ rc = local_clk_disable_nolock(clk->parent);
+err_par:
+ local_unvote_sys_vdd(clk->current_freq->sys_vdd);
+err_vdd:
+ return rc;
+}
+
+/* Disable a clock with no locking, disabling unused parents, too. */
+static int local_clk_disable_nolock(unsigned id)
+{
+ struct clk_local *clk = &soc_clk_local_tbl[id];
+ int rc = 0;
+
+ if (clk->count > 0)
+ clk->count--;
+ else {
+ pr_warning("%s: Reference counts are incorrect for clock %d!\n",
+ __func__, id);
+ return rc;
+ }
+
+ if (clk->count == 0) {
+ local_clk_disable_reg(id);
+ rc = local_src_disable(clk->current_freq->src);
+ if (rc)
+ goto err_src;
+ if (clk->parent != C(NONE))
+ rc = local_clk_disable_nolock(clk->parent);
+ if (rc)
+ goto err_par;
+ rc = local_unvote_sys_vdd(clk->current_freq->sys_vdd);
+ if (rc)
+ goto err_vdd;
+ }
+
+ return rc;
+
+err_vdd:
+ if (clk->parent != C(NONE))
+ rc = local_clk_enable_nolock(clk->parent);
+err_par:
+ local_src_enable(clk->current_freq->src);
+err_src:
+ local_clk_enable_reg(id);
+ clk->count++;
+
+ return rc;
+}
+
+/* Enable a clock and any related power rail. */
+int local_clk_enable(unsigned id)
+{
+ int rc = 0;
+ unsigned long flags;
+
+ spin_lock_irqsave(&local_clock_reg_lock, flags);
+ rc = local_clk_enable_nolock(id);
+ if (rc)
+ goto unlock;
+ /*
+ * With remote rail control, the remote processor might modify
+ * the clock control register when the rail is enabled/disabled.
+ * Enable the rail inside the lock to protect against this.
+ */
+ rc = soc_set_pwr_rail(id, 1);
+ if (rc)
+ local_clk_disable_nolock(id);
+unlock:
+ spin_unlock_irqrestore(&local_clock_reg_lock, flags);
+
+ return rc;
+}
+
+/* Disable a clock and any related power rail. */
+void local_clk_disable(unsigned id)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&local_clock_reg_lock, flags);
+ soc_set_pwr_rail(id, 0);
+ local_clk_disable_nolock(id);
+ spin_unlock_irqrestore(&local_clock_reg_lock, flags);
+}
+
+/* Turn off a clock at boot, without checking refcounts or disabling parents. */
+void local_clk_auto_off(unsigned id)
+{
+ struct clk_local *clk = &soc_clk_local_tbl[id];
+ unsigned long flags;
+
+ if (clk->type == RESET)
+ return;
+
+ spin_lock_irqsave(&local_clock_reg_lock, flags);
+ local_clk_disable_reg(id);
+ spin_unlock_irqrestore(&local_clock_reg_lock, flags);
+}
+
+/*
+ * Frequency-related functions
+ */
+
+/* Set a clock's frequency. */
+static int _local_clk_set_rate(unsigned id, struct clk_freq_tbl *nf)
+{
+ struct clk_local *clk = &soc_clk_local_tbl[id];
+ struct clk_freq_tbl *cf;
+ const int32_t *chld = clk->children;
+ int i, rc = 0;
+ unsigned long flags;
+
+ spin_lock_irqsave(&local_clock_reg_lock, flags);
+
+ /* Check if frequency is actually changed. */
+ cf = clk->current_freq;
+ if (nf == cf)
+ goto release_lock;
+
+ /* Disable branch if clock isn't dual-banked with a glitch-free MUX. */
+ if (clk->banked_mnd_masks == NULL) {
+ /* Disable all branches to prevent glitches. */
+ for (i = 0; chld && chld[i] != C(NONE); i++) {
+ struct clk_local *ch = &soc_clk_local_tbl[chld[i]];
+ /* Don't bother turning off if it is already off.
+ * Checking ch->count is cheaper (cache) than reading
+ * and writing to a register (uncached/unbuffered). */
+ if (ch->count)
+ local_clk_disable_reg(chld[i]);
+ }
+ if (clk->count)
+ local_clk_disable_reg(id);
+ }
+
+ if (clk->count) {
+ /* Vote for voltage and source for new freq. */
+ rc = local_vote_sys_vdd(nf->sys_vdd);
+ if (rc)
+ goto sys_vdd_vote_failed;
+ rc = local_src_enable(nf->src);
+ if (rc) {
+ local_unvote_sys_vdd(nf->sys_vdd);
+ goto src_enable_failed;
+ }
+ }
+
+ /* Perform clock-specific frequency switch operations. */
+ BUG_ON(!clk->set_rate);
+ clk->set_rate(clk, nf);
+
+ /* Release requirements of the old freq. */
+ if (clk->count) {
+ local_src_disable(cf->src);
+ local_unvote_sys_vdd(cf->sys_vdd);
+ }
+
+ /* Current freq must be updated before local_clk_enable_reg()
+ * is called to make sure the MNCNTR_EN bit is set correctly. */
+ clk->current_freq = nf;
+
+src_enable_failed:
+sys_vdd_vote_failed:
+ /* Enable any clocks that were disabled. */
+ if (clk->banked_mnd_masks == NULL) {
+ if (clk->count)
+ local_clk_enable_reg(id);
+ /* Enable only branches that were ON before. */
+ for (i = 0; chld && chld[i] != C(NONE); i++) {
+ struct clk_local *ch = &soc_clk_local_tbl[chld[i]];
+ if (ch->count)
+ local_clk_enable_reg(chld[i]);
+ }
+ }
+
+release_lock:
+ spin_unlock_irqrestore(&local_clock_reg_lock, flags);
+ return rc;
+}
+
+/* Set a clock to an exact rate. */
+int local_clk_set_rate(unsigned id, unsigned rate)
+{
+ struct clk_local *clk = &soc_clk_local_tbl[id];
+ struct clk_freq_tbl *nf;
+
+ if (clk->type == NORATE || clk->type == RESET)
+ return -EPERM;
+
+ for (nf = clk->freq_tbl; nf->freq_hz != FREQ_END
+ && nf->freq_hz != rate; nf++)
+ ;
+
+ if (nf->freq_hz == FREQ_END)
+ return -EINVAL;
+
+ return _local_clk_set_rate(id, nf);
+}
+
+/* Set a clock to a rate greater than some minimum. */
+int local_clk_set_min_rate(unsigned id, unsigned rate)
+{
+ struct clk_local *clk = &soc_clk_local_tbl[id];
+ struct clk_freq_tbl *nf;
+
+ if (clk->type == NORATE || clk->type == RESET)
+ return -EPERM;
+
+ for (nf = clk->freq_tbl; nf->freq_hz != FREQ_END
+ && nf->freq_hz < rate; nf++)
+ ;
+
+ if (nf->freq_hz == FREQ_END)
+ return -EINVAL;
+
+ return _local_clk_set_rate(id, nf);
+}
+
+/* Set a clock to a maximum rate. */
+int local_clk_set_max_rate(unsigned id, unsigned rate)
+{
+ return -EPERM;
+}
+
+/* Get the currently-set rate of a clock in Hz. */
+unsigned local_clk_get_rate(unsigned id)
+{
+ struct clk_local *clk = &soc_clk_local_tbl[id];
+ unsigned long flags;
+ unsigned ret = 0;
+
+ if (clk->type == NORATE || clk->type == RESET)
+ return 0;
+
+ spin_lock_irqsave(&local_clock_reg_lock, flags);
+ ret = clk->current_freq->freq_hz;
+ spin_unlock_irqrestore(&local_clock_reg_lock, flags);
+
+ /* Return 0 if the rate has never been set. Might not be correct,
+ * but it's good enough. */
+ if (ret == FREQ_END)
+ ret = 0;
+
+ return ret;
+}
+
+/* Check if a clock is currently enabled. */
+unsigned local_clk_is_enabled(unsigned id)
+{
+ struct clk_local *clk = &soc_clk_local_tbl[id];
+
+ if (clk->type == RESET)
+ return -EPERM;
+
+ return !!(soc_clk_local_tbl[id].count);
+}
+
+/* Return a supported rate that's at least the specified rate. */
+long local_clk_round_rate(unsigned id, unsigned rate)
+{
+ struct clk_local *clk = &soc_clk_local_tbl[id];
+ struct clk_freq_tbl *f;
+
+ if (clk->type == NORATE || clk->type == RESET)
+ return -EINVAL;
+
+ for (f = clk->freq_tbl; f->freq_hz != FREQ_END; f++)
+ if (f->freq_hz >= rate)
+ return f->freq_hz;
+
+ return -EPERM;
+}
diff --git a/arch/arm/mach-msm/clock-local.h b/arch/arm/mach-msm/clock-local.h
new file mode 100644
index 0000000..ebefad5
--- /dev/null
+++ b/arch/arm/mach-msm/clock-local.h
@@ -0,0 +1,232 @@
+/* Copyright (c) 2009-2010, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ *
+ */
+
+#ifndef __ARCH_ARM_MACH_MSM_CLOCK_LOCAL_H
+#define __ARCH_ARM_MACH_MSM_CLOCK_LOCAL_H
+
+#include <linux/spinlock.h>
+#include "clock.h"
+
+/*
+ * Bit manipulation macros
+ */
+#define B(x) BIT(x)
+#define BM(msb, lsb) (((((uint32_t)-1) << (31-msb)) >> (31-msb+lsb)) << lsb)
+#define BVAL(msb, lsb, val) (((val) << lsb) & BM(msb, lsb))
+
+/*
+ * Clock types
+ */
+#define MND 1 /* Integer predivider and fractional MN:D divider. */
+#define BASIC 2 /* Integer divider. */
+#define NORATE 3 /* Just on/off. */
+#define RESET 4 /* Reset only. */
+
+/*
+ * IDs for invalid sources, source selects, and XOs
+ */
+#define SRC_NONE -1
+#define SRC_SEL_NONE -1
+#define XO_NONE -1
+
+/*
+ * Halt/Status Checking Mode Macros
+ */
+#define NOCHECK 0 /* No bit to check, do nothing */
+#define HALT 1 /* Bit pol: 1 = halted */
+#define HALT_VOTED 2 /* Bit pol: 1 = halted; delay on disable */
+#define ENABLE 3 /* Bit pol: 1 = running */
+#define ENABLE_VOTED 4 /* Bit pol: 1 = running; delay on disable */
+#define DELAY 5 /* No bit to check, just delay */
+
+/*
+ * Generic frequency-definition structs and macros
+ */
+struct clk_freq_tbl {
+ const uint32_t freq_hz;
+ const int src;
+ const uint32_t md_val;
+ const uint32_t ns_val;
+ const uint32_t cc_val;
+ uint32_t mnd_en_mask;
+ const unsigned sys_vdd;
+ void *const extra_freq_data;
+};
+
+/* Some clocks have two banks to avoid glitches when switching frequencies.
+ * The unused bank is programmed while running on the other bank, and
+ * switched to afterwards. The following two structs describe the banks. */
+struct bank_mask_info {
+ void *const md_reg;
+ const uint32_t ns_mask;
+ const uint32_t rst_mask;
+ const uint32_t mnd_en_mask;
+ const uint32_t mode_mask;
+};
+
+struct banked_mnd_masks {
+ const uint32_t bank_sel_mask;
+ const struct bank_mask_info bank0_mask;
+ const struct bank_mask_info bank1_mask;
+};
+
+#define F_RAW(f, s, m_v, n_v, c_v, m_m, v, e) { \
+ .freq_hz = f, \
+ .src = s, \
+ .md_val = m_v, \
+ .ns_val = n_v, \
+ .cc_val = c_v, \
+ .mnd_en_mask = m_m, \
+ .sys_vdd = v, \
+ .extra_freq_data = e, \
+ }
+#define FREQ_END (UINT_MAX-1)
+#define F_END F_RAW(FREQ_END, SRC_NONE, 0, 0, 0, 0, LOW, NULL)
+#define PLL_RATE(l, m, n, v, d) { l, m, n, v, (d>>1) }
+
+/*
+ * Generic clock-definition struct and macros
+ */
+struct clk_local {
+ int count;
+ const uint32_t type;
+ void *const ns_reg;
+ void *const cc_reg;
+ void *const md_reg;
+ void *const reset_reg;
+ void *const halt_reg;
+ const uint32_t reset_mask;
+ const uint16_t halt_check;
+ const uint16_t halt_bit;
+ const uint32_t br_en_mask;
+ const uint32_t root_en_mask;
+ const uint32_t ns_mask;
+ const uint32_t cc_mask;
+ const uint32_t test_vector;
+ struct banked_mnd_masks *const banked_mnd_masks;
+ const int parent;
+ const uint32_t *const children;
+ void (*set_rate)(struct clk_local *, struct clk_freq_tbl *);
+ struct clk_freq_tbl *const freq_tbl;
+ struct clk_freq_tbl *current_freq;
+};
+
+#define C(x) L_##x##_CLK
+#define L_NONE_CLK -1
+#define CLK(id, t, ns_r, cc_r, md_r, r_r, r_m, h_r, h_c, h_b, br, root, \
+ n_m, c_m, s_fn, tbl, bmnd, par, chld_lst, tv) \
+ [C(id)] = { \
+ .type = t, \
+ .ns_reg = ns_r, \
+ .cc_reg = cc_r, \
+ .md_reg = md_r, \
+ .reset_reg = r_r, \
+ .halt_reg = h_r, \
+ .halt_check = h_c, \
+ .halt_bit = h_b, \
+ .reset_mask = r_m, \
+ .br_en_mask = br, \
+ .root_en_mask = root, \
+ .ns_mask = n_m, \
+ .cc_mask = c_m, \
+ .test_vector = tv, \
+ .banked_mnd_masks = bmnd, \
+ .parent = C(par), \
+ .children = chld_lst, \
+ .set_rate = s_fn, \
+ .freq_tbl = tbl, \
+ .current_freq = &local_dummy_freq, \
+ }
+
+/*
+ * Convenience macros
+ */
+#define set_1rate(clk) \
+ local_clk_set_rate(C(clk), soc_clk_local_tbl[C(clk)].freq_tbl->freq_hz)
+
+/*
+ * SYS_VDD voltage levels
+ */
+enum sys_vdd_level {
+ NONE,
+ LOW,
+ NOMINAL,
+ HIGH,
+ NUM_SYS_VDD_LEVELS
+};
+
+/*
+ * Clock source descriptions
+ */
+struct clk_source {
+ int (*enable_func)(unsigned src, unsigned enable);
+ const signed par;
+};
+
+/*
+ * Variables from SoC-specific clock drivers
+ */
+extern struct clk_local soc_clk_local_tbl[];
+extern struct clk_source soc_clk_sources[];
+
+/*
+ * Variables from clock-local driver
+ */
+extern spinlock_t local_clock_reg_lock;
+extern struct clk_freq_tbl local_dummy_freq;
+
+/*
+ * Local-clock APIs
+ */
+int local_src_enable(int src);
+int local_src_disable(int src);
+void local_clk_enable_reg(unsigned id);
+void local_clk_disable_reg(unsigned id);
+int local_vote_sys_vdd(enum sys_vdd_level level);
+int local_unvote_sys_vdd(enum sys_vdd_level level);
+
+/*
+ * clk_ops APIs
+ */
+int local_clk_enable(unsigned id);
+void local_clk_disable(unsigned id);
+void local_clk_auto_off(unsigned id);
+int local_clk_set_rate(unsigned id, unsigned rate);
+int local_clk_set_min_rate(unsigned id, unsigned rate);
+int local_clk_set_max_rate(unsigned id, unsigned rate);
+unsigned local_clk_get_rate(unsigned id);
+unsigned local_clk_is_enabled(unsigned id);
+long local_clk_round_rate(unsigned id, unsigned rate);
+
+/*
+ * Required SoC-specific functions, implemented for every supported SoC
+ */
+int soc_update_sys_vdd(enum sys_vdd_level level);
+int soc_set_pwr_rail(unsigned id, int enable);
+int soc_clk_set_flags(unsigned id, unsigned flags);
+int soc_clk_reset(unsigned id, enum clk_reset_action action);
+
+/*
+ * Generic set-rate implementations
+ */
+void set_rate_basic(struct clk_local *clk, struct clk_freq_tbl *nf);
+void set_rate_mnd(struct clk_local *clk, struct clk_freq_tbl *nf);
+void set_rate_nop(struct clk_local *clk, struct clk_freq_tbl *nf);
+
+#endif /* __ARCH_ARM_MACH_MSM_CLOCK_LOCAL_H */
+
--
Sent by an employee of the Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum.
^ permalink raw reply related [flat|nested] 23+ messages in thread* [PATCH 08/22] msm: clock-8x60: Add msm8x60 local clock driver
2010-12-17 0:49 [PATCH 00/22] MSM clock driver updates Stephen Boyd
` (6 preceding siblings ...)
2010-12-17 0:49 ` [PATCH 07/22] msm: clock: Refactor clock-7x30 into generic clock-local driver Stephen Boyd
@ 2010-12-17 0:49 ` Stephen Boyd
2010-12-17 0:49 ` [PATCH 09/22] msm: clock: Remove references to clk_ops_pcom Stephen Boyd
` (13 subsequent siblings)
21 siblings, 0 replies; 23+ messages in thread
From: Stephen Boyd @ 2010-12-17 0:49 UTC (permalink / raw)
To: linux-arm-kernel
From: Matt Wagantall <mattw@codeaurora.org>
Use the clock-local framework to implement the APIs necessary for
configuring the msm8x60's peripheral and multimedia clocks.
This includes support for clock gating, managing PLL and XO
source requirements, and setting rates. The driver also applies
any voltage constraints associated with the frequencies, and
provides a means of asserting reset signals for the clock
domains.
Tables of discrete frequency levels are used to ensure rates with
minimal jitter, power requirements, and interference potential
are used whenever possible, though the tables are extensible.
Reviewed-by: Saravana Kannan <skannan@codeaurora.org>
Signed-off-by: Matt Wagantall <mattw@codeaurora.org>
Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
---
arch/arm/mach-msm/Makefile | 2 +
arch/arm/mach-msm/clock-8x60.c | 1802 +++++++++++++++++++++++
arch/arm/mach-msm/clock-8x60.h | 216 +++
arch/arm/mach-msm/clock-local.h | 1 -
arch/arm/mach-msm/clock.h | 2 +-
arch/arm/mach-msm/include/mach/msm_iomap-8x60.h | 12 +
arch/arm/mach-msm/io.c | 3 +
7 files changed, 2036 insertions(+), 2 deletions(-)
create mode 100644 arch/arm/mach-msm/clock-8x60.c
create mode 100644 arch/arm/mach-msm/clock-8x60.h
diff --git a/arch/arm/mach-msm/Makefile b/arch/arm/mach-msm/Makefile
index 33f0c39..fa01510 100644
--- a/arch/arm/mach-msm/Makefile
+++ b/arch/arm/mach-msm/Makefile
@@ -3,7 +3,9 @@ ifdef CONFIG_MSM_PROC_COMM
obj-$(CONFIG_DEBUG_FS) += clock-debug.o
endif
obj-$(CONFIG_ARCH_MSM7X30) += clock-local.o
+obj-$(CONFIG_ARCH_MSM8X60) += clock-local.o
obj-$(CONFIG_ARCH_MSM7X30) += clock-7x30.o
+obj-$(CONFIG_ARCH_MSM8X60) += clock-8x60.o
ifndef CONFIG_ARCH_MSM8X60
obj-y += acpuclock-arm11.o
obj-y += dma.o
diff --git a/arch/arm/mach-msm/clock-8x60.c b/arch/arm/mach-msm/clock-8x60.c
new file mode 100644
index 0000000..5bbc8bb
--- /dev/null
+++ b/arch/arm/mach-msm/clock-8x60.c
@@ -0,0 +1,1802 @@
+/* Copyright (c) 2009-2010, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/err.h>
+#include <linux/ctype.h>
+#include <linux/bitops.h>
+#include <linux/io.h>
+#include <linux/spinlock.h>
+#include <linux/delay.h>
+#include <mach/msm_iomap.h>
+#include <mach/clk.h>
+
+#include "clock-local.h"
+#include "clock-8x60.h"
+
+#define REG(off) (MSM_CLK_CTL_BASE + (off))
+#define REG_MM(off) (MSM_MMSS_CLK_CTL_BASE + (off))
+#define REG_LPA(off) (MSM_LPASS_CLK_CTL_BASE + (off))
+
+/* Peripheral clock registers. */
+#define CE2_HCLK_CTL_REG REG(0x2740)
+#define CLK_HALT_CFPB_STATEA_REG REG(0x2FCC)
+#define CLK_HALT_CFPB_STATEB_REG REG(0x2FD0)
+#define CLK_HALT_CFPB_STATEC_REG REG(0x2FD4)
+#define CLK_HALT_DFAB_STATE_REG REG(0x2FC8)
+#define CLK_HALT_MSS_SMPSS_MISC_STATE_REG REG(0x2FDC)
+#define CLK_HALT_SFPB_MISC_STATE_REG REG(0x2FD8)
+#define CLK_TEST_REG REG(0x2FA0)
+#define GSBIn_HCLK_CTL_REG(n) REG(0x29C0+(0x20*((n)-1)))
+#define GSBIn_QUP_APPS_NS_REG(n) REG(0x29CC+(0x20*((n)-1)))
+#define GSBIn_RESET_REG(n) REG(0x29DC+(0x20*((n)-1)))
+#define GSBIn_UART_APPS_NS_REG(n) REG(0x29D4+(0x20*((n)-1)))
+#define PDM_CLK_NS_REG REG(0x2CC0)
+#define BB_PLL_ENA_SC0_REG REG(0x34C0)
+#define BB_PLL0_STATUS_REG REG(0x30D8)
+#define BB_PLL6_STATUS_REG REG(0x3118)
+#define BB_PLL8_L_VAL_REG REG(0x3144)
+#define BB_PLL8_M_VAL_REG REG(0x3148)
+#define BB_PLL8_MODE_REG REG(0x3140)
+#define BB_PLL8_N_VAL_REG REG(0x314C)
+#define BB_PLL8_STATUS_REG REG(0x3158)
+#define PLLTEST_PAD_CFG_REG REG(0x2FA4)
+#define PMEM_ACLK_CTL_REG REG(0x25A0)
+#define PPSS_HCLK_CTL_REG REG(0x2580)
+#define PRNG_CLK_NS_REG REG(0x2E80)
+#define RINGOSC_NS_REG REG(0x2DC0)
+#define RINGOSC_STATUS_REG REG(0x2DCC)
+#define RINGOSC_TCXO_CTL_REG REG(0x2DC4)
+#define SC0_U_CLK_BRANCH_ENA_VOTE_REG REG(0x3084)
+#define SDCn_APPS_CLK_NS_REG(n) REG(0x282C+(0x20*((n)-1)))
+#define SDCn_HCLK_CTL_REG(n) REG(0x2820+(0x20*((n)-1)))
+#define TSIF_HCLK_CTL_REG REG(0x2700)
+#define TSIF_REF_CLK_NS_REG REG(0x2710)
+#define TSSC_CLK_CTL_REG REG(0x2CA0)
+#define USB_FS1_HCLK_CTL_REG REG(0x2960)
+#define USB_FS1_RESET_REG REG(0x2974)
+#define USB_FS1_SYSTEM_CLK_CTL_REG REG(0x296C)
+#define USB_FS1_XCVR_FS_CLK_NS_REG REG(0x2968)
+#define USB_FS2_HCLK_CTL_REG REG(0x2980)
+#define USB_FS2_RESET_REG REG(0x2994)
+#define USB_FS2_SYSTEM_CLK_CLK_REG REG(0x298C)
+#define USB_FS2_XCVR_FS_CLK_NS_REG REG(0x2988)
+#define USB_HS1_HCLK_CTL_REG REG(0x2900)
+#define USB_HS1_XCVR_FS_CLK_NS REG(0x290C)
+#define USB_PHY0_RESET_REG REG(0x2E20)
+
+/* Multimedia clock registers. */
+#define AHB_EN_REG REG_MM(0x0008)
+#define AHB_EN2_REG REG_MM(0x0038)
+#define AHB_NS_REG REG_MM(0x0004)
+#define AXI_NS_REG REG_MM(0x0014)
+#define CAMCLK_NS_REG REG_MM(0x0148)
+#define CSI_CC_REG REG_MM(0x0040)
+#define CSI_NS_REG REG_MM(0x0048)
+#define DBG_BUS_VEC_A_REG REG_MM(0x01C8)
+#define DBG_BUS_VEC_B_REG REG_MM(0x01CC)
+#define DBG_BUS_VEC_C_REG REG_MM(0x01D0)
+#define DBG_BUS_VEC_D_REG REG_MM(0x01D4)
+#define DBG_BUS_VEC_E_REG REG_MM(0x01D8)
+#define DBG_BUS_VEC_F_REG REG_MM(0x01DC)
+#define DBG_BUS_VEC_H_REG REG_MM(0x01E4)
+#define DBG_CFG_REG_HS_REG REG_MM(0x01B4)
+#define DBG_CFG_REG_LS_REG REG_MM(0x01B8)
+#define GFX2D0_CC_REG REG_MM(0x0060)
+#define GFX2D0_MD0_REG REG_MM(0x0064)
+#define GFX2D0_MD1_REG REG_MM(0x0068)
+#define GFX2D0_NS_REG REG_MM(0x0070)
+#define GFX2D1_CC_REG REG_MM(0x0074)
+#define GFX2D1_MD0_REG REG_MM(0x0078)
+#define GFX2D1_MD1_REG REG_MM(0x006C)
+#define GFX2D1_NS_REG REG_MM(0x007C)
+#define GFX3D_CC_REG REG_MM(0x0080)
+#define GFX3D_MD0_REG REG_MM(0x0084)
+#define GFX3D_MD1_REG REG_MM(0x0088)
+#define GFX3D_NS_REG REG_MM(0x008C)
+#define IJPEG_CC_REG REG_MM(0x0098)
+#define IJPEG_NS_REG REG_MM(0x00A0)
+#define JPEGD_CC_REG REG_MM(0x00A4)
+#define JPEGD_NS_REG REG_MM(0x00AC)
+#define MAXI_EN_REG REG_MM(0x0018)
+#define MAXI_EN2_REG REG_MM(0x0020)
+#define MAXI_EN3_REG REG_MM(0x002C)
+#define MDP_CC_REG REG_MM(0x00C0)
+#define MDP_MD0_REG REG_MM(0x00C4)
+#define MDP_MD1_REG REG_MM(0x00C8)
+#define MDP_NS_REG REG_MM(0x00D0)
+#define MISC_CC_REG REG_MM(0x0058)
+#define MISC_CC2_REG REG_MM(0x005C)
+#define PIXEL_CC_REG REG_MM(0x00D4)
+#define PIXEL_CC2_REG REG_MM(0x0120)
+#define PIXEL_NS_REG REG_MM(0x00DC)
+#define MM_PLL0_CONFIG_REG REG_MM(0x0310)
+#define MM_PLL0_L_VAL_REG REG_MM(0x0304)
+#define MM_PLL0_M_VAL_REG REG_MM(0x0308)
+#define MM_PLL0_MODE_REG REG_MM(0x0300)
+#define MM_PLL0_N_VAL_REG REG_MM(0x030C)
+#define MM_PLL0_STATUS_REG REG_MM(0x0318)
+#define MM_PLL1_CONFIG_REG REG_MM(0x032C)
+#define MM_PLL1_L_VAL_REG REG_MM(0x0320)
+#define MM_PLL1_M_VAL_REG REG_MM(0x0324)
+#define MM_PLL1_MODE_REG REG_MM(0x031C)
+#define MM_PLL1_N_VAL_REG REG_MM(0x0328)
+#define MM_PLL1_STATUS_REG REG_MM(0x0334)
+#define MM_PLL2_CONFIG_REG REG_MM(0x0348)
+#define MM_PLL2_L_VAL_REG REG_MM(0x033C)
+#define MM_PLL2_M_VAL_REG REG_MM(0x0340)
+#define MM_PLL2_MODE_REG REG_MM(0x0338)
+#define MM_PLL2_N_VAL_REG REG_MM(0x0344)
+#define MM_PLL2_STATUS_REG REG_MM(0x0350)
+#define ROT_CC_REG REG_MM(0x00E0)
+#define ROT_NS_REG REG_MM(0x00E8)
+#define SAXI_EN_REG REG_MM(0x0030)
+#define SW_RESET_AHB_REG REG_MM(0x020C)
+#define SW_RESET_ALL_REG REG_MM(0x0204)
+#define SW_RESET_AXI_REG REG_MM(0x0208)
+#define SW_RESET_CORE_REG REG_MM(0x0210)
+#define TV_CC_REG REG_MM(0x00EC)
+#define TV_CC2_REG REG_MM(0x0124)
+#define TV_NS_REG REG_MM(0x00F4)
+#define VCODEC_CC_REG REG_MM(0x00F8)
+#define VCODEC_MD0_REG REG_MM(0x00FC)
+#define VCODEC_MD1_REG REG_MM(0x0128)
+#define VCODEC_NS_REG REG_MM(0x0100)
+#define VFE_CC_REG REG_MM(0x0104)
+#define VFE_NS_REG REG_MM(0x010C)
+#define VPE_CC_REG REG_MM(0x0110)
+#define VPE_NS_REG REG_MM(0x0118)
+
+/* Low-power Audio clock registers. */
+#define LCC_CLK_LS_DEBUG_CFG_REG REG_LPA(0x00A8)
+#define LCC_CODEC_I2S_MIC_NS_REG REG_LPA(0x0060)
+#define LCC_CODEC_I2S_MIC_STATUS_REG REG_LPA(0x0068)
+#define LCC_CODEC_I2S_SPKR_NS_REG REG_LPA(0x006C)
+#define LCC_CODEC_I2S_SPKR_STATUS_REG REG_LPA(0x0074)
+#define LCC_MI2S_NS_REG REG_LPA(0x0048)
+#define LCC_MI2S_STATUS_REG REG_LPA(0x0050)
+#define LCC_PCM_NS_REG REG_LPA(0x0054)
+#define LCC_PCM_STATUS_REG REG_LPA(0x005C)
+#define LCC_PLL0_CONFIG_REG REG_LPA(0x0014)
+#define LCC_PLL0_L_VAL_REG REG_LPA(0x0004)
+#define LCC_PLL0_M_VAL_REG REG_LPA(0x0008)
+#define LCC_PLL0_MODE_REG REG_LPA(0x0000)
+#define LCC_PLL0_N_VAL_REG REG_LPA(0x000C)
+#define LCC_PLL0_STATUS_REG REG_LPA(0x0018)
+#define LCC_PRI_PLL_CLK_CTL_REG REG_LPA(0x00C4)
+#define LCC_SPARE_I2S_MIC_NS_REG REG_LPA(0x0078)
+#define LCC_SPARE_I2S_MIC_STATUS_REG REG_LPA(0x0080)
+#define LCC_SPARE_I2S_SPKR_NS_REG REG_LPA(0x0084)
+#define LCC_SPARE_I2S_SPKR_STATUS_REG REG_LPA(0x008C)
+
+/* MUX source input identifiers. */
+#define SRC_SEL_BB_PXO 0
+#define SRC_SEL_BB_MXO 1
+#define SRC_SEL_BB_CXO SRC_SEL_BB_PXO
+#define SRC_SEL_BB_PLL0 2
+#define SRC_SEL_BB_PLL8 3
+#define SRC_SEL_BB_PLL6 4
+#define SRC_SEL_MM_PXO 0
+#define SRC_SEL_MM_PLL0 1
+#define SRC_SEL_MM_PLL1 1
+#define SRC_SEL_MM_PLL2 3
+#define SRC_SEL_MM_GPERF 2
+#define SRC_SEL_MM_GPLL0 3
+#define SRC_SEL_MM_MXO 4
+#define SRC_SEL_XO_CXO 0
+#define SRC_SEL_XO_PXO 1
+#define SRC_SEL_XO_MXO 2
+#define SRC_SEL_LPA_PXO 0
+#define SRC_SEL_LPA_CXO 1
+#define SRC_SEL_LPA_PLL0 2
+
+/* Source name mapping. */
+#define SRC_BB_PXO PXO
+#define SRC_BB_MXO MXO
+#define SRC_BB_CXO CXO
+#define SRC_BB_PLL0 PLL_0
+#define SRC_BB_PLL8 PLL_8
+#define SRC_BB_PLL6 PLL_6
+#define SRC_MM_PXO PXO
+#define SRC_MM_PLL0 PLL_1
+#define SRC_MM_PLL1 PLL_2
+#define SRC_MM_PLL2 PLL_3
+#define SRC_MM_GPERF PLL_8
+#define SRC_MM_GPLL0 PLL_0
+#define SRC_MM_MXO MXO
+#define SRC_XO_CXO CXO
+#define SRC_XO_PXO PXO
+#define SRC_XO_MXO MXO
+#define SRC_LPA_PXO PXO
+#define SRC_LPA_CXO CXO
+#define SRC_LPA_PLL0 PLL_4
+
+/* Test Vector Macros */
+#define TEST_TYPE_PER_LS 1
+#define TEST_TYPE_PER_HS 2
+#define TEST_TYPE_MM_LS 3
+#define TEST_TYPE_MM_HS 4
+#define TEST_TYPE_LPA 5
+#define TEST_TYPE_SHIFT 24
+#define TEST_CLK_SEL_MASK BM(23, 0)
+#define TEST_VECTOR(s, t) (((t) << TEST_TYPE_SHIFT) | BVAL(23, 0, (s)))
+#define TEST_PER_LS(s) TEST_VECTOR((s), TEST_TYPE_PER_LS)
+#define TEST_PER_HS(s) TEST_VECTOR((s), TEST_TYPE_PER_HS)
+#define TEST_MM_LS(s) TEST_VECTOR((s), TEST_TYPE_MM_LS)
+#define TEST_MM_HS(s) TEST_VECTOR((s), TEST_TYPE_MM_HS)
+#define TEST_LPA(s) TEST_VECTOR((s), TEST_TYPE_LPA)
+
+/*
+ * SoC-specific Set-Rate Functions
+ */
+
+static void set_rate_cam(struct clk_local *clk, struct clk_freq_tbl *nf)
+{
+ uint32_t ns_reg_val, cc_reg_val;
+
+ /* Assert MND reset. */
+ cc_reg_val = readl(clk->cc_reg);
+ cc_reg_val |= B(8);
+ writel(cc_reg_val, clk->cc_reg);
+
+ /* Program M and D values. */
+ writel(nf->md_val, clk->md_reg);
+
+ /* Program MN counter Enable and Mode. */
+ cc_reg_val &= ~(clk->cc_mask);
+ cc_reg_val |= nf->cc_val;
+ writel(cc_reg_val, clk->cc_reg);
+
+ /* Program N value, divider and source. */
+ ns_reg_val = readl(clk->ns_reg);
+ ns_reg_val &= ~(clk->ns_mask);
+ ns_reg_val |= nf->ns_val;
+ writel(ns_reg_val, clk->ns_reg);
+
+ /* Deassert MND reset. */
+ cc_reg_val &= ~B(8);
+ writel(cc_reg_val, clk->cc_reg);
+}
+
+/* Unlike other clocks, the TV rate is adjusted through PLL
+ * re-programming. It is also routed through an MND divider. */
+static void set_rate_tv(struct clk_local *clk, struct clk_freq_tbl *nf)
+{
+ struct pll_rate *rate = nf->extra_freq_data;
+ uint32_t pll_mode, pll_config, misc_cc2;
+
+ /* Disable PLL output. */
+ pll_mode = readl(MM_PLL2_MODE_REG);
+ pll_mode &= ~B(0);
+ writel(pll_mode, MM_PLL2_MODE_REG);
+
+ /* Assert active-low PLL reset. */
+ pll_mode &= ~B(2);
+ writel(pll_mode, MM_PLL2_MODE_REG);
+
+ /* Program L, M and N values. */
+ writel(rate->l_val, MM_PLL2_L_VAL_REG);
+ writel(rate->m_val, MM_PLL2_M_VAL_REG);
+ writel(rate->n_val, MM_PLL2_N_VAL_REG);
+
+ /* Configure MN counter, post-divide, VCO, and i-bits. */
+ pll_config = readl(MM_PLL2_CONFIG_REG);
+ pll_config &= ~(BM(22, 20) | BM(18, 0));
+ pll_config |= rate->n_val ? B(22) : 0;
+ pll_config |= BVAL(21, 20, rate->post_div);
+ pll_config |= BVAL(17, 16, rate->vco);
+ pll_config |= rate->i_bits;
+ writel(pll_config, MM_PLL2_CONFIG_REG);
+
+ /* Configure MND. */
+ set_rate_mnd(clk, nf);
+
+ /* Configure hdmi_ref_clk to be equal to the TV clock rate. */
+ misc_cc2 = readl(MISC_CC2_REG);
+ misc_cc2 &= ~(B(28)|BM(21, 18));
+ misc_cc2 |= (B(28)|BVAL(21, 18, (nf->ns_val >> 14) & 0x3));
+ writel(misc_cc2, MISC_CC2_REG);
+
+ /* De-assert active-low PLL reset. */
+ pll_mode |= B(2);
+ writel(pll_mode, MM_PLL2_MODE_REG);
+
+ /* Enable PLL output. */
+ pll_mode |= B(0);
+ writel(pll_mode, MM_PLL2_MODE_REG);
+}
+
+static void set_rate_mnd_banked(struct clk_local *clk, struct clk_freq_tbl *nf)
+{
+ struct banked_mnd_masks *banks = clk->banked_mnd_masks;
+ const struct bank_mask_info *new_bank_masks;
+ const struct bank_mask_info *old_bank_masks;
+ uint32_t ns_reg_val, cc_reg_val;
+ uint32_t bank_sel;
+
+ /* Determine active bank and program the other one. If the clock is
+ * off, program the active bank since bank switching won't work if
+ * both banks aren't running. */
+ cc_reg_val = readl(clk->cc_reg);
+ bank_sel = !!(cc_reg_val & banks->bank_sel_mask);
+ /* If clock is disabled, don't switch banks. */
+ bank_sel ^= !(clk->count);
+ if (bank_sel == 0) {
+ new_bank_masks = &banks->bank1_mask;
+ old_bank_masks = &banks->bank0_mask;
+ } else {
+ new_bank_masks = &banks->bank0_mask;
+ old_bank_masks = &banks->bank1_mask;
+ }
+
+ ns_reg_val = readl(clk->ns_reg);
+
+ /* Assert bank MND reset. */
+ ns_reg_val |= new_bank_masks->rst_mask;
+ writel(ns_reg_val, clk->ns_reg);
+
+ writel(nf->md_val, new_bank_masks->md_reg);
+
+ /* Enable counter only if clock is enabled. */
+ if (clk->count)
+ cc_reg_val |= new_bank_masks->mnd_en_mask;
+ else
+ cc_reg_val &= ~(new_bank_masks->mnd_en_mask);
+
+ cc_reg_val &= ~(new_bank_masks->mode_mask);
+ cc_reg_val |= (nf->cc_val & new_bank_masks->mode_mask);
+ writel(cc_reg_val, clk->cc_reg);
+
+ ns_reg_val &= ~(new_bank_masks->ns_mask);
+ ns_reg_val |= (nf->ns_val & new_bank_masks->ns_mask);
+ writel(ns_reg_val, clk->ns_reg);
+
+ /* Deassert bank MND reset. */
+ ns_reg_val &= ~(new_bank_masks->rst_mask);
+ writel(ns_reg_val, clk->ns_reg);
+
+ /* Switch to the new bank if clock is on. If it isn't, then no
+ * switch is necessary since we programmed the active bank. */
+ if (clk->count) {
+ cc_reg_val ^= banks->bank_sel_mask;
+ writel(cc_reg_val, clk->cc_reg);
+
+ /* Disable previous MN counter. */
+ cc_reg_val &= ~(old_bank_masks->mnd_en_mask);
+ writel(cc_reg_val, clk->cc_reg);
+ }
+
+ /* If this freq requires the MN counter to be enabled,
+ * update the enable mask to match the current bank. */
+ if (nf->mnd_en_mask)
+ nf->mnd_en_mask = new_bank_masks->mnd_en_mask;
+}
+
+static void set_rate_div_banked(struct clk_local *clk, struct clk_freq_tbl *nf)
+{
+ uint32_t ns_reg_val, ns_mask, bank_sel;
+
+ /* Determine active bank and program the other one. If the clock is
+ * off, program the active bank since bank switching won't work if
+ * both banks aren't running. */
+ ns_reg_val = readl(clk->ns_reg);
+ bank_sel = !!(ns_reg_val & B(30));
+ /* If clock is disabled, don't switch banks. */
+ bank_sel ^= !(clk->count);
+ if (bank_sel == 0)
+ ns_mask = (BM(29, 26) | BM(21, 19));
+ else
+ ns_mask = (BM(25, 22) | BM(18, 16));
+
+ ns_reg_val &= ~(ns_mask);
+ ns_reg_val |= (nf->ns_val & ns_mask);
+ writel(ns_reg_val, clk->ns_reg);
+
+ /* Switch to the new bank if clock is on. If it isn't, then no
+ * switch is necessary since we programmed the active bank. */
+ if (clk->count) {
+ ns_reg_val ^= B(30);
+ writel(ns_reg_val, clk->ns_reg);
+ }
+}
+
+/*
+ * Generic clock declaration macros
+ */
+#define CLK_NORATE(id, reg, br, r_r, r_m, h_r, h_c, h_b, tv) \
+ CLK(id, NORATE, NULL, reg, NULL, r_r, r_m, h_r, h_c, h_b, \
+ br, 0, 0, 0, NULL, NULL, NULL, NONE, NULL, tv)
+#define CLK_SLAVE(id, reg, br, r_r, r_m, h_r, h_c, h_b, par, tv) \
+ CLK(id, NORATE, NULL, reg, NULL, r_r, r_m, h_r, h_c, h_b, \
+ br, 0, 0, 0, NULL, NULL, NULL, par, NULL, tv)
+#define CLK_RESET(id, ns, r_m) \
+ CLK(id, RESET, NULL, NULL, NULL, ns, r_m, NULL, 0, 0, \
+ 0, 0, 0, 0, NULL, NULL, NULL, NONE, NULL, 0)
+
+/*
+ * Clock frequency definitions and macros
+ */
+#define MN_MODE_DUAL_EDGE 0x2
+#define MND_EN(b, n) (b * !!(n))
+
+/* MD Registers */
+#define MD4(m_lsb, m, n_lsb, n) \
+ (BVAL((m_lsb+3), m_lsb, m) | BVAL((n_lsb+3), n_lsb, ~(n)))
+#define MD8(m_lsb, m, n_lsb, n) \
+ (BVAL((m_lsb+7), m_lsb, m) | BVAL((n_lsb+7), n_lsb, ~(n)))
+#define MD16(m, n) (BVAL(31, 16, m) | BVAL(15, 0, ~(n)))
+
+/* NS Registers */
+#define NS(n_msb, n_lsb, n, m, mde_lsb, d_msb, d_lsb, d, s_msb, s_lsb, s) \
+ (BVAL(n_msb, n_lsb, ~(n-m)) \
+ | (BVAL((mde_lsb+1), mde_lsb, MN_MODE_DUAL_EDGE) * !!(n)) \
+ | BVAL(d_msb, d_lsb, (d-1)) | BVAL(s_msb, s_lsb, SRC_SEL_##s))
+
+#define NS_MM(n_msb, n_lsb, n, m, d_msb, d_lsb, d, s_msb, s_lsb, s) \
+ (BVAL(n_msb, n_lsb, ~(n-m)) | BVAL(d_msb, d_lsb, (d-1)) \
+ | BVAL(s_msb, s_lsb, SRC_SEL_##s))
+
+#define NS_DIVSRC(d_msb , d_lsb, d, s_msb, s_lsb, s) \
+ (BVAL(d_msb, d_lsb, (d-1)) | BVAL(s_msb, s_lsb, SRC_SEL_##s))
+
+#define NS_DIV(d_msb , d_lsb, d) \
+ BVAL(d_msb, d_lsb, (d-1))
+
+#define NS_SRC_SEL(s_msb, s_lsb, s) \
+ BVAL(s_msb, s_lsb, SRC_SEL_##s)
+
+#define NS_MND_BANKED4(n0_lsb, n1_lsb, n, m, s0_lsb, s1_lsb, s) \
+ (BVAL((n0_lsb+3), n0_lsb, ~(n-m)) \
+ | BVAL((n1_lsb+3), n1_lsb, ~(n-m)) \
+ | BVAL((s0_lsb+2), s0_lsb, SRC_SEL_##s) \
+ | BVAL((s1_lsb+2), s1_lsb, SRC_SEL_##s))
+
+#define NS_MND_BANKED8(n0_lsb, n1_lsb, n, m, s0_lsb, s1_lsb, s) \
+ (BVAL((n0_lsb+7), n0_lsb, ~(n-m)) \
+ | BVAL((n1_lsb+7), n1_lsb, ~(n-m)) \
+ | BVAL((s0_lsb+2), s0_lsb, SRC_SEL_##s) \
+ | BVAL((s1_lsb+2), s1_lsb, SRC_SEL_##s))
+
+#define NS_DIVSRC_BANKED(d0_msb, d0_lsb, d1_msb, d1_lsb, d, \
+ s0_msb, s0_lsb, s1_msb, s1_lsb, s) \
+ (BVAL(d0_msb, d0_lsb, (d-1)) | BVAL(d1_msb, d1_lsb, (d-1)) \
+ | BVAL(s0_msb, s0_lsb, SRC_SEL_##s) \
+ | BVAL(s1_msb, s1_lsb, SRC_SEL_##s))
+
+/* CC Registers */
+#define CC(mde_lsb, n) (BVAL((mde_lsb+1), mde_lsb, MN_MODE_DUAL_EDGE) * !!(n))
+#define CC_BANKED(mde0_lsb, mde1_lsb, n) \
+ ((BVAL((mde0_lsb+1), mde0_lsb, MN_MODE_DUAL_EDGE) \
+ | BVAL((mde1_lsb+1), mde1_lsb, MN_MODE_DUAL_EDGE)) \
+ * !!(n))
+
+/*
+ * Clock Descriptions
+ */
+
+/* GSBI_UART */
+#define NS_MASK_GSBI_UART (BM(31, 16) | BM(6, 0))
+#define CLK_GSBI_UART(id, ns, h_r, h_c, h_b, tv) \
+ CLK(id, MND, ns, ns, (ns-4), (ns+8), B(0), h_r, h_c, \
+ h_b, B(9), B(11), NS_MASK_GSBI_UART, 0, \
+ set_rate_mnd, clk_tbl_gsbi_uart, NULL, NONE, \
+ NULL, tv)
+#define F_GSBI_UART(f, s, d, m, n, v) \
+ F_RAW(f, SRC_##s, MD16(m, n), \
+ NS(31, 16, n, m, 5, 4, 3, d, 2, 0, s), \
+ 0, MND_EN(B(8), n), v, NULL)
+static struct clk_freq_tbl clk_tbl_gsbi_uart[] = {
+ F_GSBI_UART( 3686400, BB_PLL8, 1, 6, 625, LOW),
+ F_GSBI_UART( 7372800, BB_PLL8, 1, 12, 625, LOW),
+ F_GSBI_UART(14745600, BB_PLL8, 1, 24, 625, LOW),
+ F_GSBI_UART(16000000, BB_PLL8, 4, 1, 6, LOW),
+ F_GSBI_UART(24000000, BB_PLL8, 4, 1, 4, LOW),
+ F_GSBI_UART(32000000, BB_PLL8, 4, 1, 3, LOW),
+ F_GSBI_UART(40000000, BB_PLL8, 1, 5, 48, NOMINAL),
+ F_GSBI_UART(46400000, BB_PLL8, 1, 29, 240, NOMINAL),
+ F_GSBI_UART(48000000, BB_PLL8, 4, 1, 2, NOMINAL),
+ F_GSBI_UART(51200000, BB_PLL8, 1, 2, 15, NOMINAL),
+ F_GSBI_UART(48000000, BB_PLL8, 4, 1, 2, NOMINAL),
+ F_GSBI_UART(51200000, BB_PLL8, 1, 2, 15, NOMINAL),
+ F_GSBI_UART(56000000, BB_PLL8, 1, 7, 48, NOMINAL),
+ F_GSBI_UART(58982400, BB_PLL8, 1, 96, 625, NOMINAL),
+ F_GSBI_UART(64000000, BB_PLL8, 2, 1, 3, NOMINAL),
+ F_END,
+};
+
+/* GSBI_QUP */
+#define NS_MASK_GSBI_QUP (BM(23, 16) | BM(6, 0))
+#define CLK_GSBI_QUP(id, ns, h_r, h_c, h_b, tv) \
+ CLK(id, MND, ns, ns, (ns-4), (ns+16), B(0), h_r, h_c, \
+ h_b, B(9), B(11), NS_MASK_GSBI_QUP, 0, \
+ set_rate_mnd, clk_tbl_gsbi_qup, NULL, NONE, \
+ NULL, tv)
+#define F_GSBI_QUP(f, s, d, m, n, v) \
+ F_RAW(f, SRC_##s, MD8(16, m, 0, n), \
+ NS(23, 16, n, m, 5, 4, 3, d, 2, 0, s), \
+ 0, MND_EN(B(8), n), v, NULL)
+static struct clk_freq_tbl clk_tbl_gsbi_qup[] = {
+ F_GSBI_QUP( 1100000, BB_PXO, 1, 2, 49, LOW),
+ F_GSBI_QUP( 5400000, BB_PXO, 1, 1, 5, LOW),
+ F_GSBI_QUP(10800000, BB_PXO, 1, 2, 5, LOW),
+ F_GSBI_QUP(15060000, BB_PLL8, 1, 2, 51, LOW),
+ F_GSBI_QUP(24000000, BB_PLL8, 4, 1, 4, LOW),
+ F_GSBI_QUP(25600000, BB_PLL8, 1, 1, 15, NOMINAL),
+ F_GSBI_QUP(27000000, BB_PXO, 1, 0, 0, NOMINAL),
+ F_GSBI_QUP(48000000, BB_PLL8, 4, 1, 2, NOMINAL),
+ F_GSBI_QUP(51200000, BB_PLL8, 1, 2, 15, NOMINAL),
+ F_END,
+};
+
+/* PDM */
+#define NS_MASK_PDM (BM(1, 0))
+#define CLK_PDM(id, ns, h_r, h_c, h_b) \
+ CLK(id, BASIC, ns, ns, NULL, ns, B(12), h_r, h_c, h_b, \
+ B(9), B(11), NS_MASK_PDM, 0, \
+ set_rate_basic, clk_tbl_pdm, NULL, NONE, \
+ NULL, 0)
+#define F_PDM(f, s, d, v) \
+ F_RAW(f, SRC_##s, 0, NS_SRC_SEL(1, 0, s), 0, 0, v, NULL)
+static struct clk_freq_tbl clk_tbl_pdm[] = {
+ F_PDM(27000000, XO_PXO, 1, LOW),
+ F_END,
+};
+
+/* PRNG */
+#define NS_MASK_PRNG (BM(6, 3) | BM(2, 0))
+#define CLK_PRNG(id, ns, cc, h_r, h_c, h_b, tv) \
+ CLK(id, BASIC, ns, cc, NULL, ns, B(12), h_r, h_c, h_b, \
+ B(10), 0, NS_MASK_PRNG, 0, set_rate_basic, \
+ clk_tbl_prng, NULL, NONE, NULL, tv)
+#define F_PRNG(f, s, d, v) \
+ F_RAW(f, SRC_##s, 0, NS_DIVSRC(6, 3, d, 2, 0, s), 0, 0, v, NULL)
+static struct clk_freq_tbl clk_tbl_prng[] = {
+ F_PRNG(32000000, BB_PLL8, 12, LOW),
+ F_PRNG(64000000, BB_PLL8, 6, NOMINAL),
+ F_END,
+};
+
+/* SDC */
+#define NS_MASK_SDC (BM(23, 16) | BM(6, 0))
+#define CLK_SDC(id, ns, h_r, h_c, h_b, tv) \
+ CLK(id, MND, ns, ns, (ns-4), (ns+4), B(0), h_r, h_c, \
+ h_b, B(9), B(11), NS_MASK_SDC, 0, \
+ set_rate_mnd, clk_tbl_sdc, NULL, NONE, NULL, tv)
+#define F_SDC(f, s, d, m, n, v) \
+ F_RAW(f, SRC_##s, MD8(16, m, 0, n), \
+ NS(23, 16, n, m, 5, 4, 3, d, 2, 0, s), \
+ 0, MND_EN(B(8), n), v, NULL)
+static struct clk_freq_tbl clk_tbl_sdc[] = {
+ F_SDC( 144000, BB_PXO, 3, 2, 125, LOW),
+ F_SDC( 400000, BB_PLL8, 4, 1, 240, LOW),
+ F_SDC(16000000, BB_PLL8, 4, 1, 6, LOW),
+ F_SDC(17070000, BB_PLL8, 1, 2, 45, LOW),
+ F_SDC(20210000, BB_PLL8, 1, 1, 19, LOW),
+ F_SDC(24000000, BB_PLL8, 4, 1, 4, LOW),
+ F_SDC(48000000, BB_PLL8, 4, 1, 2, NOMINAL),
+ F_END,
+};
+
+/* TSIF_REF */
+#define NS_MASK_TSIF_REF (BM(31, 16) | BM(6, 0))
+#define CLK_TSIF_REF(id, ns, h_r, h_c, h_b, tv) \
+ CLK(id, MND, ns, ns, (ns-4), NULL, 0, h_r, h_c, h_b, \
+ B(9), B(11), NS_MASK_TSIF_REF, 0, \
+ set_rate_mnd, clk_tbl_tsif_ref, NULL, \
+ NONE, NULL, tv)
+#define F_TSIF_REF(f, s, d, m, n, v) \
+ F_RAW(f, SRC_##s, MD16(m, n), \
+ NS(31, 16, n, m, 5, 4, 3, d, 2, 0, s), \
+ 0, MND_EN(B(8), n), v, NULL)
+static struct clk_freq_tbl clk_tbl_tsif_ref[] = {
+ F_TSIF_REF(105000, BB_PXO, 1, 1, 256, LOW),
+ F_END,
+};
+
+
+/* TSSC */
+#define NS_MASK_TSSC (BM(1, 0))
+#define CLK_TSSC(id, ns, h_r, h_c, h_b, tv) \
+ CLK(id, BASIC, ns, ns, NULL, NULL, 0, h_r, h_c, h_b, \
+ B(4), 0, NS_MASK_TSSC, 0, set_rate_basic, \
+ clk_tbl_tssc, NULL, NONE, NULL, tv)
+#define F_TSSC(f, s, v) \
+ F_RAW(f, SRC_##s, 0, NS_SRC_SEL(1, 0, s), 0, 0, v, NULL)
+static struct clk_freq_tbl clk_tbl_tssc[] = {
+ F_TSSC(27000000, XO_PXO, LOW),
+ F_END,
+};
+
+/* USB_HS and USB_FS */
+#define NS_MASK_USB (BM(23, 16) | BM(6, 0))
+#define CLK_USB_HS(id, ns, h_r, h_c, h_b, tv) \
+ CLK(id, MND, ns, ns, (ns-4), (ns+4), B(0), h_r, h_c, \
+ h_b, B(9), B(11), NS_MASK_USB, 0, \
+ set_rate_mnd, clk_tbl_usb, NULL, NONE, NULL, tv)
+#define CLK_USB_FS(id, ns, chld_lst) \
+ CLK(id, MND, ns, ns, (ns-4), NULL, 0, NULL, 0, 0, \
+ 0, B(11), NS_MASK_USB, 0, set_rate_mnd, \
+ clk_tbl_usb, NULL, NONE, chld_lst, 0)
+#define F_USB(f, s, d, m, n, v) \
+ F_RAW(f, SRC_##s, MD8(16, m, 0, n), \
+ NS(23, 16, n, m, 5, 4, 3, d, 2, 0, s), \
+ 0, MND_EN(B(8), n), v, NULL)
+static struct clk_freq_tbl clk_tbl_usb[] = {
+ F_USB(60000000, BB_PLL8, 1, 5, 32, NOMINAL),
+ F_END,
+};
+
+/* CAM */
+#define NS_MASK_CAM (BM(31, 24) | BM(15, 14) | BM(2, 0))
+#define CC_MASK_CAM (BM(7, 6))
+#define CLK_CAM(id, ns, h_r, h_c, h_b, tv) \
+ CLK(id, MND, ns, (ns-8), (ns-4), NULL, 0, h_r, h_c, h_b, \
+ B(0), B(2), NS_MASK_CAM, CC_MASK_CAM, \
+ set_rate_cam, clk_tbl_cam, NULL, NONE, NULL, tv)
+#define F_CAM(f, s, d, m, n, v) \
+ F_RAW(f, SRC_##s, MD8(8, m, 0, n), \
+ NS_MM(31, 24, n, m, 15, 14, d, 2, 0, s), \
+ CC(6, n), MND_EN(B(5), n), v, NULL)
+static struct clk_freq_tbl clk_tbl_cam[] = {
+ F_CAM( 6000000, MM_GPERF, 4, 1, 16, LOW),
+ F_CAM( 8000000, MM_GPERF, 4, 1, 12, LOW),
+ F_CAM( 12000000, MM_GPERF, 4, 1, 8, LOW),
+ F_CAM( 16000000, MM_GPERF, 4, 1, 6, LOW),
+ F_CAM( 19200000, MM_GPERF, 4, 1, 5, LOW),
+ F_CAM( 24000000, MM_GPERF, 4, 1, 4, LOW),
+ F_CAM( 32000000, MM_GPERF, 4, 1, 3, LOW),
+ F_CAM( 48000000, MM_GPERF, 4, 1, 2, LOW),
+ F_CAM( 64000000, MM_GPERF, 3, 1, 2, LOW),
+ F_CAM( 96000000, MM_GPERF, 4, 0, 0, NOMINAL),
+ F_CAM(128000000, MM_GPERF, 3, 0, 0, NOMINAL),
+ F_END,
+};
+
+/* CSI */
+#define NS_MASK_CSI (BM(15, 12) | BM(2, 0))
+#define CLK_CSI(id, ns) \
+ CLK(id, BASIC, ns, (ns-8), NULL, NULL, 0, NULL, 0, 0, \
+ 0, B(2), NS_MASK_CSI, 0, set_rate_basic, \
+ clk_tbl_csi, NULL, NONE, chld_csi_src, 0)
+#define F_CSI(f, s, d, v) \
+ F_RAW(f, SRC_##s, 0, NS_DIVSRC(15, 12, d, 2, 0, s), \
+ 0, 0, v, NULL)
+static struct clk_freq_tbl clk_tbl_csi[] = {
+ F_CSI(192000000, MM_GPERF, 2, LOW),
+ F_CSI(384000000, MM_GPERF, 1, NOMINAL),
+ F_END,
+};
+
+/* DSI_BYTE */
+#define NS_MASK_DSI_BYTE BM(27, 24)
+#define CLK_DSI_BYTE(id, ns, r_r, r_m, h_r, h_c, h_b, tv) \
+ CLK(id, BASIC, ns, (ns-4), NULL, r_r, r_m, h_r, h_c, h_b, \
+ 0, B(2), NS_MASK_DSI_BYTE, 0, set_rate_basic, \
+ clk_tbl_dsi_byte, NULL, NONE, NULL, tv)
+#define F_DSI(d) F_RAW(d, SRC_NONE, 0, BVAL(27, 24, (d-1)), 0, 0, 0, NULL)
+/* The DSI_BYTE clock is sourced from the DSI PHY PLL, which may change rate
+ * without this clock driver knowing. So, overload the clk_set_rate() to set
+ * the divider (1 to 16) of the clock with respect to the PLL rate. */
+static struct clk_freq_tbl clk_tbl_dsi_byte[] = {
+ F_DSI(1), F_DSI(2), F_DSI(3), F_DSI(4),
+ F_DSI(5), F_DSI(6), F_DSI(7), F_DSI(8),
+ F_DSI(9), F_DSI(10), F_DSI(11), F_DSI(12),
+ F_DSI(13), F_DSI(14), F_DSI(15), F_DSI(16),
+ F_END,
+};
+
+/* GFX2D0 and GFX2D1 */
+static struct banked_mnd_masks bmnd_info_gfx2d0 = {
+ .bank_sel_mask = B(11),
+ .bank0_mask = {
+ .md_reg = GFX2D0_MD0_REG,
+ .ns_mask = BM(23, 20) | BM(5, 3),
+ .rst_mask = B(25),
+ .mnd_en_mask = B(8),
+ .mode_mask = BM(10, 9),
+ },
+ .bank1_mask = {
+ .md_reg = GFX2D0_MD1_REG,
+ .ns_mask = BM(19, 16) | BM(2, 0),
+ .rst_mask = B(24),
+ .mnd_en_mask = B(5),
+ .mode_mask = BM(7, 6),
+ },
+};
+#define CLK_GFX2D0(id, ns, r_r, r_m, h_r, h_c, h_b, tv) \
+ CLK(id, MND, ns, (ns-16), NULL, r_r, r_m, h_r, h_c, h_b, \
+ B(0), B(2), 0, 0, set_rate_mnd_banked, \
+ clk_tbl_gfx2d, &bmnd_info_gfx2d0, NONE, \
+ NULL, tv)
+static struct banked_mnd_masks bmnd_info_gfx2d1 = {
+ .bank_sel_mask = B(11),
+ .bank0_mask = {
+ .md_reg = GFX2D1_MD0_REG,
+ .ns_mask = BM(23, 20) | BM(5, 3),
+ .rst_mask = B(25),
+ .mnd_en_mask = B(8),
+ .mode_mask = BM(10, 9),
+ },
+ .bank1_mask = {
+ .md_reg = GFX2D1_MD1_REG,
+ .ns_mask = BM(19, 16) | BM(2, 0),
+ .rst_mask = B(24),
+ .mnd_en_mask = B(5),
+ .mode_mask = BM(7, 6),
+ },
+};
+#define CLK_GFX2D1(id, ns, r_r, r_m, h_r, h_c, h_b, tv) \
+ CLK(id, MND, ns, (ns-8), NULL, r_r, r_m, h_r, h_c, h_b, \
+ B(0), B(2), 0, 0, set_rate_mnd_banked, \
+ clk_tbl_gfx2d, &bmnd_info_gfx2d1, NONE, \
+ NULL, tv)
+#define F_GFX2D(f, s, m, n, v) \
+ F_RAW(f, SRC_##s, MD4(4, m, 0, n), \
+ NS_MND_BANKED4(20, 16, n, m, 3, 0, s), \
+ CC_BANKED(9, 6, n), MND_EN((B(8) | B(5)), n), v, NULL)
+static struct clk_freq_tbl clk_tbl_gfx2d[] = {
+ F_GFX2D( 27000000, MM_PXO, 0, 0, LOW),
+ F_GFX2D( 48000000, MM_GPERF, 1, 8, LOW),
+ F_GFX2D( 54857000, MM_GPERF, 1, 7, LOW),
+ F_GFX2D( 64000000, MM_GPERF, 1, 6, LOW),
+ F_GFX2D( 76800000, MM_GPERF, 1, 5, LOW),
+ F_GFX2D( 96000000, MM_GPERF, 1, 4, LOW),
+ F_GFX2D(128000000, MM_GPERF, 1, 3, NOMINAL),
+ F_GFX2D(145455000, MM_PLL1, 2, 11, NOMINAL),
+ F_GFX2D(160000000, MM_PLL1, 1, 5, NOMINAL),
+ F_GFX2D(177778000, MM_PLL1, 2, 9, NOMINAL),
+ F_GFX2D(200000000, MM_PLL1, 1, 4, NOMINAL),
+ F_GFX2D(228571000, MM_PLL1, 2, 7, HIGH),
+ F_END,
+};
+
+/* GFX3D */
+static struct banked_mnd_masks bmnd_info_gfx3d = {
+ .bank_sel_mask = B(11),
+ .bank0_mask = {
+ .md_reg = GFX3D_MD0_REG,
+ .ns_mask = BM(21, 18) | BM(5, 3),
+ .rst_mask = B(23),
+ .mnd_en_mask = B(8),
+ .mode_mask = BM(10, 9),
+ },
+ .bank1_mask = {
+ .md_reg = GFX3D_MD1_REG,
+ .ns_mask = BM(17, 14) | BM(2, 0),
+ .rst_mask = B(22),
+ .mnd_en_mask = B(5),
+ .mode_mask = BM(7, 6),
+ },
+};
+#define CLK_GFX3D(id, ns, r_r, r_m, h_r, h_c, h_b, par, tv) \
+ CLK(id, MND, ns, (ns-12), NULL, r_r, r_m, h_r, h_c, h_b, \
+ B(0), B(2), 0, 0, set_rate_mnd_banked, \
+ clk_tbl_gfx3d, &bmnd_info_gfx3d, par, NULL, tv)
+#define F_GFX3D(f, s, m, n, v) \
+ F_RAW(f, SRC_##s, MD4(4, m, 0, n), \
+ NS_MND_BANKED4(18, 14, n, m, 3, 0, s), \
+ CC_BANKED(9, 6, n), MND_EN((B(8) | B(5)), n), v, NULL)
+static struct clk_freq_tbl clk_tbl_gfx3d[] = {
+ F_GFX3D( 27000000, MM_PXO, 0, 0, LOW),
+ F_GFX3D( 48000000, MM_GPERF, 1, 8, LOW),
+ F_GFX3D( 54857000, MM_GPERF, 1, 7, LOW),
+ F_GFX3D( 64000000, MM_GPERF, 1, 6, LOW),
+ F_GFX3D( 76800000, MM_GPERF, 1, 5, LOW),
+ F_GFX3D( 96000000, MM_GPERF, 1, 4, LOW),
+ F_GFX3D(128000000, MM_GPERF, 1, 3, NOMINAL),
+ F_GFX3D(145455000, MM_PLL1, 2, 11, NOMINAL),
+ F_GFX3D(160000000, MM_PLL1, 1, 5, NOMINAL),
+ F_GFX3D(177778000, MM_PLL1, 2, 9, NOMINAL),
+ F_GFX3D(200000000, MM_PLL1, 1, 4, NOMINAL),
+ F_GFX3D(228571000, MM_PLL1, 2, 7, NOMINAL),
+ F_GFX3D(266667000, MM_PLL1, 1, 3, NOMINAL),
+ F_GFX3D(320000000, MM_PLL1, 2, 5, HIGH),
+ F_END,
+};
+
+/* IJPEG */
+#define NS_MASK_IJPEG (BM(23, 16) | BM(15, 12) | BM(2, 0))
+#define CC_MASK_IJPEG (BM(7, 6))
+#define CLK_IJPEG(id, ns, r_r, r_m, h_r, h_c, h_b, tv) \
+ CLK(id, MND, ns, (ns-8), (ns-4), r_r, r_m, h_r, h_c, h_b, \
+ B(0), B(2), NS_MASK_IJPEG, CC_MASK_IJPEG, \
+ set_rate_mnd, clk_tbl_ijpeg, NULL, NONE, \
+ NULL, tv)
+#define F_IJPEG(f, s, d, m, n, v) \
+ F_RAW(f, SRC_##s, MD8(8, m, 0, n), \
+ NS_MM(23, 16, n, m, 15, 12, d, 2, 0, s), \
+ CC(6, n), MND_EN(B(5), n), v, NULL)
+static struct clk_freq_tbl clk_tbl_ijpeg[] = {
+ F_IJPEG( 27000000, MM_PXO, 1, 0, 0, LOW),
+ F_IJPEG( 36570000, MM_GPERF, 1, 2, 21, LOW),
+ F_IJPEG( 54860000, MM_GPERF, 7, 0, 0, LOW),
+ F_IJPEG( 96000000, MM_GPERF, 4, 0, 0, LOW),
+ F_IJPEG(109710000, MM_GPERF, 1, 2, 7, LOW),
+ F_IJPEG(128000000, MM_GPERF, 3, 0, 0, NOMINAL),
+ F_IJPEG(153600000, MM_GPERF, 1, 2, 5, NOMINAL),
+ F_IJPEG(200000000, MM_PLL1, 4, 0, 0, NOMINAL),
+ F_IJPEG(228571000, MM_PLL1, 1, 2, 7, NOMINAL),
+ F_END,
+};
+
+/* JPEGD */
+#define NS_MASK_JPEGD (BM(15, 12) | BM(2, 0))
+#define CLK_JPEGD(id, ns, r_r, r_m, h_r, h_c, h_b, par, tv) \
+ CLK(id, BASIC, ns, (ns-8), NULL, r_r, r_m, h_r, h_c, h_b, \
+ B(0), B(2), NS_MASK_JPEGD, 0, set_rate_basic, \
+ clk_tbl_jpegd, NULL, par, NULL, tv)
+#define F_JPEGD(f, s, d, v) \
+ F_RAW(f, SRC_##s, 0, NS_DIVSRC(15, 12, d, 2, 0, s), \
+ 0, 0, v, NULL)
+static struct clk_freq_tbl clk_tbl_jpegd[] = {
+ F_JPEGD( 64000000, MM_GPERF, 6, LOW),
+ F_JPEGD( 76800000, MM_GPERF, 5, LOW),
+ F_JPEGD( 96000000, MM_GPERF, 4, LOW),
+ F_JPEGD(160000000, MM_PLL1, 5, NOMINAL),
+ F_JPEGD(200000000, MM_PLL1, 4, NOMINAL),
+ F_END,
+};
+
+/* MDP */
+static struct banked_mnd_masks bmnd_info_mdp = {
+ .bank_sel_mask = B(11),
+ .bank0_mask = {
+ .md_reg = MDP_MD0_REG,
+ .ns_mask = BM(29, 22) | BM(5, 3),
+ .rst_mask = B(31),
+ .mnd_en_mask = B(8),
+ .mode_mask = BM(10, 9),
+ },
+ .bank1_mask = {
+ .md_reg = MDP_MD1_REG,
+ .ns_mask = BM(21, 14) | BM(2, 0),
+ .rst_mask = B(30),
+ .mnd_en_mask = B(5),
+ .mode_mask = BM(7, 6),
+ },
+};
+#define CLK_MDP(id, ns, r_r, r_m, h_r, h_c, h_b, tv) \
+ CLK(id, MND, ns, (ns-16), NULL, r_r, r_m, h_r, h_c, h_b, \
+ B(0), B(2), 0, 0, set_rate_mnd_banked, \
+ clk_tbl_mdp, &bmnd_info_mdp, NONE, NULL, tv)
+#define F_MDP(f, s, m, n, v) \
+ F_RAW(f, SRC_##s, MD8(8, m, 0, n), \
+ NS_MND_BANKED8(22, 14, n, m, 3, 0, s), \
+ CC_BANKED(9, 6, n), MND_EN((B(8) | B(5)), n), v, NULL)
+static struct clk_freq_tbl clk_tbl_mdp[] = {
+ F_MDP( 9600000, MM_GPERF, 1, 40, LOW),
+ F_MDP( 13710000, MM_GPERF, 1, 28, LOW),
+ F_MDP( 27000000, MM_PXO, 0, 0, LOW),
+ F_MDP( 29540000, MM_GPERF, 1, 13, LOW),
+ F_MDP( 34910000, MM_GPERF, 1, 11, LOW),
+ F_MDP( 38400000, MM_GPERF, 1, 10, LOW),
+ F_MDP( 59080000, MM_GPERF, 2, 13, LOW),
+ F_MDP( 76800000, MM_GPERF, 1, 5, LOW),
+ F_MDP( 85330000, MM_GPERF, 2, 9, LOW),
+ F_MDP( 96000000, MM_GPERF, 1, 4, NOMINAL),
+ F_MDP(128000000, MM_GPERF, 1, 3, NOMINAL),
+ F_MDP(160000000, MM_PLL1, 1, 5, NOMINAL),
+ F_MDP(177780000, MM_PLL1, 2, 9, NOMINAL),
+ F_MDP(200000000, MM_PLL1, 1, 4, NOMINAL),
+ F_END,
+};
+
+/* MDP VSYNC */
+#define NS_MASK_MDP_VSYNC B(13)
+#define CLK_MDP_VSYNC(id, ns, r_r, r_m, h_r, h_c, h_b, tv) \
+ CLK(id, BASIC, ns, (ns-4), NULL, r_r, r_m, h_r, h_c, h_b, \
+ B(6), 0, NS_MASK_MDP_VSYNC, 0, set_rate_basic, \
+ clk_tbl_mdp_vsync, NULL, NONE, NULL, tv)
+#define F_MDP_VSYNC(f, s, v) \
+ F_RAW(f, SRC_##s, 0, NS_SRC_SEL(13, 13, s), 0, 0, v, NULL)
+static struct clk_freq_tbl clk_tbl_mdp_vsync[] = {
+ F_MDP_VSYNC(27000000, BB_PXO, LOW),
+ F_END,
+};
+
+/* PIXEL_MDP */
+#define NS_MASK_PIXEL_MDP (BM(31, 16) | BM(15, 14) | BM(2, 0))
+#define CC_MASK_PIXEL_MDP (BM(7, 6))
+#define CLK_PIXEL_MDP(id, ns, r_r, r_m, h_r, h_c, h_b, tv) \
+ CLK(id, MND, ns, (ns-8), (ns-4), r_r, r_m, h_r, h_c, h_b, \
+ B(0), B(2), NS_MASK_PIXEL_MDP, \
+ CC_MASK_PIXEL_MDP, set_rate_mnd, \
+ clk_tbl_pixel_mdp, NULL, NONE, \
+ chld_pixel_mdp, tv)
+#define F_PIXEL_MDP(f, s, d, m, n, v) \
+ F_RAW(f, SRC_##s, MD16(m, n), \
+ NS_MM(31, 16, n, m, 15, 14, d, 2, 0, s), \
+ CC(6, n), MND_EN(B(5), n), v, NULL)
+static struct clk_freq_tbl clk_tbl_pixel_mdp[] = {
+ F_PIXEL_MDP(25600000, MM_GPERF, 3, 1, 5, LOW),
+ F_PIXEL_MDP(42667000, MM_GPERF, 1, 1, 9, LOW),
+ F_PIXEL_MDP(43192000, MM_GPERF, 1, 64, 569, LOW),
+ F_PIXEL_MDP(48000000, MM_GPERF, 4, 1, 2, LOW),
+ F_PIXEL_MDP(53990000, MM_GPERF, 2, 169, 601, LOW),
+ F_PIXEL_MDP(76800000, MM_GPERF, 1, 1, 5, LOW),
+ F_END,
+};
+
+/* ROT */
+#define CLK_ROT(id, ns, r_r, r_m, h_r, h_c, h_b, tv) \
+ CLK(id, BASIC, ns, (ns-8), NULL, r_r, r_m, h_r, h_c, h_b, \
+ B(0), B(2), 0, 0, set_rate_div_banked, \
+ clk_tbl_rot, NULL, NONE, NULL, tv)
+#define F_ROT(f, s, d, v) \
+ F_RAW(f, SRC_##s, 0, \
+ NS_DIVSRC_BANKED(29, 26, 25, 22, d, 21, 19, 18, 16, \
+ s), 0, 0, v, NULL)
+static struct clk_freq_tbl clk_tbl_rot[] = {
+ F_ROT( 27000000, MM_PXO, 1, LOW),
+ F_ROT( 29540000, MM_GPERF, 13, LOW),
+ F_ROT( 32000000, MM_GPERF, 12, LOW),
+ F_ROT( 38400000, MM_GPERF, 10, LOW),
+ F_ROT( 48000000, MM_GPERF, 8, LOW),
+ F_ROT( 54860000, MM_GPERF, 7, LOW),
+ F_ROT( 64000000, MM_GPERF, 6, LOW),
+ F_ROT( 76800000, MM_GPERF, 5, LOW),
+ F_ROT( 96000000, MM_GPERF, 4, NOMINAL),
+ F_ROT(100000000, MM_PLL1, 8, NOMINAL),
+ F_ROT(114290000, MM_PLL1, 7, NOMINAL),
+ F_ROT(133330000, MM_PLL1, 6, NOMINAL),
+ F_ROT(160000000, MM_PLL1, 5, NOMINAL),
+ F_END,
+};
+
+/* TV */
+#define NS_MASK_TV (BM(23, 16) | BM(15, 14) | BM(2, 0))
+#define CC_MASK_TV (BM(7, 6))
+#define CLK_TV(id, ns) \
+ CLK(id, MND, ns, (ns-8), (ns-4), NULL, 0, NULL, 0, 0, \
+ 0, B(2), NS_MASK_TV, CC_MASK_TV, set_rate_tv, \
+ clk_tbl_tv, NULL, NONE, chld_tv_src, 0)
+#define F_TV(f, s, p_r, d, m, n, v) \
+ F_RAW(f, SRC_##s, MD8(8, m, 0, n), \
+ NS_MM(23, 16, n, m, 15, 14, d, 2, 0, s), \
+ CC(6, n), MND_EN(B(5), n), v, p_r)
+/* Switching TV freqs requires PLL reconfiguration. */
+static struct pll_rate mm_pll2_rate[] = {
+ [0] = PLL_RATE( 7, 6301, 13500, 0, 4, 0x4248B), /* 50400500 Hz */
+ [1] = PLL_RATE( 8, 0, 0, 0, 4, 0x4248B), /* 54000000 Hz */
+ [2] = PLL_RATE(16, 2, 125, 0, 4, 0x4248F), /* 108108000 Hz */
+ [3] = PLL_RATE(22, 0, 0, 2, 4, 0x6248B), /* 148500000 Hz */
+ [4] = PLL_RATE(44, 0, 0, 2, 4, 0x6248F), /* 297000000 Hz */
+};
+static struct clk_freq_tbl clk_tbl_tv[] = {
+ F_TV( 25200000, MM_PLL2, &mm_pll2_rate[0], 2, 0, 0, LOW),
+ F_TV( 27000000, MM_PLL2, &mm_pll2_rate[1], 2, 0, 0, LOW),
+ F_TV( 27030000, MM_PLL2, &mm_pll2_rate[2], 4, 0, 0, LOW),
+ F_TV( 74250000, MM_PLL2, &mm_pll2_rate[3], 2, 0, 0, NOMINAL),
+ F_TV(148500000, MM_PLL2, &mm_pll2_rate[4], 2, 0, 0, NOMINAL),
+ F_END,
+};
+
+/* VCODEC */
+#define NS_MASK_VCODEC (BM(18, 11) | BM(2, 0))
+#define CC_MASK_VCODEC (BM(7, 6))
+#define CLK_VCODEC(id, ns, r_r, r_m, h_r, h_c, h_b, par, tv) \
+ CLK(id, MND, ns, (ns-8), (ns-4), r_r, r_m, h_r, h_c, h_b, \
+ B(0), B(2), NS_MASK_VCODEC, CC_MASK_VCODEC, \
+ set_rate_mnd, clk_tbl_vcodec, NULL, par, \
+ NULL, tv)
+#define F_VCODEC(f, s, m, n, v) \
+ F_RAW(f, SRC_##s, MD8(8, m, 0, n), \
+ NS_MM(18, 11, n, m, 0, 0, 1, 2, 0, s), \
+ CC(6, n), MND_EN(B(5), n), v, NULL)
+static struct clk_freq_tbl clk_tbl_vcodec[] = {
+ F_VCODEC( 27000000, MM_PXO, 0, 0, LOW),
+ F_VCODEC( 32000000, MM_GPERF, 1, 12, LOW),
+ F_VCODEC( 48000000, MM_GPERF, 1, 8, LOW),
+ F_VCODEC( 54860000, MM_GPERF, 1, 7, LOW),
+ F_VCODEC( 96000000, MM_GPERF, 1, 4, LOW),
+ F_VCODEC(133330000, MM_PLL1, 1, 6, NOMINAL),
+ F_VCODEC(200000000, MM_PLL1, 1, 4, NOMINAL),
+ F_VCODEC(228570000, MM_PLL1, 2, 7, HIGH),
+ F_END,
+};
+
+/* VPE */
+#define NS_MASK_VPE (BM(15, 12) | BM(2, 0))
+#define CLK_VPE(id, ns, r_r, r_m, h_r, h_c, h_b, tv) \
+ CLK(id, BASIC, (ns), (ns-8), NULL, r_r, r_m, h_r, h_c, \
+ h_b, B(0), B(2), NS_MASK_VPE, 0, \
+ set_rate_basic, clk_tbl_vpe, NULL, NONE, \
+ NULL, tv)
+#define F_VPE(f, s, d, v) \
+ F_RAW(f, SRC_##s, 0, NS_DIVSRC(15, 12, d, 2, 0, s), \
+ 0, 0, v, NULL)
+static struct clk_freq_tbl clk_tbl_vpe[] = {
+ F_VPE( 27000000, MM_PXO, 1, LOW),
+ F_VPE( 34909000, MM_GPERF, 11, LOW),
+ F_VPE( 38400000, MM_GPERF, 10, LOW),
+ F_VPE( 64000000, MM_GPERF, 6, LOW),
+ F_VPE( 76800000, MM_GPERF, 5, LOW),
+ F_VPE( 96000000, MM_GPERF, 4, NOMINAL),
+ F_VPE(100000000, MM_PLL1, 8, NOMINAL),
+ F_VPE(160000000, MM_PLL1, 5, NOMINAL),
+ F_END,
+};
+
+/* VFE */
+#define NS_MASK_VFE (BM(23, 16) | BM(11, 10) | BM(2, 0))
+#define CC_MASK_VFE (BM(7, 6))
+#define CLK_VFE(id, ns, r_r, r_m, h_r, h_c, h_b, par, tv) \
+ CLK(id, MND, ns, (ns-8), (ns-4), r_r, r_m, h_r, h_c, h_b, \
+ B(0), B(2), NS_MASK_VFE, CC_MASK_VFE, \
+ set_rate_mnd, clk_tbl_vfe, NULL, par, \
+ chld_vfe, tv)
+#define F_VFE(f, s, d, m, n, v) \
+ F_RAW(f, SRC_##s, MD8(8, m, 0, n), \
+ NS_MM(23, 16, n, m, 11, 10, d, 2, 0, s), \
+ CC(6, n), MND_EN(B(5), n), v, NULL)
+static struct clk_freq_tbl clk_tbl_vfe[] = {
+ F_VFE( 13960000, MM_GPERF, 1, 2, 55, LOW),
+ F_VFE( 27000000, MM_PXO, 1, 0, 0, LOW),
+ F_VFE( 36570000, MM_GPERF, 1, 2, 21, LOW),
+ F_VFE( 38400000, MM_GPERF, 2, 1, 5, LOW),
+ F_VFE( 45180000, MM_GPERF, 1, 2, 17, LOW),
+ F_VFE( 48000000, MM_GPERF, 2, 1, 4, LOW),
+ F_VFE( 54860000, MM_GPERF, 1, 1, 7, LOW),
+ F_VFE( 64000000, MM_GPERF, 2, 1, 3, LOW),
+ F_VFE( 76800000, MM_GPERF, 1, 1, 5, LOW),
+ F_VFE( 96000000, MM_GPERF, 2, 1, 2, LOW),
+ F_VFE(109710000, MM_GPERF, 1, 2, 7, LOW),
+ F_VFE(128000000, MM_GPERF, 1, 1, 3, NOMINAL),
+ F_VFE(153600000, MM_GPERF, 1, 2, 5, NOMINAL),
+ F_VFE(200000000, MM_PLL1, 2, 1, 2, NOMINAL),
+ F_VFE(228570000, MM_PLL1, 1, 2, 7, NOMINAL),
+ F_END,
+};
+
+/* Audio Interface OSR */
+#define NS_MASK_AIF_OSR (BM(31, 24) | BM(6, 0))
+#define CLK_AIF_OSR(id, ns, h_r, h_c, h_b, tv) \
+ CLK(id, MND, ns, ns, (ns+4), ns, B(19), h_r, h_c, h_b, \
+ B(17), B(9), NS_MASK_AIF_OSR, 0, set_rate_mnd, \
+ clk_tbl_aif_osr, NULL, NONE, NULL, tv)
+#define F_AIF_OSR(f, s, d, m, n, v) \
+ F_RAW(f, SRC_##s, MD8(8, m, 0, n), \
+ NS(31, 24, n, m, 5, 4, 3, d, 2, 0, s), \
+ 0, MND_EN(B(8), n), v, NULL)
+static struct clk_freq_tbl clk_tbl_aif_osr[] = {
+ F_AIF_OSR( 768000, LPA_PLL0, 4, 1, 176, LOW),
+ F_AIF_OSR( 1024000, LPA_PLL0, 4, 1, 132, LOW),
+ F_AIF_OSR( 1536000, LPA_PLL0, 4, 1, 88, LOW),
+ F_AIF_OSR( 2048000, LPA_PLL0, 4, 1, 66, LOW),
+ F_AIF_OSR( 3072000, LPA_PLL0, 4, 1, 44, LOW),
+ F_AIF_OSR( 4096000, LPA_PLL0, 4, 1, 33, LOW),
+ F_AIF_OSR( 6144000, LPA_PLL0, 4, 1, 22, LOW),
+ F_AIF_OSR( 8192000, LPA_PLL0, 2, 1, 33, LOW),
+ F_AIF_OSR(12288000, LPA_PLL0, 4, 1, 11, LOW),
+ F_AIF_OSR(24576000, LPA_PLL0, 2, 1, 11, LOW),
+ F_END,
+};
+
+/* Audio Interface Bit */
+#define NS_MASK_AIF_BIT BM(14, 10)
+#define CLK_AIF_BIT(id, ns, h_r, h_c, h_b, tv) \
+ CLK(id, BASIC, ns, ns, 0, ns, B(19), h_r, h_c, h_b, \
+ B(15), 0, NS_MASK_AIF_BIT, 0, set_rate_basic, \
+ clk_tbl_aif_bit, NULL, NONE, NULL, tv)
+#define F_AIF_BIT(d, s) \
+ F_RAW(d, SRC_NONE, 0, (BVAL(14, 14, s) | BVAL(13, 10, (d-1))), \
+ 0, 0, 0, NULL)
+static struct clk_freq_tbl clk_tbl_aif_bit[] = {
+ F_AIF_BIT(0, 1), /* Use external clock. */
+ F_AIF_BIT(1, 0), F_AIF_BIT(2, 0), F_AIF_BIT(3, 0), F_AIF_BIT(4, 0),
+ F_AIF_BIT(5, 0), F_AIF_BIT(6, 0), F_AIF_BIT(7, 0), F_AIF_BIT(8, 0),
+ F_AIF_BIT(9, 0), F_AIF_BIT(10, 0), F_AIF_BIT(11, 0), F_AIF_BIT(12, 0),
+ F_AIF_BIT(13, 0), F_AIF_BIT(14, 0), F_AIF_BIT(15, 0), F_AIF_BIT(16, 0),
+ F_END,
+};
+
+/* PCM */
+#define NS_MASK_PCM (BM(31, 16) | BM(6, 0))
+#define CLK_PCM(id, ns, h_r, h_c, h_b, tv) \
+ CLK(id, MND, ns, ns, (ns+4), ns, B(13), h_r, h_c, h_b, \
+ B(11), B(9), NS_MASK_PCM, 0, set_rate_mnd, \
+ clk_tbl_pcm, NULL, NONE, NULL, tv)
+#define F_PCM(f, s, d, m, n, v) \
+ F_RAW(f, SRC_##s, MD16(m, n), \
+ NS(31, 16, n, m, 5, 4, 3, d, 2, 0, s), \
+ 0, MND_EN(B(8), n), v, NULL)
+static struct clk_freq_tbl clk_tbl_pcm[] = {
+ F_PCM( 512000, LPA_PLL0, 4, 1, 264, LOW),
+ F_PCM( 768000, LPA_PLL0, 4, 1, 176, LOW),
+ F_PCM( 1024000, LPA_PLL0, 4, 1, 132, LOW),
+ F_PCM( 1536000, LPA_PLL0, 4, 1, 88, LOW),
+ F_PCM( 2048000, LPA_PLL0, 4, 1, 66, LOW),
+ F_PCM( 3072000, LPA_PLL0, 4, 1, 44, LOW),
+ F_PCM( 4096000, LPA_PLL0, 4, 1, 33, LOW),
+ F_PCM( 6144000, LPA_PLL0, 4, 1, 22, LOW),
+ F_PCM( 8192000, LPA_PLL0, 2, 1, 33, LOW),
+ F_PCM(12288000, LPA_PLL0, 4, 1, 11, LOW),
+ F_PCM(24580000, LPA_PLL0, 2, 1, 11, LOW),
+ F_END,
+};
+
+/*
+ * Clock children lists
+ */
+static const uint32_t chld_usb_fs1_src[] = {C(USB_FS1_XCVR),
+ C(USB_FS1_SYS), C(NONE)};
+static const uint32_t chld_usb_fs2_src[] = {C(USB_FS2_XCVR),
+ C(USB_FS2_SYS), C(NONE)};
+static const uint32_t chld_csi_src[] = {C(CSI0), C(CSI1), C(NONE)};
+static const uint32_t chld_pixel_mdp[] = {C(PIXEL_LCDC), C(NONE)};
+static const uint32_t chld_tv_src[] = {C(TV_ENC), C(TV_DAC),
+ C(MDP_TV), C(HDMI_TV),
+ C(NONE)};
+static const uint32_t chld_vfe[] = {C(CSI0_VFE), C(CSI1_VFE),
+ C(NONE)};
+
+/*
+ * Clock table
+ */
+struct clk_local soc_clk_local_tbl[] = {
+ /*
+ * Peripheral Clocks
+ */
+ CLK_NORATE(CE2, CE2_HCLK_CTL_REG, B(4), NULL, 0,
+ CLK_HALT_CFPB_STATEC_REG, HALT, 0, TEST_PER_LS(0x93)),
+
+ CLK_GSBI_UART(GSBI1_UART, GSBIn_UART_APPS_NS_REG(1),
+ CLK_HALT_CFPB_STATEA_REG, HALT, 10, TEST_PER_LS(0x3E)),
+ CLK_GSBI_UART(GSBI2_UART, GSBIn_UART_APPS_NS_REG(2),
+ CLK_HALT_CFPB_STATEA_REG, HALT, 6, TEST_PER_LS(0x42)),
+ CLK_GSBI_UART(GSBI3_UART, GSBIn_UART_APPS_NS_REG(3),
+ CLK_HALT_CFPB_STATEA_REG, HALT, 2, TEST_PER_LS(0x46)),
+ CLK_GSBI_UART(GSBI4_UART, GSBIn_UART_APPS_NS_REG(4),
+ CLK_HALT_CFPB_STATEB_REG, HALT, 26, TEST_PER_LS(0x4A)),
+ CLK_GSBI_UART(GSBI5_UART, GSBIn_UART_APPS_NS_REG(5),
+ CLK_HALT_CFPB_STATEB_REG, HALT, 22, TEST_PER_LS(0x4E)),
+ CLK_GSBI_UART(GSBI6_UART, GSBIn_UART_APPS_NS_REG(6),
+ CLK_HALT_CFPB_STATEB_REG, HALT, 18, TEST_PER_LS(0x52)),
+ CLK_GSBI_UART(GSBI7_UART, GSBIn_UART_APPS_NS_REG(7),
+ CLK_HALT_CFPB_STATEB_REG, HALT, 14, TEST_PER_LS(0x56)),
+ CLK_GSBI_UART(GSBI8_UART, GSBIn_UART_APPS_NS_REG(8),
+ CLK_HALT_CFPB_STATEB_REG, HALT, 10, TEST_PER_LS(0x5A)),
+ CLK_GSBI_UART(GSBI9_UART, GSBIn_UART_APPS_NS_REG(9),
+ CLK_HALT_CFPB_STATEB_REG, HALT, 6, TEST_PER_LS(0x5E)),
+ CLK_GSBI_UART(GSBI10_UART, GSBIn_UART_APPS_NS_REG(10),
+ CLK_HALT_CFPB_STATEB_REG, HALT, 2, TEST_PER_LS(0x62)),
+ CLK_GSBI_UART(GSBI11_UART, GSBIn_UART_APPS_NS_REG(11),
+ CLK_HALT_CFPB_STATEC_REG, HALT, 17, TEST_PER_LS(0x66)),
+ CLK_GSBI_UART(GSBI12_UART, GSBIn_UART_APPS_NS_REG(12),
+ CLK_HALT_CFPB_STATEC_REG, HALT, 13, TEST_PER_LS(0x6A)),
+
+ CLK_GSBI_QUP(GSBI1_QUP, GSBIn_QUP_APPS_NS_REG(1),
+ CLK_HALT_CFPB_STATEA_REG, HALT, 9, TEST_PER_LS(0x3F)),
+ CLK_GSBI_QUP(GSBI2_QUP, GSBIn_QUP_APPS_NS_REG(2),
+ CLK_HALT_CFPB_STATEA_REG, HALT, 4, TEST_PER_LS(0x44)),
+ CLK_GSBI_QUP(GSBI3_QUP, GSBIn_QUP_APPS_NS_REG(3),
+ CLK_HALT_CFPB_STATEA_REG, HALT, 0, TEST_PER_LS(0x48)),
+ CLK_GSBI_QUP(GSBI4_QUP, GSBIn_QUP_APPS_NS_REG(4),
+ CLK_HALT_CFPB_STATEB_REG, HALT, 24, TEST_PER_LS(0x4C)),
+ CLK_GSBI_QUP(GSBI5_QUP, GSBIn_QUP_APPS_NS_REG(5),
+ CLK_HALT_CFPB_STATEB_REG, HALT, 20, TEST_PER_LS(0x50)),
+ CLK_GSBI_QUP(GSBI6_QUP, GSBIn_QUP_APPS_NS_REG(6),
+ CLK_HALT_CFPB_STATEB_REG, HALT, 16, TEST_PER_LS(0x54)),
+ CLK_GSBI_QUP(GSBI7_QUP, GSBIn_QUP_APPS_NS_REG(7),
+ CLK_HALT_CFPB_STATEB_REG, HALT, 12, TEST_PER_LS(0x58)),
+ CLK_GSBI_QUP(GSBI8_QUP, GSBIn_QUP_APPS_NS_REG(8),
+ CLK_HALT_CFPB_STATEB_REG, HALT, 8, TEST_PER_LS(0x5C)),
+ CLK_GSBI_QUP(GSBI9_QUP, GSBIn_QUP_APPS_NS_REG(9),
+ CLK_HALT_CFPB_STATEB_REG, HALT, 4, TEST_PER_LS(0x60)),
+ CLK_GSBI_QUP(GSBI10_QUP, GSBIn_QUP_APPS_NS_REG(10),
+ CLK_HALT_CFPB_STATEB_REG, HALT, 0, TEST_PER_LS(0x64)),
+ CLK_GSBI_QUP(GSBI11_QUP, GSBIn_QUP_APPS_NS_REG(11),
+ CLK_HALT_CFPB_STATEC_REG, HALT, 15, TEST_PER_LS(0x68)),
+ CLK_GSBI_QUP(GSBI12_QUP, GSBIn_QUP_APPS_NS_REG(12),
+ CLK_HALT_CFPB_STATEC_REG, HALT, 11, TEST_PER_LS(0x6C)),
+
+ CLK_PDM(PDM, PDM_CLK_NS_REG, CLK_HALT_CFPB_STATEC_REG, HALT, 3),
+
+ CLK_NORATE(PMEM, PMEM_ACLK_CTL_REG, B(4), NULL, 0,
+ CLK_HALT_DFAB_STATE_REG, HALT, 20, TEST_PER_LS(0x26)),
+
+ CLK_PRNG(PRNG, PRNG_CLK_NS_REG, SC0_U_CLK_BRANCH_ENA_VOTE_REG,
+ CLK_HALT_SFPB_MISC_STATE_REG, HALT_VOTED, 10,
+ TEST_PER_LS(0x7D)),
+
+ CLK_SDC(SDC1, SDCn_APPS_CLK_NS_REG(1), CLK_HALT_DFAB_STATE_REG,
+ HALT, 6, TEST_PER_LS(0x13)),
+ CLK_SDC(SDC2, SDCn_APPS_CLK_NS_REG(2), CLK_HALT_DFAB_STATE_REG,
+ HALT, 5, TEST_PER_LS(0x15)),
+ CLK_SDC(SDC3, SDCn_APPS_CLK_NS_REG(3), CLK_HALT_DFAB_STATE_REG,
+ HALT, 4, TEST_PER_LS(0x17)),
+ CLK_SDC(SDC4, SDCn_APPS_CLK_NS_REG(4), CLK_HALT_DFAB_STATE_REG,
+ HALT, 3, TEST_PER_LS(0x19)),
+ CLK_SDC(SDC5, SDCn_APPS_CLK_NS_REG(5), CLK_HALT_DFAB_STATE_REG,
+ HALT, 2, TEST_PER_LS(0x1B)),
+
+ CLK_TSIF_REF(TSIF_REF, TSIF_REF_CLK_NS_REG,
+ CLK_HALT_CFPB_STATEC_REG, HALT, 5, TEST_PER_LS(0x91)),
+
+ CLK_TSSC(TSSC, TSSC_CLK_CTL_REG,
+ CLK_HALT_CFPB_STATEC_REG, HALT, 4, TEST_PER_LS(0x94)),
+
+ CLK_USB_HS(USB_HS1_XCVR, USB_HS1_XCVR_FS_CLK_NS,
+ CLK_HALT_DFAB_STATE_REG, HALT, 0, TEST_PER_LS(0x85)),
+ CLK_RESET(USB_PHY0, USB_PHY0_RESET_REG, B(0)),
+
+ CLK_USB_FS(USB_FS1_SRC, USB_FS1_XCVR_FS_CLK_NS_REG, chld_usb_fs1_src),
+ CLK_SLAVE(USB_FS1_XCVR, USB_FS1_XCVR_FS_CLK_NS_REG, B(9),
+ USB_FS1_RESET_REG, B(1), CLK_HALT_CFPB_STATEA_REG,
+ HALT, 15, USB_FS1_SRC, TEST_PER_LS(0x8B)),
+ CLK_SLAVE(USB_FS1_SYS, USB_FS1_SYSTEM_CLK_CTL_REG, B(4),
+ USB_FS1_RESET_REG, B(0), CLK_HALT_CFPB_STATEA_REG,
+ HALT, 16, USB_FS1_SRC, TEST_PER_LS(0x8A)),
+
+ CLK_USB_FS(USB_FS2_SRC, USB_FS2_XCVR_FS_CLK_NS_REG, chld_usb_fs2_src),
+ CLK_SLAVE(USB_FS2_XCVR, USB_FS2_XCVR_FS_CLK_NS_REG, B(9),
+ USB_FS2_RESET_REG, B(1), CLK_HALT_CFPB_STATEA_REG,
+ HALT, 12, USB_FS2_SRC, TEST_PER_LS(0x8E)),
+ CLK_SLAVE(USB_FS2_SYS, USB_FS2_SYSTEM_CLK_CLK_REG, B(4),
+ USB_FS2_RESET_REG, B(0), CLK_HALT_CFPB_STATEA_REG,
+ HALT, 13, USB_FS2_SRC, TEST_PER_LS(0x8D)),
+
+ /* Fast Peripheral Bus Clocks */
+ CLK_NORATE(GSBI1_P, GSBIn_HCLK_CTL_REG(1), B(4), NULL, 0,
+ CLK_HALT_CFPB_STATEA_REG, HALT, 11, TEST_PER_LS(0x3D)),
+ CLK_NORATE(GSBI2_P, GSBIn_HCLK_CTL_REG(2), B(4), NULL, 0,
+ CLK_HALT_CFPB_STATEA_REG, HALT, 7, TEST_PER_LS(0x41)),
+ CLK_NORATE(GSBI3_P, GSBIn_HCLK_CTL_REG(3), B(4), NULL, 0,
+ CLK_HALT_CFPB_STATEA_REG, HALT, 3, TEST_PER_LS(0x45)),
+ CLK_NORATE(GSBI4_P, GSBIn_HCLK_CTL_REG(4), B(4), NULL, 0,
+ CLK_HALT_CFPB_STATEB_REG, HALT, 27, TEST_PER_LS(0x49)),
+ CLK_NORATE(GSBI5_P, GSBIn_HCLK_CTL_REG(5), B(4), NULL, 0,
+ CLK_HALT_CFPB_STATEB_REG, HALT, 23, TEST_PER_LS(0x4D)),
+ CLK_NORATE(GSBI6_P, GSBIn_HCLK_CTL_REG(6), B(4), NULL, 0,
+ CLK_HALT_CFPB_STATEB_REG, HALT, 19, TEST_PER_LS(0x51)),
+ CLK_NORATE(GSBI7_P, GSBIn_HCLK_CTL_REG(7), B(4), NULL, 0,
+ CLK_HALT_CFPB_STATEB_REG, HALT, 15, TEST_PER_LS(0x55)),
+ CLK_NORATE(GSBI8_P, GSBIn_HCLK_CTL_REG(8), B(4), NULL, 0,
+ CLK_HALT_CFPB_STATEB_REG, HALT, 11, TEST_PER_LS(0x59)),
+ CLK_NORATE(GSBI9_P, GSBIn_HCLK_CTL_REG(9), B(4), NULL, 0,
+ CLK_HALT_CFPB_STATEB_REG, HALT, 7, TEST_PER_LS(0x5D)),
+ CLK_NORATE(GSBI10_P, GSBIn_HCLK_CTL_REG(10), B(4), NULL, 0,
+ CLK_HALT_CFPB_STATEB_REG, HALT, 3, TEST_PER_LS(0x61)),
+ CLK_NORATE(GSBI11_P, GSBIn_HCLK_CTL_REG(11), B(4), NULL, 0,
+ CLK_HALT_CFPB_STATEC_REG, HALT, 18, TEST_PER_LS(0x65)),
+ CLK_NORATE(GSBI12_P, GSBIn_HCLK_CTL_REG(12), B(4), NULL, 0,
+ CLK_HALT_CFPB_STATEC_REG, HALT, 14, TEST_PER_LS(0x69)),
+
+ CLK_NORATE(PPSS_P, PPSS_HCLK_CTL_REG, B(4), NULL, 0,
+ CLK_HALT_DFAB_STATE_REG, HALT, 19, TEST_PER_LS(0x2B)),
+
+ CLK_NORATE(TSIF_P, TSIF_HCLK_CTL_REG, B(4), NULL, 0,
+ CLK_HALT_CFPB_STATEC_REG, HALT, 7, TEST_PER_LS(0x8F)),
+
+ CLK_NORATE(USB_FS1_P, USB_FS1_HCLK_CTL_REG, B(4), NULL, 0,
+ CLK_HALT_CFPB_STATEA_REG, HALT, 17, TEST_PER_LS(0x89)),
+ CLK_NORATE(USB_FS2_P, USB_FS2_HCLK_CTL_REG, B(4), NULL, 0,
+ CLK_HALT_CFPB_STATEA_REG, HALT, 14, TEST_PER_LS(0x8C)),
+
+ CLK_NORATE(USB_HS1_P, USB_HS1_HCLK_CTL_REG, B(4), NULL, 0,
+ CLK_HALT_DFAB_STATE_REG, HALT, 1, TEST_PER_LS(0x84)),
+
+ CLK_NORATE(SDC1_P, SDCn_HCLK_CTL_REG(1), B(4), NULL, 0,
+ CLK_HALT_DFAB_STATE_REG, HALT, 11, TEST_PER_LS(0x12)),
+ CLK_NORATE(SDC2_P, SDCn_HCLK_CTL_REG(2), B(4), NULL, 0,
+ CLK_HALT_DFAB_STATE_REG, HALT, 10, TEST_PER_LS(0x14)),
+ CLK_NORATE(SDC3_P, SDCn_HCLK_CTL_REG(3), B(4), NULL, 0,
+ CLK_HALT_DFAB_STATE_REG, HALT, 9, TEST_PER_LS(0x16)),
+ CLK_NORATE(SDC4_P, SDCn_HCLK_CTL_REG(4), B(4), NULL, 0,
+ CLK_HALT_DFAB_STATE_REG, HALT, 8, TEST_PER_LS(0x18)),
+ CLK_NORATE(SDC5_P, SDCn_HCLK_CTL_REG(5), B(4), NULL, 0,
+ CLK_HALT_DFAB_STATE_REG, HALT, 7, TEST_PER_LS(0x1A)),
+
+ /* HW-Voteable Clocks */
+ CLK_NORATE(ADM0, SC0_U_CLK_BRANCH_ENA_VOTE_REG, B(2), NULL, 0,
+ CLK_HALT_MSS_SMPSS_MISC_STATE_REG, HALT_VOTED, 14,
+ TEST_PER_HS(0x2A)),
+ CLK_NORATE(ADM0_P, SC0_U_CLK_BRANCH_ENA_VOTE_REG, B(3), NULL, 0,
+ CLK_HALT_MSS_SMPSS_MISC_STATE_REG, HALT_VOTED, 13,
+ TEST_PER_LS(0x80)),
+ CLK_NORATE(ADM1, SC0_U_CLK_BRANCH_ENA_VOTE_REG, B(4), NULL, 0,
+ CLK_HALT_MSS_SMPSS_MISC_STATE_REG, HALT_VOTED, 12,
+ TEST_PER_HS(0x2B)),
+ CLK_NORATE(ADM1_P, SC0_U_CLK_BRANCH_ENA_VOTE_REG, B(5), NULL, 0,
+ CLK_HALT_MSS_SMPSS_MISC_STATE_REG, HALT_VOTED, 11,
+ TEST_PER_LS(0x81)),
+ CLK_NORATE(MODEM_AHB1_P, SC0_U_CLK_BRANCH_ENA_VOTE_REG, B(0), NULL, 0,
+ CLK_HALT_MSS_SMPSS_MISC_STATE_REG, HALT_VOTED, 8,
+ TEST_PER_LS(0x08)),
+ CLK_NORATE(MODEM_AHB2_P, SC0_U_CLK_BRANCH_ENA_VOTE_REG, B(1), NULL, 0,
+ CLK_HALT_MSS_SMPSS_MISC_STATE_REG, HALT_VOTED, 7,
+ TEST_PER_LS(0x09)),
+ CLK_NORATE(PMIC_ARB0_P, SC0_U_CLK_BRANCH_ENA_VOTE_REG, B(8), NULL, 0,
+ CLK_HALT_SFPB_MISC_STATE_REG, HALT_VOTED, 22,
+ TEST_PER_LS(0x7B)),
+ CLK_NORATE(PMIC_ARB1_P, SC0_U_CLK_BRANCH_ENA_VOTE_REG, B(9), NULL, 0,
+ CLK_HALT_SFPB_MISC_STATE_REG, HALT_VOTED, 21,
+ TEST_PER_LS(0x7C)),
+ CLK_NORATE(PMIC_SSBI2, SC0_U_CLK_BRANCH_ENA_VOTE_REG, B(7), NULL, 0,
+ CLK_HALT_SFPB_MISC_STATE_REG, HALT_VOTED, 23,
+ TEST_PER_LS(0x7A)),
+ CLK_NORATE(RPM_MSG_RAM_P, SC0_U_CLK_BRANCH_ENA_VOTE_REG, B(6), NULL, 0,
+ CLK_HALT_SFPB_MISC_STATE_REG, HALT_VOTED, 12,
+ TEST_PER_LS(0x7F)),
+
+ /*
+ * Multimedia Clocks
+ */
+
+ CLK_RESET(AMP, SW_RESET_CORE_REG, B(20)),
+
+ CLK_CAM(CAM, CAMCLK_NS_REG, NULL, DELAY, 0, TEST_MM_LS(0x1D)),
+
+ CLK_CSI(CSI_SRC, CSI_NS_REG),
+ CLK_SLAVE(CSI0, CSI_CC_REG, B(0), SW_RESET_CORE_REG, B(8),
+ DBG_BUS_VEC_B_REG, HALT, 13, CSI_SRC, TEST_MM_HS(0x00)),
+ CLK_SLAVE(CSI1, CSI_CC_REG, B(7), SW_RESET_CORE_REG, B(18),
+ DBG_BUS_VEC_B_REG, HALT, 14, CSI_SRC, TEST_MM_HS(0x01)),
+
+ CLK_DSI_BYTE(DSI_BYTE, MISC_CC2_REG, SW_RESET_CORE_REG, B(7),
+ DBG_BUS_VEC_B_REG, DELAY, 0, TEST_MM_LS(0x00)),
+ CLK_NORATE(DSI_ESC, MISC_CC_REG, B(0), NULL, 0,
+ DBG_BUS_VEC_B_REG, HALT, 24, TEST_MM_LS(0x23)),
+
+ CLK_GFX2D0(GFX2D0, GFX2D0_NS_REG, SW_RESET_CORE_REG, B(14),
+ DBG_BUS_VEC_A_REG, HALT, 9, TEST_MM_HS(0x07)),
+ CLK_GFX2D1(GFX2D1, GFX2D1_NS_REG, SW_RESET_CORE_REG, B(13),
+ DBG_BUS_VEC_A_REG, HALT, 14, TEST_MM_HS(0x08)),
+ CLK_GFX3D(GFX3D, GFX3D_NS_REG, SW_RESET_CORE_REG, B(12),
+ DBG_BUS_VEC_A_REG, HALT, 4, GMEM_AXI, TEST_MM_HS(0x09)),
+
+ CLK_IJPEG(IJPEG, IJPEG_NS_REG, SW_RESET_CORE_REG, B(9),
+ DBG_BUS_VEC_A_REG, HALT, 24, TEST_MM_HS(0x05)),
+
+ CLK_RESET(IMEM, SW_RESET_CORE_REG, B(10)),
+
+ CLK_JPEGD(JPEGD, JPEGD_NS_REG, SW_RESET_CORE_REG, B(19),
+ DBG_BUS_VEC_A_REG, HALT, 19, JPEGD_AXI, TEST_MM_HS(0x0A)),
+
+ CLK_MDP(MDP, MDP_NS_REG, SW_RESET_CORE_REG, B(21),
+ DBG_BUS_VEC_C_REG, HALT, 10, TEST_MM_HS(0x1A)),
+ CLK_MDP_VSYNC(MDP_VSYNC, MISC_CC2_REG, SW_RESET_CORE_REG, B(3),
+ DBG_BUS_VEC_B_REG, HALT, 22, TEST_MM_LS(0x20)),
+
+ CLK_PIXEL_MDP(PIXEL_MDP, PIXEL_NS_REG, SW_RESET_CORE_REG, B(5),
+ DBG_BUS_VEC_C_REG, HALT, 23, TEST_MM_LS(0x04)),
+ CLK_SLAVE(PIXEL_LCDC, PIXEL_CC_REG, B(8), NULL, 0,
+ DBG_BUS_VEC_C_REG, HALT, 21, PIXEL_MDP, TEST_MM_LS(0x01)),
+
+ CLK_ROT(ROT, ROT_NS_REG, SW_RESET_CORE_REG, B(2),
+ DBG_BUS_VEC_C_REG, HALT, 15, TEST_MM_HS(0x1B)),
+
+ CLK_TV(TV_SRC, TV_NS_REG),
+ CLK_SLAVE(TV_ENC, TV_CC_REG, B(8), SW_RESET_CORE_REG, B(0),
+ DBG_BUS_VEC_D_REG, HALT, 8, TV_SRC, TEST_MM_LS(0x22)),
+ CLK_SLAVE(TV_DAC, TV_CC_REG, B(10), NULL, 0,
+ DBG_BUS_VEC_D_REG, HALT, 9, TV_SRC, TEST_MM_LS(0x21)),
+ CLK_SLAVE(MDP_TV, TV_CC_REG, B(0), SW_RESET_CORE_REG, B(4),
+ DBG_BUS_VEC_D_REG, HALT, 11, TV_SRC, TEST_MM_HS(0x1F)),
+ CLK_SLAVE(HDMI_TV, TV_CC_REG, B(12), SW_RESET_CORE_REG, B(1),
+ DBG_BUS_VEC_D_REG, HALT, 10, TV_SRC, TEST_MM_HS(0x1E)),
+
+ CLK_NORATE(HDMI_APP, MISC_CC2_REG, B(11), SW_RESET_CORE_REG, B(11),
+ DBG_BUS_VEC_B_REG, HALT, 25, TEST_MM_LS(0x1F)),
+
+ CLK_VCODEC(VCODEC, VCODEC_NS_REG, SW_RESET_CORE_REG, B(6),
+ DBG_BUS_VEC_C_REG, HALT, 29, VCODEC_AXI, TEST_MM_HS(0x0B)),
+
+ CLK_VPE(VPE, VPE_NS_REG, SW_RESET_CORE_REG, B(17),
+ DBG_BUS_VEC_A_REG, HALT, 28, TEST_MM_HS(0x1C)),
+
+ CLK_VFE(VFE, VFE_NS_REG, SW_RESET_CORE_REG, B(15),
+ DBG_BUS_VEC_B_REG, HALT, 6, VFE_AXI, TEST_MM_HS(0x06)),
+ CLK_SLAVE(CSI0_VFE, VFE_CC_REG, B(12), SW_RESET_CORE_REG, B(24),
+ DBG_BUS_VEC_B_REG, HALT, 7, VFE, TEST_MM_HS(0x03)),
+ CLK_SLAVE(CSI1_VFE, VFE_CC_REG, B(10), SW_RESET_CORE_REG, B(23),
+ DBG_BUS_VEC_B_REG, HALT, 8, VFE, TEST_MM_HS(0x04)),
+
+ /* AXI Interfaces */
+ CLK_NORATE(GMEM_AXI, MAXI_EN_REG, B(24), NULL, 0,
+ DBG_BUS_VEC_E_REG, HALT, 6, TEST_MM_HS(0x11)),
+ CLK_NORATE(JPEGD_AXI, MAXI_EN_REG, B(25), NULL, 0,
+ DBG_BUS_VEC_E_REG, HALT, 5, TEST_MM_HS(0x14)),
+ CLK_NORATE(VCODEC_AXI, MAXI_EN_REG, B(19), SW_RESET_AXI_REG,
+ B(4)|B(5), DBG_BUS_VEC_E_REG, HALT, 3, TEST_MM_HS(0x17)),
+ CLK_NORATE(VFE_AXI, MAXI_EN_REG, B(18), SW_RESET_AXI_REG, B(9),
+ DBG_BUS_VEC_E_REG, HALT, 0, TEST_MM_HS(0x18)),
+ CLK_RESET(IJPEG_AXI, SW_RESET_AXI_REG, B(14)),
+ CLK_RESET(MDP_AXI, SW_RESET_AXI_REG, B(13)),
+ CLK_RESET(ROT_AXI, SW_RESET_AXI_REG, B(6)),
+ CLK_RESET(VPE_AXI, SW_RESET_AXI_REG, B(15)),
+
+ /* AHB Interfaces */
+ CLK_NORATE(AMP_P, AHB_EN_REG, B(24), NULL, 0,
+ DBG_BUS_VEC_F_REG, HALT, 18, TEST_MM_LS(0x06)),
+ CLK_NORATE(CSI0_P, AHB_EN_REG, B(7), SW_RESET_AHB_REG, B(17),
+ DBG_BUS_VEC_F_REG, HALT, 16, TEST_MM_LS(0x07)),
+ CLK_NORATE(CSI1_P, AHB_EN_REG, B(20), SW_RESET_AHB_REG, B(16),
+ DBG_BUS_VEC_F_REG, HALT, 17, TEST_MM_LS(0x08)),
+ CLK_NORATE(DSI_M_P, AHB_EN_REG, B(9), SW_RESET_AHB_REG, B(6),
+ DBG_BUS_VEC_F_REG, HALT, 19, TEST_MM_LS(0x09)),
+ CLK_NORATE(DSI_S_P, AHB_EN_REG, B(18), SW_RESET_AHB_REG, B(5),
+ DBG_BUS_VEC_F_REG, HALT, 20, TEST_MM_LS(0x0A)),
+ CLK_NORATE(GFX2D0_P, AHB_EN_REG, B(19), SW_RESET_AHB_REG, B(12),
+ DBG_BUS_VEC_F_REG, HALT, 2, TEST_MM_LS(0x0C)),
+ CLK_NORATE(GFX2D1_P, AHB_EN_REG, B(2), SW_RESET_AHB_REG, B(11),
+ DBG_BUS_VEC_F_REG, HALT, 3, TEST_MM_LS(0x0D)),
+ CLK_NORATE(GFX3D_P, AHB_EN_REG, B(3), SW_RESET_AHB_REG, B(10),
+ DBG_BUS_VEC_F_REG, HALT, 4, TEST_MM_LS(0x0E)),
+ CLK_NORATE(HDMI_M_P, AHB_EN_REG, B(14), SW_RESET_AHB_REG, B(9),
+ DBG_BUS_VEC_F_REG, HALT, 5, TEST_MM_LS(0x0F)),
+ CLK_NORATE(HDMI_S_P, AHB_EN_REG, B(4), SW_RESET_AHB_REG, B(9),
+ DBG_BUS_VEC_F_REG, HALT, 6, TEST_MM_LS(0x10)),
+ CLK_NORATE(IJPEG_P, AHB_EN_REG, B(5), SW_RESET_AHB_REG, B(7),
+ DBG_BUS_VEC_F_REG, HALT, 9, TEST_MM_LS(0x11)),
+ CLK_NORATE(IMEM_P, AHB_EN_REG, B(6), SW_RESET_AHB_REG, B(8),
+ DBG_BUS_VEC_F_REG, HALT, 10, TEST_MM_LS(0x12)),
+ CLK_NORATE(JPEGD_P, AHB_EN_REG, B(21), SW_RESET_AHB_REG, B(4),
+ DBG_BUS_VEC_F_REG, HALT, 7, TEST_MM_LS(0x13)),
+ CLK_NORATE(MDP_P, AHB_EN_REG, B(10), SW_RESET_AHB_REG, B(3),
+ DBG_BUS_VEC_F_REG, HALT, 11, TEST_MM_LS(0x14)),
+ CLK_NORATE(ROT_P, AHB_EN_REG, B(12), SW_RESET_AHB_REG, B(2),
+ DBG_BUS_VEC_F_REG, HALT, 13, TEST_MM_LS(0x16)),
+ CLK_NORATE(SMMU_P, AHB_EN_REG, B(15), NULL, 0,
+ DBG_BUS_VEC_F_REG, HALT, 22, TEST_MM_LS(0x18)),
+ CLK_NORATE(TV_ENC_P, AHB_EN_REG, B(25), SW_RESET_AHB_REG, B(15),
+ DBG_BUS_VEC_F_REG, HALT, 23, TEST_MM_LS(0x19)),
+ CLK_NORATE(VCODEC_P, AHB_EN_REG, B(11), SW_RESET_AHB_REG, B(1),
+ DBG_BUS_VEC_F_REG, HALT, 12, TEST_MM_LS(0x1A)),
+ CLK_NORATE(VFE_P, AHB_EN_REG, B(13), SW_RESET_AHB_REG, B(0),
+ DBG_BUS_VEC_F_REG, HALT, 14, TEST_MM_LS(0x1B)),
+ CLK_NORATE(VPE_P, AHB_EN_REG, B(16), SW_RESET_AHB_REG, B(14),
+ DBG_BUS_VEC_F_REG, HALT, 15, TEST_MM_LS(0x1C)),
+
+ /*
+ * Low Power Audio Clocks
+ */
+
+ CLK_AIF_OSR(MI2S_OSR, LCC_MI2S_NS_REG,
+ LCC_MI2S_STATUS_REG, ENABLE, 1, TEST_LPA(0x0A)),
+ CLK_AIF_BIT(MI2S_BIT, LCC_MI2S_NS_REG,
+ LCC_MI2S_STATUS_REG, DELAY, 0, TEST_LPA(0x0B)),
+
+ CLK_AIF_OSR(CODEC_I2S_MIC_OSR, LCC_CODEC_I2S_MIC_NS_REG,
+ LCC_CODEC_I2S_MIC_STATUS_REG, ENABLE, 1, TEST_LPA(0x0C)),
+ CLK_AIF_BIT(CODEC_I2S_MIC_BIT, LCC_CODEC_I2S_MIC_NS_REG,
+ LCC_CODEC_I2S_MIC_STATUS_REG, DELAY, 0, TEST_LPA(0x0D)),
+
+ CLK_AIF_OSR(SPARE_I2S_MIC_OSR, LCC_SPARE_I2S_MIC_NS_REG,
+ LCC_SPARE_I2S_MIC_STATUS_REG, ENABLE, 1, TEST_LPA(0x10)),
+ CLK_AIF_BIT(SPARE_I2S_MIC_BIT, LCC_SPARE_I2S_MIC_NS_REG,
+ LCC_SPARE_I2S_MIC_STATUS_REG, DELAY, 0, TEST_LPA(0x11)),
+
+ CLK_AIF_OSR(CODEC_I2S_SPKR_OSR, LCC_CODEC_I2S_SPKR_NS_REG,
+ LCC_CODEC_I2S_SPKR_STATUS_REG, ENABLE, 1, TEST_LPA(0x0E)),
+ CLK_AIF_BIT(CODEC_I2S_SPKR_BIT, LCC_CODEC_I2S_SPKR_NS_REG,
+ LCC_CODEC_I2S_SPKR_STATUS_REG, DELAY, 0, TEST_LPA(0x0F)),
+
+ CLK_AIF_OSR(SPARE_I2S_SPKR_OSR, LCC_SPARE_I2S_SPKR_NS_REG,
+ LCC_SPARE_I2S_SPKR_STATUS_REG, ENABLE, 1, TEST_LPA(0x12)),
+ CLK_AIF_BIT(SPARE_I2S_SPKR_BIT, LCC_SPARE_I2S_SPKR_NS_REG,
+ LCC_SPARE_I2S_SPKR_STATUS_REG, DELAY, 0, TEST_LPA(0x13)),
+
+ CLK_PCM(PCM, LCC_PCM_NS_REG, LCC_PCM_STATUS_REG, ENABLE, 0,
+ TEST_LPA(0x14)),
+};
+
+/*
+ * SoC-specific functions required by clock-local driver
+ */
+
+/* Enable/disable for voteable XOs. */
+static int xo_enable(unsigned src, unsigned enable)
+{
+ /* TODO: xo voting support */
+ return 0;
+}
+
+/* Enable/disable for hardware-voteable PLLs. */
+static int voteable_pll_enable(unsigned src, unsigned enable)
+{
+ /* PLL enable/disable voting registers and masks. */
+ static const struct {
+ uint32_t *const enable_reg;
+ const uint32_t enable_mask;
+ uint32_t *const status_reg;
+ } pll_reg[] = {
+ [PLL_0] = { BB_PLL_ENA_SC0_REG, B(0), BB_PLL0_STATUS_REG },
+ [PLL_6] = { BB_PLL_ENA_SC0_REG, B(6), BB_PLL6_STATUS_REG },
+ [PLL_8] = { BB_PLL_ENA_SC0_REG, B(8), BB_PLL8_STATUS_REG },
+ };
+ int reg_val;
+
+ reg_val = readl(pll_reg[src].enable_reg);
+ if (enable) {
+ reg_val |= pll_reg[src].enable_mask;
+ writel(reg_val, pll_reg[src].enable_reg);
+
+ /* Wait until PLL is enabled. */
+ while (!(readl(pll_reg[src].status_reg) & B(16)))
+ cpu_relax();
+ } else {
+ reg_val &= ~(pll_reg[src].enable_mask);
+ writel(reg_val, pll_reg[src].enable_reg);
+ }
+
+ return 0;
+}
+
+/* Enable/disable for non-shared NT PLLs. */
+static int nt_pll_enable(unsigned src, unsigned enable)
+{
+ static const struct {
+ uint32_t *const mode_reg;
+ uint32_t *const status_reg;
+ } pll_reg[] = {
+ [PLL_1] = { MM_PLL0_MODE_REG, MM_PLL0_STATUS_REG },
+ [PLL_2] = { MM_PLL1_MODE_REG, MM_PLL1_STATUS_REG },
+ [PLL_3] = { MM_PLL2_MODE_REG, MM_PLL2_STATUS_REG },
+ };
+ uint32_t pll_mode;
+
+ pll_mode = readl(pll_reg[src].mode_reg);
+ if (enable) {
+ /* Disable PLL bypass mode. */
+ pll_mode |= B(1);
+ writel(pll_mode, pll_reg[src].mode_reg);
+
+ /* 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. */
+ pll_mode |= B(2);
+ writel(pll_mode, pll_reg[src].mode_reg);
+
+ /* Enable PLL output. */
+ pll_mode |= B(0);
+ writel(pll_mode, pll_reg[src].mode_reg);
+
+ /* Wait until PLL is enabled. */
+ while (!readl(pll_reg[src].status_reg))
+ cpu_relax();
+ } else {
+ /* Disable the PLL output, disable test mode, enable
+ * the bypass mode, and assert the reset. */
+ pll_mode &= ~BM(3, 0);
+ writel(pll_mode, pll_reg[src].mode_reg);
+ }
+
+ return 0;
+}
+
+/* Enable/disable for RPM-controlled voteable PLL4. */
+static int pll4_enable(unsigned src, unsigned enable)
+{
+ /* TODO: Vote for PLL4 via RPM */
+ return 0;
+}
+
+#define CLK_SRC(_src, _func, _par) \
+ [(_src)] = { .enable_func = (_func), .par = (_par), }
+struct clk_source soc_clk_sources[NUM_SRC] = {
+ CLK_SRC(CXO, NULL, SRC_NONE),
+ CLK_SRC(MXO, NULL, SRC_NONE),
+ CLK_SRC(PXO, xo_enable, SRC_NONE),
+ CLK_SRC(PLL_0, voteable_pll_enable, PXO),
+ CLK_SRC(PLL_1, nt_pll_enable, PXO),
+ CLK_SRC(PLL_2, nt_pll_enable, PXO),
+ CLK_SRC(PLL_3, nt_pll_enable, PXO),
+ CLK_SRC(PLL_4, pll4_enable, PXO),
+ CLK_SRC(PLL_5, NULL, CXO),
+ CLK_SRC(PLL_6, voteable_pll_enable, CXO),
+ CLK_SRC(PLL_7, nt_pll_enable, PXO),
+ CLK_SRC(PLL_8, voteable_pll_enable, PXO),
+};
+
+/* Update the sys_vdd voltage given a level. */
+int soc_update_sys_vdd(enum sys_vdd_level level)
+{
+ /* TODO: set voltage via pmic driver */
+ return 0;
+}
+
+/* Enable/disable a power rail associated with a clock. */
+int soc_set_pwr_rail(unsigned id, int enable)
+{
+ /* TODO */
+ return 0;
+}
+
+/* Implementation for clk_set_flags(). */
+int soc_clk_set_flags(unsigned id, unsigned flags)
+{
+ return -EPERM;
+}
+
+/* Implementation for clk_reset(). */
+int soc_clk_reset(unsigned id, enum clk_reset_action action)
+{
+ struct clk_local *clk = &soc_clk_local_tbl[id];
+ uint32_t reg_val, ret = 0;
+ unsigned long flags;
+
+ if (clk->reset_reg == NULL)
+ return -EPERM;
+
+ spin_lock_irqsave(&local_clock_reg_lock, flags);
+
+ reg_val = readl(clk->reset_reg);
+ switch (action) {
+ case CLK_RESET_ASSERT:
+ reg_val |= clk->reset_mask;
+ break;
+ case CLK_RESET_DEASSERT:
+ reg_val &= ~(clk->reset_mask);
+ break;
+ default:
+ ret = -EINVAL;
+ }
+ writel(reg_val, clk->reset_reg);
+
+ spin_unlock_irqrestore(&local_clock_reg_lock, flags);
+
+ return ret;
+}
+
+/*
+ * Miscellaneous clock register initializations
+ */
+
+/* Read, modify, then write-back a register. */
+static void rmwreg(uint32_t val, void *reg, uint32_t mask)
+{
+ uint32_t regval = readl(reg);
+ regval &= ~mask;
+ regval |= val;
+ writel(regval, reg);
+}
+
+static void reg_init(void)
+{
+ /* Set MM_PLL1 (PLL2) @ 800 MHz but leave it off. */
+ rmwreg(0, MM_PLL1_MODE_REG, B(0)); /* Disable output */
+ writel(29, MM_PLL1_L_VAL_REG);
+ writel(17, MM_PLL1_M_VAL_REG);
+ writel(27, MM_PLL1_N_VAL_REG);
+ /* Set ref, bypass, assert reset, disable output, disable test mode. */
+ writel(0, MM_PLL1_MODE_REG); /* PXO */
+ writel(0x00C22080, MM_PLL1_CONFIG_REG); /* Enable MN, set VCO, misc */
+
+ /* Setup MM_PLL2 (PLL3), but turn it off. Rate set by set_rate_tv(). */
+ rmwreg(0, MM_PLL2_MODE_REG, B(0)); /* Disable output */
+ /* Set ref, bypass, assert reset, disable output, disable test mode */
+ writel(0, MM_PLL2_MODE_REG); /* PXO */
+ writel(0x00800000, MM_PLL2_CONFIG_REG); /* Enable main out. */
+
+ /* Deassert MM SW_RESET_ALL signal. */
+ writel(0, SW_RESET_ALL_REG);
+
+ /* Initialize MM AHB registers: Enable the FPB clock and disable HW
+ * gating for all clocks. Also set VFE_AHB's FORCE_CORE_ON bit to
+ * prevent its memory from being collapsed when the clock is halted.
+ * The sleep and wake-up delays are set to safe values. */
+ rmwreg(0x00000003, AHB_EN_REG, 0x0F7FFFFF);
+ rmwreg(0x000007F9, AHB_EN2_REG, 0x7FFFBFFF);
+
+ /* Deassert all locally-owned MM AHB resets. */
+ rmwreg(0, SW_RESET_AHB_REG, 0xFFF7DFFF);
+
+ /* Initialize MM AXI registers: Enable HW gating for all clocks that
+ * support it. Also set FORCE_CORE_ON bits, and any sleep and wake-up
+ * delays to safe values. */
+ rmwreg(0x00038FF9, MAXI_EN_REG, 0x0FFFFFFF);
+ rmwreg(0x1A27FCFF, MAXI_EN2_REG, 0x1FFFFFFF);
+ writel(0x3FE7FCFF, MAXI_EN3_REG);
+ writel(0x000001D8, SAXI_EN_REG);
+
+ /* Initialize MM CC registers: Set MM FORCE_CORE_ON bits so that core
+ * memories retain state even when not clocked. Also, set sleep and
+ * wake-up delays to safe values. */
+ writel(0x00000000, CSI_CC_REG);
+ rmwreg(0x00000000, MISC_CC_REG, 0xFEFFF3FF);
+ rmwreg(0x000007FD, MISC_CC2_REG, 0xFFFF7FFF);
+ writel(0x80FF0000, GFX2D0_CC_REG);
+ writel(0x80FF0000, GFX2D1_CC_REG);
+ writel(0x80FF0000, GFX3D_CC_REG);
+ writel(0x80FF0000, IJPEG_CC_REG);
+ writel(0x80FF0000, JPEGD_CC_REG);
+ /* MDP and PIXEL clocks may be running at boot, don't turn them off. */
+ rmwreg(0x80FF0000, MDP_CC_REG, BM(31, 29) | BM(23, 16));
+ rmwreg(0x80FF0000, PIXEL_CC_REG, BM(31, 29) | BM(23, 16));
+ writel(0x000004FF, PIXEL_CC2_REG);
+ writel(0x80FF0000, ROT_CC_REG);
+ writel(0x80FF0000, TV_CC_REG);
+ writel(0x000004FF, TV_CC2_REG);
+ writel(0x80FF0000, VCODEC_CC_REG);
+ writel(0x80FF0000, VFE_CC_REG);
+ writel(0x80FF0000, VPE_CC_REG);
+
+ /* De-assert MM AXI resets to all hardware blocks. */
+ writel(0, SW_RESET_AXI_REG);
+
+ /* Deassert all MM core resets. */
+ writel(0, SW_RESET_CORE_REG);
+
+ /* Reset 3D core once more, with its clock enabled. This can
+ * eventually be done as part of the GDFS footswitch driver. */
+ local_clk_set_rate(C(GFX3D), 27000000);
+ local_clk_enable(C(GFX3D));
+ writel(B(12), SW_RESET_CORE_REG);
+ udelay(5);
+ writel(0, SW_RESET_CORE_REG);
+ local_clk_disable(C(GFX3D));
+
+ /* Enable TSSC and PDM PXO sources. */
+ writel(B(11), TSSC_CLK_CTL_REG);
+ writel(B(15), PDM_CLK_NS_REG);
+ /* Set the dsi_byte_clk src to the DSI PHY PLL,
+ * dsi_esc_clk to PXO/2, and the hdmi_app_clk src to PXO */
+ rmwreg(0x400001, MISC_CC2_REG, 0x424003);
+
+ /*
+ * Turn on clocks required by the SMMU driver until it properly
+ * controls its own clocks.
+ */
+ local_clk_enable(C(SMMU_P));
+ local_clk_enable(C(JPEGD_AXI));
+ local_clk_enable(C(VFE_AXI));
+ local_clk_enable(C(VCODEC_AXI));
+}
+
+/* Local clock driver initialization. */
+void __init msm_clk_soc_init(void)
+{
+ local_vote_sys_vdd(HIGH);
+ /* Initialize clock registers. */
+ reg_init();
+
+ /* Initialize rates for clocks that only support one. */
+ set_1rate(MDP_VSYNC);
+ set_1rate(TSIF_REF);
+ set_1rate(TSSC);
+ set_1rate(USB_HS1_XCVR);
+ set_1rate(USB_FS1_SRC);
+ set_1rate(USB_FS2_SRC);
+}
+
+static int msm_clk_soc_late_init(void)
+{
+ return local_unvote_sys_vdd(HIGH);
+}
+late_initcall(msm_clk_soc_late_init);
+
+/*
+ * Clock operation handler registration
+ */
+struct clk_ops soc_clk_ops_8x60 = {
+ .enable = local_clk_enable,
+ .disable = local_clk_disable,
+ .auto_off = local_clk_auto_off,
+ .set_rate = local_clk_set_rate,
+ .set_min_rate = local_clk_set_min_rate,
+ .set_max_rate = local_clk_set_max_rate,
+ .get_rate = local_clk_get_rate,
+ .is_enabled = local_clk_is_enabled,
+ .round_rate = local_clk_round_rate,
+ .reset = soc_clk_reset,
+ .set_flags = soc_clk_set_flags,
+};
diff --git a/arch/arm/mach-msm/clock-8x60.h b/arch/arm/mach-msm/clock-8x60.h
new file mode 100644
index 0000000..2019add
--- /dev/null
+++ b/arch/arm/mach-msm/clock-8x60.h
@@ -0,0 +1,216 @@
+/*
+ * Copyright (c) 2009-2010, Code Aurora Forum. 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 __ARCH_ARM_MACH_MSM_CLOCK_8X60_H
+#define __ARCH_ARM_MACH_MSM_CLOCK_8X60_H
+
+enum {
+ /* Peripheral Clocks */
+ L_CE2_CLK,
+ L_GSBI1_UART_CLK,
+ L_GSBI2_UART_CLK,
+ L_GSBI3_UART_CLK,
+ L_GSBI4_UART_CLK,
+ L_GSBI5_UART_CLK,
+ L_GSBI6_UART_CLK,
+ L_GSBI7_UART_CLK,
+ L_GSBI8_UART_CLK,
+ L_GSBI9_UART_CLK,
+ L_GSBI10_UART_CLK,
+ L_GSBI11_UART_CLK,
+ L_GSBI12_UART_CLK,
+ L_GSBI1_QUP_CLK,
+ L_GSBI2_QUP_CLK,
+ L_GSBI3_QUP_CLK,
+ L_GSBI4_QUP_CLK,
+ L_GSBI5_QUP_CLK,
+ L_GSBI6_QUP_CLK,
+ L_GSBI7_QUP_CLK,
+ L_GSBI8_QUP_CLK,
+ L_GSBI9_QUP_CLK,
+ L_GSBI10_QUP_CLK,
+ L_GSBI11_QUP_CLK,
+ L_GSBI12_QUP_CLK,
+ L_PDM_CLK,
+ L_PMEM_CLK,
+ L_PRNG_CLK,
+ L_SDC1_CLK,
+ L_SDC2_CLK,
+ L_SDC3_CLK,
+ L_SDC4_CLK,
+ L_SDC5_CLK,
+ L_TSIF_REF_CLK,
+ L_TSSC_CLK,
+ L_USB_HS1_XCVR_CLK,
+ L_USB_PHY0_CLK,
+ L_USB_FS1_SRC_CLK,
+ L_USB_FS1_XCVR_CLK,
+ L_USB_FS1_SYS_CLK,
+ L_USB_FS2_SRC_CLK,
+ L_USB_FS2_XCVR_CLK,
+ L_USB_FS2_SYS_CLK,
+
+ /* HW-Voteable Clocks */
+ L_ADM0_CLK,
+ L_ADM0_P_CLK,
+ L_ADM1_CLK,
+ L_ADM1_P_CLK,
+ L_MODEM_AHB1_P_CLK,
+ L_MODEM_AHB2_P_CLK,
+ L_PMIC_ARB0_P_CLK,
+ L_PMIC_ARB1_P_CLK,
+ L_PMIC_SSBI2_CLK,
+ L_RPM_MSG_RAM_P_CLK,
+
+ /* Fast Peripheral Bus Clocks */
+ L_GSBI1_P_CLK,
+ L_GSBI2_P_CLK,
+ L_GSBI3_P_CLK,
+ L_GSBI4_P_CLK,
+ L_GSBI5_P_CLK,
+ L_GSBI6_P_CLK,
+ L_GSBI7_P_CLK,
+ L_GSBI8_P_CLK,
+ L_GSBI9_P_CLK,
+ L_GSBI10_P_CLK,
+ L_GSBI11_P_CLK,
+ L_GSBI12_P_CLK,
+ L_PPSS_P_CLK,
+ L_TSIF_P_CLK,
+ L_USB_FS1_P_CLK,
+ L_USB_FS2_P_CLK,
+ L_USB_HS1_P_CLK,
+ L_SDC1_P_CLK,
+ L_SDC2_P_CLK,
+ L_SDC3_P_CLK,
+ L_SDC4_P_CLK,
+ L_SDC5_P_CLK,
+
+ /* Multimedia Clocks */
+ L_AMP_CLK,
+ L_CAM_CLK,
+ L_CSI_SRC_CLK,
+ L_CSI0_CLK,
+ L_CSI1_CLK,
+ L_DSI_BYTE_CLK,
+ L_DSI_ESC_CLK,
+ L_GFX2D0_CLK,
+ L_GFX2D1_CLK,
+ L_GFX3D_CLK,
+ L_IJPEG_CLK,
+ L_IMEM_CLK,
+ L_JPEGD_CLK,
+ L_MDP_CLK,
+ L_MDP_VSYNC_CLK,
+ L_PIXEL_SRC_CLK,
+ L_PIXEL_MDP_CLK,
+ L_PIXEL_LCDC_CLK,
+ L_ROT_CLK,
+ L_TV_SRC_CLK,
+ L_TV_ENC_CLK,
+ L_TV_DAC_CLK,
+ L_VCODEC_CLK,
+ L_MDP_TV_CLK,
+ L_HDMI_TV_CLK,
+ L_HDMI_APP_CLK,
+ L_VPE_CLK,
+ L_VFE_CLK,
+ L_CSI0_VFE_CLK,
+ L_CSI1_VFE_CLK,
+ L_GMEM_AXI_CLK,
+ L_JPEGD_AXI_CLK,
+ L_VCODEC_AXI_CLK,
+ L_VFE_AXI_CLK,
+ L_IJPEG_AXI_CLK,
+ L_MDP_AXI_CLK,
+ L_ROT_AXI_CLK,
+ L_VPE_AXI_CLK,
+
+ /* Multimedia Fast Peripheral Bus Clocks */
+ L_AMP_P_CLK,
+ L_CSI0_P_CLK,
+ L_CSI1_P_CLK,
+ L_DSI_M_P_CLK,
+ L_DSI_S_P_CLK,
+ L_GFX2D0_P_CLK,
+ L_GFX2D1_P_CLK,
+ L_GFX3D_P_CLK,
+ L_HDMI_M_P_CLK,
+ L_HDMI_S_P_CLK,
+ L_IJPEG_P_CLK,
+ L_IMEM_P_CLK,
+ L_JPEGD_P_CLK,
+ L_MDP_P_CLK,
+ L_ROT_P_CLK,
+ L_SMMU_P_CLK,
+ L_TV_ENC_P_CLK,
+ L_VCODEC_P_CLK,
+ L_VFE_P_CLK,
+ L_VPE_P_CLK,
+
+ /* LPA Clocks */
+ L_MI2S_SRC_CLK,
+ L_MI2S_OSR_CLK,
+ L_MI2S_BIT_CLK,
+ L_CODEC_I2S_MIC_OSR_CLK,
+ L_CODEC_I2S_MIC_BIT_CLK,
+ L_SPARE_I2S_MIC_OSR_CLK,
+ L_SPARE_I2S_MIC_BIT_CLK,
+ L_CODEC_I2S_SPKR_OSR_CLK,
+ L_CODEC_I2S_SPKR_BIT_CLK,
+ L_SPARE_I2S_SPKR_OSR_CLK,
+ L_SPARE_I2S_SPKR_BIT_CLK,
+ L_PCM_CLK,
+
+ L_NR_CLKS
+};
+
+enum clk_sources {
+ PLL_0 = 0,
+ PLL_1,
+ PLL_2,
+ PLL_3,
+ PLL_4,
+ PLL_5,
+ PLL_6,
+ PLL_7,
+ PLL_8,
+ MXO,
+ PXO,
+ CXO,
+ NUM_SRC
+};
+
+struct pll_rate {
+ const uint32_t l_val;
+ const uint32_t m_val;
+ const uint32_t n_val;
+ const uint32_t vco;
+ const uint32_t post_div;
+ const uint32_t i_bits;
+};
+#define PLL_RATE(l, m, n, v, d, i) { l, m, n, v, (d>>1), i }
+
+extern struct clk_ops soc_clk_ops_8x60;
+#define CLK_8X60(clk_name, clk_id, clk_dev, clk_flags) { \
+ .name = clk_name, \
+ .id = L_##clk_id, \
+ .remote_id = L_##clk_id, \
+ .ops = &soc_clk_ops_8x60, \
+ .flags = clk_flags, \
+ .dev = clk_dev, \
+ .dbg_name = #clk_id, \
+ }
+
+#endif
+
diff --git a/arch/arm/mach-msm/clock-local.h b/arch/arm/mach-msm/clock-local.h
index ebefad5..c168985 100644
--- a/arch/arm/mach-msm/clock-local.h
+++ b/arch/arm/mach-msm/clock-local.h
@@ -97,7 +97,6 @@ struct banked_mnd_masks {
}
#define FREQ_END (UINT_MAX-1)
#define F_END F_RAW(FREQ_END, SRC_NONE, 0, 0, 0, 0, LOW, NULL)
-#define PLL_RATE(l, m, n, v, d) { l, m, n, v, (d>>1) }
/*
* Generic clock-definition struct and macros
diff --git a/arch/arm/mach-msm/clock.h b/arch/arm/mach-msm/clock.h
index 4841ab6..44a6dd6 100644
--- a/arch/arm/mach-msm/clock.h
+++ b/arch/arm/mach-msm/clock.h
@@ -68,7 +68,7 @@ void __init msm_clk_soc_set_ops(struct clk *clk);
static inline void __init msm_clk_soc_set_ops(struct clk *clk) { }
#endif
-#if defined(CONFIG_ARCH_MSM7X30)
+#if defined(CONFIG_ARCH_MSM7X30) || defined(CONFIG_ARCH_MSM8X60)
void __init msm_clk_soc_init(void);
#else
static inline void __init msm_clk_soc_init(void) { }
diff --git a/arch/arm/mach-msm/include/mach/msm_iomap-8x60.h b/arch/arm/mach-msm/include/mach/msm_iomap-8x60.h
index 7c43a9b..c940596 100644
--- a/arch/arm/mach-msm/include/mach/msm_iomap-8x60.h
+++ b/arch/arm/mach-msm/include/mach/msm_iomap-8x60.h
@@ -55,6 +55,18 @@
#define MSM_TLMM_PHYS 0x00800000
#define MSM_TLMM_SIZE SZ_16K
+#define MSM_CLK_CTL_BASE IOMEM(0xFA010000)
+#define MSM_CLK_CTL_PHYS 0x00900000
+#define MSM_CLK_CTL_SIZE SZ_16K
+
+#define MSM_MMSS_CLK_CTL_BASE IOMEM(0xFA014000)
+#define MSM_MMSS_CLK_CTL_PHYS 0x04000000
+#define MSM_MMSS_CLK_CTL_SIZE SZ_4K
+
+#define MSM_LPASS_CLK_CTL_BASE IOMEM(0xFA015000)
+#define MSM_LPASS_CLK_CTL_PHYS 0x28000000
+#define MSM_LPASS_CLK_CTL_SIZE SZ_4K
+
#define MSM_SHARED_RAM_BASE IOMEM(0xF0100000)
#define MSM_SHARED_RAM_SIZE SZ_1M
diff --git a/arch/arm/mach-msm/io.c b/arch/arm/mach-msm/io.c
index f912d7b..d60076a 100644
--- a/arch/arm/mach-msm/io.c
+++ b/arch/arm/mach-msm/io.c
@@ -107,6 +107,9 @@ static struct map_desc msm8x60_io_desc[] __initdata = {
MSM_DEVICE(TMR),
MSM_DEVICE(ACC),
MSM_DEVICE(GCC),
+ MSM_DEVICE(CLK_CTL),
+ MSM_DEVICE(MMSS_CLK_CTL),
+ MSM_DEVICE(LPASS_CLK_CTL),
};
void __init msm_map_msm8x60_io(void)
--
Sent by an employee of the Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum.
^ permalink raw reply related [flat|nested] 23+ messages in thread* [PATCH 09/22] msm: clock: Remove references to clk_ops_pcom
2010-12-17 0:49 [PATCH 00/22] MSM clock driver updates Stephen Boyd
` (7 preceding siblings ...)
2010-12-17 0:49 ` [PATCH 08/22] msm: clock-8x60: Add msm8x60 local clock driver Stephen Boyd
@ 2010-12-17 0:49 ` Stephen Boyd
2010-12-17 0:49 ` [PATCH 10/22] msm: Move 8x60 to the real clock driver Stephen Boyd
` (12 subsequent siblings)
21 siblings, 0 replies; 23+ messages in thread
From: Stephen Boyd @ 2010-12-17 0:49 UTC (permalink / raw)
To: linux-arm-kernel
Not all devices use proc_comm. The soc_clk_set_ops() function was
unused. Determining if a clock is local vs. remote is fragile
when done by comparing clk_ops pointers. Instead, implement an
is_local() function for all clk_ops to determine if the clock is
local. Once we do this we can compile clock.c with
CONFIG_MSM_PROC_COMM=n.
Reviewed-by: Saravana Kannan <skannan@codeaurora.org>
Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
---
arch/arm/mach-msm/clock-7x30.c | 1 +
arch/arm/mach-msm/clock-8x60.c | 1 +
arch/arm/mach-msm/clock-debug.c | 3 +--
arch/arm/mach-msm/clock-local.c | 5 +++++
arch/arm/mach-msm/clock-local.h | 1 +
arch/arm/mach-msm/clock-pcom.c | 6 ++++++
arch/arm/mach-msm/clock.c | 5 -----
arch/arm/mach-msm/clock.h | 1 +
8 files changed, 16 insertions(+), 7 deletions(-)
diff --git a/arch/arm/mach-msm/clock-7x30.c b/arch/arm/mach-msm/clock-7x30.c
index 0637bee..994104f 100644
--- a/arch/arm/mach-msm/clock-7x30.c
+++ b/arch/arm/mach-msm/clock-7x30.c
@@ -1071,4 +1071,5 @@ struct clk_ops soc_clk_ops_7x30 = {
.round_rate = local_clk_round_rate,
.reset = pc_clk_reset,
.set_flags = soc_clk_set_flags,
+ .is_local = local_clk_is_local,
};
diff --git a/arch/arm/mach-msm/clock-8x60.c b/arch/arm/mach-msm/clock-8x60.c
index 5bbc8bb..e1f3c6f 100644
--- a/arch/arm/mach-msm/clock-8x60.c
+++ b/arch/arm/mach-msm/clock-8x60.c
@@ -1799,4 +1799,5 @@ struct clk_ops soc_clk_ops_8x60 = {
.round_rate = local_clk_round_rate,
.reset = soc_clk_reset,
.set_flags = soc_clk_set_flags,
+ .is_local = local_clk_is_local,
};
diff --git a/arch/arm/mach-msm/clock-debug.c b/arch/arm/mach-msm/clock-debug.c
index b67b9e82..4886404 100644
--- a/arch/arm/mach-msm/clock-debug.c
+++ b/arch/arm/mach-msm/clock-debug.c
@@ -19,7 +19,6 @@
#include <linux/debugfs.h>
#include <linux/clk.h>
#include "clock.h"
-#include "clock-pcom.h"
static int clock_debug_rate_set(void *data, u64 val)
{
@@ -79,7 +78,7 @@ static int clock_debug_local_get(void *data, u64 *val)
{
struct clk *clock = data;
- *val = clock->ops != &clk_ops_pcom;
+ *val = clock->ops->is_local(clock->id);
return 0;
}
diff --git a/arch/arm/mach-msm/clock-local.c b/arch/arm/mach-msm/clock-local.c
index d6eb6c6..44e0778 100644
--- a/arch/arm/mach-msm/clock-local.c
+++ b/arch/arm/mach-msm/clock-local.c
@@ -677,3 +677,8 @@ long local_clk_round_rate(unsigned id, unsigned rate)
return -EPERM;
}
+
+bool local_clk_is_local(unsigned id)
+{
+ return true;
+}
diff --git a/arch/arm/mach-msm/clock-local.h b/arch/arm/mach-msm/clock-local.h
index c168985..3083369 100644
--- a/arch/arm/mach-msm/clock-local.h
+++ b/arch/arm/mach-msm/clock-local.h
@@ -211,6 +211,7 @@ int local_clk_set_max_rate(unsigned id, unsigned rate);
unsigned local_clk_get_rate(unsigned id);
unsigned local_clk_is_enabled(unsigned id);
long local_clk_round_rate(unsigned id, unsigned rate);
+bool local_clk_is_local(unsigned id);
/*
* Required SoC-specific functions, implemented for every supported SoC
diff --git a/arch/arm/mach-msm/clock-pcom.c b/arch/arm/mach-msm/clock-pcom.c
index 8c4e867..63b7113 100644
--- a/arch/arm/mach-msm/clock-pcom.c
+++ b/arch/arm/mach-msm/clock-pcom.c
@@ -117,6 +117,11 @@ long pc_clk_round_rate(unsigned id, unsigned rate)
return rate;
}
+static bool pc_clk_is_local(unsigned id)
+{
+ return false;
+}
+
struct clk_ops clk_ops_pcom = {
.enable = pc_clk_enable,
.disable = pc_clk_disable,
@@ -129,4 +134,5 @@ struct clk_ops clk_ops_pcom = {
.get_rate = pc_clk_get_rate,
.is_enabled = pc_clk_is_enabled,
.round_rate = pc_clk_round_rate,
+ .is_local = pc_clk_is_local,
};
diff --git a/arch/arm/mach-msm/clock.c b/arch/arm/mach-msm/clock.c
index 56c7549..06cd313 100644
--- a/arch/arm/mach-msm/clock.c
+++ b/arch/arm/mach-msm/clock.c
@@ -21,9 +21,6 @@
#include <linux/pm_qos_params.h>
#include "clock.h"
-#include "proc_comm.h"
-#include "clock-7x30.h"
-#include "clock-pcom.h"
static DEFINE_MUTEX(clocks_mutex);
static DEFINE_SPINLOCK(clocks_lock);
@@ -84,8 +81,6 @@ EXPORT_SYMBOL(clk_disable);
int clk_reset(struct clk *clk, enum clk_reset_action action)
{
- if (!clk->ops->reset)
- clk->ops->reset = &pc_clk_reset;
return clk->ops->reset(clk->remote_id, action);
}
EXPORT_SYMBOL(clk_reset);
diff --git a/arch/arm/mach-msm/clock.h b/arch/arm/mach-msm/clock.h
index 44a6dd6..b74ba3e 100644
--- a/arch/arm/mach-msm/clock.h
+++ b/arch/arm/mach-msm/clock.h
@@ -43,6 +43,7 @@ struct clk_ops {
unsigned (*get_rate)(unsigned id);
unsigned (*is_enabled)(unsigned id);
long (*round_rate)(unsigned id, unsigned rate);
+ bool (*is_local)(unsigned id);
};
struct clk {
--
Sent by an employee of the Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum.
^ permalink raw reply related [flat|nested] 23+ messages in thread* [PATCH 10/22] msm: Move 8x60 to the real clock driver
2010-12-17 0:49 [PATCH 00/22] MSM clock driver updates Stephen Boyd
` (8 preceding siblings ...)
2010-12-17 0:49 ` [PATCH 09/22] msm: clock: Remove references to clk_ops_pcom Stephen Boyd
@ 2010-12-17 0:49 ` Stephen Boyd
2010-12-17 0:49 ` [PATCH 11/22] msm: clock Add debugfs interface to measure clock rates Stephen Boyd
` (11 subsequent siblings)
21 siblings, 0 replies; 23+ messages in thread
From: Stephen Boyd @ 2010-12-17 0:49 UTC (permalink / raw)
To: linux-arm-kernel
The dummy clock driver was added to make 8x60 compile due to
proc_comm references in clock.c. Now that those references are
gone we can compile the original clock.c with no errors and
support clocks on 8x60.
Reviewed-by: Saravana Kannan <skannan@codeaurora.org>
Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
---
arch/arm/mach-msm/Makefile | 7 +-
arch/arm/mach-msm/board-msm8x60.c | 3 +
arch/arm/mach-msm/devices-msm8x60.c | 180 +++++++++++++++++++++++++++++++++++
arch/arm/mach-msm/devices.h | 3 +
4 files changed, 189 insertions(+), 4 deletions(-)
create mode 100644 arch/arm/mach-msm/devices-msm8x60.c
diff --git a/arch/arm/mach-msm/Makefile b/arch/arm/mach-msm/Makefile
index fa01510..fb44992 100644
--- a/arch/arm/mach-msm/Makefile
+++ b/arch/arm/mach-msm/Makefile
@@ -1,7 +1,6 @@
obj-y += io.o idle.o timer.o
-ifdef CONFIG_MSM_PROC_COMM
+obj-y += clock.o
obj-$(CONFIG_DEBUG_FS) += clock-debug.o
-endif
obj-$(CONFIG_ARCH_MSM7X30) += clock-local.o
obj-$(CONFIG_ARCH_MSM8X60) += clock-local.o
obj-$(CONFIG_ARCH_MSM7X30) += clock-7x30.o
@@ -19,9 +18,9 @@ obj-y += irq.o
endif
endif
-obj-$(CONFIG_ARCH_MSM8X60) += clock-dummy.o iommu.o iommu_dev.o devices-msm8x60-iommu.o
+obj-$(CONFIG_ARCH_MSM8X60) += iommu.o iommu_dev.o devices-msm8x60-iommu.o
+obj-$(CONFIG_ARCH_MSM8X60) += devices-msm8x60.o
obj-$(CONFIG_MSM_PROC_COMM) += proc_comm.o clock-pcom.o vreg.o
-obj-$(CONFIG_MSM_PROC_COMM) += clock.o
obj-$(CONFIG_ARCH_QSD8X50) += sirc.o
obj-$(CONFIG_MSM_SMD) += smd.o smd_debug.o
obj-$(CONFIG_MSM_SMD) += last_radio_log.o
diff --git a/arch/arm/mach-msm/board-msm8x60.c b/arch/arm/mach-msm/board-msm8x60.c
index 852428b..a584d38 100644
--- a/arch/arm/mach-msm/board-msm8x60.c
+++ b/arch/arm/mach-msm/board-msm8x60.c
@@ -28,6 +28,8 @@
#include <mach/board.h>
#include <mach/msm_iomap.h>
+#include "devices.h"
+
void __iomem *gic_cpu_base_addr;
static void __init msm8x60_map_io(void)
@@ -64,6 +66,7 @@ static void __init msm8x60_init_irq(void)
static void __init msm8x60_init(void)
{
+ msm_clock_init(msm_clocks_8x60, msm_num_clocks_8x60);
}
MACHINE_START(MSM8X60_RUMI3, "QCT MSM8X60 RUMI3")
diff --git a/arch/arm/mach-msm/devices-msm8x60.c b/arch/arm/mach-msm/devices-msm8x60.c
new file mode 100644
index 0000000..1f2b189
--- /dev/null
+++ b/arch/arm/mach-msm/devices-msm8x60.c
@@ -0,0 +1,180 @@
+/* Copyright (c) 2010, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/clk.h>
+
+#include "clock.h"
+#include "clock-8x60.h"
+
+struct clk msm_clocks_8x60[] = {
+ CLK_8X60("ce_clk", CE2_CLK, NULL, OFF),
+ CLK_8X60("gsbi_uart_clk", GSBI1_UART_CLK, NULL, OFF),
+ CLK_8X60("gsbi_uart_clk", GSBI2_UART_CLK, NULL, OFF),
+ CLK_8X60("gsbi_uart_clk", GSBI3_UART_CLK, NULL, OFF),
+ CLK_8X60("gsbi_uart_clk", GSBI4_UART_CLK, NULL, OFF),
+ CLK_8X60("gsbi_uart_clk", GSBI5_UART_CLK, NULL, OFF),
+ CLK_8X60("uartdm_clk", GSBI6_UART_CLK, NULL, OFF),
+ CLK_8X60("gsbi_uart_clk", GSBI7_UART_CLK, NULL, OFF),
+ CLK_8X60("gsbi_uart_clk", GSBI8_UART_CLK, NULL, OFF),
+ CLK_8X60("gsbi_uart_clk", GSBI9_UART_CLK, NULL, OFF),
+ CLK_8X60("gsbi_uart_clk", GSBI10_UART_CLK, NULL, OFF),
+ CLK_8X60("gsbi_uart_clk", GSBI11_UART_CLK, NULL, OFF),
+ CLK_8X60("gsbi_uart_clk", GSBI12_UART_CLK, NULL, OFF),
+ CLK_8X60("gsbi_qup_clk", GSBI1_QUP_CLK, NULL, OFF),
+ CLK_8X60("gsbi_qup_clk", GSBI2_QUP_CLK, NULL, OFF),
+ CLK_8X60("gsbi_qup_clk", GSBI3_QUP_CLK, NULL, OFF),
+ CLK_8X60("gsbi_qup_clk", GSBI4_QUP_CLK, NULL, OFF),
+ CLK_8X60("gsbi_qup_clk", GSBI5_QUP_CLK, NULL, OFF),
+ CLK_8X60("gsbi_qup_clk", GSBI6_QUP_CLK, NULL, OFF),
+ CLK_8X60("gsbi_qup_clk", GSBI7_QUP_CLK, NULL, OFF),
+ CLK_8X60("gsbi_qup_clk", GSBI8_QUP_CLK, NULL, OFF),
+ CLK_8X60("gsbi_qup_clk", GSBI9_QUP_CLK, NULL, OFF),
+ CLK_8X60("gsbi_qup_clk", GSBI10_QUP_CLK, NULL, OFF),
+ CLK_8X60("gsbi_qup_clk", GSBI11_QUP_CLK, NULL, OFF),
+ CLK_8X60("gsbi_qup_clk", GSBI12_QUP_CLK, NULL, OFF),
+ CLK_8X60("pdm_clk", PDM_CLK, NULL, OFF),
+ CLK_8X60("pmem_clk", PMEM_CLK, NULL, OFF),
+ CLK_8X60("prng_clk", PRNG_CLK, NULL, OFF),
+ CLK_8X60("sdc_clk", SDC1_CLK, NULL, OFF),
+ CLK_8X60("sdc_clk", SDC2_CLK, NULL, OFF),
+ CLK_8X60("sdc_clk", SDC3_CLK, NULL, OFF),
+ CLK_8X60("sdc_clk", SDC4_CLK, NULL, OFF),
+ CLK_8X60("sdc_clk", SDC5_CLK, NULL, OFF),
+ CLK_8X60("tsif_ref_clk", TSIF_REF_CLK, NULL, OFF),
+ CLK_8X60("tssc_clk", TSSC_CLK, NULL, OFF),
+ CLK_8X60("usb_hs_clk", USB_HS1_XCVR_CLK, NULL, OFF),
+ CLK_8X60("usb_phy_clk", USB_PHY0_CLK, NULL, OFF),
+ CLK_8X60("usb_fs_src_clk", USB_FS1_SRC_CLK, NULL, OFF),
+ CLK_8X60("usb_fs_clk", USB_FS1_XCVR_CLK, NULL, OFF),
+ CLK_8X60("usb_fs_sys_clk", USB_FS1_SYS_CLK, NULL, OFF),
+ CLK_8X60("usb_fs_src_clk", USB_FS2_SRC_CLK, NULL, OFF),
+ CLK_8X60("usb_fs_clk", USB_FS2_XCVR_CLK, NULL, OFF),
+ CLK_8X60("usb_fs_sys_clk", USB_FS2_SYS_CLK, NULL, OFF),
+ CLK_8X60("gsbi_pclk", GSBI1_P_CLK, NULL, OFF),
+ CLK_8X60("gsbi_pclk", GSBI2_P_CLK, NULL, OFF),
+ CLK_8X60("gsbi_pclk", GSBI3_P_CLK, NULL, OFF),
+ CLK_8X60("gsbi_pclk", GSBI4_P_CLK, NULL, OFF),
+ CLK_8X60("gsbi_pclk", GSBI5_P_CLK, NULL, OFF),
+ CLK_8X60("uartdm_pclk", GSBI6_P_CLK, NULL, OFF),
+ CLK_8X60("gsbi_pclk", GSBI7_P_CLK, NULL, OFF),
+ CLK_8X60("gsbi_pclk", GSBI8_P_CLK, NULL, OFF),
+ CLK_8X60("gsbi_pclk", GSBI9_P_CLK, NULL, OFF),
+ CLK_8X60("gsbi_pclk", GSBI10_P_CLK, NULL, OFF),
+ CLK_8X60("gsbi_pclk", GSBI11_P_CLK, NULL, OFF),
+ CLK_8X60("gsbi_pclk", GSBI12_P_CLK, NULL, OFF),
+ CLK_8X60("gsbi_pclk", GSBI12_P_CLK, NULL, OFF),
+ CLK_8X60("ppss_pclk", PPSS_P_CLK, NULL, OFF),
+ CLK_8X60("tsif_pclk", TSIF_P_CLK, NULL, OFF),
+ CLK_8X60("usb_fs_pclk", USB_FS1_P_CLK, NULL, OFF),
+ CLK_8X60("usb_fs_pclk", USB_FS2_P_CLK, NULL, OFF),
+ CLK_8X60("usb_hs_pclk", USB_HS1_P_CLK, NULL, OFF),
+ CLK_8X60("sdc_pclk", SDC1_P_CLK, NULL, OFF),
+ CLK_8X60("sdc_pclk", SDC2_P_CLK, NULL, OFF),
+ CLK_8X60("sdc_pclk", SDC3_P_CLK, NULL, OFF),
+ CLK_8X60("sdc_pclk", SDC4_P_CLK, NULL, OFF),
+ CLK_8X60("sdc_pclk", SDC5_P_CLK, NULL, OFF),
+ CLK_8X60("adm_clk", ADM0_CLK, NULL, OFF),
+ CLK_8X60("adm_pclk", ADM0_P_CLK, NULL, OFF),
+ CLK_8X60("adm_clk", ADM1_CLK, NULL, OFF),
+ CLK_8X60("adm_pclk", ADM1_P_CLK, NULL, OFF),
+ CLK_8X60("modem_ahb1_pclk", MODEM_AHB1_P_CLK, NULL, OFF),
+ CLK_8X60("modem_ahb2_pclk", MODEM_AHB2_P_CLK, NULL, OFF),
+ CLK_8X60("pmic_arb_pclk", PMIC_ARB0_P_CLK, NULL, OFF),
+ CLK_8X60("pmic_arb_pclk", PMIC_ARB1_P_CLK, NULL, OFF),
+ CLK_8X60("pmic_ssbi2", PMIC_SSBI2_CLK, NULL, OFF),
+ CLK_8X60("rpm_msg_ram_pclk", RPM_MSG_RAM_P_CLK, NULL, OFF),
+ CLK_8X60("amp_clk", AMP_CLK, NULL, OFF),
+ CLK_8X60("cam_clk", CAM_CLK, NULL, OFF),
+ CLK_8X60("csi_src_clk", CSI_SRC_CLK, NULL, OFF),
+ CLK_8X60("csi_clk", CSI0_CLK, NULL, OFF),
+ CLK_8X60("csi_clk", CSI1_CLK, NULL, OFF),
+ CLK_8X60("dsi_byte_div_clk", DSI_BYTE_CLK, NULL, OFF),
+ CLK_8X60("dsi_esc_clk", DSI_ESC_CLK, NULL, OFF),
+ CLK_8X60("gfx2d0_clk", GFX2D0_CLK, NULL, OFF),
+ CLK_8X60("gfx2d1_clk", GFX2D1_CLK, NULL, OFF),
+ CLK_8X60("gfx3d_clk", GFX3D_CLK, NULL, OFF),
+ CLK_8X60("ijpeg_clk", IJPEG_CLK, NULL, OFF),
+ CLK_8X60("imem_clk", IMEM_CLK, NULL, OFF),
+ CLK_8X60("jpegd_clk", JPEGD_CLK, NULL, OFF),
+ CLK_8X60("mdp_clk", MDP_CLK, NULL, OFF),
+ CLK_8X60("mdp_vsync_clk", MDP_VSYNC_CLK, NULL, OFF),
+ CLK_8X60("pixel_mdp_clk", PIXEL_MDP_CLK, NULL, OFF),
+ CLK_8X60("pixel_lcdc_clk", PIXEL_LCDC_CLK, NULL, OFF),
+ CLK_8X60("rot_clk", ROT_CLK, NULL, OFF),
+ CLK_8X60("tv_src_clk", TV_SRC_CLK, NULL, OFF),
+ CLK_8X60("tv_enc_clk", TV_ENC_CLK, NULL, OFF),
+ CLK_8X60("tv_dac_clk", TV_DAC_CLK, NULL, OFF),
+ CLK_8X60("vcodec_clk", VCODEC_CLK, NULL, OFF),
+ CLK_8X60("mdp_tv_clk", MDP_TV_CLK, NULL, OFF),
+ CLK_8X60("hdmi_clk", HDMI_TV_CLK, NULL, OFF),
+ CLK_8X60("hdmi_app_clk", HDMI_APP_CLK, NULL, OFF),
+ CLK_8X60("vpe_clk", VPE_CLK, NULL, OFF),
+ CLK_8X60("vfe_clk", VFE_CLK, NULL, OFF),
+ CLK_8X60("csi_vfe_clk", CSI0_VFE_CLK, NULL, OFF),
+ CLK_8X60("csi_vfe_clk", CSI1_VFE_CLK, NULL, OFF),
+ CLK_8X60("smmu_jpegd_clk", JPEGD_AXI_CLK, NULL, OFF),
+ CLK_8X60("smmu_vfe_clk", VFE_AXI_CLK, NULL, OFF),
+ CLK_8X60("vfe_axi_clk", VFE_AXI_CLK, NULL, OFF),
+ CLK_8X60("ijpeg_axi_clk", IJPEG_AXI_CLK, NULL, OFF),
+ CLK_8X60("mdp_axi_clk", MDP_AXI_CLK, NULL, OFF),
+ CLK_8X60("rot_axi_clk", ROT_AXI_CLK, NULL, OFF),
+ CLK_8X60("vcodec_axi_clk", VCODEC_AXI_CLK, NULL, OFF),
+ CLK_8X60("vpe_axi_clk", VPE_AXI_CLK, NULL, OFF),
+ CLK_8X60("amp_pclk", AMP_P_CLK, NULL, OFF),
+ CLK_8X60("csi_pclk", CSI0_P_CLK, NULL, OFF),
+ CLK_8X60("csi_pclk", CSI1_P_CLK, NULL, OFF),
+ CLK_8X60("dsi_m_pclk", DSI_M_P_CLK, NULL, OFF),
+ CLK_8X60("dsi_s_pclk", DSI_S_P_CLK, NULL, OFF),
+ CLK_8X60("gfx2d0_pclk", GFX2D0_P_CLK, NULL, OFF),
+ CLK_8X60("gfx2d1_pclk", GFX2D1_P_CLK, NULL, OFF),
+ CLK_8X60("gfx3d_pclk", GFX3D_P_CLK, NULL, OFF),
+ CLK_8X60("hdmi_m_pclk", HDMI_M_P_CLK, NULL, OFF),
+ CLK_8X60("hdmi_s_pclk", HDMI_S_P_CLK, NULL, OFF),
+ CLK_8X60("ijpeg_pclk", IJPEG_P_CLK, NULL, OFF),
+ CLK_8X60("jpegd_pclk", JPEGD_P_CLK, NULL, OFF),
+ CLK_8X60("imem_pclk", IMEM_P_CLK, NULL, OFF),
+ CLK_8X60("mdp_pclk", MDP_P_CLK, NULL, OFF),
+ CLK_8X60("smmu_pclk", SMMU_P_CLK, NULL, OFF),
+ CLK_8X60("rotator_pclk", ROT_P_CLK, NULL, OFF),
+ CLK_8X60("tv_enc_pclk", TV_ENC_P_CLK, NULL, OFF),
+ CLK_8X60("vcodec_pclk", VCODEC_P_CLK, NULL, OFF),
+ CLK_8X60("vfe_pclk", VFE_P_CLK, NULL, OFF),
+ CLK_8X60("vpe_pclk", VPE_P_CLK, NULL, OFF),
+ CLK_8X60("mi2s_osr_clk", MI2S_OSR_CLK, NULL, OFF),
+ CLK_8X60("mi2s_bit_clk", MI2S_BIT_CLK, NULL, OFF),
+ CLK_8X60("i2s_mic_osr_clk", CODEC_I2S_MIC_OSR_CLK, NULL, OFF),
+ CLK_8X60("i2s_mic_bit_clk", CODEC_I2S_MIC_BIT_CLK, NULL, OFF),
+ CLK_8X60("i2s_mic_osr_clk", SPARE_I2S_MIC_OSR_CLK, NULL, OFF),
+ CLK_8X60("i2s_mic_bit_clk", SPARE_I2S_MIC_BIT_CLK, NULL, OFF),
+ CLK_8X60("i2s_spkr_osr_clk", CODEC_I2S_SPKR_OSR_CLK, NULL, OFF),
+ CLK_8X60("i2s_spkr_bit_clk", CODEC_I2S_SPKR_BIT_CLK, NULL, OFF),
+ CLK_8X60("i2s_spkr_osr_clk", SPARE_I2S_SPKR_OSR_CLK, NULL, OFF),
+ CLK_8X60("i2s_spkr_bit_clk", SPARE_I2S_SPKR_BIT_CLK, NULL, OFF),
+ CLK_8X60("pcm_clk", PCM_CLK, NULL, OFF),
+ CLK_8X60("iommu_clk", JPEGD_AXI_CLK, NULL, 0),
+ CLK_8X60("iommu_clk", VFE_AXI_CLK, NULL, 0),
+ CLK_8X60("iommu_clk", VCODEC_AXI_CLK, NULL, 0),
+ CLK_8X60("iommu_clk", VCODEC_AXI_CLK, NULL, 0),
+ CLK_8X60("iommu_clk", GFX3D_CLK, NULL, 0),
+ CLK_8X60("iommu_clk", GFX2D0_CLK, NULL, 0),
+ CLK_8X60("iommu_clk", GFX2D1_CLK, NULL, 0),
+};
+
+unsigned msm_num_clocks_8x60 = ARRAY_SIZE(msm_clocks_8x60);
+
diff --git a/arch/arm/mach-msm/devices.h b/arch/arm/mach-msm/devices.h
index 68b8075..81d2b5d8 100644
--- a/arch/arm/mach-msm/devices.h
+++ b/arch/arm/mach-msm/devices.h
@@ -48,4 +48,7 @@ extern unsigned msm_num_clocks_7x30;
extern struct clk msm_clocks_8x50[];
extern unsigned msm_num_clocks_8x50;
+extern struct clk msm_clocks_8x60[];
+extern unsigned msm_num_clocks_8x60;
+
#endif
--
Sent by an employee of the Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum.
^ permalink raw reply related [flat|nested] 23+ messages in thread* [PATCH 11/22] msm: clock Add debugfs interface to measure clock rates
2010-12-17 0:49 [PATCH 00/22] MSM clock driver updates Stephen Boyd
` (9 preceding siblings ...)
2010-12-17 0:49 ` [PATCH 10/22] msm: Move 8x60 to the real clock driver Stephen Boyd
@ 2010-12-17 0:49 ` Stephen Boyd
2010-12-17 0:49 ` [PATCH 12/22] msm: clock: Add list_rate debugfs nodes for locally-controlled clocks Stephen Boyd
` (10 subsequent siblings)
21 siblings, 0 replies; 23+ messages in thread
From: Stephen Boyd @ 2010-12-17 0:49 UTC (permalink / raw)
To: linux-arm-kernel
From: Matt Wagantall <mattw@codeaurora.org>
Use the SoC's ring oscillator hardware to measure the clock rate
of locally-controlled clocks. This allows for the development of
more comprehensive end-to-end clock tests.
A 'measure' debugfs node is created for each clock to perform the
measurement and retrieve the result. soc_clk_measure_rate() should
*only* be used for debug purposes since it busy-loops while the
measurement takes place (~15 ms).
Clock rates are in units of Hz. Clocks that are not locally
controlled or do not support rate measurement will return -1.
Reviewed-by: Saravana Kannan <skannan@codeaurora.org>
Signed-off-by: Matt Wagantall <mattw@codeaurora.org>
Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
---
arch/arm/mach-msm/clock-7x30.c | 90 ++++++++++++++++++++++++++++++++++
arch/arm/mach-msm/clock-8x60.c | 101 +++++++++++++++++++++++++++++++++++++++
arch/arm/mach-msm/clock-debug.c | 15 ++++++
arch/arm/mach-msm/clock-pcom.c | 7 +++
arch/arm/mach-msm/clock.h | 1 +
5 files changed, 214 insertions(+), 0 deletions(-)
diff --git a/arch/arm/mach-msm/clock-7x30.c b/arch/arm/mach-msm/clock-7x30.c
index 994104f..e13de24 100644
--- a/arch/arm/mach-msm/clock-7x30.c
+++ b/arch/arm/mach-msm/clock-7x30.c
@@ -89,6 +89,10 @@
#define VPE_NS_REG REG(0x015C)
/* Registers in the base (non-shadow) region. */
+#define CLK_TEST_BASE_REG REG_BASE(0x011C)
+#define CLK_TEST_2_BASE_REG REG_BASE(0x0384)
+#define MISC_CLK_CTL_BASE_REG REG_BASE(0x0110)
+#define PRPH_WEB_NS_BASE_REG REG_BASE(0x0080)
#define PLL0_STATUS_BASE_REG REG_BASE(0x0318)
#define PLL1_STATUS_BASE_REG REG_BASE(0x0334)
#define PLL2_STATUS_BASE_REG REG_BASE(0x0350)
@@ -96,12 +100,15 @@
#define PLL4_STATUS_BASE_REG REG_BASE(0x0254)
#define PLL5_STATUS_BASE_REG REG_BASE(0x0258)
#define PLL6_STATUS_BASE_REG REG_BASE(0x04EC)
+#define RINGOSC_CNT_BASE_REG REG_BASE(0x00FC)
#define SH2_OWN_APPS1_BASE_REG REG_BASE(0x040C)
#define SH2_OWN_APPS2_BASE_REG REG_BASE(0x0414)
#define SH2_OWN_APPS3_BASE_REG REG_BASE(0x0444)
#define SH2_OWN_GLBL_BASE_REG REG_BASE(0x0404)
#define SH2_OWN_ROW1_BASE_REG REG_BASE(0x041C)
#define SH2_OWN_ROW2_BASE_REG REG_BASE(0x0424)
+#define TCXO_CNT_BASE_REG REG_BASE(0x00F8)
+#define TCXO_CNT_DONE_BASE_REG REG_BASE(0x00F8)
/* MUX source input identifiers. */
@@ -687,6 +694,88 @@ int soc_set_pwr_rail(unsigned id, int enable)
return 0;
}
+/* Sample clock for 'tcxo4_ticks' reference clock ticks. */
+static uint32_t run_measurement(unsigned tcxo4_ticks)
+{
+ /* TCXO4_CNT_EN and RINGOSC_CNT_EN register values. */
+ uint32_t reg_val_enable = readl(MISC_CLK_CTL_BASE_REG) | 0x3;
+ uint32_t reg_val_disable = reg_val_enable & ~0x3;
+
+ /* Stop counters and set the TCXO4 counter start value. */
+ writel(reg_val_disable, MISC_CLK_CTL_BASE_REG);
+ writel(tcxo4_ticks, TCXO_CNT_BASE_REG);
+
+ /* Run measurement and wait for completion. */
+ writel(reg_val_enable, MISC_CLK_CTL_BASE_REG);
+ while (readl(TCXO_CNT_DONE_BASE_REG) == 0)
+ cpu_relax();
+
+ /* Stop counters. */
+ writel(reg_val_disable, MISC_CLK_CTL_BASE_REG);
+
+ return readl(RINGOSC_CNT_BASE_REG);
+}
+
+/* Perform a hardware rate measurement for a given clock.
+ FOR DEBUG USE ONLY: Measurements take ~15 ms! */
+signed soc_clk_measure_rate(unsigned id)
+{
+ struct clk_local *t = &soc_clk_local_tbl[id];
+ unsigned long flags;
+ uint32_t regval, prph_web_reg_old;
+ uint64_t raw_count_short, raw_count_full;
+ signed ret;
+
+ if (t->test_vector == 0)
+ return -EPERM;
+
+ spin_lock_irqsave(&local_clock_reg_lock, flags);
+
+ /* Program test vector. */
+ if (t->test_vector <= 0xFF) {
+ /* Select CLK_TEST_2 */
+ writel(0x4D40, CLK_TEST_BASE_REG);
+ writel(t->test_vector, CLK_TEST_2_BASE_REG);
+ } else
+ writel(t->test_vector, CLK_TEST_BASE_REG);
+
+ /* Enable TCXO4 clock branch and root. */
+ prph_web_reg_old = readl(PRPH_WEB_NS_BASE_REG);
+ regval = prph_web_reg_old | B(9) | B(11);
+ local_src_enable(TCXO);
+ writel(regval, PRPH_WEB_NS_BASE_REG);
+
+ /*
+ * The ring oscillator counter will not reset if the measured clock
+ * is not running. To detect this, run a short measurement before
+ * the full measurement. If the raw results of the two are the same
+ * then the clock must be off.
+ */
+
+ /* Run a short measurement. (~1 ms) */
+ raw_count_short = run_measurement(0x1000);
+ /* Run a full measurement. (~14 ms) */
+ raw_count_full = run_measurement(0x10000);
+
+ /* Disable TCXO4 clock branch and root. */
+ writel(prph_web_reg_old, PRPH_WEB_NS_BASE_REG);
+ local_src_disable(TCXO);
+
+ /* Return 0 if the clock is off. */
+ if (raw_count_full == raw_count_short)
+ ret = 0;
+ else {
+ /* Compute rate in Hz. */
+ raw_count_full = ((raw_count_full * 10) + 15) * 4800000;
+ do_div(raw_count_full, ((0x10000 * 10) + 35));
+ ret = (signed)raw_count_full;
+ }
+
+ spin_unlock_irqrestore(&local_clock_reg_lock, flags);
+
+ return ret;
+}
+
/* Implementation for clk_set_flags(). */
int soc_clk_set_flags(unsigned id, unsigned clk_flags)
{
@@ -1072,4 +1161,5 @@ struct clk_ops soc_clk_ops_7x30 = {
.reset = pc_clk_reset,
.set_flags = soc_clk_set_flags,
.is_local = local_clk_is_local,
+ .measure_rate = soc_clk_measure_rate,
};
diff --git a/arch/arm/mach-msm/clock-8x60.c b/arch/arm/mach-msm/clock-8x60.c
index e1f3c6f..6972001 100644
--- a/arch/arm/mach-msm/clock-8x60.c
+++ b/arch/arm/mach-msm/clock-8x60.c
@@ -1621,6 +1621,106 @@ int soc_set_pwr_rail(unsigned id, int enable)
return 0;
}
+/* Sample clock for 'ticks' reference clock ticks. */
+static uint32_t run_measurement(unsigned ticks)
+{
+ /* Stop counters and set the XO4 counter start value. */
+ writel(0x0, RINGOSC_TCXO_CTL_REG);
+ writel(ticks, RINGOSC_TCXO_CTL_REG);
+
+ /* Wait for timer to become ready. */
+ while ((readl(RINGOSC_STATUS_REG) & B(25)) != 0)
+ cpu_relax();
+
+ /* Run measurement and wait for completion. */
+ writel(B(20)|ticks, RINGOSC_TCXO_CTL_REG);
+ while ((readl(RINGOSC_STATUS_REG) & B(25)) == 0)
+ cpu_relax();
+
+ /* Stop counters. */
+ writel(0x0, RINGOSC_TCXO_CTL_REG);
+
+ /* Return measured ticks. */
+ return readl(RINGOSC_STATUS_REG) & BM(24, 0);
+}
+
+/* Perform a hardware rate measurement for a given clock.
+ FOR DEBUG USE ONLY: Measurements take ~15 ms! */
+int soc_clk_measure_rate(unsigned id)
+{
+ struct clk_local *clk = &soc_clk_local_tbl[id];
+ unsigned long flags;
+ uint32_t clk_sel, pdm_reg_backup, ringosc_reg_backup;
+ uint64_t raw_count_short, raw_count_full;
+ int ret;
+
+ spin_lock_irqsave(&local_clock_reg_lock, flags);
+
+ /* Program the test vector. */
+ clk_sel = clk->test_vector & TEST_CLK_SEL_MASK;
+ switch (clk->test_vector >> TEST_TYPE_SHIFT) {
+ case TEST_TYPE_PER_LS:
+ writel(0x4030D00|BVAL(7, 0, clk_sel), CLK_TEST_REG);
+ break;
+ case TEST_TYPE_PER_HS:
+ writel(0x4020000|BVAL(16, 10, clk_sel), CLK_TEST_REG);
+ break;
+ case TEST_TYPE_MM_LS:
+ writel(0x4030D97, CLK_TEST_REG);
+ writel(BVAL(6, 1, clk_sel)|B(0), DBG_CFG_REG_LS_REG);
+ break;
+ case TEST_TYPE_MM_HS:
+ writel(0x402B800, CLK_TEST_REG);
+ writel(BVAL(6, 1, clk_sel)|B(0), DBG_CFG_REG_HS_REG);
+ break;
+ case TEST_TYPE_LPA:
+ writel(0x4030D98, CLK_TEST_REG);
+ writel(BVAL(6, 1, clk_sel)|B(0), LCC_CLK_LS_DEBUG_CFG_REG);
+ break;
+ default:
+ ret = -EPERM;
+ goto err;
+ }
+
+ /* Enable CXO/4 and RINGOSC branch and root. */
+ pdm_reg_backup = readl(PDM_CLK_NS_REG);
+ ringosc_reg_backup = readl(RINGOSC_NS_REG);
+ writel(0x2898, PDM_CLK_NS_REG);
+ writel(0xA00, RINGOSC_NS_REG);
+
+ /*
+ * The ring oscillator counter will not reset if the measured clock
+ * is not running. To detect this, run a short measurement before
+ * the full measurement. If the raw results of the two are the same
+ * then the clock must be off.
+ */
+
+ /* Run a short measurement. (~1 ms) */
+ raw_count_short = run_measurement(0x1000);
+ /* Run a full measurement. (~14 ms) */
+ raw_count_full = run_measurement(0x10000);
+
+ writel(ringosc_reg_backup, RINGOSC_NS_REG);
+ writel(pdm_reg_backup, PDM_CLK_NS_REG);
+
+ /* Return 0 if the clock is off. */
+ if (raw_count_full == raw_count_short)
+ ret = 0;
+ else {
+ /* Compute rate in Hz. */
+ raw_count_full = ((raw_count_full * 10) + 15) * 4800000;
+ do_div(raw_count_full, ((0x10000 * 10) + 35));
+ ret = (int)raw_count_full;
+ }
+
+ /* Route dbg_hs_clk to PLLTEST. 300mV single-ended amplitude. */
+ writel(0x3CF8, PLLTEST_PAD_CFG_REG);
+err:
+ spin_unlock_irqrestore(&local_clock_reg_lock, flags);
+
+ return ret;
+}
+
/* Implementation for clk_set_flags(). */
int soc_clk_set_flags(unsigned id, unsigned flags)
{
@@ -1800,4 +1900,5 @@ struct clk_ops soc_clk_ops_8x60 = {
.reset = soc_clk_reset,
.set_flags = soc_clk_set_flags,
.is_local = local_clk_is_local,
+ .measure_rate = soc_clk_measure_rate,
};
diff --git a/arch/arm/mach-msm/clock-debug.c b/arch/arm/mach-msm/clock-debug.c
index 4886404..73ef9cc 100644
--- a/arch/arm/mach-msm/clock-debug.c
+++ b/arch/arm/mach-msm/clock-debug.c
@@ -49,6 +49,16 @@ static int clock_debug_rate_get(void *data, u64 *val)
DEFINE_SIMPLE_ATTRIBUTE(clock_rate_fops, clock_debug_rate_get,
clock_debug_rate_set, "%llu\n");
+static int clock_debug_measure_get(void *data, u64 *val)
+{
+ struct clk *clock = data;
+ *val = clock->ops->measure_rate(clock->id);
+ return 0;
+}
+
+DEFINE_SIMPLE_ATTRIBUTE(clock_measure_fops, clock_debug_measure_get,
+ NULL, "%lld\n");
+
static int clock_debug_enable_set(void *data, u64 val)
{
struct clk *clock = data;
@@ -123,6 +133,11 @@ int __init clock_debug_add(struct clk *clock)
if (!debugfs_create_file("is_local", S_IRUGO, clk_dir, clock,
&clock_local_fops))
goto error;
+
+ if (!debugfs_create_file("measure", S_IRUGO, clk_dir,
+ clock, &clock_measure_fops))
+ goto error;
+
return 0;
error:
debugfs_remove_recursive(clk_dir);
diff --git a/arch/arm/mach-msm/clock-pcom.c b/arch/arm/mach-msm/clock-pcom.c
index 63b7113..2f9d0d4 100644
--- a/arch/arm/mach-msm/clock-pcom.c
+++ b/arch/arm/mach-msm/clock-pcom.c
@@ -102,6 +102,12 @@ unsigned pc_clk_get_rate(unsigned id)
return id;
}
+int pc_clk_measure_rate(unsigned id)
+{
+ /* Not supported. */
+ return -EPERM;
+}
+
unsigned pc_clk_is_enabled(unsigned id)
{
if (msm_proc_comm(PCOM_CLKCTL_RPC_ENABLED, &id, NULL))
@@ -132,6 +138,7 @@ struct clk_ops clk_ops_pcom = {
.set_max_rate = pc_clk_set_max_rate,
.set_flags = pc_clk_set_flags,
.get_rate = pc_clk_get_rate,
+ .measure_rate = pc_clk_measure_rate,
.is_enabled = pc_clk_is_enabled,
.round_rate = pc_clk_round_rate,
.is_local = pc_clk_is_local,
diff --git a/arch/arm/mach-msm/clock.h b/arch/arm/mach-msm/clock.h
index b74ba3e..f09e01b 100644
--- a/arch/arm/mach-msm/clock.h
+++ b/arch/arm/mach-msm/clock.h
@@ -41,6 +41,7 @@ struct clk_ops {
int (*set_max_rate)(unsigned id, unsigned rate);
int (*set_flags)(unsigned id, unsigned flags);
unsigned (*get_rate)(unsigned id);
+ int (*measure_rate)(unsigned id);
unsigned (*is_enabled)(unsigned id);
long (*round_rate)(unsigned id, unsigned rate);
bool (*is_local)(unsigned id);
--
Sent by an employee of the Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum.
^ permalink raw reply related [flat|nested] 23+ messages in thread* [PATCH 12/22] msm: clock: Add list_rate debugfs nodes for locally-controlled clocks
2010-12-17 0:49 [PATCH 00/22] MSM clock driver updates Stephen Boyd
` (10 preceding siblings ...)
2010-12-17 0:49 ` [PATCH 11/22] msm: clock Add debugfs interface to measure clock rates Stephen Boyd
@ 2010-12-17 0:49 ` Stephen Boyd
2010-12-17 0:49 ` [PATCH 13/22] msm: clock: Push down clock count and locking into sub drivers Stephen Boyd
` (9 subsequent siblings)
21 siblings, 0 replies; 23+ messages in thread
From: Stephen Boyd @ 2010-12-17 0:49 UTC (permalink / raw)
To: linux-arm-kernel
From: Matt Wagantall <mattw@codeaurora.org>
Add debugfs nodes to list all of the supported rates for rate-settable
locally-controlled clocks. This allows a clock's supported rates to
be queried from userspace, and allows more comprehensive userspace
clock tests to be developed.
Reviewed-by: Saravana Kannan <skannan@codeaurora.org>
Signed-off-by: Matt Wagantall <mattw@codeaurora.org>
Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
---
arch/arm/mach-msm/clock-7x30.c | 1 +
arch/arm/mach-msm/clock-8x60.c | 1 +
arch/arm/mach-msm/clock-debug.c | 31 +++++++++++++++++++++++++++++++
arch/arm/mach-msm/clock-local.c | 11 +++++++++++
arch/arm/mach-msm/clock-local.h | 1 +
arch/arm/mach-msm/clock.h | 1 +
6 files changed, 46 insertions(+), 0 deletions(-)
diff --git a/arch/arm/mach-msm/clock-7x30.c b/arch/arm/mach-msm/clock-7x30.c
index e13de24..9e73d8a 100644
--- a/arch/arm/mach-msm/clock-7x30.c
+++ b/arch/arm/mach-msm/clock-7x30.c
@@ -1156,6 +1156,7 @@ struct clk_ops soc_clk_ops_7x30 = {
.set_min_rate = local_clk_set_min_rate,
.set_max_rate = local_clk_set_max_rate,
.get_rate = local_clk_get_rate,
+ .list_rate = local_clk_list_rate,
.is_enabled = local_clk_is_enabled,
.round_rate = local_clk_round_rate,
.reset = pc_clk_reset,
diff --git a/arch/arm/mach-msm/clock-8x60.c b/arch/arm/mach-msm/clock-8x60.c
index 6972001..28017b7 100644
--- a/arch/arm/mach-msm/clock-8x60.c
+++ b/arch/arm/mach-msm/clock-8x60.c
@@ -1895,6 +1895,7 @@ struct clk_ops soc_clk_ops_8x60 = {
.set_min_rate = local_clk_set_min_rate,
.set_max_rate = local_clk_set_max_rate,
.get_rate = local_clk_get_rate,
+ .list_rate = local_clk_list_rate,
.is_enabled = local_clk_is_enabled,
.round_rate = local_clk_round_rate,
.reset = soc_clk_reset,
diff --git a/arch/arm/mach-msm/clock-debug.c b/arch/arm/mach-msm/clock-debug.c
index 73ef9cc..354bc1e 100644
--- a/arch/arm/mach-msm/clock-debug.c
+++ b/arch/arm/mach-msm/clock-debug.c
@@ -17,6 +17,7 @@
#include <linux/module.h>
#include <linux/ctype.h>
#include <linux/debugfs.h>
+#include <linux/seq_file.h>
#include <linux/clk.h>
#include "clock.h"
@@ -106,6 +107,32 @@ int __init clock_debug_init(void)
return 0;
}
+static int list_rates_show(struct seq_file *m, void *unused)
+{
+ struct clk *clock = m->private;
+ int rate, i = 0;
+
+ if (clock->ops->list_rate == NULL)
+ return -EINVAL;
+
+ while ((rate = clock->ops->list_rate(clock->id, i++)) >= 0)
+ seq_printf(m, "%d\n", rate);
+
+ return 0;
+}
+
+static int list_rates_open(struct inode *inode, struct file *file)
+{
+ return single_open(file, list_rates_show, inode->i_private);
+}
+
+static const struct file_operations list_rates_fops = {
+ .open = list_rates_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = seq_release,
+};
+
int __init clock_debug_add(struct clk *clock)
{
char temp[50], *ptr;
@@ -138,6 +165,10 @@ int __init clock_debug_add(struct clk *clock)
clock, &clock_measure_fops))
goto error;
+ if (!debugfs_create_file("list_rates", S_IRUGO, clk_dir,
+ clock, &list_rates_fops))
+ goto error;
+
return 0;
error:
debugfs_remove_recursive(clk_dir);
diff --git a/arch/arm/mach-msm/clock-local.c b/arch/arm/mach-msm/clock-local.c
index 44e0778..f80efa6 100644
--- a/arch/arm/mach-msm/clock-local.c
+++ b/arch/arm/mach-msm/clock-local.c
@@ -682,3 +682,14 @@ bool local_clk_is_local(unsigned id)
{
return true;
}
+
+/* Return the nth supported frequency for a given clock. */
+int local_clk_list_rate(unsigned id, unsigned n)
+{
+ struct clk_local *clk = &soc_clk_local_tbl[id];
+
+ if (!clk->freq_tbl || clk->freq_tbl->freq_hz == FREQ_END)
+ return -ENXIO;
+
+ return (clk->freq_tbl + n)->freq_hz;
+}
diff --git a/arch/arm/mach-msm/clock-local.h b/arch/arm/mach-msm/clock-local.h
index 3083369..cf97219 100644
--- a/arch/arm/mach-msm/clock-local.h
+++ b/arch/arm/mach-msm/clock-local.h
@@ -209,6 +209,7 @@ int local_clk_set_rate(unsigned id, unsigned rate);
int local_clk_set_min_rate(unsigned id, unsigned rate);
int local_clk_set_max_rate(unsigned id, unsigned rate);
unsigned local_clk_get_rate(unsigned id);
+int local_clk_list_rate(unsigned id, unsigned n);
unsigned local_clk_is_enabled(unsigned id);
long local_clk_round_rate(unsigned id, unsigned rate);
bool local_clk_is_local(unsigned id);
diff --git a/arch/arm/mach-msm/clock.h b/arch/arm/mach-msm/clock.h
index f09e01b..67f9d9e 100644
--- a/arch/arm/mach-msm/clock.h
+++ b/arch/arm/mach-msm/clock.h
@@ -41,6 +41,7 @@ struct clk_ops {
int (*set_max_rate)(unsigned id, unsigned rate);
int (*set_flags)(unsigned id, unsigned flags);
unsigned (*get_rate)(unsigned id);
+ int (*list_rate)(unsigned id, unsigned n);
int (*measure_rate)(unsigned id);
unsigned (*is_enabled)(unsigned id);
long (*round_rate)(unsigned id, unsigned rate);
--
Sent by an employee of the Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum.
^ permalink raw reply related [flat|nested] 23+ messages in thread* [PATCH 13/22] msm: clock: Push down clock count and locking into sub drivers
2010-12-17 0:49 [PATCH 00/22] MSM clock driver updates Stephen Boyd
` (11 preceding siblings ...)
2010-12-17 0:49 ` [PATCH 12/22] msm: clock: Add list_rate debugfs nodes for locally-controlled clocks Stephen Boyd
@ 2010-12-17 0:49 ` Stephen Boyd
2010-12-17 0:49 ` [PATCH 14/22] msm: clock: Support clk_set_parent() clk_ops Stephen Boyd
` (8 subsequent siblings)
21 siblings, 0 replies; 23+ messages in thread
From: Stephen Boyd @ 2010-12-17 0:49 UTC (permalink / raw)
To: linux-arm-kernel
The clock voting code will need to call clk_set_rate() from
within a spinlock so we must push down the refcount and lock into
each sub driver to avoid recursive locking.
Reviewed-by: Saravana Kannan <skannan@codeaurora.org>
Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
---
arch/arm/mach-msm/clock-local.c | 3 +-
arch/arm/mach-msm/clock-pcom.c | 59 ++++++++++++++++++++++++++++++++++----
arch/arm/mach-msm/clock.c | 32 ++------------------
arch/arm/mach-msm/clock.h | 1 -
4 files changed, 58 insertions(+), 37 deletions(-)
diff --git a/arch/arm/mach-msm/clock-local.c b/arch/arm/mach-msm/clock-local.c
index f80efa6..86b5a9d 100644
--- a/arch/arm/mach-msm/clock-local.c
+++ b/arch/arm/mach-msm/clock-local.c
@@ -501,7 +501,8 @@ void local_clk_auto_off(unsigned id)
return;
spin_lock_irqsave(&local_clock_reg_lock, flags);
- local_clk_disable_reg(id);
+ if (clk->count == 0)
+ local_clk_disable_reg(id);
spin_unlock_irqrestore(&local_clock_reg_lock, flags);
}
diff --git a/arch/arm/mach-msm/clock-pcom.c b/arch/arm/mach-msm/clock-pcom.c
index 2f9d0d4..358e065 100644
--- a/arch/arm/mach-msm/clock-pcom.c
+++ b/arch/arm/mach-msm/clock-pcom.c
@@ -16,27 +16,72 @@
#include <linux/err.h>
#include <linux/ctype.h>
#include <linux/stddef.h>
+#include <linux/spinlock.h>
+
#include <mach/clk.h>
#include "proc_comm.h"
#include "clock.h"
#include "clock-pcom.h"
+struct clk_pcom {
+ unsigned count;
+};
+
+static struct clk_pcom pcom_clocks[P_NR_CLKS];
+
+static DEFINE_SPINLOCK(pc_clk_lock);
+
/*
* glue for the proc_comm interface
*/
int pc_clk_enable(unsigned id)
{
- int rc = msm_proc_comm(PCOM_CLKCTL_RPC_ENABLE, &id, NULL);
- if (rc < 0)
- return rc;
- else
- return (int)id < 0 ? -EINVAL : 0;
+ int rc;
+ unsigned long flags;
+ struct clk_pcom *clk = &pcom_clocks[id];
+
+ spin_lock_irqsave(&pc_clk_lock, flags);
+ if (clk->count == 0) {
+ rc = msm_proc_comm(PCOM_CLKCTL_RPC_ENABLE, &id, NULL);
+ if (rc < 0)
+ goto unlock;
+ else if ((int)id < 0) {
+ rc = -EINVAL;
+ goto unlock;
+ } else
+ rc = 0;
+ }
+ clk->count++;
+unlock:
+ spin_unlock_irqrestore(&pc_clk_lock, flags);
+ return rc;
}
void pc_clk_disable(unsigned id)
{
- msm_proc_comm(PCOM_CLKCTL_RPC_DISABLE, &id, NULL);
+ unsigned long flags;
+ struct clk_pcom *clk = &pcom_clocks[id];
+
+ spin_lock_irqsave(&pc_clk_lock, flags);
+ if (WARN_ON(clk->count == 0))
+ goto out;
+ clk->count--;
+ if (clk->count == 0)
+ msm_proc_comm(PCOM_CLKCTL_RPC_DISABLE, &id, NULL);
+out:
+ spin_unlock_irqrestore(&pc_clk_lock, flags);
+}
+
+void pc_clk_auto_off(unsigned id)
+{
+ unsigned long flags;
+ struct clk_pcom *clk = &pcom_clocks[id];
+
+ spin_lock_irqsave(&pc_clk_lock, flags);
+ if (clk->count == 0)
+ msm_proc_comm(PCOM_CLKCTL_RPC_DISABLE, &id, NULL);
+ spin_unlock_irqrestore(&pc_clk_lock, flags);
}
int pc_clk_reset(unsigned id, enum clk_reset_action action)
@@ -131,7 +176,7 @@ static bool pc_clk_is_local(unsigned id)
struct clk_ops clk_ops_pcom = {
.enable = pc_clk_enable,
.disable = pc_clk_disable,
- .auto_off = pc_clk_disable,
+ .auto_off = pc_clk_auto_off,
.reset = pc_clk_reset,
.set_rate = pc_clk_set_rate,
.set_min_rate = pc_clk_set_min_rate,
diff --git a/arch/arm/mach-msm/clock.c b/arch/arm/mach-msm/clock.c
index 06cd313..80e1d64 100644
--- a/arch/arm/mach-msm/clock.c
+++ b/arch/arm/mach-msm/clock.c
@@ -23,7 +23,6 @@
#include "clock.h"
static DEFINE_MUTEX(clocks_mutex);
-static DEFINE_SPINLOCK(clocks_lock);
static LIST_HEAD(clocks);
/*
@@ -57,25 +56,13 @@ EXPORT_SYMBOL(clk_put);
int clk_enable(struct clk *clk)
{
- unsigned long flags;
- spin_lock_irqsave(&clocks_lock, flags);
- clk->count++;
- if (clk->count == 1)
- clk->ops->enable(clk->id);
- spin_unlock_irqrestore(&clocks_lock, flags);
- return 0;
+ return clk->ops->enable(clk->id);
}
EXPORT_SYMBOL(clk_enable);
void clk_disable(struct clk *clk)
{
- unsigned long flags;
- spin_lock_irqsave(&clocks_lock, flags);
- BUG_ON(clk->count == 0);
- clk->count--;
- if (clk->count == 0)
- clk->ops->disable(clk->id);
- spin_unlock_irqrestore(&clocks_lock, flags);
+ clk->ops->disable(clk->id);
}
EXPORT_SYMBOL(clk_disable);
@@ -182,27 +169,16 @@ void __init msm_clock_init(struct clk *clock_tbl, unsigned num_clocks)
*/
static int __init clock_late_init(void)
{
- unsigned long flags;
struct clk *clk;
- unsigned count = 0;
clock_debug_init();
mutex_lock(&clocks_mutex);
list_for_each_entry(clk, &clocks, list) {
clock_debug_add(clk);
- if (clk->flags & CLKFLAG_AUTO_OFF) {
- spin_lock_irqsave(&clocks_lock, flags);
- if (!clk->count) {
- count++;
- clk->ops->auto_off(clk->id);
- }
- spin_unlock_irqrestore(&clocks_lock, flags);
- }
+ if (clk->flags & CLKFLAG_AUTO_OFF)
+ clk->ops->auto_off(clk->id);
}
mutex_unlock(&clocks_mutex);
- pr_info("clock_late_init() disabled %d unused clocks\n", count);
return 0;
}
-
late_initcall(clock_late_init);
-
diff --git a/arch/arm/mach-msm/clock.h b/arch/arm/mach-msm/clock.h
index 67f9d9e..4dc8853 100644
--- a/arch/arm/mach-msm/clock.h
+++ b/arch/arm/mach-msm/clock.h
@@ -51,7 +51,6 @@ struct clk_ops {
struct clk {
uint32_t id;
uint32_t remote_id;
- uint32_t count;
uint32_t flags;
const char *name;
struct clk_ops *ops;
--
Sent by an employee of the Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum.
^ permalink raw reply related [flat|nested] 23+ messages in thread* [PATCH 14/22] msm: clock: Support clk_set_parent() clk_ops
2010-12-17 0:49 [PATCH 00/22] MSM clock driver updates Stephen Boyd
` (12 preceding siblings ...)
2010-12-17 0:49 ` [PATCH 13/22] msm: clock: Push down clock count and locking into sub drivers Stephen Boyd
@ 2010-12-17 0:49 ` Stephen Boyd
2010-12-17 0:49 ` [PATCH 15/22] msm: clock-pcom: Add pbus specific clock ops Stephen Boyd
` (7 subsequent siblings)
21 siblings, 0 replies; 23+ messages in thread
From: Stephen Boyd @ 2010-12-17 0:49 UTC (permalink / raw)
To: linux-arm-kernel
Voting clocks are linked to the clock they vote on with a parent
pointer. Implement this API for sub drivers which wish to use it.
Reviewed-by: Saravana Kannan <skannan@codeaurora.org>
Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
---
arch/arm/mach-msm/clock.c | 2 ++
arch/arm/mach-msm/clock.h | 1 +
2 files changed, 3 insertions(+), 0 deletions(-)
diff --git a/arch/arm/mach-msm/clock.c b/arch/arm/mach-msm/clock.c
index 80e1d64..b6b7e7c 100644
--- a/arch/arm/mach-msm/clock.c
+++ b/arch/arm/mach-msm/clock.c
@@ -119,6 +119,8 @@ EXPORT_SYMBOL(clk_set_max_rate);
int clk_set_parent(struct clk *clk, struct clk *parent)
{
+ if (clk->ops->set_parent)
+ return clk->ops->set_parent(clk->id, parent);
return -ENOSYS;
}
EXPORT_SYMBOL(clk_set_parent);
diff --git a/arch/arm/mach-msm/clock.h b/arch/arm/mach-msm/clock.h
index 4dc8853..1a9fb72 100644
--- a/arch/arm/mach-msm/clock.h
+++ b/arch/arm/mach-msm/clock.h
@@ -46,6 +46,7 @@ struct clk_ops {
unsigned (*is_enabled)(unsigned id);
long (*round_rate)(unsigned id, unsigned rate);
bool (*is_local)(unsigned id);
+ int (*set_parent)(unsigned id, struct clk *parent);
};
struct clk {
--
Sent by an employee of the Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum.
^ permalink raw reply related [flat|nested] 23+ messages in thread* [PATCH 15/22] msm: clock-pcom: Add pbus specific clock ops
2010-12-17 0:49 [PATCH 00/22] MSM clock driver updates Stephen Boyd
` (13 preceding siblings ...)
2010-12-17 0:49 ` [PATCH 14/22] msm: clock: Support clk_set_parent() clk_ops Stephen Boyd
@ 2010-12-17 0:49 ` Stephen Boyd
2010-12-17 0:50 ` [PATCH 16/22] msm: clock: Implement rate voting Stephen Boyd
` (6 subsequent siblings)
21 siblings, 0 replies; 23+ messages in thread
From: Stephen Boyd @ 2010-12-17 0:49 UTC (permalink / raw)
To: linux-arm-kernel
The pbus clock always runs at half the ebi1 clock frequency.
Since ebi1 clock votes are dropped when the application processor
is power collapsed, the ebi1 clock is reserved for the acpuclock
driver. Other drivers which have ebi1 clock requirements that are
independent of application processor power status use the pbus.
To keep this change transparent across drivers and SoCs, add new
ops that divides the rate by 2 before sending the request to the
modem.
Reviewed-by: Saravana Kannan <skannan@codeaurora.org>
Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
---
arch/arm/mach-msm/clock-pcom.c | 29 +++++++++++++++++++++++++++++
arch/arm/mach-msm/clock-pcom.h | 1 +
arch/arm/mach-msm/devices-msm7x30.c | 9 ++++++++-
3 files changed, 38 insertions(+), 1 deletions(-)
diff --git a/arch/arm/mach-msm/clock-pcom.c b/arch/arm/mach-msm/clock-pcom.c
index 358e065..4616bbc 100644
--- a/arch/arm/mach-msm/clock-pcom.c
+++ b/arch/arm/mach-msm/clock-pcom.c
@@ -188,3 +188,32 @@ struct clk_ops clk_ops_pcom = {
.round_rate = pc_clk_round_rate,
.is_local = pc_clk_is_local,
};
+
+int pc_clk_set_rate2(unsigned id, unsigned rate)
+{
+ return pc_clk_set_rate(id, rate / 2);
+}
+
+int pc_clk_set_min_rate2(unsigned id, unsigned rate)
+{
+ return pc_clk_set_min_rate(id, rate / 2);
+}
+
+unsigned pc_clk_get_rate2(unsigned id)
+{
+ return pc_clk_get_rate(id) * 2;
+}
+
+struct clk_ops clk_ops_pcom_div2 = {
+ .enable = pc_clk_enable,
+ .disable = pc_clk_disable,
+ .reset = pc_clk_reset,
+ .set_rate = pc_clk_set_rate2,
+ .set_min_rate = pc_clk_set_min_rate2,
+ .set_flags = pc_clk_set_flags,
+ .get_rate = pc_clk_get_rate2,
+ .measure_rate = pc_clk_measure_rate,
+ .is_enabled = pc_clk_is_enabled,
+ .round_rate = pc_clk_round_rate,
+ .is_local = pc_clk_is_local,
+};
diff --git a/arch/arm/mach-msm/clock-pcom.h b/arch/arm/mach-msm/clock-pcom.h
index 2c813f1..e2bca82 100644
--- a/arch/arm/mach-msm/clock-pcom.h
+++ b/arch/arm/mach-msm/clock-pcom.h
@@ -139,6 +139,7 @@
struct clk_ops;
extern struct clk_ops clk_ops_pcom;
+extern struct clk_ops clk_ops_pcom_div2;
int pc_clk_reset(unsigned id, enum clk_reset_action action);
diff --git a/arch/arm/mach-msm/devices-msm7x30.c b/arch/arm/mach-msm/devices-msm7x30.c
index 55382c4..72da7cc 100644
--- a/arch/arm/mach-msm/devices-msm7x30.c
+++ b/arch/arm/mach-msm/devices-msm7x30.c
@@ -68,7 +68,14 @@ struct clk msm_clocks_7x30[] = {
CLK_PCOM("uart_clk", UART3_CLK, NULL, OFF),
CLK_PCOM("usb_phy_clk", USB_PHY_CLK, NULL, 0),
CLK_PCOM("vdc_clk", VDC_CLK, NULL, OFF | CLK_MIN),
- CLK_PCOM("pbus_clk", PBUS_CLK, NULL, CLK_MIN),
+ {
+ .name = "pbus_clk",
+ .id = P_PBUS_CLK,
+ .remote_id = P_PBUS_CLK,
+ .ops = &clk_ops_pcom_div2,
+ .flags = CLK_MIN,
+ .dbg_name = "pbus_clk",
+ },
CLK_7X30("adm_clk", ADM_CLK, NULL, 0),
CLK_7X30L("adm_pclk", ADM_P_CLK, NULL, 0),
--
Sent by an employee of the Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum.
^ permalink raw reply related [flat|nested] 23+ messages in thread* [PATCH 16/22] msm: clock: Implement rate voting
2010-12-17 0:49 [PATCH 00/22] MSM clock driver updates Stephen Boyd
` (14 preceding siblings ...)
2010-12-17 0:49 ` [PATCH 15/22] msm: clock-pcom: Add pbus specific clock ops Stephen Boyd
@ 2010-12-17 0:50 ` Stephen Boyd
2010-12-17 0:50 ` [PATCH 17/22] msm: Migrate to clock " Stephen Boyd
` (5 subsequent siblings)
21 siblings, 0 replies; 23+ messages in thread
From: Stephen Boyd @ 2010-12-17 0:50 UTC (permalink / raw)
To: linux-arm-kernel
Some clocks have multiple consumers where each consumer requires
a minimum rate. Implement a sub driver to aggregate
clk_set_rate() calls from each consumer and call clk_set_rate()
on the parent clock when the minimum requested rate of all the
voters changes.
Reviewed-by: Saravana Kannan <skannan@codeaurora.org>
Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
---
arch/arm/mach-msm/Makefile | 2 +-
arch/arm/mach-msm/clock-voter.c | 202 +++++++++++++++++++++++++++++++++++++++
arch/arm/mach-msm/clock-voter.h | 52 ++++++++++
arch/arm/mach-msm/clock.h | 3 +
4 files changed, 258 insertions(+), 1 deletions(-)
create mode 100644 arch/arm/mach-msm/clock-voter.c
create mode 100644 arch/arm/mach-msm/clock-voter.h
diff --git a/arch/arm/mach-msm/Makefile b/arch/arm/mach-msm/Makefile
index fb44992..56651b4 100644
--- a/arch/arm/mach-msm/Makefile
+++ b/arch/arm/mach-msm/Makefile
@@ -1,5 +1,5 @@
obj-y += io.o idle.o timer.o
-obj-y += clock.o
+obj-y += clock.o clock-voter.o
obj-$(CONFIG_DEBUG_FS) += clock-debug.o
obj-$(CONFIG_ARCH_MSM7X30) += clock-local.o
obj-$(CONFIG_ARCH_MSM8X60) += clock-local.o
diff --git a/arch/arm/mach-msm/clock-voter.c b/arch/arm/mach-msm/clock-voter.c
new file mode 100644
index 0000000..a0f94f8
--- /dev/null
+++ b/arch/arm/mach-msm/clock-voter.c
@@ -0,0 +1,202 @@
+/*
+ * Copyright (c) 2010, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#include <linux/spinlock.h>
+#include <linux/clk.h>
+
+#include "clock.h"
+#include "clock-voter.h"
+
+struct clk_voter {
+ unsigned count;
+ unsigned rate;
+ struct hlist_node voter_list;
+ struct clk *aggregator_clk;
+};
+
+static struct clk_voter voter_clocks[V_NR_CLKS];
+
+static DEFINE_SPINLOCK(voter_clk_lock);
+
+/* Aggregate the rate of clocks that are currently on. */
+static unsigned voter_clk_aggregate_rate(const struct clk *parent)
+{
+ struct hlist_node *pos;
+ struct clk_voter *clkh;
+ unsigned rate = 0;
+
+ hlist_for_each_entry(clkh, pos, &parent->voters, voter_list)
+ if (clkh->count)
+ rate = max(clkh->rate, rate);
+ return rate;
+}
+
+static int voter_clk_set_rate(unsigned id, unsigned rate)
+{
+ int ret = 0;
+ unsigned long flags;
+ struct hlist_node *pos;
+ struct clk_voter *clkh;
+ struct clk_voter *clk = &voter_clocks[id];
+ unsigned other_rate = 0;
+ unsigned cur_rate, new_rate;
+
+ spin_lock_irqsave(&voter_clk_lock, flags);
+
+ if (clk->count) {
+ struct clk *parent = clk->aggregator_clk;
+
+ /*
+ * Get the aggregate rate without this clock's vote and update
+ * if the new rate is different than the current rate
+ */
+ hlist_for_each_entry(clkh, pos, &parent->voters, voter_list)
+ if (clkh->count && clkh != clk)
+ other_rate = max(clkh->rate, other_rate);
+
+ cur_rate = max(other_rate, clk->rate);
+ new_rate = max(other_rate, rate);
+
+ if (new_rate != cur_rate) {
+ ret = clk_set_min_rate(parent, new_rate);
+ if (ret)
+ goto unlock;
+ }
+ }
+ clk->rate = rate;
+unlock:
+ spin_unlock_irqrestore(&voter_clk_lock, flags);
+
+ return ret;
+}
+
+static int voter_clk_enable(unsigned id)
+{
+ int ret = 0;
+ unsigned long flags;
+ unsigned cur_rate;
+ struct clk_voter *clk = &voter_clocks[id];
+
+ spin_lock_irqsave(&voter_clk_lock, flags);
+ if (clk->count == 0) {
+ struct clk *parent = clk->aggregator_clk;
+
+ /*
+ * Increase the rate if this clock is voting for a higher rate
+ * than the current rate.
+ */
+ cur_rate = voter_clk_aggregate_rate(parent);
+ if (clk->rate > cur_rate) {
+ ret = clk_set_min_rate(parent, clk->rate);
+ if (ret)
+ goto out;
+ }
+ ret = clk_enable(parent);
+ if (ret)
+ goto out;
+ }
+ clk->count++;
+out:
+ spin_unlock_irqrestore(&voter_clk_lock, flags);
+
+ return ret;
+}
+
+static void voter_clk_disable(unsigned id)
+{
+ unsigned long flags;
+ struct clk_voter *clk = &voter_clocks[id];
+ unsigned cur_rate, new_rate;
+
+ spin_lock_irqsave(&voter_clk_lock, flags);
+ if (WARN_ON(clk->count == 0))
+ goto out;
+ clk->count--;
+ if (clk->count == 0) {
+ struct clk *parent = clk->aggregator_clk;
+
+ /*
+ * Decrease the rate if this clock was the only one voting for
+ * the highest rate.
+ */
+ new_rate = voter_clk_aggregate_rate(parent);
+ cur_rate = max(new_rate, clk->rate);
+
+ if (new_rate < cur_rate)
+ clk_set_min_rate(parent, new_rate);
+
+ clk_disable(clk->aggregator_clk);
+ }
+out:
+ spin_unlock_irqrestore(&voter_clk_lock, flags);
+}
+
+static unsigned voter_clk_get_rate(unsigned id)
+{
+ unsigned rate;
+ unsigned long flags;
+ struct clk_voter *clk = &voter_clocks[id];
+
+ spin_lock_irqsave(&voter_clk_lock, flags);
+ rate = clk->rate;
+ spin_unlock_irqrestore(&voter_clk_lock, flags);
+
+ return rate;
+}
+
+static unsigned voter_clk_is_enabled(unsigned id)
+{
+ struct clk_voter *clk = &voter_clocks[id];
+ return clk->count;
+}
+
+static long voter_clk_round_rate(unsigned id, unsigned rate)
+{
+ struct clk_voter *clk = &voter_clocks[id];
+ return clk_round_rate(clk->aggregator_clk, rate);
+}
+
+static int voter_clk_set_parent(unsigned id, struct clk *parent)
+{
+ unsigned long flags;
+ struct clk_voter *clk = &voter_clocks[id];
+
+ spin_lock_irqsave(&voter_clk_lock, flags);
+ clk->aggregator_clk = parent;
+ hlist_add_head(&clk->voter_list, &parent->voters);
+ spin_unlock_irqrestore(&voter_clk_lock, flags);
+
+ return 0;
+}
+
+static bool voter_clk_is_local(unsigned id)
+{
+ return true;
+}
+
+struct clk_ops clk_ops_voter = {
+ .enable = voter_clk_enable,
+ .disable = voter_clk_disable,
+ .set_rate = voter_clk_set_rate,
+ .set_min_rate = voter_clk_set_rate,
+ .get_rate = voter_clk_get_rate,
+ .is_enabled = voter_clk_is_enabled,
+ .round_rate = voter_clk_round_rate,
+ .set_parent = voter_clk_set_parent,
+ .is_local = voter_clk_is_local,
+};
diff --git a/arch/arm/mach-msm/clock-voter.h b/arch/arm/mach-msm/clock-voter.h
new file mode 100644
index 0000000..84bc0b3
--- /dev/null
+++ b/arch/arm/mach-msm/clock-voter.h
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2010, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#ifndef __ARCH_ARM_MACH_MSM_CLOCK_VOTER_H
+#define __ARCH_ARM_MACH_MSM_CLOCK_VOTER_H
+
+enum {
+ V_EBI_ACPU,
+ V_EBI_DSI,
+ V_EBI_DTV,
+ V_EBI_KGSL,
+ V_EBI_LCDC,
+ V_EBI_MDDI,
+ V_EBI_MDP,
+ V_EBI_PM,
+ V_EBI_TV,
+ V_EBI_USB,
+ V_EBI_VCD,
+ V_EBI_VFE,
+
+ V_NR_CLKS
+};
+
+struct clk_ops;
+extern struct clk_ops clk_ops_voter;
+
+#define CLK_VOTER(clk_name, clk_id, agg_name, clk_dev, clk_flags) { \
+ .name = clk_name, \
+ .id = V_##clk_id, \
+ .flags = clk_flags | CLKFLAG_HANDLE, \
+ .dev = clk_dev, \
+ .aggregator = agg_name, \
+ .dbg_name = clk_name, \
+ .ops = &clk_ops_voter, \
+ }
+
+#endif
diff --git a/arch/arm/mach-msm/clock.h b/arch/arm/mach-msm/clock.h
index 1a9fb72..9278c03 100644
--- a/arch/arm/mach-msm/clock.h
+++ b/arch/arm/mach-msm/clock.h
@@ -25,6 +25,7 @@
#define CLKFLAG_NOINVERT 0x00000002
#define CLKFLAG_NONEST 0x00000004
#define CLKFLAG_NORESET 0x00000008
+#define CLKFLAG_HANDLE 0x00000010
#define CLK_FIRST_AVAILABLE_FLAG 0x00000100
#define CLKFLAG_AUTO_OFF 0x00000200
@@ -58,6 +59,8 @@ struct clk {
const char *dbg_name;
struct list_head list;
struct device *dev;
+ struct hlist_head voters;
+ const char *aggregator;
};
#define OFF CLKFLAG_AUTO_OFF
--
Sent by an employee of the Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum.
^ permalink raw reply related [flat|nested] 23+ messages in thread* [PATCH 17/22] msm: Migrate to clock rate voting
2010-12-17 0:49 [PATCH 00/22] MSM clock driver updates Stephen Boyd
` (15 preceding siblings ...)
2010-12-17 0:50 ` [PATCH 16/22] msm: clock: Implement rate voting Stephen Boyd
@ 2010-12-17 0:50 ` Stephen Boyd
2010-12-17 0:50 ` [PATCH 18/22] msm: clock: Migrate to clkdev Stephen Boyd
` (4 subsequent siblings)
21 siblings, 0 replies; 23+ messages in thread
From: Stephen Boyd @ 2010-12-17 0:50 UTC (permalink / raw)
To: linux-arm-kernel
Add the appropriate clock voters and integrate clock.c with the
voting driver so that voting works appropriately.
Reviewed-by: Saravana Kannan <skannan@codeaurora.org>
Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
---
arch/arm/mach-msm/clock.c | 23 +++++++++++++----------
arch/arm/mach-msm/devices-msm7x30.c | 10 ++++++++++
arch/arm/mach-msm/devices-qsd8x50.c | 9 +++++++++
3 files changed, 32 insertions(+), 10 deletions(-)
diff --git a/arch/arm/mach-msm/clock.c b/arch/arm/mach-msm/clock.c
index b6b7e7c..c505e30 100644
--- a/arch/arm/mach-msm/clock.c
+++ b/arch/arm/mach-msm/clock.c
@@ -18,7 +18,10 @@
#include <linux/list.h>
#include <linux/err.h>
#include <linux/spinlock.h>
-#include <linux/pm_qos_params.h>
+#include <linux/mutex.h>
+#include <linux/clk.h>
+#include <linux/string.h>
+#include <linux/module.h>
#include "clock.h"
@@ -139,16 +142,10 @@ int clk_set_flags(struct clk *clk, unsigned long flags)
}
EXPORT_SYMBOL(clk_set_flags);
-/* EBI1 is the only shared clock that several clients want to vote on as of
- * this commit. If this changes in the future, then it might be better to
- * make clk_min_rate handle the voting or make ebi1_clk_set_min_rate more
- * generic to support different clocks.
- */
-static struct clk *ebi1_clk;
-
void __init msm_clock_init(struct clk *clock_tbl, unsigned num_clocks)
{
unsigned n;
+ struct clk *clk;
/* Do SoC-speficic clock init operations. */
msm_clk_soc_init();
@@ -160,9 +157,15 @@ void __init msm_clock_init(struct clk *clock_tbl, unsigned num_clocks)
}
mutex_unlock(&clocks_mutex);
- ebi1_clk = clk_get(NULL, "ebi1_clk");
- BUG_ON(ebi1_clk == NULL);
+ for (n = 0; n < num_clocks; n++) {
+ clk = &clock_tbl[n];
+ if (clk->flags & CLKFLAG_HANDLE) {
+ struct clk *agg_clk = clk_get(NULL, clk->aggregator);
+ BUG_ON(IS_ERR(agg_clk));
+ clk_set_parent(clk, agg_clk);
+ }
+ }
}
/* The bootloader and/or AMSS may have left various clocks enabled.
diff --git a/arch/arm/mach-msm/devices-msm7x30.c b/arch/arm/mach-msm/devices-msm7x30.c
index 72da7cc..f18d86b 100644
--- a/arch/arm/mach-msm/devices-msm7x30.c
+++ b/arch/arm/mach-msm/devices-msm7x30.c
@@ -23,6 +23,7 @@
#include <mach/board.h>
#include "devices.h"
+#include "clock-voter.h"
#include "smd_private.h"
#include <asm/mach/flash.h>
@@ -156,6 +157,15 @@ struct clk msm_clocks_7x30[] = {
CLK_7X30("vfe_pclk", VFE_P_CLK, NULL, OFF),
CLK_7X30("vpe_clk", VPE_CLK, NULL, 0),
+ CLK_VOTER("ebi1_dtv_clk", EBI_DTV, "pbus_clk", NULL, 0),
+ CLK_VOTER("ebi1_kgsl_clk", EBI_KGSL, "pbus_clk", NULL, 0),
+ CLK_VOTER("ebi1_lcdc_clk", EBI_LCDC, "pbus_clk", NULL, 0),
+ CLK_VOTER("ebi1_mddi_clk", EBI_MDDI, "pbus_clk", NULL, 0),
+ CLK_VOTER("ebi1_tv_clk", EBI_TV, "pbus_clk", NULL, 0),
+ CLK_VOTER("ebi1_usb_clk", EBI_USB, "pbus_clk", NULL, 0),
+ CLK_VOTER("ebi1_vcd_clk", EBI_VCD, "pbus_clk", NULL, 0),
+ CLK_VOTER("ebi1_vfe_clk", EBI_VFE, "pbus_clk", NULL, 0),
+
/* 7x30 v2 hardware only. */
CLK_7X30("csi_clk", CSI0_CLK, NULL, 0),
CLK_7X30("csi_pclk", CSI0_P_CLK, NULL, 0),
diff --git a/arch/arm/mach-msm/devices-qsd8x50.c b/arch/arm/mach-msm/devices-qsd8x50.c
index 271c8bb..3b11d28 100644
--- a/arch/arm/mach-msm/devices-qsd8x50.c
+++ b/arch/arm/mach-msm/devices-qsd8x50.c
@@ -28,6 +28,7 @@
#include <mach/mmc.h>
#include "clock-pcom.h"
+#include "clock-voter.h"
static struct resource resources_uart3[] = {
{
@@ -106,6 +107,14 @@ struct clk msm_clocks_8x50[] = {
CLK_PCOM("usb_hs3_clk", USB_HS3_CLK, NULL, OFF),
CLK_PCOM("usb_hs3_pclk", USB_HS3_P_CLK, NULL, OFF),
CLK_PCOM("usb_phy_clk", USB_PHY_CLK, NULL, 0),
+
+ CLK_VOTER("ebi1_acpu_clk", EBI_ACPU, "ebi1_clk", NULL, 0),
+ CLK_VOTER("ebi1_kgsl_clk", EBI_KGSL, "ebi1_clk", NULL, 0),
+ CLK_VOTER("ebi1_lcdc_clk", EBI_LCDC, "ebi1_clk", NULL, 0),
+ CLK_VOTER("ebi1_mddi_clk", EBI_MDDI, "ebi1_clk", NULL, 0),
+ CLK_VOTER("ebi1_tv_clk", EBI_TV, "ebi1_clk", NULL, 0),
+ CLK_VOTER("ebi1_usb_clk", EBI_USB, "ebi1_clk", NULL, 0),
+ CLK_VOTER("ebi1_vfe_clk", EBI_VFE, "ebi1_clk", NULL, 0),
};
unsigned msm_num_clocks_8x50 = ARRAY_SIZE(msm_clocks_8x50);
--
Sent by an employee of the Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum.
^ permalink raw reply related [flat|nested] 23+ messages in thread* [PATCH 18/22] msm: clock: Migrate to clkdev
2010-12-17 0:49 [PATCH 00/22] MSM clock driver updates Stephen Boyd
` (16 preceding siblings ...)
2010-12-17 0:50 ` [PATCH 17/22] msm: Migrate to clock " Stephen Boyd
@ 2010-12-17 0:50 ` Stephen Boyd
2010-12-17 0:50 ` [PATCH 19/22] msm: iommu: Add bus clocks to platform data Stephen Boyd
` (3 subsequent siblings)
21 siblings, 0 replies; 23+ messages in thread
From: Stephen Boyd @ 2010-12-17 0:50 UTC (permalink / raw)
To: linux-arm-kernel
Migrating to clkdev has several advantages:
* Less code in mach-msm/clock.c
* A more robust clk_get() implementation
* clk_add_alias() support
* clk_get_sys() support
In general, this will help board authors setup clock aliases and
break the dependency on device pointers in the clock tables.
Reviewed-by: Saravana Kannan <skannan@codeaurora.org>
Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
---
arch/arm/Kconfig | 1 +
arch/arm/mach-msm/clock-7x30.h | 43 +++++++++++++++++-------------
arch/arm/mach-msm/clock-8x60.h | 16 ++++++-----
arch/arm/mach-msm/clock-pcom.h | 16 ++++++-----
arch/arm/mach-msm/clock-voter.h | 16 ++++++-----
arch/arm/mach-msm/clock.c | 37 +++++---------------------
arch/arm/mach-msm/clock.h | 2 +-
arch/arm/mach-msm/devices-msm7x00.c | 32 +++++++++++-----------
arch/arm/mach-msm/devices-msm7x30.c | 21 +++++++++------
arch/arm/mach-msm/devices-msm8x60.c | 19 ++++++++------
arch/arm/mach-msm/devices-qsd8x50.c | 5 ++-
arch/arm/mach-msm/devices.h | 8 +++---
arch/arm/mach-msm/include/mach/board.h | 4 ++-
arch/arm/mach-msm/include/mach/clkdev.h | 23 ++++++++++++++++
14 files changed, 133 insertions(+), 110 deletions(-)
create mode 100644 arch/arm/mach-msm/include/mach/clkdev.h
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index a19a526..fe25326 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -598,6 +598,7 @@ config ARCH_MSM
select HAVE_CLK
select GENERIC_CLOCKEVENTS
select ARCH_REQUIRE_GPIOLIB
+ select COMMON_CLKDEV
help
Support for Qualcomm MSM/QSD based systems. This runs on the
apps processor of the MSM/QSD and depends on a shared memory
diff --git a/arch/arm/mach-msm/clock-7x30.h b/arch/arm/mach-msm/clock-7x30.h
index 01c49c7..bece8d1 100644
--- a/arch/arm/mach-msm/clock-7x30.h
+++ b/arch/arm/mach-msm/clock-7x30.h
@@ -154,31 +154,36 @@ extern int internal_pwr_rail_ctl_auto(unsigned rail_id, bool enable);
extern struct clk_ops soc_clk_ops_7x30;
#define CLK_7X30(clk_name, clk_id, clk_dev, clk_flags) { \
- .name = clk_name, \
- .id = L_##clk_id, \
- .remote_id = P_##clk_id, \
- .flags = clk_flags, \
- .dev = clk_dev, \
- .dbg_name = #clk_id, \
+ .con_id = clk_name, \
+ .dev_id = clk_dev, \
+ .clk = &(struct clk){ \
+ .id = L_##clk_id, \
+ .remote_id = P_##clk_id, \
+ .flags = clk_flags, \
+ .dbg_name = #clk_id, \
+ }, \
}
#define CLK_7X30S(clk_name, l_id, r_id, clk_dev, clk_flags) { \
- .name = clk_name, \
- .id = L_##l_id, \
- .remote_id = P_##r_id, \
- .flags = clk_flags, \
- .dev = clk_dev, \
- .dbg_name = #l_id, \
+ .con_id = clk_name, \
+ .dev_id = clk_dev, \
+ .clk = &(struct clk){ \
+ .id = L_##l_id, \
+ .remote_id = P_##r_id, \
+ .flags = clk_flags, \
+ .dbg_name = #l_id, \
+ }, \
}
#define CLK_7X30L(clk_name, l_id, clk_dev, clk_flags) { \
- .name = clk_name, \
- .id = L_##l_id, \
- .flags = clk_flags, \
- .dev = clk_dev, \
- .dbg_name = #l_id, \
- .ops = &soc_clk_ops_7x30, \
+ .con_id = clk_name, \
+ .dev_id = clk_dev, \
+ .clk = &(struct clk){ \
+ .id = L_##l_id, \
+ .flags = clk_flags, \
+ .dbg_name = #l_id, \
+ .ops = &soc_clk_ops_7x30, \
+ }, \
}
#endif
-
diff --git a/arch/arm/mach-msm/clock-8x60.h b/arch/arm/mach-msm/clock-8x60.h
index 2019add..c6e2244 100644
--- a/arch/arm/mach-msm/clock-8x60.h
+++ b/arch/arm/mach-msm/clock-8x60.h
@@ -203,13 +203,15 @@ struct pll_rate {
extern struct clk_ops soc_clk_ops_8x60;
#define CLK_8X60(clk_name, clk_id, clk_dev, clk_flags) { \
- .name = clk_name, \
- .id = L_##clk_id, \
- .remote_id = L_##clk_id, \
- .ops = &soc_clk_ops_8x60, \
- .flags = clk_flags, \
- .dev = clk_dev, \
- .dbg_name = #clk_id, \
+ .con_id = clk_name, \
+ .dev_id = clk_dev, \
+ .clk = &(struct clk){ \
+ .id = L_##clk_id, \
+ .remote_id = L_##clk_id, \
+ .ops = &soc_clk_ops_8x60, \
+ .flags = clk_flags, \
+ .dbg_name = #clk_id, \
+ }, \
}
#endif
diff --git a/arch/arm/mach-msm/clock-pcom.h b/arch/arm/mach-msm/clock-pcom.h
index e2bca82..ef07632 100644
--- a/arch/arm/mach-msm/clock-pcom.h
+++ b/arch/arm/mach-msm/clock-pcom.h
@@ -144,13 +144,15 @@ extern struct clk_ops clk_ops_pcom_div2;
int pc_clk_reset(unsigned id, enum clk_reset_action action);
#define CLK_PCOM(clk_name, clk_id, clk_dev, clk_flags) { \
- .name = clk_name, \
- .id = P_##clk_id, \
- .remote_id = P_##clk_id, \
- .ops = &clk_ops_pcom, \
- .flags = clk_flags, \
- .dev = clk_dev, \
- .dbg_name = #clk_id, \
+ .con_id = clk_name, \
+ .dev_id = clk_dev, \
+ .clk = &(struct clk){ \
+ .id = P_##clk_id, \
+ .remote_id = P_##clk_id, \
+ .ops = &clk_ops_pcom, \
+ .flags = clk_flags, \
+ .dbg_name = #clk_id, \
+ }, \
}
#endif
diff --git a/arch/arm/mach-msm/clock-voter.h b/arch/arm/mach-msm/clock-voter.h
index 84bc0b3..d62e35d 100644
--- a/arch/arm/mach-msm/clock-voter.h
+++ b/arch/arm/mach-msm/clock-voter.h
@@ -40,13 +40,15 @@ struct clk_ops;
extern struct clk_ops clk_ops_voter;
#define CLK_VOTER(clk_name, clk_id, agg_name, clk_dev, clk_flags) { \
- .name = clk_name, \
- .id = V_##clk_id, \
- .flags = clk_flags | CLKFLAG_HANDLE, \
- .dev = clk_dev, \
- .aggregator = agg_name, \
- .dbg_name = clk_name, \
- .ops = &clk_ops_voter, \
+ .con_id = clk_name, \
+ .dev_id = clk_dev, \
+ .clk = &(struct clk){ \
+ .id = V_##clk_id, \
+ .flags = clk_flags | CLKFLAG_HANDLE, \
+ .aggregator = agg_name, \
+ .dbg_name = clk_name, \
+ .ops = &clk_ops_voter, \
+ }, \
}
#endif
diff --git a/arch/arm/mach-msm/clock.c b/arch/arm/mach-msm/clock.c
index c505e30..ca2805a 100644
--- a/arch/arm/mach-msm/clock.c
+++ b/arch/arm/mach-msm/clock.c
@@ -23,6 +23,8 @@
#include <linux/string.h>
#include <linux/module.h>
+#include <asm/clkdev.h>
+
#include "clock.h"
static DEFINE_MUTEX(clocks_mutex);
@@ -31,32 +33,6 @@ static LIST_HEAD(clocks);
/*
* Standard clock functions defined in include/linux/clk.h
*/
-struct clk *clk_get(struct device *dev, const char *id)
-{
- struct clk *clk;
-
- mutex_lock(&clocks_mutex);
-
- list_for_each_entry(clk, &clocks, list)
- if (!strcmp(id, clk->name) && clk->dev == dev)
- goto found_it;
-
- list_for_each_entry(clk, &clocks, list)
- if (!strcmp(id, clk->name) && clk->dev == NULL)
- goto found_it;
-
- clk = ERR_PTR(-ENOENT);
-found_it:
- mutex_unlock(&clocks_mutex);
- return clk;
-}
-EXPORT_SYMBOL(clk_get);
-
-void clk_put(struct clk *clk)
-{
-}
-EXPORT_SYMBOL(clk_put);
-
int clk_enable(struct clk *clk)
{
return clk->ops->enable(clk->id);
@@ -142,7 +118,7 @@ int clk_set_flags(struct clk *clk, unsigned long flags)
}
EXPORT_SYMBOL(clk_set_flags);
-void __init msm_clock_init(struct clk *clock_tbl, unsigned num_clocks)
+void __init msm_clock_init(struct clk_lookup *clock_tbl, unsigned num_clocks)
{
unsigned n;
struct clk *clk;
@@ -152,13 +128,14 @@ void __init msm_clock_init(struct clk *clock_tbl, unsigned num_clocks)
mutex_lock(&clocks_mutex);
for (n = 0; n < num_clocks; n++) {
- msm_clk_soc_set_ops(&clock_tbl[n]);
- list_add_tail(&clock_tbl[n].list, &clocks);
+ msm_clk_soc_set_ops(clock_tbl[n].clk);
+ clkdev_add(&clock_tbl[n]);
+ list_add_tail(&clock_tbl[n].clk->list, &clocks);
}
mutex_unlock(&clocks_mutex);
for (n = 0; n < num_clocks; n++) {
- clk = &clock_tbl[n];
+ clk = clock_tbl[n].clk;
if (clk->flags & CLKFLAG_HANDLE) {
struct clk *agg_clk = clk_get(NULL, clk->aggregator);
BUG_ON(IS_ERR(agg_clk));
diff --git a/arch/arm/mach-msm/clock.h b/arch/arm/mach-msm/clock.h
index 9278c03..c7449a5 100644
--- a/arch/arm/mach-msm/clock.h
+++ b/arch/arm/mach-msm/clock.h
@@ -18,6 +18,7 @@
#define __ARCH_ARM_MACH_MSM_CLOCK_H
#include <linux/init.h>
+#include <linux/types.h>
#include <linux/list.h>
#include <mach/clk.h>
@@ -54,7 +55,6 @@ struct clk {
uint32_t id;
uint32_t remote_id;
uint32_t flags;
- const char *name;
struct clk_ops *ops;
const char *dbg_name;
struct list_head list;
diff --git a/arch/arm/mach-msm/devices-msm7x00.c b/arch/arm/mach-msm/devices-msm7x00.c
index fb548a8..c3f7c06 100644
--- a/arch/arm/mach-msm/devices-msm7x00.c
+++ b/arch/arm/mach-msm/devices-msm7x00.c
@@ -18,13 +18,13 @@
#include <mach/irqs.h>
#include <mach/msm_iomap.h>
+#include <asm/clkdev.h>
#include "devices.h"
#include <asm/mach/flash.h>
#include <linux/mtd/nand.h>
#include <linux/mtd/partitions.h>
-
#include "clock.h"
#include <mach/mmc.h>
@@ -414,7 +414,7 @@ struct platform_device msm_device_mdp = {
.resource = resources_mdp,
};
-struct clk msm_clocks_7x01a[] = {
+struct clk_lookup msm_clocks_7x01a[] = {
CLK_PCOM("adm_clk", ADM_CLK, NULL, 0),
CLK_PCOM("adsp_clk", ADSP_CLK, NULL, 0),
CLK_PCOM("ebi1_clk", EBI1_CLK, NULL, 0),
@@ -423,7 +423,7 @@ struct clk msm_clocks_7x01a[] = {
CLK_PCOM("emdh_clk", EMDH_CLK, NULL, OFF),
CLK_PCOM("gp_clk", GP_CLK, NULL, 0),
CLK_PCOM("grp_clk", GRP_3D_CLK, NULL, OFF),
- CLK_PCOM("i2c_clk", I2C_CLK, &msm_device_i2c.dev, 0),
+ CLK_PCOM("i2c_clk", I2C_CLK, "msm_i2c.0", 0),
CLK_PCOM("icodec_rx_clk", ICODEC_RX_CLK, NULL, 0),
CLK_PCOM("icodec_tx_clk", ICODEC_TX_CLK, NULL, 0),
CLK_PCOM("imem_clk", IMEM_CLK, NULL, OFF),
@@ -433,25 +433,25 @@ struct clk msm_clocks_7x01a[] = {
CLK_PCOM("pcm_clk", PCM_CLK, NULL, 0),
CLK_PCOM("mddi_clk", PMDH_CLK, NULL, OFF | CLK_MINMAX),
CLK_PCOM("sdac_clk", SDAC_CLK, NULL, OFF),
- CLK_PCOM("sdc_clk", SDC1_CLK, &msm_device_sdc1.dev, OFF),
- CLK_PCOM("sdc_pclk", SDC1_P_CLK, &msm_device_sdc1.dev, OFF),
- CLK_PCOM("sdc_clk", SDC2_CLK, &msm_device_sdc2.dev, OFF),
- CLK_PCOM("sdc_pclk", SDC2_P_CLK, &msm_device_sdc2.dev, OFF),
- CLK_PCOM("sdc_clk", SDC3_CLK, &msm_device_sdc3.dev, OFF),
- CLK_PCOM("sdc_pclk", SDC3_P_CLK, &msm_device_sdc3.dev, OFF),
- CLK_PCOM("sdc_clk", SDC4_CLK, &msm_device_sdc4.dev, OFF),
- CLK_PCOM("sdc_pclk", SDC4_P_CLK, &msm_device_sdc4.dev, OFF),
+ CLK_PCOM("sdc_clk", SDC1_CLK, "msm_sdcc.1", OFF),
+ CLK_PCOM("sdc_pclk", SDC1_P_CLK, "msm_sdcc.1", OFF),
+ CLK_PCOM("sdc_clk", SDC2_CLK, "msm_sdcc.2", OFF),
+ CLK_PCOM("sdc_pclk", SDC2_P_CLK, "msm_sdcc.2", OFF),
+ CLK_PCOM("sdc_clk", SDC3_CLK, "msm_sdcc.3", OFF),
+ CLK_PCOM("sdc_pclk", SDC3_P_CLK, "msm_sdcc.3", OFF),
+ CLK_PCOM("sdc_clk", SDC4_CLK, "msm_sdcc.4", OFF),
+ CLK_PCOM("sdc_pclk", SDC4_P_CLK, "msm_sdcc.4", OFF),
CLK_PCOM("tsif_clk", TSIF_CLK, NULL, 0),
CLK_PCOM("tsif_ref_clk", TSIF_REF_CLK, NULL, 0),
CLK_PCOM("tv_dac_clk", TV_DAC_CLK, NULL, 0),
CLK_PCOM("tv_enc_clk", TV_ENC_CLK, NULL, 0),
- CLK_PCOM("uart_clk", UART1_CLK, &msm_device_uart1.dev, OFF),
- CLK_PCOM("uart_clk", UART2_CLK, &msm_device_uart2.dev, 0),
- CLK_PCOM("uart_clk", UART3_CLK, &msm_device_uart3.dev, OFF),
+ CLK_PCOM("uart_clk", UART1_CLK, "msm_serial.0", OFF),
+ CLK_PCOM("uart_clk", UART2_CLK, "msm_serial.1", 0),
+ CLK_PCOM("uart_clk", UART3_CLK, "msm_serial.2", OFF),
CLK_PCOM("uart1dm_clk", UART1DM_CLK, NULL, OFF),
CLK_PCOM("uart2dm_clk", UART2DM_CLK, NULL, 0),
- CLK_PCOM("usb_hs_clk", USB_HS_CLK, &msm_device_hsusb.dev, OFF),
- CLK_PCOM("usb_hs_pclk", USB_HS_P_CLK, &msm_device_hsusb.dev, OFF),
+ CLK_PCOM("usb_hs_clk", USB_HS_CLK, "msm_hsusb", OFF),
+ CLK_PCOM("usb_hs_pclk", USB_HS_P_CLK, "msm_hsusb", OFF),
CLK_PCOM("usb_otg_clk", USB_OTG_CLK, NULL, 0),
CLK_PCOM("vdc_clk", VDC_CLK, NULL, OFF ),
CLK_PCOM("vfe_clk", VFE_CLK, NULL, OFF),
diff --git a/arch/arm/mach-msm/devices-msm7x30.c b/arch/arm/mach-msm/devices-msm7x30.c
index f18d86b..359b427 100644
--- a/arch/arm/mach-msm/devices-msm7x30.c
+++ b/arch/arm/mach-msm/devices-msm7x30.c
@@ -17,10 +17,12 @@
#include <linux/platform_device.h>
#include <linux/dma-mapping.h>
+#include <asm/clkdev.h>
#include <mach/irqs.h>
#include <mach/msm_iomap.h>
#include <mach/dma.h>
#include <mach/board.h>
+#include <asm/clkdev.h>
#include "devices.h"
#include "clock-voter.h"
@@ -58,7 +60,8 @@ struct platform_device msm_device_smd = {
.id = -1,
};
-struct clk msm_clocks_7x30[] = {
+struct clk_lookup msm_clocks_7x30[] = {
+ CLK_PCOM("adm_clk", ADM_CLK, NULL, 0),
CLK_PCOM("adsp_clk", ADSP_CLK, NULL, 0),
CLK_PCOM("cam_m_clk", CAM_M_CLK, NULL, 0),
CLK_PCOM("camif_pad_pclk", CAMIF_PAD_P_CLK, NULL, OFF),
@@ -70,12 +73,14 @@ struct clk msm_clocks_7x30[] = {
CLK_PCOM("usb_phy_clk", USB_PHY_CLK, NULL, 0),
CLK_PCOM("vdc_clk", VDC_CLK, NULL, OFF | CLK_MIN),
{
- .name = "pbus_clk",
- .id = P_PBUS_CLK,
- .remote_id = P_PBUS_CLK,
- .ops = &clk_ops_pcom_div2,
- .flags = CLK_MIN,
- .dbg_name = "pbus_clk",
+ .con_id = "pbus_clk",
+ .clk = &(struct clk){
+ .id = P_PBUS_CLK,
+ .remote_id = P_PBUS_CLK,
+ .ops = &clk_ops_pcom_div2,
+ .flags = CLK_MIN,
+ .dbg_name = "pbus_clk",
+ }
},
CLK_7X30("adm_clk", ADM_CLK, NULL, 0),
@@ -137,7 +142,7 @@ struct clk msm_clocks_7x30[] = {
CLK_7X30("tv_enc_clk", TV_ENC_CLK, NULL, 0),
CLK_7X30S("tv_src_clk", TV_CLK, TV_ENC_CLK, NULL, 0),
CLK_7X30("uart_clk", UART1_CLK, NULL, OFF),
- CLK_7X30("uart_clk", UART2_CLK, &msm_device_uart2.dev, 0),
+ CLK_7X30("uart_clk", UART2_CLK, "msm_serial.1", 0),
CLK_7X30("uartdm_clk", UART1DM_CLK, NULL, OFF),
CLK_7X30L("uartdm_pclk", UART1DM_P_CLK, NULL, 0),
CLK_7X30("uartdm_clk", UART2DM_CLK, NULL, 0),
diff --git a/arch/arm/mach-msm/devices-msm8x60.c b/arch/arm/mach-msm/devices-msm8x60.c
index 1f2b189..8842465 100644
--- a/arch/arm/mach-msm/devices-msm8x60.c
+++ b/arch/arm/mach-msm/devices-msm8x60.c
@@ -18,11 +18,14 @@
#include <linux/kernel.h>
#include <linux/clk.h>
+#include <linux/list.h>
+
+#include <asm/clkdev.h>
#include "clock.h"
#include "clock-8x60.h"
-struct clk msm_clocks_8x60[] = {
+struct clk_lookup msm_clocks_8x60[] = {
CLK_8X60("ce_clk", CE2_CLK, NULL, OFF),
CLK_8X60("gsbi_uart_clk", GSBI1_UART_CLK, NULL, OFF),
CLK_8X60("gsbi_uart_clk", GSBI2_UART_CLK, NULL, OFF),
@@ -167,13 +170,13 @@ struct clk msm_clocks_8x60[] = {
CLK_8X60("i2s_spkr_osr_clk", SPARE_I2S_SPKR_OSR_CLK, NULL, OFF),
CLK_8X60("i2s_spkr_bit_clk", SPARE_I2S_SPKR_BIT_CLK, NULL, OFF),
CLK_8X60("pcm_clk", PCM_CLK, NULL, OFF),
- CLK_8X60("iommu_clk", JPEGD_AXI_CLK, NULL, 0),
- CLK_8X60("iommu_clk", VFE_AXI_CLK, NULL, 0),
- CLK_8X60("iommu_clk", VCODEC_AXI_CLK, NULL, 0),
- CLK_8X60("iommu_clk", VCODEC_AXI_CLK, NULL, 0),
- CLK_8X60("iommu_clk", GFX3D_CLK, NULL, 0),
- CLK_8X60("iommu_clk", GFX2D0_CLK, NULL, 0),
- CLK_8X60("iommu_clk", GFX2D1_CLK, NULL, 0),
+ CLK_8X60("iommu_clk", JPEGD_AXI_CLK, "msm_iommu.0", 0),
+ CLK_8X60("iommu_clk", VFE_AXI_CLK, "msm_iommu.6", 0),
+ CLK_8X60("iommu_clk", VCODEC_AXI_CLK, "msm_iommu.7", 0),
+ CLK_8X60("iommu_clk", VCODEC_AXI_CLK, "msm_iommu.8", 0),
+ CLK_8X60("iommu_clk", GFX3D_CLK, "msm_iommu.9", 0),
+ CLK_8X60("iommu_clk", GFX2D0_CLK, "msm_iommu.10", 0),
+ CLK_8X60("iommu_clk", GFX2D1_CLK, "msm_iommu.11", 0),
};
unsigned msm_num_clocks_8x60 = ARRAY_SIZE(msm_clocks_8x60);
diff --git a/arch/arm/mach-msm/devices-qsd8x50.c b/arch/arm/mach-msm/devices-qsd8x50.c
index 3b11d28..33a9d13 100644
--- a/arch/arm/mach-msm/devices-qsd8x50.c
+++ b/arch/arm/mach-msm/devices-qsd8x50.c
@@ -17,6 +17,7 @@
#include <linux/platform_device.h>
#include <linux/dma-mapping.h>
+#include <asm/clkdev.h>
#include <mach/irqs.h>
#include <mach/msm_iomap.h>
#include <mach/dma.h>
@@ -55,7 +56,7 @@ struct platform_device msm_device_smd = {
.id = -1,
};
-struct clk msm_clocks_8x50[] = {
+struct clk_lookup msm_clocks_8x50[] = {
CLK_PCOM("adm_clk", ADM_CLK, NULL, 0),
CLK_PCOM("ce_clk", CE_CLK, NULL, 0),
CLK_PCOM("ebi1_clk", EBI1_CLK, NULL, CLK_MIN),
@@ -92,7 +93,7 @@ struct clk msm_clocks_8x50[] = {
CLK_PCOM("tv_enc_clk", TV_ENC_CLK, NULL, 0),
CLK_PCOM("uart_clk", UART1_CLK, NULL, OFF),
CLK_PCOM("uart_clk", UART2_CLK, NULL, 0),
- CLK_PCOM("uart_clk", UART3_CLK, &msm_device_uart3.dev, OFF),
+ CLK_PCOM("uart_clk", UART3_CLK, "msm_serial.2", OFF),
CLK_PCOM("uartdm_clk", UART1DM_CLK, NULL, OFF),
CLK_PCOM("uartdm_clk", UART2DM_CLK, NULL, 0),
CLK_PCOM("usb_hs_clk", USB_HS_CLK, NULL, OFF),
diff --git a/arch/arm/mach-msm/devices.h b/arch/arm/mach-msm/devices.h
index 81d2b5d8..72405cf 100644
--- a/arch/arm/mach-msm/devices.h
+++ b/arch/arm/mach-msm/devices.h
@@ -39,16 +39,16 @@ extern struct platform_device msm_device_mddi0;
extern struct platform_device msm_device_mddi1;
extern struct platform_device msm_device_mdp;
-extern struct clk msm_clocks_7x01a[];
+extern struct clk_lookup msm_clocks_7x01a[];
extern unsigned msm_num_clocks_7x01a;
-extern struct clk msm_clocks_7x30[];
+extern struct clk_lookup msm_clocks_7x30[];
extern unsigned msm_num_clocks_7x30;
-extern struct clk msm_clocks_8x50[];
+extern struct clk_lookup msm_clocks_8x50[];
extern unsigned msm_num_clocks_8x50;
-extern struct clk msm_clocks_8x60[];
+extern struct clk_lookup msm_clocks_8x60[];
extern unsigned msm_num_clocks_8x60;
#endif
diff --git a/arch/arm/mach-msm/include/mach/board.h b/arch/arm/mach-msm/include/mach/board.h
index 6abf4a6..8652037 100644
--- a/arch/arm/mach-msm/include/mach/board.h
+++ b/arch/arm/mach-msm/include/mach/board.h
@@ -20,6 +20,8 @@
#include <linux/types.h>
#include <mach/mmc.h>
+#include <asm/clkdev.h>
+
/* platform device data structures */
struct msm_acpu_clock_platform_data
@@ -41,7 +43,7 @@ void __init msm_add_devices(void);
void __init msm_map_common_io(void);
void __init msm_init_irq(void);
void __init msm_init_gpio(void);
-void __init msm_clock_init(struct clk *clock_tbl, unsigned num_clocks);
+void __init msm_clock_init(struct clk_lookup *clock_tbl, unsigned num_clocks);
void __init msm_acpu_clock_init(struct msm_acpu_clock_platform_data *);
int __init msm_add_sdcc(unsigned int controller,
struct msm_mmc_platform_data *plat,
diff --git a/arch/arm/mach-msm/include/mach/clkdev.h b/arch/arm/mach-msm/include/mach/clkdev.h
new file mode 100644
index 0000000..939b329
--- /dev/null
+++ b/arch/arm/mach-msm/include/mach/clkdev.h
@@ -0,0 +1,23 @@
+/*
+ * Copyright (c) 2010, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+#ifndef __ASM_ARCH_MSM_CLKDEV_H
+#define __ASM_ARCH_MSM_CLKDEV_H
+
+static inline int __clk_get(struct clk *clk) { return 1; }
+static inline void __clk_put(struct clk *clk) { }
+#endif
--
Sent by an employee of the Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum.
^ permalink raw reply related [flat|nested] 23+ messages in thread* [PATCH 19/22] msm: iommu: Add bus clocks to platform data
2010-12-17 0:49 [PATCH 00/22] MSM clock driver updates Stephen Boyd
` (17 preceding siblings ...)
2010-12-17 0:50 ` [PATCH 18/22] msm: clock: Migrate to clkdev Stephen Boyd
@ 2010-12-17 0:50 ` Stephen Boyd
2010-12-17 0:50 ` [PATCH 20/22] msm: iommu: Clock control for the IOMMU driver Stephen Boyd
` (2 subsequent siblings)
21 siblings, 0 replies; 23+ messages in thread
From: Stephen Boyd @ 2010-12-17 0:50 UTC (permalink / raw)
To: linux-arm-kernel
From: Stepan Moskovchenko <stepanm@codeaurora.org>
Add the IOMMU bus clock and the IOMMU bus interconnect
clocks to the platform data for an IOMMU device. These
clocks are needed to access the IOMMU registers.
Signed-off-by: Stepan Moskovchenko <stepanm@codeaurora.org>
Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
---
arch/arm/mach-msm/include/mach/iommu.h | 7 ++++++-
1 files changed, 6 insertions(+), 1 deletions(-)
diff --git a/arch/arm/mach-msm/include/mach/iommu.h b/arch/arm/mach-msm/include/mach/iommu.h
index 296c0f1..62f6699 100644
--- a/arch/arm/mach-msm/include/mach/iommu.h
+++ b/arch/arm/mach-msm/include/mach/iommu.h
@@ -19,6 +19,7 @@
#define MSM_IOMMU_H
#include <linux/interrupt.h>
+#include <linux/clk.h>
/* Sharability attributes of MSM IOMMU mappings */
#define MSM_IOMMU_ATTR_NON_SH 0x0
@@ -74,13 +75,17 @@ struct msm_iommu_ctx_dev {
* struct msm_iommu_drvdata - A single IOMMU hardware instance
* @base: IOMMU config port base address (VA)
* @irq: Interrupt number
- *
+ * @clk: The bus clock for this IOMMU hardware instance
+ * @pclk: The clock for the IOMMU bus interconnect
+ *
* A msm_iommu_drvdata holds the global driver data about a single piece
* of an IOMMU hardware instance.
*/
struct msm_iommu_drvdata {
void __iomem *base;
int irq;
+ struct clk *clk;
+ struct clk *pclk;
};
/**
--
Sent by an employee of the Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum.
^ permalink raw reply related [flat|nested] 23+ messages in thread* [PATCH 20/22] msm: iommu: Clock control for the IOMMU driver
2010-12-17 0:49 [PATCH 00/22] MSM clock driver updates Stephen Boyd
` (18 preceding siblings ...)
2010-12-17 0:50 ` [PATCH 19/22] msm: iommu: Add bus clocks to platform data Stephen Boyd
@ 2010-12-17 0:50 ` Stephen Boyd
2010-12-17 0:50 ` [PATCH 21/22] msm: iommu: Rework clock logic and add IOMMU bus clock control Stephen Boyd
2010-12-17 0:50 ` [PATCH 22/22] msm: clock-8x60: Don't keep IOMMU clocks on at boot Stephen Boyd
21 siblings, 0 replies; 23+ messages in thread
From: Stephen Boyd @ 2010-12-17 0:50 UTC (permalink / raw)
To: linux-arm-kernel
From: Stepan Moskovchenko <stepanm@codeaurora.org>
Add clock control to the IOMMU driver. The IOMMU bus clock
(and potentially an AXI clock) need to be on to gain access
to IOMMU registers. Actively control these clocks when
needed instead of leaving them on.
Signed-off-by: Stepan Moskovchenko <stepanm@codeaurora.org>
Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
---
arch/arm/mach-msm/iommu.c | 57 +++++++++++++++++++++++++++++++++++++++++++-
1 files changed, 55 insertions(+), 2 deletions(-)
diff --git a/arch/arm/mach-msm/iommu.c b/arch/arm/mach-msm/iommu.c
index e2d58e4..c6d52ee 100644
--- a/arch/arm/mach-msm/iommu.c
+++ b/arch/arm/mach-msm/iommu.c
@@ -26,6 +26,7 @@
#include <linux/spinlock.h>
#include <linux/slab.h>
#include <linux/iommu.h>
+#include <linux/clk.h>
#include <asm/cacheflush.h>
#include <asm/sizes.h>
@@ -50,6 +51,30 @@ struct msm_priv {
struct list_head list_attached;
};
+static int __enable_clocks(struct msm_iommu_drvdata *drvdata)
+{
+ int ret;
+
+ ret = clk_enable(drvdata->pclk);
+ if (ret)
+ goto fail;
+
+ if (drvdata->clk) {
+ ret = clk_enable(drvdata->clk);
+ if (ret)
+ clk_disable(drvdata->pclk);
+ }
+fail:
+ return ret;
+}
+
+static void __disable_clocks(struct msm_iommu_drvdata *drvdata)
+{
+ if (drvdata->clk)
+ clk_disable(drvdata->clk);
+ clk_disable(drvdata->pclk);
+}
+
static int __flush_iotlb(struct iommu_domain *domain)
{
struct msm_priv *priv = domain->priv;
@@ -77,9 +102,17 @@ static int __flush_iotlb(struct iommu_domain *domain)
BUG();
iommu_drvdata = dev_get_drvdata(ctx_drvdata->pdev->dev.parent);
+ if (!iommu_drvdata)
+ BUG();
+
+ ret = __enable_clocks(iommu_drvdata);
+ if (ret)
+ goto fail;
+
SET_CTX_TLBIALL(iommu_drvdata->base, ctx_drvdata->num, 0);
+ __disable_clocks(iommu_drvdata);
}
-
+fail:
return ret;
}
@@ -265,9 +298,14 @@ static int msm_iommu_attach_dev(struct iommu_domain *domain, struct device *dev)
goto fail;
}
+ ret = __enable_clocks(iommu_drvdata);
+ if (ret)
+ goto fail;
+
__program_context(iommu_drvdata->base, ctx_dev->num,
__pa(priv->pgtable));
+ __disable_clocks(iommu_drvdata);
list_add(&(ctx_drvdata->attached_elm), &priv->list_attached);
ret = __flush_iotlb(domain);
@@ -303,7 +341,12 @@ static void msm_iommu_detach_dev(struct iommu_domain *domain,
if (ret)
goto fail;
+ ret = __enable_clocks(iommu_drvdata);
+ if (ret)
+ goto fail;
+
__reset_context(iommu_drvdata->base, ctx_dev->num);
+ __disable_clocks(iommu_drvdata);
list_del_init(&ctx_drvdata->attached_elm);
fail:
@@ -532,6 +575,10 @@ static phys_addr_t msm_iommu_iova_to_phys(struct iommu_domain *domain,
base = iommu_drvdata->base;
ctx = ctx_drvdata->num;
+ ret = __enable_clocks(iommu_drvdata);
+ if (ret)
+ goto fail;
+
/* Invalidate context TLB */
SET_CTX_TLBIALL(base, ctx, 0);
SET_V2PPR_VA(base, ctx, va >> V2Pxx_VA_SHIFT);
@@ -547,6 +594,7 @@ static phys_addr_t msm_iommu_iova_to_phys(struct iommu_domain *domain,
if (GET_FAULT(base, ctx))
ret = 0;
+ __disable_clocks(iommu_drvdata);
fail:
spin_unlock_irqrestore(&msm_iommu_lock, flags);
return ret;
@@ -590,7 +638,7 @@ irqreturn_t msm_iommu_fault_handler(int irq, void *dev_id)
struct msm_iommu_drvdata *drvdata = dev_id;
void __iomem *base;
unsigned int fsr;
- int ncb, i;
+ int ncb, i, ret;
spin_lock(&msm_iommu_lock);
@@ -604,6 +652,10 @@ irqreturn_t msm_iommu_fault_handler(int irq, void *dev_id)
pr_err("Unexpected IOMMU page fault!\n");
pr_err("base = %08x\n", (unsigned int) base);
+ ret = __enable_clocks(drvdata);
+ if (ret)
+ goto fail;
+
ncb = GET_NCB(base)+1;
for (i = 0; i < ncb; i++) {
fsr = GET_FSR(base, i);
@@ -614,6 +666,7 @@ irqreturn_t msm_iommu_fault_handler(int irq, void *dev_id)
SET_FSR(base, i, 0x4000000F);
}
}
+ __disable_clocks(drvdata);
fail:
spin_unlock(&msm_iommu_lock);
return 0;
--
Sent by an employee of the Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum.
^ permalink raw reply related [flat|nested] 23+ messages in thread* [PATCH 21/22] msm: iommu: Rework clock logic and add IOMMU bus clock control
2010-12-17 0:49 [PATCH 00/22] MSM clock driver updates Stephen Boyd
` (19 preceding siblings ...)
2010-12-17 0:50 ` [PATCH 20/22] msm: iommu: Clock control for the IOMMU driver Stephen Boyd
@ 2010-12-17 0:50 ` Stephen Boyd
2010-12-17 0:50 ` [PATCH 22/22] msm: clock-8x60: Don't keep IOMMU clocks on at boot Stephen Boyd
21 siblings, 0 replies; 23+ messages in thread
From: Stephen Boyd @ 2010-12-17 0:50 UTC (permalink / raw)
To: linux-arm-kernel
From: Stepan Moskovchenko <stepanm@codeaurora.org>
Clean up the clock control code in the probe calls, and add
support for controlling the clock for the IOMMU bus
interconnect. With the (proper) clock driver in place, the
clock control logic in the probe function can be made much
cleaner since it does not have to deal with the placeholder
driver anymore.
Signed-off-by: Stepan Moskovchenko <stepanm@codeaurora.org>
Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
---
arch/arm/mach-msm/devices-msm8x60-iommu.c | 5 -
arch/arm/mach-msm/include/mach/iommu.h | 5 -
arch/arm/mach-msm/iommu_dev.c | 204 +++++++++++++++++------------
3 files changed, 120 insertions(+), 94 deletions(-)
diff --git a/arch/arm/mach-msm/devices-msm8x60-iommu.c b/arch/arm/mach-msm/devices-msm8x60-iommu.c
index f9e7bd3..e12d7e2 100644
--- a/arch/arm/mach-msm/devices-msm8x60-iommu.c
+++ b/arch/arm/mach-msm/devices-msm8x60-iommu.c
@@ -282,7 +282,6 @@ static struct platform_device msm_root_iommu_dev = {
static struct msm_iommu_dev jpegd_iommu = {
.name = "jpegd",
- .clk_rate = -1
};
static struct msm_iommu_dev vpe_iommu = {
@@ -307,7 +306,6 @@ static struct msm_iommu_dev ijpeg_iommu = {
static struct msm_iommu_dev vfe_iommu = {
.name = "vfe",
- .clk_rate = -1
};
static struct msm_iommu_dev vcodec_a_iommu = {
@@ -320,17 +318,14 @@ static struct msm_iommu_dev vcodec_b_iommu = {
static struct msm_iommu_dev gfx3d_iommu = {
.name = "gfx3d",
- .clk_rate = 27000000
};
static struct msm_iommu_dev gfx2d0_iommu = {
.name = "gfx2d0",
- .clk_rate = 27000000
};
static struct msm_iommu_dev gfx2d1_iommu = {
.name = "gfx2d1",
- .clk_rate = 27000000
};
static struct platform_device msm_device_iommu_jpegd = {
diff --git a/arch/arm/mach-msm/include/mach/iommu.h b/arch/arm/mach-msm/include/mach/iommu.h
index 62f6699..10811ba 100644
--- a/arch/arm/mach-msm/include/mach/iommu.h
+++ b/arch/arm/mach-msm/include/mach/iommu.h
@@ -45,14 +45,9 @@
/**
* struct msm_iommu_dev - a single IOMMU hardware instance
* name Human-readable name given to this IOMMU HW instance
- * clk_rate Rate to set for this IOMMU's clock, if applicable to this
- * particular IOMMU. 0 means don't set a rate.
- * -1 means it is an AXI clock with no valid rate
- *
*/
struct msm_iommu_dev {
const char *name;
- int clk_rate;
};
/**
diff --git a/arch/arm/mach-msm/iommu_dev.c b/arch/arm/mach-msm/iommu_dev.c
index b83c73b..7f2b730 100644
--- a/arch/arm/mach-msm/iommu_dev.c
+++ b/arch/arm/mach-msm/iommu_dev.c
@@ -29,6 +29,7 @@
#include <mach/iommu_hw-8xxx.h>
#include <mach/iommu.h>
+#include <mach/clk.h>
struct iommu_ctx_iter_data {
/* input */
@@ -130,117 +131,134 @@ static int msm_iommu_probe(struct platform_device *pdev)
{
struct resource *r, *r2;
struct clk *iommu_clk;
+ struct clk *iommu_pclk;
struct msm_iommu_drvdata *drvdata;
struct msm_iommu_dev *iommu_dev = pdev->dev.platform_data;
void __iomem *regs_base;
resource_size_t len;
- int ret = 0, ncb, nm2v, irq;
+ int ret, ncb, nm2v, irq;
- if (pdev->id != -1) {
- drvdata = kzalloc(sizeof(*drvdata), GFP_KERNEL);
+ if (pdev->id == -1) {
+ msm_iommu_root_dev = pdev;
+ return 0;
+ }
- if (!drvdata) {
- ret = -ENOMEM;
- goto fail;
- }
+ drvdata = kzalloc(sizeof(*drvdata), GFP_KERNEL);
- if (!iommu_dev) {
- ret = -ENODEV;
- goto fail;
- }
+ if (!drvdata) {
+ ret = -ENOMEM;
+ goto fail;
+ }
+
+ if (!iommu_dev) {
+ ret = -ENODEV;
+ goto fail;
+ }
- if (iommu_dev->clk_rate != 0) {
- iommu_clk = clk_get(&pdev->dev, "iommu_clk");
-
- if (IS_ERR(iommu_clk)) {
- ret = -ENODEV;
- goto fail;
- }
-
- if (iommu_dev->clk_rate > 0) {
- ret = clk_set_rate(iommu_clk,
- iommu_dev->clk_rate);
- if (ret) {
- clk_put(iommu_clk);
- goto fail;
- }
- }
-
- ret = clk_enable(iommu_clk);
- if (ret) {
- clk_put(iommu_clk);
- goto fail;
- }
+ iommu_pclk = clk_get(NULL, "smmu_pclk");
+ if (IS_ERR(iommu_pclk)) {
+ ret = -ENODEV;
+ goto fail;
+ }
+
+ ret = clk_enable(iommu_pclk);
+ if (ret)
+ goto fail_enable;
+
+ iommu_clk = clk_get(&pdev->dev, "iommu_clk");
+
+ if (!IS_ERR(iommu_clk)) {
+ if (clk_get_rate(iommu_clk) == 0)
+ clk_set_min_rate(iommu_clk, 1);
+
+ ret = clk_enable(iommu_clk);
+ if (ret) {
clk_put(iommu_clk);
+ goto fail_pclk;
}
+ } else
+ iommu_clk = NULL;
- r = platform_get_resource_byname(pdev, IORESOURCE_MEM,
- "physbase");
- if (!r) {
- ret = -ENODEV;
- goto fail;
- }
+ r = platform_get_resource_byname(pdev, IORESOURCE_MEM, "physbase");
- len = r->end - r->start + 1;
+ if (!r) {
+ ret = -ENODEV;
+ goto fail_clk;
+ }
- r2 = request_mem_region(r->start, len, r->name);
- if (!r2) {
- pr_err("Could not request memory region: "
- "start=%p, len=%d\n", (void *) r->start, len);
- ret = -EBUSY;
- goto fail;
- }
+ len = r->end - r->start + 1;
- regs_base = ioremap(r2->start, len);
+ r2 = request_mem_region(r->start, len, r->name);
+ if (!r2) {
+ pr_err("Could not request memory region: start=%p, len=%d\n",
+ (void *) r->start, len);
+ ret = -EBUSY;
+ goto fail_clk;
+ }
- if (!regs_base) {
- pr_err("Could not ioremap: start=%p, len=%d\n",
- (void *) r2->start, len);
- ret = -EBUSY;
- goto fail_mem;
- }
+ regs_base = ioremap(r2->start, len);
- irq = platform_get_irq_byname(pdev, "secure_irq");
- if (irq < 0) {
- ret = -ENODEV;
- goto fail_io;
- }
+ if (!regs_base) {
+ pr_err("Could not ioremap: start=%p, len=%d\n",
+ (void *) r2->start, len);
+ ret = -EBUSY;
+ goto fail_mem;
+ }
+
+ irq = platform_get_irq_byname(pdev, "secure_irq");
+ if (irq < 0) {
+ ret = -ENODEV;
+ goto fail_io;
+ }
- mb();
+ mb();
- if (GET_IDR(regs_base) == 0) {
- pr_err("Invalid IDR value detected\n");
- ret = -ENODEV;
- goto fail_io;
- }
+ if (GET_IDR(regs_base) == 0) {
+ pr_err("Invalid IDR value detected\n");
+ ret = -ENODEV;
+ goto fail_io;
+ }
- ret = request_irq(irq, msm_iommu_fault_handler, 0,
- "msm_iommu_secure_irpt_handler", drvdata);
- if (ret) {
- pr_err("Request IRQ %d failed with ret=%d\n", irq, ret);
- goto fail_io;
- }
+ ret = request_irq(irq, msm_iommu_fault_handler, 0,
+ "msm_iommu_secure_irpt_handler", drvdata);
+ if (ret) {
+ pr_err("Request IRQ %d failed with ret=%d\n", irq, ret);
+ goto fail_io;
+ }
- msm_iommu_reset(regs_base);
- drvdata->base = regs_base;
- drvdata->irq = irq;
+ msm_iommu_reset(regs_base);
+ drvdata->pclk = iommu_pclk;
+ drvdata->clk = iommu_clk;
+ drvdata->base = regs_base;
+ drvdata->irq = irq;
- nm2v = GET_NM2VCBMT((unsigned long) regs_base);
- ncb = GET_NCB((unsigned long) regs_base);
+ nm2v = GET_NM2VCBMT((unsigned long) regs_base);
+ ncb = GET_NCB((unsigned long) regs_base);
- pr_info("device %s mapped at %p, irq %d with %d ctx banks\n",
+ pr_info("device %s mapped at %p, irq %d with %d ctx banks\n",
iommu_dev->name, regs_base, irq, ncb+1);
- platform_set_drvdata(pdev, drvdata);
- } else
- msm_iommu_root_dev = pdev;
+ platform_set_drvdata(pdev, drvdata);
- return 0;
+ if (iommu_clk)
+ clk_disable(iommu_clk);
+
+ clk_disable(iommu_pclk);
+ return 0;
fail_io:
iounmap(regs_base);
fail_mem:
release_mem_region(r->start, len);
+fail_clk:
+ if (iommu_clk) {
+ clk_disable(iommu_clk);
+ clk_put(iommu_clk);
+ }
+fail_pclk:
+ clk_disable(iommu_pclk);
+fail_enable:
+ clk_put(iommu_pclk);
fail:
kfree(drvdata);
return ret;
@@ -252,7 +270,10 @@ static int msm_iommu_remove(struct platform_device *pdev)
drv = platform_get_drvdata(pdev);
if (drv) {
- memset(drv, 0, sizeof(struct msm_iommu_drvdata));
+ if (drv->clk)
+ clk_put(drv->clk);
+ clk_put(drv->pclk);
+ memset(drv, 0, sizeof(*drv));
kfree(drv);
platform_set_drvdata(pdev, NULL);
}
@@ -264,7 +285,7 @@ static int msm_iommu_ctx_probe(struct platform_device *pdev)
struct msm_iommu_ctx_dev *c = pdev->dev.platform_data;
struct msm_iommu_drvdata *drvdata;
struct msm_iommu_ctx_drvdata *ctx_drvdata = NULL;
- int i, ret = 0;
+ int i, ret;
if (!c || !pdev->dev.parent) {
ret = -EINVAL;
goto fail;
@@ -288,6 +309,18 @@ static int msm_iommu_ctx_probe(struct platform_device *pdev)
INIT_LIST_HEAD(&ctx_drvdata->attached_elm);
platform_set_drvdata(pdev, ctx_drvdata);
+ ret = clk_enable(drvdata->pclk);
+ if (ret)
+ goto fail;
+
+ if (drvdata->clk) {
+ ret = clk_enable(drvdata->clk);
+ if (ret) {
+ clk_disable(drvdata->pclk);
+ goto fail;
+ }
+ }
+
/* Program the M2V tables for this context */
for (i = 0; i < MAX_NUM_MIDS; i++) {
int mid = c->mids[i];
@@ -310,8 +343,11 @@ static int msm_iommu_ctx_probe(struct platform_device *pdev)
SET_NSCFG(drvdata->base, mid, 3);
}
- pr_info("context device %s with bank index %d\n", c->name, c->num);
+ if (drvdata->clk)
+ clk_disable(drvdata->clk);
+ clk_disable(drvdata->pclk);
+ dev_info(&pdev->dev, "context %s using bank %d\n", c->name, c->num);
return 0;
fail:
kfree(ctx_drvdata);
--
Sent by an employee of the Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum.
^ permalink raw reply related [flat|nested] 23+ messages in thread* [PATCH 22/22] msm: clock-8x60: Don't keep IOMMU clocks on at boot
2010-12-17 0:49 [PATCH 00/22] MSM clock driver updates Stephen Boyd
` (20 preceding siblings ...)
2010-12-17 0:50 ` [PATCH 21/22] msm: iommu: Rework clock logic and add IOMMU bus clock control Stephen Boyd
@ 2010-12-17 0:50 ` Stephen Boyd
21 siblings, 0 replies; 23+ messages in thread
From: Stephen Boyd @ 2010-12-17 0:50 UTC (permalink / raw)
To: linux-arm-kernel
Now that the IOMMU driver properly handles its clocks we can stop
keeping the clocks it requires to be on during early boot.
Reviewed-by: Saravana Kannan <skannan@codeaurora.org>
Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
---
arch/arm/mach-msm/clock-8x60.c | 9 ---------
1 files changed, 0 insertions(+), 9 deletions(-)
diff --git a/arch/arm/mach-msm/clock-8x60.c b/arch/arm/mach-msm/clock-8x60.c
index 28017b7..78f33ef 100644
--- a/arch/arm/mach-msm/clock-8x60.c
+++ b/arch/arm/mach-msm/clock-8x60.c
@@ -1851,15 +1851,6 @@ static void reg_init(void)
/* Set the dsi_byte_clk src to the DSI PHY PLL,
* dsi_esc_clk to PXO/2, and the hdmi_app_clk src to PXO */
rmwreg(0x400001, MISC_CC2_REG, 0x424003);
-
- /*
- * Turn on clocks required by the SMMU driver until it properly
- * controls its own clocks.
- */
- local_clk_enable(C(SMMU_P));
- local_clk_enable(C(JPEGD_AXI));
- local_clk_enable(C(VFE_AXI));
- local_clk_enable(C(VCODEC_AXI));
}
/* Local clock driver initialization. */
--
Sent by an employee of the Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum.
^ permalink raw reply related [flat|nested] 23+ messages in thread