aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBrian Swetland <swetland@google.com>2008-09-09 14:04:14 -0400
committerBrian Swetland <swetland@google.com>2008-10-22 05:41:00 -0400
commit600f7cfebeef74a6ba961c507079e3629da5dd7a (patch)
treebac251da969e1e4d2f277793e3ba906b25b7905e
parentbcc0f6af0798e60e7527485f7125ed26632ce698 (diff)
[ARM] msm: clock: provide clk_*() api support for
Makes use of the proc_comm interface to provide clock control on MSM7X01A family SoCs. Signed-off-by: Brian Swetland <swetland@google.com>
-rw-r--r--arch/arm/mach-msm/Makefile1
-rw-r--r--arch/arm/mach-msm/board-halibut.c1
-rw-r--r--arch/arm/mach-msm/clock-7x01a.c126
-rw-r--r--arch/arm/mach-msm/clock.c218
-rw-r--r--arch/arm/mach-msm/clock.h48
-rw-r--r--arch/arm/mach-msm/include/mach/board.h1
6 files changed, 395 insertions, 0 deletions
diff --git a/arch/arm/mach-msm/Makefile b/arch/arm/mach-msm/Makefile
index d4d1deabce46..bfcb2518ba53 100644
--- a/arch/arm/mach-msm/Makefile
+++ b/arch/arm/mach-msm/Makefile
@@ -1,6 +1,7 @@
1obj-y += io.o idle.o irq.o timer.o dma.o 1obj-y += io.o idle.o irq.o timer.o dma.o
2obj-y += devices.o 2obj-y += devices.o
3obj-y += proc_comm.o 3obj-y += proc_comm.o
4obj-y += clock.o clock-7x01a.o
4 5
5obj-$(CONFIG_MACH_HALIBUT) += board-halibut.o 6obj-$(CONFIG_MACH_HALIBUT) += board-halibut.o
6 7
diff --git a/arch/arm/mach-msm/board-halibut.c b/arch/arm/mach-msm/board-halibut.c
index b263783dadb8..c2a96e3965a6 100644
--- a/arch/arm/mach-msm/board-halibut.c
+++ b/arch/arm/mach-msm/board-halibut.c
@@ -79,6 +79,7 @@ static void __init halibut_init(void)
79static void __init halibut_map_io(void) 79static void __init halibut_map_io(void)
80{ 80{
81 msm_map_common_io(); 81 msm_map_common_io();
82 msm_clock_init();
82} 83}
83 84
84MACHINE_START(HALIBUT, "Halibut Board (QCT SURF7200A)") 85MACHINE_START(HALIBUT, "Halibut Board (QCT SURF7200A)")
diff --git a/arch/arm/mach-msm/clock-7x01a.c b/arch/arm/mach-msm/clock-7x01a.c
new file mode 100644
index 000000000000..62230a3428ee
--- /dev/null
+++ b/arch/arm/mach-msm/clock-7x01a.c
@@ -0,0 +1,126 @@
1/* arch/arm/mach-msm/clock-7x01a.c
2 *
3 * Clock tables for MSM7X01A
4 *
5 * Copyright (C) 2007 Google, Inc.
6 * Copyright (c) 2007 QUALCOMM Incorporated
7 *
8 * This software is licensed under the terms of the GNU General Public
9 * License version 2, as published by the Free Software Foundation, and
10 * may be copied, distributed, and modified under those terms.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 */
18
19#include <linux/kernel.h>
20#include <linux/platform_device.h>
21
22#include "clock.h"
23#include "devices.h"
24
25/* clock IDs used by the modem processor */
26
27#define ACPU_CLK 0 /* Applications processor clock */
28#define ADM_CLK 1 /* Applications data mover clock */
29#define ADSP_CLK 2 /* ADSP clock */
30#define EBI1_CLK 3 /* External bus interface 1 clock */
31#define EBI2_CLK 4 /* External bus interface 2 clock */
32#define ECODEC_CLK 5 /* External CODEC clock */
33#define EMDH_CLK 6 /* External MDDI host clock */
34#define GP_CLK 7 /* General purpose clock */
35#define GRP_CLK 8 /* Graphics clock */
36#define I2C_CLK 9 /* I2C clock */
37#define ICODEC_RX_CLK 10 /* Internal CODEX RX clock */
38#define ICODEC_TX_CLK 11 /* Internal CODEX TX clock */
39#define IMEM_CLK 12 /* Internal graphics memory clock */
40#define MDC_CLK 13 /* MDDI client clock */
41#define MDP_CLK 14 /* Mobile display processor clock */
42#define PBUS_CLK 15 /* Peripheral bus clock */
43#define PCM_CLK 16 /* PCM clock */
44#define PMDH_CLK 17 /* Primary MDDI host clock */
45#define SDAC_CLK 18 /* Stereo DAC clock */
46#define SDC1_CLK 19 /* Secure Digital Card clocks */
47#define SDC1_PCLK 20
48#define SDC2_CLK 21
49#define SDC2_PCLK 22
50#define SDC3_CLK 23
51#define SDC3_PCLK 24
52#define SDC4_CLK 25
53#define SDC4_PCLK 26
54#define TSIF_CLK 27 /* Transport Stream Interface clocks */
55#define TSIF_REF_CLK 28
56#define TV_DAC_CLK 29 /* TV clocks */
57#define TV_ENC_CLK 30
58#define UART1_CLK 31 /* UART clocks */
59#define UART2_CLK 32
60#define UART3_CLK 33
61#define UART1DM_CLK 34
62#define UART2DM_CLK 35
63#define USB_HS_CLK 36 /* High speed USB core clock */
64#define USB_HS_PCLK 37 /* High speed USB pbus clock */
65#define USB_OTG_CLK 38 /* Full speed USB clock */
66#define VDC_CLK 39 /* Video controller clock */
67#define VFE_CLK 40 /* Camera / Video Front End clock */
68#define VFE_MDC_CLK 41 /* VFE MDDI client clock */
69
70#define NR_CLKS 42
71
72#define CLOCK(clk_name, clk_id, clk_dev, clk_flags) { \
73 .name = clk_name, \
74 .id = clk_id, \
75 .flags = clk_flags, \
76 .dev = clk_dev, \
77 }
78
79#define OFF CLKFLAG_AUTO_OFF
80#define MINMAX CLKFLAG_USE_MIN_MAX_TO_SET
81
82struct clk msm_clocks[] = {
83 CLOCK("adm_clk", ADM_CLK, NULL, 0),
84 CLOCK("adsp_clk", ADSP_CLK, NULL, 0),
85 CLOCK("ebi1_clk", EBI1_CLK, NULL, 0),
86 CLOCK("ebi2_clk", EBI2_CLK, NULL, 0),
87 CLOCK("ecodec_clk", ECODEC_CLK, NULL, 0),
88 CLOCK("emdh_clk", EMDH_CLK, NULL, OFF),
89 CLOCK("gp_clk", GP_CLK, NULL, 0),
90 CLOCK("grp_clk", GRP_CLK, NULL, OFF),
91 CLOCK("i2c_clk", I2C_CLK, &msm_device_i2c.dev, 0),
92 CLOCK("icodec_rx_clk", ICODEC_RX_CLK, NULL, 0),
93 CLOCK("icodec_tx_clk", ICODEC_TX_CLK, NULL, 0),
94 CLOCK("imem_clk", IMEM_CLK, NULL, OFF),
95 CLOCK("mdc_clk", MDC_CLK, NULL, 0),
96 CLOCK("mdp_clk", MDP_CLK, NULL, OFF),
97 CLOCK("pbus_clk", PBUS_CLK, NULL, 0),
98 CLOCK("pcm_clk", PCM_CLK, NULL, 0),
99 CLOCK("pmdh_clk", PMDH_CLK, NULL, OFF | MINMAX),
100 CLOCK("sdac_clk", SDAC_CLK, NULL, OFF),
101 CLOCK("sdc_clk", SDC1_CLK, &msm_device_sdc1.dev, OFF),
102 CLOCK("sdc_pclk", SDC1_PCLK, &msm_device_sdc1.dev, OFF),
103 CLOCK("sdc_clk", SDC2_CLK, &msm_device_sdc2.dev, OFF),
104 CLOCK("sdc_pclk", SDC2_PCLK, &msm_device_sdc2.dev, OFF),
105 CLOCK("sdc_clk", SDC3_CLK, &msm_device_sdc3.dev, OFF),
106 CLOCK("sdc_pclk", SDC3_PCLK, &msm_device_sdc3.dev, OFF),
107 CLOCK("sdc_clk", SDC4_CLK, &msm_device_sdc4.dev, OFF),
108 CLOCK("sdc_pclk", SDC4_PCLK, &msm_device_sdc4.dev, OFF),
109 CLOCK("tsif_clk", TSIF_CLK, NULL, 0),
110 CLOCK("tsif_ref_clk", TSIF_REF_CLK, NULL, 0),
111 CLOCK("tv_dac_clk", TV_DAC_CLK, NULL, 0),
112 CLOCK("tv_enc_clk", TV_ENC_CLK, NULL, 0),
113 CLOCK("uart_clk", UART1_CLK, &msm_device_uart1.dev, OFF),
114 CLOCK("uart_clk", UART2_CLK, &msm_device_uart2.dev, 0),
115 CLOCK("uart_clk", UART3_CLK, &msm_device_uart3.dev, OFF),
116 CLOCK("uart1dm_clk", UART1DM_CLK, NULL, OFF),
117 CLOCK("uart2dm_clk", UART2DM_CLK, NULL, 0),
118 CLOCK("usb_hs_clk", USB_HS_CLK, &msm_device_hsusb.dev, OFF),
119 CLOCK("usb_hs_pclk", USB_HS_PCLK, &msm_device_hsusb.dev, OFF),
120 CLOCK("usb_otg_clk", USB_OTG_CLK, NULL, 0),
121 CLOCK("vdc_clk", VDC_CLK, NULL, OFF | MINMAX),
122 CLOCK("vfe_clk", VFE_CLK, NULL, OFF),
123 CLOCK("vfe_mdc_clk", VFE_MDC_CLK, NULL, OFF),
124};
125
126unsigned msm_num_clocks = ARRAY_SIZE(msm_clocks);
diff --git a/arch/arm/mach-msm/clock.c b/arch/arm/mach-msm/clock.c
new file mode 100644
index 000000000000..3b1ce36f1032
--- /dev/null
+++ b/arch/arm/mach-msm/clock.c
@@ -0,0 +1,218 @@
1/* arch/arm/mach-msm/clock.c
2 *
3 * Copyright (C) 2007 Google, Inc.
4 * Copyright (c) 2007 QUALCOMM Incorporated
5 *
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
8 * may be copied, distributed, and modified under those terms.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 */
16
17#include <linux/version.h>
18#include <linux/kernel.h>
19#include <linux/init.h>
20#include <linux/module.h>
21#include <linux/list.h>
22#include <linux/err.h>
23#include <linux/clk.h>
24#include <linux/spinlock.h>
25
26#include "clock.h"
27#include "proc_comm.h"
28
29static DEFINE_MUTEX(clocks_mutex);
30static DEFINE_SPINLOCK(clocks_lock);
31static LIST_HEAD(clocks);
32
33/*
34 * glue for the proc_comm interface
35 */
36static inline int pc_clk_enable(unsigned id)
37{
38 return msm_proc_comm(PCOM_CLKCTL_RPC_ENABLE, &id, NULL);
39}
40
41static inline void pc_clk_disable(unsigned id)
42{
43 msm_proc_comm(PCOM_CLKCTL_RPC_DISABLE, &id, NULL);
44}
45
46static inline int pc_clk_set_rate(unsigned id, unsigned rate)
47{
48 return msm_proc_comm(PCOM_CLKCTL_RPC_SET_RATE, &id, &rate);
49}
50
51static inline int pc_clk_set_min_rate(unsigned id, unsigned rate)
52{
53 return msm_proc_comm(PCOM_CLKCTL_RPC_MIN_RATE, &id, &rate);
54}
55
56static inline int pc_clk_set_max_rate(unsigned id, unsigned rate)
57{
58 return msm_proc_comm(PCOM_CLKCTL_RPC_MAX_RATE, &id, &rate);
59}
60
61static inline int pc_clk_set_flags(unsigned id, unsigned flags)
62{
63 return msm_proc_comm(PCOM_CLKCTL_RPC_SET_FLAGS, &id, &flags);
64}
65
66static inline unsigned pc_clk_get_rate(unsigned id)
67{
68 if (msm_proc_comm(PCOM_CLKCTL_RPC_RATE, &id, NULL))
69 return 0;
70 else
71 return id;
72}
73
74static inline unsigned pc_clk_is_enabled(unsigned id)
75{
76 if (msm_proc_comm(PCOM_CLKCTL_RPC_ENABLED, &id, NULL))
77 return 0;
78 else
79 return id;
80}
81
82static inline int pc_pll_request(unsigned id, unsigned on)
83{
84 on = !!on;
85 return msm_proc_comm(PCOM_CLKCTL_RPC_PLL_REQUEST, &id, &on);
86}
87
88/*
89 * Standard clock functions defined in include/linux/clk.h
90 */
91struct clk *clk_get(struct device *dev, const char *id)
92{
93 struct clk *clk;
94
95 mutex_lock(&clocks_mutex);
96
97 list_for_each_entry(clk, &clocks, list)
98 if (!strcmp(id, clk->name) && clk->dev == dev)
99 goto found_it;
100
101 list_for_each_entry(clk, &clocks, list)
102 if (!strcmp(id, clk->name) && clk->dev == NULL)
103 goto found_it;
104
105 clk = ERR_PTR(-ENOENT);
106found_it:
107 mutex_unlock(&clocks_mutex);
108 return clk;
109}
110EXPORT_SYMBOL(clk_get);
111
112void clk_put(struct clk *clk)
113{
114}
115EXPORT_SYMBOL(clk_put);
116
117int clk_enable(struct clk *clk)
118{
119 unsigned long flags;
120 spin_lock_irqsave(&clocks_lock, flags);
121 clk->count++;
122 if (clk->count == 1)
123 pc_clk_enable(clk->id);
124 spin_unlock_irqrestore(&clocks_lock, flags);
125 return 0;
126}
127EXPORT_SYMBOL(clk_enable);
128
129void clk_disable(struct clk *clk)
130{
131 unsigned long flags;
132 spin_lock_irqsave(&clocks_lock, flags);
133 BUG_ON(clk->count == 0);
134 clk->count--;
135 if (clk->count == 0)
136 pc_clk_disable(clk->id);
137 spin_unlock_irqrestore(&clocks_lock, flags);
138}
139EXPORT_SYMBOL(clk_disable);
140
141unsigned long clk_get_rate(struct clk *clk)
142{
143 return pc_clk_get_rate(clk->id);
144}
145EXPORT_SYMBOL(clk_get_rate);
146
147int clk_set_rate(struct clk *clk, unsigned long rate)
148{
149 int ret;
150 if (clk->flags & CLKFLAG_USE_MIN_MAX_TO_SET) {
151 ret = pc_clk_set_max_rate(clk->id, rate);
152 if (ret)
153 return ret;
154 return pc_clk_set_min_rate(clk->id, rate);
155 }
156 return pc_clk_set_rate(clk->id, rate);
157}
158EXPORT_SYMBOL(clk_set_rate);
159
160int clk_set_parent(struct clk *clk, struct clk *parent)
161{
162 return -ENOSYS;
163}
164EXPORT_SYMBOL(clk_set_parent);
165
166struct clk *clk_get_parent(struct clk *clk)
167{
168 return ERR_PTR(-ENOSYS);
169}
170EXPORT_SYMBOL(clk_get_parent);
171
172int clk_set_flags(struct clk *clk, unsigned long flags)
173{
174 if (clk == NULL || IS_ERR(clk))
175 return -EINVAL;
176 return pc_clk_set_flags(clk->id, flags);
177}
178EXPORT_SYMBOL(clk_set_flags);
179
180
181void __init msm_clock_init(void)
182{
183 unsigned n;
184
185 spin_lock_init(&clocks_lock);
186 mutex_lock(&clocks_mutex);
187 for (n = 0; n < msm_num_clocks; n++)
188 list_add_tail(&msm_clocks[n].list, &clocks);
189 mutex_unlock(&clocks_mutex);
190}
191
192/* The bootloader and/or AMSS may have left various clocks enabled.
193 * Disable any clocks that belong to us (CLKFLAG_AUTO_OFF) but have
194 * not been explicitly enabled by a clk_enable() call.
195 */
196static int __init clock_late_init(void)
197{
198 unsigned long flags;
199 struct clk *clk;
200 unsigned count = 0;
201
202 mutex_lock(&clocks_mutex);
203 list_for_each_entry(clk, &clocks, list) {
204 if (clk->flags & CLKFLAG_AUTO_OFF) {
205 spin_lock_irqsave(&clocks_lock, flags);
206 if (!clk->count) {
207 count++;
208 pc_clk_disable(clk->id);
209 }
210 spin_unlock_irqrestore(&clocks_lock, flags);
211 }
212 }
213 mutex_unlock(&clocks_mutex);
214 pr_info("clock_late_init() disabled %d unused clocks\n", count);
215 return 0;
216}
217
218late_initcall(clock_late_init);
diff --git a/arch/arm/mach-msm/clock.h b/arch/arm/mach-msm/clock.h
new file mode 100644
index 000000000000..f875e1544e5f
--- /dev/null
+++ b/arch/arm/mach-msm/clock.h
@@ -0,0 +1,48 @@
1/* arch/arm/mach-msm/clock.h
2 *
3 * Copyright (C) 2007 Google, Inc.
4 * Copyright (c) 2007 QUALCOMM Incorporated
5 *
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
8 * may be copied, distributed, and modified under those terms.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 */
16
17#ifndef __ARCH_ARM_MACH_MSM_CLOCK_H
18#define __ARCH_ARM_MACH_MSM_CLOCK_H
19
20#include <linux/list.h>
21
22#define CLKFLAG_INVERT 0x00000001
23#define CLKFLAG_NOINVERT 0x00000002
24#define CLKFLAG_NONEST 0x00000004
25#define CLKFLAG_NORESET 0x00000008
26
27#define CLK_FIRST_AVAILABLE_FLAG 0x00000100
28#define CLKFLAG_USE_MIN_MAX_TO_SET 0x00000200
29#define CLKFLAG_AUTO_OFF 0x00000400
30
31struct clk {
32 uint32_t id;
33 uint32_t count;
34 uint32_t flags;
35 const char *name;
36 struct list_head list;
37 struct device *dev;
38};
39
40#define A11S_CLK_CNTL_ADDR (MSM_CSR_BASE + 0x100)
41#define A11S_CLK_SEL_ADDR (MSM_CSR_BASE + 0x104)
42#define A11S_VDD_SVS_PLEVEL_ADDR (MSM_CSR_BASE + 0x124)
43
44extern struct clk msm_clocks[];
45extern unsigned msm_num_clocks;
46
47#endif
48
diff --git a/arch/arm/mach-msm/include/mach/board.h b/arch/arm/mach-msm/include/mach/board.h
index a7639493c095..264d62e519f3 100644
--- a/arch/arm/mach-msm/include/mach/board.h
+++ b/arch/arm/mach-msm/include/mach/board.h
@@ -33,5 +33,6 @@ void __init msm_add_devices(void);
33void __init msm_map_common_io(void); 33void __init msm_map_common_io(void);
34void __init msm_init_irq(void); 34void __init msm_init_irq(void);
35void __init msm_init_gpio(void); 35void __init msm_init_gpio(void);
36void __init msm_clock_init(void);
36 37
37#endif 38#endif