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
97 return -EINVAL;
106 * 2. Make the hwspinlock SMP-safe (so we can take it from
114 ret = spin_trylock_irqsave(&hwlock->lock, *flags);
117 ret = spin_trylock_irq(&hwlock->lock);
124 ret = spin_trylock(&hwlock->lock);
130 return -EBUSY;
132 /* try to take the hwspinlock device */
133 ret = hwlock->bank->ops->trylock(hwlock);
139 spin_unlock_irqrestore(&hwlock->lock, *flags);
142 spin_unlock_irq(&hwlock->lock);
149 spin_unlock(&hwlock->lock);
153 return -EBUSY;
173 * __hwspin_lock_timeout() - lock an hwspinlock with timeout limit
186 * user need some time-consuming or sleepable operations under the hardware
190 * is handled with busy-waiting delays, hence shall not exceed few msecs.
204 * error code otherwise (most notably -ETIMEDOUT if the @hwlock is still
220 if (ret != -EBUSY)
231 return -ETIMEDOUT;
234 return -ETIMEDOUT;
238 * Allow platform-specific relax handlers to prevent
241 if (hwlock->bank->ops->relax)
242 hwlock->bank->ops->relax(hwlock);
250 * __hwspin_unlock() - unlock a specific hwspinlock
251 * @hwlock: a previously-acquired hwspinlock which we want to unlock
255 * This function will unlock a specific hwspinlock, enable preemption and
287 hwlock->bank->ops->unlock(hwlock);
292 spin_unlock_irqrestore(&hwlock->lock, *flags);
295 spin_unlock_irq(&hwlock->lock);
302 spin_unlock(&hwlock->lock);
309 * hwspin_lock_bust() - bust a specific hwspinlock
310 * @hwlock: a previously-acquired hwspinlock which we want to bust
318 * Returns: 0 on success, or -EINVAL if the hwspinlock does not exist, or
319 * the bust operation fails, and -EOPNOTSUPP if the bust operation is not
325 return -EINVAL;
327 if (!hwlock->bank->ops->bust) {
329 return -EOPNOTSUPP;
332 return hwlock->bank->ops->bust(hwlock, id);
337 * of_hwspin_lock_simple_xlate - translate hwlock_spec to return a lock id
338 * @hwlock_spec: hwlock specifier as found in the device tree
344 * or -EINVAL on invalid specifier cell count.
349 if (WARN_ON(hwlock_spec->args_count != 1))
350 return -EINVAL;
352 return hwlock_spec->args[0];
356 * of_hwspin_lock_get_id() - get lock id for an OF phandle-based specific lock
357 * @np: device node from which to request the specific hwlock
361 * get the global lock id of a specific hwspinlock using the phandle of the
362 * hwspinlock device, so that it can be requested using the normal
365 * Returns: the global lock id number on success, -EPROBE_DEFER if the
366 * hwspinlock device is not yet registered, -EINVAL on invalid args
379 ret = of_parse_phandle_with_args(np, "hwlocks", "#hwlock-cells", index,
385 ret = -ENOENT;
389 /* Find the hwspinlock device: we need its base_id */
390 ret = -EPROBE_DEFER;
401 if (device_match_of_node(hwlock->bank->dev, args.np)) {
411 if (id < 0 || id >= hwlock->bank->num_locks) {
412 ret = -EINVAL;
415 id += hwlock->bank->base_id;
424 * of_hwspin_lock_get_id_byname() - get lock id for an specified hwlock name
425 * @np: device node from which to request the specific hwlock
429 * get the global lock id of a specific hwspinlock using the specified name of
430 * the hwspinlock device, so that it can be requested using the normal
433 * Returns: the global lock id number on success, -EPROBE_DEFER if the
434 * hwspinlock device is not yet registered, -EINVAL on invalid args
443 return -EINVAL;
445 index = of_property_match_string(np, "hwlock-names", name);
462 if (ret == -EEXIST)
470 /* self-sanity check which should never fail */
504 * hwspin_lock_register() - register a new hw spinlock device
505 * @bank: the hwspinlock device, which usually provides numerous hw locks
506 * @dev: the backing device
507 * @ops: hwspinlock handlers for this device
509 * @num_locks: number of hwspinlocks provided by this device
511 * This function should be called from the underlying platform-specific
512 * implementation, to register a new hwspinlock device instance.
518 int hwspin_lock_register(struct hwspinlock_device *bank, struct device *dev,
524 if (!bank || !ops || !dev || !num_locks || !ops->trylock ||
525 !ops->unlock) {
527 return -EINVAL;
530 bank->dev = dev;
531 bank->ops = ops;
532 bank->base_id = base_id;
533 bank->num_locks = num_locks;
536 hwlock = &bank->lock[i];
538 spin_lock_init(&hwlock->lock);
539 hwlock->bank = bank;
549 while (--i >= 0)
556 * hwspin_lock_unregister() - unregister an hw spinlock device
557 * @bank: the hwspinlock device, which usually provides numerous hw locks
559 * This function should be called from the underlying platform-specific
571 for (i = 0; i < bank->num_locks; i++) {
572 hwlock = &bank->lock[i];
574 tmp = hwspin_lock_unregister_single(bank->base_id + i);
576 return -EBUSY;
578 /* self-sanity check that should never fail */
586 static void devm_hwspin_lock_unreg(struct device *dev, void *res)
591 static int devm_hwspin_lock_device_match(struct device *dev, void *res,
603 * devm_hwspin_lock_unregister() - unregister an hw spinlock device for
604 * a managed device
605 * @dev: the backing device
606 * @bank: the hwspinlock device, which usually provides numerous hw locks
608 * This function should be called from the underlying platform-specific
615 int devm_hwspin_lock_unregister(struct device *dev,
629 * devm_hwspin_lock_register() - register a new hw spinlock device for
630 * a managed device
631 * @dev: the backing device
632 * @bank: the hwspinlock device, which usually provides numerous hw locks
633 * @ops: hwspinlock handlers for this device
635 * @num_locks: number of hwspinlocks provided by this device
637 * This function should be called from the underlying platform-specific
638 * implementation, to register a new hwspinlock device instance.
644 int devm_hwspin_lock_register(struct device *dev,
654 return -ENOMEM;
669 * __hwspin_lock_request() - tag an hwspinlock as used and power it up
681 struct device *dev = hwlock->bank->dev;
686 if (!try_module_get(dev->driver->owner)) {
688 return -EINVAL;
693 if (ret < 0 && ret != -EACCES) {
694 dev_err(dev, "%s: can't power on device\n", __func__);
696 module_put(dev->driver->owner);
706 /* self-sanity check that should never fail */
713 * hwspin_lock_request_specific() - request for a specific hwspinlock
714 * @id: index of the specific hwspinlock that is requested
717 * in order to assign them a specific hwspinlock.
719 * reserve specific hwspinlock ids for predefined purposes.
762 * hwspin_lock_free() - free a specific hwspinlock
763 * @hwlock: the specific hwspinlock to free
775 struct device *dev;
781 return -EINVAL;
784 dev = hwlock->bank->dev;
793 ret = -EINVAL;
797 /* notify the underlying device that power is not needed */
807 module_put(dev->driver->owner);
815 static int devm_hwspin_lock_match(struct device *dev, void *res, void *data)
825 static void devm_hwspin_lock_release(struct device *dev, void *res)
831 * devm_hwspin_lock_free() - free a specific hwspinlock for a managed device
832 * @dev: the device to free the specific hwspinlock
833 * @hwlock: the specific hwspinlock to free
843 int devm_hwspin_lock_free(struct device *dev, struct hwspinlock *hwlock)
856 * devm_hwspin_lock_request_specific() - request for a specific hwspinlock for
857 * a managed device
858 * @dev: the device to request the specific hwspinlock
859 * @id: index of the specific hwspinlock that is requested
862 * in order to assign them a specific hwspinlock.
864 * reserve specific hwspinlock ids for predefined purposes.
870 struct hwspinlock *devm_hwspin_lock_request_specific(struct device *dev,
892 MODULE_AUTHOR("Ohad Ben-Cohen <ohad@wizery.com>");