diff -ruPN a/drivers/pinctrl/Kconfig b/drivers/pinctrl/Kconfig
--- a/drivers/pinctrl/Kconfig	2015-05-05 18:39:05.000000000 +0200
+++ b/drivers/pinctrl/Kconfig	2015-05-15 11:59:58.000000000 +0200
@@ -119,6 +119,13 @@
 	help
 	  This selects the device tree based generic pinctrl driver.
 
+config MUX_SWITCH
+  bool "Pinmux switch driver"
+  depends on PINMUX && OF
+  default n
+  help
+    Say Y here to include support for the pinmux switch driver
+
 config PINCTRL_SIRF
 	bool "CSR SiRFprimaII pin controller driver"
 	depends on ARCH_SIRF
diff -ruPN a/drivers/pinctrl/Makefile b/drivers/pinctrl/Makefile
--- a/drivers/pinctrl/Makefile	2015-05-05 18:39:05.000000000 +0200
+++ b/drivers/pinctrl/Makefile	2015-05-15 12:00:48.000000000 +0200
@@ -8,6 +8,7 @@
 ifeq ($(CONFIG_OF),y)
 obj-$(CONFIG_PINCTRL)		+= devicetree.o
 endif
+obj-$(CONFIG_MUX_SWITCH) += mux-switch.o
 obj-$(CONFIG_GENERIC_PINCONF)	+= pinconf-generic.o
 obj-$(CONFIG_PINCTRL_ADI2)	+= pinctrl-adi2.o
 obj-$(CONFIG_PINCTRL_AS3722)	+= pinctrl-as3722.o
diff -ruPN a/drivers/pinctrl/mux-switch.c b/drivers/pinctrl/mux-switch.c
--- a/drivers/pinctrl/mux-switch.c	1970-01-01 01:00:00.000000000 +0100
+++ b/drivers/pinctrl/mux-switch.c	2014-09-04 08:28:12.000000000 +0200
@@ -0,0 +1,216 @@
+/*
+ * Mux switch driver
+ * Copyright (C) 2016 M. Feser
+ * 
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ * 
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/err.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/of_gpio.h>
+#include <linux/pinctrl/pinctrl.h>
+#include <linux/pinctrl/pinmux.h>
+#include <linux/pinctrl/consumer.h>
+
+static const struct of_device_id mux_switch_of_match[] = {
+  { .compatible = "mux-switch", },
+  { },
+};
+MODULE_DEVICE_TABLE(of, mux_switch_of_match);
+
+struct mux_switch_data {
+  struct pinctrl *pinctrl;
+  char *sel;
+};
+
+static ssize_t mux_switch_show_sel(struct device *dev, struct device_attribute *attr, char *buf)
+{
+  struct platform_device *pdev = to_platform_device(dev);
+  struct mux_switch_data *data = platform_get_drvdata(pdev);
+  const char *sel;
+  
+  sel = data->sel;
+  if ((sel == NULL) || (strlen(sel) == 0))
+    sel = "none";
+  return sprintf(buf, "%s\n", sel);
+}
+
+static ssize_t mux_switch_store_sel(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
+{
+  struct platform_device *pdev = to_platform_device(dev);
+  struct mux_switch_data *data = platform_get_drvdata(pdev);
+  struct pinctrl_state *state;
+  char *sel;
+  int err;
+
+  // Sanity check
+  if ((buf[count] != '\0') || (count < 2))
+  {
+    dev_err(dev, "Invalid pinmux\n");
+    return -1;
+  }
+
+  // Copy pinmux sel and replace \n
+  sel = devm_kzalloc(dev, count + 1, GFP_KERNEL);
+  if (sel == NULL)
+  {
+    dev_err(dev, "Unable to allocate pinmux sel swap memory\n");
+    return -ENOMEM;
+  }
+  memcpy(sel, buf, count);
+  if (sel[count-1] == '\n')
+    sel[count-1] = '\0';
+
+  // Try to select the new pinmux
+  state = pinctrl_lookup_state(data->pinctrl, sel);
+  if (!IS_ERR(state)) 
+  {
+    err = pinctrl_select_state(data->pinctrl, state);
+    if (err != 0)
+      dev_err(dev, "Unable to select pinmux: %s\n", sel);
+  } 
+  else 
+  {
+    dev_err(dev, "Invalid pinmux: %s\n", sel);
+    err = PTR_RET(state);
+  }
+
+  if (err == 0)
+  {
+    // Swap pinmux sel
+    devm_kfree(dev, data->sel);
+    data->sel = sel;
+  }
+  else
+  {
+    // Free new pinmux sel
+    devm_kfree(dev, sel);
+  }
+
+  if (err != 0)
+    return err;
+  else
+    return count;
+}
+
+static DEVICE_ATTR(sel, (S_IWUSR | S_IRUGO), mux_switch_show_sel, mux_switch_store_sel);
+
+static struct attribute *mux_switch_attributes[] = {
+  &dev_attr_sel.attr,
+  NULL
+};
+
+static const struct attribute_group mux_switch_attr_group = {
+  .attrs = mux_switch_attributes,
+};
+
+static int mux_switch_probe(struct platform_device *pdev)
+{
+  struct device *dev = &pdev->dev;
+  struct mux_switch_data *data;
+  struct pinctrl_state *state;
+  char *sel;
+  int res;
+
+  // Allocate data for driver data and state name
+  data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);
+  if (data == NULL)
+  {
+    dev_err(dev, "Unable to allocate driver data memory\n");
+    return -ENOMEM;
+  }
+  sel = devm_kzalloc(dev, strlen(PINCTRL_STATE_DEFAULT) + 1, GFP_KERNEL);
+  if (sel == NULL)
+  {
+    dev_err(dev, "Unable to allocate memory for pinmux sel\n");
+    return -ENOMEM;
+  }
+  data->sel = sel;
+  strcpy(data->sel, PINCTRL_STATE_DEFAULT);
+  platform_set_drvdata(pdev, data);
+
+  // Get pinctrl handle
+  data->pinctrl = devm_pinctrl_get(dev);
+  if (IS_ERR(data->pinctrl))
+  {
+    dev_err(dev, "Unable to get pinctrl handle\n");
+    devm_kfree(dev, data);
+    return PTR_ERR(data->pinctrl);
+  }
+
+  // Try to select default mux state
+  state = pinctrl_lookup_state(data->pinctrl, data->sel);
+  if (!IS_ERR(state))
+  {
+    res = pinctrl_select_state(data->pinctrl, state);
+    if (res != 0)
+    {
+      dev_err(dev, "Unable to select pinmux: %s\n", PINCTRL_STATE_DEFAULT);
+      devm_kfree(dev, data);
+      devm_pinctrl_put(data->pinctrl);
+      return res;
+    }
+  } 
+  else
+  {
+    data->sel = "none";
+  }
+
+  // Create sysfs group
+  res = sysfs_create_group(&dev->kobj, &mux_switch_attr_group);
+  if (res)
+  {
+    dev_err(dev, "Unable to create sysfs group\n");
+    devm_kfree(dev, data);
+    devm_pinctrl_put(data->pinctrl);
+    return res;
+  }
+
+  return 0;
+}
+
+static int mux_switch_remove(struct platform_device *pdev)
+{
+  struct device *dev = &pdev->dev;
+  struct mux_switch_data *data = platform_get_drvdata(pdev);
+
+  // Remove sysfs group and free memory
+  sysfs_remove_group(&dev->kobj, &mux_switch_attr_group);
+  devm_pinctrl_put(data->pinctrl);
+  devm_kfree(dev, data);
+
+  return 0;
+}
+
+struct platform_driver mux_switch_driver = {
+  .probe		= mux_switch_probe,
+  .remove		= mux_switch_remove,
+  .driver = {
+    .name		= "mux-switch",
+    .owner		= THIS_MODULE,
+    .of_match_table	= mux_switch_of_match,
+  },
+};
+
+module_platform_driver(mux_switch_driver);
+
+MODULE_AUTHOR("Matthias Feser");
+MODULE_DESCRIPTION("Mux switch driver");
+MODULE_LICENSE("GPL");
