diff --git a/drivers/gpio/gpio-tegra186.c b/drivers/gpio/gpio-tegra186.c
index 1215e08ffe02..69bcc057db26 100644
--- a/drivers/gpio/gpio-tegra186.c
+++ b/drivers/gpio/gpio-tegra186.c
@@ -70,35 +70,12 @@ struct tegra_gpio {
 	void __iomem *base;
 };
 
-static const struct tegra_gpio_port *
-tegra186_gpio_get_port(struct tegra_gpio *gpio, unsigned int *pin)
-{
-	unsigned int start = 0, i;
-
-	for (i = 0; i < gpio->soc->num_ports; i++) {
-		const struct tegra_gpio_port *port = &gpio->soc->ports[i];
-
-		if (*pin >= start && *pin < start + port->pins) {
-			*pin -= start;
-			return port;
-		}
-
-		start += port->pins;
-	}
-
-	return NULL;
-}
-
 static void __iomem *tegra186_gpio_get_base(struct tegra_gpio *gpio,
 					    unsigned int pin)
 {
-	const struct tegra_gpio_port *port;
-
-	port = tegra186_gpio_get_port(gpio, &pin);
-	if (!port)
-		return NULL;
+	const struct tegra_gpio_port *port = &gpio->soc->ports[pin / 8];
 
-	return gpio->base + port->offset + pin * 0x20;
+	return gpio->base + port->offset + (pin % 8) * 0x20;
 }
 
 static int tegra186_gpio_get_direction(struct gpio_chip *chip,
@@ -208,68 +185,6 @@ static void tegra186_gpio_set(struct gpio_chip *chip, unsigned int offset,
 	writel(value, base + TEGRA186_GPIO_OUTPUT_VALUE);
 }
 
-static int tegra186_gpio_of_xlate(struct gpio_chip *chip,
-				  const struct of_phandle_args *spec,
-				  u32 *flags)
-{
-	struct tegra_gpio *gpio = gpiochip_get_data(chip);
-	unsigned int port, pin, i, offset = 0;
-
-	if (WARN_ON(chip->of_gpio_n_cells < 2))
-		return -EINVAL;
-
-	if (WARN_ON(spec->args_count < chip->of_gpio_n_cells))
-		return -EINVAL;
-
-	port = spec->args[0] / 8;
-	pin = spec->args[0] % 8;
-
-	if (port >= gpio->soc->num_ports) {
-		dev_err(chip->parent, "invalid port number: %u\n", port);
-		return -EINVAL;
-	}
-
-	for (i = 0; i < port; i++)
-		offset += gpio->soc->ports[i].pins;
-
-	if (flags)
-		*flags = spec->args[1];
-
-	return offset + pin;
-}
-
-static int tegra186_gpio_to_irq(struct gpio_chip *chip, unsigned int offset)
-{
-	struct tegra_gpio *gpio = gpiochip_get_data(chip);
-	struct irq_domain *domain = chip->irq.domain;
-
-	if (!gpiochip_irqchip_irq_valid(chip, offset))
-		return -ENXIO;
-
-	if (irq_domain_is_hierarchy(domain)) {
-		struct irq_fwspec spec;
-		unsigned int i;
-
-		for (i = 0; i < gpio->soc->num_ports; i++) {
-			if (offset < gpio->soc->ports[i].pins)
-				break;
-
-			offset -= gpio->soc->ports[i].pins;
-		}
-
-		offset += i * 8;
-
-		spec.fwnode = domain->fwnode;
-		spec.param_count = 2;
-		spec.param[0] = offset;
-		spec.param[1] = 0;
-
-		return irq_domain_alloc_irqs(domain, 1, NUMA_NO_NODE, &spec);
-	}
-
-	return irq_create_mapping(domain, offset);
-}
-
 static void tegra186_irq_ack(struct irq_data *data)
 {
 	struct tegra_gpio *gpio = irq_data_get_irq_chip_data(data);
@@ -372,7 +287,7 @@ static void tegra186_gpio_irq(struct irq_desc *desc)
 	struct irq_domain *domain = gpio->gpio.irq.domain;
 	struct irq_chip *chip = irq_desc_get_chip(desc);
 	unsigned int parent = irq_desc_get_irq(desc);
-	unsigned int i, offset = 0;
+	unsigned int i;
 
 	chained_irq_enter(chip, desc);
 
@@ -384,20 +299,17 @@ static void tegra186_gpio_irq(struct irq_desc *desc)
 
 		/* skip ports that are not associated with this controller */
 		if (parent != gpio->irq[port->irq])
-			goto skip;
+			continue;
 
 		value = readl(base + TEGRA186_GPIO_INTERRUPT_STATUS(1));
 
 		for_each_set_bit(pin, &value, port->pins) {
-			irq = irq_find_mapping(domain, offset + pin);
+			irq = irq_find_mapping(domain, i * 8 + pin);
 			if (WARN_ON(irq == 0))
 				continue;
 
 			generic_handle_irq(irq);
 		}
-
-skip:
-		offset += port->pins;
 	}
 
 	chained_irq_exit(chip, desc);
@@ -409,7 +321,7 @@ static int tegra186_gpio_irq_domain_translate(struct irq_domain *domain,
 					      unsigned int *type)
 {
 	struct tegra_gpio *gpio = gpiochip_get_data(domain->host_data);
-	unsigned int port, pin, i, offset = 0;
+	unsigned int port, pin;
 
 	if (WARN_ON(gpio->gpio.of_gpio_n_cells < 2))
 		return -EINVAL;
@@ -423,11 +335,8 @@ static int tegra186_gpio_irq_domain_translate(struct irq_domain *domain,
 	if (port >= gpio->soc->num_ports)
 		return -EINVAL;
 
-	for (i = 0; i < port; i++)
-		offset += gpio->soc->ports[i].pins;
-
 	*type = fwspec->param[1] & IRQ_TYPE_SENSE_MASK;
-	*hwirq = offset + pin;
+	*hwirq = port * 8 + pin;
 
 	return 0;
 }
@@ -466,6 +375,43 @@ static const struct irq_domain_ops tegra186_gpio_irq_domain_ops = {
 	.unmap = gpiochip_irq_unmap,
 };
 
+static void tegra186_gpio_set_valid_mask(struct tegra_gpio *gpio,
+					 unsigned long *mask)
+{
+	unsigned int i;
+
+	bitmap_zero(mask, gpio->gpio.ngpio);
+
+	for (i = 0; i < gpio->soc->num_ports; i++) {
+		const struct tegra_gpio_port *port = &gpio->soc->ports[i];
+
+		bitmap_set(mask, i * 8, port->pins);
+	}
+}
+
+static int tegra186_gpio_init_valid_mask(struct gpio_chip *chip)
+{
+	struct tegra_gpio *gpio = gpiochip_get_data(chip);
+
+	tegra186_gpio_set_valid_mask(gpio, chip->valid_mask);
+
+	return 0;
+}
+
+static unsigned long *tegra186_gpio_setup_valid_mask(struct tegra_gpio *gpio)
+{
+	unsigned long *mask;
+
+	mask = devm_kcalloc(gpio->gpio.parent, BITS_TO_LONGS(gpio->gpio.ngpio),
+			    sizeof(*mask), GFP_KERNEL);
+	if (!mask)
+		return ERR_PTR(-ENOMEM);
+
+	tegra186_gpio_set_valid_mask(gpio, mask);
+
+	return mask;
+}
+
 static const struct of_device_id tegra186_pmc_of_match[] = {
 	{ .compatible = "nvidia,tegra186-pmc" },
 	{ .compatible = "nvidia,tegra194-pmc" },
@@ -474,11 +420,11 @@ static const struct of_device_id tegra186_pmc_of_match[] = {
 
 static int tegra186_gpio_probe(struct platform_device *pdev)
 {
-	unsigned int i, j, offset;
 	struct gpio_irq_chip *irq;
 	struct tegra_gpio *gpio;
 	struct device_node *np;
 	struct resource *res;
+	unsigned int i, j;
 	char **names;
 	int err;
 
@@ -521,17 +467,15 @@ static int tegra186_gpio_probe(struct platform_device *pdev)
 	gpio->gpio.get = tegra186_gpio_get,
 	gpio->gpio.set = tegra186_gpio_set;
 
+	gpio->gpio.ngpio = gpio->soc->num_ports * 8;
 	gpio->gpio.base = -1;
 
-	for (i = 0; i < gpio->soc->num_ports; i++)
-		gpio->gpio.ngpio += gpio->soc->ports[i].pins;
-
 	names = devm_kcalloc(gpio->gpio.parent, gpio->gpio.ngpio,
 			     sizeof(*names), GFP_KERNEL);
 	if (!names)
 		return -ENOMEM;
 
-	for (i = 0, offset = 0; i < gpio->soc->num_ports; i++) {
+	for (i = 0; i < gpio->soc->num_ports; i++) {
 		const struct tegra_gpio_port *port = &gpio->soc->ports[i];
 		char *name;
 
@@ -541,18 +485,17 @@ static int tegra186_gpio_probe(struct platform_device *pdev)
 			if (!name)
 				return -ENOMEM;
 
-			names[offset + j] = name;
+			names[i * 8 + j] = name;
 		}
-
-		offset += port->pins;
 	}
 
 	gpio->gpio.names = (const char * const *)names;
 
 	gpio->gpio.of_node = pdev->dev.of_node;
 	gpio->gpio.of_gpio_n_cells = 2;
-	gpio->gpio.of_xlate = tegra186_gpio_of_xlate;
-	gpio->gpio.to_irq = tegra186_gpio_to_irq;
+
+	gpio->gpio.init_valid_mask = tegra186_gpio_init_valid_mask;
+	gpio->gpio.need_valid_mask = true;
 
 	gpio->intc.name = pdev->dev.of_node->name;
 	gpio->intc.irq_ack = tegra186_irq_ack;
@@ -580,18 +523,22 @@ static int tegra186_gpio_probe(struct platform_device *pdev)
 			return -EPROBE_DEFER;
 	}
 
+	irq->valid_mask = tegra186_gpio_setup_valid_mask(gpio);
+	if (IS_ERR(irq->valid_mask))
+		return PTR_ERR(irq->valid_mask);
+
+	irq->need_valid_mask = true;
+
 	irq->map = devm_kcalloc(&pdev->dev, gpio->gpio.ngpio,
 				sizeof(*irq->map), GFP_KERNEL);
 	if (!irq->map)
 		return -ENOMEM;
 
-	for (i = 0, offset = 0; i < gpio->soc->num_ports; i++) {
+	for (i = 0; i < gpio->soc->num_ports; i++) {
 		const struct tegra_gpio_port *port = &gpio->soc->ports[i];
 
 		for (j = 0; j < port->pins; j++)
-			irq->map[offset + j] = irq->parents[port->irq];
-
-		offset += port->pins;
+			irq->map[i * 8 + j] = irq->parents[port->irq];
 	}
 
 	platform_set_drvdata(pdev, gpio);
