Files
TAIXIN/sdk/driver/gpio/hggpio_v4.c

1403 lines
42 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/**
* @file hggpio_v4.c
* @author bxd
* @brief gpio
* @version
* TXW81X
* @date 2023-08-02
*
* @copyright Copyright (c) 2023
*
*/
#include "typesdef.h"
#include "errno.h"
#include "list.h"
#include "dev.h"
#include "osal/irq.h"
#include "osal/string.h"
#include "hal/gpio.h"
#include "dev/gpio/hggpio_v4.h"
#include "hggpio_v4_hw.h"
#include "osal/sleep.h"
#if 0
#define GPIO_PRINTF(fmt, args...) printf(fmt, ##args)
#else
#define GPIO_PRINTF(fmt, args...)
#endif
/* debug enable */
#define GPIO_ENBUG_EN 1
/* mode define */
#define _GPIO_PULL_NONE 0x1
#define _GPIO_PULL_UP 0x2
#define _GPIO_PULL_DOWN 0x4
#define _GPIO_OPENDRAIN_PULL_MASK 0x80
#define _GPIO_OPENDRAIN_PULL_NONE (_GPIO_OPENDRAIN_PULL_MASK | _GPIO_PULL_NONE)
#define _GPIO_OPENDRAIN_PULL_UP (_GPIO_OPENDRAIN_PULL_MASK | _GPIO_PULL_UP )
#define _GPIO_OPENDRAIN_PULL_DOWN (_GPIO_OPENDRAIN_PULL_MASK | _GPIO_PULL_DOWN)
#define _GPIO_OPENDRAIN_DROP_MASK 0x40
#define _GPIO_OPENDRAIN_DROP_NONE (_GPIO_OPENDRAIN_DROP_MASK | _GPIO_PULL_NONE)
#define _GPIO_OPENDRAIN_DROP_DOWN (_GPIO_OPENDRAIN_DROP_MASK | _GPIO_PULL_DOWN)
#define GPIO_PULL_LEVEL_MASK 0xF
/* 一些软件标志位 */
#define GPIO_FLAG_IS_INTR_EN 0x1
#define GPIO_FLAG_IS_SUSPENDED 0x2
#define SYSCTRL_FLAG_IS_SUSPEND 0x1
#define SYSCTRL_FLAG_IS_USB2GPIO 0X80
#ifdef CONFIG_SLEEP
struct gpio_sysctrl {
uint32_t flag;
uint32_t iofuncin[15];
#if defined(TXW82X)
uint32_t iomask[9];
uint32_t io_spare[4];
#else
uint32_t iomask[2];
#endif
};
static struct gpio_sysctrl gpio_sys = {
.flag = 0,
};
#endif
#define IOMASK_OPA_CLEAR 0
#define IOMASK_OPA_WRITE 1
#define IOMASK_OPA_READ 2
#define IOMASK_OPA_CHECK 3
uint32_t hggpio_v4_mask_opa(struct hggpio_v4_hw *reg, uint32_t pin_num, enum gpio_iomap_out_func func_sel, uint32_t flag)
{
uint8_t mask_offset[8] = {(&SYSCTRL->IOFUNCMASK0)-(&SYSCTRL->IOFUNCMASK0),
(&SYSCTRL->IOFUNCMASK1)-(&SYSCTRL->IOFUNCMASK0),
(&SYSCTRL->IOFUNCMASK2)-(&SYSCTRL->IOFUNCMASK0),
(&SYSCTRL->IOFUNCMASK3)-(&SYSCTRL->IOFUNCMASK0),
(&SYSCTRL->IOFUNCMASK4)-(&SYSCTRL->IOFUNCMASK0),
(&SYSCTRL->IOFUNCMASK5)-(&SYSCTRL->IOFUNCMASK0),
(&SYSCTRL->IOFUNCMASK6)-(&SYSCTRL->IOFUNCMASK0),
(&SYSCTRL->IOFUNCMASK7)-(&SYSCTRL->IOFUNCMASK0),};
uint32_t group_func_sel = ((func_sel+4)/5);
uint32_t mask_base = (uint32_t)&(SYSCTRL->IOFUNCMASK0);
uint32_t mask_bit = (group_func_sel-1) * 4;
uint32_t *maskp = (uint32_t*)(mask_base+(mask_offset[mask_bit/32]*4));
uint32_t mask_tmp = *maskp;
//Config IOMASKFUNCOUTCONx Reg
switch(flag) {
case IOMASK_OPA_CLEAR:
mask_tmp &= ~((0xf) << ((mask_bit % 32)));
break;
case IOMASK_OPA_WRITE:
mask_tmp &= ~((0xf) << ((mask_bit % 32)));
if (((func_sel-1)%5) < 4) {
mask_tmp |= (BIT((func_sel-1)%5)) << ((mask_bit %32));
}
break;
case IOMASK_OPA_READ:
if ((mask_tmp & ((0xf << (mask_bit %32)))) >> (mask_bit %32) == 0)
return 0;
else
return 1 + __builtin_ctz((mask_tmp & ((0xf << (mask_bit %32)))) >> (mask_bit %32));
case IOMASK_OPA_CHECK:
if (((func_sel-1)%5) < 4) {
return ((BIT((func_sel-1)%5)) << ((mask_bit %32))) ==
(mask_tmp & ((0xf) << ((mask_bit % 32))));
} else {
return !(mask_tmp & ((0xf) << ((mask_bit % 32))));
}
default:
;
}
*maskp = mask_tmp;
return 0;
}
static inline uint32 hggpio_v4_pin_num(struct hggpio_v4 *gpio, uint32 pin)
{
return (pin & 0xf);
}
static int32 hggpio_v4_set_pull(struct hggpio_v4_hw *reg, uint32 pin, enum gpio_pin_mode pull_mode, enum gpio_pull_level level)
{
int32 ret = RET_OK;
uint32 l_pin_pos = (pin * 4);
uint32 h_pin_pos = (pin & 0x07) * 4;
uint32 pull_level_to_reg = 0;
if (pin >= HGGPIO_V4_MAX_PINS) {
return -EINVAL;
}
switch (level) {
case (GPIO_PULL_LEVEL_NONE):
pull_level_to_reg = 0;
break;
case (GPIO_PULL_LEVEL_4_7K):
pull_level_to_reg = 2;
break;
case (GPIO_PULL_LEVEL_100K):
pull_level_to_reg = 1;
break;
default:
return -EINVAL;
}
if((reg == (void*)GPIOF_BASE && pin <= 9) || (reg == (void*)GPIOE_BASE && pin >= 4)) {
if(_GPIO_PULL_DOWN & pull_mode) {
pull_level_to_reg &= ~1;
}
}
sysctrl_unlock();
if (pin < 8) {
if (_GPIO_PULL_NONE == (pull_mode & 0xF)) {
reg->PUDL &= ~(GPIO_PULL_LEVEL_MASK << l_pin_pos);
reg->PUPL &= ~(GPIO_PULL_LEVEL_MASK << l_pin_pos);
}else if (_GPIO_PULL_DOWN & pull_mode) {
reg->PUDL = (reg->PUDL & ~ (GPIO_PULL_LEVEL_MASK << l_pin_pos)) | (pull_level_to_reg << l_pin_pos);
reg->PUPL &= ~(GPIO_PULL_LEVEL_MASK << l_pin_pos);
} else if (_GPIO_PULL_UP & pull_mode) {
reg->PUDL &= ~(GPIO_PULL_LEVEL_MASK << l_pin_pos);
reg->PUPL = (reg->PUPL & ~ (GPIO_PULL_LEVEL_MASK << l_pin_pos)) | (pull_level_to_reg << l_pin_pos);
}
} else {
if (_GPIO_PULL_NONE == (pull_mode & 0xF)) {
reg->PUDH &= ~(GPIO_PULL_LEVEL_MASK << h_pin_pos);
reg->PUPH &= ~(GPIO_PULL_LEVEL_MASK << h_pin_pos);
}else if (_GPIO_PULL_DOWN & pull_mode) {
reg->PUDH = (reg->PUDH & ~ (GPIO_PULL_LEVEL_MASK << h_pin_pos)) | (pull_level_to_reg << h_pin_pos);
reg->PUPH &= ~(GPIO_PULL_LEVEL_MASK << h_pin_pos);
} else if (_GPIO_PULL_UP & pull_mode) {
reg->PUDH &= ~(GPIO_PULL_LEVEL_MASK << h_pin_pos);
reg->PUPH = (reg->PUPH & ~ (GPIO_PULL_LEVEL_MASK << h_pin_pos)) | (pull_level_to_reg << h_pin_pos);
}
}
sysctrl_lock();
return ret;
}
static int32 hggpio_v4_set_driver_strength(struct hggpio_v4_hw *reg, uint32 pin, enum pin_driver_strength drive)
{
int32 ret = RET_OK;
uint32 pin_pos = ((pin & 0x7) * 4);
uint32 drive_to_reg = 0;
if (pin >= HGGPIO_V4_MAX_PINS) {
return -EINVAL;
}
drive_to_reg = drive;
sysctrl_unlock();
#ifdef TXW82X
// PE4-15 PF0-8的驱动等级由各自低位PD,OSPEED控制 {PD[0],DRV[0]}
if((reg == (void*)GPIOF_BASE && pin <= 9) || (reg == (void*)GPIOE_BASE && pin >= 4)) {
if (pin < 8) {
reg->OSPEEDL = (reg->OSPEEDL & ~(0xF << pin_pos)) | ((drive_to_reg&1) << pin_pos);
reg->PUDL = (reg->PUDL & ~(0xF << pin_pos)) | ((drive_to_reg>>1) << pin_pos);
} else {
reg->OSPEEDH = (reg->OSPEEDH & ~(0xF << pin_pos)) | ((drive_to_reg&1) << pin_pos);
reg->PUDH = (reg->PUDH & ~(0xF << pin_pos)) | ((drive_to_reg>>1) << pin_pos);
}
}else {
if (pin < 8) {
reg->OSPEEDL = (reg->OSPEEDL & ~(0xF << pin_pos)) | (drive_to_reg << pin_pos);
} else {
reg->OSPEEDH = (reg->OSPEEDH & ~(0xF << pin_pos)) | (drive_to_reg << pin_pos);
}
}
#else
if (pin < 8) {
reg->OSPEEDL = (reg->OSPEEDL & ~(0xF << pin_pos)) | (drive_to_reg << pin_pos);
} else {
reg->OSPEEDH = (reg->OSPEEDH & ~(0xF << pin_pos)) | (drive_to_reg << pin_pos);
}
#endif
GPIO_PRINTF("%s, GPIO: 0x%x PIN: %d STRENTH: %d\r\npudl: 0x%x pudh: 0x%x spl: 0x%x sph: 0x%x\r\n",
__FUNCTION__, reg, pin%16, drive, reg->PUDL, reg->PUDH, reg->OSPEEDL, reg->OSPEEDH);
sysctrl_lock();
return ret;
}
static int32 hggpio_v4_set_mode(struct hggpio_v4_hw *reg, uint32 pin, enum gpio_pin_mode mode, enum gpio_pull_level level)
{
uint32 pin_bit = 1UL << pin;
uint32 mode_tmp = 0;
if (pin >= HGGPIO_V4_MAX_PINS) {
return -EINVAL;
}
switch (mode) {
case GPIO_PULL_NONE:
mode_tmp = _GPIO_PULL_NONE;
SYSCTRL_REG_OPT(reg->OTYPE &= ~pin_bit);
break;
case GPIO_PULL_UP :
mode_tmp = _GPIO_PULL_UP;
SYSCTRL_REG_OPT(reg->OTYPE &= ~pin_bit);
break;
case GPIO_PULL_DOWN:
mode_tmp = _GPIO_PULL_DOWN;
SYSCTRL_REG_OPT(reg->OTYPE &= ~pin_bit);
break;
case GPIO_OPENDRAIN_PULL_NONE:
mode_tmp = _GPIO_OPENDRAIN_PULL_NONE;
SYSCTRL_REG_OPT(reg->OTYPE |= pin_bit);
break;
case GPIO_OPENDRAIN_PULL_UP:
mode_tmp = _GPIO_OPENDRAIN_PULL_UP;
SYSCTRL_REG_OPT(reg->OTYPE |= pin_bit);
break;
default:
return -EINVAL;
}
return hggpio_v4_set_pull(reg, pin, mode_tmp, level);
}
static int32_t hggpio_v4_get_omap(struct gpio_device *dev, uint32_t pin)
{
struct hggpio_v4 *gpio = (struct hggpio_v4*)dev;
struct hggpio_v4_hw *hw = (struct hggpio_v4_hw *)gpio->hw;
uint32_t iomap_out_pin_pos;
uint32_t mode_pin_pos;
uint32_t group_func;
uint32_t iofunc;
volatile uint32_t *operate_ptr = &(hw->IOFUNCOUTCON0);
if (pin < gpio->pin_num[0] || pin > gpio->pin_num[1]) {
return -EINVAL;
}
pin = hggpio_v4_pin_num(gpio, pin);
iomap_out_pin_pos = ((pin & 0x3) << 3);
mode_pin_pos = pin * 2;
operate_ptr += pin >> 2;
group_func = (((*operate_ptr) >> iomap_out_pin_pos)&0xff);
if (group_func == 0) {
return 0;
}
iofunc = group_func*5 - 5;
printf("read mask opa: %d\r\n", hggpio_v4_mask_opa(hw, pin, iofunc+1, IOMASK_OPA_READ));
if (hggpio_v4_mask_opa(hw, pin, iofunc+1, IOMASK_OPA_READ))
iofunc += hggpio_v4_mask_opa(hw, pin, iofunc+1, IOMASK_OPA_READ);
else
iofunc += 5;
return iofunc;
}
static int32_t hggpio_v4_get_imap(struct gpio_device *dev, uint32_t pin)
{
// struct hggpio_v4 *gpio = (struct hggpio_v4*)dev;
volatile uint32_t *operate_ptr = &(SYSCTRL->IOFUNCINCON0);
uint32_t reg;
for(int i = 0;i<=14;i++)
{
reg = *operate_ptr;
for(int j = 0;j<4;j++)
{
if((reg & (0xff<<(j*8))) == (pin<<(j*8))) {
return i*4+j;
}
}
operate_ptr++;
}
return 0xF000;
}
/*
* @brief:
* @ret: 返回值是16个bit, 对应16个IO(Px0->Px15). 复用了对应func则为1
*/
static int32_t hggpio_v4_get_omap_pin(struct gpio_device *dev, enum gpio_iomap_out_func iomap_out_func_sel)
{
struct hggpio_v4 *gpio = (struct hggpio_v4*)dev;
struct hggpio_v4_hw *hw = (struct hggpio_v4_hw *)gpio->hw;
unsigned int gio_func = (iomap_out_func_sel+4)/5;
uint8_t *cur_gio_func = (uint8_t *)&hw->IOFUNCOUTCON0;
int ret = 0;
if (!((hggpio_v4_mask_opa(hw, 0, iomap_out_func_sel, IOMASK_OPA_CHECK))
|| (iomap_out_func_sel == GPIO_IOMAP_OUTPUT)))
return 0;
for(int i = 0;i<16;i++)
{
if (cur_gio_func[i] == gio_func)
ret |= 1<<i;
}
return ret;
}
///////////////////////////////attach function///////////////////////
static int32_t hggpio_v4_iomap_output(struct gpio_device *gpio, uint32_t pin, enum gpio_iomap_out_func iomap_out_func_sel) {
int32 ret_val = RET_OK;
struct hggpio_v4 *dev = (struct hggpio_v4*)gpio;
struct hggpio_v4_hw *hw = (struct hggpio_v4_hw *)dev->hw;
uint32_t iomap_out_pin_pos = 0;
uint32_t mode_pin_pos = 0;
uint32_t pio = pin;
uint32_t new_func_sel = ((iomap_out_func_sel+4)/5);
volatile uint32_t *operate_ptr = &(hw->IOFUNCOUTCON0);
if (pin < dev->pin_num[0] || pin > dev->pin_num[1]) {
return -EINVAL;
}
pin = hggpio_v4_pin_num(dev, pin);
iomap_out_pin_pos = ((pin & 0x3) << 3);
mode_pin_pos = pin * 2;
operate_ptr += pin >> 2;
sysctrl_unlock();
if (GPIOC_BASE == dev->hw) {
if ((6 == pin) || (7 == pin)) {
//PC6->DP; PC7->DM change to GPIO
SYSCTRL->SYS_CON1 &= ~ BIT(18); //USB20_PHY reset
__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();
SYSCTRL->USB20_PHY_CFG3 |= (0xf << 0);
__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();
SYSCTRL->SYS_CON1 |= BIT(18);
}
}
/* clear simulation enablement for corresponding pins */
hw->AIOEN &= ~(1 << pin);
#ifdef TXW82X
//Config IOFUNCOUTCONx Reg
int old_iofunc_sel = 0;
uint32_t tmp;
//如果这个IO已经配置了IOFUNC 则清空IOFUNC以及对应的IOFUNCMASK
if( (((*operate_ptr) >> iomap_out_pin_pos)&0xff)) {
tmp = ((*operate_ptr) >> iomap_out_pin_pos)&0xff;
*operate_ptr = (*operate_ptr & ~(0xFF << iomap_out_pin_pos));
hggpio_v4_mask_opa(hw, pin, tmp*5, IOMASK_OPA_CLEAR);
old_iofunc_sel = hggpio_v4_get_omap(gpio, pio);
}
//iomap_out_func_sel = 0(LL_GPIO_OUTPUT)时不需要配mask
if(iomap_out_func_sel != 0) {
hggpio_v4_mask_opa(hw, pin, iomap_out_func_sel, IOMASK_OPA_WRITE);
}
*operate_ptr = (*operate_ptr & ~(0xFF << iomap_out_pin_pos)) | ((new_func_sel & 0x000000FF) << iomap_out_pin_pos);
#else
//Config IOFUNCOUTCONx Reg
*operate_ptr = (*operate_ptr & ~(0xFF << iomap_out_pin_pos)) | ((iomap_out_func_sel & 0x000000FF) << iomap_out_pin_pos);
#endif
//Config MODE
hw->MODE = (hw->MODE & ~(0x3 << mode_pin_pos)) | (0x01 << mode_pin_pos);
if (old_iofunc_sel) {
os_printf("GPIO Output Mapping Warning:"
"Pin %d get IOMAP func %d, the IOMAP func %d is disable\n",
pin+dev->pin_num[0], iomap_out_func_sel, old_iofunc_sel);
}
sysctrl_lock();
return ret_val;
}
static int32 hggpio_v4_iomap_input(struct gpio_device *gpio, uint32 pin, enum gpio_iomap_in_func iomap_in_func_sel) {
struct hggpio_v4 *dev = (struct hggpio_v4*)gpio;
struct hggpio_v4_hw *hw = (struct hggpio_v4_hw *)dev->hw;
int32 ret_val = RET_OK;
uint32 pin_num_temp = 0;
uint32 pin_pos = (iomap_in_func_sel & 0x3) << 3;
volatile uint32 *operate_ptr = &(SYSCTRL->IOFUNCINCON0);
if (pin < dev->pin_num[0] || pin > dev->pin_num[1]) {
return -EINVAL;
}
pin = hggpio_v4_pin_num(dev, pin);
pin_num_temp = pin;
sysctrl_unlock();
if (GPIOC_BASE == dev->hw) {
if ((6 == pin) || (7 == pin)) {
//PC6->DP; PC7->DM change to GPIO
SYSCTRL->SYS_CON1 &= ~ BIT(18); //USB20_PHY reset
__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();
SYSCTRL->USB20_PHY_CFG3 |= (0xf << 0);
__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();
SYSCTRL->SYS_CON1 |= BIT(18);
}
}
if (hw) {
hw->AIOEN &= ~(1 << pin);
}
if (0xF000 != (0xF000 & iomap_in_func_sel)) {
//Config IOMAP_INPUT
if (GPIOA_BASE == (uint32_t)dev->hw) {
pin_num_temp = pin_num_temp + 0x00;
} else if (GPIOB_BASE == (uint32_t)dev->hw) {
pin_num_temp = pin_num_temp + 0x10;
} else if (GPIOC_BASE == (uint32_t)dev->hw) {
pin_num_temp = pin_num_temp + 0x20;
} else if (GPIOD_BASE == (uint32_t)dev->hw) {
pin_num_temp = pin_num_temp + 0x30;
} else if (GPIOE_BASE == (uint32_t)dev->hw) {
pin_num_temp = pin_num_temp + 0x40;
} else if ((!dev->hw) && (!pin)) {
pin_num_temp = INMAP_CONST_1;
} else if ((!dev->hw) && ( pin)) {
pin_num_temp = INMAP_CONST_0;
}
operate_ptr = operate_ptr + (iomap_in_func_sel >> 2);
*operate_ptr = (*operate_ptr & ~(0xFF << pin_pos)) | pin_num_temp << pin_pos;
}
//Config input mode
if (hw) {
hw->MODE = hw->MODE & ~(0x03 << (pin * 2));
}
sysctrl_lock();
return ret_val;
}
static int32 hggpio_v4_iomap_inout(struct gpio_device *gpio, uint32 pin, enum gpio_iomap_in_func iomap_in_func_sel, enum gpio_iomap_out_func iomap_out_func_sel) {
if (RET_OK != hggpio_v4_iomap_input(gpio, pin, iomap_in_func_sel)) {
return RET_ERR;
}
if (RET_OK != hggpio_v4_iomap_output(gpio, pin, iomap_out_func_sel)) {
return RET_ERR;
}
return RET_OK;
}
static int32 hggpio_v4_dir(struct gpio_device *gpio,uint32 pin, enum gpio_pin_direction direction)
{
if (GPIO_DIR_INPUT != direction && GPIO_DIR_OUTPUT != direction) {
return -EINVAL;
}
if (GPIO_DIR_INPUT == direction) {
if (RET_OK != hggpio_v4_iomap_input(gpio, pin, GPIO_IOMAP_INPUT)) {
return RET_ERR;
}
} else {
if (RET_OK != hggpio_v4_iomap_output(gpio, pin, GPIO_IOMAP_OUTPUT)) {
return RET_ERR;
}
}
return RET_OK;
}
static int32_t hggpio_v4_somap_config(struct gpio_device *gpio, uint32_t pin, enum smap_node node, enum smap_output smap)
{
uint16_t iomap[4] = {
GPIO_IOMAP_OUT_SPARE0,
GPIO_IOMAP_OUT_SPARE1,
GPIO_IOMAP_OUT_SPARE2,
GPIO_IOMAP_OUT_SPARE3,
};
hggpio_v4_iomap_output(gpio, pin, iomap[node]);
sysctrl_unlock();
SYSCTRL->SPAREIO_CON &= ~(0xff << (node<<3));
SYSCTRL->SPAREIO_CON |= ((smap)<< (node<<3));
sysctrl_lock();
//同步
delay_us(10);
return 0;
}
static int32_t hggpio_v4_simap_config(struct gpio_device *gpio, uint32_t pin, enum smap_node node, enum smap_output smap)
{
volatile uint32_t *smap_icon = &SYSCTRL->SPARE_I_CON0;
node -= 4;
//0-2 刚好 是3个 SPARE IN MAP
hggpio_v4_iomap_input(gpio, pin, node);
sysctrl_unlock();
smap_icon += (smap/16);
*smap_icon = (node+1) << (2*(smap%16));
sysctrl_lock();
//同步
delay_us(10);
return 0;
}
#if HGGPIO_V4_DIR_ATOMIC_EN
static int32 hggpio_v4_dir_atomic(struct gpio_device *gpio,uint32 pin, enum gpio_pin_direction direction)
{
#if defined(__CORTEX_M) && ((__CORTEX_M == 0x03) || (__CORTEX_M == 0x04))
if (RET_OK != hggpio_v4_dir(gpio, pin, direction)) {
return RET_ERR;
}
#else
uint32 flags = disable_irq();
if (RET_OK != hggpio_v4_dir(gpio, pin, direction)) {
enable_irq(flags);
return RET_ERR;
}
enable_irq(flags);
#endif
return RET_OK;
}
#endif
static int32 hggpio_v4_mode(struct gpio_device *gpio, uint32 pin, enum gpio_pin_mode mode, enum gpio_pull_level level)
{
struct hggpio_v4 *dev = (struct hggpio_v4 *)gpio;
struct hggpio_v4_hw *hw = (struct hggpio_v4_hw *)dev->hw;
if (pin < dev->pin_num[0] || pin > dev->pin_num[1]) {
return -EINVAL;
}
pin = hggpio_v4_pin_num(dev, pin);
sysctrl_unlock();
if (GPIOC_BASE == dev->hw) {
if ((6 == pin) || (7 == pin)) {
//PC6->DP; PC7->DM change to GPIO
SYSCTRL->SYS_CON1 &= ~ BIT(18); //USB20_PHY reset
__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();
SYSCTRL->USB20_PHY_CFG3 |= (0xf << 0);
__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();
SYSCTRL->SYS_CON1 |= BIT(18);
}
}
sysctrl_lock();
return hggpio_v4_set_mode(hw, pin, mode, level);
}
#if HGGPIO_V4_DRIVER_STRENGTH_EN
static int32 hggpio_v4_driver_strength(struct gpio_device *gpio, uint32 pin, enum pin_driver_strength strength)
{
struct hggpio_v4 *dev = (struct hggpio_v4 *)gpio;
struct hggpio_v4_hw *hw = (struct hggpio_v4_hw *)dev->hw;
if (pin < dev->pin_num[0] || pin > dev->pin_num[1]) {
return -EINVAL;
}
pin = hggpio_v4_pin_num(dev, pin);
return hggpio_v4_set_driver_strength(hw, pin, strength);
}
#endif
static int32 hggpio_v4_get(struct gpio_device *gpio, uint32 pin)
{
struct hggpio_v4 *dev = (struct hggpio_v4 *)gpio;
struct hggpio_v4_hw *hw = (struct hggpio_v4_hw *)dev->hw;
if (pin < dev->pin_num[0] || pin > dev->pin_num[1]) {
return -EINVAL;
}
pin = hggpio_v4_pin_num(dev, pin);
sysctrl_unlock();
if (GPIOC_BASE == dev->hw) {
if ((6 == pin) || (7 == pin)) {
//PC6->DP; PC7->DM change to GPIO
SYSCTRL->SYS_CON1 &= ~ BIT(18); //USB20_PHY reset
__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();
SYSCTRL->USB20_PHY_CFG3 |= (0xf << 0);
__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();
SYSCTRL->SYS_CON1 |= BIT(18);
}
}
sysctrl_lock();
return (hw->IDAT & (1UL << pin)) ? 1 : 0;
}
static int32 hggpio_v4_set(struct gpio_device *gpio, uint32 pin, uint32 val)
{
struct hggpio_v4 *dev = (struct hggpio_v4 *)gpio;
struct hggpio_v4_hw *hw = (struct hggpio_v4_hw *)dev->hw;
if (pin < dev->pin_num[0] || pin > dev->pin_num[1]) {
return -EINVAL;
}
pin = hggpio_v4_pin_num(dev, pin);
sysctrl_unlock();
if (GPIOC_BASE == dev->hw) {
if ((6 == pin) || (7 == pin)) {
//PC6->DP; PC7->DM change to GPIO
SYSCTRL->SYS_CON1 &= ~ BIT(18); //USB20_PHY reset
__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();
SYSCTRL->USB20_PHY_CFG3 |= (0xf << 0);
__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();
SYSCTRL->SYS_CON1 |= BIT(18);
}
}
sysctrl_lock();
if (val) {
hw->ODAT |= (1UL << pin);
} else {
hw->ODAT &= ~(1UL << pin);
}
return RET_OK;
}
int32 hggpio_v4_set_ieen(struct gpio_device *gpio, uint32 pin, int32 val)
{
struct hggpio_v4 *dev = (struct hggpio_v4 *)gpio;
struct hggpio_v4_hw *hw = (struct hggpio_v4_hw *)dev->hw;
if (pin < dev->pin_num[0] || pin > dev->pin_num[1]) {
return -EINVAL;
}
pin = hggpio_v4_pin_num(dev, pin);
if (val) {
hw->IEEN |= (1UL << pin);
} else {
hw->IEEN &= ~(1UL << pin);
}
return RET_OK;
}
#if HGGPIO_V4_LOCK_EN
static int32 hggpio_v4_lock(struct gpio_device *gpio, uint32 pin)
{
struct hggpio_v4 *dev = (struct hggpio_v4 *)gpio;
struct hggpio_v4_hw *hw = (struct hggpio_v4_hw *)dev->hw;
uint32 tmp = 0x00010000;
if (pin < dev->pin_num[0] || pin > dev->pin_num[1]) {
return -EINVAL;
}
pin = hggpio_v4_pin_num(dev, pin);
tmp |= (1UL << pin);
/* Set LCKK bit */
hw->LCK = tmp;
/* Reset LCKK bit */
hw->LCK = (1UL << pin);
/* Set LCKK bit */
hw->LCK = tmp;
/* Read LCKK bit*/
tmp = hw->LCK;
/* Read LCKK bit*/
tmp = hw->LCK;
if (0 == (tmp & 0x00010000)) {
return RET_ERR;
}
return RET_OK;
}
#endif
#if HGGPIO_V4_DEBUNCE_EN
static int32 hggpio_v4_debunce(struct gpio_device *gpio, uint32 pin, int32 enable)
{
struct hggpio_v4 *dev = (struct hggpio_v4 *)gpio;
struct hggpio_v4_hw *hw = (struct hggpio_v4_hw *)dev->hw;
if (pin < dev->pin_num[0] || pin > dev->pin_num[1]) {
return -EINVAL;
}
pin = hggpio_v4_pin_num(dev, pin);
if (enable) {
hw->DEBEN |= (1UL << pin);
} else {
hw->DEBEN &= ~(1UL << pin);
}
return RET_OK;
}
#endif
#if HGGPIO_V4_TOGGLE_EN
static int32 hggpio_v4_toggle(struct gpio_device *gpio, uint32 pin)
{
struct hggpio_v4 *dev = (struct hggpio_v4 *)gpio;
struct hggpio_v4_hw *hw = (struct hggpio_v4_hw *)dev->hw;
if (pin < dev->pin_num[0] || pin > dev->pin_num[1]) {
return -EINVAL;
}
pin = hggpio_v4_pin_num(dev, pin);
hw->TGL = (1UL << pin);
return RET_OK;
}
#endif
#if HGGPIO_V4_SET_ATOMIC_EN
static int32 hggpio_v4_set_atomic(struct gpio_device *gpio, uint32 pin, int32 value)
{
#if defined(__CORTEX_M) && ((__CORTEX_M == 0x03) || (__CORTEX_M == 0x04))
struct hggpio_v4 *dev = (struct hggpio_v4 *)gpio;
struct hggpio_v4_hw *hw = (struct hggpio_v4_hw *)dev->hw;
if (pin < dev->pin_num[0] || pin > dev->pin_num[1]) {
return -EINVAL;
}
pin = hggpio_v4_pin_num(dev, pin);
REG_BIT_BAND((uint32)&hw->ODAT, pin) = value;
#else
uint32 flags = disable_irq();
hggpio_v4_set(gpio, pin, value);
enable_irq(flags);
#endif
return RET_OK;
}
#endif
/**********************************************************************************/
/******************* GPIO EXTERNAL FUNCTIONAL *****************************/
/**********************************************************************************/
#if HGGPIO_V4_ANALOG_EN
static int32 hggpio_v4_analog(struct gpio_device *gpio, uint32 pin, int32 enable, int32 aioen)
{
struct hggpio_v4 *dev = (struct hggpio_v4 *)gpio;
struct hggpio_v4_hw *hw = (struct hggpio_v4_hw *)dev->hw;
if (pin < dev->pin_num[0] || pin > dev->pin_num[1]) {
return -EINVAL;
}
pin = hggpio_v4_pin_num(dev, pin);
sysctrl_unlock();
if (enable) {
hw->MODE = (hw->MODE &~ (0x3 << pin*2)) | (0x3 << pin*2);
} else {
hw->MODE = (hw->MODE & ~(3UL << (pin*2)));
}
if (aioen) {
hw->AIOEN |= (1UL << (pin));
} else {
hw->AIOEN &= ~(1UL << (pin));
}
sysctrl_lock();
return RET_OK;
}
#endif
#if HGGPIO_V4_INPUT_LAG_EN
static int32 hggpio_v4_input_lag(struct gpio_device *gpio, uint32 pin, int32 enable)
{
struct hggpio_v4 *dev = (struct hggpio_v4 *)gpio;
struct hggpio_v4_hw *hw = (struct hggpio_v4_hw *)dev->hw;
if (pin < dev->pin_num[0] || pin > dev->pin_num[1]) {
return -EINVAL;
}
pin = hggpio_v4_pin_num(dev, pin);
sysctrl_unlock();
if (enable) {
hw->HY |= (1UL << pin);
} else {
hw->HY &= ~(1UL << pin);
}
sysctrl_lock();
return RET_OK;
}
#endif
static int32 hggpio_v4_afio(struct gpio_device *gpio, uint32 pin, enum gpio_afio_set afio)
{
uint32 pin_loc;
struct hggpio_v4 *dev = (struct hggpio_v4 *)gpio;
struct hggpio_v4_hw *hw = (struct hggpio_v4_hw *)dev->hw;
if (pin < dev->pin_num[0] || pin > dev->pin_num[1]) {
return -EINVAL;
}
pin = hggpio_v4_pin_num(dev, pin);
pin_loc = (pin & 0x7) * 4;
sysctrl_unlock();
hw->AIOEN &= ~(1UL << (pin));
/* set alternate function mode */
hw->MODE = (hw->MODE & ~(3UL << (pin*2))) | (2UL << (pin*2));
if (pin < 8) {
hw->AFRL = (hw->AFRL & ~(0xFUL << (pin_loc))) | (afio << (pin_loc));
} else {
hw->AFRH = (hw->AFRH & ~(0xFUL << (pin_loc))) | (afio << (pin_loc));
}
sysctrl_lock();
return RET_OK;
}
static int32 hggpio_v4_int(struct gpio_device *gpio, uint32 pin, enum gpio_irq_event evt)
{
uint32 pin_bit = 0;
int32 ret_val = RET_OK;
struct hggpio_v4 *dev = (struct hggpio_v4 *)gpio;
struct hggpio_v4_hw *hw = (struct hggpio_v4_hw *)dev->hw;
if (pin > HGGPIO_V4_MAX_PINS) {
return -EINVAL;
}
pin_bit = (1 << pin);
sysctrl_unlock();
switch(evt) {
case (GPIO_IRQ_EVENT_NONE): {
hw->IMK &= ~pin_bit;
hw->TRG0 = (hw->TRG0 &~ ((0x3) << pin*2)) | ((0x3) << pin*2);
};break;
case (GPIO_IRQ_EVENT_ALL): {
hw->IMK |= pin_bit;
hw->TRG0 = (hw->TRG0 &~ ((0x3) << pin*2)) | ((0x0) << pin*2);
};break;
case (GPIO_IRQ_EVENT_RISE): {
hw->IMK |= pin_bit;
hw->TRG0 = (hw->TRG0 &~ ((0x3) << pin*2)) | ((0x2) << pin*2);
};break;
case (GPIO_IRQ_EVENT_FALL): {
hw->IMK |= pin_bit;
hw->TRG0 = (hw->TRG0 &~ ((0x3) << pin*2)) | ((0x1) << pin*2);
};break;
default: {
ret_val = -ENOTSUPP;
break;
}
}
sysctrl_lock();
return RET_OK;
}
#if HGGPIO_V4_ADC_ANALOG_INPUT_EN
static int32 hggpio_v4_adc_analog_input(struct gpio_device *gpio, uint32 pin, int32 value) {
uint32 pin_bit = 0;
struct hggpio_v4 *dev = (struct hggpio_v4*)gpio;
struct hggpio_v4_hw *hw = (struct hggpio_v4_hw *)dev->hw;
if (pin < dev->pin_num[0] || pin > dev->pin_num[1]) {
return -EINVAL;
}
pin = hggpio_v4_pin_num(dev, pin);
pin_bit = (1 << pin);
sysctrl_unlock();
if (value) {
hw->MODE = (hw->MODE &~ (0x3 << pin*2)) | (0x3 << pin*2);
hw->AIOEN &= ~pin_bit;
hw->ADC_AIOEN |= pin_bit;
} else {
hw->ADC_AIOEN &= ~pin_bit;
hw->MODE = (hw->MODE &~ (0x3 << pin*2));
}
sysctrl_lock();
return RET_OK;
}
#endif
#if HGGPIO_V4_TK_ANALOG_INPUT_EN
static int32 hggpio_v4_tk_analog_input(struct gpio_device *gpio, uint32 pin, int32 value) {
uint32 pin_bit = 0;
struct hggpio_v4 *dev = (struct hggpio_v4*)gpio;
struct hggpio_v4_hw *hw = (struct hggpio_v4_hw *)dev->hw;
if (pin < dev->pin_num[0] || pin > dev->pin_num[1]) {
return -EINVAL;
}
pin = hggpio_v4_pin_num(dev, pin);
pin_bit = (1 << pin);
sysctrl_unlock();
if (value) {
hw->MODE = (hw->MODE &~ (0x3 << pin*2)) | (0x3 << pin*2);
//hw->AIOEN &= ~pin_bit;
//hw->TK_AIOEN |= pin_bit;
} else {
//hw->TK_AIOEN &= ~pin_bit;
hw->MODE = (hw->MODE &~ (0x3 << pin*2));
}
sysctrl_lock();
return RET_OK;
}
#endif
static int32 hggpio_v4_ioctl(struct gpio_device *gpio, uint32 pin, uint32 cmd, uint32 param1, uint32 param2)
{
int32 ret_val = RET_OK;
switch (cmd) {
#if HGGPIO_V4_INPUT_LAG_EN
case GPIO_INPUT_DELAY_ON_OFF:
ret_val = hggpio_v4_input_lag(gpio, pin, param1);
break;
#endif
#if HGGPIO_V4_LOCK_EN
case GPIO_LOCK:
ret_val = hggpio_v4_lock(gpio, pin);
break;
#endif
#if HGGPIO_V4_DEBUNCE_EN
case GPIO_DEBUNCE:
ret_val = hggpio_v4_debunce(gpio, pin, param1);
break;
#endif
#if HGGPIO_V4_TOGGLE_EN
case GPIO_OUTPUT_TOGGLE:
ret_val = hggpio_v4_toggle(gpio, pin);
break;
#endif
#if HGGPIO_V4_DIR_ATOMIC_EN
case GPIO_DIR_ATOMIC:
ret_val = hggpio_v4_dir_atomic(gpio, pin, param1);
break;
#endif
#if HGGPIO_V4_SET_ATOMIC_EN
case GPIO_VALUE_ATOMIC:
ret_val = hggpio_v4_set_atomic(gpio, pin, param1);
break;
#endif
#if HGGPIO_V4_ADC_ANALOG_INPUT_EN
case GPIO_CMD_ADC_ANALOG:
ret_val = hggpio_v4_adc_analog_input(gpio, pin, param1);
break;
#endif
#if HGGPIO_V4_TK_ANALOG_INPUT_EN
case GPIO_CMD_TK_ANALOG:
ret_val = hggpio_v4_tk_analog_input(gpio, pin, param1);
break;
#endif
case GPIO_CMD_DRIVER_STRENGTH:
ret_val = hggpio_v4_driver_strength(gpio, pin, param1);
break;
case GPIO_CMD_AFIO_SET:
ret_val = hggpio_v4_afio(gpio, pin, param1);
break;
case GPIO_CMD_IOMAP_OUT_FUNC:
ret_val = hggpio_v4_iomap_output(gpio, pin, param1);
break;
case GPIO_CMD_IOMAP_IN_FUNC:
ret_val = hggpio_v4_iomap_input(gpio, pin, param1);
break;
case GPIO_CMD_IOMAP_INOUT_FUNC:
ret_val = hggpio_v4_iomap_inout(gpio, pin, param1, param2);
break;
case GPIO_GENERAL_ANALOG:
ret_val = hggpio_v4_analog(gpio, pin, param1, 1);
break;
case GPIO_AIODIS_ANALOG:
ret_val = hggpio_v4_analog(gpio, pin, param1, 0);
break;
case GPIO_CMD_SET_IEEN:
ret_val = hggpio_v4_set_ieen(gpio, pin, param1);
break;
#ifdef TXW82X
case GPIO_GET_OUTMAP:
ret_val = hggpio_v4_get_omap(gpio, pin);
break;
case GPIO_GET_INMAP:
ret_val = hggpio_v4_get_imap(gpio, pin);
break;
case GPIO_SET_SMAP:
if(param1 < SMAP_IN_1) {
ret_val = hggpio_v4_somap_config(gpio, pin, param1, param2);
} else {
ret_val = hggpio_v4_simap_config(gpio, pin, param1, param2);
}
case GPIO_GET_OUTMAP_PIN:
ret_val = hggpio_v4_get_omap_pin(gpio, param1);
break;
#endif
default:
ret_val = -ENOTSUPP;
break;
}
return ret_val;
}
/**********************************************************************************/
/******************* GPIO IRQ FUNCTIONAL *****************************/
/**********************************************************************************/
static void hggpio_v4_irq_handler(void *data)
{
int32 i = 0;
struct hggpio_v4 *dev = (struct hggpio_v4 *)data;
struct hggpio_v4_hw *hw = (struct hggpio_v4_hw *)dev->hw;
enum gpio_irq_event evt = GPIO_IRQ_EVENT_NONE;
uint32 pending = hw->PND;
uint32 trg0 = hw->TRG0;
hw->PNDCLR = 0xFFFFFFFF;
for (i = 0; i < HGGPIO_V4_MAX_PINS; i++) {
if (pending & BIT(i)) {
if ((trg0&(0x3 << i)) == (0x1)) {
evt = GPIO_IRQ_EVENT_FALL;
} else if ((trg0&(0x3 << i)) == (0x2)) {
evt = GPIO_IRQ_EVENT_RISE;
} else {
evt = (hw->IDAT & BIT(i)) ? GPIO_IRQ_EVENT_RISE : GPIO_IRQ_EVENT_FALL;
}
if (dev->irq_hdl[i]) {
dev->irq_hdl[i](dev->pin_id[i], evt, 0, 0);
}
}
}
}
static int32 hggpio_v4_request_pin_irq(struct gpio_device *gpio, uint32 pin, gpio_irq_hdl handler, uint32 data, enum gpio_irq_event evt)
{
int32 ret = RET_OK;
struct hggpio_v4 *dev = (struct hggpio_v4 *)gpio;
if (pin < dev->pin_num[0] || pin > dev->pin_num[1]) {
return -EINVAL;
}
pin = hggpio_v4_pin_num(dev, pin);
dev->irq_hdl[pin] = handler;
dev->pin_id[pin] = data;
ret = request_irq(dev->irq_num, hggpio_v4_irq_handler, (void *)dev);
ASSERT(ret == RET_OK);
hggpio_v4_int(gpio, pin, evt);
irq_enable(dev->irq_num);
dev->flag |= GPIO_FLAG_IS_INTR_EN;
return RET_OK;
}
static int32 hggpio_v4_release_pin_irq(struct gpio_device *gpio, uint32 pin, enum gpio_irq_event evt)
{
struct hggpio_v4 *dev = (struct hggpio_v4 *)gpio;
if (pin < dev->pin_num[0] || pin > dev->pin_num[1]) {
return -EINVAL;
}
pin = hggpio_v4_pin_num(dev, pin);
dev->irq_hdl[pin] = NULL;
dev->pin_id[pin] = 0;
return hggpio_v4_int(gpio, pin, 0);
}
static int32 hggpio_v4_enable_irq(struct gpio_device *gpio, uint32 pin, uint32 enable)
{
struct hggpio_v4 *dev = (struct hggpio_v4 *)gpio;
if (pin < dev->pin_num[0] || pin > dev->pin_num[1]) {
return -EINVAL;
}
pin = hggpio_v4_pin_num(dev, pin);
if (enable) {
irq_enable(dev->irq_num);
} else {
irq_disable(dev->irq_num);
}
return RET_OK;
}
#ifdef CONFIG_SLEEP
// #define HGGPIO_SLEEP_TEST(dev) hg_gpio_sleep_test(dev)
#define HGGPIO_SLEEP_TEST(dev)
void hg_gpio_sleep_test(struct hggpio_v4 *gpio)
{
uint32_t flag = disable_irq();
struct hggpio_v4_hw *hw = (struct hggpio_v4_hw *)gpio->hw;
uint32_t *p32;
if(hw == (void*)GPIOE_BASE) {
p32 = (void*)&SYSCTRL->IOFUNCINCON0;
_os_printf("IOFUNCIN:\r\n");
for(int i = 0;i<15;i++)
{
_os_printf("0x%x\r\n", p32[i]);
}
_os_printf("\r\n");
_os_printf("IOFUNCMASK: [0x%x, 0x%x, 0x%x, 0x%x]\r\n"
"[0x%x, 0x%x, 0x%x, 0x%x, 0x%x]\r\n""spare: [0x%x, 0x%x, 0x%x, 0x%x]",
SYSCTRL->IOFUNCMASK0, SYSCTRL->IOFUNCMASK1, SYSCTRL->IOFUNCMASK2,
SYSCTRL->IOFUNCMASK3, SYSCTRL->IOFUNCMASK4, SYSCTRL->IOFUNCMASK5,
SYSCTRL->IOFUNCMASK6, SYSCTRL->IOFUNCMASK7, SYSCTRL->IOFUNCMASK8,
SYSCTRL->SPAREIO_CON, SYSCTRL->SPARE_I_CON0, SYSCTRL->SPARE_I_CON1,
SYSCTRL->SPARE_I_CON2
);
}
_os_printf("*********gpio 0x%x\r\n", hw);
p32 = (void*)hw;
for(int j = 0;j<0x20+1;j+=4)
{
_os_printf("0x%08x 0x%08x 0x%08x 0x%08x\r\n",
p32[j], p32[j+1], p32[j+2], p32[j+3]);
}
enable_irq(flag);
}
int32 hggpio_v4_suspend(struct dev_obj *obj)
{
struct hggpio_v4 *gpio = (struct hggpio_v4 *)obj;
struct hggpio_v4_hw *hw = (struct hggpio_v4_hw *)gpio->hw;
gpio->bk.MODE = hw->MODE;
gpio->bk.OTYPE = hw->OTYPE;
gpio->bk.OSPEEDL = hw->OSPEEDL;
gpio->bk.OSPEEDH = hw->OSPEEDH;
gpio->bk.PUPL = hw->PUPL;
gpio->bk.PUPH = hw->PUPH;
gpio->bk.PUDL = hw->PUDL;
gpio->bk.PUDH = hw->PUDH;
gpio->bk.ODAT = hw->ODAT;
gpio->bk.AFRL = hw->AFRL;
gpio->bk.AFRH = hw->AFRH;
gpio->bk.IMK = hw->IMK;
gpio->bk.DEBEN = hw->DEBEN;
gpio->bk.AIOEN = hw->AIOEN;
gpio->bk.TRG0 = hw->TRG0;
gpio->bk.IEEN = hw->IEEN;
gpio->bk.IOFUNCOUTCON0 = hw->IOFUNCOUTCON0;
gpio->bk.IOFUNCOUTCON1 = hw->IOFUNCOUTCON1;
gpio->bk.IOFUNCOUTCON2 = hw->IOFUNCOUTCON2;
gpio->bk.IOFUNCOUTCON3 = hw->IOFUNCOUTCON3;
gpio->flag |= GPIO_FLAG_IS_SUSPENDED;
memcpy(gpio_sys.iofuncin, (void*)&SYSCTRL->IOFUNCINCON0, 15*4);
#if defined(TXW82X)
gpio_sys.iomask[0] = SYSCTRL->IOFUNCMASK0;
gpio_sys.iomask[1] = SYSCTRL->IOFUNCMASK1;
gpio_sys.iomask[2] = SYSCTRL->IOFUNCMASK2;
gpio_sys.iomask[3] = SYSCTRL->IOFUNCMASK3;
gpio_sys.iomask[4] = SYSCTRL->IOFUNCMASK4;
gpio_sys.iomask[5] = SYSCTRL->IOFUNCMASK5;
gpio_sys.iomask[6] = SYSCTRL->IOFUNCMASK6;
gpio_sys.iomask[7] = SYSCTRL->IOFUNCMASK7;
gpio_sys.iomask[8] = SYSCTRL->IOFUNCMASK8;
gpio_sys.io_spare[0] = SYSCTRL->SPAREIO_CON;
gpio_sys.io_spare[1] = SYSCTRL->SPARE_I_CON0;
gpio_sys.io_spare[2] = SYSCTRL->SPARE_I_CON1;
gpio_sys.io_spare[3] = SYSCTRL->SPARE_I_CON2;
#else
gpio_sys.iomask[0] = SYSCTRL->IOFUNCMASK0;
gpio_sys.iomask[1] = SYSCTRL->IOFUNCMASK1;
#endif
gpio_sys.flag |= SYSCTRL_FLAG_IS_SUSPEND;
if(SYSCTRL->USB20_PHY_CFG3 & 0x8) {
gpio_sys.flag |= SYSCTRL_FLAG_IS_USB2GPIO;
} else {
gpio_sys.flag &= ~SYSCTRL_FLAG_IS_USB2GPIO;
}
HGGPIO_SLEEP_TEST(gpio);
return 0;
}
int32 hggpio_v4_resume(struct dev_obj *obj)
{
struct hggpio_v4 *gpio = (struct hggpio_v4 *)obj;
struct hggpio_v4_hw *hw = (struct hggpio_v4_hw *)gpio->hw;
if(gpio->flag & GPIO_FLAG_IS_SUSPENDED) {
hw->MODE = gpio->bk.MODE;
hw->OTYPE = gpio->bk.OTYPE;
hw->OSPEEDL = gpio->bk.OSPEEDL;
hw->OSPEEDH = gpio->bk.OSPEEDH;
hw->PUPL = gpio->bk.PUPL;
hw->PUPH = gpio->bk.PUPH;
hw->PUDL = gpio->bk.PUDL;
hw->PUDH = gpio->bk.PUDH;
hw->ODAT = gpio->bk.ODAT;
hw->AFRL = gpio->bk.AFRL;
hw->AFRH = gpio->bk.AFRH;
hw->IMK = gpio->bk.IMK;
hw->DEBEN = gpio->bk.DEBEN;
hw->AIOEN = gpio->bk.AIOEN;
hw->TRG0 = gpio->bk.TRG0;
hw->IEEN = gpio->bk.IEEN;
hw->IOFUNCOUTCON0 = gpio->bk.IOFUNCOUTCON0;
hw->IOFUNCOUTCON1 = gpio->bk.IOFUNCOUTCON1;
hw->IOFUNCOUTCON2 = gpio->bk.IOFUNCOUTCON2;
hw->IOFUNCOUTCON3 = gpio->bk.IOFUNCOUTCON3;
gpio->flag &= ~GPIO_FLAG_IS_SUSPENDED;
}
if(gpio_sys.flag & SYSCTRL_FLAG_IS_SUSPEND) {
sysctrl_unlock();
memcpy((void*)&SYSCTRL->IOFUNCINCON0, gpio_sys.iofuncin, 15*4);
#if defined(TXW82X)
SYSCTRL->IOFUNCMASK0 = gpio_sys.iomask[0];
SYSCTRL->IOFUNCMASK1 = gpio_sys.iomask[1];
SYSCTRL->IOFUNCMASK2 = gpio_sys.iomask[2];
SYSCTRL->IOFUNCMASK3 = gpio_sys.iomask[3];
SYSCTRL->IOFUNCMASK4 = gpio_sys.iomask[4];
SYSCTRL->IOFUNCMASK5 = gpio_sys.iomask[5];
SYSCTRL->IOFUNCMASK6 = gpio_sys.iomask[6];
SYSCTRL->IOFUNCMASK7 = gpio_sys.iomask[7];
SYSCTRL->IOFUNCMASK8 = gpio_sys.iomask[8];
SYSCTRL->SPAREIO_CON = gpio_sys.io_spare[0];
SYSCTRL->SPARE_I_CON0 = gpio_sys.io_spare[1];
SYSCTRL->SPARE_I_CON1 = gpio_sys.io_spare[2];
SYSCTRL->SPARE_I_CON2 = gpio_sys.io_spare[3];
#else
SYSCTRL->IOFUNCMASK0 = gpio_sys.iomask[0];
SYSCTRL->IOFUNCMASK1 = gpio_sys.iomask[1];
#endif
if(gpio_sys.flag & SYSCTRL_FLAG_IS_USB2GPIO) {
//PC6->DP; PC7->DM change to GPIO
SYSCTRL->SYS_CON1 &= ~ BIT(18); //USB20_PHY reset
__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();
SYSCTRL->USB20_PHY_CFG3 |= (0xf << 0);
__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();__NOP();
SYSCTRL->SYS_CON1 |= BIT(18);
}
sysctrl_lock();
gpio_sys.flag &= ~SYSCTRL_FLAG_IS_SUSPEND;
}
HGGPIO_SLEEP_TEST(gpio);
return 0;
}
#else
int32_t hggpio_v4_suspend(struct hggpio_v4 *gpio)
{
return 0;
}
int32_t hggpio_v4_resume(struct hggpio_v4 *gpio)
{
return 0;
}
#endif
static const struct gpio_hal_ops gpio_v4_ops = {
.mode = hggpio_v4_mode,
.dir = hggpio_v4_dir,
.set = hggpio_v4_set,
.get = hggpio_v4_get,
.ioctl = hggpio_v4_ioctl,
.request_pin_irq = hggpio_v4_request_pin_irq,
.release_pin_irq = hggpio_v4_release_pin_irq,
#ifdef CONFIG_SLEEP
.ops.suspend = hggpio_v4_suspend,
.ops.resume = hggpio_v4_resume,
#endif
};
int32 hggpio_v4_attach(uint32 dev_id, struct hggpio_v4 *gpio)
{
int32 i = 0;
// struct hggpio_v4 *dev = (struct hggpio_v4*)gpio;
// struct hggpio_v4_hw *hw = (struct hggpio_v4_hw *)dev->hw;
//V2 IOFUNCOUTCON0-3无复位值故全写0 ----- !初始值的初始化迁移到其他地方了
// memset((void *)&hw->IOFUNCOUTCON0, 0, sizeof(hw->IOFUNCOUTCON0)*4);
gpio->dev.dev.ops = (const struct devobj_ops *)&gpio_v4_ops;
for (i = 0; i < HGGPIO_V4_MAX_PINS; i++) {
gpio->irq_hdl[i] = NULL;
}
irq_disable(gpio->irq_num);
dev_register(dev_id, (struct dev_obj *)gpio);
return RET_OK;
}