diff --git a/drivers/pinctrl/sunxi/pinctrl-sunxi.c b/drivers/pinctrl/sunxi/pinctrl-sunxi.c
index ff7c5439a458e..0d08c48b57b65 100644
--- a/drivers/pinctrl/sunxi/pinctrl-sunxi.c
+++ b/drivers/pinctrl/sunxi/pinctrl-sunxi.c
@@ -971,18 +971,21 @@ static int sunxi_pinctrl_gpio_set(struct gpio_chip *chip, unsigned int offset,
 
 	sunxi_data_reg(pctl, offset, &reg, &shift, &mask);
 
-	raw_spin_lock_irqsave(&pctl->lock, flags);
-
-	val = readl(pctl->membase + reg);
-
-	if (value)
-		val |= mask;
-	else
-		val &= ~mask;
-
-	writel(val, pctl->membase + reg);
-
-	raw_spin_unlock_irqrestore(&pctl->lock, flags);
+	if (pctl->flags & SUNXI_PINCTRL_HAS_SET_CLEAR_REGS) {
+		if (value)
+			writel(mask, pctl->membase + reg + DATA_SET_OFFSET);
+		else
+			writel(mask, pctl->membase + reg + DATA_CLR_OFFSET);
+	} else {
+		raw_spin_lock_irqsave(&pctl->lock, flags);
+		val = readl(pctl->membase + reg);
+		if (value)
+			val |= mask;
+		else
+			val &= ~mask;
+		writel(val, pctl->membase + reg);
+		raw_spin_unlock_irqrestore(&pctl->lock, flags);
+	}
 
 	return 0;
 }
diff --git a/drivers/pinctrl/sunxi/pinctrl-sunxi.h b/drivers/pinctrl/sunxi/pinctrl-sunxi.h
index 2b9e93972a5d3..96f1cb9d6c89c 100644
--- a/drivers/pinctrl/sunxi/pinctrl-sunxi.h
+++ b/drivers/pinctrl/sunxi/pinctrl-sunxi.h
@@ -43,6 +43,8 @@
 #define MUX_REGS_OFFSET		0x0
 #define MUX_FIELD_WIDTH		4
 #define DATA_REGS_OFFSET	0x10
+#define DATA_SET_OFFSET			0x04
+#define DATA_CLR_OFFSET			0x08
 #define DATA_FIELD_WIDTH	1
 #define DLEVEL_REGS_OFFSET	0x14
 #define DLEVEL_FIELD_WIDTH	2
@@ -99,6 +101,7 @@
 #define SUNXI_PINCTRL_PORTF_SWITCH	BIT(9)
 #define SUNXI_PINCTRL_ELEVEN_BANKS	BIT(10)
 #define SUNXI_PINCTRL_NCAT3_REG_LAYOUT	BIT(11)
+#define SUNXI_PINCTRL_HAS_SET_CLEAR_REGS	BIT(12)
 
 #define PIO_NCAT3_POW_MOD_SEL_REG	0x040
 #define PIO_POW_MOD_SEL_REG		0x340
