How to make gpio high-level in cboot?

hi,
i use functions in tegrabl_gpio.c to pull GPIO17 high,but GPIO17 is still low,can you find something wrong in my codes?

static struct gpio_driver drv = {
{
.name = TEGRA_GPIO_MAIN_DRIVER_NAME,
.phandle = -1,
.ops = &tegra_gpio_ops,
.chip_id = TEGRA_GPIO_MAIN_CHIPID,
.driver_data = (void *)&tegra_gpio_id_main,
},
{
.name = TEGRA_GPIO_AON_DRIVER_NAME,
.phandle = -1,
.ops = &tegra_gpio_ops,
.chip_id = TEGRA_GPIO_AON_CHIPID,
.driver_data = (void *)&tegra_gpio_id_aon,
},
};

gpio_config(drv, 449, GPIO_PINMODE_OUTPUT);
gpio_write(drv,449, GPIO_PIN_STATE_HIGH);

hello gaozejun,

you may check pinmux spreadsheets, that GPIO17 (i.e. GPIO3_PQ.01) were configure as pull-down by default.
could you please customize that for updating board configuration.
thanks

I need to control GPIO17 to output high or low level to feed watchdog in cboot ,so I must use tegrabl_gpio_write and tegrabl_gpio_config.
If GPIO17 (i.e. GPIO3_PQ.01) were configure as pull-down by default, can i still control it to output different levels?

hello gaozejun,

I think you’re miscalculate GPIO number for controlling.
according to gpio header, GPIO3_PQ.01 should belong to main GPIO controller groups.
$L4T_Sources/r32.4.2/Linux_for_Tegra/source/public/kernel/nvidia/include/dt-bindings/gpio/tegra194-gpio.h

/* GPIOs implemented by main GPIO controller */
...
#define TEGRA194_MAIN_GPIO_PORT_Q 16

#define TEGRA194_MAIN_GPIO(port, offset) \
        ((TEGRA194_MAIN_GPIO_PORT_##port * 8) + offset)

you may also refer to GPIO offsets from the kernel booting messages,
for example,

[    0.877253] gpiochip_setup_dev: registered GPIOs 288 to 511 on device: gpiochip0 (tegra-gpio)
[    0.886001] gpiochip_setup_dev: registered GPIOs 248 to 287 on device: gpiochip1 (tegra-gpio-aon)

GPIO3_PQ.01 should have pin number as shown, (16*8) + 288 + 1 = 417.
please have a try to control that with APIs.
thanks

I still can not control the GPIO17 with code shown below.

static struct gpio_driver drv = {
{
.name = TEGRA_GPIO_MAIN_DRIVER_NAME,
.phandle = -1,
.ops = &tegra_gpio_ops,
.chip_id = TEGRA_GPIO_MAIN_CHIPID,
.driver_data = (void *)&tegra_gpio_id_main,
},
{
.name = TEGRA_GPIO_AON_DRIVER_NAME,
.phandle = -1,
.ops = &tegra_gpio_ops,
.chip_id = TEGRA_GPIO_AON_CHIPID,
.driver_data = (void *)&tegra_gpio_id_aon,
},
};
#define FEED_WDT 417
void feed_wdt(void)
{
tegrabl_gpio_write(FEED_WDT, GPIO_PIN_STATE_HIGH, drv[0].driver_data);
tegrabl_mdelay(100);
tegrabl_gpio_write(FEED_WDT, GPIO_PIN_STATE_LOW, drv[0].driver_data);
}

I run “feed_wdt()” in cboot_src_t19x/bootloader/partner/common/drivers/gpio/tegrabl_gpio.c.
My cboot_src_t19x code is running on Xavier platform.
Whether or not you have verified these functions
(
.read = &tegrabl_gpio_read,
.write = &tegrabl_gpio_write,
.config = &tegrabl_gpio_config
)?

I have check the hardware, gpio can output high/low level in driver of kernel, so hardware is ok.

hello gaozejun,

could you please also gather bootloader messages for checking,
you might add some debug prints to indicate you’d toggle GPIO17.
thanks

I add some debug prints.It shows that running code has enter this function gpio_config(),
error = gpio_config(gpio_drv, gpio_num, GPIO_PINMODE_OUTPUT);
if (error != TEGRABL_NO_ERROR) {
pr_error(“%s: Error config gpio pin\n”, func);
return error;
}
But gpio_config return error.

#define FEED_WDT 417
uint32_t gpio_wdt_out(void)
{
tegrabl_error_t error = TEGRABL_NO_ERROR;
struct gpio_driver *gpio_drv;
uint32_t chip_id;
uint32_t gpio_num;

chip_id = TEGRA_GPIO_MAIN_CHIPID;
gpio_num = FEED_WDT;
pr_info("Enabling gpio chip_id = %u, gpio pin = %u\n", chip_id, gpio_num);

	pr_info("\n----------gpio_wdt_out----------\n");

error = tegrabl_gpio_driver_get(chip_id, &gpio_drv);
if (error != TEGRABL_NO_ERROR) {
	pr_error("%s: Can't get gpio driver\n", __func__);
	return error;
}

error = gpio_config(gpio_drv, gpio_num, GPIO_PINMODE_OUTPUT);
if (error != TEGRABL_NO_ERROR) {
	pr_error("%s: Error config gpio pin\n", __func__);
	return error;
}

error = gpio_write(gpio_drv, gpio_num, GPIO_PIN_STATE_HIGH);
if (error != TEGRABL_NO_ERROR) {
	pr_error("%s: Error enabling gpio pin\n", __func__);
	return error;
}

 tegrabl_mdelay(20);

error = gpio_write(gpio_drv, gpio_num, GPIO_PIN_STATE_LOW);
if (error != TEGRABL_NO_ERROR) {
	pr_error("%s: Error enabling gpio pin\n", __func__);
	return error;
}

return 0;

}

I doubt the parameter of gpio_num is not the value of (group+(port*8)+pin).

hello gaozejun,

you’re right, above pin number calculation formula was based-on boot into linux kernel.
please using cboot marcos for writing GPIO pins,
for example,

static status_t tegra_gpio_write(uint32_t gpio_num, enum gpio_pin_state state, void *drv_data)
{
        ...
        GPIO_WRITE(GPIO_PORT_BASE(gpio_num), OUT, GPIO_PIN(gpio_num), reg_val);

I have solved this problem.
The parameter gpio_num is the value of (port*8)+pin, not include group.
SO in this function, GPIO17(GPIO3_PQ.01) will be 129.

Hi,

I am also trying to control GPIO in Cboot. I have followed the same way as mentioned above. But I am not able to control the GPIO.
I am using Jetson AGX Xavier. trying to control the GPIO3_PBB.00 (routed to 40-pin GPIO Header)
This GPIO is on TEGRA_GPIO_AON_CHIPID. And I followed the same calculation to get gpio_num:
(port*8)+pin
(TEGRA_GPIO_BANK_ID_BB * 8) + pin = (1 * 8) + 0 = 8.
But I used to control the same GPIO in my kernel modules using
(TEGRA_GPIO_BANK_ID_BB * 8) + offset = (1 * 8) + 248 = 256.
If I give gpio_num = 256. I will get invalid GPIO. and If I give 8. Not getting any Error. But GPIO is not toggling as per my code.
I have added a code snippet below I have added this snippet in tegrabl_gpio.c :

pin = 8;

pr_info("%s: check  pin = %d\n", __func__, pin);

err = tegrabl_gpio_driver_get(chip_id, &gpio_drv);
if (err != TEGRABL_NO_ERROR) {
	pr_error("%s: Failed to get GPIO driver struct\n", __func__);
	TEGRABL_SET_HIGHEST_MODULE(err);
	return err;
}
err = gpio_config(gpio_drv, pin, GPIO_PINMODE_OUTPUT);
if (err != TEGRABL_NO_ERROR) {
	pr_error("%s: Failed to configure GPIO pin: %d\n", __func__, pin);
	TEGRABL_SET_HIGHEST_MODULE(err);
	return err;
}

while(1)
{
err = gpio_write(gpio_drv, pin, GPIO_PIN_STATE_HIGH);
if (err != TEGRABL_NO_ERROR) {
	pr_error("%s: Failed to write GPIO pin: %d\n", __func__, pin);
	TEGRABL_SET_HIGHEST_MODULE(err);
	return err;
}
tegrabl_mdelay(1000);

err = gpio_write(gpio_drv, pin, GPIO_PIN_STATE_LOW);
if (err != TEGRABL_NO_ERROR) {
	pr_error("%s: Failed to write GPIO pin: %d\n", __func__, pin);
	TEGRABL_SET_HIGHEST_MODULE(err);
	return err;
}
     tegrabl_mdelay(1000);
}

Please Let me know. If I am missing anything. Do I need to make any changes to device tree ??

Best Regards,
Prasanna

you may check below for reference, #define TEGRA_MAIN_GPIO_PORT_BB 21
its GPIO number should be 21*8+0 = 168.
thanks

please check post #25 for corrections.

Hi Jerry,

Thanks for input. I changed the pin to 168. And tested the same. Still I am not able to control the i/o.

Below is the some of the Logs I have taken :
[0002.294] I> gpio_validation: check pin in Cboot = 168
[0002.294] I> tegrabl_gpio_config: gpio_num = 168, mode = 1, id = 0xa0667508
[0002.300] I> is_gpio_valid: bank = 21, bank_Max = 28

[0002.305] I> tegrabl_gpio_write: gpio_num = 168, state = 1, id = 0xa0667508
[0002.312] I> is_gpio_valid: bank = 21, bank_Max = 28
[0003.317] I> tegrabl_gpio_write: gpio_num = 168, state = 0, id = 0xa0667508
[0003.317] I> is_gpio_valid: bank = 21, bank_Max = 28
[0003.318] I> tegrabl_gpio_write: gpio_num = 168, state = 1, id = 0xa0667508
[0003.318] I> is_gpio_valid: bank = 21, bank_Max = 28
[0004.319] I> tegrabl_gpio_write: gpio_num = 168, state = 0, id = 0xa0667508
[0004.319] I> is_gpio_valid: bank = 21, bank_Max = 28

I have added, Above mentioned snippet in “tegrabl_gpio.c” and I am calling my function from “platform.c”.
Any device tree change is required. ?

Thanks,
Prasanna

hello prasanna,

it looks there’s no failures, how do you determine your GPIO did not toggling as per your codes.

Hi Jerry,

We need to use #define TEGRA194_AON_GPIO_PORT_BB 1 only. After making the pin num as 8. and configured as an input and tried to read the status of i/o it is working. But still as a output I am not able to toggle the i/o. I am using oscilloscope to probe the signals to check the i/o toggle.

[0124.506] I> is_gpio_valid: bank = 1, bank_Max = 5
[0125.007] I> grl_gpio_validation: Pin Read Value = 0 — Pin-16 connected to GND
[0125.007] I> is_gpio_valid: bank = 1, bank_Max = 5
[0125.507] I> grl_gpio_validation: Pin Read Value = 1 — Pin-16 connected to 3.3V

And I confirmed the respective GPIO is a part of A-ON not from MAIN GPIO Controller
gpiochip1: GPIOs 248-287, parent: platform/c2f0000.gpio, tegra-gpio-aon:
gpio-253 ( |pex-refclk-sel-low ) out lo
gpio-256 ( |sysfs ) out hi
gpio-284 ( |power-key ) in hi

And as per Wayne comment from the link “GPIO numbering - mapping to sysfs GPIO for JETSON XAVIER - #4 by WayneWWW” Need to refer tegra194-gpio.h for xavier and tegra186-gpio.h for TX2.
Correct me If I am wrong.

After changing the pin num to 8 and as input. I am able to get the status of the i/o. But as a output. I am not able to control. And the HW is working fine. I verified from user space application.

Thanks,
Prasanna

it’s correct that you should refer to tegra194-gpio.h for Xavier’s GPIO definition.
i.e. #define TEGRA194_AON_GPIO_PORT_BB 1

you may check kernel messages for the AON-GPIO allocation range, it’s starting from 248.
i.e. [ 0.882955] gpiochip_setup_dev: registered GPIOs 248 to 287 on device: gpiochip1 (tegra-gpio-aon)

so,
let me correct my previous comments, this pin GPIO3_PBB.00, GPIO number = 1*8+248 = 256.

Yes. Based on that kernel log messages and I derived the respective GPIO number as 256 and keeping 256 able to control the i/o in user space application and as well kernel modules.

But in case of Cboot. I need to use below formula to calculate the GPIO Pin number. Correct ?
(port*8)+pin = (1 * 8) + 0 = 8. With Pin num as 8. and GPIO as input is working. But as output not working. for using the i/o in cboot as output any other changes required. Please let us know.

Thanks,
Prasanna

hello prasanna,

since the default pin direction of GPIO3_PBB.00 is input.
you may also have MB1 configurations to update the pin direction as output.
you may review your board configuration file to have confirmation,
for example,

tegra19x-mb1-pinmux-p2888-0000-a04-p2822-0000-b01.cfg
...
pinmux.0x0c303040 = 0x0000c054; # can1_stb_pbb0: rsvd0, pull-down, tristate-enable, input-enable

here’s documentation, Jetson Xavier NX and Jetson AGX Xavier Series MB1 Platform Configuration show the steps to customize the Jetson Xavier devices’ pinmux configuration file.
thanks