text: /****************************************************************************
   * arch/arm/src/imxrt/imxrt_gpio.c
   *
   *   Copyright (C) 2018-2019 Gregory Nutt. All rights reserved.
   *   Author: Gregory Nutt <gnutt@nuttx.org>
   *           Dave Marples <dave@marples.net>
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   *
   * 1. Redistributions of source code must retain the above copyright
   *    notice, this list of conditions and the following disclaimer.
   * 2. Redistributions in binary form must reproduce the above copyright
   *    notice, this list of conditions and the following disclaimer in
   *    the documentation and/or other materials provided with the
   *    distribution.
   * 3. Neither the name NuttX nor the names of its contributors may be
   *    used to endorse or promote products derived from this software
   *    without specific prior written permission.
   *
   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
   * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
   * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
   * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
   * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
   * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
   * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
   * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
   * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
   * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
   * POSSIBILITY OF SUCH DAMAGE.
   *
   ****************************************************************************/
  
  /****************************************************************************
   * Included Files
   ****************************************************************************/
  
  #include <nuttx/config.h>
  
  #include <sys/types.h>
  #include <stdint.h>
  #include <stdbool.h>
  #include <errno.h>
  
  #include <nuttx/irq.h>
  
  #include "chip.h"
  #include "up_arch.h"
  #include "imxrt_iomuxc.h"
  #include "imxrt_gpio.h"
  #include "hardware/imxrt_daisy.h"
  
  /****************************************************************************
   * Pre-processor Definitions
   ****************************************************************************/
  
  #define IMXRT_PADMUX_INVALID    255
  
  /****************************************************************************
   * Private Data
   ****************************************************************************/
  
  static const uint8_t g_gpio1_padmux[IMXRT_GPIO_NPINS] =
  {
    IMXRT_PADMUX_GPIO_AD_B0_00_INDEX,           /* GPIO1 Pin 0 */
    IMXRT_PADMUX_GPIO_AD_B0_01_INDEX,           /* GPIO1 Pin 1 */
    IMXRT_PADMUX_GPIO_AD_B0_02_INDEX,           /* GPIO1 Pin 2 */
    IMXRT_PADMUX_GPIO_AD_B0_03_INDEX,           /* GPIO1 Pin 3 */
    IMXRT_PADMUX_GPIO_AD_B0_04_INDEX,           /* GPIO1 Pin 4 */
    IMXRT_PADMUX_GPIO_AD_B0_05_INDEX,           /* GPIO1 Pin 5 */
    IMXRT_PADMUX_GPIO_AD_B0_06_INDEX,           /* GPIO1 Pin 6 */
    IMXRT_PADMUX_GPIO_AD_B0_07_INDEX,           /* GPIO1 Pin 7 */
  
    IMXRT_PADMUX_GPIO_AD_B0_08_INDEX,           /* GPIO1 Pin 8 */
    IMXRT_PADMUX_GPIO_AD_B0_09_INDEX,           /* GPIO1 Pin 9 */
    IMXRT_PADMUX_GPIO_AD_B0_10_INDEX,           /* GPIO1 Pin 10 */
    IMXRT_PADMUX_GPIO_AD_B0_11_INDEX,           /* GPIO1 Pin 11 */
    IMXRT_PADMUX_GPIO_AD_B0_12_INDEX,           /* GPIO1 Pin 12 */
    IMXRT_PADMUX_GPIO_AD_B0_13_INDEX,           /* GPIO1 Pin 13 */
    IMXRT_PADMUX_GPIO_AD_B0_14_INDEX,           /* GPIO1 Pin 14 */
    IMXRT_PADMUX_GPIO_AD_B0_15_INDEX,           /* GPIO1 Pin 15 */
  
    IMXRT_PADMUX_GPIO_AD_B1_00_INDEX,           /* GPIO1 Pin 16 */
    IMXRT_PADMUX_GPIO_AD_B1_01_INDEX,           /* GPIO1 Pin 17 */
    IMXRT_PADMUX_GPIO_AD_B1_02_INDEX,           /* GPIO1 Pin 18 */
    IMXRT_PADMUX_GPIO_AD_B1_03_INDEX,           /* GPIO1 Pin 19 */
    IMXRT_PADMUX_GPIO_AD_B1_04_INDEX,           /* GPIO1 Pin 20 */
    IMXRT_PADMUX_GPIO_AD_B1_05_INDEX,           /* GPIO1 Pin 21 */
    IMXRT_PADMUX_GPIO_AD_B1_06_INDEX,           /* GPIO1 Pin 22 */
    IMXRT_PADMUX_GPIO_AD_B1_07_INDEX,           /* GPIO1 Pin 23 */
  
    IMXRT_PADMUX_GPIO_AD_B1_08_INDEX,           /* GPIO1 Pin 24 */
    IMXRT_PADMUX_GPIO_AD_B1_09_INDEX,           /* GPIO1 Pin 25 */
    IMXRT_PADMUX_GPIO_AD_B1_10_INDEX,           /* GPIO1 Pin 26 */
    IMXRT_PADMUX_GPIO_AD_B1_11_INDEX,           /* GPIO1 Pin 27 */
    IMXRT_PADMUX_GPIO_AD_B1_12_INDEX,           /* GPIO1 Pin 28 */
    IMXRT_PADMUX_GPIO_AD_B1_13_INDEX,           /* GPIO1 Pin 29 */
    IMXRT_PADMUX_GPIO_AD_B1_14_INDEX,           /* GPIO1 Pin 30 */
    IMXRT_PADMUX_GPIO_AD_B1_15_INDEX            /* GPIO1 Pin 31 */
  };
  
  #if (defined(CONFIG_ARCH_FAMILY_IMXRT105x) || defined(CONFIG_ARCH_FAMILY_IMXRT106x))
  static const uint8_t g_gpio2_padmux[IMXRT_GPIO_NPINS] =
  {
    IMXRT_PADMUX_GPIO_B0_00_INDEX,              /* GPIO2 Pin 0 */
    IMXRT_PADMUX_GPIO_B0_01_INDEX,              /* GPIO2 Pin 1 */
    IMXRT_PADMUX_GPIO_B0_02_INDEX,              /* GPIO2 Pin 2 */
    IMXRT_PADMUX_GPIO_B0_03_INDEX,              /* GPIO2 Pin 3 */
    IMXRT_PADMUX_GPIO_B0_04_INDEX,              /* GPIO2 Pin 4 */
    IMXRT_PADMUX_GPIO_B0_05_INDEX,              /* GPIO2 Pin 5 */
    IMXRT_PADMUX_GPIO_B0_06_INDEX,              /* GPIO2 Pin 6 */
    IMXRT_PADMUX_GPIO_B0_07_INDEX,              /* GPIO2 Pin 7 */
  
    IMXRT_PADMUX_GPIO_B0_08_INDEX,              /* GPIO2 Pin 8 */
    IMXRT_PADMUX_GPIO_B0_09_INDEX,              /* GPIO2 Pin 9 */
    IMXRT_PADMUX_GPIO_B0_10_INDEX,              /* GPIO2 Pin 10 */
    IMXRT_PADMUX_GPIO_B0_11_INDEX,              /* GPIO2 Pin 11 */
    IMXRT_PADMUX_GPIO_B0_12_INDEX,              /* GPIO2 Pin 12 */
    IMXRT_PADMUX_GPIO_B0_13_INDEX,              /* GPIO2 Pin 13 */
    IMXRT_PADMUX_GPIO_B0_14_INDEX,              /* GPIO2 Pin 14 */
    IMXRT_PADMUX_GPIO_B0_15_INDEX,              /* GPIO2 Pin 15 */
  
    IMXRT_PADMUX_GPIO_B1_00_INDEX,              /* GPIO2 Pin 16 */
    IMXRT_PADMUX_GPIO_B1_01_INDEX,              /* GPIO2 Pin 17 */
    IMXRT_PADMUX_GPIO_B1_02_INDEX,              /* GPIO2 Pin 18 */
    IMXRT_PADMUX_GPIO_B1_03_INDEX,              /* GPIO2 Pin 19 */
    IMXRT_PADMUX_GPIO_B1_04_INDEX,              /* GPIO2 Pin 20 */
    IMXRT_PADMUX_GPIO_B1_05_INDEX,              /* GPIO2 Pin 21 */
    IMXRT_PADMUX_GPIO_B1_06_INDEX,              /* GPIO2 Pin 22 */
    IMXRT_PADMUX_GPIO_B1_07_INDEX,              /* GPIO2 Pin 23 */
  
    IMXRT_PADMUX_GPIO_B1_08_INDEX,              /* GPIO2 Pin 24 */
    IMXRT_PADMUX_GPIO_B1_09_INDEX,              /* GPIO2 Pin 25 */
    IMXRT_PADMUX_GPIO_B1_10_INDEX,              /* GPIO2 Pin 26 */
    IMXRT_PADMUX_GPIO_B1_11_INDEX,              /* GPIO2 Pin 27 */
    IMXRT_PADMUX_GPIO_B1_12_INDEX,              /* GPIO2 Pin 28 */
    IMXRT_PADMUX_GPIO_B1_13_INDEX,              /* GPIO2 Pin 29 */
    IMXRT_PADMUX_GPIO_B1_14_INDEX,              /* GPIO2 Pin 30 */
    IMXRT_PADMUX_GPIO_B1_15_INDEX               /* GPIO2 Pin 31 */
  };
  
  #elif defined(CONFIG_ARCH_FAMILY_IMXRT102x)
  static const uint8_t g_gpio2_padmux[IMXRT_GPIO_NPINS] =
  {
    IMXRT_PADMUX_GPIO_EMC_00_INDEX,              /* GPIO2 Pin 0 */
    IMXRT_PADMUX_GPIO_EMC_01_INDEX,              /* GPIO2 Pin 1 */
    IMXRT_PADMUX_GPIO_EMC_02_INDEX,              /* GPIO2 Pin 2 */
    IMXRT_PADMUX_GPIO_EMC_03_INDEX,              /* GPIO2 Pin 3 */
    IMXRT_PADMUX_GPIO_EMC_04_INDEX,              /* GPIO2 Pin 4 */
    IMXRT_PADMUX_GPIO_EMC_05_INDEX,              /* GPIO2 Pin 5 */
    IMXRT_PADMUX_GPIO_EMC_06_INDEX,              /* GPIO2 Pin 6 */
    IMXRT_PADMUX_GPIO_EMC_07_INDEX,              /* GPIO2 Pin 7 */
  
    IMXRT_PADMUX_GPIO_EMC_08_INDEX,              /* GPIO2 Pin 8 */
    IMXRT_PADMUX_GPIO_EMC_09_INDEX,              /* GPIO2 Pin 9 */
    IMXRT_PADMUX_GPIO_EMC_10_INDEX,              /* GPIO2 Pin 10 */
    IMXRT_PADMUX_GPIO_EMC_11_INDEX,              /* GPIO2 Pin 11 */
    IMXRT_PADMUX_GPIO_EMC_12_INDEX,              /* GPIO2 Pin 12 */
    IMXRT_PADMUX_GPIO_EMC_13_INDEX,              /* GPIO2 Pin 13 */
    IMXRT_PADMUX_GPIO_EMC_14_INDEX,              /* GPIO2 Pin 14 */
    IMXRT_PADMUX_GPIO_EMC_15_INDEX,              /* GPIO2 Pin 15 */
  
    IMXRT_PADMUX_GPIO_EMC_16_INDEX,              /* GPIO2 Pin 16 */
    IMXRT_PADMUX_GPIO_EMC_17_INDEX,              /* GPIO2 Pin 17 */
    IMXRT_PADMUX_GPIO_EMC_18_INDEX,              /* GPIO2 Pin 18 */
    IMXRT_PADMUX_GPIO_EMC_19_INDEX,              /* GPIO2 Pin 19 */
    IMXRT_PADMUX_GPIO_EMC_20_INDEX,              /* GPIO2 Pin 20 */
    IMXRT_PADMUX_GPIO_EMC_21_INDEX,              /* GPIO2 Pin 21 */
    IMXRT_PADMUX_GPIO_EMC_22_INDEX,              /* GPIO2 Pin 22 */
    IMXRT_PADMUX_GPIO_EMC_23_INDEX,              /* GPIO2 Pin 23 */
  
    IMXRT_PADMUX_GPIO_EMC_24_INDEX,              /* GPIO2 Pin 24 */
    IMXRT_PADMUX_GPIO_EMC_25_INDEX,              /* GPIO2 Pin 25 */
    IMXRT_PADMUX_GPIO_EMC_26_INDEX,              /* GPIO2 Pin 26 */
    IMXRT_PADMUX_GPIO_EMC_27_INDEX,              /* GPIO2 Pin 27 */
    IMXRT_PADMUX_GPIO_EMC_28_INDEX,              /* GPIO2 Pin 28 */
    IMXRT_PADMUX_GPIO_EMC_29_INDEX,              /* GPIO2 Pin 29 */
    IMXRT_PADMUX_GPIO_EMC_30_INDEX,              /* GPIO2 Pin 30 */
    IMXRT_PADMUX_GPIO_EMC_31_INDEX               /* GPIO2 Pin 31 */
  };
  #else
  #  error "Unrecognised IMXRT family member"
  #endif
  
  #if (defined(CONFIG_ARCH_FAMILY_IMXRT105x) || defined(CONFIG_ARCH_FAMILY_IMXRT106x))
  static const uint8_t g_gpio3_padmux[IMXRT_GPIO_NPINS] =
  {
    IMXRT_PADMUX_GPIO_SD_B1_00_INDEX,           /* GPIO3 Pin 0 */
    IMXRT_PADMUX_GPIO_SD_B1_01_INDEX,           /* GPIO3 Pin 1 */
    IMXRT_PADMUX_GPIO_SD_B1_02_INDEX,           /* GPIO3 Pin 2 */
    IMXRT_PADMUX_GPIO_SD_B1_03_INDEX,           /* GPIO3 Pin 3 */
    IMXRT_PADMUX_GPIO_SD_B1_04_INDEX,           /* GPIO3 Pin 4 */
    IMXRT_PADMUX_GPIO_SD_B1_05_INDEX,           /* GPIO3 Pin 5 */
    IMXRT_PADMUX_GPIO_SD_B1_06_INDEX,           /* GPIO3 Pin 6 */
    IMXRT_PADMUX_GPIO_SD_B1_07_INDEX,           /* GPIO3 Pin 7 */
  
    IMXRT_PADMUX_GPIO_SD_B1_08_INDEX,           /* GPIO3 Pin 8 */
    IMXRT_PADMUX_GPIO_SD_B1_09_INDEX,           /* GPIO3 Pin 9 */
    IMXRT_PADMUX_GPIO_SD_B1_10_INDEX,           /* GPIO3 Pin 10 */
    IMXRT_PADMUX_GPIO_SD_B1_11_INDEX,           /* GPIO3 Pin 11 */
    IMXRT_PADMUX_GPIO_SD_B0_00_INDEX,           /* GPIO3 Pin 12 */
    IMXRT_PADMUX_GPIO_SD_B0_01_INDEX,           /* GPIO3 Pin 13 */
    IMXRT_PADMUX_GPIO_SD_B0_02_INDEX,           /* GPIO3 Pin 14 */
    IMXRT_PADMUX_GPIO_SD_B0_03_INDEX,           /* GPIO3 Pin 15 */
  
    IMXRT_PADMUX_GPIO_SD_B0_04_INDEX,           /* GPIO3 Pin 16 */
    IMXRT_PADMUX_GPIO_SD_B0_05_INDEX,           /* GPIO3 Pin 17 */
    IMXRT_PADMUX_GPIO_EMC_32_INDEX,             /* GPIO3 Pin 18 */
    IMXRT_PADMUX_GPIO_EMC_33_INDEX,             /* GPIO3 Pin 19 */
    IMXRT_PADMUX_GPIO_EMC_34_INDEX,             /* GPIO3 Pin 20 */
    IMXRT_PADMUX_GPIO_EMC_35_INDEX,             /* GPIO3 Pin 21 */
    IMXRT_PADMUX_GPIO_EMC_36_INDEX,             /* GPIO3 Pin 22 */
    IMXRT_PADMUX_GPIO_EMC_37_INDEX,             /* GPIO3 Pin 23 */
  
    IMXRT_PADMUX_GPIO_EMC_38_INDEX,             /* GPIO3 Pin 24 */
    IMXRT_PADMUX_GPIO_EMC_39_INDEX,             /* GPIO3 Pin 25 */
    IMXRT_PADMUX_GPIO_EMC_40_INDEX,             /* GPIO3 Pin 26 */
    IMXRT_PADMUX_GPIO_EMC_41_INDEX,             /* GPIO3 Pin 27 */
    IMXRT_PADMUX_INVALID,                       /* GPIO3 Pin 28 */
    IMXRT_PADMUX_INVALID,                       /* GPIO3 Pin 29 */
    IMXRT_PADMUX_INVALID,                       /* GPIO3 Pin 30 */
    IMXRT_PADMUX_INVALID                        /* GPIO3 Pin 31 */
  };
  #elif defined(CONFIG_ARCH_FAMILY_IMXRT102x)
  static const uint8_t g_gpio3_padmux[IMXRT_GPIO_NPINS] =
  {
    IMXRT_PADMUX_GPIO_EMC_32_INDEX,             /* GPIO3 Pin 0 */
    IMXRT_PADMUX_GPIO_EMC_33_INDEX,             /* GPIO3 Pin 1 */
    IMXRT_PADMUX_GPIO_EMC_34_INDEX,             /* GPIO3 Pin 2 */
    IMXRT_PADMUX_GPIO_EMC_35_INDEX,             /* GPIO3 Pin 3 */
    IMXRT_PADMUX_GPIO_EMC_36_INDEX,             /* GPIO3 Pin 4 */
    IMXRT_PADMUX_GPIO_EMC_37_INDEX,             /* GPIO3 Pin 5 */
    IMXRT_PADMUX_GPIO_EMC_38_INDEX,             /* GPIO3 Pin 6 */
    IMXRT_PADMUX_GPIO_EMC_39_INDEX,             /* GPIO3 Pin 7 */
  
    IMXRT_PADMUX_GPIO_EMC_40_INDEX,             /* GPIO3 Pin 8 */
    IMXRT_PADMUX_GPIO_EMC_41_INDEX,             /* GPIO3 Pin 9 */
    IMXRT_PADMUX_INVALID,                       /* GPIO3 Pin 10 */
    IMXRT_PADMUX_INVALID,                       /* GPIO3 Pin 11 */
    IMXRT_PADMUX_INVALID,                       /* GPIO3 Pin 12 */
    IMXRT_PADMUX_GPIO_SD_B0_00_INDEX,           /* GPIO3 Pin 13 */
    IMXRT_PADMUX_GPIO_SD_B0_01_INDEX,           /* GPIO3 Pin 14 */
    IMXRT_PADMUX_GPIO_SD_B0_02_INDEX,           /* GPIO3 Pin 15 */
  
    IMXRT_PADMUX_GPIO_SD_B0_03_INDEX,           /* GPIO3 Pin 16 */
    IMXRT_PADMUX_GPIO_SD_B0_04_INDEX,           /* GPIO3 Pin 17 */
    IMXRT_PADMUX_GPIO_SD_B0_05_INDEX,           /* GPIO3 Pin 18 */
    IMXRT_PADMUX_GPIO_SD_B0_06_INDEX,           /* GPIO3 Pin 19 */
    IMXRT_PADMUX_GPIO_SD_B1_00_INDEX,           /* GPIO3 Pin 20 */
    IMXRT_PADMUX_GPIO_SD_B1_01_INDEX,           /* GPIO3 Pin 21 */
    IMXRT_PADMUX_GPIO_SD_B1_02_INDEX,           /* GPIO3 Pin 22 */
    IMXRT_PADMUX_GPIO_SD_B1_03_INDEX,           /* GPIO3 Pin 23 */
  
    IMXRT_PADMUX_GPIO_SD_B1_04_INDEX,           /* GPIO3 Pin 24 */
    IMXRT_PADMUX_GPIO_SD_B1_05_INDEX,           /* GPIO3 Pin 25 */
    IMXRT_PADMUX_GPIO_SD_B1_06_INDEX,           /* GPIO3 Pin 26 */
    IMXRT_PADMUX_GPIO_SD_B1_07_INDEX,           /* GPIO3 Pin 27 */
    IMXRT_PADMUX_GPIO_SD_B1_08_INDEX,           /* GPIO3 Pin 28 */
    IMXRT_PADMUX_GPIO_SD_B1_09_INDEX,           /* GPIO3 Pin 29 */
    IMXRT_PADMUX_GPIO_SD_B1_10_INDEX,           /* GPIO3 Pin 30 */
    IMXRT_PADMUX_GPIO_SD_B1_11_INDEX,           /* GPIO3 Pin 31 */
  };
  #endif
  
  #if (defined(CONFIG_ARCH_FAMILY_IMXRT105x) || defined(CONFIG_ARCH_FAMILY_IMXRT106x))
  static const uint8_t g_gpio4_padmux[IMXRT_GPIO_NPINS] =
  {
    IMXRT_PADMUX_GPIO_EMC_00_INDEX,             /* GPIO4 Pin 0 */
    IMXRT_PADMUX_GPIO_EMC_01_INDEX,             /* GPIO4 Pin 1 */
    IMXRT_PADMUX_GPIO_EMC_02_INDEX,             /* GPIO4 Pin 2 */
    IMXRT_PADMUX_GPIO_EMC_03_INDEX,             /* GPIO4 Pin 3 */
    IMXRT_PADMUX_GPIO_EMC_04_INDEX,             /* GPIO4 Pin 4 */
    IMXRT_PADMUX_GPIO_EMC_05_INDEX,             /* GPIO4 Pin 5 */
    IMXRT_PADMUX_GPIO_EMC_06_INDEX,             /* GPIO4 Pin 6 */
    IMXRT_PADMUX_GPIO_EMC_07_INDEX,             /* GPIO4 Pin 7 */
  
    IMXRT_PADMUX_GPIO_EMC_08_INDEX,             /* GPIO4 Pin 8 */
    IMXRT_PADMUX_GPIO_EMC_09_INDEX,             /* GPIO4 Pin 9 */
    IMXRT_PADMUX_GPIO_EMC_10_INDEX,             /* GPIO4 Pin 10 */
    IMXRT_PADMUX_GPIO_EMC_11_INDEX,             /* GPIO4 Pin 11 */
    IMXRT_PADMUX_GPIO_EMC_12_INDEX,             /* GPIO4 Pin 12 */
    IMXRT_PADMUX_GPIO_EMC_13_INDEX,             /* GPIO4 Pin 13 */
    IMXRT_PADMUX_GPIO_EMC_14_INDEX,             /* GPIO4 Pin 14 */
    IMXRT_PADMUX_GPIO_EMC_15_INDEX,             /* GPIO4 Pin 15 */
  
    IMXRT_PADMUX_GPIO_EMC_16_INDEX,             /* GPIO4 Pin 16 */
    IMXRT_PADMUX_GPIO_EMC_17_INDEX,             /* GPIO4 Pin 17 */
    IMXRT_PADMUX_GPIO_EMC_18_INDEX,             /* GPIO4 Pin 18 */
    IMXRT_PADMUX_GPIO_EMC_19_INDEX,             /* GPIO4 Pin 19 */
    IMXRT_PADMUX_GPIO_EMC_20_INDEX,             /* GPIO4 Pin 20 */
    IMXRT_PADMUX_GPIO_EMC_21_INDEX,             /* GPIO4 Pin 21 */
    IMXRT_PADMUX_GPIO_EMC_22_INDEX,             /* GPIO4 Pin 22 */
    IMXRT_PADMUX_GPIO_EMC_23_INDEX,             /* GPIO4 Pin 23 */
  
    IMXRT_PADMUX_GPIO_EMC_24_INDEX,             /* GPIO4 Pin 24 */
    IMXRT_PADMUX_GPIO_EMC_25_INDEX,             /* GPIO4 Pin 25 */
    IMXRT_PADMUX_GPIO_EMC_26_INDEX,             /* GPIO4 Pin 26 */
    IMXRT_PADMUX_GPIO_EMC_27_INDEX,             /* GPIO4 Pin 27 */
    IMXRT_PADMUX_GPIO_EMC_28_INDEX,             /* GPIO4 Pin 28 */
    IMXRT_PADMUX_GPIO_EMC_29_INDEX,             /* GPIO4 Pin 29 */
    IMXRT_PADMUX_GPIO_EMC_30_INDEX,             /* GPIO4 Pin 30 */
    IMXRT_PADMUX_GPIO_EMC_31_INDEX              /* GPIO4 Pin 31 */
  };
  #endif
  
  static const uint8_t g_gpio5_padmux[IMXRT_GPIO_NPINS] =
  {
    IMXRT_PADMUX_WAKEUP_INDEX,                  /* GPIO5 Pin 0 */
    IMXRT_PADMUX_PMIC_ON_REQ_INDEX,             /* GPIO5 Pin 1 */
    IMXRT_PADMUX_PMIC_STBY_REQ_INDEX,           /* GPIO5 Pin 2 */
    IMXRT_PADMUX_INVALID,                       /* GPIO5 Pin 3 */
    IMXRT_PADMUX_INVALID,                       /* GPIO5 Pin 4 */
    IMXRT_PADMUX_INVALID,                       /* GPIO5 Pin 5 */
    IMXRT_PADMUX_INVALID,                       /* GPIO5 Pin 6 */
    IMXRT_PADMUX_INVALID,                       /* GPIO5 Pin 7 */
  
    IMXRT_PADMUX_INVALID,                       /* GPIO5 Pin 8 */
    IMXRT_PADMUX_INVALID,                       /* GPIO5 Pin 9 */
    IMXRT_PADMUX_INVALID,                       /* GPIO5 Pin 10 */
    IMXRT_PADMUX_INVALID,                       /* GPIO5 Pin 11 */
    IMXRT_PADMUX_INVALID,                       /* GPIO5 Pin 12 */
    IMXRT_PADMUX_INVALID,                       /* GPIO5 Pin 13 */
    IMXRT_PADMUX_INVALID,                       /* GPIO5 Pin 14 */
    IMXRT_PADMUX_INVALID,                       /* GPIO5 Pin 15 */
  
    IMXRT_PADMUX_INVALID,                       /* GPIO5 Pin 16 */
    IMXRT_PADMUX_INVALID,                       /* GPIO5 Pin 17 */
    IMXRT_PADMUX_INVALID,                       /* GPIO5 Pin 18 */
    IMXRT_PADMUX_INVALID,                       /* GPIO5 Pin 19 */
    IMXRT_PADMUX_INVALID,                       /* GPIO5 Pin 20 */
    IMXRT_PADMUX_INVALID,                       /* GPIO5 Pin 21 */
    IMXRT_PADMUX_INVALID,                       /* GPIO5 Pin 22 */
    IMXRT_PADMUX_INVALID,                       /* GPIO5 Pin 23 */
  
    IMXRT_PADMUX_INVALID,                       /* GPIO5 Pin 24 */
    IMXRT_PADMUX_INVALID,                       /* GPIO5 Pin 25 */
    IMXRT_PADMUX_INVALID,                       /* GPIO5 Pin 26 */
    IMXRT_PADMUX_INVALID,                       /* GPIO5 Pin 27 */
    IMXRT_PADMUX_INVALID,                       /* GPIO5 Pin 28 */
    IMXRT_PADMUX_INVALID,                       /* GPIO5 Pin 29 */
    IMXRT_PADMUX_INVALID,                       /* GPIO5 Pin 30 */
    IMXRT_PADMUX_INVALID                        /* GPIO5 Pin 31 */
  };
  
  static FAR const uint8_t *g_gpio_padmux[IMXRT_GPIO_NPORTS + 1] =
  {
    g_gpio1_padmux,                             /* GPIO1 */
    g_gpio2_padmux,                             /* GPIO2 */
    g_gpio3_padmux,                             /* GPIO3 */
  #if (defined(CONFIG_ARCH_FAMILY_IMXRT105x) || defined(CONFIG_ARCH_FAMILY_IMXRT106x))
    g_gpio4_padmux,                             /* GPIO4 */
  #else
    NULL,                                       /* GPIO4 doesn't exist on 102x */
  #endif
    g_gpio5_padmux,                             /* GPIO5 */
  #if IMXRT_GPIO_NPORTS > 5
    g_gpio1_padmux,                             /* GPIO6 */
    g_gpio2_padmux,                             /* GPIO7 */
    g_gpio3_padmux,                             /* GPIO8 */
    g_gpio4_padmux,                             /* GPIO9 */
  #endif
    NULL                                        /* End of list */
  };
  
  /************************************************************************************
   * Public Data
   ************************************************************************************/
  
  /* Look-up table that maps GPIO1..GPIOn indexes into GPIO register base addresses */
  
  uintptr_t g_gpio_base[IMXRT_GPIO_NPORTS] =
  {
    IMXRT_GPIO1_BASE
  #if IMXRT_GPIO_NPORTS > 1
    , IMXRT_GPIO2_BASE
  #endif
  #if IMXRT_GPIO_NPORTS > 2
    , IMXRT_GPIO3_BASE
  #endif
  #if IMXRT_GPIO_NPORTS > 3
  #if (defined(CONFIG_ARCH_FAMILY_IMXRT105x) || defined(CONFIG_ARCH_FAMILY_IMXRT106x))
    , IMXRT_GPIO4_BASE
  #else
    , 0
  #endif
  #endif
  #if IMXRT_GPIO_NPORTS > 4
    , IMXRT_GPIO5_BASE
  #endif
  #if IMXRT_GPIO_NPORTS > 5
    , IMXRT_GPIO6_BASE
  #endif
  #if IMXRT_GPIO_NPORTS > 6
    , IMXRT_GPIO7_BASE
  #endif
  #if IMXRT_GPIO_NPORTS > 7
    , IMXRT_GPIO8_BASE
  #endif
  #if IMXRT_GPIO_NPORTS > 8
    , IMXRT_GPIO9_BASE
  #endif
  };
  
  /****************************************************************************
   * Private Functions
   ****************************************************************************/
  
  /****************************************************************************
   * Name: imxrt_padmux_address
   ****************************************************************************/
  
  static uintptr_t imxrt_padmux_address(unsigned int index)
  {
  #if defined(IMXRT_PAD1MUX_OFFSET)
    if (index >= IMXRT_PADMUX_GPIO_SPI_B0_00_INDEX)
      {
        return (IMXRT_PAD1MUX_OFFSET(index - IMXRT_PADMUX_GPIO_SPI_B0_00_INDEX));
      }
  #endif
    if (index >= IMXRT_PADMUX_WAKEUP_INDEX)
      {
        return (IMXRT_PADMUX_ADDRESS_SNVS(index - IMXRT_PADMUX_WAKEUP_INDEX));
      }
  
    return (IMXRT_PADMUX_ADDRESS(index));
  }
  
  /****************************************************************************
   * Name: imxrt_padctl_address
   ****************************************************************************/
  
  static uintptr_t imxrt_padctl_address(unsigned int index)
  {
  #if defined(IMXRT_PAD1CTL_OFFSET)
    if (index >= IMXRT_PADCTL_GPIO_SPI_B0_00_INDEX)
      {
        return (IMXRT_PAD1CTL_OFFSET(index - IMXRT_PADCTL_GPIO_SPI_B0_00_INDEX));
      }
  #endif
    if (index >= IMXRT_PADCTL_WAKEUP_INDEX)
      {
        return (IMXRT_PADCTL_ADDRESS_SNVS(index - IMXRT_PADCTL_WAKEUP_INDEX));
      }
  
    return (IMXRT_PADCTL_ADDRESS(index));
  }
  
  /****************************************************************************
   * Name: imxrt_gpio_dirout
   ****************************************************************************/
  
  static inline void imxrt_gpio_dirout(int port, int pin)
  {
    uint32_t regval = getreg32(IMXRT_GPIO_GDIR(port));
    regval |= GPIO_PIN(pin);
    putreg32(regval, IMXRT_GPIO_GDIR(port));
  }
  
  /****************************************************************************
   * Name: imxrt_gpio_dirin
   ****************************************************************************/
  
  static inline void imxrt_gpio_dirin(int port, int pin)
  {
    uint32_t regval = getreg32(IMXRT_GPIO_GDIR(port));
    regval &= ~GPIO_PIN(pin);
    putreg32(regval, IMXRT_GPIO_GDIR(port));
  }
  
  /****************************************************************************
   * Name: imxrt_gpio_setoutput
   ****************************************************************************/
  
  static void imxrt_gpio_setoutput(int port, int pin, bool value)
  {
    uintptr_t regaddr = IMXRT_GPIO_DR(port);
    uint32_t regval;
  
    regval = getreg32(regaddr);
    if (value)
      {
        regval |= GPIO_PIN(pin);
      }
    else
      {
        regval &= ~GPIO_PIN(pin);
      }
  
    putreg32(regval, regaddr);
  }
  
  /****************************************************************************
   * Name: imxrt_gpio_getinput
   ****************************************************************************/
  
  static inline bool imxrt_gpio_getinput(int port, int pin)
  {
    uintptr_t regaddr = IMXRT_GPIO_DR(port);
    uint32_t regval;
  
    regval = getreg32(regaddr);
    return ((regval & GPIO_PIN(pin)) != 0);
  }
  
  /****************************************************************************
   * Name: imxrt_gpio_select
   * GPIO{1234}(l) and GPIO{6789}(h) share same IO MUX function, GPIO_MUXn
   * selects one GPIO function.
   * 0: GPIOl[n] is selected
   * 1: GPIOh[n] is selected
   ****************************************************************************/
  
  static inline int imxrt_gpio_select(int port, int pin)
  {
  #if IMXRT_GPIO_NPORTS > 5
    uint32_t gpr = port;
    uint32_t setbits = 1 << pin;
    uint32_t clearbits = 1 << pin;
    uintptr_t regaddr = (uintptr_t) IMXRT_IOMUXC_GPR_GPR26;
  
    if (port != GPIO5)
      {
        /* Uses GPR26 as the base */
  
        if (port >= GPIO6)
          {
            /* Map port to correct gpr index and set the GPIO_MUX3_GPIO[b]_SEL
             * bit
             */
  
            gpr = port - GPIO6;
            clearbits = 0;
          }
        else
          {
            /* The port is correct gpr index, so just clear the
             * GPIO_MUX3_GPIO[b]_SEL bit.
             */
  
            setbits = 0;
          }
  
        regaddr |= gpr * sizeof(uint32_t);
        modifyreg32(regaddr, clearbits, setbits);
      }
  #endif
    return OK;
  }
  
  /****************************************************************************
   * Name: imxrt_gpio_configinput
   ****************************************************************************/
  
  static int imxrt_gpio_configinput(gpio_pinset_t pinset)
  {
    int port = (pinset & GPIO_PORT_MASK) >> GPIO_PORT_SHIFT;
    int pin  = (pinset & GPIO_PIN_MASK) >> GPIO_PIN_SHIFT;
    FAR const uint8_t *table;
    iomux_pinset_t ioset;
    uintptr_t regaddr;
    unsigned int index;
  
    DEBUGASSERT((unsigned int)port < IMXRT_GPIO_NPORTS);
  
    /* Configure pin as in input */
  
    imxrt_gpio_dirin(port, pin);
  
    /* Configure pin as a GPIO */
  
    table = g_gpio_padmux[port];
    if (table == NULL)
      {
        return -EINVAL;
      }
  
    index = (unsigned int)table[pin];
    if (index >= IMXRT_PADMUX_NREGISTERS)
      {
        return -EINVAL;
      }
    regaddr = imxrt_padmux_address(index);
    putreg32(PADMUX_MUXMODE_ALT5, regaddr);
  
    imxrt_gpio_select(port, pin);
  
    /* Configure pin pad settings */
  
    index = imxrt_padmux_map(index);
    if (index >= IMXRT_PADCTL_NREGISTERS)
      {
        return -EINVAL;
      }
  
    regaddr = imxrt_padctl_address(index);
    ioset   = (iomux_pinset_t)((pinset & GPIO_IOMUX_MASK) >> GPIO_IOMUX_SHIFT);
    return imxrt_iomux_configure(regaddr, ioset);
  }
  
  /****************************************************************************
   * Name: imxrt_gpio_configoutput
   ****************************************************************************/
  
  static inline int imxrt_gpio_configoutput(gpio_pinset_t pinset)
  {
    int port   = (pinset & GPIO_PORT_MASK) >> GPIO_PORT_SHIFT;
    int pin    = (pinset & GPIO_PIN_MASK) >> GPIO_PIN_SHIFT;
    bool value = ((pinset & GPIO_OUTPUT_ONE) != 0);
  
    DEBUGASSERT((unsigned int)port < IMXRT_GPIO_NPORTS);
  
    /* Set the output value */
  
    imxrt_gpio_setoutput(port, pin, value);
  
    /* Convert the configured input GPIO to an output */
  
    imxrt_gpio_dirout(port, pin);
    return OK;
  }
  
  /****************************************************************************
   * Name: imxrt_gpio_configperiph
   ****************************************************************************/
  
  static inline int imxrt_gpio_configperiph(gpio_pinset_t pinset)
  {
    iomux_pinset_t ioset;
    uintptr_t regaddr;
    uint32_t regval;
    uint32_t alt;
    unsigned int index;
  
    /* Configure pin as a peripheral via SW MUX Control Register */
  
    index   = ((pinset & GPIO_PADMUX_MASK) >> GPIO_PADMUX_SHIFT);
    regaddr = imxrt_padmux_address(index);
  
    alt     = (pinset & GPIO_ALT_MASK) >> GPIO_ALT_SHIFT;
    regval  = alt << PADMUX_MUXMODE_SHIFT;
    regval |= (pinset & GPIO_SION_MASK) ? PADMUX_SION : 0;
  
    putreg32(regval, regaddr);
  
    /* Configure pin Daisy Select Input Daisy Register */
  
    imxrt_daisy_select(index, alt);
  
    /* Configure pin pad settings SW PAD Control Register*/
  
    index = imxrt_padmux_map(index);
    if (index >= IMXRT_PADCTL_NREGISTERS)
      {
        return -EINVAL;
      }
  
    regaddr = imxrt_padctl_address(index);
    ioset   = (iomux_pinset_t)((pinset & GPIO_IOMUX_MASK) >> GPIO_IOMUX_SHIFT);
    return imxrt_iomux_configure(regaddr, ioset);
  }
  
  /****************************************************************************
   * Public Functions
   ****************************************************************************/
  
  /****************************************************************************
   * Name: imxrt_config_gpio
   *
   * Description:
   *   Configure a GPIO pin based on pin-encoded description of the pin.
   *
   ****************************************************************************/
  
  int imxrt_config_gpio(gpio_pinset_t pinset)
  {
    irqstate_t flags;
    int ret;
  
    /* Configure the pin as an input initially to avoid any spurious outputs */
  
    flags = enter_critical_section();
  
    /* Configure based upon the pin mode */
  
    switch (pinset & GPIO_MODE_MASK)
      {
        case GPIO_INPUT:
          {
            /* Configure the pin as a GPIO input */
  
            ret = imxrt_gpio_configinput(pinset);
          }
          break;
  
        case GPIO_OUTPUT:
          {
            /* First configure the pin as a GPIO input to avoid output
             * glitches.
             */
  
            ret = imxrt_gpio_configinput(pinset);
            if (ret >= 0)
              {
                /* Convert the input to an output */
  
                ret = imxrt_gpio_configoutput(pinset);
              }
          }
          break;
  
        case GPIO_PERIPH:
          {
            /* Configure the pin as a peripheral */
  
            ret = imxrt_gpio_configperiph(pinset);
          }
          break;
  
  #ifdef CONFIG_IMXRT_GPIO_IRQ
        case GPIO_INTERRUPT:
          {
            /* Configure the pin as a GPIO input */
  
            ret = imxrt_gpio_configinput(pinset);
            if (ret == OK)
              {
                ret = imxrt_gpioirq_configure(pinset);
              }
          }
          break;
  #endif
  
        default:
          ret = -EINVAL;
          break;
      }
  
    leave_critical_section(flags);
    return ret;
  }
  
  /************************************************************************************
   * Name: imxrt_gpio_write
   *
   * Description:
   *   Write one or zero to the selected GPIO pin
   *
   ************************************************************************************/
  
  void imxrt_gpio_write(gpio_pinset_t pinset, bool value)
  {
    irqstate_t flags;
    int port = (pinset & GPIO_PORT_MASK) >> GPIO_PORT_SHIFT;
    int pin  = (pinset & GPIO_PIN_MASK) >> GPIO_PIN_SHIFT;
  
    DEBUGASSERT((unsigned int)port < IMXRT_GPIO_NPORTS);
  
    flags = enter_critical_section();
    imxrt_gpio_setoutput(port, pin, value);
    leave_critical_section(flags);
  }
  
  /************************************************************************************
   * Name: imxrt_gpio_read
   *
   * Description:
   *   Read one or zero from the selected GPIO pin
   *
   ************************************************************************************/
  
  bool imxrt_gpio_read(gpio_pinset_t pinset)
  {
    irqstate_t flags;
    int port = (pinset & GPIO_PORT_MASK) >> GPIO_PORT_SHIFT;
    int pin  = (pinset & GPIO_PIN_MASK) >> GPIO_PIN_SHIFT;
    bool value;
  
    DEBUGASSERT((unsigned int)port < IMXRT_GPIO_NPORTS);
  
    flags = enter_critical_section();
    value = imxrt_gpio_getinput(port, pin);
    leave_critical_section(flags);
    return value;
  }
  