[PATCH 6/6] gpio: Add tegra124 gpio support

andreas.koelbl at st.oth-regensburg.de andreas.koelbl at st.oth-regensburg.de
Mon Jul 31 22:27:23 UTC 2017


From: Andreas Kölbl <andreas.koelbl at st.oth-regensburg.de>

Implements the interface definded in libbsp/shared for Tegra124 processors.

bsp specific: The bank parameter has to include the port specified by the
              tegra124 address map
              In order to set a pin either in input or output mode requires an
              additional pointer of type uint32_t passing the pinmux port of the
              bank
---
 c/src/lib/libbsp/arm/jetson-tk1/Makefile.am        |   5 +
 c/src/lib/libbsp/arm/jetson-tk1/README             |   3 +
 .../lib/libbsp/arm/jetson-tk1/gpio/tegra124-gpio.c | 271 +++++++++++++++++++++
 c/src/lib/libbsp/arm/jetson-tk1/include/bsp.h      |   4 +
 .../libbsp/arm/jetson-tk1/include/tegra124-gpio.h  |  61 +++++
 .../arm/jetson-tk1/startup/mm_config_table.c       |  14 ++
 6 files changed, 358 insertions(+)
 create mode 100644 c/src/lib/libbsp/arm/jetson-tk1/gpio/tegra124-gpio.c
 create mode 100644 c/src/lib/libbsp/arm/jetson-tk1/include/tegra124-gpio.h

diff --git a/c/src/lib/libbsp/arm/jetson-tk1/Makefile.am b/c/src/lib/libbsp/arm/jetson-tk1/Makefile.am
index 37d2ca267e..4ec5c81b14 100644
--- a/c/src/lib/libbsp/arm/jetson-tk1/Makefile.am
+++ b/c/src/lib/libbsp/arm/jetson-tk1/Makefile.am
@@ -44,6 +44,7 @@ include_bsp_HEADERS += include/cmdline.h
 include_bsp_HEADERS += include/irq.h
 include_bsp_HEADERS += include/memory.h
 include_bsp_HEADERS += include/mmu.h
+include_bsp_HEADERS += include/tegra124-gpio.h
 
 ###############################################################################
 # Data                                                       #
@@ -107,6 +108,10 @@ libbsp_a_SOURCES += ../../shared/src/irq-legacy.c
 libbsp_a_SOURCES += ../../shared/src/irq-server.c
 libbsp_a_SOURCES += ../../shared/src/irq-shell.c
 
+# GPIO
+libbsp_a_SOURCES += ../../shared/gpio.c
+libbsp_a_SOURCES += gpio/tegra124-gpio.c
+
 # Restart
 libbsp_a_SOURCES += startup/bspreset.c
 
diff --git a/c/src/lib/libbsp/arm/jetson-tk1/README b/c/src/lib/libbsp/arm/jetson-tk1/README
index 13821c7082..50022cf30c 100644
--- a/c/src/lib/libbsp/arm/jetson-tk1/README
+++ b/c/src/lib/libbsp/arm/jetson-tk1/README
@@ -4,6 +4,7 @@ This BSP currently supports the following devices:
   - Console using UART-D on DB9 connector and UART-A on the J3A2 Pin header
   - Clock using the ARM internal CP15 timer
   - Benchmark timer using the Nvidia Generic Timer TimerUS
+  - GPIOs
 
 Checkout the options described in include/bspopts.h.in in order to configure
 the second console or let the consoles operate interrupt driven.
@@ -12,6 +13,7 @@ Currently, following IRQs are used:
   If configured NS8250_CONSOLE_USE_INTERRUPTS=1)
     - 122
     - 68
+  - 119 for the GPIO_6 bank (PU0 - PU6)
 
 Also allow the following memory regions:
   - UARTA 0x40 at 0x70006000
@@ -19,3 +21,4 @@ Also allow the following memory regions:
   - Nvidia Timers 0x1000 at 0x60005000
   - RAM 64MB at 0x90000000
   - PINMUX AUX 0x1000 at 0x70003000
+  - GPIO 0x1000 at 0x6000d000
diff --git a/c/src/lib/libbsp/arm/jetson-tk1/gpio/tegra124-gpio.c b/c/src/lib/libbsp/arm/jetson-tk1/gpio/tegra124-gpio.c
new file mode 100644
index 0000000000..da35b6dfe0
--- /dev/null
+++ b/c/src/lib/libbsp/arm/jetson-tk1/gpio/tegra124-gpio.c
@@ -0,0 +1,271 @@
+/*
+ * Copyright (c) OTH Regensburg, 2017
+ *   Author: Andreas Kölbl
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.org/license/LICENSE.
+ */
+
+#include <bsp.h>
+#include <bsp/gpio.h>
+#include <bsp/memory.h>
+#include <bsp/tegra124-gpio.h>
+
+#define GPIO_CNF 0x00
+#define GPIO_OE 0x10
+#define GPIO_OUT 0x20
+#define GPIO_IN 0x30
+#define GPIO_INT_STA 0x40
+#define GPIO_INT_ENB 0x50
+#define GPIO_INT_LVL 0x60
+#define GPIO_INT_CLR 0x70
+
+#define GPIO_MSK_CNF 0x80
+#define GPIO_MSK_OE 0x90
+#define GPIO_MSK_OUT 0xa0
+#define GPIO_MSK_INT_STA 0xc0
+#define GPIO_MSK_INT_ENB 0xd0
+#define GPIO_MSK_INT_LVL 0xe0
+
+/*
+ * To achieve a performant and compatible implementation the bank parameter has
+ * also to include the gpio port address, Tegra K1 TRM, p. 278
+ */
+
+static inline void tegra_gpio_write(
+  uintptr_t gpio_reg,
+  uint32_t  bank,
+  uint32_t  value
+)
+{
+  mmio_write( GPIO_BASE + gpio_reg + bank, value );
+}
+
+static uint32_t tegra_gpio_read(
+  uintptr_t gpio_reg,
+  uint32_t  bank
+)
+{
+  return mmio_read( GPIO_BASE + gpio_reg + bank );
+}
+
+static inline void pinmux_write(
+  uint32_t              pinmux_reg,
+  uint32_t              pin,
+  tegra_pinmux_property property
+)
+{
+  mmio_write( PINMUX_AUX + pinmux_reg + 4 * pin, property );
+}
+
+static inline uint32_t pinmux_read(
+  uint32_t pinmux_reg,
+  uint32_t pin
+)
+{
+  return mmio_read( PINMUX_AUX + pinmux_reg + 4 * pin );
+}
+
+static inline void gpio_set_level(
+  uint32_t             bank,
+  uint32_t             pin,
+  rtems_gpio_interrupt sens
+)
+{
+  uint32_t value;
+
+  value = tegra_gpio_read( GPIO_INT_LVL, bank );
+
+  value &= ~( ( 1 << pin ) | ( ( 1 << 8 ) << pin ) | ( ( 1 << 16 ) << pin ) );
+
+  if ( sens != NONE ) {
+    value |= ( 1 << 8 ) << pin;
+  }
+
+  if ( sens == RISING_EDGE || sens == HIGH_LEVEL ) {
+    value |= 1 << pin;
+  } else if ( sens == BOTH_EDGES ) {
+    value |= ( 1 << 16 ) << pin;
+  }
+
+  tegra_gpio_write( GPIO_INT_LVL, bank, value );
+}
+
+rtems_status_code rtems_gpio_bsp_multi_set(uint32_t bank, uint32_t bitmask)
+{
+  tegra_gpio_write( GPIO_OUT, bank, bitmask & 0xff );
+
+  return RTEMS_SUCCESSFUL;
+}
+
+rtems_status_code rtems_gpio_bsp_multi_clear(uint32_t bank, uint32_t bitmask)
+{
+  tegra_gpio_write( GPIO_MSK_OUT, bank, bitmask << 8 );
+
+  return RTEMS_SUCCESSFUL;
+}
+
+uint32_t rtems_gpio_bsp_multi_read(uint32_t bank, uint32_t bitmask)
+{
+  return tegra_gpio_read( GPIO_IN, bank ) & bitmask;
+}
+
+rtems_status_code rtems_gpio_bsp_set(uint32_t bank, uint32_t pin)
+{
+  tegra_gpio_write( GPIO_MSK_OUT, bank, ( ( 1 << 8 ) << pin ) | ( 1 << pin ) );
+
+  return RTEMS_SUCCESSFUL;
+}
+
+rtems_status_code rtems_gpio_bsp_clear(uint32_t bank, uint32_t pin)
+{
+  tegra_gpio_write( GPIO_MSK_OUT, bank, ( 1 << 8 ) << pin );
+
+  return RTEMS_SUCCESSFUL;
+}
+
+uint32_t rtems_gpio_bsp_get_value(uint32_t bank, uint32_t pin)
+{
+  return ( ( tegra_gpio_read( GPIO_IN, bank ) & ( 1 << pin ) ) != 0 );
+}
+
+rtems_status_code rtems_gpio_bsp_select_input(
+  uint32_t bank,
+  uint32_t pin,
+  void    *pinmux_reg
+)
+{
+  pinmux_write(
+    *( (uint32_t *) ( pinmux_reg ) ),
+    pin,
+    TEGRA_E_INPUT | TEGRA_TRISTATE
+  );
+  tegra_gpio_write( GPIO_MSK_CNF, bank, 1 << pin );
+  tegra_gpio_write( GPIO_MSK_OE, bank, 1 << pin );
+
+  return RTEMS_SUCCESSFUL;
+}
+
+rtems_status_code rtems_gpio_bsp_select_output(
+  uint32_t bank,
+  uint32_t pin,
+  void    *pinmux_reg
+)
+{
+  pinmux_write( *( (uint32_t *) ( pinmux_reg ) ), pin, 0 );
+  tegra_gpio_write( GPIO_MSK_CNF, bank, 1 << pin );
+  tegra_gpio_write( GPIO_MSK_OE, bank, ( ( 1 << 8 ) << pin ) | ( 1 << pin ) );
+
+  return RTEMS_SUCCESSFUL;
+}
+
+rtems_status_code rtems_gpio_bsp_select_specific_io(
+  uint32_t bank,
+  uint32_t pin,
+  uint32_t function,
+  void    *pin_data
+)
+{
+  pinmux_write( bank, pin, (tegra_pinmux_property) function );
+
+  return RTEMS_SUCCESSFUL;
+}
+
+rtems_status_code rtems_gpio_bsp_set_resistor_mode(
+  uint32_t             bank,
+  uint32_t             pin,
+  rtems_gpio_pull_mode mode
+)
+{
+  switch ( mode ) {
+    case PULL_UP:
+      pinmux_write( bank, pin, TEGRA_PULL_UP );
+      break;
+    case PULL_DOWN:
+      pinmux_write( bank, pin, TEGRA_PULL_DOWN );
+      break;
+    case NO_PULL_RESISTOR:
+      pinmux_write( bank, pin, TEGRA_PULL_DISABLED );
+      break;
+    default:
+
+      return RTEMS_INVALID_NUMBER;
+  }
+
+  return RTEMS_SUCCESSFUL;
+}
+
+rtems_vector_number rtems_gpio_bsp_get_vector( uint32_t bank )
+{
+  if ( ( bank / 0x100 ) > sizeof( gpio_vector_table ) ) {
+    return -1;
+  }
+
+  return gpio_vector_table[ bank / 0x100 ];
+}
+
+uint32_t rtems_gpio_bsp_interrupt_line( rtems_vector_number vector )
+{
+  uint32_t bank;
+
+  for ( bank = 0; bank < sizeof( gpio_vector_table ); bank++ ) {
+    if ( gpio_vector_table[ bank ] == vector ) {
+      tegra_gpio_write( GPIO_INT_CLR, bank * 0x100, 0xff );
+
+      return tegra_gpio_read( GPIO_INT_STA, bank * 0x100 );
+    }
+  }
+
+  return RTEMS_INVALID_NUMBER;
+}
+
+rtems_status_code rtems_gpio_bsp_enable_interrupt(
+  uint32_t             bank,
+  uint32_t             pin,
+  rtems_gpio_interrupt interrupt
+)
+{
+  tegra_gpio_write( GPIO_INT_CLR, bank, 1 << pin );
+  gpio_set_level( bank, pin, interrupt );
+  tegra_gpio_write( GPIO_MSK_INT_ENB,
+    bank,
+    ( ( 1 << 8 ) << pin ) | ( 1 << pin ) );
+
+  return RTEMS_SUCCESSFUL;
+}
+
+rtems_status_code rtems_gpio_bsp_disable_interrupt(
+  uint32_t             bank,
+  uint32_t             pin,
+  rtems_gpio_interrupt interrupt
+)
+{
+  uint32_t level;
+
+  tegra_gpio_write( GPIO_INT_CLR, bank, 1 << pin );
+  level = tegra_gpio_read( GPIO_INT_LVL, bank );
+  tegra_gpio_write( GPIO_MSK_INT_ENB, bank, ( ( 1 << 8 ) << pin ) );
+  tegra_gpio_write( GPIO_INT_LVL, bank, level & ~interrupt );
+
+  return RTEMS_SUCCESSFUL;
+}
+
+rtems_status_code rtems_gpio_bsp_multi_select(
+  rtems_gpio_multiple_pin_select *pins,
+  uint32_t                        pin_count,
+  uint32_t                        select_bank
+)
+{
+  return RTEMS_NOT_DEFINED;
+}
+
+rtems_status_code rtems_gpio_bsp_specific_group_operation(
+  uint32_t  bank,
+  uint32_t *pins,
+  uint32_t  pin_count,
+  void     *arg
+)
+{
+  return RTEMS_NOT_DEFINED;
+}
diff --git a/c/src/lib/libbsp/arm/jetson-tk1/include/bsp.h b/c/src/lib/libbsp/arm/jetson-tk1/include/bsp.h
index ea4dcb74e4..a9a47584a6 100644
--- a/c/src/lib/libbsp/arm/jetson-tk1/include/bsp.h
+++ b/c/src/lib/libbsp/arm/jetson-tk1/include/bsp.h
@@ -22,4 +22,8 @@
 
 #define TIMER_BASE ((void *) 0x60005000)
 
+#define BSP_GPIO_PINS_PER_BANK 32
+#define BSP_GPIO_BANK_COUNT 8
+#define BSP_GPIO_PIN_COUNT (BSP_GPIO_PINS_PER_BANK * BSP_GPIO_BANK_COUNT)
+
 #endif /* LIBBSP_ARM_JETSONTK1_BSP_H */
diff --git a/c/src/lib/libbsp/arm/jetson-tk1/include/tegra124-gpio.h b/c/src/lib/libbsp/arm/jetson-tk1/include/tegra124-gpio.h
new file mode 100644
index 0000000000..cbfb6e4f3f
--- /dev/null
+++ b/c/src/lib/libbsp/arm/jetson-tk1/include/tegra124-gpio.h
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) OTH Regensburg, 2017
+ *   Author: Andreas Kölbl
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.org/license/LICENSE.
+ */
+
+#ifndef LIBBSP_ARM_JETSON_GPIO_H
+#define LIBBSP_ARM_JETSON_GPIO_H
+
+#define GPIO_BASE ((void *) 0x6000d000)
+#define PINMUX_AUX ((void *) 0x70003000)
+
+#define GPIO1_IRQ (32 + 32)
+#define GPIO2_IRQ (33 + 32)
+#define GPIO3_IRQ (34 + 32)
+#define GPIO4_IRQ (35 + 32)
+#define GPIO5_IRQ (55 + 32)
+#define GPIO6_IRQ (87 + 32)
+#define GPIO7_IRQ (89 + 32)
+#define GPIO8_IRQ (125 + 32)
+
+static const uint8_t gpio_vector_table[ BSP_GPIO_BANK_COUNT ] = {
+  GPIO1_IRQ,
+  GPIO2_IRQ,
+  GPIO3_IRQ,
+  GPIO4_IRQ,
+  GPIO5_IRQ,
+  GPIO6_IRQ,
+  GPIO7_IRQ,
+  GPIO8_IRQ,
+};
+
+typedef enum {
+  TEGRA_SFIO0 = ((0 << 1) | (0 << 0)),
+  TEGRA_SFIO1 = ((0 << 1) | (0 << 0)),
+  TEGRA_SFIO2 = ((1 << 1) | (0 << 0)),
+  TEGRA_SFIO3 = ((1 << 1) | (1 << 0)),
+  TEGRA_PULL_DISABLED = ((0 << 3) | (0 << 2)),
+  TEGRA_PULL_DOWN = ((0 << 3) | (1 << 2)),
+  TEGRA_PULL_UP = ((1 << 3) | (0 << 2)),
+  TEGRA_TRISTATE = (1 << 4),
+  TEGRA_E_INPUT = (1 << 5),
+  TEGRA_E_OPEN_DRAIN = (1 << 6), /* Matters only for DD pads */
+  TEGRA_LOCK = (1 << 7),
+  TEGRA_IO_RESET = (1 << 8),    /* Matters only for LV pads */
+} tegra_pinmux_property;
+
+typedef enum {
+  GPIO_PU0 = 0x184,
+  GMI_AD8 = 0x210,
+} pinmux_ball;
+
+typedef enum {
+  GPIO_DIR_IN,
+  GPIO_DIR_OUT,
+} gpio_direction;
+
+#endif /* LIBBSP_ARM_JETSON_GPIO_H */
diff --git a/c/src/lib/libbsp/arm/jetson-tk1/startup/mm_config_table.c b/c/src/lib/libbsp/arm/jetson-tk1/startup/mm_config_table.c
index a8c3f41ccf..603ff6fac0 100644
--- a/c/src/lib/libbsp/arm/jetson-tk1/startup/mm_config_table.c
+++ b/c/src/lib/libbsp/arm/jetson-tk1/startup/mm_config_table.c
@@ -10,6 +10,8 @@
 #include <bsp.h>
 #include <bspopts.h>
 #include <bsp/car.h>
+#include <bsp/tegra124-gpio.h>
+#include <bsp/cmdline.h>
 #include <bsp/console.h>
 #include <bsp/arm-cp15-start.h>
 
@@ -26,6 +28,10 @@ BSP_START_DATA_SECTION const arm_cp15_start_section_config
 arm_cp15_start_mmu_config_table[] = {
   ARMV7_CP15_START_DEFAULT_SECTIONS,
   {
+    .begin = (uint32_t) BSP_CMDLINE_LOCATION,
+    .end = (uint32_t) BSP_CMDLINE_LOCATION + 0x4000,
+    .flags = ARMV7_MMU_DATA_READ_WRITE_CACHED
+  }, {
     .begin = (uint32_t) CAR,
     .end = (uint32_t) (CAR + 0x1000),
     .flags = ARMV7_MMU_DEVICE
@@ -38,6 +44,14 @@ arm_cp15_start_mmu_config_table[] = {
     .end = (uint32_t) (APB_MISC_BASE + 0x1000),
     .flags = ARMV7_MMU_DEVICE
   }, {
+    .begin = (uint32_t) GPIO_BASE,
+    .end = (uint32_t) (GPIO_BASE + 0x1000),
+    .flags = ARMV7_MMU_DEVICE
+  }, {
+    .begin = (uint32_t) PINMUX_AUX,
+    .end = (uint32_t) (PINMUX_AUX + 0x1000),
+    .flags = ARMV7_MMU_DEVICE
+  }, {
     .begin = (uint32_t) UARTA,
     .end = (uint32_t) UARTA + 0x1000,
     .flags = ARMV7_MMU_DEVICE
-- 
2.13.3



More information about the devel mailing list