From patchwork Mon Oct 10 01:17:59 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Vadim Fedorenko X-Patchwork-Id: 13002179 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id E81F5C43219 for ; Mon, 10 Oct 2022 01:19:02 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S230092AbiJJBTB (ORCPT ); Sun, 9 Oct 2022 21:19:01 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:36028 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230387AbiJJBSv (ORCPT ); Sun, 9 Oct 2022 21:18:51 -0400 Received: from novek.ru (unknown [213.148.174.62]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 93A872E9E3; Sun, 9 Oct 2022 18:18:48 -0700 (PDT) Received: from nat1.ooonet.ru (gw.zelenaya.net [91.207.137.40]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by novek.ru (Postfix) with ESMTPSA id 751E4504BE0; Mon, 10 Oct 2022 04:14:48 +0300 (MSK) DKIM-Filter: OpenDKIM Filter v2.11.0 novek.ru 751E4504BE0 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=novek.ru; s=mail; t=1665364491; bh=r0LsBUnIVu+07SSOpJ+WM+d/OJrUs02fho5jO7YOPO0=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=J6wvkfdRBd4IkeZvADrnNehgMq7mYOfpaBMrDdpd+LuiGdwZGIUsPdr6gLSmFvsVg jKSXi9tchMenN4hjSTsM3+ew0+oSOOfLLngDX/DPEOuB/zoHAKc32/I7GSkxNfKXgG ICWn23j52lW4TSWpCmjyOrFvZWQPbOIE6vbXGnN4= From: Vadim Fedorenko To: Jakub Kicinski , Jiri Pirko , Arkadiusz Kubalewski Cc: netdev@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-clk@vger.kernel.org, Vadim Fedorenko Subject: [RFC PATCH v3 1/6] dpll: Add DPLL framework base functions Date: Mon, 10 Oct 2022 04:17:59 +0300 Message-Id: <20221010011804.23716-2-vfedorenko@novek.ru> X-Mailer: git-send-email 2.27.0 In-Reply-To: <20221010011804.23716-1-vfedorenko@novek.ru> References: <20221010011804.23716-1-vfedorenko@novek.ru> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org X-Patchwork-State: RFC From: Vadim Fedorenko DPLL framework is used to represent and configure DPLL devices in systems. Each device that has DPLL and can configure sources and outputs can use this framework. Signed-off-by: Vadim Fedorenko Co-developed-by: Jakub Kicinski Co-developed-by: Arkadiusz Kubalewski --- MAINTAINERS | 8 + drivers/Kconfig | 2 + drivers/Makefile | 1 + drivers/dpll/Kconfig | 7 + drivers/dpll/Makefile | 7 + drivers/dpll/dpll_core.c | 177 +++++++++++++++ drivers/dpll/dpll_core.h | 41 ++++ drivers/dpll/dpll_netlink.c | 417 ++++++++++++++++++++++++++++++++++++ drivers/dpll/dpll_netlink.h | 7 + include/linux/dpll.h | 29 +++ include/uapi/linux/dpll.h | 101 +++++++++ 11 files changed, 797 insertions(+) create mode 100644 drivers/dpll/Kconfig create mode 100644 drivers/dpll/Makefile create mode 100644 drivers/dpll/dpll_core.c create mode 100644 drivers/dpll/dpll_core.h create mode 100644 drivers/dpll/dpll_netlink.c create mode 100644 drivers/dpll/dpll_netlink.h create mode 100644 include/linux/dpll.h create mode 100644 include/uapi/linux/dpll.h diff --git a/MAINTAINERS b/MAINTAINERS index 9ca84cb5ab4a..e2f4fede937f 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -6301,6 +6301,14 @@ F: Documentation/networking/device_drivers/ethernet/freescale/dpaa2/switch-drive F: drivers/net/ethernet/freescale/dpaa2/dpaa2-switch* F: drivers/net/ethernet/freescale/dpaa2/dpsw* +DPLL CLOCK SUBSYSTEM +M: Vadim Fedorenko +L: netdev@vger.kernel.org +S: Maintained +F: drivers/dpll/* +F: include/net/dpll.h +F: include/uapi/linux/dpll.h + DRBD DRIVER M: Philipp Reisner M: Lars Ellenberg diff --git a/drivers/Kconfig b/drivers/Kconfig index 19ee995bd0ae..a3e00294a995 100644 --- a/drivers/Kconfig +++ b/drivers/Kconfig @@ -239,4 +239,6 @@ source "drivers/peci/Kconfig" source "drivers/hte/Kconfig" +source "drivers/dpll/Kconfig" + endmenu diff --git a/drivers/Makefile b/drivers/Makefile index 057857258bfd..78a68f1621cc 100644 --- a/drivers/Makefile +++ b/drivers/Makefile @@ -188,3 +188,4 @@ obj-$(CONFIG_COUNTER) += counter/ obj-$(CONFIG_MOST) += most/ obj-$(CONFIG_PECI) += peci/ obj-$(CONFIG_HTE) += hte/ +obj-$(CONFIG_DPLL) += dpll/ diff --git a/drivers/dpll/Kconfig b/drivers/dpll/Kconfig new file mode 100644 index 000000000000..a4cae73f20d3 --- /dev/null +++ b/drivers/dpll/Kconfig @@ -0,0 +1,7 @@ +# SPDX-License-Identifier: GPL-2.0-only +# +# Generic DPLL drivers configuration +# + +config DPLL + bool diff --git a/drivers/dpll/Makefile b/drivers/dpll/Makefile new file mode 100644 index 000000000000..0748c80097e4 --- /dev/null +++ b/drivers/dpll/Makefile @@ -0,0 +1,7 @@ +# SPDX-License-Identifier: GPL-2.0 +# +# Makefile for DPLL drivers. +# + +obj-$(CONFIG_DPLL) += dpll_sys.o +dpll_sys-y += dpll_core.o dpll_netlink.o diff --git a/drivers/dpll/dpll_core.c b/drivers/dpll/dpll_core.c new file mode 100644 index 000000000000..7fdee145e82c --- /dev/null +++ b/drivers/dpll/dpll_core.c @@ -0,0 +1,177 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * dpll_core.c - Generic DPLL Management class support. + * + * Copyright (c) 2021 Meta Platforms, Inc. and affiliates + */ + +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + +#include +#include +#include +#include + +#include "dpll_core.h" + +static DEFINE_MUTEX(dpll_device_xa_lock); +static DEFINE_XARRAY_FLAGS(dpll_device_xa, XA_FLAGS_ALLOC); +#define DPLL_REGISTERED XA_MARK_1 + +#define ASSERT_DPLL_REGISTERED(d) \ + WARN_ON_ONCE(!xa_get_mark(&dpll_device_xa, (d)->id, DPLL_REGISTERED)) +#define ASSERT_DPLL_NOT_REGISTERED(d) \ + WARN_ON_ONCE(xa_get_mark(&dpll_device_xa, (d)->id, DPLL_REGISTERED)) + + +int for_each_dpll_device(int id, int (*cb)(struct dpll_device *, void *), + void *data) +{ + struct dpll_device *dpll; + unsigned long index; + int ret = 0; + + mutex_lock(&dpll_device_xa_lock); + xa_for_each_start(&dpll_device_xa, index, dpll, id) { + if (!xa_get_mark(&dpll_device_xa, index, DPLL_REGISTERED)) + continue; + ret = cb(dpll, data); + if (ret) + break; + } + mutex_unlock(&dpll_device_xa_lock); + + return ret; +} + +struct dpll_device *dpll_device_get_by_id(int id) +{ + struct dpll_device *dpll = NULL; + + if (xa_get_mark(&dpll_device_xa, id, DPLL_REGISTERED)) + dpll = xa_load(&dpll_device_xa, id); + return dpll; +} + +struct dpll_device *dpll_device_get_by_name(const char *name) +{ + struct dpll_device *dpll, *ret = NULL; + unsigned long index; + + mutex_lock(&dpll_device_xa_lock); + xa_for_each_marked(&dpll_device_xa, index, dpll, DPLL_REGISTERED) { + if (!strcmp(dev_name(&dpll->dev), name)) { + ret = dpll; + break; + } + } + mutex_unlock(&dpll_device_xa_lock); + + return ret; +} + +void *dpll_priv(struct dpll_device *dpll) +{ + return dpll->priv; +} +EXPORT_SYMBOL_GPL(dpll_priv); + +static void dpll_device_release(struct device *dev) +{ + struct dpll_device *dpll; + + dpll = to_dpll_device(dev); + + dpll_device_unregister(dpll); + dpll_device_free(dpll); +} + +static struct class dpll_class = { + .name = "dpll", + .dev_release = dpll_device_release, +}; + +struct dpll_device *dpll_device_alloc(struct dpll_device_ops *ops, const char *name, + int sources_count, int outputs_count, void *priv) +{ + struct dpll_device *dpll; + int ret; + + dpll = kzalloc(sizeof(*dpll), GFP_KERNEL); + if (!dpll) + return ERR_PTR(-ENOMEM); + + mutex_init(&dpll->lock); + dpll->ops = ops; + dpll->dev.class = &dpll_class; + dpll->sources_count = sources_count; + dpll->outputs_count = outputs_count; + + mutex_lock(&dpll_device_xa_lock); + ret = xa_alloc(&dpll_device_xa, &dpll->id, dpll, xa_limit_16b, GFP_KERNEL); + if (ret) + goto error; + dev_set_name(&dpll->dev, "%s%d", name ? name : "dpll", dpll->id); + mutex_unlock(&dpll_device_xa_lock); + dpll->priv = priv; + + return dpll; + +error: + mutex_unlock(&dpll_device_xa_lock); + kfree(dpll); + return ERR_PTR(ret); +} +EXPORT_SYMBOL_GPL(dpll_device_alloc); + +void dpll_device_free(struct dpll_device *dpll) +{ + if (!dpll) + return; + + mutex_destroy(&dpll->lock); + kfree(dpll); +} +EXPORT_SYMBOL_GPL(dpll_device_free); + +void dpll_device_register(struct dpll_device *dpll) +{ + ASSERT_DPLL_NOT_REGISTERED(dpll); + + mutex_lock(&dpll_device_xa_lock); + xa_set_mark(&dpll_device_xa, dpll->id, DPLL_REGISTERED); + mutex_unlock(&dpll_device_xa_lock); +} +EXPORT_SYMBOL_GPL(dpll_device_register); + +void dpll_device_unregister(struct dpll_device *dpll) +{ + ASSERT_DPLL_REGISTERED(dpll); + + mutex_lock(&dpll_device_xa_lock); + xa_erase(&dpll_device_xa, dpll->id); + mutex_unlock(&dpll_device_xa_lock); +} +EXPORT_SYMBOL_GPL(dpll_device_unregister); + +static int __init dpll_init(void) +{ + int ret; + + ret = dpll_netlink_init(); + if (ret) + goto error; + + ret = class_register(&dpll_class); + if (ret) + goto unregister_netlink; + + return 0; + +unregister_netlink: + dpll_netlink_finish(); +error: + mutex_destroy(&dpll_device_xa_lock); + return ret; +} +subsys_initcall(dpll_init); diff --git a/drivers/dpll/dpll_core.h b/drivers/dpll/dpll_core.h new file mode 100644 index 000000000000..4b6fc9eb228f --- /dev/null +++ b/drivers/dpll/dpll_core.h @@ -0,0 +1,41 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2021 Meta Platforms, Inc. and affiliates + */ + +#ifndef __DPLL_CORE_H__ +#define __DPLL_CORE_H__ + +#include + +#include "dpll_netlink.h" + +/** + * struct dpll_device - structure for a DPLL device + * @id: unique id number for each edvice + * @dev: &struct device for this dpll device + * @sources_count: amount of input sources this dpll_device supports + * @outputs_count: amount of outputs this dpll_device supports + * @ops: operations this &dpll_device supports + * @lock: mutex to serialize operations + * @priv: pointer to private information of owner + */ +struct dpll_device { + int id; + struct device dev; + int sources_count; + int outputs_count; + struct dpll_device_ops *ops; + struct mutex lock; + void *priv; +}; + +#define to_dpll_device(_dev) \ + container_of(_dev, struct dpll_device, dev) + +int for_each_dpll_device(int id, int (*cb)(struct dpll_device *, void *), + void *data); +struct dpll_device *dpll_device_get_by_id(int id); +struct dpll_device *dpll_device_get_by_name(const char *name); +void dpll_device_unregister(struct dpll_device *dpll); +#endif diff --git a/drivers/dpll/dpll_netlink.c b/drivers/dpll/dpll_netlink.c new file mode 100644 index 000000000000..31966e0eec3a --- /dev/null +++ b/drivers/dpll/dpll_netlink.c @@ -0,0 +1,417 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Generic netlink for DPLL management framework + * + * Copyright (c) 2021 Meta Platforms, Inc. and affiliates + * + */ +#include +#include +#include +#include "dpll_core.h" + +#include + +static const struct genl_multicast_group dpll_genl_mcgrps[] = { + { .name = DPLL_CONFIG_DEVICE_GROUP_NAME, }, + { .name = DPLL_CONFIG_SOURCE_GROUP_NAME, }, + { .name = DPLL_CONFIG_OUTPUT_GROUP_NAME, }, + { .name = DPLL_MONITOR_GROUP_NAME, }, +}; + +static const struct nla_policy dpll_genl_get_policy[] = { + [DPLLA_DEVICE_ID] = { .type = NLA_U32 }, + [DPLLA_DEVICE_NAME] = { .type = NLA_STRING, + .len = DPLL_NAME_LENGTH }, + [DPLLA_FLAGS] = { .type = NLA_U32 }, +}; + +static const struct nla_policy dpll_genl_set_source_policy[] = { + [DPLLA_DEVICE_ID] = { .type = NLA_U32 }, + [DPLLA_SOURCE_ID] = { .type = NLA_U32 }, + [DPLLA_SOURCE_TYPE] = { .type = NLA_U32 }, +}; + +static const struct nla_policy dpll_genl_set_output_policy[] = { + [DPLLA_DEVICE_ID] = { .type = NLA_U32 }, + [DPLLA_OUTPUT_ID] = { .type = NLA_U32 }, + [DPLLA_OUTPUT_TYPE] = { .type = NLA_U32 }, +}; + +struct param { + struct netlink_callback *cb; + struct dpll_device *dpll; + struct sk_buff *msg; + int dpll_id; + int dpll_source_id; + int dpll_source_type; + int dpll_output_id; + int dpll_output_type; +}; + +struct dpll_dump_ctx { + struct dpll_device *dev; + int flags; + int pos_idx; + int pos_src_idx; + int pos_out_idx; +}; + +typedef int (*cb_t)(struct param *); + +static struct genl_family dpll_gnl_family; + +static struct dpll_dump_ctx *dpll_dump_context(struct netlink_callback *cb) +{ + return (struct dpll_dump_ctx *)cb->ctx; +} + +static int __dpll_cmd_device_dump_one(struct dpll_device *dpll, + struct sk_buff *msg) +{ + if (nla_put_u32(msg, DPLLA_DEVICE_ID, dpll->id)) + return -EMSGSIZE; + + if (nla_put_string(msg, DPLLA_DEVICE_NAME, dev_name(&dpll->dev))) + return -EMSGSIZE; + + return 0; +} + +static int __dpll_cmd_dump_sources(struct dpll_device *dpll, + struct sk_buff *msg) +{ + struct nlattr *src_attr; + int i, ret = 0, type; + + for (i = 0; i < dpll->sources_count; i++) { + src_attr = nla_nest_start(msg, DPLLA_SOURCE); + if (!src_attr) { + ret = -EMSGSIZE; + break; + } + type = dpll->ops->get_source_type(dpll, i); + if (nla_put_u32(msg, DPLLA_SOURCE_ID, i) || + nla_put_u32(msg, DPLLA_SOURCE_TYPE, type)) { + nla_nest_cancel(msg, src_attr); + ret = -EMSGSIZE; + break; + } + if (dpll->ops->get_source_supported) { + for (type = 0; type <= DPLL_TYPE_MAX; type++) { + ret = dpll->ops->get_source_supported(dpll, i, type); + if (ret && nla_put_u32(msg, DPLLA_SOURCE_SUPPORTED, type)) { + ret = -EMSGSIZE; + break; + } + } + ret = 0; + } + nla_nest_end(msg, src_attr); + } + + return ret; +} + +static int __dpll_cmd_dump_outputs(struct dpll_device *dpll, + struct sk_buff *msg) +{ + struct nlattr *out_attr; + int i, ret = 0, type; + + for (i = 0; i < dpll->outputs_count; i++) { + out_attr = nla_nest_start(msg, DPLLA_OUTPUT); + if (!out_attr) { + ret = -EMSGSIZE; + break; + } + type = dpll->ops->get_output_type(dpll, i); + if (nla_put_u32(msg, DPLLA_OUTPUT_ID, i) || + nla_put_u32(msg, DPLLA_OUTPUT_TYPE, type)) { + nla_nest_cancel(msg, out_attr); + ret = -EMSGSIZE; + break; + } + if (dpll->ops->get_output_supported) { + for (type = 0; type <= DPLL_TYPE_MAX; type++) { + ret = dpll->ops->get_output_supported(dpll, i, type); + if (ret && nla_put_u32(msg, DPLLA_OUTPUT_SUPPORTED, type)) { + ret = -EMSGSIZE; + break; + } + } + ret = 0; + } + nla_nest_end(msg, out_attr); + } + + return ret; +} + +static int __dpll_cmd_dump_status(struct dpll_device *dpll, + struct sk_buff *msg) +{ + int ret; + + if (dpll->ops->get_status) { + ret = dpll->ops->get_status(dpll); + if (nla_put_u32(msg, DPLLA_STATUS, ret)) + return -EMSGSIZE; + } + + if (dpll->ops->get_temp) { + ret = dpll->ops->get_temp(dpll); + if (nla_put_u32(msg, DPLLA_TEMP, ret)) + return -EMSGSIZE; + } + + if (dpll->ops->get_lock_status) { + ret = dpll->ops->get_lock_status(dpll); + if (nla_put_u32(msg, DPLLA_LOCK_STATUS, ret)) + return -EMSGSIZE; + } + + return 0; +} + +static int +dpll_device_dump_one(struct dpll_device *dpll, struct sk_buff *msg, + u32 portid, u32 seq, int flags) +{ + struct nlattr *hdr; + int ret; + + hdr = genlmsg_put(msg, portid, seq, &dpll_gnl_family, 0, + DPLL_CMD_DEVICE_GET); + if (!hdr) + return -EMSGSIZE; + + mutex_lock(&dpll->lock); + ret = __dpll_cmd_device_dump_one(dpll, msg); + if (ret) + goto out_unlock; + + if (flags & DPLL_FLAG_SOURCES && dpll->ops->get_source_type) { + ret = __dpll_cmd_dump_sources(dpll, msg); + if (ret) + goto out_unlock; + } + + if (flags & DPLL_FLAG_OUTPUTS && dpll->ops->get_output_type) { + ret = __dpll_cmd_dump_outputs(dpll, msg); + if (ret) + goto out_unlock; + } + + if (flags & DPLL_FLAG_STATUS) { + ret = __dpll_cmd_dump_status(dpll, msg); + if (ret) + goto out_unlock; + } + mutex_unlock(&dpll->lock); + genlmsg_end(msg, hdr); + + return 0; + +out_unlock: + mutex_unlock(&dpll->lock); + genlmsg_cancel(msg, hdr); + + return ret; +} + +static int dpll_genl_cmd_set_source(struct sk_buff *skb, struct genl_info *info) +{ + struct dpll_device *dpll = info->user_ptr[0]; + struct nlattr **attrs = info->attrs; + int ret = 0, src_id, type; + + if (!attrs[DPLLA_SOURCE_ID] || + !attrs[DPLLA_SOURCE_TYPE]) + return -EINVAL; + + if (!dpll->ops->set_source_type) + return -EOPNOTSUPP; + + src_id = nla_get_u32(attrs[DPLLA_SOURCE_ID]); + type = nla_get_u32(attrs[DPLLA_SOURCE_TYPE]); + + mutex_lock(&dpll->lock); + ret = dpll->ops->set_source_type(dpll, src_id, type); + mutex_unlock(&dpll->lock); + + return ret; +} + +static int dpll_genl_cmd_set_output(struct sk_buff *skb, struct genl_info *info) +{ + struct dpll_device *dpll = info->user_ptr[0]; + struct nlattr **attrs = info->attrs; + int ret = 0, out_id, type; + + if (!attrs[DPLLA_OUTPUT_ID] || + !attrs[DPLLA_OUTPUT_TYPE]) + return -EINVAL; + + if (!dpll->ops->set_output_type) + return -EOPNOTSUPP; + + out_id = nla_get_u32(attrs[DPLLA_OUTPUT_ID]); + type = nla_get_u32(attrs[DPLLA_OUTPUT_TYPE]); + + mutex_lock(&dpll->lock); + ret = dpll->ops->set_output_type(dpll, out_id, type); + mutex_unlock(&dpll->lock); + + return ret; +} + +static int dpll_device_loop_cb(struct dpll_device *dpll, void *data) +{ + struct dpll_dump_ctx *ctx; + struct param *p = (struct param *)data; + + ctx = dpll_dump_context(p->cb); + + ctx->pos_idx = dpll->id; + + return dpll_device_dump_one(dpll, p->msg, 0, 0, ctx->flags); +} + +static int +dpll_cmd_device_dump(struct sk_buff *skb, struct netlink_callback *cb) +{ + struct dpll_dump_ctx *ctx = dpll_dump_context(cb); + struct param p = { .cb = cb, .msg = skb }; + + return for_each_dpll_device(ctx->pos_idx, dpll_device_loop_cb, &p); +} + +static int +dpll_genl_cmd_device_get_id(struct sk_buff *skb, struct genl_info *info) +{ + struct dpll_device *dpll = info->user_ptr[0]; + struct nlattr **attrs = info->attrs; + struct sk_buff *msg; + int flags = 0; + int ret; + + if (attrs[DPLLA_FLAGS]) + flags = nla_get_u32(attrs[DPLLA_FLAGS]); + + msg = genlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL); + if (!msg) + return -ENOMEM; + + ret = dpll_device_dump_one(dpll, msg, info->snd_portid, info->snd_seq, + flags); + if (ret) + goto out_free_msg; + + return genlmsg_reply(msg, info); + +out_free_msg: + nlmsg_free(msg); + return ret; + +} + +static int dpll_genl_cmd_start(struct netlink_callback *cb) +{ + const struct genl_dumpit_info *info = genl_dumpit_info(cb); + struct dpll_dump_ctx *ctx = dpll_dump_context(cb); + + ctx->dev = NULL; + if (info->attrs[DPLLA_FLAGS]) + ctx->flags = nla_get_u32(info->attrs[DPLLA_FLAGS]); + else + ctx->flags = 0; + ctx->pos_idx = 0; + ctx->pos_src_idx = 0; + ctx->pos_out_idx = 0; + return 0; +} + +static int dpll_pre_doit(const struct genl_ops *ops, struct sk_buff *skb, + struct genl_info *info) +{ + struct dpll_device *dpll_id = NULL, *dpll_name = NULL; + + if (!info->attrs[DPLLA_DEVICE_ID] && + !info->attrs[DPLLA_DEVICE_NAME]) + return -EINVAL; + + if (info->attrs[DPLLA_DEVICE_ID]) { + u32 id = nla_get_u32(info->attrs[DPLLA_DEVICE_ID]); + + dpll_id = dpll_device_get_by_id(id); + if (!dpll_id) + return -ENODEV; + info->user_ptr[0] = dpll_id; + } + if (info->attrs[DPLLA_DEVICE_NAME]) { + const char *name = nla_data(info->attrs[DPLLA_DEVICE_NAME]); + + dpll_name = dpll_device_get_by_name(name); + if (!dpll_name) + return -ENODEV; + + if (dpll_id && dpll_name != dpll_id) + return -EINVAL; + info->user_ptr[0] = dpll_name; + } + + return 0; +} + +static const struct genl_ops dpll_genl_ops[] = { + { + .cmd = DPLL_CMD_DEVICE_GET, + .flags = GENL_UNS_ADMIN_PERM, + .start = dpll_genl_cmd_start, + .dumpit = dpll_cmd_device_dump, + .doit = dpll_genl_cmd_device_get_id, + .policy = dpll_genl_get_policy, + .maxattr = ARRAY_SIZE(dpll_genl_get_policy) - 1, + }, + { + .cmd = DPLL_CMD_SET_SOURCE_TYPE, + .flags = GENL_UNS_ADMIN_PERM, + .doit = dpll_genl_cmd_set_source, + .policy = dpll_genl_set_source_policy, + .maxattr = ARRAY_SIZE(dpll_genl_set_source_policy) - 1, + }, + { + .cmd = DPLL_CMD_SET_OUTPUT_TYPE, + .flags = GENL_UNS_ADMIN_PERM, + .doit = dpll_genl_cmd_set_output, + .policy = dpll_genl_set_output_policy, + .maxattr = ARRAY_SIZE(dpll_genl_set_output_policy) - 1, + }, +}; + +static struct genl_family dpll_gnl_family __ro_after_init = { + .hdrsize = 0, + .name = DPLL_FAMILY_NAME, + .version = DPLL_VERSION, + .ops = dpll_genl_ops, + .n_ops = ARRAY_SIZE(dpll_genl_ops), + .mcgrps = dpll_genl_mcgrps, + .n_mcgrps = ARRAY_SIZE(dpll_genl_mcgrps), + .pre_doit = dpll_pre_doit, +}; + +int __init dpll_netlink_init(void) +{ + return genl_register_family(&dpll_gnl_family); +} + +void dpll_netlink_finish(void) +{ + genl_unregister_family(&dpll_gnl_family); +} + +void __exit dpll_netlink_fini(void) +{ + dpll_netlink_finish(); +} diff --git a/drivers/dpll/dpll_netlink.h b/drivers/dpll/dpll_netlink.h new file mode 100644 index 000000000000..e2d100f59dd6 --- /dev/null +++ b/drivers/dpll/dpll_netlink.h @@ -0,0 +1,7 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2021 Meta Platforms, Inc. and affiliates + */ + +int __init dpll_netlink_init(void); +void dpll_netlink_finish(void); diff --git a/include/linux/dpll.h b/include/linux/dpll.h new file mode 100644 index 000000000000..9d49b19d03d9 --- /dev/null +++ b/include/linux/dpll.h @@ -0,0 +1,29 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2021 Meta Platforms, Inc. and affiliates + */ + +#ifndef __DPLL_H__ +#define __DPLL_H__ + +struct dpll_device; + +struct dpll_device_ops { + int (*get_status)(struct dpll_device *dpll); + int (*get_temp)(struct dpll_device *dpll); + int (*get_lock_status)(struct dpll_device *dpll); + int (*get_source_type)(struct dpll_device *dpll, int id); + int (*get_source_supported)(struct dpll_device *dpll, int id, int type); + int (*get_output_type)(struct dpll_device *dpll, int id); + int (*get_output_supported)(struct dpll_device *dpll, int id, int type); + int (*set_source_type)(struct dpll_device *dpll, int id, int val); + int (*set_output_type)(struct dpll_device *dpll, int id, int val); +}; + +struct dpll_device *dpll_device_alloc(struct dpll_device_ops *ops, const char *name, + int sources_count, int outputs_count, void *priv); +void dpll_device_register(struct dpll_device *dpll); +void dpll_device_unregister(struct dpll_device *dpll); +void dpll_device_free(struct dpll_device *dpll); +void *dpll_priv(struct dpll_device *dpll); +#endif diff --git a/include/uapi/linux/dpll.h b/include/uapi/linux/dpll.h new file mode 100644 index 000000000000..fcbea5a5e4d6 --- /dev/null +++ b/include/uapi/linux/dpll.h @@ -0,0 +1,101 @@ +/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ +#ifndef _UAPI_LINUX_DPLL_H +#define _UAPI_LINUX_DPLL_H + +#define DPLL_NAME_LENGTH 20 + +/* Adding event notification support elements */ +#define DPLL_FAMILY_NAME "dpll" +#define DPLL_VERSION 0x01 +#define DPLL_CONFIG_DEVICE_GROUP_NAME "config" +#define DPLL_CONFIG_SOURCE_GROUP_NAME "source" +#define DPLL_CONFIG_OUTPUT_GROUP_NAME "output" +#define DPLL_MONITOR_GROUP_NAME "monitor" + +#define DPLL_FLAG_SOURCES 1 +#define DPLL_FLAG_OUTPUTS 2 +#define DPLL_FLAG_STATUS 4 + +/* Attributes of dpll_genl_family */ +enum dpll_genl_attr { + DPLLA_UNSPEC, + DPLLA_DEVICE_ID, + DPLLA_DEVICE_NAME, + DPLLA_SOURCE, + DPLLA_SOURCE_ID, + DPLLA_SOURCE_TYPE, + DPLLA_SOURCE_SUPPORTED, + DPLLA_OUTPUT, + DPLLA_OUTPUT_ID, + DPLLA_OUTPUT_TYPE, + DPLLA_OUTPUT_SUPPORTED, + DPLLA_STATUS, + DPLLA_TEMP, + DPLLA_LOCK_STATUS, + DPLLA_FLAGS, + + __DPLLA_MAX, +}; +#define DPLLA_MAX (__DPLLA_MAX - 1) + +/* DPLL status provides information of device status */ +enum dpll_genl_status { + DPLL_STATUS_NONE, + DPLL_STATUS_CALIBRATING, + DPLL_STATUS_LOCKED, + + __DPLL_STATUS_MAX, +}; +#define DPLL_STATUS_MAX (__DPLL_STATUS_MAX - 1) + +/* DPLL signal types used as source or as output */ +enum dpll_genl_signal_type { + DPLL_TYPE_EXT_1PPS, + DPLL_TYPE_EXT_10MHZ, + DPLL_TYPE_SYNCE_ETH_PORT, + DPLL_TYPE_INT_OSCILLATOR, + DPLL_TYPE_GNSS, + + __DPLL_TYPE_MAX, +}; +#define DPLL_TYPE_MAX (__DPLL_TYPE_MAX - 1) + +/* DPLL lock status provides information of source used to lock the device */ +enum dpll_genl_lock_status { + DPLL_LOCK_STATUS_UNLOCKED, + DPLL_LOCK_STATUS_EXT_1PPS, + DPLL_LOCK_STATUS_EXT_10MHZ, + DPLL_LOCK_STATUS_SYNCE, + DPLL_LOCK_STATUS_INT_OSCILLATOR, + DPLL_LOCK_STATUS_GNSS, + + __DPLL_LOCK_STATUS_MAX, +}; +#define DPLL_LOCK_STATUS_MAX (__DPLL_LOCK_STATUS_MAX - 1) + +/* Events of dpll_genl_family */ +enum dpll_genl_event { + DPLL_EVENT_UNSPEC, + DPLL_EVENT_DEVICE_CREATE, /* DPLL device creation */ + DPLL_EVENT_DEVICE_DELETE, /* DPLL device deletion */ + DPLL_EVENT_STATUS_LOCKED, /* DPLL device locked to source */ + DPLL_EVENT_STATUS_UNLOCKED, /* DPLL device freerun */ + DPLL_EVENT_SOURCE_CHANGE, /* DPLL device source changed */ + DPLL_EVENT_OUTPUT_CHANGE, /* DPLL device output changed */ + + __DPLL_EVENT_MAX, +}; +#define DPLL_EVENT_MAX (__DPLL_EVENT_MAX - 1) + +/* Commands supported by the dpll_genl_family */ +enum dpll_genl_cmd { + DPLL_CMD_UNSPEC, + DPLL_CMD_DEVICE_GET, /* List of DPLL devices id */ + DPLL_CMD_SET_SOURCE_TYPE, /* Set the DPLL device source type */ + DPLL_CMD_SET_OUTPUT_TYPE, /* Set the DPLL device output type */ + + __DPLL_CMD_MAX, +}; +#define DPLL_CMD_MAX (__DPLL_CMD_MAX - 1) + +#endif /* _UAPI_LINUX_DPLL_H */ From patchwork Mon Oct 10 01:18:00 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Vadim Fedorenko X-Patchwork-Id: 13002176 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id CE9BCC433F5 for ; Mon, 10 Oct 2022 01:18:41 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S230403AbiJJBSi (ORCPT ); Sun, 9 Oct 2022 21:18:38 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:35870 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230370AbiJJBSd (ORCPT ); Sun, 9 Oct 2022 21:18:33 -0400 Received: from novek.ru (unknown [213.148.174.62]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 62B5E2F3AE; Sun, 9 Oct 2022 18:18:22 -0700 (PDT) Received: from nat1.ooonet.ru (gw.zelenaya.net [91.207.137.40]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by novek.ru (Postfix) with ESMTPSA id C53AB504DEE; Mon, 10 Oct 2022 04:14:51 +0300 (MSK) DKIM-Filter: OpenDKIM Filter v2.11.0 novek.ru C53AB504DEE DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=novek.ru; s=mail; t=1665364493; bh=yyAnr5alMdz0gJxmpa4bCIpZ4JyGR+qBnxDUsvKCa1o=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=zfJ1hvA4Em3njJ+ZS30qRiu7WgldU6rMvFMSucfkBiDFDvxonJbi1sZDoOunumu3K idCk0arSvws7TUNz+FQDLuAZVG19nsNhQ4oxog6hCFZ1QTZGLngYAqvlAx7+tGrZ5K h9W0fpsod38QYGavzOvieOztE9CRnswGZlMPRt+o= From: Vadim Fedorenko To: Jakub Kicinski , Jiri Pirko , Arkadiusz Kubalewski Cc: netdev@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-clk@vger.kernel.org, Vadim Fedorenko Subject: [RFC PATCH v3 2/6] dpll: add netlink events Date: Mon, 10 Oct 2022 04:18:00 +0300 Message-Id: <20221010011804.23716-3-vfedorenko@novek.ru> X-Mailer: git-send-email 2.27.0 In-Reply-To: <20221010011804.23716-1-vfedorenko@novek.ru> References: <20221010011804.23716-1-vfedorenko@novek.ru> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org X-Patchwork-State: RFC From: Vadim Fedorenko Add netlink interface to enable notification of users about events in DPLL framework. Part of this interface should be used by drivers directly, i.e. lock status changes. Signed-off-by: Vadim Fedorenko --- drivers/dpll/dpll_core.c | 3 + drivers/dpll/dpll_netlink.c | 151 ++++++++++++++++++++++++++++++++++++ drivers/dpll/dpll_netlink.h | 3 + include/linux/dpll.h | 5 ++ 4 files changed, 162 insertions(+) diff --git a/drivers/dpll/dpll_core.c b/drivers/dpll/dpll_core.c index 7fdee145e82c..732165b77e38 100644 --- a/drivers/dpll/dpll_core.c +++ b/drivers/dpll/dpll_core.c @@ -115,6 +115,8 @@ struct dpll_device *dpll_device_alloc(struct dpll_device_ops *ops, const char *n mutex_unlock(&dpll_device_xa_lock); dpll->priv = priv; + dpll_notify_device_create(dpll->id, dev_name(&dpll->dev)); + return dpll; error: @@ -150,6 +152,7 @@ void dpll_device_unregister(struct dpll_device *dpll) mutex_lock(&dpll_device_xa_lock); xa_erase(&dpll_device_xa, dpll->id); + dpll_notify_device_delete(dpll->id); mutex_unlock(&dpll_device_xa_lock); } EXPORT_SYMBOL_GPL(dpll_device_unregister); diff --git a/drivers/dpll/dpll_netlink.c b/drivers/dpll/dpll_netlink.c index 31966e0eec3a..6dc92b5b712e 100644 --- a/drivers/dpll/dpll_netlink.c +++ b/drivers/dpll/dpll_netlink.c @@ -47,6 +47,9 @@ struct param { int dpll_source_type; int dpll_output_id; int dpll_output_type; + int dpll_status; + int dpll_event_group; + const char *dpll_name; }; struct dpll_dump_ctx { @@ -240,6 +243,9 @@ static int dpll_genl_cmd_set_source(struct sk_buff *skb, struct genl_info *info) ret = dpll->ops->set_source_type(dpll, src_id, type); mutex_unlock(&dpll->lock); + if (!ret) + dpll_notify_source_change(dpll->id, src_id, type); + return ret; } @@ -263,6 +269,9 @@ static int dpll_genl_cmd_set_output(struct sk_buff *skb, struct genl_info *info) ret = dpll->ops->set_output_type(dpll, out_id, type); mutex_unlock(&dpll->lock); + if (!ret) + dpll_notify_output_change(dpll->id, out_id, type); + return ret; } @@ -401,6 +410,148 @@ static struct genl_family dpll_gnl_family __ro_after_init = { .pre_doit = dpll_pre_doit, }; +static int dpll_event_device_create(struct param *p) +{ + if (nla_put_u32(p->msg, DPLLA_DEVICE_ID, p->dpll_id) || + nla_put_string(p->msg, DPLLA_DEVICE_NAME, p->dpll_name)) + return -EMSGSIZE; + + return 0; +} + +static int dpll_event_device_delete(struct param *p) +{ + if (nla_put_u32(p->msg, DPLLA_DEVICE_ID, p->dpll_id)) + return -EMSGSIZE; + + return 0; +} + +static int dpll_event_status(struct param *p) +{ + if (nla_put_u32(p->msg, DPLLA_DEVICE_ID, p->dpll_id) || + nla_put_u32(p->msg, DPLLA_LOCK_STATUS, p->dpll_status)) + return -EMSGSIZE; + + return 0; +} + +static int dpll_event_source_change(struct param *p) +{ + if (nla_put_u32(p->msg, DPLLA_DEVICE_ID, p->dpll_id) || + nla_put_u32(p->msg, DPLLA_SOURCE_ID, p->dpll_source_id) || + nla_put_u32(p->msg, DPLLA_SOURCE_TYPE, p->dpll_source_type)) + return -EMSGSIZE; + + return 0; +} + +static int dpll_event_output_change(struct param *p) +{ + if (nla_put_u32(p->msg, DPLLA_DEVICE_ID, p->dpll_id) || + nla_put_u32(p->msg, DPLLA_OUTPUT_ID, p->dpll_output_id) || + nla_put_u32(p->msg, DPLLA_OUTPUT_TYPE, p->dpll_output_type)) + return -EMSGSIZE; + + return 0; +} + +static const cb_t event_cb[] = { + [DPLL_EVENT_DEVICE_CREATE] = dpll_event_device_create, + [DPLL_EVENT_DEVICE_DELETE] = dpll_event_device_delete, + [DPLL_EVENT_STATUS_LOCKED] = dpll_event_status, + [DPLL_EVENT_STATUS_UNLOCKED] = dpll_event_status, + [DPLL_EVENT_SOURCE_CHANGE] = dpll_event_source_change, + [DPLL_EVENT_OUTPUT_CHANGE] = dpll_event_output_change, +}; +/* + * Generic netlink DPLL event encoding + */ +static int dpll_send_event(enum dpll_genl_event event, + struct param *p) +{ + struct sk_buff *msg; + int ret = -EMSGSIZE; + void *hdr; + + msg = genlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL); + if (!msg) + return -ENOMEM; + p->msg = msg; + + hdr = genlmsg_put(msg, 0, 0, &dpll_gnl_family, 0, event); + if (!hdr) + goto out_free_msg; + + ret = event_cb[event](p); + if (ret) + goto out_cancel_msg; + + genlmsg_end(msg, hdr); + + genlmsg_multicast(&dpll_gnl_family, msg, 0, p->dpll_event_group, GFP_KERNEL); + + return 0; + +out_cancel_msg: + genlmsg_cancel(msg, hdr); +out_free_msg: + nlmsg_free(msg); + + return ret; +} + +int dpll_notify_device_create(int dpll_id, const char *name) +{ + struct param p = { .dpll_id = dpll_id, .dpll_name = name, + .dpll_event_group = 0 }; + + return dpll_send_event(DPLL_EVENT_DEVICE_CREATE, &p); +} + +int dpll_notify_device_delete(int dpll_id) +{ + struct param p = { .dpll_id = dpll_id, .dpll_event_group = 0 }; + + return dpll_send_event(DPLL_EVENT_DEVICE_DELETE, &p); +} + +int dpll_notify_status_locked(int dpll_id) +{ + struct param p = { .dpll_id = dpll_id, .dpll_status = 1, + .dpll_event_group = 3 }; + + return dpll_send_event(DPLL_EVENT_STATUS_LOCKED, &p); +} +EXPORT_SYMBOL_GPL(dpll_notify_status_locked); + +int dpll_notify_status_unlocked(int dpll_id) +{ + struct param p = { .dpll_id = dpll_id, .dpll_status = 0, + .dpll_event_group = 3 }; + + return dpll_send_event(DPLL_EVENT_STATUS_UNLOCKED, &p); +} +EXPORT_SYMBOL_GPL(dpll_notify_status_unlocked); + +int dpll_notify_source_change(int dpll_id, int source_id, int source_type) +{ + struct param p = { .dpll_id = dpll_id, .dpll_source_id = source_id, + .dpll_source_type = source_type, .dpll_event_group = 1 }; + + return dpll_send_event(DPLL_EVENT_SOURCE_CHANGE, &p); +} +EXPORT_SYMBOL_GPL(dpll_notify_source_change); + +int dpll_notify_output_change(int dpll_id, int output_id, int output_type) +{ + struct param p = { .dpll_id = dpll_id, .dpll_output_id = output_id, + .dpll_output_type = output_type, .dpll_event_group = 2 }; + + return dpll_send_event(DPLL_EVENT_OUTPUT_CHANGE, &p); +} +EXPORT_SYMBOL_GPL(dpll_notify_output_change); + int __init dpll_netlink_init(void) { return genl_register_family(&dpll_gnl_family); diff --git a/drivers/dpll/dpll_netlink.h b/drivers/dpll/dpll_netlink.h index e2d100f59dd6..5c1d1072e818 100644 --- a/drivers/dpll/dpll_netlink.h +++ b/drivers/dpll/dpll_netlink.h @@ -3,5 +3,8 @@ * Copyright (c) 2021 Meta Platforms, Inc. and affiliates */ +int dpll_notify_device_create(int dpll_id, const char *name); +int dpll_notify_device_delete(int dpll_id); + int __init dpll_netlink_init(void); void dpll_netlink_finish(void); diff --git a/include/linux/dpll.h b/include/linux/dpll.h index 9d49b19d03d9..32558965cd41 100644 --- a/include/linux/dpll.h +++ b/include/linux/dpll.h @@ -26,4 +26,9 @@ void dpll_device_register(struct dpll_device *dpll); void dpll_device_unregister(struct dpll_device *dpll); void dpll_device_free(struct dpll_device *dpll); void *dpll_priv(struct dpll_device *dpll); + +int dpll_notify_status_locked(int dpll_id); +int dpll_notify_status_unlocked(int dpll_id); +int dpll_notify_source_change(int dpll_id, int source_id, int source_type); +int dpll_notify_output_change(int dpll_id, int output_id, int output_type); #endif From patchwork Mon Oct 10 01:18:01 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Vadim Fedorenko X-Patchwork-Id: 13002175 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 244F1C4332F for ; Mon, 10 Oct 2022 01:18:39 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S230416AbiJJBSh (ORCPT ); Sun, 9 Oct 2022 21:18:37 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:35848 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230245AbiJJBSd (ORCPT ); Sun, 9 Oct 2022 21:18:33 -0400 Received: from novek.ru (unknown [213.148.174.62]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 577CE2F396; Sun, 9 Oct 2022 18:18:22 -0700 (PDT) Received: from nat1.ooonet.ru (gw.zelenaya.net [91.207.137.40]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by novek.ru (Postfix) with ESMTPSA id 74C8B504DF2; Mon, 10 Oct 2022 04:14:53 +0300 (MSK) DKIM-Filter: OpenDKIM Filter v2.11.0 novek.ru 74C8B504DF2 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=novek.ru; s=mail; t=1665364495; bh=mS0zmDplOjFREXpN4RVnYstoFhKoOWs5C56CnqjBIbw=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=XvZAKThO5YT3tgvLFckqBq0+9Q+/U9fVJsZC+l2eio+hhCQUT6F87QECu4a6gHO8/ E8H9Zuy+p3Pjn2efXZ0jxXQILQruICr6qfcRKH1qhVdqqtPVxzNKRHeEM3FKaZWZ1w +jHFLKz0pjP4B74MYrMhz3bTrW38UPZqfmp97jDc= From: Vadim Fedorenko To: Jakub Kicinski , Jiri Pirko , Arkadiusz Kubalewski Cc: netdev@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-clk@vger.kernel.org, Vadim Fedorenko Subject: [RFC PATCH v3 3/6] dpll: add support for source selection modes Date: Mon, 10 Oct 2022 04:18:01 +0300 Message-Id: <20221010011804.23716-4-vfedorenko@novek.ru> X-Mailer: git-send-email 2.27.0 In-Reply-To: <20221010011804.23716-1-vfedorenko@novek.ru> References: <20221010011804.23716-1-vfedorenko@novek.ru> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org X-Patchwork-State: RFC From: Arkadiusz Kubalewski Allow to configure dpll device for different source selection modes. Allow to configure priority of a sources for autmoatic selection mode. Signed-off-by: Arkadiusz Kubalewski --- drivers/dpll/dpll_netlink.c | 170 ++++++++++++++++++++++++++++++++++-- drivers/dpll/dpll_netlink.h | 2 + include/linux/dpll.h | 7 ++ include/uapi/linux/dpll.h | 22 ++++- 4 files changed, 192 insertions(+), 9 deletions(-) diff --git a/drivers/dpll/dpll_netlink.c b/drivers/dpll/dpll_netlink.c index 6dc92b5b712e..a5779871537a 100644 --- a/drivers/dpll/dpll_netlink.c +++ b/drivers/dpll/dpll_netlink.c @@ -23,6 +23,7 @@ static const struct nla_policy dpll_genl_get_policy[] = { [DPLLA_DEVICE_ID] = { .type = NLA_U32 }, [DPLLA_DEVICE_NAME] = { .type = NLA_STRING, .len = DPLL_NAME_LENGTH }, + [DPLLA_DEVICE_SRC_SELECT_MODE] = { .type = NLA_U32 }, [DPLLA_FLAGS] = { .type = NLA_U32 }, }; @@ -38,13 +39,26 @@ static const struct nla_policy dpll_genl_set_output_policy[] = { [DPLLA_OUTPUT_TYPE] = { .type = NLA_U32 }, }; +static const struct nla_policy dpll_genl_set_src_select_mode_policy[] = { + [DPLLA_DEVICE_ID] = { .type = NLA_U32 }, + [DPLLA_DEVICE_SRC_SELECT_MODE] = { .type = NLA_U32 }, +}; + +static const struct nla_policy dpll_genl_set_source_prio_policy[] = { + [DPLLA_DEVICE_ID] = { .type = NLA_U32 }, + [DPLLA_SOURCE_ID] = { .type = NLA_U32 }, + [DPLLA_SOURCE_PRIO] = { .type = NLA_U32 }, +}; + struct param { struct netlink_callback *cb; struct dpll_device *dpll; struct sk_buff *msg; int dpll_id; + int dpll_src_select_mode; int dpll_source_id; int dpll_source_type; + int dpll_source_prio; int dpll_output_id; int dpll_output_type; int dpll_status; @@ -84,8 +98,8 @@ static int __dpll_cmd_device_dump_one(struct dpll_device *dpll, static int __dpll_cmd_dump_sources(struct dpll_device *dpll, struct sk_buff *msg) { + int i, ret = 0, type, prio; struct nlattr *src_attr; - int i, ret = 0, type; for (i = 0; i < dpll->sources_count; i++) { src_attr = nla_nest_start(msg, DPLLA_SOURCE); @@ -110,6 +124,14 @@ static int __dpll_cmd_dump_sources(struct dpll_device *dpll, } ret = 0; } + if (dpll->ops->get_source_prio) { + prio = dpll->ops->get_source_prio(dpll, i); + if (nla_put_u32(msg, DPLLA_SOURCE_PRIO, prio)) { + nla_nest_cancel(msg, src_attr); + ret = -EMSGSIZE; + break; + } + } nla_nest_end(msg, src_attr); } @@ -154,26 +176,51 @@ static int __dpll_cmd_dump_outputs(struct dpll_device *dpll, static int __dpll_cmd_dump_status(struct dpll_device *dpll, struct sk_buff *msg) { - int ret; + struct dpll_device_ops *ops = dpll->ops; + int ret, type, attr; - if (dpll->ops->get_status) { - ret = dpll->ops->get_status(dpll); + if (ops->get_status) { + ret = ops->get_status(dpll); if (nla_put_u32(msg, DPLLA_STATUS, ret)) return -EMSGSIZE; } - if (dpll->ops->get_temp) { - ret = dpll->ops->get_temp(dpll); + if (ops->get_temp) { + ret = ops->get_temp(dpll); if (nla_put_u32(msg, DPLLA_TEMP, ret)) return -EMSGSIZE; } - if (dpll->ops->get_lock_status) { - ret = dpll->ops->get_lock_status(dpll); + if (ops->get_lock_status) { + ret = ops->get_lock_status(dpll); if (nla_put_u32(msg, DPLLA_LOCK_STATUS, ret)) return -EMSGSIZE; } + if (ops->get_source_select_mode) { + ret = ops->get_source_select_mode(dpll); + if (nla_put_u32(msg, DPLLA_DEVICE_SRC_SELECT_MODE, ret)) + return -EMSGSIZE; + } else { + if (nla_put_u32(msg, DPLLA_DEVICE_SRC_SELECT_MODE, + DPLL_SRC_SELECT_FORCED)) + return -EMSGSIZE; + } + + if (ops->get_source_select_mode_supported) { + attr = DPLLA_DEVICE_SRC_SELECT_MODE_SUPPORTED; + for (type = 0; type <= DPLL_SRC_SELECT_MAX; type++) { + ret = ops->get_source_select_mode_supported(dpll, + type); + if (ret && nla_put_u32(msg, attr, type)) + return -EMSGSIZE; + } + } else { + if (nla_put_u32(msg, DPLLA_DEVICE_SRC_SELECT_MODE_SUPPORTED, + DPLL_SRC_SELECT_FORCED)) + return -EMSGSIZE; + } + return 0; } @@ -275,6 +322,56 @@ static int dpll_genl_cmd_set_output(struct sk_buff *skb, struct genl_info *info) return ret; } +static int dpll_genl_cmd_set_source_prio(struct sk_buff *skb, struct genl_info *info) +{ + struct dpll_device *dpll = info->user_ptr[0]; + struct nlattr **attrs = info->attrs; + int ret = 0, src_id, prio; + + if (!attrs[DPLLA_SOURCE_ID] || + !attrs[DPLLA_SOURCE_PRIO]) + return -EINVAL; + + if (!dpll->ops->set_source_prio) + return -EOPNOTSUPP; + + src_id = nla_get_u32(attrs[DPLLA_SOURCE_ID]); + prio = nla_get_u32(attrs[DPLLA_SOURCE_PRIO]); + + mutex_lock(&dpll->lock); + ret = dpll->ops->set_source_prio(dpll, src_id, prio); + mutex_unlock(&dpll->lock); + + if (!ret) + dpll_notify_source_prio_change(dpll->id, src_id, prio); + + return ret; +} + +static int dpll_genl_cmd_set_select_mode(struct sk_buff *skb, struct genl_info *info) +{ + struct dpll_device *dpll = info->user_ptr[0]; + struct nlattr **attrs = info->attrs; + int ret = 0, mode; + + if (!attrs[DPLLA_DEVICE_SRC_SELECT_MODE]) + return -EINVAL; + + if (!dpll->ops->set_source_select_mode) + return -EOPNOTSUPP; + + mode = nla_get_u32(attrs[DPLLA_DEVICE_SRC_SELECT_MODE]); + + mutex_lock(&dpll->lock); + ret = dpll->ops->set_source_select_mode(dpll, mode); + mutex_unlock(&dpll->lock); + + if (!ret) + dpll_notify_source_select_mode_change(dpll->id, mode); + + return ret; +} + static int dpll_device_loop_cb(struct dpll_device *dpll, void *data) { struct dpll_dump_ctx *ctx; @@ -397,6 +494,20 @@ static const struct genl_ops dpll_genl_ops[] = { .policy = dpll_genl_set_output_policy, .maxattr = ARRAY_SIZE(dpll_genl_set_output_policy) - 1, }, + { + .cmd = DPLL_CMD_SET_SRC_SELECT_MODE, + .flags = GENL_UNS_ADMIN_PERM, + .doit = dpll_genl_cmd_set_select_mode, + .policy = dpll_genl_set_src_select_mode_policy, + .maxattr = ARRAY_SIZE(dpll_genl_set_src_select_mode_policy) - 1, + }, + { + .cmd = DPLL_CMD_SET_SOURCE_PRIO, + .flags = GENL_UNS_ADMIN_PERM, + .doit = dpll_genl_cmd_set_source_prio, + .policy = dpll_genl_set_source_prio_policy, + .maxattr = ARRAY_SIZE(dpll_genl_set_source_prio_policy) - 1, + }, }; static struct genl_family dpll_gnl_family __ro_after_init = { @@ -456,6 +567,26 @@ static int dpll_event_output_change(struct param *p) return 0; } +static int dpll_event_source_prio(struct param *p) +{ + if (nla_put_u32(p->msg, DPLLA_DEVICE_ID, p->dpll_id) || + nla_put_u32(p->msg, DPLLA_SOURCE_ID, p->dpll_source_id) || + nla_put_u32(p->msg, DPLLA_SOURCE_PRIO, p->dpll_source_prio)) + return -EMSGSIZE; + + return 0; +} + +static int dpll_event_select_mode(struct param *p) +{ + if (nla_put_u32(p->msg, DPLLA_DEVICE_ID, p->dpll_id) || + nla_put_u32(p->msg, DPLLA_DEVICE_SRC_SELECT_MODE, + p->dpll_src_select_mode)) + return -EMSGSIZE; + + return 0; +} + static const cb_t event_cb[] = { [DPLL_EVENT_DEVICE_CREATE] = dpll_event_device_create, [DPLL_EVENT_DEVICE_DELETE] = dpll_event_device_delete, @@ -463,7 +594,10 @@ static const cb_t event_cb[] = { [DPLL_EVENT_STATUS_UNLOCKED] = dpll_event_status, [DPLL_EVENT_SOURCE_CHANGE] = dpll_event_source_change, [DPLL_EVENT_OUTPUT_CHANGE] = dpll_event_output_change, + [DPLL_EVENT_SOURCE_PRIO] = dpll_event_source_prio, + [DPLL_EVENT_SELECT_MODE] = dpll_event_select_mode, }; + /* * Generic netlink DPLL event encoding */ @@ -552,6 +686,26 @@ int dpll_notify_output_change(int dpll_id, int output_id, int output_type) } EXPORT_SYMBOL_GPL(dpll_notify_output_change); +int dpll_notify_source_select_mode_change(int dpll_id, int new_mode) +{ + struct param p = { .dpll_id = dpll_id, + .dpll_src_select_mode = new_mode, + .dpll_event_group = 0 }; + + return dpll_send_event(DPLL_EVENT_SELECT_MODE, &p); +} +EXPORT_SYMBOL_GPL(dpll_notify_source_select_mode_change); + +int dpll_notify_source_prio_change(int dpll_id, int source_id, int prio) +{ + struct param p = { .dpll_id = dpll_id, .dpll_source_id = source_id, + .dpll_source_prio = prio, + .dpll_event_group = 1 }; + + return dpll_send_event(DPLL_EVENT_SOURCE_PRIO, &p); +} +EXPORT_SYMBOL_GPL(dpll_notify_source_prio_change); + int __init dpll_netlink_init(void) { return genl_register_family(&dpll_gnl_family); diff --git a/drivers/dpll/dpll_netlink.h b/drivers/dpll/dpll_netlink.h index 5c1d1072e818..a4962fa0c8c2 100644 --- a/drivers/dpll/dpll_netlink.h +++ b/drivers/dpll/dpll_netlink.h @@ -5,6 +5,8 @@ int dpll_notify_device_create(int dpll_id, const char *name); int dpll_notify_device_delete(int dpll_id); +int dpll_notify_source_prio(int dpll_id, int source_id, int prio); +int dpll_notify_select_mode(int dpll_id, int mode); int __init dpll_netlink_init(void); void dpll_netlink_finish(void); diff --git a/include/linux/dpll.h b/include/linux/dpll.h index 32558965cd41..3fe957a06b90 100644 --- a/include/linux/dpll.h +++ b/include/linux/dpll.h @@ -12,12 +12,17 @@ struct dpll_device_ops { int (*get_status)(struct dpll_device *dpll); int (*get_temp)(struct dpll_device *dpll); int (*get_lock_status)(struct dpll_device *dpll); + int (*get_source_select_mode)(struct dpll_device *dpll); + int (*get_source_select_mode_supported)(struct dpll_device *dpll, int type); int (*get_source_type)(struct dpll_device *dpll, int id); int (*get_source_supported)(struct dpll_device *dpll, int id, int type); + int (*get_source_prio)(struct dpll_device *dpll, int id); int (*get_output_type)(struct dpll_device *dpll, int id); int (*get_output_supported)(struct dpll_device *dpll, int id, int type); int (*set_source_type)(struct dpll_device *dpll, int id, int val); int (*set_output_type)(struct dpll_device *dpll, int id, int val); + int (*set_source_select_mode)(struct dpll_device *dpll, int mode); + int (*set_source_prio)(struct dpll_device *dpll, int id, int prio); }; struct dpll_device *dpll_device_alloc(struct dpll_device_ops *ops, const char *name, @@ -31,4 +36,6 @@ int dpll_notify_status_locked(int dpll_id); int dpll_notify_status_unlocked(int dpll_id); int dpll_notify_source_change(int dpll_id, int source_id, int source_type); int dpll_notify_output_change(int dpll_id, int output_id, int output_type); +int dpll_notify_source_select_mode_change(int dpll_id, int source_select_mode); +int dpll_notify_source_prio_change(int dpll_id, int source_id, int prio); #endif diff --git a/include/uapi/linux/dpll.h b/include/uapi/linux/dpll.h index fcbea5a5e4d6..f6b674e5cf01 100644 --- a/include/uapi/linux/dpll.h +++ b/include/uapi/linux/dpll.h @@ -21,10 +21,13 @@ enum dpll_genl_attr { DPLLA_UNSPEC, DPLLA_DEVICE_ID, DPLLA_DEVICE_NAME, + DPLLA_DEVICE_SRC_SELECT_MODE, + DPLLA_DEVICE_SRC_SELECT_MODE_SUPPORTED, DPLLA_SOURCE, DPLLA_SOURCE_ID, DPLLA_SOURCE_TYPE, DPLLA_SOURCE_SUPPORTED, + DPLLA_SOURCE_PRIO, DPLLA_OUTPUT, DPLLA_OUTPUT_ID, DPLLA_OUTPUT_TYPE, @@ -82,6 +85,8 @@ enum dpll_genl_event { DPLL_EVENT_STATUS_UNLOCKED, /* DPLL device freerun */ DPLL_EVENT_SOURCE_CHANGE, /* DPLL device source changed */ DPLL_EVENT_OUTPUT_CHANGE, /* DPLL device output changed */ + DPLL_EVENT_SOURCE_PRIO, + DPLL_EVENT_SELECT_MODE, __DPLL_EVENT_MAX, }; @@ -90,12 +95,27 @@ enum dpll_genl_event { /* Commands supported by the dpll_genl_family */ enum dpll_genl_cmd { DPLL_CMD_UNSPEC, - DPLL_CMD_DEVICE_GET, /* List of DPLL devices id */ + DPLL_CMD_DEVICE_GET, /* List of DPLL devices id */ DPLL_CMD_SET_SOURCE_TYPE, /* Set the DPLL device source type */ DPLL_CMD_SET_OUTPUT_TYPE, /* Set the DPLL device output type */ + DPLL_CMD_SET_SRC_SELECT_MODE,/* Set mode for selection of a source */ + DPLL_CMD_SET_SOURCE_PRIO, /* Set priority of a source */ __DPLL_CMD_MAX, }; #define DPLL_CMD_MAX (__DPLL_CMD_MAX - 1) +/* Source select modes of dpll */ +enum dpll_genl_source_select_mode { + DPLL_SRC_SELECT_UNSPEC, + DPLL_SRC_SELECT_FORCED, /* Source forced by DPLL_CMD_SET_SOURCE_TYPE */ + DPLL_SRC_SELECT_AUTOMATIC,/* highest prio, valid source, auto selected by dpll */ + DPLL_SRC_SELECT_HOLDOVER, /* forced holdover */ + DPLL_SRC_SELECT_FREERUN, /* dpll driven on system clk, no holdover available */ + DPLL_SRC_SELECT_NCO, /* Set the DPLL device output type */ + + __DPLL_SRC_SELECT_MAX, +}; +#define DPLL_SRC_SELECT_MAX (__DPLL_SRC_SELECT_MAX - 1) + #endif /* _UAPI_LINUX_DPLL_H */ From patchwork Mon Oct 10 01:18:02 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Vadim Fedorenko X-Patchwork-Id: 13002180 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 57D27C433F5 for ; Mon, 10 Oct 2022 01:19:04 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S230387AbiJJBTC (ORCPT ); Sun, 9 Oct 2022 21:19:02 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:36374 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230390AbiJJBSz (ORCPT ); Sun, 9 Oct 2022 21:18:55 -0400 Received: from novek.ru (unknown [213.148.174.62]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 11EAF30F46; Sun, 9 Oct 2022 18:18:53 -0700 (PDT) Received: from nat1.ooonet.ru (gw.zelenaya.net [91.207.137.40]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by novek.ru (Postfix) with ESMTPSA id 65E0F504E54; Mon, 10 Oct 2022 04:14:55 +0300 (MSK) DKIM-Filter: OpenDKIM Filter v2.11.0 novek.ru 65E0F504E54 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=novek.ru; s=mail; t=1665364496; bh=FsVkCsqxnKVxj6zdLWSSwLUhMTznP9XeXVsfc6pdzqU=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=VU91bOV+Cycf3B79zE4xI89AxaQTnM06LqpSrtX5ZQn/6PHvBRYMCZqa4xy3XmbCj nA0tEXQXn+igdDKp0qzJAhFmJomBfyW6j99voqdE3An970R/DNhThXVWQU7Cis1GXi dYFGW2cFgzZs9BrI7YBNNJp6WFyrBoTHrcqEbAHg= From: Vadim Fedorenko To: Jakub Kicinski , Jiri Pirko , Arkadiusz Kubalewski Cc: netdev@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-clk@vger.kernel.org, Vadim Fedorenko Subject: [RFC PATCH v3 4/6] dpll: get source/output name Date: Mon, 10 Oct 2022 04:18:02 +0300 Message-Id: <20221010011804.23716-5-vfedorenko@novek.ru> X-Mailer: git-send-email 2.27.0 In-Reply-To: <20221010011804.23716-1-vfedorenko@novek.ru> References: <20221010011804.23716-1-vfedorenko@novek.ru> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org X-Patchwork-State: RFC From: Arkadiusz Kubalewski Dump names of sources and outputs in response to DPLL_CMD_DEVICE_GET dump request. Signed-off-by: Arkadiusz Kubalewski --- drivers/dpll/dpll_netlink.c | 24 ++++++++++++++++++++++++ include/linux/dpll.h | 2 ++ include/uapi/linux/dpll.h | 2 ++ 3 files changed, 28 insertions(+) diff --git a/drivers/dpll/dpll_netlink.c b/drivers/dpll/dpll_netlink.c index a5779871537a..e3604c10b59e 100644 --- a/drivers/dpll/dpll_netlink.c +++ b/drivers/dpll/dpll_netlink.c @@ -31,12 +31,16 @@ static const struct nla_policy dpll_genl_set_source_policy[] = { [DPLLA_DEVICE_ID] = { .type = NLA_U32 }, [DPLLA_SOURCE_ID] = { .type = NLA_U32 }, [DPLLA_SOURCE_TYPE] = { .type = NLA_U32 }, + [DPLLA_SOURCE_NAME] = { .type = NLA_STRING, + .len = DPLL_NAME_LENGTH }, }; static const struct nla_policy dpll_genl_set_output_policy[] = { [DPLLA_DEVICE_ID] = { .type = NLA_U32 }, [DPLLA_OUTPUT_ID] = { .type = NLA_U32 }, [DPLLA_OUTPUT_TYPE] = { .type = NLA_U32 }, + [DPLLA_OUTPUT_NAME] = { .type = NLA_STRING, + .len = DPLL_NAME_LENGTH }, }; static const struct nla_policy dpll_genl_set_src_select_mode_policy[] = { @@ -100,6 +104,7 @@ static int __dpll_cmd_dump_sources(struct dpll_device *dpll, { int i, ret = 0, type, prio; struct nlattr *src_attr; + const char *name; for (i = 0; i < dpll->sources_count; i++) { src_attr = nla_nest_start(msg, DPLLA_SOURCE); @@ -132,6 +137,15 @@ static int __dpll_cmd_dump_sources(struct dpll_device *dpll, break; } } + if (dpll->ops->get_source_name) { + name = dpll->ops->get_source_name(dpll, i); + if (name && nla_put_string(msg, DPLLA_SOURCE_NAME, + name)) { + nla_nest_cancel(msg, src_attr); + ret = -EMSGSIZE; + break; + } + } nla_nest_end(msg, src_attr); } @@ -143,6 +157,7 @@ static int __dpll_cmd_dump_outputs(struct dpll_device *dpll, { struct nlattr *out_attr; int i, ret = 0, type; + const char *name; for (i = 0; i < dpll->outputs_count; i++) { out_attr = nla_nest_start(msg, DPLLA_OUTPUT); @@ -167,6 +182,15 @@ static int __dpll_cmd_dump_outputs(struct dpll_device *dpll, } ret = 0; } + if (dpll->ops->get_output_name) { + name = dpll->ops->get_output_name(dpll, i); + if (name && nla_put_string(msg, DPLLA_OUTPUT_NAME, + name)) { + nla_nest_cancel(msg, out_attr); + ret = -EMSGSIZE; + break; + } + } nla_nest_end(msg, out_attr); } diff --git a/include/linux/dpll.h b/include/linux/dpll.h index 3fe957a06b90..2f4964dc28f0 100644 --- a/include/linux/dpll.h +++ b/include/linux/dpll.h @@ -23,6 +23,8 @@ struct dpll_device_ops { int (*set_output_type)(struct dpll_device *dpll, int id, int val); int (*set_source_select_mode)(struct dpll_device *dpll, int mode); int (*set_source_prio)(struct dpll_device *dpll, int id, int prio); + const char *(*get_source_name)(struct dpll_device *dpll, int id); + const char *(*get_output_name)(struct dpll_device *dpll, int id); }; struct dpll_device *dpll_device_alloc(struct dpll_device_ops *ops, const char *name, diff --git a/include/uapi/linux/dpll.h b/include/uapi/linux/dpll.h index f6b674e5cf01..8782d3425aae 100644 --- a/include/uapi/linux/dpll.h +++ b/include/uapi/linux/dpll.h @@ -26,11 +26,13 @@ enum dpll_genl_attr { DPLLA_SOURCE, DPLLA_SOURCE_ID, DPLLA_SOURCE_TYPE, + DPLLA_SOURCE_NAME, DPLLA_SOURCE_SUPPORTED, DPLLA_SOURCE_PRIO, DPLLA_OUTPUT, DPLLA_OUTPUT_ID, DPLLA_OUTPUT_TYPE, + DPLLA_OUTPUT_NAME, DPLLA_OUTPUT_SUPPORTED, DPLLA_STATUS, DPLLA_TEMP, From patchwork Mon Oct 10 01:18:03 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Vadim Fedorenko X-Patchwork-Id: 13002177 X-Patchwork-Delegate: kuba@kernel.org Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 870D2C4332F for ; Mon, 10 Oct 2022 01:18:52 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S230499AbiJJBSv (ORCPT ); Sun, 9 Oct 2022 21:18:51 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:35944 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230357AbiJJBSk (ORCPT ); Sun, 9 Oct 2022 21:18:40 -0400 Received: from novek.ru (unknown [213.148.174.62]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 98D392E9D8; Sun, 9 Oct 2022 18:18:34 -0700 (PDT) Received: from nat1.ooonet.ru (gw.zelenaya.net [91.207.137.40]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by novek.ru (Postfix) with ESMTPSA id E495B504E55; Mon, 10 Oct 2022 04:14:56 +0300 (MSK) DKIM-Filter: OpenDKIM Filter v2.11.0 novek.ru E495B504E55 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=novek.ru; s=mail; t=1665364498; bh=XLHIvhz9omIEbrPi1AG5YDmm+bbkVnYbVuLRgaKLvoE=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=sE9K+oJV6ORuVdu3MsM15fleM8DZrdYjLf15jUo22ykf3XGVemNTIhK6pZ3sWDeNR DM+dnAuR8AmsFgQKTMm5gnAncLOd0KrHt2U6yc7aO9iqYMQjQGXldz606wgCuecJoB WFDyzIsm+hbhA6tib3QiCE2/NWSAp9Bm2qk+faT8= From: Vadim Fedorenko To: Jakub Kicinski , Jiri Pirko , Arkadiusz Kubalewski Cc: netdev@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-clk@vger.kernel.org, Vadim Fedorenko Subject: [RFC PATCH v3 5/6] dpll: documentation on DPLL subsystem interface Date: Mon, 10 Oct 2022 04:18:03 +0300 Message-Id: <20221010011804.23716-6-vfedorenko@novek.ru> X-Mailer: git-send-email 2.27.0 In-Reply-To: <20221010011804.23716-1-vfedorenko@novek.ru> References: <20221010011804.23716-1-vfedorenko@novek.ru> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org X-Patchwork-Delegate: kuba@kernel.org X-Patchwork-State: RFC From: Vadim Fedorenko Add documentation explaining common netlink interface to configure DPLL devices and monitoring events. Common way to implement DPLL device in a driver is also covered. Signed-off-by: Vadim Fedorenko --- Documentation/networking/dpll.rst | 157 +++++++++++++++++++++++++++++ Documentation/networking/index.rst | 1 + 2 files changed, 158 insertions(+) create mode 100644 Documentation/networking/dpll.rst diff --git a/Documentation/networking/dpll.rst b/Documentation/networking/dpll.rst new file mode 100644 index 000000000000..00c15b19aefb --- /dev/null +++ b/Documentation/networking/dpll.rst @@ -0,0 +1,157 @@ +.. SPDX-License-Identifier: GPL-2.0 + +=============================== +The Linux kernel DPLL subsystem +=============================== + + +The main purpose of DPLL subsystem is to provide general interface +to configure devices that use any kind of Digital PLL and could use +different sources of signal to synchronize to as well as different +types of outputs. The inputs and outputs could be internal components +of the device as well as external connections. The main interface is +NETLINK_GENERIC based protocol with config and monitoring groups of +commands defined. + +Configuration commands group +============================ + +Configuration commands are used to get information about registered +DPLL devices as well as get or set configuration of each used input +or output. As DPLL device could not be abstract and reflects real +hardware, there is no way to add new DPLL device via netlink from +user space and each device should be registered by it's driver. + +List of command with possible attributes +======================================== + +All constants identifying command types use ``DPLL_CMD_`` prefix and +suffix according to command purpose. All attributes use ``DPLLA_`` +prefix and suffix according to attribute purpose: + + ===================================== ============================= + ``DEVICE_GET`` userspace to get device info + ``DEVICE_ID`` attr internal device index + ``DEVICE_NAME`` attr DPLL device name + ``STATUS`` attr DPLL device status info + ``DEVICE_SRC_SELECT_MODE`` attr DPLL source selection + mode + ``DEVICE_SRC_SELECT_MODE_SUPPORTED`` attr supported source + selection modes + ``LOCK_STATUS`` attr internal frequency-lock + status + ``TEMP`` attr device temperature + information + ``SET_SOURCE`` userspace to set + sources/inputs configuration + ``DEVICE_ID`` attr internal device index + to configure source pin + ``SOURCE_ID`` attr index of source pin to + configure + ``SOURCE_NAME`` attr name of source pin to + configure + ``SOURCE_TYPE`` attr configuration value for + selected source pin + ``SET_OUTPUT`` userspace to set outputs + configuration + ``DEVICE_ID`` attr internal device index to + configure output pin + ``OUTPUT_ID`` attr index of output pin to + configure + ``OUTPUT_NAME`` attr name of output pin to + configure + ``OUTPUT_TYPE`` attr configuration value for + selected output pin + ``SET_SRC_SELECT_MODE`` userspace to set source pin + selection mode + ``DEVICE_ID`` attr internal device index + ``DEVICE_SRC_SELECT_MODE`` attr source selection mode + ``SET_SOURCE_PRIO`` userspace to set priority of + a source pin for automatic + source selection mode + ``DEVICE_ID`` attr internal device index + for source pin + ``SOURCE_ID`` attr index of source pin to + configure + ``SOURCE_PRIO`` attr priority of a source pin + + +The pre-defined enums +===================== + +These enums are used to select type values for source/input and +output pins: + + ============================= ====================================== + ``DPLL_TYPE_EXT_1PPS`` External 1PPS source + ``DPLL_TYPE_EXT_10MHZ`` External 10MHz source + ``DPLL_TYPE_SYNCE_ETH_PORT`` SyncE on Ethernet port + ``DPLL_TYPE_INT_OSCILLATOR`` Internal Oscillator (i.e. Holdover + with Atomic Clock as a Source) + ``DPLL_TYPE_GNSS`` GNSS 1PPS source + ``DPLL_TYPE_CUSTOM`` Custom frequency + +Values for monitoring attributes STATUS: + + ============================= ====================================== + ``DPLL_STATUS_NONE`` No information provided + ``DPLL_STATUS_CALIBRATING`` DPLL device is not locked to the + source frequency + ``DPLL_STATUS_LOCKED`` DPLL device is locked to the source + frequency + + +Possible DPLL source selection mode values: + + ============================= ====================================== + ``DPLL_SRC_SELECT_FORCED`` source pin is force-selected by + DPLL_CMD_SET_SOURCE_TYPE + ``DPLL_SRC_SELECT_AUTOMATIC`` source pin ise auto selected according + to configured priorities and source + signal validity + ``DPLL_SRC_SELECT_HOLDOVER`` force holdover mode of DPLL + ``DPLL_SRC_SELECT_FREERUN`` DPLL is driven by supplied system + clock without holdover capabilities + ``DPLL_SRC_SELECT_NCO`` similar to FREERUN, with possibility + to numerically control frequency offset + +Notifications +================ + +DPLL device can provide notifications regarding status changes of the +device, i.e. lock status changes, source/output type changes or alarms. +This is the multicast group that is used to notify user-space apps via +netlink socket: + + ============================== ==================================== + ``DPLL_EVENT_DEVICE_CREATE`` New DPLL device was created + ``DPLL_EVENT_DEVICE_DELETE`` DPLL device was deleted + ``DPLL_EVENT_STATUS_LOCKED`` DPLL device has locked to source + ``DPLL_EVENT_STATUS_UNLOCKED`` DPLL device is in freerun or + in calibration mode + ``DPLL_EVENT_SOURCE_CHANGE`` DPLL device source changed + ``DPLL_EVENT_OUTPUT_CHANGE`` DPLL device output changed + ``DPLL_EVENT_SOURCE_PRIO`` DPLL device source priority changed + ``DPLL_EVENT_SELECT_MODE`` DPLL device source selection mode + changed + +Device driver implementation +============================ + +For device to operate as DPLL subsystem device, it should implement +set of operations and register device via ``dpll_device_alloc`` and +``dpll_device_register`` providing desired device name and set of +supported operations as well as the amount of sources/input pins and +output pins. If there is no specific name supplied, dpll subsystem +will use ``dpll%d`` template to create device name. Notifications of +adding or removing DPLL devices are created within subsystem itself, +but notifications about configurations changes or alarms should be +implemented within driver as different ways of confirmation could be +used. All the interfaces for notification messages could be found in +````, constats and enums are placed in ```` +to be consistent with user-space. + +There is no strict requeriment to implement all the operations for +each device, every operation handler is checked for existence and +ENOTSUPP is returned in case of absence of specific handler. + diff --git a/Documentation/networking/index.rst b/Documentation/networking/index.rst index 16a153bcc5fe..612d322a3380 100644 --- a/Documentation/networking/index.rst +++ b/Documentation/networking/index.rst @@ -16,6 +16,7 @@ Contents: device_drivers/index dsa/index devlink/index + dpll caif/index ethtool-netlink ieee802154 From patchwork Mon Oct 10 01:18:04 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Vadim Fedorenko X-Patchwork-Id: 13002181 X-Patchwork-Delegate: kuba@kernel.org Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id EAFD6C433F5 for ; Mon, 10 Oct 2022 01:19:19 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S230327AbiJJBTP (ORCPT ); Sun, 9 Oct 2022 21:19:15 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:36620 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230319AbiJJBTJ (ORCPT ); Sun, 9 Oct 2022 21:19:09 -0400 Received: from novek.ru (unknown [213.148.174.62]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id DE46231DD3; Sun, 9 Oct 2022 18:19:04 -0700 (PDT) Received: from nat1.ooonet.ru (gw.zelenaya.net [91.207.137.40]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by novek.ru (Postfix) with ESMTPSA id B3C1F504E56; Mon, 10 Oct 2022 04:14:58 +0300 (MSK) DKIM-Filter: OpenDKIM Filter v2.11.0 novek.ru B3C1F504E56 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=novek.ru; s=mail; t=1665364500; bh=1gkc8mZdjRaJkgi2fCTpH3SfdmFXxYsZvsHDJD5oReI=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=vS5C/b61z6zt/Oe0MktMuCpJI3AbBQKiKnaKTfsfFE2UlghQkNs5WrPKW6srSatZk PJUx4qdjxm/Hd3FYd0mOSyA/T10WabYBWPJhRiDCA7A2uT1lw5z7bPXcFLZq7q/2Mn lMakwBM9pahlCsh/7zLqedZDTdIwmVZOJWU6Rkyg= From: Vadim Fedorenko To: Jakub Kicinski , Jiri Pirko , Arkadiusz Kubalewski Cc: netdev@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-clk@vger.kernel.org, Vadim Fedorenko Subject: [RFC PATCH v3 6/6] ptp_ocp: implement DPLL ops Date: Mon, 10 Oct 2022 04:18:04 +0300 Message-Id: <20221010011804.23716-7-vfedorenko@novek.ru> X-Mailer: git-send-email 2.27.0 In-Reply-To: <20221010011804.23716-1-vfedorenko@novek.ru> References: <20221010011804.23716-1-vfedorenko@novek.ru> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org X-Patchwork-Delegate: kuba@kernel.org X-Patchwork-State: RFC From: Vadim Fedorenko Implement DPLL operations in ptp_ocp driver. Signed-off-by: Vadim Fedorenko --- drivers/ptp/Kconfig | 1 + drivers/ptp/ptp_ocp.c | 170 ++++++++++++++++++++++++++++++-------- include/uapi/linux/dpll.h | 2 + 3 files changed, 137 insertions(+), 36 deletions(-) diff --git a/drivers/ptp/Kconfig b/drivers/ptp/Kconfig index fe4971b65c64..8c4cfabc1bfa 100644 --- a/drivers/ptp/Kconfig +++ b/drivers/ptp/Kconfig @@ -177,6 +177,7 @@ config PTP_1588_CLOCK_OCP depends on COMMON_CLK select NET_DEVLINK select CRC16 + select DPLL help This driver adds support for an OpenCompute time card. diff --git a/drivers/ptp/ptp_ocp.c b/drivers/ptp/ptp_ocp.c index d36c3f597f77..a01c0c721802 100644 --- a/drivers/ptp/ptp_ocp.c +++ b/drivers/ptp/ptp_ocp.c @@ -21,6 +21,8 @@ #include #include #include +#include +#include #define PCI_VENDOR_ID_FACEBOOK 0x1d9b #define PCI_DEVICE_ID_FACEBOOK_TIMECARD 0x0400 @@ -336,6 +338,7 @@ struct ptp_ocp { struct ptp_ocp_signal signal[4]; struct ptp_ocp_sma_connector sma[4]; const struct ocp_sma_op *sma_op; + struct dpll_device *dpll; }; #define OCP_REQ_TIMESTAMP BIT(0) @@ -660,18 +663,19 @@ static DEFINE_IDR(ptp_ocp_idr); struct ocp_selector { const char *name; int value; + int dpll_type; }; static const struct ocp_selector ptp_ocp_clock[] = { - { .name = "NONE", .value = 0 }, - { .name = "TOD", .value = 1 }, - { .name = "IRIG", .value = 2 }, - { .name = "PPS", .value = 3 }, - { .name = "PTP", .value = 4 }, - { .name = "RTC", .value = 5 }, - { .name = "DCF", .value = 6 }, - { .name = "REGS", .value = 0xfe }, - { .name = "EXT", .value = 0xff }, + { .name = "NONE", .value = 0, .dpll_type = 0 }, + { .name = "TOD", .value = 1, .dpll_type = 0 }, + { .name = "IRIG", .value = 2, .dpll_type = 0 }, + { .name = "PPS", .value = 3, .dpll_type = 0 }, + { .name = "PTP", .value = 4, .dpll_type = 0 }, + { .name = "RTC", .value = 5, .dpll_type = 0 }, + { .name = "DCF", .value = 6, .dpll_type = 0 }, + { .name = "REGS", .value = 0xfe, .dpll_type = 0 }, + { .name = "EXT", .value = 0xff, .dpll_type = 0 }, { } }; @@ -680,37 +684,37 @@ static const struct ocp_selector ptp_ocp_clock[] = { #define SMA_SELECT_MASK GENMASK(14, 0) static const struct ocp_selector ptp_ocp_sma_in[] = { - { .name = "10Mhz", .value = 0x0000 }, - { .name = "PPS1", .value = 0x0001 }, - { .name = "PPS2", .value = 0x0002 }, - { .name = "TS1", .value = 0x0004 }, - { .name = "TS2", .value = 0x0008 }, - { .name = "IRIG", .value = 0x0010 }, - { .name = "DCF", .value = 0x0020 }, - { .name = "TS3", .value = 0x0040 }, - { .name = "TS4", .value = 0x0080 }, - { .name = "FREQ1", .value = 0x0100 }, - { .name = "FREQ2", .value = 0x0200 }, - { .name = "FREQ3", .value = 0x0400 }, - { .name = "FREQ4", .value = 0x0800 }, - { .name = "None", .value = SMA_DISABLE }, + { .name = "10Mhz", .value = 0x0000, .dpll_type = DPLL_TYPE_EXT_10MHZ }, + { .name = "PPS1", .value = 0x0001, .dpll_type = DPLL_TYPE_EXT_1PPS }, + { .name = "PPS2", .value = 0x0002, .dpll_type = DPLL_TYPE_EXT_1PPS }, + { .name = "TS1", .value = 0x0004, .dpll_type = DPLL_TYPE_CUSTOM }, + { .name = "TS2", .value = 0x0008, .dpll_type = DPLL_TYPE_CUSTOM }, + { .name = "IRIG", .value = 0x0010, .dpll_type = DPLL_TYPE_CUSTOM }, + { .name = "DCF", .value = 0x0020, .dpll_type = DPLL_TYPE_CUSTOM }, + { .name = "TS3", .value = 0x0040, .dpll_type = DPLL_TYPE_CUSTOM }, + { .name = "TS4", .value = 0x0080, .dpll_type = DPLL_TYPE_CUSTOM }, + { .name = "FREQ1", .value = 0x0100, .dpll_type = DPLL_TYPE_CUSTOM }, + { .name = "FREQ2", .value = 0x0200, .dpll_type = DPLL_TYPE_CUSTOM }, + { .name = "FREQ3", .value = 0x0400, .dpll_type = DPLL_TYPE_CUSTOM }, + { .name = "FREQ4", .value = 0x0800, .dpll_type = DPLL_TYPE_CUSTOM }, + { .name = "None", .value = SMA_DISABLE, .dpll_type = DPLL_TYPE_NONE }, { } }; static const struct ocp_selector ptp_ocp_sma_out[] = { - { .name = "10Mhz", .value = 0x0000 }, - { .name = "PHC", .value = 0x0001 }, - { .name = "MAC", .value = 0x0002 }, - { .name = "GNSS1", .value = 0x0004 }, - { .name = "GNSS2", .value = 0x0008 }, - { .name = "IRIG", .value = 0x0010 }, - { .name = "DCF", .value = 0x0020 }, - { .name = "GEN1", .value = 0x0040 }, - { .name = "GEN2", .value = 0x0080 }, - { .name = "GEN3", .value = 0x0100 }, - { .name = "GEN4", .value = 0x0200 }, - { .name = "GND", .value = 0x2000 }, - { .name = "VCC", .value = 0x4000 }, + { .name = "10Mhz", .value = 0x0000, .dpll_type = DPLL_TYPE_EXT_10MHZ }, + { .name = "PHC", .value = 0x0001, .dpll_type = DPLL_TYPE_INT_OSCILLATOR }, + { .name = "MAC", .value = 0x0002, .dpll_type = DPLL_TYPE_INT_OSCILLATOR }, + { .name = "GNSS1", .value = 0x0004, .dpll_type = DPLL_TYPE_GNSS }, + { .name = "GNSS2", .value = 0x0008, .dpll_type = DPLL_TYPE_GNSS }, + { .name = "IRIG", .value = 0x0010, .dpll_type = DPLL_TYPE_CUSTOM }, + { .name = "DCF", .value = 0x0020, .dpll_type = DPLL_TYPE_CUSTOM }, + { .name = "GEN1", .value = 0x0040, .dpll_type = DPLL_TYPE_CUSTOM }, + { .name = "GEN2", .value = 0x0080, .dpll_type = DPLL_TYPE_CUSTOM }, + { .name = "GEN3", .value = 0x0100, .dpll_type = DPLL_TYPE_CUSTOM }, + { .name = "GEN4", .value = 0x0200, .dpll_type = DPLL_TYPE_CUSTOM }, + { .name = "GND", .value = 0x2000, .dpll_type = DPLL_TYPE_CUSTOM }, + { .name = "VCC", .value = 0x4000, .dpll_type = DPLL_TYPE_CUSTOM }, { } }; @@ -3707,6 +3711,90 @@ ptp_ocp_detach(struct ptp_ocp *bp) device_unregister(&bp->dev); } +static int ptp_ocp_dpll_get_status(struct dpll_device *dpll) +{ + struct ptp_ocp *bp = (struct ptp_ocp *)dpll_priv(dpll); + int sync; + + sync = ioread32(&bp->reg->status) & OCP_STATUS_IN_SYNC; + return sync; +} + +static int ptp_ocp_dpll_get_lock_status(struct dpll_device *dpll) +{ + struct ptp_ocp *bp = (struct ptp_ocp *)dpll_priv(dpll); + int sync; + + sync = ioread32(&bp->reg->status) & OCP_STATUS_IN_SYNC; + return sync; +} + +static int ptp_ocp_sma_get_dpll_type(struct ptp_ocp *bp, int sma_nr) +{ + const struct ocp_selector *tbl; + u32 val; + + if (bp->sma[sma_nr].mode == SMA_MODE_IN) + tbl = bp->sma_op->tbl[0]; + else + tbl = bp->sma_op->tbl[1]; + + val = ptp_ocp_sma_get(bp, sma_nr); + return tbl[val].dpll_type; +} + +static int ptp_ocp_dpll_type_supported(struct dpll_device *dpll, int sma, int type, int dir) +{ + struct ptp_ocp *bp = (struct ptp_ocp *)dpll_priv(dpll); + const struct ocp_selector *tbl = bp->sma_op->tbl[dir]; + int i; + + for (i = 0; i < sizeof(*tbl); i++) { + if (tbl[i].dpll_type == type) + return 1; + } + return 0; +} + +static int ptp_ocp_dpll_get_source_type(struct dpll_device *dpll, int sma) +{ + struct ptp_ocp *bp = (struct ptp_ocp *)dpll_priv(dpll); + + if (bp->sma[sma].mode != SMA_MODE_IN) + return -1; + + return ptp_ocp_sma_get_dpll_type(bp, sma); +} + +static int ptp_ocp_dpll_get_source_supported(struct dpll_device *dpll, int sma, int type) +{ + return ptp_ocp_dpll_type_supported(dpll, sma, type, 0); +} + +static int ptp_ocp_dpll_get_output_type(struct dpll_device *dpll, int sma) +{ + struct ptp_ocp *bp = (struct ptp_ocp *)dpll_priv(dpll); + + if (bp->sma[sma].mode != SMA_MODE_OUT) + return -1; + + return ptp_ocp_sma_get_dpll_type(bp, sma); +} + +static int ptp_ocp_dpll_get_output_supported(struct dpll_device *dpll, int sma, int type) +{ + return ptp_ocp_dpll_type_supported(dpll, sma, type, 1); +} + +static struct dpll_device_ops dpll_ops = { + .get_status = ptp_ocp_dpll_get_status, + .get_lock_status = ptp_ocp_dpll_get_lock_status, + .get_source_type = ptp_ocp_dpll_get_source_type, + .get_source_supported = ptp_ocp_dpll_get_source_supported, + .get_output_type = ptp_ocp_dpll_get_output_type, + .get_output_supported = ptp_ocp_dpll_get_output_supported, +}; + static int ptp_ocp_probe(struct pci_dev *pdev, const struct pci_device_id *id) { @@ -3762,6 +3850,14 @@ ptp_ocp_probe(struct pci_dev *pdev, const struct pci_device_id *id) ptp_ocp_info(bp); devlink_register(devlink); + + bp->dpll = dpll_device_alloc(&dpll_ops, "ocp", ARRAY_SIZE(bp->sma), ARRAY_SIZE(bp->sma), bp); + if (!bp->dpll) { + dev_err(&pdev->dev, "dpll_device_alloc failed\n"); + return 0; + } + dpll_device_register(bp->dpll); + return 0; out: @@ -3779,6 +3875,8 @@ ptp_ocp_remove(struct pci_dev *pdev) struct ptp_ocp *bp = pci_get_drvdata(pdev); struct devlink *devlink = priv_to_devlink(bp); + dpll_device_unregister(bp->dpll); + dpll_device_free(bp->dpll); devlink_unregister(devlink); ptp_ocp_detach(bp); pci_disable_device(pdev); diff --git a/include/uapi/linux/dpll.h b/include/uapi/linux/dpll.h index 8782d3425aae..59fc6ef81b40 100644 --- a/include/uapi/linux/dpll.h +++ b/include/uapi/linux/dpll.h @@ -55,11 +55,13 @@ enum dpll_genl_status { /* DPLL signal types used as source or as output */ enum dpll_genl_signal_type { + DPLL_TYPE_NONE, DPLL_TYPE_EXT_1PPS, DPLL_TYPE_EXT_10MHZ, DPLL_TYPE_SYNCE_ETH_PORT, DPLL_TYPE_INT_OSCILLATOR, DPLL_TYPE_GNSS, + DPLL_TYPE_CUSTOM, __DPLL_TYPE_MAX, };