Kongyang Liu | 80bf1f7 | 2024-06-11 17:41:14 +0800 | [diff] [blame] | 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__ */ |