#define CY8C95X0_PIN_TO_OFFSET(x) (((x) >= 20) ? ((x) + 4) : (x))
 
+#define CY8C95X0_MUX_REGMAP_TO_PORT(x) ((x) / MUXED_STRIDE)
+#define CY8C95X0_MUX_REGMAP_TO_REG(x) (((x) % MUXED_STRIDE) + CY8C95X0_INTMASK)
+#define CY8C95X0_MUX_REGMAP_TO_OFFSET(x, p) ((x) - CY8C95X0_INTMASK + (p) * MUXED_STRIDE)
+
 static const struct i2c_device_id cy8c95x0_id[] = {
        { "cy8c9520", 20, },
        { "cy8c9540", 40, },
 #define MAX_BANK 8
 #define BANK_SZ 8
 #define MAX_LINE       (MAX_BANK * BANK_SZ)
-
+#define MUXED_STRIDE   16
 #define CY8C95X0_GPIO_MASK             GENMASK(7, 0)
 
 /**
  * struct cy8c95x0_pinctrl - driver data
- * @regmap:         Device's regmap
+ * @regmap:         Device's regmap. Only direct access registers.
+ * @muxed_regmap:   Regmap for all muxed registers.
  * @irq_lock:       IRQ bus lock
  * @i2c_lock:       Mutex for the device internal mux register
  * @irq_mask:       I/O bits affected by interrupts
  */
 struct cy8c95x0_pinctrl {
        struct regmap *regmap;
+       struct regmap *muxed_regmap;
        struct mutex irq_lock;
        struct mutex i2c_lock;
        DECLARE_BITMAP(irq_mask, MAX_LINE);
        }
 }
 
+static bool cy8c95x0_muxed_register(unsigned int reg)
+{
+       switch (reg) {
+       case CY8C95X0_INTMASK:
+       case CY8C95X0_PWMSEL:
+       case CY8C95X0_INVERT:
+       case CY8C95X0_DIRECTION:
+       case CY8C95X0_DRV_PU:
+       case CY8C95X0_DRV_PD:
+       case CY8C95X0_DRV_ODH:
+       case CY8C95X0_DRV_ODL:
+       case CY8C95X0_DRV_PP_FAST:
+       case CY8C95X0_DRV_PP_SLOW:
+       case CY8C95X0_DRV_HIZ:
+               return true;
+       default:
+               return false;
+       }
+}
+
+static bool cy8c95x0_wc_register(unsigned int reg)
+{
+       switch (reg) {
+       case CY8C95X0_DRV_PU:
+       case CY8C95X0_DRV_PD:
+       case CY8C95X0_DRV_ODH:
+       case CY8C95X0_DRV_ODL:
+       case CY8C95X0_DRV_PP_FAST:
+       case CY8C95X0_DRV_PP_SLOW:
+       case CY8C95X0_DRV_HIZ:
+               return true;
+       default:
+               return false;
+       }
+}
+
+static bool cy8c95x0_quick_path_register(unsigned int reg)
+{
+       switch (reg) {
+       case CY8C95X0_INPUT_(0) ... CY8C95X0_INPUT_(7):
+       case CY8C95X0_INTSTATUS_(0) ... CY8C95X0_INTSTATUS_(7):
+       case CY8C95X0_OUTPUT_(0) ... CY8C95X0_OUTPUT_(7):
+               return true;
+       default:
+               return false;
+       }
+}
+
 static const struct reg_default cy8c95x0_reg_defaults[] = {
        { CY8C95X0_OUTPUT_(0), GENMASK(7, 0) },
        { CY8C95X0_OUTPUT_(1), GENMASK(7, 0) },
        { CY8C95X0_PWMSEL, 0 },
 };
 
+static int
+cy8c95x0_mux_reg_read(void *context, unsigned int off, unsigned int *val)
+{
+       struct cy8c95x0_pinctrl *chip = context;
+       u8 port = CY8C95X0_MUX_REGMAP_TO_PORT(off);
+       int ret, reg = CY8C95X0_MUX_REGMAP_TO_REG(off);
+
+       mutex_lock(&chip->i2c_lock);
+       /* Select the correct bank */
+       ret = regmap_write(chip->regmap, CY8C95X0_PORTSEL, port);
+       if (ret < 0)
+               goto out;
+
+       /*
+        * Read the register through direct access regmap. The target range
+        * is marked volatile.
+        */
+       ret = regmap_read(chip->regmap, reg, val);
+out:
+       mutex_unlock(&chip->i2c_lock);
+
+       return ret;
+}
+
+static int
+cy8c95x0_mux_reg_write(void *context, unsigned int off, unsigned int val)
+{
+       struct cy8c95x0_pinctrl *chip = context;
+       u8 port = CY8C95X0_MUX_REGMAP_TO_PORT(off);
+       int ret, reg = CY8C95X0_MUX_REGMAP_TO_REG(off);
+
+       mutex_lock(&chip->i2c_lock);
+       /* Select the correct bank */
+       ret = regmap_write(chip->regmap, CY8C95X0_PORTSEL, port);
+       if (ret < 0)
+               goto out;
+
+       /*
+        * Write the register through direct access regmap. The target range
+        * is marked volatile.
+        */
+       ret = regmap_write(chip->regmap, reg, val);
+out:
+       mutex_unlock(&chip->i2c_lock);
+
+       return ret;
+}
+
+static bool cy8c95x0_mux_accessible_register(struct device *dev, unsigned int off)
+{
+       struct i2c_client *i2c = to_i2c_client(dev);
+       struct cy8c95x0_pinctrl *chip = i2c_get_clientdata(i2c);
+       u8 port = CY8C95X0_MUX_REGMAP_TO_PORT(off);
+       u8 reg = CY8C95X0_MUX_REGMAP_TO_REG(off);
+
+       if (port >= chip->nport)
+               return false;
+
+       return cy8c95x0_muxed_register(reg);
+}
+
+static struct regmap_bus cy8c95x0_regmap_bus = {
+       .reg_read = cy8c95x0_mux_reg_read,
+       .reg_write = cy8c95x0_mux_reg_write,
+};
+
+/* Regmap for muxed registers CY8C95X0_INTMASK - CY8C95X0_DRV_HIZ */
+static const struct regmap_config cy8c95x0_muxed_regmap = {
+       .name = "muxed",
+       .reg_bits = 8,
+       .val_bits = 8,
+       .cache_type = REGCACHE_FLAT,
+       .use_single_read = true,
+       .use_single_write = true,
+       .max_register = MUXED_STRIDE * BANK_SZ,
+       .num_reg_defaults_raw = MUXED_STRIDE * BANK_SZ,
+       .readable_reg = cy8c95x0_mux_accessible_register,
+       .writeable_reg = cy8c95x0_mux_accessible_register,
+};
+
+/* Direct access regmap */
 static const struct regmap_config cy8c95x0_i2c_regmap = {
+       .name = "direct",
        .reg_bits = 8,
        .val_bits = 8,
 
        .max_register = CY8C95X0_COMMAND,
 };
 
+static inline int cy8c95x0_regmap_update_bits_base(struct cy8c95x0_pinctrl *chip,
+                                                  unsigned int reg,
+                                                  unsigned int port,
+                                                  unsigned int mask,
+                                                  unsigned int val,
+                                                  bool *change, bool async,
+                                                  bool force)
+{
+       struct regmap *regmap;
+       int ret, off, i, read_val;
+
+       /* Caller should never modify PORTSEL directly */
+       if (reg == CY8C95X0_PORTSEL)
+               return -EINVAL;
+
+       /* Registers behind the PORTSEL mux have their own regmap */
+       if (cy8c95x0_muxed_register(reg)) {
+               regmap = chip->muxed_regmap;
+               off = CY8C95X0_MUX_REGMAP_TO_OFFSET(reg, port);
+       } else {
+               regmap = chip->regmap;
+               /* Quick path direct access registers honor the port argument */
+               if (cy8c95x0_quick_path_register(reg))
+                       off = reg + port;
+               else
+                       off = reg;
+       }
+
+       ret = regmap_update_bits_base(regmap, off, mask, val, change, async, force);
+       if (ret < 0)
+               return ret;
+
+       /* Update the cache when a WC bit is written */
+       if (cy8c95x0_wc_register(reg) && (mask & val)) {
+               for (i = CY8C95X0_DRV_PU; i <= CY8C95X0_DRV_HIZ; i++) {
+                       if (i == reg)
+                               continue;
+                       off = CY8C95X0_MUX_REGMAP_TO_OFFSET(i, port);
+
+                       ret = regmap_read(regmap, off, &read_val);
+                       if (ret < 0)
+                               continue;
+
+                       if (!(read_val & mask & val))
+                               continue;
+
+                       regcache_cache_only(regmap, true);
+                       regmap_update_bits(regmap, off, mask & val, 0);
+                       regcache_cache_only(regmap, false);
+               }
+       }
+
+       return ret;
+}
+
+/**
+ * cy8c95x0_regmap_write_bits() - writes a register using the regmap cache
+ * @chip: The pinctrl to work on
+ * @reg: The register to write to. Can be direct access or muxed register.
+ *       MUST NOT be the PORTSEL register.
+ * @port: The port to be used for muxed registers or quick path direct access
+ *        registers. Otherwise unused.
+ * @mask: Bitmask to change
+ * @val: New value for bitmask
+ *
+ * This function handles the register writes to the direct access registers and
+ * the muxed registers while caching all register accesses, internally handling
+ * the correct state of the PORTSEL register and protecting the access to muxed
+ * registers.
+ * The caller must only use this function to change registers behind the PORTSEL mux.
+ *
+ * Return: 0 for successful request, else a corresponding error value
+ */
+static int cy8c95x0_regmap_write_bits(struct cy8c95x0_pinctrl *chip, unsigned int reg,
+                                     unsigned int port, unsigned int mask, unsigned int val)
+{
+       return cy8c95x0_regmap_update_bits_base(chip, reg, port, mask, val, NULL, false, true);
+}
+
+/**
+ * cy8c95x0_regmap_update_bits() - updates a register using the regmap cache
+ * @chip: The pinctrl to work on
+ * @reg: The register to write to. Can be direct access or muxed register.
+ *       MUST NOT be the PORTSEL register.
+ * @port: The port to be used for muxed registers or quick path direct access
+ *        registers. Otherwise unused.
+ * @mask: Bitmask to change
+ * @val: New value for bitmask
+ *
+ * This function handles the register updates to the direct access registers and
+ * the muxed registers while caching all register accesses, internally handling
+ * the correct state of the PORTSEL register and protecting the access to muxed
+ * registers.
+ * The caller must only use this function to change registers behind the PORTSEL mux.
+ *
+ * Return: 0 for successful request, else a corresponding error value
+ */
+static int cy8c95x0_regmap_update_bits(struct cy8c95x0_pinctrl *chip, unsigned int reg,
+                                      unsigned int port, unsigned int mask, unsigned int val)
+{
+       return cy8c95x0_regmap_update_bits_base(chip, reg, port, mask, val, NULL, false, false);
+}
+
+/**
+ * cy8c95x0_regmap_read() - reads a register using the regmap cache
+ * @chip: The pinctrl to work on
+ * @reg: The register to read from. Can be direct access or muxed register.
+ * @port: The port to be used for muxed registers or quick path direct access
+ *        registers. Otherwise unused.
+ * @read_val: Value read from hardware or cache
+ *
+ * This function handles the register reads from the direct access registers and
+ * the muxed registers while caching all register accesses, internally handling
+ * the correct state of the PORTSEL register and protecting the access to muxed
+ * registers.
+ * The caller must only use this function to read registers behind the PORTSEL mux.
+ *
+ * Return: 0 for successful request, else a corresponding error value
+ */
+static int cy8c95x0_regmap_read(struct cy8c95x0_pinctrl *chip, unsigned int reg,
+                               unsigned int port, unsigned int *read_val)
+{
+       struct regmap *regmap;
+       int off;
+
+       /* Registers behind the PORTSEL mux have their own regmap */
+       if (cy8c95x0_muxed_register(reg)) {
+               regmap = chip->muxed_regmap;
+               off = CY8C95X0_MUX_REGMAP_TO_OFFSET(reg, port);
+       } else {
+               regmap = chip->regmap;
+               /* Quick path direct access registers honor the port argument */
+               if (cy8c95x0_quick_path_register(reg))
+                       off = reg + port;
+               else
+                       off = reg;
+       }
+
+       return regmap_read(regmap, off, read_val);
+}
+
 static int cy8c95x0_write_regs_mask(struct cy8c95x0_pinctrl *chip, int reg,
                                    unsigned long *val, unsigned long *mask)
 {
        DECLARE_BITMAP(tval, MAX_LINE);
        int write_val;
        int ret = 0;
-       int i, off = 0;
+       int i;
        u8 bits;
 
        /* Add the 4 bit gap of Gport2 */
        bitmap_shift_left(tval, tval, 4, MAX_LINE);
        bitmap_replace(tval, tval, val, chip->shiftmask, BANK_SZ * 3);
 
-       mutex_lock(&chip->i2c_lock);
        for (i = 0; i < chip->nport; i++) {
                /* Skip over unused banks */
                bits = bitmap_get_value8(tmask, i * BANK_SZ);
                if (!bits)
                        continue;
 
-               switch (reg) {
-               /* Muxed registers */
-               case CY8C95X0_INTMASK:
-               case CY8C95X0_PWMSEL:
-               case CY8C95X0_INVERT:
-               case CY8C95X0_DIRECTION:
-               case CY8C95X0_DRV_PU:
-               case CY8C95X0_DRV_PD:
-               case CY8C95X0_DRV_ODH:
-               case CY8C95X0_DRV_ODL:
-               case CY8C95X0_DRV_PP_FAST:
-               case CY8C95X0_DRV_PP_SLOW:
-               case CY8C95X0_DRV_HIZ:
-                       ret = regmap_write(chip->regmap, CY8C95X0_PORTSEL, i);
-                       if (ret < 0)
-                               goto out;
-                       off = reg;
-                       break;
-               /* Direct access registers */
-               case CY8C95X0_INPUT:
-               case CY8C95X0_OUTPUT:
-               case CY8C95X0_INTSTATUS:
-                       off = reg + i;
-                       break;
-               default:
-                       ret = -EINVAL;
-                       goto out;
-               }
-
                write_val = bitmap_get_value8(tval, i * BANK_SZ);
 
-               ret = regmap_update_bits(chip->regmap, off, bits, write_val);
+               ret = cy8c95x0_regmap_update_bits(chip, reg, i, bits, write_val);
                if (ret < 0)
                        goto out;
        }
 out:
-       mutex_unlock(&chip->i2c_lock);
 
        if (ret < 0)
-               dev_err(chip->dev, "failed writing register %d: err %d\n", off, ret);
+               dev_err(chip->dev, "failed writing register %d, port %d: err %d\n", reg, i, ret);
 
        return ret;
 }
        DECLARE_BITMAP(tmp, MAX_LINE);
        int read_val;
        int ret = 0;
-       int i, off = 0;
+       int i;
        u8 bits;
 
        /* Add the 4 bit gap of Gport2 */
        bitmap_shift_left(tval, tval, 4, MAX_LINE);
        bitmap_replace(tval, tval, val, chip->shiftmask, BANK_SZ * 3);
 
-       mutex_lock(&chip->i2c_lock);
        for (i = 0; i < chip->nport; i++) {
                /* Skip over unused banks */
                bits = bitmap_get_value8(tmask, i * BANK_SZ);
                if (!bits)
                        continue;
 
-               switch (reg) {
-               /* Muxed registers */
-               case CY8C95X0_INTMASK:
-               case CY8C95X0_PWMSEL:
-               case CY8C95X0_INVERT:
-               case CY8C95X0_DIRECTION:
-               case CY8C95X0_DRV_PU:
-               case CY8C95X0_DRV_PD:
-               case CY8C95X0_DRV_ODH:
-               case CY8C95X0_DRV_ODL:
-               case CY8C95X0_DRV_PP_FAST:
-               case CY8C95X0_DRV_PP_SLOW:
-               case CY8C95X0_DRV_HIZ:
-                       ret = regmap_write(chip->regmap, CY8C95X0_PORTSEL, i);
-                       if (ret < 0)
-                               goto out;
-                       off = reg;
-                       break;
-               /* Direct access registers */
-               case CY8C95X0_INPUT:
-               case CY8C95X0_OUTPUT:
-               case CY8C95X0_INTSTATUS:
-                       off = reg + i;
-                       break;
-               default:
-                       ret = -EINVAL;
-                       goto out;
-               }
-
-               ret = regmap_read(chip->regmap, off, &read_val);
+               ret = cy8c95x0_regmap_read(chip, reg, i, &read_val);
                if (ret < 0)
                        goto out;
 
        bitmap_replace(val, tmp, tval, chip->shiftmask, MAX_LINE);
 
 out:
-       mutex_unlock(&chip->i2c_lock);
-
        if (ret < 0)
-               dev_err(chip->dev, "failed reading register %d: err %d\n", off, ret);
+               dev_err(chip->dev, "failed reading register %d, port %d: err %d\n", reg, i, ret);
 
        return ret;
 }
 {
        struct cy8c95x0_pinctrl *chip = gpiochip_get_data(gc);
        u8 port = cypress_get_port(chip, off);
-       u8 outreg = CY8C95X0_OUTPUT_(port);
        u8 bit = cypress_get_pin_mask(chip, off);
        int ret;
 
        /* Set output level */
-       ret = regmap_write_bits(chip->regmap, outreg, bit, val ? bit : 0);
+       ret = cy8c95x0_regmap_write_bits(chip, CY8C95X0_OUTPUT, port, bit, val ? bit : 0);
        if (ret)
                return ret;
 
 static int cy8c95x0_gpio_get_value(struct gpio_chip *gc, unsigned int off)
 {
        struct cy8c95x0_pinctrl *chip = gpiochip_get_data(gc);
-       u8 inreg = CY8C95X0_INPUT_(cypress_get_port(chip, off));
+       u8 port = cypress_get_port(chip, off);
        u8 bit = cypress_get_pin_mask(chip, off);
        u32 reg_val;
        int ret;
 
-       ret = regmap_read(chip->regmap, inreg, ®_val);
+       ret = cy8c95x0_regmap_read(chip, CY8C95X0_INPUT, port, ®_val);
        if (ret < 0) {
                /*
                 * NOTE:
                                    int val)
 {
        struct cy8c95x0_pinctrl *chip = gpiochip_get_data(gc);
-       u8 outreg = CY8C95X0_OUTPUT_(cypress_get_port(chip, off));
+       u8 port = cypress_get_port(chip, off);
        u8 bit = cypress_get_pin_mask(chip, off);
 
-       regmap_write_bits(chip->regmap, outreg, bit, val ? bit : 0);
+       cy8c95x0_regmap_write_bits(chip, CY8C95X0_OUTPUT, port, bit, val ? bit : 0);
 }
 
 static int cy8c95x0_gpio_get_direction(struct gpio_chip *gc, unsigned int off)
        u32 reg_val;
        int ret;
 
-       mutex_lock(&chip->i2c_lock);
-
-       ret = regmap_write(chip->regmap, CY8C95X0_PORTSEL, port);
-       if (ret < 0)
-               goto out;
-
-       ret = regmap_read(chip->regmap, CY8C95X0_DIRECTION, ®_val);
+       ret = cy8c95x0_regmap_read(chip, CY8C95X0_DIRECTION, port, ®_val);
        if (ret < 0)
                goto out;
 
-       mutex_unlock(&chip->i2c_lock);
-
        if (reg_val & bit)
                return GPIO_LINE_DIRECTION_IN;
 
        return GPIO_LINE_DIRECTION_OUT;
 out:
-       mutex_unlock(&chip->i2c_lock);
        return ret;
 }
 
        u16 arg = 0;
        int ret;
 
-       mutex_lock(&chip->i2c_lock);
-
-       /* Select port */
-       ret = regmap_write(chip->regmap, CY8C95X0_PORTSEL, port);
-       if (ret < 0)
-               goto out;
-
        switch (param) {
        case PIN_CONFIG_BIAS_PULL_UP:
                reg = CY8C95X0_DRV_PU;
                reg = CY8C95X0_PWMSEL;
                break;
        case PIN_CONFIG_OUTPUT:
-               reg = CY8C95X0_OUTPUT_(port);
+               reg = CY8C95X0_OUTPUT;
                break;
        case PIN_CONFIG_OUTPUT_ENABLE:
                reg = CY8C95X0_DIRECTION;
         * Writing 1 to one of the drive mode registers will automatically
         * clear conflicting set bits in the other drive mode registers.
         */
-       ret = regmap_read(chip->regmap, reg, ®_val);
+       ret = cy8c95x0_regmap_read(chip, reg, port, ®_val);
+       if (ret < 0)
+               goto out;
+
        if (reg_val & bit)
                arg = 1;
 
        *config = pinconf_to_config_packed(param, (u16)arg);
 out:
-       mutex_unlock(&chip->i2c_lock);
-
        return ret;
 }
 
        unsigned int reg;
        int ret;
 
-       mutex_lock(&chip->i2c_lock);
-
-       /* Select port */
-       ret = regmap_write(chip->regmap, CY8C95X0_PORTSEL, port);
-       if (ret < 0)
-               goto out;
-
        switch (param) {
        case PIN_CONFIG_BIAS_PULL_UP:
                __clear_bit(off, chip->push_pull);
         * Writing 1 to one of the drive mode registers will automatically
         * clear conflicting set bits in the other drive mode registers.
         */
-       ret = regmap_write_bits(chip->regmap, reg, bit, bit);
-
+       ret = cy8c95x0_regmap_write_bits(chip, reg, port, bit, bit);
 out:
-       mutex_unlock(&chip->i2c_lock);
        return ret;
 }
 
 {
        u8 port = cypress_get_port(chip, off);
        u8 bit = cypress_get_pin_mask(chip, off);
-       int ret;
 
-       /* Select port */
-       ret = regmap_write(chip->regmap, CY8C95X0_PORTSEL, port);
-       if (ret < 0)
-               return ret;
-
-       return regmap_write_bits(chip->regmap, CY8C95X0_PWMSEL, bit, mode ? bit : 0);
+       return cy8c95x0_regmap_write_bits(chip, CY8C95X0_PWMSEL, port, bit, mode ? bit : 0);
 }
 
 static int cy8c95x0_pinmux_mode(struct cy8c95x0_pinctrl *chip,
                return 0;
 
        /* Set direction to output & set output to 1 so that PWM can work */
-       ret = regmap_write_bits(chip->regmap, CY8C95X0_DIRECTION, bit, bit);
+       ret = cy8c95x0_regmap_write_bits(chip, CY8C95X0_DIRECTION, port, bit, bit);
        if (ret < 0)
                return ret;
 
-       return regmap_write_bits(chip->regmap, CY8C95X0_OUTPUT_(port), bit, bit);
+       return cy8c95x0_regmap_write_bits(chip, CY8C95X0_OUTPUT, port, bit, bit);
 }
 
 static int cy8c95x0_set_mux(struct pinctrl_dev *pctldev, unsigned int selector,
                            unsigned int group)
 {
        struct cy8c95x0_pinctrl *chip = pinctrl_dev_get_drvdata(pctldev);
-       int ret;
 
-       mutex_lock(&chip->i2c_lock);
-       ret = cy8c95x0_pinmux_mode(chip, selector, group);
-       mutex_unlock(&chip->i2c_lock);
-
-       return ret;
+       return cy8c95x0_pinmux_mode(chip, selector, group);
 }
 
 static int cy8c95x0_gpio_request_enable(struct pinctrl_dev *pctldev,
                                        unsigned int pin)
 {
        struct cy8c95x0_pinctrl *chip = pinctrl_dev_get_drvdata(pctldev);
-       int ret;
-
-       mutex_lock(&chip->i2c_lock);
-       ret = cy8c95x0_set_mode(chip, pin, false);
-       mutex_unlock(&chip->i2c_lock);
 
-       return ret;
+       return cy8c95x0_set_mode(chip, pin, false);
 }
 
 static int cy8c95x0_pinmux_direction(struct cy8c95x0_pinctrl *chip,
        u8 bit = cypress_get_pin_mask(chip, pin);
        int ret;
 
-       /* Select port... */
-       ret = regmap_write(chip->regmap, CY8C95X0_PORTSEL, port);
-       if (ret)
-               return ret;
-
-       /* ...then direction */
-       ret = regmap_write_bits(chip->regmap, CY8C95X0_DIRECTION, bit, input ? bit : 0);
+       ret = cy8c95x0_regmap_write_bits(chip, CY8C95X0_DIRECTION, port, bit, input ? bit : 0);
        if (ret)
                return ret;
 
         * the direction register isn't sufficient in Push-Pull mode.
         */
        if (input && test_bit(pin, chip->push_pull)) {
-               ret = regmap_write_bits(chip->regmap, CY8C95X0_DRV_HIZ, bit, bit);
+               ret = cy8c95x0_regmap_write_bits(chip, CY8C95X0_DRV_HIZ, port, bit, bit);
                if (ret)
                        return ret;
 
                                       unsigned int pin, bool input)
 {
        struct cy8c95x0_pinctrl *chip = pinctrl_dev_get_drvdata(pctldev);
-       int ret;
 
-       mutex_lock(&chip->i2c_lock);
-       ret = cy8c95x0_pinmux_direction(chip, pin, input);
-       mutex_unlock(&chip->i2c_lock);
-
-       return ret;
+       return cy8c95x0_pinmux_direction(chip, pin, input);
 }
 
 static const struct pinmux_ops cy8c95x0_pmxops = {
                gpiod_set_consumer_name(chip->gpio_reset, "CY8C95X0 RESET");
        }
 
+       /* Generic regmap for direct access registers */
        chip->regmap = devm_regmap_init_i2c(client, &cy8c95x0_i2c_regmap);
        if (IS_ERR(chip->regmap)) {
                ret = PTR_ERR(chip->regmap);
                goto err_exit;
        }
 
+       /* Port specific regmap behind PORTSEL mux */
+       chip->muxed_regmap = devm_regmap_init(&client->dev, &cy8c95x0_regmap_bus,
+                                             chip, &cy8c95x0_muxed_regmap);
+       if (IS_ERR(chip->muxed_regmap)) {
+               ret = dev_err_probe(&client->dev, PTR_ERR(chip->muxed_regmap),
+                                   "Failed to register muxed regmap\n");
+               goto err_exit;
+       }
+
        bitmap_zero(chip->push_pull, MAX_LINE);
        bitmap_zero(chip->shiftmask, MAX_LINE);
        bitmap_set(chip->shiftmask, 0, 20);