blob: c587b43170429cef028aecba47009386f5a507ab [file] [log] [blame]
Matt Wagantall7e0b6c92012-01-20 18:48:05 -08001/* Copyright (c) 2009-2012, Code Aurora Forum. All rights reserved.
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002 *
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) \
Matt Wagantall07c45472012-02-10 23:27:24 -080030 ((BVAL((m_lsb+3), m_lsb, m) | BVAL((n_lsb+3), n_lsb, ~(n))) \
31 * !!(n))
Stephen Boydd10d2642012-01-23 18:09:00 -080032#define MD8(m_lsb, m, n_lsb, n) \
Matt Wagantall07c45472012-02-10 23:27:24 -080033 ((BVAL((m_lsb+7), m_lsb, m) | BVAL((n_lsb+7), n_lsb, ~(n))) \
34 * !!(n))
35#define MD16(m, n) ((BVAL(31, 16, m) | BVAL(15, 0, ~(n))) * !!(n))
Stephen Boydd10d2642012-01-23 18:09:00 -080036
37/* NS Registers */
38#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 -080039 (BVAL(n_msb, n_lsb, ~(n-m) * !!(n)) \
Stephen Boydd10d2642012-01-23 18:09:00 -080040 | (BVAL((mde_lsb+1), mde_lsb, MN_MODE_DUAL_EDGE) * !!(n)) \
41 | BVAL(d_msb, d_lsb, (d-1)) | BVAL(s_msb, s_lsb, s))
42
43#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 -080044 (BVAL(n_msb, n_lsb, ~(n-m) * !!(n))|BVAL(d_msb, d_lsb, (d-1)) \
Stephen Boydd10d2642012-01-23 18:09:00 -080045 | BVAL(s_msb, s_lsb, s))
46
47#define NS_DIVSRC(d_msb, d_lsb, d, s_msb, s_lsb, s) \
48 (BVAL(d_msb, d_lsb, (d-1)) | BVAL(s_msb, s_lsb, s))
49
50#define NS_DIV(d_msb, d_lsb, d) \
51 BVAL(d_msb, d_lsb, (d-1))
52
53#define NS_SRC_SEL(s_msb, s_lsb, s) \
54 BVAL(s_msb, s_lsb, s)
55
56#define NS_MND_BANKED4(n0_lsb, n1_lsb, n, m, s0_lsb, s1_lsb, s) \
Stephen Boydfad06d52012-01-23 18:15:22 -080057 (BVAL((n0_lsb+3), n0_lsb, ~(n-m) * !!(n)) \
58 | BVAL((n1_lsb+3), n1_lsb, ~(n-m) * !!(n)) \
Stephen Boydd10d2642012-01-23 18:09:00 -080059 | BVAL((s0_lsb+2), s0_lsb, s) \
60 | BVAL((s1_lsb+2), s1_lsb, s))
61
62#define NS_MND_BANKED8(n0_lsb, n1_lsb, n, m, s0_lsb, s1_lsb, s) \
Stephen Boydfad06d52012-01-23 18:15:22 -080063 (BVAL((n0_lsb+7), n0_lsb, ~(n-m) * !!(n)) \
64 | BVAL((n1_lsb+7), n1_lsb, ~(n-m) * !!(n)) \
Stephen Boydd10d2642012-01-23 18:09:00 -080065 | BVAL((s0_lsb+2), s0_lsb, s) \
66 | BVAL((s1_lsb+2), s1_lsb, s))
67
68#define NS_DIVSRC_BANKED(d0_msb, d0_lsb, d1_msb, d1_lsb, d, \
69 s0_msb, s0_lsb, s1_msb, s1_lsb, s) \
70 (BVAL(d0_msb, d0_lsb, (d-1)) | BVAL(d1_msb, d1_lsb, (d-1)) \
71 | BVAL(s0_msb, s0_lsb, s) \
72 | BVAL(s1_msb, s1_lsb, s))
73
74/* CC Registers */
75#define CC(mde_lsb, n) (BVAL((mde_lsb+1), mde_lsb, MN_MODE_DUAL_EDGE) * !!(n))
76#define CC_BANKED(mde0_lsb, mde1_lsb, n) \
77 ((BVAL((mde0_lsb+1), mde0_lsb, MN_MODE_DUAL_EDGE) \
78 | BVAL((mde1_lsb+1), mde1_lsb, MN_MODE_DUAL_EDGE)) \
79 * !!(n))
80
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070081/*
82 * Halt/Status Checking Mode Macros
83 */
84#define HALT 0 /* Bit pol: 1 = halted */
85#define NOCHECK 1 /* No bit to check, do nothing */
86#define HALT_VOTED 2 /* Bit pol: 1 = halted; delay on disable */
87#define ENABLE 3 /* Bit pol: 1 = running */
88#define ENABLE_VOTED 4 /* Bit pol: 1 = running; delay on disable */
89#define DELAY 5 /* No bit to check, just delay */
90
91/*
92 * Clock Definition Macros
93 */
94#define DEFINE_CLK_MEASURE(name) \
95 struct clk name = { \
96 .ops = &clk_ops_measure, \
97 .dbg_name = #name, \
98 CLK_INIT(name), \
99 }; \
100
101/*
102 * Generic frequency-definition structs and macros
103 */
104struct clk_freq_tbl {
105 const uint32_t freq_hz;
Matt Wagantall07c45472012-02-10 23:27:24 -0800106 struct clk *const src_clk;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700107 const uint32_t md_val;
108 const uint32_t ns_val;
109 const uint32_t ctl_val;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700110 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 Wagantall07c45472012-02-10 23:27:24 -0800130#define F_RAW(f, sc, m_v, n_v, c_v, 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, \
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700136 .extra_freq_data = e, \
137 }
138#define FREQ_END (UINT_MAX-1)
Matt Wagantalle18bbc82011-10-06 10:07:28 -0700139#define F_END { .freq_hz = FREQ_END }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700140
141/**
142 * struct branch - branch on/off
143 * @ctl_reg: clock control register
144 * @en_mask: ORed with @ctl_reg to enable the clock
Stephen Boyda52d7e32011-11-10 11:59:00 -0800145 * @hwcg_reg: hardware clock gating register
146 * @hwcg_mask: ORed with @hwcg_reg to enable hardware clock gating
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700147 * @halt_reg: halt register
148 * @halt_check: type of halt check to perform
149 * @halt_bit: ANDed with @halt_reg to test for clock halted
150 * @reset_reg: reset register
151 * @reset_mask: ORed with @reset_reg to reset the clock domain
152 */
153struct branch {
154 void __iomem *const ctl_reg;
155 const u32 en_mask;
156
Stephen Boyda52d7e32011-11-10 11:59:00 -0800157 void __iomem *hwcg_reg;
158 u32 hwcg_mask;
159
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700160 void __iomem *const halt_reg;
161 const u16 halt_check;
162 const u16 halt_bit;
163
164 void __iomem *const reset_reg;
165 const u32 reset_mask;
Matt Wagantall7e0b6c92012-01-20 18:48:05 -0800166
167 void __iomem *const retain_reg;
168 const u32 retain_mask;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700169};
170
Stephen Boyda52d7e32011-11-10 11:59:00 -0800171int branch_reset(struct branch *b, enum clk_reset_action action);
Stephen Boyd092fd182011-10-21 15:56:30 -0700172void __branch_clk_enable_reg(const struct branch *clk, const char *name);
173u32 __branch_clk_disable_reg(const struct branch *clk, const char *name);
Stephen Boyda52d7e32011-11-10 11:59:00 -0800174int branch_clk_handoff(struct clk *c);
Matt Wagantall7e0b6c92012-01-20 18:48:05 -0800175int branch_clk_set_flags(struct clk *clk, unsigned flags);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700176
177/*
178 * Generic clock-definition struct and macros
179 */
180struct rcg_clk {
181 bool enabled;
182 void *const ns_reg;
183 void *const md_reg;
184
185 const uint32_t root_en_mask;
186 uint32_t ns_mask;
187 const uint32_t ctl_mask;
Matt Wagantall07c45472012-02-10 23:27:24 -0800188 uint32_t mnd_en_mask;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700189
Stephen Boydc78d9a72011-07-20 00:46:24 -0700190 void *bank_info;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700191 void (*set_rate)(struct rcg_clk *, struct clk_freq_tbl *);
Stephen Boydc78d9a72011-07-20 00:46:24 -0700192
Tianyi Goubaf6d342011-08-30 21:49:02 -0700193 struct clk_freq_tbl *freq_tbl;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700194 struct clk_freq_tbl *current_freq;
195
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700196 struct branch b;
197 struct clk c;
198};
199
200static inline struct rcg_clk *to_rcg_clk(struct clk *clk)
201{
202 return container_of(clk, struct rcg_clk, c);
203}
204
Matt Wagantall84f43fd2011-08-16 23:28:38 -0700205extern struct clk_freq_tbl rcg_dummy_freq;
206
Matt Wagantall0625ea02011-07-13 18:51:56 -0700207int rcg_clk_enable(struct clk *clk);
208void rcg_clk_disable(struct clk *clk);
Matt Wagantall9de3bfb2011-11-03 20:13:12 -0700209int rcg_clk_set_rate(struct clk *clk, unsigned long rate);
Matt Wagantall9de3bfb2011-11-03 20:13:12 -0700210unsigned long rcg_clk_get_rate(struct clk *clk);
Matt Wagantall0625ea02011-07-13 18:51:56 -0700211int rcg_clk_list_rate(struct clk *clk, unsigned n);
212int rcg_clk_is_enabled(struct clk *clk);
Matt Wagantall9de3bfb2011-11-03 20:13:12 -0700213long rcg_clk_round_rate(struct clk *clk, unsigned long rate);
Matt Wagantall0625ea02011-07-13 18:51:56 -0700214struct clk *rcg_clk_get_parent(struct clk *c);
Matt Wagantall271a6cd2011-09-20 16:06:31 -0700215int rcg_clk_handoff(struct clk *c);
Stephen Boyd7bf28142011-12-07 00:30:52 -0800216int rcg_clk_reset(struct clk *clk, enum clk_reset_action action);
Stephen Boyda52d7e32011-11-10 11:59:00 -0800217void rcg_clk_enable_hwcg(struct clk *clk);
218void rcg_clk_disable_hwcg(struct clk *clk);
219int rcg_clk_in_hwcg_mode(struct clk *c);
Matt Wagantall7e0b6c92012-01-20 18:48:05 -0800220int rcg_clk_set_flags(struct clk *clk, unsigned flags);
Matt Wagantall0625ea02011-07-13 18:51:56 -0700221
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700222/**
Stephen Boydb8ad8222011-11-28 12:17:58 -0800223 * struct cdiv_clk - integer divider clock with external source selection
224 * @ns_reg: source select and divider settings register
225 * @ext_mask: bit to set to select an external source
226 * @cur_div: current divider setting (or 0 for external source)
227 * @max_div: maximum divider value supported (must be power of 2)
228 * @div_offset: number of bits to shift divider left by in @ns_reg
229 * @b: branch
230 * @c: clock
231 */
232struct cdiv_clk {
233 void __iomem *const ns_reg;
234 u32 ext_mask;
235
236 unsigned long cur_div;
237 u8 div_offset;
238 u32 max_div;
239
240 struct branch b;
241 struct clk c;
242};
243
244static inline struct cdiv_clk *to_cdiv_clk(struct clk *clk)
245{
246 return container_of(clk, struct cdiv_clk, c);
247}
248
249extern struct clk_ops clk_ops_cdiv;
250
251/**
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700252 * struct fixed_clk - fixed rate clock (used for crystal oscillators)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700253 * @c: clk
254 */
255struct fixed_clk {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700256 struct clk c;
257};
258
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700259/**
260 * struct pll_vote_clk - phase locked loop (HW voteable)
Vikram Mulukutla31680ae2011-11-04 14:23:55 -0700261 * @soft_vote: soft voting variable for multiple PLL software instances
262 * @soft_vote_mask: soft voting mask for multiple PLL software instances
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700263 * @en_reg: enable register
264 * @en_mask: ORed with @en_reg to enable the clock
265 * @status_reg: status register
266 * @parent: clock source
267 * @c: clk
268 */
269struct pll_vote_clk {
Vikram Mulukutla31680ae2011-11-04 14:23:55 -0700270 u32 *soft_vote;
271 const u32 soft_vote_mask;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700272 void __iomem *const en_reg;
273 const u32 en_mask;
274
275 void __iomem *const status_reg;
276
277 struct clk *parent;
278 struct clk c;
279};
280
281extern struct clk_ops clk_ops_pll_vote;
282
283static inline struct pll_vote_clk *to_pll_vote_clk(struct clk *clk)
284{
285 return container_of(clk, struct pll_vote_clk, c);
286}
287
288/**
289 * struct pll_clk - phase locked loop
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700290 * @mode_reg: enable register
291 * @parent: clock source
292 * @c: clk
293 */
294struct pll_clk {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700295 void __iomem *const mode_reg;
296
297 struct clk *parent;
298 struct clk c;
299};
300
301extern struct clk_ops clk_ops_pll;
302
303static inline struct pll_clk *to_pll_clk(struct clk *clk)
304{
305 return container_of(clk, struct pll_clk, c);
306}
307
Vikram Mulukutla489e39e2011-08-31 18:04:05 -0700308int sr_pll_clk_enable(struct clk *clk);
309
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700310/**
311 * struct branch_clk - branch
312 * @enabled: true if clock is on, false otherwise
313 * @b: branch
314 * @parent: clock source
315 * @c: clk
316 *
317 * An on/off switch with a rate derived from the parent.
318 */
319struct branch_clk {
320 bool enabled;
321 struct branch b;
322 struct clk *parent;
323 struct clk c;
324};
325
326static inline struct branch_clk *to_branch_clk(struct clk *clk)
327{
328 return container_of(clk, struct branch_clk, c);
329}
330
331int branch_clk_enable(struct clk *clk);
332void branch_clk_disable(struct clk *clk);
333struct clk *branch_clk_get_parent(struct clk *clk);
334int branch_clk_set_parent(struct clk *clk, struct clk *parent);
335int branch_clk_is_enabled(struct clk *clk);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700336int branch_clk_reset(struct clk *c, enum clk_reset_action action);
Stephen Boyda52d7e32011-11-10 11:59:00 -0800337void branch_clk_enable_hwcg(struct clk *clk);
338void branch_clk_disable_hwcg(struct clk *clk);
339int branch_clk_in_hwcg_mode(struct clk *c);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700340
341/**
342 * struct measure_clk - for rate measurement debug use
343 * @sample_ticks: sample period in reference clock ticks
344 * @multiplier: measurement scale-up factor
345 * @divider: measurement scale-down factor
346 * @c: clk
347*/
348struct measure_clk {
349 u64 sample_ticks;
350 u32 multiplier;
351 u32 divider;
352 struct clk c;
353};
354
355extern struct clk_ops clk_ops_measure;
356
357static inline struct measure_clk *to_measure_clk(struct clk *clk)
358{
359 return container_of(clk, struct measure_clk, c);
360}
361
362/*
363 * Variables from clock-local driver
364 */
365extern spinlock_t local_clock_reg_lock;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700366extern struct fixed_clk gnd_clk;
367
368/*
369 * Local-clock APIs
370 */
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700371bool local_clk_is_local(struct clk *clk);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700372
373/*
Vikram Mulukutla31680ae2011-11-04 14:23:55 -0700374 * PLL vote clock APIs
375 */
376int pll_vote_clk_enable(struct clk *clk);
377void pll_vote_clk_disable(struct clk *clk);
Vikram Mulukutla31680ae2011-11-04 14:23:55 -0700378struct clk *pll_vote_clk_get_parent(struct clk *clk);
379int pll_vote_clk_is_enabled(struct clk *clk);
380
381/*
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700382 * Generic set-rate implementations
383 */
384void set_rate_mnd(struct rcg_clk *clk, struct clk_freq_tbl *nf);
385void set_rate_nop(struct rcg_clk *clk, struct clk_freq_tbl *nf);
386void set_rate_mnd_8(struct rcg_clk *clk, struct clk_freq_tbl *nf);
387void set_rate_mnd_banked(struct rcg_clk *clk, struct clk_freq_tbl *nf);
388void set_rate_div_banked(struct rcg_clk *clk, struct clk_freq_tbl *nf);
389
390#endif /* __ARCH_ARM_MACH_MSM_CLOCK_LOCAL_H */
391