You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@nuttx.apache.org by xi...@apache.org on 2022/06/07 14:26:40 UTC

[incubator-nuttx] branch master updated: arm/tlsr82: gpio driver bug fix and optimize.

This is an automated email from the ASF dual-hosted git repository.

xiaoxiang pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-nuttx.git


The following commit(s) were added to refs/heads/master by this push:
     new af87921eda arm/tlsr82: gpio driver bug fix and optimize.
af87921eda is described below

commit af87921eda43728372b05a5b4bd6022cd1287b48
Author: wangbowen6 <wa...@xiaomi.com>
AuthorDate: Tue Jun 7 16:09:19 2022 +0800

    arm/tlsr82: gpio driver bug fix and optimize.
    
    Signed-off-by: wangbowen6 <wa...@xiaomi.com>
---
 arch/arm/src/tlsr82/Kconfig                        |   8 ++
 arch/arm/src/tlsr82/hardware/tlsr82_gpio.h         |   2 +-
 arch/arm/src/tlsr82/tlsr82_gpio.c                  | 139 +++++++++++++++++++--
 arch/arm/src/tlsr82/tlsr82_gpio.h                  |   2 +-
 .../arm/tlsr82/tlsr8278adk80d/src/tlsr8278_gpio.c  | 126 ++++++++++++-------
 5 files changed, 218 insertions(+), 59 deletions(-)

diff --git a/arch/arm/src/tlsr82/Kconfig b/arch/arm/src/tlsr82/Kconfig
index 8587ed74b5..d9d34918e0 100644
--- a/arch/arm/src/tlsr82/Kconfig
+++ b/arch/arm/src/tlsr82/Kconfig
@@ -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
diff --git a/arch/arm/src/tlsr82/hardware/tlsr82_gpio.h b/arch/arm/src/tlsr82/hardware/tlsr82_gpio.h
index d8ca83bca2..fa5241892c 100644
--- a/arch/arm/src/tlsr82/hardware/tlsr82_gpio.h
+++ b/arch/arm/src/tlsr82/hardware/tlsr82_gpio.h
@@ -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))
diff --git a/arch/arm/src/tlsr82/tlsr82_gpio.c b/arch/arm/src/tlsr82/tlsr82_gpio.c
index 5bd0a5c158..31be903d30 100644
--- a/arch/arm/src/tlsr82/tlsr82_gpio.c
+++ b/arch/arm/src/tlsr82/tlsr82_gpio.c
@@ -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
  *
diff --git a/arch/arm/src/tlsr82/tlsr82_gpio.h b/arch/arm/src/tlsr82/tlsr82_gpio.h
index 29859a23bf..e16f12c984 100644
--- a/arch/arm/src/tlsr82/tlsr82_gpio.h
+++ b/arch/arm/src/tlsr82/tlsr82_gpio.h
@@ -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 */
 
diff --git a/boards/arm/tlsr82/tlsr8278adk80d/src/tlsr8278_gpio.c b/boards/arm/tlsr82/tlsr8278adk80d/src/tlsr8278_gpio.c
index 484737faa2..8695eb1600 100644
--- a/boards/arm/tlsr82/tlsr8278adk80d/src/tlsr8278_gpio.c
+++ b/boards/arm/tlsr82/tlsr8278adk80d/src/tlsr8278_gpio.c
@@ -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);
-
-      /* Configure the pin that will be used as input */
+      tlsr82gpio = &g_gpdevs[i];
+      tlsr82gpio->gpio.gp_pintype = tlsr82gpio->init_pintype;
+      tlsr82gpio->gpio.gp_ops     = &gpio_ops;
+      tlsr82gpio->id              = i;
+
+      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 */