hc
2024-02-20 102a0743326a03cd1a1202ceda21e175b7d3575c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
/* SPDX-License-Identifier: GPL-2.0 */
/*
 * Copyright (C) 2022 Rockchip Electronics Co. Ltd.
 *
 * Author: Joseph Chen <chenjh@rock-chips.com>
 */
 
#ifndef _CRU_CORE_H_
#define _CRU_CORE_H_
 
#include "hal_def.h"
#include "hal_os_def.h"
 
#define DEBUG_CRU_INIT 0
#define CRU_LOGLEVEL   3
 
#define __cru_print(level, fmt, ...)                                        \
({                                                                          \
    level < CRU_LOGLEVEL ? HAL_SYSLOG("[HAL CRU] " fmt, ##__VA_ARGS__) : 0; \
})
#define CRU_ERR(fmt, ...)  __cru_print(0, "ERROR: " fmt, ##__VA_ARGS__)
#define CRU_WARN(fmt, ...) __cru_print(1, "WARN: " fmt, ##__VA_ARGS__)
#define CRU_MSG(fmt, ...)  __cru_print(2, fmt, ##__VA_ARGS__)
#define CRU_DBG(fmt, ...)  __cru_print(3, fmt, ##__VA_ARGS__) /* driver */
#define CRU_DBGF(fmt, ...) __cru_print(4, fmt, ##__VA_ARGS__) /* core function */
#define CRU_DBGR(fmt, ...) __cru_print(5, fmt, ##__VA_ARGS__) /* core register */
 
#define HAL_ENABLE_SET_RATE_VERIFY 0
 
#define _MHZ(n)           ((n) * 1000000U)
#define OSC_24M           _MHZ(24)
#define HAL_HWCLK_MAX_NUM 16
#define PLL_MAX_NUM       2
 
typedef enum {
    RKX110_CPLL = 0,
    RKX110_RXPLL,
    RKX120_CPLL = 0,
    RKX120_TXPLL,
} HAL_PLLType;
 
typedef enum {
    CLK_UNDEF,
    CLK_RKX110,
    CLK_RKX120,
    CLK_ALL,
    CLK_MAX,
} HAL_ClockType;
 
/*
 * hwclk flags
 */
#define CLK_FLG_SET_RATE_VERIFY (1 << 0)  /* set and readback verify */
 
struct hwclk;
 
struct xferclk {
    HAL_ClockType type;
    u32 version;
    char *name; /* slave addr is expected */
    void *client;
    HAL_RegRead_t *read;
    HAL_RegWrite_t *write;
};
 
struct clkTable {
    uint8_t type;
    const char *name;
    uint32_t clk;
    const char * *parents;
    uint32_t numParents;
    const char *extParent;
    uint32_t (*getFreq)(struct hwclk *hw, uint32_t clockName);
};
 
struct clkOps {
    struct clkTable *clkTable;
    HAL_Status (*clkInit)(struct hwclk *hw, struct xferclk *xfer);
    HAL_Status (*clkInitTestout)(struct hwclk *hw, uint32_t clockName,
                                 uint32_t muxValue, uint32_t divValue);
    HAL_Status (*clkSetFreq)(struct hwclk *hw, uint32_t clockName, uint32_t rate);
    uint32_t (*clkGetFreq)(struct hwclk *hw, uint32_t clockName);
};
 
struct clkGate {
    uint8_t enable_count;
};
 
struct hwclk {
    char name[32];
    uint32_t flags;
    HAL_ClockType type;
    uint32_t pllRate[PLL_MAX_NUM];
 
    uint32_t cru_base;
    uint32_t gate_con0;
    uint32_t sel_con0;
    uint32_t softrst_con0;
    uint32_t gbl_srst_fst;
 
    struct xferclk xfer;
    struct clkOps *ops;
    struct clkGate *gate;
    uint32_t num_gate;
 
    HAL_Mutex lock;
};
 
#define MASK_TO_WE(msk)       ((msk) << 16)
#define VAL_MASK_WE(msk, val) ((MASK_TO_WE(msk)) | (val))
#define WRITE_REG_MASK_WE(reg, msk, val) \
                 WRITE_REG(reg, (VAL_MASK_WE(msk, val)))
 
#define _GENMASK(h, l)           (((~0UL) << (l)) & (~0UL >> (HAL_BITS_PER_LONG - 1 - (h))))
#define _GENVAL(x, h, l)         ((uint32_t)(((x) & _GENMASK(h, l)) >> (l)))
#define _GENVAL_D16(x, h, l)     ((uint32_t)(((x) & _GENMASK(h, l)) / 16))
#define _GENVAL_D16_REM(x, h, l) ((uint32_t)(((x) & _GENMASK(h, l)) % 16))
#define _WIDTH_TO_MASK(w)        ((1 << (w)) - 1)
 
/*
 * RESET/GATE fields:
 *   [31:16]: reserved
 *   [15:12]: bank
 *   [11:0]:  id
 */
#define CLK_RESET_GET_REG_OFFSET(x) _GENVAL_D16(x, 11, 0)
#define CLK_RESET_GET_BITS_SHIFT(x) _GENVAL_D16_REM(x, 11, 0)
#define CLK_RESET_GET_REG_BANK(x)   _GENVAL(x, 15, 12)
 
#define CLK_GATE_GET_REG_OFFSET(x) CLK_RESET_GET_REG_OFFSET(x)
#define CLK_GATE_GET_BITS_SHIFT(x) CLK_RESET_GET_BITS_SHIFT(x)
#define CLK_GATE_GET_REG_BANK(x)   CLK_RESET_GET_REG_BANK(x)
 
/*
 * MUX/DIV fields:
 *   [31:24]: width
 *   [23:16]: shift
 *   [15:12]: reserved
 *   [11:8]:  bank
 *   [7:0]:   reg
 */
#define CLK_MUX_GET_REG_OFFSET(x) _GENVAL(x, 7,  0)
#define CLK_MUX_GET_BANK(x)       _GENVAL(x, 11, 8)
#define CLK_MUX_GET_BITS_SHIFT(x) _GENVAL(x, 23, 16)
#define CLK_MUX_GET_WIDTH(x)      _GENVAL(x, 31, 24)
#define CLK_MUX_GET_MASK(x)       (_WIDTH_TO_MASK(CLK_MUX_GET_WIDTH(x)) << CLK_MUX_GET_BITS_SHIFT(x))
 
#define CLK_DIV_GET_REG_OFFSET(x) CLK_MUX_GET_REG_OFFSET(x)
#define CLK_DIV_GET_BANK(x)       CLK_MUX_GET_BANK(x)
#define CLK_DIV_GET_BITS_SHIFT(x) CLK_MUX_GET_BITS_SHIFT(x)
#define CLK_DIV_GET_WIDTH(x)      CLK_MUX_GET_WIDTH(x)
#define CLK_DIV_GET_MASK(x)       CLK_MUX_GET_MASK(x)
#define CLK_DIV_GET_MAXDIV(x)     ((1 << CLK_DIV_GET_WIDTH(x)) - 1)
 
#define CLK_GET_MUX(v32) \
        ((uint32_t)((v32) & 0x0F0F00FFU))
#define CLK_GET_DIV(v32)                           \
        ((uint32_t)((((v32) & 0x0000FF00U) >> 8) | \
        (((v32) & 0xF0F00000U) >> 4)))
#define COMPOSITE_CLK(mux, div)                           \
        (((mux) & 0x0F0F00FFU) | (((div) & 0xFFU) << 8) | \
        (((div) & 0x0F0F0000U) << 4))
 
#define PNAME(x) static const char *x[]
 
typedef enum {
    DUMP_UNDEF,
    DUMP_INT,
    DUMP_EXT,
} HAL_DumpType;
 
#define CLK_DECLARE(_type, _name, _clk, _parents, _numParents, _extParent, _getFreq) \
{                                                                                    \
    .type = _type,                                                                   \
    .name = _name,                                                                   \
    .clk = _clk,                                                                     \
    .parents = _parents,                                                             \
    .numParents = _numParents,                                                       \
    .extParent = _extParent,                                                         \
    .getFreq = _getFreq,                                                             \
}
 
#define CLK_DECLARE_INT(_name, _clk, _parents) \
    CLK_DECLARE(DUMP_INT, _name, _clk, _parents, HAL_ARRAY_SIZE(_parents), HAL_NULL, HAL_NULL)
 
#define CLK_DECLARE_EXT_PARENT(_name, _clk, _extParent, _getFreq) \
    CLK_DECLARE(DUMP_EXT, _name, _clk, HAL_NULL, 0, _extParent, _getFreq)
 
#define CLK_DECLARE_EXT(_name, _clk, _getFreq) \
    CLK_DECLARE_EXT_PARENT(_name, _clk, HAL_NULL, _getFreq)
 
#define RK_PLL_RATE(_rate, _refdiv, _fbdiv, _postdiv1, _postdiv2, _dsmpd, _frac) \
    {                                                                            \
        .rate = _rate##U, .fbDiv = _fbdiv, .postDiv1 = _postdiv1,                \
        .refDiv = _refdiv, .postDiv2 = _postdiv2, .dsmpd = _dsmpd,               \
        .frac = _frac,                                                           \
    }
 
#define DIV_NO_REM(pFreq, freq, maxDiv) \
        ((!((pFreq) % (freq))) && ((pFreq) / (freq) <= (maxDiv)))
 
#define HAL_DIV_ROUND_UP(x, y) (((x) + (y) - 1) / (y))
 
/***************************** Structure Definition **************************/
 
struct PLL_CONFIG {
    uint32_t rate;
 
    union {
        struct {
            uint32_t fbDiv;
            uint32_t postDiv1;
            uint32_t refDiv;
            uint32_t postDiv2;
            uint32_t dsmpd;
            uint32_t frac;
        };
    };
};
 
typedef enum {
    PLL_CPLL,
    PLL_RXPLL,
    PLL_TXPLL,
} eCRU_PLL;
 
struct PLL_SETUP {
    eCRU_PLL id;
    uint32_t conOffset0;
    uint32_t conOffset1;
    uint32_t conOffset2;
    uint32_t conOffset3;
    uint32_t conOffset6;
    uint32_t modeOffset;
    uint32_t stat0;
    uint32_t modeShift;
    uint32_t lockShift;
    uint32_t modeMask;
    const struct PLL_CONFIG *rateTable;
    uint8_t minRefdiv;
    uint8_t maxRefdiv;
    uint32_t minVco;
    uint32_t maxVco;
    uint32_t minFout;
    uint32_t maxFout;
    uint8_t sscgEn;
};
 
typedef enum {
    GLB_SRST_FST = 0xfdb9,
    GLB_SRST_SND = 0xeca8,
} eCRU_GlbSrstType;
 
/***************************** Function Declare ******************************/
uint32_t HAL_CRU_Read(struct hwclk *hw, uint32_t reg);
uint32_t HAL_CRU_Write(struct hwclk *hw, uint32_t reg, uint32_t val);
uint32_t HAL_CRU_WriteMask(struct hwclk *hw, uint32_t reg,
                           uint32_t msk, uint32_t val);
 
int HAL_CRU_FreqGetMux4(struct hwclk *hw,
                        uint32_t freq, uint32_t freq0,
                        uint32_t freq1, uint32_t freq2, uint32_t freq3);
int HAL_CRU_FreqGetMux3(struct hwclk *hw,
                        uint32_t freq, uint32_t freq0,
                        uint32_t freq1, uint32_t freq2);
int HAL_CRU_FreqGetMux2(struct hwclk *hw,
                        uint32_t freq, uint32_t freq0, uint32_t freq1);
 
uint32_t HAL_CRU_MuxGetFreq4(struct hwclk *hw, uint32_t muxName,
                             uint32_t freq0, uint32_t freq1,
                             uint32_t freq2, uint32_t freq3);
uint32_t HAL_CRU_MuxGetFreq3(struct hwclk *hw, uint32_t muxName,
                             uint32_t freq0, uint32_t freq1, uint32_t freq2);
uint32_t HAL_CRU_MuxGetFreq2(struct hwclk *hw, uint32_t muxName,
                             uint32_t freq0, uint32_t freq1);
 
int HAL_CRU_RoundFreqGetMux4(struct hwclk *hw, uint32_t freq,
                             uint32_t pFreq0, uint32_t pFreq1,
                             uint32_t pFreq2, uint32_t pFreq3, uint32_t *pFreqOut);
int HAL_CRU_RoundFreqGetMux3(struct hwclk *hw, uint32_t freq,
                             uint32_t pFreq0, uint32_t pFreq1,
                             uint32_t pFreq2, uint32_t *pFreqOut);
int HAL_CRU_RoundFreqGetMux2(struct hwclk *hw, uint32_t freq,
                             uint32_t pFreq0, uint32_t pFreq1, uint32_t *pFreqOut);
 
/**
 * @brief Get pll freq.
 * @param  pSetup: Contains PLL register parameters
 * @return pll rate.
 */
uint32_t HAL_CRU_GetPllFreq(struct hwclk *hw, struct PLL_SETUP *pSetup);
 
/**
 * @brief Set pll freq.
 * @param  pSetup: Contains PLL register parameters
 * @param  rate: pll set
 * @return HAL_Status.
 */
HAL_Status HAL_CRU_SetPllFreq(struct hwclk *hw, struct PLL_SETUP *pSetup, uint32_t rate);
 
/**
 * @brief Set pll power up.
 * @param  pSetup: Contains PLL register parameters
 * @return HAL_Status.
 */
HAL_Status HAL_CRU_SetPllPowerUp(struct hwclk *hw, struct PLL_SETUP *pSetup);
 
/**
 * @brief Set pll power down.
 * @param  pSetup: Contains PLL register parameters
 * @return HAL_Status.
 */
HAL_Status HAL_CRU_SetPllPowerDown(struct hwclk *hw, struct PLL_SETUP *pSetup);
 
/**
 * @brief Check if clk is enabled
 * @param  clk: clock to check
 * @return HAL_Check.
 */
HAL_Check HAL_CRU_ClkIsEnabled(struct hwclk *hw, uint32_t clk);
 
/**
 * @brief Enable clk
 * @param  clk: clock to set
 * @return HAL_Status.
 */
HAL_Status HAL_CRU_ClkEnable(struct hwclk *hw, uint32_t clk);
 
/**
 * @brief Disable clk
 * @param  clk: clock to set
 * @return HAL_Status.
 */
HAL_Status HAL_CRU_ClkDisable(struct hwclk *hw, uint32_t clk);
 
/**
 * @brief Check if clk is reset
 * @param  clk: clock to check
 * @return HAL_Check.
 */
HAL_Check HAL_CRU_ClkIsReset(struct hwclk *hw, uint32_t clk);
 
/**
 * @brief Assert the reset to the clk
 * @param  clk: clock to assert
 * @return HAL_Status.
 */
HAL_Status HAL_CRU_ClkResetAssert(struct hwclk *hw, uint32_t clk);
 
/**
 * @brief Deassert the reset to the clk
 * @param  clk: clock to deassert
 * @return HAL_Status.
 */
HAL_Status HAL_CRU_ClkResetDeassert(struct hwclk *hw, uint32_t clk);
 
/**
 * @brief  Set integer div
 * @param  divName: div id(struct hwclk *hw, Contains div offset, shift, mask information)
 * @param  divValue: div value
 * @return NONE
 */
HAL_Status HAL_CRU_ClkSetDiv(struct hwclk *hw, uint32_t divName, uint32_t divValue);
 
/**
 * @brief  Get integer div
 * @param  divName: div id (struct hwclk *hw,, Contains div offset, shift, mask information)
 * @return div value
 */
uint32_t HAL_CRU_ClkGetDiv(struct hwclk *hw, uint32_t divName);
 
/**
 * @brief  Set mux
 * @param  muxName: mux id (struct hwclk *hw,, Contains mux offset, shift, mask information)
 * @param  muxValue: mux value
 * @return NONE
 */
HAL_Status HAL_CRU_ClkSetMux(struct hwclk *hw, uint32_t muxName, uint32_t muxValue);
 
/**
 * @brief  Get mux
 * @param  muxName: mux id (struct hwclk *hw, Contains mux offset, shift, mask information)
 * @return mux value
 */
uint32_t HAL_CRU_ClkGetMux(struct hwclk *hw, uint32_t muxName);
 
/**
 * @brief Get clk freq.
 * @param  clockName: CLOCK_Name id.
 * @return rate.
 * @attention these APIs allow direct use in the HAL layer.
 */
uint32_t HAL_CRU_ClkGetFreq(struct hwclk *hw, uint32_t clockName);
 
/**
 * @brief Set clk freq.
 * @param  clockName: CLOCK_Name id.
 * @param  rate: clk rate.
 * @return HAL_Status.
 * @attention these APIs allow direct use in the HAL layer.
 */
HAL_Status HAL_CRU_ClkSetFreq(struct hwclk *hw, uint32_t clockName, uint32_t rate);
 
/**
 * @brief  assert CRU global software reset.
 * @param  type: global software reset type.
 * @return HAL_INVAL if the SoC does not support.
 */
HAL_Status HAL_CRU_SetGlbSrst(struct hwclk *hw, eCRU_GlbSrstType type);
 
/**
 * @brief  Set clk testout
 * @param  clockName: CLOCK_Name id.
 * @param  muxValue: mux value.
 * @param  divValue: div value.
 * @return HAL_INVAL if the SoC does not support.
 */
HAL_Status HAL_CRU_ClkSetTestout(struct hwclk *hw, uint32_t clockName,
                                 uint32_t muxValue, uint32_t divValue);
/**
 * @brief  Dump all clock tree
 */
void HAL_CRU_ClkDumpTree(HAL_ClockType type);
 
/**
 * @brief  CRU init for chip
 * @return HAL_INVAL if the SoC does not support.
 */
HAL_Status HAL_CRU_Init(void);
 
/**
 * @brief  Register CRU
 * @param  xfer: the data to register
 * @return hwclk descriptor.
 */
struct hwclk *HAL_CRU_Register(struct xferclk xfer);
 
/**
 * @brief  Get hwclk
 * @param  client: the unit data to find hwclk
 * @return hwclk descriptor.
 */
struct hwclk *HAL_CRU_ClkGet(void *client);
 
/************************** chip ops *************************************/
extern struct clkOps rkx110_clk_ops;
extern struct clkOps rkx120_clk_ops;
extern struct clkOps rkx111_clk_ops;
extern struct clkOps rkx121_clk_ops;
#endif