cam_io_util.c 5.5 KB

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