-
Environment
BackgroundWe have an embedded application that controls FPGA enable / reset signals via GPIO. On this SoC the data direction register (PDDR) and the output latch (PDOR) are physically separate registers, so our intuition is that flipping direction should not alter the output latch — when a pin is switched to output, it We use libgpiod v2 to manage the lines. Wrapper functions in our application follow this pattern: /* gpio_open(pad, is_input=false) */
gpiod_line_settings_reset(settings);
gpiod_line_settings_set_direction(settings, GPIOD_LINE_DIRECTION_OUTPUT);
gpiod_line_config_add_line_settings(config, &offset, 1, settings);
req = gpiod_chip_request_lines(chip, req_cfg, config);
/* gpio_set_direction(pad, is_input=false) — caller re-asserts OUTPUT */
gpiod_line_settings_set_direction(settings, GPIOD_LINE_DIRECTION_OUTPUT);
gpiod_line_config_add_line_settings(config, &offset, 1, settings);
gpiod_line_request_reconfigure_lines(req, config);
/* gpio_set_output(pad) — caller wants HIGH */
gpiod_line_request_set_value(req, offset, GPIOD_LINE_VALUE_ACTIVE);
What we observe
Reading the sourceKernel ( if (lflags & GPIO_V2_LINE_FLAG_OUTPUT) {
__set_bit(FLAG_IS_OUT, &desc->flags);
ret = gpiod_direction_output_nonotify(desc, !!output_value);
}The vf610-gpio driver in turn writes PSOR/PCOR before changing direction (direction itself is then applied via iomuxc OBE through static int vf610_gpio_direction_output(struct gpio_chip *chip,
unsigned int gpio, int value)
{
vf610_gpio_set(chip, gpio, value); /* unconditional PSOR/PCOR write */
/* have_paddr is false for vf610, so PDDR is not touched here */
return pinctrl_gpio_direction_output(chip, gpio);
}So on this SoC, a libgpiod-driven Minimal pseudocode reproducerstruct gpiod_chip *chip = gpiod_chip_open("/dev/gpiochip3");
unsigned int offset = 23;
struct gpiod_line_settings *settings = gpiod_line_settings_new();
struct gpiod_line_config *config = gpiod_line_config_new();
struct gpiod_request_config *req_cfg = gpiod_request_config_new();
/* Step 1: request OUTPUT with value HIGH */
gpiod_line_settings_set_direction(settings, GPIOD_LINE_DIRECTION_OUTPUT);
gpiod_line_settings_set_output_value(settings, GPIOD_LINE_VALUE_ACTIVE);
gpiod_line_config_add_line_settings(config, &offset, 1, settings);
struct gpiod_line_request *req =
gpiod_chip_request_lines(chip, req_cfg, config);
/* Expected and observed: line HIGH */
/* Step 2: reconfigure — same direction, no explicit output_value */
gpiod_line_settings_reset(settings);
gpiod_line_settings_set_direction(settings, GPIOD_LINE_DIRECTION_OUTPUT);
gpiod_line_config_add_line_settings(config, &offset, 1, settings);
gpiod_line_request_reconfigure_lines(req, config);
/* Observed: line driven LOW (because output_value defaults to INACTIVE) */(We have not yet built and run this exact sequence as a standalone binary on the target — we plan to. If maintainers prefer, we will publish the standalone reproducer first.) Questions
Thanks for your time. |
Beta Was this translation helpful? Give feedback.
Replies: 1 comment
-
I'm not sure this is a libgpiod problem. It looks more like the behavior of the linux kernel driver is the culprit?
Yes, you have a set of settings in
Not really. When you drive a line, you better know what the value's got to be.
Yes, either keep the value in some local context struct or read it before reconfiguring the line. |
Beta Was this translation helpful? Give feedback.
I'm not sure this is a libgpiod problem. It looks more like the behavior of the linux kernel driver is the culprit?
gpiod_line_request_reconfigure_lines()doesn't write anything to the latch - it just forwards a request to the GPIO core in the kernel which in turns asks the driver to do a bunch of things. The driver may end up writing to the given register but doesn't have to.