struct sunxi_pinctrl *pctl = platform_get_drvdata(pdev);
        int i;
 
-       pctl->ngroups = pctl->desc->npins;
+       /*
+        * Allocate groups
+        *
+        * We assume that the number of groups is the number of pins
+        * given in the data array.
 
-       /* Allocate groups */
+        * This will not always be true, since some pins might not be
+        * available in the current variant, but fortunately for us,
+        * this means that the number of pins is the maximum group
+        * number we will ever see.
+        */
        pctl->groups = devm_kzalloc(&pdev->dev,
-                                   pctl->ngroups * sizeof(*pctl->groups),
+                                   pctl->desc->npins * sizeof(*pctl->groups),
                                    GFP_KERNEL);
        if (!pctl->groups)
                return -ENOMEM;
 
        for (i = 0; i < pctl->desc->npins; i++) {
                const struct sunxi_desc_pin *pin = pctl->desc->pins + i;
-               struct sunxi_pinctrl_group *group = pctl->groups + i;
+               struct sunxi_pinctrl_group *group = pctl->groups + pctl->ngroups;
+
+               if (pin->variant && !(pctl->variant & pin->variant))
+                       continue;
 
                group->name = pin->pin.name;
                group->pin = pin->pin.number;
+
+               /* And now we count the actual number of pins / groups */
+               pctl->ngroups++;
        }
 
        /*
         * we'll reallocate that later anyway
         */
        pctl->functions = devm_kzalloc(&pdev->dev,
-                               pctl->desc->npins * sizeof(*pctl->functions),
-                               GFP_KERNEL);
+                                      pctl->ngroups * sizeof(*pctl->functions),
+                                      GFP_KERNEL);
        if (!pctl->functions)
                return -ENOMEM;
 
        /* Count functions and their associated groups */
        for (i = 0; i < pctl->desc->npins; i++) {
                const struct sunxi_desc_pin *pin = pctl->desc->pins + i;
-               struct sunxi_desc_function *func = pin->functions;
+               struct sunxi_desc_function *func;
+
+               if (pin->variant && !(pctl->variant & pin->variant))
+                       continue;
+
+               for (func = pin->functions; func->name; func++) {
+                       if (func->variant && !(pctl->variant & func->variant))
+                               continue;
 
-               while (func->name) {
                        /* Create interrupt mapping while we're at it */
                        if (!strcmp(func->name, "irq")) {
                                int irqnum = func->irqnum + func->irqbank * IRQ_PER_BANK;
                        }
 
                        sunxi_pinctrl_add_function(pctl, func->name);
-                       func++;
                }
        }
 
+       /* And now allocated and fill the array for real */
        pctl->functions = krealloc(pctl->functions,
-                               pctl->nfunctions * sizeof(*pctl->functions),
-                               GFP_KERNEL);
+                                  pctl->nfunctions * sizeof(*pctl->functions),
+                                  GFP_KERNEL);
+       if (!pctl->functions) {
+               kfree(pctl->functions);
+               return -ENOMEM;
+       }
 
        for (i = 0; i < pctl->desc->npins; i++) {
                const struct sunxi_desc_pin *pin = pctl->desc->pins + i;
-               struct sunxi_desc_function *func = pin->functions;
+               struct sunxi_desc_function *func;
 
-               while (func->name) {
+               if (pin->variant && !(pctl->variant & pin->variant))
+                       continue;
+
+               for (func = pin->functions; func->name; func++) {
                        struct sunxi_pinctrl_function *func_item;
                        const char **func_grp;
 
+                       if (func->variant && !(pctl->variant & func->variant))
+                               continue;
+
                        func_item = sunxi_pinctrl_find_function_by_name(pctl,
                                                                        func->name);
                        if (!func_item)
                                func_grp++;
 
                        *func_grp = pin->pin.name;
-                       func++;
                }
        }
 
        return 0;
 }
 
-int sunxi_pinctrl_init(struct platform_device *pdev,
-                      const struct sunxi_pinctrl_desc *desc)
+int sunxi_pinctrl_init_with_variant(struct platform_device *pdev,
+                                   const struct sunxi_pinctrl_desc *desc,
+                                   unsigned long variant)
 {
        struct device_node *node = pdev->dev.of_node;
        struct pinctrl_desc *pctrl_desc;
        struct pinctrl_pin_desc *pins;
        struct sunxi_pinctrl *pctl;
        struct resource *res;
-       int i, ret, last_pin;
+       int i, ret, last_pin, pin_idx;
        struct clk *clk;
 
        pctl = devm_kzalloc(&pdev->dev, sizeof(*pctl), GFP_KERNEL);
 
        pctl->dev = &pdev->dev;
        pctl->desc = desc;
+       pctl->variant = variant;
 
        pctl->irq_array = devm_kcalloc(&pdev->dev,
                                       IRQ_PER_BANK * pctl->desc->irq_banks,
        if (!pins)
                return -ENOMEM;
 
-       for (i = 0; i < pctl->desc->npins; i++)
-               pins[i] = pctl->desc->pins[i].pin;
+       for (i = 0, pin_idx = 0; i < pctl->desc->npins; i++) {
+               const struct sunxi_desc_pin *pin = pctl->desc->pins + i;
+
+               if (pin->variant && !(pctl->variant & pin->variant))
+                       continue;
+
+               pins[pin_idx++] = pin->pin;
+       }
 
        pctrl_desc = devm_kzalloc(&pdev->dev,
                                  sizeof(*pctrl_desc),
        pctrl_desc->name = dev_name(&pdev->dev);
        pctrl_desc->owner = THIS_MODULE;
        pctrl_desc->pins = pins;
-       pctrl_desc->npins = pctl->desc->npins;
+       pctrl_desc->npins = pctl->ngroups;
        pctrl_desc->confops = &sunxi_pconf_ops;
        pctrl_desc->pctlops = &sunxi_pctrl_ops;
        pctrl_desc->pmxops =  &sunxi_pmx_ops;
 
 #define SUN4I_FUNC_IRQ         6
 
 struct sunxi_desc_function {
+       unsigned long   variant;
        const char      *name;
        u8              muxval;
        u8              irqbank;
 
 struct sunxi_desc_pin {
        struct pinctrl_pin_desc         pin;
+       unsigned long                   variant;
        struct sunxi_desc_function      *functions;
 };
 
        unsigned                        *irq_array;
        spinlock_t                      lock;
        struct pinctrl_dev              *pctl_dev;
+       unsigned long                   variant;
 };
 
 #define SUNXI_PIN(_pin, ...)                                   \
                        __VA_ARGS__, { } },                     \
        }
 
+#define SUNXI_PIN_VARIANT(_pin, _variant, ...)                 \
+       {                                                       \
+               .pin = _pin,                                    \
+               .variant = _variant,                            \
+               .functions = (struct sunxi_desc_function[]){    \
+                       __VA_ARGS__, { } },                     \
+       }
+
 #define SUNXI_FUNCTION(_val, _name)                            \
        {                                                       \
                .name = _name,                                  \
                .muxval = _val,                                 \
        }
 
+#define SUNXI_FUNCTION_VARIANT(_val, _name, _variant)          \
+       {                                                       \
+               .name = _name,                                  \
+               .muxval = _val,                                 \
+               .variant = _variant,                            \
+       }
+
 #define SUNXI_FUNCTION_IRQ(_val, _irq)                         \
        {                                                       \
                .name = "irq",                                  \
        return irq_num * IRQ_STATUS_IRQ_BITS;
 }
 
-int sunxi_pinctrl_init(struct platform_device *pdev,
-                      const struct sunxi_pinctrl_desc *desc);
+int sunxi_pinctrl_init_with_variant(struct platform_device *pdev,
+                                   const struct sunxi_pinctrl_desc *desc,
+                                   unsigned long variant);
+
+#define sunxi_pinctrl_init(_dev, _desc) \
+       sunxi_pinctrl_init_with_variant(_dev, _desc, 0)
 
 #endif /* __PINCTRL_SUNXI_H */