ubwcp_hw.c 9.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. /*
  3. * Copyright (c) 2022-2023 Qualcomm Innovation Center, Inc. All rights reserved.
  4. */
  5. #define pr_fmt(fmt) "%s: hw: %s(): " fmt, KBUILD_MODNAME, __func__
  6. #include <linux/module.h>
  7. #include <linux/kernel.h>
  8. #include <linux/dma-buf.h>
  9. #include <linux/slab.h>
  10. #include <linux/cdev.h>
  11. #include <linux/qcom_scm.h>
  12. #include <linux/delay.h>
  13. #include "ubwcp_hw.h"
  14. static bool ubwcp_hw_trace_en;
  15. //#define DBG(fmt, args...)
  16. #define DBG(fmt, args...) \
  17. do { \
  18. if (unlikely(ubwcp_hw_trace_en)) \
  19. pr_err(fmt "\n", ##args); \
  20. } while (0)
  21. #define ERR(fmt, args...) pr_err_ratelimited(": %d: ~~~ERROR~~~: " fmt "\n", __LINE__, ##args)
  22. MODULE_LICENSE("GPL");
  23. #define PAGE_ADDR_4K(_x) ((_x) >> 12)
  24. /* register offsets from base */
  25. #define RANGE_LOWER 0x0000
  26. #define RANGE_HIGHER 0x0800
  27. #define DESC_BASE 0x1000
  28. #define DESC_BASE_STRIDE 0x1004
  29. #define CONFIG 0x1008
  30. #define ENCODER_CONFIG 0x100C
  31. #define ENCODER_STATUS 0x1010
  32. #define DECODER_CONFIG 0x1014
  33. #define DECODER_STATUS 0x1018
  34. #define RANGE_CHECK_FAIL 0x101C
  35. #define RANGE_CHECK_CONTROL 0x1020
  36. #define RANGE_CHECK_STATUS 0x1060
  37. #define FLUSH_CONTROL 0x10A0
  38. #define FLUSH_STATUS 0x10A4
  39. #define INTERRUPT_SET 0x10B0
  40. #define INTERRUPT_STATUS_READ 0x10C0
  41. #define INTERRUPT_STATUS_WRITE 0x10C4
  42. #define INTERRUPT_STATUS_ENCODE 0x10C8
  43. #define INTERRUPT_STATUS_DECODE 0x10CC
  44. #define INTERRUPT_READ_SRC_LOW 0x1100
  45. #define INTERRUPT_READ_SRC_HIGH 0x1104
  46. #define INTERRUPT_WRITE_SRC_LOW 0x1108
  47. #define INTERRUPT_WRITE_SRC_HIGH 0x110C
  48. #define INTERRUPT_ENCODE_SRC_LOW 0x1110
  49. #define INTERRUPT_ENCODE_SRC_HIGH 0x1114
  50. #define INTERRUPT_DECODE_SRC_LOW 0x1118
  51. #define INTERRUPT_DECODE_SRC_HIGH 0x111C
  52. #define INTERRUPT_CLEAR 0x1120
  53. #define QNS4_PARAMS 0x1124
  54. #define OVERRIDE 0x112C
  55. #define VERSION_CONTROL 0x1130
  56. #define SPARE 0x1188
  57. #define UBWCP_DEBUG_REG_RW
  58. /* read/write register */
  59. #if defined(UBWCP_DEBUG_REG_RW)
  60. #define UBWCP_REG_READ(_base, _offset) \
  61. ({u32 _reg; \
  62. _reg = ioread32(_base + _offset); \
  63. DBG("READ : 0x%x -> 0x%08x", _offset, _reg); \
  64. _reg; })
  65. #define UBWCP_REG_WRITE(_base, _offset, _value) \
  66. { \
  67. DBG("WRITE: 0x%x <- 0x%08x", _offset, _value); \
  68. iowrite32(_value, _base + _offset); \
  69. }
  70. #else
  71. #define UBWCP_REG_READ(_base, _offset) ioread32(_base + _offset)
  72. #define UBWCP_REG_WRITE(_base, _offset, _value) iowrite32(_value, _base + _offset)
  73. #endif
  74. #define UBWCP_REG_READ_NO_DBG(_base, _offset) ioread32(_base + _offset)
  75. #define UBWCP_REG_WRITE_NO_DBG(_base, _offset, _value) iowrite32(_value, _base + _offset)
  76. void ubwcp_hw_interrupt_enable(void __iomem *base, u16 interrupt, bool enable)
  77. {
  78. u32 value;
  79. value = UBWCP_REG_READ(base, INTERRUPT_SET);
  80. if (enable)
  81. value = value | (1 << interrupt);
  82. else
  83. value = value & ~(1 << interrupt);
  84. UBWCP_REG_WRITE(base, INTERRUPT_SET, value);
  85. }
  86. EXPORT_SYMBOL(ubwcp_hw_interrupt_enable);
  87. void ubwcp_hw_interrupt_clear(void __iomem *base, u16 interrupt)
  88. {
  89. UBWCP_REG_WRITE_NO_DBG(base, INTERRUPT_CLEAR, (1 << interrupt));
  90. }
  91. EXPORT_SYMBOL(ubwcp_hw_interrupt_clear);
  92. int ubwcp_hw_interrupt_status(void __iomem *base, u16 interrupt)
  93. {
  94. int value = -1;
  95. switch (interrupt) {
  96. case INTERRUPT_READ_ERROR:
  97. value = UBWCP_REG_READ(base, INTERRUPT_STATUS_READ) & 0x1;
  98. break;
  99. case INTERRUPT_WRITE_ERROR:
  100. value = UBWCP_REG_READ(base, INTERRUPT_STATUS_WRITE) & 0x1;
  101. break;
  102. case INTERRUPT_DECODE_ERROR:
  103. value = UBWCP_REG_READ(base, INTERRUPT_STATUS_DECODE) & 0x1;
  104. break;
  105. case INTERRUPT_ENCODE_ERROR:
  106. value = UBWCP_REG_READ(base, INTERRUPT_STATUS_ENCODE) & 0x1;
  107. break;
  108. default:
  109. /* TBD: fatal error? */
  110. break;
  111. }
  112. return value;
  113. }
  114. /* returns the address which caused this interrupt */
  115. u64 ubwcp_hw_interrupt_src_address(void __iomem *base, u16 interrupt)
  116. {
  117. u32 addr_low;
  118. u32 addr_high;
  119. switch (interrupt) {
  120. case INTERRUPT_READ_ERROR:
  121. addr_low = UBWCP_REG_READ_NO_DBG(base, INTERRUPT_READ_SRC_LOW);
  122. addr_high = UBWCP_REG_READ_NO_DBG(base, INTERRUPT_READ_SRC_HIGH) & 0xF;
  123. break;
  124. case INTERRUPT_WRITE_ERROR:
  125. addr_low = UBWCP_REG_READ_NO_DBG(base, INTERRUPT_WRITE_SRC_LOW);
  126. addr_high = UBWCP_REG_READ_NO_DBG(base, INTERRUPT_WRITE_SRC_HIGH) & 0xF;
  127. break;
  128. case INTERRUPT_DECODE_ERROR:
  129. addr_low = UBWCP_REG_READ_NO_DBG(base, INTERRUPT_DECODE_SRC_LOW);
  130. addr_high = UBWCP_REG_READ_NO_DBG(base, INTERRUPT_DECODE_SRC_HIGH) & 0xF;
  131. break;
  132. case INTERRUPT_ENCODE_ERROR:
  133. addr_low = UBWCP_REG_READ_NO_DBG(base, INTERRUPT_ENCODE_SRC_LOW);
  134. addr_high = UBWCP_REG_READ_NO_DBG(base, INTERRUPT_ENCODE_SRC_HIGH) & 0xF;
  135. break;
  136. default:
  137. /* TBD: fatal error? */
  138. addr_low = 0x0;
  139. addr_high = 0x0;
  140. break;
  141. }
  142. return ((addr_high << 31) | addr_low);
  143. }
  144. EXPORT_SYMBOL(ubwcp_hw_interrupt_src_address);
  145. /*
  146. * @index: index of buffer (from 0 to 255)
  147. * @pa : ULA PA start address
  148. * @size : size of ULA PA address range
  149. */
  150. void ubwcp_hw_set_range_check(void __iomem *base, u16 index, phys_addr_t pa, size_t size)
  151. {
  152. u32 lower;
  153. u32 higher;
  154. lower = PAGE_ADDR_4K(pa);
  155. higher = PAGE_ADDR_4K(pa + size);
  156. UBWCP_REG_WRITE(base, RANGE_LOWER + index*4, lower);
  157. UBWCP_REG_WRITE(base, RANGE_HIGHER + index*4, higher);
  158. }
  159. EXPORT_SYMBOL(ubwcp_hw_set_range_check);
  160. /* enable range ck:
  161. * identify control register for this index.
  162. * 32bits in each ctrl reg. upto 8 regs for 256 indexes
  163. */
  164. void ubwcp_hw_enable_range_check(void __iomem *base, u16 index)
  165. {
  166. u32 val;
  167. u16 ctrl_reg = index >> 5;
  168. val = UBWCP_REG_READ(base, RANGE_CHECK_CONTROL + ctrl_reg*4);
  169. val |= (1 << (index & 0x1F));
  170. UBWCP_REG_WRITE(base, RANGE_CHECK_CONTROL + ctrl_reg*4, val);
  171. }
  172. EXPORT_SYMBOL(ubwcp_hw_enable_range_check);
  173. /* Disable range check with flush */
  174. int ubwcp_hw_disable_range_check_with_flush(void __iomem *base, u16 index)
  175. {
  176. u32 flush_complete = 0;
  177. u32 count = 20;
  178. u32 val;
  179. u16 ctrl_reg = index >> 5;
  180. //assert flush
  181. UBWCP_REG_WRITE(base, FLUSH_CONTROL, 0x3);
  182. //poll for flush done
  183. do {
  184. flush_complete = UBWCP_REG_READ(base, FLUSH_STATUS) & 0x1;
  185. if (flush_complete) {
  186. //disable range ck
  187. val = UBWCP_REG_READ(base, RANGE_CHECK_CONTROL + ctrl_reg*4);
  188. val &= ~(1 << (index & 0x1F));
  189. UBWCP_REG_WRITE(base, RANGE_CHECK_CONTROL + ctrl_reg*4, val);
  190. //clear flush
  191. UBWCP_REG_WRITE(base, FLUSH_CONTROL, 0x0);
  192. return 0;
  193. }
  194. udelay(100);
  195. } while (count--);
  196. ERR("~~~~~ FLUSH FAILED ~~~~~");
  197. return -1;
  198. }
  199. EXPORT_SYMBOL(ubwcp_hw_disable_range_check_with_flush);
  200. void ubwcp_hw_set_buf_desc(void __iomem *base, u64 desc_addr, u16 desc_stride)
  201. {
  202. UBWCP_REG_WRITE(base, DESC_BASE, PAGE_ADDR_4K(desc_addr));
  203. UBWCP_REG_WRITE(base, DESC_BASE_STRIDE, desc_stride);
  204. }
  205. EXPORT_SYMBOL(ubwcp_hw_set_buf_desc);
  206. /* Value set here is returned upon read of an address that fails range check.
  207. * Writes are ignored.
  208. * Will also generate range_check_fail interrupt if enabled.
  209. * if we don't program, default value is: 0x92929292
  210. */
  211. void ubwcp_hw_set_default_range_check_value(void __iomem *base, u32 val)
  212. {
  213. UBWCP_REG_WRITE(base, RANGE_CHECK_FAIL, val);
  214. }
  215. void ubwcp_hw_version(void __iomem *base, u32 *major, u32 *minor)
  216. {
  217. u32 version;
  218. version = UBWCP_REG_READ(base, VERSION_CONTROL);
  219. *major = version & 0xF;
  220. *minor = (version & 0xF0) >> 4;
  221. }
  222. EXPORT_SYMBOL(ubwcp_hw_version);
  223. /* TBD: */
  224. void ubwcp_hw_macro_tile_config(void __iomem *base)
  225. {
  226. //TODO: In future add in support for LP4
  227. //May be able to determine DDR version via call to
  228. //of_fdt_get_ddrtype()
  229. /*
  230. * For Lanai assume 4 Channel LP5 DDR so from HSR
  231. * MAL Size 32B
  232. * Highest Bank Bit 16
  233. * Level 1 Bank Swizzling Disable
  234. * Level 2 Bank Swizzling Enable
  235. * Level 3 Bank Swizzling Enable
  236. * Bank Spreading Enable
  237. * Macrotiling Configuration (Num Channels) 8
  238. */
  239. UBWCP_REG_WRITE(base, CONFIG, 0x1E3);
  240. }
  241. /* TBD: */
  242. void ubwcp_hw_decoder_config(void __iomem *base)
  243. {
  244. /*
  245. * For Lanai assume AMSBC (UBWC4.4/4.3) algorithm is used == b11
  246. * For Lanai assume 4 Channel LP5 DDR so MAL Size 32B == b0
  247. */
  248. UBWCP_REG_WRITE(base, DECODER_CONFIG, 0x7);
  249. }
  250. /* TBD: */
  251. void ubwcp_hw_encoder_config(void __iomem *base)
  252. {
  253. /*
  254. * For Lanai assume AMSBC (UBWC4.4/4.3) algorithm is used == b11
  255. * For Lanai assume 4 Channel LP5 DDR so MAL Size 32B == b0
  256. */
  257. UBWCP_REG_WRITE(base, ENCODER_CONFIG, 0x7);
  258. }
  259. int ubwcp_hw_flush(void __iomem *base)
  260. {
  261. u32 flush_complete = 0;
  262. u32 count = 20;
  263. UBWCP_REG_WRITE(base, FLUSH_CONTROL, 0x3);
  264. do {
  265. flush_complete = UBWCP_REG_READ(base, FLUSH_STATUS) & 0x1;
  266. if (flush_complete) {
  267. UBWCP_REG_WRITE(base, FLUSH_CONTROL, 0x0);
  268. return 0;
  269. }
  270. udelay(100);
  271. } while (count--);
  272. ERR("~~~~~ FLUSH FAILED ~~~~~");
  273. return -1;
  274. }
  275. EXPORT_SYMBOL(ubwcp_hw_flush);
  276. void ubwcp_hw_power_vote_status(void __iomem *pwr_ctrl, u8 *vote, u8 *status)
  277. {
  278. u32 reg;
  279. reg = UBWCP_REG_READ(pwr_ctrl, 0);
  280. *vote = (reg & BIT(0)) >> 0;
  281. *status = (reg & BIT(31)) >> 31;
  282. }
  283. void ubwcp_hw_one_time_init(void __iomem *base)
  284. {
  285. u32 reg;
  286. /* Spare reg config: set bit-9: SCC & bit-1: padding */
  287. reg = UBWCP_REG_READ(base, SPARE);
  288. reg |= BIT(9) | BIT(1);
  289. UBWCP_REG_WRITE(base, SPARE, reg);
  290. /* Configure SID */
  291. reg = UBWCP_REG_READ(base, QNS4_PARAMS);
  292. reg &= ~(0x3F);
  293. reg |= 0x1; /* desc buffer */
  294. reg |= (0 << 3); /* pixel data */
  295. UBWCP_REG_WRITE(base, QNS4_PARAMS, reg);
  296. ubwcp_hw_decoder_config(base);
  297. ubwcp_hw_encoder_config(base);
  298. ubwcp_hw_macro_tile_config(base);
  299. }
  300. EXPORT_SYMBOL(ubwcp_hw_one_time_init);
  301. void ubwcp_hw_trace_set(bool value)
  302. {
  303. ubwcp_hw_trace_en = value;
  304. }
  305. EXPORT_SYMBOL(ubwcp_hw_trace_set);
  306. void ubwcp_hw_trace_get(bool *value)
  307. {
  308. *value = ubwcp_hw_trace_en;
  309. }
  310. EXPORT_SYMBOL(ubwcp_hw_trace_get);