arm/tlsr82: gpio driver bug fix and optimize.

Signed-off-by: wangbowen6 <wangbowen6@xiaomi.com>
This commit is contained in:
wangbowen6 2022-06-07 16:09:19 +08:00 committed by Xiang Xiao
parent 8217c646a7
commit af87921eda
5 changed files with 217 additions and 58 deletions

View File

@ -209,6 +209,14 @@ config TLSR82_GPIO_VALIDATION
gpio can be configured be this multiplex function. But this function gpio can be configured be this multiplex function. But this function
need more flash space. need more flash space.
config TLSR82_GPIO_DUMPREGS
bool "Tlsr82 gpio dump registers enable"
default n
depends on DEBUG_GPIO_INFO
---help---
If enable this config, developer can call tlsr82_gpio_dumpregs() to
dump all the gpio registers.
endif endif
menuconfig TLSR82_I2C menuconfig TLSR82_I2C

View File

@ -90,7 +90,7 @@
#define GPIO_IRQ_NORMAL_ALL_REG REG_ADDR8(0x5b5) #define GPIO_IRQ_NORMAL_ALL_REG REG_ADDR8(0x5b5)
#define GPIO_IRQ_RISC_EN_REG REG_ADDR8(0x642) #define GPIO_IRQ_RISC_EN_REG REG_ADDR8(0x642)
#define GPIO_IRQ_NORMAL_REG(group) REG_ADDR8(0x587 + (group)) #define GPIO_IRQ_NORMAL_REG(group) REG_ADDR8(0x587 + ((group) << 3))
#define GPIO_IRQ_M0_REG(group) REG_ADDR8(0x5b8 + (group)) #define GPIO_IRQ_M0_REG(group) REG_ADDR8(0x5b8 + (group))
#define GPIO_IRQ_M1_REG(group) REG_ADDR8(0x5c0 + (group)) #define GPIO_IRQ_M1_REG(group) REG_ADDR8(0x5c0 + (group))
#define GPIO_IRQ_M2_REG(group) REG_ADDR8(0x5c8 + (group)) #define GPIO_IRQ_M2_REG(group) REG_ADDR8(0x5c8 + (group))

View File

@ -69,6 +69,12 @@ struct tlsr82_gpio_irq_cb gpio_irq_cbs[CONFIG_GPIO_IRQ_MAX_NUM];
* Private Function Prototypes * Private Function Prototypes
****************************************************************************/ ****************************************************************************/
#ifdef CONFIG_TLSR82_GPIO_DUMPREGS
static void tlsr82_gpio_dumpregs(const char *msg);
#else
# define tlsr82_gpio_dumpregs(msg)
#endif
static void tlsr82_gpio_ds_ctrl(gpio_cfg_t cfg, uint8_t ds); static void tlsr82_gpio_ds_ctrl(gpio_cfg_t cfg, uint8_t ds);
static void tlsr82_gpio_pol_ctrl(gpio_cfg_t cfg, uint8_t pol); static void tlsr82_gpio_pol_ctrl(gpio_cfg_t cfg, uint8_t pol);
@ -76,6 +82,62 @@ static void tlsr82_gpio_pol_ctrl(gpio_cfg_t cfg, uint8_t pol);
* Private Functions * Private Functions
****************************************************************************/ ****************************************************************************/
#ifdef CONFIG_TLSR82_GPIO_DUMPREGS
static void tlsr82_gpio_dumpregs(const char *msg)
{
int i = 0;
gpioinfo("%s\n", msg);
for (i = 0; i < 5; i++)
{
gpioinfo("Group %d Gpio Register:\n", i);
gpioinfo(" ACT=0x%02x\n", GPIO_SETTING_ACT_REG(i));
gpioinfo(" IN =0x%02x\n", GPIO_SETTING_IN_REG(i));
if (i != 3)
{
gpioinfo(" IE =0x%02x\n", GPIO_SETTING_IE_REG(i));
}
else
{
gpioinfo(" IE =0x%02x\n", tlsr82_analog_read(ANALOG_PC_IE_ADDR));
}
gpioinfo(" OEN=0x%02x\n", GPIO_SETTING_OEN_REG(i));
gpioinfo(" OUT=0x%02x\n", GPIO_SETTING_OUT_REG(i));
gpioinfo(" POL=0x%02x\n", GPIO_SETTING_POL_REG(i));
if (i != 3)
{
gpioinfo(" DS =0x%02x\n", GPIO_SETTING_DS_REG(i));
}
else
{
gpioinfo(" DS =0x%02x\n", tlsr82_analog_read(ANALOG_PC_DS_ADDR));
}
}
gpioinfo("Interrupt Register:\n");
for (i = 0; i < 5; i++)
{
gpioinfo(" IRQ NORMAL %d: 0x%02x\n", i, GPIO_IRQ_NORMAL_REG(i));
}
gpioinfo(" IRQ NORMAL ALL 0x%02x\n", GPIO_IRQ_NORMAL_ALL_REG);
gpioinfo(" IRQ RISC: 0x%02x\n", GPIO_IRQ_RISC_EN_REG);
gpioinfo(" IRQ MASK: 0x%08lx\n", IRQ_MASK_REG);
for (i = 0; i < CONFIG_GPIO_IRQ_MAX_NUM; i++)
{
gpioinfo("gpio_irq_cbs[%d]->arg : 0x%08x\n",
i, gpio_irq_cbs[i].arg);
gpioinfo("gpio_irq_cbs[%d]->callback: 0x%08x\n",
i, gpio_irq_cbs[i].callback);
gpioinfo("gpio_irq_cbs[%d]->cfg : 0x%08x\n",
i, gpio_irq_cbs[i].cfg);
}
}
#endif
/**************************************************************************** /****************************************************************************
* Name: tlsr82_gpio_ds_ctrl * Name: tlsr82_gpio_ds_ctrl
* *
@ -184,6 +246,8 @@ static int tlsr82_gpio_irq(int irq, void *context, void *arg)
xcpt_t callback; xcpt_t callback;
int ret = OK; int ret = OK;
gpioinfo("Gpio irq entry!\n");
/* Clear the GPIO interrupt status */ /* Clear the GPIO interrupt status */
BM_SET(IRQ_SRC_REG, 1 << NR_GPIO_IRQ); BM_SET(IRQ_SRC_REG, 1 << NR_GPIO_IRQ);
@ -219,6 +283,8 @@ static int tlsr82_gpio_risc0_irq(int irq, void *context, void *arg)
xcpt_t callback; xcpt_t callback;
int ret = OK; int ret = OK;
gpioinfo("Gpio risc0 irq entry!\n");
/* Clear the GPIO interrupt status */ /* Clear the GPIO interrupt status */
BM_SET(IRQ_SRC_REG, 1 << NR_GPIO_RISC0_IRQ); BM_SET(IRQ_SRC_REG, 1 << NR_GPIO_RISC0_IRQ);
@ -254,6 +320,8 @@ static int tlsr82_gpio_risc1_irq(int irq, void *context, void *arg)
xcpt_t callback; xcpt_t callback;
int ret = OK; int ret = OK;
gpioinfo("Gpio risc1 irq entry!\n");
/* Clear the GPIO interrupt status */ /* Clear the GPIO interrupt status */
BM_SET(IRQ_SRC_REG, 1 << NR_GPIO_RISC1_IRQ); BM_SET(IRQ_SRC_REG, 1 << NR_GPIO_RISC1_IRQ);
@ -486,21 +554,17 @@ int tlsr82_gpioconfig(gpio_cfg_t cfg)
if (GPIO_IS(AF, INPUT, cfg)) if (GPIO_IS(AF, INPUT, cfg))
{ {
/* GPIO setting act as GPIO */
BM_SET(GPIO_SETTING_ACT_REG(group), BIT(pin));
/* IE and OEN should be set to 1 for Input usage */ /* IE and OEN should be set to 1 for Input usage */
tlsr82_gpio_input_ctrl(cfg, true); tlsr82_gpio_input_ctrl(cfg, true);
tlsr82_gpio_output_ctrl(cfg, false); tlsr82_gpio_output_ctrl(cfg, false);
}
else if (GPIO_IS(AF, OUTPUT, cfg))
{
/* GPIO setting act as GPIO */ /* GPIO setting act as GPIO */
BM_SET(GPIO_SETTING_ACT_REG(group), BIT(pin)); BM_SET(GPIO_SETTING_ACT_REG(group), BIT(pin));
}
else if (GPIO_IS(AF, OUTPUT, cfg))
{
/* IE and OEN should be set to 0 for Output usage */ /* IE and OEN should be set to 0 for Output usage */
tlsr82_gpio_input_ctrl(cfg, false); tlsr82_gpio_input_ctrl(cfg, false);
@ -509,6 +573,10 @@ int tlsr82_gpioconfig(gpio_cfg_t cfg)
/* Drive Strength config */ /* Drive Strength config */
tlsr82_gpio_ds_ctrl(cfg, (bool)GPIO_GET(DS, cfg)); tlsr82_gpio_ds_ctrl(cfg, (bool)GPIO_GET(DS, cfg));
/* GPIO setting act as GPIO */
BM_SET(GPIO_SETTING_ACT_REG(group), BIT(pin));
} }
else if (GPIO_GET(AF, cfg) >= GPIO_VAL(AF, MUX0) && else if (GPIO_GET(AF, cfg) >= GPIO_VAL(AF, MUX0) &&
GPIO_GET(AF, cfg) <= GPIO_VAL(AF, MUX3)) GPIO_GET(AF, cfg) <= GPIO_VAL(AF, MUX3))
@ -667,6 +735,8 @@ void tlsr82_gpioirqinitialize(void)
* Description: * Description:
* Config the gpio irq according to the cfg, and attach or * Config the gpio irq according to the cfg, and attach or
* detach the interrupt callback function according to value of func. * detach the interrupt callback function according to value of func.
* High Level or Rising Edge trigger, should set the pull-down resistor
* Low Level or Failing Edge trigger, should set the pull-up resistor
* *
****************************************************************************/ ****************************************************************************/
@ -676,6 +746,8 @@ int tlsr82_gpioirqconfig(gpio_cfg_t cfg, xcpt_t func, void *arg)
int i; int i;
gpio_cfg_t pinset; gpio_cfg_t pinset;
gpioinfo("cfg=0x%lx, func=0x%lx\n", cfg, (uint32_t)func);
/* Get pin information from cfg */ /* Get pin information from cfg */
pinset = GPIO_CFG2PIN(cfg); pinset = GPIO_CFG2PIN(cfg);
@ -744,18 +816,26 @@ int tlsr82_gpioirqconfig(gpio_cfg_t cfg, xcpt_t func, void *arg)
tlsr82_gpioirqenable(cfg); tlsr82_gpioirqenable(cfg);
} }
/* GPIO must be in input mode for gpio interrupt */ /* Configure the gpio */
tlsr82_gpioconfig(pinset | GPIO_AF_INPUT | GPIO_PUPD_NONE); tlsr82_gpioconfig(cfg);
/* Config gpio interrupt polarity */ /* Config gpio interrupt polarity */
tlsr82_gpio_pol_ctrl(GPIO_CFG2SDKPIN(cfg), GPIO_GET(POL, cfg)); tlsr82_gpio_pol_ctrl(cfg, GPIO_GET(POL, cfg));
/* Clear the interrupt flag */
tlsr82_gpioirqclear(cfg);
/* Enable corresponding gpio interrupt */ /* Enable corresponding gpio interrupt */
tlsr82_gpioirqenable_all(); tlsr82_gpioirqenable_all();
/* Dump the gpio register for debug */
tlsr82_gpio_dumpregs("tlsr82_gpioirqconfig()");
return OK; return OK;
} }
#endif #endif
@ -884,6 +964,43 @@ void tlsr82_gpioirqdisable(gpio_cfg_t cfg)
#endif #endif
/****************************************************************************
* Name: tlsr82_gpioirqclear
*
* Description:
* Clear the interrupt flag for specified GPIO IRQ
*
****************************************************************************/
#ifdef CONFIG_TLSR82_GPIO_IRQ
void tlsr82_gpioirqclear(gpio_cfg_t cfg)
{
uint32_t irqmode;
irqmode = (uint32_t)GPIO_GET(IRQ, cfg);
/* Clear corresponding gpio interrupt flag */
if (irqmode == GPIO_IRQ_NORMAL_VAL)
{
BM_SET(IRQ_SRC_REG, BIT(NR_GPIO_IRQ));
}
else if (irqmode == GPIO_IRQ_RISC0_VAL)
{
BM_SET(IRQ_SRC_REG, BIT(NR_GPIO_RISC0_IRQ));
}
else if (irqmode == GPIO_IRQ_RISC1_VAL)
{
BM_SET(IRQ_SRC_REG, BIT(NR_GPIO_RISC1_IRQ));
}
else
{
gpioerr("GPIO irq type is not correct, cfg=0x%lx\n", cfg);
}
}
#endif
/**************************************************************************** /****************************************************************************
* Name: tlsr82_gpioirqdisable_all * Name: tlsr82_gpioirqdisable_all
* *

View File

@ -144,7 +144,7 @@
#define GPIO_POL_SHIFT 23 #define GPIO_POL_SHIFT 23
#define GPIO_POL_MASK (0x1 << GPIO_POL_SHIFT) #define GPIO_POL_MASK (0x1 << GPIO_POL_SHIFT)
#define GPIO_POL_RISE (0 << GPIO_POL_SHIFT) #define GPIO_POL_RISE (0 << GPIO_POL_SHIFT)
#define GPIO_POL_FAIL (1 << GPIO_POL_SHIFT) #define GPIO_POL_FALL (1 << GPIO_POL_SHIFT)
/* GPIO specific pin definitions */ /* GPIO specific pin definitions */

View File

@ -47,9 +47,11 @@
struct tlsr82gpio_dev_s struct tlsr82gpio_dev_s
{ {
struct gpio_dev_s gpio; struct gpio_dev_s gpio; /* GPIO Device */
pin_interrupt_t callback; pin_interrupt_t callback; /* Interrupt callback */
uint8_t id; uint8_t id; /* ID */
gpio_cfg_t pinset; /* The pin set */
const enum gpio_pintype_e init_pintype; /* The pin type */
}; };
/**************************************************************************** /****************************************************************************
@ -78,24 +80,26 @@ static const struct gpio_operations_s gpio_ops =
.go_setpintype = tlsr82_go_setpintype, .go_setpintype = tlsr82_go_setpintype,
}; };
static gpio_cfg_t g_gpios[BOARD_NGPIO] = static struct tlsr82gpio_dev_s g_gpdevs[BOARD_NGPIO] =
{ {
GPIO_PIN_PD6 | GPIO_AF_INPUT | GPIO_PUPD_NONE,
GPIO_PIN_PD0 | GPIO_AF_OUTPUT | GPIO_PUPD_NONE,
GPIO_PIN_PD1 | GPIO_AF_OUTPUT | GPIO_PUPD_NONE,
GPIO_PIN_PB3 | GPIO_IRQ_NORMAL | GPIO_POL_RISE,
};
static const enum gpio_pintype_e g_init_pintype[BOARD_NGPIO] =
{ {
GPIO_INPUT_PIN, .pinset = GPIO_PIN_PD6,
GPIO_OUTPUT_PIN, .init_pintype = GPIO_INPUT_PIN_PULLDOWN,
GPIO_OUTPUT_PIN, },
GPIO_INTERRUPT_RISING_PIN, {
.pinset = GPIO_PIN_PD0,
.init_pintype = GPIO_OUTPUT_PIN,
},
{
.pinset = GPIO_PIN_PD1,
.init_pintype = GPIO_OUTPUT_PIN,
},
{
.pinset = GPIO_PIN_PB3,
.init_pintype = GPIO_INTERRUPT_FALLING_PIN,
}
}; };
static struct tlsr82gpio_dev_s g_gpdevs[BOARD_NGPIO];
/**************************************************************************** /****************************************************************************
* Private Functions * Private Functions
****************************************************************************/ ****************************************************************************/
@ -117,9 +121,9 @@ static int tlsr82_go_read(struct gpio_dev_s *dev, bool *value)
DEBUGASSERT(tlsr82gpio != NULL && value != NULL); DEBUGASSERT(tlsr82gpio != NULL && value != NULL);
DEBUGASSERT(tlsr82gpio->id < BOARD_NGPIO); DEBUGASSERT(tlsr82gpio->id < BOARD_NGPIO);
gpioinfo("Reading...\n"); gpioinfo("Reading, pinset=0x%08lx\n", tlsr82gpio->pinset);
*value = tlsr82_gpioread(g_gpios[tlsr82gpio->id]); *value = tlsr82_gpioread(tlsr82gpio->pinset);
return OK; return OK;
} }
@ -129,9 +133,9 @@ static int tlsr82_go_write(struct gpio_dev_s *dev, bool value)
DEBUGASSERT(tlsr82gpio != NULL); DEBUGASSERT(tlsr82gpio != NULL);
DEBUGASSERT(tlsr82gpio->id < BOARD_NGPIO); DEBUGASSERT(tlsr82gpio->id < BOARD_NGPIO);
gpioinfo("Writing %d\n", (int)value); gpioinfo("Writing %d\n, pinset=0x%08lx\n", (int)value, tlsr82gpio->pinset);
tlsr82_gpiowrite(g_gpios[tlsr82gpio->id], value); tlsr82_gpiowrite(tlsr82gpio->pinset, value);
return OK; return OK;
} }
@ -144,7 +148,7 @@ static int tlsr82_go_attach(struct gpio_dev_s *dev,
/* Make sure the interrupt is disabled */ /* Make sure the interrupt is disabled */
tlsr82_gpioirqconfig(g_gpios[tlsr82gpio->id], NULL, NULL); tlsr82_gpioirqconfig(tlsr82gpio->pinset, NULL, NULL);
gpioinfo("Attach %p\n", callback); gpioinfo("Attach %p\n", callback);
tlsr82gpio->callback = callback; tlsr82gpio->callback = callback;
@ -155,8 +159,6 @@ static int tlsr82_go_enable(struct gpio_dev_s *dev, bool enable)
{ {
struct tlsr82gpio_dev_s *tlsr82gpio = (struct tlsr82gpio_dev_s *)dev; struct tlsr82gpio_dev_s *tlsr82gpio = (struct tlsr82gpio_dev_s *)dev;
uint8_t gpioid = tlsr82gpio->id;
if (enable) if (enable)
{ {
if (tlsr82gpio->callback != NULL) if (tlsr82gpio->callback != NULL)
@ -165,8 +167,8 @@ static int tlsr82_go_enable(struct gpio_dev_s *dev, bool enable)
/* Configure the interrupt for rising edge */ /* Configure the interrupt for rising edge */
tlsr82_gpioirqconfig(g_gpios[gpioid], tlsr82_go_interrupt, tlsr82_gpioirqconfig(tlsr82gpio->pinset, tlsr82_go_interrupt,
&g_gpdevs[gpioid]); tlsr82gpio);
} }
else else
{ {
@ -176,7 +178,7 @@ static int tlsr82_go_enable(struct gpio_dev_s *dev, bool enable)
else else
{ {
gpioinfo("Disable the interrupt\n"); gpioinfo("Disable the interrupt\n");
tlsr82_gpioirqconfig(g_gpios[gpioid], NULL, NULL); tlsr82_gpioirqconfig(tlsr82gpio->pinset, NULL, NULL);
} }
return OK; return OK;
@ -187,9 +189,11 @@ static int tlsr82_go_setpintype(struct gpio_dev_s *dev,
{ {
int ret = OK; int ret = OK;
gpio_cfg_t cfg; gpio_cfg_t cfg;
gpio_cfg_t irq;
struct tlsr82gpio_dev_s *tlsr82gpio = (struct tlsr82gpio_dev_s *)dev; struct tlsr82gpio_dev_s *tlsr82gpio = (struct tlsr82gpio_dev_s *)dev;
cfg = GPIO_CFG2PIN(g_gpios[tlsr82gpio->id]); cfg = GPIO_CFG2PIN(tlsr82gpio->pinset);
irq = tlsr82gpio->pinset & GPIO_IRQ_MASK;
switch (pintype) switch (pintype)
{ {
@ -216,31 +220,51 @@ static int tlsr82_go_setpintype(struct gpio_dev_s *dev,
case GPIO_OUTPUT_PIN: case GPIO_OUTPUT_PIN:
{ {
cfg = GPIO_AF_OUTPUT | GPIO_DS_HIGH; cfg |= GPIO_AF_OUTPUT | GPIO_DS_HIGH;
tlsr82_gpioconfig(cfg); tlsr82_gpioconfig(cfg);
} }
break; break;
case GPIO_INTERRUPT_PIN: case GPIO_INTERRUPT_PIN:
case GPIO_INTERRUPT_HIGH_PIN:
case GPIO_INTERRUPT_RISING_PIN: case GPIO_INTERRUPT_RISING_PIN:
{ {
cfg |= GPIO_AF_INPUT | GPIO_PUPD_NONE | GPIO_IRQ_NORMAL | cfg |= GPIO_AF_INPUT | GPIO_PUPD_PD100K | GPIO_POL_RISE;
GPIO_POL_RISE; if (irq == GPIO_IRQ_DISABLE)
{
/* If do not specify the interrupt type, default normal */
cfg |= GPIO_IRQ_NORMAL;
}
else
{
cfg |= irq;
}
tlsr82_gpioirqconfig(cfg, NULL, NULL); tlsr82_gpioirqconfig(cfg, NULL, NULL);
} }
break; break;
case GPIO_INTERRUPT_LOW_PIN:
case GPIO_INTERRUPT_FALLING_PIN: case GPIO_INTERRUPT_FALLING_PIN:
{ {
cfg |= GPIO_AF_INPUT | GPIO_PUPD_NONE | GPIO_IRQ_NORMAL | cfg |= GPIO_AF_INPUT | GPIO_PUPD_PU10K | GPIO_POL_FALL;
GPIO_POL_FAIL; if (irq == GPIO_IRQ_DISABLE)
{
/* If do not specify the interrupt type, default normal */
cfg |= GPIO_IRQ_NORMAL;
}
else
{
cfg |= irq;
}
tlsr82_gpioirqconfig(cfg, NULL, NULL); tlsr82_gpioirqconfig(cfg, NULL, NULL);
} }
break; break;
case GPIO_OUTPUT_PIN_OPENDRAIN: case GPIO_OUTPUT_PIN_OPENDRAIN:
case GPIO_INTERRUPT_HIGH_PIN:
case GPIO_INTERRUPT_LOW_PIN:
case GPIO_INTERRUPT_BOTH_PIN: case GPIO_INTERRUPT_BOTH_PIN:
default: default:
{ {
@ -252,7 +276,9 @@ static int tlsr82_go_setpintype(struct gpio_dev_s *dev,
/* Assign back the config information */ /* Assign back the config information */
g_gpios[tlsr82gpio->id] = cfg; tlsr82gpio->pinset = cfg;
gpioinfo("pinset=0x%08lx\n", cfg);
errout: errout:
return ret; return ret;
@ -269,22 +295,30 @@ errout:
int tlsr82_gpio_initialize(void) int tlsr82_gpio_initialize(void)
{ {
int i; int i;
int ret = OK;
struct tlsr82gpio_dev_s *tlsr82gpio;
tlsr82_gpioirqconfig(g_gpios[3], NULL, NULL); tlsr82_gpioirqinitialize();
for (i = 0; i < BOARD_NGPIO; i++) for (i = 0; i < BOARD_NGPIO; i++)
{ {
g_gpdevs[i].gpio.gp_pintype = g_init_pintype[i]; tlsr82gpio = &g_gpdevs[i];
g_gpdevs[i].gpio.gp_ops = &gpio_ops; tlsr82gpio->gpio.gp_pintype = tlsr82gpio->init_pintype;
g_gpdevs[i].id = i; tlsr82gpio->gpio.gp_ops = &gpio_ops;
gpio_pin_register(&g_gpdevs[i].gpio, i); tlsr82gpio->id = i;
/* Configure the pin that will be used as input */ ret = tlsr82_go_setpintype(&tlsr82gpio->gpio,
tlsr82gpio->init_pintype);
tlsr82_gpioconfig(g_gpios[i]); if (ret < 0)
{
goto out;
} }
return 0; gpio_pin_register(&tlsr82gpio->gpio, i);
}
out:
return ret;
} }
#endif /* CONFIG_DEV_GPIO && !CONFIG_GPIO_LOWER_HALF */ #endif /* CONFIG_DEV_GPIO && !CONFIG_GPIO_LOWER_HALF */