1297 lines
36 KiB
C
1297 lines
36 KiB
C
/**
|
|
* @file sdrv_gpio.c
|
|
* @brief Sdrv GPIO driver.
|
|
*
|
|
* @copyright Copyright (c) 2022 Semidrive Semiconductor.
|
|
* All rights reserved.
|
|
*/
|
|
|
|
#include <bits.h>
|
|
#include <debug.h>
|
|
#include <device_pin.h>
|
|
#include <irq.h>
|
|
#include <irq_num.h>
|
|
#include <param.h>
|
|
#include <part.h>
|
|
#include <reg.h>
|
|
#include <regs_base.h>
|
|
#include <sdrv_gpio.h>
|
|
#include <types.h>
|
|
|
|
#define REG_OEN_OFFSET (0x580u)
|
|
#define REG_DATA_IN_OFFSET (0x600u)
|
|
#define REG_DATA_OUT_OFFSET (0x680u)
|
|
#define REG_SINT_EN_OFFSET (0x700u)
|
|
#define REG_SINT_MASK_OFFSET (0x780u)
|
|
#define REG_SINT_TYPE_OFFSET (0x800u)
|
|
#define REG_SINT_POL_OFFSET (0x880u)
|
|
#define REG_SINT_BOE_OFFSET (0x900u)
|
|
#define REG_SINT_STATUS_OFFSET (0x980u)
|
|
#define REG_SINT_STATUS_UNMASK_OFFSET (0xa00u)
|
|
#define REG_SINT_EDGE_CLR_OFFSET (0xa80u)
|
|
#define REG_AINT_EN_OFFSET (0xb00u)
|
|
#define REG_AINT_MASK_OFFSET (0xb80u)
|
|
#define REG_AINT_TYPE_OFFSET (0xc00u)
|
|
#define REG_AINT_POL_OFFSET (0xc80u)
|
|
#define REG_AINT_BOE_OFFSET (0xd00u)
|
|
#define REG_AINT_STATUS_OFFSET (0xd80u)
|
|
#define REG_AINT_STATUS_UNMASK_OFFSET (0xe00u)
|
|
#define REG_AINT_EDGE_CLR_OFFSET (0xe80u)
|
|
|
|
#define REG_INT_SHARE(p) ((p)*0x4 + 0x1000)
|
|
|
|
/* GPIO controller register bits */
|
|
#define DIR_IN 0
|
|
#define DIR_OUT 1
|
|
#define INT_TYPE_LEVEL_SENSITIVE 0
|
|
#define INT_TYPE_EDGE_SENSITIVE 1
|
|
#define INT_POLARITY_LOW_OR_NEGATIVE 0
|
|
#define INT_POLARITY_HIGH_OR_POSITIVE 1
|
|
#define INT_BOTH_EDGE_SINGLE 0
|
|
#define INT_BOTH_EDGE_BOTH 1
|
|
|
|
#define PIN_OFFSET(pin) ((pin) / 32 * 0x10)
|
|
#define PIN_SET_OFFSET(pin) (PIN_OFFSET(pin) + 0x4)
|
|
#define PIN_CLR_OFFSET(pin) (PIN_OFFSET(pin) + 0x8)
|
|
#define PIN_TOG_OFFSET(pin) (PIN_OFFSET(pin) + 0xC)
|
|
#define PIN_BIT(pin) ((pin) % 32)
|
|
#define PIN_MASK(pin) (1ul << PIN_BIT(pin))
|
|
|
|
typedef struct sdrv_gpio_handler {
|
|
sdrv_gpio_interrupt_handler_t handler;
|
|
void *arg;
|
|
} sdrv_gpio_handler_t;
|
|
|
|
typedef struct sdrv_gpio_irq {
|
|
uint32_t irq;
|
|
uint32_t refs;
|
|
} sdrv_gpio_irq_t;
|
|
|
|
static sdrv_gpio_handler_t gpio_irq_handler[TAISHAN_PIN_NUM];
|
|
|
|
#if (CONFIG_E3L)
|
|
static sdrv_gpio_irq_t gpio_irq_info[4] = {
|
|
{GPIO_SF_SYNC_GRP_0_INTR_NUM, 0}, /*0*/
|
|
{GPIO_SF_SYNC_GRP_1_INTR_NUM, 0}, /*1*/
|
|
{GPIO_SF_SYNC_GRP_2_INTR_NUM, 0}, /*2*/
|
|
{GPIO_SF_SYNC_GRP_3_INTR_NUM, 0}, /*3*/
|
|
};
|
|
#else
|
|
static sdrv_gpio_irq_t gpio_irq_info[8] = {
|
|
{GPIO_SF_SYNC_GRP_0_INTR_NUM, 0}, /*0*/
|
|
{GPIO_SF_SYNC_GRP_1_INTR_NUM, 0}, /*1*/
|
|
{GPIO_SF_SYNC_GRP_2_INTR_NUM, 0}, /*2*/
|
|
{GPIO_SF_SYNC_GRP_3_INTR_NUM, 0}, /*3*/
|
|
{GPIO_SF_SYNC_GRP_4_INTR_NUM, 0}, /*4*/
|
|
|
|
{GPIO_AP_SYNC_GRP_0_INTR_NUM, 0}, /*5*/
|
|
{GPIO_AP_SYNC_GRP_1_INTR_NUM, 0}, /*6*/
|
|
{GPIO_AP_SYNC_GRP_2_INTR_NUM, 0}, /*7*/
|
|
};
|
|
#endif
|
|
|
|
static int32_t get_array_index(uint32_t pin_index)
|
|
{
|
|
int32_t array_index;
|
|
uint32_t ctrl_index;
|
|
|
|
array_index = 0;
|
|
ctrl_index = pin_index;
|
|
|
|
#if (CONFIG_E3 || CONFIG_D3)
|
|
if (ctrl_index >= TAISHAN_SAFETY_PIN_NUM) {
|
|
ctrl_index -= TAISHAN_SAFETY_PIN_NUM;
|
|
array_index = 5;
|
|
}
|
|
#endif
|
|
|
|
array_index += (ctrl_index / 32U);
|
|
|
|
return (array_index < ARRAY_SIZE(gpio_irq_info)) ? array_index : -1;
|
|
}
|
|
|
|
static int gpio_irq_common_handler(uint32_t irq, void *arg)
|
|
{
|
|
uint32_t array_index = (uint32_t)arg;
|
|
uint32_t irq_status;
|
|
uint32_t async_irq_status;
|
|
uint32_t pin_start;
|
|
uint32_t clear_reg;
|
|
|
|
if ((array_index >= ARRAY_SIZE(gpio_irq_info)) ||
|
|
(irq != gpio_irq_info[array_index].irq)) {
|
|
return SDRV_GPIO_BAD_PIN;
|
|
}
|
|
|
|
if (array_index < 5) {
|
|
irq_status = readl(APB_GPIO_SF_BASE + REG_SINT_STATUS_OFFSET +
|
|
array_index * 0x10);
|
|
async_irq_status = readl(APB_GPIO_SF_BASE + REG_AINT_STATUS_OFFSET +
|
|
array_index * 0x10);
|
|
pin_start = array_index * 32;
|
|
clear_reg = APB_GPIO_SF_BASE + array_index * 0x10 + 0x4;
|
|
}
|
|
#if (!CONFIG_E3L)
|
|
else {
|
|
array_index -= 5;
|
|
irq_status = readl(APB_GPIO_AP_BASE + REG_SINT_STATUS_OFFSET +
|
|
array_index * 0x10);
|
|
async_irq_status = readl(APB_GPIO_AP_BASE + REG_AINT_STATUS_OFFSET +
|
|
array_index * 0x10);
|
|
pin_start = array_index * 32 + TAISHAN_AP_PIN_START;
|
|
clear_reg = APB_GPIO_AP_BASE + array_index * 0x10 + 0x4;
|
|
}
|
|
#endif
|
|
|
|
for (uint32_t i = 0; i < 32; i++) {
|
|
if ((irq_status & (0x1u << i)) || (async_irq_status & (0x1u << i))) {
|
|
if (gpio_irq_handler[pin_start + i].handler) {
|
|
writel((0x1u << i), clear_reg + REG_SINT_EDGE_CLR_OFFSET);
|
|
writel((0x1u << i), clear_reg + REG_AINT_EDGE_CLR_OFFSET);
|
|
|
|
gpio_irq_handler[pin_start + i].handler(
|
|
irq, pin_start + i, gpio_irq_handler[pin_start + i].arg);
|
|
}
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static bool gpio_read(paddr_t base, uint32_t reg_offset, uint32_t pin)
|
|
{
|
|
uint32_t val = readl(base + reg_offset + PIN_OFFSET(pin));
|
|
return ((val & PIN_MASK(pin)) == 0) ? false : true;
|
|
}
|
|
|
|
static void gpio_write(paddr_t base, uint32_t reg_offset, uint32_t pin,
|
|
bool val)
|
|
{
|
|
(val == true)
|
|
? writel(PIN_MASK(pin), base + reg_offset + PIN_SET_OFFSET(pin))
|
|
: writel(PIN_MASK(pin), base + reg_offset + PIN_CLR_OFFSET(pin));
|
|
}
|
|
|
|
static void gpio_toggle(paddr_t base, uint32_t reg_offset, uint32_t pin)
|
|
{
|
|
writel(PIN_MASK(pin), base + reg_offset + PIN_TOG_OFFSET(pin));
|
|
}
|
|
|
|
static status_t do_sdrv_gpio_set_pin_interrupt(uint32_t ctrl_base, uint32_t ctrl_index, gpio_interrupt_e intr)
|
|
{
|
|
gpio_write(ctrl_base, REG_SINT_MASK_OFFSET, ctrl_index, 1);
|
|
gpio_write(ctrl_base, REG_SINT_EN_OFFSET, ctrl_index, 0);
|
|
gpio_write(ctrl_base, REG_SINT_EDGE_CLR_OFFSET, ctrl_index, 1);
|
|
|
|
gpio_write(ctrl_base, REG_OEN_OFFSET, ctrl_index, DIR_IN);
|
|
|
|
switch (intr) {
|
|
case GPIO_INTR_DISABLE:
|
|
break;
|
|
|
|
case GPIO_INTR_HIGH_LEVEL:
|
|
gpio_write(ctrl_base, REG_SINT_TYPE_OFFSET, ctrl_index,
|
|
INT_TYPE_LEVEL_SENSITIVE);
|
|
gpio_write(ctrl_base, REG_SINT_POL_OFFSET, ctrl_index,
|
|
INT_POLARITY_HIGH_OR_POSITIVE);
|
|
break;
|
|
|
|
case GPIO_INTR_LOW_LEVEL:
|
|
gpio_write(ctrl_base, REG_SINT_TYPE_OFFSET, ctrl_index,
|
|
INT_TYPE_LEVEL_SENSITIVE);
|
|
gpio_write(ctrl_base, REG_SINT_POL_OFFSET, ctrl_index,
|
|
INT_POLARITY_LOW_OR_NEGATIVE);
|
|
break;
|
|
|
|
case GPIO_INTR_RISING_EDGE:
|
|
gpio_write(ctrl_base, REG_SINT_BOE_OFFSET, ctrl_index,
|
|
INT_BOTH_EDGE_SINGLE);
|
|
gpio_write(ctrl_base, REG_SINT_TYPE_OFFSET, ctrl_index,
|
|
INT_TYPE_EDGE_SENSITIVE);
|
|
gpio_write(ctrl_base, REG_SINT_POL_OFFSET, ctrl_index,
|
|
INT_POLARITY_HIGH_OR_POSITIVE);
|
|
break;
|
|
|
|
case GPIO_INTR_FALLING_EDGE:
|
|
gpio_write(ctrl_base, REG_SINT_BOE_OFFSET, ctrl_index,
|
|
INT_BOTH_EDGE_SINGLE);
|
|
gpio_write(ctrl_base, REG_SINT_TYPE_OFFSET, ctrl_index,
|
|
INT_TYPE_EDGE_SENSITIVE);
|
|
gpio_write(ctrl_base, REG_SINT_POL_OFFSET, ctrl_index,
|
|
INT_POLARITY_LOW_OR_NEGATIVE);
|
|
break;
|
|
|
|
case GPIO_INTR_BOTH_EDGE:
|
|
gpio_write(ctrl_base, REG_SINT_BOE_OFFSET, ctrl_index,
|
|
INT_BOTH_EDGE_BOTH);
|
|
gpio_write(ctrl_base, REG_SINT_TYPE_OFFSET, ctrl_index,
|
|
INT_TYPE_EDGE_SENSITIVE);
|
|
break;
|
|
|
|
default:
|
|
return SDRV_STATUS_INVALID_PARAM;
|
|
}
|
|
|
|
return SDRV_STATUS_OK;
|
|
}
|
|
|
|
static status_t do_sdrv_gpio_set_pin_async_interrupt(uint32_t ctrl_base, uint32_t ctrl_index,
|
|
gpio_interrupt_e intr)
|
|
{
|
|
gpio_write(ctrl_base, REG_AINT_MASK_OFFSET, ctrl_index, 1);
|
|
gpio_write(ctrl_base, REG_AINT_EN_OFFSET, ctrl_index, 0);
|
|
gpio_write(ctrl_base, REG_AINT_EDGE_CLR_OFFSET, ctrl_index, 1);
|
|
|
|
gpio_write(ctrl_base, REG_OEN_OFFSET, ctrl_index, DIR_IN);
|
|
|
|
switch (intr) {
|
|
case GPIO_INTR_DISABLE:
|
|
break;
|
|
|
|
case GPIO_INTR_HIGH_LEVEL:
|
|
gpio_write(ctrl_base, REG_AINT_TYPE_OFFSET, ctrl_index,
|
|
INT_TYPE_LEVEL_SENSITIVE);
|
|
gpio_write(ctrl_base, REG_AINT_POL_OFFSET, ctrl_index,
|
|
INT_POLARITY_HIGH_OR_POSITIVE);
|
|
break;
|
|
|
|
case GPIO_INTR_LOW_LEVEL:
|
|
gpio_write(ctrl_base, REG_AINT_TYPE_OFFSET, ctrl_index,
|
|
INT_TYPE_LEVEL_SENSITIVE);
|
|
gpio_write(ctrl_base, REG_AINT_POL_OFFSET, ctrl_index,
|
|
INT_POLARITY_LOW_OR_NEGATIVE);
|
|
break;
|
|
|
|
case GPIO_INTR_RISING_EDGE:
|
|
gpio_write(ctrl_base, REG_AINT_BOE_OFFSET, ctrl_index,
|
|
INT_BOTH_EDGE_SINGLE);
|
|
gpio_write(ctrl_base, REG_AINT_TYPE_OFFSET, ctrl_index,
|
|
INT_TYPE_EDGE_SENSITIVE);
|
|
gpio_write(ctrl_base, REG_AINT_POL_OFFSET, ctrl_index,
|
|
INT_POLARITY_HIGH_OR_POSITIVE);
|
|
break;
|
|
|
|
case GPIO_INTR_FALLING_EDGE:
|
|
gpio_write(ctrl_base, REG_AINT_BOE_OFFSET, ctrl_index,
|
|
INT_BOTH_EDGE_SINGLE);
|
|
gpio_write(ctrl_base, REG_AINT_TYPE_OFFSET, ctrl_index,
|
|
INT_TYPE_EDGE_SENSITIVE);
|
|
gpio_write(ctrl_base, REG_AINT_POL_OFFSET, ctrl_index,
|
|
INT_POLARITY_LOW_OR_NEGATIVE);
|
|
break;
|
|
|
|
case GPIO_INTR_BOTH_EDGE:
|
|
gpio_write(ctrl_base, REG_AINT_BOE_OFFSET, ctrl_index,
|
|
INT_BOTH_EDGE_BOTH);
|
|
gpio_write(ctrl_base, REG_AINT_TYPE_OFFSET, ctrl_index,
|
|
INT_TYPE_EDGE_SENSITIVE);
|
|
break;
|
|
|
|
default:
|
|
return SDRV_STATUS_INVALID_PARAM;
|
|
}
|
|
|
|
return SDRV_STATUS_OK;
|
|
}
|
|
|
|
/**
|
|
* @brief Config gpio direction.
|
|
*
|
|
* This function config gpio as input or output.
|
|
*
|
|
* @param [in] pin_index defined pin macro in pinctrl.h.
|
|
* @param [in] dir direction defined as gpio_direction_e.
|
|
*/
|
|
status_t sdrv_gpio_set_pin_direction(uint32_t pin_index, gpio_direction_e dir)
|
|
{
|
|
uint32_t ctrl_base;
|
|
uint32_t ctrl_index;
|
|
|
|
if (pin_index < TAISHAN_PIN_NUM) {
|
|
ctrl_base = TAISHAN_GPIO_GET_BASE(pin_index);
|
|
ctrl_index = TAISHAN_GPIO_GET_INDEX(pin_index);
|
|
|
|
if (dir == GPIO_DIR_OUT) {
|
|
gpio_write(ctrl_base, REG_OEN_OFFSET, ctrl_index, DIR_OUT);
|
|
} else {
|
|
gpio_write(ctrl_base, REG_OEN_OFFSET, ctrl_index, DIR_IN);
|
|
}
|
|
|
|
return SDRV_STATUS_OK;
|
|
} else {
|
|
return SDRV_GPIO_BAD_PIN;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @brief Config gpio output level.
|
|
*
|
|
* This function config gpio output high or low level.
|
|
*
|
|
* @param [in] pin_index defined pin macro in pinctrl.h.
|
|
* @param [in] level true represents high, false represents low.
|
|
*/
|
|
status_t sdrv_gpio_set_pin_output_level(uint32_t pin_index, bool level)
|
|
{
|
|
uint32_t ctrl_base;
|
|
uint32_t ctrl_index;
|
|
|
|
if (pin_index < TAISHAN_PIN_NUM) {
|
|
ctrl_base = TAISHAN_GPIO_GET_BASE(pin_index);
|
|
ctrl_index = TAISHAN_GPIO_GET_INDEX(pin_index);
|
|
|
|
if (level) {
|
|
gpio_write(ctrl_base, REG_DATA_OUT_OFFSET, ctrl_index, true);
|
|
} else {
|
|
gpio_write(ctrl_base, REG_DATA_OUT_OFFSET, ctrl_index, false);
|
|
}
|
|
|
|
return SDRV_STATUS_OK;
|
|
} else {
|
|
return SDRV_GPIO_BAD_PIN;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @brief Get gpio output level.
|
|
*
|
|
* This function read gpio output data register for specific pin.
|
|
*
|
|
* @param [in] pin_index defined pin macro in pinctrl.h.
|
|
* @return true represents high configed, false represents low configed.
|
|
*/
|
|
bool sdrv_gpio_get_pin_output_level(uint32_t pin_index)
|
|
{
|
|
uint32_t ctrl_base;
|
|
uint32_t ctrl_index;
|
|
bool ret = false;
|
|
|
|
if (pin_index < TAISHAN_PIN_NUM) {
|
|
ctrl_base = TAISHAN_GPIO_GET_BASE(pin_index);
|
|
ctrl_index = TAISHAN_GPIO_GET_INDEX(pin_index);
|
|
|
|
ret = gpio_read(ctrl_base, REG_DATA_OUT_OFFSET, ctrl_index);
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
/**
|
|
* @brief Toggle specific pin output level.
|
|
*
|
|
* This function toggle output level for specific pin, for example, if pin
|
|
* output high at first, after call this function, it will output low.
|
|
*
|
|
* @param [in] pin_index defined pin macro in pinctrl.h.
|
|
*/
|
|
status_t sdrv_gpio_toggle_pin_output_level(uint32_t pin_index)
|
|
{
|
|
uint32_t ctrl_base;
|
|
uint32_t ctrl_index;
|
|
|
|
if (pin_index < TAISHAN_PIN_NUM) {
|
|
ctrl_base = TAISHAN_GPIO_GET_BASE(pin_index);
|
|
ctrl_index = TAISHAN_GPIO_GET_INDEX(pin_index);
|
|
|
|
gpio_toggle(ctrl_base, REG_DATA_OUT_OFFSET, ctrl_index);
|
|
|
|
return SDRV_STATUS_OK;
|
|
} else {
|
|
return SDRV_GPIO_BAD_PIN;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @brief Get specific pin input level.
|
|
*
|
|
* This function read pin input level.
|
|
*
|
|
* @param [in] pin_index defined pin macro in pinctrl.h.
|
|
* @return true represents high level, false represents low level.
|
|
*/
|
|
bool sdrv_gpio_read_pin_input_level(uint32_t pin_index)
|
|
{
|
|
uint32_t ctrl_base;
|
|
uint32_t ctrl_index;
|
|
bool ret = false;
|
|
|
|
if (pin_index < TAISHAN_PIN_NUM) {
|
|
ctrl_base = TAISHAN_GPIO_GET_BASE(pin_index);
|
|
ctrl_index = TAISHAN_GPIO_GET_INDEX(pin_index);
|
|
|
|
ret = gpio_read(ctrl_base, REG_DATA_IN_OFFSET, ctrl_index);
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
/**
|
|
* @brief Config interrupt type for specific pin.
|
|
*
|
|
* This function config pin as interrupt type, after configuration, you also
|
|
* need call sdrv_gpio_pin_interrupt_enable for starting receive interrupt.
|
|
*
|
|
* @param [in] pin_index defined pin macro in pinctrl.h.
|
|
* @param [in] intr interrupt type defined in gpio_interrupt_e.
|
|
*/
|
|
status_t sdrv_gpio_set_pin_interrupt(uint32_t pin_index, gpio_interrupt_e intr)
|
|
{
|
|
uint32_t ctrl_base;
|
|
uint32_t ctrl_index;
|
|
|
|
if (pin_index >= TAISHAN_PIN_NUM) {
|
|
return SDRV_GPIO_BAD_PIN;
|
|
}
|
|
|
|
ctrl_base = TAISHAN_GPIO_GET_BASE(pin_index);
|
|
ctrl_index = TAISHAN_GPIO_GET_INDEX(pin_index);
|
|
|
|
return do_sdrv_gpio_set_pin_interrupt(ctrl_base, ctrl_index, intr);
|
|
}
|
|
|
|
/**
|
|
* @brief Enable interrupt for specific pin.
|
|
*
|
|
* This function config pin interrupt enable register and unmask pin interrupt
|
|
* status.
|
|
*
|
|
* @param [in] pin_index defined pin macro in pinctrl.h.
|
|
*/
|
|
status_t sdrv_gpio_pin_interrupt_enable(uint32_t pin_index)
|
|
{
|
|
uint32_t ctrl_base;
|
|
uint32_t ctrl_index;
|
|
|
|
if (pin_index < TAISHAN_PIN_NUM) {
|
|
ctrl_base = TAISHAN_GPIO_GET_BASE(pin_index);
|
|
ctrl_index = TAISHAN_GPIO_GET_INDEX(pin_index);
|
|
|
|
gpio_write(ctrl_base, REG_SINT_MASK_OFFSET, ctrl_index, 0);
|
|
gpio_write(ctrl_base, REG_SINT_EN_OFFSET, ctrl_index, 1);
|
|
|
|
return SDRV_STATUS_OK;
|
|
} else {
|
|
return SDRV_GPIO_BAD_PIN;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @brief Disable interrupt for specific pin.
|
|
*
|
|
* This function config pin interrupt disable register and mask pin interrupt
|
|
* status.
|
|
*
|
|
* @param [in] pin_index defined pin macro in pinctrl.h.
|
|
*/
|
|
status_t sdrv_gpio_pin_interrupt_disable(uint32_t pin_index)
|
|
{
|
|
uint32_t ctrl_base;
|
|
uint32_t ctrl_index;
|
|
|
|
if (pin_index < TAISHAN_PIN_NUM) {
|
|
ctrl_base = TAISHAN_GPIO_GET_BASE(pin_index);
|
|
ctrl_index = TAISHAN_GPIO_GET_INDEX(pin_index);
|
|
|
|
gpio_write(ctrl_base, REG_SINT_MASK_OFFSET, ctrl_index, 1);
|
|
gpio_write(ctrl_base, REG_SINT_EN_OFFSET, ctrl_index, 0);
|
|
|
|
return SDRV_STATUS_OK;
|
|
} else {
|
|
return SDRV_GPIO_BAD_PIN;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @brief Get specific pin interrupt status.
|
|
*
|
|
* This function read pin interrupt status register.
|
|
*
|
|
* @param [in] pin_index defined pin macro in pinctrl.h.
|
|
* @return true represents interrupt status is set, false represents no
|
|
* interrupt status.
|
|
*/
|
|
bool sdrv_gpio_pin_interrupt_status(uint32_t pin_index)
|
|
{
|
|
uint32_t ctrl_base;
|
|
uint32_t ctrl_index;
|
|
bool ret = false;
|
|
|
|
if (pin_index < TAISHAN_PIN_NUM) {
|
|
ctrl_base = TAISHAN_GPIO_GET_BASE(pin_index);
|
|
ctrl_index = TAISHAN_GPIO_GET_INDEX(pin_index);
|
|
|
|
ret = gpio_read(ctrl_base, REG_SINT_STATUS_OFFSET, ctrl_index);
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
/**
|
|
* @brief Clear specific pin interrupt status.
|
|
*
|
|
* This function clear pin interrupt status. Only edge interrupt type need clear
|
|
* status, level type should inactive source level.
|
|
*
|
|
* @param [in] pin_index defined pin macro in pinctrl.h.
|
|
*/
|
|
status_t sdrv_gpio_clear_pin_interrupt_status(uint32_t pin_index)
|
|
{
|
|
uint32_t ctrl_base;
|
|
uint32_t ctrl_index;
|
|
|
|
if (pin_index < TAISHAN_PIN_NUM) {
|
|
ctrl_base = TAISHAN_GPIO_GET_BASE(pin_index);
|
|
ctrl_index = TAISHAN_GPIO_GET_INDEX(pin_index);
|
|
|
|
gpio_write(ctrl_base, REG_SINT_EDGE_CLR_OFFSET, ctrl_index, 1);
|
|
|
|
return SDRV_STATUS_OK;
|
|
} else {
|
|
return SDRV_GPIO_BAD_PIN;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @brief Config asynchronous interrupt type for specific pin.
|
|
*
|
|
* This function config pin as interrupt type using asynchronous way. Compare to
|
|
* normal interrupt way, asynchronous interrupt can also receive interrupt
|
|
* without clock, so it can be work in lowpower mode.
|
|
*
|
|
* @param [in] pin_index defined pin macro in pinctrl.h.
|
|
* @param [in] intr interrupt type defined in gpio_interrupt_e.
|
|
*/
|
|
status_t sdrv_gpio_set_pin_async_interrupt(uint32_t pin_index,
|
|
gpio_interrupt_e intr)
|
|
{
|
|
uint32_t ctrl_base;
|
|
uint32_t ctrl_index;
|
|
|
|
if (pin_index >= TAISHAN_PIN_NUM) {
|
|
return SDRV_GPIO_BAD_PIN;
|
|
}
|
|
|
|
ctrl_base = TAISHAN_GPIO_GET_BASE(pin_index);
|
|
ctrl_index = TAISHAN_GPIO_GET_INDEX(pin_index);
|
|
|
|
return do_sdrv_gpio_set_pin_async_interrupt(ctrl_base, ctrl_index, intr);
|
|
}
|
|
|
|
/**
|
|
* @brief Enable asynchronous interrupt for specific pin.
|
|
*
|
|
* This function config pin interrupt enable register and unmask pin interrupt
|
|
* status.
|
|
*
|
|
* @param [in] pin_index defined pin macro in pinctrl.h.
|
|
*/
|
|
status_t sdrv_gpio_pin_async_interrupt_enable(uint32_t pin_index)
|
|
{
|
|
uint32_t ctrl_base;
|
|
uint32_t ctrl_index;
|
|
|
|
if (pin_index < TAISHAN_PIN_NUM) {
|
|
ctrl_base = TAISHAN_GPIO_GET_BASE(pin_index);
|
|
ctrl_index = TAISHAN_GPIO_GET_INDEX(pin_index);
|
|
|
|
gpio_write(ctrl_base, REG_AINT_MASK_OFFSET, ctrl_index, 0);
|
|
gpio_write(ctrl_base, REG_AINT_EN_OFFSET, ctrl_index, 1);
|
|
|
|
return SDRV_STATUS_OK;
|
|
} else {
|
|
return SDRV_GPIO_BAD_PIN;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @brief Disable asynchronous interrupt for specific pin.
|
|
*
|
|
* This function config pin interrupt disable register and mask pin interrupt
|
|
* status.
|
|
*
|
|
* @param [in] pin_index defined pin macro in pinctrl.h.
|
|
*/
|
|
status_t sdrv_gpio_pin_async_interrupt_disable(uint32_t pin_index)
|
|
{
|
|
uint32_t ctrl_base;
|
|
uint32_t ctrl_index;
|
|
|
|
if (pin_index < TAISHAN_PIN_NUM) {
|
|
ctrl_base = TAISHAN_GPIO_GET_BASE(pin_index);
|
|
ctrl_index = TAISHAN_GPIO_GET_INDEX(pin_index);
|
|
|
|
gpio_write(ctrl_base, REG_AINT_MASK_OFFSET, ctrl_index, 1);
|
|
gpio_write(ctrl_base, REG_AINT_EN_OFFSET, ctrl_index, 0);
|
|
|
|
return SDRV_STATUS_OK;
|
|
} else {
|
|
return SDRV_GPIO_BAD_PIN;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @brief Get specific pin asynchronous interrupt status.
|
|
*
|
|
* This function read pin asynchronous interrupt status register.
|
|
*
|
|
* @param [in] pin_index defined pin macro in pinctrl.h.
|
|
* @return true represents interrupt status is set, false represents no
|
|
* interrupt status.
|
|
*/
|
|
bool sdrv_gpio_pin_async_interrupt_status(uint32_t pin_index)
|
|
{
|
|
uint32_t ctrl_base;
|
|
uint32_t ctrl_index;
|
|
bool ret = false;
|
|
|
|
if (pin_index < TAISHAN_PIN_NUM) {
|
|
ctrl_base = TAISHAN_GPIO_GET_BASE(pin_index);
|
|
ctrl_index = TAISHAN_GPIO_GET_INDEX(pin_index);
|
|
|
|
ret = gpio_read(ctrl_base, REG_AINT_STATUS_OFFSET, ctrl_index);
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
/**
|
|
* @brief Clear specific pin asynchronous interrupt status.
|
|
*
|
|
* This function clear pin asynchronous interrupt status. Only edge interrupt
|
|
* type need clear status, level type should inactive source level.
|
|
*
|
|
* @param [in] pin_index defined pin macro in pinctrl.h.
|
|
*/
|
|
status_t sdrv_gpio_clear_pin_async_interrupt_status(uint32_t pin_index)
|
|
{
|
|
uint32_t ctrl_base;
|
|
uint32_t ctrl_index;
|
|
|
|
if (pin_index < TAISHAN_PIN_NUM) {
|
|
ctrl_base = TAISHAN_GPIO_GET_BASE(pin_index);
|
|
ctrl_index = TAISHAN_GPIO_GET_INDEX(pin_index);
|
|
|
|
gpio_write(ctrl_base, REG_AINT_EDGE_CLR_OFFSET, ctrl_index, 1);
|
|
|
|
return SDRV_STATUS_OK;
|
|
} else {
|
|
return SDRV_GPIO_BAD_PIN;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @brief Register interrupt callback function for specific pin.
|
|
*
|
|
* This function register pin interrupt callback. It according to pin index
|
|
* getting irq number, and use irq_attach/irq_enable to enable it. Each 32 pin
|
|
* share one interrupt number.
|
|
*
|
|
* @param [in] pin_index defined pin macro in pinctrl.h.
|
|
* @param [in] handler callback function handler.
|
|
* @param [in] arg callback function param.
|
|
*/
|
|
status_t sdrv_gpio_register_interrupt_handler(
|
|
uint32_t pin_index, sdrv_gpio_interrupt_handler_t handler, void *arg)
|
|
{
|
|
status_t ret;
|
|
irq_state_t irq_stat;
|
|
uint32_t refs;
|
|
int32_t array_index;
|
|
|
|
if (pin_index >= TAISHAN_PIN_NUM) {
|
|
return SDRV_GPIO_BAD_PIN;
|
|
}
|
|
|
|
array_index = get_array_index(pin_index);
|
|
if (array_index < 0) {
|
|
return SDRV_GPIO_BAD_PIN;
|
|
}
|
|
|
|
irq_stat = arch_irq_save();
|
|
|
|
gpio_irq_handler[pin_index].handler = handler;
|
|
gpio_irq_handler[pin_index].arg = arg;
|
|
|
|
refs = ++(gpio_irq_info[array_index].refs);
|
|
|
|
arch_irq_restore(irq_stat);
|
|
|
|
if (refs == 1) {
|
|
ret = irq_attach(gpio_irq_info[array_index].irq,
|
|
gpio_irq_common_handler, (void *)array_index);
|
|
if (ret == SDRV_STATUS_OK) {
|
|
irq_enable(gpio_irq_info[array_index].irq);
|
|
} else {
|
|
return SDRV_GPIO_IRQ_ATTACH_FAIL;
|
|
}
|
|
}
|
|
|
|
return SDRV_STATUS_OK;
|
|
}
|
|
|
|
/**
|
|
* @brief Unregister interrupt callback function for specific pin.
|
|
*
|
|
* This function unregister pin interrupt callback. If it is last pin for its
|
|
* group interrupt number, irq_disable/irq_detach will be called.
|
|
*
|
|
* @param [in] pin_index defined pin macro in pinctrl.h.
|
|
*/
|
|
status_t sdrv_gpio_unregister_interrupt_handler(uint32_t pin_index)
|
|
{
|
|
irq_state_t irq_stat;
|
|
uint32_t refs;
|
|
int32_t array_index;
|
|
|
|
if (pin_index >= TAISHAN_PIN_NUM) {
|
|
return SDRV_GPIO_BAD_PIN;
|
|
}
|
|
|
|
array_index = get_array_index(pin_index);
|
|
if (array_index < 0) {
|
|
return SDRV_GPIO_BAD_PIN;
|
|
}
|
|
|
|
irq_stat = arch_irq_save();
|
|
|
|
gpio_irq_handler[pin_index].handler = NULL;
|
|
gpio_irq_handler[pin_index].arg = NULL;
|
|
|
|
refs = --(gpio_irq_info[array_index].refs);
|
|
|
|
arch_irq_restore(irq_stat);
|
|
|
|
if (refs == 0) {
|
|
irq_disable(gpio_irq_info[array_index].irq);
|
|
irq_detach(gpio_irq_info[array_index].irq);
|
|
}
|
|
|
|
return SDRV_STATUS_OK;
|
|
}
|
|
|
|
/**
|
|
* @brief Set gpio interrupt share with other core.
|
|
*
|
|
* This function set gpio interrupt with core sp or sx. Pin interrupt default
|
|
* send to sf only, if you want use other core handler this interrupt, you must
|
|
* share interrupt with core.
|
|
*
|
|
* @param [in] pin_index defined pin macro in pinctrl.h.
|
|
* @param [in] mask OR'ed value defined in gpio_interrupt_share_e.
|
|
*/
|
|
status_t sdrv_gpio_interrupt_share_with(uint32_t pin_index, uint32_t mask)
|
|
{
|
|
uint32_t ctrl_base;
|
|
uint32_t ctrl_index;
|
|
uint32_t val;
|
|
|
|
if (pin_index < TAISHAN_PIN_NUM) {
|
|
ctrl_base = TAISHAN_GPIO_GET_BASE(pin_index);
|
|
ctrl_index = TAISHAN_GPIO_GET_INDEX(pin_index);
|
|
|
|
val = readl(ctrl_base + REG_INT_SHARE(ctrl_index));
|
|
val |= (mask & 0xffffu);
|
|
writel(val, ctrl_base + REG_INT_SHARE(ctrl_index));
|
|
|
|
return SDRV_STATUS_OK;
|
|
} else {
|
|
return SDRV_GPIO_BAD_PIN;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @brief Cancel gpio interrupt share with other core.
|
|
*
|
|
* This function cancel gpio interrupt with core sp or sx.
|
|
*
|
|
* @param [in] pin_index defined pin macro in pinctrl.h.
|
|
* @param [in] mask OR'ed value defined in gpio_interrupt_share_e.
|
|
*/
|
|
status_t sdrv_gpio_cancel_interrupt_share_with(uint32_t pin_index,
|
|
uint32_t mask)
|
|
{
|
|
uint32_t ctrl_base;
|
|
uint32_t ctrl_index;
|
|
uint32_t val;
|
|
|
|
if (pin_index < TAISHAN_PIN_NUM) {
|
|
ctrl_base = TAISHAN_GPIO_GET_BASE(pin_index);
|
|
ctrl_index = TAISHAN_GPIO_GET_INDEX(pin_index);
|
|
|
|
val = readl(ctrl_base + REG_INT_SHARE(ctrl_index));
|
|
val &= ~(mask & 0xffffu);
|
|
writel(val, ctrl_base + REG_INT_SHARE(ctrl_index));
|
|
|
|
return SDRV_STATUS_OK;
|
|
} else {
|
|
return SDRV_GPIO_BAD_PIN;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @brief Config gpio direction.
|
|
*
|
|
* This function config gpio as input or output.
|
|
*
|
|
* @param [in] gpio_ctrl gpio instance.
|
|
* @param [in] pin_index defined pin macro in pinctrl.h.
|
|
* @param [in] dir direction defined as gpio_direction_e.
|
|
*/
|
|
status_t sdrv_gpio_ctrl_set_pin_direction(sdrv_gpio_t *gpio_ctrl,
|
|
uint32_t pin_index,
|
|
gpio_direction_e dir)
|
|
{
|
|
uint32_t ctrl_base;
|
|
uint32_t ctrl_index;
|
|
|
|
if (!gpio_ctrl) {
|
|
return SDRV_GPIO_CTRL_NULL;
|
|
}
|
|
|
|
ctrl_base = gpio_ctrl->base;
|
|
ctrl_index = pin_index - gpio_ctrl->pin_start;
|
|
|
|
if (ctrl_index < gpio_ctrl->pin_num) {
|
|
if (dir == GPIO_DIR_OUT) {
|
|
gpio_write(ctrl_base, REG_OEN_OFFSET, ctrl_index, DIR_OUT);
|
|
} else {
|
|
gpio_write(ctrl_base, REG_OEN_OFFSET, ctrl_index, DIR_IN);
|
|
}
|
|
|
|
return SDRV_STATUS_OK;
|
|
} else {
|
|
return SDRV_GPIO_BAD_PIN;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @brief Config gpio output level.
|
|
*
|
|
* This function config gpio output high or low level.
|
|
*
|
|
* @param [in] gpio_ctrl gpio instance.
|
|
* @param [in] pin_index defined pin macro in pinctrl.h.
|
|
* @param [in] level true represents high, false represents low.
|
|
*/
|
|
status_t sdrv_gpio_ctrl_set_pin_output_level(sdrv_gpio_t *gpio_ctrl,
|
|
uint32_t pin_index, bool level)
|
|
{
|
|
uint32_t ctrl_base;
|
|
uint32_t ctrl_index;
|
|
|
|
if (!gpio_ctrl) {
|
|
return SDRV_GPIO_CTRL_NULL;
|
|
}
|
|
|
|
ctrl_base = gpio_ctrl->base;
|
|
ctrl_index = pin_index - gpio_ctrl->pin_start;
|
|
|
|
if (ctrl_index < gpio_ctrl->pin_num) {
|
|
if (level) {
|
|
gpio_write(ctrl_base, REG_DATA_OUT_OFFSET, ctrl_index, true);
|
|
} else {
|
|
gpio_write(ctrl_base, REG_DATA_OUT_OFFSET, ctrl_index, false);
|
|
}
|
|
|
|
return SDRV_STATUS_OK;
|
|
} else {
|
|
return SDRV_GPIO_BAD_PIN;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @brief Toggle specific pin output level.
|
|
*
|
|
* This function toggle output level for specific pin, for example, if pin
|
|
* output high at first, after call this function, it will output low.
|
|
*
|
|
* @param [in] gpio_ctrl gpio instance.
|
|
* @param [in] pin_index defined pin macro in pinctrl.h.
|
|
*/
|
|
status_t sdrv_gpio_ctrl_toggle_pin_output_level(sdrv_gpio_t *gpio_ctrl,
|
|
uint32_t pin_index)
|
|
{
|
|
uint32_t ctrl_base;
|
|
uint32_t ctrl_index;
|
|
|
|
if (!gpio_ctrl) {
|
|
return SDRV_GPIO_CTRL_NULL;
|
|
}
|
|
|
|
ctrl_base = gpio_ctrl->base;
|
|
ctrl_index = pin_index - gpio_ctrl->pin_start;
|
|
|
|
if (ctrl_index < gpio_ctrl->pin_num) {
|
|
gpio_toggle(ctrl_base, REG_DATA_OUT_OFFSET, ctrl_index);
|
|
|
|
return SDRV_STATUS_OK;
|
|
} else {
|
|
return SDRV_GPIO_BAD_PIN;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @brief Get specific pin input level.
|
|
*
|
|
* This function read pin input level.
|
|
*
|
|
* @param [in] gpio_ctrl gpio instance.
|
|
* @param [in] pin_index defined pin macro in pinctrl.h.
|
|
* @return true represents high level, false represents low level.
|
|
*/
|
|
bool sdrv_gpio_ctrl_read_pin_input_level(sdrv_gpio_t *gpio_ctrl,
|
|
uint32_t pin_index)
|
|
{
|
|
uint32_t ctrl_base;
|
|
uint32_t ctrl_index;
|
|
bool ret = false;
|
|
|
|
if (gpio_ctrl) {
|
|
ctrl_base = gpio_ctrl->base;
|
|
ctrl_index = pin_index - gpio_ctrl->pin_start;
|
|
|
|
if (ctrl_index < gpio_ctrl->pin_num) {
|
|
ret = gpio_read(ctrl_base, REG_DATA_IN_OFFSET, ctrl_index);
|
|
}
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
/**
|
|
* @brief Get gpio output level.
|
|
*
|
|
* This function read gpio output data register for specific pin.
|
|
*
|
|
* @param [in] gpio_ctrl gpio instance.
|
|
* @param [in] pin_index defined pin macro in pinctrl.h.
|
|
* @return true represents high configed, false represents low configed.
|
|
*/
|
|
bool sdrv_gpio_ctrl_get_pin_output_level(sdrv_gpio_t *gpio_ctrl,
|
|
uint32_t pin_index)
|
|
{
|
|
uint32_t ctrl_base;
|
|
uint32_t ctrl_index;
|
|
bool ret = false;
|
|
|
|
if (gpio_ctrl) {
|
|
ctrl_base = gpio_ctrl->base;
|
|
ctrl_index = pin_index - gpio_ctrl->pin_start;
|
|
|
|
if (ctrl_index < gpio_ctrl->pin_num) {
|
|
ret = gpio_read(ctrl_base, REG_DATA_OUT_OFFSET, ctrl_index);
|
|
}
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
/**
|
|
* @brief Config interrupt type for specific pin.
|
|
*
|
|
* This function config pin as interrupt type, after configuration, you also
|
|
* need call sdrv_gpio_pin_interrupt_enable for starting receive interrupt.
|
|
*
|
|
* @param [in] gpio_ctrl gpio instance.
|
|
* @param [in] pin_index defined pin macro in pinctrl.h.
|
|
* @param [in] intr interrupt type defined in gpio_interrupt_e.
|
|
*/
|
|
status_t sdrv_gpio_ctrl_set_pin_interrupt(sdrv_gpio_t *gpio_ctrl,
|
|
uint32_t pin_index,
|
|
gpio_interrupt_e intr)
|
|
{
|
|
uint32_t ctrl_base;
|
|
uint32_t ctrl_index;
|
|
|
|
if (!gpio_ctrl) {
|
|
return SDRV_GPIO_CTRL_NULL;
|
|
}
|
|
|
|
ctrl_base = gpio_ctrl->base;
|
|
ctrl_index = pin_index - gpio_ctrl->pin_start;
|
|
|
|
if (ctrl_index < gpio_ctrl->pin_num) {
|
|
return do_sdrv_gpio_set_pin_interrupt(ctrl_base, ctrl_index, intr);
|
|
} else {
|
|
return SDRV_GPIO_BAD_PIN;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @brief Enable interrupt for specific pin.
|
|
*
|
|
* This function config pin interrupt enable register and unmask pin interrupt
|
|
* status.
|
|
*
|
|
* @param [in] gpio_ctrl gpio instance.
|
|
* @param [in] pin_index defined pin macro in pinctrl.h.
|
|
*/
|
|
status_t sdrv_gpio_ctrl_pin_interrupt_enable(sdrv_gpio_t *gpio_ctrl,
|
|
uint32_t pin_index)
|
|
{
|
|
uint32_t ctrl_base;
|
|
uint32_t ctrl_index;
|
|
|
|
if (!gpio_ctrl) {
|
|
return SDRV_GPIO_CTRL_NULL;
|
|
}
|
|
|
|
ctrl_base = gpio_ctrl->base;
|
|
ctrl_index = pin_index - gpio_ctrl->pin_start;
|
|
|
|
if (ctrl_index < gpio_ctrl->pin_num) {
|
|
gpio_write(ctrl_base, REG_SINT_MASK_OFFSET, ctrl_index, 0);
|
|
gpio_write(ctrl_base, REG_SINT_EN_OFFSET, ctrl_index, 1);
|
|
|
|
return SDRV_STATUS_OK;
|
|
} else {
|
|
return SDRV_GPIO_BAD_PIN;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @brief Disable interrupt for specific pin.
|
|
*
|
|
* This function config pin interrupt disable register and mask pin interrupt
|
|
* status.
|
|
*
|
|
* @param [in] gpio_ctrl gpio instance.
|
|
* @param [in] pin_index defined pin macro in pinctrl.h.
|
|
*/
|
|
status_t sdrv_gpio_ctrl_pin_interrupt_disable(sdrv_gpio_t *gpio_ctrl,
|
|
uint32_t pin_index)
|
|
{
|
|
uint32_t ctrl_base;
|
|
uint32_t ctrl_index;
|
|
|
|
if (!gpio_ctrl) {
|
|
return SDRV_GPIO_CTRL_NULL;
|
|
}
|
|
|
|
ctrl_base = gpio_ctrl->base;
|
|
ctrl_index = pin_index - gpio_ctrl->pin_start;
|
|
|
|
if (ctrl_index < gpio_ctrl->pin_num) {
|
|
gpio_write(ctrl_base, REG_SINT_MASK_OFFSET, ctrl_index, 1);
|
|
gpio_write(ctrl_base, REG_SINT_EN_OFFSET, ctrl_index, 0);
|
|
|
|
return SDRV_STATUS_OK;
|
|
} else {
|
|
return SDRV_GPIO_BAD_PIN;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @brief Get specific pin interrupt status.
|
|
*
|
|
* This function read pin interrupt status register.
|
|
*
|
|
* @param [in] gpio_ctrl gpio instance.
|
|
* @param [in] pin_index defined pin macro in pinctrl.h.
|
|
* @return true represents interrupt status is set, false represents no
|
|
* interrupt status.
|
|
*/
|
|
bool sdrv_gpio_ctrl_pin_interrupt_status(sdrv_gpio_t *gpio_ctrl,
|
|
uint32_t pin_index)
|
|
{
|
|
uint32_t ctrl_base;
|
|
uint32_t ctrl_index;
|
|
bool ret = false;
|
|
|
|
if (gpio_ctrl) {
|
|
ctrl_base = gpio_ctrl->base;
|
|
ctrl_index = pin_index - gpio_ctrl->pin_start;
|
|
|
|
if (ctrl_index < gpio_ctrl->pin_num) {
|
|
ret = gpio_read(ctrl_base, REG_SINT_STATUS_OFFSET, ctrl_index);
|
|
}
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
/**
|
|
* @brief Clear specific pin interrupt status.
|
|
*
|
|
* This function clear pin interrupt status. Only edge interrupt type need clear
|
|
* status, level type should inactive source level.
|
|
*
|
|
* @param [in] gpio_ctrl gpio instance.
|
|
* @param [in] pin_index defined pin macro in pinctrl.h.
|
|
*/
|
|
status_t sdrv_gpio_ctrl_clear_pin_interrupt_status(sdrv_gpio_t *gpio_ctrl,
|
|
uint32_t pin_index)
|
|
{
|
|
uint32_t ctrl_base;
|
|
uint32_t ctrl_index;
|
|
|
|
if (!gpio_ctrl) {
|
|
return SDRV_GPIO_CTRL_NULL;
|
|
}
|
|
|
|
ctrl_base = gpio_ctrl->base;
|
|
ctrl_index = pin_index - gpio_ctrl->pin_start;
|
|
|
|
if (ctrl_index < gpio_ctrl->pin_num) {
|
|
gpio_write(ctrl_base, REG_SINT_EDGE_CLR_OFFSET, ctrl_index, 1);
|
|
return SDRV_STATUS_OK;
|
|
} else {
|
|
return SDRV_GPIO_BAD_PIN;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @brief Config asynchronous interrupt type for specific pin.
|
|
*
|
|
* This function config pin as interrupt type using asynchronous way. Compare to
|
|
* normal interrupt way, asynchronous interrupt can also receive interrupt
|
|
* without clock, so it can be work in lowpower mode.
|
|
*
|
|
* @param [in] gpio_ctrl gpio instance.
|
|
* @param [in] pin_index defined pin macro in pinctrl.h.
|
|
* @param [in] intr interrupt type defined in gpio_interrupt_e.
|
|
*/
|
|
status_t sdrv_gpio_ctrl_set_pin_async_interrupt(sdrv_gpio_t *gpio_ctrl,
|
|
uint32_t pin_index,
|
|
gpio_interrupt_e intr)
|
|
{
|
|
uint32_t ctrl_base;
|
|
uint32_t ctrl_index;
|
|
|
|
if (!gpio_ctrl) {
|
|
return SDRV_GPIO_CTRL_NULL;
|
|
}
|
|
|
|
ctrl_base = gpio_ctrl->base;
|
|
ctrl_index = pin_index - gpio_ctrl->pin_start;
|
|
|
|
if (ctrl_index < gpio_ctrl->pin_num) {
|
|
return do_sdrv_gpio_set_pin_async_interrupt(ctrl_base, ctrl_index, intr);
|
|
} else {
|
|
return SDRV_GPIO_BAD_PIN;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @brief Enable asynchronous interrupt for specific pin.
|
|
*
|
|
* This function config pin interrupt enable register and unmask pin interrupt
|
|
* status.
|
|
*
|
|
* @param [in] gpio_ctrl gpio instance.
|
|
* @param [in] pin_index defined pin macro in pinctrl.h.
|
|
*/
|
|
status_t sdrv_gpio_ctrl_pin_async_interrupt_enable(sdrv_gpio_t *gpio_ctrl,
|
|
uint32_t pin_index)
|
|
{
|
|
uint32_t ctrl_base;
|
|
uint32_t ctrl_index;
|
|
|
|
if (!gpio_ctrl) {
|
|
return SDRV_GPIO_CTRL_NULL;
|
|
}
|
|
|
|
ctrl_base = gpio_ctrl->base;
|
|
ctrl_index = pin_index - gpio_ctrl->pin_start;
|
|
|
|
if (ctrl_index < gpio_ctrl->pin_num) {
|
|
gpio_write(ctrl_base, REG_AINT_MASK_OFFSET, ctrl_index, 0);
|
|
gpio_write(ctrl_base, REG_AINT_EN_OFFSET, ctrl_index, 1);
|
|
|
|
return SDRV_STATUS_OK;
|
|
} else {
|
|
return SDRV_GPIO_BAD_PIN;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @brief Disable asynchronous interrupt for specific pin.
|
|
*
|
|
* This function config pin interrupt disable register and mask pin interrupt
|
|
* status.
|
|
*
|
|
* @param [in] gpio_ctrl gpio instance.
|
|
* @param [in] pin_index defined pin macro in pinctrl.h.
|
|
*/
|
|
status_t sdrv_gpio_ctrl_pin_async_interrupt_disable(sdrv_gpio_t *gpio_ctrl,
|
|
uint32_t pin_index)
|
|
{
|
|
uint32_t ctrl_base;
|
|
uint32_t ctrl_index;
|
|
|
|
if (!gpio_ctrl) {
|
|
return SDRV_GPIO_CTRL_NULL;
|
|
}
|
|
|
|
ctrl_base = gpio_ctrl->base;
|
|
ctrl_index = pin_index - gpio_ctrl->pin_start;
|
|
|
|
if (ctrl_index < gpio_ctrl->pin_num) {
|
|
gpio_write(ctrl_base, REG_AINT_MASK_OFFSET, ctrl_index, 1);
|
|
gpio_write(ctrl_base, REG_AINT_EN_OFFSET, ctrl_index, 0);
|
|
|
|
return SDRV_STATUS_OK;
|
|
} else {
|
|
return SDRV_GPIO_BAD_PIN;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @brief Get specific pin asynchronous interrupt status.
|
|
*
|
|
* This function read pin asynchronous interrupt status register.
|
|
*
|
|
* @param [in] gpio_ctrl gpio instance.
|
|
* @param [in] pin_index defined pin macro in pinctrl.h.
|
|
* @return true represents interrupt status is set, false represents no
|
|
* interrupt status.
|
|
*/
|
|
bool sdrv_gpio_ctrl_pin_async_interrupt_status(sdrv_gpio_t *gpio_ctrl,
|
|
uint32_t pin_index)
|
|
{
|
|
uint32_t ctrl_base;
|
|
uint32_t ctrl_index;
|
|
bool ret = false;
|
|
|
|
if (gpio_ctrl) {
|
|
ctrl_base = gpio_ctrl->base;
|
|
ctrl_index = pin_index - gpio_ctrl->pin_start;
|
|
|
|
if (ctrl_index < gpio_ctrl->pin_num) {
|
|
ret = gpio_read(ctrl_base, REG_AINT_STATUS_OFFSET, ctrl_index);
|
|
}
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
/**
|
|
* @brief Clear specific pin asynchronous interrupt status.
|
|
*
|
|
* This function clear pin asynchronous interrupt status. Only edge interrupt
|
|
* type need clear status, level type should inactive source level.
|
|
*
|
|
* @param [in] gpio_ctrl gpio instance.
|
|
* @param [in] pin_index defined pin macro in pinctrl.h.
|
|
*/
|
|
status_t sdrv_gpio_ctrl_clear_pin_async_interrupt_status(sdrv_gpio_t *gpio_ctrl,
|
|
uint32_t pin_index)
|
|
{
|
|
uint32_t ctrl_base;
|
|
uint32_t ctrl_index;
|
|
|
|
if (!gpio_ctrl) {
|
|
return SDRV_GPIO_CTRL_NULL;
|
|
}
|
|
|
|
ctrl_base = gpio_ctrl->base;
|
|
ctrl_index = pin_index - gpio_ctrl->pin_start;
|
|
|
|
if (ctrl_index < gpio_ctrl->pin_num) {
|
|
gpio_write(ctrl_base, REG_AINT_EDGE_CLR_OFFSET, ctrl_index, 1);
|
|
return SDRV_STATUS_OK;
|
|
} else {
|
|
return SDRV_GPIO_BAD_PIN;
|
|
}
|
|
}
|