030-hwspinlock-core-add-device-tree-support.patch 5.5 KB

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