ipq806x: fix uninitialized variable usage in cpufreq-krait
[openwrt.git] / target / linux / ipq806x / patches-4.1 / 030-hwspinlock-core-add-device-tree-support.patch
1 From fb7737e949e31d8a71acee6bbb670f32dbd2a2c0 Mon Sep 17 00:00:00 2001
2 From: Suman Anna <s-anna@ti.com>
3 Date: Wed, 4 Mar 2015 20:01:14 -0600
4 Subject: [PATCH] hwspinlock/core: add device tree support
5
6 This patch adds a new OF-friendly API of_hwspin_lock_get_id()
7 for hwspinlock clients to use/request locks from a hwspinlock
8 device instantiated through a device-tree blob. This new API
9 can be used by hwspinlock clients to get the id for a specific
10 lock using the phandle + args specifier, so that it can be
11 requested using the available hwspin_lock_request_specific()
12 API.
13
14 Signed-off-by: Suman Anna <s-anna@ti.com>
15 Reviewed-by: Bjorn Andersson <bjorn.andersson@sonymobile.com>
16 [small comment clarification]
17 Signed-off-by: Ohad Ben-Cohen <ohad@wizery.com>
18 ---
19  Documentation/hwspinlock.txt         | 10 +++++
20  drivers/hwspinlock/hwspinlock_core.c | 79 ++++++++++++++++++++++++++++++++++++
21  include/linux/hwspinlock.h           |  7 ++++
22  3 files changed, 96 insertions(+)
23
24 --- a/Documentation/hwspinlock.txt
25 +++ b/Documentation/hwspinlock.txt
26 @@ -48,6 +48,16 @@ independent, drivers.
27       ids for predefined purposes.
28       Should be called from a process context (might sleep).
29  
30 +  int of_hwspin_lock_get_id(struct device_node *np, int index);
31 +   - retrieve the global lock id for an OF phandle-based specific lock.
32 +     This function provides a means for DT users of a hwspinlock module
33 +     to get the global lock id of a specific hwspinlock, so that it can
34 +     be requested using the normal hwspin_lock_request_specific() API.
35 +     The function returns a lock id number on success, -EPROBE_DEFER if
36 +     the hwspinlock device is not yet registered with the core, or other
37 +     error values.
38 +     Should be called from a process context (might sleep).
39 +
40    int hwspin_lock_free(struct hwspinlock *hwlock);
41     - free a previously-assigned hwspinlock; returns 0 on success, or an
42       appropriate error code on failure (e.g. -EINVAL if the hwspinlock
43 --- a/drivers/hwspinlock/hwspinlock_core.c
44 +++ b/drivers/hwspinlock/hwspinlock_core.c
45 @@ -27,6 +27,7 @@
46  #include <linux/hwspinlock.h>
47  #include <linux/pm_runtime.h>
48  #include <linux/mutex.h>
49 +#include <linux/of.h>
50  
51  #include "hwspinlock_internal.h"
52  
53 @@ -257,6 +258,84 @@ void __hwspin_unlock(struct hwspinlock *
54  }
55  EXPORT_SYMBOL_GPL(__hwspin_unlock);
56  
57 +/**
58 + * of_hwspin_lock_simple_xlate - translate hwlock_spec to return a lock id
59 + * @bank: the hwspinlock device bank
60 + * @hwlock_spec: hwlock specifier as found in the device tree
61 + *
62 + * This is a simple translation function, suitable for hwspinlock platform
63 + * drivers that only has a lock specifier length of 1.
64 + *
65 + * Returns a relative index of the lock within a specified bank on success,
66 + * or -EINVAL on invalid specifier cell count.
67 + */
68 +static inline int
69 +of_hwspin_lock_simple_xlate(const struct of_phandle_args *hwlock_spec)
70 +{
71 +       if (WARN_ON(hwlock_spec->args_count != 1))
72 +               return -EINVAL;
73 +
74 +       return hwlock_spec->args[0];
75 +}
76 +
77 +/**
78 + * of_hwspin_lock_get_id() - get lock id for an OF phandle-based specific lock
79 + * @np: device node from which to request the specific hwlock
80 + * @index: index of the hwlock in the list of values
81 + *
82 + * This function provides a means for DT users of the hwspinlock module to
83 + * get the global lock id of a specific hwspinlock using the phandle of the
84 + * hwspinlock device, so that it can be requested using the normal
85 + * hwspin_lock_request_specific() API.
86 + *
87 + * Returns the global lock id number on success, -EPROBE_DEFER if the hwspinlock
88 + * device is not yet registered, -EINVAL on invalid args specifier value or an
89 + * appropriate error as returned from the OF parsing of the DT client node.
90 + */
91 +int of_hwspin_lock_get_id(struct device_node *np, int index)
92 +{
93 +       struct of_phandle_args args;
94 +       struct hwspinlock *hwlock;
95 +       struct radix_tree_iter iter;
96 +       void **slot;
97 +       int id;
98 +       int ret;
99 +
100 +       ret = of_parse_phandle_with_args(np, "hwlocks", "#hwlock-cells", index,
101 +                                        &args);
102 +       if (ret)
103 +               return ret;
104 +
105 +       /* Find the hwspinlock device: we need its base_id */
106 +       ret = -EPROBE_DEFER;
107 +       rcu_read_lock();
108 +       radix_tree_for_each_slot(slot, &hwspinlock_tree, &iter, 0) {
109 +               hwlock = radix_tree_deref_slot(slot);
110 +               if (unlikely(!hwlock))
111 +                       continue;
112 +
113 +               if (hwlock->bank->dev->of_node == args.np) {
114 +                       ret = 0;
115 +                       break;
116 +               }
117 +       }
118 +       rcu_read_unlock();
119 +       if (ret < 0)
120 +               goto out;
121 +
122 +       id = of_hwspin_lock_simple_xlate(&args);
123 +       if (id < 0 || id >= hwlock->bank->num_locks) {
124 +               ret = -EINVAL;
125 +               goto out;
126 +       }
127 +       id += hwlock->bank->base_id;
128 +
129 +out:
130 +       of_node_put(args.np);
131 +       return ret ? ret : id;
132 +}
133 +EXPORT_SYMBOL_GPL(of_hwspin_lock_get_id);
134 +
135  static int hwspin_lock_register_single(struct hwspinlock *hwlock, int id)
136  {
137         struct hwspinlock *tmp;
138 --- a/include/linux/hwspinlock.h
139 +++ b/include/linux/hwspinlock.h
140 @@ -26,6 +26,7 @@
141  #define HWLOCK_IRQ     0x02    /* Disable interrupts, don't save state */
142  
143  struct device;
144 +struct device_node;
145  struct hwspinlock;
146  struct hwspinlock_device;
147  struct hwspinlock_ops;
148 @@ -66,6 +67,7 @@ int hwspin_lock_unregister(struct hwspin
149  struct hwspinlock *hwspin_lock_request(void);
150  struct hwspinlock *hwspin_lock_request_specific(unsigned int id);
151  int hwspin_lock_free(struct hwspinlock *hwlock);
152 +int of_hwspin_lock_get_id(struct device_node *np, int index);
153  int hwspin_lock_get_id(struct hwspinlock *hwlock);
154  int __hwspin_lock_timeout(struct hwspinlock *, unsigned int, int,
155                                                         unsigned long *);
156 @@ -120,6 +122,11 @@ void __hwspin_unlock(struct hwspinlock *
157  {
158  }
159  
160 +static inline int of_hwspin_lock_get_id(struct device_node *np, int index)
161 +{
162 +       return 0;
163 +}
164 +
165  static inline int hwspin_lock_get_id(struct hwspinlock *hwlock)
166  {
167         return 0;