GPIO /dev/mem IN/OUT

I am attempting to use memory mapped IO to sample and set GPIO pins at a rate of approx 160kHz (CLK pin w/synchronous data using s/w driven GPIOs).

UART1_TX and UART1_RX are already connected and would be preferred to use in GPIO mode.

Also available for deadbug would be GPIO4, GPIO5, GPIO20, GPIO21

Using SYSFS methods for I/O is too slow to keep up with the data rate.

I have tried following previous guides to determine how to memory-map these GPIOs but have not been able to find the proper mapping for accessing IN and OUT values. Cross-checking “sudo cat /sys/kernel/debug/tegra_gpio” - my memory mapping attempts for IN/OUT did not match and mostly I read FF.

In contrast, I can read the pin control registers using memory mapped IO.

hello jasonpcb,

may I know what’s your actual use-case.
you should see Topic 144550, for several ways to access GPIOs. such as, kernel APIs, python scripts, C++ samples.
in addition, here’re steps to improve GPIO interrupt performance, Topic 192147.

The new links given confirm the /dev/mem method as the best. However, I have not been able to arrive at the correct addresses for the GPIOs to read the IN value and write the OUT value. This is a fairly common stumbling block.

The existing references for nano, etc. have been previously reviewed before posting.

The use case is communicating with external data acquisition devices connected through a clock qualified serial TX/RX.

Busybox’s devmem reads to the correct memory addresses for the listed GPIOs (IN and OUT reg) would be enough to start.

hello jasonpcb,

please also check the pinmux configuration file,
you’ll see the address and default values for each pin.
for example, tegra19x-mb1-pinmux-p2888-0000-a04-p2822-0000-b01.cfg.

Thanks - I think I’m getting there. Since the pinmux has reference to outputs to bias pins high/low - I can resolve the “OUT” memory addresses. Offsets of CONFIG vs CONTROL vs OUT do not follow an expected amount of offsets between these three. Therefore, I am not able to be positive about inferring the memory mapping for the IN (INPUT) register to read the GPIO high/low state for input or bidir pins.

If I say CONFIG is at memory address offset 0x0000 for each pin, then my map currently is:

0x0000 CONFIG
0x0010 OUT

Control and out are mapped with no bits between. Config and control have an undefined space of 4x2 (2 32-bit regs between). One guess would be IN is at offset 0x0014, but I’m not certain.

Also, is there a bitmap spec of config+control? I can infer some meaning from the pinmux but would prefer the reference.

I have the PADCTL definition from the TRM (which is a different memory mapping 0x023xxxxx or 0x024xxxxx space. This is helpful for pin properties.

I do not have the “IN” address mapping found yet to read the state of the pin as an input.

hello jasonpcb,

there’s a concept, it’s E_INPUT to configure the pin for the pads
for example, PADCTL_<padctl_group>_<ball_Name>_* .E_INPUT=ENABLE to turn on input receiver.
please refer to TRM, check [ Programming Sequence for Input Mode] for details.

I had reviewed this section which covers the input setup. However, I didn’t see a reference to a register to read to “sample” the pin state as high vs low.

For instance, pin G5 in the pinmux shows addr 0x022140b0 as the OUT register. For bidir support (and similar to other flavored SOMs) I’m looking for a register (MMIO) to read the IN. Even the TRM, for the next output section, didn’t spell out the OUT register but this was derived from the pinmux.

I’m not having any problem with control – that’s all spelled out nicely in the TRM. I’m having problem with sampling the pin itself to do software edge detect on clock and then just straight sampling on the data pin.

Say we’re dealing with GPIO20 as incoming 160kHz clock and GPIO21 is a data pin synchronous to the 160kHz clock.

I’m not having issue “setting up” the pins as input. I haven’t found how to resolve which register I read to grab the value as driven by an external device (serial bit bang sampling with software).

PADCTL_ regs (I get this)

      E_SCHMT                                                 = 0x00000000 // [12:12] DISABLE [DISABLE=0,ENABLE=1]
      GPIO_SF_SEL                                             = 0x00000001 // [10:10] SFIO [GPIO=0,SFIO=1]
      E_LPDR                                                  = 0x00000000 // [08:08] DISABLE [DISABLE=0,ENABLE=1]
      E_INPUT                                                 = 0x00000001 // [06:06] ENABLE [DISABLE=0,ENABLE=1]
      E_IO_HV                                                 = 0x00000001 // [05:05] ENABLE [DISABLE=0,ENABLE=1]
      TRISTATE                                                = 0x00000001 // [04:04] TRISTATE [PASSTHROUGH=0,TRISTATE=1]
      PUPD                                                    = 0x00000001 // [03:02] PULL_DOWN [NONE=0,PULL_DOWN=1,PULL_UP=2,RSVD=3]
      PM                                                      = 0x00000000 // [01:00] VGP3 [EXTPERIPH4=1,RSVD2=2,RSVD3=3,VGP3=0]

Assuming I set PADCTL.E_INPUT, where do I read the sampled value?


Set PM field as per PinMux selection in pad control register PADCTL_<padctl_group><ball_name>*.PM =

0x0: Primary

0x1: Alt1

0x2: Alt2

0x3: Alt3

Set SFIO/GPIO selection to SFIO selection, (PADCTL_<padctl_group><ball_name>*.GPIO_SFIO_SEL =

HSIO) (nothing but SFIO).

Set (PADCTL_<padctl_group><ball_name>* .TRISTATE = TRISTATE) to disable SoC functional logic

driving the I/O.

Set (PADCTL_<padctl_group><ball_name>* .E_INPUT= ENABLE) to turn on input receiver.

The specific I/O controllers driving the I/Os is configured and activated.

(End TRM)

At this point (in the TRM guide) I have an input pin “configured and activated” - but where do I read the value to determine the driven value (as driven by an external device wired to the GPIO header pins?

This is the documentation I am not resolving.