mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
From: Ali Rouhi <arouhi@sitime.com>
To: "jiri@resnulli.us" <jiri@resnulli.us>
Cc: "vadim.fedorenko@linux.dev" <vadim.fedorenko@linux.dev>,
	"arkadiusz.kubalewski@intel.com" <arkadiusz.kubalewski@intel.com>,
	"ivecera@redhat.com" <ivecera@redhat.com>,
	"kuba@kernel.org" <kuba@kernel.org>,
	"pabeni@redhat.com" <pabeni@redhat.com>,
	"robh@kernel.org" <robh@kernel.org>,
	"krzk+dt@kernel.org" <krzk+dt@kernel.org>,
	"conor+dt@kernel.org" <conor+dt@kernel.org>,
	"cjubran@nvidia.com" <cjubran@nvidia.com>,
	"Oleg.Zadorozhnyi@devoxsoftware.com"
	<Oleg.Zadorozhnyi@devoxsoftware.com>,
	"prabhakar.mahadev-lad.rj@bp.renesas.com"
	<prabhakar.mahadev-lad.rj@bp.renesas.com>,
	"devicetree@vger.kernel.org" <devicetree@vger.kernel.org>,
	"netdev@vger.kernel.org" <netdev@vger.kernel.org>,
	"linux-kernel@vger.kernel.org" <linux-kernel@vger.kernel.org>
Subject: [PATCH net-next v15 05/13] dpll: sit9531x: read DPLL types and pin properties from system firmware
Date: Tue, 10 Nov 2026 20:26:12 +0000	[thread overview]
Message-ID: <20261110202607.55744-6-arouhi@sitime.com> (raw)
In-Reply-To: <20261110202607.55744-1-arouhi@sitime.com>

From: Oleg Zadorozhnyi <Oleg.Zadorozhnyi@devoxsoftware.com>

Read the DPLL type and, for each pin, its label, direction, capabilities
and supported frequencies from the firmware node, with defaults for a
node that gives none.

Inputs are the P and N lanes of four pairs: a pair run single-ended
gives two inputs, a differential pair one. Outputs are labeled OUTn by
the driver's index, while reg stays the die slot the binding defines, so
one binding serves both variants.

An output with no supported-frequencies-hz is advertised as a continuous
range, since the core refuses every frequency request on a pin with
none.

Signed-off-by: Oleg Zadorozhnyi <Oleg.Zadorozhnyi@devoxsoftware.com>
Signed-off-by: Ali Rouhi <arouhi@sitime.com>
---
 drivers/dpll/sit9531x/Makefile |   2 +-
 drivers/dpll/sit9531x/core.h   |  56 ++++++
 drivers/dpll/sit9531x/prop.c   | 327 +++++++++++++++++++++++++++++++++
 drivers/dpll/sit9531x/prop.h   |  37 ++++
 4 files changed, 421 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 0f826313eff8..7a81c9b14b7f 100644
--- a/drivers/dpll/sit9531x/core.h
+++ b/drivers/dpll/sit9531x/core.h
@@ -23,7 +23,15 @@
 
 #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 line, is two pins: an input pin on the PLL that
+ * locks to it, numbered after the inputs and the xtal, and an output pin on the
+ * PLL that drives it, numbered after the 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 +49,35 @@ 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
+ * @sig_mode: signal mode of the input pair, read from CLKINx_INPUT_MODE at
+ *   probe
+ */
+struct sit9531x_ref {
+	u64		freq;
+	enum sit9531x_signal_mode	sig_mode;
+};
+
+/*
+ * struct sit9531x_out - output state
+ * @freq: output frequency in Hz
+ */
+struct sit9531x_out {
+	u64		freq;
+};
+
 /*
  * struct sit9531x_dev - SiT9531x device instance
  * @dev: parent device
@@ -51,6 +88,8 @@ struct sit9531x_chip_info {
  * @page_lock: held across a page select and its transfer; nests inside
  *   @multiop_lock
  * @page: current page, -1 when unknown
+ * @ref: input reference states
+ * @out: output states
  * @xtal_freq: crystal frequency in Hz
  * @reset_gpio: optional reset line, NULL if absent
  */
@@ -65,11 +104,28 @@ struct sit9531x_dev {
 	struct mutex			page_lock;
 	int				page;
 
+	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;
 };
 
+/*
+ * Input index 2n is the P lane and 2n + 1 the N lane of pair n; index
+ * SIT9531X_MAX_INPUTS is the XO.
+ */
+
+static inline u8 sit9531x_input_pair(u8 index)
+{
+	return index >> 1;
+}
+
+static inline bool sit9531x_input_is_n(u8 index)
+{
+	return index & 1;
+}
+
 /* Register page of PLL @pll_idx (0 = PLLA, 3 = PLLD). */
 static inline u8 sit9531x_pll_page(u8 pll_idx)
 {
diff --git a/drivers/dpll/sit9531x/prop.c b/drivers/dpll/sit9531x/prop.c
new file mode 100644
index 000000000000..b9405eba49a3
--- /dev/null
+++ b/drivers/dpll/sit9531x/prop.c
@@ -0,0 +1,327 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * SiTime SiT9531x firmware node property parsing
+ *
+ * Copyright (C) 2026 SiTime Corp.
+ * Author: Ali Rouhi <arouhi@sitime.com>
+ * Author: Oleg Zadorozhnyi <Oleg.Zadorozhnyi@devoxsoftware.com>
+ *
+ * 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"
+
+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');
+}
+
+/* A differential input pair is labeled IN<n>; its N lane is not registered. */
+static void
+sit9531x_prop_pin_package_label_set(struct sit9531x_dev *sitdev,
+				    struct sit9531x_pin_props *props,
+				    enum dpll_pin_direction dir, u8 id)
+{
+	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;
+	}
+
+	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;
+	}
+
+	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
+		/*
+		 * Package numbering; on the SiT95317 it differs from the chip
+		 * slot that the registers and the binding's reg use.
+		 */
+		snprintf(props->package_label, sizeof(props->package_label),
+			 "OUT%u", id);
+
+	props->dpll_props.package_label = props->package_label;
+}
+
+/* An output's reg is the chip slot it drives, not the driver's index. */
+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;
+	}
+
+	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;
+}
+
+/* Free the result with sit9531x_pin_props_put(). */
+struct sit9531x_pin_props *
+sit9531x_pin_props_get(struct sit9531x_dev *sitdev,
+		       enum dpll_pin_direction dir, u8 index)
+{
+	bool sync_in = dir == DPLL_PIN_DIRECTION_INPUT &&
+		       index == SIT9531X_INTSYNC_PIN_ID;
+	bool sync_out = dir == DPLL_PIN_DIRECTION_OUTPUT &&
+			index == SIT9531X_INTSYNC_OUT_PIN_ID;
+	bool xo = dir == DPLL_PIN_DIRECTION_INPUT &&
+		  index == SIT9531X_MAX_INPUTS;
+	struct dpll_pin_frequency *ranges;
+	struct sit9531x_pin_props *props;
+	int i, j, num_freqs = 0, rc;
+	u32 *freqs = NULL;
+	const char *type;
+	u64 curr_freq;
+
+	props = kzalloc_obj(*props, GFP_KERNEL);
+	if (!props)
+		return ERR_PTR(-ENOMEM);
+
+	if (sync_in) {
+		/* INTSYNC destination: a reference the PLL can lock to. */
+		props->dpll_props.type = DPLL_PIN_TYPE_INT_OSCILLATOR;
+		props->dpll_props.capabilities =
+			DPLL_PIN_CAPABILITIES_STATE_CAN_CHANGE;
+		curr_freq = 0;
+	} else if (sync_out) {
+		/* INTSYNC source: driving it is not a reference selection */
+		props->dpll_props.type = DPLL_PIN_TYPE_INT_OSCILLATOR;
+		props->dpll_props.capabilities =
+			DPLL_PIN_CAPABILITIES_STATE_CAN_CHANGE;
+		curr_freq = 0;
+	} else if (xo) {
+		props->dpll_props.type = DPLL_PIN_TYPE_INT_OSCILLATOR;
+		props->dpll_props.capabilities = 0;
+		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 {
+		props->dpll_props.type = DPLL_PIN_TYPE_EXT;
+		props->dpll_props.capabilities =
+			DPLL_PIN_CAPABILITIES_STATE_CAN_CHANGE;
+		curr_freq = 0;
+	}
+
+	sit9531x_prop_pin_package_label_set(sitdev, props, dir, index);
+
+	/* Internal pins take no properties from the firmware node. */
+	if (sync_in || sync_out || xo)
+		goto skip_fwnode_props;
+
+	rc = sit9531x_prop_pin_fwnode_get(sitdev, props, dir, index);
+	if (rc)
+		goto skip_fwnode_props;
+
+	fwnode_property_read_string(props->fwnode, "label",
+				    &props->dpll_props.board_label);
+
+	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);
+	}
+
+	if (!fwnode_property_present(props->fwnode,
+				     "supported-frequencies-hz"))
+		goto skip_fwnode_props;
+
+	/* A -hz property is 32-bit; no rate of this part needs more. */
+	num_freqs = fwnode_property_count_u32(props->fwnode,
+					      "supported-frequencies-hz");
+	if (num_freqs <= 0) {
+		rc = num_freqs ? num_freqs : -EINVAL;
+		dev_err(sitdev->dev,
+			"malformed supported-frequencies-hz for %s: %d\n",
+			props->package_label, rc);
+		goto err_alloc_freqs;
+	}
+
+	freqs = kcalloc(num_freqs, sizeof(*freqs), GFP_KERNEL);
+	if (!freqs) {
+		rc = -ENOMEM;
+		goto err_alloc_freqs;
+	}
+
+	rc = fwnode_property_read_u32_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;
+	}
+
+	/* The first listed rate seeds the input's rate */
+	if (num_freqs > 0 && dir == DPLL_PIN_DIRECTION_INPUT && !xo)
+		curr_freq = freqs[0];
+
+skip_fwnode_props:
+	if (sync_in || sync_out)
+		return props;
+
+	/*
+	 * An output with no listed rates gets one wide range, as the setter
+	 * checks Fvco/N; the XO gets its one rate.
+	 */
+	ranges = kcalloc(num_freqs + 1, sizeof(*ranges), GFP_KERNEL);
+	if (!ranges) {
+		rc = -ENOMEM;
+		goto err_alloc_ranges;
+	}
+
+	/* Set after the last allocation that can fail */
+	if (curr_freq && dir == DPLL_PIN_DIRECTION_INPUT)
+		sitdev->ref[index].freq = curr_freq;
+
+	j = 0;
+
+	for (i = 0; i < num_freqs; i++) {
+		struct dpll_pin_frequency freq = DPLL_PIN_FREQUENCY(freqs[i]);
+
+		ranges[j++] = freq;
+	}
+
+	if (!num_freqs && dir == DPLL_PIN_DIRECTION_OUTPUT) {
+		ranges[j].min = 1;
+		ranges[j].max = 1000000000ULL; /* 1 GHz */
+		j++;
+	} else if (!num_freqs && curr_freq) {
+		struct dpll_pin_frequency f = DPLL_PIN_FREQUENCY(curr_freq);
+
+		ranges[j++] = f;
+	}
+
+	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);
+}
+
+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);
+}
+
+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 || !types[index])
+		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..b16db0bc51c6
--- /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@sitime.com>
+ * Author: Oleg Zadorozhnyi <Oleg.Zadorozhnyi@devoxsoftware.com>
+ */
+
+#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.39.2 (Apple Git-143)


  parent reply	other threads:[~2026-11-10 20:26 UTC|newest]

Thread overview: 15+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-11-10 20:26 [PATCH net-next v15 00/13] dpll: add SiTime SiT9531x DPLL clock driver Ali Rouhi
2026-11-10 20:26 ` [PATCH net-next v15 01/13] dpll: omit pin phase attributes the driver has no value for Ali Rouhi
2026-11-11 15:35   ` Ivan Vecera
2026-11-10 20:26 ` [PATCH net-next v15 02/13] dt-bindings: vendor-prefixes: add SiTime Corporation Ali Rouhi
2026-11-10 20:26 ` [PATCH net-next v15 03/13] dt-bindings: dpll: add SiTime SiT95316 clock generator Ali Rouhi
2026-11-10 20:26 ` [PATCH net-next v15 04/13] dpll: add basic SiTime SiT9531x support Ali Rouhi
2026-11-10 20:26 ` [PATCH net-next v15 06/13] dpll: sit9531x: register DPLL devices and pins Ali Rouhi
2026-11-10 20:26 ` Ali Rouhi [this message]
2026-11-10 20:26 ` [PATCH net-next v15 07/13] dpll: sit9531x: implement input pin state on a DPLL Ali Rouhi
2026-11-10 20:26 ` [PATCH net-next v15 09/13] dpll: sit9531x: add support to get and set frequency on pins Ali Rouhi
2026-11-10 20:26 ` [PATCH net-next v15 08/13] dpll: sit9531x: add support to get and set priority on input pins Ali Rouhi
2026-11-10 20:26 ` [PATCH net-next v15 10/13] dpll: sit9531x: implement output pin state on a DPLL Ali Rouhi
2026-11-10 20:26 ` [PATCH net-next v15 12/13] dpll: sit9531x: add support to get phase offset on the connected input pin Ali Rouhi
2026-11-10 20:26 ` [PATCH net-next v15 11/13] dpll: sit9531x: add support to adjust output phase Ali Rouhi
2026-11-10 20:26 ` [PATCH net-next v15 13/13] dpll: sit9531x: model the inter-PLL sync line as a pair of pins Ali Rouhi

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20261110202607.55744-6-arouhi@sitime.com \
    --to=arouhi@sitime.com \
    --cc=Oleg.Zadorozhnyi@devoxsoftware.com \
    --cc=arkadiusz.kubalewski@intel.com \
    --cc=cjubran@nvidia.com \
    --cc=conor+dt@kernel.org \
    --cc=devicetree@vger.kernel.org \
    --cc=ivecera@redhat.com \
    --cc=jiri@resnulli.us \
    --cc=krzk+dt@kernel.org \
    --cc=kuba@kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=netdev@vger.kernel.org \
    --cc=pabeni@redhat.com \
    --cc=prabhakar.mahadev-lad.rj@bp.renesas.com \
    --cc=robh@kernel.org \
    --cc=vadim.fedorenko@linux.dev \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®