FXL6408 driver - enable PULL-UP settings

I’m working with the FXL6408 GPIO expander. I’ve noticed you have two drivers:

Where the former uses regmap.
I need to set the Pull-Up register (0xd) to 0xff so all lanes are up. Ideally, I would do this from application space using GPIO Character Device Userspace API v2 using gpiohandle_request and GPIOHANDLE_REQUEST_BIAS_PULL_UP. However this requires the set_config function pointer to be set on the gpio_chip instance in the kernel driver. What is the best driver to use to do this, i.e. the old one or the new one? And how do you recommend to do this?

Hi, I’m the Toradex AI Assistant. The Toradex Support team will follow up with you shortly!

Did you like my answer?

:+1: :-1:


Hello,

Thank you for reaching out with your question. While specific information about the FXL6408 GPIO expander drivers and their pull-up settings isn’t available in the provided documentation, I can guide you on general GPIO configuration using the recommended tools.

Toradex supports GPIO configuration through the libgpiod interface. The sysfs GPIO interface has been deprecated, and the GPIO Character Device API (libgpiod) is now the preferred method for accessing GPIOs. You can utilize libgpiod’s command-line tools or its C API for GPIO configuration.

If you need more detailed guidance on using libgpiod for general GPIO configuration, please let me know, and I’d be happy to assist further.

Best regards,
Toradex AI Assistant

Hi @pfjf2!

We always recommend using the newer version (either for a kernel or driver), so I would suggest using the latest version.

Regarding how to implement it, you should write an overlay following the example in the kernel documentation. You’ll have to write the FXL6408 node inside an i2c node using the variables mentioned in the documentation, adapted for your use case.

Besides that, you’ll have to use gpio-hog node to configure the pull-up. You can find more about the gpio-hog and examples of it in gpio.txt (on the Linux kernel documentation).

Best regards.
Lucas Azeituno.

I got the old driver working with this patch:

--- gpio-fxl6408_toradex.c	2025-04-30 09:11:27.114399994 +0100
+++ gpio-fxl6408.c	2025-04-30 09:10:47.525653972 +0100
@@ -68,6 +68,7 @@
 	/* Caches of register values so we don't have to read-modify-write. */
 	u8 reg_io_dir;
 	u8 reg_output;
+	u8 reg_pullup;
 };
 
 static int fxl6408_gpio_direction_input(struct gpio_chip *gc, unsigned off)
@@ -148,6 +149,38 @@
 	mutex_unlock(&chip->i2c_lock);
 }
 
+static int fxl6408_gpio_set_config(struct gpio_chip* gc, unsigned int off, unsigned long cfg)
+{
+	struct fxl6408_chip* 	chip 	= gpiochip_get_data(gc);
+	enum pin_config_param	param	= pinconf_to_config_param(cfg);
+
+	int ret;
+
+	mutex_lock(&chip->i2c_lock);
+
+	switch(param) 
+	{
+	case PIN_CONFIG_BIAS_PULL_UP:
+		chip->reg_pullup |= BIT(off);
+		ret = i2c_smbus_write_byte_data(chip->client, FXL6408_PULL_UP, chip->reg_pullup);
+		// dev_info(&chip->client->dev, "FXL6408 setting PULLUP on %u - reg pullup %u - ret %d\n", off, chip->reg_pullup, ret);
+		break;
+	case PIN_CONFIG_BIAS_PULL_DOWN:
+		chip->reg_pullup &= ~BIT(off);
+		ret = i2c_smbus_write_byte_data(chip->client, FXL6408_PULL_UP, chip->reg_pullup);
+		// dev_info(&chip->client->dev, "FXL6408 setting PULLDOWN on %u - reg pullup %u - ret %d\n", off, chip->reg_pullup, ret);
+		break;
+	default:
+		ret = -ENOTSUPP;
+		// dev_info(&chip->client->dev, "FXL6408 unsupported param %d for off %u\n", param, off);
+		break;
+	}
+
+	mutex_unlock(&chip->i2c_lock);
+
+	return ret;
+}
+
 static int fxl6408_probe(struct i2c_client *client,
 			 const struct i2c_device_id *id)
 {
@@ -184,7 +217,7 @@
 	chip->client = client;
 	mutex_init(&chip->i2c_lock);
 
-	/* if configured, set initial output state and direction,
+	/* if configured, set initial output state, direction and pull-up state
 	 * otherwise read them from the chip */
 	if (of_property_read_u32(dev->of_node, "inital_io_dir", &val)) {
 		chip->reg_io_dir = i2c_smbus_read_byte_data(client, FXL6408_IO_DIR);
@@ -198,6 +231,12 @@
 		chip->reg_output = val & 0xff;
 		i2c_smbus_write_byte_data(client, FXL6408_OUTPUT, chip->reg_output);
 	}
+	if (of_property_read_u32(dev->of_node, "inital_pullup", &val)) {
+		chip->reg_pullup = i2c_smbus_read_byte_data(client, FXL6408_PULL_UP);
+	} else {
+		chip->reg_pullup = val & 0xff;
+		i2c_smbus_write_byte_data(client, FXL6408_PULL_UP, chip->reg_pullup);
+	}
 
 	gc = &chip->gpio_chip;
 	gc->direction_input  = fxl6408_gpio_direction_input;
@@ -206,6 +245,7 @@
 	gc->get = fxl6408_gpio_get_value;
 	gc->set = fxl6408_gpio_set_value;
 	gc->set_multiple = fxl6408_gpio_set_multiple;
+	gc->set_config = fxl6408_gpio_set_config;
 	gc->can_sleep = true;
 
 	gc->base =-1;

Then when using the GPIO API V2 in linux, i can do something like:

struct gpiohandle_request req;
....
req.flag |= GPIOHANDLE_REQUEST_BIAS_PULL_UP;
...
ret = ::ioctl(chip_fd, GPIO_GET_LINEHANDLE_IOCTL, &req);
...

Hi @pfjf2!

Were you able to solve the issue with this patch?
Can I consider this topic solved? If I can, please mark your answer as the solution.

Best regards.
Lucas Azeituno

Yes this resolved it. Would you like me to submit a pull request?

Hi @pfjf2!

We don’t accept patches in this branch anymore, because it is BSP 5 and it is in EOL.

Thanks for sharing it with us.

Best regards.
Lucas Azeituno