1 /* SPDX-License-Identifier: GPL-2.0+ */ 2 /* 3 * Copyright (c) 2024, Kongyang Liu <seashell11234455@gmail.com> 4 * 5 */ 6 7 #ifndef __CLK_SOPHGO_IP_H__ 8 #define __CLK_SOPHGO_IP_H__ 9 10 #include <clk.h> 11 12 #include "clk-common.h" 13 14 struct cv1800b_mmux_parent_info { 15 const char *name; 16 u8 clk_sel; 17 u8 index; 18 }; 19 20 struct cv1800b_clk_gate { 21 struct clk clk; 22 const char *name; 23 const char *parent_name; 24 void __iomem *base; 25 struct cv1800b_clk_regbit gate; 26 }; 27 28 struct cv1800b_clk_div { 29 struct clk clk; 30 const char *name; 31 const char *parent_name; 32 void __iomem *base; 33 struct cv1800b_clk_regbit gate; 34 struct cv1800b_clk_regfield div; 35 int div_init; 36 }; 37 38 struct cv1800b_clk_bypass_div { 39 struct cv1800b_clk_div div; 40 struct cv1800b_clk_regbit bypass; 41 }; 42 43 struct cv1800b_clk_fixed_div { 44 struct clk clk; 45 const char *name; 46 const char *parent_name; 47 void __iomem *base; 48 struct cv1800b_clk_regbit gate; 49 int div; 50 }; 51 52 struct cv1800b_clk_bypass_fixed_div { 53 struct cv1800b_clk_fixed_div div; 54 struct cv1800b_clk_regbit bypass; 55 }; 56 57 struct cv1800b_clk_mux { 58 struct clk clk; 59 const char *name; 60 const char * const *parent_names; 61 u8 num_parents; 62 void __iomem *base; 63 struct cv1800b_clk_regbit gate; 64 struct cv1800b_clk_regfield div; 65 int div_init; 66 struct cv1800b_clk_regfield mux; 67 }; 68 69 struct cv1800b_clk_bypass_mux { 70 struct cv1800b_clk_mux mux; 71 struct cv1800b_clk_regbit bypass; 72 }; 73 74 struct cv1800b_clk_mmux { 75 struct clk clk; 76 const char *name; 77 const struct cv1800b_mmux_parent_info *parent_infos; 78 u8 num_parents; 79 void __iomem *base; 80 struct cv1800b_clk_regbit gate; 81 struct cv1800b_clk_regfield div[2]; 82 int div_init[2]; 83 struct cv1800b_clk_regfield mux[2]; 84 struct cv1800b_clk_regbit bypass; 85 struct cv1800b_clk_regbit clk_sel; 86 }; 87 88 struct cv1800b_clk_audio { 89 struct clk clk; 90 const char *name; 91 const char *parent_name; 92 void __iomem *base; 93 struct cv1800b_clk_regbit src_en; 94 struct cv1800b_clk_regbit output_en; 95 struct cv1800b_clk_regbit div_en; 96 struct cv1800b_clk_regbit div_up; 97 struct cv1800b_clk_regfield m; 98 struct cv1800b_clk_regfield n; 99 }; 100 101 #define CV1800B_GATE(_id, _name, _parent, \ 102 _gate_offset, _gate_shift, \ 103 _flags) \ 104 { \ 105 .clk = { \ 106 .id = CV1800B_CLK_ID_TRANSFORM(_id), \ 107 .flags = _flags, \ 108 }, \ 109 .name = _name, \ 110 .parent_name = _parent, \ 111 .gate = CV1800B_CLK_REGBIT(_gate_offset, _gate_shift), \ 112 } 113 114 #define CV1800B_DIV(_id, _name, _parent, \ 115 _gate_offset, _gate_shift, \ 116 _div_offset, _div_shift, _div_width, \ 117 _div_init, _flags) \ 118 { \ 119 .clk = { \ 120 .id = CV1800B_CLK_ID_TRANSFORM(_id), \ 121 .flags = _flags, \ 122 }, \ 123 .name = _name, \ 124 .parent_name = _parent, \ 125 .gate = CV1800B_CLK_REGBIT(_gate_offset, _gate_shift), \ 126 .div = CV1800B_CLK_REGFIELD(_div_offset, _div_shift, \ 127 _div_width), \ 128 .div_init = _div_init, \ 129 } 130 131 #define CV1800B_BYPASS_DIV(_id, _name, _parent, \ 132 _gate_offset, _gate_shift, \ 133 _div_offset, _div_shift, \ 134 _div_width, _div_init, \ 135 _bypass_offset, _bypass_shift, \ 136 _flags) \ 137 { \ 138 .div = CV1800B_DIV(_id, _name, _parent, \ 139 _gate_offset, _gate_shift, \ 140 _div_offset, _div_shift, _div_width, \ 141 _div_init, _flags), \ 142 .bypass = CV1800B_CLK_REGBIT(_bypass_offset, \ 143 _bypass_shift), \ 144 } 145 146 #define CV1800B_FIXED_DIV(_id, _name, _parent, \ 147 _gate_offset, _gate_shift, \ 148 _div, _flags) \ 149 { \ 150 .clk = { \ 151 .id = CV1800B_CLK_ID_TRANSFORM(_id), \ 152 .flags = _flags, \ 153 }, \ 154 .name = _name, \ 155 .parent_name = _parent, \ 156 .gate = CV1800B_CLK_REGBIT(_gate_offset, _gate_shift), \ 157 .div = _div, \ 158 } 159 160 #define CV1800B_BYPASS_FIXED_DIV(_id, _name, _parent, \ 161 _gate_offset, _gate_shift, \ 162 _div, \ 163 _bypass_offset, _bypass_shift, \ 164 _flags) \ 165 { \ 166 .div = CV1800B_FIXED_DIV(_id, _name, _parent, \ 167 _gate_offset, _gate_shift, \ 168 _div, _flags), \ 169 .bypass = CV1800B_CLK_REGBIT(_bypass_offset, \ 170 _bypass_shift) \ 171 } 172 173 #define CV1800B_MUX(_id, _name, _parents, \ 174 _gate_offset, _gate_shift, \ 175 _div_offset, _div_shift, _div_width, _div_init, \ 176 _mux_offset, _mux_shift, _mux_width, \ 177 _flags) \ 178 { \ 179 .clk = { \ 180 .id = CV1800B_CLK_ID_TRANSFORM(_id), \ 181 .flags = _flags, \ 182 }, \ 183 .name = _name, \ 184 .parent_names = _parents, \ 185 .num_parents = ARRAY_SIZE(_parents), \ 186 .gate = CV1800B_CLK_REGBIT(_gate_offset, _gate_shift), \ 187 .div = CV1800B_CLK_REGFIELD(_div_offset, _div_shift, \ 188 _div_width), \ 189 .div_init = _div_init, \ 190 .mux = CV1800B_CLK_REGFIELD(_mux_offset, _mux_shift, \ 191 _mux_width), \ 192 } 193 194 #define CV1800B_BYPASS_MUX(_id, _name, _parents, \ 195 _gate_offset, _gate_shift, \ 196 _div_offset, _div_shift, \ 197 _div_width, _div_init, \ 198 _mux_offset, _mux_shift, _mux_width, \ 199 _bypass_offset, _bypass_shift, \ 200 _flags) \ 201 { \ 202 .mux = CV1800B_MUX(_id, _name, _parents, \ 203 _gate_offset, _gate_shift, \ 204 _div_offset, _div_shift, \ 205 _div_width, _div_init, \ 206 _mux_offset, _mux_shift, _mux_width, \ 207 _flags), \ 208 .bypass = CV1800B_CLK_REGBIT(_bypass_offset, \ 209 _bypass_shift), \ 210 } 211 212 #define CV1800B_MMUX(_id, _name, _parents, \ 213 _gate_offset, _gate_shift, \ 214 _div0_offset, _div0_shift, _div0_width, _div0_init,\ 215 _div1_offset, _div1_shift, _div1_width, _div1_init,\ 216 _mux0_offset, _mux0_shift, _mux0_width, \ 217 _mux1_offset, _mux1_shift, _mux1_width, \ 218 _bypass_offset, _bypass_shift, \ 219 _clk_sel_offset, _clk_sel_shift, \ 220 _flags) \ 221 { \ 222 .clk = { \ 223 .id = CV1800B_CLK_ID_TRANSFORM(_id), \ 224 .flags = _flags, \ 225 }, \ 226 .name = _name, \ 227 .parent_infos = _parents, \ 228 .num_parents = ARRAY_SIZE(_parents), \ 229 .gate = CV1800B_CLK_REGBIT(_gate_offset, _gate_shift), \ 230 .div = { \ 231 CV1800B_CLK_REGFIELD(_div0_offset, _div0_shift, \ 232 _div0_width), \ 233 CV1800B_CLK_REGFIELD(_div1_offset, _div1_shift, \ 234 _div1_width), \ 235 }, \ 236 .div_init = { _div0_init, _div1_init }, \ 237 .mux = { \ 238 CV1800B_CLK_REGFIELD(_mux0_offset, _mux0_shift, \ 239 _mux0_width), \ 240 CV1800B_CLK_REGFIELD(_mux1_offset, _mux1_shift, \ 241 _mux1_width), \ 242 }, \ 243 .bypass = CV1800B_CLK_REGBIT(_bypass_offset, \ 244 _bypass_shift), \ 245 .clk_sel = CV1800B_CLK_REGBIT(_clk_sel_offset, \ 246 _clk_sel_shift), \ 247 } 248 249 #define CV1800B_AUDIO(_id, _name, _parent, \ 250 _src_en_offset, _src_en_shift, \ 251 _output_en_offset, _output_en_shift, \ 252 _div_en_offset, _div_en_shift, \ 253 _div_up_offset, _div_up_shift, \ 254 _m_offset, _m_shift, _m_width, \ 255 _n_offset, _n_shift, _n_width, \ 256 _flags) \ 257 { \ 258 .clk = { \ 259 .id = CV1800B_CLK_ID_TRANSFORM(_id), \ 260 .flags = _flags, \ 261 }, \ 262 .name = _name, \ 263 .parent_name = _parent, \ 264 .src_en = CV1800B_CLK_REGBIT(_src_en_offset, \ 265 _src_en_shift), \ 266 .output_en = CV1800B_CLK_REGBIT(_output_en_offset, \ 267 _output_en_shift), \ 268 .div_en = CV1800B_CLK_REGBIT(_div_en_offset, \ 269 _div_en_shift), \ 270 .div_up = CV1800B_CLK_REGBIT(_div_up_offset, \ 271 _div_up_shift), \ 272 .m = CV1800B_CLK_REGFIELD(_m_offset, _m_shift, \ 273 _m_width), \ 274 .n = CV1800B_CLK_REGFIELD(_n_offset, _n_shift, \ 275 _n_width), \ 276 } 277 278 extern const struct clk_ops cv1800b_clk_gate_ops; 279 extern const struct clk_ops cv1800b_clk_div_ops; 280 extern const struct clk_ops cv1800b_clk_bypass_div_ops; 281 extern const struct clk_ops cv1800b_clk_fixed_div_ops; 282 extern const struct clk_ops cv1800b_clk_bypass_fixed_div_ops; 283 extern const struct clk_ops cv1800b_clk_mux_ops; 284 extern const struct clk_ops cv1800b_clk_bypass_mux_ops; 285 extern const struct clk_ops cv1800b_clk_mmux_ops; 286 extern const struct clk_ops cv1800b_clk_audio_ops; 287 288 #endif /* __CLK_SOPHGO_IP_H__ */ 289