diff --git a/drivers/pinctrl/intel/pinctrl-intel.c b/drivers/pinctrl/intel/pinctrl-intel.c
index 12a1af45acb98557de6184e934360dc056fbc01a..4c2369a8d926cd92c1e61ec36490d282ca43490c 100644
--- a/drivers/pinctrl/intel/pinctrl-intel.c
+++ b/drivers/pinctrl/intel/pinctrl-intel.c
@@ -806,22 +806,63 @@ static const struct gpio_chip intel_gpio_chip = {
 	.set_config = gpiochip_generic_config,
 };
 
+/**
+ * intel_gpio_to_pin() - Translate from GPIO offset to pin number
+ * @pctrl: Pinctrl structure
+ * @offset: GPIO offset from gpiolib
+ * @commmunity: Community is filled here if not %NULL
+ * @padgrp: Pad group is filled here if not %NULL
+ *
+ * When coming through gpiolib irqchip, the GPIO offset is not
+ * automatically translated to pinctrl pin number. This function can be
+ * used to find out the corresponding pinctrl pin.
+ */
+static int intel_gpio_to_pin(struct intel_pinctrl *pctrl, unsigned offset,
+			     const struct intel_community **community,
+			     const struct intel_padgroup **padgrp)
+{
+	int i;
+
+	for (i = 0; i < pctrl->ncommunities; i++) {
+		const struct intel_community *comm = &pctrl->communities[i];
+		int j;
+
+		for (j = 0; j < comm->ngpps; j++) {
+			const struct intel_padgroup *pgrp = &comm->gpps[j];
+
+			if (pgrp->gpio_base < 0)
+				continue;
+
+			if (offset >= pgrp->gpio_base &&
+			    offset < pgrp->gpio_base + pgrp->size) {
+				int pin;
+
+				pin = pgrp->base + offset - pgrp->gpio_base;
+				if (community)
+					*community = comm;
+				if (padgrp)
+					*padgrp = pgrp;
+
+				return pin;
+			}
+		}
+	}
+
+	return -EINVAL;
+}
+
 static void intel_gpio_irq_ack(struct irq_data *d)
 {
 	struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
 	struct intel_pinctrl *pctrl = gpiochip_get_data(gc);
 	const struct intel_community *community;
-	unsigned pin = irqd_to_hwirq(d);
+	const struct intel_padgroup *padgrp;
+	int pin;
 
-	community = intel_get_community(pctrl, pin);
-	if (community) {
-		const struct intel_padgroup *padgrp;
+	pin = intel_gpio_to_pin(pctrl, irqd_to_hwirq(d), &community, &padgrp);
+	if (pin >= 0) {
 		unsigned gpp, gpp_offset, is_offset;
 
-		padgrp = intel_community_get_padgroup(community, pin);
-		if (!padgrp)
-			return;
-
 		gpp = padgrp->reg_num;
 		gpp_offset = padgroup_offset(padgrp, pin);
 		is_offset = community->is_offset + gpp * 4;
@@ -837,19 +878,15 @@ static void intel_gpio_irq_enable(struct irq_data *d)
 	struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
 	struct intel_pinctrl *pctrl = gpiochip_get_data(gc);
 	const struct intel_community *community;
-	unsigned pin = irqd_to_hwirq(d);
+	const struct intel_padgroup *padgrp;
+	int pin;
 
-	community = intel_get_community(pctrl, pin);
-	if (community) {
-		const struct intel_padgroup *padgrp;
+	pin = intel_gpio_to_pin(pctrl, irqd_to_hwirq(d), &community, &padgrp);
+	if (pin >= 0) {
 		unsigned gpp, gpp_offset, is_offset;
 		unsigned long flags;
 		u32 value;
 
-		padgrp = intel_community_get_padgroup(community, pin);
-		if (!padgrp)
-			return;
-
 		gpp = padgrp->reg_num;
 		gpp_offset = padgroup_offset(padgrp, pin);
 		is_offset = community->is_offset + gpp * 4;
@@ -870,20 +907,16 @@ static void intel_gpio_irq_mask_unmask(struct irq_data *d, bool mask)
 	struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
 	struct intel_pinctrl *pctrl = gpiochip_get_data(gc);
 	const struct intel_community *community;
-	unsigned pin = irqd_to_hwirq(d);
+	const struct intel_padgroup *padgrp;
+	int pin;
 
-	community = intel_get_community(pctrl, pin);
-	if (community) {
-		const struct intel_padgroup *padgrp;
+	pin = intel_gpio_to_pin(pctrl, irqd_to_hwirq(d), &community, &padgrp);
+	if (pin >= 0) {
 		unsigned gpp, gpp_offset;
 		unsigned long flags;
 		void __iomem *reg;
 		u32 value;
 
-		padgrp = intel_community_get_padgroup(community, pin);
-		if (!padgrp)
-			return;
-
 		gpp = padgrp->reg_num;
 		gpp_offset = padgroup_offset(padgrp, pin);
 
@@ -914,7 +947,7 @@ static int intel_gpio_irq_type(struct irq_data *d, unsigned type)
 {
 	struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
 	struct intel_pinctrl *pctrl = gpiochip_get_data(gc);
-	unsigned pin = irqd_to_hwirq(d);
+	unsigned pin = intel_gpio_to_pin(pctrl, irqd_to_hwirq(d), NULL, NULL);
 	unsigned long flags;
 	void __iomem *reg;
 	u32 value;
@@ -969,7 +1002,7 @@ static int intel_gpio_irq_wake(struct irq_data *d, unsigned int on)
 {
 	struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
 	struct intel_pinctrl *pctrl = gpiochip_get_data(gc);
-	unsigned pin = irqd_to_hwirq(d);
+	unsigned pin = intel_gpio_to_pin(pctrl, irqd_to_hwirq(d), NULL, NULL);
 
 	if (on)
 		enable_irq_wake(pctrl->irq);
@@ -1000,14 +1033,10 @@ static irqreturn_t intel_gpio_community_irq_handler(struct intel_pinctrl *pctrl,
 		pending &= enabled;
 
 		for_each_set_bit(gpp_offset, &pending, padgrp->size) {
-			unsigned padno, irq;
-
-			padno = padgrp->base - community->pin_base + gpp_offset;
-			if (padno >= community->npins)
-				break;
+			unsigned irq;
 
 			irq = irq_find_mapping(gc->irq.domain,
-					       community->pin_base + padno);
+					       padgrp->gpio_base + gpp_offset);
 			generic_handle_irq(irq);
 
 			ret |= IRQ_HANDLED;
@@ -1044,13 +1073,56 @@ static struct irq_chip intel_gpio_irqchip = {
 	.flags = IRQCHIP_MASK_ON_SUSPEND,
 };
 
+static int intel_gpio_add_pin_ranges(struct intel_pinctrl *pctrl,
+				     const struct intel_community *community)
+{
+	int ret, i;
+
+	for (i = 0; i < community->ngpps; i++) {
+		const struct intel_padgroup *gpp = &community->gpps[i];
+
+		if (gpp->gpio_base < 0)
+			continue;
+
+		ret = gpiochip_add_pin_range(&pctrl->chip, dev_name(pctrl->dev),
+					     gpp->gpio_base, gpp->base,
+					     gpp->size);
+		if (ret)
+			return ret;
+	}
+
+	return ret;
+}
+
+static unsigned intel_gpio_ngpio(const struct intel_pinctrl *pctrl)
+{
+	const struct intel_community *community;
+	unsigned ngpio = 0;
+	int i, j;
+
+	for (i = 0; i < pctrl->ncommunities; i++) {
+		community = &pctrl->communities[i];
+		for (j = 0; j < community->ngpps; j++) {
+			const struct intel_padgroup *gpp = &community->gpps[j];
+
+			if (gpp->gpio_base < 0)
+				continue;
+
+			if (gpp->gpio_base + gpp->size > ngpio)
+				ngpio = gpp->gpio_base + gpp->size;
+		}
+	}
+
+	return ngpio;
+}
+
 static int intel_gpio_probe(struct intel_pinctrl *pctrl, int irq)
 {
-	int ret;
+	int ret, i;
 
 	pctrl->chip = intel_gpio_chip;
 
-	pctrl->chip.ngpio = pctrl->soc->npins;
+	pctrl->chip.ngpio = intel_gpio_ngpio(pctrl);
 	pctrl->chip.label = dev_name(pctrl->dev);
 	pctrl->chip.parent = pctrl->dev;
 	pctrl->chip.base = -1;
@@ -1062,11 +1134,14 @@ static int intel_gpio_probe(struct intel_pinctrl *pctrl, int irq)
 		return ret;
 	}
 
-	ret = gpiochip_add_pin_range(&pctrl->chip, dev_name(pctrl->dev),
-				     0, 0, pctrl->soc->npins);
-	if (ret) {
-		dev_err(pctrl->dev, "failed to add GPIO pin range\n");
-		return ret;
+	for (i = 0; i < pctrl->ncommunities; i++) {
+		struct intel_community *community = &pctrl->communities[i];
+
+		ret = intel_gpio_add_pin_ranges(pctrl, community);
+		if (ret) {
+			dev_err(pctrl->dev, "failed to add GPIO pin range\n");
+			return ret;
+		}
 	}
 
 	/*
@@ -1126,6 +1201,9 @@ static int intel_pinctrl_add_padgroups(struct intel_pinctrl *pctrl,
 		if (gpps[i].size > 32)
 			return -EINVAL;
 
+		if (!gpps[i].gpio_base)
+			gpps[i].gpio_base = gpps[i].base;
+
 		gpps[i].padown_num = padown_num;
 
 		/*
diff --git a/drivers/pinctrl/intel/pinctrl-intel.h b/drivers/pinctrl/intel/pinctrl-intel.h
index 13b0bd6eb2a25441b1a29d9ff87931351f1125ce..98fdf9adf6236a1fcdebf1f24c26ced8aec65700 100644
--- a/drivers/pinctrl/intel/pinctrl-intel.h
+++ b/drivers/pinctrl/intel/pinctrl-intel.h
@@ -51,6 +51,8 @@ struct intel_function {
  * @reg_num: GPI_IS register number
  * @base: Starting pin of this group
  * @size: Size of this group (maximum is 32).
+ * @gpio_base: Starting GPIO base of this group (%0 if matches with @base,
+ *	       and %-1 if no GPIO mapping should be created)
  * @padown_num: PAD_OWN register number (assigned by the core driver)
  *
  * If pad groups of a community are not the same size, use this structure
@@ -60,6 +62,7 @@ struct intel_padgroup {
 	unsigned reg_num;
 	unsigned base;
 	unsigned size;
+	int gpio_base;
 	unsigned padown_num;
 };