Xavier AGX /dev/mem gpio

I’m trying to read GPIO pin 33 on the 40 pin connector. According to the TRM/pinmux this is GPIO pin 248 on the AON PAA.0 from what I can tell this shoudl be at 0x0c2f0000 + 0x1000. When I look at gpio-tegra186.cpp and tegra194-gpio.h thitegra_AON_GPIO_PORTAA is 0 but looking at TEGRA_AON_GPIO_PORT_INFO the reg_offset is cind* 0x200 where cind is 6.
When I map /dev/mem to 0xc2f1000 if I ignore reg_offset I’m able to read the Input (at offset 0x30) but it never changes. If I try to add the reg_offset of 0xc00 I get a segmentation fault.

I’ve seen examples for different versions of the jetson but not for Xavier AGX.

Any help in figuring out the correct address would be appreciated.

hello dgolick ,

the quickest way for checking the address of the GPIO pin were refer to the board’s pinmux configuration file.
for example,
tegra186-mb1-bct-pinmux-quill-p3310-1000-c03.cfg

pinmux.0x0c303028 = 0x00000054; # can_gpio0_paa0: rsvd0, pull-down, tristate-enable, input-enable

Thanks Jerry,
I’ve used the pinmux to find that it is PAA.0 and I know from using SYSFS interface that its GPIO 248 , but this hasn’t help to get the correct physical address for the correct memory mapped GPIO address.

SYSFS works fine but it’s too slow for our purposes and the kernel transition is undesirable. We are reading at about 80 khz and can’t afford a missed transition

From Jetson Hackson Xavier pin 33 === gpio248:
gpio248 CAN1_DOUTCAN #1 Data Out*3.3V* 33

From Xavier PinMux we have:
CAN1_DOUT H61 CAN1_DOUT AA49 GPIO3_PAA.00

From the kernel dtbindings/tegra194-gpio.h
/* GPIOs implemented by AON GPIO controller */
#define TEGRA194_AON_GPIO_PORT_AA 0

and from kernel gpio-tegra186.cpp
TEGRA_AON_GPIO_PORT_INFO(AA, 0, 6, 8),
and
#define TEGRA194_AON_GPIO_PORT_INFO(port, cid, cind, npins)
[TEGRA194_AON_GPIO_PORT_##port] = {
.port_name = #port,
.cont_id = cid,
.port_index = cind,
.valid_pins = npins,
.reg_index = 1,
.scr_offset = cind * 0x40,
.reg_offset = cind * 0x200, \

Which gives reg_offset of 6* 0x200 or 0xc00

From Xavier TRM we get the base address:
AON_GPIO_0 0x0c2f0000 0x0c2fffff SYSTEM

So now things get hazy… I see most people using a register offset of 0x1000. Reading IN (offset 0x30) from base register 0xc2f0000 gives an access violation.

If instead I read from 0xc2f1000 at offset 0x30 I can read a value but it doesn’t match what I read through SYSFS.

If I add the reg_offset of 0xC00 I get an access violation.

There seem to be a number of github examples for other jetson configurations but none for Xavier AGX.

Thanks in advance.

hello dgolick,

you need to check tegra194 series for Xavier’s GPIO settings.

hello dgolick,

BTW,
you may try below commands to check the reg address of this GPIO pin.
for example,
# cat /sys/kernel/debug/tegra_pinctrl_reg | grep paa0

I’m not sure what you mean by “check tegra194 series”. Is there a specific doc or source file you are suggesting?

Jerry, is there documentation of the AON GPIO controller? It seems like it may have a different gpio controller/layout. One of my colleagues remembers reading that it had a different stride between ports.

This finds an address of c303000 but that address always reads back 0xc055 (the value shown in the file.
If I use sysfs to change it from an input to an output I read back 0xc005. So it seems related to the GPIO configuration but not the gpio controller itself.

/sys/kernel/debug/gpio has the line
gpiochip1: GPIOs 248-287 platform/c2f000-gpio/tegra-gpio-aon
This matches what I expect the gpio pin 248 should be in the AON gpio controller. None the less I can’t find the working controller to read back the correct value of pin 33 (gpio 248)

I really need the AON memory map for the Xavier AGX but I can’t seem to find it in any documentation. Doesn’t Nvidia expect us to use the GPIO? Really the jetson doesn’t seem adequately supported to do embedded development.

hello dgolick,

my meant you should check header file, tegra194-gpio.h for Jetson AGX Xavier series configurations.
it’s Xavier Series SoC Technical Reference Manual for the documentation, please check chapter-8.5 [Multi-Purpose I/O Pins and Pin Multiplexing (PinMux)] for reference.
thanks

I verified the base address of the pin (pin 33 on the 40 pin connector) is GPIO 248
I verified the base address of the AON with the GPIO (and the address of the padctrl) from the TRM:
AON_GPIO_0 0x0c2f0000 0x0c2fffff SYSTEM
PADCTL_A15 0x0c303000 0x0c303fff SYSTEM

From the pinmux spread-sheet this is defined as PAA.0

From kernel source code (tegra194-gpio.h and gpio-tegra186.cpp) I get:
struct tegra_gpio_port_soc_info tegra194_aon_gpio_cinfo = {
TEGRA194_AON_GPIO_PORT_INFO(AA, 0, 3, 8),
which defines the reg_offset as 0x600

And of course the IN offset is 0x30.

I’ve been using SYSFS to set the direction of the pin and then trying to read a high value from the pin.

It appears to me that the the GPIO controller starts at offset 0x1000 from the base address.

The most pressing question is what is the offset from the base address to read this pin?

Hi dgolick,
You can refer cpp definitions to get gpio controller address and tegra194-gpio.h to get final gpio number.
For PAA.0:
From gpio-tegra186.cpp, you can see
static struct tegra_gpio_port_soc_info tegra194_aon_gpio_cinfo = {
TEGRA194_AON_GPIO_PORT_INFO(AA, 0, 3, 8),

and
#define TEGRA194_AON_GPIO_PORT_INFO(port, cid, cind, npins)
[TEGRA194_AON_GPIO_PORT_##port] = {
.port_name = #port,
.cont_id = cid,
.port_index = cind,
.valid_pins = npins,
.reg_index = 1,
.scr_offset = cind * 0x40,
.reg_offset = cind * 0x200,

means reg_offset = 3x200=600
add it with base: 0x0c2f1000+600=0x0c2f1600.

I see you have mentioned TEGRA_AON_GPIO_PORT_INFO(AA, 0, 6, 8),
which is wrong.
Please refer tegra194_aon_gpio_cinfo structure in the driver.
Let me know if you need more info.

Thanks,
Shubhi

thanks shubi,

Great information.

I’ve tried the offset 0xc2f1600 + 0x30 for IN and that doesn’t seem to work.

Is the GPIO register offsets different in the AON?

I’ve been using:

struct GPIO_mem {
uint32_t CNF[4];
uint32_t OE[4];
uint32_t OUT[4];
uint32_t IN[4];
uint32_t INT_STA[4];
uint32_t INT_ENB[4];
uint32_t INT_LVL[4];
uint32_t INT_CLR[4];
};

as the memory layout but I saw one example that had:

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

This would imply a layout of

ruct GPIO_mem {
uint32_t CNF[2];
uint32_t IN[2];

uint32_t OE[2];
uint32_t OUT[2];

};

this is correct.
Why were you adding 0x30 to check input value?
correct register will be : 0xc2f1608

Thanks so much.

Is the memory layout of the gpio controller documented somewhere?

hello dgolick,

please access Xavier Series SoC Technical Reference Manual,
you may check system address map for details,
for example,

| Block Name   | Start Address | End Address |
| AON_GPIO_0   | 0x0c2f0000    | 0x0c2fffff  |