pwm: rockchip: State of pwm clock should synchronize with pwm enabled state
[firefly-linux-kernel-4.4.55.git] / drivers / pinctrl / pinconf.c
index 596a2522a6b1750b2c4c94c22f7c4177847f5bb4..4dd7722f993552a4c8cd698cdc2f8d224dc337c4 100644 (file)
@@ -28,16 +28,8 @@ int pinconf_check_ops(struct pinctrl_dev *pctldev)
 {
        const struct pinconf_ops *ops = pctldev->desc->confops;
 
-       /* We must be able to read out pin status */
-       if (!ops->pin_config_get && !ops->pin_config_group_get) {
-               dev_err(pctldev->dev,
-                       "pinconf must be able to read out pin status\n");
-               return -EINVAL;
-       }
        /* We have to be able to config the pins in SOME way */
-       if (!ops->pin_config_set && !ops->pin_config_group_set
-               && !ops->pin_config_set_bulk
-               && !ops->pin_config_group_set_bulk) {
+       if (!ops->pin_config_set && !ops->pin_config_group_set) {
                dev_err(pctldev->dev,
                        "pinconf has to be able to set a pins config\n");
                return -EINVAL;
@@ -69,9 +61,9 @@ int pin_config_get_for_pin(struct pinctrl_dev *pctldev, unsigned pin,
        const struct pinconf_ops *ops = pctldev->desc->confops;
 
        if (!ops || !ops->pin_config_get) {
-               dev_err(pctldev->dev, "cannot get pin configuration, missing "
-                       "pin_config_get() function in driver\n");
-               return -EINVAL;
+               dev_dbg(pctldev->dev,
+                       "cannot get pin configuration, .pin_config_get missing in driver\n");
+               return -ENOTSUPP;
        }
 
        return ops->pin_config_get(pctldev, pin, config);
@@ -95,10 +87,10 @@ int pin_config_group_get(const char *dev_name, const char *pin_group,
        ops = pctldev->desc->confops;
 
        if (!ops || !ops->pin_config_group_get) {
-               dev_err(pctldev->dev, "cannot get configuration for pin "
+               dev_dbg(pctldev->dev, "cannot get configuration for pin "
                        "group, missing group config get function in "
                        "driver\n");
-               ret = -EINVAL;
+               ret = -ENOTSUPP;
                goto unlock;
        }
 
@@ -160,7 +152,7 @@ int pinconf_apply_setting(struct pinctrl_setting const *setting)
 {
        struct pinctrl_dev *pctldev = setting->pctldev;
        const struct pinconf_ops *ops = pctldev->desc->confops;
-       int ret, i;
+       int ret;
 
        if (!ops) {
                dev_err(pctldev->dev, "missing confops\n");
@@ -169,67 +161,36 @@ int pinconf_apply_setting(struct pinctrl_setting const *setting)
 
        switch (setting->type) {
        case PIN_MAP_TYPE_CONFIGS_PIN:
-               if (!ops->pin_config_set && !ops->pin_config_set_bulk) {
+               if (!ops->pin_config_set) {
                        dev_err(pctldev->dev, "missing pin_config_set op\n");
                        return -EINVAL;
                }
-               if (ops->pin_config_set_bulk) {
-                       ret = ops->pin_config_set_bulk(pctldev,
-                                       setting->data.configs.group_or_pin,
-                                       setting->data.configs.configs,
-                                       setting->data.configs.num_configs);
-                       if (ret < 0) {
-                               dev_err(pctldev->dev,
-                                       "pin_config_set_bulk op failed for pin %d\n",
-                                       setting->data.configs.group_or_pin);
-                               return ret;
-                       }
-               } else if (ops->pin_config_set) {
-                       for (i = 0; i < setting->data.configs.num_configs; i++) {
-                               ret = ops->pin_config_set(pctldev,
-                                                         setting->data.configs.group_or_pin,
-                                                         setting->data.configs.configs[i]);
-                               if (ret < 0) {
-                                       dev_err(pctldev->dev,
-                                               "pin_config_set op failed for pin %d config %08lx\n",
-                                               setting->data.configs.group_or_pin,
-                                               setting->data.configs.configs[i]);
-                                       return ret;
-                               }
-                       }
+               ret = ops->pin_config_set(pctldev,
+                               setting->data.configs.group_or_pin,
+                               setting->data.configs.configs,
+                               setting->data.configs.num_configs);
+               if (ret < 0) {
+                       dev_err(pctldev->dev,
+                               "pin_config_set op failed for pin %d\n",
+                               setting->data.configs.group_or_pin);
+                       return ret;
                }
                break;
        case PIN_MAP_TYPE_CONFIGS_GROUP:
-               if (!ops->pin_config_group_set &&
-                   !ops->pin_config_group_set_bulk) {
+               if (!ops->pin_config_group_set) {
                        dev_err(pctldev->dev,
                                "missing pin_config_group_set op\n");
                        return -EINVAL;
                }
-               if (ops->pin_config_group_set_bulk) {
-                       ret = ops->pin_config_group_set_bulk(pctldev,
-                                       setting->data.configs.group_or_pin,
-                                       setting->data.configs.configs,
-                                       setting->data.configs.num_configs);
-                       if (ret < 0) {
-                               dev_err(pctldev->dev,
-                                       "pin_config_group_set_bulk op failed for group %d\n",
-                                       setting->data.configs.group_or_pin);
-                               return ret;
-                       }
-               } else if (ops->pin_config_group_set) {
-                       for (i = 0; i < setting->data.configs.num_configs; i++) {
-                               ret = ops->pin_config_group_set(pctldev,
-                                       setting->data.configs.group_or_pin,
-                                       setting->data.configs.configs[i]);
-                               if (ret < 0) {
-                                       dev_err(pctldev->dev,
-                                               "pin_config_group_set op failed for group %d config %08lx\n",
-                                               setting->data.configs.group_or_pin,
-                                               setting->data.configs.configs[i]);
-                                       return ret;
-                               }
-                       }
+               ret = ops->pin_config_group_set(pctldev,
+                               setting->data.configs.group_or_pin,
+                               setting->data.configs.configs,
+                               setting->data.configs.num_configs);
+               if (ret < 0) {
+                       dev_err(pctldev->dev,
+                               "pin_config_group_set op failed for group %d\n",
+                               setting->data.configs.group_or_pin);
+                       return ret;
                }
                break;
        default:
@@ -241,18 +202,34 @@ int pinconf_apply_setting(struct pinctrl_setting const *setting)
 
 #ifdef CONFIG_DEBUG_FS
 
-void pinconf_show_map(struct seq_file *s, struct pinctrl_map const *map)
+static void pinconf_show_config(struct seq_file *s, struct pinctrl_dev *pctldev,
+                     unsigned long *configs, unsigned num_configs)
 {
-       struct pinctrl_dev *pctldev;
        const struct pinconf_ops *confops;
        int i;
 
-       pctldev = get_pinctrl_dev_from_devname(map->ctrl_dev_name);
        if (pctldev)
                confops = pctldev->desc->confops;
        else
                confops = NULL;
 
+       for (i = 0; i < num_configs; i++) {
+               seq_puts(s, "config ");
+               if (confops && confops->pin_config_config_dbg_show)
+                       confops->pin_config_config_dbg_show(pctldev, s,
+                                                           configs[i]);
+               else
+                       seq_printf(s, "%08lx", configs[i]);
+               seq_puts(s, "\n");
+       }
+}
+
+void pinconf_show_map(struct seq_file *s, struct pinctrl_map const *map)
+{
+       struct pinctrl_dev *pctldev;
+
+       pctldev = get_pinctrl_dev_from_devname(map->ctrl_dev_name);
+
        switch (map->type) {
        case PIN_MAP_TYPE_CONFIGS_PIN:
                seq_printf(s, "pin ");
@@ -266,15 +243,8 @@ void pinconf_show_map(struct seq_file *s, struct pinctrl_map const *map)
 
        seq_printf(s, "%s\n", map->data.configs.group_or_pin);
 
-       for (i = 0; i < map->data.configs.num_configs; i++) {
-               seq_printf(s, "config ");
-               if (confops && confops->pin_config_config_dbg_show)
-                       confops->pin_config_config_dbg_show(pctldev, s,
-                                               map->data.configs.configs[i]);
-               else
-                       seq_printf(s, "%08lx", map->data.configs.configs[i]);
-               seq_printf(s, "\n");
-       }
+       pinconf_show_config(s, pctldev, map->data.configs.configs,
+                           map->data.configs.num_configs);
 }
 
 void pinconf_show_setting(struct seq_file *s,
@@ -282,9 +252,7 @@ void pinconf_show_setting(struct seq_file *s,
 {
        struct pinctrl_dev *pctldev = setting->pctldev;
        const struct pinctrl_ops *pctlops = pctldev->desc->pctlops;
-       const struct pinconf_ops *confops = pctldev->desc->confops;
        struct pin_desc *desc;
-       int i;
 
        switch (setting->type) {
        case PIN_MAP_TYPE_CONFIGS_PIN:
@@ -308,17 +276,8 @@ void pinconf_show_setting(struct seq_file *s,
         * FIXME: We should really get the pin controler to dump the config
         * values, so they can be decoded to something meaningful.
         */
-       for (i = 0; i < setting->data.configs.num_configs; i++) {
-               seq_printf(s, " ");
-               if (confops && confops->pin_config_config_dbg_show)
-                       confops->pin_config_config_dbg_show(pctldev, s,
-                               setting->data.configs.configs[i]);
-               else
-                       seq_printf(s, "%08lx",
-                                  setting->data.configs.configs[i]);
-       }
-
-       seq_printf(s, "\n");
+       pinconf_show_config(s, pctldev, setting->data.configs.configs,
+                           setting->data.configs.num_configs);
 }
 
 static void pinconf_dump_pin(struct pinctrl_dev *pctldev,
@@ -327,7 +286,7 @@ static void pinconf_dump_pin(struct pinctrl_dev *pctldev,
        const struct pinconf_ops *ops = pctldev->desc->confops;
 
        /* no-op when not using generic pin config */
-       pinconf_generic_dump_pin(pctldev, s, pin);
+       pinconf_generic_dump_pins(pctldev, s, NULL, pin);
        if (ops && ops->pin_config_dbg_show)
                ops->pin_config_dbg_show(pctldev, s, pin);
 }
@@ -335,12 +294,8 @@ static void pinconf_dump_pin(struct pinctrl_dev *pctldev,
 static int pinconf_pins_show(struct seq_file *s, void *what)
 {
        struct pinctrl_dev *pctldev = s->private;
-       const struct pinconf_ops *ops = pctldev->desc->confops;
        unsigned i, pin;
 
-       if (!ops || !ops->pin_config_get)
-               return 0;
-
        seq_puts(s, "Pin config settings per pin\n");
        seq_puts(s, "Format: pin (name): configs\n");
 
@@ -376,7 +331,7 @@ static void pinconf_dump_group(struct pinctrl_dev *pctldev,
        const struct pinconf_ops *ops = pctldev->desc->confops;
 
        /* no-op when not using generic pin config */
-       pinconf_generic_dump_group(pctldev, s, gname);
+       pinconf_generic_dump_pins(pctldev, s, gname, 0);
        if (ops && ops->pin_config_group_dbg_show)
                ops->pin_config_group_dbg_show(pctldev, s, selector);
 }
@@ -385,13 +340,9 @@ static int pinconf_groups_show(struct seq_file *s, void *what)
 {
        struct pinctrl_dev *pctldev = s->private;
        const struct pinctrl_ops *pctlops = pctldev->desc->pctlops;
-       const struct pinconf_ops *ops = pctldev->desc->confops;
        unsigned ngroups = pctlops->get_groups_count(pctldev);
        unsigned selector = 0;
 
-       if (!ops || !ops->pin_config_group_get)
-               return 0;
-
        seq_puts(s, "Pin config settings per pin group\n");
        seq_puts(s, "Format: group (name): configs\n");
 
@@ -457,13 +408,10 @@ static int pinconf_dbg_config_print(struct seq_file *s, void *d)
 {
        struct pinctrl_maps *maps_node;
        const struct pinctrl_map *map;
-       struct pinctrl_dev *pctldev = NULL;
-       const struct pinconf_ops *confops = NULL;
-       const struct pinctrl_map_configs *configs;
+       const struct pinctrl_map *found = NULL;
+       struct pinctrl_dev *pctldev;
        struct dbg_cfg *dbg = &pinconf_dbg_conf;
-       int i, j;
-       bool found = false;
-       unsigned long config;
+       int i;
 
        mutex_lock(&pinctrl_maps_mutex);
 
@@ -476,19 +424,10 @@ static int pinconf_dbg_config_print(struct seq_file *s, void *d)
                if (strcmp(map->name, dbg->state_name))
                        continue;
 
-               for (j = 0; j < map->data.configs.num_configs; j++) {
-                       if (!strcmp(map->data.configs.group_or_pin,
-                                       dbg->pin_name)) {
-                               /*
-                                * We found the right pin / state, read the
-                                * config and he pctldev for later use
-                                */
-                               configs = &map->data.configs;
-                               pctldev = get_pinctrl_dev_from_devname
-                                       (map->ctrl_dev_name);
-                               found = true;
-                               break;
-                       }
+               if (!strcmp(map->data.configs.group_or_pin, dbg->pin_name)) {
+                       /* We found the right pin */
+                       found = map;
+                       break;
                }
        }
 
@@ -502,16 +441,11 @@ static int pinconf_dbg_config_print(struct seq_file *s, void *d)
                goto exit;
        }
 
-       config = *(configs->configs);
-       seq_printf(s, "Dev %s has config of %s in state %s: 0x%08lX\n",
-                       dbg->dev_name, dbg->pin_name,
-                       dbg->state_name, config);
-
-       if (pctldev)
-               confops = pctldev->desc->confops;
-
-       if (confops && confops->pin_config_config_dbg_show)
-               confops->pin_config_config_dbg_show(pctldev, s, config);
+       pctldev = get_pinctrl_dev_from_devname(found->ctrl_dev_name);
+       seq_printf(s, "Dev %s has config of %s in state %s:\n",
+                  dbg->dev_name, dbg->pin_name, dbg->state_name);
+       pinconf_show_config(s, pctldev, found->data.configs.configs,
+                           found->data.configs.num_configs);
 
 exit:
        mutex_unlock(&pinctrl_maps_mutex);
@@ -523,23 +457,25 @@ exit:
  * pinconf_dbg_config_write() - modify the pinctrl config in the pinctrl
  * map, of a dev/pin/state entry based on user entries to pinconf-config
  * @user_buf: contains the modification request with expected format:
- *     modify config_pin <devicename> <state> <pinname> <newvalue>
+ *     modify <config> <devicename> <state> <name> <newvalue>
  * modify is literal string, alternatives like add/delete not supported yet
- * config_pin is literal, alternatives like config_mux not supported yet
- * <devicename> <state> <pinname> are values that should match the pinctrl-maps
+ * <config> is the configuration to be changed. Supported configs are
+ *     "config_pin" or "config_group", alternatives like config_mux are not
+ *     supported yet.
+ * <devicename> <state> <name> are values that should match the pinctrl-maps
  * <newvalue> reflects the new config and is driver dependant
  */
-static int pinconf_dbg_config_write(struct file *file,
+static ssize_t pinconf_dbg_config_write(struct file *file,
        const char __user *user_buf, size_t count, loff_t *ppos)
 {
        struct pinctrl_maps *maps_node;
        const struct pinctrl_map *map;
-       struct pinctrl_dev *pctldev = NULL;
+       const struct pinctrl_map *found = NULL;
+       struct pinctrl_dev *pctldev;
        const struct pinconf_ops *confops = NULL;
        struct dbg_cfg *dbg = &pinconf_dbg_conf;
        const struct pinctrl_map_configs *configs;
        char config[MAX_NAME_LEN+1];
-       bool found = false;
        char buf[128];
        char *b = &buf[0];
        int buf_size;
@@ -547,7 +483,7 @@ static int pinconf_dbg_config_write(struct file *file,
        int i;
 
        /* Get userspace string and assure termination */
-       buf_size = min(count, (sizeof(buf)-1));
+       buf_size = min(count, sizeof(buf) - 1);
        if (copy_from_user(buf, user_buf, buf_size))
                return -EFAULT;
        buf[buf_size] = 0;
@@ -564,13 +500,19 @@ static int pinconf_dbg_config_write(struct file *file,
        if (strcmp(token, "modify"))
                return -EINVAL;
 
-       /* Get arg type: "config_pin" type supported so far */
+       /*
+        * Get arg type: "config_pin" and "config_group"
+        *                types are supported so far
+        */
        token = strsep(&b, " ");
        if (!token)
                return -EINVAL;
-       if (strcmp(token, "config_pin"))
+       if (!strcmp(token, "config_pin"))
+               dbg->map_type = PIN_MAP_TYPE_CONFIGS_PIN;
+       else if (!strcmp(token, "config_group"))
+               dbg->map_type = PIN_MAP_TYPE_CONFIGS_GROUP;
+       else
                return -EINVAL;
-       dbg->map_type = PIN_MAP_TYPE_CONFIGS_PIN;
 
        /* get arg 'device_name' */
        token = strsep(&b, " ");
@@ -617,10 +559,7 @@ static int pinconf_dbg_config_write(struct file *file,
 
                /*  we found the right pin / state, so overwrite config */
                if (!strcmp(map->data.configs.group_or_pin, dbg->pin_name)) {
-                       found = true;
-                       pctldev = get_pinctrl_dev_from_devname(
-                                       map->ctrl_dev_name);
-                       configs = &map->data.configs;
+                       found = map;
                        break;
                }
        }
@@ -630,10 +569,12 @@ static int pinconf_dbg_config_write(struct file *file,
                goto exit;
        }
 
+       pctldev = get_pinctrl_dev_from_devname(found->ctrl_dev_name);
        if (pctldev)
                confops = pctldev->desc->confops;
 
        if (confops && confops->pin_config_dbg_parse_modify) {
+               configs = &found->data.configs;
                for (i = 0; i < configs->num_configs; i++) {
                        confops->pin_config_dbg_parse_modify(pctldev,
                                                     config,