1 | /* SPDX-License-Identifier: GPL-2.0-only */ |
2 | /* |
3 | * Copyright (c) 2012-2020, NVIDIA CORPORATION. All rights reserved. |
4 | */ |
5 | |
6 | #ifndef __LINUX_CLK_TEGRA_H_ |
7 | #define __LINUX_CLK_TEGRA_H_ |
8 | |
9 | #include <linux/types.h> |
10 | #include <linux/bug.h> |
11 | |
12 | /* |
13 | * Tegra CPU clock and reset control ops |
14 | * |
15 | * wait_for_reset: |
16 | * keep waiting until the CPU in reset state |
17 | * put_in_reset: |
18 | * put the CPU in reset state |
19 | * out_of_reset: |
20 | * release the CPU from reset state |
21 | * enable_clock: |
22 | * CPU clock un-gate |
23 | * disable_clock: |
24 | * CPU clock gate |
25 | * rail_off_ready: |
26 | * CPU is ready for rail off |
27 | * suspend: |
28 | * save the clock settings when CPU go into low-power state |
29 | * resume: |
30 | * restore the clock settings when CPU exit low-power state |
31 | */ |
32 | struct tegra_cpu_car_ops { |
33 | void (*wait_for_reset)(u32 cpu); |
34 | void (*put_in_reset)(u32 cpu); |
35 | void (*out_of_reset)(u32 cpu); |
36 | void (*enable_clock)(u32 cpu); |
37 | void (*disable_clock)(u32 cpu); |
38 | #ifdef CONFIG_PM_SLEEP |
39 | bool (*rail_off_ready)(void); |
40 | void (*suspend)(void); |
41 | void (*resume)(void); |
42 | #endif |
43 | }; |
44 | |
45 | #ifdef CONFIG_ARCH_TEGRA |
46 | extern struct tegra_cpu_car_ops *tegra_cpu_car_ops; |
47 | |
48 | static inline void tegra_wait_cpu_in_reset(u32 cpu) |
49 | { |
50 | if (WARN_ON(!tegra_cpu_car_ops->wait_for_reset)) |
51 | return; |
52 | |
53 | tegra_cpu_car_ops->wait_for_reset(cpu); |
54 | } |
55 | |
56 | static inline void tegra_put_cpu_in_reset(u32 cpu) |
57 | { |
58 | if (WARN_ON(!tegra_cpu_car_ops->put_in_reset)) |
59 | return; |
60 | |
61 | tegra_cpu_car_ops->put_in_reset(cpu); |
62 | } |
63 | |
64 | static inline void tegra_cpu_out_of_reset(u32 cpu) |
65 | { |
66 | if (WARN_ON(!tegra_cpu_car_ops->out_of_reset)) |
67 | return; |
68 | |
69 | tegra_cpu_car_ops->out_of_reset(cpu); |
70 | } |
71 | |
72 | static inline void tegra_enable_cpu_clock(u32 cpu) |
73 | { |
74 | if (WARN_ON(!tegra_cpu_car_ops->enable_clock)) |
75 | return; |
76 | |
77 | tegra_cpu_car_ops->enable_clock(cpu); |
78 | } |
79 | |
80 | static inline void tegra_disable_cpu_clock(u32 cpu) |
81 | { |
82 | if (WARN_ON(!tegra_cpu_car_ops->disable_clock)) |
83 | return; |
84 | |
85 | tegra_cpu_car_ops->disable_clock(cpu); |
86 | } |
87 | #else |
88 | static inline void tegra_wait_cpu_in_reset(u32 cpu) |
89 | { |
90 | } |
91 | |
92 | static inline void tegra_put_cpu_in_reset(u32 cpu) |
93 | { |
94 | } |
95 | |
96 | static inline void tegra_cpu_out_of_reset(u32 cpu) |
97 | { |
98 | } |
99 | |
100 | static inline void tegra_enable_cpu_clock(u32 cpu) |
101 | { |
102 | } |
103 | |
104 | static inline void tegra_disable_cpu_clock(u32 cpu) |
105 | { |
106 | } |
107 | #endif |
108 | |
109 | #if defined(CONFIG_ARCH_TEGRA) && defined(CONFIG_PM_SLEEP) |
110 | static inline bool tegra_cpu_rail_off_ready(void) |
111 | { |
112 | if (WARN_ON(!tegra_cpu_car_ops->rail_off_ready)) |
113 | return false; |
114 | |
115 | return tegra_cpu_car_ops->rail_off_ready(); |
116 | } |
117 | |
118 | static inline void tegra_cpu_clock_suspend(void) |
119 | { |
120 | if (WARN_ON(!tegra_cpu_car_ops->suspend)) |
121 | return; |
122 | |
123 | tegra_cpu_car_ops->suspend(); |
124 | } |
125 | |
126 | static inline void tegra_cpu_clock_resume(void) |
127 | { |
128 | if (WARN_ON(!tegra_cpu_car_ops->resume)) |
129 | return; |
130 | |
131 | tegra_cpu_car_ops->resume(); |
132 | } |
133 | #else |
134 | static inline bool tegra_cpu_rail_off_ready(void) |
135 | { |
136 | return false; |
137 | } |
138 | |
139 | static inline void tegra_cpu_clock_suspend(void) |
140 | { |
141 | } |
142 | |
143 | static inline void tegra_cpu_clock_resume(void) |
144 | { |
145 | } |
146 | #endif |
147 | |
148 | struct clk; |
149 | struct tegra_emc; |
150 | |
151 | typedef long (tegra20_clk_emc_round_cb)(unsigned long rate, |
152 | unsigned long min_rate, |
153 | unsigned long max_rate, |
154 | void *arg); |
155 | typedef int (tegra124_emc_prepare_timing_change_cb)(struct tegra_emc *emc, |
156 | unsigned long rate); |
157 | typedef void (tegra124_emc_complete_timing_change_cb)(struct tegra_emc *emc, |
158 | unsigned long rate); |
159 | |
160 | struct tegra210_clk_emc_config { |
161 | unsigned long rate; |
162 | bool same_freq; |
163 | u32 value; |
164 | |
165 | unsigned long parent_rate; |
166 | u8 parent; |
167 | }; |
168 | |
169 | struct tegra210_clk_emc_provider { |
170 | struct module *owner; |
171 | struct device *dev; |
172 | |
173 | struct tegra210_clk_emc_config *configs; |
174 | unsigned int num_configs; |
175 | |
176 | int (*set_rate)(struct device *dev, |
177 | const struct tegra210_clk_emc_config *config); |
178 | }; |
179 | |
180 | #if defined(CONFIG_ARCH_TEGRA_2x_SOC) || defined(CONFIG_ARCH_TEGRA_3x_SOC) |
181 | void tegra20_clk_set_emc_round_callback(tegra20_clk_emc_round_cb *round_cb, |
182 | void *cb_arg); |
183 | int tegra20_clk_prepare_emc_mc_same_freq(struct clk *emc_clk, bool same); |
184 | #else |
185 | static inline void |
186 | tegra20_clk_set_emc_round_callback(tegra20_clk_emc_round_cb *round_cb, |
187 | void *cb_arg) |
188 | { |
189 | } |
190 | |
191 | static inline int |
192 | tegra20_clk_prepare_emc_mc_same_freq(struct clk *emc_clk, bool same) |
193 | { |
194 | return 0; |
195 | } |
196 | #endif |
197 | |
198 | #ifdef CONFIG_TEGRA124_CLK_EMC |
199 | void tegra124_clk_set_emc_callbacks(tegra124_emc_prepare_timing_change_cb *prep_cb, |
200 | tegra124_emc_complete_timing_change_cb *complete_cb); |
201 | #else |
202 | static inline void |
203 | tegra124_clk_set_emc_callbacks(tegra124_emc_prepare_timing_change_cb *prep_cb, |
204 | tegra124_emc_complete_timing_change_cb *complete_cb) |
205 | { |
206 | } |
207 | #endif |
208 | |
209 | #ifdef CONFIG_ARCH_TEGRA_210_SOC |
210 | int tegra210_plle_hw_sequence_start(void); |
211 | bool tegra210_plle_hw_sequence_is_enabled(void); |
212 | void tegra210_xusb_pll_hw_control_enable(void); |
213 | void tegra210_xusb_pll_hw_sequence_start(void); |
214 | void tegra210_sata_pll_hw_control_enable(void); |
215 | void tegra210_sata_pll_hw_sequence_start(void); |
216 | void tegra210_set_sata_pll_seq_sw(bool state); |
217 | void tegra210_put_utmipll_in_iddq(void); |
218 | void tegra210_put_utmipll_out_iddq(void); |
219 | int tegra210_clk_handle_mbist_war(unsigned int id); |
220 | void tegra210_clk_emc_dll_enable(bool flag); |
221 | void tegra210_clk_emc_dll_update_setting(u32 emc_dll_src_value); |
222 | void tegra210_clk_emc_update_setting(u32 emc_src_value); |
223 | |
224 | int tegra210_clk_emc_attach(struct clk *clk, |
225 | struct tegra210_clk_emc_provider *provider); |
226 | void tegra210_clk_emc_detach(struct clk *clk); |
227 | #else |
228 | static inline int tegra210_plle_hw_sequence_start(void) |
229 | { |
230 | return 0; |
231 | } |
232 | |
233 | static inline bool tegra210_plle_hw_sequence_is_enabled(void) |
234 | { |
235 | return false; |
236 | } |
237 | |
238 | static inline int tegra210_clk_handle_mbist_war(unsigned int id) |
239 | { |
240 | return 0; |
241 | } |
242 | |
243 | static inline int |
244 | tegra210_clk_emc_attach(struct clk *clk, |
245 | struct tegra210_clk_emc_provider *provider) |
246 | { |
247 | return 0; |
248 | } |
249 | |
250 | static inline void tegra210_xusb_pll_hw_control_enable(void) {} |
251 | static inline void tegra210_xusb_pll_hw_sequence_start(void) {} |
252 | static inline void tegra210_sata_pll_hw_control_enable(void) {} |
253 | static inline void tegra210_sata_pll_hw_sequence_start(void) {} |
254 | static inline void tegra210_set_sata_pll_seq_sw(bool state) {} |
255 | static inline void tegra210_put_utmipll_in_iddq(void) {} |
256 | static inline void tegra210_put_utmipll_out_iddq(void) {} |
257 | static inline void tegra210_clk_emc_dll_enable(bool flag) {} |
258 | static inline void tegra210_clk_emc_dll_update_setting(u32 emc_dll_src_value) {} |
259 | static inline void tegra210_clk_emc_update_setting(u32 emc_src_value) {} |
260 | static inline void tegra210_clk_emc_detach(struct clk *clk) {} |
261 | #endif |
262 | |
263 | #endif /* __LINUX_CLK_TEGRA_H_ */ |
264 | |