cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

pinctrl-aspeed.c (15941B)


      1// SPDX-License-Identifier: GPL-2.0-or-later
      2/*
      3 * Copyright (C) 2016 IBM Corp.
      4 */
      5
      6#include <linux/mfd/syscon.h>
      7#include <linux/platform_device.h>
      8#include <linux/slab.h>
      9#include <linux/string.h>
     10#include "../core.h"
     11#include "pinctrl-aspeed.h"
     12
     13int aspeed_pinctrl_get_groups_count(struct pinctrl_dev *pctldev)
     14{
     15	struct aspeed_pinctrl_data *pdata = pinctrl_dev_get_drvdata(pctldev);
     16
     17	return pdata->pinmux.ngroups;
     18}
     19
     20const char *aspeed_pinctrl_get_group_name(struct pinctrl_dev *pctldev,
     21		unsigned int group)
     22{
     23	struct aspeed_pinctrl_data *pdata = pinctrl_dev_get_drvdata(pctldev);
     24
     25	return pdata->pinmux.groups[group].name;
     26}
     27
     28int aspeed_pinctrl_get_group_pins(struct pinctrl_dev *pctldev,
     29				  unsigned int group, const unsigned int **pins,
     30				  unsigned int *npins)
     31{
     32	struct aspeed_pinctrl_data *pdata = pinctrl_dev_get_drvdata(pctldev);
     33
     34	*pins = &pdata->pinmux.groups[group].pins[0];
     35	*npins = pdata->pinmux.groups[group].npins;
     36
     37	return 0;
     38}
     39
     40void aspeed_pinctrl_pin_dbg_show(struct pinctrl_dev *pctldev,
     41				 struct seq_file *s, unsigned int offset)
     42{
     43	seq_printf(s, " %s", dev_name(pctldev->dev));
     44}
     45
     46int aspeed_pinmux_get_fn_count(struct pinctrl_dev *pctldev)
     47{
     48	struct aspeed_pinctrl_data *pdata = pinctrl_dev_get_drvdata(pctldev);
     49
     50	return pdata->pinmux.nfunctions;
     51}
     52
     53const char *aspeed_pinmux_get_fn_name(struct pinctrl_dev *pctldev,
     54				      unsigned int function)
     55{
     56	struct aspeed_pinctrl_data *pdata = pinctrl_dev_get_drvdata(pctldev);
     57
     58	return pdata->pinmux.functions[function].name;
     59}
     60
     61int aspeed_pinmux_get_fn_groups(struct pinctrl_dev *pctldev,
     62				unsigned int function,
     63				const char * const **groups,
     64				unsigned int * const num_groups)
     65{
     66	struct aspeed_pinctrl_data *pdata = pinctrl_dev_get_drvdata(pctldev);
     67
     68	*groups = pdata->pinmux.functions[function].groups;
     69	*num_groups = pdata->pinmux.functions[function].ngroups;
     70
     71	return 0;
     72}
     73
     74static int aspeed_sig_expr_enable(struct aspeed_pinmux_data *ctx,
     75				  const struct aspeed_sig_expr *expr)
     76{
     77	int ret;
     78
     79	pr_debug("Enabling signal %s for %s\n", expr->signal,
     80		 expr->function);
     81
     82	ret = aspeed_sig_expr_eval(ctx, expr, true);
     83	if (ret < 0)
     84		return ret;
     85
     86	if (!ret)
     87		return aspeed_sig_expr_set(ctx, expr, true);
     88
     89	return 0;
     90}
     91
     92static int aspeed_sig_expr_disable(struct aspeed_pinmux_data *ctx,
     93				   const struct aspeed_sig_expr *expr)
     94{
     95	int ret;
     96
     97	pr_debug("Disabling signal %s for %s\n", expr->signal,
     98		 expr->function);
     99
    100	ret = aspeed_sig_expr_eval(ctx, expr, true);
    101	if (ret < 0)
    102		return ret;
    103
    104	if (ret)
    105		return aspeed_sig_expr_set(ctx, expr, false);
    106
    107	return 0;
    108}
    109
    110/**
    111 * aspeed_disable_sig() - Disable a signal on a pin by disabling all provided
    112 * signal expressions.
    113 *
    114 * @ctx: The pinmux context
    115 * @exprs: The list of signal expressions (from a priority level on a pin)
    116 *
    117 * Return: 0 if all expressions are disabled, otherwise a negative error code
    118 */
    119static int aspeed_disable_sig(struct aspeed_pinmux_data *ctx,
    120			      const struct aspeed_sig_expr **exprs)
    121{
    122	int ret = 0;
    123
    124	if (!exprs)
    125		return true;
    126
    127	while (*exprs && !ret) {
    128		ret = aspeed_sig_expr_disable(ctx, *exprs);
    129		exprs++;
    130	}
    131
    132	return ret;
    133}
    134
    135/**
    136 * aspeed_find_expr_by_name - Search for the signal expression needed to
    137 * enable the pin's signal for the requested function.
    138 *
    139 * @exprs: List of signal expressions (haystack)
    140 * @name: The name of the requested function (needle)
    141 *
    142 * Return: A pointer to the signal expression whose function tag matches the
    143 * provided name, otherwise NULL.
    144 *
    145 */
    146static const struct aspeed_sig_expr *aspeed_find_expr_by_name(
    147		const struct aspeed_sig_expr **exprs, const char *name)
    148{
    149	while (*exprs) {
    150		if (strcmp((*exprs)->function, name) == 0)
    151			return *exprs;
    152		exprs++;
    153	}
    154
    155	return NULL;
    156}
    157
    158static char *get_defined_attribute(const struct aspeed_pin_desc *pdesc,
    159				   const char *(*get)(
    160					   const struct aspeed_sig_expr *))
    161{
    162	char *found = NULL;
    163	size_t len = 0;
    164	const struct aspeed_sig_expr ***prios, **funcs, *expr;
    165
    166	prios = pdesc->prios;
    167
    168	while ((funcs = *prios)) {
    169		while ((expr = *funcs)) {
    170			const char *str = get(expr);
    171			size_t delta = strlen(str) + 2;
    172			char *expanded;
    173
    174			expanded = krealloc(found, len + delta + 1, GFP_KERNEL);
    175			if (!expanded) {
    176				kfree(found);
    177				return expanded;
    178			}
    179
    180			found = expanded;
    181			found[len] = '\0';
    182			len += delta;
    183
    184			strcat(found, str);
    185			strcat(found, ", ");
    186
    187			funcs++;
    188		}
    189		prios++;
    190	}
    191
    192	if (len < 2) {
    193		kfree(found);
    194		return NULL;
    195	}
    196
    197	found[len - 2] = '\0';
    198
    199	return found;
    200}
    201
    202static const char *aspeed_sig_expr_function(const struct aspeed_sig_expr *expr)
    203{
    204	return expr->function;
    205}
    206
    207static char *get_defined_functions(const struct aspeed_pin_desc *pdesc)
    208{
    209	return get_defined_attribute(pdesc, aspeed_sig_expr_function);
    210}
    211
    212static const char *aspeed_sig_expr_signal(const struct aspeed_sig_expr *expr)
    213{
    214	return expr->signal;
    215}
    216
    217static char *get_defined_signals(const struct aspeed_pin_desc *pdesc)
    218{
    219	return get_defined_attribute(pdesc, aspeed_sig_expr_signal);
    220}
    221
    222int aspeed_pinmux_set_mux(struct pinctrl_dev *pctldev, unsigned int function,
    223			  unsigned int group)
    224{
    225	int i;
    226	int ret;
    227	struct aspeed_pinctrl_data *pdata = pinctrl_dev_get_drvdata(pctldev);
    228	const struct aspeed_pin_group *pgroup = &pdata->pinmux.groups[group];
    229	const struct aspeed_pin_function *pfunc =
    230		&pdata->pinmux.functions[function];
    231
    232	for (i = 0; i < pgroup->npins; i++) {
    233		int pin = pgroup->pins[i];
    234		const struct aspeed_pin_desc *pdesc = pdata->pins[pin].drv_data;
    235		const struct aspeed_sig_expr *expr = NULL;
    236		const struct aspeed_sig_expr **funcs;
    237		const struct aspeed_sig_expr ***prios;
    238
    239		if (!pdesc)
    240			return -EINVAL;
    241
    242		pr_debug("Muxing pin %s for %s\n", pdesc->name, pfunc->name);
    243
    244		prios = pdesc->prios;
    245
    246		if (!prios)
    247			continue;
    248
    249		/* Disable functions at a higher priority than that requested */
    250		while ((funcs = *prios)) {
    251			expr = aspeed_find_expr_by_name(funcs, pfunc->name);
    252
    253			if (expr)
    254				break;
    255
    256			ret = aspeed_disable_sig(&pdata->pinmux, funcs);
    257			if (ret)
    258				return ret;
    259
    260			prios++;
    261		}
    262
    263		if (!expr) {
    264			char *functions = get_defined_functions(pdesc);
    265			char *signals = get_defined_signals(pdesc);
    266
    267			pr_warn("No function %s found on pin %s (%d). Found signal(s) %s for function(s) %s\n",
    268				pfunc->name, pdesc->name, pin, signals,
    269				functions);
    270			kfree(signals);
    271			kfree(functions);
    272
    273			return -ENXIO;
    274		}
    275
    276		ret = aspeed_sig_expr_enable(&pdata->pinmux, expr);
    277		if (ret)
    278			return ret;
    279
    280		pr_debug("Muxed pin %s as %s for %s\n", pdesc->name, expr->signal,
    281			 expr->function);
    282	}
    283
    284	return 0;
    285}
    286
    287static bool aspeed_expr_is_gpio(const struct aspeed_sig_expr *expr)
    288{
    289	/*
    290	 * We need to differentiate between GPIO and non-GPIO signals to
    291	 * implement the gpio_request_enable() interface. For better or worse
    292	 * the ASPEED pinctrl driver uses the expression names to determine
    293	 * whether an expression will mux a pin for GPIO.
    294	 *
    295	 * Generally we have the following - A GPIO such as B1 has:
    296	 *
    297	 *    - expr->signal set to "GPIOB1"
    298	 *    - expr->function set to "GPIOB1"
    299	 *
    300	 * Using this fact we can determine whether the provided expression is
    301	 * a GPIO expression by testing the signal name for the string prefix
    302	 * "GPIO".
    303	 *
    304	 * However, some GPIOs are input-only, and the ASPEED datasheets name
    305	 * them differently. An input-only GPIO such as T0 has:
    306	 *
    307	 *    - expr->signal set to "GPIT0"
    308	 *    - expr->function set to "GPIT0"
    309	 *
    310	 * It's tempting to generalise the prefix test from "GPIO" to "GPI" to
    311	 * account for both GPIOs and GPIs, but in doing so we run aground on
    312	 * another feature:
    313	 *
    314	 * Some pins in the ASPEED BMC SoCs have a "pass-through" GPIO
    315	 * function where the input state of one pin is replicated as the
    316	 * output state of another (as if they were shorted together - a mux
    317	 * configuration that is typically enabled by hardware strapping).
    318	 * This feature allows the BMC to pass e.g. power button state through
    319	 * to the host while the BMC is yet to boot, but take control of the
    320	 * button state once the BMC has booted by muxing each pin as a
    321	 * separate, pin-specific GPIO.
    322	 *
    323	 * Conceptually this pass-through mode is a form of GPIO and is named
    324	 * as such in the datasheets, e.g. "GPID0". This naming similarity
    325	 * trips us up with the simple GPI-prefixed-signal-name scheme
    326	 * discussed above, as the pass-through configuration is not what we
    327	 * want when muxing a pin as GPIO for the GPIO subsystem.
    328	 *
    329	 * On e.g. the AST2400, a pass-through function "GPID0" is grouped on
    330	 * balls A18 and D16, where we have:
    331	 *
    332	 *    For ball A18:
    333	 *    - expr->signal set to "GPID0IN"
    334	 *    - expr->function set to "GPID0"
    335	 *
    336	 *    For ball D16:
    337	 *    - expr->signal set to "GPID0OUT"
    338	 *    - expr->function set to "GPID0"
    339	 *
    340	 * By contrast, the pin-specific GPIO expressions for the same pins are
    341	 * as follows:
    342	 *
    343	 *    For ball A18:
    344	 *    - expr->signal looks like "GPIOD0"
    345	 *    - expr->function looks like "GPIOD0"
    346	 *
    347	 *    For ball D16:
    348	 *    - expr->signal looks like "GPIOD1"
    349	 *    - expr->function looks like "GPIOD1"
    350	 *
    351	 * Testing both the signal _and_ function names gives us the means
    352	 * differentiate the pass-through GPIO pinmux configuration from the
    353	 * pin-specific configuration that the GPIO subsystem is after: An
    354	 * expression is a pin-specific (non-pass-through) GPIO configuration
    355	 * if the signal prefix is "GPI" and the signal name matches the
    356	 * function name.
    357	 */
    358	return !strncmp(expr->signal, "GPI", 3) &&
    359			!strcmp(expr->signal, expr->function);
    360}
    361
    362static bool aspeed_gpio_in_exprs(const struct aspeed_sig_expr **exprs)
    363{
    364	if (!exprs)
    365		return false;
    366
    367	while (*exprs) {
    368		if (aspeed_expr_is_gpio(*exprs))
    369			return true;
    370		exprs++;
    371	}
    372
    373	return false;
    374}
    375
    376int aspeed_gpio_request_enable(struct pinctrl_dev *pctldev,
    377			       struct pinctrl_gpio_range *range,
    378			       unsigned int offset)
    379{
    380	int ret;
    381	struct aspeed_pinctrl_data *pdata = pinctrl_dev_get_drvdata(pctldev);
    382	const struct aspeed_pin_desc *pdesc = pdata->pins[offset].drv_data;
    383	const struct aspeed_sig_expr ***prios, **funcs, *expr;
    384
    385	if (!pdesc)
    386		return -EINVAL;
    387
    388	prios = pdesc->prios;
    389
    390	if (!prios)
    391		return -ENXIO;
    392
    393	pr_debug("Muxing pin %s for GPIO\n", pdesc->name);
    394
    395	/* Disable any functions of higher priority than GPIO */
    396	while ((funcs = *prios)) {
    397		if (aspeed_gpio_in_exprs(funcs))
    398			break;
    399
    400		ret = aspeed_disable_sig(&pdata->pinmux, funcs);
    401		if (ret)
    402			return ret;
    403
    404		prios++;
    405	}
    406
    407	if (!funcs) {
    408		char *signals = get_defined_signals(pdesc);
    409
    410		pr_warn("No GPIO signal type found on pin %s (%d). Found: %s\n",
    411			pdesc->name, offset, signals);
    412		kfree(signals);
    413
    414		return -ENXIO;
    415	}
    416
    417	expr = *funcs;
    418
    419	/*
    420	 * Disabling all higher-priority expressions is enough to enable the
    421	 * lowest-priority signal type. As such it has no associated
    422	 * expression.
    423	 */
    424	if (!expr) {
    425		pr_debug("Muxed pin %s as GPIO\n", pdesc->name);
    426		return 0;
    427	}
    428
    429	/*
    430	 * If GPIO is not the lowest priority signal type, assume there is only
    431	 * one expression defined to enable the GPIO function
    432	 */
    433	ret = aspeed_sig_expr_enable(&pdata->pinmux, expr);
    434	if (ret)
    435		return ret;
    436
    437	pr_debug("Muxed pin %s as %s\n", pdesc->name, expr->signal);
    438
    439	return 0;
    440}
    441
    442int aspeed_pinctrl_probe(struct platform_device *pdev,
    443			 struct pinctrl_desc *pdesc,
    444			 struct aspeed_pinctrl_data *pdata)
    445{
    446	struct device *parent;
    447	struct pinctrl_dev *pctl;
    448
    449	parent = pdev->dev.parent;
    450	if (!parent) {
    451		dev_err(&pdev->dev, "No parent for syscon pincontroller\n");
    452		return -ENODEV;
    453	}
    454
    455	pdata->scu = syscon_node_to_regmap(parent->of_node);
    456	if (IS_ERR(pdata->scu)) {
    457		dev_err(&pdev->dev, "No regmap for syscon pincontroller parent\n");
    458		return PTR_ERR(pdata->scu);
    459	}
    460
    461	pdata->pinmux.maps[ASPEED_IP_SCU] = pdata->scu;
    462
    463	pctl = pinctrl_register(pdesc, &pdev->dev, pdata);
    464
    465	if (IS_ERR(pctl)) {
    466		dev_err(&pdev->dev, "Failed to register pinctrl\n");
    467		return PTR_ERR(pctl);
    468	}
    469
    470	platform_set_drvdata(pdev, pdata);
    471
    472	return 0;
    473}
    474
    475static inline bool pin_in_config_range(unsigned int offset,
    476		const struct aspeed_pin_config *config)
    477{
    478	return offset >= config->pins[0] && offset <= config->pins[1];
    479}
    480
    481static inline const struct aspeed_pin_config *find_pinconf_config(
    482		const struct aspeed_pinctrl_data *pdata,
    483		unsigned int offset,
    484		enum pin_config_param param)
    485{
    486	unsigned int i;
    487
    488	for (i = 0; i < pdata->nconfigs; i++) {
    489		if (param == pdata->configs[i].param &&
    490				pin_in_config_range(offset, &pdata->configs[i]))
    491			return &pdata->configs[i];
    492	}
    493
    494	return NULL;
    495}
    496
    497enum aspeed_pin_config_map_type { MAP_TYPE_ARG, MAP_TYPE_VAL };
    498
    499static const struct aspeed_pin_config_map *find_pinconf_map(
    500		const struct aspeed_pinctrl_data *pdata,
    501		enum pin_config_param param,
    502		enum aspeed_pin_config_map_type type,
    503		s64 value)
    504{
    505	int i;
    506
    507	for (i = 0; i < pdata->nconfmaps; i++) {
    508		const struct aspeed_pin_config_map *elem;
    509		bool match;
    510
    511		elem = &pdata->confmaps[i];
    512
    513		switch (type) {
    514		case MAP_TYPE_ARG:
    515			match = (elem->arg == -1 || elem->arg == value);
    516			break;
    517		case MAP_TYPE_VAL:
    518			match = (elem->val == value);
    519			break;
    520		}
    521
    522		if (param == elem->param && match)
    523			return elem;
    524	}
    525
    526	return NULL;
    527}
    528
    529int aspeed_pin_config_get(struct pinctrl_dev *pctldev, unsigned int offset,
    530		unsigned long *config)
    531{
    532	const enum pin_config_param param = pinconf_to_config_param(*config);
    533	const struct aspeed_pin_config_map *pmap;
    534	const struct aspeed_pinctrl_data *pdata;
    535	const struct aspeed_pin_config *pconf;
    536	unsigned int val;
    537	int rc = 0;
    538	u32 arg;
    539
    540	pdata = pinctrl_dev_get_drvdata(pctldev);
    541	pconf = find_pinconf_config(pdata, offset, param);
    542	if (!pconf)
    543		return -ENOTSUPP;
    544
    545	rc = regmap_read(pdata->scu, pconf->reg, &val);
    546	if (rc < 0)
    547		return rc;
    548
    549	pmap = find_pinconf_map(pdata, param, MAP_TYPE_VAL,
    550			(val & pconf->mask) >> __ffs(pconf->mask));
    551
    552	if (!pmap)
    553		return -EINVAL;
    554
    555	if (param == PIN_CONFIG_DRIVE_STRENGTH)
    556		arg = (u32) pmap->arg;
    557	else if (param == PIN_CONFIG_BIAS_PULL_DOWN)
    558		arg = !!pmap->arg;
    559	else
    560		arg = 1;
    561
    562	if (!arg)
    563		return -EINVAL;
    564
    565	*config = pinconf_to_config_packed(param, arg);
    566
    567	return 0;
    568}
    569
    570int aspeed_pin_config_set(struct pinctrl_dev *pctldev, unsigned int offset,
    571		unsigned long *configs, unsigned int num_configs)
    572{
    573	const struct aspeed_pinctrl_data *pdata;
    574	unsigned int i;
    575	int rc = 0;
    576
    577	pdata = pinctrl_dev_get_drvdata(pctldev);
    578
    579	for (i = 0; i < num_configs; i++) {
    580		const struct aspeed_pin_config_map *pmap;
    581		const struct aspeed_pin_config *pconf;
    582		enum pin_config_param param;
    583		unsigned int val;
    584		u32 arg;
    585
    586		param = pinconf_to_config_param(configs[i]);
    587		arg = pinconf_to_config_argument(configs[i]);
    588
    589		pconf = find_pinconf_config(pdata, offset, param);
    590		if (!pconf)
    591			return -ENOTSUPP;
    592
    593		pmap = find_pinconf_map(pdata, param, MAP_TYPE_ARG, arg);
    594
    595		if (WARN_ON(!pmap))
    596			return -EINVAL;
    597
    598		val = pmap->val << __ffs(pconf->mask);
    599
    600		rc = regmap_update_bits(pdata->scu, pconf->reg,
    601					pconf->mask, val);
    602
    603		if (rc < 0)
    604			return rc;
    605
    606		pr_debug("%s: Set SCU%02X[0x%08X]=0x%X for param %d(=%d) on pin %d\n",
    607				__func__, pconf->reg, pconf->mask,
    608				val, param, arg, offset);
    609	}
    610
    611	return 0;
    612}
    613
    614int aspeed_pin_config_group_get(struct pinctrl_dev *pctldev,
    615		unsigned int selector,
    616		unsigned long *config)
    617{
    618	const unsigned int *pins;
    619	unsigned int npins;
    620	int rc;
    621
    622	rc = aspeed_pinctrl_get_group_pins(pctldev, selector, &pins, &npins);
    623	if (rc < 0)
    624		return rc;
    625
    626	if (!npins)
    627		return -ENODEV;
    628
    629	rc = aspeed_pin_config_get(pctldev, pins[0], config);
    630
    631	return rc;
    632}
    633
    634int aspeed_pin_config_group_set(struct pinctrl_dev *pctldev,
    635		unsigned int selector,
    636		unsigned long *configs,
    637		unsigned int num_configs)
    638{
    639	const unsigned int *pins;
    640	unsigned int npins;
    641	int rc;
    642	int i;
    643
    644	pr_debug("%s: Fetching pins for group selector %d\n",
    645			__func__, selector);
    646	rc = aspeed_pinctrl_get_group_pins(pctldev, selector, &pins, &npins);
    647	if (rc < 0)
    648		return rc;
    649
    650	for (i = 0; i < npins; i++) {
    651		rc = aspeed_pin_config_set(pctldev, pins[i], configs,
    652				num_configs);
    653		if (rc < 0)
    654			return rc;
    655	}
    656
    657	return 0;
    658}