Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit fb7737e9 authored by Suman Anna's avatar Suman Anna Committed by Ohad Ben-Cohen
Browse files

hwspinlock/core: add device tree support



This patch adds a new OF-friendly API of_hwspin_lock_get_id()
for hwspinlock clients to use/request locks from a hwspinlock
device instantiated through a device-tree blob. This new API
can be used by hwspinlock clients to get the id for a specific
lock using the phandle + args specifier, so that it can be
requested using the available hwspin_lock_request_specific()
API.

Signed-off-by: default avatarSuman Anna <s-anna@ti.com>
Reviewed-by: default avatarBjorn Andersson <bjorn.andersson@sonymobile.com>
[small comment clarification]
Signed-off-by: default avatarOhad Ben-Cohen <ohad@wizery.com>
parent 0ce8cf2f
Loading
Loading
Loading
Loading
+10 −0
Original line number Diff line number Diff line
@@ -48,6 +48,16 @@ independent, drivers.
     ids for predefined purposes.
     Should be called from a process context (might sleep).

  int of_hwspin_lock_get_id(struct device_node *np, int index);
   - retrieve the global lock id for an OF phandle-based specific lock.
     This function provides a means for DT users of a hwspinlock module
     to get the global lock id of a specific hwspinlock, so that it can
     be requested using the normal hwspin_lock_request_specific() API.
     The function returns a lock id number on success, -EPROBE_DEFER if
     the hwspinlock device is not yet registered with the core, or other
     error values.
     Should be called from a process context (might sleep).

  int hwspin_lock_free(struct hwspinlock *hwlock);
   - free a previously-assigned hwspinlock; returns 0 on success, or an
     appropriate error code on failure (e.g. -EINVAL if the hwspinlock
+79 −0
Original line number Diff line number Diff line
@@ -27,6 +27,7 @@
#include <linux/hwspinlock.h>
#include <linux/pm_runtime.h>
#include <linux/mutex.h>
#include <linux/of.h>

#include "hwspinlock_internal.h"

@@ -257,6 +258,84 @@ void __hwspin_unlock(struct hwspinlock *hwlock, int mode, unsigned long *flags)
}
EXPORT_SYMBOL_GPL(__hwspin_unlock);

/**
 * of_hwspin_lock_simple_xlate - translate hwlock_spec to return a lock id
 * @bank: the hwspinlock device bank
 * @hwlock_spec: hwlock specifier as found in the device tree
 *
 * This is a simple translation function, suitable for hwspinlock platform
 * drivers that only has a lock specifier length of 1.
 *
 * Returns a relative index of the lock within a specified bank on success,
 * or -EINVAL on invalid specifier cell count.
 */
static inline int
of_hwspin_lock_simple_xlate(const struct of_phandle_args *hwlock_spec)
{
	if (WARN_ON(hwlock_spec->args_count != 1))
		return -EINVAL;

	return hwlock_spec->args[0];
}

/**
 * of_hwspin_lock_get_id() - get lock id for an OF phandle-based specific lock
 * @np: device node from which to request the specific hwlock
 * @index: index of the hwlock in the list of values
 *
 * This function provides a means for DT users of the hwspinlock module to
 * get the global lock id of a specific hwspinlock using the phandle of the
 * hwspinlock device, so that it can be requested using the normal
 * hwspin_lock_request_specific() API.
 *
 * Returns the global lock id number on success, -EPROBE_DEFER if the hwspinlock
 * device is not yet registered, -EINVAL on invalid args specifier value or an
 * appropriate error as returned from the OF parsing of the DT client node.
 */
int of_hwspin_lock_get_id(struct device_node *np, int index)
{
	struct of_phandle_args args;
	struct hwspinlock *hwlock;
	struct radix_tree_iter iter;
	void **slot;
	int id;
	int ret;

	ret = of_parse_phandle_with_args(np, "hwlocks", "#hwlock-cells", index,
					 &args);
	if (ret)
		return ret;

	/* Find the hwspinlock device: we need its base_id */
	ret = -EPROBE_DEFER;
	rcu_read_lock();
	radix_tree_for_each_slot(slot, &hwspinlock_tree, &iter, 0) {
		hwlock = radix_tree_deref_slot(slot);
		if (unlikely(!hwlock))
			continue;

		if (hwlock->bank->dev->of_node == args.np) {
			ret = 0;
			break;
		}
	}
	rcu_read_unlock();
	if (ret < 0)
		goto out;

	id = of_hwspin_lock_simple_xlate(&args);
	if (id < 0 || id >= hwlock->bank->num_locks) {
		ret = -EINVAL;
		goto out;
	}
	id += hwlock->bank->base_id;

out:
	of_node_put(args.np);
	return ret ? ret : id;
}
EXPORT_SYMBOL_GPL(of_hwspin_lock_get_id);

static int hwspin_lock_register_single(struct hwspinlock *hwlock, int id)
{
	struct hwspinlock *tmp;
+7 −0
Original line number Diff line number Diff line
@@ -26,6 +26,7 @@
#define HWLOCK_IRQ	0x02	/* Disable interrupts, don't save state */

struct device;
struct device_node;
struct hwspinlock;
struct hwspinlock_device;
struct hwspinlock_ops;
@@ -66,6 +67,7 @@ int hwspin_lock_unregister(struct hwspinlock_device *bank);
struct hwspinlock *hwspin_lock_request(void);
struct hwspinlock *hwspin_lock_request_specific(unsigned int id);
int hwspin_lock_free(struct hwspinlock *hwlock);
int of_hwspin_lock_get_id(struct device_node *np, int index);
int hwspin_lock_get_id(struct hwspinlock *hwlock);
int __hwspin_lock_timeout(struct hwspinlock *, unsigned int, int,
							unsigned long *);
@@ -120,6 +122,11 @@ void __hwspin_unlock(struct hwspinlock *hwlock, int mode, unsigned long *flags)
{
}

static inline int of_hwspin_lock_get_id(struct device_node *np, int index)
{
	return 0;
}

static inline int hwspin_lock_get_id(struct hwspinlock *hwlock)
{
	return 0;