[RFC PATCH v7 1/8] dpll: spec: Add Netlink spec in YAML

Kubalewski, Arkadiusz arkadiusz.kubalewski at intel.com
Thu May 11 00:38:04 PDT 2023


>From: Jiri Pirko <jiri at resnulli.us>
>Sent: Thursday, May 4, 2023 2:03 PM
>
>Fri, Apr 28, 2023 at 02:20:02AM CEST, vadfed at meta.com wrote:
>>From: Arkadiusz Kubalewski <arkadiusz.kubalewski at intel.com>
>>
>>Add a protocol spec for DPLL.
>>Add code generated from the spec.
>>
>>Signed-off-by: Jakub Kicinski <kuba at kernel.org>
>>Signed-off-by: Michal Michalik <michal.michalik at intel.com>
>>Signed-off-by: Arkadiusz Kubalewski <arkadiusz.kubalewski at intel.com>
>>Signed-off-by: Vadim Fedorenko <vadim.fedorenko at linux.dev>
>>---
>> Documentation/netlink/specs/dpll.yaml | 472 ++++++++++++++++++++++++++
>> drivers/dpll/dpll_nl.c                | 126 +++++++
>> drivers/dpll/dpll_nl.h                |  42 +++
>> include/uapi/linux/dpll.h             | 202 +++++++++++
>> 4 files changed, 842 insertions(+)
>> create mode 100644 Documentation/netlink/specs/dpll.yaml
>> create mode 100644 drivers/dpll/dpll_nl.c
>> create mode 100644 drivers/dpll/dpll_nl.h
>> create mode 100644 include/uapi/linux/dpll.h
>>
>>diff --git a/Documentation/netlink/specs/dpll.yaml
>>b/Documentation/netlink/specs/dpll.yaml
>>new file mode 100644
>>index 000000000000..67ca0f6cf2d5
>>--- /dev/null
>>+++ b/Documentation/netlink/specs/dpll.yaml
>>@@ -0,0 +1,472 @@
>>+# SPDX-License-Identifier: ((GPL-2.0 WITH Linux-syscall-note) OR BSD-3-
>>Clause)
>>+
>>+name: dpll
>>+
>>+doc: DPLL subsystem.
>>+
>>+definitions:
>>+  -
>>+    type: enum
>>+    name: mode
>>+    doc: |
>>+      working-modes a dpll can support, differentiate if and how dpll
>>selects
>>+      one of its sources to syntonize with it, valid values for DPLL_A_MODE
>>+      attribute
>>+    entries:
>>+      -
>>+        name: unspec
>
>In general, why exactly do we need unspec values in enums and CMDs?
>What is the usecase. If there isn't please remove.
>

Sure, fixed.

>
>>+        doc: unspecified value
>>+      -
>>+        name: manual
>>+        doc: source can be only selected by sending a request to dpll
>>+      -
>>+        name: automatic
>>+        doc: highest prio, valid source, auto selected by dpll
>>+      -
>>+        name: holdover
>>+        doc: dpll forced into holdover mode
>>+      -
>>+        name: freerun
>>+        doc: dpll driven on system clk, no holdover available
>
>Remove "no holdover available". This is not a state, this is a mode
>configuration. If holdover is or isn't available, is a runtime info.
>

Fiexd.

>
>>+      -
>>+        name: nco
>>+        doc: dpll driven by Numerically Controlled Oscillator
>>+    render-max: true
>>+  -
>>+    type: enum
>>+    name: lock-status
>>+    doc: |
>>+      provides information of dpll device lock status, valid values for
>>+      DPLL_A_LOCK_STATUS attribute
>>+    entries:
>>+      -
>>+        name: unspec
>>+        doc: unspecified value
>>+      -
>>+        name: unlocked
>>+        doc: |
>>+          dpll was not yet locked to any valid source (or is in one of
>>+          modes: DPLL_MODE_FREERUN, DPLL_MODE_NCO)
>>+      -
>>+        name: calibrating
>>+        doc: dpll is trying to lock to a valid signal
>>+      -
>>+        name: locked
>>+        doc: dpll is locked
>>+      -
>>+        name: holdover
>>+        doc: |
>>+          dpll is in holdover state - lost a valid lock or was forced by
>>+          selecting DPLL_MODE_HOLDOVER mode
>
>Is it needed to mention the holdover mode. It's slightly confusing,
>because user might understand that the lock-status is always "holdover"
>in case of "holdover" mode. But it could be "unlocked", can't it?
>Perhaps I don't understand the flows there correctly :/
>

Yes, it could be unlocked even when user requests the 'holdover' mode, i.e.
when the dpll was not locked to a valid source before requesting the mode.
Improved the docs:
        name: holdover
        doc: |
          dpll is in holdover state - lost a valid lock or was forced
          by selecting DPLL_MODE_HOLDOVER mode (latter possible only
          when dpll lock-state was already DPLL_LOCK_STATUS_LOCKED,
	  if it was not, the dpll's lock-status will remain
          DPLL_LOCK_STATUS_UNLOCKED even if user requests
          DPLL_MODE_HOLDOVER)
Is that better?

>
>>+    render-max: true
>>+  -
>>+    type: const
>>+    name: temp-divider
>>+    value: 10
>>+    doc: |
>>+      temperature divider allowing userspace to calculate the
>>+      temperature as float with single digit precision.
>>+      Value of (DPLL_A_TEMP / DPLL_TEMP_DIVIDER) is integer part of
>>+      tempearture value.
>
>s/tempearture/temperature/
>
>Didn't checkpatch warn you?
>

Fixed, thanks!
No, I don't think it did.

>
>>+      Value of (DPLL_A_TEMP % DPLL_TEMP_DIVIDER) is fractional part of
>>+      temperature value.
>>+  -
>>+    type: enum
>>+    name: type
>>+    doc: type of dpll, valid values for DPLL_A_TYPE attribute
>>+    entries:
>>+      -
>>+        name: unspec
>>+        doc: unspecified value
>>+      -
>>+        name: pps
>>+        doc: dpll produces Pulse-Per-Second signal
>>+      -
>>+        name: eec
>>+        doc: dpll drives the Ethernet Equipment Clock
>>+    render-max: true
>>+  -
>>+    type: enum
>>+    name: pin-type
>>+    doc: |
>>+      defines possible types of a pin, valid values for DPLL_A_PIN_TYPE
>>+      attribute
>>+    entries:
>>+      -
>>+        name: unspec
>>+        doc: unspecified value
>>+      -
>>+        name: mux
>>+        doc: aggregates another layer of selectable pins
>>+      -
>>+        name: ext
>>+        doc: external source
>>+      -
>>+        name: synce-eth-port
>>+        doc: ethernet port PHY's recovered clock
>>+      -
>>+        name: int-oscillator
>>+        doc: device internal oscillator
>
>Is this somehow related to the mode "nco" (Numerically Controlled
>Oscillator)?
>

Yes.

>
>
>>+      -
>>+        name: gnss
>>+        doc: GNSS recovered clock
>>+    render-max: true
>>+  -
>>+    type: enum
>>+    name: pin-direction
>>+    doc: |
>>+      defines possible direction of a pin, valid values for
>>+      DPLL_A_PIN_DIRECTION attribute
>>+    entries:
>>+      -
>>+        name: unspec
>>+        doc: unspecified value
>>+      -
>>+        name: source
>>+        doc: pin used as a source of a signal
>>+      -
>>+        name: output
>>+        doc: pin used to output the signal
>>+    render-max: true
>>+  -
>>+    type: const
>>+    name: pin-frequency-1-hz
>>+    value: 1
>>+  -
>>+    type: const
>>+    name: pin-frequency-10-mhz
>>+    value: 10000000
>>+  -
>>+    type: enum
>>+    name: pin-state
>>+    doc: |
>>+      defines possible states of a pin, valid values for
>>+      DPLL_A_PIN_STATE attribute
>>+    entries:
>>+      -
>>+        name: unspec
>>+        doc: unspecified value
>>+      -
>>+        name: connected
>>+        doc: pin connected, active source of phase locked loop
>>+      -
>>+        name: disconnected
>>+        doc: pin disconnected, not considered as a valid source
>>+      -
>>+        name: selectable
>>+        doc: pin enabled for automatic source selection
>>+    render-max: true
>>+  -
>>+    type: flags
>>+    name: pin-caps
>>+    doc: |
>>+      defines possible capabilities of a pin, valid flags on
>>+      DPLL_A_PIN_CAPS attribute
>>+    entries:
>>+      -
>>+        name: direction-can-change
>>+      -
>>+        name: priority-can-change
>>+      -
>>+        name: state-can-change
>>+  -
>>+    type: enum
>>+    name: event
>>+    doc: events of dpll generic netlink family
>>+    entries:
>>+      -
>>+        name: unspec
>>+        doc: invalid event type
>>+      -
>>+        name: device-create
>>+        doc: dpll device created
>>+      -
>>+        name: device-delete
>>+        doc: dpll device deleted
>>+      -
>>+        name: device-change
>
>Please have a separate create/delete/change values for pins.
>

Makes sense, but details, pin creation doesn't occur from uAPI perspective,
as the pins itself are not visible to the user. They are visible after they
are registered with a device, thus we would have to do something like:
- pin-register
- pin-unregister
- pin-change

Does it make sense?

>
>>+        doc: |
>>+          attribute of dpll device or pin changed, reason is to be found
>>with
>>+          an attribute type (DPLL_A_*) received with the event
>>+
>>+
>>+attribute-sets:
>>+  -
>>+    name: dpll
>>+    enum-name: dplla
>>+    attributes:
>>+      -
>>+        name: device
>>+        type: nest
>>+        value: 1
>
>Why not 0?
>

Sorry I don't recall what exact technical reasons are behind it, but all
netlink attributes I have found have 0 value attribute unused/unspec.

>Also, Plese don't have this attr as a first one. It is related to
>PIN_GET/SET cmd, it should be somewhere among related attributes.
>
>Definitelly, the handle ATTR/ATTTs should be the first one/ones.
>

Sure, fixed.

>
>
>>+        multi-attr: true
>>+        nested-attributes: device
>>+      -
>>+        name: id
>>+        type: u32
>>+      -
>>+        name: dev-name
>>+        type: string
>>+      -
>>+        name: bus-name
>>+        type: string
>>+      -
>>+        name: mode
>>+        type: u8
>>+        enum: mode
>>+      -
>>+        name: mode-supported
>>+        type: u8
>>+        enum: mode
>>+        multi-attr: true
>>+      -
>>+        name: lock-status
>>+        type: u8
>>+        enum: lock-status
>>+      -
>>+        name: temp
>>+        type: s32
>>+      -
>>+        name: clock-id
>>+        type: u64
>>+      -
>>+        name: type
>>+        type: u8
>>+        enum: type
>>+      -
>>+        name: pin-idx
>>+        type: u32
>>+      -
>>+        name: pin-label
>>+        type: string
>>+      -
>>+        name: pin-type
>>+        type: u8
>>+        enum: pin-type
>>+      -
>>+        name: pin-direction
>>+        type: u8
>>+        enum: pin-direction
>>+      -
>>+        name: pin-frequency
>>+        type: u64
>>+      -
>>+        name: pin-frequency-supported
>>+        type: nest
>>+        multi-attr: true
>>+        nested-attributes: pin-frequency-range
>>+      -
>>+        name: pin-frequency-min
>>+        type: u64
>>+      -
>>+        name: pin-frequency-max
>>+        type: u64
>>+      -
>>+        name: pin-prio
>>+        type: u32
>>+      -
>>+        name: pin-state
>>+        type: u8
>>+        enum: pin-state
>>+      -
>>+        name: pin-parent
>>+        type: nest
>>+        multi-attr: true
>>+        nested-attributes: pin-parent
>>+      -
>>+        name: pin-parent-idx
>>+        type: u32
>>+      -
>>+        name: pin-rclk-device
>>+        type: string
>>+      -
>>+        name: pin-dpll-caps
>>+        type: u32
>>+  -
>>+    name: device
>>+    subset-of: dpll
>>+    attributes:
>>+      -
>>+        name: id
>>+        type: u32
>>+        value: 2
>>+      -
>>+        name: dev-name
>>+        type: string
>>+      -
>>+        name: bus-name
>>+        type: string
>>+      -
>>+        name: mode
>>+        type: u8
>>+        enum: mode
>>+      -
>>+        name: mode-supported
>>+        type: u8
>>+        enum: mode
>>+        multi-attr: true
>>+      -
>>+        name: lock-status
>>+        type: u8
>>+        enum: lock-status
>>+      -
>>+        name: temp
>>+        type: s32
>>+      -
>>+        name: clock-id
>>+        type: u64
>>+      -
>>+        name: type
>>+        type: u8
>>+        enum: type
>>+      -
>>+        name: pin-prio
>>+        type: u32
>>+        value: 19
>
>Do you still need to pass values for a subset? That is odd. Well, I
>think is is odd to pass anything other than names in subset definition,
>the rest of the info is in the original attribute set definition,
>isn't it?
>Jakub?
>

Yes it is fixed, I will remove those.

>
>>+      -
>>+        name: pin-state
>>+        type: u8
>>+        enum: pin-state
>>+  -
>>+    name: pin-parent
>>+    subset-of: dpll
>>+    attributes:
>>+      -
>>+        name: pin-state
>>+        type: u8
>>+        value: 20
>>+        enum: pin-state
>>+      -
>>+        name: pin-parent-idx
>>+        type: u32
>>+        value: 22
>>+      -
>>+        name: pin-rclk-device
>>+        type: string
>>+  -
>>+    name: pin-frequency-range
>>+    subset-of: dpll
>>+    attributes:
>>+      -
>>+        name: pin-frequency-min
>>+        type: u64
>>+        value: 17
>>+      -
>>+        name: pin-frequency-max
>>+        type: u64
>>+
>>+operations:
>>+  list:
>>+    -
>>+      name: unspec
>>+      doc: unused
>>+
>>+    -
>>+      name: device-get
>>+      doc: |
>>+        Get list of DPLL devices (dump) or attributes of a single dpll
>>device
>>+      attribute-set: dpll
>>+      flags: [ admin-perm ]
>
>I may be missing something, but why do you enforce adming perm for
>get/dump cmds?
>

Yes, security reasons, we don't want regular users to spam-query the driver
ops. Also explained in docs:
All netlink commands require ``GENL_ADMIN_PERM``. This is to prevent
any spamming/D.o.S. from unauthorized userspace applications.

>
>>+
>>+      do:
>>+        pre: dpll-pre-doit
>>+        post: dpll-post-doit
>>+        request:
>>+          attributes:
>>+            - id
>>+            - bus-name
>>+            - dev-name
>>+        reply:
>>+          attributes:
>>+            - device
>>+
>>+      dump:
>>+        pre: dpll-pre-dumpit
>>+        post: dpll-post-dumpit
>>+        reply:
>>+          attributes:
>>+            - device
>
>I might be missing something, but this means "device" netdev attribute
>DPLL_A_DEVICE, right? If yes, that is incorrect and you should list all
>the device attrs.
>

Actually this means that attributes expected in response to this command are
from `device` subset.
But I see your point, will make `device` subset only for pin's nested
attributes, and here will list device attributes.

>
>>+
>>+    -
>>+      name: device-set
>>+      doc: Set attributes for a DPLL device
>>+      attribute-set: dpll
>>+      flags: [ admin-perm ]
>>+
>>+      do:
>>+        pre: dpll-pre-doit
>>+        post: dpll-post-doit
>>+        request:
>>+          attributes:
>>+            - id
>>+            - bus-name
>>+            - dev-name
>>+            - mode
>>+
>>+    -
>>+      name: pin-get
>>+      doc: |
>>+        Get list of pins and its attributes.
>>+        - dump request without any attributes given - list all the pins
>>in the system
>>+        - dump request with target dpll - list all the pins registered
>>with a given dpll device
>>+        - do request with target dpll and target pin - single pin attributes
>>+      attribute-set: dpll
>>+      flags: [ admin-perm ]
>>+
>>+      do:
>>+        pre: dpll-pin-pre-doit
>>+        post: dpll-pin-post-doit
>>+        request:
>>+          attributes:
>>+            - id
>>+            - bus-name
>>+            - dev-name
>>+            - pin-idx
>>+        reply: &pin-attrs
>>+          attributes:
>>+            - pin-idx
>>+            - pin-label
>>+            - pin-type
>>+            - pin-direction
>>+            - pin-frequency
>>+            - pin-frequency-supported
>>+            - pin-parent
>>+            - pin-rclk-device
>>+            - pin-dpll-caps
>>+            - device
>>+
>>+      dump:
>>+        pre: dpll-pin-pre-dumpit
>>+        post: dpll-pin-post-dumpit
>>+        request:
>>+          attributes:
>>+            - id
>>+            - bus-name
>>+            - dev-name
>>+        reply: *pin-attrs
>>+
>>+    -
>>+      name: pin-set
>>+      doc: Set attributes of a target pin
>>+      attribute-set: dpll
>>+      flags: [ admin-perm ]
>>+
>>+      do:
>>+        pre: dpll-pin-pre-doit
>>+        post: dpll-pin-post-doit
>>+        request:
>>+          attributes:
>>+            - id
>>+            - bus-name
>>+            - dev-name
>>+            - pin-idx
>>+            - pin-frequency
>>+            - pin-direction
>>+            - pin-prio
>>+            - pin-state
>>+            - pin-parent-idx
>>+
>>+mcast-groups:
>>+  list:
>>+    -
>>+      name: monitor
>>diff --git a/drivers/dpll/dpll_nl.c b/drivers/dpll/dpll_nl.c
>>new file mode 100644
>>index 000000000000..2f8643f401b0
>>--- /dev/null
>>+++ b/drivers/dpll/dpll_nl.c
>>@@ -0,0 +1,126 @@
>>+// SPDX-License-Identifier: ((GPL-2.0 WITH Linux-syscall-note) OR BSD-3-
>>Clause)
>>+/* Do not edit directly, auto-generated from: */
>>+/*	Documentation/netlink/specs/dpll.yaml */
>>+/* YNL-GEN kernel source */
>>+
>>+#include <net/netlink.h>
>>+#include <net/genetlink.h>
>>+
>>+#include "dpll_nl.h"
>>+
>>+#include <linux/dpll.h>
>>+
>>+/* DPLL_CMD_DEVICE_GET - do */
>>+static const struct nla_policy dpll_device_get_nl_policy[DPLL_A_BUS_NAME
>>+ 1] = {
>>+	[DPLL_A_ID] = { .type = NLA_U32, },
>>+	[DPLL_A_BUS_NAME] = { .type = NLA_NUL_STRING, },
>>+	[DPLL_A_DEV_NAME] = { .type = NLA_NUL_STRING, },
>>+};
>>+
>>+/* DPLL_CMD_DEVICE_SET - do */
>>+static const struct nla_policy dpll_device_set_nl_policy[DPLL_A_MODE + 1]
>>= {
>>+	[DPLL_A_ID] = { .type = NLA_U32, },
>>+	[DPLL_A_BUS_NAME] = { .type = NLA_NUL_STRING, },
>>+	[DPLL_A_DEV_NAME] = { .type = NLA_NUL_STRING, },
>>+	[DPLL_A_MODE] = NLA_POLICY_MAX(NLA_U8, 5),
>
>I know it is a matter of the generator script, still have to note it
>hurts my eyes to see "5" here :)
>

Yes, that's true.

Thanks!
Arkadiusz

>
>>+};
>>+
>>+/* DPLL_CMD_PIN_GET - do */
>>+static const struct nla_policy dpll_pin_get_do_nl_policy[DPLL_A_PIN_IDX +
>>1] = {
>>+	[DPLL_A_ID] = { .type = NLA_U32, },
>>+	[DPLL_A_BUS_NAME] = { .type = NLA_NUL_STRING, },
>>+	[DPLL_A_DEV_NAME] = { .type = NLA_NUL_STRING, },
>>+	[DPLL_A_PIN_IDX] = { .type = NLA_U32, },
>>+};
>>+
>>+/* DPLL_CMD_PIN_GET - dump */
>>+static const struct nla_policy
>>dpll_pin_get_dump_nl_policy[DPLL_A_BUS_NAME + 1] = {
>>+	[DPLL_A_ID] = { .type = NLA_U32, },
>>+	[DPLL_A_BUS_NAME] = { .type = NLA_NUL_STRING, },
>>+	[DPLL_A_DEV_NAME] = { .type = NLA_NUL_STRING, },
>>+};
>>+
>>+/* DPLL_CMD_PIN_SET - do */
>>+static const struct nla_policy
>>dpll_pin_set_nl_policy[DPLL_A_PIN_PARENT_IDX + 1] = {
>>+	[DPLL_A_ID] = { .type = NLA_U32, },
>>+	[DPLL_A_BUS_NAME] = { .type = NLA_NUL_STRING, },
>>+	[DPLL_A_DEV_NAME] = { .type = NLA_NUL_STRING, },
>>+	[DPLL_A_PIN_IDX] = { .type = NLA_U32, },
>>+	[DPLL_A_PIN_FREQUENCY] = { .type = NLA_U64, },
>>+	[DPLL_A_PIN_DIRECTION] = NLA_POLICY_MAX(NLA_U8, 2),
>>+	[DPLL_A_PIN_PRIO] = { .type = NLA_U32, },
>>+	[DPLL_A_PIN_STATE] = NLA_POLICY_MAX(NLA_U8, 3),
>>+	[DPLL_A_PIN_PARENT_IDX] = { .type = NLA_U32, },
>>+};
>>+
>>+/* Ops table for dpll */
>>+static const struct genl_split_ops dpll_nl_ops[] = {
>>+	{
>>+		.cmd		= DPLL_CMD_DEVICE_GET,
>>+		.pre_doit	= dpll_pre_doit,
>>+		.doit		= dpll_nl_device_get_doit,
>>+		.post_doit	= dpll_post_doit,
>>+		.policy		= dpll_device_get_nl_policy,
>>+		.maxattr	= DPLL_A_BUS_NAME,
>>+		.flags		= GENL_ADMIN_PERM | GENL_CMD_CAP_DO,
>>+	},
>>+	{
>>+		.cmd	= DPLL_CMD_DEVICE_GET,
>>+		.start	= dpll_pre_dumpit,
>>+		.dumpit	= dpll_nl_device_get_dumpit,
>>+		.done	= dpll_post_dumpit,
>>+		.flags	= GENL_ADMIN_PERM | GENL_CMD_CAP_DUMP,
>>+	},
>>+	{
>>+		.cmd		= DPLL_CMD_DEVICE_SET,
>>+		.pre_doit	= dpll_pre_doit,
>>+		.doit		= dpll_nl_device_set_doit,
>>+		.post_doit	= dpll_post_doit,
>>+		.policy		= dpll_device_set_nl_policy,
>>+		.maxattr	= DPLL_A_MODE,
>>+		.flags		= GENL_ADMIN_PERM | GENL_CMD_CAP_DO,
>>+	},
>>+	{
>>+		.cmd		= DPLL_CMD_PIN_GET,
>>+		.pre_doit	= dpll_pin_pre_doit,
>>+		.doit		= dpll_nl_pin_get_doit,
>>+		.post_doit	= dpll_pin_post_doit,
>>+		.policy		= dpll_pin_get_do_nl_policy,
>>+		.maxattr	= DPLL_A_PIN_IDX,
>>+		.flags		= GENL_ADMIN_PERM | GENL_CMD_CAP_DO,
>>+	},
>>+	{
>>+		.cmd		= DPLL_CMD_PIN_GET,
>>+		.start		= dpll_pin_pre_dumpit,
>>+		.dumpit		= dpll_nl_pin_get_dumpit,
>>+		.done		= dpll_pin_post_dumpit,
>>+		.policy		= dpll_pin_get_dump_nl_policy,
>>+		.maxattr	= DPLL_A_BUS_NAME,
>>+		.flags		= GENL_ADMIN_PERM | GENL_CMD_CAP_DUMP,
>>+	},
>>+	{
>>+		.cmd		= DPLL_CMD_PIN_SET,
>>+		.pre_doit	= dpll_pin_pre_doit,
>>+		.doit		= dpll_nl_pin_set_doit,
>>+		.post_doit	= dpll_pin_post_doit,
>>+		.policy		= dpll_pin_set_nl_policy,
>>+		.maxattr	= DPLL_A_PIN_PARENT_IDX,
>>+		.flags		= GENL_ADMIN_PERM | GENL_CMD_CAP_DO,
>>+	},
>>+};
>>+
>>+static const struct genl_multicast_group dpll_nl_mcgrps[] = {
>>+	[DPLL_NLGRP_MONITOR] = { "monitor", },
>>+};
>>+
>>+struct genl_family dpll_nl_family __ro_after_init = {
>>+	.name		= DPLL_FAMILY_NAME,
>>+	.version	= DPLL_FAMILY_VERSION,
>>+	.netnsok	= true,
>>+	.parallel_ops	= true,
>>+	.module		= THIS_MODULE,
>>+	.split_ops	= dpll_nl_ops,
>>+	.n_split_ops	= ARRAY_SIZE(dpll_nl_ops),
>>+	.mcgrps		= dpll_nl_mcgrps,
>>+	.n_mcgrps	= ARRAY_SIZE(dpll_nl_mcgrps),
>>+};
>>diff --git a/drivers/dpll/dpll_nl.h b/drivers/dpll/dpll_nl.h
>>new file mode 100644
>>index 000000000000..57ab2da562ba
>>--- /dev/null
>>+++ b/drivers/dpll/dpll_nl.h
>>@@ -0,0 +1,42 @@
>>+/* SPDX-License-Identifier: ((GPL-2.0 WITH Linux-syscall-note) OR BSD-3-
>>Clause) */
>>+/* Do not edit directly, auto-generated from: */
>>+/*	Documentation/netlink/specs/dpll.yaml */
>>+/* YNL-GEN kernel header */
>>+
>>+#ifndef _LINUX_DPLL_GEN_H
>>+#define _LINUX_DPLL_GEN_H
>>+
>>+#include <net/netlink.h>
>>+#include <net/genetlink.h>
>>+
>>+#include <linux/dpll.h>
>>+
>>+int dpll_pre_doit(const struct genl_split_ops *ops, struct sk_buff *skb,
>>+		  struct genl_info *info);
>>+int dpll_pin_pre_doit(const struct genl_split_ops *ops, struct sk_buff *skb,
>>+		      struct genl_info *info);
>>+void
>>+dpll_post_doit(const struct genl_split_ops *ops, struct sk_buff *skb,
>>+	       struct genl_info *info);
>>+void
>>+dpll_pin_post_doit(const struct genl_split_ops *ops, struct sk_buff *skb,
>>+		   struct genl_info *info);
>>+int dpll_pre_dumpit(struct netlink_callback *cb);
>>+int dpll_pin_pre_dumpit(struct netlink_callback *cb);
>>+int dpll_post_dumpit(struct netlink_callback *cb);
>>+int dpll_pin_post_dumpit(struct netlink_callback *cb);
>>+
>>+int dpll_nl_device_get_doit(struct sk_buff *skb, struct genl_info *info);
>>+int dpll_nl_device_get_dumpit(struct sk_buff *skb, struct
>>netlink_callback *cb);
>>+int dpll_nl_device_set_doit(struct sk_buff *skb, struct genl_info *info);
>>+int dpll_nl_pin_get_doit(struct sk_buff *skb, struct genl_info *info);
>>+int dpll_nl_pin_get_dumpit(struct sk_buff *skb, struct netlink_callback
>>*cb);
>>+int dpll_nl_pin_set_doit(struct sk_buff *skb, struct genl_info *info);
>>+
>>+enum {
>>+	DPLL_NLGRP_MONITOR,
>>+};
>>+
>>+extern struct genl_family dpll_nl_family;
>>+
>>+#endif /* _LINUX_DPLL_GEN_H */
>>diff --git a/include/uapi/linux/dpll.h b/include/uapi/linux/dpll.h
>>new file mode 100644
>>index 000000000000..e188bc189754
>>--- /dev/null
>>+++ b/include/uapi/linux/dpll.h
>>@@ -0,0 +1,202 @@
>>+/* SPDX-License-Identifier: ((GPL-2.0 WITH Linux-syscall-note) OR BSD-3-
>>Clause) */
>>+/* Do not edit directly, auto-generated from: */
>>+/*	Documentation/netlink/specs/dpll.yaml */
>>+/* YNL-GEN uapi header */
>>+
>>+#ifndef _UAPI_LINUX_DPLL_H
>>+#define _UAPI_LINUX_DPLL_H
>>+
>>+#define DPLL_FAMILY_NAME	"dpll"
>>+#define DPLL_FAMILY_VERSION	1
>>+
>>+/**
>>+ * enum dpll_mode - working-modes a dpll can support, differentiate if and
>>how
>>+ *   dpll selects one of its sources to syntonize with it, valid values for
>>+ *   DPLL_A_MODE attribute
>>+ * @DPLL_MODE_UNSPEC: unspecified value
>>+ * @DPLL_MODE_MANUAL: source can be only selected by sending a request to
>>dpll
>>+ * @DPLL_MODE_AUTOMATIC: highest prio, valid source, auto selected by dpll
>>+ * @DPLL_MODE_HOLDOVER: dpll forced into holdover mode
>>+ * @DPLL_MODE_FREERUN: dpll driven on system clk, no holdover available
>>+ * @DPLL_MODE_NCO: dpll driven by Numerically Controlled Oscillator
>>+ */
>>+enum dpll_mode {
>>+	DPLL_MODE_UNSPEC,
>>+	DPLL_MODE_MANUAL,
>>+	DPLL_MODE_AUTOMATIC,
>>+	DPLL_MODE_HOLDOVER,
>>+	DPLL_MODE_FREERUN,
>>+	DPLL_MODE_NCO,
>>+
>>+	__DPLL_MODE_MAX,
>>+	DPLL_MODE_MAX = (__DPLL_MODE_MAX - 1)
>>+};
>>+
>>+/**
>>+ * enum dpll_lock_status - provides information of dpll device lock
>>status,
>>+ *   valid values for DPLL_A_LOCK_STATUS attribute
>>+ * @DPLL_LOCK_STATUS_UNSPEC: unspecified value
>>+ * @DPLL_LOCK_STATUS_UNLOCKED: dpll was not yet locked to any valid
>>source (or
>>+ *   is in one of modes: DPLL_MODE_FREERUN, DPLL_MODE_NCO)
>>+ * @DPLL_LOCK_STATUS_CALIBRATING: dpll is trying to lock to a valid
>>signal
>>+ * @DPLL_LOCK_STATUS_LOCKED: dpll is locked
>>+ * @DPLL_LOCK_STATUS_HOLDOVER: dpll is in holdover state - lost a valid
>>lock or
>>+ *   was forced by selecting DPLL_MODE_HOLDOVER mode
>>+ */
>>+enum dpll_lock_status {
>>+	DPLL_LOCK_STATUS_UNSPEC,
>>+	DPLL_LOCK_STATUS_UNLOCKED,
>>+	DPLL_LOCK_STATUS_CALIBRATING,
>>+	DPLL_LOCK_STATUS_LOCKED,
>>+	DPLL_LOCK_STATUS_HOLDOVER,
>>+
>>+	__DPLL_LOCK_STATUS_MAX,
>>+	DPLL_LOCK_STATUS_MAX = (__DPLL_LOCK_STATUS_MAX - 1)
>>+};
>>+
>>+#define DPLL_TEMP_DIVIDER	10
>>+
>>+/**
>>+ * enum dpll_type - type of dpll, valid values for DPLL_A_TYPE attribute
>>+ * @DPLL_TYPE_UNSPEC: unspecified value
>>+ * @DPLL_TYPE_PPS: dpll produces Pulse-Per-Second signal
>>+ * @DPLL_TYPE_EEC: dpll drives the Ethernet Equipment Clock
>>+ */
>>+enum dpll_type {
>>+	DPLL_TYPE_UNSPEC,
>>+	DPLL_TYPE_PPS,
>>+	DPLL_TYPE_EEC,
>>+
>>+	__DPLL_TYPE_MAX,
>>+	DPLL_TYPE_MAX = (__DPLL_TYPE_MAX - 1)
>>+};
>>+
>>+/**
>>+ * enum dpll_pin_type - defines possible types of a pin, valid values for
>>+ *   DPLL_A_PIN_TYPE attribute
>>+ * @DPLL_PIN_TYPE_UNSPEC: unspecified value
>>+ * @DPLL_PIN_TYPE_MUX: aggregates another layer of selectable pins
>>+ * @DPLL_PIN_TYPE_EXT: external source
>>+ * @DPLL_PIN_TYPE_SYNCE_ETH_PORT: ethernet port PHY's recovered clock
>>+ * @DPLL_PIN_TYPE_INT_OSCILLATOR: device internal oscillator
>>+ * @DPLL_PIN_TYPE_GNSS: GNSS recovered clock
>>+ */
>>+enum dpll_pin_type {
>>+	DPLL_PIN_TYPE_UNSPEC,
>>+	DPLL_PIN_TYPE_MUX,
>>+	DPLL_PIN_TYPE_EXT,
>>+	DPLL_PIN_TYPE_SYNCE_ETH_PORT,
>>+	DPLL_PIN_TYPE_INT_OSCILLATOR,
>>+	DPLL_PIN_TYPE_GNSS,
>>+
>>+	__DPLL_PIN_TYPE_MAX,
>>+	DPLL_PIN_TYPE_MAX = (__DPLL_PIN_TYPE_MAX - 1)
>>+};
>>+
>>+/**
>>+ * enum dpll_pin_direction - defines possible direction of a pin, valid
>>values
>>+ *   for DPLL_A_PIN_DIRECTION attribute
>>+ * @DPLL_PIN_DIRECTION_UNSPEC: unspecified value
>>+ * @DPLL_PIN_DIRECTION_SOURCE: pin used as a source of a signal
>>+ * @DPLL_PIN_DIRECTION_OUTPUT: pin used to output the signal
>>+ */
>>+enum dpll_pin_direction {
>>+	DPLL_PIN_DIRECTION_UNSPEC,
>>+	DPLL_PIN_DIRECTION_SOURCE,
>>+	DPLL_PIN_DIRECTION_OUTPUT,
>>+
>>+	__DPLL_PIN_DIRECTION_MAX,
>>+	DPLL_PIN_DIRECTION_MAX = (__DPLL_PIN_DIRECTION_MAX - 1)
>>+};
>>+
>>+#define DPLL_PIN_FREQUENCY_1_HZ		1
>>+#define DPLL_PIN_FREQUENCY_10_MHZ	10000000
>>+
>>+/**
>>+ * enum dpll_pin_state - defines possible states of a pin, valid values for
>>+ *   DPLL_A_PIN_STATE attribute
>>+ * @DPLL_PIN_STATE_UNSPEC: unspecified value
>>+ * @DPLL_PIN_STATE_CONNECTED: pin connected, active source of phase
>locked loop
>>+ * @DPLL_PIN_STATE_DISCONNECTED: pin disconnected, not considered as a valid
>>+ *   source
>>+ * @DPLL_PIN_STATE_SELECTABLE: pin enabled for automatic source selection
>>+ */
>>+enum dpll_pin_state {
>>+	DPLL_PIN_STATE_UNSPEC,
>>+	DPLL_PIN_STATE_CONNECTED,
>>+	DPLL_PIN_STATE_DISCONNECTED,
>>+	DPLL_PIN_STATE_SELECTABLE,
>>+
>>+	__DPLL_PIN_STATE_MAX,
>>+	DPLL_PIN_STATE_MAX = (__DPLL_PIN_STATE_MAX - 1)
>>+};
>>+
>>+/**
>>+ * enum dpll_pin_caps - defines possible capabilities of a pin, valid
>>flags on
>>+ *   DPLL_A_PIN_CAPS attribute
>>+ */
>>+enum dpll_pin_caps {
>>+	DPLL_PIN_CAPS_DIRECTION_CAN_CHANGE = 1,
>>+	DPLL_PIN_CAPS_PRIORITY_CAN_CHANGE = 2,
>>+	DPLL_PIN_CAPS_STATE_CAN_CHANGE = 4,
>>+};
>>+
>>+/**
>>+ * enum dpll_event - events of dpll generic netlink family
>>+ * @DPLL_EVENT_UNSPEC: invalid event type
>>+ * @DPLL_EVENT_DEVICE_CREATE: dpll device created
>>+ * @DPLL_EVENT_DEVICE_DELETE: dpll device deleted
>>+ * @DPLL_EVENT_DEVICE_CHANGE: attribute of dpll device or pin changed,
>>reason
>>+ *   is to be found with an attribute type (DPLL_A_*) received with the
>>event
>>+ */
>>+enum dpll_event {
>>+	DPLL_EVENT_UNSPEC,
>>+	DPLL_EVENT_DEVICE_CREATE,
>>+	DPLL_EVENT_DEVICE_DELETE,
>>+	DPLL_EVENT_DEVICE_CHANGE,
>>+};
>>+
>>+enum dplla {
>>+	DPLL_A_DEVICE = 1,
>>+	DPLL_A_ID,
>>+	DPLL_A_DEV_NAME,
>>+	DPLL_A_BUS_NAME,
>>+	DPLL_A_MODE,
>>+	DPLL_A_MODE_SUPPORTED,
>>+	DPLL_A_LOCK_STATUS,
>>+	DPLL_A_TEMP,
>>+	DPLL_A_CLOCK_ID,
>>+	DPLL_A_TYPE,
>>+	DPLL_A_PIN_IDX,
>>+	DPLL_A_PIN_LABEL,
>>+	DPLL_A_PIN_TYPE,
>>+	DPLL_A_PIN_DIRECTION,
>>+	DPLL_A_PIN_FREQUENCY,
>>+	DPLL_A_PIN_FREQUENCY_SUPPORTED,
>>+	DPLL_A_PIN_FREQUENCY_MIN,
>>+	DPLL_A_PIN_FREQUENCY_MAX,
>>+	DPLL_A_PIN_PRIO,
>>+	DPLL_A_PIN_STATE,
>>+	DPLL_A_PIN_PARENT,
>>+	DPLL_A_PIN_PARENT_IDX,
>>+	DPLL_A_PIN_RCLK_DEVICE,
>>+	DPLL_A_PIN_DPLL_CAPS,
>>+
>>+	__DPLL_A_MAX,
>>+	DPLL_A_MAX = (__DPLL_A_MAX - 1)
>>+};
>>+
>>+enum {
>>+	DPLL_CMD_UNSPEC = 1,
>>+	DPLL_CMD_DEVICE_GET,
>>+	DPLL_CMD_DEVICE_SET,
>>+	DPLL_CMD_PIN_GET,
>>+	DPLL_CMD_PIN_SET,
>>+
>>+	__DPLL_CMD_MAX,
>>+	DPLL_CMD_MAX = (__DPLL_CMD_MAX - 1)
>>+};
>>+
>>+#define DPLL_MCGRP_MONITOR	"monitor"
>>+
>>+#endif /* _UAPI_LINUX_DPLL_H */
>>--
>>2.34.1
>>



More information about the linux-arm-kernel mailing list