mirror of
https://github.com/torvalds/linux.git
synced 2026-03-08 03:24:45 +01:00
dpll: Allow associating dpll pin with a firmware node
Extend the DPLL core to support associating a DPLL pin with a firmware node. This association is required to allow other subsystems (such as network drivers) to locate and request specific DPLL pins defined in the Device Tree or ACPI. * Add a .fwnode field to the struct dpll_pin * Introduce dpll_pin_fwnode_set() helper to allow the provider driver to associate a pin with a fwnode after the pin has been allocated * Introduce fwnode_dpll_pin_find() helper to allow consumers to search for a registered DPLL pin using its associated fwnode handle * Ensure the fwnode reference is properly released in dpll_pin_put() Reviewed-by: Aleksandr Loktionov <aleksandr.loktionov@intel.com> Reviewed-by: Vadim Fedorenko <vadim.fedorenko@linux.dev> Signed-off-by: Ivan Vecera <ivecera@redhat.com> Reviewed-by: Arkadiusz Kubalewski <arkadiusz.kubalewski@intel.com> Link: https://patch.msgid.link/20260203174002.705176-2-ivecera@redhat.com Signed-off-by: Paolo Abeni <pabeni@redhat.com>
This commit is contained in:
parent
0e6c95c988
commit
d0f4771e2b
3 changed files with 62 additions and 0 deletions
|
|
@ -10,6 +10,7 @@
|
|||
|
||||
#include <linux/device.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/property.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/string.h>
|
||||
|
||||
|
|
@ -595,12 +596,60 @@ void dpll_pin_put(struct dpll_pin *pin)
|
|||
xa_destroy(&pin->parent_refs);
|
||||
xa_destroy(&pin->ref_sync_pins);
|
||||
dpll_pin_prop_free(&pin->prop);
|
||||
fwnode_handle_put(pin->fwnode);
|
||||
kfree_rcu(pin, rcu);
|
||||
}
|
||||
mutex_unlock(&dpll_lock);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(dpll_pin_put);
|
||||
|
||||
/**
|
||||
* dpll_pin_fwnode_set - set dpll pin firmware node reference
|
||||
* @pin: pointer to a dpll pin
|
||||
* @fwnode: firmware node handle
|
||||
*
|
||||
* Set firmware node handle for the given dpll pin.
|
||||
*/
|
||||
void dpll_pin_fwnode_set(struct dpll_pin *pin, struct fwnode_handle *fwnode)
|
||||
{
|
||||
mutex_lock(&dpll_lock);
|
||||
fwnode_handle_put(pin->fwnode); /* Drop fwnode previously set */
|
||||
pin->fwnode = fwnode_handle_get(fwnode);
|
||||
mutex_unlock(&dpll_lock);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(dpll_pin_fwnode_set);
|
||||
|
||||
/**
|
||||
* fwnode_dpll_pin_find - find dpll pin by firmware node reference
|
||||
* @fwnode: reference to firmware node
|
||||
*
|
||||
* Get existing object of a pin that is associated with given firmware node
|
||||
* reference.
|
||||
*
|
||||
* Context: Acquires a lock (dpll_lock)
|
||||
* Return:
|
||||
* * valid dpll_pin pointer on success
|
||||
* * NULL when no such pin exists
|
||||
*/
|
||||
struct dpll_pin *fwnode_dpll_pin_find(struct fwnode_handle *fwnode)
|
||||
{
|
||||
struct dpll_pin *pin, *ret = NULL;
|
||||
unsigned long index;
|
||||
|
||||
mutex_lock(&dpll_lock);
|
||||
xa_for_each(&dpll_pin_xa, index, pin) {
|
||||
if (pin->fwnode == fwnode) {
|
||||
ret = pin;
|
||||
refcount_inc(&ret->refcount);
|
||||
break;
|
||||
}
|
||||
}
|
||||
mutex_unlock(&dpll_lock);
|
||||
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(fwnode_dpll_pin_find);
|
||||
|
||||
static int
|
||||
__dpll_pin_register(struct dpll_device *dpll, struct dpll_pin *pin,
|
||||
const struct dpll_pin_ops *ops, void *priv, void *cookie)
|
||||
|
|
|
|||
|
|
@ -42,6 +42,7 @@ struct dpll_device {
|
|||
* @pin_idx: index of a pin given by dev driver
|
||||
* @clock_id: clock_id of creator
|
||||
* @module: module of creator
|
||||
* @fwnode: optional reference to firmware node
|
||||
* @dpll_refs: hold referencees to dplls pin was registered with
|
||||
* @parent_refs: hold references to parent pins pin was registered with
|
||||
* @ref_sync_pins: hold references to pins for Reference SYNC feature
|
||||
|
|
@ -54,6 +55,7 @@ struct dpll_pin {
|
|||
u32 pin_idx;
|
||||
u64 clock_id;
|
||||
struct module *module;
|
||||
struct fwnode_handle *fwnode;
|
||||
struct xarray dpll_refs;
|
||||
struct xarray parent_refs;
|
||||
struct xarray ref_sync_pins;
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@
|
|||
struct dpll_device;
|
||||
struct dpll_pin;
|
||||
struct dpll_pin_esync;
|
||||
struct fwnode_handle;
|
||||
|
||||
struct dpll_device_ops {
|
||||
int (*mode_get)(const struct dpll_device *dpll, void *dpll_priv,
|
||||
|
|
@ -178,6 +179,8 @@ void dpll_netdev_pin_clear(struct net_device *dev);
|
|||
size_t dpll_netdev_pin_handle_size(const struct net_device *dev);
|
||||
int dpll_netdev_add_pin_handle(struct sk_buff *msg,
|
||||
const struct net_device *dev);
|
||||
|
||||
struct dpll_pin *fwnode_dpll_pin_find(struct fwnode_handle *fwnode);
|
||||
#else
|
||||
static inline void
|
||||
dpll_netdev_pin_set(struct net_device *dev, struct dpll_pin *dpll_pin) { }
|
||||
|
|
@ -193,6 +196,12 @@ dpll_netdev_add_pin_handle(struct sk_buff *msg, const struct net_device *dev)
|
|||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline struct dpll_pin *
|
||||
fwnode_dpll_pin_find(struct fwnode_handle *fwnode)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
struct dpll_device *
|
||||
|
|
@ -218,6 +227,8 @@ void dpll_pin_unregister(struct dpll_device *dpll, struct dpll_pin *pin,
|
|||
|
||||
void dpll_pin_put(struct dpll_pin *pin);
|
||||
|
||||
void dpll_pin_fwnode_set(struct dpll_pin *pin, struct fwnode_handle *fwnode);
|
||||
|
||||
int dpll_pin_on_pin_register(struct dpll_pin *parent, struct dpll_pin *pin,
|
||||
const struct dpll_pin_ops *ops, void *priv);
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue