diff options
Diffstat (limited to 'arch/arm')
-rw-r--r-- | arch/arm/mach-msm/Makefile | 1 | ||||
-rw-r--r-- | arch/arm/mach-msm/board-halibut.c | 1 | ||||
-rw-r--r-- | arch/arm/mach-msm/clock-7x01a.c | 126 | ||||
-rw-r--r-- | arch/arm/mach-msm/clock.c | 218 | ||||
-rw-r--r-- | arch/arm/mach-msm/clock.h | 48 | ||||
-rw-r--r-- | arch/arm/mach-msm/include/mach/board.h | 1 |
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 @@ | |||
1 | obj-y += io.o idle.o irq.o timer.o dma.o | 1 | obj-y += io.o idle.o irq.o timer.o dma.o |
2 | obj-y += devices.o | 2 | obj-y += devices.o |
3 | obj-y += proc_comm.o | 3 | obj-y += proc_comm.o |
4 | obj-y += clock.o clock-7x01a.o | ||
4 | 5 | ||
5 | obj-$(CONFIG_MACH_HALIBUT) += board-halibut.o | 6 | obj-$(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) | |||
79 | static void __init halibut_map_io(void) | 79 | static 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 | ||
84 | MACHINE_START(HALIBUT, "Halibut Board (QCT SURF7200A)") | 85 | MACHINE_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 | |||
82 | struct 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 | |||
126 | unsigned 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 | |||
29 | static DEFINE_MUTEX(clocks_mutex); | ||
30 | static DEFINE_SPINLOCK(clocks_lock); | ||
31 | static LIST_HEAD(clocks); | ||
32 | |||
33 | /* | ||
34 | * glue for the proc_comm interface | ||
35 | */ | ||
36 | static inline int pc_clk_enable(unsigned id) | ||
37 | { | ||
38 | return msm_proc_comm(PCOM_CLKCTL_RPC_ENABLE, &id, NULL); | ||
39 | } | ||
40 | |||
41 | static inline void pc_clk_disable(unsigned id) | ||
42 | { | ||
43 | msm_proc_comm(PCOM_CLKCTL_RPC_DISABLE, &id, NULL); | ||
44 | } | ||
45 | |||
46 | static 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 | |||
51 | static 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 | |||
56 | static 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 | |||
61 | static 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 | |||
66 | static 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 | |||
74 | static 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 | |||
82 | static 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 | */ | ||
91 | struct 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); | ||
106 | found_it: | ||
107 | mutex_unlock(&clocks_mutex); | ||
108 | return clk; | ||
109 | } | ||
110 | EXPORT_SYMBOL(clk_get); | ||
111 | |||
112 | void clk_put(struct clk *clk) | ||
113 | { | ||
114 | } | ||
115 | EXPORT_SYMBOL(clk_put); | ||
116 | |||
117 | int 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 | } | ||
127 | EXPORT_SYMBOL(clk_enable); | ||
128 | |||
129 | void 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 | } | ||
139 | EXPORT_SYMBOL(clk_disable); | ||
140 | |||
141 | unsigned long clk_get_rate(struct clk *clk) | ||
142 | { | ||
143 | return pc_clk_get_rate(clk->id); | ||
144 | } | ||
145 | EXPORT_SYMBOL(clk_get_rate); | ||
146 | |||
147 | int 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 | } | ||
158 | EXPORT_SYMBOL(clk_set_rate); | ||
159 | |||
160 | int clk_set_parent(struct clk *clk, struct clk *parent) | ||
161 | { | ||
162 | return -ENOSYS; | ||
163 | } | ||
164 | EXPORT_SYMBOL(clk_set_parent); | ||
165 | |||
166 | struct clk *clk_get_parent(struct clk *clk) | ||
167 | { | ||
168 | return ERR_PTR(-ENOSYS); | ||
169 | } | ||
170 | EXPORT_SYMBOL(clk_get_parent); | ||
171 | |||
172 | int 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 | } | ||
178 | EXPORT_SYMBOL(clk_set_flags); | ||
179 | |||
180 | |||
181 | void __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 | */ | ||
196 | static 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 | |||
218 | late_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 | |||
31 | struct 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 | |||
44 | extern struct clk msm_clocks[]; | ||
45 | extern 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); | |||
33 | void __init msm_map_common_io(void); | 33 | void __init msm_map_common_io(void); |
34 | void __init msm_init_irq(void); | 34 | void __init msm_init_irq(void); |
35 | void __init msm_init_gpio(void); | 35 | void __init msm_init_gpio(void); |
36 | void __init msm_clock_init(void); | ||
36 | 37 | ||
37 | #endif | 38 | #endif |