blob: 9476850519709ecab92286d5d71ea72966e3a437 [file] [log] [blame]
Duy Truong790f06d2013-02-13 16:38:12 -08001/* Copyright (c) 2009-2012, The Linux Foundation. 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>
Matt Wagantall33d01f52012-02-23 23:27:44 -080018#include <mach/clk-provider.h>
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070019
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;
Stephen Boyd230a6742012-09-21 14:17:11 -0700156extern struct clk_ops clk_ops_smi_2x;
Stephen Boyd409b8b42012-04-10 12:12:56 -0700157extern struct clk_ops clk_ops_reset;
158
Stephen Boyda52d7e32011-11-10 11:59:00 -0800159int branch_reset(struct branch *b, enum clk_reset_action action);
Matt Wagantall0de1b3f2012-06-05 19:52:43 -0700160void __branch_enable_reg(const struct branch *b, const char *name);
161u32 __branch_disable_reg(const struct branch *b, const char *name);
Matt Wagantallf82f2942012-01-27 13:56:13 -0800162enum handoff branch_handoff(struct branch *b, struct clk *c);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700163
164/*
165 * Generic clock-definition struct and macros
166 */
167struct rcg_clk {
Stephen Boydd86d1f22012-01-24 17:36:34 -0800168 bool prepared;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700169 bool enabled;
170 void *const ns_reg;
171 void *const md_reg;
172
173 const uint32_t root_en_mask;
174 uint32_t ns_mask;
175 const uint32_t ctl_mask;
Matt Wagantall07c45472012-02-10 23:27:24 -0800176 uint32_t mnd_en_mask;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700177
Stephen Boydc78d9a72011-07-20 00:46:24 -0700178 void *bank_info;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700179 void (*set_rate)(struct rcg_clk *, struct clk_freq_tbl *);
Stephen Boydc78d9a72011-07-20 00:46:24 -0700180
Tianyi Goubaf6d342011-08-30 21:49:02 -0700181 struct clk_freq_tbl *freq_tbl;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700182 struct clk_freq_tbl *current_freq;
183
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700184 struct branch b;
185 struct clk c;
186};
187
Matt Wagantallf82f2942012-01-27 13:56:13 -0800188static inline struct rcg_clk *to_rcg_clk(struct clk *c)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700189{
Matt Wagantallf82f2942012-01-27 13:56:13 -0800190 return container_of(c, struct rcg_clk, c);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700191}
192
Stephen Boyd409b8b42012-04-10 12:12:56 -0700193extern struct clk_ops clk_ops_rcg;
Matt Wagantall84f43fd2011-08-16 23:28:38 -0700194
Stephen Boyd409b8b42012-04-10 12:12:56 -0700195extern struct clk_freq_tbl rcg_dummy_freq;
Matt Wagantall0625ea02011-07-13 18:51:56 -0700196
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700197/**
Stephen Boydb8ad8222011-11-28 12:17:58 -0800198 * struct cdiv_clk - integer divider clock with external source selection
199 * @ns_reg: source select and divider settings register
200 * @ext_mask: bit to set to select an external source
201 * @cur_div: current divider setting (or 0 for external source)
202 * @max_div: maximum divider value supported (must be power of 2)
203 * @div_offset: number of bits to shift divider left by in @ns_reg
204 * @b: branch
205 * @c: clock
206 */
207struct cdiv_clk {
208 void __iomem *const ns_reg;
209 u32 ext_mask;
210
211 unsigned long cur_div;
212 u8 div_offset;
213 u32 max_div;
214
215 struct branch b;
216 struct clk c;
217};
218
Matt Wagantallf82f2942012-01-27 13:56:13 -0800219static inline struct cdiv_clk *to_cdiv_clk(struct clk *c)
Stephen Boydb8ad8222011-11-28 12:17:58 -0800220{
Matt Wagantallf82f2942012-01-27 13:56:13 -0800221 return container_of(c, struct cdiv_clk, c);
Stephen Boydb8ad8222011-11-28 12:17:58 -0800222}
223
224extern struct clk_ops clk_ops_cdiv;
225
226/**
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700227 * struct fixed_clk - fixed rate clock (used for crystal oscillators)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700228 * @c: clk
229 */
230struct fixed_clk {
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700231 struct clk c;
232};
233
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700234/**
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700235 * struct branch_clk - branch
236 * @enabled: true if clock is on, false otherwise
237 * @b: branch
Matt Wagantallf82f2942012-01-27 13:56:13 -0800238 * @c: clock
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700239 *
240 * An on/off switch with a rate derived from the parent.
241 */
242struct branch_clk {
243 bool enabled;
244 struct branch b;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700245 struct clk c;
246};
247
Matt Wagantallf82f2942012-01-27 13:56:13 -0800248static inline struct branch_clk *to_branch_clk(struct clk *c)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700249{
Matt Wagantallf82f2942012-01-27 13:56:13 -0800250 return container_of(c, struct branch_clk, c);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700251}
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
Matt Wagantallf82f2942012-01-27 13:56:13 -0800258 * @c: clock
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700259*/
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
Matt Wagantallf82f2942012-01-27 13:56:13 -0800269static inline struct measure_clk *to_measure_clk(struct clk *c)
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700270{
Matt Wagantallf82f2942012-01-27 13:56:13 -0800271 return container_of(c, struct measure_clk, c);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700272}
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 */
Matt Wagantallf82f2942012-01-27 13:56:13 -0800283void set_rate_mnd(struct rcg_clk *rcg, struct clk_freq_tbl *nf);
284void set_rate_nop(struct rcg_clk *rcg, struct clk_freq_tbl *nf);
285void set_rate_mnd_8(struct rcg_clk *rcg, struct clk_freq_tbl *nf);
286void set_rate_mnd_banked(struct rcg_clk *rcg, struct clk_freq_tbl *nf);
287void set_rate_div_banked(struct rcg_clk *rcg, struct clk_freq_tbl *nf);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700288
289#endif /* __ARCH_ARM_MACH_MSM_CLOCK_LOCAL_H */
290