diff --git a/Documentation/devicetree/bindings/pinctrl/pinctrl-mcp23s08.txt b/Documentation/devicetree/bindings/pinctrl/pinctrl-mcp23s08.txt
index 9c451c20dda4..92aa91027c68 100644
--- a/Documentation/devicetree/bindings/pinctrl/pinctrl-mcp23s08.txt
+++ b/Documentation/devicetree/bindings/pinctrl/pinctrl-mcp23s08.txt
@@ -58,6 +58,10 @@ Optional device specific properties:
         On devices with only one interrupt output this property is useless.
 - microchip,irq-active-high: Sets the INTPOL flag in the IOCON register. This
         configures the IRQ output polarity as active high.
+- microchip,irq-open-drain: Sets the ODR flag in the IOCON register. This
+        configures the IRQ output as active low open-drain and allows sharing
+	of the IRQ line among several chips. Note that irq-active-high and
+	irq-open-drain are mutually exclusive.
 
 Example I2C (with interrupt):
 gpiom1: gpio@20 {
diff --git a/drivers/pinctrl/pinctrl-mcp23s08.c b/drivers/pinctrl/pinctrl-mcp23s08.c
index c017860619d6..186101c575e3 100644
--- a/drivers/pinctrl/pinctrl-mcp23s08.c
+++ b/drivers/pinctrl/pinctrl-mcp23s08.c
@@ -54,9 +54,15 @@
 
 struct mcp23s08;
 
+enum mcp23s08_irq_regime {
+	MCP_IRQ_PULL_LOW,
+	MCP_IRQ_PUSH_UP,
+	MCP_IRQ_OPEN_DRAIN
+};
+
 struct mcp23s08 {
 	u8			addr;
-	bool			irq_active_high;
+	enum mcp23s08_irq_regime	irq_regime;
 	bool			reg_shift;
 
 	u16			irq_rise;
@@ -625,10 +631,17 @@ static int mcp23s08_irq_setup(struct mcp23s08 *mcp)
 	int err;
 	unsigned long irqflags = IRQF_ONESHOT | IRQF_SHARED;
 
-	if (mcp->irq_active_high)
-		irqflags |= IRQF_TRIGGER_HIGH;
-	else
+	switch (mcp->irq_regime) {
+	case MCP_IRQ_PULL_LOW:
 		irqflags |= IRQF_TRIGGER_LOW;
+		break;
+	case MCP_IRQ_PUSH_UP:
+		irqflags |= IRQF_TRIGGER_HIGH;
+		break;
+	case MCP_IRQ_OPEN_DRAIN:
+		irqflags |= IRQF_TRIGGER_LOW | IRQF_SHARED;
+		break;
+	}
 
 	err = devm_request_threaded_irq(chip->parent, mcp->irq, NULL,
 					mcp23s08_irq,
@@ -780,7 +793,7 @@ static int mcp23s08_probe_one(struct mcp23s08 *mcp, struct device *dev,
 
 	mcp->dev = dev;
 	mcp->addr = addr;
-	mcp->irq_active_high = false;
+	mcp->irq_regime = MCP_IRQ_PULL_LOW;
 
 	mcp->chip.direction_input = mcp23s08_direction_input;
 	mcp->chip.get = mcp23s08_get;
@@ -866,33 +879,52 @@ static int mcp23s08_probe_one(struct mcp23s08 *mcp, struct device *dev,
 	mcp->irq_controller =
 		device_property_read_bool(dev, "interrupt-controller");
 	if (mcp->irq && mcp->irq_controller) {
-		mcp->irq_active_high =
-			device_property_read_bool(dev,
-					      "microchip,irq-active-high");
+		bool irq_active_high = device_property_read_bool(dev,
+						"microchip,irq-active-high");
+		bool irq_open_drain = device_property_read_bool(dev,
+						"microchip,irq-open-drain");
+		if (irq_active_high && irq_open_drain) {
+			dev_err(dev, "microchip,irq-open-drain and "
+				"microchip,irq-active-high are mutually exclusive\n");
+			ret = -EINVAL;
+			goto fail;
+		} else if (irq_active_high) {
+			mcp->irq_regime = MCP_IRQ_PUSH_UP;
+		} else if (irq_open_drain) {
+			mcp->irq_regime = MCP_IRQ_OPEN_DRAIN;
+		}
 
 		mirror = device_property_read_bool(dev, "microchip,irq-mirror");
 	}
 
-	if ((status & IOCON_SEQOP) || !(status & IOCON_HAEN) || mirror ||
-	     mcp->irq_active_high) {
-		/* mcp23s17 has IOCON twice, make sure they are in sync */
-		status &= ~(IOCON_SEQOP | (IOCON_SEQOP << 8));
-		status |= IOCON_HAEN | (IOCON_HAEN << 8);
-		if (mcp->irq_active_high)
-			status |= IOCON_INTPOL | (IOCON_INTPOL << 8);
-		else
-			status &= ~(IOCON_INTPOL | (IOCON_INTPOL << 8));
+	/* mcp23s17 has IOCON twice, make sure they are in sync */
+	status &= ~(IOCON_SEQOP | (IOCON_SEQOP << 8));
+	status |= IOCON_HAEN | (IOCON_HAEN << 8);
 
-		if (mirror)
-			status |= IOCON_MIRROR | (IOCON_MIRROR << 8);
+	switch (mcp->irq_regime) {
+	case MCP_IRQ_PUSH_UP:
+		status |= IOCON_INTPOL | (IOCON_INTPOL << 8);
+		status &= ~(IOCON_ODR | (IOCON_ODR << 8));
+		break;
+	case MCP_IRQ_PULL_LOW:
+		status &= ~(IOCON_INTPOL | (IOCON_INTPOL << 8));
+		status &= ~(IOCON_ODR | (IOCON_ODR << 8));
+		break;
+	case MCP_IRQ_OPEN_DRAIN:
+		/* ODR overrides INTPOL */
+		status |= IOCON_ODR | (IOCON_ODR << 8);
+		break;
+	}
 
-		if (type == MCP_TYPE_S18 || type == MCP_TYPE_018)
-			status |= IOCON_INTCC | (IOCON_INTCC << 8);
+	if (mirror)
+		status |= IOCON_MIRROR | (IOCON_MIRROR << 8);
 
-		ret = mcp_write(mcp, MCP_IOCON, status);
-		if (ret < 0)
-			goto fail;
-	}
+	if (type == MCP_TYPE_S18 || type == MCP_TYPE_018)
+		status |= IOCON_INTCC | (IOCON_INTCC << 8);
+
+	ret = mcp_write(mcp, MCP_IOCON, status);
+	if (ret < 0)
+		goto fail;
 
 	ret = devm_gpiochip_add_data(dev, &mcp->chip, mcp);
 	if (ret < 0)
