1 /* SPDX-License-Identifier: GPL-2.0-only */ 2 3 #ifndef _ZL3073X_CORE_H 4 #define _ZL3073X_CORE_H 5 6 #include <linux/bitfield.h> 7 #include <linux/kthread.h> 8 #include <linux/list.h> 9 #include <linux/mutex.h> 10 #include <linux/types.h> 11 12 #include "regs.h" 13 14 struct device; 15 struct regmap; 16 struct zl3073x_dpll; 17 18 /* 19 * Hardware limits for ZL3073x chip family 20 */ 21 #define ZL3073X_MAX_CHANNELS 5 22 #define ZL3073X_NUM_REFS 10 23 #define ZL3073X_NUM_OUTS 10 24 #define ZL3073X_NUM_SYNTHS 5 25 #define ZL3073X_NUM_INPUT_PINS ZL3073X_NUM_REFS 26 #define ZL3073X_NUM_OUTPUT_PINS (ZL3073X_NUM_OUTS * 2) 27 #define ZL3073X_NUM_PINS (ZL3073X_NUM_INPUT_PINS + \ 28 ZL3073X_NUM_OUTPUT_PINS) 29 30 /** 31 * struct zl3073x_ref - input reference invariant info 32 * @enabled: input reference is enabled or disabled 33 * @diff: true if input reference is differential 34 * @ffo: current fractional frequency offset 35 */ 36 struct zl3073x_ref { 37 bool enabled; 38 bool diff; 39 s64 ffo; 40 }; 41 42 /** 43 * struct zl3073x_out - output invariant info 44 * @enabled: out is enabled or disabled 45 * @synth: synthesizer the out is connected to 46 * @signal_format: out signal format 47 */ 48 struct zl3073x_out { 49 bool enabled; 50 u8 synth; 51 u8 signal_format; 52 }; 53 54 /** 55 * struct zl3073x_synth - synthesizer invariant info 56 * @freq: synthesizer frequency 57 * @dpll: ID of DPLL the synthesizer is driven by 58 * @enabled: synth is enabled or disabled 59 */ 60 struct zl3073x_synth { 61 u32 freq; 62 u8 dpll; 63 bool enabled; 64 }; 65 66 /** 67 * struct zl3073x_dev - zl3073x device 68 * @dev: pointer to device 69 * @regmap: regmap to access device registers 70 * @multiop_lock: to serialize multiple register operations 71 * @ref: array of input references' invariants 72 * @out: array of outs' invariants 73 * @synth: array of synths' invariants 74 * @dplls: list of DPLLs 75 * @kworker: thread for periodic work 76 * @work: periodic work 77 * @clock_id: clock id of the device 78 * @phase_avg_factor: phase offset measurement averaging factor 79 */ 80 struct zl3073x_dev { 81 struct device *dev; 82 struct regmap *regmap; 83 struct mutex multiop_lock; 84 85 /* Invariants */ 86 struct zl3073x_ref ref[ZL3073X_NUM_REFS]; 87 struct zl3073x_out out[ZL3073X_NUM_OUTS]; 88 struct zl3073x_synth synth[ZL3073X_NUM_SYNTHS]; 89 90 /* DPLL channels */ 91 struct list_head dplls; 92 93 /* Monitor */ 94 struct kthread_worker *kworker; 95 struct kthread_delayed_work work; 96 97 /* Devlink parameters */ 98 u64 clock_id; 99 u8 phase_avg_factor; 100 }; 101 102 struct zl3073x_chip_info { 103 const u16 *ids; 104 size_t num_ids; 105 int num_channels; 106 }; 107 108 extern const struct zl3073x_chip_info zl30731_chip_info; 109 extern const struct zl3073x_chip_info zl30732_chip_info; 110 extern const struct zl3073x_chip_info zl30733_chip_info; 111 extern const struct zl3073x_chip_info zl30734_chip_info; 112 extern const struct zl3073x_chip_info zl30735_chip_info; 113 extern const struct regmap_config zl3073x_regmap_config; 114 115 struct zl3073x_dev *zl3073x_devm_alloc(struct device *dev); 116 int zl3073x_dev_probe(struct zl3073x_dev *zldev, 117 const struct zl3073x_chip_info *chip_info); 118 119 int zl3073x_dev_start(struct zl3073x_dev *zldev, bool full); 120 void zl3073x_dev_stop(struct zl3073x_dev *zldev); 121 122 static inline u8 zl3073x_dev_phase_avg_factor_get(struct zl3073x_dev *zldev) 123 { 124 return zldev->phase_avg_factor; 125 } 126 127 int zl3073x_dev_phase_avg_factor_set(struct zl3073x_dev *zldev, u8 factor); 128 129 /********************** 130 * Registers operations 131 **********************/ 132 133 /** 134 * struct zl3073x_hwreg_seq_item - HW register write sequence item 135 * @addr: HW register to be written 136 * @value: value to be written to HW register 137 * @mask: bitmask indicating bits to be updated 138 * @wait: number of ms to wait after register write 139 */ 140 struct zl3073x_hwreg_seq_item { 141 u32 addr; 142 u32 value; 143 u32 mask; 144 u32 wait; 145 }; 146 147 #define HWREG_SEQ_ITEM(_addr, _value, _mask, _wait) \ 148 { \ 149 .addr = _addr, \ 150 .value = FIELD_PREP_CONST(_mask, _value), \ 151 .mask = _mask, \ 152 .wait = _wait, \ 153 } 154 155 int zl3073x_mb_op(struct zl3073x_dev *zldev, unsigned int op_reg, u8 op_val, 156 unsigned int mask_reg, u16 mask_val); 157 int zl3073x_poll_zero_u8(struct zl3073x_dev *zldev, unsigned int reg, u8 mask); 158 int zl3073x_read_u8(struct zl3073x_dev *zldev, unsigned int reg, u8 *val); 159 int zl3073x_read_u16(struct zl3073x_dev *zldev, unsigned int reg, u16 *val); 160 int zl3073x_read_u32(struct zl3073x_dev *zldev, unsigned int reg, u32 *val); 161 int zl3073x_read_u48(struct zl3073x_dev *zldev, unsigned int reg, u64 *val); 162 int zl3073x_write_u8(struct zl3073x_dev *zldev, unsigned int reg, u8 val); 163 int zl3073x_write_u16(struct zl3073x_dev *zldev, unsigned int reg, u16 val); 164 int zl3073x_write_u32(struct zl3073x_dev *zldev, unsigned int reg, u32 val); 165 int zl3073x_write_u48(struct zl3073x_dev *zldev, unsigned int reg, u64 val); 166 int zl3073x_read_hwreg(struct zl3073x_dev *zldev, u32 addr, u32 *value); 167 int zl3073x_write_hwreg(struct zl3073x_dev *zldev, u32 addr, u32 value); 168 int zl3073x_update_hwreg(struct zl3073x_dev *zldev, u32 addr, u32 value, 169 u32 mask); 170 int zl3073x_write_hwreg_seq(struct zl3073x_dev *zldev, 171 const struct zl3073x_hwreg_seq_item *seq, 172 size_t num_items); 173 174 /***************** 175 * Misc operations 176 *****************/ 177 178 int zl3073x_ref_freq_factorize(u32 freq, u16 *base, u16 *mult); 179 int zl3073x_ref_phase_offsets_update(struct zl3073x_dev *zldev, int channel); 180 181 static inline bool 182 zl3073x_is_n_pin(u8 id) 183 { 184 /* P-pins ids are even while N-pins are odd */ 185 return id & 1; 186 } 187 188 static inline bool 189 zl3073x_is_p_pin(u8 id) 190 { 191 return !zl3073x_is_n_pin(id); 192 } 193 194 /** 195 * zl3073x_input_pin_ref_get - get reference for given input pin 196 * @id: input pin id 197 * 198 * Return: reference id for the given input pin 199 */ 200 static inline u8 201 zl3073x_input_pin_ref_get(u8 id) 202 { 203 return id; 204 } 205 206 /** 207 * zl3073x_output_pin_out_get - get output for the given output pin 208 * @id: output pin id 209 * 210 * Return: output id for the given output pin 211 */ 212 static inline u8 213 zl3073x_output_pin_out_get(u8 id) 214 { 215 /* Output pin pair shares the single output */ 216 return id / 2; 217 } 218 219 /** 220 * zl3073x_ref_ffo_get - get current fractional frequency offset 221 * @zldev: pointer to zl3073x device 222 * @index: input reference index 223 * 224 * Return: the latest measured fractional frequency offset 225 */ 226 static inline s64 227 zl3073x_ref_ffo_get(struct zl3073x_dev *zldev, u8 index) 228 { 229 return zldev->ref[index].ffo; 230 } 231 232 /** 233 * zl3073x_ref_is_diff - check if the given input reference is differential 234 * @zldev: pointer to zl3073x device 235 * @index: input reference index 236 * 237 * Return: true if reference is differential, false if reference is single-ended 238 */ 239 static inline bool 240 zl3073x_ref_is_diff(struct zl3073x_dev *zldev, u8 index) 241 { 242 return zldev->ref[index].diff; 243 } 244 245 /** 246 * zl3073x_ref_is_enabled - check if the given input reference is enabled 247 * @zldev: pointer to zl3073x device 248 * @index: input reference index 249 * 250 * Return: true if input refernce is enabled, false otherwise 251 */ 252 static inline bool 253 zl3073x_ref_is_enabled(struct zl3073x_dev *zldev, u8 index) 254 { 255 return zldev->ref[index].enabled; 256 } 257 258 /** 259 * zl3073x_synth_dpll_get - get DPLL ID the synth is driven by 260 * @zldev: pointer to zl3073x device 261 * @index: synth index 262 * 263 * Return: ID of DPLL the given synthetizer is driven by 264 */ 265 static inline u8 266 zl3073x_synth_dpll_get(struct zl3073x_dev *zldev, u8 index) 267 { 268 return zldev->synth[index].dpll; 269 } 270 271 /** 272 * zl3073x_synth_freq_get - get synth current freq 273 * @zldev: pointer to zl3073x device 274 * @index: synth index 275 * 276 * Return: frequency of given synthetizer 277 */ 278 static inline u32 279 zl3073x_synth_freq_get(struct zl3073x_dev *zldev, u8 index) 280 { 281 return zldev->synth[index].freq; 282 } 283 284 /** 285 * zl3073x_synth_is_enabled - check if the given synth is enabled 286 * @zldev: pointer to zl3073x device 287 * @index: synth index 288 * 289 * Return: true if synth is enabled, false otherwise 290 */ 291 static inline bool 292 zl3073x_synth_is_enabled(struct zl3073x_dev *zldev, u8 index) 293 { 294 return zldev->synth[index].enabled; 295 } 296 297 /** 298 * zl3073x_out_synth_get - get synth connected to given output 299 * @zldev: pointer to zl3073x device 300 * @index: output index 301 * 302 * Return: index of synth connected to given output. 303 */ 304 static inline u8 305 zl3073x_out_synth_get(struct zl3073x_dev *zldev, u8 index) 306 { 307 return zldev->out[index].synth; 308 } 309 310 /** 311 * zl3073x_out_is_enabled - check if the given output is enabled 312 * @zldev: pointer to zl3073x device 313 * @index: output index 314 * 315 * Return: true if the output is enabled, false otherwise 316 */ 317 static inline bool 318 zl3073x_out_is_enabled(struct zl3073x_dev *zldev, u8 index) 319 { 320 u8 synth; 321 322 /* Output is enabled only if associated synth is enabled */ 323 synth = zl3073x_out_synth_get(zldev, index); 324 if (zl3073x_synth_is_enabled(zldev, synth)) 325 return zldev->out[index].enabled; 326 327 return false; 328 } 329 330 /** 331 * zl3073x_out_signal_format_get - get output signal format 332 * @zldev: pointer to zl3073x device 333 * @index: output index 334 * 335 * Return: signal format of given output 336 */ 337 static inline u8 338 zl3073x_out_signal_format_get(struct zl3073x_dev *zldev, u8 index) 339 { 340 return zldev->out[index].signal_format; 341 } 342 343 /** 344 * zl3073x_out_dpll_get - get DPLL ID the output is driven by 345 * @zldev: pointer to zl3073x device 346 * @index: output index 347 * 348 * Return: ID of DPLL the given output is driven by 349 */ 350 static inline 351 u8 zl3073x_out_dpll_get(struct zl3073x_dev *zldev, u8 index) 352 { 353 u8 synth; 354 355 /* Get synthesizer connected to given output */ 356 synth = zl3073x_out_synth_get(zldev, index); 357 358 /* Return DPLL that drives the synth */ 359 return zl3073x_synth_dpll_get(zldev, synth); 360 } 361 362 /** 363 * zl3073x_out_is_diff - check if the given output is differential 364 * @zldev: pointer to zl3073x device 365 * @index: output index 366 * 367 * Return: true if output is differential, false if output is single-ended 368 */ 369 static inline bool 370 zl3073x_out_is_diff(struct zl3073x_dev *zldev, u8 index) 371 { 372 switch (zl3073x_out_signal_format_get(zldev, index)) { 373 case ZL_OUTPUT_MODE_SIGNAL_FORMAT_LVDS: 374 case ZL_OUTPUT_MODE_SIGNAL_FORMAT_DIFF: 375 case ZL_OUTPUT_MODE_SIGNAL_FORMAT_LOWVCM: 376 return true; 377 default: 378 break; 379 } 380 381 return false; 382 } 383 384 /** 385 * zl3073x_output_pin_is_enabled - check if the given output pin is enabled 386 * @zldev: pointer to zl3073x device 387 * @id: output pin id 388 * 389 * Checks if the output of the given output pin is enabled and also that 390 * its signal format also enables the given pin. 391 * 392 * Return: true if output pin is enabled, false if output pin is disabled 393 */ 394 static inline bool 395 zl3073x_output_pin_is_enabled(struct zl3073x_dev *zldev, u8 id) 396 { 397 u8 output = zl3073x_output_pin_out_get(id); 398 399 /* Check if the whole output is enabled */ 400 if (!zl3073x_out_is_enabled(zldev, output)) 401 return false; 402 403 /* Check signal format */ 404 switch (zl3073x_out_signal_format_get(zldev, output)) { 405 case ZL_OUTPUT_MODE_SIGNAL_FORMAT_DISABLED: 406 /* Both output pins are disabled by signal format */ 407 return false; 408 409 case ZL_OUTPUT_MODE_SIGNAL_FORMAT_1P: 410 /* Output is one single ended P-pin output */ 411 if (zl3073x_is_n_pin(id)) 412 return false; 413 break; 414 case ZL_OUTPUT_MODE_SIGNAL_FORMAT_1N: 415 /* Output is one single ended N-pin output */ 416 if (zl3073x_is_p_pin(id)) 417 return false; 418 break; 419 default: 420 /* For other format both pins are enabled */ 421 break; 422 } 423 424 return true; 425 } 426 427 #endif /* _ZL3073X_CORE_H */ 428