Merge branch 'dpll-zl3073x-add-ref-sync-pair-support'

Ivan Vecera says:

====================
dpll: zl3073x: add ref-sync pair support

This series adds Reference-Sync pair support to the ZL3073x DPLL driver.
A Ref-Sync pair consists of a clock reference and a low-frequency sync
signal (e.g. 1 PPS) where the DPLL locks to the clock reference but
phase-aligns to the sync reference.

Patches 1-3 are preparatory cleanups and helper additions:
- Clean up esync get/set callbacks with early returns and use the
  zl3073x_out_is_ndiv() helper
- Convert open-coded clear-and-set bitfield patterns to FIELD_MODIFY()
- Add ref sync control and output clock type accessor helpers

Patch 4 adds the 'ref-sync-sources' phandle-array property to the
dpll-pin device tree binding schema and updates the ZL3073x binding
examples.

Patch 5 implements the driver support:
- ref_sync_get/set callbacks with frequency validation
- Automatic sync source exclusion from reference selection
- Device tree based ref-sync pair registration

Tested and verified on Microchip EDS2 (pcb8385) development board.
====================

Link: https://patch.msgid.link/20260408102716.443099-1-ivecera@redhat.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
Jakub Kicinski 2026-04-12 08:27:43 -07:00
commit d24b443429
9 changed files with 351 additions and 82 deletions

View File

@ -36,6 +36,19 @@ properties:
description: String exposed as the pin board label
$ref: /schemas/types.yaml#/definitions/string
ref-sync-sources:
description: |
List of phandles to input pins that can serve as the sync source
in a Reference-Sync pair with this pin acting as the clock source.
A Ref-Sync pair consists of a clock reference and a low-frequency
sync signal. The DPLL locks to the clock reference but
phase-aligns to the sync reference.
Only valid for input pins. Each referenced pin must be a
different input pin on the same device.
$ref: /schemas/types.yaml#/definitions/phandle-array
items:
maxItems: 1
supported-frequencies-hz:
description: List of supported frequencies for this pin, expressed in Hz.

View File

@ -52,11 +52,19 @@ examples:
#address-cells = <1>;
#size-cells = <0>;
pin@0 { /* REF0P */
sync0: pin@0 { /* REF0P - 1 PPS sync source */
reg = <0>;
connection-type = "ext";
label = "Input 0";
supported-frequencies-hz = /bits/ 64 <1 1000>;
label = "SMA1";
supported-frequencies-hz = /bits/ 64 <1>;
};
pin@1 { /* REF0N - clock source, can pair with sync0 */
reg = <1>;
connection-type = "ext";
label = "SMA2";
supported-frequencies-hz = /bits/ 64 <10000 10000000>;
ref-sync-sources = <&sync0>;
};
};
@ -90,11 +98,19 @@ examples:
#address-cells = <1>;
#size-cells = <0>;
pin@0 { /* REF0P */
sync1: pin@0 { /* REF0P - 1 PPS sync source */
reg = <0>;
connection-type = "ext";
label = "Input 0";
supported-frequencies-hz = /bits/ 64 <1 1000>;
connection-type = "gnss";
label = "GNSS_1PPS_IN";
supported-frequencies-hz = /bits/ 64 <1>;
};
pin@1 { /* REF0N - clock source */
reg = <1>;
connection-type = "gnss";
label = "GNSS_10M_IN";
supported-frequencies-hz = /bits/ 64 <10000000>;
ref-sync-sources = <&sync1>;
};
};

View File

@ -66,8 +66,7 @@ static inline u8 zl3073x_chan_ref_get(const struct zl3073x_chan *chan)
*/
static inline void zl3073x_chan_mode_set(struct zl3073x_chan *chan, u8 mode)
{
chan->mode_refsel &= ~ZL_DPLL_MODE_REFSEL_MODE;
chan->mode_refsel |= FIELD_PREP(ZL_DPLL_MODE_REFSEL_MODE, mode);
FIELD_MODIFY(ZL_DPLL_MODE_REFSEL_MODE, &chan->mode_refsel, mode);
}
/**
@ -77,8 +76,7 @@ static inline void zl3073x_chan_mode_set(struct zl3073x_chan *chan, u8 mode)
*/
static inline void zl3073x_chan_ref_set(struct zl3073x_chan *chan, u8 ref)
{
chan->mode_refsel &= ~ZL_DPLL_MODE_REFSEL_REF;
chan->mode_refsel |= FIELD_PREP(ZL_DPLL_MODE_REFSEL_REF, ref);
FIELD_MODIFY(ZL_DPLL_MODE_REFSEL_REF, &chan->mode_refsel, ref);
}
/**
@ -110,13 +108,10 @@ zl3073x_chan_ref_prio_set(struct zl3073x_chan *chan, u8 ref, u8 prio)
{
u8 *val = &chan->ref_prio[ref / 2];
if (!(ref & 1)) {
*val &= ~ZL_DPLL_REF_PRIO_REF_P;
*val |= FIELD_PREP(ZL_DPLL_REF_PRIO_REF_P, prio);
} else {
*val &= ~ZL_DPLL_REF_PRIO_REF_N;
*val |= FIELD_PREP(ZL_DPLL_REF_PRIO_REF_N, prio);
}
if (!(ref & 1))
FIELD_MODIFY(ZL_DPLL_REF_PRIO_REF_P, val, prio);
else
FIELD_MODIFY(ZL_DPLL_REF_PRIO_REF_N, val, prio);
}
/**

View File

@ -805,8 +805,7 @@ int zl3073x_dev_phase_avg_factor_set(struct zl3073x_dev *zldev, u8 factor)
value = (factor + 1) & 0x0f;
/* Update phase measurement control register */
dpll_meas_ctrl &= ~ZL_DPLL_MEAS_CTRL_AVG_FACTOR;
dpll_meas_ctrl |= FIELD_PREP(ZL_DPLL_MEAS_CTRL_AVG_FACTOR, value);
FIELD_MODIFY(ZL_DPLL_MEAS_CTRL_AVG_FACTOR, &dpll_meas_ctrl, value);
rc = zl3073x_write_u8(zldev, ZL_REG_DPLL_MEAS_CTRL, dpll_meas_ctrl);
if (rc)
return rc;

View File

@ -13,6 +13,7 @@
#include <linux/module.h>
#include <linux/netlink.h>
#include <linux/platform_device.h>
#include <linux/property.h>
#include <linux/slab.h>
#include <linux/sprintf.h>
@ -30,6 +31,7 @@
* @dpll: DPLL the pin is registered to
* @dpll_pin: pointer to registered dpll_pin
* @tracker: tracking object for the acquired reference
* @fwnode: firmware node handle
* @label: package label
* @dir: pin direction
* @id: pin id
@ -46,6 +48,7 @@ struct zl3073x_dpll_pin {
struct zl3073x_dpll *dpll;
struct dpll_pin *dpll_pin;
dpll_tracker tracker;
struct fwnode_handle *fwnode;
char label[8];
enum dpll_pin_direction dir;
u8 id;
@ -133,7 +136,13 @@ zl3073x_dpll_input_pin_esync_get(const struct dpll_pin *dpll_pin,
ref_id = zl3073x_input_pin_ref_get(pin->id);
ref = zl3073x_ref_state_get(zldev, ref_id);
switch (FIELD_GET(ZL_REF_SYNC_CTRL_MODE, ref->sync_ctrl)) {
if (!pin->esync_control || zl3073x_ref_freq_get(ref) <= 1)
return -EOPNOTSUPP;
esync->range = esync_freq_ranges;
esync->range_num = ARRAY_SIZE(esync_freq_ranges);
switch (zl3073x_ref_sync_mode_get(ref)) {
case ZL_REF_SYNC_CTRL_MODE_50_50_ESYNC_25_75:
esync->freq = ref->esync_n_div == ZL_REF_ESYNC_DIV_1HZ ? 1 : 0;
esync->pulse = 25;
@ -144,17 +153,6 @@ zl3073x_dpll_input_pin_esync_get(const struct dpll_pin *dpll_pin,
break;
}
/* If the pin supports esync control expose its range but only
* if the current reference frequency is > 1 Hz.
*/
if (pin->esync_control && zl3073x_ref_freq_get(ref) > 1) {
esync->range = esync_freq_ranges;
esync->range_num = ARRAY_SIZE(esync_freq_ranges);
} else {
esync->range = NULL;
esync->range_num = 0;
}
return 0;
}
@ -180,8 +178,7 @@ zl3073x_dpll_input_pin_esync_set(const struct dpll_pin *dpll_pin,
else
sync_mode = ZL_REF_SYNC_CTRL_MODE_50_50_ESYNC_25_75;
ref.sync_ctrl &= ~ZL_REF_SYNC_CTRL_MODE;
ref.sync_ctrl |= FIELD_PREP(ZL_REF_SYNC_CTRL_MODE, sync_mode);
zl3073x_ref_sync_mode_set(&ref, sync_mode);
if (freq) {
/* 1 Hz is only supported frequency now */
@ -192,6 +189,109 @@ zl3073x_dpll_input_pin_esync_set(const struct dpll_pin *dpll_pin,
return zl3073x_ref_state_set(zldev, ref_id, &ref);
}
static int
zl3073x_dpll_input_pin_ref_sync_get(const struct dpll_pin *dpll_pin,
void *pin_priv,
const struct dpll_pin *ref_sync_pin,
void *ref_sync_pin_priv,
enum dpll_pin_state *state,
struct netlink_ext_ack *extack)
{
struct zl3073x_dpll_pin *sync_pin = ref_sync_pin_priv;
struct zl3073x_dpll_pin *pin = pin_priv;
struct zl3073x_dpll *zldpll = pin->dpll;
struct zl3073x_dev *zldev = zldpll->dev;
const struct zl3073x_ref *ref;
u8 ref_id, mode, pair;
ref_id = zl3073x_input_pin_ref_get(pin->id);
ref = zl3073x_ref_state_get(zldev, ref_id);
mode = zl3073x_ref_sync_mode_get(ref);
pair = zl3073x_ref_sync_pair_get(ref);
if (mode == ZL_REF_SYNC_CTRL_MODE_REFSYNC_PAIR &&
pair == zl3073x_input_pin_ref_get(sync_pin->id))
*state = DPLL_PIN_STATE_CONNECTED;
else
*state = DPLL_PIN_STATE_DISCONNECTED;
return 0;
}
static int
zl3073x_dpll_input_pin_ref_sync_set(const struct dpll_pin *dpll_pin,
void *pin_priv,
const struct dpll_pin *ref_sync_pin,
void *ref_sync_pin_priv,
const enum dpll_pin_state state,
struct netlink_ext_ack *extack)
{
struct zl3073x_dpll_pin *sync_pin = ref_sync_pin_priv;
struct zl3073x_dpll_pin *pin = pin_priv;
struct zl3073x_dpll *zldpll = pin->dpll;
struct zl3073x_dev *zldev = zldpll->dev;
u8 mode, ref_id, sync_ref_id;
struct zl3073x_chan chan;
struct zl3073x_ref ref;
int rc;
ref_id = zl3073x_input_pin_ref_get(pin->id);
sync_ref_id = zl3073x_input_pin_ref_get(sync_pin->id);
ref = *zl3073x_ref_state_get(zldev, ref_id);
if (state == DPLL_PIN_STATE_CONNECTED) {
const struct zl3073x_ref *sync_ref;
u32 ref_freq, sync_freq;
sync_ref = zl3073x_ref_state_get(zldev, sync_ref_id);
ref_freq = zl3073x_ref_freq_get(&ref);
sync_freq = zl3073x_ref_freq_get(sync_ref);
/* Sync signal must be 8 kHz or less and clock reference
* must be 1 kHz or more and higher than the sync signal.
*/
if (sync_freq > 8000) {
NL_SET_ERR_MSG(extack,
"sync frequency must be 8 kHz or less");
return -EINVAL;
}
if (ref_freq < 1000) {
NL_SET_ERR_MSG(extack,
"clock frequency must be 1 kHz or more");
return -EINVAL;
}
if (ref_freq <= sync_freq) {
NL_SET_ERR_MSG(extack,
"clock frequency must be higher than sync frequency");
return -EINVAL;
}
zl3073x_ref_sync_pair_set(&ref, sync_ref_id);
mode = ZL_REF_SYNC_CTRL_MODE_REFSYNC_PAIR;
} else {
mode = ZL_REF_SYNC_CTRL_MODE_REFSYNC_PAIR_OFF;
}
zl3073x_ref_sync_mode_set(&ref, mode);
rc = zl3073x_ref_state_set(zldev, ref_id, &ref);
if (rc)
return rc;
/* Exclude sync source from automatic reference selection by setting
* its priority to NONE. On disconnect the priority is left as NONE
* and the user must explicitly make the pin selectable again.
*/
if (state == DPLL_PIN_STATE_CONNECTED) {
chan = *zl3073x_chan_state_get(zldev, zldpll->id);
zl3073x_chan_ref_prio_set(&chan, sync_ref_id,
ZL_DPLL_REF_PRIO_NONE);
return zl3073x_chan_state_set(zldev, zldpll->id, &chan);
}
return 0;
}
static int
zl3073x_dpll_input_pin_ffo_get(const struct dpll_pin *dpll_pin, void *pin_priv,
const struct dpll_device *dpll, void *dpll_priv,
@ -599,8 +699,8 @@ zl3073x_dpll_output_pin_esync_get(const struct dpll_pin *dpll_pin,
struct zl3073x_dpll_pin *pin = pin_priv;
const struct zl3073x_synth *synth;
const struct zl3073x_out *out;
u8 clock_type, out_id;
u32 synth_freq;
u32 synth_freq, out_freq;
u8 out_id;
out_id = zl3073x_output_pin_out_get(pin->id);
out = zl3073x_out_state_get(zldev, out_id);
@ -609,29 +709,30 @@ zl3073x_dpll_output_pin_esync_get(const struct dpll_pin *dpll_pin,
* for N-division is also used for the esync divider so both cannot
* be used.
*/
switch (zl3073x_out_signal_format_get(out)) {
case ZL_OUTPUT_MODE_SIGNAL_FORMAT_2_NDIV:
case ZL_OUTPUT_MODE_SIGNAL_FORMAT_2_NDIV_INV:
if (zl3073x_out_is_ndiv(out))
return -EOPNOTSUPP;
default:
break;
}
/* Get attached synth frequency */
synth = zl3073x_synth_state_get(zldev, zl3073x_out_synth_get(out));
synth_freq = zl3073x_synth_freq_get(synth);
out_freq = synth_freq / out->div;
clock_type = FIELD_GET(ZL_OUTPUT_MODE_CLOCK_TYPE, out->mode);
if (clock_type != ZL_OUTPUT_MODE_CLOCK_TYPE_ESYNC) {
if (!pin->esync_control || out_freq <= 1)
return -EOPNOTSUPP;
esync->range = esync_freq_ranges;
esync->range_num = ARRAY_SIZE(esync_freq_ranges);
if (zl3073x_out_clock_type_get(out) != ZL_OUTPUT_MODE_CLOCK_TYPE_ESYNC) {
/* No need to read esync data if it is not enabled */
esync->freq = 0;
esync->pulse = 0;
goto finish;
return 0;
}
/* Compute esync frequency */
esync->freq = synth_freq / out->div / out->esync_n_period;
esync->freq = out_freq / out->esync_n_period;
/* By comparing the esync_pulse_width to the half of the pulse width
* the esync pulse percentage can be determined.
@ -640,18 +741,6 @@ zl3073x_dpll_output_pin_esync_get(const struct dpll_pin *dpll_pin,
*/
esync->pulse = (50 * out->esync_n_width) / out->div;
finish:
/* Set supported esync ranges if the pin supports esync control and
* if the output frequency is > 1 Hz.
*/
if (pin->esync_control && (synth_freq / out->div) > 1) {
esync->range = esync_freq_ranges;
esync->range_num = ARRAY_SIZE(esync_freq_ranges);
} else {
esync->range = NULL;
esync->range_num = 0;
}
return 0;
}
@ -667,8 +756,8 @@ zl3073x_dpll_output_pin_esync_set(const struct dpll_pin *dpll_pin,
struct zl3073x_dpll_pin *pin = pin_priv;
const struct zl3073x_synth *synth;
struct zl3073x_out out;
u8 clock_type, out_id;
u32 synth_freq;
u8 out_id;
out_id = zl3073x_output_pin_out_get(pin->id);
out = *zl3073x_out_state_get(zldev, out_id);
@ -677,23 +766,16 @@ zl3073x_dpll_output_pin_esync_set(const struct dpll_pin *dpll_pin,
* for N-division is also used for the esync divider so both cannot
* be used.
*/
switch (zl3073x_out_signal_format_get(&out)) {
case ZL_OUTPUT_MODE_SIGNAL_FORMAT_2_NDIV:
case ZL_OUTPUT_MODE_SIGNAL_FORMAT_2_NDIV_INV:
if (zl3073x_out_is_ndiv(&out))
return -EOPNOTSUPP;
default:
break;
}
/* Select clock type */
if (freq)
clock_type = ZL_OUTPUT_MODE_CLOCK_TYPE_ESYNC;
else
clock_type = ZL_OUTPUT_MODE_CLOCK_TYPE_NORMAL;
/* Update clock type in output mode */
out.mode &= ~ZL_OUTPUT_MODE_CLOCK_TYPE;
out.mode |= FIELD_PREP(ZL_OUTPUT_MODE_CLOCK_TYPE, clock_type);
if (freq)
zl3073x_out_clock_type_set(&out,
ZL_OUTPUT_MODE_CLOCK_TYPE_ESYNC);
else
zl3073x_out_clock_type_set(&out,
ZL_OUTPUT_MODE_CLOCK_TYPE_NORMAL);
/* If esync is being disabled just write mailbox and finish */
if (!freq)
@ -745,9 +827,9 @@ zl3073x_dpll_output_pin_frequency_set(const struct dpll_pin *dpll_pin,
struct zl3073x_dev *zldev = zldpll->dev;
struct zl3073x_dpll_pin *pin = pin_priv;
const struct zl3073x_synth *synth;
u8 out_id, signal_format;
u32 new_div, synth_freq;
struct zl3073x_out out;
u8 out_id;
out_id = zl3073x_output_pin_out_get(pin->id);
out = *zl3073x_out_state_get(zldev, out_id);
@ -757,12 +839,8 @@ zl3073x_dpll_output_pin_frequency_set(const struct dpll_pin *dpll_pin,
synth_freq = zl3073x_synth_freq_get(synth);
new_div = synth_freq / (u32)frequency;
/* Get used signal format for the given output */
signal_format = zl3073x_out_signal_format_get(&out);
/* Check signal format */
if (signal_format != ZL_OUTPUT_MODE_SIGNAL_FORMAT_2_NDIV &&
signal_format != ZL_OUTPUT_MODE_SIGNAL_FORMAT_2_NDIV_INV) {
if (!zl3073x_out_is_ndiv(&out)) {
/* For non N-divided signal formats the frequency is computed
* as division of synth frequency and output divisor.
*/
@ -1175,6 +1253,8 @@ static const struct dpll_pin_ops zl3073x_dpll_input_pin_ops = {
.phase_adjust_set = zl3073x_dpll_input_pin_phase_adjust_set,
.prio_get = zl3073x_dpll_input_pin_prio_get,
.prio_set = zl3073x_dpll_input_pin_prio_set,
.ref_sync_get = zl3073x_dpll_input_pin_ref_sync_get,
.ref_sync_set = zl3073x_dpll_input_pin_ref_sync_set,
.state_on_dpll_get = zl3073x_dpll_input_pin_state_on_dpll_get,
.state_on_dpll_set = zl3073x_dpll_input_pin_state_on_dpll_set,
};
@ -1267,8 +1347,11 @@ zl3073x_dpll_pin_register(struct zl3073x_dpll_pin *pin, u32 index)
if (IS_ERR(props))
return PTR_ERR(props);
/* Save package label, esync capability and phase adjust granularity */
/* Save package label, fwnode, esync capability and phase adjust
* granularity.
*/
strscpy(pin->label, props->package_label);
pin->fwnode = fwnode_handle_get(props->fwnode);
pin->esync_control = props->esync_control;
pin->phase_gran = props->dpll_props.phase_gran;
@ -1313,6 +1396,8 @@ zl3073x_dpll_pin_register(struct zl3073x_dpll_pin *pin, u32 index)
dpll_pin_put(pin->dpll_pin, &pin->tracker);
pin->dpll_pin = NULL;
err_pin_get:
fwnode_handle_put(pin->fwnode);
pin->fwnode = NULL;
zl3073x_pin_props_put(props);
return rc;
@ -1342,6 +1427,9 @@ zl3073x_dpll_pin_unregister(struct zl3073x_dpll_pin *pin)
dpll_pin_put(pin->dpll_pin, &pin->tracker);
pin->dpll_pin = NULL;
fwnode_handle_put(pin->fwnode);
pin->fwnode = NULL;
}
/**
@ -1855,6 +1943,88 @@ zl3073x_dpll_free(struct zl3073x_dpll *zldpll)
kfree(zldpll);
}
/**
* zl3073x_dpll_ref_sync_pair_register - register ref_sync pairs for a pin
* @pin: pointer to zl3073x_dpll_pin structure
*
* Iterates 'ref-sync-sources' phandles in the pin's firmware node and
* registers each declared pairing.
*
* Return: 0 on success, <0 on error
*/
static int
zl3073x_dpll_ref_sync_pair_register(struct zl3073x_dpll_pin *pin)
{
struct zl3073x_dev *zldev = pin->dpll->dev;
struct fwnode_handle *fwnode;
struct dpll_pin *sync_pin;
dpll_tracker tracker;
int n, rc;
for (n = 0; ; n++) {
/* Get n'th ref-sync source */
fwnode = fwnode_find_reference(pin->fwnode, "ref-sync-sources",
n);
if (IS_ERR(fwnode)) {
rc = PTR_ERR(fwnode);
break;
}
/* Find associated dpll pin */
sync_pin = fwnode_dpll_pin_find(fwnode, &tracker);
fwnode_handle_put(fwnode);
if (!sync_pin) {
dev_warn(zldev->dev, "%s: ref-sync source %d not found",
pin->label, n);
continue;
}
/* Register new ref-sync pair */
rc = dpll_pin_ref_sync_pair_add(pin->dpll_pin, sync_pin);
dpll_pin_put(sync_pin, &tracker);
/* -EBUSY means pairing already exists from another DPLL's
* registration.
*/
if (rc && rc != -EBUSY) {
dev_err(zldev->dev,
"%s: failed to add ref-sync source %d: %pe",
pin->label, n, ERR_PTR(rc));
break;
}
}
return rc != -ENOENT ? rc : 0;
}
/**
* zl3073x_dpll_ref_sync_pairs_register - register ref_sync pairs for a DPLL
* @zldpll: pointer to zl3073x_dpll structure
*
* Iterates all registered input pins of the given DPLL and establishes
* ref_sync pairings declared by 'ref-sync-sources' phandles in the
* device tree.
*
* Return: 0 on success, <0 on error
*/
static int
zl3073x_dpll_ref_sync_pairs_register(struct zl3073x_dpll *zldpll)
{
struct zl3073x_dpll_pin *pin;
int rc;
list_for_each_entry(pin, &zldpll->pins, list) {
if (!zl3073x_dpll_is_input_pin(pin) || !pin->fwnode)
continue;
rc = zl3073x_dpll_ref_sync_pair_register(pin);
if (rc)
return rc;
}
return 0;
}
/**
* zl3073x_dpll_register - register DPLL device and all its pins
* @zldpll: pointer to zl3073x_dpll structure
@ -1878,6 +2048,13 @@ zl3073x_dpll_register(struct zl3073x_dpll *zldpll)
return rc;
}
rc = zl3073x_dpll_ref_sync_pairs_register(zldpll);
if (rc) {
zl3073x_dpll_pins_unregister(zldpll);
zl3073x_dpll_device_unregister(zldpll);
return rc;
}
return 0;
}

View File

@ -194,8 +194,7 @@ zl3073x_flash_cmd_wait(struct zl3073x_dev *zldev, u32 operation,
if (rc)
return rc;
value &= ~ZL_WRITE_FLASH_OP;
value |= FIELD_PREP(ZL_WRITE_FLASH_OP, operation);
FIELD_MODIFY(ZL_WRITE_FLASH_OP, &value, operation);
rc = zl3073x_write_u8(zldev, ZL_REG_WRITE_FLASH, value);
if (rc)

View File

@ -42,6 +42,28 @@ const struct zl3073x_out *zl3073x_out_state_get(struct zl3073x_dev *zldev,
int zl3073x_out_state_set(struct zl3073x_dev *zldev, u8 index,
const struct zl3073x_out *out);
/**
* zl3073x_out_clock_type_get - get output clock type
* @out: pointer to out state
*
* Return: clock type of given output (ZL_OUTPUT_MODE_CLOCK_TYPE_*)
*/
static inline u8 zl3073x_out_clock_type_get(const struct zl3073x_out *out)
{
return FIELD_GET(ZL_OUTPUT_MODE_CLOCK_TYPE, out->mode);
}
/**
* zl3073x_out_clock_type_set - set output clock type
* @out: pointer to out state
* @type: clock type (ZL_OUTPUT_MODE_CLOCK_TYPE_*)
*/
static inline void
zl3073x_out_clock_type_set(struct zl3073x_out *out, u8 type)
{
FIELD_MODIFY(ZL_OUTPUT_MODE_CLOCK_TYPE, &out->mode, type);
}
/**
* zl3073x_out_signal_format_get - get output signal format
* @out: pointer to out state

View File

@ -120,6 +120,52 @@ zl3073x_ref_freq_set(struct zl3073x_ref *ref, u32 freq)
return 0;
}
/**
* zl3073x_ref_sync_mode_get - get sync control mode
* @ref: pointer to ref state
*
* Return: sync control mode (ZL_REF_SYNC_CTRL_MODE_*)
*/
static inline u8
zl3073x_ref_sync_mode_get(const struct zl3073x_ref *ref)
{
return FIELD_GET(ZL_REF_SYNC_CTRL_MODE, ref->sync_ctrl);
}
/**
* zl3073x_ref_sync_mode_set - set sync control mode
* @ref: pointer to ref state
* @mode: sync control mode (ZL_REF_SYNC_CTRL_MODE_*)
*/
static inline void
zl3073x_ref_sync_mode_set(struct zl3073x_ref *ref, u8 mode)
{
FIELD_MODIFY(ZL_REF_SYNC_CTRL_MODE, &ref->sync_ctrl, mode);
}
/**
* zl3073x_ref_sync_pair_get - get sync pair reference index
* @ref: pointer to ref state
*
* Return: paired reference index
*/
static inline u8
zl3073x_ref_sync_pair_get(const struct zl3073x_ref *ref)
{
return FIELD_GET(ZL_REF_SYNC_CTRL_PAIR, ref->sync_ctrl);
}
/**
* zl3073x_ref_sync_pair_set - set sync pair reference index
* @ref: pointer to ref state
* @pair: paired reference index
*/
static inline void
zl3073x_ref_sync_pair_set(struct zl3073x_ref *ref, u8 pair)
{
FIELD_MODIFY(ZL_REF_SYNC_CTRL_PAIR, &ref->sync_ctrl, pair);
}
/**
* zl3073x_ref_is_diff - check if the given input reference is differential
* @ref: pointer to ref state

View File

@ -213,7 +213,9 @@
#define ZL_REG_REF_SYNC_CTRL ZL_REG(10, 0x2e, 1)
#define ZL_REF_SYNC_CTRL_MODE GENMASK(2, 0)
#define ZL_REF_SYNC_CTRL_MODE_REFSYNC_PAIR_OFF 0
#define ZL_REF_SYNC_CTRL_MODE_REFSYNC_PAIR 1
#define ZL_REF_SYNC_CTRL_MODE_50_50_ESYNC_25_75 2
#define ZL_REF_SYNC_CTRL_PAIR GENMASK(7, 4)
#define ZL_REG_REF_ESYNC_DIV ZL_REG(10, 0x30, 4)
#define ZL_REF_ESYNC_DIV_1HZ 0