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