1*1b72c59dSHaylen Chu /* SPDX-License-Identifier: GPL-2.0-only */
2*1b72c59dSHaylen Chu /*
3*1b72c59dSHaylen Chu * Copyright (c) 2024 SpacemiT Technology Co. Ltd
4*1b72c59dSHaylen Chu * Copyright (c) 2024-2025 Haylen Chu <heylenay@4d2.org>
5*1b72c59dSHaylen Chu */
6*1b72c59dSHaylen Chu
7*1b72c59dSHaylen Chu #ifndef _CCU_PLL_H_
8*1b72c59dSHaylen Chu #define _CCU_PLL_H_
9*1b72c59dSHaylen Chu
10*1b72c59dSHaylen Chu #include <linux/clk-provider.h>
11*1b72c59dSHaylen Chu
12*1b72c59dSHaylen Chu #include "ccu_common.h"
13*1b72c59dSHaylen Chu
14*1b72c59dSHaylen Chu /**
15*1b72c59dSHaylen Chu * struct ccu_pll_rate_tbl - Structure mapping between PLL rate and register
16*1b72c59dSHaylen Chu * configuration.
17*1b72c59dSHaylen Chu *
18*1b72c59dSHaylen Chu * @rate: PLL rate
19*1b72c59dSHaylen Chu * @swcr1: Register value of PLLX_SW1_CTRL (PLLx_SWCR1).
20*1b72c59dSHaylen Chu * @swcr3: Register value of the PLLx_SW3_CTRL's lowest 31 bits of
21*1b72c59dSHaylen Chu * PLLx_SW3_CTRL (PLLx_SWCR3). This highest bit is for enabling
22*1b72c59dSHaylen Chu * the PLL and not contained in this field.
23*1b72c59dSHaylen Chu */
24*1b72c59dSHaylen Chu struct ccu_pll_rate_tbl {
25*1b72c59dSHaylen Chu unsigned long rate;
26*1b72c59dSHaylen Chu u32 swcr1;
27*1b72c59dSHaylen Chu u32 swcr3;
28*1b72c59dSHaylen Chu };
29*1b72c59dSHaylen Chu
30*1b72c59dSHaylen Chu struct ccu_pll_config {
31*1b72c59dSHaylen Chu const struct ccu_pll_rate_tbl *rate_tbl;
32*1b72c59dSHaylen Chu u32 tbl_num;
33*1b72c59dSHaylen Chu u32 reg_lock;
34*1b72c59dSHaylen Chu u32 mask_lock;
35*1b72c59dSHaylen Chu };
36*1b72c59dSHaylen Chu
37*1b72c59dSHaylen Chu #define CCU_PLL_RATE(_rate, _swcr1, _swcr3) \
38*1b72c59dSHaylen Chu { \
39*1b72c59dSHaylen Chu .rate = _rate, \
40*1b72c59dSHaylen Chu .swcr1 = _swcr1, \
41*1b72c59dSHaylen Chu .swcr3 = _swcr3, \
42*1b72c59dSHaylen Chu }
43*1b72c59dSHaylen Chu
44*1b72c59dSHaylen Chu struct ccu_pll {
45*1b72c59dSHaylen Chu struct ccu_common common;
46*1b72c59dSHaylen Chu struct ccu_pll_config config;
47*1b72c59dSHaylen Chu };
48*1b72c59dSHaylen Chu
49*1b72c59dSHaylen Chu #define CCU_PLL_CONFIG(_table, _reg_lock, _mask_lock) \
50*1b72c59dSHaylen Chu { \
51*1b72c59dSHaylen Chu .rate_tbl = _table, \
52*1b72c59dSHaylen Chu .tbl_num = ARRAY_SIZE(_table), \
53*1b72c59dSHaylen Chu .reg_lock = (_reg_lock), \
54*1b72c59dSHaylen Chu .mask_lock = (_mask_lock), \
55*1b72c59dSHaylen Chu }
56*1b72c59dSHaylen Chu
57*1b72c59dSHaylen Chu #define CCU_PLL_HWINIT(_name, _flags) \
58*1b72c59dSHaylen Chu (&(struct clk_init_data) { \
59*1b72c59dSHaylen Chu .name = #_name, \
60*1b72c59dSHaylen Chu .ops = &spacemit_ccu_pll_ops, \
61*1b72c59dSHaylen Chu .parent_data = &(struct clk_parent_data) { .index = 0 }, \
62*1b72c59dSHaylen Chu .num_parents = 1, \
63*1b72c59dSHaylen Chu .flags = _flags, \
64*1b72c59dSHaylen Chu })
65*1b72c59dSHaylen Chu
66*1b72c59dSHaylen Chu #define CCU_PLL_DEFINE(_name, _table, _reg_swcr1, _reg_swcr3, _reg_lock, \
67*1b72c59dSHaylen Chu _mask_lock, _flags) \
68*1b72c59dSHaylen Chu static struct ccu_pll _name = { \
69*1b72c59dSHaylen Chu .config = CCU_PLL_CONFIG(_table, _reg_lock, _mask_lock), \
70*1b72c59dSHaylen Chu .common = { \
71*1b72c59dSHaylen Chu .reg_swcr1 = _reg_swcr1, \
72*1b72c59dSHaylen Chu .reg_swcr3 = _reg_swcr3, \
73*1b72c59dSHaylen Chu .hw.init = CCU_PLL_HWINIT(_name, _flags) \
74*1b72c59dSHaylen Chu } \
75*1b72c59dSHaylen Chu }
76*1b72c59dSHaylen Chu
hw_to_ccu_pll(struct clk_hw * hw)77*1b72c59dSHaylen Chu static inline struct ccu_pll *hw_to_ccu_pll(struct clk_hw *hw)
78*1b72c59dSHaylen Chu {
79*1b72c59dSHaylen Chu struct ccu_common *common = hw_to_ccu_common(hw);
80*1b72c59dSHaylen Chu
81*1b72c59dSHaylen Chu return container_of(common, struct ccu_pll, common);
82*1b72c59dSHaylen Chu }
83*1b72c59dSHaylen Chu
84*1b72c59dSHaylen Chu extern const struct clk_ops spacemit_ccu_pll_ops;
85*1b72c59dSHaylen Chu
86*1b72c59dSHaylen Chu #endif
87