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 * @clock_id: clock id of the device 72 * @ref: array of input references' invariants 73 * @out: array of outs' invariants 74 * @synth: array of synths' invariants 75 * @dplls: list of DPLLs 76 * @kworker: thread for periodic work 77 * @work: periodic work 78 */ 79 struct zl3073x_dev { 80 struct device *dev; 81 struct regmap *regmap; 82 struct mutex multiop_lock; 83 u64 clock_id; 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 98 struct zl3073x_chip_info { 99 const u16 *ids; 100 size_t num_ids; 101 int num_channels; 102 }; 103 104 extern const struct zl3073x_chip_info zl30731_chip_info; 105 extern const struct zl3073x_chip_info zl30732_chip_info; 106 extern const struct zl3073x_chip_info zl30733_chip_info; 107 extern const struct zl3073x_chip_info zl30734_chip_info; 108 extern const struct zl3073x_chip_info zl30735_chip_info; 109 extern const struct regmap_config zl3073x_regmap_config; 110 111 struct zl3073x_dev *zl3073x_devm_alloc(struct device *dev); 112 int zl3073x_dev_probe(struct zl3073x_dev *zldev, 113 const struct zl3073x_chip_info *chip_info); 114 115 int zl3073x_dev_start(struct zl3073x_dev *zldev, bool full); 116 void zl3073x_dev_stop(struct zl3073x_dev *zldev); 117 118 /********************** 119 * Registers operations 120 **********************/ 121 122 /** 123 * struct zl3073x_hwreg_seq_item - HW register write sequence item 124 * @addr: HW register to be written 125 * @value: value to be written to HW register 126 * @mask: bitmask indicating bits to be updated 127 * @wait: number of ms to wait after register write 128 */ 129 struct zl3073x_hwreg_seq_item { 130 u32 addr; 131 u32 value; 132 u32 mask; 133 u32 wait; 134 }; 135 136 #define HWREG_SEQ_ITEM(_addr, _value, _mask, _wait) \ 137 { \ 138 .addr = _addr, \ 139 .value = FIELD_PREP_CONST(_mask, _value), \ 140 .mask = _mask, \ 141 .wait = _wait, \ 142 } 143 144 int zl3073x_mb_op(struct zl3073x_dev *zldev, unsigned int op_reg, u8 op_val, 145 unsigned int mask_reg, u16 mask_val); 146 int zl3073x_poll_zero_u8(struct zl3073x_dev *zldev, unsigned int reg, u8 mask); 147 int zl3073x_read_u8(struct zl3073x_dev *zldev, unsigned int reg, u8 *val); 148 int zl3073x_read_u16(struct zl3073x_dev *zldev, unsigned int reg, u16 *val); 149 int zl3073x_read_u32(struct zl3073x_dev *zldev, unsigned int reg, u32 *val); 150 int zl3073x_read_u48(struct zl3073x_dev *zldev, unsigned int reg, u64 *val); 151 int zl3073x_write_u8(struct zl3073x_dev *zldev, unsigned int reg, u8 val); 152 int zl3073x_write_u16(struct zl3073x_dev *zldev, unsigned int reg, u16 val); 153 int zl3073x_write_u32(struct zl3073x_dev *zldev, unsigned int reg, u32 val); 154 int zl3073x_write_u48(struct zl3073x_dev *zldev, unsigned int reg, u64 val); 155 int zl3073x_read_hwreg(struct zl3073x_dev *zldev, u32 addr, u32 *value); 156 int zl3073x_write_hwreg(struct zl3073x_dev *zldev, u32 addr, u32 value); 157 int zl3073x_update_hwreg(struct zl3073x_dev *zldev, u32 addr, u32 value, 158 u32 mask); 159 int zl3073x_write_hwreg_seq(struct zl3073x_dev *zldev, 160 const struct zl3073x_hwreg_seq_item *seq, 161 size_t num_items); 162 163 /***************** 164 * Misc operations 165 *****************/ 166 167 int zl3073x_ref_freq_factorize(u32 freq, u16 *base, u16 *mult); 168 int zl3073x_ref_phase_offsets_update(struct zl3073x_dev *zldev, int channel); 169 170 static inline bool 171 zl3073x_is_n_pin(u8 id) 172 { 173 /* P-pins ids are even while N-pins are odd */ 174 return id & 1; 175 } 176 177 static inline bool 178 zl3073x_is_p_pin(u8 id) 179 { 180 return !zl3073x_is_n_pin(id); 181 } 182 183 /** 184 * zl3073x_input_pin_ref_get - get reference for given input pin 185 * @id: input pin id 186 * 187 * Return: reference id for the given input pin 188 */ 189 static inline u8 190 zl3073x_input_pin_ref_get(u8 id) 191 { 192 return id; 193 } 194 195 /** 196 * zl3073x_output_pin_out_get - get output for the given output pin 197 * @id: output pin id 198 * 199 * Return: output id for the given output pin 200 */ 201 static inline u8 202 zl3073x_output_pin_out_get(u8 id) 203 { 204 /* Output pin pair shares the single output */ 205 return id / 2; 206 } 207 208 /** 209 * zl3073x_ref_ffo_get - get current fractional frequency offset 210 * @zldev: pointer to zl3073x device 211 * @index: input reference index 212 * 213 * Return: the latest measured fractional frequency offset 214 */ 215 static inline s64 216 zl3073x_ref_ffo_get(struct zl3073x_dev *zldev, u8 index) 217 { 218 return zldev->ref[index].ffo; 219 } 220 221 /** 222 * zl3073x_ref_is_diff - check if the given input reference is differential 223 * @zldev: pointer to zl3073x device 224 * @index: input reference index 225 * 226 * Return: true if reference is differential, false if reference is single-ended 227 */ 228 static inline bool 229 zl3073x_ref_is_diff(struct zl3073x_dev *zldev, u8 index) 230 { 231 return zldev->ref[index].diff; 232 } 233 234 /** 235 * zl3073x_ref_is_enabled - check if the given input reference is enabled 236 * @zldev: pointer to zl3073x device 237 * @index: input reference index 238 * 239 * Return: true if input refernce is enabled, false otherwise 240 */ 241 static inline bool 242 zl3073x_ref_is_enabled(struct zl3073x_dev *zldev, u8 index) 243 { 244 return zldev->ref[index].enabled; 245 } 246 247 /** 248 * zl3073x_synth_dpll_get - get DPLL ID the synth is driven by 249 * @zldev: pointer to zl3073x device 250 * @index: synth index 251 * 252 * Return: ID of DPLL the given synthetizer is driven by 253 */ 254 static inline u8 255 zl3073x_synth_dpll_get(struct zl3073x_dev *zldev, u8 index) 256 { 257 return zldev->synth[index].dpll; 258 } 259 260 /** 261 * zl3073x_synth_freq_get - get synth current freq 262 * @zldev: pointer to zl3073x device 263 * @index: synth index 264 * 265 * Return: frequency of given synthetizer 266 */ 267 static inline u32 268 zl3073x_synth_freq_get(struct zl3073x_dev *zldev, u8 index) 269 { 270 return zldev->synth[index].freq; 271 } 272 273 /** 274 * zl3073x_synth_is_enabled - check if the given synth is enabled 275 * @zldev: pointer to zl3073x device 276 * @index: synth index 277 * 278 * Return: true if synth is enabled, false otherwise 279 */ 280 static inline bool 281 zl3073x_synth_is_enabled(struct zl3073x_dev *zldev, u8 index) 282 { 283 return zldev->synth[index].enabled; 284 } 285 286 /** 287 * zl3073x_out_synth_get - get synth connected to given output 288 * @zldev: pointer to zl3073x device 289 * @index: output index 290 * 291 * Return: index of synth connected to given output. 292 */ 293 static inline u8 294 zl3073x_out_synth_get(struct zl3073x_dev *zldev, u8 index) 295 { 296 return zldev->out[index].synth; 297 } 298 299 /** 300 * zl3073x_out_is_enabled - check if the given output is enabled 301 * @zldev: pointer to zl3073x device 302 * @index: output index 303 * 304 * Return: true if the output is enabled, false otherwise 305 */ 306 static inline bool 307 zl3073x_out_is_enabled(struct zl3073x_dev *zldev, u8 index) 308 { 309 u8 synth; 310 311 /* Output is enabled only if associated synth is enabled */ 312 synth = zl3073x_out_synth_get(zldev, index); 313 if (zl3073x_synth_is_enabled(zldev, synth)) 314 return zldev->out[index].enabled; 315 316 return false; 317 } 318 319 /** 320 * zl3073x_out_signal_format_get - get output signal format 321 * @zldev: pointer to zl3073x device 322 * @index: output index 323 * 324 * Return: signal format of given output 325 */ 326 static inline u8 327 zl3073x_out_signal_format_get(struct zl3073x_dev *zldev, u8 index) 328 { 329 return zldev->out[index].signal_format; 330 } 331 332 /** 333 * zl3073x_out_dpll_get - get DPLL ID the output is driven by 334 * @zldev: pointer to zl3073x device 335 * @index: output index 336 * 337 * Return: ID of DPLL the given output is driven by 338 */ 339 static inline 340 u8 zl3073x_out_dpll_get(struct zl3073x_dev *zldev, u8 index) 341 { 342 u8 synth; 343 344 /* Get synthesizer connected to given output */ 345 synth = zl3073x_out_synth_get(zldev, index); 346 347 /* Return DPLL that drives the synth */ 348 return zl3073x_synth_dpll_get(zldev, synth); 349 } 350 351 /** 352 * zl3073x_out_is_diff - check if the given output is differential 353 * @zldev: pointer to zl3073x device 354 * @index: output index 355 * 356 * Return: true if output is differential, false if output is single-ended 357 */ 358 static inline bool 359 zl3073x_out_is_diff(struct zl3073x_dev *zldev, u8 index) 360 { 361 switch (zl3073x_out_signal_format_get(zldev, index)) { 362 case ZL_OUTPUT_MODE_SIGNAL_FORMAT_LVDS: 363 case ZL_OUTPUT_MODE_SIGNAL_FORMAT_DIFF: 364 case ZL_OUTPUT_MODE_SIGNAL_FORMAT_LOWVCM: 365 return true; 366 default: 367 break; 368 } 369 370 return false; 371 } 372 373 /** 374 * zl3073x_output_pin_is_enabled - check if the given output pin is enabled 375 * @zldev: pointer to zl3073x device 376 * @id: output pin id 377 * 378 * Checks if the output of the given output pin is enabled and also that 379 * its signal format also enables the given pin. 380 * 381 * Return: true if output pin is enabled, false if output pin is disabled 382 */ 383 static inline bool 384 zl3073x_output_pin_is_enabled(struct zl3073x_dev *zldev, u8 id) 385 { 386 u8 output = zl3073x_output_pin_out_get(id); 387 388 /* Check if the whole output is enabled */ 389 if (!zl3073x_out_is_enabled(zldev, output)) 390 return false; 391 392 /* Check signal format */ 393 switch (zl3073x_out_signal_format_get(zldev, output)) { 394 case ZL_OUTPUT_MODE_SIGNAL_FORMAT_DISABLED: 395 /* Both output pins are disabled by signal format */ 396 return false; 397 398 case ZL_OUTPUT_MODE_SIGNAL_FORMAT_1P: 399 /* Output is one single ended P-pin output */ 400 if (zl3073x_is_n_pin(id)) 401 return false; 402 break; 403 case ZL_OUTPUT_MODE_SIGNAL_FORMAT_1N: 404 /* Output is one single ended N-pin output */ 405 if (zl3073x_is_p_pin(id)) 406 return false; 407 break; 408 default: 409 /* For other format both pins are enabled */ 410 break; 411 } 412 413 return true; 414 } 415 416 #endif /* _ZL3073X_CORE_H */ 417