[PATCH v7 4/6] pinctrl: Add RTL8231 pin control and GPIO support

Sander Vanheule posted 6 patches 2 weeks ago
There is a newer version of this series
[PATCH v7 4/6] pinctrl: Add RTL8231 pin control and GPIO support
Posted by Sander Vanheule 2 weeks ago
This driver implements the GPIO and pin muxing features provided by the
RTL8231. The device should be instantiated as an MFD child, where the
parent device has already configured the regmap used for register
access.

Debouncing is only available for the six highest GPIOs, and must be
emulated when other pins are used for (button) inputs. Although
described in the bindings, drive strength selection is currently not
implemented.

Signed-off-by: Sander Vanheule <sander@svanheule.net>
Reviewed-by: Linus Walleij <linus.walleij@linaro.org>
---
Changes since v6:
- Use uintptr_t storage for enum rtl8231_pin_function
- Simplify safe direction configuration
- Add GPIOLIB dependency
- Add Linus's review tag
---
 drivers/pinctrl/Kconfig           |  12 +
 drivers/pinctrl/Makefile          |   1 +
 drivers/pinctrl/pinctrl-rtl8231.c | 533 ++++++++++++++++++++++++++++++
 3 files changed, 546 insertions(+)
 create mode 100644 drivers/pinctrl/pinctrl-rtl8231.c

diff --git a/drivers/pinctrl/Kconfig b/drivers/pinctrl/Kconfig
index 4f8507ebbdac..107c59f8aa7d 100644
--- a/drivers/pinctrl/Kconfig
+++ b/drivers/pinctrl/Kconfig
@@ -520,6 +520,18 @@ config PINCTRL_ROCKCHIP
 	help
           This support pinctrl and GPIO driver for Rockchip SoCs.
 
+config PINCTRL_RTL8231
+	tristate "Realtek RTL8231 GPIO expander's pin controller"
+	depends on MFD_RTL8231
+	default MFD_RTL8231
+	select GENERIC_PINCONF
+	select GENERIC_PINMUX_FUNCTIONS
+	select GPIOLIB
+	select GPIO_REGMAP
+	help
+	  Support for RTL8231 expander's GPIOs and pin controller.
+	  When built as a module, the module will be called pinctrl-rtl8231.
+
 config PINCTRL_SCMI
 	tristate "Pinctrl driver using SCMI protocol interface"
 	depends on ARM_SCMI_PROTOCOL || COMPILE_TEST
diff --git a/drivers/pinctrl/Makefile b/drivers/pinctrl/Makefile
index e0cfb9b7c99b..ded51723d452 100644
--- a/drivers/pinctrl/Makefile
+++ b/drivers/pinctrl/Makefile
@@ -52,6 +52,7 @@ obj-$(CONFIG_PINCTRL_PISTACHIO)	+= pinctrl-pistachio.o
 obj-$(CONFIG_PINCTRL_RK805)	+= pinctrl-rk805.o
 obj-$(CONFIG_PINCTRL_ROCKCHIP)	+= pinctrl-rockchip.o
 obj-$(CONFIG_PINCTRL_RP1)       += pinctrl-rp1.o
+obj-$(CONFIG_PINCTRL_RTL8231)	+= pinctrl-rtl8231.o
 obj-$(CONFIG_PINCTRL_SCMI)	+= pinctrl-scmi.o
 obj-$(CONFIG_PINCTRL_SINGLE)	+= pinctrl-single.o
 obj-$(CONFIG_PINCTRL_ST) 	+= pinctrl-st.o
diff --git a/drivers/pinctrl/pinctrl-rtl8231.c b/drivers/pinctrl/pinctrl-rtl8231.c
new file mode 100644
index 000000000000..a06cbdbb2018
--- /dev/null
+++ b/drivers/pinctrl/pinctrl-rtl8231.c
@@ -0,0 +1,533 @@
+// SPDX-License-Identifier: GPL-2.0-only
+
+#include <linux/bitfield.h>
+#include <linux/gpio/driver.h>
+#include <linux/gpio/regmap.h>
+#include <linux/module.h>
+#include <linux/pinctrl/pinconf.h>
+#include <linux/pinctrl/pinctrl.h>
+#include <linux/pinctrl/pinmux.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+
+#include "core.h"
+#include "pinmux.h"
+#include <linux/mfd/rtl8231.h>
+
+#define RTL8231_NUM_GPIOS		37
+#define RTL8231_DEBOUNCE_USEC		100000
+#define RTL8231_DEBOUNCE_MIN_OFFSET	31
+
+struct rtl8231_pin_ctrl {
+	struct regmap *map;
+};
+
+/*
+ * Pin controller functionality
+ */
+enum rtl8231_pin_function : uintptr_t {
+	RTL8231_PIN_FUNCTION_GPIO = BIT(0),
+	RTL8231_PIN_FUNCTION_LED = BIT(1),
+	RTL8231_PIN_FUNCTION_PWM = BIT(2),
+};
+
+struct rtl8231_function_info {
+	enum rtl8231_pin_function flag;
+	const char *name;
+};
+
+#define RTL8231_FUNCTION(_name, _flag)	\
+((struct rtl8231_function_info) {	\
+		.flag = (_flag),	\
+		.name = (_name),	\
+	})
+
+static const struct rtl8231_function_info rtl8231_pin_functions[] = {
+	RTL8231_FUNCTION("gpio", RTL8231_PIN_FUNCTION_GPIO),
+	RTL8231_FUNCTION("led", RTL8231_PIN_FUNCTION_LED),
+	RTL8231_FUNCTION("pwm", RTL8231_PIN_FUNCTION_PWM),
+};
+
+struct rtl8231_pin_desc {
+	enum rtl8231_pin_function functions:8;
+	u8 reg;
+	u8 offset;
+	u8 gpio_function_value;
+};
+
+#define RTL8231_PIN_DESC(_num, _func, _reg, _fld, _val)			\
+	[(_num)] = ((struct rtl8231_pin_desc) {				\
+		.functions = RTL8231_PIN_FUNCTION_GPIO | (_func),	\
+		.reg = (_reg),						\
+		.offset = (_fld),					\
+		.gpio_function_value = (_val),				\
+	})
+#define RTL8231_GPIO_PIN_DESC(_num, _reg, _fld)			\
+	RTL8231_PIN_DESC(_num, 0, _reg, _fld, RTL8231_PIN_MODE_GPIO)
+#define RTL8231_LED_PIN_DESC(_num, _reg, _fld)			\
+	RTL8231_PIN_DESC(_num, RTL8231_PIN_FUNCTION_LED, _reg, _fld, RTL8231_PIN_MODE_GPIO)
+#define RTL8231_PWM_PIN_DESC(_num, _reg, _fld)			\
+	RTL8231_PIN_DESC(_num, RTL8231_PIN_FUNCTION_PWM, _reg, _fld, 0)
+
+/*
+ * All pins have a GPIO/LED mux bit, but the bits for pins 35/36 are read-only. Use this bit
+ * for the GPIO-only pin instead of a placeholder, so the rest of the logic can stay generic.
+ */
+static const struct rtl8231_pin_desc rtl8231_pin_data[RTL8231_NUM_GPIOS] = {
+	RTL8231_LED_PIN_DESC(0, RTL8231_REG_PIN_MODE0, 0),
+	RTL8231_LED_PIN_DESC(1, RTL8231_REG_PIN_MODE0, 1),
+	RTL8231_LED_PIN_DESC(2, RTL8231_REG_PIN_MODE0, 2),
+	RTL8231_LED_PIN_DESC(3, RTL8231_REG_PIN_MODE0, 3),
+	RTL8231_LED_PIN_DESC(4, RTL8231_REG_PIN_MODE0, 4),
+	RTL8231_LED_PIN_DESC(5, RTL8231_REG_PIN_MODE0, 5),
+	RTL8231_LED_PIN_DESC(6, RTL8231_REG_PIN_MODE0, 6),
+	RTL8231_LED_PIN_DESC(7, RTL8231_REG_PIN_MODE0, 7),
+	RTL8231_LED_PIN_DESC(8, RTL8231_REG_PIN_MODE0, 8),
+	RTL8231_LED_PIN_DESC(9, RTL8231_REG_PIN_MODE0, 9),
+	RTL8231_LED_PIN_DESC(10, RTL8231_REG_PIN_MODE0, 10),
+	RTL8231_LED_PIN_DESC(11, RTL8231_REG_PIN_MODE0, 11),
+	RTL8231_LED_PIN_DESC(12, RTL8231_REG_PIN_MODE0, 12),
+	RTL8231_LED_PIN_DESC(13, RTL8231_REG_PIN_MODE0, 13),
+	RTL8231_LED_PIN_DESC(14, RTL8231_REG_PIN_MODE0, 14),
+	RTL8231_LED_PIN_DESC(15, RTL8231_REG_PIN_MODE0, 15),
+	RTL8231_LED_PIN_DESC(16, RTL8231_REG_PIN_MODE1, 0),
+	RTL8231_LED_PIN_DESC(17, RTL8231_REG_PIN_MODE1, 1),
+	RTL8231_LED_PIN_DESC(18, RTL8231_REG_PIN_MODE1, 2),
+	RTL8231_LED_PIN_DESC(19, RTL8231_REG_PIN_MODE1, 3),
+	RTL8231_LED_PIN_DESC(20, RTL8231_REG_PIN_MODE1, 4),
+	RTL8231_LED_PIN_DESC(21, RTL8231_REG_PIN_MODE1, 5),
+	RTL8231_LED_PIN_DESC(22, RTL8231_REG_PIN_MODE1, 6),
+	RTL8231_LED_PIN_DESC(23, RTL8231_REG_PIN_MODE1, 7),
+	RTL8231_LED_PIN_DESC(24, RTL8231_REG_PIN_MODE1, 8),
+	RTL8231_LED_PIN_DESC(25, RTL8231_REG_PIN_MODE1, 9),
+	RTL8231_LED_PIN_DESC(26, RTL8231_REG_PIN_MODE1, 10),
+	RTL8231_LED_PIN_DESC(27, RTL8231_REG_PIN_MODE1, 11),
+	RTL8231_LED_PIN_DESC(28, RTL8231_REG_PIN_MODE1, 12),
+	RTL8231_LED_PIN_DESC(29, RTL8231_REG_PIN_MODE1, 13),
+	RTL8231_LED_PIN_DESC(30, RTL8231_REG_PIN_MODE1, 14),
+	RTL8231_LED_PIN_DESC(31, RTL8231_REG_PIN_MODE1, 15),
+	RTL8231_LED_PIN_DESC(32, RTL8231_REG_PIN_HI_CFG, 0),
+	RTL8231_LED_PIN_DESC(33, RTL8231_REG_PIN_HI_CFG, 1),
+	RTL8231_LED_PIN_DESC(34, RTL8231_REG_PIN_HI_CFG, 2),
+	RTL8231_PWM_PIN_DESC(35, RTL8231_REG_FUNC1, 3),
+	RTL8231_GPIO_PIN_DESC(36, RTL8231_REG_PIN_HI_CFG, 4),
+};
+static const unsigned int PWM_PIN = 35;
+
+#define RTL8231_PIN(_num)					\
+	((struct pinctrl_pin_desc) {				\
+		.number = (_num),				\
+		.name = "gpio" #_num,				\
+		.drv_data = (void *) &rtl8231_pin_data[(_num)]	\
+	})
+
+static const struct pinctrl_pin_desc rtl8231_pins[RTL8231_NUM_GPIOS] = {
+	RTL8231_PIN(0),
+	RTL8231_PIN(1),
+	RTL8231_PIN(2),
+	RTL8231_PIN(3),
+	RTL8231_PIN(4),
+	RTL8231_PIN(5),
+	RTL8231_PIN(6),
+	RTL8231_PIN(7),
+	RTL8231_PIN(8),
+	RTL8231_PIN(9),
+	RTL8231_PIN(10),
+	RTL8231_PIN(11),
+	RTL8231_PIN(12),
+	RTL8231_PIN(13),
+	RTL8231_PIN(14),
+	RTL8231_PIN(15),
+	RTL8231_PIN(16),
+	RTL8231_PIN(17),
+	RTL8231_PIN(18),
+	RTL8231_PIN(19),
+	RTL8231_PIN(20),
+	RTL8231_PIN(21),
+	RTL8231_PIN(22),
+	RTL8231_PIN(23),
+	RTL8231_PIN(24),
+	RTL8231_PIN(25),
+	RTL8231_PIN(26),
+	RTL8231_PIN(27),
+	RTL8231_PIN(28),
+	RTL8231_PIN(29),
+	RTL8231_PIN(30),
+	RTL8231_PIN(31),
+	RTL8231_PIN(32),
+	RTL8231_PIN(33),
+	RTL8231_PIN(34),
+	RTL8231_PIN(35),
+	RTL8231_PIN(36),
+};
+
+static int rtl8231_get_groups_count(struct pinctrl_dev *pctldev)
+{
+	return ARRAY_SIZE(rtl8231_pins);
+}
+
+static const char *rtl8231_get_group_name(struct pinctrl_dev *pctldev, unsigned int selector)
+{
+	return rtl8231_pins[selector].name;
+}
+
+static int rtl8231_get_group_pins(struct pinctrl_dev *pctldev, unsigned int selector,
+	const unsigned int **pins, unsigned int *num_pins)
+{
+	if (selector >= ARRAY_SIZE(rtl8231_pins))
+		return -EINVAL;
+
+	*pins = &rtl8231_pins[selector].number;
+	*num_pins = 1;
+
+	return 0;
+}
+
+static const struct pinctrl_ops rtl8231_pinctrl_ops = {
+	.get_groups_count = rtl8231_get_groups_count,
+	.get_group_name = rtl8231_get_group_name,
+	.get_group_pins = rtl8231_get_group_pins,
+	.dt_node_to_map = pinconf_generic_dt_node_to_map_all,
+	.dt_free_map = pinconf_generic_dt_free_map,
+};
+
+static int rtl8231_set_mux(struct pinctrl_dev *pctldev, unsigned int func_selector,
+	unsigned int group_selector)
+{
+	const struct function_desc *func = pinmux_generic_get_function(pctldev, func_selector);
+	const struct rtl8231_pin_desc *desc = rtl8231_pins[group_selector].drv_data;
+	const struct rtl8231_pin_ctrl *ctrl = pinctrl_dev_get_drvdata(pctldev);
+	enum rtl8231_pin_function func_flag = (uintptr_t) func->data;
+	unsigned int function_mask;
+	unsigned int gpio_function;
+
+	if (!(desc->functions & func_flag))
+		return -EINVAL;
+
+	function_mask = BIT(desc->offset);
+	gpio_function = desc->gpio_function_value << desc->offset;
+
+	if (func_flag == RTL8231_PIN_FUNCTION_GPIO)
+		return regmap_update_bits(ctrl->map, desc->reg, function_mask, gpio_function);
+	else
+		return regmap_update_bits(ctrl->map, desc->reg, function_mask, ~gpio_function);
+}
+
+static int rtl8231_gpio_request_enable(struct pinctrl_dev *pctldev,
+	struct pinctrl_gpio_range *range, unsigned int offset)
+{
+	const struct rtl8231_pin_desc *desc = rtl8231_pins[offset].drv_data;
+	const struct rtl8231_pin_ctrl *ctrl = pinctrl_dev_get_drvdata(pctldev);
+	unsigned int function_mask;
+	unsigned int gpio_function;
+
+	function_mask = BIT(desc->offset);
+	gpio_function = desc->gpio_function_value << desc->offset;
+
+	return regmap_update_bits(ctrl->map, desc->reg, function_mask, gpio_function);
+}
+
+static const struct pinmux_ops rtl8231_pinmux_ops = {
+	.get_functions_count = pinmux_generic_get_function_count,
+	.get_function_name = pinmux_generic_get_function_name,
+	.get_function_groups = pinmux_generic_get_function_groups,
+	.function_is_gpio = pinmux_generic_function_is_gpio,
+	.set_mux = rtl8231_set_mux,
+	.gpio_request_enable = rtl8231_gpio_request_enable,
+	.strict = true,
+};
+
+static int rtl8231_pin_config_get(struct pinctrl_dev *pctldev, unsigned int offset,
+	unsigned long *config)
+{
+	const struct rtl8231_pin_ctrl *ctrl = pinctrl_dev_get_drvdata(pctldev);
+	unsigned int param = pinconf_to_config_param(*config);
+	unsigned int arg;
+	int err;
+	int v;
+
+	switch (param) {
+	case PIN_CONFIG_INPUT_DEBOUNCE:
+		if (offset < RTL8231_DEBOUNCE_MIN_OFFSET)
+			return -EINVAL;
+
+		err = regmap_read(ctrl->map, RTL8231_REG_FUNC1, &v);
+		if (err)
+			return err;
+
+		v = FIELD_GET(RTL8231_FUNC1_DEBOUNCE_MASK, v);
+		if (v & BIT(offset - RTL8231_DEBOUNCE_MIN_OFFSET))
+			arg = RTL8231_DEBOUNCE_USEC;
+		else
+			arg = 0;
+		break;
+	default:
+		return -ENOTSUPP;
+	}
+
+	*config = pinconf_to_config_packed(param, arg);
+
+	return 0;
+}
+
+static int rtl8231_pin_config_set(struct pinctrl_dev *pctldev, unsigned int offset,
+	unsigned long *configs, unsigned int num_configs)
+{
+	const struct rtl8231_pin_ctrl *ctrl = pinctrl_dev_get_drvdata(pctldev);
+	unsigned int param, arg;
+	unsigned int pin_mask;
+	int err;
+	int i;
+
+	for (i = 0; i < num_configs; i++) {
+		param = pinconf_to_config_param(configs[i]);
+		arg = pinconf_to_config_argument(configs[i]);
+
+		switch (param) {
+		case PIN_CONFIG_INPUT_DEBOUNCE:
+			if (offset < RTL8231_DEBOUNCE_MIN_OFFSET)
+				return -EINVAL;
+
+			pin_mask = FIELD_PREP(RTL8231_FUNC1_DEBOUNCE_MASK,
+				BIT(offset - RTL8231_DEBOUNCE_MIN_OFFSET));
+
+			switch (arg) {
+			case 0:
+				err = regmap_update_bits(ctrl->map, RTL8231_REG_FUNC1,
+					pin_mask, 0);
+				break;
+			case RTL8231_DEBOUNCE_USEC:
+				err = regmap_update_bits(ctrl->map, RTL8231_REG_FUNC1,
+					pin_mask, pin_mask);
+				break;
+			default:
+				return -EINVAL;
+			}
+
+			break;
+		default:
+			return -ENOTSUPP;
+		}
+	}
+
+	return err;
+}
+
+static const struct pinconf_ops rtl8231_pinconf_ops = {
+	.is_generic = true,
+	.pin_config_get = rtl8231_pin_config_get,
+	.pin_config_set = rtl8231_pin_config_set,
+};
+
+static int rtl8231_pinctrl_init_functions(struct pinctrl_dev *pctl,
+	const struct pinctrl_desc *pctl_desc)
+{
+	enum rtl8231_pin_function flag;
+	struct pinfunction func;
+	const char **groups;
+	unsigned int f_idx;
+	const char *name;
+	unsigned int pin;
+	int num_groups;
+	int err;
+
+	for (f_idx = 0; f_idx < ARRAY_SIZE(rtl8231_pin_functions); f_idx++) {
+		name = rtl8231_pin_functions[f_idx].name;
+		flag = rtl8231_pin_functions[f_idx].flag;
+
+		for (pin = 0, num_groups = 0; pin < pctl_desc->npins; pin++)
+			if (rtl8231_pin_data[pin].functions & flag)
+				num_groups++;
+
+		groups = devm_kcalloc(pctl->dev, num_groups, sizeof(*groups), GFP_KERNEL);
+		if (!groups)
+			return -ENOMEM;
+
+		for (pin = 0, num_groups = 0; pin < pctl_desc->npins; pin++)
+			if (rtl8231_pin_data[pin].functions & flag)
+				groups[num_groups++] = rtl8231_pins[pin].name;
+
+		func = PINCTRL_PINFUNCTION(name, groups, num_groups);
+		if (flag == RTL8231_PIN_FUNCTION_GPIO)
+			func.flags |= PINFUNCTION_FLAG_GPIO;
+
+		err = pinmux_generic_add_pinfunction(pctl, &func, (void *) flag);
+		if (err < 0)
+			return err;
+	}
+
+	return 0;
+}
+
+struct pin_field_info {
+	const struct reg_field gpio_dir;
+	const struct reg_field mode;
+};
+
+static const struct pin_field_info pin_fields[] = {
+	{
+		.gpio_dir = REG_FIELD(RTL8231_REG_GPIO_DIR0, 0, 15),
+		.mode = REG_FIELD(RTL8231_REG_PIN_MODE0, 0, 15),
+	},
+	{
+		.gpio_dir = REG_FIELD(RTL8231_REG_GPIO_DIR1, 0, 15),
+		.mode = REG_FIELD(RTL8231_REG_PIN_MODE1, 0, 15),
+	},
+	{
+		.gpio_dir = REG_FIELD(RTL8231_REG_PIN_HI_CFG, 5, 9),
+		.mode = REG_FIELD(RTL8231_REG_PIN_HI_CFG, 0, 4),
+	},
+};
+
+static int rtl8231_configure_safe(struct device *dev, struct regmap *map)
+{
+	struct regmap_field *field_mode;
+	struct regmap_field *field_dir;
+	unsigned int is_input;
+	unsigned int is_gpio;
+	int err;
+
+	for (unsigned int i = 0; i < ARRAY_SIZE(pin_fields); i++) {
+		field_dir = devm_regmap_field_alloc(dev, map, pin_fields[i].gpio_dir);
+		if (IS_ERR(field_dir))
+			return PTR_ERR(field_dir);
+
+		field_mode = devm_regmap_field_alloc(dev, map, pin_fields[i].mode);
+		if (IS_ERR(field_mode))
+			return PTR_ERR(field_mode);
+
+		err = regmap_field_read(field_dir, &is_input);
+		if (err)
+			return err;
+
+		err = regmap_field_read(field_mode, &is_gpio);
+		if (err)
+			return err;
+
+		/* Enable field for PWM (on GPIO35) is in another register */
+		if (pin_fields[i].mode.reg == RTL8231_REG_PIN_HI_CFG) {
+			err = regmap_test_bits(map, rtl8231_pin_data[PWM_PIN].reg,
+					BIT(rtl8231_pin_data[PWM_PIN].offset));
+			if (err < 0)
+				return err;
+
+			if (err)
+				is_gpio &= ~BIT(PWM_PIN % RTL8231_BITS_VAL);
+		}
+
+		/*
+		 * Set every pin that is not muxed as a GPIO to gpio-in. That
+		 * way the pin will be high impedance when it is muxed to GPIO,
+		 * preventing unwanted glitches.
+		 * The pin muxes are left as-is, so there are no signal changes.
+		 */
+		regmap_field_write(field_dir, is_input | ~is_gpio);
+
+		devm_regmap_field_free(dev, field_dir);
+		devm_regmap_field_free(dev, field_mode);
+	}
+
+	return 0;
+}
+
+static const struct pinctrl_desc rtl8231_pctl_desc = {
+	.name = "rtl8231-pinctrl",
+	.owner = THIS_MODULE,
+	.confops = &rtl8231_pinconf_ops,
+	.pctlops = &rtl8231_pinctrl_ops,
+	.pmxops = &rtl8231_pinmux_ops,
+	.npins = ARRAY_SIZE(rtl8231_pins),
+	.pins = rtl8231_pins,
+};
+
+static int rtl8231_pinctrl_init(struct device *dev, struct rtl8231_pin_ctrl *ctrl)
+{
+	struct pinctrl_dev *pctldev;
+	int err;
+
+	err = devm_pinctrl_register_and_init(dev->parent, &rtl8231_pctl_desc, ctrl, &pctldev);
+	if (err) {
+		dev_err(dev, "failed to register pin controller\n");
+		return err;
+	}
+
+	err = rtl8231_pinctrl_init_functions(pctldev, &rtl8231_pctl_desc);
+	if (err)
+		return err;
+
+	err = pinctrl_enable(pctldev);
+	if (err)
+		dev_err(dev, "failed to enable pin controller\n");
+
+	return err;
+}
+
+/*
+ * GPIO controller functionality
+ */
+static int rtl8231_gpio_reg_mask_xlate(struct gpio_regmap *gpio, unsigned int base,
+	unsigned int offset, unsigned int *reg, unsigned int *mask)
+{
+	unsigned int pin_mask = BIT(offset % RTL8231_BITS_VAL);
+
+	if (base == RTL8231_REG_GPIO_DATA0 || offset < 32) {
+		*reg = base + offset / RTL8231_BITS_VAL;
+		*mask = pin_mask;
+	} else if (base == RTL8231_REG_GPIO_DIR0) {
+		*reg = RTL8231_REG_PIN_HI_CFG;
+		*mask = FIELD_PREP(RTL8231_PIN_HI_CFG_DIR_MASK, pin_mask);
+	} else {
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int rtl8231_pinctrl_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct rtl8231_pin_ctrl *ctrl;
+	struct gpio_regmap_config gpio_cfg = {};
+	int err;
+
+	ctrl = devm_kzalloc(dev, sizeof(*ctrl), GFP_KERNEL);
+	if (!ctrl)
+		return -ENOMEM;
+
+	ctrl->map = dev_get_regmap(dev->parent, NULL);
+	if (!ctrl->map)
+		return -ENODEV;
+
+	err = rtl8231_configure_safe(dev, ctrl->map);
+	if (err)
+		return err;
+
+	err = rtl8231_pinctrl_init(dev, ctrl);
+	if (err)
+		return err;
+
+	gpio_cfg.regmap = ctrl->map;
+	gpio_cfg.parent = dev->parent;
+	gpio_cfg.ngpio = RTL8231_NUM_GPIOS;
+	gpio_cfg.ngpio_per_reg = RTL8231_BITS_VAL;
+
+	gpio_cfg.reg_dat_base = GPIO_REGMAP_ADDR(RTL8231_REG_GPIO_DATA0);
+	gpio_cfg.reg_set_base = GPIO_REGMAP_ADDR(RTL8231_REG_GPIO_DATA0);
+	gpio_cfg.reg_dir_in_base = GPIO_REGMAP_ADDR(RTL8231_REG_GPIO_DIR0);
+
+	gpio_cfg.reg_mask_xlate = rtl8231_gpio_reg_mask_xlate;
+
+	return PTR_ERR_OR_ZERO(devm_gpio_regmap_register(dev, &gpio_cfg));
+}
+
+static struct platform_driver rtl8231_pinctrl_driver = {
+	.driver = {
+		.name = "rtl8231-pinctrl",
+	},
+	.probe = rtl8231_pinctrl_probe,
+};
+module_platform_driver(rtl8231_pinctrl_driver);
+
+MODULE_AUTHOR("Sander Vanheule <sander@svanheule.net>");
+MODULE_DESCRIPTION("Realtek RTL8231 pin control and GPIO support");
+MODULE_LICENSE("GPL");
-- 
2.51.1
Re: [PATCH v7 4/6] pinctrl: Add RTL8231 pin control and GPIO support
Posted by kernel test robot 1 week, 5 days ago
Hi Sander,

kernel test robot noticed the following build errors:

[auto build test ERROR on lee-mfd/for-mfd-next]
[also build test ERROR on lee-mfd/for-mfd-fixes lee-leds/for-leds-next linusw-pinctrl/devel linusw-pinctrl/for-next linus/master v6.18-rc6 next-20251119]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]

url:    https://github.com/intel-lab-lkp/linux/commits/Sander-Vanheule/dt-bindings-leds-Binding-for-RTL8231-scan-matrix/20251118-055707
base:   https://git.kernel.org/pub/scm/linux/kernel/git/lee/mfd.git for-mfd-next
patch link:    https://lore.kernel.org/r/20251117215138.4353-5-sander%40svanheule.net
patch subject: [PATCH v7 4/6] pinctrl: Add RTL8231 pin control and GPIO support
config: x86_64-randconfig-122-20251119 (https://download.01.org/0day-ci/archive/20251120/202511200318.xcfHOO5R-lkp@intel.com/config)
compiler: gcc-14 (Debian 14.2.0-19) 14.2.0
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20251120/202511200318.xcfHOO5R-lkp@intel.com/reproduce)

If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202511200318.xcfHOO5R-lkp@intel.com/

All errors (new ones prefixed by >>):

   ld: drivers/pinctrl/pinctrl-rtl8231.o: in function `pinconf_generic_dt_node_to_map_all':
   include/linux/pinctrl/pinconf-generic.h:235:(.text+0x6e4): undefined reference to `pinconf_generic_dt_node_to_map'
>> ld: drivers/pinctrl/pinctrl-rtl8231.o:(.rodata+0x248): undefined reference to `pinconf_generic_dt_free_map'

-- 
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki
Re: [PATCH v7 4/6] pinctrl: Add RTL8231 pin control and GPIO support
Posted by kernel test robot 1 week, 5 days ago
Hi Sander,

kernel test robot noticed the following build warnings:

[auto build test WARNING on lee-mfd/for-mfd-next]
[also build test WARNING on lee-mfd/for-mfd-fixes lee-leds/for-leds-next linusw-pinctrl/devel linusw-pinctrl/for-next linus/master v6.18-rc6 next-20251118]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]

url:    https://github.com/intel-lab-lkp/linux/commits/Sander-Vanheule/dt-bindings-leds-Binding-for-RTL8231-scan-matrix/20251118-055707
base:   https://git.kernel.org/pub/scm/linux/kernel/git/lee/mfd.git for-mfd-next
patch link:    https://lore.kernel.org/r/20251117215138.4353-5-sander%40svanheule.net
patch subject: [PATCH v7 4/6] pinctrl: Add RTL8231 pin control and GPIO support
config: i386-randconfig-063-20251119 (https://download.01.org/0day-ci/archive/20251119/202511191158.bVKUDrKa-lkp@intel.com/config)
compiler: gcc-14 (Debian 14.2.0-19) 14.2.0
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20251119/202511191158.bVKUDrKa-lkp@intel.com/reproduce)

If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202511191158.bVKUDrKa-lkp@intel.com/

sparse warnings: (new ones prefixed by >>)
>> drivers/pinctrl/pinctrl-rtl8231.c:28:27: sparse: sparse: missing identifier in declaration
   drivers/pinctrl/pinctrl-rtl8231.c:28:27: sparse: sparse: Expected ; at the end of type declaration
   drivers/pinctrl/pinctrl-rtl8231.c:28:27: sparse: sparse: got :
>> drivers/pinctrl/pinctrl-rtl8231.c:52:44: sparse: sparse: invalid bitfield specifier for type incomplete type enum rtl8231_pin_function.
   drivers/pinctrl/pinctrl-rtl8231.c:46:9: sparse: sparse: undefined identifier 'RTL8231_PIN_FUNCTION_GPIO'
   drivers/pinctrl/pinctrl-rtl8231.c:47:9: sparse: sparse: undefined identifier 'RTL8231_PIN_FUNCTION_LED'
   drivers/pinctrl/pinctrl-rtl8231.c:48:9: sparse: sparse: undefined identifier 'RTL8231_PIN_FUNCTION_PWM'
   drivers/pinctrl/pinctrl-rtl8231.c:77:9: sparse: sparse: undefined identifier 'RTL8231_PIN_FUNCTION_GPIO'
   drivers/pinctrl/pinctrl-rtl8231.c:77:9: sparse: sparse: undefined identifier 'RTL8231_PIN_FUNCTION_LED'
   drivers/pinctrl/pinctrl-rtl8231.c:78:9: sparse: sparse: undefined identifier 'RTL8231_PIN_FUNCTION_GPIO'
   drivers/pinctrl/pinctrl-rtl8231.c:78:9: sparse: sparse: undefined identifier 'RTL8231_PIN_FUNCTION_LED'
   drivers/pinctrl/pinctrl-rtl8231.c:79:9: sparse: sparse: undefined identifier 'RTL8231_PIN_FUNCTION_GPIO'
   drivers/pinctrl/pinctrl-rtl8231.c:79:9: sparse: sparse: undefined identifier 'RTL8231_PIN_FUNCTION_LED'
   drivers/pinctrl/pinctrl-rtl8231.c:80:9: sparse: sparse: undefined identifier 'RTL8231_PIN_FUNCTION_GPIO'
   drivers/pinctrl/pinctrl-rtl8231.c:80:9: sparse: sparse: undefined identifier 'RTL8231_PIN_FUNCTION_LED'
   drivers/pinctrl/pinctrl-rtl8231.c:81:9: sparse: sparse: undefined identifier 'RTL8231_PIN_FUNCTION_GPIO'
   drivers/pinctrl/pinctrl-rtl8231.c:81:9: sparse: sparse: undefined identifier 'RTL8231_PIN_FUNCTION_LED'
   drivers/pinctrl/pinctrl-rtl8231.c:82:9: sparse: sparse: undefined identifier 'RTL8231_PIN_FUNCTION_GPIO'
   drivers/pinctrl/pinctrl-rtl8231.c:82:9: sparse: sparse: undefined identifier 'RTL8231_PIN_FUNCTION_LED'
   drivers/pinctrl/pinctrl-rtl8231.c:83:9: sparse: sparse: undefined identifier 'RTL8231_PIN_FUNCTION_GPIO'
   drivers/pinctrl/pinctrl-rtl8231.c:83:9: sparse: sparse: undefined identifier 'RTL8231_PIN_FUNCTION_LED'
   drivers/pinctrl/pinctrl-rtl8231.c:84:9: sparse: sparse: undefined identifier 'RTL8231_PIN_FUNCTION_GPIO'
   drivers/pinctrl/pinctrl-rtl8231.c:84:9: sparse: sparse: undefined identifier 'RTL8231_PIN_FUNCTION_LED'
   drivers/pinctrl/pinctrl-rtl8231.c:85:9: sparse: sparse: undefined identifier 'RTL8231_PIN_FUNCTION_GPIO'
   drivers/pinctrl/pinctrl-rtl8231.c:85:9: sparse: sparse: undefined identifier 'RTL8231_PIN_FUNCTION_LED'
   drivers/pinctrl/pinctrl-rtl8231.c:86:9: sparse: sparse: undefined identifier 'RTL8231_PIN_FUNCTION_GPIO'
   drivers/pinctrl/pinctrl-rtl8231.c:86:9: sparse: sparse: undefined identifier 'RTL8231_PIN_FUNCTION_LED'
   drivers/pinctrl/pinctrl-rtl8231.c:87:9: sparse: sparse: undefined identifier 'RTL8231_PIN_FUNCTION_GPIO'
   drivers/pinctrl/pinctrl-rtl8231.c:87:9: sparse: sparse: undefined identifier 'RTL8231_PIN_FUNCTION_LED'
   drivers/pinctrl/pinctrl-rtl8231.c:88:9: sparse: sparse: undefined identifier 'RTL8231_PIN_FUNCTION_GPIO'
   drivers/pinctrl/pinctrl-rtl8231.c:88:9: sparse: sparse: undefined identifier 'RTL8231_PIN_FUNCTION_LED'
   drivers/pinctrl/pinctrl-rtl8231.c:89:9: sparse: sparse: undefined identifier 'RTL8231_PIN_FUNCTION_GPIO'
   drivers/pinctrl/pinctrl-rtl8231.c:89:9: sparse: sparse: undefined identifier 'RTL8231_PIN_FUNCTION_LED'
   drivers/pinctrl/pinctrl-rtl8231.c:90:9: sparse: sparse: undefined identifier 'RTL8231_PIN_FUNCTION_GPIO'
   drivers/pinctrl/pinctrl-rtl8231.c:90:9: sparse: sparse: undefined identifier 'RTL8231_PIN_FUNCTION_LED'
   drivers/pinctrl/pinctrl-rtl8231.c:91:9: sparse: sparse: undefined identifier 'RTL8231_PIN_FUNCTION_GPIO'
   drivers/pinctrl/pinctrl-rtl8231.c:91:9: sparse: sparse: undefined identifier 'RTL8231_PIN_FUNCTION_LED'
   drivers/pinctrl/pinctrl-rtl8231.c:92:9: sparse: sparse: undefined identifier 'RTL8231_PIN_FUNCTION_GPIO'
   drivers/pinctrl/pinctrl-rtl8231.c:92:9: sparse: sparse: undefined identifier 'RTL8231_PIN_FUNCTION_LED'
   drivers/pinctrl/pinctrl-rtl8231.c:93:9: sparse: sparse: undefined identifier 'RTL8231_PIN_FUNCTION_GPIO'
   drivers/pinctrl/pinctrl-rtl8231.c:93:9: sparse: sparse: undefined identifier 'RTL8231_PIN_FUNCTION_LED'
   drivers/pinctrl/pinctrl-rtl8231.c:94:9: sparse: sparse: undefined identifier 'RTL8231_PIN_FUNCTION_GPIO'
   drivers/pinctrl/pinctrl-rtl8231.c:94:9: sparse: sparse: undefined identifier 'RTL8231_PIN_FUNCTION_LED'
   drivers/pinctrl/pinctrl-rtl8231.c:95:9: sparse: sparse: undefined identifier 'RTL8231_PIN_FUNCTION_GPIO'
   drivers/pinctrl/pinctrl-rtl8231.c:95:9: sparse: sparse: undefined identifier 'RTL8231_PIN_FUNCTION_LED'
   drivers/pinctrl/pinctrl-rtl8231.c:96:9: sparse: sparse: undefined identifier 'RTL8231_PIN_FUNCTION_GPIO'
   drivers/pinctrl/pinctrl-rtl8231.c:96:9: sparse: sparse: undefined identifier 'RTL8231_PIN_FUNCTION_LED'
   drivers/pinctrl/pinctrl-rtl8231.c:97:9: sparse: sparse: undefined identifier 'RTL8231_PIN_FUNCTION_GPIO'
   drivers/pinctrl/pinctrl-rtl8231.c:97:9: sparse: sparse: undefined identifier 'RTL8231_PIN_FUNCTION_LED'
   drivers/pinctrl/pinctrl-rtl8231.c:98:9: sparse: sparse: undefined identifier 'RTL8231_PIN_FUNCTION_GPIO'
   drivers/pinctrl/pinctrl-rtl8231.c:98:9: sparse: sparse: undefined identifier 'RTL8231_PIN_FUNCTION_LED'
   drivers/pinctrl/pinctrl-rtl8231.c:99:9: sparse: sparse: undefined identifier 'RTL8231_PIN_FUNCTION_GPIO'
   drivers/pinctrl/pinctrl-rtl8231.c:99:9: sparse: sparse: undefined identifier 'RTL8231_PIN_FUNCTION_LED'
   drivers/pinctrl/pinctrl-rtl8231.c:100:9: sparse: sparse: undefined identifier 'RTL8231_PIN_FUNCTION_GPIO'
   drivers/pinctrl/pinctrl-rtl8231.c:100:9: sparse: sparse: undefined identifier 'RTL8231_PIN_FUNCTION_LED'
   drivers/pinctrl/pinctrl-rtl8231.c:101:9: sparse: sparse: undefined identifier 'RTL8231_PIN_FUNCTION_GPIO'
   drivers/pinctrl/pinctrl-rtl8231.c:101:9: sparse: sparse: undefined identifier 'RTL8231_PIN_FUNCTION_LED'
   drivers/pinctrl/pinctrl-rtl8231.c:102:9: sparse: sparse: undefined identifier 'RTL8231_PIN_FUNCTION_GPIO'
   drivers/pinctrl/pinctrl-rtl8231.c:102:9: sparse: sparse: undefined identifier 'RTL8231_PIN_FUNCTION_LED'
   drivers/pinctrl/pinctrl-rtl8231.c:103:9: sparse: sparse: undefined identifier 'RTL8231_PIN_FUNCTION_GPIO'
   drivers/pinctrl/pinctrl-rtl8231.c:103:9: sparse: sparse: undefined identifier 'RTL8231_PIN_FUNCTION_LED'
   drivers/pinctrl/pinctrl-rtl8231.c:104:9: sparse: sparse: undefined identifier 'RTL8231_PIN_FUNCTION_GPIO'
   drivers/pinctrl/pinctrl-rtl8231.c:104:9: sparse: sparse: undefined identifier 'RTL8231_PIN_FUNCTION_LED'
   drivers/pinctrl/pinctrl-rtl8231.c:105:9: sparse: sparse: undefined identifier 'RTL8231_PIN_FUNCTION_GPIO'
   drivers/pinctrl/pinctrl-rtl8231.c:105:9: sparse: sparse: undefined identifier 'RTL8231_PIN_FUNCTION_LED'
   drivers/pinctrl/pinctrl-rtl8231.c:106:9: sparse: sparse: undefined identifier 'RTL8231_PIN_FUNCTION_GPIO'
   drivers/pinctrl/pinctrl-rtl8231.c:106:9: sparse: sparse: undefined identifier 'RTL8231_PIN_FUNCTION_LED'
   drivers/pinctrl/pinctrl-rtl8231.c:107:9: sparse: sparse: undefined identifier 'RTL8231_PIN_FUNCTION_GPIO'
   drivers/pinctrl/pinctrl-rtl8231.c:107:9: sparse: sparse: undefined identifier 'RTL8231_PIN_FUNCTION_LED'
   drivers/pinctrl/pinctrl-rtl8231.c:108:9: sparse: sparse: undefined identifier 'RTL8231_PIN_FUNCTION_GPIO'
   drivers/pinctrl/pinctrl-rtl8231.c:108:9: sparse: sparse: undefined identifier 'RTL8231_PIN_FUNCTION_LED'
   drivers/pinctrl/pinctrl-rtl8231.c:109:9: sparse: sparse: undefined identifier 'RTL8231_PIN_FUNCTION_GPIO'
   drivers/pinctrl/pinctrl-rtl8231.c:109:9: sparse: sparse: undefined identifier 'RTL8231_PIN_FUNCTION_LED'
   drivers/pinctrl/pinctrl-rtl8231.c:110:9: sparse: sparse: undefined identifier 'RTL8231_PIN_FUNCTION_GPIO'
   drivers/pinctrl/pinctrl-rtl8231.c:110:9: sparse: sparse: undefined identifier 'RTL8231_PIN_FUNCTION_LED'
   drivers/pinctrl/pinctrl-rtl8231.c:111:9: sparse: sparse: undefined identifier 'RTL8231_PIN_FUNCTION_GPIO'
   drivers/pinctrl/pinctrl-rtl8231.c:111:9: sparse: sparse: undefined identifier 'RTL8231_PIN_FUNCTION_LED'
   drivers/pinctrl/pinctrl-rtl8231.c:112:9: sparse: sparse: undefined identifier 'RTL8231_PIN_FUNCTION_GPIO'
   drivers/pinctrl/pinctrl-rtl8231.c:112:9: sparse: sparse: undefined identifier 'RTL8231_PIN_FUNCTION_PWM'
   drivers/pinctrl/pinctrl-rtl8231.c:113:9: sparse: sparse: undefined identifier 'RTL8231_PIN_FUNCTION_GPIO'
>> drivers/pinctrl/pinctrl-rtl8231.c:204:31: sparse: sparse: incompatible types for operation (&):
   drivers/pinctrl/pinctrl-rtl8231.c:204:31: sparse:    incomplete type enum rtl8231_pin_function const functions
   drivers/pinctrl/pinctrl-rtl8231.c:204:31: sparse:    incomplete type enum rtl8231_pin_function func_flag
   drivers/pinctrl/pinctrl-rtl8231.c:210:26: sparse: sparse: undefined identifier 'RTL8231_PIN_FUNCTION_GPIO'
   drivers/pinctrl/pinctrl-rtl8231.c:339:61: sparse: sparse: incompatible types for operation (&):
   drivers/pinctrl/pinctrl-rtl8231.c:339:61: sparse:    incomplete type enum rtl8231_pin_function const functions
   drivers/pinctrl/pinctrl-rtl8231.c:339:61: sparse:    incomplete type enum rtl8231_pin_function flag
   drivers/pinctrl/pinctrl-rtl8231.c:347:61: sparse: sparse: incompatible types for operation (&):
   drivers/pinctrl/pinctrl-rtl8231.c:347:61: sparse:    incomplete type enum rtl8231_pin_function const functions
   drivers/pinctrl/pinctrl-rtl8231.c:347:61: sparse:    incomplete type enum rtl8231_pin_function flag
   drivers/pinctrl/pinctrl-rtl8231.c:351:29: sparse: sparse: undefined identifier 'RTL8231_PIN_FUNCTION_GPIO'

vim +28 drivers/pinctrl/pinctrl-rtl8231.c

    24	
    25	/*
    26	 * Pin controller functionality
    27	 */
  > 28	enum rtl8231_pin_function : uintptr_t {
    29		RTL8231_PIN_FUNCTION_GPIO = BIT(0),
    30		RTL8231_PIN_FUNCTION_LED = BIT(1),
    31		RTL8231_PIN_FUNCTION_PWM = BIT(2),
    32	};
    33	
    34	struct rtl8231_function_info {
    35		enum rtl8231_pin_function flag;
    36		const char *name;
    37	};
    38	
    39	#define RTL8231_FUNCTION(_name, _flag)	\
    40	((struct rtl8231_function_info) {	\
    41			.flag = (_flag),	\
    42			.name = (_name),	\
    43		})
    44	
    45	static const struct rtl8231_function_info rtl8231_pin_functions[] = {
    46		RTL8231_FUNCTION("gpio", RTL8231_PIN_FUNCTION_GPIO),
    47		RTL8231_FUNCTION("led", RTL8231_PIN_FUNCTION_LED),
    48		RTL8231_FUNCTION("pwm", RTL8231_PIN_FUNCTION_PWM),
    49	};
    50	
    51	struct rtl8231_pin_desc {
  > 52		enum rtl8231_pin_function functions:8;
    53		u8 reg;
    54		u8 offset;
    55		u8 gpio_function_value;
    56	};
    57	
    58	#define RTL8231_PIN_DESC(_num, _func, _reg, _fld, _val)			\
    59		[(_num)] = ((struct rtl8231_pin_desc) {				\
    60			.functions = RTL8231_PIN_FUNCTION_GPIO | (_func),	\
    61			.reg = (_reg),						\
    62			.offset = (_fld),					\
    63			.gpio_function_value = (_val),				\
    64		})
    65	#define RTL8231_GPIO_PIN_DESC(_num, _reg, _fld)			\
    66		RTL8231_PIN_DESC(_num, 0, _reg, _fld, RTL8231_PIN_MODE_GPIO)
    67	#define RTL8231_LED_PIN_DESC(_num, _reg, _fld)			\
    68		RTL8231_PIN_DESC(_num, RTL8231_PIN_FUNCTION_LED, _reg, _fld, RTL8231_PIN_MODE_GPIO)
    69	#define RTL8231_PWM_PIN_DESC(_num, _reg, _fld)			\
    70		RTL8231_PIN_DESC(_num, RTL8231_PIN_FUNCTION_PWM, _reg, _fld, 0)
    71	
    72	/*
    73	 * All pins have a GPIO/LED mux bit, but the bits for pins 35/36 are read-only. Use this bit
    74	 * for the GPIO-only pin instead of a placeholder, so the rest of the logic can stay generic.
    75	 */
    76	static const struct rtl8231_pin_desc rtl8231_pin_data[RTL8231_NUM_GPIOS] = {
    77		RTL8231_LED_PIN_DESC(0, RTL8231_REG_PIN_MODE0, 0),
    78		RTL8231_LED_PIN_DESC(1, RTL8231_REG_PIN_MODE0, 1),
    79		RTL8231_LED_PIN_DESC(2, RTL8231_REG_PIN_MODE0, 2),
    80		RTL8231_LED_PIN_DESC(3, RTL8231_REG_PIN_MODE0, 3),
    81		RTL8231_LED_PIN_DESC(4, RTL8231_REG_PIN_MODE0, 4),
    82		RTL8231_LED_PIN_DESC(5, RTL8231_REG_PIN_MODE0, 5),
    83		RTL8231_LED_PIN_DESC(6, RTL8231_REG_PIN_MODE0, 6),
    84		RTL8231_LED_PIN_DESC(7, RTL8231_REG_PIN_MODE0, 7),
    85		RTL8231_LED_PIN_DESC(8, RTL8231_REG_PIN_MODE0, 8),
    86		RTL8231_LED_PIN_DESC(9, RTL8231_REG_PIN_MODE0, 9),
    87		RTL8231_LED_PIN_DESC(10, RTL8231_REG_PIN_MODE0, 10),
    88		RTL8231_LED_PIN_DESC(11, RTL8231_REG_PIN_MODE0, 11),
    89		RTL8231_LED_PIN_DESC(12, RTL8231_REG_PIN_MODE0, 12),
    90		RTL8231_LED_PIN_DESC(13, RTL8231_REG_PIN_MODE0, 13),
    91		RTL8231_LED_PIN_DESC(14, RTL8231_REG_PIN_MODE0, 14),
    92		RTL8231_LED_PIN_DESC(15, RTL8231_REG_PIN_MODE0, 15),
    93		RTL8231_LED_PIN_DESC(16, RTL8231_REG_PIN_MODE1, 0),
    94		RTL8231_LED_PIN_DESC(17, RTL8231_REG_PIN_MODE1, 1),
    95		RTL8231_LED_PIN_DESC(18, RTL8231_REG_PIN_MODE1, 2),
    96		RTL8231_LED_PIN_DESC(19, RTL8231_REG_PIN_MODE1, 3),
    97		RTL8231_LED_PIN_DESC(20, RTL8231_REG_PIN_MODE1, 4),
    98		RTL8231_LED_PIN_DESC(21, RTL8231_REG_PIN_MODE1, 5),
    99		RTL8231_LED_PIN_DESC(22, RTL8231_REG_PIN_MODE1, 6),
   100		RTL8231_LED_PIN_DESC(23, RTL8231_REG_PIN_MODE1, 7),
   101		RTL8231_LED_PIN_DESC(24, RTL8231_REG_PIN_MODE1, 8),
   102		RTL8231_LED_PIN_DESC(25, RTL8231_REG_PIN_MODE1, 9),
   103		RTL8231_LED_PIN_DESC(26, RTL8231_REG_PIN_MODE1, 10),
   104		RTL8231_LED_PIN_DESC(27, RTL8231_REG_PIN_MODE1, 11),
   105		RTL8231_LED_PIN_DESC(28, RTL8231_REG_PIN_MODE1, 12),
   106		RTL8231_LED_PIN_DESC(29, RTL8231_REG_PIN_MODE1, 13),
   107		RTL8231_LED_PIN_DESC(30, RTL8231_REG_PIN_MODE1, 14),
   108		RTL8231_LED_PIN_DESC(31, RTL8231_REG_PIN_MODE1, 15),
   109		RTL8231_LED_PIN_DESC(32, RTL8231_REG_PIN_HI_CFG, 0),
   110		RTL8231_LED_PIN_DESC(33, RTL8231_REG_PIN_HI_CFG, 1),
   111		RTL8231_LED_PIN_DESC(34, RTL8231_REG_PIN_HI_CFG, 2),
   112		RTL8231_PWM_PIN_DESC(35, RTL8231_REG_FUNC1, 3),
   113		RTL8231_GPIO_PIN_DESC(36, RTL8231_REG_PIN_HI_CFG, 4),
   114	};
   115	static const unsigned int PWM_PIN = 35;
   116	
   117	#define RTL8231_PIN(_num)					\
   118		((struct pinctrl_pin_desc) {				\
   119			.number = (_num),				\
   120			.name = "gpio" #_num,				\
   121			.drv_data = (void *) &rtl8231_pin_data[(_num)]	\
   122		})
   123	
   124	static const struct pinctrl_pin_desc rtl8231_pins[RTL8231_NUM_GPIOS] = {
   125		RTL8231_PIN(0),
   126		RTL8231_PIN(1),
   127		RTL8231_PIN(2),
   128		RTL8231_PIN(3),
   129		RTL8231_PIN(4),
   130		RTL8231_PIN(5),
   131		RTL8231_PIN(6),
   132		RTL8231_PIN(7),
   133		RTL8231_PIN(8),
   134		RTL8231_PIN(9),
   135		RTL8231_PIN(10),
   136		RTL8231_PIN(11),
   137		RTL8231_PIN(12),
   138		RTL8231_PIN(13),
   139		RTL8231_PIN(14),
   140		RTL8231_PIN(15),
   141		RTL8231_PIN(16),
   142		RTL8231_PIN(17),
   143		RTL8231_PIN(18),
   144		RTL8231_PIN(19),
   145		RTL8231_PIN(20),
   146		RTL8231_PIN(21),
   147		RTL8231_PIN(22),
   148		RTL8231_PIN(23),
   149		RTL8231_PIN(24),
   150		RTL8231_PIN(25),
   151		RTL8231_PIN(26),
   152		RTL8231_PIN(27),
   153		RTL8231_PIN(28),
   154		RTL8231_PIN(29),
   155		RTL8231_PIN(30),
   156		RTL8231_PIN(31),
   157		RTL8231_PIN(32),
   158		RTL8231_PIN(33),
   159		RTL8231_PIN(34),
   160		RTL8231_PIN(35),
   161		RTL8231_PIN(36),
   162	};
   163	
   164	static int rtl8231_get_groups_count(struct pinctrl_dev *pctldev)
   165	{
   166		return ARRAY_SIZE(rtl8231_pins);
   167	}
   168	
   169	static const char *rtl8231_get_group_name(struct pinctrl_dev *pctldev, unsigned int selector)
   170	{
   171		return rtl8231_pins[selector].name;
   172	}
   173	
   174	static int rtl8231_get_group_pins(struct pinctrl_dev *pctldev, unsigned int selector,
   175		const unsigned int **pins, unsigned int *num_pins)
   176	{
   177		if (selector >= ARRAY_SIZE(rtl8231_pins))
   178			return -EINVAL;
   179	
   180		*pins = &rtl8231_pins[selector].number;
   181		*num_pins = 1;
   182	
   183		return 0;
   184	}
   185	
   186	static const struct pinctrl_ops rtl8231_pinctrl_ops = {
   187		.get_groups_count = rtl8231_get_groups_count,
   188		.get_group_name = rtl8231_get_group_name,
   189		.get_group_pins = rtl8231_get_group_pins,
   190		.dt_node_to_map = pinconf_generic_dt_node_to_map_all,
   191		.dt_free_map = pinconf_generic_dt_free_map,
   192	};
   193	
   194	static int rtl8231_set_mux(struct pinctrl_dev *pctldev, unsigned int func_selector,
   195		unsigned int group_selector)
   196	{
   197		const struct function_desc *func = pinmux_generic_get_function(pctldev, func_selector);
   198		const struct rtl8231_pin_desc *desc = rtl8231_pins[group_selector].drv_data;
   199		const struct rtl8231_pin_ctrl *ctrl = pinctrl_dev_get_drvdata(pctldev);
   200		enum rtl8231_pin_function func_flag = (uintptr_t) func->data;
   201		unsigned int function_mask;
   202		unsigned int gpio_function;
   203	
 > 204		if (!(desc->functions & func_flag))
   205			return -EINVAL;
   206	
   207		function_mask = BIT(desc->offset);
   208		gpio_function = desc->gpio_function_value << desc->offset;
   209	
   210		if (func_flag == RTL8231_PIN_FUNCTION_GPIO)
   211			return regmap_update_bits(ctrl->map, desc->reg, function_mask, gpio_function);
   212		else
   213			return regmap_update_bits(ctrl->map, desc->reg, function_mask, ~gpio_function);
   214	}
   215	

-- 
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki
Re: [PATCH v7 4/6] pinctrl: Add RTL8231 pin control and GPIO support
Posted by Sander Vanheule 1 week, 5 days ago
On Wed, 2025-11-19 at 12:19 +0800, kernel test robot wrote:
> Hi Sander,
> 
> kernel test robot noticed the following build warnings:
> 
> [auto build test WARNING on lee-mfd/for-mfd-next]
> [also build test WARNING on lee-mfd/for-mfd-fixes lee-leds/for-leds-next linusw-
> pinctrl/devel linusw-pinctrl/for-next linus/master v6.18-rc6 next-20251118]
> [If your patch is applied to the wrong git tree, kindly drop us a note.
> And when submitting patch, we suggest to use '--base' as documented in
> https://git-scm.com/docs/git-format-patch#_base_tree_information]
> 
> url:   
> https://github.com/intel-lab-lkp/linux/commits/Sander-Vanheule/dt-bindings-leds-Binding-for-RTL8231-scan-matrix/20251118-055707
> base:   https://git.kernel.org/pub/scm/linux/kernel/git/lee/mfd.git for-mfd-next
> patch link:    https://lore.kernel.org/r/20251117215138.4353-5-sander%40svanheule.net
> patch subject: [PATCH v7 4/6] pinctrl: Add RTL8231 pin control and GPIO support
> config: i386-randconfig-063-20251119
> (https://download.01.org/0day-ci/archive/20251119/202511191158.bVKUDrKa-lkp@intel.com/co
> nfig)
> compiler: gcc-14 (Debian 14.2.0-19) 14.2.0
> reproduce (this is a W=1 build):
> (https://download.01.org/0day-ci/archive/20251119/202511191158.bVKUDrKa-lkp@intel.com/re
> produce)
> 
> If you fix the issue in a separate patch/commit (i.e. not just a new version of
> the same patch/commit), kindly add following tags
> > Reported-by: kernel test robot <lkp@intel.com>
> > Closes: https://lore.kernel.org/oe-kbuild-all/202511191158.bVKUDrKa-lkp@intel.com/
> 
> sparse warnings: (new ones prefixed by >>)
> > > drivers/pinctrl/pinctrl-rtl8231.c:28:27: sparse: sparse: missing identifier in
> > > declaration
>    drivers/pinctrl/pinctrl-rtl8231.c:28:27: sparse: sparse: Expected ; at the end of
> type declaration
>    drivers/pinctrl/pinctrl-rtl8231.c:28:27: sparse: sparse: got :
> > > drivers/pinctrl/pinctrl-rtl8231.c:52:44: sparse: sparse: invalid bitfield specifier
> > > for type incomplete type enum rtl8231_pin_function.


sparse doesn't seem to understand the enum type specifier either. Fixed by instead casting
rtl8231_pin_function where a uintptr_t is required.

Best,
Sander
Re: [PATCH v7 4/6] pinctrl: Add RTL8231 pin control and GPIO support
Posted by kernel test robot 1 week, 6 days ago
Hi Sander,

kernel test robot noticed the following build errors:

[auto build test ERROR on lee-mfd/for-mfd-next]
[also build test ERROR on lee-mfd/for-mfd-fixes lee-leds/for-leds-next linusw-pinctrl/devel linusw-pinctrl/for-next linus/master v6.18-rc6 next-20251118]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]

url:    https://github.com/intel-lab-lkp/linux/commits/Sander-Vanheule/dt-bindings-leds-Binding-for-RTL8231-scan-matrix/20251118-055707
base:   https://git.kernel.org/pub/scm/linux/kernel/git/lee/mfd.git for-mfd-next
patch link:    https://lore.kernel.org/r/20251117215138.4353-5-sander%40svanheule.net
patch subject: [PATCH v7 4/6] pinctrl: Add RTL8231 pin control and GPIO support
config: nios2-allmodconfig (https://download.01.org/0day-ci/archive/20251119/202511190436.9oQLbI8A-lkp@intel.com/config)
compiler: nios2-linux-gcc (GCC) 11.5.0
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20251119/202511190436.9oQLbI8A-lkp@intel.com/reproduce)

If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202511190436.9oQLbI8A-lkp@intel.com/

All error/warnings (new ones prefixed by >>):

>> drivers/pinctrl/pinctrl-rtl8231.c:28:27: error: expected identifier or '(' before ':' token
      28 | enum rtl8231_pin_function : uintptr_t {
         |                           ^
>> drivers/pinctrl/pinctrl-rtl8231.c:35:35: error: field 'flag' has incomplete type
      35 |         enum rtl8231_pin_function flag;
         |                                   ^~~~
>> drivers/pinctrl/pinctrl-rtl8231.c:46:34: error: 'RTL8231_PIN_FUNCTION_GPIO' undeclared here (not in a function); did you mean 'RTL8231_PIN_MODE_GPIO'?
      46 |         RTL8231_FUNCTION("gpio", RTL8231_PIN_FUNCTION_GPIO),
         |                                  ^~~~~~~~~~~~~~~~~~~~~~~~~
   drivers/pinctrl/pinctrl-rtl8231.c:41:26: note: in definition of macro 'RTL8231_FUNCTION'
      41 |                 .flag = (_flag),        \
         |                          ^~~~~
>> drivers/pinctrl/pinctrl-rtl8231.c:47:33: error: 'RTL8231_PIN_FUNCTION_LED' undeclared here (not in a function); did you mean 'RTL8231_FUNCTION'?
      47 |         RTL8231_FUNCTION("led", RTL8231_PIN_FUNCTION_LED),
         |                                 ^~~~~~~~~~~~~~~~~~~~~~~~
   drivers/pinctrl/pinctrl-rtl8231.c:41:26: note: in definition of macro 'RTL8231_FUNCTION'
      41 |                 .flag = (_flag),        \
         |                          ^~~~~
>> drivers/pinctrl/pinctrl-rtl8231.c:48:33: error: 'RTL8231_PIN_FUNCTION_PWM' undeclared here (not in a function); did you mean 'RTL8231_FUNCTION'?
      48 |         RTL8231_FUNCTION("pwm", RTL8231_PIN_FUNCTION_PWM),
         |                                 ^~~~~~~~~~~~~~~~~~~~~~~~
   drivers/pinctrl/pinctrl-rtl8231.c:41:26: note: in definition of macro 'RTL8231_FUNCTION'
      41 |                 .flag = (_flag),        \
         |                          ^~~~~
>> drivers/pinctrl/pinctrl-rtl8231.c:52:35: warning: 'functions' is narrower than values of its type
      52 |         enum rtl8231_pin_function functions:8;
         |                                   ^~~~~~~~~
>> drivers/pinctrl/pinctrl-rtl8231.c:52:35: error: field 'functions' has incomplete type
   drivers/pinctrl/pinctrl-rtl8231.c: In function 'rtl8231_set_mux':
>> drivers/pinctrl/pinctrl-rtl8231.c:200:14: error: variable 'func_flag' has initializer but incomplete type
     200 |         enum rtl8231_pin_function func_flag = (uintptr_t) func->data;
         |              ^~~~~~~~~~~~~~~~~~~~
>> drivers/pinctrl/pinctrl-rtl8231.c:200:35: error: storage size of 'func_flag' isn't known
     200 |         enum rtl8231_pin_function func_flag = (uintptr_t) func->data;
         |                                   ^~~~~~~~~
>> drivers/pinctrl/pinctrl-rtl8231.c:200:35: warning: unused variable 'func_flag' [-Wunused-variable]
   drivers/pinctrl/pinctrl-rtl8231.c: In function 'rtl8231_pinctrl_init_functions':
>> drivers/pinctrl/pinctrl-rtl8231.c:325:35: error: storage size of 'flag' isn't known
     325 |         enum rtl8231_pin_function flag;
         |                                   ^~~~
>> drivers/pinctrl/pinctrl-rtl8231.c:325:35: warning: unused variable 'flag' [-Wunused-variable]
   drivers/pinctrl/pinctrl-rtl8231.c: In function 'rtl8231_set_mux':
>> drivers/pinctrl/pinctrl-rtl8231.c:214:1: warning: control reaches end of non-void function [-Wreturn-type]
     214 | }
         | ^


vim +28 drivers/pinctrl/pinctrl-rtl8231.c

    24	
    25	/*
    26	 * Pin controller functionality
    27	 */
  > 28	enum rtl8231_pin_function : uintptr_t {
    29		RTL8231_PIN_FUNCTION_GPIO = BIT(0),
    30		RTL8231_PIN_FUNCTION_LED = BIT(1),
    31		RTL8231_PIN_FUNCTION_PWM = BIT(2),
    32	};
    33	
    34	struct rtl8231_function_info {
  > 35		enum rtl8231_pin_function flag;
    36		const char *name;
    37	};
    38	
    39	#define RTL8231_FUNCTION(_name, _flag)	\
    40	((struct rtl8231_function_info) {	\
    41			.flag = (_flag),	\
    42			.name = (_name),	\
    43		})
    44	
    45	static const struct rtl8231_function_info rtl8231_pin_functions[] = {
  > 46		RTL8231_FUNCTION("gpio", RTL8231_PIN_FUNCTION_GPIO),
  > 47		RTL8231_FUNCTION("led", RTL8231_PIN_FUNCTION_LED),
  > 48		RTL8231_FUNCTION("pwm", RTL8231_PIN_FUNCTION_PWM),
    49	};
    50	
    51	struct rtl8231_pin_desc {
  > 52		enum rtl8231_pin_function functions:8;
    53		u8 reg;
    54		u8 offset;
    55		u8 gpio_function_value;
    56	};
    57	
    58	#define RTL8231_PIN_DESC(_num, _func, _reg, _fld, _val)			\
    59		[(_num)] = ((struct rtl8231_pin_desc) {				\
    60			.functions = RTL8231_PIN_FUNCTION_GPIO | (_func),	\
    61			.reg = (_reg),						\
    62			.offset = (_fld),					\
    63			.gpio_function_value = (_val),				\
    64		})
    65	#define RTL8231_GPIO_PIN_DESC(_num, _reg, _fld)			\
    66		RTL8231_PIN_DESC(_num, 0, _reg, _fld, RTL8231_PIN_MODE_GPIO)
    67	#define RTL8231_LED_PIN_DESC(_num, _reg, _fld)			\
    68		RTL8231_PIN_DESC(_num, RTL8231_PIN_FUNCTION_LED, _reg, _fld, RTL8231_PIN_MODE_GPIO)
    69	#define RTL8231_PWM_PIN_DESC(_num, _reg, _fld)			\
    70		RTL8231_PIN_DESC(_num, RTL8231_PIN_FUNCTION_PWM, _reg, _fld, 0)
    71	
    72	/*
    73	 * All pins have a GPIO/LED mux bit, but the bits for pins 35/36 are read-only. Use this bit
    74	 * for the GPIO-only pin instead of a placeholder, so the rest of the logic can stay generic.
    75	 */
    76	static const struct rtl8231_pin_desc rtl8231_pin_data[RTL8231_NUM_GPIOS] = {
    77		RTL8231_LED_PIN_DESC(0, RTL8231_REG_PIN_MODE0, 0),
    78		RTL8231_LED_PIN_DESC(1, RTL8231_REG_PIN_MODE0, 1),
    79		RTL8231_LED_PIN_DESC(2, RTL8231_REG_PIN_MODE0, 2),
    80		RTL8231_LED_PIN_DESC(3, RTL8231_REG_PIN_MODE0, 3),
    81		RTL8231_LED_PIN_DESC(4, RTL8231_REG_PIN_MODE0, 4),
    82		RTL8231_LED_PIN_DESC(5, RTL8231_REG_PIN_MODE0, 5),
    83		RTL8231_LED_PIN_DESC(6, RTL8231_REG_PIN_MODE0, 6),
    84		RTL8231_LED_PIN_DESC(7, RTL8231_REG_PIN_MODE0, 7),
    85		RTL8231_LED_PIN_DESC(8, RTL8231_REG_PIN_MODE0, 8),
    86		RTL8231_LED_PIN_DESC(9, RTL8231_REG_PIN_MODE0, 9),
    87		RTL8231_LED_PIN_DESC(10, RTL8231_REG_PIN_MODE0, 10),
    88		RTL8231_LED_PIN_DESC(11, RTL8231_REG_PIN_MODE0, 11),
    89		RTL8231_LED_PIN_DESC(12, RTL8231_REG_PIN_MODE0, 12),
    90		RTL8231_LED_PIN_DESC(13, RTL8231_REG_PIN_MODE0, 13),
    91		RTL8231_LED_PIN_DESC(14, RTL8231_REG_PIN_MODE0, 14),
    92		RTL8231_LED_PIN_DESC(15, RTL8231_REG_PIN_MODE0, 15),
    93		RTL8231_LED_PIN_DESC(16, RTL8231_REG_PIN_MODE1, 0),
    94		RTL8231_LED_PIN_DESC(17, RTL8231_REG_PIN_MODE1, 1),
    95		RTL8231_LED_PIN_DESC(18, RTL8231_REG_PIN_MODE1, 2),
    96		RTL8231_LED_PIN_DESC(19, RTL8231_REG_PIN_MODE1, 3),
    97		RTL8231_LED_PIN_DESC(20, RTL8231_REG_PIN_MODE1, 4),
    98		RTL8231_LED_PIN_DESC(21, RTL8231_REG_PIN_MODE1, 5),
    99		RTL8231_LED_PIN_DESC(22, RTL8231_REG_PIN_MODE1, 6),
   100		RTL8231_LED_PIN_DESC(23, RTL8231_REG_PIN_MODE1, 7),
   101		RTL8231_LED_PIN_DESC(24, RTL8231_REG_PIN_MODE1, 8),
   102		RTL8231_LED_PIN_DESC(25, RTL8231_REG_PIN_MODE1, 9),
   103		RTL8231_LED_PIN_DESC(26, RTL8231_REG_PIN_MODE1, 10),
   104		RTL8231_LED_PIN_DESC(27, RTL8231_REG_PIN_MODE1, 11),
   105		RTL8231_LED_PIN_DESC(28, RTL8231_REG_PIN_MODE1, 12),
   106		RTL8231_LED_PIN_DESC(29, RTL8231_REG_PIN_MODE1, 13),
   107		RTL8231_LED_PIN_DESC(30, RTL8231_REG_PIN_MODE1, 14),
   108		RTL8231_LED_PIN_DESC(31, RTL8231_REG_PIN_MODE1, 15),
   109		RTL8231_LED_PIN_DESC(32, RTL8231_REG_PIN_HI_CFG, 0),
   110		RTL8231_LED_PIN_DESC(33, RTL8231_REG_PIN_HI_CFG, 1),
   111		RTL8231_LED_PIN_DESC(34, RTL8231_REG_PIN_HI_CFG, 2),
   112		RTL8231_PWM_PIN_DESC(35, RTL8231_REG_FUNC1, 3),
   113		RTL8231_GPIO_PIN_DESC(36, RTL8231_REG_PIN_HI_CFG, 4),
   114	};
   115	static const unsigned int PWM_PIN = 35;
   116	
   117	#define RTL8231_PIN(_num)					\
   118		((struct pinctrl_pin_desc) {				\
   119			.number = (_num),				\
   120			.name = "gpio" #_num,				\
   121			.drv_data = (void *) &rtl8231_pin_data[(_num)]	\
   122		})
   123	
   124	static const struct pinctrl_pin_desc rtl8231_pins[RTL8231_NUM_GPIOS] = {
   125		RTL8231_PIN(0),
   126		RTL8231_PIN(1),
   127		RTL8231_PIN(2),
   128		RTL8231_PIN(3),
   129		RTL8231_PIN(4),
   130		RTL8231_PIN(5),
   131		RTL8231_PIN(6),
   132		RTL8231_PIN(7),
   133		RTL8231_PIN(8),
   134		RTL8231_PIN(9),
   135		RTL8231_PIN(10),
   136		RTL8231_PIN(11),
   137		RTL8231_PIN(12),
   138		RTL8231_PIN(13),
   139		RTL8231_PIN(14),
   140		RTL8231_PIN(15),
   141		RTL8231_PIN(16),
   142		RTL8231_PIN(17),
   143		RTL8231_PIN(18),
   144		RTL8231_PIN(19),
   145		RTL8231_PIN(20),
   146		RTL8231_PIN(21),
   147		RTL8231_PIN(22),
   148		RTL8231_PIN(23),
   149		RTL8231_PIN(24),
   150		RTL8231_PIN(25),
   151		RTL8231_PIN(26),
   152		RTL8231_PIN(27),
   153		RTL8231_PIN(28),
   154		RTL8231_PIN(29),
   155		RTL8231_PIN(30),
   156		RTL8231_PIN(31),
   157		RTL8231_PIN(32),
   158		RTL8231_PIN(33),
   159		RTL8231_PIN(34),
   160		RTL8231_PIN(35),
   161		RTL8231_PIN(36),
   162	};
   163	
   164	static int rtl8231_get_groups_count(struct pinctrl_dev *pctldev)
   165	{
   166		return ARRAY_SIZE(rtl8231_pins);
   167	}
   168	
   169	static const char *rtl8231_get_group_name(struct pinctrl_dev *pctldev, unsigned int selector)
   170	{
   171		return rtl8231_pins[selector].name;
   172	}
   173	
   174	static int rtl8231_get_group_pins(struct pinctrl_dev *pctldev, unsigned int selector,
   175		const unsigned int **pins, unsigned int *num_pins)
   176	{
   177		if (selector >= ARRAY_SIZE(rtl8231_pins))
   178			return -EINVAL;
   179	
   180		*pins = &rtl8231_pins[selector].number;
   181		*num_pins = 1;
   182	
   183		return 0;
   184	}
   185	
   186	static const struct pinctrl_ops rtl8231_pinctrl_ops = {
   187		.get_groups_count = rtl8231_get_groups_count,
   188		.get_group_name = rtl8231_get_group_name,
   189		.get_group_pins = rtl8231_get_group_pins,
   190		.dt_node_to_map = pinconf_generic_dt_node_to_map_all,
   191		.dt_free_map = pinconf_generic_dt_free_map,
   192	};
   193	
   194	static int rtl8231_set_mux(struct pinctrl_dev *pctldev, unsigned int func_selector,
   195		unsigned int group_selector)
   196	{
   197		const struct function_desc *func = pinmux_generic_get_function(pctldev, func_selector);
   198		const struct rtl8231_pin_desc *desc = rtl8231_pins[group_selector].drv_data;
   199		const struct rtl8231_pin_ctrl *ctrl = pinctrl_dev_get_drvdata(pctldev);
 > 200		enum rtl8231_pin_function func_flag = (uintptr_t) func->data;
   201		unsigned int function_mask;
   202		unsigned int gpio_function;
   203	
   204		if (!(desc->functions & func_flag))
   205			return -EINVAL;
   206	
   207		function_mask = BIT(desc->offset);
   208		gpio_function = desc->gpio_function_value << desc->offset;
   209	
   210		if (func_flag == RTL8231_PIN_FUNCTION_GPIO)
   211			return regmap_update_bits(ctrl->map, desc->reg, function_mask, gpio_function);
   212		else
   213			return regmap_update_bits(ctrl->map, desc->reg, function_mask, ~gpio_function);
 > 214	}
   215	

-- 
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki
Re: [PATCH v7 4/6] pinctrl: Add RTL8231 pin control and GPIO support
Posted by Sander Vanheule 1 week, 6 days ago
On Wed, 2025-11-19 at 05:19 +0800, kernel test robot wrote:
> Hi Sander,
> 
> kernel test robot noticed the following build errors:
> 
> [auto build test ERROR on lee-mfd/for-mfd-next]
> [also build test ERROR on lee-mfd/for-mfd-fixes lee-leds/for-leds-next linusw-
> pinctrl/devel linusw-pinctrl/for-next linus/master v6.18-rc6 next-20251118]
> [If your patch is applied to the wrong git tree, kindly drop us a note.
> And when submitting patch, we suggest to use '--base' as documented in
> https://git-scm.com/docs/git-format-patch#_base_tree_information]
> 
> url:   
> https://github.com/intel-lab-lkp/linux/commits/Sander-Vanheule/dt-bindings-leds-Binding-for-RTL8231-scan-matrix/20251118-055707
> base:   https://git.kernel.org/pub/scm/linux/kernel/git/lee/mfd.git for-mfd-next
> patch link:    https://lore.kernel.org/r/20251117215138.4353-5-sander%40svanheule.net
> patch subject: [PATCH v7 4/6] pinctrl: Add RTL8231 pin control and GPIO support
> config: nios2-allmodconfig
> (https://download.01.org/0day-ci/archive/20251119/202511190436.9oQLbI8A-lkp@intel.com/co
> nfig)
> compiler: nios2-linux-gcc (GCC) 11.5.0
> reproduce (this is a W=1 build):
> (https://download.01.org/0day-ci/archive/20251119/202511190436.9oQLbI8A-lkp@intel.com/re
> produce)
> 
> If you fix the issue in a separate patch/commit (i.e. not just a new version of
> the same patch/commit), kindly add following tags
> > Reported-by: kernel test robot <lkp@intel.com>
> > Closes: https://lore.kernel.org/oe-kbuild-all/202511190436.9oQLbI8A-lkp@intel.com/
> 
> All error/warnings (new ones prefixed by >>):
> 
> > > drivers/pinctrl/pinctrl-rtl8231.c:28:27: error: expected identifier or '(' before
> > > ':' token
>       28 | enum rtl8231_pin_function : uintptr_t {
>          |                           ^

This isn't supported yet pre-C23 and before GCC 13. I will look to ensure the a properly
sized integer is stored into the pinfunction's data pointer.

Best,
Sander