Lines Matching +full:- +full:pin
1 // SPDX-License-Identifier: GPL-2.0
3 * dpll_core.c - DPLL subsystem kernel-space interface implementation.
29 WARN_ON_ONCE(!xa_get_mark(&dpll_device_xa, (d)->id, DPLL_REGISTERED))
31 WARN_ON_ONCE(xa_get_mark(&dpll_device_xa, (d)->id, DPLL_REGISTERED))
33 WARN_ON_ONCE(!xa_get_mark(&dpll_pin_xa, (p)->id, DPLL_REGISTERED))
63 list_for_each_entry(reg, &ref->registration_list, list) { in dpll_pin_registration_find()
64 if (reg->ops == ops && reg->priv == priv && in dpll_pin_registration_find()
65 reg->cookie == cookie) in dpll_pin_registration_find()
72 dpll_xa_ref_pin_add(struct xarray *xa_pins, struct dpll_pin *pin, in dpll_xa_ref_pin_add() argument
83 if (ref->pin != pin) in dpll_xa_ref_pin_add()
87 refcount_inc(&ref->refcount); in dpll_xa_ref_pin_add()
97 return -ENOMEM; in dpll_xa_ref_pin_add()
98 ref->pin = pin; in dpll_xa_ref_pin_add()
99 INIT_LIST_HEAD(&ref->registration_list); in dpll_xa_ref_pin_add()
100 ret = xa_insert(xa_pins, pin->pin_idx, ref, GFP_KERNEL); in dpll_xa_ref_pin_add()
105 refcount_set(&ref->refcount, 1); in dpll_xa_ref_pin_add()
111 xa_erase(xa_pins, pin->pin_idx); in dpll_xa_ref_pin_add()
114 return -ENOMEM; in dpll_xa_ref_pin_add()
116 reg->ops = ops; in dpll_xa_ref_pin_add()
117 reg->priv = priv; in dpll_xa_ref_pin_add()
118 reg->cookie = cookie; in dpll_xa_ref_pin_add()
120 refcount_inc(&ref->refcount); in dpll_xa_ref_pin_add()
121 list_add_tail(®->list, &ref->registration_list); in dpll_xa_ref_pin_add()
126 static int dpll_xa_ref_pin_del(struct xarray *xa_pins, struct dpll_pin *pin, in dpll_xa_ref_pin_del() argument
135 if (ref->pin != pin) in dpll_xa_ref_pin_del()
139 return -EINVAL; in dpll_xa_ref_pin_del()
140 list_del(®->list); in dpll_xa_ref_pin_del()
142 if (refcount_dec_and_test(&ref->refcount)) { in dpll_xa_ref_pin_del()
144 WARN_ON(!list_empty(&ref->registration_list)); in dpll_xa_ref_pin_del()
150 return -EINVAL; in dpll_xa_ref_pin_del()
164 if (ref->dpll != dpll) in dpll_xa_ref_dpll_add()
168 refcount_inc(&ref->refcount); in dpll_xa_ref_dpll_add()
178 return -ENOMEM; in dpll_xa_ref_dpll_add()
179 ref->dpll = dpll; in dpll_xa_ref_dpll_add()
180 INIT_LIST_HEAD(&ref->registration_list); in dpll_xa_ref_dpll_add()
181 ret = xa_insert(xa_dplls, dpll->id, ref, GFP_KERNEL); in dpll_xa_ref_dpll_add()
186 refcount_set(&ref->refcount, 1); in dpll_xa_ref_dpll_add()
192 xa_erase(xa_dplls, dpll->id); in dpll_xa_ref_dpll_add()
195 return -ENOMEM; in dpll_xa_ref_dpll_add()
197 reg->ops = ops; in dpll_xa_ref_dpll_add()
198 reg->priv = priv; in dpll_xa_ref_dpll_add()
199 reg->cookie = cookie; in dpll_xa_ref_dpll_add()
201 refcount_inc(&ref->refcount); in dpll_xa_ref_dpll_add()
202 list_add_tail(®->list, &ref->registration_list); in dpll_xa_ref_dpll_add()
216 if (ref->dpll != dpll) in dpll_xa_ref_dpll_del()
221 list_del(®->list); in dpll_xa_ref_dpll_del()
223 if (refcount_dec_and_test(&ref->refcount)) { in dpll_xa_ref_dpll_del()
225 WARN_ON(!list_empty(&ref->registration_list)); in dpll_xa_ref_dpll_del()
250 return ERR_PTR(-ENOMEM); in dpll_device_alloc()
251 refcount_set(&dpll->refcount, 1); in dpll_device_alloc()
252 INIT_LIST_HEAD(&dpll->registration_list); in dpll_device_alloc()
253 dpll->device_idx = device_idx; in dpll_device_alloc()
254 dpll->clock_id = clock_id; in dpll_device_alloc()
255 dpll->module = module; in dpll_device_alloc()
256 ret = xa_alloc_cyclic(&dpll_device_xa, &dpll->id, dpll, xa_limit_32b, in dpll_device_alloc()
262 xa_init_flags(&dpll->pin_refs, XA_FLAGS_ALLOC); in dpll_device_alloc()
268 * dpll_device_get - find existing or create new dpll device
279 * * ERR_PTR(X) - error
289 if (dpll->clock_id == clock_id && in dpll_device_get()
290 dpll->device_idx == device_idx && in dpll_device_get()
291 dpll->module == module) { in dpll_device_get()
293 refcount_inc(&ret->refcount); in dpll_device_get()
306 * dpll_device_put - decrease the refcount and free memory if possible
316 if (refcount_dec_and_test(&dpll->refcount)) { in dpll_device_put()
318 WARN_ON_ONCE(!xa_empty(&dpll->pin_refs)); in dpll_device_put()
319 xa_destroy(&dpll->pin_refs); in dpll_device_put()
320 xa_erase(&dpll_device_xa, dpll->id); in dpll_device_put()
321 WARN_ON(!list_empty(&dpll->registration_list)); in dpll_device_put()
334 list_for_each_entry(reg, &dpll->registration_list, list) { in dpll_device_registration_find()
335 if (reg->ops == ops && reg->priv == priv) in dpll_device_registration_find()
342 * dpll_device_register - register the dpll device in the subsystem
353 * * negative - error value
362 return -EINVAL; in dpll_device_register()
363 if (WARN_ON(!ops->mode_get)) in dpll_device_register()
364 return -EINVAL; in dpll_device_register()
365 if (WARN_ON(!ops->lock_status_get)) in dpll_device_register()
366 return -EINVAL; in dpll_device_register()
368 return -EINVAL; in dpll_device_register()
374 return -EEXIST; in dpll_device_register()
380 return -ENOMEM; in dpll_device_register()
382 reg->ops = ops; in dpll_device_register()
383 reg->priv = priv; in dpll_device_register()
384 dpll->type = type; in dpll_device_register()
385 first_registration = list_empty(&dpll->registration_list); in dpll_device_register()
386 list_add_tail(®->list, &dpll->registration_list); in dpll_device_register()
392 xa_set_mark(&dpll_device_xa, dpll->id, DPLL_REGISTERED); in dpll_device_register()
401 * dpll_device_unregister - unregister dpll device
423 list_del(®->list); in dpll_device_unregister()
426 if (!list_empty(&dpll->registration_list)) { in dpll_device_unregister()
430 xa_clear_mark(&dpll_device_xa, dpll->id, DPLL_REGISTERED); in dpll_device_unregister()
437 kfree(prop->package_label); in dpll_pin_prop_free()
438 kfree(prop->panel_label); in dpll_pin_prop_free()
439 kfree(prop->board_label); in dpll_pin_prop_free()
440 kfree(prop->freq_supported); in dpll_pin_prop_free()
446 if (WARN_ON(src->freq_supported && !src->freq_supported_num)) in dpll_pin_prop_dup()
447 return -EINVAL; in dpll_pin_prop_dup()
450 if (src->freq_supported) { in dpll_pin_prop_dup()
451 size_t freq_size = src->freq_supported_num * in dpll_pin_prop_dup()
452 sizeof(*src->freq_supported); in dpll_pin_prop_dup()
453 dst->freq_supported = kmemdup(src->freq_supported, in dpll_pin_prop_dup()
455 if (!dst->freq_supported) in dpll_pin_prop_dup()
456 return -ENOMEM; in dpll_pin_prop_dup()
458 if (src->board_label) { in dpll_pin_prop_dup()
459 dst->board_label = kstrdup(src->board_label, GFP_KERNEL); in dpll_pin_prop_dup()
460 if (!dst->board_label) in dpll_pin_prop_dup()
463 if (src->panel_label) { in dpll_pin_prop_dup()
464 dst->panel_label = kstrdup(src->panel_label, GFP_KERNEL); in dpll_pin_prop_dup()
465 if (!dst->panel_label) in dpll_pin_prop_dup()
468 if (src->package_label) { in dpll_pin_prop_dup()
469 dst->package_label = kstrdup(src->package_label, GFP_KERNEL); in dpll_pin_prop_dup()
470 if (!dst->package_label) in dpll_pin_prop_dup()
477 kfree(dst->panel_label); in dpll_pin_prop_dup()
479 kfree(dst->board_label); in dpll_pin_prop_dup()
481 kfree(dst->freq_supported); in dpll_pin_prop_dup()
482 return -ENOMEM; in dpll_pin_prop_dup()
489 struct dpll_pin *pin; in dpll_pin_alloc() local
492 pin = kzalloc(sizeof(*pin), GFP_KERNEL); in dpll_pin_alloc()
493 if (!pin) in dpll_pin_alloc()
494 return ERR_PTR(-ENOMEM); in dpll_pin_alloc()
495 pin->pin_idx = pin_idx; in dpll_pin_alloc()
496 pin->clock_id = clock_id; in dpll_pin_alloc()
497 pin->module = module; in dpll_pin_alloc()
498 if (WARN_ON(prop->type < DPLL_PIN_TYPE_MUX || in dpll_pin_alloc()
499 prop->type > DPLL_PIN_TYPE_MAX)) { in dpll_pin_alloc()
500 ret = -EINVAL; in dpll_pin_alloc()
503 ret = dpll_pin_prop_dup(prop, &pin->prop); in dpll_pin_alloc()
506 refcount_set(&pin->refcount, 1); in dpll_pin_alloc()
507 xa_init_flags(&pin->dpll_refs, XA_FLAGS_ALLOC); in dpll_pin_alloc()
508 xa_init_flags(&pin->parent_refs, XA_FLAGS_ALLOC); in dpll_pin_alloc()
509 xa_init_flags(&pin->ref_sync_pins, XA_FLAGS_ALLOC); in dpll_pin_alloc()
510 ret = xa_alloc_cyclic(&dpll_pin_xa, &pin->id, pin, xa_limit_32b, in dpll_pin_alloc()
514 return pin; in dpll_pin_alloc()
516 xa_destroy(&pin->dpll_refs); in dpll_pin_alloc()
517 xa_destroy(&pin->parent_refs); in dpll_pin_alloc()
518 xa_destroy(&pin->ref_sync_pins); in dpll_pin_alloc()
519 dpll_pin_prop_free(&pin->prop); in dpll_pin_alloc()
521 kfree(pin); in dpll_pin_alloc()
528 rcu_assign_pointer(dev->dpll_pin, dpll_pin); in dpll_netdev_pin_assign()
546 * dpll_pin_get - find existing or create new dpll pin
550 * @prop: dpll pin properties
552 * Get existing object of a pin (unique for given arguments) or create new
558 * * ERR_PTR(X) - error
569 if (pos->clock_id == clock_id && in dpll_pin_get()
570 pos->pin_idx == pin_idx && in dpll_pin_get()
571 pos->module == module) { in dpll_pin_get()
573 refcount_inc(&ret->refcount); in dpll_pin_get()
586 * dpll_pin_put - decrease the refcount and free memory if possible
587 * @pin: pointer to a pin to be put
589 * Drop reference for a pin, if all references are gone, delete pin object.
593 void dpll_pin_put(struct dpll_pin *pin) in dpll_pin_put() argument
596 if (refcount_dec_and_test(&pin->refcount)) { in dpll_pin_put()
597 xa_erase(&dpll_pin_xa, pin->id); in dpll_pin_put()
598 xa_destroy(&pin->dpll_refs); in dpll_pin_put()
599 xa_destroy(&pin->parent_refs); in dpll_pin_put()
600 xa_destroy(&pin->ref_sync_pins); in dpll_pin_put()
601 dpll_pin_prop_free(&pin->prop); in dpll_pin_put()
602 kfree_rcu(pin, rcu); in dpll_pin_put()
609 __dpll_pin_register(struct dpll_device *dpll, struct dpll_pin *pin, in __dpll_pin_register() argument
614 ret = dpll_xa_ref_pin_add(&dpll->pin_refs, pin, ops, priv, cookie); in __dpll_pin_register()
617 ret = dpll_xa_ref_dpll_add(&pin->dpll_refs, dpll, ops, priv, cookie); in __dpll_pin_register()
620 xa_set_mark(&dpll_pin_xa, pin->id, DPLL_REGISTERED); in __dpll_pin_register()
621 dpll_pin_create_ntf(pin); in __dpll_pin_register()
626 dpll_xa_ref_pin_del(&dpll->pin_refs, pin, ops, priv, cookie); in __dpll_pin_register()
631 * dpll_pin_register - register the dpll pin in the subsystem
633 * @pin: pointer to a dpll pin
634 * @ops: ops for a dpll pin ops
640 * * negative - error value
643 dpll_pin_register(struct dpll_device *dpll, struct dpll_pin *pin, in dpll_pin_register() argument
649 WARN_ON(!ops->state_on_dpll_get) || in dpll_pin_register()
650 WARN_ON(!ops->direction_get)) in dpll_pin_register()
651 return -EINVAL; in dpll_pin_register()
654 if (WARN_ON(!(dpll->module == pin->module && in dpll_pin_register()
655 dpll->clock_id == pin->clock_id))) in dpll_pin_register()
656 ret = -EINVAL; in dpll_pin_register()
658 ret = __dpll_pin_register(dpll, pin, ops, priv, NULL); in dpll_pin_register()
667 struct dpll_pin *pin, *ref_sync_pin; in dpll_pin_ref_sync_pair_del() local
670 xa_for_each(&dpll_pin_xa, i, pin) { in dpll_pin_ref_sync_pair_del()
671 ref_sync_pin = xa_load(&pin->ref_sync_pins, ref_sync_pin_id); in dpll_pin_ref_sync_pair_del()
673 xa_erase(&pin->ref_sync_pins, ref_sync_pin_id); in dpll_pin_ref_sync_pair_del()
674 __dpll_pin_change_ntf(pin); in dpll_pin_ref_sync_pair_del()
680 __dpll_pin_unregister(struct dpll_device *dpll, struct dpll_pin *pin, in __dpll_pin_unregister() argument
683 ASSERT_DPLL_PIN_REGISTERED(pin); in __dpll_pin_unregister()
684 dpll_pin_ref_sync_pair_del(pin->id); in __dpll_pin_unregister()
685 dpll_xa_ref_pin_del(&dpll->pin_refs, pin, ops, priv, cookie); in __dpll_pin_unregister()
686 dpll_xa_ref_dpll_del(&pin->dpll_refs, dpll, ops, priv, cookie); in __dpll_pin_unregister()
687 if (xa_empty(&pin->dpll_refs)) in __dpll_pin_unregister()
688 xa_clear_mark(&dpll_pin_xa, pin->id, DPLL_REGISTERED); in __dpll_pin_unregister()
692 * dpll_pin_unregister - unregister dpll pin from dpll device
694 * @pin: pointer to a pin
695 * @ops: ops for a dpll pin
701 void dpll_pin_unregister(struct dpll_device *dpll, struct dpll_pin *pin, in dpll_pin_unregister() argument
704 if (WARN_ON(xa_empty(&dpll->pin_refs))) in dpll_pin_unregister()
706 if (WARN_ON(!xa_empty(&pin->parent_refs))) in dpll_pin_unregister()
710 dpll_pin_delete_ntf(pin); in dpll_pin_unregister()
711 __dpll_pin_unregister(dpll, pin, ops, priv, NULL); in dpll_pin_unregister()
717 * dpll_pin_on_pin_register - register a pin with a parent pin
718 * @parent: pointer to a parent pin
719 * @pin: pointer to a pin
720 * @ops: ops for a dpll pin
723 * Register a pin with a parent pin, create references between them and
724 * between newly registered pin and dplls connected with a parent pin.
729 * * negative - error value
731 int dpll_pin_on_pin_register(struct dpll_pin *parent, struct dpll_pin *pin, in dpll_pin_on_pin_register() argument
738 if (WARN_ON(parent->prop.type != DPLL_PIN_TYPE_MUX)) in dpll_pin_on_pin_register()
739 return -EINVAL; in dpll_pin_on_pin_register()
742 WARN_ON(!ops->state_on_pin_get) || in dpll_pin_on_pin_register()
743 WARN_ON(!ops->direction_get)) in dpll_pin_on_pin_register()
744 return -EINVAL; in dpll_pin_on_pin_register()
747 ret = dpll_xa_ref_pin_add(&pin->parent_refs, parent, ops, priv, pin); in dpll_pin_on_pin_register()
750 refcount_inc(&pin->refcount); in dpll_pin_on_pin_register()
751 xa_for_each(&parent->dpll_refs, i, ref) { in dpll_pin_on_pin_register()
752 ret = __dpll_pin_register(ref->dpll, pin, ops, priv, parent); in dpll_pin_on_pin_register()
757 dpll_pin_create_ntf(pin); in dpll_pin_on_pin_register()
764 xa_for_each(&parent->dpll_refs, i, ref) in dpll_pin_on_pin_register()
766 __dpll_pin_unregister(ref->dpll, pin, ops, priv, in dpll_pin_on_pin_register()
768 dpll_pin_delete_ntf(pin); in dpll_pin_on_pin_register()
770 refcount_dec(&pin->refcount); in dpll_pin_on_pin_register()
771 dpll_xa_ref_pin_del(&pin->parent_refs, parent, ops, priv, pin); in dpll_pin_on_pin_register()
779 * dpll_pin_on_pin_unregister - unregister dpll pin from a parent pin
780 * @parent: pointer to a parent pin
781 * @pin: pointer to a pin
782 * @ops: ops for a dpll pin
788 void dpll_pin_on_pin_unregister(struct dpll_pin *parent, struct dpll_pin *pin, in dpll_pin_on_pin_unregister() argument
795 dpll_pin_delete_ntf(pin); in dpll_pin_on_pin_unregister()
796 dpll_xa_ref_pin_del(&pin->parent_refs, parent, ops, priv, pin); in dpll_pin_on_pin_unregister()
797 refcount_dec(&pin->refcount); in dpll_pin_on_pin_unregister()
798 xa_for_each(&pin->dpll_refs, i, ref) in dpll_pin_on_pin_unregister()
799 __dpll_pin_unregister(ref->dpll, pin, ops, priv, parent); in dpll_pin_on_pin_unregister()
805 * dpll_pin_ref_sync_pair_add - create a reference sync signal pin pair
806 * @pin: pin which produces the base frequency
807 * @ref_sync_pin: pin which produces the sync signal
809 * Once pins are paired, the user-space configuration of reference sync pair
814 * * negative - error value
816 int dpll_pin_ref_sync_pair_add(struct dpll_pin *pin, in dpll_pin_ref_sync_pair_add() argument
822 ret = xa_insert(&pin->ref_sync_pins, ref_sync_pin->id, in dpll_pin_ref_sync_pair_add()
824 __dpll_pin_change_ntf(pin); in dpll_pin_ref_sync_pair_add()
836 reg = list_first_entry_or_null((struct list_head *)&dpll->registration_list, in dpll_device_registration_first()
847 return reg->priv; in dpll_priv()
855 return reg->ops; in dpll_device_ops()
863 reg = list_first_entry_or_null(&ref->registration_list, in dpll_pin_registration_first()
870 struct dpll_pin *pin) in dpll_pin_on_dpll_priv() argument
875 ref = xa_load(&dpll->pin_refs, pin->pin_idx); in dpll_pin_on_dpll_priv()
879 return reg->priv; in dpll_pin_on_dpll_priv()
883 struct dpll_pin *pin) in dpll_pin_on_pin_priv() argument
888 ref = xa_load(&pin->parent_refs, parent->pin_idx); in dpll_pin_on_pin_priv()
892 return reg->priv; in dpll_pin_on_pin_priv()
900 return reg->ops; in dpll_pin_ops()