cvmx-fpa1.h 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196
  1. /* SPDX-License-Identifier: GPL-2.0 */
  2. /*
  3. * Copyright (C) 2020 Marvell International Ltd.
  4. *
  5. * Interface to the hardware Free Pool Allocator on Octeon chips.
  6. * These are the legacy models, i.e. prior to CN78XX/CN76XX.
  7. */
  8. #ifndef __CVMX_FPA1_HW_H__
  9. #define __CVMX_FPA1_HW_H__
  10. #include "cvmx-scratch.h"
  11. #include "cvmx-fpa-defs.h"
  12. #include "cvmx-fpa3.h"
  13. /* Legacy pool range is 0..7 and 8 on CN68XX */
  14. typedef int cvmx_fpa1_pool_t;
  15. #define CVMX_FPA1_NUM_POOLS 8
  16. #define CVMX_FPA1_INVALID_POOL ((cvmx_fpa1_pool_t)-1)
  17. #define CVMX_FPA1_NAME_SIZE 16
  18. /**
  19. * Structure describing the data format used for stores to the FPA.
  20. */
  21. typedef union {
  22. u64 u64;
  23. struct {
  24. u64 scraddr : 8;
  25. u64 len : 8;
  26. u64 did : 8;
  27. u64 addr : 40;
  28. } s;
  29. } cvmx_fpa1_iobdma_data_t;
  30. /*
  31. * Allocate or reserve the specified fpa pool.
  32. *
  33. * @param pool FPA pool to allocate/reserve. If -1 it
  34. * finds an empty pool to allocate.
  35. * Return: Alloctaed pool number or CVMX_FPA1_POOL_INVALID
  36. * if fails to allocate the pool
  37. */
  38. cvmx_fpa1_pool_t cvmx_fpa1_reserve_pool(cvmx_fpa1_pool_t pool);
  39. /**
  40. * Free the specified fpa pool.
  41. * @param pool Pool to free
  42. * Return: 0 for success -1 failure
  43. */
  44. int cvmx_fpa1_release_pool(cvmx_fpa1_pool_t pool);
  45. static inline void cvmx_fpa1_free(void *ptr, cvmx_fpa1_pool_t pool, u64 num_cache_lines)
  46. {
  47. cvmx_addr_t newptr;
  48. newptr.u64 = cvmx_ptr_to_phys(ptr);
  49. newptr.sfilldidspace.didspace = CVMX_ADDR_DIDSPACE(CVMX_FULL_DID(CVMX_OCT_DID_FPA, pool));
  50. /* Make sure that any previous writes to memory go out before we free
  51. * this buffer. This also serves as a barrier to prevent GCC from
  52. * reordering operations to after the free.
  53. */
  54. CVMX_SYNCWS;
  55. /* value written is number of cache lines not written back */
  56. cvmx_write_io(newptr.u64, num_cache_lines);
  57. }
  58. static inline void cvmx_fpa1_free_nosync(void *ptr, cvmx_fpa1_pool_t pool,
  59. unsigned int num_cache_lines)
  60. {
  61. cvmx_addr_t newptr;
  62. newptr.u64 = cvmx_ptr_to_phys(ptr);
  63. newptr.sfilldidspace.didspace = CVMX_ADDR_DIDSPACE(CVMX_FULL_DID(CVMX_OCT_DID_FPA, pool));
  64. /* Prevent GCC from reordering around free */
  65. asm volatile("" : : : "memory");
  66. /* value written is number of cache lines not written back */
  67. cvmx_write_io(newptr.u64, num_cache_lines);
  68. }
  69. /**
  70. * Enable the FPA for use. Must be performed after any CSR
  71. * configuration but before any other FPA functions.
  72. */
  73. static inline void cvmx_fpa1_enable(void)
  74. {
  75. cvmx_fpa_ctl_status_t status;
  76. status.u64 = csr_rd(CVMX_FPA_CTL_STATUS);
  77. if (status.s.enb) {
  78. /*
  79. * CN68XXP1 should not reset the FPA (doing so may break
  80. * the SSO, so we may end up enabling it more than once.
  81. * Just return and don't spew messages.
  82. */
  83. return;
  84. }
  85. status.u64 = 0;
  86. status.s.enb = 1;
  87. csr_wr(CVMX_FPA_CTL_STATUS, status.u64);
  88. }
  89. /**
  90. * Reset FPA to disable. Make sure buffers from all FPA pools are freed
  91. * before disabling FPA.
  92. */
  93. static inline void cvmx_fpa1_disable(void)
  94. {
  95. cvmx_fpa_ctl_status_t status;
  96. if (OCTEON_IS_MODEL(OCTEON_CN68XX_PASS1))
  97. return;
  98. status.u64 = csr_rd(CVMX_FPA_CTL_STATUS);
  99. status.s.reset = 1;
  100. csr_wr(CVMX_FPA_CTL_STATUS, status.u64);
  101. }
  102. static inline void *cvmx_fpa1_alloc(cvmx_fpa1_pool_t pool)
  103. {
  104. u64 address;
  105. for (;;) {
  106. address = csr_rd(CVMX_ADDR_DID(CVMX_FULL_DID(CVMX_OCT_DID_FPA, pool)));
  107. if (cvmx_likely(address)) {
  108. return cvmx_phys_to_ptr(address);
  109. } else {
  110. if (csr_rd(CVMX_FPA_QUEX_AVAILABLE(pool)) > 0)
  111. udelay(50);
  112. else
  113. return NULL;
  114. }
  115. }
  116. }
  117. /**
  118. * Asynchronously get a new block from the FPA
  119. * @INTERNAL
  120. *
  121. * The result of cvmx_fpa_async_alloc() may be retrieved using
  122. * cvmx_fpa_async_alloc_finish().
  123. *
  124. * @param scr_addr Local scratch address to put response in. This is a byte
  125. * address but must be 8 byte aligned.
  126. * @param pool Pool to get the block from
  127. */
  128. static inline void cvmx_fpa1_async_alloc(u64 scr_addr, cvmx_fpa1_pool_t pool)
  129. {
  130. cvmx_fpa1_iobdma_data_t data;
  131. /* Hardware only uses 64 bit aligned locations, so convert from byte
  132. * address to 64-bit index
  133. */
  134. data.u64 = 0ull;
  135. data.s.scraddr = scr_addr >> 3;
  136. data.s.len = 1;
  137. data.s.did = CVMX_FULL_DID(CVMX_OCT_DID_FPA, pool);
  138. data.s.addr = 0;
  139. cvmx_scratch_write64(scr_addr, 0ull);
  140. CVMX_SYNCW;
  141. cvmx_send_single(data.u64);
  142. }
  143. /**
  144. * Retrieve the result of cvmx_fpa_async_alloc
  145. * @INTERNAL
  146. *
  147. * @param scr_addr The Local scratch address. Must be the same value
  148. * passed to cvmx_fpa_async_alloc().
  149. *
  150. * @param pool Pool the block came from. Must be the same value
  151. * passed to cvmx_fpa_async_alloc.
  152. *
  153. * Return: Pointer to the block or NULL on failure
  154. */
  155. static inline void *cvmx_fpa1_async_alloc_finish(u64 scr_addr, cvmx_fpa1_pool_t pool)
  156. {
  157. u64 address;
  158. CVMX_SYNCIOBDMA;
  159. address = cvmx_scratch_read64(scr_addr);
  160. if (cvmx_likely(address))
  161. return cvmx_phys_to_ptr(address);
  162. else
  163. return cvmx_fpa1_alloc(pool);
  164. }
  165. static inline u64 cvmx_fpa1_get_available(cvmx_fpa1_pool_t pool)
  166. {
  167. return csr_rd(CVMX_FPA_QUEX_AVAILABLE(pool));
  168. }
  169. #endif /* __CVMX_FPA1_HW_H__ */