1 /* SPDX-License-Identifier: GPL-2.0-only */ 2 3 #ifndef _ZL3073X_CHAN_H 4 #define _ZL3073X_CHAN_H 5 6 #include <linux/bitfield.h> 7 #include <linux/stddef.h> 8 #include <linux/types.h> 9 10 #include "regs.h" 11 12 struct zl3073x_dev; 13 14 /** 15 * struct zl3073x_chan - DPLL channel state 16 * @mode_refsel: mode and reference selection register value 17 * @ref_prio: reference priority registers (4 bits per ref, P/N packed) 18 * @mon_status: monitor status register value 19 * @refsel_status: reference selection status register value 20 * @df_offset: frequency offset vs tracked reference in 2^-48 steps 21 */ 22 struct zl3073x_chan { 23 struct_group(cfg, 24 u8 mode_refsel; 25 u8 ref_prio[ZL3073X_NUM_REFS / 2]; 26 ); 27 struct_group(stat, 28 u8 mon_status; 29 u8 refsel_status; 30 s64 df_offset; 31 ); 32 }; 33 34 int zl3073x_chan_state_fetch(struct zl3073x_dev *zldev, u8 index); 35 const struct zl3073x_chan *zl3073x_chan_state_get(struct zl3073x_dev *zldev, 36 u8 index); 37 int zl3073x_chan_state_set(struct zl3073x_dev *zldev, u8 index, 38 const struct zl3073x_chan *chan); 39 40 int zl3073x_chan_state_update(struct zl3073x_dev *zldev, u8 index); 41 42 /** 43 * zl3073x_chan_df_offset_get - get cached df_offset vs tracked reference 44 * @chan: pointer to channel state 45 * 46 * Return: frequency offset in 2^-48 steps 47 */ 48 static inline s64 49 zl3073x_chan_df_offset_get(const struct zl3073x_chan *chan) 50 { 51 return chan->df_offset; 52 } 53 54 /** 55 * zl3073x_chan_mode_get - get DPLL channel operating mode 56 * @chan: pointer to channel state 57 * 58 * Return: reference selection mode of the given DPLL channel 59 */ 60 static inline u8 zl3073x_chan_mode_get(const struct zl3073x_chan *chan) 61 { 62 return FIELD_GET(ZL_DPLL_MODE_REFSEL_MODE, chan->mode_refsel); 63 } 64 65 /** 66 * zl3073x_chan_ref_get - get manually selected reference 67 * @chan: pointer to channel state 68 * 69 * Return: reference selected in forced reference lock mode 70 */ 71 static inline u8 zl3073x_chan_ref_get(const struct zl3073x_chan *chan) 72 { 73 return FIELD_GET(ZL_DPLL_MODE_REFSEL_REF, chan->mode_refsel); 74 } 75 76 /** 77 * zl3073x_chan_mode_set - set DPLL channel operating mode 78 * @chan: pointer to channel state 79 * @mode: mode to set 80 */ 81 static inline void zl3073x_chan_mode_set(struct zl3073x_chan *chan, u8 mode) 82 { 83 FIELD_MODIFY(ZL_DPLL_MODE_REFSEL_MODE, &chan->mode_refsel, mode); 84 } 85 86 /** 87 * zl3073x_chan_ref_set - set manually selected reference 88 * @chan: pointer to channel state 89 * @ref: reference to set 90 */ 91 static inline void zl3073x_chan_ref_set(struct zl3073x_chan *chan, u8 ref) 92 { 93 FIELD_MODIFY(ZL_DPLL_MODE_REFSEL_REF, &chan->mode_refsel, ref); 94 } 95 96 /** 97 * zl3073x_chan_ref_prio_get - get reference priority 98 * @chan: pointer to channel state 99 * @ref: input reference index 100 * 101 * Return: priority of the given reference <0, 15> 102 */ 103 static inline u8 104 zl3073x_chan_ref_prio_get(const struct zl3073x_chan *chan, u8 ref) 105 { 106 u8 val = chan->ref_prio[ref / 2]; 107 108 if (!(ref & 1)) 109 return FIELD_GET(ZL_DPLL_REF_PRIO_REF_P, val); 110 else 111 return FIELD_GET(ZL_DPLL_REF_PRIO_REF_N, val); 112 } 113 114 /** 115 * zl3073x_chan_ref_prio_set - set reference priority 116 * @chan: pointer to channel state 117 * @ref: input reference index 118 * @prio: priority to set 119 */ 120 static inline void 121 zl3073x_chan_ref_prio_set(struct zl3073x_chan *chan, u8 ref, u8 prio) 122 { 123 u8 *val = &chan->ref_prio[ref / 2]; 124 125 if (!(ref & 1)) 126 FIELD_MODIFY(ZL_DPLL_REF_PRIO_REF_P, val, prio); 127 else 128 FIELD_MODIFY(ZL_DPLL_REF_PRIO_REF_N, val, prio); 129 } 130 131 /** 132 * zl3073x_chan_ref_is_selectable - check if reference is selectable 133 * @chan: pointer to channel state 134 * @ref: input reference index 135 * 136 * Return: true if the reference priority is not NONE, false otherwise 137 */ 138 static inline bool 139 zl3073x_chan_ref_is_selectable(const struct zl3073x_chan *chan, u8 ref) 140 { 141 return zl3073x_chan_ref_prio_get(chan, ref) != ZL_DPLL_REF_PRIO_NONE; 142 } 143 144 /** 145 * zl3073x_chan_lock_state_get - get DPLL channel lock state 146 * @chan: pointer to channel state 147 * 148 * Return: lock state of the given DPLL channel 149 */ 150 static inline u8 zl3073x_chan_lock_state_get(const struct zl3073x_chan *chan) 151 { 152 return FIELD_GET(ZL_DPLL_MON_STATUS_STATE, chan->mon_status); 153 } 154 155 /** 156 * zl3073x_chan_is_ho_ready - check if holdover is ready 157 * @chan: pointer to channel state 158 * 159 * Return: true if holdover is ready, false otherwise 160 */ 161 static inline bool zl3073x_chan_is_ho_ready(const struct zl3073x_chan *chan) 162 { 163 return !!FIELD_GET(ZL_DPLL_MON_STATUS_HO_READY, chan->mon_status); 164 } 165 166 /** 167 * zl3073x_chan_refsel_state_get - get reference selection state 168 * @chan: pointer to channel state 169 * 170 * Return: reference selection state of the given DPLL channel 171 */ 172 static inline u8 zl3073x_chan_refsel_state_get(const struct zl3073x_chan *chan) 173 { 174 return FIELD_GET(ZL_DPLL_REFSEL_STATUS_STATE, chan->refsel_status); 175 } 176 177 /** 178 * zl3073x_chan_refsel_ref_get - get currently selected reference in auto mode 179 * @chan: pointer to channel state 180 * 181 * Return: reference selected by the DPLL in automatic mode 182 */ 183 static inline u8 zl3073x_chan_refsel_ref_get(const struct zl3073x_chan *chan) 184 { 185 return FIELD_GET(ZL_DPLL_REFSEL_STATUS_REFSEL, chan->refsel_status); 186 } 187 188 #endif /* _ZL3073X_CHAN_H */ 189