diff --git a/drivers/pinctrl/meson/Kconfig b/drivers/pinctrl/meson/Kconfig
index ee820a57a0e0..162642d7289b 100644
--- a/drivers/pinctrl/meson/Kconfig
+++ b/drivers/pinctrl/meson/Kconfig
@@ -2,6 +2,7 @@ if ARCH_MESON
 
 config PINCTRL_MESON
 	select PINCTRL_GENERIC
+	select PINCONF
 	bool
 
 config PINCTRL_MESON_GX_PMX
diff --git a/drivers/pinctrl/meson/pinctrl-meson-axg-pmx.c b/drivers/pinctrl/meson/pinctrl-meson-axg-pmx.c
index c82413d08f34..f9065723eea9 100644
--- a/drivers/pinctrl/meson/pinctrl-meson-axg-pmx.c
+++ b/drivers/pinctrl/meson/pinctrl-meson-axg-pmx.c
@@ -93,6 +93,12 @@ static int meson_axg_pinmux_group_set(struct udevice *dev,
 	return 0;
 }
 
+const struct pinconf_param meson_axg_pinconf_params[] = {
+	{ "bias-disable", PIN_CONFIG_BIAS_DISABLE, 0 },
+	{ "bias-pull-up", PIN_CONFIG_BIAS_PULL_UP, 1 },
+	{ "bias-pull-down", PIN_CONFIG_BIAS_PULL_DOWN, 1 },
+};
+
 const struct pinctrl_ops meson_axg_pinctrl_ops = {
 	.get_groups_count = meson_pinctrl_get_groups_count,
 	.get_group_name = meson_pinctrl_get_group_name,
@@ -100,6 +106,10 @@ const struct pinctrl_ops meson_axg_pinctrl_ops = {
 	.get_function_name = meson_pinmux_get_function_name,
 	.pinmux_group_set = meson_axg_pinmux_group_set,
 	.set_state = pinctrl_generic_set_state,
+	.pinconf_params = meson_axg_pinconf_params
+	.pinconf_num_params = ARRAY_SIZE(meson_axg_pinconf_params),
+	.pinconf_set = meson_pinconf_set,
+	.pinconf_group_set = meson_pinconf_group_set,
 };
 
 static int meson_axg_gpio_request(struct udevice *dev,
diff --git a/drivers/pinctrl/meson/pinctrl-meson-gx-pmx.c b/drivers/pinctrl/meson/pinctrl-meson-gx-pmx.c
index fc1538ea719e..cf72576b6ce2 100644
--- a/drivers/pinctrl/meson/pinctrl-meson-gx-pmx.c
+++ b/drivers/pinctrl/meson/pinctrl-meson-gx-pmx.c
@@ -72,6 +72,12 @@ static int meson_gx_pinmux_group_set(struct udevice *dev,
 	return 0;
 }
 
+const struct pinconf_param meson_gx_pinconf_params[] = {
+	{ "bias-disable", PIN_CONFIG_BIAS_DISABLE, 0 },
+	{ "bias-pull-up", PIN_CONFIG_BIAS_PULL_UP, 1 },
+	{ "bias-pull-down", PIN_CONFIG_BIAS_PULL_DOWN, 1 },
+};
+
 const struct pinctrl_ops meson_gx_pinctrl_ops = {
 	.get_groups_count = meson_pinctrl_get_groups_count,
 	.get_group_name = meson_pinctrl_get_group_name,
@@ -79,6 +85,10 @@ const struct pinctrl_ops meson_gx_pinctrl_ops = {
 	.get_function_name = meson_pinmux_get_function_name,
 	.pinmux_group_set = meson_gx_pinmux_group_set,
 	.set_state = pinctrl_generic_set_state,
+	.pinconf_params = meson_gx_pinconf_params,
+	.pinconf_num_params = ARRAY_SIZE(meson_gx_pinconf_params),
+	.pinconf_set = meson_pinconf_set,
+	.pinconf_group_set = meson_pinconf_group_set,
 };
 
 static const struct dm_gpio_ops meson_gx_gpio_ops = {
diff --git a/drivers/pinctrl/meson/pinctrl-meson.c b/drivers/pinctrl/meson/pinctrl-meson.c
index b539749752c8..fa3d78858a9e 100644
--- a/drivers/pinctrl/meson/pinctrl-meson.c
+++ b/drivers/pinctrl/meson/pinctrl-meson.c
@@ -57,7 +57,7 @@ static int meson_gpio_calc_reg_and_bit(struct udevice *dev, unsigned int offset,
 				       enum meson_reg_type reg_type,
 				       unsigned int *reg, unsigned int *bit)
 {
-	struct meson_pinctrl *priv = dev_get_priv(dev->parent);
+	struct meson_pinctrl *priv = dev_get_priv(dev);
 	struct meson_bank *bank = NULL;
 	struct meson_reg_desc *desc;
 	unsigned int pin;
@@ -89,7 +89,8 @@ int meson_gpio_get(struct udevice *dev, unsigned int offset)
 	unsigned int reg, bit;
 	int ret;
 
-	ret = meson_gpio_calc_reg_and_bit(dev, offset, REG_IN, &reg, &bit);
+	ret = meson_gpio_calc_reg_and_bit(dev->parent, offset, REG_IN, &reg,
+					  &bit);
 	if (ret)
 		return ret;
 
@@ -102,7 +103,8 @@ int meson_gpio_set(struct udevice *dev, unsigned int offset, int value)
 	unsigned int reg, bit;
 	int ret;
 
-	ret = meson_gpio_calc_reg_and_bit(dev, offset, REG_OUT, &reg, &bit);
+	ret = meson_gpio_calc_reg_and_bit(dev->parent, offset, REG_OUT, &reg,
+					  &bit);
 	if (ret)
 		return ret;
 
@@ -117,7 +119,8 @@ int meson_gpio_get_direction(struct udevice *dev, unsigned int offset)
 	unsigned int reg, bit, val;
 	int ret;
 
-	ret = meson_gpio_calc_reg_and_bit(dev, offset, REG_DIR, &reg, &bit);
+	ret = meson_gpio_calc_reg_and_bit(dev->parent, offset, REG_DIR, &reg,
+					  &bit);
 	if (ret)
 		return ret;
 
@@ -132,7 +135,8 @@ int meson_gpio_direction_input(struct udevice *dev, unsigned int offset)
 	unsigned int reg, bit;
 	int ret;
 
-	ret = meson_gpio_calc_reg_and_bit(dev, offset, REG_DIR, &reg, &bit);
+	ret = meson_gpio_calc_reg_and_bit(dev->parent, offset, REG_DIR, &reg,
+					  &bit);
 	if (ret)
 		return ret;
 
@@ -148,13 +152,15 @@ int meson_gpio_direction_output(struct udevice *dev,
 	unsigned int reg, bit;
 	int ret;
 
-	ret = meson_gpio_calc_reg_and_bit(dev, offset, REG_DIR, &reg, &bit);
+	ret = meson_gpio_calc_reg_and_bit(dev->parent, offset, REG_DIR, &reg,
+					  &bit);
 	if (ret)
 		return ret;
 
 	clrbits_le32(priv->reg_gpio + reg, BIT(bit));
 
-	ret = meson_gpio_calc_reg_and_bit(dev, offset, REG_OUT, &reg, &bit);
+	ret = meson_gpio_calc_reg_and_bit(dev->parent, offset, REG_OUT, &reg,
+					  &bit);
 	if (ret)
 		return ret;
 
@@ -163,6 +169,72 @@ int meson_gpio_direction_output(struct udevice *dev,
 	return 0;
 }
 
+static int meson_pinconf_bias_set(struct udevice *dev, unsigned int pin,
+				  unsigned int param)
+{
+	struct meson_pinctrl *priv = dev_get_priv(dev);
+	unsigned int offset = pin - priv->data->pin_base;
+	unsigned int reg, bit;
+	int ret;
+
+	ret = meson_gpio_calc_reg_and_bit(dev, offset, REG_PULLEN, &reg, &bit);
+	if (ret)
+		return ret;
+
+	if (param == PIN_CONFIG_BIAS_DISABLE) {
+		clrsetbits_le32(priv->reg_pullen + reg, BIT(bit), 0);
+		return 0;
+	}
+
+	/* othewise, enable the bias and select level */
+	clrsetbits_le32(priv->reg_pullen + reg, BIT(bit), 1);
+	ret = meson_gpio_calc_reg_and_bit(dev, offset, REG_PULL, &reg, &bit);
+	if (ret)
+		return ret;
+
+	clrsetbits_le32(priv->reg_pull + reg, BIT(bit),
+			param == PIN_CONFIG_BIAS_PULL_UP);
+
+	return 0;
+}
+
+int meson_pinconf_set(struct udevice *dev, unsigned int pin,
+		      unsigned int param, unsigned int arg)
+{
+	int ret;
+
+	switch (param) {
+	case PIN_CONFIG_BIAS_DISABLE:
+	case PIN_CONFIG_BIAS_PULL_UP:
+	case PIN_CONFIG_BIAS_PULL_DOWN:
+		ret = meson_pinconf_bias_set(dev, pin, param);
+		break;
+
+	default:
+		dev_err(dev, "unsupported configuration parameter %u\n", param);
+		return -EINVAL;
+	}
+
+	return ret;
+}
+
+int meson_pinconf_group_set(struct udevice *dev,
+			    unsigned int group_selector,
+			    unsigned int param, unsigned int arg)
+{
+	struct meson_pinctrl *priv = dev_get_priv(dev);
+	struct meson_pmx_group *grp = &priv->data->groups[group_selector];
+	int i, ret;
+
+	for (i = 0; i < grp->num_pins; i++) {
+		ret = meson_pinconf_set(dev, grp->pins[i], param, arg);
+		if (ret)
+			return ret;
+	}
+
+	return 0;
+}
+
 int meson_gpio_probe(struct udevice *dev)
 {
 	struct meson_pinctrl *priv = dev_get_priv(dev->parent);
@@ -240,6 +312,21 @@ int meson_pinctrl_probe(struct udevice *dev)
 		return -EINVAL;
 	}
 	priv->reg_gpio = (void __iomem *)addr;
+
+	addr = parse_address(gpio, "pull", na, ns);
+	if (addr == FDT_ADDR_T_NONE) {
+		debug("pull address not found\n");
+		return -EINVAL;
+	}
+	priv->reg_pull = (void __iomem *)addr;
+
+	addr = parse_address(gpio, "pull-enable", na, ns);
+	/* Use pull region if pull-enable one is not present */
+	if (addr == FDT_ADDR_T_NONE)
+		priv->reg_pullen = priv->reg_pull;
+	else
+		priv->reg_pullen = (void __iomem *)addr;
+
 	priv->data = (struct meson_pinctrl_data *)dev_get_driver_data(dev);
 
 	/* Lookup GPIO driver */
diff --git a/drivers/pinctrl/meson/pinctrl-meson.h b/drivers/pinctrl/meson/pinctrl-meson.h
index bdee721fc007..28085a7495d4 100644
--- a/drivers/pinctrl/meson/pinctrl-meson.h
+++ b/drivers/pinctrl/meson/pinctrl-meson.h
@@ -39,6 +39,8 @@ struct meson_pinctrl {
 	struct meson_pinctrl_data *data;
 	void __iomem *reg_mux;
 	void __iomem *reg_gpio;
+	void __iomem *reg_pull;
+	void __iomem *reg_pullen;
 };
 
 /**
@@ -130,4 +132,10 @@ int meson_gpio_direction_output(struct udevice *dev, unsigned int offset,
 				int value);
 int meson_gpio_probe(struct udevice *dev);
 
+int meson_pinconf_set(struct udevice *dev, unsigned int pin,
+		      unsigned int param, unsigned int arg);
+int meson_pinconf_group_set(struct udevice *dev,
+			    unsigned int group_selector,
+			    unsigned int param, unsigned int arg);
+
 #endif /* __PINCTRL_MESON_H__ */
