162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later
262306a36Sopenharmony_ci/* Copyright (C) 2019 IBM Corp. */
362306a36Sopenharmony_ci
462306a36Sopenharmony_ci/* Pieces to enable drivers to implement the .set callback */
562306a36Sopenharmony_ci
662306a36Sopenharmony_ci#include "pinmux-aspeed.h"
762306a36Sopenharmony_ci
862306a36Sopenharmony_cistatic const char *const aspeed_pinmux_ips[] = {
962306a36Sopenharmony_ci	[ASPEED_IP_SCU] = "SCU",
1062306a36Sopenharmony_ci	[ASPEED_IP_GFX] = "GFX",
1162306a36Sopenharmony_ci	[ASPEED_IP_LPC] = "LPC",
1262306a36Sopenharmony_ci};
1362306a36Sopenharmony_ci
1462306a36Sopenharmony_cistatic inline void aspeed_sig_desc_print_val(
1562306a36Sopenharmony_ci		const struct aspeed_sig_desc *desc, bool enable, u32 rv)
1662306a36Sopenharmony_ci{
1762306a36Sopenharmony_ci	pr_debug("Want %s%X[0x%08X]=0x%X, got 0x%X from 0x%08X\n",
1862306a36Sopenharmony_ci			aspeed_pinmux_ips[desc->ip], desc->reg,
1962306a36Sopenharmony_ci			desc->mask, enable ? desc->enable : desc->disable,
2062306a36Sopenharmony_ci			(rv & desc->mask) >> __ffs(desc->mask), rv);
2162306a36Sopenharmony_ci}
2262306a36Sopenharmony_ci
2362306a36Sopenharmony_ci/**
2462306a36Sopenharmony_ci * aspeed_sig_desc_eval() - Query the enabled or disabled state of a signal
2562306a36Sopenharmony_ci * descriptor.
2662306a36Sopenharmony_ci *
2762306a36Sopenharmony_ci * @desc: The signal descriptor of interest
2862306a36Sopenharmony_ci * @enabled: True to query the enabled state, false to query disabled state
2962306a36Sopenharmony_ci * @map: The IP block's regmap instance
3062306a36Sopenharmony_ci *
3162306a36Sopenharmony_ci * Return: 1 if the descriptor's bitfield is configured to the state
3262306a36Sopenharmony_ci * selected by @enabled, 0 if not, and less than zero if an unrecoverable
3362306a36Sopenharmony_ci * failure occurred
3462306a36Sopenharmony_ci *
3562306a36Sopenharmony_ci * Evaluation of descriptor state is non-trivial in that it is not a binary
3662306a36Sopenharmony_ci * outcome: The bitfields can be greater than one bit in size and thus can take
3762306a36Sopenharmony_ci * a value that is neither the enabled nor disabled state recorded in the
3862306a36Sopenharmony_ci * descriptor (typically this means a different function to the one of interest
3962306a36Sopenharmony_ci * is enabled). Thus we must explicitly test for either condition as required.
4062306a36Sopenharmony_ci */
4162306a36Sopenharmony_ciint aspeed_sig_desc_eval(const struct aspeed_sig_desc *desc,
4262306a36Sopenharmony_ci			 bool enabled, struct regmap *map)
4362306a36Sopenharmony_ci{
4462306a36Sopenharmony_ci	int ret;
4562306a36Sopenharmony_ci	unsigned int raw;
4662306a36Sopenharmony_ci	u32 want;
4762306a36Sopenharmony_ci
4862306a36Sopenharmony_ci	if (!map)
4962306a36Sopenharmony_ci		return -ENODEV;
5062306a36Sopenharmony_ci
5162306a36Sopenharmony_ci	ret = regmap_read(map, desc->reg, &raw);
5262306a36Sopenharmony_ci	if (ret)
5362306a36Sopenharmony_ci		return ret;
5462306a36Sopenharmony_ci
5562306a36Sopenharmony_ci	aspeed_sig_desc_print_val(desc, enabled, raw);
5662306a36Sopenharmony_ci	want = enabled ? desc->enable : desc->disable;
5762306a36Sopenharmony_ci
5862306a36Sopenharmony_ci	return ((raw & desc->mask) >> __ffs(desc->mask)) == want;
5962306a36Sopenharmony_ci}
6062306a36Sopenharmony_ci
6162306a36Sopenharmony_ci/**
6262306a36Sopenharmony_ci * aspeed_sig_expr_eval - Query the enabled or disabled state for a
6362306a36Sopenharmony_ci * mux function's signal on a pin
6462306a36Sopenharmony_ci *
6562306a36Sopenharmony_ci * @ctx: The driver context for the pinctrl IP
6662306a36Sopenharmony_ci * @expr: An expression controlling the signal for a mux function on a pin
6762306a36Sopenharmony_ci * @enabled: True to query the enabled state, false to query disabled state
6862306a36Sopenharmony_ci *
6962306a36Sopenharmony_ci * Return: 1 if the expression composed by @enabled evaluates true, 0 if not,
7062306a36Sopenharmony_ci * and less than zero if an unrecoverable failure occurred.
7162306a36Sopenharmony_ci *
7262306a36Sopenharmony_ci * A mux function is enabled or disabled if the function's signal expression
7362306a36Sopenharmony_ci * for each pin in the function's pin group evaluates true for the desired
7462306a36Sopenharmony_ci * state. An signal expression evaluates true if all of its associated signal
7562306a36Sopenharmony_ci * descriptors evaluate true for the desired state.
7662306a36Sopenharmony_ci *
7762306a36Sopenharmony_ci * If an expression's state is described by more than one bit, either through
7862306a36Sopenharmony_ci * multi-bit bitfields in a single signal descriptor or through multiple signal
7962306a36Sopenharmony_ci * descriptors of a single bit then it is possible for the expression to be in
8062306a36Sopenharmony_ci * neither the enabled nor disabled state. Thus we must explicitly test for
8162306a36Sopenharmony_ci * either condition as required.
8262306a36Sopenharmony_ci */
8362306a36Sopenharmony_ciint aspeed_sig_expr_eval(struct aspeed_pinmux_data *ctx,
8462306a36Sopenharmony_ci			 const struct aspeed_sig_expr *expr, bool enabled)
8562306a36Sopenharmony_ci{
8662306a36Sopenharmony_ci	int ret;
8762306a36Sopenharmony_ci	int i;
8862306a36Sopenharmony_ci
8962306a36Sopenharmony_ci	if (ctx->ops->eval)
9062306a36Sopenharmony_ci		return ctx->ops->eval(ctx, expr, enabled);
9162306a36Sopenharmony_ci
9262306a36Sopenharmony_ci	for (i = 0; i < expr->ndescs; i++) {
9362306a36Sopenharmony_ci		const struct aspeed_sig_desc *desc = &expr->descs[i];
9462306a36Sopenharmony_ci
9562306a36Sopenharmony_ci		ret = aspeed_sig_desc_eval(desc, enabled, ctx->maps[desc->ip]);
9662306a36Sopenharmony_ci		if (ret <= 0)
9762306a36Sopenharmony_ci			return ret;
9862306a36Sopenharmony_ci	}
9962306a36Sopenharmony_ci
10062306a36Sopenharmony_ci	return 1;
10162306a36Sopenharmony_ci}
102