hal_gpadc.c 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494
  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 <hal_interrupt.h>
  28. #include <hal_clk.h>
  29. #include <sunxi_hal_gpadc.h>
  30. #include <hal_reset.h>
  31. hal_gpadc_t hal_gpadc;
  32. #if defined(CONFIG_SOC_SUN20IW1)
  33. static hal_gpadc_status_t hal_gpadc_clk_init(hal_gpadc_t *gpadc)
  34. {
  35. hal_clk_type_t clk_type = HAL_SUNXI_CCU;
  36. hal_clk_id_t gpadc_clk_id = gpadc->bus_clk;
  37. hal_clk_t mclk;
  38. hal_reset_type_t reset_type = HAL_SUNXI_RESET;
  39. hal_reset_id_t gpadc_reset_id = gpadc->rst_clk;
  40. struct reset_control *reset;
  41. mclk = hal_clock_get(clk_type, gpadc_clk_id);
  42. if(hal_clock_enable(mclk))
  43. {
  44. GPADC_ERR("gpadc clk enable failed!\n");
  45. return GPADC_ERROR;
  46. }
  47. gpadc->mbus_clk = mclk;
  48. reset = hal_reset_control_get(reset_type, gpadc_reset_id);
  49. if (hal_reset_control_deassert(reset))
  50. {
  51. GPADC_ERR("gpadc reset deassert failed!\n");
  52. return GPADC_ERROR;
  53. }
  54. hal_reset_control_put(reset);
  55. return GPADC_OK;
  56. }
  57. #else
  58. static hal_gpadc_status_t hal_gpadc_clk_init(hal_gpadc_t *gpadc)
  59. {
  60. #if !defined(CONFIG_ARCH_SUN8IW18P1)
  61. if (hal_clk_set_parent(gpadc->mclk, gpadc->pclk))
  62. {
  63. GPADC_ERR("[gpadc] clk set parent failed!");
  64. return GPADC_ERROR;
  65. }
  66. #endif
  67. if (hal_clock_enable(gpadc->mclk))
  68. {
  69. GPADC_ERR("[gpadc] clk enable mclk failed!");
  70. return GPADC_ERROR;
  71. }
  72. return GPADC_OK;
  73. }
  74. #endif
  75. static int gpadc_channel_check_valid(hal_gpadc_channel_t channal)
  76. {
  77. hal_gpadc_t *gpadc = &hal_gpadc;
  78. return channal < gpadc->channel_num ? 0 : -1 ;
  79. }
  80. static void gpadc_channel_select(hal_gpadc_channel_t channal)
  81. {
  82. uint32_t reg_val;
  83. hal_gpadc_t *gpadc = &hal_gpadc;
  84. reg_val = readl((unsigned long)(gpadc->reg_base) + GP_CS_EN_REG);
  85. reg_val |= (0x01 << channal);
  86. writel(reg_val, (unsigned long)(gpadc->reg_base) + GP_CS_EN_REG);
  87. }
  88. static void gpadc_channel_deselect(hal_gpadc_channel_t channal)
  89. {
  90. uint32_t reg_val;
  91. hal_gpadc_t *gpadc = &hal_gpadc;
  92. reg_val = readl((unsigned long)(gpadc->reg_base) + GP_CS_EN_REG);
  93. reg_val &= ~(0x01 << channal);
  94. writel(reg_val, (unsigned long)(gpadc->reg_base) + GP_CS_EN_REG);
  95. }
  96. static void gpadc_compare_select(hal_gpadc_channel_t channal)
  97. {
  98. uint32_t reg_val;
  99. hal_gpadc_t *gpadc = &hal_gpadc;
  100. reg_val = readl((unsigned long)(gpadc->reg_base) + GP_CS_EN_REG);
  101. reg_val |= (GP_CH0_CMP_EN << channal);
  102. writel(reg_val, (unsigned long)(gpadc->reg_base) + GP_CS_EN_REG);
  103. }
  104. static void gpadc_compare_deselect(hal_gpadc_channel_t channal)
  105. {
  106. uint32_t reg_val;
  107. hal_gpadc_t *gpadc = &hal_gpadc;
  108. reg_val = readl((unsigned long)(gpadc->reg_base) + GP_CTRL_REG);
  109. reg_val &= ~(GP_CH0_CMP_EN << channal);
  110. writel(reg_val, (unsigned long)(gpadc->reg_base) + GP_CTRL_REG);
  111. }
  112. static void gpadc_channel_enable_lowirq(hal_gpadc_channel_t channal)
  113. {
  114. uint32_t reg_val;
  115. hal_gpadc_t *gpadc = &hal_gpadc;
  116. reg_val = readl((unsigned long)(gpadc->reg_base) + GP_DATAL_INTC_REG);
  117. reg_val |= (0x01 << channal);
  118. writel(reg_val, (unsigned long)(gpadc->reg_base) + GP_DATAL_INTC_REG);
  119. }
  120. static void gpadc_channel_disable_lowirq(hal_gpadc_channel_t channal)
  121. {
  122. uint32_t reg_val;
  123. hal_gpadc_t *gpadc = &hal_gpadc;
  124. reg_val = readl((unsigned long)(gpadc->reg_base) + GP_DATAL_INTC_REG);
  125. reg_val &= ~(0x01 << channal);
  126. writel(reg_val, (unsigned long)(gpadc->reg_base) + GP_DATAL_INTC_REG);
  127. }
  128. static void gpadc_channel_compare_lowdata(hal_gpadc_channel_t channal,
  129. uint32_t low_uv)
  130. {
  131. uint32_t reg_val = 0, low = 0, unit = 0;
  132. hal_gpadc_t *gpadc = &hal_gpadc;
  133. /* analog voltage range 0~1.8v, 12bits sample rate, unit=1.8v/(2^12) */
  134. unit = VOL_RANGE / 4096; /* 12bits sample rate */
  135. low = low_uv / unit;
  136. if (low > VOL_VALUE_MASK)
  137. {
  138. low = VOL_VALUE_MASK;
  139. }
  140. reg_val = readl((unsigned long)(gpadc->reg_base) + GP_CH0_CMP_DATA_REG + 4 * channal);
  141. reg_val &= ~VOL_VALUE_MASK;
  142. reg_val |= (low & VOL_VALUE_MASK);
  143. writel(reg_val, (unsigned long)(gpadc->reg_base) + GP_CH0_CMP_DATA_REG + 4 * channal);
  144. }
  145. static void gpadc_channel_enable_highirq(hal_gpadc_channel_t channal)
  146. {
  147. uint32_t reg_val;
  148. hal_gpadc_t *gpadc = &hal_gpadc;
  149. reg_val = readl((unsigned long)(gpadc->reg_base) + GP_DATAH_INTC_REG);
  150. reg_val |= (1 << channal);
  151. writel(reg_val, (unsigned long)(gpadc->reg_base) + GP_DATAH_INTC_REG);
  152. }
  153. static void gpadc_channel_disable_highirq(hal_gpadc_channel_t channal)
  154. {
  155. uint32_t reg_val;
  156. hal_gpadc_t *gpadc = &hal_gpadc;
  157. reg_val = readl((unsigned long)(gpadc->reg_base) + GP_DATAH_INTC_REG);
  158. reg_val &= ~(1 << channal);
  159. writel(reg_val, (unsigned long)(gpadc->reg_base) + GP_DATAH_INTC_REG);
  160. }
  161. static void gpadc_channel_compare_highdata(hal_gpadc_channel_t channal,
  162. uint32_t hig_uv)
  163. {
  164. uint32_t reg_val = 0, hig_val = 0, unit_val = 0;
  165. hal_gpadc_t *gpadc = &hal_gpadc;
  166. /* anolog voltage range 0~1.8v, 12bits sample rate, unit=1.8v/(2^12) */
  167. unit_val = VOL_RANGE / 4096; /* 12bits sample rate */
  168. hig_val = hig_uv / unit_val;
  169. if (hig_val > VOL_VALUE_MASK)
  170. {
  171. hig_val = VOL_VALUE_MASK;
  172. }
  173. reg_val = readl((unsigned long)(gpadc->reg_base) + GP_CH0_CMP_DATA_REG + 4 * channal);
  174. reg_val &= ~(VOL_VALUE_MASK << 16);
  175. reg_val |= (hig_val & VOL_VALUE_MASK) << 16;
  176. writel(reg_val, (unsigned long)(gpadc->reg_base) + GP_CH0_CMP_DATA_REG + 4 * channal);
  177. }
  178. /* clk_in: source clock, round_clk: sample rate */
  179. static void gpadc_sample_rate_set(uint32_t reg_base, uint32_t clk_in,
  180. uint32_t round_clk)
  181. {
  182. uint32_t div, reg_val;
  183. if (round_clk > clk_in)
  184. {
  185. GPADC_ERR("invalid round clk!");
  186. }
  187. div = clk_in / round_clk - 1 ;
  188. reg_val = readl((unsigned long)(reg_base) + GP_SR_REG);
  189. reg_val &= ~GP_SR_CON;
  190. reg_val |= (div << 16);
  191. writel(reg_val, (unsigned long)(reg_base) + GP_SR_REG);
  192. }
  193. static void gpadc_calibration_enable(uint32_t reg_base)
  194. {
  195. uint32_t reg_val;
  196. reg_val = readl((unsigned long)(reg_base) + GP_CTRL_REG);
  197. reg_val |= GP_CALI_EN;
  198. writel(reg_val, (unsigned long)(reg_base) + GP_CTRL_REG);
  199. }
  200. static void gpadc_mode_select(uint32_t reg_base,
  201. enum gp_select_mode mode)
  202. {
  203. uint32_t reg_val;
  204. reg_val = readl((unsigned long)(reg_base) + GP_CTRL_REG);
  205. reg_val &= ~GP_MODE_SELECT;
  206. reg_val |= (mode << 18);
  207. writel(reg_val, (unsigned long)(reg_base) + GP_CTRL_REG);
  208. }
  209. /* enable gpadc function, true:enable, false:disable */
  210. static void gpadc_enable(uint32_t reg_base)
  211. {
  212. uint32_t reg_val = 0;
  213. reg_val = readl((unsigned long)(reg_base) + GP_CTRL_REG);
  214. reg_val |= GP_ADC_EN;
  215. writel(reg_val, (unsigned long)(reg_base) + GP_CTRL_REG);
  216. }
  217. /* enable gpadc function, true:enable, false:disable */
  218. static void gpadc_disable(uint32_t reg_base)
  219. {
  220. uint32_t reg_val = 0;
  221. reg_val = readl((unsigned long)(reg_base) + GP_CTRL_REG);
  222. reg_val &= ~GP_ADC_EN;
  223. writel(reg_val, (unsigned long)(reg_base) + GP_CTRL_REG);
  224. }
  225. static uint32_t gpadc_read_channel_irq_enable(uint32_t reg_base)
  226. {
  227. return readl((unsigned long)(reg_base) + GP_DATA_INTC_REG);
  228. }
  229. static uint32_t gpadc_read_channel_lowirq_enable(uint32_t reg_base)
  230. {
  231. return readl((unsigned long)(reg_base) + GP_DATAL_INTC_REG);
  232. }
  233. static uint32_t gpadc_read_channel_highirq_enable(uint32_t reg_base)
  234. {
  235. return readl((unsigned long)(reg_base) + GP_DATAH_INTC_REG);
  236. }
  237. static uint32_t gpadc_channel_irq_status(uint32_t reg_base)
  238. {
  239. return readl((unsigned long)(reg_base) + GP_DATA_INTS_REG);
  240. }
  241. static void gpadc_channel_clear_irq(uint32_t reg_base, uint32_t flags)
  242. {
  243. writel(flags, (unsigned long)(reg_base) + GP_DATA_INTS_REG);
  244. }
  245. static uint32_t gpadc_channel_lowirq_status(uint32_t reg_base)
  246. {
  247. return readl((unsigned long)(reg_base) + GP_DATAL_INTS_REG);
  248. }
  249. static void gpadc_channel_clear_lowirq(uint32_t reg_base, uint32_t flags)
  250. {
  251. writel(flags, (unsigned long)(reg_base) + GP_DATAL_INTS_REG);
  252. }
  253. static uint32_t gpadc_channel_highirq_status(uint32_t reg_base)
  254. {
  255. return readl((unsigned long)(reg_base) + GP_DATAH_INTS_REG);
  256. }
  257. static void gpadc_channel_clear_highirq(uint32_t reg_base, uint32_t flags)
  258. {
  259. writel(flags, (unsigned long)(reg_base) + GP_DATAH_INTS_REG);
  260. }
  261. static int gpadc_read_data(uint32_t reg_base, hal_gpadc_channel_t channal)
  262. {
  263. return readl((unsigned long)(reg_base) + GP_CH0_DATA_REG + 4 * channal) & GP_CH_DATA_MASK;
  264. }
  265. int hal_gpadc_callback(uint32_t data_type, uint32_t data)
  266. {
  267. GPADC_INFO("gpadc interrupt, data_type is %ld", data_type);
  268. return 0;
  269. }
  270. static irqreturn_t gpadc_handler(int irq, void *dev)
  271. {
  272. hal_gpadc_t *gpadc = (hal_gpadc_t *)dev;
  273. uint32_t reg_val, reg_low, reg_high;
  274. uint32_t reg_enable, reg_enable_low, reg_enable_high;
  275. uint32_t i, data = 0;
  276. reg_enable = gpadc_read_channel_irq_enable(gpadc->reg_base);
  277. reg_enable_low = gpadc_read_channel_lowirq_enable(gpadc->reg_base);
  278. reg_enable_high = gpadc_read_channel_highirq_enable(gpadc->reg_base);
  279. reg_val = gpadc_channel_irq_status(gpadc->reg_base);
  280. gpadc_channel_clear_irq(gpadc->reg_base, reg_val);
  281. reg_low = gpadc_channel_lowirq_status(gpadc->reg_base);
  282. gpadc_channel_clear_lowirq(gpadc->reg_base, reg_val);
  283. reg_high = gpadc_channel_highirq_status(gpadc->reg_base);
  284. gpadc_channel_clear_highirq(gpadc->reg_base, reg_val);
  285. for (i = 0; i < gpadc->channel_num; i++)
  286. {
  287. if (reg_low & (1 << i) & reg_enable_low)
  288. {
  289. data = gpadc_read_data(gpadc->reg_base, i);
  290. gpadc_channel_enable_highirq(i);
  291. if (gpadc->callback[i])
  292. {
  293. gpadc->callback[i](GPADC_DOWN, data);
  294. }
  295. }
  296. if (reg_high & (1 << i) & reg_enable_high)
  297. {
  298. gpadc_channel_disable_highirq(i);
  299. gpadc->callback[i](GPADC_UP, data);
  300. }
  301. }
  302. return 0;
  303. }
  304. hal_gpadc_status_t hal_gpadc_register_callback(hal_gpadc_channel_t channal,
  305. gpadc_callback_t user_callback)
  306. {
  307. hal_gpadc_t *gpadc = &hal_gpadc;
  308. if (gpadc_channel_check_valid(channal))
  309. {
  310. return GPADC_CHANNEL_ERROR;
  311. }
  312. if (user_callback == NULL)
  313. {
  314. return GPADC_ERROR;
  315. }
  316. gpadc->callback[channal] = user_callback;
  317. return GPADC_OK;
  318. }
  319. hal_gpadc_status_t hal_gpadc_channel_init(hal_gpadc_channel_t channal)
  320. {
  321. hal_gpadc_t *gpadc = &hal_gpadc;
  322. if (gpadc_channel_check_valid(channal))
  323. {
  324. return GPADC_CHANNEL_ERROR;
  325. }
  326. gpadc_channel_select(channal);
  327. gpadc_compare_select(channal);
  328. gpadc_channel_enable_lowirq(channal);
  329. gpadc_channel_compare_lowdata(channal, COMPARE_LOWDATA);
  330. gpadc_channel_compare_highdata(channal, COMPARE_HIGDATA);
  331. return GPADC_OK;
  332. }
  333. hal_gpadc_status_t hal_gpadc_channel_exit(hal_gpadc_channel_t channal)
  334. {
  335. hal_gpadc_t *gpadc = &hal_gpadc;
  336. if (gpadc_channel_check_valid(channal))
  337. {
  338. return GPADC_CHANNEL_ERROR;
  339. }
  340. gpadc_channel_deselect(channal);
  341. gpadc_compare_deselect(channal);
  342. gpadc_channel_disable_lowirq(channal);
  343. return GPADC_OK;
  344. }
  345. static void hal_gpadc_setup(hal_gpadc_t *gpadc)
  346. {
  347. uint8_t i;
  348. gpadc->reg_base = GPADC_BASE;
  349. gpadc->channel_num = CHANNEL_NUM;
  350. gpadc->irq_num = SUNXI_GPADC_IRQ;
  351. gpadc->sample_rate = DEFAULT_SR;
  352. #if defined(CONFIG_SOC_SUN20IW1)
  353. gpadc->bus_clk = CLK_BUS_GPADC;
  354. gpadc->rst_clk = RST_BUS_GPADC;
  355. #else
  356. gpadc->pclk = HAL_CLK_SRC_HOSC24M;
  357. gpadc->mclk = HAL_CLK_PERIPH_GPADC;
  358. #endif
  359. gpadc->mode = GP_CONTINUOUS_MODE;
  360. for (i = 0; i < gpadc->channel_num; i++)
  361. {
  362. gpadc->callback[i] = hal_gpadc_callback;
  363. }
  364. };
  365. int hal_gpadc_init(void)
  366. {
  367. hal_gpadc_t *gpadc = &hal_gpadc;
  368. hal_gpadc_setup(gpadc);
  369. if (hal_gpadc_clk_init(gpadc))
  370. {
  371. GPADC_ERR("gpadc init clk error");
  372. return GPADC_CLK_ERROR;
  373. }
  374. GPADC_INFO("gpadc set sample rate");
  375. gpadc_sample_rate_set(gpadc->reg_base, OSC_24MHZ, gpadc->sample_rate);
  376. if (request_irq(gpadc->irq_num, gpadc_handler, IRQF_NO_SUSPEND, "gpadc", gpadc))
  377. {
  378. return GPADC_IRQ_ERROR;
  379. }
  380. enable_irq(gpadc->irq_num);
  381. GPADC_INFO("gpadc enable calibration");
  382. gpadc_calibration_enable(gpadc->reg_base);
  383. gpadc_mode_select(gpadc->reg_base, gpadc->mode);
  384. gpadc_enable(gpadc->reg_base);
  385. return GPADC_OK;
  386. }
  387. hal_gpadc_status_t hal_gpadc_deinit(void)
  388. {
  389. disable_irq(hal_gpadc.irq_num);
  390. #if defined(CONFIG_SOC_SUN20IW1)
  391. hal_clock_disable(hal_gpadc.mbus_clk);
  392. #else
  393. hal_clock_disable(hal_gpadc.mclk);
  394. #endif
  395. return GPADC_OK;
  396. }
  397. //device_initcall(hal_gpadc_init);