Commit 9431063a authored by Vadim Fedorenko's avatar Vadim Fedorenko Committed by David S. Miller

dpll: core: Add DPLL framework base functions

DPLL framework is used to represent and configure DPLL devices
in systems. Each device that has DPLL and can configure inputs
and outputs can use this framework.

Implement core framework functions for further interactions
with device drivers implementing dpll subsystem, as well as for
interactions of DPLL netlink framework part with the subsystem
itself.
Co-developed-by: default avatarMilena Olech <milena.olech@intel.com>
Signed-off-by: default avatarMilena Olech <milena.olech@intel.com>
Co-developed-by: default avatarMichal Michalik <michal.michalik@intel.com>
Signed-off-by: default avatarMichal Michalik <michal.michalik@intel.com>
Signed-off-by: default avatarVadim Fedorenko <vadim.fedorenko@linux.dev>
Co-developed-by: default avatarArkadiusz Kubalewski <arkadiusz.kubalewski@intel.com>
Signed-off-by: default avatarArkadiusz Kubalewski <arkadiusz.kubalewski@intel.com>
Signed-off-by: default avatarJiri Pirko <jiri@nvidia.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 3badff3a
......@@ -6333,6 +6333,17 @@ 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 SUBSYSTEM
M: Vadim Fedorenko <vadim.fedorenko@linux.dev>
M: Arkadiusz Kubalewski <arkadiusz.kubalewski@intel.com>
M: Jiri Pirko <jiri@resnulli.us>
L: netdev@vger.kernel.org
S: Supported
F: Documentation/driver-api/dpll.rst
F: drivers/dpll/*
F: include/net/dpll.h
F: include/uapi/linux/dpll.h
DRBD DRIVER
M: Philipp Reisner <philipp.reisner@linbit.com>
M: Lars Ellenberg <lars.ellenberg@linbit.com>
......
......@@ -243,4 +243,6 @@ source "drivers/hte/Kconfig"
source "drivers/cdx/Kconfig"
source "drivers/dpll/Kconfig"
endmenu
......@@ -197,5 +197,6 @@ obj-$(CONFIG_PECI) += peci/
obj-$(CONFIG_HTE) += hte/
obj-$(CONFIG_DRM_ACCEL) += accel/
obj-$(CONFIG_CDX_BUS) += cdx/
obj-$(CONFIG_DPLL) += dpll/
obj-$(CONFIG_S390) += s390/
# SPDX-License-Identifier: GPL-2.0-only
#
# Generic DPLL drivers configuration
#
config DPLL
bool
# SPDX-License-Identifier: GPL-2.0
#
# Makefile for DPLL drivers.
#
obj-$(CONFIG_DPLL) += dpll.o
dpll-y += dpll_core.o
dpll-y += dpll_netlink.o
dpll-y += dpll_nl.o
This diff is collapsed.
/* SPDX-License-Identifier: GPL-2.0 */
/*
* Copyright (c) 2023 Meta Platforms, Inc. and affiliates
* Copyright (c) 2023 Intel and affiliates
*/
#ifndef __DPLL_CORE_H__
#define __DPLL_CORE_H__
#include <linux/dpll.h>
#include <linux/list.h>
#include <linux/refcount.h>
#include "dpll_nl.h"
#define DPLL_REGISTERED XA_MARK_1
/**
* struct dpll_device - stores DPLL device internal data
* @id: unique id number for device given by dpll subsystem
* @device_idx: id given by dev driver
* @clock_id: unique identifier (clock_id) of a dpll
* @module: module of creator
* @type: type of a dpll
* @pin_refs: stores pins registered within a dpll
* @refcount: refcount
* @registration_list: list of registered ops and priv data of dpll owners
**/
struct dpll_device {
u32 id;
u32 device_idx;
u64 clock_id;
struct module *module;
enum dpll_type type;
struct xarray pin_refs;
refcount_t refcount;
struct list_head registration_list;
};
/**
* struct dpll_pin - structure for a dpll pin
* @id: unique id number for pin given by dpll subsystem
* @pin_idx: index of a pin given by dev driver
* @clock_id: clock_id of creator
* @module: module of creator
* @dpll_refs: hold referencees to dplls pin was registered with
* @parent_refs: hold references to parent pins pin was registered with
* @prop: pointer to pin properties given by registerer
* @rclk_dev_name: holds name of device when pin can recover clock from it
* @refcount: refcount
**/
struct dpll_pin {
u32 id;
u32 pin_idx;
u64 clock_id;
struct module *module;
struct xarray dpll_refs;
struct xarray parent_refs;
const struct dpll_pin_properties *prop;
refcount_t refcount;
};
/**
* struct dpll_pin_ref - structure for referencing either dpll or pins
* @dpll: pointer to a dpll
* @pin: pointer to a pin
* @registration_list: list of ops and priv data registered with the ref
* @refcount: refcount
**/
struct dpll_pin_ref {
union {
struct dpll_device *dpll;
struct dpll_pin *pin;
};
struct list_head registration_list;
refcount_t refcount;
};
void *dpll_priv(struct dpll_device *dpll);
void *dpll_pin_on_dpll_priv(struct dpll_device *dpll, struct dpll_pin *pin);
void *dpll_pin_on_pin_priv(struct dpll_pin *parent, struct dpll_pin *pin);
const struct dpll_device_ops *dpll_device_ops(struct dpll_device *dpll);
struct dpll_device *dpll_device_get_by_id(int id);
const struct dpll_pin_ops *dpll_pin_ops(struct dpll_pin_ref *ref);
struct dpll_pin_ref *dpll_xa_ref_dpll_first(struct xarray *xa_refs);
extern struct xarray dpll_device_xa;
extern struct xarray dpll_pin_xa;
extern struct mutex dpll_lock;
#endif
/* SPDX-License-Identifier: GPL-2.0 */
/*
* Copyright (c) 2023 Meta Platforms, Inc. and affiliates
* Copyright (c) 2023 Intel and affiliates
*/
#ifndef __DPLL_H__
#define __DPLL_H__
#include <uapi/linux/dpll.h>
#include <linux/device.h>
#include <linux/netlink.h>
struct dpll_device;
struct dpll_pin;
struct dpll_device_ops {
int (*mode_get)(const struct dpll_device *dpll, void *dpll_priv,
enum dpll_mode *mode, struct netlink_ext_ack *extack);
bool (*mode_supported)(const struct dpll_device *dpll, void *dpll_priv,
const enum dpll_mode mode,
struct netlink_ext_ack *extack);
int (*lock_status_get)(const struct dpll_device *dpll, void *dpll_priv,
enum dpll_lock_status *status,
struct netlink_ext_ack *extack);
int (*temp_get)(const struct dpll_device *dpll, void *dpll_priv,
s32 *temp, struct netlink_ext_ack *extack);
};
struct dpll_pin_ops {
int (*frequency_set)(const struct dpll_pin *pin, void *pin_priv,
const struct dpll_device *dpll, void *dpll_priv,
const u64 frequency,
struct netlink_ext_ack *extack);
int (*frequency_get)(const struct dpll_pin *pin, void *pin_priv,
const struct dpll_device *dpll, void *dpll_priv,
u64 *frequency, struct netlink_ext_ack *extack);
int (*direction_set)(const struct dpll_pin *pin, void *pin_priv,
const struct dpll_device *dpll, void *dpll_priv,
const enum dpll_pin_direction direction,
struct netlink_ext_ack *extack);
int (*direction_get)(const struct dpll_pin *pin, void *pin_priv,
const struct dpll_device *dpll, void *dpll_priv,
enum dpll_pin_direction *direction,
struct netlink_ext_ack *extack);
int (*state_on_pin_get)(const struct dpll_pin *pin, void *pin_priv,
const struct dpll_pin *parent_pin,
void *parent_pin_priv,
enum dpll_pin_state *state,
struct netlink_ext_ack *extack);
int (*state_on_dpll_get)(const struct dpll_pin *pin, void *pin_priv,
const struct dpll_device *dpll,
void *dpll_priv, enum dpll_pin_state *state,
struct netlink_ext_ack *extack);
int (*state_on_pin_set)(const struct dpll_pin *pin, void *pin_priv,
const struct dpll_pin *parent_pin,
void *parent_pin_priv,
const enum dpll_pin_state state,
struct netlink_ext_ack *extack);
int (*state_on_dpll_set)(const struct dpll_pin *pin, void *pin_priv,
const struct dpll_device *dpll,
void *dpll_priv,
const enum dpll_pin_state state,
struct netlink_ext_ack *extack);
int (*prio_get)(const struct dpll_pin *pin, void *pin_priv,
const struct dpll_device *dpll, void *dpll_priv,
u32 *prio, struct netlink_ext_ack *extack);
int (*prio_set)(const struct dpll_pin *pin, void *pin_priv,
const struct dpll_device *dpll, void *dpll_priv,
const u32 prio, struct netlink_ext_ack *extack);
};
struct dpll_pin_frequency {
u64 min;
u64 max;
};
#define DPLL_PIN_FREQUENCY_RANGE(_min, _max) \
{ \
.min = _min, \
.max = _max, \
}
#define DPLL_PIN_FREQUENCY(_val) DPLL_PIN_FREQUENCY_RANGE(_val, _val)
#define DPLL_PIN_FREQUENCY_1PPS \
DPLL_PIN_FREQUENCY(DPLL_PIN_FREQUENCY_1_HZ)
#define DPLL_PIN_FREQUENCY_10MHZ \
DPLL_PIN_FREQUENCY(DPLL_PIN_FREQUENCY_10_MHZ)
#define DPLL_PIN_FREQUENCY_IRIG_B \
DPLL_PIN_FREQUENCY(DPLL_PIN_FREQUENCY_10_KHZ)
#define DPLL_PIN_FREQUENCY_DCF77 \
DPLL_PIN_FREQUENCY(DPLL_PIN_FREQUENCY_77_5_KHZ)
struct dpll_pin_properties {
const char *board_label;
const char *panel_label;
const char *package_label;
enum dpll_pin_type type;
unsigned long capabilities;
u32 freq_supported_num;
struct dpll_pin_frequency *freq_supported;
};
struct dpll_device *
dpll_device_get(u64 clock_id, u32 dev_driver_id, struct module *module);
void dpll_device_put(struct dpll_device *dpll);
int dpll_device_register(struct dpll_device *dpll, enum dpll_type type,
const struct dpll_device_ops *ops, void *priv);
void dpll_device_unregister(struct dpll_device *dpll,
const struct dpll_device_ops *ops, void *priv);
struct dpll_pin *
dpll_pin_get(u64 clock_id, u32 dev_driver_id, struct module *module,
const struct dpll_pin_properties *prop);
int dpll_pin_register(struct dpll_device *dpll, struct dpll_pin *pin,
const struct dpll_pin_ops *ops, void *priv);
void dpll_pin_unregister(struct dpll_device *dpll, struct dpll_pin *pin,
const struct dpll_pin_ops *ops, void *priv);
void dpll_pin_put(struct dpll_pin *pin);
int dpll_pin_on_pin_register(struct dpll_pin *parent, struct dpll_pin *pin,
const struct dpll_pin_ops *ops, void *priv);
void dpll_pin_on_pin_unregister(struct dpll_pin *parent, struct dpll_pin *pin,
const struct dpll_pin_ops *ops, void *priv);
#endif
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment