aboutsummaryrefslogtreecommitdiffstats
path: root/target/linux/ipq806x/patches-4.1/030-hwspinlock-core-add-device-tree-support.patch
diff options
context:
space:
mode:
Diffstat (limited to 'target/linux/ipq806x/patches-4.1/030-hwspinlock-core-add-device-tree-support.patch')
-rw-r--r--target/linux/ipq806x/patches-4.1/030-hwspinlock-core-add-device-tree-support.patch167
1 files changed, 167 insertions, 0 deletions
diff --git a/target/linux/ipq806x/patches-4.1/030-hwspinlock-core-add-device-tree-support.patch b/target/linux/ipq806x/patches-4.1/030-hwspinlock-core-add-device-tree-support.patch
new file mode 100644
index 0000000..04f35b7
--- /dev/null
+++ b/target/linux/ipq806x/patches-4.1/030-hwspinlock-core-add-device-tree-support.patch
@@ -0,0 +1,167 @@
+From fb7737e949e31d8a71acee6bbb670f32dbd2a2c0 Mon Sep 17 00:00:00 2001
+From: Suman Anna <s-anna@ti.com>
+Date: Wed, 4 Mar 2015 20:01:14 -0600
+Subject: [PATCH] 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: Suman Anna <s-anna@ti.com>
+Reviewed-by: Bjorn Andersson <bjorn.andersson@sonymobile.com>
+[small comment clarification]
+Signed-off-by: Ohad Ben-Cohen <ohad@wizery.com>
+---
+ Documentation/hwspinlock.txt | 10 +++++
+ drivers/hwspinlock/hwspinlock_core.c | 79 ++++++++++++++++++++++++++++++++++++
+ include/linux/hwspinlock.h | 7 ++++
+ 3 files changed, 96 insertions(+)
+
+--- a/Documentation/hwspinlock.txt
++++ b/Documentation/hwspinlock.txt
+@@ -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
+--- a/drivers/hwspinlock/hwspinlock_core.c
++++ b/drivers/hwspinlock/hwspinlock_core.c
+@@ -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 *
+ }
+ 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;
+--- a/include/linux/hwspinlock.h
++++ b/include/linux/hwspinlock.h
+@@ -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 hwspin
+ 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 *
+ {
+ }
+
++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;