^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) * Utils functions to implement the pincontrol driver.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) * Copyright (c) 2013, NVIDIA Corporation.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) * Author: Laxman Dewangan <ldewangan@nvidia.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) * This program is free software; you can redistribute it and/or
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) * modify it under the terms of the GNU General Public License as
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) * published by the Free Software Foundation version 2.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) * This program is distributed "as is" WITHOUT ANY WARRANTY of any kind,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) * whether express or implied; without even the implied warranty of
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) * General Public License for more details.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) * You should have received a copy of the GNU General Public License
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) * along with this program; if not, write to the Free Software
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) * 02111-1307, USA
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) #include <linux/device.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) #include <linux/export.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) #include <linux/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) #include <linux/pinctrl/pinctrl.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) #include <linux/of.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) #include "core.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) #include "pinctrl-utils.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) int pinctrl_utils_reserve_map(struct pinctrl_dev *pctldev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) struct pinctrl_map **map, unsigned *reserved_maps,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) unsigned *num_maps, unsigned reserve)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) unsigned old_num = *reserved_maps;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) unsigned new_num = *num_maps + reserve;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) struct pinctrl_map *new_map;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) if (old_num >= new_num)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) new_map = krealloc(*map, sizeof(*new_map) * new_num, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) if (!new_map) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) dev_err(pctldev->dev, "krealloc(map) failed\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) memset(new_map + old_num, 0, (new_num - old_num) * sizeof(*new_map));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) *map = new_map;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) *reserved_maps = new_num;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) EXPORT_SYMBOL_GPL(pinctrl_utils_reserve_map);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) int pinctrl_utils_add_map_mux(struct pinctrl_dev *pctldev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) struct pinctrl_map **map, unsigned *reserved_maps,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) unsigned *num_maps, const char *group,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) const char *function)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) if (WARN_ON(*num_maps == *reserved_maps))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) return -ENOSPC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) (*map)[*num_maps].type = PIN_MAP_TYPE_MUX_GROUP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) (*map)[*num_maps].data.mux.group = group;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) (*map)[*num_maps].data.mux.function = function;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) (*num_maps)++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) EXPORT_SYMBOL_GPL(pinctrl_utils_add_map_mux);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) int pinctrl_utils_add_map_configs(struct pinctrl_dev *pctldev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) struct pinctrl_map **map, unsigned *reserved_maps,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) unsigned *num_maps, const char *group,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) unsigned long *configs, unsigned num_configs,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) enum pinctrl_map_type type)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) unsigned long *dup_configs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) if (WARN_ON(*num_maps == *reserved_maps))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) return -ENOSPC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) dup_configs = kmemdup(configs, num_configs * sizeof(*dup_configs),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) if (!dup_configs)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) (*map)[*num_maps].type = type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) (*map)[*num_maps].data.configs.group_or_pin = group;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) (*map)[*num_maps].data.configs.configs = dup_configs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) (*map)[*num_maps].data.configs.num_configs = num_configs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) (*num_maps)++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) EXPORT_SYMBOL_GPL(pinctrl_utils_add_map_configs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) int pinctrl_utils_add_config(struct pinctrl_dev *pctldev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) unsigned long **configs, unsigned *num_configs,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) unsigned long config)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) unsigned old_num = *num_configs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) unsigned new_num = old_num + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) unsigned long *new_configs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) new_configs = krealloc(*configs, sizeof(*new_configs) * new_num,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) if (!new_configs) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) dev_err(pctldev->dev, "krealloc(configs) failed\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) new_configs[old_num] = config;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) *configs = new_configs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) *num_configs = new_num;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) EXPORT_SYMBOL_GPL(pinctrl_utils_add_config);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) void pinctrl_utils_free_map(struct pinctrl_dev *pctldev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) struct pinctrl_map *map, unsigned num_maps)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) for (i = 0; i < num_maps; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) switch (map[i].type) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) case PIN_MAP_TYPE_CONFIGS_GROUP:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) case PIN_MAP_TYPE_CONFIGS_PIN:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) kfree(map[i].data.configs.configs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) kfree(map);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) EXPORT_SYMBOL_GPL(pinctrl_utils_free_map);