blob: 88bbaf3ebdfe113692fc69829178e79818e20478 [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
Stephen Boydd10d2642012-01-23 18:09:00 -080020#define MN_MODE_DUAL_EDGE 0x2
21
22/* MD Registers */
23#define MD4(m_lsb, m, n_lsb, n) \
Matt Wagantall07c45472012-02-10 23:27:24 -080024 ((BVAL((m_lsb+3), m_lsb, m) | BVAL((n_lsb+3), n_lsb, ~(n))) \
25 * !!(n))
Stephen Boydd10d2642012-01-23 18:09:00 -080026#define MD8(m_lsb, m, n_lsb, n) \
Matt Wagantall07c45472012-02-10 23:27:24 -080027 ((BVAL((m_lsb+7), m_lsb, m) | BVAL((n_lsb+7), n_lsb, ~(n))) \
28 * !!(n))
29#define MD16(m, n) ((BVAL(31, 16, m) | BVAL(15, 0, ~(n))) * !!(n))
Stephen Boydd10d2642012-01-23 18:09:00 -080030
31/* NS Registers */
32#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 -080033 (BVAL(n_msb, n_lsb, ~(n-m) * !!(n)) \
Stephen Boydd10d2642012-01-23 18:09:00 -080034 | (BVAL((mde_lsb+1), mde_lsb, MN_MODE_DUAL_EDGE) * !!(n)) \
35 | BVAL(d_msb, d_lsb, (d-1)) | BVAL(s_msb, s_lsb, s))
36
37#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 -080038 (BVAL(n_msb, n_lsb, ~(n-m) * !!(n))|BVAL(d_msb, d_lsb, (d-1)) \
Stephen Boydd10d2642012-01-23 18:09:00 -080039 | BVAL(s_msb, s_lsb, s))
40
41#define NS_DIVSRC(d_msb, d_lsb, d, s_msb, s_lsb, s) \
42 (BVAL(d_msb, d_lsb, (d-1)) | BVAL(s_msb, s_lsb, s))
43
44#define NS_DIV(d_msb, d_lsb, d) \
45 BVAL(d_msb, d_lsb, (d-1))
46
47#define NS_SRC_SEL(s_msb, s_lsb, s) \
48 BVAL(s_msb, s_lsb, s)
49
50#define NS_MND_BANKED4(n0_lsb, n1_lsb, n, m, s0_lsb, s1_lsb, s) \
Stephen Boydfad06d52012-01-23 18:15:22 -080051 (BVAL((n0_lsb+3), n0_lsb, ~(n-m) * !!(n)) \
52 | BVAL((n1_lsb+3), n1_lsb, ~(n-m) * !!(n)) \
Stephen Boydd10d2642012-01-23 18:09:00 -080053 | BVAL((s0_lsb+2), s0_lsb, s) \
54 | BVAL((s1_lsb+2), s1_lsb, s))
55
56#define NS_MND_BANKED8(n0_lsb, n1_lsb, n, m, s0_lsb, s1_lsb, s) \
Stephen Boydfad06d52012-01-23 18:15:22 -080057 (BVAL((n0_lsb+7), n0_lsb, ~(n-m) * !!(n)) \
58 | BVAL((n1_lsb+7), 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_DIVSRC_BANKED(d0_msb, d0_lsb, d1_msb, d1_lsb, d, \
63 s0_msb, s0_lsb, s1_msb, s1_lsb, s) \
64 (BVAL(d0_msb, d0_lsb, (d-1)) | BVAL(d1_msb, d1_lsb, (d-1)) \
65 | BVAL(s0_msb, s0_lsb, s) \
66 | BVAL(s1_msb, s1_lsb, s))
67
68/* CC Registers */
69#define CC(mde_lsb, n) (BVAL((mde_lsb+1), mde_lsb, MN_MODE_DUAL_EDGE) * !!(n))
70#define CC_BANKED(mde0_lsb, mde1_lsb, n) \
71 ((BVAL((mde0_lsb+1), mde0_lsb, MN_MODE_DUAL_EDGE) \
72 | BVAL((mde1_lsb+1), mde1_lsb, MN_MODE_DUAL_EDGE)) \
73 * !!(n))
74
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070075/*
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070076 * Clock Definition Macros
77 */
78#define DEFINE_CLK_MEASURE(name) \
79 struct clk name = { \
80 .ops = &clk_ops_measure, \
81 .dbg_name = #name, \
82 CLK_INIT(name), \
83 }; \
84
85/*
86 * Generic frequency-definition structs and macros
87 */
88struct clk_freq_tbl {
89 const uint32_t freq_hz;
Matt Wagantall07c45472012-02-10 23:27:24 -080090 struct clk *const src_clk;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070091 const uint32_t md_val;
92 const uint32_t ns_val;
93 const uint32_t ctl_val;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070094 void *const extra_freq_data;
95};
96
97/* Some clocks have two banks to avoid glitches when switching frequencies.
98 * The unused bank is programmed while running on the other bank, and
99 * switched to afterwards. The following two structs describe the banks. */
100struct bank_mask_info {
101 void *const md_reg;
102 const uint32_t ns_mask;
103 const uint32_t rst_mask;
104 const uint32_t mnd_en_mask;
105 const uint32_t mode_mask;
106};
107
108struct bank_masks {
109 const uint32_t bank_sel_mask;
110 const struct bank_mask_info bank0_mask;
111 const struct bank_mask_info bank1_mask;
112};
113
Matt Wagantall07c45472012-02-10 23:27:24 -0800114#define F_RAW(f, sc, m_v, n_v, c_v, e) { \
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700115 .freq_hz = f, \
116 .src_clk = sc, \
117 .md_val = m_v, \
118 .ns_val = n_v, \
119 .ctl_val = c_v, \
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700120 .extra_freq_data = e, \
121 }
122#define FREQ_END (UINT_MAX-1)
Matt Wagantalle18bbc82011-10-06 10:07:28 -0700123#define F_END { .freq_hz = FREQ_END }
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700124
125/**
126 * struct branch - branch on/off
127 * @ctl_reg: clock control register
128 * @en_mask: ORed with @ctl_reg to enable the clock
Stephen Boyda52d7e32011-11-10 11:59:00 -0800129 * @hwcg_reg: hardware clock gating register
130 * @hwcg_mask: ORed with @hwcg_reg to enable hardware clock gating
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700131 * @halt_reg: halt register
132 * @halt_check: type of halt check to perform
133 * @halt_bit: ANDed with @halt_reg to test for clock halted
134 * @reset_reg: reset register
135 * @reset_mask: ORed with @reset_reg to reset the clock domain
136 */
137struct branch {
138 void __iomem *const ctl_reg;
139 const u32 en_mask;
140
Stephen Boyda52d7e32011-11-10 11:59:00 -0800141 void __iomem *hwcg_reg;
142 u32 hwcg_mask;
143
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700144 void __iomem *const halt_reg;
145 const u16 halt_check;
146 const u16 halt_bit;
147
148 void __iomem *const reset_reg;
149 const u32 reset_mask;
Matt Wagantall7e0b6c92012-01-20 18:48:05 -0800150
151 void __iomem *const retain_reg;
152 const u32 retain_mask;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700153};
154
Stephen Boyda52d7e32011-11-10 11:59:00 -0800155int branch_reset(struct branch *b, enum clk_reset_action action);
Stephen Boyd092fd182011-10-21 15:56:30 -0700156void __branch_clk_enable_reg(const struct branch *clk, const char *name);
157u32 __branch_clk_disable_reg(const struct branch *clk, const char *name);
Matt Wagantalla15833b2012-04-03 11:00:56 -0700158enum handoff branch_clk_handoff(struct clk *c);
159enum handoff branch_handoff(struct branch *clk, struct clk *c);
Matt Wagantall7e0b6c92012-01-20 18:48:05 -0800160int branch_clk_set_flags(struct clk *clk, unsigned flags);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700161
162/*
163 * Generic clock-definition struct and macros
164 */
165struct rcg_clk {
166 bool enabled;
167 void *const ns_reg;
168 void *const md_reg;
169
170 const uint32_t root_en_mask;
171 uint32_t ns_mask;
172 const uint32_t ctl_mask;
Matt Wagantall07c45472012-02-10 23:27:24 -0800173 uint32_t mnd_en_mask;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700174
Stephen Boydc78d9a72011-07-20 00:46:24 -0700175 void *bank_info;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700176 void (*set_rate)(struct rcg_clk *, struct clk_freq_tbl *);
Stephen Boydc78d9a72011-07-20 00:46:24 -0700177
Tianyi Goubaf6d342011-08-30 21:49:02 -0700178 struct clk_freq_tbl *freq_tbl;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700179 struct clk_freq_tbl *current_freq;
180
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700181 struct branch b;
182 struct clk c;
183};
184
185static inline struct rcg_clk *to_rcg_clk(struct clk *clk)
186{
187 return container_of(clk, struct rcg_clk, c);
188}
189
Matt Wagantall84f43fd2011-08-16 23:28:38 -0700190extern struct clk_freq_tbl rcg_dummy_freq;
191
Matt Wagantall0625ea02011-07-13 18:51:56 -0700192int rcg_clk_enable(struct clk *clk);
193void rcg_clk_disable(struct clk *clk);
Matt Wagantall9de3bfb2011-11-03 20:13:12 -0700194int rcg_clk_set_rate(struct clk *clk, unsigned long rate);
Matt Wagantall0625ea02011-07-13 18:51:56 -0700195int rcg_clk_list_rate(struct clk *clk, unsigned n);
196int rcg_clk_is_enabled(struct clk *clk);
Matt Wagantall9de3bfb2011-11-03 20:13:12 -0700197long rcg_clk_round_rate(struct clk *clk, unsigned long rate);
Matt Wagantall0625ea02011-07-13 18:51:56 -0700198struct clk *rcg_clk_get_parent(struct clk *c);
Matt Wagantalla15833b2012-04-03 11:00:56 -0700199enum handoff rcg_clk_handoff(struct clk *c);
Stephen Boyd7bf28142011-12-07 00:30:52 -0800200int rcg_clk_reset(struct clk *clk, enum clk_reset_action action);
Stephen Boyda52d7e32011-11-10 11:59:00 -0800201void rcg_clk_enable_hwcg(struct clk *clk);
202void rcg_clk_disable_hwcg(struct clk *clk);
203int rcg_clk_in_hwcg_mode(struct clk *c);
Matt Wagantall7e0b6c92012-01-20 18:48:05 -0800204int rcg_clk_set_flags(struct clk *clk, unsigned flags);
Matt Wagantall0625ea02011-07-13 18:51:56 -0700205
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700206/**
Stephen Boydb8ad8222011-11-28 12:17:58 -0800207 * struct cdiv_clk - integer divider clock with external source selection
208 * @ns_reg: source select and divider settings register
209 * @ext_mask: bit to set to select an external source
210 * @cur_div: current divider setting (or 0 for external source)
211 * @max_div: maximum divider value supported (must be power of 2)
212 * @div_offset: number of bits to shift divider left by in @ns_reg
213 * @b: branch
214 * @c: clock
215 */
216struct cdiv_clk {
217 void __iomem *const ns_reg;
218 u32 ext_mask;
219
220 unsigned long cur_div;
221 u8 div_offset;
222 u32 max_div;
223
224 struct branch b;
225 struct clk c;
226};
227
228static inline struct cdiv_clk *to_cdiv_clk(struct clk *clk)
229{
230 return container_of(clk, struct cdiv_clk, c);
231}
232
233extern struct clk_ops clk_ops_cdiv;
234
235/**
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700236 * struct fixed_clk - fixed rate clock (used for crystal oscillators)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700237 * @c: clk
238 */
239struct fixed_clk {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700240 struct clk c;
241};
242
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700243/**
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700244 * struct branch_clk - branch
245 * @enabled: true if clock is on, false otherwise
246 * @b: branch
247 * @parent: clock source
248 * @c: clk
249 *
250 * An on/off switch with a rate derived from the parent.
251 */
252struct branch_clk {
253 bool enabled;
254 struct branch b;
255 struct clk *parent;
256 struct clk c;
257};
258
259static inline struct branch_clk *to_branch_clk(struct clk *clk)
260{
261 return container_of(clk, struct branch_clk, c);
262}
263
264int branch_clk_enable(struct clk *clk);
265void branch_clk_disable(struct clk *clk);
266struct clk *branch_clk_get_parent(struct clk *clk);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700267int branch_clk_is_enabled(struct clk *clk);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700268int branch_clk_reset(struct clk *c, enum clk_reset_action action);
Stephen Boyda52d7e32011-11-10 11:59:00 -0800269void branch_clk_enable_hwcg(struct clk *clk);
270void branch_clk_disable_hwcg(struct clk *clk);
271int branch_clk_in_hwcg_mode(struct clk *c);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700272
273/**
274 * struct measure_clk - for rate measurement debug use
275 * @sample_ticks: sample period in reference clock ticks
276 * @multiplier: measurement scale-up factor
277 * @divider: measurement scale-down factor
278 * @c: clk
279*/
280struct measure_clk {
281 u64 sample_ticks;
282 u32 multiplier;
283 u32 divider;
284 struct clk c;
285};
286
287extern struct clk_ops clk_ops_measure;
288
289static inline struct measure_clk *to_measure_clk(struct clk *clk)
290{
291 return container_of(clk, struct measure_clk, c);
292}
293
294/*
295 * Variables from clock-local driver
296 */
297extern spinlock_t local_clock_reg_lock;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700298extern struct fixed_clk gnd_clk;
299
300/*
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700301 * Generic set-rate implementations
302 */
303void set_rate_mnd(struct rcg_clk *clk, struct clk_freq_tbl *nf);
304void set_rate_nop(struct rcg_clk *clk, struct clk_freq_tbl *nf);
305void set_rate_mnd_8(struct rcg_clk *clk, struct clk_freq_tbl *nf);
306void set_rate_mnd_banked(struct rcg_clk *clk, struct clk_freq_tbl *nf);
307void set_rate_div_banked(struct rcg_clk *clk, struct clk_freq_tbl *nf);
308
309#endif /* __ARCH_ARM_MACH_MSM_CLOCK_LOCAL_H */
310