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
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
menuconfig TLSR82_I2C

View File

@ -90,7 +90,7 @@
#define GPIO_IRQ_NORMAL_ALL_REG REG_ADDR8(0x5b5)
#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_M1_REG(group) REG_ADDR8(0x5c0 + (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
****************************************************************************/
#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_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
****************************************************************************/
#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
*
@ -184,6 +246,8 @@ static int tlsr82_gpio_irq(int irq, void *context, void *arg)
xcpt_t callback;
int ret = OK;
gpioinfo("Gpio irq entry!\n");
/* Clear the GPIO interrupt status */
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;
int ret = OK;
gpioinfo("Gpio risc0 irq entry!\n");
/* Clear the GPIO interrupt status */
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;
int ret = OK;
gpioinfo("Gpio risc1 irq entry!\n");
/* Clear the GPIO interrupt status */
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))
{
/* 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 */
tlsr82_gpio_input_ctrl(cfg, true);
tlsr82_gpio_output_ctrl(cfg, false);
}
else if (GPIO_IS(AF, OUTPUT, cfg))
{
/* GPIO setting act as GPIO */
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 */
tlsr82_gpio_input_ctrl(cfg, false);
@ -509,6 +573,10 @@ int tlsr82_gpioconfig(gpio_cfg_t cfg)
/* Drive Strength config */
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) &&
GPIO_GET(AF, cfg) <= GPIO_VAL(AF, MUX3))
@ -667,6 +735,8 @@ void tlsr82_gpioirqinitialize(void)
* Description:
* Config the gpio irq according to the cfg, and attach or
* 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;
gpio_cfg_t pinset;
gpioinfo("cfg=0x%lx, func=0x%lx\n", cfg, (uint32_t)func);
/* Get pin information from cfg */
pinset = GPIO_CFG2PIN(cfg);
@ -744,18 +816,26 @@ int tlsr82_gpioirqconfig(gpio_cfg_t cfg, xcpt_t func, void *arg)
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 */
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 */
tlsr82_gpioirqenable_all();
/* Dump the gpio register for debug */
tlsr82_gpio_dumpregs("tlsr82_gpioirqconfig()");
return OK;
}
#endif
@ -884,6 +964,43 @@ void tlsr82_gpioirqdisable(gpio_cfg_t cfg)
#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
*

View File

@ -144,7 +144,7 @@
#define GPIO_POL_SHIFT 23
#define GPIO_POL_MASK (0x1 << 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 */

View File

@ -47,9 +47,11 @@
struct tlsr82gpio_dev_s
{
struct gpio_dev_s gpio;
pin_interrupt_t callback;
uint8_t id;
struct gpio_dev_s gpio; /* GPIO Device */
pin_interrupt_t callback; /* Interrupt callback */
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,
};
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,
{
.pinset = GPIO_PIN_PD6,
.init_pintype = GPIO_INPUT_PIN_PULLDOWN,
},
{
.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 const enum gpio_pintype_e g_init_pintype[BOARD_NGPIO] =
{
GPIO_INPUT_PIN,
GPIO_OUTPUT_PIN,
GPIO_OUTPUT_PIN,
GPIO_INTERRUPT_RISING_PIN,
};
static struct tlsr82gpio_dev_s g_gpdevs[BOARD_NGPIO];
/****************************************************************************
* 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->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;
}
@ -129,9 +133,9 @@ static int tlsr82_go_write(struct gpio_dev_s *dev, bool value)
DEBUGASSERT(tlsr82gpio != NULL);
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;
}
@ -144,7 +148,7 @@ static int tlsr82_go_attach(struct gpio_dev_s *dev,
/* 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);
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;
uint8_t gpioid = tlsr82gpio->id;
if (enable)
{
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 */
tlsr82_gpioirqconfig(g_gpios[gpioid], tlsr82_go_interrupt,
&g_gpdevs[gpioid]);
tlsr82_gpioirqconfig(tlsr82gpio->pinset, tlsr82_go_interrupt,
tlsr82gpio);
}
else
{
@ -176,7 +178,7 @@ static int tlsr82_go_enable(struct gpio_dev_s *dev, bool enable)
else
{
gpioinfo("Disable the interrupt\n");
tlsr82_gpioirqconfig(g_gpios[gpioid], NULL, NULL);
tlsr82_gpioirqconfig(tlsr82gpio->pinset, NULL, NULL);
}
return OK;
@ -187,9 +189,11 @@ static int tlsr82_go_setpintype(struct gpio_dev_s *dev,
{
int ret = OK;
gpio_cfg_t cfg;
gpio_cfg_t irq;
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)
{
@ -216,31 +220,51 @@ static int tlsr82_go_setpintype(struct gpio_dev_s *dev,
case GPIO_OUTPUT_PIN:
{
cfg = GPIO_AF_OUTPUT | GPIO_DS_HIGH;
cfg |= GPIO_AF_OUTPUT | GPIO_DS_HIGH;
tlsr82_gpioconfig(cfg);
}
break;
case GPIO_INTERRUPT_PIN:
case GPIO_INTERRUPT_HIGH_PIN:
case GPIO_INTERRUPT_RISING_PIN:
{
cfg |= GPIO_AF_INPUT | GPIO_PUPD_NONE | GPIO_IRQ_NORMAL |
GPIO_POL_RISE;
cfg |= GPIO_AF_INPUT | GPIO_PUPD_PD100K | 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);
}
break;
case GPIO_INTERRUPT_LOW_PIN:
case GPIO_INTERRUPT_FALLING_PIN:
{
cfg |= GPIO_AF_INPUT | GPIO_PUPD_NONE | GPIO_IRQ_NORMAL |
GPIO_POL_FAIL;
cfg |= GPIO_AF_INPUT | GPIO_PUPD_PU10K | GPIO_POL_FALL;
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);
}
break;
case GPIO_OUTPUT_PIN_OPENDRAIN:
case GPIO_INTERRUPT_HIGH_PIN:
case GPIO_INTERRUPT_LOW_PIN:
case GPIO_INTERRUPT_BOTH_PIN:
default:
{
@ -252,7 +276,9 @@ static int tlsr82_go_setpintype(struct gpio_dev_s *dev,
/* Assign back the config information */
g_gpios[tlsr82gpio->id] = cfg;
tlsr82gpio->pinset = cfg;
gpioinfo("pinset=0x%08lx\n", cfg);
errout:
return ret;
@ -269,22 +295,30 @@ errout:
int tlsr82_gpio_initialize(void)
{
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++)
{
g_gpdevs[i].gpio.gp_pintype = g_init_pintype[i];
g_gpdevs[i].gpio.gp_ops = &gpio_ops;
g_gpdevs[i].id = i;
gpio_pin_register(&g_gpdevs[i].gpio, i);
tlsr82gpio = &g_gpdevs[i];
tlsr82gpio->gpio.gp_pintype = tlsr82gpio->init_pintype;
tlsr82gpio->gpio.gp_ops = &gpio_ops;
tlsr82gpio->id = i;
/* Configure the pin that will be used as input */
ret = tlsr82_go_setpintype(&tlsr82gpio->gpio,
tlsr82gpio->init_pintype);
if (ret < 0)
{
goto out;
}
tlsr82_gpioconfig(g_gpios[i]);
gpio_pin_register(&tlsr82gpio->gpio, i);
}
return 0;
out:
return ret;
}
#endif /* CONFIG_DEV_GPIO && !CONFIG_GPIO_LOWER_HALF */