aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorStephen Boyd <sboyd@codeaurora.org>2013-06-17 13:43:19 -0400
committerDavid Brown <davidb@codeaurora.org>2013-06-24 16:08:05 -0400
commit8cc7f5338e729b79194e6c22e3c794faaef974b8 (patch)
treed9fad83dcb3e260ad862907a80431ad70d51883e
parent421faca0b538d1ed5f2065cbbc6bbec38f49a54f (diff)
ARM: msm: Migrate to common clock framework
Move the existing clock code in mach-msm to the common clock framework. We lose our capability to set the rate of and enable a clock through debugfs. This is ok though because the debugfs features are mainly used for testing and development of new clock code. To maintain compatibility with the original MSM clock code we make a wrapper for clk_reset() that calls the struct msm_clk specific reset function. This is necessary for the usb and sdcc devices on MSM until a better suited API is made available. Cc: Saravana Kannan <skannan@codeaurora.org> Acked-by: Mike Turquette <mturquette@linaro.org> Signed-off-by: Stephen Boyd <sboyd@codeaurora.org> Signed-off-by: David Brown <davidb@codeaurora.org>
-rw-r--r--arch/arm/Kconfig2
-rw-r--r--arch/arm/mach-msm/Makefile1
-rw-r--r--arch/arm/mach-msm/clock-debug.c123
-rw-r--r--arch/arm/mach-msm/clock-pcom.c118
-rw-r--r--arch/arm/mach-msm/clock-pcom.h30
-rw-r--r--arch/arm/mach-msm/clock.c146
-rw-r--r--arch/arm/mach-msm/clock.h46
-rw-r--r--arch/arm/mach-msm/devices-msm7x00.c2
-rw-r--r--arch/arm/mach-msm/devices-msm7x30.c2
-rw-r--r--arch/arm/mach-msm/devices-qsd8x50.c2
10 files changed, 108 insertions, 364 deletions
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index d423d58f938d..af88c834a7c2 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -622,8 +622,8 @@ config ARCH_MSM
622 bool "Qualcomm MSM" 622 bool "Qualcomm MSM"
623 select ARCH_REQUIRE_GPIOLIB 623 select ARCH_REQUIRE_GPIOLIB
624 select CLKDEV_LOOKUP 624 select CLKDEV_LOOKUP
625 select COMMON_CLK
625 select GENERIC_CLOCKEVENTS 626 select GENERIC_CLOCKEVENTS
626 select HAVE_CLK
627 help 627 help
628 Support for Qualcomm MSM/QSD based systems. This runs on the 628 Support for Qualcomm MSM/QSD based systems. This runs on the
629 apps processor of the MSM/QSD and depends on a shared memory 629 apps processor of the MSM/QSD and depends on a shared memory
diff --git a/arch/arm/mach-msm/Makefile b/arch/arm/mach-msm/Makefile
index 3dbae7406e0f..700d77b7eb1a 100644
--- a/arch/arm/mach-msm/Makefile
+++ b/arch/arm/mach-msm/Makefile
@@ -1,6 +1,5 @@
1obj-y += io.o timer.o 1obj-y += io.o timer.o
2obj-y += clock.o 2obj-y += clock.o
3obj-$(CONFIG_DEBUG_FS) += clock-debug.o
4 3
5obj-$(CONFIG_MSM_VIC) += irq-vic.o 4obj-$(CONFIG_MSM_VIC) += irq-vic.o
6obj-$(CONFIG_MSM_IOMMU) += devices-iommu.o 5obj-$(CONFIG_MSM_IOMMU) += devices-iommu.o
diff --git a/arch/arm/mach-msm/clock-debug.c b/arch/arm/mach-msm/clock-debug.c
deleted file mode 100644
index c4b34d7d26fb..000000000000
--- a/arch/arm/mach-msm/clock-debug.c
+++ /dev/null
@@ -1,123 +0,0 @@
1/*
2 * Copyright (C) 2007 Google, Inc.
3 * Copyright (c) 2007-2010, Code Aurora Forum. All rights reserved.
4 *
5 * This software is licensed under the terms of the GNU General Public
6 * License version 2, as published by the Free Software Foundation, and
7 * may be copied, distributed, and modified under those terms.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 */
15
16#include <linux/kernel.h>
17#include <linux/module.h>
18#include <linux/ctype.h>
19#include <linux/debugfs.h>
20#include <linux/clk.h>
21#include "clock.h"
22
23static int clock_debug_rate_set(void *data, u64 val)
24{
25 struct clk *clock = data;
26 int ret;
27
28 ret = clk_set_rate(clock, val);
29 if (ret != 0)
30 printk(KERN_ERR "clk_set%s_rate failed (%d)\n",
31 (clock->flags & CLK_MIN) ? "_min" : "", ret);
32 return ret;
33}
34
35static int clock_debug_rate_get(void *data, u64 *val)
36{
37 struct clk *clock = data;
38 *val = clk_get_rate(clock);
39 return 0;
40}
41
42DEFINE_SIMPLE_ATTRIBUTE(clock_rate_fops, clock_debug_rate_get,
43 clock_debug_rate_set, "%llu\n");
44
45static int clock_debug_enable_set(void *data, u64 val)
46{
47 struct clk *clock = data;
48 int rc = 0;
49
50 if (val)
51 rc = clock->ops->enable(clock->id);
52 else
53 clock->ops->disable(clock->id);
54
55 return rc;
56}
57
58static int clock_debug_enable_get(void *data, u64 *val)
59{
60 struct clk *clock = data;
61
62 *val = clock->ops->is_enabled(clock->id);
63
64 return 0;
65}
66
67DEFINE_SIMPLE_ATTRIBUTE(clock_enable_fops, clock_debug_enable_get,
68 clock_debug_enable_set, "%llu\n");
69
70static int clock_debug_local_get(void *data, u64 *val)
71{
72 struct clk *clock = data;
73
74 *val = clock->ops->is_local(clock->id);
75
76 return 0;
77}
78
79DEFINE_SIMPLE_ATTRIBUTE(clock_local_fops, clock_debug_local_get,
80 NULL, "%llu\n");
81
82static struct dentry *debugfs_base;
83
84int __init clock_debug_init(void)
85{
86 debugfs_base = debugfs_create_dir("clk", NULL);
87 if (!debugfs_base)
88 return -ENOMEM;
89 return 0;
90}
91
92int __init clock_debug_add(struct clk *clock)
93{
94 char temp[50], *ptr;
95 struct dentry *clk_dir;
96
97 if (!debugfs_base)
98 return -ENOMEM;
99
100 strncpy(temp, clock->dbg_name, ARRAY_SIZE(temp)-1);
101 for (ptr = temp; *ptr; ptr++)
102 *ptr = tolower(*ptr);
103
104 clk_dir = debugfs_create_dir(temp, debugfs_base);
105 if (!clk_dir)
106 return -ENOMEM;
107
108 if (!debugfs_create_file("rate", S_IRUGO | S_IWUSR, clk_dir,
109 clock, &clock_rate_fops))
110 goto error;
111
112 if (!debugfs_create_file("enable", S_IRUGO | S_IWUSR, clk_dir,
113 clock, &clock_enable_fops))
114 goto error;
115
116 if (!debugfs_create_file("is_local", S_IRUGO, clk_dir, clock,
117 &clock_local_fops))
118 goto error;
119 return 0;
120error:
121 debugfs_remove_recursive(clk_dir);
122 return -ENOMEM;
123}
diff --git a/arch/arm/mach-msm/clock-pcom.c b/arch/arm/mach-msm/clock-pcom.c
index 632173186a69..9a80449518e6 100644
--- a/arch/arm/mach-msm/clock-pcom.c
+++ b/arch/arm/mach-msm/clock-pcom.c
@@ -1,6 +1,6 @@
1/* 1/*
2 * Copyright (C) 2007 Google, Inc. 2 * Copyright (C) 2007 Google, Inc.
3 * Copyright (c) 2007-2010, Code Aurora Forum. All rights reserved. 3 * Copyright (c) 2007-2012, The Linux Foundation. All rights reserved.
4 * 4 *
5 * This software is licensed under the terms of the GNU General Public 5 * This software is licensed under the terms of the GNU General Public
6 * License version 2, as published by the Free Software Foundation, and 6 * License version 2, as published by the Free Software Foundation, and
@@ -13,9 +13,12 @@
13 * 13 *
14 */ 14 */
15 15
16#include <linux/kernel.h>
16#include <linux/err.h> 17#include <linux/err.h>
17#include <linux/platform_device.h> 18#include <linux/platform_device.h>
18#include <linux/module.h> 19#include <linux/module.h>
20#include <linux/clk-provider.h>
21#include <linux/clkdev.h>
19 22
20#include <mach/clk.h> 23#include <mach/clk.h>
21 24
@@ -23,11 +26,20 @@
23#include "clock.h" 26#include "clock.h"
24#include "clock-pcom.h" 27#include "clock-pcom.h"
25 28
26/* 29struct clk_pcom {
27 * glue for the proc_comm interface 30 unsigned id;
28 */ 31 unsigned long flags;
29static int pc_clk_enable(unsigned id) 32 struct msm_clk msm_clk;
33};
34
35static inline struct clk_pcom *to_clk_pcom(struct clk_hw *hw)
30{ 36{
37 return container_of(to_msm_clk(hw), struct clk_pcom, msm_clk);
38}
39
40static int pc_clk_enable(struct clk_hw *hw)
41{
42 unsigned id = to_clk_pcom(hw)->id;
31 int rc = msm_proc_comm(PCOM_CLKCTL_RPC_ENABLE, &id, NULL); 43 int rc = msm_proc_comm(PCOM_CLKCTL_RPC_ENABLE, &id, NULL);
32 if (rc < 0) 44 if (rc < 0)
33 return rc; 45 return rc;
@@ -35,14 +47,16 @@ static int pc_clk_enable(unsigned id)
35 return (int)id < 0 ? -EINVAL : 0; 47 return (int)id < 0 ? -EINVAL : 0;
36} 48}
37 49
38static void pc_clk_disable(unsigned id) 50static void pc_clk_disable(struct clk_hw *hw)
39{ 51{
52 unsigned id = to_clk_pcom(hw)->id;
40 msm_proc_comm(PCOM_CLKCTL_RPC_DISABLE, &id, NULL); 53 msm_proc_comm(PCOM_CLKCTL_RPC_DISABLE, &id, NULL);
41} 54}
42 55
43int pc_clk_reset(unsigned id, enum clk_reset_action action) 56static int pc_clk_reset(struct clk_hw *hw, enum clk_reset_action action)
44{ 57{
45 int rc; 58 int rc;
59 unsigned id = to_clk_pcom(hw)->id;
46 60
47 if (action == CLK_RESET_ASSERT) 61 if (action == CLK_RESET_ASSERT)
48 rc = msm_proc_comm(PCOM_CLKCTL_RPC_RESET_ASSERT, &id, NULL); 62 rc = msm_proc_comm(PCOM_CLKCTL_RPC_RESET_ASSERT, &id, NULL);
@@ -55,83 +69,99 @@ int pc_clk_reset(unsigned id, enum clk_reset_action action)
55 return (int)id < 0 ? -EINVAL : 0; 69 return (int)id < 0 ? -EINVAL : 0;
56} 70}
57 71
58static int pc_clk_set_rate(unsigned id, unsigned rate) 72static int pc_clk_set_rate(struct clk_hw *hw, unsigned long new_rate,
73 unsigned long p_rate)
59{ 74{
60 /* The rate _might_ be rounded off to the nearest KHz value by the 75 struct clk_pcom *p = to_clk_pcom(hw);
76 unsigned id = p->id, rate = new_rate;
77 int rc;
78
79 /*
80 * The rate _might_ be rounded off to the nearest KHz value by the
61 * remote function. So a return value of 0 doesn't necessarily mean 81 * remote function. So a return value of 0 doesn't necessarily mean
62 * that the exact rate was set successfully. 82 * that the exact rate was set successfully.
63 */ 83 */
64 int rc = msm_proc_comm(PCOM_CLKCTL_RPC_SET_RATE, &id, &rate); 84 if (p->flags & CLKFLAG_MIN)
65 if (rc < 0) 85 rc = msm_proc_comm(PCOM_CLKCTL_RPC_MIN_RATE, &id, &rate);
66 return rc;
67 else
68 return (int)id < 0 ? -EINVAL : 0;
69}
70
71static int pc_clk_set_min_rate(unsigned id, unsigned rate)
72{
73 int rc = msm_proc_comm(PCOM_CLKCTL_RPC_MIN_RATE, &id, &rate);
74 if (rc < 0)
75 return rc;
76 else 86 else
77 return (int)id < 0 ? -EINVAL : 0; 87 rc = msm_proc_comm(PCOM_CLKCTL_RPC_SET_RATE, &id, &rate);
78}
79
80static int pc_clk_set_max_rate(unsigned id, unsigned rate)
81{
82 int rc = msm_proc_comm(PCOM_CLKCTL_RPC_MAX_RATE, &id, &rate);
83 if (rc < 0) 88 if (rc < 0)
84 return rc; 89 return rc;
85 else 90 else
86 return (int)id < 0 ? -EINVAL : 0; 91 return (int)id < 0 ? -EINVAL : 0;
87} 92}
88 93
89static unsigned pc_clk_get_rate(unsigned id) 94static unsigned long pc_clk_recalc_rate(struct clk_hw *hw, unsigned long p_rate)
90{ 95{
96 unsigned id = to_clk_pcom(hw)->id;
91 if (msm_proc_comm(PCOM_CLKCTL_RPC_RATE, &id, NULL)) 97 if (msm_proc_comm(PCOM_CLKCTL_RPC_RATE, &id, NULL))
92 return 0; 98 return 0;
93 else 99 else
94 return id; 100 return id;
95} 101}
96 102
97static unsigned pc_clk_is_enabled(unsigned id) 103static int pc_clk_is_enabled(struct clk_hw *hw)
98{ 104{
105 unsigned id = to_clk_pcom(hw)->id;
99 if (msm_proc_comm(PCOM_CLKCTL_RPC_ENABLED, &id, NULL)) 106 if (msm_proc_comm(PCOM_CLKCTL_RPC_ENABLED, &id, NULL))
100 return 0; 107 return 0;
101 else 108 else
102 return id; 109 return id;
103} 110}
104 111
105static long pc_clk_round_rate(unsigned id, unsigned rate) 112static long pc_clk_round_rate(struct clk_hw *hw, unsigned long rate,
113 unsigned long *p_rate)
106{ 114{
107
108 /* Not really supported; pc_clk_set_rate() does rounding on it's own. */ 115 /* Not really supported; pc_clk_set_rate() does rounding on it's own. */
109 return rate; 116 return rate;
110} 117}
111 118
112static bool pc_clk_is_local(unsigned id) 119static struct clk_ops clk_ops_pcom = {
113{
114 return false;
115}
116
117struct clk_ops clk_ops_pcom = {
118 .enable = pc_clk_enable, 120 .enable = pc_clk_enable,
119 .disable = pc_clk_disable, 121 .disable = pc_clk_disable,
120 .auto_off = pc_clk_disable,
121 .reset = pc_clk_reset,
122 .set_rate = pc_clk_set_rate, 122 .set_rate = pc_clk_set_rate,
123 .set_min_rate = pc_clk_set_min_rate, 123 .recalc_rate = pc_clk_recalc_rate,
124 .set_max_rate = pc_clk_set_max_rate,
125 .get_rate = pc_clk_get_rate,
126 .is_enabled = pc_clk_is_enabled, 124 .is_enabled = pc_clk_is_enabled,
127 .round_rate = pc_clk_round_rate, 125 .round_rate = pc_clk_round_rate,
128 .is_local = pc_clk_is_local,
129}; 126};
130 127
131static int msm_clock_pcom_probe(struct platform_device *pdev) 128static int msm_clock_pcom_probe(struct platform_device *pdev)
132{ 129{
133 const struct pcom_clk_pdata *pdata = pdev->dev.platform_data; 130 const struct pcom_clk_pdata *pdata = pdev->dev.platform_data;
134 msm_clock_init(pdata->lookup, pdata->num_lookups); 131 int i, ret;
132
133 for (i = 0; i < pdata->num_lookups; i++) {
134 const struct clk_pcom_desc *desc = &pdata->lookup[i];
135 struct clk *c;
136 struct clk_pcom *p;
137 struct clk_hw *hw;
138 struct clk_init_data init;
139
140 p = devm_kzalloc(&pdev->dev, sizeof(*p), GFP_KERNEL);
141 if (!p)
142 return -ENOMEM;
143
144 p->id = desc->id;
145 p->flags = desc->flags;
146 p->msm_clk.reset = pc_clk_reset;
147
148 hw = &p->msm_clk.hw;
149 hw->init = &init;
150
151 init.name = desc->name;
152 init.ops = &clk_ops_pcom;
153 init.num_parents = 0;
154 init.flags = CLK_IS_ROOT;
155
156 if (!(p->flags & CLKFLAG_AUTO_OFF))
157 init.flags |= CLK_IGNORE_UNUSED;
158
159 c = devm_clk_register(&pdev->dev, hw);
160 ret = clk_register_clkdev(c, desc->con, desc->dev);
161 if (ret)
162 return ret;
163 }
164
135 return 0; 165 return 0;
136} 166}
137 167
diff --git a/arch/arm/mach-msm/clock-pcom.h b/arch/arm/mach-msm/clock-pcom.h
index 87406a373d2b..5bb164fd46a8 100644
--- a/arch/arm/mach-msm/clock-pcom.h
+++ b/arch/arm/mach-msm/clock-pcom.h
@@ -1,4 +1,5 @@
1/* Copyright (c) 2009, Code Aurora Forum. All rights reserved. 1/*
2 * Copyright (c) 2009-2012, The Linux Foundation. All rights reserved.
2 * 3 *
3 * This program is free software; you can redistribute it and/or modify 4 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License version 2 and 5 * it under the terms of the GNU General Public License version 2 and
@@ -120,26 +121,25 @@
120 121
121#define P_NR_CLKS 102 122#define P_NR_CLKS 102
122 123
123struct clk_ops; 124struct clk_pcom_desc {
124extern struct clk_ops clk_ops_pcom; 125 unsigned id;
126 const char *name;
127 const char *con;
128 const char *dev;
129 unsigned long flags;
130};
125 131
126struct pcom_clk_pdata { 132struct pcom_clk_pdata {
127 struct clk_lookup *lookup; 133 struct clk_pcom_desc *lookup;
128 u32 num_lookups; 134 u32 num_lookups;
129}; 135};
130 136
131int pc_clk_reset(unsigned id, enum clk_reset_action action);
132
133#define CLK_PCOM(clk_name, clk_id, clk_dev, clk_flags) { \ 137#define CLK_PCOM(clk_name, clk_id, clk_dev, clk_flags) { \
134 .con_id = clk_name, \ 138 .id = P_##clk_id, \
135 .dev_id = clk_dev, \ 139 .name = #clk_id, \
136 .clk = &(struct clk){ \ 140 .con = clk_name, \
137 .id = P_##clk_id, \ 141 .dev = clk_dev, \
138 .remote_id = P_##clk_id, \ 142 .flags = clk_flags, \
139 .ops = &clk_ops_pcom, \
140 .flags = clk_flags, \
141 .dbg_name = #clk_id, \
142 }, \
143 } 143 }
144 144
145#endif 145#endif
diff --git a/arch/arm/mach-msm/clock.c b/arch/arm/mach-msm/clock.c
index d72dd3770298..35ea02b52483 100644
--- a/arch/arm/mach-msm/clock.c
+++ b/arch/arm/mach-msm/clock.c
@@ -1,7 +1,7 @@
1/* arch/arm/mach-msm/clock.c 1/* arch/arm/mach-msm/clock.c
2 * 2 *
3 * Copyright (C) 2007 Google, Inc. 3 * Copyright (C) 2007 Google, Inc.
4 * Copyright (c) 2007-2010, Code Aurora Forum. All rights reserved. 4 * Copyright (c) 2007-2012, The Linux Foundation. All rights reserved.
5 * 5 *
6 * This software is licensed under the terms of the GNU General Public 6 * This software is licensed under the terms of the GNU General Public
7 * License version 2, as published by the Free Software Foundation, and 7 * License version 2, as published by the Free Software Foundation, and
@@ -14,151 +14,15 @@
14 * 14 *
15 */ 15 */
16 16
17#include <linux/kernel.h> 17#include <linux/clk-provider.h>
18#include <linux/list.h>
19#include <linux/err.h>
20#include <linux/spinlock.h>
21#include <linux/pm_qos.h>
22#include <linux/mutex.h>
23#include <linux/clk.h>
24#include <linux/string.h>
25#include <linux/module.h> 18#include <linux/module.h>
26#include <linux/clkdev.h>
27 19
28#include "clock.h" 20#include "clock.h"
29 21
30static DEFINE_MUTEX(clocks_mutex);
31static DEFINE_SPINLOCK(clocks_lock);
32static LIST_HEAD(clocks);
33
34/*
35 * Standard clock functions defined in include/linux/clk.h
36 */
37int clk_enable(struct clk *clk)
38{
39 unsigned long flags;
40 spin_lock_irqsave(&clocks_lock, flags);
41 clk->count++;
42 if (clk->count == 1)
43 clk->ops->enable(clk->id);
44 spin_unlock_irqrestore(&clocks_lock, flags);
45 return 0;
46}
47EXPORT_SYMBOL(clk_enable);
48
49void clk_disable(struct clk *clk)
50{
51 unsigned long flags;
52 spin_lock_irqsave(&clocks_lock, flags);
53 BUG_ON(clk->count == 0);
54 clk->count--;
55 if (clk->count == 0)
56 clk->ops->disable(clk->id);
57 spin_unlock_irqrestore(&clocks_lock, flags);
58}
59EXPORT_SYMBOL(clk_disable);
60
61int clk_reset(struct clk *clk, enum clk_reset_action action) 22int clk_reset(struct clk *clk, enum clk_reset_action action)
62{ 23{
63 return clk->ops->reset(clk->remote_id, action); 24 struct clk_hw *hw = __clk_get_hw(clk);
25 struct msm_clk *m = to_msm_clk(hw);
26 return m->reset(hw, action);
64} 27}
65EXPORT_SYMBOL(clk_reset); 28EXPORT_SYMBOL(clk_reset);
66
67unsigned long clk_get_rate(struct clk *clk)
68{
69 return clk->ops->get_rate(clk->id);
70}
71EXPORT_SYMBOL(clk_get_rate);
72
73int clk_set_rate(struct clk *clk, unsigned long rate)
74{
75 int ret;
76 if (clk->flags & CLKFLAG_MAX) {
77 ret = clk->ops->set_max_rate(clk->id, rate);
78 if (ret)
79 return ret;
80 }
81 if (clk->flags & CLKFLAG_MIN) {
82 ret = clk->ops->set_min_rate(clk->id, rate);
83 if (ret)
84 return ret;
85 }
86
87 if (clk->flags & CLKFLAG_MAX || clk->flags & CLKFLAG_MIN)
88 return ret;
89
90 return clk->ops->set_rate(clk->id, rate);
91}
92EXPORT_SYMBOL(clk_set_rate);
93
94long clk_round_rate(struct clk *clk, unsigned long rate)
95{
96 return clk->ops->round_rate(clk->id, rate);
97}
98EXPORT_SYMBOL(clk_round_rate);
99
100int clk_set_parent(struct clk *clk, struct clk *parent)
101{
102 return -ENOSYS;
103}
104EXPORT_SYMBOL(clk_set_parent);
105
106struct clk *clk_get_parent(struct clk *clk)
107{
108 return ERR_PTR(-ENOSYS);
109}
110EXPORT_SYMBOL(clk_get_parent);
111
112/* EBI1 is the only shared clock that several clients want to vote on as of
113 * this commit. If this changes in the future, then it might be better to
114 * make clk_min_rate handle the voting or make ebi1_clk_set_min_rate more
115 * generic to support different clocks.
116 */
117static struct clk *ebi1_clk;
118
119void msm_clock_init(struct clk_lookup *clock_tbl, size_t num_clocks)
120{
121 unsigned n;
122
123 mutex_lock(&clocks_mutex);
124 for (n = 0; n < num_clocks; n++) {
125 clkdev_add(&clock_tbl[n]);
126 list_add_tail(&clock_tbl[n].clk->list, &clocks);
127 }
128 mutex_unlock(&clocks_mutex);
129
130 ebi1_clk = clk_get(NULL, "ebi1_clk");
131 BUG_ON(ebi1_clk == NULL);
132
133}
134
135/* The bootloader and/or AMSS may have left various clocks enabled.
136 * Disable any clocks that belong to us (CLKFLAG_AUTO_OFF) but have
137 * not been explicitly enabled by a clk_enable() call.
138 */
139static int __init clock_late_init(void)
140{
141 unsigned long flags;
142 struct clk *clk;
143 unsigned count = 0;
144
145 clock_debug_init();
146 mutex_lock(&clocks_mutex);
147 list_for_each_entry(clk, &clocks, list) {
148 clock_debug_add(clk);
149 if (clk->flags & CLKFLAG_AUTO_OFF) {
150 spin_lock_irqsave(&clocks_lock, flags);
151 if (!clk->count) {
152 count++;
153 clk->ops->auto_off(clk->id);
154 }
155 spin_unlock_irqrestore(&clocks_lock, flags);
156 }
157 }
158 mutex_unlock(&clocks_mutex);
159 pr_info("clock_late_init() disabled %d unused clocks\n", count);
160 return 0;
161}
162
163late_initcall(clock_late_init);
164
diff --git a/arch/arm/mach-msm/clock.h b/arch/arm/mach-msm/clock.h
index cc76bfe9ba46..42d29dd7aafc 100644
--- a/arch/arm/mach-msm/clock.h
+++ b/arch/arm/mach-msm/clock.h
@@ -1,7 +1,7 @@
1/* arch/arm/mach-msm/clock.h 1/* arch/arm/mach-msm/clock.h
2 * 2 *
3 * Copyright (C) 2007 Google, Inc. 3 * Copyright (C) 2007 Google, Inc.
4 * Copyright (c) 2007-2010, Code Aurora Forum. All rights reserved. 4 * Copyright (c) 2007-2012, The Linux Foundation. All rights reserved.
5 * 5 *
6 * This software is licensed under the terms of the GNU General Public 6 * This software is licensed under the terms of the GNU General Public
7 * License version 2, as published by the Free Software Foundation, and 7 * License version 2, as published by the Free Software Foundation, and
@@ -17,8 +17,7 @@
17#ifndef __ARCH_ARM_MACH_MSM_CLOCK_H 17#ifndef __ARCH_ARM_MACH_MSM_CLOCK_H
18#define __ARCH_ARM_MACH_MSM_CLOCK_H 18#define __ARCH_ARM_MACH_MSM_CLOCK_H
19 19
20#include <linux/init.h> 20#include <linux/clk-provider.h>
21#include <linux/list.h>
22#include <mach/clk.h> 21#include <mach/clk.h>
23 22
24#define CLK_FIRST_AVAILABLE_FLAG 0x00000100 23#define CLK_FIRST_AVAILABLE_FLAG 0x00000100
@@ -26,44 +25,19 @@
26#define CLKFLAG_MIN 0x00000400 25#define CLKFLAG_MIN 0x00000400
27#define CLKFLAG_MAX 0x00000800 26#define CLKFLAG_MAX 0x00000800
28 27
29struct clk_ops {
30 int (*enable)(unsigned id);
31 void (*disable)(unsigned id);
32 void (*auto_off)(unsigned id);
33 int (*reset)(unsigned id, enum clk_reset_action action);
34 int (*set_rate)(unsigned id, unsigned rate);
35 int (*set_min_rate)(unsigned id, unsigned rate);
36 int (*set_max_rate)(unsigned id, unsigned rate);
37 unsigned (*get_rate)(unsigned id);
38 unsigned (*is_enabled)(unsigned id);
39 long (*round_rate)(unsigned id, unsigned rate);
40 bool (*is_local)(unsigned id);
41};
42
43struct clk {
44 uint32_t id;
45 uint32_t remote_id;
46 uint32_t count;
47 uint32_t flags;
48 struct clk_ops *ops;
49 const char *dbg_name;
50 struct list_head list;
51};
52
53#define OFF CLKFLAG_AUTO_OFF 28#define OFF CLKFLAG_AUTO_OFF
54#define CLK_MIN CLKFLAG_MIN 29#define CLK_MIN CLKFLAG_MIN
55#define CLK_MAX CLKFLAG_MAX 30#define CLK_MAX CLKFLAG_MAX
56#define CLK_MINMAX (CLK_MIN | CLK_MAX) 31#define CLK_MINMAX (CLK_MIN | CLK_MAX)
57 32
58#ifdef CONFIG_DEBUG_FS 33struct msm_clk {
59int __init clock_debug_init(void); 34 int (*reset)(struct clk_hw *hw, enum clk_reset_action action);
60int __init clock_debug_add(struct clk *clock); 35 struct clk_hw hw;
61#else 36};
62static inline int __init clock_debug_init(void) { return 0; }
63static inline int __init clock_debug_add(struct clk *clock) { return 0; }
64#endif
65 37
66struct clk_lookup; 38static inline struct msm_clk *to_msm_clk(struct clk_hw *hw)
67void msm_clock_init(struct clk_lookup *clock_tbl, size_t num_clocks); 39{
40 return container_of(hw, struct msm_clk, hw);
41}
68 42
69#endif 43#endif
diff --git a/arch/arm/mach-msm/devices-msm7x00.c b/arch/arm/mach-msm/devices-msm7x00.c
index 9edfe68e9fe9..6d50fb964863 100644
--- a/arch/arm/mach-msm/devices-msm7x00.c
+++ b/arch/arm/mach-msm/devices-msm7x00.c
@@ -425,7 +425,7 @@ struct platform_device msm_device_mdp = {
425 .resource = resources_mdp, 425 .resource = resources_mdp,
426}; 426};
427 427
428static struct clk_lookup msm_clocks_7x01a[] = { 428static struct clk_pcom_desc msm_clocks_7x01a[] = {
429 CLK_PCOM("adm_clk", ADM_CLK, NULL, 0), 429 CLK_PCOM("adm_clk", ADM_CLK, NULL, 0),
430 CLK_PCOM("adsp_clk", ADSP_CLK, NULL, 0), 430 CLK_PCOM("adsp_clk", ADSP_CLK, NULL, 0),
431 CLK_PCOM("ebi1_clk", EBI1_CLK, NULL, 0), 431 CLK_PCOM("ebi1_clk", EBI1_CLK, NULL, 0),
diff --git a/arch/arm/mach-msm/devices-msm7x30.c b/arch/arm/mach-msm/devices-msm7x30.c
index 6444f0e618f6..d4db75acff56 100644
--- a/arch/arm/mach-msm/devices-msm7x30.c
+++ b/arch/arm/mach-msm/devices-msm7x30.c
@@ -161,7 +161,7 @@ struct platform_device msm_device_hsusb_host = {
161 }, 161 },
162}; 162};
163 163
164static struct clk_lookup msm_clocks_7x30[] = { 164static struct clk_pcom_desc msm_clocks_7x30[] = {
165 CLK_PCOM("adm_clk", ADM_CLK, NULL, 0), 165 CLK_PCOM("adm_clk", ADM_CLK, NULL, 0),
166 CLK_PCOM("adsp_clk", ADSP_CLK, NULL, 0), 166 CLK_PCOM("adsp_clk", ADSP_CLK, NULL, 0),
167 CLK_PCOM("cam_m_clk", CAM_M_CLK, NULL, 0), 167 CLK_PCOM("cam_m_clk", CAM_M_CLK, NULL, 0),
diff --git a/arch/arm/mach-msm/devices-qsd8x50.c b/arch/arm/mach-msm/devices-qsd8x50.c
index caa9a1f0bcbd..f5518112284b 100644
--- a/arch/arm/mach-msm/devices-qsd8x50.c
+++ b/arch/arm/mach-msm/devices-qsd8x50.c
@@ -323,7 +323,7 @@ int __init msm_add_sdcc(unsigned int controller,
323 return platform_device_register(pdev); 323 return platform_device_register(pdev);
324} 324}
325 325
326static struct clk_lookup msm_clocks_8x50[] = { 326static struct clk_pcom_desc msm_clocks_8x50[] = {
327 CLK_PCOM("adm_clk", ADM_CLK, NULL, 0), 327 CLK_PCOM("adm_clk", ADM_CLK, NULL, 0),
328 CLK_PCOM("ce_clk", CE_CLK, NULL, 0), 328 CLK_PCOM("ce_clk", CE_CLK, NULL, 0),
329 CLK_PCOM("ebi1_clk", EBI1_CLK, NULL, CLK_MIN), 329 CLK_PCOM("ebi1_clk", EBI1_CLK, NULL, CLK_MIN),