Lines Matching +full:device +full:- +full:specific

1 // SPDX-License-Identifier: GPL-2.0
5 * Copyright (C) 2010 Texas Instruments Incorporated - http://www.ti.com
7 * Contact: Ohad Ben-Cohen <ohad@wizery.com>
19 #include <linux/radix-tree.h>
36 * and provides easy-to-use API which makes the hwspinlock core code simple
54 * as the radix-tree API requires that users provide all synchronisation.
55 * A mutex is needed because we're using non-atomic radix tree allocations.
61 * __hwspin_trylock() - attempt to lock a specific hwspinlock
72 * user need some time-consuming or sleepable operations under the hardware
87 * Returns 0 if we successfully locked the hwspinlock or -EBUSY if
96 return -EINVAL; in __hwspin_trylock()
105 * 2. Make the hwspinlock SMP-safe (so we can take it from in __hwspin_trylock()
113 ret = spin_trylock_irqsave(&hwlock->lock, *flags); in __hwspin_trylock()
116 ret = spin_trylock_irq(&hwlock->lock); in __hwspin_trylock()
123 ret = spin_trylock(&hwlock->lock); in __hwspin_trylock()
129 return -EBUSY; in __hwspin_trylock()
131 /* try to take the hwspinlock device */ in __hwspin_trylock()
132 ret = hwlock->bank->ops->trylock(hwlock); in __hwspin_trylock()
138 spin_unlock_irqrestore(&hwlock->lock, *flags); in __hwspin_trylock()
141 spin_unlock_irq(&hwlock->lock); in __hwspin_trylock()
148 spin_unlock(&hwlock->lock); in __hwspin_trylock()
152 return -EBUSY; in __hwspin_trylock()
172 * __hwspin_lock_timeout() - lock an hwspinlock with timeout limit
185 * user need some time-consuming or sleepable operations under the hardware
189 * is handled with busy-waiting delays, hence shall not exceed few msecs.
203 * error code otherwise (most notably -ETIMEDOUT if the @hwlock is still
217 if (ret != -EBUSY) in __hwspin_lock_timeout()
228 return -ETIMEDOUT; in __hwspin_lock_timeout()
231 return -ETIMEDOUT; in __hwspin_lock_timeout()
235 * Allow platform-specific relax handlers to prevent in __hwspin_lock_timeout()
238 if (hwlock->bank->ops->relax) in __hwspin_lock_timeout()
239 hwlock->bank->ops->relax(hwlock); in __hwspin_lock_timeout()
247 * __hwspin_unlock() - unlock a specific hwspinlock
248 * @hwlock: a previously-acquired hwspinlock which we want to unlock
252 * This function will unlock a specific hwspinlock, enable preemption and
284 hwlock->bank->ops->unlock(hwlock); in __hwspin_unlock()
289 spin_unlock_irqrestore(&hwlock->lock, *flags); in __hwspin_unlock()
292 spin_unlock_irq(&hwlock->lock); in __hwspin_unlock()
299 spin_unlock(&hwlock->lock); in __hwspin_unlock()
306 * hwspin_lock_bust() - bust a specific hwspinlock
307 * @hwlock: a previously-acquired hwspinlock which we want to bust
315 * Returns: 0 on success, or -EINVAL if the hwspinlock does not exist, or
316 * the bust operation fails, and -EOPNOTSUPP if the bust operation is not
322 return -EINVAL; in hwspin_lock_bust()
324 if (!hwlock->bank->ops->bust) { in hwspin_lock_bust()
326 return -EOPNOTSUPP; in hwspin_lock_bust()
329 return hwlock->bank->ops->bust(hwlock, id); in hwspin_lock_bust()
334 * of_hwspin_lock_simple_xlate - translate hwlock_spec to return a lock id
335 * @bank: the hwspinlock device bank
336 * @hwlock_spec: hwlock specifier as found in the device tree
342 * or -EINVAL on invalid specifier cell count.
347 if (WARN_ON(hwlock_spec->args_count != 1)) in of_hwspin_lock_simple_xlate()
348 return -EINVAL; in of_hwspin_lock_simple_xlate()
350 return hwlock_spec->args[0]; in of_hwspin_lock_simple_xlate()
354 * of_hwspin_lock_get_id() - get lock id for an OF phandle-based specific lock
355 * @np: device node from which to request the specific hwlock
359 * get the global lock id of a specific hwspinlock using the phandle of the
360 * hwspinlock device, so that it can be requested using the normal
363 * Returns the global lock id number on success, -EPROBE_DEFER if the hwspinlock
364 * device is not yet registered, -EINVAL on invalid args specifier value or an
376 ret = of_parse_phandle_with_args(np, "hwlocks", "#hwlock-cells", index, in of_hwspin_lock_get_id()
382 ret = -ENOENT; in of_hwspin_lock_get_id()
386 /* Find the hwspinlock device: we need its base_id */ in of_hwspin_lock_get_id()
387 ret = -EPROBE_DEFER; in of_hwspin_lock_get_id()
398 if (device_match_of_node(hwlock->bank->dev, args.np)) { in of_hwspin_lock_get_id()
408 if (id < 0 || id >= hwlock->bank->num_locks) { in of_hwspin_lock_get_id()
409 ret = -EINVAL; in of_hwspin_lock_get_id()
412 id += hwlock->bank->base_id; in of_hwspin_lock_get_id()
421 * of_hwspin_lock_get_id_byname() - get lock id for an specified hwlock name
422 * @np: device node from which to request the specific hwlock
426 * get the global lock id of a specific hwspinlock using the specified name of
427 * the hwspinlock device, so that it can be requested using the normal
430 * Returns the global lock id number on success, -EPROBE_DEFER if the hwspinlock
431 * device is not yet registered, -EINVAL on invalid args specifier value or an
439 return -EINVAL; in of_hwspin_lock_get_id_byname()
441 index = of_property_match_string(np, "hwlock-names", name); in of_hwspin_lock_get_id_byname()
458 if (ret == -EEXIST) in hwspin_lock_register_single()
466 /* self-sanity check which should never fail */ in hwspin_lock_register_single()
500 * hwspin_lock_register() - register a new hw spinlock device
501 * @bank: the hwspinlock device, which usually provides numerous hw locks
502 * @dev: the backing device
503 * @ops: hwspinlock handlers for this device
505 * @num_locks: number of hwspinlocks provided by this device
507 * This function should be called from the underlying platform-specific
508 * implementation, to register a new hwspinlock device instance.
514 int hwspin_lock_register(struct hwspinlock_device *bank, struct device *dev, in hwspin_lock_register()
520 if (!bank || !ops || !dev || !num_locks || !ops->trylock || in hwspin_lock_register()
521 !ops->unlock) { in hwspin_lock_register()
523 return -EINVAL; in hwspin_lock_register()
526 bank->dev = dev; in hwspin_lock_register()
527 bank->ops = ops; in hwspin_lock_register()
528 bank->base_id = base_id; in hwspin_lock_register()
529 bank->num_locks = num_locks; in hwspin_lock_register()
532 hwlock = &bank->lock[i]; in hwspin_lock_register()
534 spin_lock_init(&hwlock->lock); in hwspin_lock_register()
535 hwlock->bank = bank; in hwspin_lock_register()
545 while (--i >= 0) in hwspin_lock_register()
552 * hwspin_lock_unregister() - unregister an hw spinlock device
553 * @bank: the hwspinlock device, which usually provides numerous hw locks
555 * This function should be called from the underlying platform-specific
567 for (i = 0; i < bank->num_locks; i++) { in hwspin_lock_unregister()
568 hwlock = &bank->lock[i]; in hwspin_lock_unregister()
570 tmp = hwspin_lock_unregister_single(bank->base_id + i); in hwspin_lock_unregister()
572 return -EBUSY; in hwspin_lock_unregister()
574 /* self-sanity check that should never fail */ in hwspin_lock_unregister()
582 static void devm_hwspin_lock_unreg(struct device *dev, void *res) in devm_hwspin_lock_unreg()
587 static int devm_hwspin_lock_device_match(struct device *dev, void *res, in devm_hwspin_lock_device_match()
599 * devm_hwspin_lock_unregister() - unregister an hw spinlock device for
600 * a managed device
601 * @dev: the backing device
602 * @bank: the hwspinlock device, which usually provides numerous hw locks
604 * This function should be called from the underlying platform-specific
611 int devm_hwspin_lock_unregister(struct device *dev, in devm_hwspin_lock_unregister()
625 * devm_hwspin_lock_register() - register a new hw spinlock device for
626 * a managed device
627 * @dev: the backing device
628 * @bank: the hwspinlock device, which usually provides numerous hw locks
629 * @ops: hwspinlock handlers for this device
631 * @num_locks: number of hwspinlocks provided by this device
633 * This function should be called from the underlying platform-specific
634 * implementation, to register a new hwspinlock device instance.
640 int devm_hwspin_lock_register(struct device *dev, in devm_hwspin_lock_register()
650 return -ENOMEM; in devm_hwspin_lock_register()
665 * __hwspin_lock_request() - tag an hwspinlock as used and power it up
676 struct device *dev = hwlock->bank->dev; in __hwspin_lock_request()
681 if (!try_module_get(dev->driver->owner)) { in __hwspin_lock_request()
683 return -EINVAL; in __hwspin_lock_request()
688 if (ret < 0 && ret != -EACCES) { in __hwspin_lock_request()
689 dev_err(dev, "%s: can't power on device\n", __func__); in __hwspin_lock_request()
691 module_put(dev->driver->owner); in __hwspin_lock_request()
701 /* self-sanity check that should never fail */ in __hwspin_lock_request()
708 * hwspin_lock_get_id() - retrieve id number of a given hwspinlock
711 * Returns the id number of a given @hwlock, or -EINVAL if @hwlock is invalid.
717 return -EINVAL; in hwspin_lock_get_id()
725 * hwspin_lock_request() - request an hwspinlock
727 * This function should be called by users of the hwspinlock device,
768 * hwspin_lock_request_specific() - request for a specific hwspinlock
769 * @id: index of the specific hwspinlock that is requested
772 * in order to assign them a specific hwspinlock.
774 * reserve specific hwspinlock ids for predefined purposes.
817 * hwspin_lock_free() - free a specific hwspinlock
818 * @hwlock: the specific hwspinlock to free
830 struct device *dev; in hwspin_lock_free()
836 return -EINVAL; in hwspin_lock_free()
839 dev = hwlock->bank->dev; in hwspin_lock_free()
848 ret = -EINVAL; in hwspin_lock_free()
852 /* notify the underlying device that power is not needed */ in hwspin_lock_free()
862 module_put(dev->driver->owner); in hwspin_lock_free()
870 static int devm_hwspin_lock_match(struct device *dev, void *res, void *data) in devm_hwspin_lock_match()
880 static void devm_hwspin_lock_release(struct device *dev, void *res) in devm_hwspin_lock_release()
886 * devm_hwspin_lock_free() - free a specific hwspinlock for a managed device
887 * @dev: the device to free the specific hwspinlock
888 * @hwlock: the specific hwspinlock to free
898 int devm_hwspin_lock_free(struct device *dev, struct hwspinlock *hwlock) in devm_hwspin_lock_free()
911 * devm_hwspin_lock_request() - request an hwspinlock for a managed device
912 * @dev: the device to request an hwspinlock
914 * This function should be called by users of the hwspinlock device,
924 struct hwspinlock *devm_hwspin_lock_request(struct device *dev) in devm_hwspin_lock_request()
945 * devm_hwspin_lock_request_specific() - request for a specific hwspinlock for
946 * a managed device
947 * @dev: the device to request the specific hwspinlock
948 * @id: index of the specific hwspinlock that is requested
951 * in order to assign them a specific hwspinlock.
953 * reserve specific hwspinlock ids for predefined purposes.
959 struct hwspinlock *devm_hwspin_lock_request_specific(struct device *dev, in devm_hwspin_lock_request_specific()
981 MODULE_AUTHOR("Ohad Ben-Cohen <ohad@wizery.com>");