18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later
28c2ecf20Sopenharmony_ci/* Copyright (C) 2019 IBM Corp. */
38c2ecf20Sopenharmony_ci
48c2ecf20Sopenharmony_ci/* Pieces to enable drivers to implement the .set callback */
58c2ecf20Sopenharmony_ci
68c2ecf20Sopenharmony_ci#include "pinmux-aspeed.h"
78c2ecf20Sopenharmony_ci
88c2ecf20Sopenharmony_cistatic const char *const aspeed_pinmux_ips[] = {
98c2ecf20Sopenharmony_ci	[ASPEED_IP_SCU] = "SCU",
108c2ecf20Sopenharmony_ci	[ASPEED_IP_GFX] = "GFX",
118c2ecf20Sopenharmony_ci	[ASPEED_IP_LPC] = "LPC",
128c2ecf20Sopenharmony_ci};
138c2ecf20Sopenharmony_ci
148c2ecf20Sopenharmony_cistatic inline void aspeed_sig_desc_print_val(
158c2ecf20Sopenharmony_ci		const struct aspeed_sig_desc *desc, bool enable, u32 rv)
168c2ecf20Sopenharmony_ci{
178c2ecf20Sopenharmony_ci	pr_debug("Want %s%X[0x%08X]=0x%X, got 0x%X from 0x%08X\n",
188c2ecf20Sopenharmony_ci			aspeed_pinmux_ips[desc->ip], desc->reg,
198c2ecf20Sopenharmony_ci			desc->mask, enable ? desc->enable : desc->disable,
208c2ecf20Sopenharmony_ci			(rv & desc->mask) >> __ffs(desc->mask), rv);
218c2ecf20Sopenharmony_ci}
228c2ecf20Sopenharmony_ci
238c2ecf20Sopenharmony_ci/**
248c2ecf20Sopenharmony_ci * Query the enabled or disabled state of a signal descriptor
258c2ecf20Sopenharmony_ci *
268c2ecf20Sopenharmony_ci * @desc: The signal descriptor of interest
278c2ecf20Sopenharmony_ci * @enabled: True to query the enabled state, false to query disabled state
288c2ecf20Sopenharmony_ci * @map: The IP block's regmap instance
298c2ecf20Sopenharmony_ci *
308c2ecf20Sopenharmony_ci * Return: 1 if the descriptor's bitfield is configured to the state
318c2ecf20Sopenharmony_ci * selected by @enabled, 0 if not, and less than zero if an unrecoverable
328c2ecf20Sopenharmony_ci * failure occurred
338c2ecf20Sopenharmony_ci *
348c2ecf20Sopenharmony_ci * Evaluation of descriptor state is non-trivial in that it is not a binary
358c2ecf20Sopenharmony_ci * outcome: The bitfields can be greater than one bit in size and thus can take
368c2ecf20Sopenharmony_ci * a value that is neither the enabled nor disabled state recorded in the
378c2ecf20Sopenharmony_ci * descriptor (typically this means a different function to the one of interest
388c2ecf20Sopenharmony_ci * is enabled). Thus we must explicitly test for either condition as required.
398c2ecf20Sopenharmony_ci */
408c2ecf20Sopenharmony_ciint aspeed_sig_desc_eval(const struct aspeed_sig_desc *desc,
418c2ecf20Sopenharmony_ci			 bool enabled, struct regmap *map)
428c2ecf20Sopenharmony_ci{
438c2ecf20Sopenharmony_ci	int ret;
448c2ecf20Sopenharmony_ci	unsigned int raw;
458c2ecf20Sopenharmony_ci	u32 want;
468c2ecf20Sopenharmony_ci
478c2ecf20Sopenharmony_ci	if (!map)
488c2ecf20Sopenharmony_ci		return -ENODEV;
498c2ecf20Sopenharmony_ci
508c2ecf20Sopenharmony_ci	ret = regmap_read(map, desc->reg, &raw);
518c2ecf20Sopenharmony_ci	if (ret)
528c2ecf20Sopenharmony_ci		return ret;
538c2ecf20Sopenharmony_ci
548c2ecf20Sopenharmony_ci	aspeed_sig_desc_print_val(desc, enabled, raw);
558c2ecf20Sopenharmony_ci	want = enabled ? desc->enable : desc->disable;
568c2ecf20Sopenharmony_ci
578c2ecf20Sopenharmony_ci	return ((raw & desc->mask) >> __ffs(desc->mask)) == want;
588c2ecf20Sopenharmony_ci}
598c2ecf20Sopenharmony_ci
608c2ecf20Sopenharmony_ci/**
618c2ecf20Sopenharmony_ci * Query the enabled or disabled state for a mux function's signal on a pin
628c2ecf20Sopenharmony_ci *
638c2ecf20Sopenharmony_ci * @ctx: The driver context for the pinctrl IP
648c2ecf20Sopenharmony_ci * @expr: An expression controlling the signal for a mux function on a pin
658c2ecf20Sopenharmony_ci * @enabled: True to query the enabled state, false to query disabled state
668c2ecf20Sopenharmony_ci *
678c2ecf20Sopenharmony_ci * Return: 1 if the expression composed by @enabled evaluates true, 0 if not,
688c2ecf20Sopenharmony_ci * and less than zero if an unrecoverable failure occurred.
698c2ecf20Sopenharmony_ci *
708c2ecf20Sopenharmony_ci * A mux function is enabled or disabled if the function's signal expression
718c2ecf20Sopenharmony_ci * for each pin in the function's pin group evaluates true for the desired
728c2ecf20Sopenharmony_ci * state. An signal expression evaluates true if all of its associated signal
738c2ecf20Sopenharmony_ci * descriptors evaluate true for the desired state.
748c2ecf20Sopenharmony_ci *
758c2ecf20Sopenharmony_ci * If an expression's state is described by more than one bit, either through
768c2ecf20Sopenharmony_ci * multi-bit bitfields in a single signal descriptor or through multiple signal
778c2ecf20Sopenharmony_ci * descriptors of a single bit then it is possible for the expression to be in
788c2ecf20Sopenharmony_ci * neither the enabled nor disabled state. Thus we must explicitly test for
798c2ecf20Sopenharmony_ci * either condition as required.
808c2ecf20Sopenharmony_ci */
818c2ecf20Sopenharmony_ciint aspeed_sig_expr_eval(struct aspeed_pinmux_data *ctx,
828c2ecf20Sopenharmony_ci			 const struct aspeed_sig_expr *expr, bool enabled)
838c2ecf20Sopenharmony_ci{
848c2ecf20Sopenharmony_ci	int ret;
858c2ecf20Sopenharmony_ci	int i;
868c2ecf20Sopenharmony_ci
878c2ecf20Sopenharmony_ci	if (ctx->ops->eval)
888c2ecf20Sopenharmony_ci		return ctx->ops->eval(ctx, expr, enabled);
898c2ecf20Sopenharmony_ci
908c2ecf20Sopenharmony_ci	for (i = 0; i < expr->ndescs; i++) {
918c2ecf20Sopenharmony_ci		const struct aspeed_sig_desc *desc = &expr->descs[i];
928c2ecf20Sopenharmony_ci
938c2ecf20Sopenharmony_ci		ret = aspeed_sig_desc_eval(desc, enabled, ctx->maps[desc->ip]);
948c2ecf20Sopenharmony_ci		if (ret <= 0)
958c2ecf20Sopenharmony_ci			return ret;
968c2ecf20Sopenharmony_ci	}
978c2ecf20Sopenharmony_ci
988c2ecf20Sopenharmony_ci	return 1;
998c2ecf20Sopenharmony_ci}
100