pinctrl: support pinconfig on the U300
[firefly-linux-kernel-4.4.55.git] / drivers / pinctrl / pinctrl-u300.c
index fc4a281caba55817e2cab9d2cd691e557e58cabc..26eb8ccd72d5e350f0ca28c369191ad9194b3301 100644 (file)
@@ -19,6 +19,9 @@
 #include <linux/err.h>
 #include <linux/pinctrl/pinctrl.h>
 #include <linux/pinctrl/pinmux.h>
+#include <linux/pinctrl/pinconf.h>
+#include <linux/pinctrl/pinconf-generic.h>
+#include "pinctrl-coh901.h"
 
 /*
  * Register definitions for the U300 Padmux control registers in the
@@ -1044,12 +1047,69 @@ static struct pinctrl_gpio_range u300_gpio_ranges[] = {
        U300_GPIO_RANGE(25, 181, 1),
 };
 
+static struct pinctrl_gpio_range *u300_match_gpio_range(unsigned pin)
+{
+       int i;
+
+       for (i = 0; i < ARRAY_SIZE(u300_gpio_ranges); i++) {
+               struct pinctrl_gpio_range *range;
+
+               range = &u300_gpio_ranges[i];
+               if (pin >= range->pin_base &&
+                   pin <= (range->pin_base + range->npins - 1))
+                       return range;
+       }
+       return NULL;
+}
+
+int u300_pin_config_get(struct pinctrl_dev *pctldev,
+                       unsigned pin,
+                       unsigned long *config)
+{
+       struct pinctrl_gpio_range *range = u300_match_gpio_range(pin);
+
+       /* We get config for those pins we CAN get it for and that's it */
+       if (!range)
+               return -ENOTSUPP;
+
+       return u300_gpio_config_get(range->gc,
+                                   (pin - range->pin_base + range->base),
+                                   config);
+}
+
+int u300_pin_config_set(struct pinctrl_dev *pctldev,
+                       unsigned pin,
+                       unsigned long config)
+{
+       struct pinctrl_gpio_range *range = u300_match_gpio_range(pin);
+       int ret;
+
+       if (!range)
+               return -EINVAL;
+
+       /* Note: none of these configurations take any argument */
+       ret = u300_gpio_config_set(range->gc,
+                                  (pin - range->pin_base + range->base),
+                                  pinconf_to_config_param(config));
+       if (ret)
+               return ret;
+
+       return 0;
+}
+
+static struct pinconf_ops u300_pconf_ops = {
+       .is_generic = true,
+       .pin_config_get = u300_pin_config_get,
+       .pin_config_set = u300_pin_config_set,
+};
+
 static struct pinctrl_desc u300_pmx_desc = {
        .name = DRIVER_NAME,
        .pins = u300_pads,
        .npins = ARRAY_SIZE(u300_pads),
        .pctlops = &u300_pctrl_ops,
        .pmxops = &u300_pmx_ops,
+       .confops = &u300_pconf_ops,
        .owner = THIS_MODULE,
 };