1 /* SPDX-License-Identifier: GPL-2.0-only */ 2 /* 3 * Copyright (c) 2024 SpacemiT Technology Co. Ltd 4 * Copyright (c) 2024-2025 Haylen Chu <heylenay@4d2.org> 5 */ 6 7 #ifndef _CCU_PLL_H_ 8 #define _CCU_PLL_H_ 9 10 #include <linux/clk-provider.h> 11 12 #include "ccu_common.h" 13 14 /** 15 * struct ccu_pll_rate_tbl - Structure mapping between PLL rate and register 16 * configuration. 17 * 18 * @rate: PLL rate 19 * @swcr1: Value of register PLLx_SW1_CTRL. 20 * @swcr2: Value of register PLLAx_SW2_CTRL. 21 * @swcr3: value of register PLLx_SW3_CTRL. 22 * 23 * See below tables for the register used in PPL/PPLA clocks 24 * 25 * Regular PLL type 26 * | Enable | swcr3 | PLLx_SW3_CTRL - BIT[31] | 27 * ----------------------------------------------- 28 * | Config | swcr1 | PLLx_SW1_CTRL - BIT[31:0] | 29 * | | swcr2 | Not used | 30 * | | swcr3 | PLLx_SW3_CTRL - BIT[30:0] | 31 * 32 * Special PLL type A 33 * | Enable | swcr2 | PLLAx_SW2_CTRL - BIT[16] | 34 * ----------------------------------------------- 35 * | Config | swcr1 | PLLAx_SW1_CTRL - BIT[31:0] | 36 * | | swcr2 | PLLAx_SW2_CTRL - BIT[15:8] | 37 * | | swcr3 | PLLAx_SW3_CTRL - BIT[31:0] | 38 * 39 */ 40 struct ccu_pll_rate_tbl { 41 unsigned long rate; 42 u32 swcr1; 43 u32 swcr2; 44 u32 swcr3; 45 }; 46 47 struct ccu_pll_config { 48 const struct ccu_pll_rate_tbl *rate_tbl; 49 u32 tbl_num; 50 u32 reg_lock; 51 u32 mask_lock; 52 }; 53 54 #define CCU_PLL_RATE(_rate, _swcr1, _swcr3) \ 55 { \ 56 .rate = _rate, \ 57 .swcr1 = _swcr1, \ 58 .swcr3 = _swcr3, \ 59 } 60 61 #define CCU_PLLA_RATE(_rate, _swcr1, _swcr2, _swcr3) \ 62 { \ 63 .rate = _rate, \ 64 .swcr1 = _swcr1, \ 65 .swcr2 = _swcr2, \ 66 .swcr3 = _swcr3, \ 67 } 68 69 struct ccu_pll { 70 struct ccu_common common; 71 struct ccu_pll_config config; 72 }; 73 74 #define CCU_PLL_CONFIG(_table, _reg_lock, _mask_lock) \ 75 { \ 76 .rate_tbl = _table, \ 77 .tbl_num = ARRAY_SIZE(_table), \ 78 .reg_lock = (_reg_lock), \ 79 .mask_lock = (_mask_lock), \ 80 } 81 82 #define CCU_PLL_COMMON_HWINIT(_name, _ops, _flags) \ 83 (&(struct clk_init_data) { \ 84 .name = #_name, \ 85 .ops = _ops, \ 86 .parent_data = &(struct clk_parent_data) { .index = 0 }, \ 87 .num_parents = 1, \ 88 .flags = _flags, \ 89 }) 90 91 #define CCU_PLL_X_DEFINE(_name, _table, _reg_swcr1, _reg_swcr2, _reg_swcr3, \ 92 _reg_lock, _mask_lock, _ops, _flags) \ 93 static struct ccu_pll _name = { \ 94 .config = CCU_PLL_CONFIG(_table, _reg_lock, _mask_lock), \ 95 .common = { \ 96 .reg_swcr1 = _reg_swcr1, \ 97 .reg_swcr2 = _reg_swcr2, \ 98 .reg_swcr3 = _reg_swcr3, \ 99 .hw.init = CCU_PLL_COMMON_HWINIT(_name, _ops, _flags) \ 100 } \ 101 } 102 103 #define CCU_PLL_DEFINE(_name, _table, _reg_swcr1, _reg_swcr3, _reg_lock, \ 104 _mask_lock, _flags) \ 105 CCU_PLL_X_DEFINE(_name, _table, _reg_swcr1, 0, _reg_swcr3, \ 106 _reg_lock, _mask_lock, &spacemit_ccu_pll_ops, _flags) 107 108 #define CCU_PLLA_DEFINE(_name, _table, _reg_swcr1, _reg_swcr2, _reg_swcr3, \ 109 _reg_lock, _mask_lock, _flags) \ 110 CCU_PLL_X_DEFINE(_name, _table, _reg_swcr1, _reg_swcr2, _reg_swcr3, \ 111 _reg_lock, _mask_lock, &spacemit_ccu_plla_ops, _flags) 112 113 static inline struct ccu_pll *hw_to_ccu_pll(struct clk_hw *hw) 114 { 115 struct ccu_common *common = hw_to_ccu_common(hw); 116 117 return container_of(common, struct ccu_pll, common); 118 } 119 120 extern const struct clk_ops spacemit_ccu_pll_ops; 121 extern const struct clk_ops spacemit_ccu_plla_ops; 122 123 #endif 124