cregit-Linux how code gets into the kernel

Release 4.11 drivers/pinctrl/berlin/berlin.c

/*
 * Marvell Berlin SoC pinctrl core driver
 *
 * Copyright (C) 2014 Marvell Technology Group Ltd.
 *
 * Antoine Ténart <antoine.tenart@free-electrons.com>
 *
 * This file is licensed under the terms of the GNU General Public
 * License version 2. This program is licensed "as is" without any
 * warranty of any kind, whether express or implied.
 */

#include <linux/io.h>
#include <linux/mfd/syscon.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/of_address.h>
#include <linux/of_device.h>
#include <linux/pinctrl/pinctrl.h>
#include <linux/pinctrl/pinmux.h>
#include <linux/platform_device.h>
#include <linux/regmap.h>
#include <linux/slab.h>

#include "../core.h"
#include "../pinctrl-utils.h"
#include "berlin.h"


struct berlin_pinctrl {
	
struct regmap *regmap;
	
struct device *dev;
	
const struct berlin_pinctrl_desc *desc;
	
struct berlin_pinctrl_function *functions;
	
unsigned nfunctions;
	
struct pinctrl_dev *pctrl_dev;
};


static int berlin_pinctrl_get_group_count(struct pinctrl_dev *pctrl_dev) { struct berlin_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctrl_dev); return pctrl->desc->ngroups; }

Contributors

PersonTokensPropCommitsCommitProp
Antoine Ténart28100.00%1100.00%
Total28100.00%1100.00%


static const char *berlin_pinctrl_get_group_name(struct pinctrl_dev *pctrl_dev, unsigned group) { struct berlin_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctrl_dev); return pctrl->desc->groups[group].name; }

Contributors

PersonTokensPropCommitsCommitProp
Antoine Ténart38100.00%1100.00%
Total38100.00%1100.00%


static int berlin_pinctrl_dt_node_to_map(struct pinctrl_dev *pctrl_dev, struct device_node *node, struct pinctrl_map **map, unsigned *num_maps) { struct berlin_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctrl_dev); struct property *prop; const char *function_name, *group_name; unsigned reserved_maps = 0; int ret, ngroups; *map = NULL; *num_maps = 0; ret = of_property_read_string(node, "function", &function_name); if (ret) { dev_err(pctrl->dev, "missing function property in node %s\n", node->name); return -EINVAL; } ngroups = of_property_count_strings(node, "groups"); if (ngroups < 0) { dev_err(pctrl->dev, "missing groups property in node %s\n", node->name); return -EINVAL; } ret = pinctrl_utils_reserve_map(pctrl_dev, map, &reserved_maps, num_maps, ngroups); if (ret) { dev_err(pctrl->dev, "can't reserve map: %d\n", ret); return ret; } of_property_for_each_string(node, "groups", prop, group_name) { ret = pinctrl_utils_add_map_mux(pctrl_dev, map, &reserved_maps, num_maps, group_name, function_name); if (ret) { dev_err(pctrl->dev, "can't add map: %d\n", ret); return ret; } } return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Antoine Ténart227100.00%1100.00%
Total227100.00%1100.00%

static const struct pinctrl_ops berlin_pinctrl_ops = { .get_groups_count = &berlin_pinctrl_get_group_count, .get_group_name = &berlin_pinctrl_get_group_name, .dt_node_to_map = &berlin_pinctrl_dt_node_to_map, .dt_free_map = &pinctrl_utils_free_map, };
static int berlin_pinmux_get_functions_count(struct pinctrl_dev *pctrl_dev) { struct berlin_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctrl_dev); return pctrl->nfunctions; }

Contributors

PersonTokensPropCommitsCommitProp
Antoine Ténart26100.00%1100.00%
Total26100.00%1100.00%


static const char *berlin_pinmux_get_function_name(struct pinctrl_dev *pctrl_dev, unsigned function) { struct berlin_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctrl_dev); return pctrl->functions[function].name; }

Contributors

PersonTokensPropCommitsCommitProp
Antoine Ténart36100.00%1100.00%
Total36100.00%1100.00%


static int berlin_pinmux_get_function_groups(struct pinctrl_dev *pctrl_dev, unsigned function, const char * const **groups, unsigned * const num_groups) { struct berlin_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctrl_dev); *groups = pctrl->functions[function].groups; *num_groups = pctrl->functions[function].ngroups; return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Antoine Ténart64100.00%1100.00%
Total64100.00%1100.00%


static struct berlin_desc_function * berlin_pinctrl_find_function_by_name(struct berlin_pinctrl *pctrl, const struct berlin_desc_group *group, const char *fname) { struct berlin_desc_function *function = group->functions; while (function->name) { if (!strcmp(function->name, fname)) return function; function++; } return NULL; }

Contributors

PersonTokensPropCommitsCommitProp
Antoine Ténart62100.00%1100.00%
Total62100.00%1100.00%


static int berlin_pinmux_set(struct pinctrl_dev *pctrl_dev, unsigned function, unsigned group) { struct berlin_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctrl_dev); const struct berlin_desc_group *group_desc = pctrl->desc->groups + group; struct berlin_pinctrl_function *func = pctrl->functions + function; struct berlin_desc_function *function_desc = berlin_pinctrl_find_function_by_name(pctrl, group_desc, func->name); u32 mask, val; if (!function_desc) return -EINVAL; mask = GENMASK(group_desc->lsb + group_desc->bit_width - 1, group_desc->lsb); val = function_desc->muxval << group_desc->lsb; regmap_update_bits(pctrl->regmap, group_desc->offset, mask, val); return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Antoine Ténart12899.22%150.00%
Linus Walleij10.78%150.00%
Total129100.00%2100.00%

static const struct pinmux_ops berlin_pinmux_ops = { .get_functions_count = &berlin_pinmux_get_functions_count, .get_function_name = &berlin_pinmux_get_function_name, .get_function_groups = &berlin_pinmux_get_function_groups, .set_mux = &berlin_pinmux_set, };
static int berlin_pinctrl_add_function(struct berlin_pinctrl *pctrl, const char *name) { struct berlin_pinctrl_function *function = pctrl->functions; while (function->name) { if (!strcmp(function->name, name)) { function->ngroups++; return -EEXIST; } function++; } function->name = name; function->ngroups = 1; pctrl->nfunctions++; return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Antoine Ténart79100.00%1100.00%
Total79100.00%1100.00%


static int berlin_pinctrl_build_state(struct platform_device *pdev) { struct berlin_pinctrl *pctrl = platform_get_drvdata(pdev); struct berlin_desc_group const *desc_group; struct berlin_desc_function const *desc_function; int i, max_functions = 0; pctrl->nfunctions = 0; for (i = 0; i < pctrl->desc->ngroups; i++) { desc_group = pctrl->desc->groups + i; /* compute the maxiumum number of functions a group can have */ max_functions += 1 << (desc_group->bit_width + 1); } /* we will reallocate later */ pctrl->functions = devm_kzalloc(&pdev->dev, max_functions * sizeof(*pctrl->functions), GFP_KERNEL); if (!pctrl->functions) return -ENOMEM; /* register all functions */ for (i = 0; i < pctrl->desc->ngroups; i++) { desc_group = pctrl->desc->groups + i; desc_function = desc_group->functions; while (desc_function->name) { berlin_pinctrl_add_function(pctrl, desc_function->name); desc_function++; } } pctrl->functions = krealloc(pctrl->functions, pctrl->nfunctions * sizeof(*pctrl->functions), GFP_KERNEL); /* map functions to theirs groups */ for (i = 0; i < pctrl->desc->ngroups; i++) { desc_group = pctrl->desc->groups + i; desc_function = desc_group->functions; while (desc_function->name) { struct berlin_pinctrl_function *function = pctrl->functions; const char **groups; bool found = false; while (function->name) { if (!strcmp(desc_function->name, function->name)) { found = true; break; } function++; } if (!found) return -EINVAL; if (!function->groups) { function->groups = devm_kzalloc(&pdev->dev, function->ngroups * sizeof(char *), GFP_KERNEL); if (!function->groups) return -ENOMEM; } groups = function->groups; while (*groups) groups++; *groups = desc_group->name; desc_function++; } } return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Antoine Ténart381100.00%1100.00%
Total381100.00%1100.00%

static struct pinctrl_desc berlin_pctrl_desc = { .name = "berlin-pinctrl", .pctlops = &berlin_pinctrl_ops, .pmxops = &berlin_pinmux_ops, .owner = THIS_MODULE, };
int berlin_pinctrl_probe_regmap(struct platform_device *pdev, const struct berlin_pinctrl_desc *desc, struct regmap *regmap) { struct device *dev = &pdev->dev; struct berlin_pinctrl *pctrl; int ret; pctrl = devm_kzalloc(dev, sizeof(*pctrl), GFP_KERNEL); if (!pctrl) return -ENOMEM; platform_set_drvdata(pdev, pctrl); pctrl->regmap = regmap; pctrl->dev = &pdev->dev; pctrl->desc = desc; ret = berlin_pinctrl_build_state(pdev); if (ret) { dev_err(dev, "cannot build driver state: %d\n", ret); return ret; } pctrl->pctrl_dev = devm_pinctrl_register(dev, &berlin_pctrl_desc, pctrl); if (IS_ERR(pctrl->pctrl_dev)) { dev_err(dev, "failed to register pinctrl driver\n"); return PTR_ERR(pctrl->pctrl_dev); } return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Antoine Ténart14188.68%125.00%
Masahiro Yamada95.66%125.00%
JiSheng Zhang63.77%125.00%
Laxman Dewangan31.89%125.00%
Total159100.00%4100.00%


int berlin_pinctrl_probe(struct platform_device *pdev, const struct berlin_pinctrl_desc *desc) { struct device *dev = &pdev->dev; struct device_node *parent_np = of_get_parent(dev->of_node); struct regmap *regmap = syscon_node_to_regmap(parent_np); of_node_put(parent_np); if (IS_ERR(regmap)) return PTR_ERR(regmap); return berlin_pinctrl_probe_regmap(pdev, desc, regmap); }

Contributors

PersonTokensPropCommitsCommitProp
JiSheng Zhang76100.00%1100.00%
Total76100.00%1100.00%


Overall Contributors

PersonTokensPropCommitsCommitProp
Antoine Ténart137793.36%337.50%
JiSheng Zhang825.56%112.50%
Masahiro Yamada90.61%112.50%
Laxman Dewangan30.20%112.50%
Linus Walleij30.20%112.50%
Irina Tirdea10.07%112.50%
Total1475100.00%8100.00%
Information contained on this website is for historical information purposes only and does not indicate or represent copyright ownership.
Created with cregit.