hal_ir.c 10.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349
  1. /* Copyright (c) 2019-2025 Allwinner Technology Co., Ltd. ALL rights reserved.
  2. * Allwinner is a trademark of Allwinner Technology Co.,Ltd., registered in
  3. * the the People's Republic of China and other countries.
  4. * All Allwinner Technology Co.,Ltd. trademarks are used with permission.
  5. * DISCLAIMER
  6. * THIRD PARTY LICENCES MAY BE REQUIRED TO IMPLEMENT THE SOLUTION/PRODUCT.
  7. * IF YOU NEED TO INTEGRATE THIRD PARTY¡¯S TECHNOLOGY (SONY, DTS, DOLBY, AVS OR MPEGLA, ETC.)
  8. * IN ALLWINNERS¡¯SDK OR PRODUCTS, YOU SHALL BE SOLELY RESPONSIBLE TO OBTAIN
  9. * ALL APPROPRIATELY REQUIRED THIRD PARTY LICENCES.
  10. * ALLWINNER SHALL HAVE NO WARRANTY, INDEMNITY OR OTHER OBLIGATIONS WITH RESPECT TO MATTERS
  11. * COVERED UNDER ANY REQUIRED THIRD PARTY LICENSE.
  12. * YOU ARE SOLELY RESPONSIBLE FOR YOUR USAGE OF THIRD PARTY¡¯S TECHNOLOGY.
  13. * THIS SOFTWARE IS PROVIDED BY ALLWINNER"AS IS" AND TO THE MAXIMUM EXTENT
  14. * PERMITTED BY LAW, ALLWINNER EXPRESSLY DISCLAIMS ALL WARRANTIES OF ANY KIND,
  15. * WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING WITHOUT LIMITATION REGARDING
  16. * THE TITLE, NON-INFRINGEMENT, ACCURACY, CONDITION, COMPLETENESS, PERFORMANCE
  17. * OR MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  18. * IN NO EVENT SHALL ALLWINNER BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  19. * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
  20. * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  21. * LOSS OF USE, DATA, OR PROFITS, OR BUSINESS INTERRUPTION)
  22. * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
  23. * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  24. * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
  25. * OF THE POSSIBILITY OF SUCH DAMAGE.
  26. */
  27. #include <interrupt.h>
  28. #include <hal_clk.h>
  29. #include <sunxi_hal_ir.h>
  30. #include <init.h>
  31. #define IRADC_ERR(fmt, arg...) printf("%s()%d " fmt, __func__, __LINE__, ##arg)
  32. #define IRADC_INIT(fmt, arg...) printf("%s()%d " fmt, __func__, __LINE__, ##arg)
  33. #ifdef IRADC_DEBUG
  34. #define IR_INFO(fmt, arg...) printf("%s()%d " fmt, __func__, __LINE__, ##arg)
  35. #define IR_INFO_IRQ(fmt, arg...) __log("%s()%d " fmt, __func__, __LINE__, ##arg)
  36. #else
  37. #define IR_INFO(fmt, arg...) \
  38. do { \
  39. } while (0);
  40. #define IR_INFO_IRQ(fmt, arg...) \
  41. do { \
  42. } while (0);
  43. #endif
  44. hal_ir_t hal_ir;
  45. static inline u8 ir_get_data(uint32_t reg_base)
  46. {
  47. return (u8)(hal_readl(reg_base + IR_RXDAT_REG) & 0xff);
  48. }
  49. static inline uint32_t ir_get_intsta(uint32_t reg_base)
  50. {
  51. return hal_readl(reg_base + IR_RXINTS_REG);
  52. }
  53. static inline void ir_clr_intsta(uint32_t reg_base, uint32_t bitmap)
  54. {
  55. uint32_t tmp = hal_readl(reg_base + IR_RXINTS_REG);
  56. tmp &= ~0xff;
  57. tmp |= bitmap & 0xff;
  58. hal_writel(tmp, reg_base + IR_RXINTS_REG);
  59. }
  60. static irqreturn_t ir_handler(int irq, void *dev)
  61. {
  62. hal_ir_t *ir = (hal_ir_t *)dev;
  63. uint32_t intsta, dcnt;
  64. uint32_t i = 0;
  65. uint32_t reg_data = 0;
  66. IR_INFO_IRQ("IR RX IRQ Serve\n");
  67. intsta = ir_get_intsta(ir->reg_base);
  68. ir_clr_intsta(ir->reg_base, intsta);
  69. /* get the count of signal */
  70. dcnt = (intsta >> 8) & 0x7f;
  71. IR_INFO_IRQ("receive cnt :%d\n", dcnt);
  72. /* Read FIFO and fill the raw event */
  73. for (i = 0; i < dcnt; i++)
  74. {
  75. /* get the data from fifo */
  76. reg_data = ir_get_data(ir->reg_base);
  77. ir->callback(IR_RXINTS_RXDA, reg_data);
  78. }
  79. if (intsta & IR_RXINTS_RXPE)
  80. {
  81. /* The last pulse can not call ir_raw_event_store() since miss
  82. * invert level in above, manu call
  83. */
  84. ir->callback(IR_RXINTS_RXPE, reg_data);
  85. }
  86. if (intsta & IR_RXINTS_RXOF)
  87. {
  88. /* FIFO Overflow */
  89. ir->callback(IR_RXINTS_RXPE, reg_data);
  90. }
  91. return IRQ_HANDLED;
  92. }
  93. static void ir_mode_set(uint32_t reg_base, enum ir_mode set_mode)
  94. {
  95. uint32_t ctrl_reg = 0;
  96. switch (set_mode)
  97. {
  98. case CIR_MODE_ENABLE:
  99. ctrl_reg = hal_readl(reg_base + IR_CTRL_REG);
  100. ctrl_reg |= IR_CIR_MODE;
  101. break;
  102. case IR_MODULE_ENABLE:
  103. ctrl_reg = hal_readl(reg_base + IR_CTRL_REG);
  104. ctrl_reg |= IR_ENTIRE_ENABLE;
  105. break;
  106. case IR_BOTH_PULSE_MODE:
  107. ctrl_reg = hal_readl(reg_base + IR_CTRL_REG);
  108. ctrl_reg |= IR_BOTH_PULSE;
  109. break;
  110. case IR_LOW_PULSE_MODE:
  111. ctrl_reg = hal_readl(reg_base + IR_CTRL_REG);
  112. ctrl_reg |= IR_LOW_PULSE;
  113. break;
  114. case IR_HIGH_PULSE_MODE:
  115. ctrl_reg = hal_readl(reg_base + IR_CTRL_REG);
  116. ctrl_reg |= IR_HIGH_PULSE;
  117. break;
  118. default:
  119. IRADC_ERR("ir_mode_set error!!\n");
  120. return;
  121. }
  122. hal_writel(ctrl_reg, reg_base + IR_CTRL_REG);
  123. }
  124. static void ir_sample_config(uint32_t reg_base,
  125. enum ir_sample_config set_sample)
  126. {
  127. uint32_t sample_reg = 0;
  128. sample_reg = hal_readl(reg_base + IR_SPLCFG_REG);
  129. switch (set_sample)
  130. {
  131. case IR_SAMPLE_REG_CLEAR:
  132. sample_reg = 0;
  133. break;
  134. case IR_CLK_SAMPLE:
  135. sample_reg |= IR_SAMPLE_DEV;
  136. break;
  137. case IR_FILTER_TH_NEC:
  138. sample_reg |= IR_RXFILT_VAL;
  139. break;
  140. case IR_FILTER_TH_RC5:
  141. sample_reg |= IR_RXFILT_VAL_RC5;
  142. break;
  143. case IR_IDLE_TH:
  144. sample_reg |= IR_RXIDLE_VAL;
  145. break;
  146. case IR_ACTIVE_TH:
  147. sample_reg |= IR_ACTIVE_T;
  148. sample_reg |= IR_ACTIVE_T_C;
  149. break;
  150. case IR_ACTIVE_TH_SAMPLE:
  151. sample_reg |= IR_ACTIVE_T_SAMPLE;
  152. sample_reg &= ~IR_ACTIVE_T_C;
  153. break;
  154. default:
  155. IRADC_ERR("config err !\n");;
  156. }
  157. hal_writel(sample_reg, reg_base + IR_SPLCFG_REG);
  158. }
  159. static void ir_signal_invert(uint32_t reg_base)
  160. {
  161. uint32_t reg_value;
  162. reg_value = 0x1 << 2;
  163. hal_writel(reg_value, reg_base + IR_RXCFG_REG);
  164. }
  165. static void ir_irq_config(uint32_t reg_base, enum ir_irq_config set_irq)
  166. {
  167. uint32_t irq_reg = 0;
  168. switch (set_irq)
  169. {
  170. case IR_IRQ_STATUS_CLEAR:
  171. hal_writel(0xef, reg_base + IR_RXINTS_REG);
  172. return;
  173. case IR_IRQ_ENABLE:
  174. irq_reg = hal_readl(reg_base + IR_RXINTE_REG);
  175. irq_reg |= IR_IRQ_STATUS;
  176. break;
  177. case IR_IRQ_FIFO_SIZE:
  178. irq_reg = hal_readl(reg_base + IR_RXINTE_REG);
  179. irq_reg |= IR_FIFO_20;
  180. break;
  181. default:
  182. return;
  183. }
  184. hal_writel(irq_reg, reg_base + IR_RXINTE_REG);
  185. }
  186. static void hal_ir_reg_cfg(uint32_t reg_base)
  187. {
  188. /* Enable IR Mode */
  189. ir_mode_set(reg_base, CIR_MODE_ENABLE);
  190. /* Config IR Smaple Register */
  191. ir_sample_config(reg_base, IR_SAMPLE_REG_CLEAR);
  192. ir_sample_config(reg_base, IR_CLK_SAMPLE);
  193. ir_sample_config(reg_base, IR_IDLE_TH); /* Set Idle Threshold */
  194. /* rc5 Set Active Threshold */
  195. ir_sample_config(reg_base, IR_ACTIVE_TH_SAMPLE);
  196. ir_sample_config(reg_base, IR_FILTER_TH_NEC); /* Set Filter Threshold */
  197. ir_signal_invert(reg_base);
  198. /* Clear All Rx Interrupt Status */
  199. ir_irq_config(reg_base, IR_IRQ_STATUS_CLEAR);
  200. /* Set Rx Interrupt Enable */
  201. ir_irq_config(reg_base, IR_IRQ_ENABLE);
  202. /* Rx FIFO Threshold = FIFOsz/2; */
  203. ir_irq_config(reg_base, IR_IRQ_FIFO_SIZE);
  204. /* for NEC decode which start with high level in the header so should
  205. * use IR_HIGH_PULSE_MODE mode, but some ICs don't support this function
  206. * therefor use IR_BOTH_PULSE_MODE mode as default
  207. */
  208. ir_mode_set(reg_base, IR_BOTH_PULSE_MODE);
  209. /* Enable IR Module */
  210. ir_mode_set(reg_base, IR_MODULE_ENABLE);
  211. }
  212. static hal_ir_status_t hal_ir_clk_init(void)
  213. {
  214. int ret;
  215. int32_t rate;
  216. hal_clk_id_t mclk = HAL_CLK_PERIPH_IRTX;
  217. ret = hal_clk_set_parent(mclk, HAL_CLK_SRC_HOSC24M);
  218. if (ret)
  219. {
  220. IRADC_ERR("[ir] clk set parent failed! return %d\n", ret);
  221. return IR_CLK_ERR;
  222. }
  223. rate = hal_clk_round_rate(mclk, IR_CLK);
  224. if (rate < 0)
  225. {
  226. IRADC_ERR("[ir] clk round rate failed! return %ld\n", rate);
  227. return IR_CLK_ERR;
  228. }
  229. ret = hal_clk_set_rate(mclk, rate);
  230. if (ret)
  231. {
  232. IRADC_ERR("[ir] clk set rate failed! return %d\n", ret);
  233. return IR_CLK_ERR;
  234. }
  235. rate = hal_clk_get_rate(mclk);
  236. if (rate < 0)
  237. {
  238. IRADC_ERR("[ir] clk get rate failed! return %ld\n", rate);
  239. return IR_CLK_ERR;
  240. }
  241. ret = hal_clock_enable(mclk);
  242. if (ret)
  243. {
  244. IRADC_ERR("[ir] couldn't enable mlck! return %d\n", ret);
  245. return IR_CLK_ERR;
  246. }
  247. return IR_OK;
  248. }
  249. static hal_ir_status_t hal_ir_pinctrl_init(hal_ir_t *ir)
  250. {
  251. int ret;
  252. ret = hal_gpio_pinmux_set_function(ir->pin, ir->pin_mux);
  253. if (ret)
  254. {
  255. IRADC_ERR(
  256. "[ir] PIN set function failed! return %d\n", ret);
  257. return IR_PIN_ERR;
  258. }
  259. ret = hal_gpio_set_driving_level(ir->pin, ir->pin_drv);
  260. if (ret)
  261. {
  262. IRADC_ERR(
  263. "[ir] PIN set driving level failed! return %d\n", ret);
  264. return IR_PIN_ERR;
  265. }
  266. return IR_OK;
  267. }
  268. int hal_ir_register_callback(ir_callback_t callback)
  269. {
  270. hal_ir_t *ir = &hal_ir;
  271. ir->callback = callback;
  272. return IR_OK;
  273. }
  274. int hal_ir_init(void)
  275. {
  276. hal_ir_t *ir = &hal_ir;
  277. ir->reg_base = SUNXI_IRADC_PBASE;
  278. ir->irq_num = SUNXI_IRQ_IRADC;
  279. ir->pin = IRADC_PIN;
  280. ir->pin_drv = IR_DRVSEL;
  281. ir->pin_mux = IR_MUXSEL;
  282. IRADC_INIT("ir init\n");
  283. if (hal_ir_pinctrl_init(ir))
  284. {
  285. IRADC_ERR("ir init pinctrl error\n");
  286. return IR_PIN_ERR;
  287. }
  288. if (hal_ir_clk_init())
  289. {
  290. IRADC_ERR("ir init clk error\n");
  291. return IR_CLK_ERR;
  292. }
  293. hal_ir_reg_cfg(ir->reg_base);
  294. if (request_irq(ir->irq_num, ir_handler, 0, "ir", ir))
  295. {
  296. IRADC_ERR("ir request irq failed\n");
  297. return IR_IRQ_ERR;
  298. }
  299. enable_irq(ir->irq_num);
  300. return IR_OK;
  301. }