123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481 |
- /* ------------------------------------------
- * Copyright (c) 2016, Synopsys, Inc. All rights reserved.
- * Redistribution and use in source and binary forms, with or without modification,
- * are permitted provided that the following conditions are met:
- * 1) Redistributions of source code must retain the above copyright notice, this
- * list of conditions and the following disclaimer.
- * 2) Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation and/or
- * other materials provided with the distribution.
- * 3) Neither the name of the Synopsys, Inc., nor the names of its contributors may
- * be used to endorse or promote products derived from this software without
- * specific prior written permission.
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
- * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
- * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * \version 2016.05
- * \date 2014-07-22
- * \author Wayne Ren(Wei.Ren@synopsys.com)
- --------------------------------------------- */
- /**
- * \defgroup DEVICE_DW_GPIO Designware GPIO Driver
- * \ingroup DEVICE_DW
- * \brief Designware GPIO Driver Implementation
- */
- /**
- * \file
- * \brief designware gpio driver
- * \ingroup DEVICE_DW_GPIO
- * \brief Designware GPIO driver
- */
- #include "inc/embARC_toolchain.h"
- #include "inc/embARC_error.h"
- #include "inc/arc/arc_exception.h"
- #include "device/designware/gpio/dw_gpio.h"
- /** check expressions used in DesignWare GPIO driver implementation */
- #define DW_GPIO_CHECK_EXP(EXPR, ERROR_CODE) CHECK_EXP(EXPR, ercd, ERROR_CODE, error_exit)
- #ifndef DISABLE_DEVICE_OBJECT_VALID_CHECK
- /** valid check of uart info object */
- #define VALID_CHK_GPIO_INFO_OBJECT(gpioinfo_obj_ptr) { \
- DW_GPIO_CHECK_EXP((gpioinfo_obj_ptr)!=NULL, E_OBJ); \
- DW_GPIO_CHECK_EXP(((gpioinfo_obj_ptr)->gpio_ctrl)!=NULL, E_OBJ); \
- }
- #endif
- /**
- * \defgroup DEVICE_DW_GPIO_STATIC DesignWare GPIO Driver Static Functions
- * \ingroup DEVICE_DW_GPIO
- * \brief Static or inline functions, variables for DesignWare GPIO handle gpio operations,
- * only used in this file
- * @{
- */
- Inline uint32_t dw_gpio_read_ext(DW_GPIO_PORT_PTR port)
- {
- return port->regs->EXT_PORTS[port->no];
- }
- Inline uint32_t dw_gpio_read_dir(DW_GPIO_PORT_PTR port)
- {
- return port->regs->SWPORTS[port->no].DDR;
- }
- Inline uint32_t dw_gpio_read_dr(DW_GPIO_PORT_PTR port)
- {
- return port->regs->SWPORTS[port->no].DR;
- }
- Inline uint32_t dw_gpio_read_mthd(DW_GPIO_PORT_PTR port)
- {
- return port->regs->INTEN;
- }
- Inline void dw_gpio_int_enable(DW_GPIO_PORT_PTR port, uint32_t bit_mask)
- {
- port->regs->INTEN |= bit_mask;
- }
- Inline void dw_gpio_int_disable(DW_GPIO_PORT_PTR port, uint32_t bit_mask)
- {
- port->regs->INTEN &= (~bit_mask);
- }
- Inline void dw_gpio_int_mask(DW_GPIO_PORT_PTR port, uint32_t bit_mask)
- {
- port->regs->INTMASK |= bit_mask;
- }
- Inline void dw_gpio_int_unmask(DW_GPIO_PORT_PTR port, uint32_t bit_mask)
- {
- port->regs->INTMASK &= (~bit_mask);
- }
- Inline uint32_t dw_gpio_int_read_level(DW_GPIO_PORT_PTR port)
- {
- return port->regs->INTTYPE_LEVEL;
- }
- Inline uint32_t dw_gpio_int_read_polarity(DW_GPIO_PORT_PTR port)
- {
- return port->regs->INT_POLARITY;
- }
- Inline uint32_t dw_gpio_int_read_debounce(DW_GPIO_PORT_PTR port)
- {
- return port->regs->DEBOUNCE;
- }
- Inline uint32_t dw_gpio_int_read_status(DW_GPIO_PORT_PTR port)
- {
- return port->regs->INTSTATUS;
- }
- Inline void dw_gpio_int_clear(DW_GPIO_PORT_PTR port, uint32_t bit_mask)
- {
- port->regs->PORTA_EOI = bit_mask;
- }
- static void dw_gpio_int_write_level(DW_GPIO_PORT_PTR port, uint32_t bit_mask, uint32_t bit_level)
- {
- uint32_t reg_val;
- reg_val = port->regs->INTTYPE_LEVEL;
- reg_val &= (~bit_mask);
- bit_level &= bit_mask;
- reg_val |= bit_level;
- port->regs->INTTYPE_LEVEL = reg_val;
- }
- static void dw_gpio_int_write_polarity(DW_GPIO_PORT_PTR port, uint32_t bit_mask, uint32_t bit_polarity)
- {
- uint32_t reg_val;
- reg_val = port->regs->INT_POLARITY;
- reg_val &= (~bit_mask);
- bit_polarity &= bit_mask;
- reg_val |= bit_polarity;
- port->regs->INT_POLARITY = reg_val;
- }
- static void dw_gpio_int_write_debounce(DW_GPIO_PORT_PTR port, uint32_t bit_mask, uint32_t bit_debounce)
- {
- uint32_t reg_val;
- reg_val = port->regs->DEBOUNCE;
- reg_val &= (~bit_mask);
- bit_debounce &= bit_mask;
- reg_val |= bit_debounce;
- port->regs->DEBOUNCE = reg_val;
- }
- static void dw_gpio_set_int_cfg(DW_GPIO_PORT_PTR port, DEV_GPIO_INT_CFG *int_cfg)
- {
- dw_gpio_int_write_level(port, int_cfg->int_bit_mask, int_cfg->int_bit_type);
- dw_gpio_int_write_polarity(port, int_cfg->int_bit_mask, int_cfg->int_bit_polarity);
- dw_gpio_int_write_debounce(port, int_cfg->int_bit_mask, int_cfg->int_bit_debounce);
- }
- static void dw_gpio_get_int_cfg(DW_GPIO_PORT_PTR port, DEV_GPIO_INT_CFG *int_cfg)
- {
- int_cfg->int_bit_type = dw_gpio_int_read_level(port) & int_cfg->int_bit_mask;
- int_cfg->int_bit_polarity = dw_gpio_int_read_polarity(port) & int_cfg->int_bit_mask;
- int_cfg->int_bit_debounce = dw_gpio_int_read_debounce(port) & int_cfg->int_bit_mask;
- }
- static void dw_gpio_write_dr(DW_GPIO_PORT_PTR port, uint32_t bit_mask, uint32_t val)
- {
- uint32_t temp_reg;
- temp_reg = port->regs->SWPORTS[port->no].DR;
- temp_reg &= ~bit_mask;
- val &= bit_mask;
- temp_reg |= val;
- port->regs->SWPORTS[port->no].DR = temp_reg;
- }
- static void dw_gpio_write_dir(DW_GPIO_PORT_PTR port, uint32_t bit_mask, uint32_t val)
- {
- uint32_t temp_reg;
- temp_reg = port->regs->SWPORTS[port->no].DDR;
- temp_reg &= ~bit_mask;
- val &= bit_mask;
- temp_reg |= val;
- port->regs->SWPORTS[port->no].DDR = temp_reg;
- }
- static uint32_t dw_gpio_read_val(DW_GPIO_PORT_PTR port)
- {
- uint32_t val;
- val = dw_gpio_read_ext(port) & (~dw_gpio_read_dir(port));
- val |= dw_gpio_read_dr(port) & dw_gpio_read_dir(port);
- return val;
- }
- /** @} end of group DEVICE_DW_GPIO_STATIC */
- /* interface for DEV_GPIO */
- /** Open designware gpio device with specified io direction configuration */
- int32_t dw_gpio_open(DEV_GPIO *gpio_obj, uint32_t dir)
- {
- int32_t ercd = E_OK;
- DEV_GPIO_INFO_PTR port_info_ptr = &(gpio_obj->gpio_info);
- /* START ERROR CHECK */
- VALID_CHK_GPIO_INFO_OBJECT(port_info_ptr);
- /* END OF ERROR CHECK */
- DW_GPIO_PORT_PTR port = (DW_GPIO_PORT_PTR)(port_info_ptr->gpio_ctrl);
- DW_GPIO_CHECK_EXP(port->no <= DW_GPIO_PORT_D, E_OBJ);
- port_info_ptr->opn_cnt ++;
- if (port_info_ptr->opn_cnt > 1) { /* opened before */
- if (dir == port_info_ptr->direction) { /* direction is the same */
- return E_OK;
- } else { /* open with different direction */
- return E_OPNED;
- }
- }
- dw_gpio_write_dir(port, port->valid_bit_mask, dir);
- if (port->no == DW_GPIO_PORT_A) {
- dw_gpio_int_clear(port, DW_GPIO_MASK_ALL);
- dw_gpio_int_disable(port, DW_GPIO_MASK_ALL);
- dw_gpio_int_unmask(port, DW_GPIO_MASK_ALL);
- /* install gpio interrupt handler */
- int_handler_install(port->intno, port->int_handler);
- int_disable(port->intno);
- /** Set int type, int polarity and debounce configuration to default settings of device gpio */
- dw_gpio_set_int_cfg(port, (DEV_GPIO_INT_CFG *)(&gpio_int_cfg_default));
- port_info_ptr->method = dw_gpio_read_mthd(port);
- } else {
- port_info_ptr->method = DEV_GPIO_BITS_MTHD_DEFAULT;
- }
- dw_gpio_write_dr(port, port->valid_bit_mask, 0);
- port_info_ptr->direction = dir;
- port_info_ptr->extra = NULL;
- error_exit:
- return ercd;
- }
- /** Close designware gpio device */
- int32_t dw_gpio_close(DEV_GPIO *gpio_obj)
- {
- int32_t ercd = E_OK;
- DEV_GPIO_INFO_PTR port_info_ptr = &(gpio_obj->gpio_info);
- /* START ERROR CHECK */
- VALID_CHK_GPIO_INFO_OBJECT(port_info_ptr);
- /* END OF ERROR CHECK */
- DW_GPIO_PORT_PTR port = (DW_GPIO_PORT_PTR)(port_info_ptr->gpio_ctrl);
- DW_GPIO_CHECK_EXP(port->no <= DW_GPIO_PORT_D, E_OBJ);
- DW_GPIO_CHECK_EXP(port_info_ptr->opn_cnt > 0, E_OK);
- port_info_ptr->opn_cnt --;
- if (port_info_ptr->opn_cnt == 0) {
- dw_gpio_write_dr(port, port->valid_bit_mask, 0);
- dw_gpio_write_dir(port, port->valid_bit_mask, 0);
- if (port->no == DW_GPIO_PORT_A) {
- dw_gpio_int_clear(port, DW_GPIO_MASK_ALL);
- dw_gpio_int_disable(port, DW_GPIO_MASK_ALL);
- int_disable(port->intno);
- }
- port_info_ptr->direction = 0;
- port_info_ptr->method = 0;
- port_info_ptr->extra = NULL;
- } else {
- ercd = E_OPNED;
- }
- error_exit:
- return ercd;
- }
- /** Read designware gpio device value */
- int32_t dw_gpio_read(DEV_GPIO *gpio_obj, uint32_t *val, uint32_t mask)
- {
- int32_t ercd = E_OK;
- DEV_GPIO_INFO_PTR port_info_ptr = &(gpio_obj->gpio_info);
- /* START ERROR CHECK */
- VALID_CHK_GPIO_INFO_OBJECT(port_info_ptr);
- /* END OF ERROR CHECK */
- DW_GPIO_PORT_PTR port = (DW_GPIO_PORT_PTR)(port_info_ptr->gpio_ctrl);
- DW_GPIO_CHECK_EXP(port->no <= DW_GPIO_PORT_D, E_OBJ);
- DW_GPIO_CHECK_EXP(port_info_ptr->opn_cnt > 0, E_CLSED);
- DW_GPIO_CHECK_EXP(val!=NULL, E_PAR);
- //*val = dw_gpio_read_ext(port) & mask;
- *val = dw_gpio_read_val(port) & mask;
- error_exit:
- return ercd;
- }
- /** Write designware gpio device value */
- int32_t dw_gpio_write(DEV_GPIO *gpio_obj, uint32_t val, uint32_t mask)
- {
- int32_t ercd = E_OK;
- DEV_GPIO_INFO_PTR port_info_ptr = &(gpio_obj->gpio_info);
- /* START ERROR CHECK */
- VALID_CHK_GPIO_INFO_OBJECT(port_info_ptr);
- /* END OF ERROR CHECK */
- DW_GPIO_PORT_PTR port = (DW_GPIO_PORT_PTR)(port_info_ptr->gpio_ctrl);
- DW_GPIO_CHECK_EXP(port->no <= DW_GPIO_PORT_D, E_OBJ);
- DW_GPIO_CHECK_EXP(port_info_ptr->opn_cnt > 0, E_CLSED);
- dw_gpio_write_dr(port, mask, val);
- error_exit:
- return ercd;
- }
- /** Control designware gpio device */
- int32_t dw_gpio_control(DEV_GPIO *gpio_obj, uint32_t ctrl_cmd, void *param)
- {
- int32_t ercd = E_OK;
- DEV_GPIO_INFO_PTR port_info_ptr = &(gpio_obj->gpio_info);
- /* START ERROR CHECK */
- VALID_CHK_GPIO_INFO_OBJECT(port_info_ptr);
- /* END OF ERROR CHECK */
- DW_GPIO_PORT_PTR port = (DW_GPIO_PORT_PTR)(port_info_ptr->gpio_ctrl);
- DW_GPIO_CHECK_EXP(port->no <= DW_GPIO_PORT_D, E_OBJ);
- DW_GPIO_CHECK_EXP(port_info_ptr->opn_cnt > 0, E_CLSED);
- uint32_t val32; /** to receive unsigned int value */
- if (ctrl_cmd == GPIO_CMD_SET_BIT_DIR_INPUT) {
- val32 = (uint32_t)param;
- dw_gpio_write_dir(port, val32, DW_GPIO_INPUT_ALL);
- port_info_ptr->direction = dw_gpio_read_dir(port);
- } else if (ctrl_cmd == GPIO_CMD_SET_BIT_DIR_OUTPUT) {
- val32 = (uint32_t)param;
- dw_gpio_write_dir(port, val32, DW_GPIO_OUTPUT_ALL);
- port_info_ptr->direction = dw_gpio_read_dir(port);
- } else if (ctrl_cmd == GPIO_CMD_GET_BIT_DIR) {
- DW_GPIO_CHECK_EXP((param!=NULL) && CHECK_ALIGN_4BYTES(param), E_PAR);
- port_info_ptr->direction = dw_gpio_read_dir(port);
- *((int32_t *)param) = port_info_ptr->direction;
- } else {
- DW_GPIO_CHECK_EXP(port->no == DW_GPIO_PORT_A, E_NOSPT);
- /* output pin cannot be used as interrupt */
- DEV_GPIO_INT_CFG *gpio_int_cfg;
- DEV_GPIO_BIT_ISR *port_bit_isr;
- switch (ctrl_cmd) {
- case GPIO_CMD_SET_BIT_INT_CFG:
- DW_GPIO_CHECK_EXP((param!=NULL) && CHECK_ALIGN_4BYTES(param), E_PAR);
- gpio_int_cfg = (DEV_GPIO_INT_CFG *)param;
- dw_gpio_set_int_cfg(port, gpio_int_cfg);
- break;
- case GPIO_CMD_GET_BIT_INT_CFG:
- DW_GPIO_CHECK_EXP((param!=NULL) && CHECK_ALIGN_4BYTES(param), E_PAR);
- gpio_int_cfg = (DEV_GPIO_INT_CFG *)param;
- /** read configuration, each bit stands for different configuration */
- dw_gpio_get_int_cfg(port, gpio_int_cfg);
- break;
- case GPIO_CMD_SET_BIT_ISR:
- DW_GPIO_CHECK_EXP((param!=NULL) && CHECK_ALIGN_4BYTES(param), E_PAR);
- port_bit_isr = (DEV_GPIO_BIT_ISR *)param;
- if (port_bit_isr->int_bit_ofs < port->gpio_bit_isr->int_bit_max_cnt) {
- port->gpio_bit_isr->int_bit_handler_ptr[port_bit_isr->int_bit_ofs] = port_bit_isr->int_bit_handler;
- } else {
- ercd = E_PAR;
- }
- break;
- case GPIO_CMD_GET_BIT_ISR:
- DW_GPIO_CHECK_EXP((param!=NULL) && CHECK_ALIGN_4BYTES(param), E_PAR);
- port_bit_isr = (DEV_GPIO_BIT_ISR *)param;
- if (port_bit_isr->int_bit_ofs < port->gpio_bit_isr->int_bit_max_cnt) {
- port_bit_isr->int_bit_handler = port->gpio_bit_isr->int_bit_handler_ptr[port_bit_isr->int_bit_ofs];
- } else {
- ercd = E_PAR;
- }
- break;
- case GPIO_CMD_ENA_BIT_INT:
- val32 = (uint32_t)param;
- dw_gpio_int_enable(port, val32);
- port_info_ptr->method = dw_gpio_read_mthd(port);
- if (port_info_ptr->method) {
- int_enable(port->intno);
- }
- break;
- case GPIO_CMD_DIS_BIT_INT:
- val32 = (uint32_t)param;
- dw_gpio_int_disable(port, val32);
- port_info_ptr->method = dw_gpio_read_mthd(port);
- if (port_info_ptr->method == 0) {
- int_disable(port->intno);
- }
- break;
- case GPIO_CMD_GET_BIT_MTHD:
- DW_GPIO_CHECK_EXP((param!=NULL) && CHECK_ALIGN_4BYTES(param), E_PAR);
- port_info_ptr->method = dw_gpio_read_mthd(port);
- *((int32_t *)param) = port_info_ptr->method;
- break;
- default:
- ercd = E_NOSPT;
- break;
- }
- }
- error_exit:
- return ercd;
- }
- /** designware gpio interrupt process */
- int32_t dw_gpio_isr_handler(DEV_GPIO *gpio_obj, void *ptr)
- {
- int32_t ercd = E_OK;
- DEV_GPIO_INFO_PTR port_info_ptr = &(gpio_obj->gpio_info);
- /* START ERROR CHECK */
- VALID_CHK_GPIO_INFO_OBJECT(port_info_ptr);
- /* END OF ERROR CHECK */
- DW_GPIO_PORT_PTR port = (DW_GPIO_PORT_PTR)(port_info_ptr->gpio_ctrl);
- DW_GPIO_CHECK_EXP(port->no == DW_GPIO_PORT_A, E_NOSPT);
- uint32_t i, gpio_bit_isr_state;
- uint32_t max_int_bit_count = 0;
- /** read interrupt status */
- gpio_bit_isr_state = dw_gpio_int_read_status(port);
- if (port->gpio_bit_isr) {
- max_int_bit_count = (port->gpio_bit_isr->int_bit_max_cnt);
- } else {
- dw_gpio_int_clear(port, gpio_bit_isr_state);
- }
- for (i=0; i<max_int_bit_count; i++) {
- if (gpio_bit_isr_state & (1<<i)) {
- /* this bit interrupt enabled */
- if (port->gpio_bit_isr->int_bit_handler_ptr[i]) {
- port->gpio_bit_isr->int_bit_handler_ptr[i](gpio_obj);
- }
- dw_gpio_int_clear(port, (1<<i)); /** clear this bit interrupt */
- }
- }
- error_exit:
- return ercd;
- }
|