hwspinlock.h 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180
  1. /*
  2. * Copyright (c) 2006-2023, RT-Thread Development Team
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. *
  6. * Change Logs:
  7. * Date Author Notes
  8. * 2023-09-23 GuEe-GUI first version
  9. */
  10. #ifndef __HWSPINLOCK_H__
  11. #define __HWSPINLOCK_H__
  12. #include <rtdef.h>
  13. struct rt_hwspinlock;
  14. struct rt_hwspinlock_ops;
  15. struct rt_hwspinlock_bank;
  16. /**
  17. * @brief Register a hardware spinlock bank
  18. *
  19. * A bank represents a contiguous set of hardware spinlocks provided by
  20. * a hardware module. This API installs the bank into the system-wide list
  21. * so that each individual lock can be retrieved and used by clients.
  22. *
  23. * @param bank Pointer to the hardware spinlock bank
  24. * @return RT_EOK on success, otherwise an error code
  25. */
  26. rt_err_t rt_hwspinlock_bank_register(struct rt_hwspinlock_bank *bank);
  27. /**
  28. * @brief Unregister a hardware spinlock bank
  29. *
  30. * Removes the bank from the global registry. All locks under the bank
  31. * become unavailable. Caller must ensure no active users remain.
  32. *
  33. * @param bank Pointer to the hardware spinlock bank
  34. * @return RT_EOK on success, otherwise an error code
  35. */
  36. rt_err_t rt_hwspinlock_bank_unregister(struct rt_hwspinlock_bank *bank);
  37. /**
  38. * @brief Try to acquire a hardware spinlock (raw interface)
  39. *
  40. * The raw interface allows hardware drivers to retrieve the IRQ level
  41. * before acquiring the lock, enabling IRQ-safe usage scenarios.
  42. *
  43. * @param hwlock Pointer to the hardware spinlock
  44. * @param out_irq_level If non-NULL, returns saved IRQ level
  45. *
  46. * @return RT_EOK if lock is acquired, -RT_EBUSY if lock is held by others
  47. */
  48. rt_err_t rt_hwspin_trylock_raw(struct rt_hwspinlock *hwlock,
  49. rt_ubase_t *out_irq_level);
  50. /**
  51. * @brief Acquire a hardware spinlock with timeout (raw interface)
  52. *
  53. * Spins or relaxes according to the hardware implementation until the
  54. * lock becomes available or timeout expires. IRQ level handling is optional.
  55. *
  56. * @param hwlock Pointer to the hardware spinlock
  57. * @param timeout_ms Timeout in milliseconds
  58. * @param out_irq_level If non-NULL, returns saved IRQ level
  59. *
  60. * @return RT_EOK on success, -RT_ETIMEOUT if timed out
  61. */
  62. rt_err_t rt_hwspin_lock_timeout_raw(struct rt_hwspinlock *hwlock,
  63. rt_uint32_t timeout_ms, rt_ubase_t *out_irq_level);
  64. /**
  65. * @brief Release a hardware spinlock (raw interface)
  66. *
  67. * Restores IRQ state if @p out_irq_level is provided.
  68. *
  69. * @param hwlock Pointer to the hardware spinlock
  70. * @param out_irq_level IRQ level saved during lock operation
  71. */
  72. void rt_hwspin_unlock_raw(struct rt_hwspinlock *hwlock,
  73. rt_ubase_t *out_irq_level);
  74. /**
  75. * @brief Try to acquire a hardware spinlock (no IRQ management)
  76. */
  77. rt_inline rt_err_t rt_hwspin_trylock(struct rt_hwspinlock *hwlock)
  78. {
  79. return rt_hwspin_trylock_raw(hwlock, RT_NULL);
  80. }
  81. /**
  82. * @brief Try to acquire a hardware spinlock with IRQ saving
  83. */
  84. rt_inline rt_err_t rt_hwspin_trylock_irqsave(struct rt_hwspinlock *hwlock,
  85. rt_ubase_t *out_irq_level)
  86. {
  87. return rt_hwspin_trylock_raw(hwlock, out_irq_level);
  88. }
  89. /**
  90. * @brief Acquire a hardware spinlock with timeout (no IRQ management)
  91. */
  92. rt_inline rt_err_t rt_hwspin_lock_timeout(struct rt_hwspinlock *hwlock,
  93. rt_uint32_t timeout_ms)
  94. {
  95. return rt_hwspin_lock_timeout_raw(hwlock, timeout_ms, RT_NULL);
  96. }
  97. /**
  98. * @brief Acquire a hardware spinlock with timeout and IRQ saving
  99. */
  100. rt_inline rt_err_t rt_hwspin_lock_timeout_irqsave(struct rt_hwspinlock *hwlock,
  101. rt_uint32_t timeout_ms, rt_ubase_t *out_level)
  102. {
  103. return rt_hwspin_lock_timeout_raw(hwlock, timeout_ms, out_level);
  104. }
  105. /**
  106. * @brief Release a hardware spinlock (no IRQ management)
  107. */
  108. rt_inline void rt_hwspin_unlock(struct rt_hwspinlock *hwlock)
  109. {
  110. rt_hwspin_unlock_raw(hwlock, RT_NULL);
  111. }
  112. /**
  113. * @brief Release a hardware spinlock and restore IRQ level
  114. */
  115. rt_inline void rt_hwspin_unlock_irqsave(struct rt_hwspinlock *hwlock,
  116. rt_ubase_t *out_level)
  117. {
  118. rt_hwspin_unlock_raw(hwlock, out_level);
  119. }
  120. /**
  121. * @brief Acquire a free hardware spinlock from any registered bank
  122. *
  123. * The returned lock must later be released via rt_hwspinlock_put().
  124. *
  125. * @return Pointer to a hardware spinlock, or NULL if none available
  126. */
  127. struct rt_hwspinlock *rt_hwspinlock_get(void);
  128. /**
  129. * @brief Get hardware spinlock by index from a specific device
  130. *
  131. * @param dev Device providing hardware spinlocks
  132. * @param index Hardware spinlock index within device/bank
  133. *
  134. * @return Pointer to the hardware spinlock, or NULL if invalid index
  135. */
  136. struct rt_hwspinlock *rt_hwspinlock_get_by_index(struct rt_device *dev, int index);
  137. /**
  138. * @brief Get hardware spinlock by name from a specific device
  139. *
  140. * Names are assigned by device drivers and mapped to lock indices.
  141. *
  142. * @return Pointer to the hardware spinlock, or NULL if name not found
  143. */
  144. struct rt_hwspinlock *rt_hwspinlock_get_by_name(struct rt_device *dev, const char *name);
  145. /**
  146. * @brief Release hardware spinlock reference obtained from get()
  147. *
  148. * Does not unlock the spinlock; only decreases usage count.
  149. */
  150. void rt_hwspinlock_put(struct rt_hwspinlock *hwlock);
  151. /**
  152. * @brief Get hardware spinlock by index from device tree node
  153. */
  154. struct rt_hwspinlock *rt_ofw_get_hwspinlock_by_index(struct rt_ofw_node *np, int index);
  155. /**
  156. * @brief Get hardware spinlock by name from device tree node
  157. */
  158. struct rt_hwspinlock *rt_ofw_get_hwspinlock_by_name(struct rt_ofw_node *np, const char *name);
  159. #endif /* __HWSPINLOCK_H__ */