382 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/*3 * Core driver for the pin config portions of the pin control subsystem4 *5 * Copyright (C) 2011 ST-Ericsson SA6 * Written on behalf of Linaro for ST-Ericsson7 *8 * Author: Linus Walleij <linus.walleij@linaro.org>9 */10#define pr_fmt(fmt) "pinconfig core: " fmt11 12#include <linux/array_size.h>13#include <linux/debugfs.h>14#include <linux/device.h>15#include <linux/init.h>16#include <linux/module.h>17#include <linux/seq_file.h>18#include <linux/slab.h>19 20#include <linux/pinctrl/machine.h>21#include <linux/pinctrl/pinconf.h>22#include <linux/pinctrl/pinctrl.h>23 24#include "core.h"25#include "pinconf.h"26 27int pinconf_check_ops(struct pinctrl_dev *pctldev)28{29 const struct pinconf_ops *ops = pctldev->desc->confops;30 31 /* We have to be able to config the pins in SOME way */32 if (!ops->pin_config_set && !ops->pin_config_group_set) {33 dev_err(pctldev->dev,34 "pinconf has to be able to set a pins config\n");35 return -EINVAL;36 }37 return 0;38}39 40int pinconf_validate_map(const struct pinctrl_map *map, int i)41{42 if (!map->data.configs.group_or_pin) {43 pr_err("failed to register map %s (%d): no group/pin given\n",44 map->name, i);45 return -EINVAL;46 }47 48 if (!map->data.configs.num_configs ||49 !map->data.configs.configs) {50 pr_err("failed to register map %s (%d): no configs given\n",51 map->name, i);52 return -EINVAL;53 }54 55 return 0;56}57 58int pin_config_get_for_pin(struct pinctrl_dev *pctldev, unsigned int pin,59 unsigned long *config)60{61 const struct pinconf_ops *ops = pctldev->desc->confops;62 63 if (!ops || !ops->pin_config_get) {64 dev_dbg(pctldev->dev,65 "cannot get pin configuration, .pin_config_get missing in driver\n");66 return -ENOTSUPP;67 }68 69 return ops->pin_config_get(pctldev, pin, config);70}71 72int pin_config_group_get(const char *dev_name, const char *pin_group,73 unsigned long *config)74{75 struct pinctrl_dev *pctldev;76 const struct pinconf_ops *ops;77 int selector, ret;78 79 pctldev = get_pinctrl_dev_from_devname(dev_name);80 if (!pctldev) {81 ret = -EINVAL;82 return ret;83 }84 85 mutex_lock(&pctldev->mutex);86 87 ops = pctldev->desc->confops;88 89 if (!ops || !ops->pin_config_group_get) {90 dev_dbg(pctldev->dev,91 "cannot get configuration for pin group, missing group config get function in driver\n");92 ret = -ENOTSUPP;93 goto unlock;94 }95 96 selector = pinctrl_get_group_selector(pctldev, pin_group);97 if (selector < 0) {98 ret = selector;99 goto unlock;100 }101 102 ret = ops->pin_config_group_get(pctldev, selector, config);103 104unlock:105 mutex_unlock(&pctldev->mutex);106 return ret;107}108 109int pinconf_map_to_setting(const struct pinctrl_map *map,110 struct pinctrl_setting *setting)111{112 struct pinctrl_dev *pctldev = setting->pctldev;113 int pin;114 115 switch (setting->type) {116 case PIN_MAP_TYPE_CONFIGS_PIN:117 pin = pin_get_from_name(pctldev,118 map->data.configs.group_or_pin);119 if (pin < 0) {120 dev_err(pctldev->dev, "could not map pin config for \"%s\"",121 map->data.configs.group_or_pin);122 return pin;123 }124 setting->data.configs.group_or_pin = pin;125 break;126 case PIN_MAP_TYPE_CONFIGS_GROUP:127 pin = pinctrl_get_group_selector(pctldev,128 map->data.configs.group_or_pin);129 if (pin < 0) {130 dev_err(pctldev->dev, "could not map group config for \"%s\"",131 map->data.configs.group_or_pin);132 return pin;133 }134 setting->data.configs.group_or_pin = pin;135 break;136 default:137 return -EINVAL;138 }139 140 setting->data.configs.num_configs = map->data.configs.num_configs;141 setting->data.configs.configs = map->data.configs.configs;142 143 return 0;144}145 146void pinconf_free_setting(const struct pinctrl_setting *setting)147{148}149 150int pinconf_apply_setting(const struct pinctrl_setting *setting)151{152 struct pinctrl_dev *pctldev = setting->pctldev;153 const struct pinconf_ops *ops = pctldev->desc->confops;154 int ret;155 156 if (!ops) {157 dev_err(pctldev->dev, "missing confops\n");158 return -EINVAL;159 }160 161 switch (setting->type) {162 case PIN_MAP_TYPE_CONFIGS_PIN:163 if (!ops->pin_config_set) {164 dev_err(pctldev->dev, "missing pin_config_set op\n");165 return -EINVAL;166 }167 ret = ops->pin_config_set(pctldev,168 setting->data.configs.group_or_pin,169 setting->data.configs.configs,170 setting->data.configs.num_configs);171 if (ret < 0) {172 dev_err(pctldev->dev,173 "pin_config_set op failed for pin %d\n",174 setting->data.configs.group_or_pin);175 return ret;176 }177 break;178 case PIN_MAP_TYPE_CONFIGS_GROUP:179 if (!ops->pin_config_group_set) {180 dev_err(pctldev->dev,181 "missing pin_config_group_set op\n");182 return -EINVAL;183 }184 ret = ops->pin_config_group_set(pctldev,185 setting->data.configs.group_or_pin,186 setting->data.configs.configs,187 setting->data.configs.num_configs);188 if (ret < 0) {189 dev_err(pctldev->dev,190 "pin_config_group_set op failed for group %d\n",191 setting->data.configs.group_or_pin);192 return ret;193 }194 break;195 default:196 return -EINVAL;197 }198 199 return 0;200}201 202int pinconf_set_config(struct pinctrl_dev *pctldev, unsigned int pin,203 unsigned long *configs, size_t nconfigs)204{205 const struct pinconf_ops *ops;206 207 ops = pctldev->desc->confops;208 if (!ops || !ops->pin_config_set)209 return -ENOTSUPP;210 211 return ops->pin_config_set(pctldev, pin, configs, nconfigs);212}213 214#ifdef CONFIG_DEBUG_FS215 216static void pinconf_show_config(struct seq_file *s, struct pinctrl_dev *pctldev,217 unsigned long *configs, unsigned int num_configs)218{219 const struct pinconf_ops *confops;220 int i;221 222 if (pctldev)223 confops = pctldev->desc->confops;224 else225 confops = NULL;226 227 for (i = 0; i < num_configs; i++) {228 seq_puts(s, "config ");229 if (confops && confops->pin_config_config_dbg_show)230 confops->pin_config_config_dbg_show(pctldev, s,231 configs[i]);232 else233 seq_printf(s, "%08lx", configs[i]);234 seq_putc(s, '\n');235 }236}237 238void pinconf_show_map(struct seq_file *s, const struct pinctrl_map *map)239{240 struct pinctrl_dev *pctldev;241 242 pctldev = get_pinctrl_dev_from_devname(map->ctrl_dev_name);243 244 switch (map->type) {245 case PIN_MAP_TYPE_CONFIGS_PIN:246 seq_puts(s, "pin ");247 break;248 case PIN_MAP_TYPE_CONFIGS_GROUP:249 seq_puts(s, "group ");250 break;251 default:252 break;253 }254 255 seq_printf(s, "%s\n", map->data.configs.group_or_pin);256 257 pinconf_show_config(s, pctldev, map->data.configs.configs,258 map->data.configs.num_configs);259}260 261void pinconf_show_setting(struct seq_file *s,262 const struct pinctrl_setting *setting)263{264 struct pinctrl_dev *pctldev = setting->pctldev;265 const struct pinctrl_ops *pctlops = pctldev->desc->pctlops;266 struct pin_desc *desc;267 268 switch (setting->type) {269 case PIN_MAP_TYPE_CONFIGS_PIN:270 desc = pin_desc_get(setting->pctldev,271 setting->data.configs.group_or_pin);272 seq_printf(s, "pin %s (%d)", desc->name,273 setting->data.configs.group_or_pin);274 break;275 case PIN_MAP_TYPE_CONFIGS_GROUP:276 seq_printf(s, "group %s (%d)",277 pctlops->get_group_name(pctldev,278 setting->data.configs.group_or_pin),279 setting->data.configs.group_or_pin);280 break;281 default:282 break;283 }284 285 /*286 * FIXME: We should really get the pin controller to dump the config287 * values, so they can be decoded to something meaningful.288 */289 pinconf_show_config(s, pctldev, setting->data.configs.configs,290 setting->data.configs.num_configs);291}292 293static void pinconf_dump_pin(struct pinctrl_dev *pctldev,294 struct seq_file *s, int pin)295{296 const struct pinconf_ops *ops = pctldev->desc->confops;297 298 /* no-op when not using generic pin config */299 pinconf_generic_dump_pins(pctldev, s, NULL, pin);300 if (ops && ops->pin_config_dbg_show)301 ops->pin_config_dbg_show(pctldev, s, pin);302}303 304static int pinconf_pins_show(struct seq_file *s, void *what)305{306 struct pinctrl_dev *pctldev = s->private;307 unsigned int i, pin;308 309 seq_puts(s, "Pin config settings per pin\n");310 seq_puts(s, "Format: pin (name): configs\n");311 312 mutex_lock(&pctldev->mutex);313 314 /* The pin number can be retrived from the pin controller descriptor */315 for (i = 0; i < pctldev->desc->npins; i++) {316 struct pin_desc *desc;317 318 pin = pctldev->desc->pins[i].number;319 desc = pin_desc_get(pctldev, pin);320 /* Skip if we cannot search the pin */321 if (!desc)322 continue;323 324 seq_printf(s, "pin %d (%s): ", pin, desc->name);325 326 pinconf_dump_pin(pctldev, s, pin);327 seq_putc(s, '\n');328 }329 330 mutex_unlock(&pctldev->mutex);331 332 return 0;333}334 335static void pinconf_dump_group(struct pinctrl_dev *pctldev,336 struct seq_file *s, unsigned int selector,337 const char *gname)338{339 const struct pinconf_ops *ops = pctldev->desc->confops;340 341 /* no-op when not using generic pin config */342 pinconf_generic_dump_pins(pctldev, s, gname, 0);343 if (ops && ops->pin_config_group_dbg_show)344 ops->pin_config_group_dbg_show(pctldev, s, selector);345}346 347static int pinconf_groups_show(struct seq_file *s, void *what)348{349 struct pinctrl_dev *pctldev = s->private;350 const struct pinctrl_ops *pctlops = pctldev->desc->pctlops;351 unsigned int ngroups = pctlops->get_groups_count(pctldev);352 unsigned int selector = 0;353 354 seq_puts(s, "Pin config settings per pin group\n");355 seq_puts(s, "Format: group (name): configs\n");356 357 while (selector < ngroups) {358 const char *gname = pctlops->get_group_name(pctldev, selector);359 360 seq_printf(s, "%u (%s): ", selector, gname);361 pinconf_dump_group(pctldev, s, selector, gname);362 seq_putc(s, '\n');363 selector++;364 }365 366 return 0;367}368 369DEFINE_SHOW_ATTRIBUTE(pinconf_pins);370DEFINE_SHOW_ATTRIBUTE(pinconf_groups);371 372void pinconf_init_device_debugfs(struct dentry *devroot,373 struct pinctrl_dev *pctldev)374{375 debugfs_create_file("pinconf-pins", 0444,376 devroot, pctldev, &pinconf_pins_fops);377 debugfs_create_file("pinconf-groups", 0444,378 devroot, pctldev, &pinconf_groups_fops);379}380 381#endif382