brintos

brintos / linux-shallow public Read only

0
0
Text · 3.2 KiB · b880e44 Raw
130 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/*3 * Utils functions to implement the pincontrol driver.4 *5 * Copyright (c) 2013, NVIDIA Corporation.6 *7 * Author: Laxman Dewangan <ldewangan@nvidia.com>8 */9#include <linux/array_size.h>10#include <linux/device.h>11#include <linux/export.h>12#include <linux/of.h>13#include <linux/slab.h>14 15#include <linux/pinctrl/pinctrl.h>16 17#include "core.h"18#include "pinctrl-utils.h"19 20int pinctrl_utils_reserve_map(struct pinctrl_dev *pctldev,21		struct pinctrl_map **map, unsigned int *reserved_maps,22		unsigned int *num_maps, unsigned int reserve)23{24	unsigned int old_num = *reserved_maps;25	unsigned int new_num = *num_maps + reserve;26	struct pinctrl_map *new_map;27 28	if (old_num >= new_num)29		return 0;30 31	new_map = krealloc_array(*map, new_num, sizeof(*new_map), GFP_KERNEL);32	if (!new_map) {33		dev_err(pctldev->dev, "krealloc(map) failed\n");34		return -ENOMEM;35	}36 37	memset(new_map + old_num, 0, (new_num - old_num) * sizeof(*new_map));38 39	*map = new_map;40	*reserved_maps = new_num;41	return 0;42}43EXPORT_SYMBOL_GPL(pinctrl_utils_reserve_map);44 45int pinctrl_utils_add_map_mux(struct pinctrl_dev *pctldev,46		struct pinctrl_map **map, unsigned int *reserved_maps,47		unsigned int *num_maps, const char *group,48		const char *function)49{50	if (WARN_ON(*num_maps == *reserved_maps))51		return -ENOSPC;52 53	(*map)[*num_maps].type = PIN_MAP_TYPE_MUX_GROUP;54	(*map)[*num_maps].data.mux.group = group;55	(*map)[*num_maps].data.mux.function = function;56	(*num_maps)++;57 58	return 0;59}60EXPORT_SYMBOL_GPL(pinctrl_utils_add_map_mux);61 62int pinctrl_utils_add_map_configs(struct pinctrl_dev *pctldev,63		struct pinctrl_map **map, unsigned int *reserved_maps,64		unsigned int *num_maps, const char *group,65		unsigned long *configs, unsigned int num_configs,66		enum pinctrl_map_type type)67{68	unsigned long *dup_configs;69 70	if (WARN_ON(*num_maps == *reserved_maps))71		return -ENOSPC;72 73	dup_configs = kmemdup_array(configs, num_configs,74				sizeof(*dup_configs), GFP_KERNEL);75	if (!dup_configs)76		return -ENOMEM;77 78	(*map)[*num_maps].type = type;79	(*map)[*num_maps].data.configs.group_or_pin = group;80	(*map)[*num_maps].data.configs.configs = dup_configs;81	(*map)[*num_maps].data.configs.num_configs = num_configs;82	(*num_maps)++;83 84	return 0;85}86EXPORT_SYMBOL_GPL(pinctrl_utils_add_map_configs);87 88int pinctrl_utils_add_config(struct pinctrl_dev *pctldev,89		unsigned long **configs, unsigned int *num_configs,90		unsigned long config)91{92	unsigned int old_num = *num_configs;93	unsigned int new_num = old_num + 1;94	unsigned long *new_configs;95 96	new_configs = krealloc(*configs, sizeof(*new_configs) * new_num,97			       GFP_KERNEL);98	if (!new_configs) {99		dev_err(pctldev->dev, "krealloc(configs) failed\n");100		return -ENOMEM;101	}102 103	new_configs[old_num] = config;104 105	*configs = new_configs;106	*num_configs = new_num;107 108	return 0;109}110EXPORT_SYMBOL_GPL(pinctrl_utils_add_config);111 112void pinctrl_utils_free_map(struct pinctrl_dev *pctldev,113	      struct pinctrl_map *map, unsigned int num_maps)114{115	int i;116 117	for (i = 0; i < num_maps; i++) {118		switch (map[i].type) {119		case PIN_MAP_TYPE_CONFIGS_GROUP:120		case PIN_MAP_TYPE_CONFIGS_PIN:121			kfree(map[i].data.configs.configs);122			break;123		default:124			break;125		}126	}127	kfree(map);128}129EXPORT_SYMBOL_GPL(pinctrl_utils_free_map);130