How to change pinmux regs in CBoot?

I am trying to change the pinmux config in CBoot using this code:

NV_WRITE32(NV_ADDRESS_MAP_PADCTL_A0_BASE + 0xd040, 0x00000005); // Z3
NV_WRITE32(NV_ADDRESS_MAP_PADCTL_A0_BASE + 0xd058, 0x00000005); // Z5
NV_WRITE32(NV_ADDRESS_MAP_PADCTL_A0_BASE + 0xd010, 0x00000009); // Z6
NV_WRITE32(NV_ADDRESS_MAP_PADCTL_A0_BASE + 0x0028, 0x0000000a); // Q5

But unfortunately the last line results in an boot error:

[0001.393] -----------------------------------------------
[0001.398] Synchronous Exception: DATA ABORT (FAR: 2430028)
[0001.403] -----------------------------------------------
[0001.409] PAR_ELX: 0x80f
[0001.412] ESR 0x96000047: ec 0x25, il 0x1, iss 0x47
[0001.417] -----------------------------------------------
[0001.422] [Stack Trace]
[0001.426] => pc:0xA060F434, sp:0xA0684DA0
[0001.430] => pc:0xA060018C, sp:0xA0684FD0
[0001.433] -----------------------------------------------
[0001.439] iframe 0xa0684cb0:
[0001.441] x0 0x 2430028 x1 0x a x2 0x a x3 0x 15
[0001.450] x4 0x 0 x5 0x a0684d80 x6 0x 20 x7 0x 3
[0001.460] x8 0x 7 x9 0x a x10 0x aafff60f x11 0x a0600010
[0001.469] x12 0x 0 x13 0x 0 x14 0x 0 x15 0x 3c0
[0001.478] x16 0x 0 x17 0x 0 x18 0x a600000 x19 0x f2820000
[0001.487] x20 0x a0662418 x21 0x 0 x22 0x a0600190 x23 0x 0
[0001.496] x24 0x 0 x25 0x 0 x26 0x 0 x27 0x 0
[0001.505] x28 0x 0 x29 0x a0684fd0 lr 0x a060f404 sp 0x a0684da0
[0001.514] elr 0x a060f434
[0001.517] spsr 0x 600002c9
[0001.520] -----------------------------------------------
[0001.526] panic (caller 0xa0601238): die

How can I fix that? I can change pinmux regs in Linux userspace, but what’s the problem here?

Changing the pinmux spreadsheet in cfg shall change the pinmux in cboot also. Could you use that to change first?

Yes it works. But this method is not suitable for me. I don’t want change default *.cfg files, because its add complexity to patching SDK. I just want to change pinmux regs in the CBoot runtime as it does when the Linux kernel boots.

hello avv,

may I know how you obtain the reg address, the offsets should only consider after it boot into linux.

I used bootloader/t186ref/BCT/tegra19x-mb1-pinmux-p3668-a01.cfg and “Xavier Series SoC Technical Reference Manual” (for check) to get addresses. Also, I found macros NV_ADDRESS_MAP_PADCTL_A0_BASE in CBoot code that evaluates as padctl regs base address (0x2430000).
For example, reg PADCTL_UART_SPI1_SCK_0 (GPIO Z3) have offset 0x40 in PADCTL_A13 (0x0243d000), then I get the full address using expression NV_ADDRESS_MAP_PADCTL_A0_BASE + 0xd040.

hello avv,

you should also refer to public release sources,
i.e. $L4T_Sources/r32.6.1/Linux_for_Tegra/source/public/cboot/bootloader/partner/common/drivers/gpio/tegrabl_gpio.c

instead of using NV_WRITE32 to program GPIO directly.
you may check this internal function to get register address.
for example,

static inline uint32_t reg(...)
        return id->base_addr + bank_base + (reg - GPIO_N_ENABLE_CONFIG_00_0) +
                        (gpio * (GPIO_N_ENABLE_CONFIG_01_0 - GPIO_N_ENABLE_CONFIG_00_0));

you should only using the GPIO pin number to access GPIOs.
please use these Tegra GPIO driver APIs in CBoot. for example, tegrabl_gpio_read(), and tegrabl_gpio_write().

To access the GPIO I am using this CBoot driver as you mentioned. But unfortunately the function call gpio_config(gpio_main_drv, TEGRA_GPIO(Z, 3), GPIO_PINMODE_OUTPUT) does not change the pin direction from default input to output.
Instead, I found that pinmux configuration for MB1 in .cfg file works well. But this solution does not suit me.

this looks incorrect,
you may also refer to the GPIO header file for Xavier series, i.e. tegra194-gpio.h ,
please have a try by using… TEGRA194_MAIN_GPIO(Z, 3) for confirmation,

There is no definition of the TEGRA194_MAIN_GPIO in the CBoot sources for 32.5.1. Check with grep -r TEGRA194_MAIN_GPIO in the source directory.

TEGRA_GPIO works as needed with tegrabl_gpio_read() and tegrabl_gpio_write() functions. I checked this with oscilloscope with pinmux configured in MB1.

hello avv,

please also refer to this topic as see-also, How to make gpio high-level in cboot? - #16 by JerryChang

How to make gpio high-level in cboot? does not contain any information about changing the direction of the pin in the CBoot code.

hello avv,

please refer to the code,
can’t you use tegrabl_gpio_config() to configure GPIO direction in CBoot soruces?

static tegrabl_error_t tegrabl_gpio_config()
  	switch (mode) {
  		gpio_set_output_control(id, gpio_num, GPIO_OUT_CONTROL_DRIVEN);
  		gpio_set_direction(id, gpio_num, mode);

I tried to use it. Unfortunately, calling tegrabl_gpio_config() function does not change the direction of the pin in any way.

hello avv,

let’s back to your original question,
may I know what’s the actual use-case to change the pinmux settings for those 4 GPIOs/pins in CBoot.
could you please also share diff file to indicate all the cboot changes you’ve done for reference.

may I know what’s the actual use-case to change the pinmux settings for those 4 GPIOs/pins in CBoot.

I use them to control SPI OLED display.

could you please also share diff file to indicate all the cboot changes you’ve done for reference.

See the patch in the attached files.

mypatch.patch (5.5 KB)

hello avv,

may I know what’s the core CBoot changes?
the patch only shows the implementation to wiggle the GPIOs.

the recommended approach is modification via pinmux (i.e. the pinmux dtsi file, which you’ve claim it works OK).

The patch in the attachment contains in general all the changes that were made. A line NV_WRITE32(NV_ADDRESS_MAP_PADCTL_A0_BASE + 0x0028, 0x0000000a); leads to the error described in the 1st post.

mypatch.patch (5.9 KB)

hello avv,

please use the 32-bit register write marco in the NV_WRITE32(), you may also read it back and print it out to ensure you’ve gotten the correct register.
you’re not seeing it changes, perhaps you’re doing this before GPIO/pinmux initialization from the core DTSI files.

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.