#include <linux/bitops.h>
 #include <linux/err.h>
 #include <linux/errno.h>
+#include <linux/init.h>
 #include <linux/io.h>
 #include <linux/ioport.h>
 #include <linux/kernel.h>
-#include <linux/init.h>
+#include <linux/math.h>
 #include <linux/of.h>
 #include <linux/of_device.h>
 #include <linux/pinctrl/machine.h>
                *maskp = (1 << crp->var_field_width[in_pos]) - 1;
                *posp = crp->reg_width;
                for (k = 0; k <= in_pos; k++)
-                       *posp -= crp->var_field_width[k];
+                       *posp -= abs(crp->var_field_width[k]);
        }
 }
 
                if (!r_width)
                        break;
 
-               for (bit_pos = 0; bit_pos < r_width; bit_pos += curr_width) {
+               for (bit_pos = 0; bit_pos < r_width; bit_pos += curr_width, m++) {
                        u32 ncomb;
                        u32 n;
 
-                       if (f_width)
+                       if (f_width) {
                                curr_width = f_width;
-                       else
-                               curr_width = config_reg->var_field_width[m];
+                       } else {
+                               curr_width = abs(config_reg->var_field_width[m]);
+                               if (config_reg->var_field_width[m] < 0)
+                                       continue;
+                       }
 
                        ncomb = 1 << curr_width;
                        for (n = 0; n < ncomb; n++) {
                                }
                        }
                        pos += ncomb;
-                       m++;
                }
                k++;
        }
 static void __init sh_pfc_check_cfg_reg(const char *drvname,
                                        const struct pinmux_cfg_reg *cfg_reg)
 {
-       unsigned int i, n, rw, fw;
+       unsigned int i, n, rw;
+       int fw;
 
        sh_pfc_check_reg(drvname, cfg_reg->reg,
                         GENMASK(cfg_reg->reg_width - 1, 0));
        }
 
        for (i = 0, n = 0, rw = 0; (fw = cfg_reg->var_field_width[i]); i++) {
-               if (fw > 3 && is0s(&cfg_reg->enum_ids[n], 1 << fw))
-                       sh_pfc_warn("reg 0x%x: reserved field [%u:%u] can be split to reduce table size\n",
-                                   cfg_reg->reg, rw, rw + fw - 1);
-               n += 1 << fw;
-               rw += fw;
+               if (fw < 0) {
+                       rw += -fw;
+               } else {
+                       if (is0s(&cfg_reg->enum_ids[n], 1 << fw))
+                               sh_pfc_warn("reg 0x%x: field [%u:%u] can be described as reserved\n",
+                                           cfg_reg->reg, rw, rw + fw - 1);
+                       n += 1 << fw;
+                       rw += fw;
+               }
        }
 
        if (rw != cfg_reg->reg_width)
 
 #define SET_NR_ENUM_IDS(n)
 #endif
        const u16 *enum_ids;
-       const u8 *var_field_width;
+       const s8 *var_field_width;
 };
 
 #define GROUP(...)     __VA_ARGS__
  *   - r_width: Width of the register (in bits)
  *   - f_widths: List of widths of the register fields (in bits), from left
  *               to right (i.e. MSB to LSB), wrapped using the GROUP() macro.
- *   - ids: For each register field (from left to right, i.e. MSB to LSB),
- *          2^f_widths[i] enum IDs must be specified, one for each possible
- *          combination of the register field bit values, all wrapped using
- *          the GROUP() macro.
+ *               Reserved fields are indicated by negating the field width.
+ *   - ids: For each non-reserved register field (from left to right, i.e. MSB
+ *          to LSB), 2^f_widths[i] enum IDs must be specified, one for each
+ *          possible combination of the register field bit values, all wrapped
+ *          using the GROUP() macro.
  */
 #define PINMUX_CFG_REG_VAR(name, r, r_width, f_widths, ids)            \
        .reg = r, .reg_width = r_width,                                 \
-       .var_field_width = (const u8 []) { f_widths, 0 },               \
+       .var_field_width = (const s8 []) { f_widths, 0 },               \
        SET_NR_ENUM_IDS(sizeof((const u16 []) { ids }) / sizeof(u16))   \
        .enum_ids = (const u16 []) { ids }