[PATCH v10 04/14] dpll: sit9531x: read DPLL types and pin properties from system firmware

From: Ali Rouhi

Date: Mon Sep 21 2026 - 16:16:01 EST


From: Oleg Zadorozhnyi <Oleg.Zadorozhnyi@xxxxxxxxxxxxxxxxx>

The DPLL core wants a type per device and a property set per pin: a
label, the direction, the capabilities, and the frequencies the pin
supports. None of that can be read from the chip -- which frequencies a
board actually presents on a given input is a board fact -- so they come
from the firmware node, with defaults for a node that does not describe
them.

Input pins are interleaved P and N lanes of four differential pairs, so a
logical index maps to a pair and a lane, and a pair configured
single-ended presents two independent inputs where a differential one
presents one. The labels follow from that, and the two extra input
positions -- the crystal and the inter-PLL sync net -- are named
separately.

Two of the advertised properties are worth naming. Outputs get a
phase-adjust window of one millisecond either way, which is wider than
the dynamic range but costs nothing and is what keeps the subsystem from
refusing every request; the granularity is one picosecond, because the
achievable delays are whole VCO cycles plus thirty-picosecond steps and
so form no uniform lattice for the core to check against. And an output
whose node lists no supported frequencies is advertised as a continuous
range rather than nothing at all, since those pins do accept a frequency
set; a request inside the range that the integer output divider cannot
produce is refused when it is made.

Kept in its own file, and introduced before anything is registered, so
the registration code that follows has nothing to say about firmware.

Signed-off-by: Oleg Zadorozhnyi <Oleg.Zadorozhnyi@xxxxxxxxxxxxxxxxx>
Assisted-by: Claude:claude-4-opus [chat]
Signed-off-by: Ali Rouhi <arouhi@xxxxxxxxxx>
---

Notes:
Changes in v10:
Named and matched output pins by the chip pin they drive rather than
by the driver's index for them, which differ on the variant whose
outputs are bonded out from a subset of the slots.

Took an output's current rate from its divider instead of the first
entry of the list of rates the board supports.

Advertised the phase-adjust window and the priority capability from the
patches that implement them.

Described the advertised phase window and the fallback frequency range
in the commit message.

Dropped the esync-control property, since the patch that read
it has been withdrawn.

drivers/dpll/sit9531x/Makefile | 2 +-
drivers/dpll/sit9531x/core.h | 72 ++++++
drivers/dpll/sit9531x/prop.c | 430 +++++++++++++++++++++++++++++++++
drivers/dpll/sit9531x/prop.h | 37 +++
4 files changed, 540 insertions(+), 1 deletion(-)
create mode 100644 drivers/dpll/sit9531x/prop.c
create mode 100644 drivers/dpll/sit9531x/prop.h

diff --git a/drivers/dpll/sit9531x/Makefile b/drivers/dpll/sit9531x/Makefile
index a221fe55386a..819af61123f5 100644
--- a/drivers/dpll/sit9531x/Makefile
+++ b/drivers/dpll/sit9531x/Makefile
@@ -1,4 +1,4 @@
# SPDX-License-Identifier: GPL-2.0-only

obj-$(CONFIG_SIT9531X_DPLL) += sit9531x.o
-sit9531x-y := core.o
+sit9531x-y := core.o prop.o
diff --git a/drivers/dpll/sit9531x/core.h b/drivers/dpll/sit9531x/core.h
index 76a2632f0ce4..230b21b9e238 100644
--- a/drivers/dpll/sit9531x/core.h
+++ b/drivers/dpll/sit9531x/core.h
@@ -23,7 +23,17 @@

#define SIT9531X_NUM_PLLS 4
#define SIT9531X_MAX_INPUTS 8
+#define SIT9531X_NUM_INPUT_PAIRS (SIT9531X_MAX_INPUTS / 2)
#define SIT9531X_MAX_OUTPUTS 12
+/*
+ * INTSYNC (the inter-PLL sync net) is modeled as two pins. The
+ * destination PLL that locks to INTSYNC sees an input pin
+ * (SIT9531X_INTSYNC_PIN_ID, in the input id namespace after the physical
+ * inputs and the xtal); the source PLL that drives INTSYNC sees an output
+ * pin (SIT9531X_INTSYNC_OUT_PIN_ID, appended after the physical outputs).
+ */
+#define SIT9531X_INTSYNC_PIN_ID (SIT9531X_MAX_INPUTS + 1)
+#define SIT9531X_INTSYNC_OUT_PIN_ID SIT9531X_MAX_OUTPUTS

/*
* struct sit9531x_chip_info - chip variant identification
@@ -41,6 +51,39 @@ struct sit9531x_chip_info {
const u8 *clkout_map;
};

+/*
+ * enum sit9531x_signal_mode - input signal electrical mode
+ * @SIT9531X_MODE_SE: single-ended
+ * @SIT9531X_MODE_DE: differential
+ */
+enum sit9531x_signal_mode {
+ SIT9531X_MODE_SE = 0,
+ SIT9531X_MODE_DE,
+};
+
+/*
+ * struct sit9531x_ref - input reference state
+ * @freq: configured frequency in Hz
+ * @label: board label from DT or default
+ * @sig_mode: signal mode of the pair this lane belongs to
+ * (detected from CLKINx_INPUT_MODE at probe)
+ */
+struct sit9531x_ref {
+ u32 freq;
+ const char *label;
+ enum sit9531x_signal_mode sig_mode;
+};
+
+/*
+ * struct sit9531x_out - output state
+ * @freq: configured frequency in Hz
+ * @label: board label from DT or default
+ */
+struct sit9531x_out {
+ u32 freq;
+ const char *label;
+};
+
/*
* struct sit9531x_dev - SiT9531x device instance
* @dev: parent device
@@ -48,6 +91,8 @@ struct sit9531x_chip_info {
* @regmap: paged register map
* @info: detected chip variant info
* @multiop_lock: serializes multi-register sequences
+ * @ref: array of input reference states
+ * @out: array of output states
* @xtal_freq: crystal oscillator frequency in Hz
* @reset_gpio: optional reset line (DT "reset-gpios"), NULL if absent
*/
@@ -59,11 +104,38 @@ struct sit9531x_dev {
/* Serializes multi-step register sequences */
struct mutex multiop_lock;

+ /* Hardware state */
+ struct sit9531x_ref ref[SIT9531X_MAX_INPUTS + 1]; /* +1 for xtal */
+ struct sit9531x_out out[SIT9531X_MAX_OUTPUTS];
u32 xtal_freq;

struct gpio_desc *reset_gpio;
};

+/*
+ * Logical input pins are interleaved: even index = P lane, odd
+ * index = N lane of pair index/2 (IN0P, IN0N, IN1P, IN1N, ...).
+ * Index SIT9531X_MAX_INPUTS is the XO input.
+ */
+
+/*
+ * sit9531x_input_pair - get input pair number for a logical input index
+ * @index: logical input pin index
+ */
+static inline u8 sit9531x_input_pair(u8 index)
+{
+ return index >> 1;
+}
+
+/*
+ * sit9531x_input_is_n - check if a logical input index is an N lane
+ * @index: logical input pin index
+ */
+static inline bool sit9531x_input_is_n(u8 index)
+{
+ return index & 1;
+}
+
/*
* sit9531x_pll_page - get register page for PLL index
* @pll_idx: PLL index (0 = PLLA, 3 = PLLD)
diff --git a/drivers/dpll/sit9531x/prop.c b/drivers/dpll/sit9531x/prop.c
new file mode 100644
index 000000000000..1a09bd168163
--- /dev/null
+++ b/drivers/dpll/sit9531x/prop.c
@@ -0,0 +1,430 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * SiTime SiT9531x firmware node property parsing
+ *
+ * Copyright (C) 2026 SiTime Corp.
+ * Author: Ali Rouhi <arouhi@xxxxxxxxxx>
+ * Author: Oleg Zadorozhnyi <Oleg.Zadorozhnyi@xxxxxxxxxxxxxxxxx>
+ *
+ * Retrieves pin properties from Device Tree firmware nodes (or
+ * applies defaults when no firmware node exists).
+ */
+
+#include <linux/dev_printk.h>
+#include <linux/dpll.h>
+#include <linux/err.h>
+#include <linux/fwnode.h>
+#include <linux/property.h>
+#include <linux/slab.h>
+#include <linux/string.h>
+
+#include "core.h"
+#include "prop.h"
+
+/*
+ * sit9531x_input_pin_label - fill the package label for an input pin
+ *
+ * Split out so input-naming changes stay local to this helper.
+ */
+static void sit9531x_input_pin_label(struct sit9531x_dev *sitdev,
+ struct sit9531x_pin_props *props, u8 id)
+{
+ u8 pair = sit9531x_input_pair(id);
+
+ if (sitdev->ref[id].sig_mode == SIT9531X_MODE_DE)
+ snprintf(props->package_label,
+ sizeof(props->package_label), "IN%u", pair);
+ else
+ snprintf(props->package_label,
+ sizeof(props->package_label), "IN%u%c", pair,
+ sit9531x_input_is_n(id) ? 'N' : 'P');
+}
+
+/*
+ * sit9531x_prop_pin_package_label_set - generate package label
+ * @dir: pin direction
+ * @id: pin index
+ *
+ * Generates a package label string. Output pins are named "OUT0",
+ * "OUT1", ... Input pins are named after the physical pair and lane:
+ * "IN0P", "IN0N", "IN1P", ... for single-ended lanes, or "IN0",
+ * "IN1", ... when the pair is configured differential (the N lane is
+ * not registered in that case).
+ */
+static void
+sit9531x_prop_pin_package_label_set(struct sit9531x_dev *sitdev,
+ struct sit9531x_pin_props *props,
+ enum dpll_pin_direction dir, u8 id)
+{
+ /* The internal INTSYNC pin has a fixed label */
+ if (dir == DPLL_PIN_DIRECTION_INPUT &&
+ id == SIT9531X_INTSYNC_PIN_ID) {
+ strscpy(props->package_label, "INTSYNC",
+ sizeof(props->package_label));
+ props->dpll_props.package_label = props->package_label;
+ return;
+ }
+
+ /* The internal XO reference has a fixed label */
+ if (dir == DPLL_PIN_DIRECTION_INPUT && id == SIT9531X_MAX_INPUTS) {
+ strscpy(props->package_label, "XO",
+ sizeof(props->package_label));
+ props->dpll_props.package_label = props->package_label;
+ return;
+ }
+
+ /* The internal INTSYNC source (output) pin has a fixed label */
+ if (dir == DPLL_PIN_DIRECTION_OUTPUT &&
+ id == SIT9531X_INTSYNC_OUT_PIN_ID) {
+ strscpy(props->package_label, "SYNCOUT",
+ sizeof(props->package_label));
+ props->dpll_props.package_label = props->package_label;
+ return;
+ }
+
+ if (dir == DPLL_PIN_DIRECTION_INPUT)
+ sit9531x_input_pin_label(sitdev, props, id);
+ else
+ /*
+ * Name the chip pin, not the driver's index for it. The
+ * two differ on the variant whose outputs are bonded out
+ * from a subset of the twelve slots, and a package label
+ * that named the index would point at a pin that is not
+ * the one being driven.
+ */
+ snprintf(props->package_label, sizeof(props->package_label),
+ "OUT%u", sitdev->info->clkout_map[id]);
+
+ props->dpll_props.package_label = props->package_label;
+}
+
+/*
+ * sit9531x_prop_pin_fwnode_get - find firmware node for a pin
+ * @dir: pin direction
+ * @id: pin index
+ *
+ * Searches for input-pins/output-pins child nodes in DT, looking for a
+ * child whose "reg" property matches the pin. The binding describes reg
+ * as the hardware index, so an output is matched by the chip slot it
+ * drives rather than by the driver's index for it: on the variant where
+ * the two differ, a board describing the pin it wired would otherwise
+ * have its properties applied to a different one.
+ *
+ * Return: 0 on success, -ENOENT if no firmware node exists
+ */
+static int
+sit9531x_prop_pin_fwnode_get(struct sit9531x_dev *sitdev,
+ struct sit9531x_pin_props *props,
+ enum dpll_pin_direction dir, u8 id)
+{
+ struct fwnode_handle *pins_node, *pin_node;
+ const char *node_name;
+
+ if (dir == DPLL_PIN_DIRECTION_INPUT) {
+ node_name = "input-pins";
+ } else {
+ node_name = "output-pins";
+ if (id < sitdev->info->num_outputs)
+ id = sitdev->info->clkout_map[id];
+ }
+
+ pins_node = device_get_named_child_node(sitdev->dev, node_name);
+ if (!pins_node) {
+ dev_dbg(sitdev->dev, "'%s' sub-node is missing\n", node_name);
+ return -ENOENT;
+ }
+
+ /* Enumerate child pin nodes and find the requested one */
+ fwnode_for_each_child_node(pins_node, pin_node) {
+ u32 reg;
+
+ if (fwnode_property_read_u32(pin_node, "reg", &reg))
+ continue;
+
+ if (id == reg)
+ break;
+ }
+
+ fwnode_handle_put(pins_node);
+
+ props->fwnode = pin_node;
+
+ dev_dbg(sitdev->dev, "Firmware node for %s %sfound\n",
+ props->package_label, pin_node ? "" : "NOT ");
+
+ return pin_node ? 0 : -ENOENT;
+}
+
+/*
+ * sit9531x_pin_props_get - get pin properties for a given pin
+ * @dir: pin direction (INPUT or OUTPUT)
+ * @index: pin index
+ *
+ * Allocates a pin properties structure, generates a package label,
+ * looks up the firmware node if available, and reads optional
+ * properties (label, connection-type, supported-frequencies-hz).
+ *
+ * Call sit9531x_pin_props_put() to free the returned structure.
+ *
+ * Return: pointer to pin properties on success, error pointer on error
+ */
+struct sit9531x_pin_props *
+sit9531x_pin_props_get(struct sit9531x_dev *sitdev,
+ enum dpll_pin_direction dir, u8 index)
+{
+ struct dpll_pin_frequency *ranges;
+ struct sit9531x_pin_props *props;
+ int i, j, num_freqs = 0, rc;
+ u64 *freqs = NULL;
+ const char *type;
+ u64 curr_freq;
+
+ props = kzalloc_obj(*props, GFP_KERNEL);
+ if (!props)
+ return ERR_PTR(-ENOMEM);
+
+ if (dir == DPLL_PIN_DIRECTION_INPUT &&
+ index == SIT9531X_INTSYNC_PIN_ID) {
+ /*
+ * INTSYNC destination pin: a PLL locks to the INTSYNC net as a
+ * reference, so it can be connected and re-prioritised.
+ */
+ props->dpll_props.type = DPLL_PIN_TYPE_INT_OSCILLATOR;
+ props->dpll_props.capabilities =
+ DPLL_PIN_CAPABILITIES_STATE_CAN_CHANGE;
+ curr_freq = 0;
+ } else if (dir == DPLL_PIN_DIRECTION_OUTPUT &&
+ index == SIT9531X_INTSYNC_OUT_PIN_ID) {
+ /*
+ * INTSYNC source pin: a PLL drives the INTSYNC net. It can be
+ * connected/disconnected but carries no priority (driving the
+ * net is not a reference selection) and no frequency.
+ */
+ props->dpll_props.type = DPLL_PIN_TYPE_INT_OSCILLATOR;
+ props->dpll_props.capabilities =
+ DPLL_PIN_CAPABILITIES_STATE_CAN_CHANGE;
+ curr_freq = 0;
+ } else if (dir == DPLL_PIN_DIRECTION_INPUT &&
+ index == SIT9531X_MAX_INPUTS) {
+ /* The XO reference is fixed: no state or priority control. */
+ props->dpll_props.type = DPLL_PIN_TYPE_INT_OSCILLATOR;
+ props->dpll_props.capabilities = 0;
+ sitdev->ref[index].freq = sitdev->xtal_freq;
+ curr_freq = sitdev->xtal_freq;
+ } else if (dir == DPLL_PIN_DIRECTION_INPUT) {
+ props->dpll_props.type = DPLL_PIN_TYPE_EXT;
+ props->dpll_props.capabilities =
+ DPLL_PIN_CAPABILITIES_STATE_CAN_CHANGE;
+ curr_freq = sitdev->ref[index].freq;
+ } else {
+ /*
+ * A synthesized clock output is an external connection with
+ * no more specific meaning; a board that knows better says
+ * so through the pin's connection-type property below.
+ */
+ props->dpll_props.type = DPLL_PIN_TYPE_EXT;
+ props->dpll_props.capabilities =
+ DPLL_PIN_CAPABILITIES_STATE_CAN_CHANGE;
+ curr_freq = sitdev->out[index].freq;
+ }
+
+ /* Generate package label */
+ sit9531x_prop_pin_package_label_set(sitdev, props, dir, index);
+
+ /*
+ * Both INTSYNC pins are internal to the chip and have no board-level
+ * wiring, so they take no properties from the firmware node.
+ */
+ if (dir == DPLL_PIN_DIRECTION_INPUT &&
+ (index == SIT9531X_INTSYNC_PIN_ID ||
+ index == SIT9531X_MAX_INPUTS))
+ goto skip_fwnode_props;
+ if (dir == DPLL_PIN_DIRECTION_OUTPUT &&
+ index == SIT9531X_INTSYNC_OUT_PIN_ID)
+ goto skip_fwnode_props;
+
+ rc = sit9531x_prop_pin_fwnode_get(sitdev, props, dir, index);
+ if (rc)
+ goto skip_fwnode_props;
+
+ /* Look for "label" property -> board label */
+ fwnode_property_read_string(props->fwnode, "label",
+ &props->dpll_props.board_label);
+
+ /* Look for "connection-type" property -> pin type enum */
+ if (!fwnode_property_read_string(props->fwnode, "connection-type",
+ &type)) {
+ if (!strcmp(type, "ext"))
+ props->dpll_props.type = DPLL_PIN_TYPE_EXT;
+ else if (!strcmp(type, "gnss"))
+ props->dpll_props.type = DPLL_PIN_TYPE_GNSS;
+ else if (!strcmp(type, "int"))
+ props->dpll_props.type = DPLL_PIN_TYPE_INT_OSCILLATOR;
+ else if (!strcmp(type, "synce"))
+ props->dpll_props.type = DPLL_PIN_TYPE_SYNCE_ETH_PORT;
+ else if (!strcmp(type, "mux"))
+ props->dpll_props.type = DPLL_PIN_TYPE_MUX;
+ else
+ dev_warn(sitdev->dev,
+ "Unknown pin type '%s'\n", type);
+ }
+
+ num_freqs = fwnode_property_count_u64(props->fwnode,
+ "supported-frequencies-hz");
+ if (num_freqs <= 0) {
+ num_freqs = 0;
+ goto skip_fwnode_props;
+ }
+
+ freqs = kcalloc(num_freqs, sizeof(*freqs), GFP_KERNEL);
+ if (!freqs) {
+ rc = -ENOMEM;
+ goto err_alloc_freqs;
+ }
+
+ rc = fwnode_property_read_u64_array(props->fwnode,
+ "supported-frequencies-hz",
+ freqs, num_freqs);
+ if (rc) {
+ dev_warn(sitdev->dev,
+ "failed to parse supported-frequencies-hz for %s: %d\n",
+ props->package_label, rc);
+ goto err_alloc_ranges;
+ }
+
+ /*
+ * Seed the runtime ref->freq / out->freq with the first DT-listed
+ * supported frequency so the netlink frequency_get callback reports
+ * a sane initial value before any pin_set occurs. DT lists the
+ * physically-wired reference frequency for each input pin and the
+ * default output frequency for each output pin.
+ */
+ if (num_freqs > 0) {
+ if (dir != DPLL_PIN_DIRECTION_INPUT ||
+ index != SIT9531X_MAX_INPUTS)
+ curr_freq = freqs[0];
+ }
+
+skip_fwnode_props:
+ /* Neither INTSYNC pin carries a frequency attribute */
+ if (dir == DPLL_PIN_DIRECTION_INPUT &&
+ index == SIT9531X_INTSYNC_PIN_ID)
+ return props;
+ if (dir == DPLL_PIN_DIRECTION_OUTPUT &&
+ index == SIT9531X_INTSYNC_OUT_PIN_ID)
+ return props;
+
+ /*
+ * Advertise only concrete values from firmware plus current runtime
+ * value. For outputs without a firmware list, publish one wide range as
+ * an explicit fallback because those pins do support frequency_set.
+ */
+ ranges = kcalloc(num_freqs + 2, sizeof(*ranges), GFP_KERNEL);
+ if (!ranges) {
+ rc = -ENOMEM;
+ goto err_alloc_ranges;
+ }
+
+ /*
+ * Publish the seeded rate only once the pin is certain to be built.
+ * The allocation above is the last thing that can fail, and a call
+ * that reports failure must not leave the device's cached rate
+ * changed behind it.
+ */
+ if (curr_freq) {
+ if (dir == DPLL_PIN_DIRECTION_INPUT)
+ sitdev->ref[index].freq = curr_freq;
+ else
+ sitdev->out[index].freq = curr_freq;
+ }
+
+ j = 0;
+
+ /* Current frequency first, when known. */
+ if (curr_freq) {
+ struct dpll_pin_frequency f = DPLL_PIN_FREQUENCY(curr_freq);
+
+ ranges[j++] = f;
+ }
+
+ for (i = 0; i < num_freqs; i++) {
+ struct dpll_pin_frequency freq = DPLL_PIN_FREQUENCY(freqs[i]);
+
+ if (freqs[i] == curr_freq)
+ continue;
+ ranges[j++] = freq;
+ }
+
+ if (dir == DPLL_PIN_DIRECTION_OUTPUT && num_freqs == 0) {
+ ranges[j].min = 1;
+ ranges[j].max = 1000000000ULL; /* 1 GHz */
+ j++;
+ }
+
+ if (j > 0) {
+ props->dpll_props.freq_supported = ranges;
+ props->dpll_props.freq_supported_num = j;
+ } else {
+ kfree(ranges);
+ props->dpll_props.freq_supported = NULL;
+ props->dpll_props.freq_supported_num = 0;
+ }
+
+ kfree(freqs);
+
+ return props;
+
+err_alloc_ranges:
+ kfree(freqs);
+err_alloc_freqs:
+ fwnode_handle_put(props->fwnode);
+ kfree(props);
+
+ return ERR_PTR(rc);
+}
+
+/*
+ * sit9531x_pin_props_put - release pin properties
+ * @props: pin properties to free
+ */
+void sit9531x_pin_props_put(struct sit9531x_pin_props *props)
+{
+ kfree(props->dpll_props.freq_supported);
+
+ if (props->fwnode)
+ fwnode_handle_put(props->fwnode);
+
+ kfree(props);
+}
+
+/*
+ * sit9531x_prop_dpll_type_get - get DPLL channel type from firmware
+ * @index: DPLL channel index (0-3)
+ *
+ * Reads the "dpll-types" string array property from the firmware node
+ * and returns the corresponding DPLL type enum.
+ *
+ * Return: DPLL type for the given channel (default: DPLL_TYPE_PPS)
+ */
+enum dpll_type
+sit9531x_prop_dpll_type_get(struct sit9531x_dev *sitdev, u8 index)
+{
+ const char *types[SIT9531X_NUM_PLLS];
+ int count;
+
+ count = device_property_read_string_array(sitdev->dev, "dpll-types",
+ types, ARRAY_SIZE(types));
+
+ if (index >= count)
+ return DPLL_TYPE_PPS;
+
+ if (!strcmp(types[index], "pps"))
+ return DPLL_TYPE_PPS;
+ else if (!strcmp(types[index], "eec"))
+ return DPLL_TYPE_EEC;
+
+ dev_warn(sitdev->dev, "Unknown DPLL type '%s', using default\n",
+ types[index]);
+
+ return DPLL_TYPE_PPS;
+}
diff --git a/drivers/dpll/sit9531x/prop.h b/drivers/dpll/sit9531x/prop.h
new file mode 100644
index 000000000000..a65efdfd9ef8
--- /dev/null
+++ b/drivers/dpll/sit9531x/prop.h
@@ -0,0 +1,37 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * SiTime SiT9531x firmware node property parsing
+ *
+ * Copyright (C) 2026 SiTime Corp.
+ * Author: Ali Rouhi <arouhi@xxxxxxxxxx>
+ * Author: Oleg Zadorozhnyi <Oleg.Zadorozhnyi@xxxxxxxxxxxxxxxxx>
+ */
+
+#ifndef _SIT9531X_PROP_H
+#define _SIT9531X_PROP_H
+
+#include <linux/dpll.h>
+#include <linux/fwnode.h>
+
+struct sit9531x_dev;
+
+/*
+ * struct sit9531x_pin_props - pin properties from firmware
+ * @fwnode: firmware node handle (NULL if no DT node)
+ * @dpll_props: DPLL core pin properties
+ * @package_label: pin package label (e.g. "IN0", "OUT3")
+ */
+struct sit9531x_pin_props {
+ struct fwnode_handle *fwnode;
+ struct dpll_pin_properties dpll_props;
+ char package_label[8];
+};
+
+enum dpll_type sit9531x_prop_dpll_type_get(struct sit9531x_dev *sitdev,
+ u8 index);
+struct sit9531x_pin_props *sit9531x_pin_props_get(struct sit9531x_dev *sitdev,
+ enum dpll_pin_direction dir,
+ u8 index);
+void sit9531x_pin_props_put(struct sit9531x_pin_props *props);
+
+#endif /* _SIT9531X_PROP_H */
--
2.43.0