blob: 9292e5d2faff1a056a55624876efb7af04b6fa01 [file] [log] [blame]
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001/* Copyright (c) 2009-2011, Code Aurora Forum. All rights reserved.
2 *
3 * 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 * only version 2 as published by the Free Software Foundation.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 *
12 */
13
14#ifndef __ARCH_ARM_MACH_MSM_CLOCK_LOCAL_H
15#define __ARCH_ARM_MACH_MSM_CLOCK_LOCAL_H
16
17#include <linux/spinlock.h>
18#include "clock.h"
19
20/*
21 * Bit manipulation macros
22 */
23#define BM(msb, lsb) (((((uint32_t)-1) << (31-msb)) >> (31-msb+lsb)) << lsb)
24#define BVAL(msb, lsb, val) (((val) << lsb) & BM(msb, lsb))
25
Stephen Boydd10d2642012-01-23 18:09:00 -080026#define MN_MODE_DUAL_EDGE 0x2
27
28/* MD Registers */
29#define MD4(m_lsb, m, n_lsb, n) \
30 (BVAL((m_lsb+3), m_lsb, m) | BVAL((n_lsb+3), n_lsb, ~(n)))
31#define MD8(m_lsb, m, n_lsb, n) \
32 (BVAL((m_lsb+7), m_lsb, m) | BVAL((n_lsb+7), n_lsb, ~(n)))
33#define MD16(m, n) (BVAL(31, 16, m) | BVAL(15, 0, ~(n)))
34
35/* NS Registers */
36#define NS(n_msb, n_lsb, n, m, mde_lsb, d_msb, d_lsb, d, s_msb, s_lsb, s) \
Stephen Boydfad06d52012-01-23 18:15:22 -080037 (BVAL(n_msb, n_lsb, ~(n-m) * !!(n)) \
Stephen Boydd10d2642012-01-23 18:09:00 -080038 | (BVAL((mde_lsb+1), mde_lsb, MN_MODE_DUAL_EDGE) * !!(n)) \
39 | BVAL(d_msb, d_lsb, (d-1)) | BVAL(s_msb, s_lsb, s))
40
41#define NS_MM(n_msb, n_lsb, n, m, d_msb, d_lsb, d, s_msb, s_lsb, s) \
Stephen Boydfad06d52012-01-23 18:15:22 -080042 (BVAL(n_msb, n_lsb, ~(n-m) * !!(n))|BVAL(d_msb, d_lsb, (d-1)) \
Stephen Boydd10d2642012-01-23 18:09:00 -080043 | BVAL(s_msb, s_lsb, s))
44
45#define NS_DIVSRC(d_msb, d_lsb, d, s_msb, s_lsb, s) \
46 (BVAL(d_msb, d_lsb, (d-1)) | BVAL(s_msb, s_lsb, s))
47
48#define NS_DIV(d_msb, d_lsb, d) \
49 BVAL(d_msb, d_lsb, (d-1))
50
51#define NS_SRC_SEL(s_msb, s_lsb, s) \
52 BVAL(s_msb, s_lsb, s)
53
54#define NS_MND_BANKED4(n0_lsb, n1_lsb, n, m, s0_lsb, s1_lsb, s) \
Stephen Boydfad06d52012-01-23 18:15:22 -080055 (BVAL((n0_lsb+3), n0_lsb, ~(n-m) * !!(n)) \
56 | BVAL((n1_lsb+3), n1_lsb, ~(n-m) * !!(n)) \
Stephen Boydd10d2642012-01-23 18:09:00 -080057 | BVAL((s0_lsb+2), s0_lsb, s) \
58 | BVAL((s1_lsb+2), s1_lsb, s))
59
60#define NS_MND_BANKED8(n0_lsb, n1_lsb, n, m, s0_lsb, s1_lsb, s) \
Stephen Boydfad06d52012-01-23 18:15:22 -080061 (BVAL((n0_lsb+7), n0_lsb, ~(n-m) * !!(n)) \
62 | BVAL((n1_lsb+7), n1_lsb, ~(n-m) * !!(n)) \
Stephen Boydd10d2642012-01-23 18:09:00 -080063 | BVAL((s0_lsb+2), s0_lsb, s) \
64 | BVAL((s1_lsb+2), s1_lsb, s))
65
66#define NS_DIVSRC_BANKED(d0_msb, d0_lsb, d1_msb, d1_lsb, d, \
67 s0_msb, s0_lsb, s1_msb, s1_lsb, s) \
68 (BVAL(d0_msb, d0_lsb, (d-1)) | BVAL(d1_msb, d1_lsb, (d-1)) \
69 | BVAL(s0_msb, s0_lsb, s) \
70 | BVAL(s1_msb, s1_lsb, s))
71
72/* CC Registers */
73#define CC(mde_lsb, n) (BVAL((mde_lsb+1), mde_lsb, MN_MODE_DUAL_EDGE) * !!(n))
74#define CC_BANKED(mde0_lsb, mde1_lsb, n) \
75 ((BVAL((mde0_lsb+1), mde0_lsb, MN_MODE_DUAL_EDGE) \
76 | BVAL((mde1_lsb+1), mde1_lsb, MN_MODE_DUAL_EDGE)) \
77 * !!(n))
78
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070079/*
80 * Halt/Status Checking Mode Macros
81 */
82#define HALT 0 /* Bit pol: 1 = halted */
83#define NOCHECK 1 /* No bit to check, do nothing */
84#define HALT_VOTED 2 /* Bit pol: 1 = halted; delay on disable */
85#define ENABLE 3 /* Bit pol: 1 = running */
86#define ENABLE_VOTED 4 /* Bit pol: 1 = running; delay on disable */
87#define DELAY 5 /* No bit to check, just delay */
88
89/*
90 * Clock Definition Macros
91 */
92#define DEFINE_CLK_MEASURE(name) \
93 struct clk name = { \
94 .ops = &clk_ops_measure, \
95 .dbg_name = #name, \
96 CLK_INIT(name), \
97 }; \
98
99/*
100 * Generic frequency-definition structs and macros
101 */
102struct clk_freq_tbl {
103 const uint32_t freq_hz;
104 struct clk *src_clk;
105 const uint32_t md_val;
106 const uint32_t ns_val;
107 const uint32_t ctl_val;
108 uint32_t mnd_en_mask;
109 const unsigned sys_vdd;
110 void *const extra_freq_data;
111};
112
113/* Some clocks have two banks to avoid glitches when switching frequencies.
114 * The unused bank is programmed while running on the other bank, and
115 * switched to afterwards. The following two structs describe the banks. */
116struct bank_mask_info {
117 void *const md_reg;
118 const uint32_t ns_mask;
119 const uint32_t rst_mask;
120 const uint32_t mnd_en_mask;
121 const uint32_t mode_mask;
122};
123
124struct bank_masks {
125 const uint32_t bank_sel_mask;
126 const struct bank_mask_info bank0_mask;
127 const struct bank_mask_info bank1_mask;
128};
129
Matt Wagantalle18bbc82011-10-06 10:07:28 -0700130#define F_RAW(f, sc, m_v, n_v, c_v, m_m, e) { \
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700131 .freq_hz = f, \
132 .src_clk = sc, \
133 .md_val = m_v, \
134 .ns_val = n_v, \
135 .ctl_val = c_v, \
136 .mnd_en_mask = m_m, \
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700137 .extra_freq_data = e, \
138 }
139#define FREQ_END (UINT_MAX-1)
Matt Wagantalle18bbc82011-10-06 10:07:28 -0700140#define F_END { .freq_hz = FREQ_END }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700141
142/**
143 * struct branch - branch on/off
144 * @ctl_reg: clock control register
145 * @en_mask: ORed with @ctl_reg to enable the clock
Stephen Boyda52d7e32011-11-10 11:59:00 -0800146 * @hwcg_reg: hardware clock gating register
147 * @hwcg_mask: ORed with @hwcg_reg to enable hardware clock gating
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700148 * @halt_reg: halt register
149 * @halt_check: type of halt check to perform
150 * @halt_bit: ANDed with @halt_reg to test for clock halted
151 * @reset_reg: reset register
152 * @reset_mask: ORed with @reset_reg to reset the clock domain
153 */
154struct branch {
155 void __iomem *const ctl_reg;
156 const u32 en_mask;
157
Stephen Boyda52d7e32011-11-10 11:59:00 -0800158 void __iomem *hwcg_reg;
159 u32 hwcg_mask;
160
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700161 void __iomem *const halt_reg;
162 const u16 halt_check;
163 const u16 halt_bit;
164
165 void __iomem *const reset_reg;
166 const u32 reset_mask;
167};
168
Stephen Boyda52d7e32011-11-10 11:59:00 -0800169int branch_reset(struct branch *b, enum clk_reset_action action);
Stephen Boyd092fd182011-10-21 15:56:30 -0700170void __branch_clk_enable_reg(const struct branch *clk, const char *name);
171u32 __branch_clk_disable_reg(const struct branch *clk, const char *name);
Stephen Boyda52d7e32011-11-10 11:59:00 -0800172int branch_clk_handoff(struct clk *c);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700173
174/*
175 * Generic clock-definition struct and macros
176 */
177struct rcg_clk {
178 bool enabled;
179 void *const ns_reg;
180 void *const md_reg;
181
182 const uint32_t root_en_mask;
183 uint32_t ns_mask;
184 const uint32_t ctl_mask;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700185
Stephen Boydc78d9a72011-07-20 00:46:24 -0700186 void *bank_info;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700187 void (*set_rate)(struct rcg_clk *, struct clk_freq_tbl *);
Stephen Boydc78d9a72011-07-20 00:46:24 -0700188
Tianyi Goubaf6d342011-08-30 21:49:02 -0700189 struct clk_freq_tbl *freq_tbl;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700190 struct clk_freq_tbl *current_freq;
191
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700192 struct branch b;
193 struct clk c;
194};
195
196static inline struct rcg_clk *to_rcg_clk(struct clk *clk)
197{
198 return container_of(clk, struct rcg_clk, c);
199}
200
Matt Wagantall84f43fd2011-08-16 23:28:38 -0700201extern struct clk_freq_tbl rcg_dummy_freq;
202
Matt Wagantall0625ea02011-07-13 18:51:56 -0700203int rcg_clk_enable(struct clk *clk);
204void rcg_clk_disable(struct clk *clk);
Matt Wagantall9de3bfb2011-11-03 20:13:12 -0700205int rcg_clk_set_rate(struct clk *clk, unsigned long rate);
Matt Wagantall9de3bfb2011-11-03 20:13:12 -0700206unsigned long rcg_clk_get_rate(struct clk *clk);
Matt Wagantall0625ea02011-07-13 18:51:56 -0700207int rcg_clk_list_rate(struct clk *clk, unsigned n);
208int rcg_clk_is_enabled(struct clk *clk);
Matt Wagantall9de3bfb2011-11-03 20:13:12 -0700209long rcg_clk_round_rate(struct clk *clk, unsigned long rate);
Matt Wagantall0625ea02011-07-13 18:51:56 -0700210struct clk *rcg_clk_get_parent(struct clk *c);
Matt Wagantall271a6cd2011-09-20 16:06:31 -0700211int rcg_clk_handoff(struct clk *c);
Stephen Boyd7bf28142011-12-07 00:30:52 -0800212int rcg_clk_reset(struct clk *clk, enum clk_reset_action action);
Stephen Boyda52d7e32011-11-10 11:59:00 -0800213void rcg_clk_enable_hwcg(struct clk *clk);
214void rcg_clk_disable_hwcg(struct clk *clk);
215int rcg_clk_in_hwcg_mode(struct clk *c);
Matt Wagantall0625ea02011-07-13 18:51:56 -0700216
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700217/**
Stephen Boydb8ad8222011-11-28 12:17:58 -0800218 * struct cdiv_clk - integer divider clock with external source selection
219 * @ns_reg: source select and divider settings register
220 * @ext_mask: bit to set to select an external source
221 * @cur_div: current divider setting (or 0 for external source)
222 * @max_div: maximum divider value supported (must be power of 2)
223 * @div_offset: number of bits to shift divider left by in @ns_reg
224 * @b: branch
225 * @c: clock
226 */
227struct cdiv_clk {
228 void __iomem *const ns_reg;
229 u32 ext_mask;
230
231 unsigned long cur_div;
232 u8 div_offset;
233 u32 max_div;
234
235 struct branch b;
236 struct clk c;
237};
238
239static inline struct cdiv_clk *to_cdiv_clk(struct clk *clk)
240{
241 return container_of(clk, struct cdiv_clk, c);
242}
243
244extern struct clk_ops clk_ops_cdiv;
245
246/**
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700247 * struct fixed_clk - fixed rate clock (used for crystal oscillators)
248 * @rate: output rate
249 * @c: clk
250 */
251struct fixed_clk {
252 unsigned long rate;
253 struct clk c;
254};
255
256static inline struct fixed_clk *to_fixed_clk(struct clk *clk)
257{
258 return container_of(clk, struct fixed_clk, c);
259}
260
Matt Wagantall9de3bfb2011-11-03 20:13:12 -0700261static inline unsigned long fixed_clk_get_rate(struct clk *clk)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700262{
263 struct fixed_clk *f = to_fixed_clk(clk);
264 return f->rate;
265}
266
267
268/**
269 * struct pll_vote_clk - phase locked loop (HW voteable)
270 * @rate: output rate
Vikram Mulukutla31680ae2011-11-04 14:23:55 -0700271 * @soft_vote: soft voting variable for multiple PLL software instances
272 * @soft_vote_mask: soft voting mask for multiple PLL software instances
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700273 * @en_reg: enable register
274 * @en_mask: ORed with @en_reg to enable the clock
275 * @status_reg: status register
276 * @parent: clock source
277 * @c: clk
278 */
279struct pll_vote_clk {
280 unsigned long rate;
281
Vikram Mulukutla31680ae2011-11-04 14:23:55 -0700282 u32 *soft_vote;
283 const u32 soft_vote_mask;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700284 void __iomem *const en_reg;
285 const u32 en_mask;
286
287 void __iomem *const status_reg;
288
289 struct clk *parent;
290 struct clk c;
291};
292
293extern struct clk_ops clk_ops_pll_vote;
294
295static inline struct pll_vote_clk *to_pll_vote_clk(struct clk *clk)
296{
297 return container_of(clk, struct pll_vote_clk, c);
298}
299
300/**
301 * struct pll_clk - phase locked loop
302 * @rate: output rate
303 * @mode_reg: enable register
304 * @parent: clock source
305 * @c: clk
306 */
307struct pll_clk {
308 unsigned long rate;
309
310 void __iomem *const mode_reg;
311
312 struct clk *parent;
313 struct clk c;
314};
315
316extern struct clk_ops clk_ops_pll;
317
318static inline struct pll_clk *to_pll_clk(struct clk *clk)
319{
320 return container_of(clk, struct pll_clk, c);
321}
322
Vikram Mulukutla489e39e2011-08-31 18:04:05 -0700323int sr_pll_clk_enable(struct clk *clk);
324
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700325/**
326 * struct branch_clk - branch
327 * @enabled: true if clock is on, false otherwise
328 * @b: branch
329 * @parent: clock source
330 * @c: clk
331 *
332 * An on/off switch with a rate derived from the parent.
333 */
334struct branch_clk {
335 bool enabled;
336 struct branch b;
337 struct clk *parent;
338 struct clk c;
339};
340
341static inline struct branch_clk *to_branch_clk(struct clk *clk)
342{
343 return container_of(clk, struct branch_clk, c);
344}
345
346int branch_clk_enable(struct clk *clk);
347void branch_clk_disable(struct clk *clk);
348struct clk *branch_clk_get_parent(struct clk *clk);
349int branch_clk_set_parent(struct clk *clk, struct clk *parent);
350int branch_clk_is_enabled(struct clk *clk);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700351int branch_clk_reset(struct clk *c, enum clk_reset_action action);
Stephen Boyda52d7e32011-11-10 11:59:00 -0800352void branch_clk_enable_hwcg(struct clk *clk);
353void branch_clk_disable_hwcg(struct clk *clk);
354int branch_clk_in_hwcg_mode(struct clk *c);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700355
356/**
357 * struct measure_clk - for rate measurement debug use
358 * @sample_ticks: sample period in reference clock ticks
359 * @multiplier: measurement scale-up factor
360 * @divider: measurement scale-down factor
361 * @c: clk
362*/
363struct measure_clk {
364 u64 sample_ticks;
365 u32 multiplier;
366 u32 divider;
367 struct clk c;
368};
369
370extern struct clk_ops clk_ops_measure;
371
372static inline struct measure_clk *to_measure_clk(struct clk *clk)
373{
374 return container_of(clk, struct measure_clk, c);
375}
376
377/*
378 * Variables from clock-local driver
379 */
380extern spinlock_t local_clock_reg_lock;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700381extern struct fixed_clk gnd_clk;
382
383/*
384 * Local-clock APIs
385 */
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700386bool local_clk_is_local(struct clk *clk);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700387
388/*
Vikram Mulukutla31680ae2011-11-04 14:23:55 -0700389 * PLL vote clock APIs
390 */
391int pll_vote_clk_enable(struct clk *clk);
392void pll_vote_clk_disable(struct clk *clk);
393unsigned long pll_vote_clk_get_rate(struct clk *clk);
394struct clk *pll_vote_clk_get_parent(struct clk *clk);
395int pll_vote_clk_is_enabled(struct clk *clk);
396
397/*
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700398 * Generic set-rate implementations
399 */
400void set_rate_mnd(struct rcg_clk *clk, struct clk_freq_tbl *nf);
401void set_rate_nop(struct rcg_clk *clk, struct clk_freq_tbl *nf);
402void set_rate_mnd_8(struct rcg_clk *clk, struct clk_freq_tbl *nf);
403void set_rate_mnd_banked(struct rcg_clk *clk, struct clk_freq_tbl *nf);
404void set_rate_div_banked(struct rcg_clk *clk, struct clk_freq_tbl *nf);
405
406#endif /* __ARCH_ARM_MACH_MSM_CLOCK_LOCAL_H */
407