cam_io_util.c 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. /*
  3. * Copyright (c) 2011-2014, 2017-2018, The Linux Foundation.
  4. * All rights reserved.
  5. */
  6. #include <linux/delay.h>
  7. #include <linux/io.h>
  8. #include <linux/err.h>
  9. #include "cam_io_util.h"
  10. #include "cam_debug_util.h"
  11. int cam_io_w(uint32_t data, void __iomem *addr)
  12. {
  13. if (!addr)
  14. return -EINVAL;
  15. CAM_DBG(CAM_UTIL, "0x%pK %08x", addr, data);
  16. writel_relaxed_no_log(data, addr);
  17. return 0;
  18. }
  19. int cam_io_w_mb(uint32_t data, void __iomem *addr)
  20. {
  21. if (!addr)
  22. return -EINVAL;
  23. CAM_DBG(CAM_UTIL, "0x%pK %08x", addr, data);
  24. /* Ensure previous writes are done */
  25. wmb();
  26. writel_relaxed_no_log(data, addr);
  27. /* Ensure previous writes are done */
  28. wmb();
  29. return 0;
  30. }
  31. uint32_t cam_io_r(void __iomem *addr)
  32. {
  33. uint32_t data;
  34. if (!addr) {
  35. CAM_ERR(CAM_UTIL, "Invalid args");
  36. return 0;
  37. }
  38. data = readl_relaxed(addr);
  39. CAM_DBG(CAM_UTIL, "0x%pK %08x", addr, data);
  40. return data;
  41. }
  42. uint32_t cam_io_r_mb(void __iomem *addr)
  43. {
  44. uint32_t data;
  45. if (!addr) {
  46. CAM_ERR(CAM_UTIL, "Invalid args");
  47. return 0;
  48. }
  49. /* Ensure previous read is done */
  50. rmb();
  51. data = readl_relaxed(addr);
  52. CAM_DBG(CAM_UTIL, "0x%pK %08x", addr, data);
  53. /* Ensure previous read is done */
  54. rmb();
  55. return data;
  56. }
  57. int cam_io_memcpy(void __iomem *dest_addr,
  58. void __iomem *src_addr, uint32_t len)
  59. {
  60. int i;
  61. uint32_t *d = (uint32_t *) dest_addr;
  62. uint32_t *s = (uint32_t *) src_addr;
  63. if (!dest_addr || !src_addr)
  64. return -EINVAL;
  65. CAM_DBG(CAM_UTIL, "%pK %pK %d", dest_addr, src_addr, len);
  66. for (i = 0; i < len/4; i++) {
  67. CAM_DBG(CAM_UTIL, "0x%pK %08x", d, *s);
  68. writel_relaxed(*s++, d++);
  69. }
  70. return 0;
  71. }
  72. int cam_io_memcpy_mb(void __iomem *dest_addr,
  73. void __iomem *src_addr, uint32_t len)
  74. {
  75. int i;
  76. uint32_t *d = (uint32_t *) dest_addr;
  77. uint32_t *s = (uint32_t *) src_addr;
  78. if (!dest_addr || !src_addr)
  79. return -EINVAL;
  80. CAM_DBG(CAM_UTIL, "%pK %pK %d", dest_addr, src_addr, len);
  81. /*
  82. * Do not use cam_io_w_mb to avoid double wmb() after a write
  83. * and before the next write.
  84. */
  85. wmb();
  86. for (i = 0; i < (len / 4); i++) {
  87. CAM_DBG(CAM_UTIL, "0x%pK %08x", d, *s);
  88. writel_relaxed(*s++, d++);
  89. }
  90. /* Ensure previous writes are done */
  91. wmb();
  92. return 0;
  93. }
  94. int cam_io_poll_value(void __iomem *addr, uint32_t wait_data, uint32_t retry,
  95. unsigned long min_usecs, unsigned long max_usecs)
  96. {
  97. uint32_t tmp, cnt = 0;
  98. int rc = 0;
  99. if (!addr)
  100. return -EINVAL;
  101. tmp = readl_relaxed(addr);
  102. while ((tmp != wait_data) && (cnt++ < retry)) {
  103. if (min_usecs > 0 && max_usecs > 0)
  104. usleep_range(min_usecs, max_usecs);
  105. tmp = readl_relaxed(addr);
  106. }
  107. if (cnt > retry) {
  108. CAM_DBG(CAM_UTIL, "Poll failed by value");
  109. rc = -EINVAL;
  110. }
  111. return rc;
  112. }
  113. int cam_io_poll_value_wmask(void __iomem *addr, uint32_t wait_data,
  114. uint32_t bmask, uint32_t retry, unsigned long min_usecs,
  115. unsigned long max_usecs)
  116. {
  117. uint32_t tmp, cnt = 0;
  118. int rc = 0;
  119. if (!addr)
  120. return -EINVAL;
  121. tmp = readl_relaxed(addr);
  122. while (((tmp & bmask) != wait_data) && (cnt++ < retry)) {
  123. if (min_usecs > 0 && max_usecs > 0)
  124. usleep_range(min_usecs, max_usecs);
  125. tmp = readl_relaxed(addr);
  126. }
  127. if (cnt > retry) {
  128. CAM_DBG(CAM_UTIL, "Poll failed with mask");
  129. rc = -EINVAL;
  130. }
  131. return rc;
  132. }
  133. int cam_io_w_same_offset_block(const uint32_t *data, void __iomem *addr,
  134. uint32_t len)
  135. {
  136. int i;
  137. if (!data || !len || !addr)
  138. return -EINVAL;
  139. for (i = 0; i < len; i++) {
  140. CAM_DBG(CAM_UTIL, "i= %d len =%d val=%x addr =%pK",
  141. i, len, data[i], addr);
  142. writel_relaxed(data[i], addr);
  143. }
  144. return 0;
  145. }
  146. int cam_io_w_mb_same_offset_block(const uint32_t *data, void __iomem *addr,
  147. uint32_t len)
  148. {
  149. int i;
  150. if (!data || !len || !addr)
  151. return -EINVAL;
  152. for (i = 0; i < len; i++) {
  153. CAM_DBG(CAM_UTIL, "i= %d len =%d val=%x addr =%pK",
  154. i, len, data[i], addr);
  155. /* Ensure previous writes are done */
  156. wmb();
  157. writel_relaxed(data[i], addr);
  158. }
  159. return 0;
  160. }
  161. #define __OFFSET(__i) (data[__i][0])
  162. #define __VAL(__i) (data[__i][1])
  163. int cam_io_w_offset_val_block(const uint32_t data[][2],
  164. void __iomem *addr_base, uint32_t len)
  165. {
  166. int i;
  167. if (!data || !len || !addr_base)
  168. return -EINVAL;
  169. for (i = 0; i < len; i++) {
  170. CAM_DBG(CAM_UTIL, "i= %d len =%d val=%x addr_base =%pK reg=%x",
  171. i, len, __VAL(i), addr_base, __OFFSET(i));
  172. writel_relaxed(__VAL(i), addr_base + __OFFSET(i));
  173. }
  174. return 0;
  175. }
  176. int cam_io_w_mb_offset_val_block(const uint32_t data[][2],
  177. void __iomem *addr_base, uint32_t len)
  178. {
  179. int i;
  180. if (!data || !len || !addr_base)
  181. return -EINVAL;
  182. /* Ensure write is done */
  183. wmb();
  184. for (i = 0; i < len; i++) {
  185. CAM_DBG(CAM_UTIL, "i= %d len =%d val=%x addr_base =%pK reg=%x",
  186. i, len, __VAL(i), addr_base, __OFFSET(i));
  187. writel_relaxed(__VAL(i), addr_base + __OFFSET(i));
  188. }
  189. return 0;
  190. }
  191. #define BYTES_PER_REGISTER 4
  192. #define NUM_REGISTER_PER_LINE 4
  193. #define REG_OFFSET(__start, __i) (__start + (__i * BYTES_PER_REGISTER))
  194. int cam_io_dump(void __iomem *base_addr, uint32_t start_offset, int size)
  195. {
  196. char line_str[128];
  197. char *p_str;
  198. int i;
  199. uint32_t data;
  200. CAM_DBG(CAM_UTIL, "addr=%pK offset=0x%x size=%d",
  201. base_addr, start_offset, size);
  202. if (!base_addr || (size <= 0))
  203. return -EINVAL;
  204. line_str[0] = '\0';
  205. p_str = line_str;
  206. for (i = 0; i < size; i++) {
  207. if (i % NUM_REGISTER_PER_LINE == 0) {
  208. snprintf(p_str, 12, "0x%08x: ",
  209. REG_OFFSET(start_offset, i));
  210. p_str += 11;
  211. }
  212. data = readl_relaxed(base_addr + REG_OFFSET(start_offset, i));
  213. snprintf(p_str, 9, "%08x ", data);
  214. p_str += 8;
  215. if ((i + 1) % NUM_REGISTER_PER_LINE == 0) {
  216. CAM_ERR(CAM_UTIL, "%s", line_str);
  217. line_str[0] = '\0';
  218. p_str = line_str;
  219. }
  220. }
  221. if (line_str[0] != '\0')
  222. CAM_ERR(CAM_UTIL, "%s", line_str);
  223. return 0;
  224. }