diff --git a/drivers/dpll/dpll_attr.c b/drivers/dpll/dpll_attr.c
new file mode 100644
index 000000000000..9cf957978ff5
--- /dev/null
+++ b/drivers/dpll/dpll_attr.c
@@ -0,0 +1,278 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ *  dpll_attr.c - dpll attributes handling helper class.
+ *
+ *  Copyright (c) 2022, Intel Corporation.
+ */
+
+#include <linux/dpll.h>
+#include <linux/bitops.h>
+#include <linux/slab.h>
+
+struct dpll_attr {
+	unsigned long valid_mask;
+	enum dpll_lock_status lock_status;
+	s32 temp;
+	u32 source_pin_idx;
+	enum dpll_mode mode;
+	unsigned long mode_supported_mask;
+	unsigned int netifindex;
+};
+
+static const int MAX_BITS = BITS_PER_TYPE(unsigned long);
+
+struct dpll_attr *dpll_attr_alloc(void)
+{
+	return kzalloc(sizeof(struct dpll_attr), GFP_KERNEL);
+}
+EXPORT_SYMBOL_GPL(dpll_attr_alloc);
+
+void dpll_attr_free(struct dpll_attr *attr)
+{
+	kfree(attr);
+}
+EXPORT_SYMBOL_GPL(dpll_attr_free);
+
+void dpll_attr_clear(struct dpll_attr *attr)
+{
+	memset(attr, 0, sizeof(*attr));
+}
+EXPORT_SYMBOL_GPL(dpll_attr_clear);
+
+bool dpll_attr_valid(enum dplla attr_id, const struct dpll_attr *attr)
+{
+	if (!attr)
+		return false;
+	if (attr_id > 0 && attr_id < BITS_PER_LONG)
+		return test_bit(attr_id, &attr->valid_mask);
+
+	return false;
+}
+EXPORT_SYMBOL_GPL(dpll_attr_valid);
+
+int
+dpll_attr_copy(struct dpll_attr *dst, const struct dpll_attr *src)
+{
+	if (!src || !dst)
+		return -EFAULT;
+	memcpy(dst, src, sizeof(*dst));
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(dpll_attr_copy);
+
+static inline bool dpll_lock_status_valid(enum dpll_lock_status status)
+{
+	if (status >= DPLL_LOCK_STATUS_UNSPEC &&
+	    status <= DPLL_LOCK_STATUS_MAX)
+		return true;
+
+	return false;
+}
+
+int dpll_attr_lock_status_set(struct dpll_attr *attr,
+			      enum dpll_lock_status status)
+{
+	if (!attr)
+		return -EFAULT;
+	if (!dpll_lock_status_valid(status))
+		return -EINVAL;
+
+	attr->lock_status = status;
+	set_bit(DPLLA_LOCK_STATUS, &attr->valid_mask);
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(dpll_attr_lock_status_set);
+
+enum dpll_lock_status dpll_attr_lock_status_get(const struct dpll_attr *attr)
+{
+	if (!dpll_attr_valid(DPLLA_LOCK_STATUS, attr))
+		return DPLL_LOCK_STATUS_UNSPEC;
+
+	return attr->lock_status;
+}
+EXPORT_SYMBOL_GPL(dpll_attr_lock_status_get);
+
+int dpll_attr_temp_set(struct dpll_attr *attr, s32 temp)
+{
+	if (!attr)
+		return -EFAULT;
+
+	attr->temp = temp;
+	set_bit(DPLLA_TEMP, &attr->valid_mask);
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(dpll_attr_temp_set);
+
+int dpll_attr_temp_get(const struct dpll_attr *attr, s32 *temp)
+{
+	if (!attr || !temp)
+		return -EFAULT;
+	if (!dpll_attr_valid(DPLLA_TEMP, attr))
+		return -EINVAL;
+
+	*temp = attr->temp;
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(dpll_attr_temp_get);
+
+int dpll_attr_source_idx_set(struct dpll_attr *attr, u32 source_idx)
+{
+	if (!attr)
+		return -EFAULT;
+
+	attr->source_pin_idx = source_idx;
+	set_bit(DPLLA_SOURCE_PIN_IDX, &attr->valid_mask);
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(dpll_attr_source_idx_set);
+
+int dpll_attr_source_idx_get(const struct dpll_attr *attr, u32 *source_idx)
+{
+	if (!attr || !source_idx)
+		return -EFAULT;
+	if (!dpll_attr_valid(DPLLA_SOURCE_PIN_IDX, attr))
+		return -EINVAL;
+
+	*source_idx = attr->source_pin_idx;
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(dpll_attr_source_idx_get);
+
+static inline bool dpll_mode_valid(enum dpll_mode mode)
+{
+	if (mode >= DPLL_MODE_UNSPEC &&
+	    mode <= DPLL_MODE_MAX)
+		return true;
+
+	return false;
+}
+
+int dpll_attr_mode_set(struct dpll_attr *attr, enum dpll_mode mode)
+{
+	if (!attr)
+		return -EFAULT;
+	if (!dpll_mode_valid(mode))
+		return -EINVAL;
+
+	attr->mode = mode;
+	set_bit(DPLLA_MODE, &attr->valid_mask);
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(dpll_attr_mode_set);
+
+enum dpll_mode dpll_attr_mode_get(const struct dpll_attr *attr)
+{
+	if (!attr || !dpll_attr_valid(DPLLA_MODE, attr))
+		return DPLL_MODE_UNSPEC;
+
+	return attr->mode;
+}
+EXPORT_SYMBOL_GPL(dpll_attr_mode_get);
+
+int dpll_attr_mode_supported_set(struct dpll_attr *attr, enum dpll_mode mode)
+{
+	if (!attr)
+		return -EFAULT;
+	if (!dpll_mode_valid(mode))
+		return -EINVAL;
+
+	set_bit(mode, &attr->mode_supported_mask);
+	set_bit(DPLLA_MODE_SUPPORTED, &attr->valid_mask);
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(dpll_attr_mode_supported_set);
+
+bool dpll_attr_mode_supported(const struct dpll_attr *attr,
+			      enum dpll_mode mode)
+{
+	if (!dpll_mode_valid(mode))
+		return false;
+	if (!dpll_attr_valid(DPLLA_MODE_SUPPORTED, attr))
+		return false;
+
+	return test_bit(mode, &attr->mode_supported_mask);
+}
+EXPORT_SYMBOL_GPL(dpll_attr_mode_supported);
+
+int dpll_attr_netifindex_set(struct dpll_attr *attr, unsigned int netifindex)
+{
+	if (!attr)
+		return -EFAULT;
+
+	attr->netifindex = netifindex;
+	set_bit(DPLLA_NETIFINDEX, &attr->valid_mask);
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(dpll_attr_netifindex_set);
+
+int dpll_attr_netifindex_get(const struct dpll_attr *attr,
+			     unsigned int *netifindex)
+{
+	if (!dpll_attr_valid(DPLLA_NETIFINDEX, attr))
+		return -EINVAL;
+
+	*netifindex = attr->netifindex;
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(dpll_attr_netifindex_get);
+
+static bool dpll_attr_changed(const enum dplla attr_id,
+			      struct dpll_attr *new,
+			      struct dpll_attr *old)
+{
+	if (dpll_attr_valid(attr_id, new)) {
+		if (dpll_attr_valid(attr_id, old)) {
+			switch (attr_id) {
+			case DPLLA_MODE:
+				if (new->mode != old->mode)
+					return true;
+				break;
+			case DPLLA_SOURCE_PIN_IDX:
+				if (new->source_pin_idx != old->source_pin_idx)
+					return true;
+				break;
+			default:
+				return false;
+			}
+		} else {
+			return true;
+		}
+	}
+
+	return false;
+}
+
+int dpll_attr_delta(struct dpll_attr *delta, struct dpll_attr *new,
+		    struct dpll_attr *old)
+{
+	int ret = -EINVAL;
+
+	if (!delta || !new || !old)
+		return -EFAULT;
+
+	dpll_attr_clear(delta);
+
+	if (dpll_attr_changed(DPLLA_MODE, new, old)) {
+		ret = dpll_attr_mode_set(delta, new->mode);
+		if (ret)
+			return ret;
+	}
+	if (dpll_attr_changed(DPLLA_SOURCE_PIN_IDX, new, old)) {
+		ret = dpll_attr_source_idx_set(delta, new->source_pin_idx);
+		if (ret)
+			return ret;
+	}
+
+	return ret;
+}
+EXPORT_SYMBOL_GPL(dpll_attr_delta);
diff --git a/drivers/dpll/dpll_pin_attr.c b/drivers/dpll/dpll_pin_attr.c
new file mode 100644
index 000000000000..bf57476228af
--- /dev/null
+++ b/drivers/dpll/dpll_pin_attr.c
@@ -0,0 +1,456 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ *  dpll_pin_attr.c - Pin attribute handling helper class.
+ *
+ *  Copyright (c) 2022, Intel Corporation.
+ */
+
+#include <linux/dpll.h>
+#include <linux/bitops.h>
+#include <linux/slab.h>
+
+struct dpll_pin_attr {
+	unsigned long valid_mask;
+	enum dpll_pin_type type;
+	unsigned long types_supported_mask;
+	enum dpll_pin_signal_type signal_type;
+	unsigned long signal_types_supported_mask;
+	u32 custom_freq;
+	unsigned long state_mask;
+	unsigned long state_supported_mask;
+	u32 prio;
+	unsigned int netifindex;
+};
+
+static const int MAX_BITS = BITS_PER_TYPE(unsigned long);
+
+struct dpll_pin_attr *dpll_pin_attr_alloc(void)
+{
+	return kzalloc(sizeof(struct dpll_pin_attr), GFP_KERNEL);
+}
+EXPORT_SYMBOL_GPL(dpll_pin_attr_alloc);
+
+void dpll_pin_attr_free(struct dpll_pin_attr *attr)
+{
+	kfree(attr);
+}
+EXPORT_SYMBOL_GPL(dpll_pin_attr_free);
+
+void dpll_pin_attr_clear(struct dpll_pin_attr *attr)
+{
+	memset(attr, 0, sizeof(*attr));
+}
+EXPORT_SYMBOL_GPL(dpll_pin_attr_clear);
+
+bool dpll_pin_attr_valid(enum dplla attr_id, const struct dpll_pin_attr *attr)
+{
+	if (!attr)
+		return false;
+	if (attr_id > 0 && attr_id < BITS_PER_LONG)
+		return test_bit(attr_id, &attr->valid_mask);
+
+	return false;
+}
+EXPORT_SYMBOL_GPL(dpll_pin_attr_valid);
+
+int
+dpll_pin_attr_copy(struct dpll_pin_attr *dst, const struct dpll_pin_attr *src)
+{
+	if (!src || !dst)
+		return -EFAULT;
+	memcpy(dst, src, sizeof(*dst));
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(dpll_pin_attr_copy);
+
+static inline bool dpll_pin_type_valid(enum dpll_pin_type type)
+{
+	if (type >= DPLL_PIN_TYPE_UNSPEC && type <= DPLL_PIN_TYPE_MAX)
+		return true;
+
+	return false;
+}
+
+int dpll_pin_attr_type_set(struct dpll_pin_attr *attr, enum dpll_pin_type type)
+{
+	if (!attr)
+		return -EFAULT;
+	if (!dpll_pin_type_valid(type))
+		return -EINVAL;
+
+	attr->type = type;
+	set_bit(DPLLA_PIN_TYPE, &attr->valid_mask);
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(dpll_pin_attr_type_set);
+
+enum dpll_pin_type dpll_pin_attr_type_get(const struct dpll_pin_attr *attr)
+{
+	if (!dpll_pin_attr_valid(DPLLA_PIN_TYPE, attr))
+		return DPLL_PIN_TYPE_UNSPEC;
+
+	return attr->type;
+}
+EXPORT_SYMBOL_GPL(dpll_pin_attr_type_get);
+
+int dpll_pin_attr_type_supported_set(struct dpll_pin_attr *attr,
+				     enum dpll_pin_type type)
+{
+	if (!attr)
+		return -EFAULT;
+	if (!dpll_pin_type_valid(type))
+		return -EINVAL;
+
+	set_bit(type, &attr->types_supported_mask);
+	set_bit(DPLLA_PIN_TYPE_SUPPORTED, &attr->valid_mask);
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(dpll_pin_attr_type_supported_set);
+
+bool dpll_pin_attr_type_supported(const struct dpll_pin_attr *attr,
+				     enum dpll_pin_type type)
+{
+	if (!dpll_pin_type_valid(type))
+		return false;
+	if (!dpll_pin_attr_valid(DPLLA_PIN_TYPE_SUPPORTED, attr))
+		return false;
+
+	return test_bit(type, &attr->types_supported_mask);
+}
+EXPORT_SYMBOL_GPL(dpll_pin_attr_type_supported);
+
+static inline bool dpll_pin_signal_type_valid(enum dpll_pin_signal_type type)
+{
+	if (type >= DPLL_PIN_SIGNAL_TYPE_UNSPEC &&
+	    type <= DPLL_PIN_SIGNAL_TYPE_MAX)
+		return true;
+
+	return false;
+}
+
+int dpll_pin_attr_signal_type_set(struct dpll_pin_attr *attr,
+				  enum dpll_pin_signal_type type)
+{
+	if (!attr)
+		return -EFAULT;
+	if (!dpll_pin_signal_type_valid(type))
+		return -EINVAL;
+
+	attr->signal_type = type;
+	set_bit(DPLLA_PIN_SIGNAL_TYPE, &attr->valid_mask);
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(dpll_pin_attr_signal_type_set);
+
+enum dpll_pin_signal_type
+dpll_pin_attr_signal_type_get(const struct dpll_pin_attr *attr)
+{
+	if (!dpll_pin_attr_valid(DPLLA_PIN_SIGNAL_TYPE, attr))
+		return DPLL_PIN_SIGNAL_TYPE_UNSPEC;
+
+	return attr->signal_type;
+}
+EXPORT_SYMBOL_GPL(dpll_pin_attr_signal_type_get);
+
+int dpll_pin_attr_signal_type_supported_set(struct dpll_pin_attr *attr,
+					    enum dpll_pin_signal_type type)
+{
+	if (!attr)
+		return -EFAULT;
+	if (!dpll_pin_signal_type_valid(type))
+		return -EINVAL;
+
+	set_bit(type, &attr->signal_types_supported_mask);
+	set_bit(DPLLA_PIN_SIGNAL_TYPE_SUPPORTED, &attr->valid_mask);
+
+	return 0;
+
+}
+EXPORT_SYMBOL_GPL(dpll_pin_attr_signal_type_supported_set);
+
+bool dpll_pin_attr_signal_type_supported(const struct dpll_pin_attr *attr,
+					    enum dpll_pin_signal_type type)
+{
+	if (!dpll_pin_signal_type_valid(type))
+		return false;
+	if (!dpll_pin_attr_valid(DPLLA_PIN_SIGNAL_TYPE_SUPPORTED, attr))
+		return false;
+
+	return test_bit(type, &attr->signal_types_supported_mask);
+}
+EXPORT_SYMBOL_GPL(dpll_pin_attr_signal_type_supported);
+
+int dpll_pin_attr_custom_freq_set(struct dpll_pin_attr *attr, u32 freq)
+{
+	if (!attr)
+		return -EFAULT;
+
+	attr->custom_freq = freq;
+	set_bit(DPLLA_PIN_CUSTOM_FREQ, &attr->valid_mask);
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(dpll_pin_attr_custom_freq_set);
+
+int dpll_pin_attr_custom_freq_get(const struct dpll_pin_attr *attr, u32 *freq)
+{
+	if (!attr || !freq)
+		return -EFAULT;
+	if (!test_bit(DPLLA_PIN_CUSTOM_FREQ, &attr->valid_mask))
+		return -EINVAL;
+
+	*freq = attr->custom_freq;
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(dpll_pin_attr_custom_freq_get);
+
+static inline bool dpll_pin_state_valid(enum dpll_pin_state state)
+{
+	if (state >= DPLL_PIN_STATE_UNSPEC &&
+	    state <= DPLL_PIN_STATE_MAX)
+		return true;
+
+	return false;
+}
+
+int dpll_pin_attr_state_set(struct dpll_pin_attr *attr,
+			    enum dpll_pin_state state)
+{
+	if (!attr)
+		return -EFAULT;
+	if (!dpll_pin_state_valid(state))
+		return -EINVAL;
+	if (state == DPLL_PIN_STATE_CONNECTED) {
+		if (test_bit(DPLL_PIN_STATE_DISCONNECTED, &attr->state_mask))
+			return -EINVAL;
+	} else if (state == DPLL_PIN_STATE_DISCONNECTED) {
+		if (test_bit(DPLL_PIN_STATE_CONNECTED, &attr->state_mask))
+			return -EINVAL;
+	}
+
+	set_bit(state, &attr->state_mask);
+	set_bit(DPLLA_PIN_STATE, &attr->valid_mask);
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(dpll_pin_attr_state_set);
+
+bool dpll_pin_attr_state_enabled(const struct dpll_pin_attr *attr,
+				 enum dpll_pin_state state)
+{
+	if (!dpll_pin_state_valid(state))
+		return false;
+	if (!dpll_pin_attr_valid(DPLLA_PIN_STATE, attr))
+		return false;
+
+	return test_bit(state, &attr->state_mask);
+}
+EXPORT_SYMBOL_GPL(dpll_pin_attr_state_enabled);
+
+int dpll_pin_attr_state_supported_set(struct dpll_pin_attr *attr,
+				      enum dpll_pin_state state)
+{
+	if (!attr)
+		return -EFAULT;
+	if (!dpll_pin_state_valid(state))
+		return -EINVAL;
+
+	set_bit(state, &attr->state_supported_mask);
+	set_bit(DPLLA_PIN_STATE_SUPPORTED, &attr->valid_mask);
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(dpll_pin_attr_state_supported_set);
+
+bool dpll_pin_attr_state_supported(const struct dpll_pin_attr *attr,
+				   enum dpll_pin_state state)
+{
+	if (!dpll_pin_state_valid(state))
+		return false;
+	if (!dpll_pin_attr_valid(DPLLA_PIN_STATE_SUPPORTED, attr))
+		return false;
+
+	return test_bit(state, &attr->state_supported_mask);
+}
+EXPORT_SYMBOL_GPL(dpll_pin_attr_state_supported);
+
+int dpll_pin_attr_prio_set(struct dpll_pin_attr *attr, u32 prio)
+{
+	if (!attr)
+		return -EFAULT;
+	if (prio > PIN_PRIO_LOWEST)
+		return -EINVAL;
+
+	attr->prio = prio;
+	set_bit(DPLLA_PIN_PRIO, &attr->valid_mask);
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(dpll_pin_attr_prio_set);
+
+int dpll_pin_attr_prio_get(const struct dpll_pin_attr *attr, u32 *prio)
+{
+	if (!attr || !prio)
+		return -EFAULT;
+	if (!dpll_pin_attr_valid(DPLLA_PIN_PRIO, attr))
+		return -EINVAL;
+
+	*prio = attr->prio;
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(dpll_pin_attr_prio_get);
+
+int dpll_pin_attr_netifindex_set(struct dpll_pin_attr *attr, unsigned int netifindex)
+{
+	if (!attr)
+		return -EFAULT;
+
+	attr->netifindex = netifindex;
+	set_bit(DPLLA_PIN_NETIFINDEX, &attr->valid_mask);
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(dpll_pin_attr_netifindex_set);
+
+int dpll_pin_attr_netifindex_get(const struct dpll_pin_attr *attr,
+				 unsigned int *netifindex)
+{
+	if (!dpll_pin_attr_valid(DPLLA_PIN_NETIFINDEX, attr))
+		return -EINVAL;
+
+	*netifindex = attr->netifindex;
+	return true;
+}
+EXPORT_SYMBOL_GPL(dpll_pin_attr_netifindex_get);
+
+static bool dpll_pin_attr_changed(const enum dplla attr_id,
+				  struct dpll_pin_attr *new,
+				  struct dpll_pin_attr *old)
+{
+	if (dpll_pin_attr_valid(attr_id, new)) {
+		if (dpll_pin_attr_valid(attr_id, old)) {
+			switch (attr_id) {
+			case DPLLA_PIN_TYPE:
+				if (new->type != old->type)
+					return true;
+				break;
+			case DPLLA_PIN_SIGNAL_TYPE:
+				if (new->signal_type != old->signal_type)
+					return true;
+				break;
+			case DPLLA_PIN_CUSTOM_FREQ:
+				if (new->custom_freq != old->custom_freq)
+					return true;
+				break;
+			case DPLLA_PIN_STATE:
+				if (new->state_mask != old->state_mask)
+					return true;
+				break;
+			case DPLLA_PIN_PRIO:
+				if (new->prio != old->prio)
+					return true;
+				break;
+			default:
+				return false;
+			}
+		} else {
+			return true;
+		}
+	}
+
+	return false;
+}
+
+int dpll_pin_attr_delta(struct dpll_pin_attr *delta, struct dpll_pin_attr *new,
+			struct dpll_pin_attr *old)
+{
+	int ret = -EINVAL;
+
+	if (!delta || !new || !old)
+		return -EFAULT;
+
+	dpll_pin_attr_clear(delta);
+
+	if (dpll_pin_attr_changed(DPLLA_PIN_TYPE, new, old)) {
+		ret = dpll_pin_attr_type_set(delta, new->type);
+		if (ret)
+			return ret;
+	}
+	if (dpll_pin_attr_changed(DPLLA_PIN_SIGNAL_TYPE, new, old)) {
+		ret = dpll_pin_attr_signal_type_set(delta, new->signal_type);
+		if (ret)
+			return ret;
+	}
+	if (dpll_pin_attr_changed(DPLLA_PIN_CUSTOM_FREQ, new, old)) {
+		ret = dpll_pin_attr_custom_freq_set(delta, new->custom_freq);
+		if (ret)
+			return ret;
+	}
+	if (dpll_pin_attr_changed(DPLLA_PIN_STATE, new, old)) {
+		enum dpll_pin_state i;
+
+		for (i = DPLL_PIN_STATE_UNSPEC + 1;
+		     i <= DPLL_PIN_STATE_MAX; i++)
+			if (test_bit(i, &new->state_mask)) {
+				ret = dpll_pin_attr_state_set(delta, i);
+				if (ret)
+					return ret;
+			}
+	}
+	if (dpll_pin_attr_changed(DPLLA_PIN_PRIO, new, old)) {
+		ret = dpll_pin_attr_prio_set(delta, new->prio);
+		if (ret)
+			return ret;
+	}
+
+	return ret;
+}
+EXPORT_SYMBOL_GPL(dpll_pin_attr_delta);
+
+int dpll_pin_attr_prep_common(struct dpll_pin_attr *common,
+			      const struct dpll_pin_attr *reference)
+{
+	if (!common || !reference)
+		return -EFAULT;
+	dpll_pin_attr_clear(common);
+	if (dpll_pin_attr_valid(DPLLA_PIN_TYPE, reference)) {
+		common->type = reference->type;
+		set_bit(DPLLA_PIN_TYPE, &common->valid_mask);
+	}
+	if (dpll_pin_attr_valid(DPLLA_PIN_SIGNAL_TYPE, reference)) {
+		common->signal_type = reference->signal_type;
+		set_bit(DPLLA_PIN_SIGNAL_TYPE, &common->valid_mask);
+	}
+	if (dpll_pin_attr_valid(DPLLA_PIN_CUSTOM_FREQ, reference)) {
+		common->custom_freq = reference->custom_freq;
+		set_bit(DPLLA_PIN_CUSTOM_FREQ, &common->valid_mask);
+	}
+	if (dpll_pin_attr_valid(DPLLA_PIN_STATE, reference)) {
+		common->state_mask = reference->state_mask;
+		set_bit(DPLLA_PIN_STATE, &common->valid_mask);
+	}
+	return common->valid_mask ? PIN_ATTR_CHANGE : 0;
+}
+EXPORT_SYMBOL_GPL(dpll_pin_attr_prep_common);
+
+
+int dpll_pin_attr_prep_exclusive(struct dpll_pin_attr *exclusive,
+				 const struct dpll_pin_attr *reference)
+{
+	if (!exclusive || !reference)
+		return -EFAULT;
+	dpll_pin_attr_clear(exclusive);
+	if (dpll_pin_attr_valid(DPLLA_PIN_PRIO, reference)) {
+		exclusive->prio = reference->prio;
+		set_bit(DPLLA_PIN_PRIO, &exclusive->valid_mask);
+	}
+	return exclusive->valid_mask ? PIN_ATTR_CHANGE : 0;
+}
+EXPORT_SYMBOL_GPL(dpll_pin_attr_prep_exclusive);
+
diff --git a/include/linux/dpll_attr.h b/include/linux/dpll_attr.h
new file mode 100644
index 000000000000..fe5e2188ca0b
--- /dev/null
+++ b/include/linux/dpll_attr.h
@@ -0,0 +1,433 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ *  dpll_attr.h - Header for attribute handling helper class.
+ *
+ *  Copyright (c) 2022, Intel Corporation.
+ */
+
+#ifndef __DPLL_ATTR_H__
+#define __DPLL_ATTR_H__
+
+#include <linux/types.h>
+
+struct dpll_attr;
+struct dpll_pin_attr;
+
+#define PIN_PRIO_HIGHEST	0
+#define PIN_PRIO_LOWEST		0xff
+#define PIN_ATTR_CHANGE		1
+
+/**
+ * dpll_attr_alloc - allocate a dpll attributes struct
+ *
+ * Return: pointer if succeeded, NULL otherwise.
+ */
+struct dpll_attr *dpll_attr_alloc(void);
+
+/**
+ * dpll_attr_free - frees a dpll attributes struct
+ * @attr: structure with dpll attributes
+ */
+void dpll_attr_free(struct dpll_attr *attr);
+
+/**
+ * dpll_attr_clear - clears a dpll attributes struct
+ * @attr: structure with dpll attributes
+ */
+void dpll_attr_clear(struct dpll_attr *attr);
+
+/**
+ * dpll_attr_valid - checks if a attribute is valid
+ * @attr_id: attribute to be checked
+ * @attr: structure with dpll attributes
+ *
+ * Checks if the attribute has been set before and if stored value is valid.
+ * Return: true if valid, false otherwise.
+ */
+bool dpll_attr_valid(enum dplla attr_id, const struct dpll_attr *attr);
+
+/**
+ * dpll_attr_copy - create a copy of the dpll attributes structure
+ * @dst: destination structure with dpll attributes
+ * @src: source structure with dpll attributes
+ *
+ * Memory needs to be allocated before calling this function.
+ * Return: 0 if succeeds, error code otherwise.
+ */
+int
+dpll_attr_copy(struct dpll_attr *dst, const struct dpll_attr *src);
+
+/**
+ * dpll_attr_lock_status_set - set the lock status in the attributes
+ * @attr: structure with dpll attributes
+ * @status: dpll lock status to be set
+ *
+ * Return: 0 if succeeds, error code otherwise.
+ */
+int dpll_attr_lock_status_set(struct dpll_attr *attr,
+			      enum dpll_lock_status status);
+
+/**
+ * dpll_attr_lock_status_get - get the lock status from the attributes
+ * @attr: structure with dpll attributes
+ *
+ * Return: dpll lock status
+ */
+enum dpll_lock_status
+dpll_attr_lock_status_get(const struct dpll_attr *attr);
+
+/**
+ * dpll_attr_temp_set - set the temperature in the attributes
+ * @attr: structure with dpll attributes
+ * @temp: temperature to be set
+ *
+ * Return: 0 if succeeds, error code otherwise.
+ */
+int dpll_attr_temp_set(struct dpll_attr *attr, s32 temp);
+
+/**
+ * dpll_attr_temp_get - get the temperature from the attributes
+ * @attr: structure with dpll attributes
+ * @temp: temperature (out)
+ *
+ * Return: 0 if succeeds, error code otherwise.
+ */
+int dpll_attr_temp_get(const struct dpll_attr *attr, s32 *temp);
+
+/**
+ * dpll_attr_source_idx_set - set the source id in the attributes
+ * @attr: structure with dpll attributes
+ * @source_idx: source id to be set
+ *
+ * Return: 0 if succeeds, error code otherwise.
+ */
+int dpll_attr_source_idx_set(struct dpll_attr *attr, u32 source_idx);
+
+/**
+ * dpll_attr_source_idx_get - get the source id from the attributes
+ * @attr: structure with dpll attributes
+ * @source_idx: source id (out)
+ *
+ * Return: 0 if succeeds, error code otherwise.
+ */
+int dpll_attr_source_idx_get(const struct dpll_attr *attr, u32 *source_idx);
+
+/**
+ * dpll_attr_mode_set - set the dpll mode in the attributes
+ * @attr: structure with dpll attributes
+ * @mode: dpll mode to be set
+ *
+ * Return: 0 if succeeds, error code otherwise.
+ */
+int dpll_attr_mode_set(struct dpll_attr *attr, enum dpll_mode mode);
+
+/**
+ * dpll_attr_mode_get - get the dpll mode from the attributes
+ * @attr: structure with dpll attributes
+ *
+ * Return: dpll mode.
+ */
+enum dpll_mode dpll_attr_mode_get(const struct dpll_attr *attr);
+
+/**
+ * dpll_attr_mode_set - set the dpll supported mode in the attributes
+ * @attr: structure with dpll attributes
+ * @mode: dpll mode to be set in supported modes
+ *
+ * Return: 0 if succeeds, error code otherwise.
+ */
+int dpll_attr_mode_supported_set(struct dpll_attr *attr, enum dpll_mode mode);
+
+/**
+ * dpll_attr_mode_supported - check if the dpll mode is supported
+ * @attr: structure with dpll attributes
+ * @mode: dpll mode to be checked
+ *
+ * Return: true if mode supported, false otherwise.
+ */
+bool dpll_attr_mode_supported(const struct dpll_attr *attr,
+			      enum dpll_mode mode);
+
+/**
+ * dpll_attr_netifindex_set - set the netifindex in the attributes
+ * @attr: structure with dpll attributes
+ * @netifindex: parameter to be set in attributes
+ *
+ * Return: 0 if succeeds, error code otherwise.
+ */
+int dpll_attr_netifindex_set(struct dpll_attr *attr, unsigned int netifindex);
+
+/**
+ * dpll_attr_netifindex_get - get the netifindex from the attributes
+ * @attr: structure with dpll attributes
+ * @netifindex: retrieved parameter
+ *
+ * Return: 0 if succeeds, error code otherwise.
+ */
+int dpll_attr_netifindex_get(const struct dpll_attr *attr,
+			     unsigned int *netifindex);
+
+/**
+ * dpll_attr_delta - calculate the difference between two dpll attribute sets
+ * @delta: structure with delta of dpll attributes
+ * @new: structure with new dpll attributes
+ * @old: structure with old dpll attributes
+ *
+ * Return: 0 if succeeds, error code otherwise.
+ */
+int dpll_attr_delta(struct dpll_attr *delta, struct dpll_attr *new,
+		    struct dpll_attr *old);
+
+/**
+ * dpll_pin_attr_alloc - allocate a dpll pin attributes struct
+ *
+ * Return: pointer if succeeded, NULL otherwise.
+ */
+struct dpll_pin_attr *dpll_pin_attr_alloc(void);
+
+/**
+ * dpll_pin_attr_free - frees a dpll pin attributes struct
+ * @attr: structure with dpll pin attributes
+ */
+void dpll_pin_attr_free(struct dpll_pin_attr *attr);
+
+/**
+ * dpll_pin_attr_clear - clears a dpll pin attributes struct
+ * @attr: structure with dpll attributes
+ */
+void dpll_pin_attr_clear(struct dpll_pin_attr *attr);
+
+/**
+ * dpll_pin_attr_valid - checks if a pin attribute is valid
+ * @attr_id: attribute to be checked
+ * @attr: structure with dpll pin attributes
+ *
+ * Checks if the attribute has been set before and if stored value is valid.
+ * Return: true if valid, false otherwise.
+ */
+bool dpll_pin_attr_valid(enum dplla attr_id, const struct dpll_pin_attr *attr);
+
+/**
+ * dpll_pin_attr_copy - create a copy of the dpll pin attributes structure
+ * @dst: destination structure with dpll pin attributes
+ * @src: source structure with dpll pin attributes
+ *
+ * Memory needs to be allocated before calling this function.
+ * Return: 0 if succeeds, error code otherwise.
+ */
+int
+dpll_pin_attr_copy(struct dpll_pin_attr *dst, const struct dpll_pin_attr *src);
+
+/**
+ * dpll_pin_attr_type_set - set the pin type in the attributes
+ * @attr: structure with dpll pin attributes
+ * @type: parameter to be set in attributes
+ *
+ * Return: 0 if succeeds, error code otherwise.
+ */
+int dpll_pin_attr_type_set(struct dpll_pin_attr *attr, enum dpll_pin_type type);
+
+/**
+ * dpll_pin_attr_type_get - get the pin type from the attributes
+ * @attr: structure with dpll pin attributes
+ *
+ * Return: dpll pin type.
+ */
+enum dpll_pin_type dpll_pin_attr_type_get(const struct dpll_pin_attr *attr);
+
+/**
+ * dpll_pin_attr_type_supported_set - set the dpll pin supported type in the
+ * attributes
+ * @attr: structure with dpll attributes
+ * @type: pin type to be set in supported modes
+ *
+ * Return: 0 if succeeds, error code otherwise.
+ */
+int dpll_pin_attr_type_supported_set(struct dpll_pin_attr *attr,
+				     enum dpll_pin_type type);
+
+/**
+ * dpll_pin_attr_type_supported - check if the pin type is supported
+ * @attr: structure with dpll attributes
+ * @type: dpll mode to be checked
+ *
+ * Return: true if type supported, false otherwise.
+ */
+bool dpll_pin_attr_type_supported(const struct dpll_pin_attr *attr,
+				     enum dpll_pin_type type);
+
+/**
+ * dpll_pin_attr_signal_type_set - set the pin signal type in the attributes
+ * @attr: structure with dpll attributes
+ * @type: pin signal type to be set in supported modes
+ *
+ * Return: 0 if succeeds, error code otherwise.
+ */
+int dpll_pin_attr_signal_type_set(struct dpll_pin_attr *attr,
+				  enum dpll_pin_signal_type type);
+
+/**
+ * dpll_pin_attr_signal_type_get - get the pin signal type from the attributes
+ * @attr: structure with dpll pin attributes
+ *
+ * Return: pin signal type.
+ */
+enum dpll_pin_signal_type
+dpll_pin_attr_signal_type_get(const struct dpll_pin_attr *attr);
+
+/**
+ * dpll_pin_attr_signal_type_supported_set - set the dpll pin supported signal
+ * type in the attributes
+ * @attr: structure with dpll attributes
+ * @type: pin signal type to be set in supported types
+ *
+ * Return: 0 if succeeds, error code otherwise.
+ */
+int dpll_pin_attr_signal_type_supported_set(struct dpll_pin_attr *attr,
+					    enum dpll_pin_signal_type type);
+
+/**
+ * dpll_pin_attr_signal_type_supported - check if the pin signal type is
+ * supported
+ * @attr: structure with dpll attributes
+ * @type: pin signal type to be checked
+ *
+ * Return: true if type supported, false otherwise.
+ */
+bool dpll_pin_attr_signal_type_supported(const struct dpll_pin_attr *attr,
+					    enum dpll_pin_signal_type type);
+
+/**
+ * dpll_pin_attr_custom_freq_set - set the custom frequency in the attributes
+ * @attr: structure with dpll pin attributes
+ * @freq: parameter to be set in attributes
+ *
+ * Return: 0 if succeeds, error code otherwise.
+ */
+int dpll_pin_attr_custom_freq_set(struct dpll_pin_attr *attr, u32 freq);
+
+/**
+ * dpll_pin_attr_custom_freq_get - get the pin type from the attributes
+ * @attr: structure with dpll pin attributes
+ * @freq: parameter to be retrieved
+ *
+ * Return: 0 if succeeds, error code otherwise.
+ */
+int dpll_pin_attr_custom_freq_get(const struct dpll_pin_attr *attr, u32 *freq);
+
+/**
+ * dpll_pin_attr_state_set - set the pin state the attributes
+ * @attr: structure with dpll pin attributes
+ * @state: parameter to be set in attributes
+ *
+ * Return: 0 if succeeds, error code otherwise.
+ */
+int dpll_pin_attr_state_set(struct dpll_pin_attr *attr,
+			    enum dpll_pin_state state);
+
+/**
+ * dpll_pin_attr_state_enabled - check if state is enabled
+ * @attr: structure with dpll pin attributes
+ * @state: parameter to be checked in attributes
+ *
+ * Return: true if enabled, false otherwise.
+ */
+bool dpll_pin_attr_state_enabled(const struct dpll_pin_attr *attr,
+				 enum dpll_pin_state state);
+
+/**
+ * dpll_pin_attr_state_supported_set - set the supported pin state in the
+ * attributes
+ * @attr: structure with dpll attributes
+ * @state: pin state to be set in supported types
+ *
+ * Return: 0 if succeeds, error code otherwise.
+ */
+int dpll_pin_attr_state_supported_set(struct dpll_pin_attr *attr,
+				      enum dpll_pin_state state);
+
+/**
+ * dpll_pin_attr_state_supported - check if the pin state is supported
+ * @attr: structure with dpll attributes
+ * @state: pin signal type to be checked
+ *
+ * Return: true if state supported, false otherwise.
+ */
+bool dpll_pin_attr_state_supported(const struct dpll_pin_attr *attr,
+				   enum dpll_pin_state state);
+
+/**
+ * dpll_pin_attr_prio_set - set the pin priority in the attributes
+ * @attr: structure with dpll pin attributes
+ * @prio: parameter to be set in attributes
+ *
+ * Return: 0 if succeeds, error code otherwise.
+ */
+int dpll_pin_attr_prio_set(struct dpll_pin_attr *attr, u32 prio);
+
+/**
+ * dpll_pin_attr_prio_get - get the pin priority from the attributes
+ * @attr: structure with dpll pin attributes
+ * @prio: parameter to be retrieved
+ *
+ * Return: 0 if succeeds, error code otherwise.
+ */
+int dpll_pin_attr_prio_get(const struct dpll_pin_attr *attr, u32 *prio);
+
+/**
+ * dpll_pin_attr_netifindex_set - set the pin netifindex in the attributes
+ * @attr: structure with dpll pin attributes
+ * @netifindex: parameter to be set in attributes
+ *
+ * Return: 0 if succeeds, error code otherwise.
+ */
+int dpll_pin_attr_netifindex_set(struct dpll_pin_attr *attr,
+				 unsigned int netifindex);
+
+/**
+ * dpll_pin_attr_netifindex_get - get the pin netifindex from the attributes
+ * @attr: structure with dpll pin attributes
+ * @netifindex: parameter to be retrieved
+ *
+ * Return: 0 if succeeds, error code otherwise.
+ */
+int dpll_pin_attr_netifindex_get(const struct dpll_pin_attr *attr,
+				 unsigned int *netifindex);
+
+/**
+ * dpll_attr_delta - calculate the difference between two dpll pin attribute sets
+ * @delta: structure with delta of dpll pin attributes
+ * @new: structure with new dpll pin attributes
+ * @old: structure with old dpll pin attributes
+ *
+ * Return: 0 if succeeds, error code otherwise.
+ */
+int dpll_pin_attr_delta(struct dpll_pin_attr *delta, struct dpll_pin_attr *new,
+			struct dpll_pin_attr *old);
+
+/**
+ * dpll_pin_attr_prep_common - calculate the common dpll pin attributes
+ * @common: structure with common dpll pin attributes
+ * @reference: referenced structure with dpll pin attributes
+ *
+ * Some of the pin attributes applies to all DPLLs and other are exclusive.
+ * This function calculates if any of the common pin attributes are set.
+ * Return: 0 if succeeds, error code otherwise.
+ */
+int dpll_pin_attr_prep_common(struct dpll_pin_attr *common,
+			      const struct dpll_pin_attr *reference);
+
+/**
+ * dpll_pin_attr_prep_exclusive - calculate the exclusive dpll pin attributes
+ * @exclusive: structure with common dpll pin attributes
+ * @reference: referenced structure with dpll pin attributes
+ *
+ * Some of the pin attributes applies to all DPLLs and other are exclusive.
+ * This function calculates if any of the exclusive pin attributes are set.
+ * Return: 0 if succeeds, error code otherwise.
+ */
+int dpll_pin_attr_prep_exclusive(struct dpll_pin_attr *exclusive,
+				 const struct dpll_pin_attr *reference);
+
+
+#endif /* __DPLL_ATTR_H__ */
