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