dw_gpio.c 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481
  1. /* ------------------------------------------
  2. * Copyright (c) 2016, Synopsys, Inc. All rights reserved.
  3. * Redistribution and use in source and binary forms, with or without modification,
  4. * are permitted provided that the following conditions are met:
  5. * 1) Redistributions of source code must retain the above copyright notice, this
  6. * list of conditions and the following disclaimer.
  7. * 2) Redistributions in binary form must reproduce the above copyright notice,
  8. * this list of conditions and the following disclaimer in the documentation and/or
  9. * other materials provided with the distribution.
  10. * 3) Neither the name of the Synopsys, Inc., nor the names of its contributors may
  11. * be used to endorse or promote products derived from this software without
  12. * specific prior written permission.
  13. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
  14. * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  15. * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  16. * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
  17. * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
  18. * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  19. * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
  20. * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  21. * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  22. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  23. *
  24. * \version 2016.05
  25. * \date 2014-07-22
  26. * \author Wayne Ren(Wei.Ren@synopsys.com)
  27. --------------------------------------------- */
  28. /**
  29. * \defgroup DEVICE_DW_GPIO Designware GPIO Driver
  30. * \ingroup DEVICE_DW
  31. * \brief Designware GPIO Driver Implementation
  32. */
  33. /**
  34. * \file
  35. * \brief designware gpio driver
  36. * \ingroup DEVICE_DW_GPIO
  37. * \brief Designware GPIO driver
  38. */
  39. #include "inc/embARC_toolchain.h"
  40. #include "inc/embARC_error.h"
  41. #include "inc/arc/arc_exception.h"
  42. #include "device/designware/gpio/dw_gpio.h"
  43. /** check expressions used in DesignWare GPIO driver implementation */
  44. #define DW_GPIO_CHECK_EXP(EXPR, ERROR_CODE) CHECK_EXP(EXPR, ercd, ERROR_CODE, error_exit)
  45. #ifndef DISABLE_DEVICE_OBJECT_VALID_CHECK
  46. /** valid check of uart info object */
  47. #define VALID_CHK_GPIO_INFO_OBJECT(gpioinfo_obj_ptr) { \
  48. DW_GPIO_CHECK_EXP((gpioinfo_obj_ptr)!=NULL, E_OBJ); \
  49. DW_GPIO_CHECK_EXP(((gpioinfo_obj_ptr)->gpio_ctrl)!=NULL, E_OBJ); \
  50. }
  51. #endif
  52. /**
  53. * \defgroup DEVICE_DW_GPIO_STATIC DesignWare GPIO Driver Static Functions
  54. * \ingroup DEVICE_DW_GPIO
  55. * \brief Static or inline functions, variables for DesignWare GPIO handle gpio operations,
  56. * only used in this file
  57. * @{
  58. */
  59. Inline uint32_t dw_gpio_read_ext(DW_GPIO_PORT_PTR port)
  60. {
  61. return port->regs->EXT_PORTS[port->no];
  62. }
  63. Inline uint32_t dw_gpio_read_dir(DW_GPIO_PORT_PTR port)
  64. {
  65. return port->regs->SWPORTS[port->no].DDR;
  66. }
  67. Inline uint32_t dw_gpio_read_dr(DW_GPIO_PORT_PTR port)
  68. {
  69. return port->regs->SWPORTS[port->no].DR;
  70. }
  71. Inline uint32_t dw_gpio_read_mthd(DW_GPIO_PORT_PTR port)
  72. {
  73. return port->regs->INTEN;
  74. }
  75. Inline void dw_gpio_int_enable(DW_GPIO_PORT_PTR port, uint32_t bit_mask)
  76. {
  77. port->regs->INTEN |= bit_mask;
  78. }
  79. Inline void dw_gpio_int_disable(DW_GPIO_PORT_PTR port, uint32_t bit_mask)
  80. {
  81. port->regs->INTEN &= (~bit_mask);
  82. }
  83. Inline void dw_gpio_int_mask(DW_GPIO_PORT_PTR port, uint32_t bit_mask)
  84. {
  85. port->regs->INTMASK |= bit_mask;
  86. }
  87. Inline void dw_gpio_int_unmask(DW_GPIO_PORT_PTR port, uint32_t bit_mask)
  88. {
  89. port->regs->INTMASK &= (~bit_mask);
  90. }
  91. Inline uint32_t dw_gpio_int_read_level(DW_GPIO_PORT_PTR port)
  92. {
  93. return port->regs->INTTYPE_LEVEL;
  94. }
  95. Inline uint32_t dw_gpio_int_read_polarity(DW_GPIO_PORT_PTR port)
  96. {
  97. return port->regs->INT_POLARITY;
  98. }
  99. Inline uint32_t dw_gpio_int_read_debounce(DW_GPIO_PORT_PTR port)
  100. {
  101. return port->regs->DEBOUNCE;
  102. }
  103. Inline uint32_t dw_gpio_int_read_status(DW_GPIO_PORT_PTR port)
  104. {
  105. return port->regs->INTSTATUS;
  106. }
  107. Inline void dw_gpio_int_clear(DW_GPIO_PORT_PTR port, uint32_t bit_mask)
  108. {
  109. port->regs->PORTA_EOI = bit_mask;
  110. }
  111. static void dw_gpio_int_write_level(DW_GPIO_PORT_PTR port, uint32_t bit_mask, uint32_t bit_level)
  112. {
  113. uint32_t reg_val;
  114. reg_val = port->regs->INTTYPE_LEVEL;
  115. reg_val &= (~bit_mask);
  116. bit_level &= bit_mask;
  117. reg_val |= bit_level;
  118. port->regs->INTTYPE_LEVEL = reg_val;
  119. }
  120. static void dw_gpio_int_write_polarity(DW_GPIO_PORT_PTR port, uint32_t bit_mask, uint32_t bit_polarity)
  121. {
  122. uint32_t reg_val;
  123. reg_val = port->regs->INT_POLARITY;
  124. reg_val &= (~bit_mask);
  125. bit_polarity &= bit_mask;
  126. reg_val |= bit_polarity;
  127. port->regs->INT_POLARITY = reg_val;
  128. }
  129. static void dw_gpio_int_write_debounce(DW_GPIO_PORT_PTR port, uint32_t bit_mask, uint32_t bit_debounce)
  130. {
  131. uint32_t reg_val;
  132. reg_val = port->regs->DEBOUNCE;
  133. reg_val &= (~bit_mask);
  134. bit_debounce &= bit_mask;
  135. reg_val |= bit_debounce;
  136. port->regs->DEBOUNCE = reg_val;
  137. }
  138. static void dw_gpio_set_int_cfg(DW_GPIO_PORT_PTR port, DEV_GPIO_INT_CFG *int_cfg)
  139. {
  140. dw_gpio_int_write_level(port, int_cfg->int_bit_mask, int_cfg->int_bit_type);
  141. dw_gpio_int_write_polarity(port, int_cfg->int_bit_mask, int_cfg->int_bit_polarity);
  142. dw_gpio_int_write_debounce(port, int_cfg->int_bit_mask, int_cfg->int_bit_debounce);
  143. }
  144. static void dw_gpio_get_int_cfg(DW_GPIO_PORT_PTR port, DEV_GPIO_INT_CFG *int_cfg)
  145. {
  146. int_cfg->int_bit_type = dw_gpio_int_read_level(port) & int_cfg->int_bit_mask;
  147. int_cfg->int_bit_polarity = dw_gpio_int_read_polarity(port) & int_cfg->int_bit_mask;
  148. int_cfg->int_bit_debounce = dw_gpio_int_read_debounce(port) & int_cfg->int_bit_mask;
  149. }
  150. static void dw_gpio_write_dr(DW_GPIO_PORT_PTR port, uint32_t bit_mask, uint32_t val)
  151. {
  152. uint32_t temp_reg;
  153. temp_reg = port->regs->SWPORTS[port->no].DR;
  154. temp_reg &= ~bit_mask;
  155. val &= bit_mask;
  156. temp_reg |= val;
  157. port->regs->SWPORTS[port->no].DR = temp_reg;
  158. }
  159. static void dw_gpio_write_dir(DW_GPIO_PORT_PTR port, uint32_t bit_mask, uint32_t val)
  160. {
  161. uint32_t temp_reg;
  162. temp_reg = port->regs->SWPORTS[port->no].DDR;
  163. temp_reg &= ~bit_mask;
  164. val &= bit_mask;
  165. temp_reg |= val;
  166. port->regs->SWPORTS[port->no].DDR = temp_reg;
  167. }
  168. static uint32_t dw_gpio_read_val(DW_GPIO_PORT_PTR port)
  169. {
  170. uint32_t val;
  171. val = dw_gpio_read_ext(port) & (~dw_gpio_read_dir(port));
  172. val |= dw_gpio_read_dr(port) & dw_gpio_read_dir(port);
  173. return val;
  174. }
  175. /** @} end of group DEVICE_DW_GPIO_STATIC */
  176. /* interface for DEV_GPIO */
  177. /** Open designware gpio device with specified io direction configuration */
  178. int32_t dw_gpio_open(DEV_GPIO *gpio_obj, uint32_t dir)
  179. {
  180. int32_t ercd = E_OK;
  181. DEV_GPIO_INFO_PTR port_info_ptr = &(gpio_obj->gpio_info);
  182. /* START ERROR CHECK */
  183. VALID_CHK_GPIO_INFO_OBJECT(port_info_ptr);
  184. /* END OF ERROR CHECK */
  185. DW_GPIO_PORT_PTR port = (DW_GPIO_PORT_PTR)(port_info_ptr->gpio_ctrl);
  186. DW_GPIO_CHECK_EXP(port->no <= DW_GPIO_PORT_D, E_OBJ);
  187. port_info_ptr->opn_cnt ++;
  188. if (port_info_ptr->opn_cnt > 1) { /* opened before */
  189. if (dir == port_info_ptr->direction) { /* direction is the same */
  190. return E_OK;
  191. } else { /* open with different direction */
  192. return E_OPNED;
  193. }
  194. }
  195. dw_gpio_write_dir(port, port->valid_bit_mask, dir);
  196. if (port->no == DW_GPIO_PORT_A) {
  197. dw_gpio_int_clear(port, DW_GPIO_MASK_ALL);
  198. dw_gpio_int_disable(port, DW_GPIO_MASK_ALL);
  199. dw_gpio_int_unmask(port, DW_GPIO_MASK_ALL);
  200. /* install gpio interrupt handler */
  201. int_handler_install(port->intno, port->int_handler);
  202. int_disable(port->intno);
  203. /** Set int type, int polarity and debounce configuration to default settings of device gpio */
  204. dw_gpio_set_int_cfg(port, (DEV_GPIO_INT_CFG *)(&gpio_int_cfg_default));
  205. port_info_ptr->method = dw_gpio_read_mthd(port);
  206. } else {
  207. port_info_ptr->method = DEV_GPIO_BITS_MTHD_DEFAULT;
  208. }
  209. dw_gpio_write_dr(port, port->valid_bit_mask, 0);
  210. port_info_ptr->direction = dir;
  211. port_info_ptr->extra = NULL;
  212. error_exit:
  213. return ercd;
  214. }
  215. /** Close designware gpio device */
  216. int32_t dw_gpio_close(DEV_GPIO *gpio_obj)
  217. {
  218. int32_t ercd = E_OK;
  219. DEV_GPIO_INFO_PTR port_info_ptr = &(gpio_obj->gpio_info);
  220. /* START ERROR CHECK */
  221. VALID_CHK_GPIO_INFO_OBJECT(port_info_ptr);
  222. /* END OF ERROR CHECK */
  223. DW_GPIO_PORT_PTR port = (DW_GPIO_PORT_PTR)(port_info_ptr->gpio_ctrl);
  224. DW_GPIO_CHECK_EXP(port->no <= DW_GPIO_PORT_D, E_OBJ);
  225. DW_GPIO_CHECK_EXP(port_info_ptr->opn_cnt > 0, E_OK);
  226. port_info_ptr->opn_cnt --;
  227. if (port_info_ptr->opn_cnt == 0) {
  228. dw_gpio_write_dr(port, port->valid_bit_mask, 0);
  229. dw_gpio_write_dir(port, port->valid_bit_mask, 0);
  230. if (port->no == DW_GPIO_PORT_A) {
  231. dw_gpio_int_clear(port, DW_GPIO_MASK_ALL);
  232. dw_gpio_int_disable(port, DW_GPIO_MASK_ALL);
  233. int_disable(port->intno);
  234. }
  235. port_info_ptr->direction = 0;
  236. port_info_ptr->method = 0;
  237. port_info_ptr->extra = NULL;
  238. } else {
  239. ercd = E_OPNED;
  240. }
  241. error_exit:
  242. return ercd;
  243. }
  244. /** Read designware gpio device value */
  245. int32_t dw_gpio_read(DEV_GPIO *gpio_obj, uint32_t *val, uint32_t mask)
  246. {
  247. int32_t ercd = E_OK;
  248. DEV_GPIO_INFO_PTR port_info_ptr = &(gpio_obj->gpio_info);
  249. /* START ERROR CHECK */
  250. VALID_CHK_GPIO_INFO_OBJECT(port_info_ptr);
  251. /* END OF ERROR CHECK */
  252. DW_GPIO_PORT_PTR port = (DW_GPIO_PORT_PTR)(port_info_ptr->gpio_ctrl);
  253. DW_GPIO_CHECK_EXP(port->no <= DW_GPIO_PORT_D, E_OBJ);
  254. DW_GPIO_CHECK_EXP(port_info_ptr->opn_cnt > 0, E_CLSED);
  255. DW_GPIO_CHECK_EXP(val!=NULL, E_PAR);
  256. //*val = dw_gpio_read_ext(port) & mask;
  257. *val = dw_gpio_read_val(port) & mask;
  258. error_exit:
  259. return ercd;
  260. }
  261. /** Write designware gpio device value */
  262. int32_t dw_gpio_write(DEV_GPIO *gpio_obj, uint32_t val, uint32_t mask)
  263. {
  264. int32_t ercd = E_OK;
  265. DEV_GPIO_INFO_PTR port_info_ptr = &(gpio_obj->gpio_info);
  266. /* START ERROR CHECK */
  267. VALID_CHK_GPIO_INFO_OBJECT(port_info_ptr);
  268. /* END OF ERROR CHECK */
  269. DW_GPIO_PORT_PTR port = (DW_GPIO_PORT_PTR)(port_info_ptr->gpio_ctrl);
  270. DW_GPIO_CHECK_EXP(port->no <= DW_GPIO_PORT_D, E_OBJ);
  271. DW_GPIO_CHECK_EXP(port_info_ptr->opn_cnt > 0, E_CLSED);
  272. dw_gpio_write_dr(port, mask, val);
  273. error_exit:
  274. return ercd;
  275. }
  276. /** Control designware gpio device */
  277. int32_t dw_gpio_control(DEV_GPIO *gpio_obj, uint32_t ctrl_cmd, void *param)
  278. {
  279. int32_t ercd = E_OK;
  280. DEV_GPIO_INFO_PTR port_info_ptr = &(gpio_obj->gpio_info);
  281. /* START ERROR CHECK */
  282. VALID_CHK_GPIO_INFO_OBJECT(port_info_ptr);
  283. /* END OF ERROR CHECK */
  284. DW_GPIO_PORT_PTR port = (DW_GPIO_PORT_PTR)(port_info_ptr->gpio_ctrl);
  285. DW_GPIO_CHECK_EXP(port->no <= DW_GPIO_PORT_D, E_OBJ);
  286. DW_GPIO_CHECK_EXP(port_info_ptr->opn_cnt > 0, E_CLSED);
  287. uint32_t val32; /** to receive unsigned int value */
  288. if (ctrl_cmd == GPIO_CMD_SET_BIT_DIR_INPUT) {
  289. val32 = (uint32_t)param;
  290. dw_gpio_write_dir(port, val32, DW_GPIO_INPUT_ALL);
  291. port_info_ptr->direction = dw_gpio_read_dir(port);
  292. } else if (ctrl_cmd == GPIO_CMD_SET_BIT_DIR_OUTPUT) {
  293. val32 = (uint32_t)param;
  294. dw_gpio_write_dir(port, val32, DW_GPIO_OUTPUT_ALL);
  295. port_info_ptr->direction = dw_gpio_read_dir(port);
  296. } else if (ctrl_cmd == GPIO_CMD_GET_BIT_DIR) {
  297. DW_GPIO_CHECK_EXP((param!=NULL) && CHECK_ALIGN_4BYTES(param), E_PAR);
  298. port_info_ptr->direction = dw_gpio_read_dir(port);
  299. *((int32_t *)param) = port_info_ptr->direction;
  300. } else {
  301. DW_GPIO_CHECK_EXP(port->no == DW_GPIO_PORT_A, E_NOSPT);
  302. /* output pin cannot be used as interrupt */
  303. DEV_GPIO_INT_CFG *gpio_int_cfg;
  304. DEV_GPIO_BIT_ISR *port_bit_isr;
  305. switch (ctrl_cmd) {
  306. case GPIO_CMD_SET_BIT_INT_CFG:
  307. DW_GPIO_CHECK_EXP((param!=NULL) && CHECK_ALIGN_4BYTES(param), E_PAR);
  308. gpio_int_cfg = (DEV_GPIO_INT_CFG *)param;
  309. dw_gpio_set_int_cfg(port, gpio_int_cfg);
  310. break;
  311. case GPIO_CMD_GET_BIT_INT_CFG:
  312. DW_GPIO_CHECK_EXP((param!=NULL) && CHECK_ALIGN_4BYTES(param), E_PAR);
  313. gpio_int_cfg = (DEV_GPIO_INT_CFG *)param;
  314. /** read configuration, each bit stands for different configuration */
  315. dw_gpio_get_int_cfg(port, gpio_int_cfg);
  316. break;
  317. case GPIO_CMD_SET_BIT_ISR:
  318. DW_GPIO_CHECK_EXP((param!=NULL) && CHECK_ALIGN_4BYTES(param), E_PAR);
  319. port_bit_isr = (DEV_GPIO_BIT_ISR *)param;
  320. if (port_bit_isr->int_bit_ofs < port->gpio_bit_isr->int_bit_max_cnt) {
  321. port->gpio_bit_isr->int_bit_handler_ptr[port_bit_isr->int_bit_ofs] = port_bit_isr->int_bit_handler;
  322. } else {
  323. ercd = E_PAR;
  324. }
  325. break;
  326. case GPIO_CMD_GET_BIT_ISR:
  327. DW_GPIO_CHECK_EXP((param!=NULL) && CHECK_ALIGN_4BYTES(param), E_PAR);
  328. port_bit_isr = (DEV_GPIO_BIT_ISR *)param;
  329. if (port_bit_isr->int_bit_ofs < port->gpio_bit_isr->int_bit_max_cnt) {
  330. port_bit_isr->int_bit_handler = port->gpio_bit_isr->int_bit_handler_ptr[port_bit_isr->int_bit_ofs];
  331. } else {
  332. ercd = E_PAR;
  333. }
  334. break;
  335. case GPIO_CMD_ENA_BIT_INT:
  336. val32 = (uint32_t)param;
  337. dw_gpio_int_enable(port, val32);
  338. port_info_ptr->method = dw_gpio_read_mthd(port);
  339. if (port_info_ptr->method) {
  340. int_enable(port->intno);
  341. }
  342. break;
  343. case GPIO_CMD_DIS_BIT_INT:
  344. val32 = (uint32_t)param;
  345. dw_gpio_int_disable(port, val32);
  346. port_info_ptr->method = dw_gpio_read_mthd(port);
  347. if (port_info_ptr->method == 0) {
  348. int_disable(port->intno);
  349. }
  350. break;
  351. case GPIO_CMD_GET_BIT_MTHD:
  352. DW_GPIO_CHECK_EXP((param!=NULL) && CHECK_ALIGN_4BYTES(param), E_PAR);
  353. port_info_ptr->method = dw_gpio_read_mthd(port);
  354. *((int32_t *)param) = port_info_ptr->method;
  355. break;
  356. default:
  357. ercd = E_NOSPT;
  358. break;
  359. }
  360. }
  361. error_exit:
  362. return ercd;
  363. }
  364. /** designware gpio interrupt process */
  365. int32_t dw_gpio_isr_handler(DEV_GPIO *gpio_obj, void *ptr)
  366. {
  367. int32_t ercd = E_OK;
  368. DEV_GPIO_INFO_PTR port_info_ptr = &(gpio_obj->gpio_info);
  369. /* START ERROR CHECK */
  370. VALID_CHK_GPIO_INFO_OBJECT(port_info_ptr);
  371. /* END OF ERROR CHECK */
  372. DW_GPIO_PORT_PTR port = (DW_GPIO_PORT_PTR)(port_info_ptr->gpio_ctrl);
  373. DW_GPIO_CHECK_EXP(port->no == DW_GPIO_PORT_A, E_NOSPT);
  374. uint32_t i, gpio_bit_isr_state;
  375. uint32_t max_int_bit_count = 0;
  376. /** read interrupt status */
  377. gpio_bit_isr_state = dw_gpio_int_read_status(port);
  378. if (port->gpio_bit_isr) {
  379. max_int_bit_count = (port->gpio_bit_isr->int_bit_max_cnt);
  380. } else {
  381. dw_gpio_int_clear(port, gpio_bit_isr_state);
  382. }
  383. for (i=0; i<max_int_bit_count; i++) {
  384. if (gpio_bit_isr_state & (1<<i)) {
  385. /* this bit interrupt enabled */
  386. if (port->gpio_bit_isr->int_bit_handler_ptr[i]) {
  387. port->gpio_bit_isr->int_bit_handler_ptr[i](gpio_obj);
  388. }
  389. dw_gpio_int_clear(port, (1<<i)); /** clear this bit interrupt */
  390. }
  391. }
  392. error_exit:
  393. return ercd;
  394. }