Bitbanging gpio lines on TX2

Both TX1 and TX2 are running the 3.2 release. Both have clocks set to maximum. I am attaching simplified test code which can be compiled natively on TX1 and TX2 and gives very different speeds on each.

Many thanks.

main.c : Compile using: g++ bitBang.c -o bitBang . Run using: sudo ./bitBang

/*----------------------------------------------------------------------*/
/*  Include dependant headers.                                          */
/*----------------------------------------------------------------------*/
#include <assert.h>
#include <stdint.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/mman.h>
#include <stdio.h>
#include <time.h>

/*----------------------------------------------------------------------*/
/*  Declare local/private types.                                        */
/*----------------------------------------------------------------------*/

/*! GPIO register base. */
static volatile uint8_t *       TegraGpio_X1RegBase       = NULL;
static volatile uint8_t *       TegraMainGpio_X2RegBase   = NULL;
static volatile uint8_t *       TegraAonGpio_X2RegBase    = NULL;

static const unsigned int      ClkGpioPinNumX2   = 388; // GPIO8
//static const unsigned int      DataGpioPinNumX2  = 298; // GPIO9

static const unsigned int      ClkGpioPinNumX1   = 187; // GPIO8
//static const unsigned int      DataGpioPinNumX1  = 186; // GPIO9

static int                     TegraGpio_MemFd   = -1;

static int                      DeviceType                =   0 ;   //!< 0: n/a 1: TX1 2: TX2

/*----------------------------------------------------------------------*/
/*  Define local/private data.                                          */
/*----------------------------------------------------------------------*/

#define GPIO_BASE                    (0x6000D000)
#define GPIO_CONTROLLER              (0x0100)
#define GPIO_PORTS_PER_CONTROLLER    (0x04)
#define GPIO_BITS_PER_PORT           (0x08)
#define GPIO_BITS_PER_CONTROLLER     (GPIO_BITS_PER_PORT * GPIO_PORTS_PER_CONTROLLER)

#define GPIO_CNF                     (0x80)
#define GPIO_OE                      (0x90)
#define GPIO_OUT                     (0xA0)
#define GPIO_IN                      (0x30)

// X2 definitions

#define MAIN_GPIO_BASE_X2           (0x02200000 + 0x10000)
#define AON_GPIO_BASE_X2            (0x0C2F0000 + 0x01000)

#define X2_CNF_OFFSET                   0x00
#define X2_IN_OFFSET           0x08
#define X2_OE_OFFSET          0x0C
#define X2_OUT_OFFSET          0x10

#define X2_CONF_OUTPUT                  0x03
#define X2_CONF_INPUT                   0x01

#define X2_OUTPUT_DRIVE                 0x00
#define X2_OUTPUT_FLOAT                 0x01

#define sysFs_Main_PinNumOffset         320
#define sysFs_Aon_PinNumOffset          256

/*! @brief  Read the Tegra_Id_Fuse value
 *
 *  @return 33 if TX1, 24 if TX2
 */
int tegraFuseValue()
{
  int     val           = 0;

  FILE *  tegraChipId     = fopen("/sys/module/tegra_fuse/parameters/tegra_chip_id","r");
  assert( tegraChipId );

  fscanf(tegraChipId, "%d",&val );

  fclose(tegraChipId);

  return val;
}

/*! @brief  LookupTable for TX2 sysfs pins
 *
 *  @return register address for the sysFsPin Id, NULL for pin Number = 0.
 */
volatile uint8_t *
TegraGpio_BaseAddressX2(
    unsigned int    inSysFsPinNum  //!< Pin Number used in TegraGpio_PinLookupX
 )
{
    //!@pre Not open.
    if( 0 == inSysFsPinNum)
    {
        return NULL;
    }

    assert(  (sysFs_Aon_PinNumOffset < inSysFsPinNum ) &&  (( sysFs_Main_PinNumOffset + 5 * 8 * 8 ) > inSysFsPinNum ) );
    unsigned int sysFsPinOffset  = (inSysFsPinNum - sysFs_Aon_PinNumOffset) % 8 ;

volatile uint8_t * baseRegisterAddress = NULL ;
    if( inSysFsPinNum < sysFs_Main_PinNumOffset)
    {
        #define TEGRA_AON_GPIO_PORT_S           0
        #define TEGRA_AON_GPIO_PORT_U           1
        #define TEGRA_AON_GPIO_PORT_V           2
        #define TEGRA_AON_GPIO_PORT_W           3
        #define TEGRA_AON_GPIO_PORT_Z           4
        #define TEGRA_AON_GPIO_PORT_AA          5
        #define TEGRA_AON_GPIO_PORT_EE          6
        #define TEGRA_AON_GPIO_PORT_FF          7

        #define TEGRA_AON_GPIO_PORT_S_ORDER     1
        #define TEGRA_AON_GPIO_PORT_U_ORDER     2
        #define TEGRA_AON_GPIO_PORT_V_ORDER     4
        #define TEGRA_AON_GPIO_PORT_W_ORDER     5
        #define TEGRA_AON_GPIO_PORT_Z_ORDER     7
        #define TEGRA_AON_GPIO_PORT_AA_ORDER    6
        #define TEGRA_AON_GPIO_PORT_EE_ORDER    3
        #define TEGRA_AON_GPIO_PORT_FF_ORDER    0
        unsigned int sysFsPortNum = (inSysFsPinNum - sysFs_Aon_PinNumOffset) / 8;
        assert(sysFsPortNum < 8);
        int AON_LOOKUP[8];
        AON_LOOKUP[TEGRA_AON_GPIO_PORT_S] = TEGRA_AON_GPIO_PORT_S_ORDER;
        AON_LOOKUP[TEGRA_AON_GPIO_PORT_U] = TEGRA_AON_GPIO_PORT_U_ORDER;
        AON_LOOKUP[TEGRA_AON_GPIO_PORT_V] = TEGRA_AON_GPIO_PORT_V_ORDER;
        AON_LOOKUP[TEGRA_AON_GPIO_PORT_W] = TEGRA_AON_GPIO_PORT_W_ORDER;
        AON_LOOKUP[TEGRA_AON_GPIO_PORT_Z] = TEGRA_AON_GPIO_PORT_Z_ORDER;
        AON_LOOKUP[TEGRA_AON_GPIO_PORT_AA] = TEGRA_AON_GPIO_PORT_AA_ORDER;
        AON_LOOKUP[TEGRA_AON_GPIO_PORT_EE] = TEGRA_AON_GPIO_PORT_EE_ORDER;
        AON_LOOKUP[TEGRA_AON_GPIO_PORT_FF] = TEGRA_AON_GPIO_PORT_FF_ORDER;
        baseRegisterAddress = TegraAonGpio_X2RegBase + 0x200 * AON_LOOKUP[sysFsPortNum] + sysFsPinOffset * 0x20;
    }
    else
    {
        #define TEGRA_MAIN_GPIO_PORT_A          0
        #define TEGRA_MAIN_GPIO_PORT_B          1
        #define TEGRA_MAIN_GPIO_PORT_C          2
        #define TEGRA_MAIN_GPIO_PORT_D          3
        #define TEGRA_MAIN_GPIO_PORT_E          4
        #define TEGRA_MAIN_GPIO_PORT_F          5
        #define TEGRA_MAIN_GPIO_PORT_G          6
        #define TEGRA_MAIN_GPIO_PORT_H          7
        #define TEGRA_MAIN_GPIO_PORT_I          8
        #define TEGRA_MAIN_GPIO_PORT_J          9
        #define TEGRA_MAIN_GPIO_PORT_K          10
        #define TEGRA_MAIN_GPIO_PORT_L          11
        #define TEGRA_MAIN_GPIO_PORT_M          12
        #define TEGRA_MAIN_GPIO_PORT_N          13
        #define TEGRA_MAIN_GPIO_PORT_O          14
        #define TEGRA_MAIN_GPIO_PORT_P          15
        #define TEGRA_MAIN_GPIO_PORT_Q          16
        #define TEGRA_MAIN_GPIO_PORT_R          17
        #define TEGRA_MAIN_GPIO_PORT_T          18
        #define TEGRA_MAIN_GPIO_PORT_X          19
        #define TEGRA_MAIN_GPIO_PORT_Y          20
        #define TEGRA_MAIN_GPIO_PORT_BB         21
        #define TEGRA_MAIN_GPIO_PORT_CC         22
        #define TEGRA_MAIN_GPIO_PORT_DD         23

#define TEGRA_MAIN_GPIO_PORT_N_ORDER    0
        #define TEGRA_MAIN_GPIO_PORT_O_ORDER    1
        #define TEGRA_MAIN_GPIO_PORT_Q_ORDER    2
        #define TEGRA_MAIN_GPIO_PORT_T_ORDER    3
        #define TEGRA_MAIN_GPIO_PORT_I_ORDER    4
        #define TEGRA_MAIN_GPIO_PORT_R_ORDER    5

        #define TEGRA_MAIN_GPIO_PORT_H_ORDER    8
        #define TEGRA_MAIN_GPIO_PORT_L_ORDER    9
        #define TEGRA_MAIN_GPIO_PORT_X_ORDER    10
        #define TEGRA_MAIN_GPIO_PORT_Y_ORDER    11

        #define TEGRA_MAIN_GPIO_PORT_A_ORDER    16
        #define TEGRA_MAIN_GPIO_PORT_E_ORDER    17
        #define TEGRA_MAIN_GPIO_PORT_F_ORDER    18
        #define TEGRA_MAIN_GPIO_PORT_BB_ORDER   19

        #define TEGRA_MAIN_GPIO_PORT_B_ORDER    24
        #define TEGRA_MAIN_GPIO_PORT_C_ORDER    25
        #define TEGRA_MAIN_GPIO_PORT_D_ORDER    26

        #define TEGRA_MAIN_GPIO_PORT_P_ORDER    32
        #define TEGRA_MAIN_GPIO_PORT_G_ORDER    33

        #define TEGRA_MAIN_GPIO_PORT_J_ORDER    40
        #define TEGRA_MAIN_GPIO_PORT_K_ORDER    41
        #define TEGRA_MAIN_GPIO_PORT_CC_ORDER   42
        #define TEGRA_MAIN_GPIO_PORT_M_ORDER    43

        #define TEGRA_MAIN_GPIO_PORT_DD_ORDER   44

unsigned int sysFsPortNum = (inSysFsPinNum - sysFs_Main_PinNumOffset) / 8;
        assert(sysFsPortNum < 24);

       int MAIN_LOOKUP[24];
       MAIN_LOOKUP[TEGRA_MAIN_GPIO_PORT_N] = TEGRA_MAIN_GPIO_PORT_N_ORDER;
       MAIN_LOOKUP[TEGRA_MAIN_GPIO_PORT_O] = TEGRA_MAIN_GPIO_PORT_O_ORDER;
       MAIN_LOOKUP[TEGRA_MAIN_GPIO_PORT_Q] = TEGRA_MAIN_GPIO_PORT_Q_ORDER;
       MAIN_LOOKUP[TEGRA_MAIN_GPIO_PORT_T] = TEGRA_MAIN_GPIO_PORT_T_ORDER;
       MAIN_LOOKUP[TEGRA_MAIN_GPIO_PORT_I] = TEGRA_MAIN_GPIO_PORT_I_ORDER;
       MAIN_LOOKUP[TEGRA_MAIN_GPIO_PORT_R] = TEGRA_MAIN_GPIO_PORT_R_ORDER;

       MAIN_LOOKUP[TEGRA_MAIN_GPIO_PORT_H] = TEGRA_MAIN_GPIO_PORT_H_ORDER;
       MAIN_LOOKUP[TEGRA_MAIN_GPIO_PORT_L] = TEGRA_MAIN_GPIO_PORT_L_ORDER;
       MAIN_LOOKUP[TEGRA_MAIN_GPIO_PORT_X] = TEGRA_MAIN_GPIO_PORT_X_ORDER;
       MAIN_LOOKUP[TEGRA_MAIN_GPIO_PORT_Y] = TEGRA_MAIN_GPIO_PORT_Y_ORDER;

       MAIN_LOOKUP[TEGRA_MAIN_GPIO_PORT_A] = TEGRA_MAIN_GPIO_PORT_A_ORDER;
       MAIN_LOOKUP[TEGRA_MAIN_GPIO_PORT_E] = TEGRA_MAIN_GPIO_PORT_E_ORDER;
       MAIN_LOOKUP[TEGRA_MAIN_GPIO_PORT_F] = TEGRA_MAIN_GPIO_PORT_F_ORDER;
       MAIN_LOOKUP[TEGRA_MAIN_GPIO_PORT_BB] = TEGRA_MAIN_GPIO_PORT_BB_ORDER;

       MAIN_LOOKUP[TEGRA_MAIN_GPIO_PORT_B] = TEGRA_MAIN_GPIO_PORT_B_ORDER;
       MAIN_LOOKUP[TEGRA_MAIN_GPIO_PORT_C] = TEGRA_MAIN_GPIO_PORT_C_ORDER;
       MAIN_LOOKUP[TEGRA_MAIN_GPIO_PORT_D] = TEGRA_MAIN_GPIO_PORT_D_ORDER;

       MAIN_LOOKUP[TEGRA_MAIN_GPIO_PORT_P] = TEGRA_MAIN_GPIO_PORT_P_ORDER;
       MAIN_LOOKUP[TEGRA_MAIN_GPIO_PORT_G] = TEGRA_MAIN_GPIO_PORT_G_ORDER;

       MAIN_LOOKUP[TEGRA_MAIN_GPIO_PORT_J] = TEGRA_MAIN_GPIO_PORT_J_ORDER;
       MAIN_LOOKUP[TEGRA_MAIN_GPIO_PORT_K] = TEGRA_MAIN_GPIO_PORT_K_ORDER;
       MAIN_LOOKUP[TEGRA_MAIN_GPIO_PORT_CC] = TEGRA_MAIN_GPIO_PORT_CC_ORDER;
       MAIN_LOOKUP[TEGRA_MAIN_GPIO_PORT_M] = TEGRA_MAIN_GPIO_PORT_M_ORDER;

      baseRegisterAddress = TegraMainGpio_X2RegBase + 0x200 * MAIN_LOOKUP[sysFsPortNum] + sysFsPinOffset * 0x20;
    }
    assert(baseRegisterAddress);
    return baseRegisterAddress ;
}

/*----------------------------------------------------------------------*/
/*  Define external api.                                                */
/*----------------------------------------------------------------------*/

unsigned long
gpioTx1PinOffset (
    unsigned int inGpioNum
)
{
    return (( (((inGpioNum % GPIO_BITS_PER_CONTROLLER) / GPIO_BITS_PER_PORT) * GPIO_PORTS_PER_CONTROLLER) + ((inGpioNum / GPIO_BITS_PER_CONTROLLER) * GPIO_CONTROLLER) ));
}

/*! @brief  Instantiate a VDU class and a GPU Mgr class
 */
int main()
{

    volatile uint32_t * TegraGpioClk_CnfReg;
    volatile uint32_t * TegraGpioClk_OeReg ;
    volatile uint32_t * TegraGpioClk_OutReg;
    volatile uint32_t * TegraGpioClk_InReg ; (void) TegraGpioClk_InReg;

    unsigned int TegraGpioClk_OutHighValue          = 0x01;
    unsigned int TegraGpioClk_OutLowValue           = 0x00;

    //Open Gpios

    if( (TegraGpio_MemFd = open( "/dev/mem", O_RDWR | O_SYNC)) >= 0 ) // RATS: ignore Filename constructed by us so known to be
      switch( tegraFuseValue() ) // Is TX1 or TX2
      {
        case 33 : DeviceType = 1; break;
        case 24 : DeviceType = 2; break;
        default: assert( 1 == DeviceType || 2 == DeviceType );
      }

// Open TX1 pins and map registers.
    if (1 == DeviceType)
    {
        //  Use mmap to gain access to GPIO register via a memory pointer.
        TegraGpio_X1RegBase   = (uint8_t *)mmap(
                                NULL,
                                0x1000,
                                PROT_READ|PROT_WRITE,
                                MAP_SHARED,
                                TegraGpio_MemFd,
                                GPIO_BASE );

        //  Init lookup arrays.
        assert( (long)TegraGpio_X1RegBase > 0 );

        unsigned long clkGpioPinOffset = gpioTx1PinOffset( ClkGpioPinNumX1 );

        TegraGpioClk_CnfReg               = (volatile uint32_t *)(TegraGpio_X1RegBase + clkGpioPinOffset + GPIO_CNF );
        TegraGpioClk_OeReg                = (volatile uint32_t *)(TegraGpio_X1RegBase + clkGpioPinOffset + GPIO_OE );
        TegraGpioClk_OutReg               = (volatile uint32_t *)(TegraGpio_X1RegBase + clkGpioPinOffset + GPIO_OUT );
        TegraGpioClk_InReg                = (volatile uint32_t *)(TegraGpio_X1RegBase + clkGpioPinOffset + GPIO_IN );
        TegraGpioClk_OutHighValue         = (0x0101U << (ClkGpioPinNumX1 % 8 ) );
        TegraGpioClk_OutLowValue          = (0x0100U << (ClkGpioPinNumX1 % 8 ) );
    }

if (2 == DeviceType)
    {
     //  Use mmap to gain access to GPIO register via a memory pointer.
    TegraMainGpio_X2RegBase   = (uint8_t *)mmap(
                            NULL,
                            0x10000,
                            PROT_READ|PROT_WRITE,
                            MAP_SHARED,
                            TegraGpio_MemFd,
                            MAIN_GPIO_BASE_X2 );
    TegraAonGpio_X2RegBase   = (uint8_t *)mmap(
                            NULL,
                            0x2000,
                            PROT_READ|PROT_WRITE,
                            MAP_SHARED,
                            TegraGpio_MemFd,
                            AON_GPIO_BASE_X2 );

      //  Init lookup arrays.
      assert( (long)TegraMainGpio_X2RegBase > 0 );
      assert( (long)TegraAonGpio_X2RegBase > 0 );

volatile uint8_t* clkPinBaseAddress    = TegraGpio_BaseAddressX2( ClkGpioPinNumX2);

      TegraGpioClk_CnfReg               = (volatile uint32_t *)(clkPinBaseAddress + X2_CNF_OFFSET );
      TegraGpioClk_OeReg                = (volatile uint32_t *)(clkPinBaseAddress + X2_OE_OFFSET );
      TegraGpioClk_OutReg               = (volatile uint32_t *)(clkPinBaseAddress + X2_OUT_OFFSET );
      TegraGpioClk_InReg                = (volatile uint32_t *)(clkPinBaseAddress + X2_IN_OFFSET );
      TegraGpioClk_OutHighValue         = 0x01;
      TegraGpioClk_OutLowValue          = 0x00;
    }

// Set Clk as output

if(1 == DeviceType)
        {
        *TegraGpioClk_CnfReg         = (0x0101U << ( ClkGpioPinNumX1 % 8 ));   // Gpio to change, set as GPIO.
        *TegraGpioClk_OeReg          = (0x0101U << ( ClkGpioPinNumX1 % 8 ));   // Gpio to change, set as output.
        }

        if(2 == DeviceType)
        {
            *TegraGpioClk_CnfReg         = (X2_CONF_OUTPUT );   // Gpio to change, set as GPIO.
            *TegraGpioClk_OeReg          = (X2_OUTPUT_DRIVE) ;   // Gpio to change, set as output.
        }

// Toggle Gpios

clock_t startTime = time(NULL);

    unsigned int numClockPeriods = 100 * 1000 * 1000 ;

 for (unsigned int iClk = 0 ; iClk < numClockPeriods ; ++iClk)
 {

    *TegraGpioClk_OutReg = TegraGpioClk_OutHighValue;
    *TegraGpioClk_OutReg = TegraGpioClk_OutLowValue;
 }

    clock_t finishTime = time(NULL);
    double duration = ( finishTime - startTime );

     printf("\n Time taken %.2f, Clock speed %.2f MHz", duration , numClockPeriods / (duration * 1000000));

// Close Gpios

if (1 == DeviceType)
    {
    int rc  = munmap( (void *)TegraGpio_X1RegBase, GPIO_CONTROLLER );
    assert( 0 == rc );  (void)rc;

    TegraGpio_X1RegBase     = NULL;
    }

    if(2 == DeviceType)
    {
    int rc  = munmap( (void *)TegraMainGpio_X2RegBase, 0x10000 );
    rc      += munmap( (void *)TegraAonGpio_X2RegBase, 0x2000 );
    assert( 0 == rc );  (void)rc;

    TegraMainGpio_X2RegBase       = NULL;
    TegraAonGpio_X2RegBase        = NULL;
    }

close( TegraGpio_MemFd );   TegraGpio_MemFd = -1;

    return(0);
}