blob: ffc7057406ae399b7d536d0d7df68d14befe763f [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 = { \
Matt Wagantallae053222012-05-14 19:42:07 -070080 .ops = &clk_ops_empty, \
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070081 .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 Boyd409b8b42012-04-10 12:12:56 -0700155extern struct clk_ops clk_ops_branch;
156extern struct clk_ops clk_ops_reset;
157
Stephen Boyda52d7e32011-11-10 11:59:00 -0800158int branch_reset(struct branch *b, enum clk_reset_action action);
Stephen Boyd092fd182011-10-21 15:56:30 -0700159void __branch_clk_enable_reg(const struct branch *clk, const char *name);
160u32 __branch_clk_disable_reg(const struct branch *clk, const char *name);
Matt Wagantalla15833b2012-04-03 11:00:56 -0700161enum handoff branch_handoff(struct branch *clk, struct clk *c);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700162
163/*
164 * Generic clock-definition struct and macros
165 */
166struct rcg_clk {
167 bool enabled;
168 void *const ns_reg;
169 void *const md_reg;
170
171 const uint32_t root_en_mask;
172 uint32_t ns_mask;
173 const uint32_t ctl_mask;
Matt Wagantall07c45472012-02-10 23:27:24 -0800174 uint32_t mnd_en_mask;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700175
Stephen Boydc78d9a72011-07-20 00:46:24 -0700176 void *bank_info;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700177 void (*set_rate)(struct rcg_clk *, struct clk_freq_tbl *);
Stephen Boydc78d9a72011-07-20 00:46:24 -0700178
Tianyi Goubaf6d342011-08-30 21:49:02 -0700179 struct clk_freq_tbl *freq_tbl;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700180 struct clk_freq_tbl *current_freq;
181
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700182 struct branch b;
183 struct clk c;
184};
185
186static inline struct rcg_clk *to_rcg_clk(struct clk *clk)
187{
188 return container_of(clk, struct rcg_clk, c);
189}
190
Stephen Boyd409b8b42012-04-10 12:12:56 -0700191extern struct clk_ops clk_ops_rcg;
Matt Wagantall84f43fd2011-08-16 23:28:38 -0700192
Stephen Boyd409b8b42012-04-10 12:12:56 -0700193extern struct clk_freq_tbl rcg_dummy_freq;
Matt Wagantall0625ea02011-07-13 18:51:56 -0700194
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700195/**
Stephen Boydb8ad8222011-11-28 12:17:58 -0800196 * struct cdiv_clk - integer divider clock with external source selection
197 * @ns_reg: source select and divider settings register
198 * @ext_mask: bit to set to select an external source
199 * @cur_div: current divider setting (or 0 for external source)
200 * @max_div: maximum divider value supported (must be power of 2)
201 * @div_offset: number of bits to shift divider left by in @ns_reg
202 * @b: branch
203 * @c: clock
204 */
205struct cdiv_clk {
206 void __iomem *const ns_reg;
207 u32 ext_mask;
208
209 unsigned long cur_div;
210 u8 div_offset;
211 u32 max_div;
212
213 struct branch b;
214 struct clk c;
215};
216
217static inline struct cdiv_clk *to_cdiv_clk(struct clk *clk)
218{
219 return container_of(clk, struct cdiv_clk, c);
220}
221
222extern struct clk_ops clk_ops_cdiv;
223
224/**
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700225 * struct fixed_clk - fixed rate clock (used for crystal oscillators)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700226 * @c: clk
227 */
228struct fixed_clk {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700229 struct clk c;
230};
231
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700232/**
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700233 * struct branch_clk - branch
234 * @enabled: true if clock is on, false otherwise
235 * @b: branch
236 * @parent: clock source
237 * @c: clk
238 *
239 * An on/off switch with a rate derived from the parent.
240 */
241struct branch_clk {
242 bool enabled;
243 struct branch b;
244 struct clk *parent;
245 struct clk c;
246};
247
248static inline struct branch_clk *to_branch_clk(struct clk *clk)
249{
250 return container_of(clk, struct branch_clk, c);
251}
252
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700253/**
254 * struct measure_clk - for rate measurement debug use
255 * @sample_ticks: sample period in reference clock ticks
256 * @multiplier: measurement scale-up factor
257 * @divider: measurement scale-down factor
258 * @c: clk
259*/
260struct measure_clk {
261 u64 sample_ticks;
262 u32 multiplier;
263 u32 divider;
264 struct clk c;
265};
266
Matt Wagantallae053222012-05-14 19:42:07 -0700267extern struct clk_ops clk_ops_empty;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700268
269static inline struct measure_clk *to_measure_clk(struct clk *clk)
270{
271 return container_of(clk, struct measure_clk, c);
272}
273
274/*
275 * Variables from clock-local driver
276 */
277extern spinlock_t local_clock_reg_lock;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700278extern struct fixed_clk gnd_clk;
279
280/*
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700281 * Generic set-rate implementations
282 */
283void set_rate_mnd(struct rcg_clk *clk, struct clk_freq_tbl *nf);
284void set_rate_nop(struct rcg_clk *clk, struct clk_freq_tbl *nf);
285void set_rate_mnd_8(struct rcg_clk *clk, struct clk_freq_tbl *nf);
286void set_rate_mnd_banked(struct rcg_clk *clk, struct clk_freq_tbl *nf);
287void set_rate_div_banked(struct rcg_clk *clk, struct clk_freq_tbl *nf);
288
289#endif /* __ARCH_ARM_MACH_MSM_CLOCK_LOCAL_H */
290