1 /*
2  * Renesas SCP/MCP Software
3  * Copyright (c) 2020-2022, Renesas Electronics Corporation. All rights
4  * reserved.
5  *
6  * SPDX-License-Identifier: BSD-3-Clause
7  */
8 
9 /* The use of "subordinate" may not be in sync with platform documentation */
10 
11 #ifndef MOD_RCAR_CLOCK_H
12 #define MOD_RCAR_CLOCK_H
13 
14 #include <rcar_mmap.h>
15 #include <utils_def.h>
16 
17 #include <mod_clock.h>
18 
19 #include <fwk_element.h>
20 
21 #include <stdint.h>
22 
23 /*!
24  * \addtogroup GroupRCARModule RCAR Product Modules
25  * @{
26  */
27 
28 /*!
29  * \defgroup GroupRCARClock Clock
30  * @{
31  */
32 
33 /*!
34  * \brief Clock driver interface.
35  */
36 struct mod_rcar_clock_drv_api {
37     /*! Name of the driver */
38     const char *name;
39 
40     /*!
41      * \brief Set a new clock rate by providing a frequency in Hertz (Hz).
42      *
43      * \param clock_id Clock device identifier.
44      *
45      * \param rate The desired frequency in Hertz.
46      *
47      * \param round_mode The type of rounding to perform, if required, to
48      *      achieve the given rate.
49      *
50      * \retval FWK_SUCCESS The operation succeeded.
51      * \return One of the standard framework error codes.
52      */
53     int (*set_rate)(
54         fwk_id_t clock_id,
55         uint64_t rate,
56         enum mod_clock_round_mode round_mode);
57 
58     /*!
59      * \brief Get the current rate of a clock in Hertz (Hz).
60      *
61      * \param clock_id Clock device identifier.
62      *
63      * \param [out] rate The current clock rate in Hertz.
64      *
65      * \retval FWK_SUCCESS The operation succeeded.
66      * \return One of the standard framework error codes.
67      */
68     int (*get_rate)(fwk_id_t clock_id, uint64_t *rate);
69 
70     /*!
71      * \brief Get a clock rate in Hertz from an index into the clock's range.
72      *
73      * \param clock_id Clock device identifier.
74      *
75      * \param rate_index The index into the clock's range to get the rate of.
76      *
77      * \param[out] rate The rate, in Hertz, corresponding to the index.
78      *
79      * \retval FWK_SUCCESS The operation succeeded.
80      * \return One of the standard framework error codes.
81      */
82     int (*get_rate_from_index)(
83         fwk_id_t clock_id,
84         unsigned int rate_index,
85         uint64_t *rate);
86 
87     /*!
88      * \brief Set the running state of a clock.
89      *
90      * \param clock_id Clock device identifier.
91      *
92      * \param state One of the valid clock states.
93      *
94      * \retval FWK_SUCCESS The operation succeeded.
95      * \return One of the standard framework error codes.
96      */
97     int (*set_state)(fwk_id_t clock_id, enum mod_clock_state state);
98 
99     /*!
100      * \brief Get the running state of a clock.
101      *
102      * \param clock_id Clock device identifier.
103      *
104      * \param[out] state The current clock state.
105      *
106      * \retval FWK_SUCCESS The operation succeeded.
107      * \return One of the standard framework error codes.
108      */
109     int (*get_state)(fwk_id_t clock_id, enum mod_clock_state *state);
110 
111     /*!
112      * \brief Get the range of rates that the clock supports.
113      *
114      * \param clock_id Clock device identifier.
115      *
116      * \param[out] range The clock range structure.
117      *
118      * \retval FWK_SUCCESS The operation succeeded.
119      * \return One of the standard framework error codes.
120      */
121     int (*get_range)(fwk_id_t clock_id, struct mod_clock_range *range);
122 
123     /*!
124      * \brief Handle the condition where the state of a clock's power domain is
125      *     about to change.
126      *
127      * \details This function will be called prior to the change in power
128      *     state occurring so that the clock driver implementing this API is
129      *     able to perform any required preparatory work beforehand.
130      *
131      * \note This function is optional. If the driver does not control any
132      *     clocks that require power state awareness then the pointer may be set
133      *     to NULL.
134      *
135      * \param clock_id Clock device identifier.
136      *
137      * \param current_state The current power state that the clock's power
138      *     domain will transition away from.
139      *
140      * \param new_state The power state that the clock's power domain will
141      *     transition to.
142      *
143      * \retval FWK_SUCCESS The operation succeeded.
144      * \return One of the standard framework error codes.
145      */
146     int (*process_pending_power_transition)(
147         fwk_id_t clock_id,
148         unsigned int current_state,
149         unsigned int new_state);
150 
151     /*!
152      * \brief Handle the condition where the state of a clock's power domain
153      *     has changed.
154      *
155      * \details This function will be called after the change in power state
156      *     has occurred. The driver can take any appropriate actions that are
157      *     required to accommodate the new state. The transition can be to a
158      *     deeper power state (e.g. ON->OFF) or to a shallower power state
159      *     (e.g. OFF->ON).
160      *
161      * \note This function is optional. If the driver does not control any
162      *     clocks that require power state awareness then the pointer may be set
163      *     to NULL.
164      *
165      * \param clock_id Clock device identifier.
166      *
167      * \param state The power state that the clock's power domain transitioned
168      *     to.
169      *
170      * \retval FWK_SUCCESS The operation succeeded.
171      * \return One of the standard framework error codes.
172      */
173     int (*process_power_transition)(fwk_id_t clock_id, unsigned int state);
174 };
175 
176 /*!
177  * \brief APIs provided by the driver.
178  */
179 enum mod_rcar_clock_api_type {
180     /*! An implementation of the Clock HAL module's clock driver API */
181     MOD_RCAR_CLOCK_API_TYPE_CLOCK,
182     /*! A low-level API for direct control of CSS clocks */
183     MOD_RCAR_CLOCK_API_TYPE_CSS,
184     MOD_RCAR_CLOCK_API_TYPE_SYSTEM,
185     MOD_RCAR_CLOCK_API_COUNT,
186 };
187 
188 /*!
189  * \brief Sub-types of rcar clock.
190  */
191 enum mod_rcar_clock_type {
192     /*! A clock with a fixed source. Only its divider can be changed. */
193     MOD_RCAR_CLOCK_TYPE_SINGLE_SOURCE,
194     /*! A clock with multiple, selectable sources and at least one divider. */
195     MOD_RCAR_CLOCK_TYPE_MULTI_SOURCE,
196     /*!
197      * A clock with multiple, selectable sources, at least one divider, and
198      * support for modulation.
199      */
200     MOD_RCAR_CLOCK_TYPE_CLUSTER,
201 };
202 
203 /*!
204  * \brief Divider register types.
205  */
206 enum mod_rcar_clock_msclock_divider {
207     /*! Divider affecting the A57 PLL clock source. */
208     MOD_RCAR_CLOCK_A57_DIVIDER_DIV_EXT = 1,
209     /*! Divider affecting the A53 PLL clock source. */
210     MOD_RCAR_CLOCK_A53_DIVIDER_DIV_EXT = 2,
211 };
212 
213 /*!
214  * \brief Selectable clock sources for V8.2 cluster clocks.
215  */
216 enum mod_clusclock_source {
217     /*! The clock source is set to a private cluster PLL */
218     MOD_RCAR_CLOCK_CLUSCLK_SOURCE_PLL0 = 0,
219     /*! The clock source is set to a private cluster PLL */
220     MOD_RCAR_CLOCK_CLUSCLK_SOURCE_PLL1 = 1,
221     /*! The clock source is set to a private cluster PLL */
222     MOD_RCAR_CLOCK_CLUSCLK_SOURCE_PLL2 = 2,
223     /*! The clock source is set to a private cluster PLL */
224     MOD_RCAR_CLOCK_CLUSCLK_SOURCE_PLL3 = 3,
225     /*! The clock source is set to a private cluster PLL */
226     MOD_RCAR_CLOCK_CLUSCLK_SOURCE_PLL4 = 4,
227     /*! The clock source is set to a private cluster PLL */
228     MOD_RCAR_CLOCK_CLUSCLK_SOURCE_PLL5 = 5,
229     /*! The clock source is set to a private cluster PLL */
230     MOD_RCAR_CLOCK_CLUSCLK_SOURCE_PLL6 = 6,
231     /*! The clock source is set to a private cluster PLL */
232     MOD_RCAR_CLOCK_CLUSCLK_SOURCE_PLL7 = 7,
233     /*! Number of valid clock sources */
234     MOD_RCAR_CLOCK_CLUSCLK_SOURCE_MAX
235 };
236 
237 /*!
238  * \brief Rate lookup entry.
239  */
240 struct mod_rcar_clock_rate {
241     /*! Rate in Hertz. */
242     uint64_t rate;
243     /*! Clock source used to obtain the rate (multi-source clocks only). */
244     uint8_t source;
245     /*! The divider register to use (multi-source clocks only). */
246     enum mod_rcar_clock_msclock_divider divider_reg;
247     /*! Divider used to obtain the rate. */
248     uint8_t divider;
249 };
250 
251 /*!
252  * \brief Ext clock rate lookup entry.
253  */
254 struct mod_ext_clock_rate {
255     /*! Rate in Hertz. */
256     uint32_t ext_clk_rate;
257 };
258 
259 /*!
260  * \brief Subsystem clock device configuration.
261  */
262 struct mod_rcar_clock_dev_config {
263     /*! The type of the clock device. */
264     enum mod_rcar_clock_type type;
265 
266     /*!
267      * \brief Indicates whether the clock is part of a CSS clock group (\c true)
268      *     or operating as an independent clock (\c false).
269      */
270     bool is_group_member;
271 
272     /*! Pointer to the clock's control register. */
273     volatile uint32_t *const control_reg;
274 
275     /*! Pointer to the clock's modulator register, if any. */
276     volatile uint32_t *const modulator_reg;
277 
278     /*! Pointer to the clock's DIV_SYS divider register, if any. */
279     volatile uint32_t *const divsys_reg;
280 
281     /*! Pointer to the clock's DIV_EXT divider register, if any. */
282     volatile uint32_t *const divext_reg;
283 
284     /*! Pointer to the clock's rate lookup table. */
285     const struct mod_rcar_clock_rate *rate_table;
286 
287     /*! The number of rates in the rate lookup table. */
288     uint32_t rate_count;
289 
290     /*! The rate, in Hz, to set during module initialization. */
291     uint64_t initial_rate;
292 
293     /*!
294      * If \c true, the driver will not attempt to set a default frequency, or to
295      * otherwise configure the PLL during the pre-runtime phase. The PLL is
296      * expected to be initialized later in response to a notification or other
297      * event.
298      */
299     const bool defer_initialization;
300 };
301 
302 /*!
303  * @cond
304  */
305 
306 /* Device context */
307 struct rcar_clock_dev_ctx {
308     bool initialized;
309     uint64_t current_rate;
310     enum mod_clock_state current_state;
311     const struct mod_rcar_clock_dev_config *config;
312 };
313 
314 /* Module context */
315 struct rcar_clock_ctx {
316     struct rcar_clock_dev_ctx *dev_ctx_table;
317     unsigned int dev_count;
318     uint32_t extal_clk;
319 };
320 
321 struct op_points {
322     unsigned long freq; /* Hz */
323     unsigned long volt; /* uV */
324 };
325 
326 #define PLL_BASE_CLOCK (16640000UL)
327 #define CPG_FRQCRB (CPG_BASE + 0x0004)
328 #define CPG_FRQCRB_KICK 0x80000000
329 #define CPG_FRQCRC (CPG_BASE + 0x00e0)
330 #define CPG_FRQCRC_ZFC_A57_MASK 0x00001F00
331 #define CPG_FRQCRC_ZFC_A57_SHIFT 8
332 #define CPG_FRQCRC_ZFC_A53_MASK 0x0000001F
333 #define CPG_FRQCRC_ZFC_A53_SHIFT 0
334 #ifndef CPG_PLL0CR
335 #    define CPG_PLL0CR (CPG_BASE + 0x00d8)
336 #endif
337 #define CPG_PLL0CR_ZFC_MASK 0x7F000000
338 #define CPG_PLL0CR_ZFC_SHIFT 24
339 #ifndef CPG_PLL2CR
340 #    define CPG_PLL2CR (CPG_BASE + 0x002c)
341 #endif
342 #define CPG_PLL2CR_ZFC_MASK 0x7F000000
343 #define CPG_PLL2CR_ZFC_SHIFT 24
344 
345 #define min(x, y) \
346     ({ \
347         __typeof__(x) _x = (x); \
348         __typeof__(y) _y = (y); \
349         _x < _y ? _x : _y; \
350     })
351 
352 #define max(x, y) \
353     ({ \
354         __typeof__(x) _x = (x); \
355         __typeof__(y) _y = (y); \
356         _x > _y ? _x : _y; \
357     })
358 
359 #define clamp(val, lo, hi) min((__typeof__(val))max(val, lo), hi)
360 
361 #define A57_DOMAIN 0
362 #define A53_DOMAIN 1
363 #define NR_H3_A57_OPP 5
364 #define NR_M3_A57_OPP 6
365 #define NR_H3_A53_OPP 3
366 #define NR_M3_A53_OPP 4
367 #define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
368 #define DIV_ROUND(n, d) (((n) + (d) / 2) / (d))
369 
370 /* CPG base address */
371 #define CPG_PLLECR 0x00D0
372 
373 /* Implementation for customized clocks (Z-clk, Z2-clk, PLL0-clk) for CPUFreq */
374 #define CPG_PLLECR_PLL0ST BIT(8)
375 #define CPG_PLLECR_PLL2ST BIT(10)
376 
377 /* Define for PLL0 clk driver */
378 #define CPG_PLLCR_STC_MASK 0x7f000000
379 #define CPG_PLLCR_STC_SHIFT 24
380 
381 /* Modify for Z-clock and Z2-clock
382  *
383  * Traits of this clock:
384  * prepare - clk_prepare only ensures that parents are prepared
385  * enable - clk_enable only ensures that parents are enabled
386  * rate - rate is adjustable.  clk->rate = parent->rate * mult / 32
387  * parent - fixed parent.  No clk_set_parent support
388  */
389 #define CPG_FRQCRC_ZFC_MASK (0x1f << 8)
390 #define CPG_FRQCRC_ZFC_SHIFT 8
391 #define CPG_FRQCRC_Z2FC_MASK 0x1f
392 #define Z_CLK_MAX_THRESHOLD 1500000000U
393 #define Z2_CLK_MAX_THRESHOLD 1200000000U
394 
395 extern int32_t rcar_iic_dvfs_receive(
396     uint8_t subordinate,
397     uint8_t reg,
398     uint8_t *data);
399 extern int32_t rcar_iic_dvfs_send(
400     uint8_t subordinate,
401     uint8_t regr,
402     uint8_t data);
403 
404 /*!
405  * @endcond
406  */
407 
408 /*!
409  * @}
410  */
411 
412 /*!
413  * @}
414  */
415 
416 #endif /* MOD_RCAR_CLOCK_H */
417