How to make gpio high-level in cboot?

Dear,
I do not find a function in cboot code to pull gpio output high level or low, is there any way can help me do this?
whether or not can i change the gpio level through writing gpio regs with some funs? I really need this way.

hello gaozejun,

please access cboot sources via download center.
you’ll need to check Tegra GPIO driver APIs for accessing GPIO pins.
for example,
$L4T_Sources/r32.4.2/Linux_for_Tegra/source/public/cboot/bootloader/partner/common/drivers/gpio/tegrabl_gpio.c

static tegrabl_error_t tegrabl_gpio_read(uint32_t gpio_num, gpio_pin_state_t *state, void *drv_data)
{...}

static tegrabl_error_t tegrabl_gpio_config(uint32_t gpio_num, gpio_pin_mode_t mode, void *drv_data)
{...}

I have seen tegrabl_gpio_read{} and tegrabl_gpio_config,but i want to change gpio levels through writing gpio regs,becasue functions(tegrabl_gpio_read{} and tegrabl_gpio_config) initialization are too late, i need to pull GPIO15 high as soon as possible.

hello gaozejun,

you may access pinmux spreadsheets through download center, please also check the documentation for Pinmux and GPIO Configuration to change the board configurations.
thanks

GPIO17 is a pin for feeding watchdog,i need to change its levels between 1s.So i need a function to writing gpio regs.
if there is no functions to read or write gpio regs ,is there any example to show me how wo can use tegrabl_gpio_read(write/config).

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.