Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * Core driver for the pin config portions of the pin control subsystem
0004  *
0005  * Copyright (C) 2011 ST-Ericsson SA
0006  * Written on behalf of Linaro for ST-Ericsson
0007  *
0008  * Author: Linus Walleij <linus.walleij@linaro.org>
0009  */
0010 #define pr_fmt(fmt) "pinconfig core: " fmt
0011 
0012 #include <linux/kernel.h>
0013 #include <linux/module.h>
0014 #include <linux/init.h>
0015 #include <linux/device.h>
0016 #include <linux/slab.h>
0017 #include <linux/debugfs.h>
0018 #include <linux/seq_file.h>
0019 #include <linux/pinctrl/machine.h>
0020 #include <linux/pinctrl/pinctrl.h>
0021 #include <linux/pinctrl/pinconf.h>
0022 #include "core.h"
0023 #include "pinconf.h"
0024 
0025 int pinconf_check_ops(struct pinctrl_dev *pctldev)
0026 {
0027     const struct pinconf_ops *ops = pctldev->desc->confops;
0028 
0029     /* We have to be able to config the pins in SOME way */
0030     if (!ops->pin_config_set && !ops->pin_config_group_set) {
0031         dev_err(pctldev->dev,
0032             "pinconf has to be able to set a pins config\n");
0033         return -EINVAL;
0034     }
0035     return 0;
0036 }
0037 
0038 int pinconf_validate_map(const struct pinctrl_map *map, int i)
0039 {
0040     if (!map->data.configs.group_or_pin) {
0041         pr_err("failed to register map %s (%d): no group/pin given\n",
0042                map->name, i);
0043         return -EINVAL;
0044     }
0045 
0046     if (!map->data.configs.num_configs ||
0047             !map->data.configs.configs) {
0048         pr_err("failed to register map %s (%d): no configs given\n",
0049                map->name, i);
0050         return -EINVAL;
0051     }
0052 
0053     return 0;
0054 }
0055 
0056 int pin_config_get_for_pin(struct pinctrl_dev *pctldev, unsigned pin,
0057                unsigned long *config)
0058 {
0059     const struct pinconf_ops *ops = pctldev->desc->confops;
0060 
0061     if (!ops || !ops->pin_config_get) {
0062         dev_dbg(pctldev->dev,
0063             "cannot get pin configuration, .pin_config_get missing in driver\n");
0064         return -ENOTSUPP;
0065     }
0066 
0067     return ops->pin_config_get(pctldev, pin, config);
0068 }
0069 
0070 int pin_config_group_get(const char *dev_name, const char *pin_group,
0071              unsigned long *config)
0072 {
0073     struct pinctrl_dev *pctldev;
0074     const struct pinconf_ops *ops;
0075     int selector, ret;
0076 
0077     pctldev = get_pinctrl_dev_from_devname(dev_name);
0078     if (!pctldev) {
0079         ret = -EINVAL;
0080         return ret;
0081     }
0082 
0083     mutex_lock(&pctldev->mutex);
0084 
0085     ops = pctldev->desc->confops;
0086 
0087     if (!ops || !ops->pin_config_group_get) {
0088         dev_dbg(pctldev->dev,
0089             "cannot get configuration for pin group, missing group config get function in driver\n");
0090         ret = -ENOTSUPP;
0091         goto unlock;
0092     }
0093 
0094     selector = pinctrl_get_group_selector(pctldev, pin_group);
0095     if (selector < 0) {
0096         ret = selector;
0097         goto unlock;
0098     }
0099 
0100     ret = ops->pin_config_group_get(pctldev, selector, config);
0101 
0102 unlock:
0103     mutex_unlock(&pctldev->mutex);
0104     return ret;
0105 }
0106 
0107 int pinconf_map_to_setting(const struct pinctrl_map *map,
0108               struct pinctrl_setting *setting)
0109 {
0110     struct pinctrl_dev *pctldev = setting->pctldev;
0111     int pin;
0112 
0113     switch (setting->type) {
0114     case PIN_MAP_TYPE_CONFIGS_PIN:
0115         pin = pin_get_from_name(pctldev,
0116                     map->data.configs.group_or_pin);
0117         if (pin < 0) {
0118             dev_err(pctldev->dev, "could not map pin config for \"%s\"",
0119                 map->data.configs.group_or_pin);
0120             return pin;
0121         }
0122         setting->data.configs.group_or_pin = pin;
0123         break;
0124     case PIN_MAP_TYPE_CONFIGS_GROUP:
0125         pin = pinctrl_get_group_selector(pctldev,
0126                      map->data.configs.group_or_pin);
0127         if (pin < 0) {
0128             dev_err(pctldev->dev, "could not map group config for \"%s\"",
0129                 map->data.configs.group_or_pin);
0130             return pin;
0131         }
0132         setting->data.configs.group_or_pin = pin;
0133         break;
0134     default:
0135         return -EINVAL;
0136     }
0137 
0138     setting->data.configs.num_configs = map->data.configs.num_configs;
0139     setting->data.configs.configs = map->data.configs.configs;
0140 
0141     return 0;
0142 }
0143 
0144 void pinconf_free_setting(const struct pinctrl_setting *setting)
0145 {
0146 }
0147 
0148 int pinconf_apply_setting(const struct pinctrl_setting *setting)
0149 {
0150     struct pinctrl_dev *pctldev = setting->pctldev;
0151     const struct pinconf_ops *ops = pctldev->desc->confops;
0152     int ret;
0153 
0154     if (!ops) {
0155         dev_err(pctldev->dev, "missing confops\n");
0156         return -EINVAL;
0157     }
0158 
0159     switch (setting->type) {
0160     case PIN_MAP_TYPE_CONFIGS_PIN:
0161         if (!ops->pin_config_set) {
0162             dev_err(pctldev->dev, "missing pin_config_set op\n");
0163             return -EINVAL;
0164         }
0165         ret = ops->pin_config_set(pctldev,
0166                 setting->data.configs.group_or_pin,
0167                 setting->data.configs.configs,
0168                 setting->data.configs.num_configs);
0169         if (ret < 0) {
0170             dev_err(pctldev->dev,
0171                 "pin_config_set op failed for pin %d\n",
0172                 setting->data.configs.group_or_pin);
0173             return ret;
0174         }
0175         break;
0176     case PIN_MAP_TYPE_CONFIGS_GROUP:
0177         if (!ops->pin_config_group_set) {
0178             dev_err(pctldev->dev,
0179                 "missing pin_config_group_set op\n");
0180             return -EINVAL;
0181         }
0182         ret = ops->pin_config_group_set(pctldev,
0183                 setting->data.configs.group_or_pin,
0184                 setting->data.configs.configs,
0185                 setting->data.configs.num_configs);
0186         if (ret < 0) {
0187             dev_err(pctldev->dev,
0188                 "pin_config_group_set op failed for group %d\n",
0189                 setting->data.configs.group_or_pin);
0190             return ret;
0191         }
0192         break;
0193     default:
0194         return -EINVAL;
0195     }
0196 
0197     return 0;
0198 }
0199 
0200 int pinconf_set_config(struct pinctrl_dev *pctldev, unsigned pin,
0201                unsigned long *configs, size_t nconfigs)
0202 {
0203     const struct pinconf_ops *ops;
0204 
0205     ops = pctldev->desc->confops;
0206     if (!ops || !ops->pin_config_set)
0207         return -ENOTSUPP;
0208 
0209     return ops->pin_config_set(pctldev, pin, configs, nconfigs);
0210 }
0211 
0212 #ifdef CONFIG_DEBUG_FS
0213 
0214 static void pinconf_show_config(struct seq_file *s, struct pinctrl_dev *pctldev,
0215               unsigned long *configs, unsigned num_configs)
0216 {
0217     const struct pinconf_ops *confops;
0218     int i;
0219 
0220     if (pctldev)
0221         confops = pctldev->desc->confops;
0222     else
0223         confops = NULL;
0224 
0225     for (i = 0; i < num_configs; i++) {
0226         seq_puts(s, "config ");
0227         if (confops && confops->pin_config_config_dbg_show)
0228             confops->pin_config_config_dbg_show(pctldev, s,
0229                                 configs[i]);
0230         else
0231             seq_printf(s, "%08lx", configs[i]);
0232         seq_putc(s, '\n');
0233     }
0234 }
0235 
0236 void pinconf_show_map(struct seq_file *s, const struct pinctrl_map *map)
0237 {
0238     struct pinctrl_dev *pctldev;
0239 
0240     pctldev = get_pinctrl_dev_from_devname(map->ctrl_dev_name);
0241 
0242     switch (map->type) {
0243     case PIN_MAP_TYPE_CONFIGS_PIN:
0244         seq_puts(s, "pin ");
0245         break;
0246     case PIN_MAP_TYPE_CONFIGS_GROUP:
0247         seq_puts(s, "group ");
0248         break;
0249     default:
0250         break;
0251     }
0252 
0253     seq_printf(s, "%s\n", map->data.configs.group_or_pin);
0254 
0255     pinconf_show_config(s, pctldev, map->data.configs.configs,
0256                 map->data.configs.num_configs);
0257 }
0258 
0259 void pinconf_show_setting(struct seq_file *s,
0260               const struct pinctrl_setting *setting)
0261 {
0262     struct pinctrl_dev *pctldev = setting->pctldev;
0263     const struct pinctrl_ops *pctlops = pctldev->desc->pctlops;
0264     struct pin_desc *desc;
0265 
0266     switch (setting->type) {
0267     case PIN_MAP_TYPE_CONFIGS_PIN:
0268         desc = pin_desc_get(setting->pctldev,
0269                     setting->data.configs.group_or_pin);
0270         seq_printf(s, "pin %s (%d)", desc->name,
0271                setting->data.configs.group_or_pin);
0272         break;
0273     case PIN_MAP_TYPE_CONFIGS_GROUP:
0274         seq_printf(s, "group %s (%d)",
0275                pctlops->get_group_name(pctldev,
0276                     setting->data.configs.group_or_pin),
0277                setting->data.configs.group_or_pin);
0278         break;
0279     default:
0280         break;
0281     }
0282 
0283     /*
0284      * FIXME: We should really get the pin controller to dump the config
0285      * values, so they can be decoded to something meaningful.
0286      */
0287     pinconf_show_config(s, pctldev, setting->data.configs.configs,
0288                 setting->data.configs.num_configs);
0289 }
0290 
0291 static void pinconf_dump_pin(struct pinctrl_dev *pctldev,
0292                  struct seq_file *s, int pin)
0293 {
0294     const struct pinconf_ops *ops = pctldev->desc->confops;
0295 
0296     /* no-op when not using generic pin config */
0297     pinconf_generic_dump_pins(pctldev, s, NULL, pin);
0298     if (ops && ops->pin_config_dbg_show)
0299         ops->pin_config_dbg_show(pctldev, s, pin);
0300 }
0301 
0302 static int pinconf_pins_show(struct seq_file *s, void *what)
0303 {
0304     struct pinctrl_dev *pctldev = s->private;
0305     unsigned i, pin;
0306 
0307     seq_puts(s, "Pin config settings per pin\n");
0308     seq_puts(s, "Format: pin (name): configs\n");
0309 
0310     mutex_lock(&pctldev->mutex);
0311 
0312     /* The pin number can be retrived from the pin controller descriptor */
0313     for (i = 0; i < pctldev->desc->npins; i++) {
0314         struct pin_desc *desc;
0315 
0316         pin = pctldev->desc->pins[i].number;
0317         desc = pin_desc_get(pctldev, pin);
0318         /* Skip if we cannot search the pin */
0319         if (!desc)
0320             continue;
0321 
0322         seq_printf(s, "pin %d (%s): ", pin, desc->name);
0323 
0324         pinconf_dump_pin(pctldev, s, pin);
0325         seq_putc(s, '\n');
0326     }
0327 
0328     mutex_unlock(&pctldev->mutex);
0329 
0330     return 0;
0331 }
0332 
0333 static void pinconf_dump_group(struct pinctrl_dev *pctldev,
0334                    struct seq_file *s, unsigned selector,
0335                    const char *gname)
0336 {
0337     const struct pinconf_ops *ops = pctldev->desc->confops;
0338 
0339     /* no-op when not using generic pin config */
0340     pinconf_generic_dump_pins(pctldev, s, gname, 0);
0341     if (ops && ops->pin_config_group_dbg_show)
0342         ops->pin_config_group_dbg_show(pctldev, s, selector);
0343 }
0344 
0345 static int pinconf_groups_show(struct seq_file *s, void *what)
0346 {
0347     struct pinctrl_dev *pctldev = s->private;
0348     const struct pinctrl_ops *pctlops = pctldev->desc->pctlops;
0349     unsigned ngroups = pctlops->get_groups_count(pctldev);
0350     unsigned selector = 0;
0351 
0352     seq_puts(s, "Pin config settings per pin group\n");
0353     seq_puts(s, "Format: group (name): configs\n");
0354 
0355     while (selector < ngroups) {
0356         const char *gname = pctlops->get_group_name(pctldev, selector);
0357 
0358         seq_printf(s, "%u (%s): ", selector, gname);
0359         pinconf_dump_group(pctldev, s, selector, gname);
0360         seq_putc(s, '\n');
0361         selector++;
0362     }
0363 
0364     return 0;
0365 }
0366 
0367 DEFINE_SHOW_ATTRIBUTE(pinconf_pins);
0368 DEFINE_SHOW_ATTRIBUTE(pinconf_groups);
0369 
0370 void pinconf_init_device_debugfs(struct dentry *devroot,
0371              struct pinctrl_dev *pctldev)
0372 {
0373     debugfs_create_file("pinconf-pins", 0444,
0374                 devroot, pctldev, &pinconf_pins_fops);
0375     debugfs_create_file("pinconf-groups", 0444,
0376                 devroot, pctldev, &pinconf_groups_fops);
0377 }
0378 
0379 #endif